001: package com.completex.objective.components.persistency.ocache.impl;
002:
003: import com.completex.objective.components.OdalRuntimeException;
004: import com.completex.objective.components.ocache.ValueTransformer;
005: import com.completex.objective.components.persistency.AbstractPersistentObject;
006: import com.completex.objective.components.persistency.PersistentObject;
007: import com.completex.objective.components.persistency.OdalRuntimePersistencyException;
008:
009: import java.util.ArrayList;
010: import java.util.Collection;
011: import java.util.HashSet;
012: import java.util.Iterator;
013: import java.util.LinkedList;
014:
015: /**
016: * ValueTransformer implementation that optionally clones and flattens/unflattes
017: * AbstractPersistentObject instances
018: *
019: * @author Gennady Krizhevsky
020: */
021: public class PoValueTransformer implements ValueTransformer {
022:
023: private boolean flatten = true;
024: private boolean clone = true;
025:
026: public PoValueTransformer() {
027: }
028:
029: /**
030: *
031: * @param flatten if true then the object is stored in its flattened form and gets unflattened when retrieved from the cache
032: * @param clone if true then the object gets cloned before it is stored and retrieved from the cache
033: */
034: public PoValueTransformer(boolean flatten, boolean clone) {
035: this .flatten = flatten;
036: this .clone = clone;
037: }
038:
039: /**
040: * Optionally (depending on <t>flatten</t> flag) flattens objects of 2 types: AbstractPersistentObject
041: * or Collection of AbstractPersistentObject instances before cachings.
042: * Does nothing if the value is not of AbstractPersistentObject type.
043: *
044: * @see ValueTransformer#afterGet(Object, Object)
045: */
046: public Object beforePut(Object key, Object value) {
047: if (value instanceof AbstractPersistentObject) {
048: AbstractPersistentObject persistent = cast(value);
049: persistent = clonePersistent(persistent);
050: return flattenPersistent(persistent);
051: } else if (value instanceof Collection) {
052: Collection collection = cloneCollection((Collection) value);
053: return flattenCollection(collection);
054: } else {
055: // Do nothing
056: }
057: return value;
058: }
059:
060: /**
061: * Optionally (depending on <t>clone/flatten</t> flags) clones and/or unflattens cached objects of 2 types: AbstractPersistentObject
062: * or Collection of AbstractPersistentObject instances.
063: * Does nothing if the value is not of AbstractPersistentObject type.
064: *
065: * @see ValueTransformer#afterGet(Object, Object)
066: */
067: public Object afterGet(Object key, Object value) {
068: if (value instanceof AbstractPersistentObject) {
069: AbstractPersistentObject persistent = cast(value);
070: persistent = clonePersistent(persistent);
071: return unflattenPersistent(persistent);
072: } else if (value instanceof Collection) {
073: Collection collection = cloneCollection((Collection) value);
074: return unflattenCollection(collection);
075: } else {
076: // Do nothing
077: }
078: return value;
079: }
080:
081: /**
082: * Returns copy of a collection with cloned <t>AbstractPersistentObject</t> instances.
083: * If the collection is not of <t>AbstractPersistentObject</t> instances then returns a copy of the
084: * collection referencing the same objects as the original one.
085: * Does nothing if <code>clone == false</code>
086: *
087: * @param collection collection to clone
088: * @return Returns copy of a collection with cloned <t>AbstractPersistentObject</t> instances.
089: * If the collection is not of <t>AbstractPersistentObject</t> instances then returns a copy of the
090: * collection referencing the same objects as the original one.
091: * @throws OdalRuntimeException if the collection is not instance of Cloneable
092: */
093: protected Collection cloneCollection(Collection collection) {
094: Collection cloned = null;
095: if (clone) {
096: if (collection instanceof ArrayList) {
097: cloned = new ArrayList(collection.size());
098: } else if (collection instanceof LinkedList) {
099: cloned = new LinkedList();
100: } else if (collection instanceof HashSet) {
101: cloned = new HashSet();
102: } else {
103: cloned = newAnyCollection(collection);
104: }
105: for (Iterator iterator = collection.iterator(); iterator
106: .hasNext();) {
107: Object value = iterator.next();
108: if (value instanceof AbstractPersistentObject) {
109: cloned
110: .add(clonePersistent(((AbstractPersistentObject) value)));
111: }
112: }
113: }
114: return cloned;
115: }
116:
117: /**
118: * Gets new instance of any Java Collection that has no arguments cinstructor.
119: *
120: * @param collection
121: * @return cloned collection
122: * @throws OdalRuntimeException if error happens
123: */
124: private Collection newAnyCollection(Collection collection) {
125: Collection cloned;
126: try {
127: cloned = (Collection) Class.forName(
128: collection.getClass().getName()).newInstance();
129: } catch (Exception e) {
130: throw new OdalRuntimePersistencyException(
131: "Cannot clone collection " + collection, e);
132: }
133: return cloned;
134: }
135:
136: /**
137: * Optionally unflattens collection of AbstractPersistentObject instances.
138: * Does nothing if <code>flatten == false</code>
139: *
140: * @param collection collection to unflatten - gets unflatted in process
141: * @return unflatten collection
142: */
143: protected Collection unflattenCollection(Collection collection) {
144: if (flatten) {
145: for (Iterator iterator = collection.iterator(); iterator
146: .hasNext();) {
147: Object obj = iterator.next();
148: if (obj instanceof AbstractPersistentObject) {
149: unflattenPersistent(((AbstractPersistentObject) obj));
150: }
151: }
152: }
153: return collection;
154: }
155:
156: protected AbstractPersistentObject unflattenPersistent(
157: AbstractPersistentObject persistent) {
158: if (flatten && persistent != null) {
159: persistent.unflatten();
160: }
161: return persistent;
162: }
163:
164: protected AbstractPersistentObject flattenPersistent(
165: AbstractPersistentObject persistent) {
166: if (flatten && persistent != null) {
167: persistent.flatten();
168: }
169: return persistent;
170: }
171:
172: /**
173: * Optionally flattens collection of AbstractPersistentObject instances.
174: * Does nothing if <code>flatten == false</code>
175: *
176: * @param collection
177: */
178: protected Collection flattenCollection(Collection collection) {
179: if (flatten) {
180: for (Iterator iterator = collection.iterator(); iterator
181: .hasNext();) {
182: Object obj = iterator.next();
183: if (obj instanceof AbstractPersistentObject) {
184: flattenPersistent(((AbstractPersistentObject) obj));
185: }
186: }
187: }
188: return collection;
189: }
190:
191: protected AbstractPersistentObject clonePersistent(
192: AbstractPersistentObject persistent) {
193: if (clone && persistent != null) {
194: try {
195: persistent = (PersistentObject) persistent.clone();
196: } catch (Exception e) {
197: throw new OdalRuntimePersistencyException(e);
198: }
199: }
200: return persistent;
201: }
202:
203: /**
204: * Casts the value to AbstractPersistentObject type
205: *
206: * @param value
207: * @return AbstractPersistentObject
208: */
209: protected AbstractPersistentObject cast(Object value) {
210: return (AbstractPersistentObject) value;
211: }
212:
213: public boolean isFlatten() {
214: return flatten;
215: }
216:
217: void setFlatten(boolean flatten) {
218: this .flatten = flatten;
219: }
220:
221: public boolean isClone() {
222: return clone;
223: }
224:
225: void setClone(boolean clone) {
226: this.clone = clone;
227: }
228: }
|