001: /*
002: * Copyright 2004-2006 the original author or authors.
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: package org.compass.core.impl;
018:
019: import org.compass.core.CompassAnalyzerHelper;
020: import org.compass.core.CompassException;
021: import org.compass.core.CompassHits;
022: import org.compass.core.CompassQuery;
023: import org.compass.core.CompassQueryBuilder;
024: import org.compass.core.CompassQueryFilterBuilder;
025: import org.compass.core.CompassSession;
026: import org.compass.core.CompassTermFreqsBuilder;
027: import org.compass.core.CompassTransaction;
028: import org.compass.core.CompassTransaction.TransactionIsolation;
029: import org.compass.core.Resource;
030: import org.compass.core.cache.first.FirstLevelCache;
031: import org.compass.core.cache.first.NullFirstLevelCache;
032: import org.compass.core.cascade.CascadingManager;
033: import org.compass.core.config.CompassSettings;
034: import org.compass.core.config.RuntimeCompassSettings;
035: import org.compass.core.engine.SearchEngine;
036: import org.compass.core.engine.SearchEngineAnalyzerHelper;
037: import org.compass.core.engine.SearchEngineQueryBuilder;
038: import org.compass.core.engine.SearchEngineQueryFilterBuilder;
039: import org.compass.core.mapping.CascadeMapping;
040: import org.compass.core.mapping.CompassMapping;
041: import org.compass.core.marshall.DefaultMarshallingStrategy;
042: import org.compass.core.marshall.MarshallingContext;
043: import org.compass.core.marshall.MarshallingException;
044: import org.compass.core.marshall.MarshallingStrategy;
045: import org.compass.core.metadata.CompassMetaData;
046: import org.compass.core.spi.InternalCompass;
047: import org.compass.core.spi.InternalCompassSession;
048: import org.compass.core.spi.InternalResource;
049: import org.compass.core.spi.ResourceKey;
050: import org.compass.core.transaction.LocalTransactionFactory;
051: import org.compass.core.transaction.TransactionFactory;
052:
053: /**
054: * @author kimchy
055: */
056: // TODO we need to support multiple resource with ResourceKey and first cache
057: public class DefaultCompassSession implements InternalCompassSession {
058:
059: private InternalCompass compass;
060:
061: private CompassMapping mapping;
062:
063: private CompassMetaData compassMetaData;
064:
065: private SearchEngine searchEngine;
066:
067: private TransactionFactory transactionFactory;
068:
069: private LocalTransactionFactory localTransactionFactory;
070:
071: private MarshallingStrategy marshallingStrategy;
072:
073: private FirstLevelCache firstLevelCache;
074:
075: private boolean closed = false;
076:
077: private RuntimeCompassSettings runtimeSettings;
078:
079: private CascadingManager cascadingManager;
080:
081: public DefaultCompassSession(
082: RuntimeCompassSettings runtimeSettings,
083: InternalCompass compass, SearchEngine searchEngine,
084: FirstLevelCache firstLevelCache) {
085: this .compass = compass;
086: this .mapping = compass.getMapping();
087: this .compassMetaData = compass.getMetaData();
088: this .transactionFactory = compass.getTransactionFactory();
089: this .localTransactionFactory = compass
090: .getLocalTransactionFactory();
091: this .runtimeSettings = runtimeSettings;
092: this .searchEngine = searchEngine;
093: this .firstLevelCache = firstLevelCache;
094: this .marshallingStrategy = new DefaultMarshallingStrategy(
095: mapping, searchEngine, compass.getConverterLookup(),
096: this );
097: this .cascadingManager = new CascadingManager(this );
098:
099: transactionFactory.tryJoinExistingTransaction(this );
100: }
101:
102: public CompassSettings getSettings() {
103: return runtimeSettings;
104: }
105:
106: public CompassQueryBuilder queryBuilder() throws CompassException {
107: checkClosed();
108: SearchEngineQueryBuilder searchEngineQueryBuilder = searchEngine
109: .queryBuilder();
110: return new DefaultCompassQueryBuilder(searchEngineQueryBuilder,
111: this );
112: }
113:
114: public CompassQueryFilterBuilder queryFilterBuilder()
115: throws CompassException {
116: checkClosed();
117: SearchEngineQueryFilterBuilder searchEngineQueryFilterBuilder = searchEngine
118: .queryFilterBuilder();
119: return new DefaultCompassQueryFilterBuilder(
120: searchEngineQueryFilterBuilder, this );
121: }
122:
123: public CompassTermFreqsBuilder termFreqsBuilder(String... names)
124: throws CompassException {
125: checkClosed();
126: return new DefaultCompassTermFreqsBuilder(this , names);
127: }
128:
129: public CompassAnalyzerHelper analyzerHelper()
130: throws CompassException {
131: checkClosed();
132: SearchEngineAnalyzerHelper analyzerHelper = searchEngine
133: .analyzerHelper();
134: return new DefaultCompassAnalyzerHelper(analyzerHelper, this );
135: }
136:
137: public CompassTransaction beginTransaction()
138: throws CompassException {
139: checkClosed();
140: return transactionFactory.beginTransaction(this , null);
141: }
142:
143: public CompassTransaction beginTransaction(
144: TransactionIsolation transactionIsolation)
145: throws CompassException {
146: checkClosed();
147: if (transactionIsolation == TransactionIsolation.BATCH_INSERT) {
148: firstLevelCache = new NullFirstLevelCache();
149: }
150: return transactionFactory.beginTransaction(this ,
151: transactionIsolation);
152: }
153:
154: public CompassTransaction beginLocalTransaction()
155: throws CompassException {
156: checkClosed();
157: return localTransactionFactory.beginTransaction(this , null);
158: }
159:
160: public void flush() throws CompassException {
161: checkClosed();
162: searchEngine.flush();
163: }
164:
165: public Resource getResource(Class clazz, Object... ids)
166: throws CompassException {
167: return getResource(clazz, (Object) ids);
168: }
169:
170: public Resource getResource(Class clazz, Object id)
171: throws CompassException {
172: checkClosed();
173: Resource idResource = marshallingStrategy
174: .marshallIds(clazz, id);
175: return getResourceByIdResource(idResource);
176: }
177:
178: public Resource getResource(String alias, Object... ids)
179: throws CompassException {
180: return getResource(alias, (Object) ids);
181: }
182:
183: public Resource getResource(String alias, Object id)
184: throws CompassException {
185: checkClosed();
186: Resource idResource = marshallingStrategy
187: .marshallIds(alias, id);
188: return getResourceByIdResource(idResource);
189: }
190:
191: public Resource getResourceByIdResource(Resource idResource) {
192: checkClosed();
193: ResourceKey key = ((InternalResource) idResource).resourceKey();
194: Resource cachedValue = firstLevelCache.getResource(key);
195: if (cachedValue != null) {
196: return cachedValue;
197: }
198: Resource value = searchEngine.get(idResource);
199: firstLevelCache.setResource(key, value);
200: return value;
201: }
202:
203: public <T> T get(Class<T> clazz, Object... ids)
204: throws CompassException {
205: return get(clazz, (Object) ids);
206: }
207:
208: public <T> T get(Class<T> clazz, Object id) throws CompassException {
209: checkClosed();
210: Resource resource = getResource(clazz, id);
211: if (resource == null) {
212: return null;
213: }
214: //noinspection unchecked
215: return (T) getByResource(resource);
216: }
217:
218: public Object get(String alias, Object... ids)
219: throws CompassException {
220: return get(alias, (Object) ids);
221: }
222:
223: public Object get(String alias, Object id) throws CompassException {
224: checkClosed();
225: Resource resource = getResource(alias, id);
226: if (resource == null) {
227: return null;
228: }
229: return getByResource(resource);
230: }
231:
232: public Object get(String alias, Object id,
233: MarshallingContext context) throws CompassException {
234: checkClosed();
235: Resource resource = getResource(alias, id);
236: if (resource == null) {
237: return null;
238: }
239: return getByResource(resource, context);
240: }
241:
242: public Object getByResource(Resource resource) {
243: checkClosed();
244: return getByResource(resource, null);
245: }
246:
247: public Object getByResource(Resource resource,
248: MarshallingContext context) {
249: checkClosed();
250: ResourceKey key = ((InternalResource) resource).resourceKey();
251: Object cachedValue = firstLevelCache.get(key);
252: if (cachedValue != null) {
253: return cachedValue;
254: }
255: Object value;
256: if (context == null) {
257: value = marshallingStrategy.unmarshall(resource);
258: } else {
259: value = marshallingStrategy.unmarshall(resource, context);
260: }
261: firstLevelCache.set(key, value);
262: return value;
263: }
264:
265: public Resource loadResource(Class clazz, Object... ids)
266: throws CompassException {
267: return loadResource(clazz, (Object) ids);
268: }
269:
270: public Resource loadResource(Class clazz, Object id)
271: throws CompassException {
272: checkClosed();
273: Resource idResource = marshallingStrategy
274: .marshallIds(clazz, id);
275: return loadResourceByIdResource(idResource);
276: }
277:
278: public Resource loadResource(String alias, Object... ids)
279: throws CompassException {
280: return loadResource(alias, (Object) ids);
281: }
282:
283: public Resource loadResource(String alias, Object id)
284: throws CompassException {
285: checkClosed();
286: Resource idResource = marshallingStrategy
287: .marshallIds(alias, id);
288: return loadResourceByIdResource(idResource);
289: }
290:
291: public Resource loadResourceByIdResource(Resource idResource) {
292: checkClosed();
293: ResourceKey key = ((InternalResource) idResource).resourceKey();
294: Resource cachedValue = firstLevelCache.getResource(key);
295: if (cachedValue != null) {
296: return cachedValue;
297: }
298: Resource value = searchEngine.load(idResource);
299: firstLevelCache.setResource(key, value);
300: return value;
301: }
302:
303: public <T> T load(Class<T> clazz, Object... ids)
304: throws CompassException {
305: return load(clazz, (Object) ids);
306: }
307:
308: public <T> T load(Class<T> clazz, Object id)
309: throws CompassException {
310: checkClosed();
311: Resource resource = loadResource(clazz, id);
312: //noinspection unchecked
313: return (T) getByResource(resource);
314: }
315:
316: public Object load(String alias, Object... ids)
317: throws CompassException {
318: return load(alias, (Object) ids);
319: }
320:
321: public Object load(String alias, Object id) throws CompassException {
322: checkClosed();
323: Resource resource = loadResource(alias, id);
324: return getByResource(resource);
325: }
326:
327: public CompassHits find(String query) throws CompassException {
328: checkClosed();
329: return queryBuilder().queryString(query).toQuery().hits();
330: }
331:
332: public void create(String alias, Object object)
333: throws CompassException {
334: checkClosed();
335: Resource resource = marshallingStrategy.marshall(alias, object);
336: if (resource != null) {
337: searchEngine.create(resource);
338: ResourceKey key = ((InternalResource) resource)
339: .resourceKey();
340: firstLevelCache.set(key, object);
341: }
342: boolean performedCascading = cascadingManager.cascade(alias,
343: object, CascadeMapping.Cascade.CREATE);
344: if (resource == null && !performedCascading) {
345: throw new MarshallingException(
346: "Alias ["
347: + alias
348: + "] has no root mappings and no cascading defined, no operation was perfomed");
349: }
350: }
351:
352: public void create(Object object) throws CompassException {
353: checkClosed();
354: boolean performedCascading;
355: Resource resource = marshallingStrategy.marshall(object);
356: if (resource != null) {
357: searchEngine.create(resource);
358: ResourceKey key = ((InternalResource) resource)
359: .resourceKey();
360: firstLevelCache.set(key, object);
361: // if we found a resource, we perform the cascading based on its alias
362: performedCascading = cascadingManager.cascade(key
363: .getAlias(), object, CascadeMapping.Cascade.CREATE);
364: } else {
365: // actuall, no root mapping to create a resource, try and create one based on the object
366: performedCascading = cascadingManager.cascade(object,
367: CascadeMapping.Cascade.CREATE);
368: }
369: if (resource == null && !performedCascading) {
370: throw new MarshallingException(
371: "Object ["
372: + object.getClass().getName()
373: + "] has no root mappings and no cascading defined, no operation was perfomed");
374: }
375: }
376:
377: public void save(String alias, Object object)
378: throws CompassException {
379: checkClosed();
380: Resource resource = marshallingStrategy.marshall(alias, object);
381: if (resource != null) {
382: searchEngine.save(resource);
383: ResourceKey key = ((InternalResource) resource)
384: .resourceKey();
385: firstLevelCache.set(key, object);
386: }
387: boolean performedCascading = cascadingManager.cascade(alias,
388: object, CascadeMapping.Cascade.SAVE);
389: if (resource == null && !performedCascading) {
390: throw new MarshallingException(
391: "Alias ["
392: + alias
393: + "] has no root mappings and no cascading defined, no operation was perfomed");
394: }
395: }
396:
397: public void save(Object object) throws CompassException {
398: checkClosed();
399: boolean performedCascading;
400: Resource resource = marshallingStrategy.marshall(object);
401: if (resource != null) {
402: searchEngine.save(resource);
403: ResourceKey key = ((InternalResource) resource)
404: .resourceKey();
405: firstLevelCache.set(key, object);
406: performedCascading = cascadingManager.cascade(key
407: .getAlias(), object, CascadeMapping.Cascade.SAVE);
408: } else {
409: performedCascading = cascadingManager.cascade(object,
410: CascadeMapping.Cascade.SAVE);
411: }
412: if (resource == null && !performedCascading) {
413: throw new MarshallingException(
414: "Object ["
415: + object.getClass().getName()
416: + "] has no root mappings and no cascading defined, no operation was perfomed");
417: }
418: }
419:
420: public void saveResource(Resource resource) throws CompassException {
421: searchEngine.save(resource);
422: }
423:
424: public void delete(String alias, Object... ids)
425: throws CompassException {
426: delete(alias, (Object) ids);
427: }
428:
429: public void delete(String alias, Object obj)
430: throws CompassException {
431: checkClosed();
432: Resource idResource = marshallingStrategy.marshallIds(alias,
433: obj);
434: if (idResource != null) {
435: delete(idResource);
436: }
437: boolean performedCascading = cascadingManager.cascade(alias,
438: obj, CascadeMapping.Cascade.DELETE);
439: if (idResource == null && !performedCascading) {
440: throw new MarshallingException(
441: "Alias ["
442: + alias
443: + "] has no root mappings and no cascading defined, no operation was perfomed");
444: }
445: }
446:
447: public void delete(Class clazz, Object... ids)
448: throws CompassException {
449: delete(clazz, (Object) ids);
450: }
451:
452: public void delete(Class clazz, Object obj) throws CompassException {
453: checkClosed();
454: boolean performedCascading;
455: Resource idResource = marshallingStrategy.marshallIds(clazz,
456: obj);
457: if (idResource != null) {
458: delete(idResource);
459: performedCascading = cascadingManager.cascade(idResource
460: .getAlias(), obj, CascadeMapping.Cascade.DELETE);
461: } else {
462: performedCascading = cascadingManager.cascade(clazz, obj,
463: CascadeMapping.Cascade.DELETE);
464: }
465: if (idResource == null && !performedCascading) {
466: throw new MarshallingException(
467: "Object ["
468: + clazz
469: + "] has no root mappings and no cascading defined, no operation was perfomed");
470: }
471: }
472:
473: public void delete(Object obj) throws CompassException {
474: checkClosed();
475: boolean performedCascading;
476: Resource idResource = marshallingStrategy.marshallIds(obj);
477: if (idResource != null) {
478: delete(idResource);
479: performedCascading = cascadingManager.cascade(idResource
480: .getAlias(), obj, CascadeMapping.Cascade.DELETE);
481: } else {
482: performedCascading = cascadingManager.cascade(obj,
483: CascadeMapping.Cascade.DELETE);
484: }
485: if (idResource == null && !performedCascading) {
486: throw new MarshallingException(
487: "Object ["
488: + obj.getClass().getName()
489: + "] has no root mappings and no cascading defined, no operation was perfomed");
490: }
491: }
492:
493: public void delete(Resource resource) throws CompassException {
494: checkClosed();
495: firstLevelCache.evict(((InternalResource) resource)
496: .resourceKey());
497: searchEngine.delete(resource);
498: }
499:
500: public void delete(CompassQuery query) throws CompassException {
501: checkClosed();
502: // TODO since we don't marshall to objects, we won't get cascading
503: CompassHits hits = query.hits();
504: for (int i = 0; i < hits.length(); i++) {
505: delete(hits.resource(i));
506: }
507: }
508:
509: public void evict(Object obj) {
510: checkClosed();
511: Resource idResource = marshallingStrategy.marshallIds(obj
512: .getClass(), obj);
513: ResourceKey key = ((InternalResource) idResource).resourceKey();
514: firstLevelCache.evict(key);
515: }
516:
517: public void evict(String alias, Object id) {
518: checkClosed();
519: Resource idResource = marshallingStrategy
520: .marshallIds(alias, id);
521: ResourceKey key = ((InternalResource) idResource).resourceKey();
522: firstLevelCache.evict(key);
523: }
524:
525: public void evict(Resource resource) {
526: checkClosed();
527: ResourceKey key = ((InternalResource) resource).resourceKey();
528: firstLevelCache.evict(key);
529: }
530:
531: public void evictAll() {
532: checkClosed();
533: firstLevelCache.evictAll();
534: }
535:
536: public void close() throws CompassException {
537: if (closed) {
538: return;
539: }
540: CompassSession transactionBoundSession = transactionFactory
541: .getTransactionBoundSession();
542: if (transactionBoundSession == null
543: || transactionBoundSession != this ) {
544: closed = true;
545: firstLevelCache.evictAll();
546: searchEngine.close();
547: }
548: }
549:
550: public boolean isClosed() {
551: return this .closed;
552: }
553:
554: public InternalCompass getCompass() {
555: return compass;
556: }
557:
558: public SearchEngine getSearchEngine() {
559: return searchEngine;
560: }
561:
562: public MarshallingStrategy getMarshallingStrategy() {
563: return marshallingStrategy;
564: }
565:
566: public FirstLevelCache getFirstLevelCache() {
567: return firstLevelCache;
568: }
569:
570: public CompassMapping getMapping() {
571: return mapping;
572: }
573:
574: public CompassMetaData getMetaData() {
575: return compassMetaData;
576: }
577:
578: private void checkClosed() throws IllegalStateException {
579: if (closed) {
580: throw new IllegalStateException(
581: "CompassSession already closed");
582: }
583: }
584: }
|