KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > jofti > cache > adapter > ObjectGridListenerAdapter


1 package com.jofti.cache.adapter;
2
3 import java.util.HashMap JavaDoc;
4 import java.util.Iterator JavaDoc;
5 import java.util.LinkedHashMap JavaDoc;
6 import java.util.List JavaDoc;
7 import java.util.Map JavaDoc;
8 import java.util.Properties JavaDoc;
9 import java.util.Set JavaDoc;
10 import java.util.Map.Entry;
11
12 import org.apache.commons.logging.Log;
13 import org.apache.commons.logging.LogFactory;
14
15 import com.ibm.websphere.objectgrid.BackingMap;
16 import com.ibm.websphere.objectgrid.IndexAlreadyDefinedException;
17 import com.ibm.websphere.objectgrid.IndexUndefinedException;
18 import com.ibm.websphere.objectgrid.ObjectGridException;
19 import com.ibm.websphere.objectgrid.ObjectMap;
20 import com.ibm.websphere.objectgrid.Session;
21 import com.ibm.websphere.objectgrid.TxID;
22 import com.ibm.websphere.objectgrid.plugins.index.DynamicIndexCallback;
23 import com.jofti.api.CacheAccessor;
24 import com.jofti.api.IndexQuery;
25 import com.jofti.cache.BaseAdaptor;
26 import com.jofti.cache.CacheListenerAdapter;
27 import com.jofti.cache.adapter.listener.ObjectGridEventListener;
28 import com.jofti.core.IParsedQuery;
29 import com.jofti.core.InternalIndex;
30 import com.jofti.exception.JoftiException;
31 import com.jofti.introspect.ClassIntrospector;
32 import com.jofti.parser.ClassFieldMethods;
33 import com.jofti.util.CompositeComparator;
34 import com.jofti.util.ObjectProcedureAdapter;
35 import com.jofti.util.OpenHashMap;
36 import com.jofti.util.ValueTreeMap;
37 import com.tangosol.net.NamedCache;
38 import com.tangosol.util.MapEvent;
39
40 /**
41
42  *
43  * The adapter implementation specific to ObjectGrid.</p>
44  *
45  * The adapter takes care of the implementation specific details for converting
46  * between the process the index expects and the behaviour of ObjectGrid.</p>
47  *
48  * The Listener adapter is for use as a listener to ObjectGrid and does not provide the get, set, remove methods
49  * that the wrapper adapter provides. The addition, removal and getting of values from the Cache must be
50  * done on the Cache implementation directly. This is the preferred way of using an already existing Cache.</p>
51  *
52  * The start up of the adapter will also try and index any elements already in
53  * the cache.<P>
54  *
55  * @author Steve Woodcock
56  * <p>
57  * @version 1.0
58  * @since 1.1
59  */

60 public class ObjectGridListenerAdapter extends BaseAdaptor implements CacheAccessor, CacheListenerAdapter
61 {
62
63
64     private static Log log = LogFactory
65                                                     .getLog(ObjectGridListenerAdapter.class);
66
67
68     private String JavaDoc name;
69
70     public InternalIndex index;
71
72     private ObjectGridEventListener eventListener = null;
73     
74     
75     private BackingMap cache =null;
76
77     private Object JavaDoc loadLock = new Object JavaDoc();
78     
79     private boolean loaded =true;
80
81     private boolean dynamicIndex =false;
82     
83     private boolean plugIn =false;
84     
85     public ObjectGridListenerAdapter()
86     {
87     }
88
89     public ObjectGridListenerAdapter(Object JavaDoc cache)
90     {
91         this.cache = (BackingMap) cache;
92
93     }
94     /* (non-Javadoc)
95      * @see com.jofti.cache.LifeCycleAdapter#init(java.util.Properties)
96      */

97     public synchronized void init(Properties JavaDoc properties) throws JoftiException
98     {
99         if (properties != null) {
100             String JavaDoc key = null;
101             for (Iterator JavaDoc it = properties.keySet().iterator(); it.hasNext();) {
102                 key = (String JavaDoc) it.next();
103                 if (MUTABLE_VALUES.equalsIgnoreCase(key)) {
104                     checkMutable = Boolean.valueOf(
105                             properties.getProperty(key)).booleanValue();
106                     if (log.isInfoEnabled()) {
107                         log.info("Mutability checking is set to "
108                                 + checkMutable);
109                     }
110                 }
111                 if ("file".equalsIgnoreCase(key)) {
112                     log.warn("Listener adapters cannot be used to start up a Cache - check docs for Adapter Type");
113                     throw new JoftiException("Listener adapters cannot be used to start up a Cache - check docs for Adapter Type");
114                 }
115                 if ("plugin".equalsIgnoreCase(key)) {
116                     log.info("Listener used as plug-in");
117                     plugIn =true;
118                 }
119             }
120         }
121
122      
123         if (cache == null) {
124             throw new JoftiException("Cache cannot be null for listener adapter");
125         } else {
126                 log.info("Index started using cache "+ cache.getName());
127         }
128         eventListener = new ObjectGridEventListener(this, name);
129     
130     }
131
132     
133  
134    
135
136     /* (non-Javadoc)
137      * @see com.jofti.cache.LifeCycleAdapter#destroy()
138      */

139     public synchronized void destroy() throws JoftiException
140     {
141         
142         try {
143             cache.removeMapEventListener(eventListener);
144         } catch (IllegalStateException JavaDoc e) {
145             log.warn("Unable to remove event listener:",e);
146         }
147             if (!dynamicIndex){
148                 List JavaDoc indexes = cache.getMapIndexPlugins();
149                 for(int i=0;i<indexes.size();i++){
150                     if (indexes.get(i) == eventListener){
151                         indexes.remove(i);
152                     }
153                 }
154             }else{
155                     try {
156                         cache.removeDynamicIndex(name);
157                     } catch (IndexUndefinedException e) {
158                         log.warn("Unable to remove dynamic Index:",e);
159                     } catch (IllegalArgumentException JavaDoc e) {
160                         
161                         log.warn("Unable to remove dynamic Index:",e);
162                     }
163                 
164             }
165            if (index != null){
166                 index.removeAll();
167            }
168            log.info("Removed index from cache:"+name);
169         
170     }
171
172     /* (non-Javadoc)
173      * @see com.jofti.cache.LifeCycleAdapter#getName()
174      */

175     public String JavaDoc getName()
176     {
177         return name;
178     }
179
180     /* (non-Javadoc)
181      * @see com.jofti.cache.LifeCycleAdapter#setName(java.lang.String)
182      */

183     public void setName(String JavaDoc name)
184     {
185         this.name = name;
186     }
187
188     public String JavaDoc toString()
189     {
190         return "ObjectGridCache(" + getName() + ')';
191     }
192
193   
194
195
196     /*
197      * (non-Javadoc)
198      *
199      * @see com.jofticache.CacheAdapter#setInternalIndex(com.jofti.core.InternalIndex)
200      */

201     public void setInternalIndex(InternalIndex index)
202     {
203         this.index = index;
204
205     }
206
207     /* (non-Javadoc)
208      * @see com.jofti.api.IndexCache#query(com.jofti.api.IndexQuery)
209      */

210     public Map JavaDoc query(IndexQuery query) throws JoftiException
211     {
212         
213         while (!loaded){
214             synchronized (loadLock) {
215                 try {
216                     loadLock.wait();
217                 }catch (InterruptedException JavaDoc e){
218                     
219                 }
220             }
221         }
222         Map JavaDoc temp = null;
223         
224         query = processQuery(query,index.getParserManager());
225        
226         acquireQueryLock();
227         try {
228         
229         temp=index.query(query);
230         } finally {
231             releaseQueryLock();
232         }
233         return getCacheValues(temp, (IParsedQuery)query,index.getIntrospector());
234
235     }
236
237     
238
239     /* (non-Javadoc)
240      * @see com.jofti.cache.CacheLocking#checkMutable(java.lang.Object, java.lang.Object)
241      */

242     protected Object JavaDoc checkMutable(Object JavaDoc key, Object JavaDoc result)
243     {
244         try {
245             // first parse the object - again
246
Map JavaDoc cacheObjectValues = index.getIntrospector().getAttributeValues(
247                     result);
248
249             Map JavaDoc indexObjectValues = index.getAttributesByKey(decorateKey( key));
250             
251             if (cacheObjectValues.equals(indexObjectValues)) {
252                 return result;
253             } else {
254                 if (log.isDebugEnabled()) {
255                     log.debug("Object under Key " + key
256                             + " - attributes changed without re-insert");
257                 }
258             }
259             // then get the values for the key
260

261         } catch (JoftiException e) {
262             log.warn("Error checking mutability", e);
263         }
264
265         return null;
266     }
267
268     /**
269      * @param cache
270      */

271     public void setCacheImpl(Object JavaDoc cache){
272         ObjectGridListenerAdapter.this.cache = (BackingMap)cache;
273         
274         
275     }
276     
277     public Map JavaDoc getCacheValues(Map JavaDoc col, final IParsedQuery query,
278             final ClassIntrospector introspector) throws JoftiException {
279
280         
281         final Map JavaDoc returnClasses = query.getResultFieldsMap();
282         final CompositeComparator comp = query.getOrderingComparator();
283         final int maxResults = query.getMaxResults();
284         final int startEntry = query.getFirstResult();
285         
286         Map JavaDoc interim = null;
287         if (comp ==null || comp.getSize() ==0){
288             interim =new HashMap JavaDoc(col.size() + 2, 1.00f);
289         }else{
290             interim = new ValueTreeMap(comp);
291         }
292         
293         // return map
294
final Map JavaDoc temp = interim;
295         
296         
297
298         // the results should always be an OpenHashMap
299
OpenHashMap originalMap = (OpenHashMap) col;
300
301         Session session =null;
302         // get the session that we aredoing our stuff in
303
try {
304          session= cache.getObjectGrid().getSession();
305         
306         
307         
308         final ObjectMap map =session.getMap(cache.getName());
309         
310         
311         session.begin();
312         // populate the return Map
313
originalMap.forEachPair(new ObjectProcedureAdapter() {
314             
315             public boolean apply(Object JavaDoc key, Object JavaDoc value) throws RuntimeException JavaDoc{
316                 
317                 //this will be an alias or null or it is not in the return set and we can ignore it
318
if (value == null || returnClasses ==null || returnClasses.containsKey(value)) {
319                     // see if we have the class in the return map
320

321                     // strip the key of wrapper if it is noncomparable
322
key = stripKey(key);
323
324                     Object JavaDoc result = null;
325                     try {
326                         result =getCacheValue(map, key);
327                     } catch (Exception JavaDoc e) {
328                         throw new RuntimeException JavaDoc(e);
329                     }
330
331                     if (result == null) {
332                         if (log.isWarnEnabled()) {
333                             log
334                                     .warn("Index and cache have become out of date for key "
335                                             + key);
336                         }
337                     } else {
338                         // get the methods to be operated on the value
339
if (checkMutable) {
340                             result = checkMutable(key, result);
341                             // mutability check failed
342
if (result == null) {
343                                 if (log.isDebugEnabled()) {
344                                     log
345                                             .debug("Object under key:"
346                                                     + key
347                                                     + " has changed in cache since it was indexed");
348                                 }
349                                 return true;
350                             }
351                         }
352                         
353                         
354                         if (returnClasses != null) {
355                             // we need to get the value from result if we are using fields
356
ClassFieldMethods fieldSet = (ClassFieldMethods) returnClasses
357                                     .get(value);
358
359                             Map JavaDoc tempMap = fieldSet != null ? fieldSet
360                                     .getFieldMap() : null;
361
362                             if (tempMap != null && tempMap.size() > 0) {
363                                 // get the fields and apply the values to them
364

365                                     Map JavaDoc resultMap = new LinkedHashMap JavaDoc();
366                 
367                                     resultMap = introspector.getResultValuesFromObject(resultMap,result,tempMap);
368                                     
369                                     // no values means no mapping in results
370
if (resultMap.size()>0){
371                                         Object JavaDoc[] res = new Object JavaDoc[resultMap.size()];
372                                         Iterator JavaDoc it = resultMap.entrySet().iterator();
373                                         for (int i = 0;i<resultMap.size();i++){
374                                             Map.Entry JavaDoc entry = (Map.Entry JavaDoc)it.next();
375                                             res[i]= entry.getValue();
376                                         }
377                                         temp.put(key,res);
378                                     }
379                                     
380                             } else {
381                                 // there are no fields just return the value
382
temp.put(key, result);
383                             }
384                         } else {
385                             temp.put(key, result);
386                         }
387                     }
388
389                 }
390                 return true;
391             }
392         });
393
394         } catch(Exception JavaDoc e){
395             throw new JoftiException(e);
396         }finally{
397             if (session != null){
398                 try {
399                     if(log.isDebugEnabled()){
400                         log.debug("finished search: terminating search tx "+session.getTxID());
401                     }
402                 session.commit();
403                 } catch(Exception JavaDoc e){
404                     log.warn("unable to close transaction for query", e);
405                 }
406             }
407         }
408         // now limit result size
409
if (maxResults >0 || startEntry >0){
410             return limitResults(temp, startEntry, maxResults);
411         }else if (startEntry <0 || maxResults <0){
412             if (startEntry <0){
413                 throw new IllegalArgumentException JavaDoc("startResult cannot be less than 0:"+startEntry);
414             }
415             if (maxResults <0){
416                 throw new IllegalArgumentException JavaDoc("maxResults cannot be less than 0:"+maxResults);
417             }
418         }
419         
420         
421         return temp;
422     }
423
424     protected Object JavaDoc getCacheValue(ObjectMap map, Object JavaDoc key) throws ObjectGridException{
425         
426         return map.get(key);
427         
428     }
429
430     /* (non-Javadoc)
431      * @see com.jofti.cache.LifeCycleAdapter#start()
432      */

433     public void start() throws JoftiException {
434         if (cache != null){
435             addListener();
436             
437         }
438         
439         
440         
441     }
442
443     private void addListener() throws JoftiException {
444         cache.addMapEventListener(eventListener);
445         
446         if (!plugIn){
447             try {
448                 cache.addMapIndexPlugin(eventListener);
449             } catch (IllegalStateException JavaDoc e) {
450                 //add the dynamic listener
451
loaded =false;
452                 try {
453                     cache.createDynamicIndex(eventListener, new DynamicListener());
454                     dynamicIndex =true;
455                     // load the initial values
456
// loadInitialValues();
457
} catch (Exception JavaDoc e1) {
458                     throw new JoftiException(e1);
459                 }
460                 
461             } catch (IndexAlreadyDefinedException iae){
462                 throw new JoftiException(iae);
463             }
464         }
465     }
466
467     class DynamicListener implements DynamicIndexCallback{
468
469         public void destroy(String JavaDoc s) {
470             log.info("dynamic index destroyed:"+s);
471             
472         }
473
474         public void error(String JavaDoc s, Throwable JavaDoc throwable) {
475             log.error(s, throwable);
476             synchronized (loadLock) {
477                 loaded =true;
478                 loadLock.notifyAll();
479             }
480             
481             
482         }
483
484         public void ready(String JavaDoc s) {
485             log.info("dynamic index ready:"+s);
486             synchronized (loadLock) {
487                 loaded =true;
488                 loadLock.notifyAll();
489             }
490             
491             
492         }
493         
494     }
495      
496
497     /* (non-Javadoc)
498      * @see com.jofti.cache.CacheLocking#getIndex()
499      */

500     public InternalIndex getIndex() {
501         
502         return index;
503     }
504
505     /* (non-Javadoc)
506      * @see com.jofti.api.CacheAccessor#getCacheImpl()
507      */

508     public Object JavaDoc getCacheImpl() {
509         
510         return cache;
511     }
512
513     public IndexQuery addQuery(String JavaDoc name, IndexQuery query)throws JoftiException {
514         
515         return index.getParserManager().addQuery(name, query);
516     }
517
518     /* (non-Javadoc)
519      * @see com.jofti.api.Index#getQuery(java.lang.String)
520      */

521     public IndexQuery getQuery(String JavaDoc name) {
522         
523         return index.getParserManager().getQuery(name);
524     }
525
526     protected Object JavaDoc getCacheValue(Object JavaDoc key) {
527         // intentional no-op
528
return null;
529     }
530
531     public ObjectGridEventListener getEventListener() {
532         return eventListener;
533     }
534     
535 }
Popular Tags