001: /*
002: * Created on 19-Feb-2005
003: *
004:
005: */
006: package com.jofti.cache.adapter;
007:
008: import java.util.ArrayList;
009: import java.util.Collection;
010: import java.util.HashMap;
011: import java.util.HashSet;
012: import java.util.List;
013: import java.util.Map;
014: import java.util.Properties;
015: import java.util.Set;
016:
017: import com.jofti.api.IndexQuery;
018: import com.jofti.btree.BTree;
019: import com.jofti.core.GenericIndexFactory;
020: import com.jofti.core.InternalIndex;
021: import com.jofti.exception.JoftiException;
022: import com.jofti.introspect.ClassIntrospector;
023: import com.jofti.tree.NameSpacedTreeIndex;
024: import com.jofti.tree.TreeIndex;
025:
026: /**
027: *
028: *
029: * Used by the JBossCacheAdapter to provide Transaction isolation for the
030: * changes to the index. In effect each transaction acquires its own mini-index which stores the
031: * changes to the larger main index. These changes are then applied on a commit (after the cache changes have committed).
032: *
033: * @author Steve Woodcock (steve@jofti.com)<p>
034: */
035:
036: public class ChangeRecorder {
037:
038: public final static Object DUMMY_VALUE = new Object();
039:
040: protected InternalIndex index = null;
041: private Set removedKeys = new HashSet();
042: private Map updatedMap = new HashMap();
043:
044: private ClassIntrospector parser = null;
045:
046: //stores values that were originally in the map but have been removed in the transaction
047: private Map removedValues = new HashMap();
048:
049: public ChangeRecorder(ClassIntrospector parser) {
050: this .parser = parser;
051: }
052:
053: /**
054: * Initialises a new NameSpacedtreeIndex so local changes can be stored.
055: * @param props - properties to strat index with.
056: * @throws JoftiException
057: */
058: public void init(Properties props, String indexType)
059: throws JoftiException {
060: index = GenericIndexFactory.getInstance().createIndex(
061: indexType, parser, props, "localIndex");
062:
063: }
064:
065: /**
066: * @return A collection of all the local tree values in the recorder
067: * @throws JoftiException
068: */
069: public Collection getAllTreeValues() throws JoftiException {
070:
071: return ((NameSpacedTreeIndex) index).getAllKeyEntriesFromTree();
072:
073: }
074:
075: /**
076: * Removes an object from the local index. This method also adds the removed key and
077: * values to the removedValues map so when committed a full list of removed objects can be
078: * identified.
079: * @param key
080: * @param value
081: * @param parser
082: * @throws JoftiException
083: */
084: public synchronized void remove(Object key, Object value,
085: ClassIntrospector parser) throws JoftiException {
086:
087: List temp = (List) removedValues.get(key);
088: if (temp == null) {
089: temp = new ArrayList();
090:
091: }
092: temp.add(value);
093: removedValues.put(key, temp);
094: index.remove((Comparable) key, value);
095:
096: }
097:
098: /**
099: * Removes an object mapping from the change recorder.
100: * <p>
101: * @param key
102: * @param parser
103: * @throws JoftiException
104: */
105: public synchronized void remove(Object key, ClassIntrospector parser)
106: throws JoftiException {
107:
108: removedKeys.add(key);
109: index.removeByKey((Comparable) key);
110:
111: }
112:
113: /**
114: * Adds a value to the ChangeRecorder.<p>
115: * @param key
116: * @param value
117: * @param parser
118: * @throws JoftiException
119: */
120: public synchronized void add(Object key, Object value,
121: ClassIntrospector parser) throws JoftiException {
122:
123: index.insert((Comparable) key, value);
124:
125: }
126:
127: /**
128: * Checks the local index to see if it contains the key.<p>
129: * @param key
130: * @param parser
131: * @return a boolean indicating if the change recorder contains the key
132: * @throws JoftiException
133: */
134: public boolean contains(Object key, ClassIntrospector parser)
135: throws JoftiException {
136:
137: return index.contains((Comparable) key);
138:
139: }
140:
141: /**
142: * Notifies the Change Recorder that an attribute has been updated in the local index.<p>
143: * @param key
144: * @param oldValue
145: * @param value
146: * @param parser
147: * @throws JoftiException
148: */
149: public synchronized void update(Object key, Object oldValue,
150: Object value, ClassIntrospector parser)
151: throws JoftiException {
152:
153: // remove if we already have set it
154: index.removeByKey((Comparable) key);
155:
156: // add to the updated list
157: List temp = (List) updatedMap.get(key);
158: if (temp == null) {
159: temp = new ArrayList();
160:
161: }
162: temp.add(oldValue);
163: updatedMap.put(key, temp);
164:
165: // insert the new value
166: index.insert((Comparable) key, value);
167:
168: }
169:
170: Map getRemovedMap() {
171: return removedValues;
172: }
173:
174: Map getUpdatedMap() {
175: return updatedMap;
176: }
177:
178: /**
179: * @return Returns the removedKeys.
180: */
181: public Set getRemovedKeys() {
182: return removedKeys;
183: }
184:
185: /**
186: * Executes a query against the local index.
187: * @param query
188: * @return A Map containing the results of the query
189: * @throws JoftiException
190: */
191: public Map query(IndexQuery query) throws JoftiException {
192: return index.query(query);
193: }
194: }
|