001: /*
002: * Copyright 2006 Davide Deidda
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: /*
018: * EntityMap.java
019: *
020: * Created on 15 October 2005, 15:56
021: *
022: * To change this template, choose Tools | Template Manager
023: * and open the template in the editor.
024: */
025:
026: package it.biobytes.ammentos.util;
027:
028: import it.biobytes.ammentos.Ammentos;
029: import it.biobytes.ammentos.Field;
030: import it.biobytes.ammentos.PersistenceException;
031: import java.util.*;
032: import it.biobytes.ammentos.query.*;
033: import java.util.logging.Logger;
034:
035: /**
036: *
037: * @author davide
038: */
039: public class EntityMap<K, T> extends TreeMap<K, T> implements
040: EntityCollection {
041: private boolean m_touched;
042: private boolean m_touchSensible;
043: private Query m_query;
044: private Logger m_logger = Logger.getLogger("ammentos");
045: private Class<T> m_class;
046: private Map<K, T> m_snapshot;
047: private boolean m_saving;
048: private boolean m_deleteOnRemove;
049: private Field m_keyField;
050:
051: public EntityMap(Class<T> c, Field keyField, Query query,
052: boolean deleteOnRemove) {
053: m_class = c;
054: m_query = query;
055: m_touchSensible = true;
056: m_deleteOnRemove = deleteOnRemove;
057: m_keyField = keyField;
058: }
059:
060: public EntityMap(Class<T> c, Field keyField, Query qry,
061: Map<K, T> map, boolean deleteOnRemove) {
062: this (c, keyField, qry, deleteOnRemove);
063: m_touchSensible = false;
064: if ((map != null) && (map.size() > 0)) {
065:
066: super .putAll(map);
067: m_touched = true;
068: }
069: m_touchSensible = true;
070: }
071:
072: @Override
073: public SortedMap<K, T> tailMap(K fromKey) {
074: touch();
075: SortedMap retValue;
076: retValue = super .tailMap(fromKey);
077: return retValue;
078: }
079:
080: @Override
081: public SortedMap<K, T> headMap(K toKey) {
082: touch();
083: SortedMap retValue;
084:
085: retValue = super .headMap(toKey);
086: return retValue;
087: }
088:
089: @Override
090: public T remove(Object key) {
091: touch();
092: T retValue;
093:
094: retValue = super .remove(key);
095: return retValue;
096: }
097:
098: @Override
099: public boolean containsKey(Object key) {
100: touch();
101: boolean retValue;
102:
103: retValue = super .containsKey(key);
104: return retValue;
105: }
106:
107: @Override
108: public boolean containsValue(Object value) {
109: touch();
110: boolean retValue;
111:
112: retValue = super .containsValue(value);
113: return retValue;
114: }
115:
116: @Override
117: public boolean equals(Object o) {
118: touch();
119: boolean retValue;
120:
121: retValue = super .equals(o);
122: return retValue;
123: }
124:
125: @Override
126: public T get(Object key) {
127: touch();
128: T retValue;
129:
130: retValue = super .get(key);
131: return retValue;
132: }
133:
134: @Override
135: public T put(K key, T value) {
136: touch();
137: T retValue;
138:
139: retValue = super .put(key, value);
140: return retValue;
141: }
142:
143: @Override
144: public void putAll(Map<? extends K, ? extends T> map) {
145: touch();
146: super .putAll(map);
147: }
148:
149: @Override
150: public Collection<T> values() {
151: touch();
152: Collection retValue;
153:
154: retValue = super .values();
155: return retValue;
156: }
157:
158: @Override
159: public String toString() {
160: touch();
161: String retValue;
162:
163: retValue = super .toString();
164: return retValue;
165: }
166:
167: @Override
168: public SortedMap<K, T> subMap(K fromKey, K toKey) {
169: touch();
170: SortedMap retValue;
171:
172: retValue = super .subMap(fromKey, toKey);
173: return retValue;
174: }
175:
176: @Override
177: public int size() {
178: touch();
179: int retValue;
180:
181: retValue = super .size();
182: return retValue;
183: }
184:
185: @Override
186: public K lastKey() {
187: touch();
188: K retValue;
189:
190: retValue = super .lastKey();
191: return retValue;
192: }
193:
194: @Override
195: public Set<K> keySet() {
196: touch();
197: Set retValue;
198:
199: retValue = super .keySet();
200: return retValue;
201: }
202:
203: @Override
204: public void clear() {
205: touch();
206: super .clear();
207: }
208:
209: @Override
210: public Object clone() {
211: touch();
212: Object retValue;
213:
214: retValue = super .clone();
215: return retValue;
216: }
217:
218: @Override
219: public Comparator<K> comparator() {
220: touch();
221: Comparator retValue;
222:
223: retValue = super .comparator();
224: return retValue;
225: }
226:
227: @Override
228: public Set<Map.Entry<K, T>> entrySet() {
229: touch();
230: Set retValue;
231:
232: retValue = super .entrySet();
233: return retValue;
234: }
235:
236: @Override
237: public K firstKey() {
238: touch();
239: K retValue;
240:
241: retValue = super .firstKey();
242: return retValue;
243: }
244:
245: @Override
246: public int hashCode() {
247: touch();
248: int retValue;
249:
250: retValue = super .hashCode();
251: return retValue;
252: }
253:
254: @Override
255: public boolean isEmpty() {
256: touch();
257: boolean retValue;
258:
259: retValue = super .isEmpty();
260: return retValue;
261: }
262:
263: private synchronized void touch() {
264: m_logger.info("touch called. m_touched: " + m_touched);
265: if (!m_touchSensible)
266: return;
267: if (!m_touched) {
268: load();
269: m_touched = true;
270: }
271: }
272:
273: private synchronized void load() {
274: m_logger.info("load called");
275: try {
276: // Loads objects without beeing touched
277: m_touchSensible = false;
278: m_logger.info("query: " + m_query.getSql());
279: List<T> objs = Ammentos.load(m_class, m_query);
280: m_logger.info("objects loaded: " + objs.size());
281:
282: for (T obj : objs) {
283: put((K) m_keyField.get(obj), obj);
284: }
285:
286: takeSnapshot();
287: m_touchSensible = true;
288: } catch (PersistenceException e) {
289: m_logger.severe("Error loading query");
290: }
291: }
292:
293: private synchronized void takeSnapshot() {
294: m_touchSensible = false;
295: m_snapshot = new TreeMap<K, T>(this );
296: m_touchSensible = true;
297: }
298:
299: public synchronized void save() throws PersistenceException {
300: if ((!m_saving) && m_touched) {
301: m_saving = true;
302: try {
303: // Manages removed elements
304: m_logger.info("deleteOnRemove: " + m_deleteOnRemove);
305: m_logger.info("snapshot: " + m_snapshot);
306:
307: if (m_snapshot != null) {
308: // Removes from snapshot all present elements
309: m_snapshot.values().removeAll(this .values());
310: m_logger.info("snapshot after removeAll: "
311: + m_snapshot);
312:
313: if (m_deleteOnRemove) {
314: for (T obj : m_snapshot.values()) {
315: Ammentos.delete(obj);
316: }
317: } else {
318: for (T obj : m_snapshot.values()) {
319: Ammentos.save(obj);
320: }
321: }
322: }
323:
324: m_touchSensible = false;
325: for (T obj : this .values()) {
326: m_logger.info("saving: "
327: + System.identityHashCode(obj));
328: Ammentos.save(obj);
329: m_logger.info("saved: "
330: + System.identityHashCode(obj));
331: }
332: m_touchSensible = true;
333: } finally {
334: takeSnapshot();
335: m_saving = false;
336: }
337: }
338: }
339:
340: public synchronized void delete() throws PersistenceException {
341: for (T obj : this.values()) {
342: Ammentos.delete(obj);
343: }
344: }
345: }
|