1 | package de.uka.ipd.sdq.sensorframework.dao.file; |
2 | |
3 | import java.util.Collection; |
4 | import java.util.Collections; |
5 | import java.util.HashMap; |
6 | |
7 | import de.uka.ipd.sdq.sensorframework.dao.file.entities.SerializableEntity; |
8 | import de.uka.ipd.sdq.sensorframework.entities.dao.IDAOFactory; |
9 | |
10 | /** |
11 | * An abstract implementation of a file DAO. The DAO is based on the following principle. All entities |
12 | * are stored in a hashmap which hashes IDs to entities. The hashmap is fully loaded from the background |
13 | * storage at startup, manipulated in memory, and finally stored back on request or when the DAO is disposed. |
14 | * |
15 | * @author Steffen Becker |
16 | * |
17 | * @param <T> The type of the entities this DAO is able to handle |
18 | */ |
19 | public abstract class AbstractFileDAO<T> { |
20 | |
21 | /** |
22 | * Interface to other DAOs |
23 | */ |
24 | protected FileDAOFactory factory = null; |
25 | |
26 | /** |
27 | * Prefix of the file which stores the elements controlled by this DAO |
28 | */ |
29 | private String myPrefix; |
30 | |
31 | /** |
32 | * ID Generator instance. Used by subclasses to create IDs of new elements |
33 | */ |
34 | protected IDGenerator idGen; |
35 | |
36 | /** |
37 | * A cache/storage for elements in this DAO |
38 | */ |
39 | private HashMap<Long, T> entitiesCache = null;//why not a sorted map? |
40 | |
41 | |
42 | /** Constructor of this DAO |
43 | * @param factory Interface to other DAOs |
44 | * @param idGen Identifier Generator used for new elements |
45 | * @param prefix Filename prefix for the filename used to persist the elements controlled by this DAO |
46 | */ |
47 | public AbstractFileDAO(IDAOFactory factory, IDGenerator idGen, String prefix) { |
48 | this.factory = (FileDAOFactory)factory; |
49 | this.idGen = idGen; |
50 | this.myPrefix = prefix; |
51 | loadDataFromStorage(); |
52 | } |
53 | |
54 | /** |
55 | * Load all elements controlled by this DAO into memory. Called on startup to initialise this DAO |
56 | */ |
57 | @SuppressWarnings("unchecked") |
58 | private void loadDataFromStorage() { |
59 | this.entitiesCache = (HashMap<Long, T>) this.factory.getFileManager().deserializeFromFile(this.myPrefix); |
60 | if (this.entitiesCache == null) { |
61 | this.entitiesCache = new HashMap<Long, T>(); |
62 | } else { |
63 | for (T value : this.entitiesCache.values()) { |
64 | SerializableEntity serializable = (SerializableEntity) value; |
65 | serializable.setFactory(this.factory); |
66 | } |
67 | } |
68 | } |
69 | |
70 | /** |
71 | * Stores all elements controlled by this DAO on the persistent storage |
72 | */ |
73 | public void storeAll() { |
74 | factory.getFileManager().serializeToFile(this.myPrefix,entitiesCache); |
75 | } |
76 | |
77 | /** Get entity with given ID from DAO |
78 | * @param id ID of the element to retrieve. The element with ID id has to exist otherwise an |
79 | * IllegalArguementException is thrown |
80 | * @return The requested element |
81 | */ |
82 | public T get(long id) { |
83 | if (!entitiesCache.containsKey(id)) |
84 | throw new IllegalArgumentException("Entity with ID "+id+" not found in DAO"); |
85 | return entitiesCache.get(id); |
86 | } |
87 | |
88 | /** |
89 | * Store a new element in this DAO. Used by subclasses to register newly created elements |
90 | * @param entity A new element. The element must not be controlled by the DAO already |
91 | */ |
92 | protected void putEntity(T entity) { |
93 | SerializableEntity serialisable = (SerializableEntity) entity; |
94 | if (entitiesCache.containsKey(serialisable.getID())) |
95 | throw new IllegalArgumentException("Entity with ID "+serialisable.getID()+" already exists in this DAO"); |
96 | this.entitiesCache.put(serialisable.getID(), entity); |
97 | } |
98 | |
99 | /** Returns a list of all entities stored in this DAO |
100 | * @return A list of all entities stored in this DAO |
101 | */ |
102 | protected Collection<T> getAllEntities() { |
103 | return Collections.unmodifiableCollection(entitiesCache.values()); |
104 | } |
105 | |
106 | /** Remove the given entity from this DAO's control |
107 | * @param entity The entity to remove |
108 | * @param doCascade If true, all entities which depend on the passed entity are deleted as well |
109 | */ |
110 | public void removeEntity(T entity, boolean doCascade) { |
111 | if (entity == null) |
112 | throw new IllegalArgumentException("Entity can not be null"); |
113 | if (!entitiesCache.containsValue(entity)) |
114 | throw new IllegalArgumentException("Entity not controlled by this DAO"); |
115 | |
116 | if (doCascade == true) { |
117 | throw new UnsupportedOperationException(); |
118 | } |
119 | |
120 | entitiesCache.remove(((SerializableEntity)entity).getID()); |
121 | } |
122 | |
123 | /** |
124 | * Disposes this DAO. This includes persisting all changes to the background storage |
125 | */ |
126 | public void dispose() { |
127 | this.storeAll(); |
128 | this.entitiesCache.clear(); |
129 | } |
130 | } |