added containsValue method to retrieve value object for maps
[cdmlib.git] / cdmlib-persistence / src / main / java / eu / etaxonomy / cdm / persistence / dao / hibernate / common / CdmGenericDaoImpl.java
1 /**
2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
5 *
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
8 */
9
10 package eu.etaxonomy.cdm.persistence.dao.hibernate.common;
11
12 import java.lang.reflect.Field;
13 import java.lang.reflect.InvocationTargetException;
14 import java.lang.reflect.Method;
15 import java.lang.reflect.Modifier;
16 import java.util.ArrayList;
17 import java.util.Collection;
18 import java.util.HashMap;
19 import java.util.HashSet;
20 import java.util.List;
21 import java.util.Map;
22 import java.util.Set;
23
24 import javax.naming.Reference;
25
26 import org.apache.commons.lang.StringUtils;
27 import org.apache.commons.lang.UnhandledException;
28 import org.apache.log4j.Logger;
29 import org.hibernate.Criteria;
30 import org.hibernate.HibernateException;
31 import org.hibernate.MappingException;
32 import org.hibernate.Query;
33 import org.hibernate.Session;
34 import org.hibernate.SessionFactory;
35 import org.hibernate.collection.internal.AbstractPersistentCollection;
36 import org.hibernate.collection.spi.PersistentCollection;
37 import org.hibernate.criterion.CriteriaSpecification;
38 import org.hibernate.criterion.Criterion;
39 import org.hibernate.criterion.Restrictions;
40 import org.hibernate.engine.spi.CollectionEntry;
41 import org.hibernate.engine.spi.SessionFactoryImplementor;
42 import org.hibernate.engine.spi.SessionImplementor;
43 import org.hibernate.internal.SessionFactoryImpl;
44 import org.hibernate.internal.SessionImpl;
45 import org.hibernate.metadata.ClassMetadata;
46 import org.hibernate.metadata.CollectionMetadata;
47 import org.hibernate.persister.collection.CollectionPersister;
48 import org.hibernate.persister.collection.OneToManyPersister;
49 import org.hibernate.persister.entity.AbstractEntityPersister;
50 import org.hibernate.stat.Statistics;
51 import org.hibernate.type.AnyType;
52 import org.hibernate.type.BooleanType;
53 import org.hibernate.type.CollectionType;
54 import org.hibernate.type.ComponentType;
55 import org.hibernate.type.DoubleType;
56 import org.hibernate.type.EntityType;
57 import org.hibernate.type.EnumType;
58 import org.hibernate.type.FloatType;
59 import org.hibernate.type.IntegerType;
60 import org.hibernate.type.LongType;
61 import org.hibernate.type.MaterializedClobType;
62 import org.hibernate.type.SerializableType;
63 import org.hibernate.type.SetType;
64 import org.hibernate.type.StringType;
65 import org.hibernate.type.Type;
66 import org.jadira.usertype.dateandtime.joda.PersistentDateTime;
67 import org.springframework.dao.DataAccessException;
68 import org.springframework.stereotype.Repository;
69
70 import eu.etaxonomy.cdm.common.CdmUtils;
71 import eu.etaxonomy.cdm.common.DoubleResult;
72 import eu.etaxonomy.cdm.hibernate.DOIUserType;
73 import eu.etaxonomy.cdm.hibernate.EnumUserType;
74 import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
75 import eu.etaxonomy.cdm.hibernate.PartialUserType;
76 import eu.etaxonomy.cdm.hibernate.URIUserType;
77 import eu.etaxonomy.cdm.hibernate.UUIDUserType;
78 import eu.etaxonomy.cdm.hibernate.WSDLDefinitionUserType;
79 import eu.etaxonomy.cdm.model.common.AnnotatableEntity;
80 import eu.etaxonomy.cdm.model.common.Annotation;
81 import eu.etaxonomy.cdm.model.common.CdmBase;
82 import eu.etaxonomy.cdm.model.common.Extension;
83 import eu.etaxonomy.cdm.model.common.ICdmBase;
84 import eu.etaxonomy.cdm.model.common.IdentifiableEntity;
85 import eu.etaxonomy.cdm.model.common.Marker;
86 import eu.etaxonomy.cdm.model.metadata.CdmMetaData;
87 import eu.etaxonomy.cdm.model.name.BotanicalName;
88 import eu.etaxonomy.cdm.model.name.TaxonNameBase;
89 import eu.etaxonomy.cdm.model.taxon.Taxon;
90 import eu.etaxonomy.cdm.persistence.dao.common.ICdmGenericDao;
91 import eu.etaxonomy.cdm.strategy.match.CacheMatcher;
92 import eu.etaxonomy.cdm.strategy.match.DefaultMatchStrategy;
93 import eu.etaxonomy.cdm.strategy.match.FieldMatcher;
94 import eu.etaxonomy.cdm.strategy.match.IMatchStrategy;
95 import eu.etaxonomy.cdm.strategy.match.IMatchable;
96 import eu.etaxonomy.cdm.strategy.match.MatchException;
97 import eu.etaxonomy.cdm.strategy.match.MatchMode;
98 import eu.etaxonomy.cdm.strategy.match.Matching;
99 import eu.etaxonomy.cdm.strategy.merge.DefaultMergeStrategy;
100 import eu.etaxonomy.cdm.strategy.merge.IMergable;
101 import eu.etaxonomy.cdm.strategy.merge.IMergeStrategy;
102 import eu.etaxonomy.cdm.strategy.merge.MergeException;
103
104 @Repository
105 public class CdmGenericDaoImpl extends CdmEntityDaoBase<CdmBase> implements ICdmGenericDao{
106 private static final Logger logger = Logger.getLogger(CdmGenericDaoImpl.class);
107
108
109 private Set<Class<? extends CdmBase>> allCdmClasses = null;
110 private Map<Class<? extends CdmBase>, Set<ReferenceHolder>> referenceMap = new HashMap<Class<? extends CdmBase>, Set<ReferenceHolder>>();
111
112 private class ReferenceHolder{
113 String propertyName;
114 Class<? extends CdmBase> otherClass;
115 Class<? extends CdmBase> itemClass;
116 public boolean isCollection(){return itemClass != null;};
117 public String toString(){return otherClass.getSimpleName() + "." + propertyName ;};
118 }
119
120
121 public CdmGenericDaoImpl() {
122 super(CdmBase.class);
123 }
124
125 @Override
126 public List<CdmBase> getCdmBasesByFieldAndClass(Class clazz, String propertyName, CdmBase referencedCdmBase){
127 Session session = super.getSession();
128 Criteria criteria = session.createCriteria(clazz);
129 criteria.add(Restrictions.eq(propertyName, referencedCdmBase));
130 return criteria.list();
131 }
132
133 @Override
134 public List<CdmBase> getCdmBasesWithItemInCollection(Class itemClass, Class clazz, String propertyName, CdmBase item){
135 Session session = super.getSession();
136 String thisClassStr = itemClass.getSimpleName();
137 String otherClassStr = clazz.getSimpleName();
138 String queryStr = " SELECT other FROM "+ thisClassStr + " this, " + otherClassStr + " other " +
139 " WHERE this = :referencedObject AND this member of other."+propertyName ;
140 Query query = session.createQuery(queryStr).setEntity("referencedObject", item);
141 List<CdmBase> result = query.list();
142 return result;
143 }
144
145 @Override
146 public Set<Class<? extends CdmBase>> getAllCdmClasses(boolean includeAbstractClasses){
147 Set<Class<? extends CdmBase>> result = new HashSet<Class<? extends CdmBase>>();
148
149 SessionFactory sessionFactory = getSession().getSessionFactory();
150 Map<?,?> allClassMetadata = sessionFactory.getAllClassMetadata();
151 Collection<?> keys = allClassMetadata.keySet();
152 for (Object oKey : keys){
153 if (oKey instanceof String){
154 String strKey = (String)oKey;
155 if (! strKey.endsWith("_AUD")){
156 try {
157 Class clazz = Class.forName(strKey);
158 boolean isAbstractClass = Modifier.isAbstract(clazz.getModifiers());
159 if (! isAbstractClass || includeAbstractClasses){
160 result.add(clazz);
161 }
162 } catch (ClassNotFoundException e) {
163 logger.warn("Class not found: " + strKey);
164 }
165 }
166 }else{
167 logger.warn("key is not of type String: " + oKey);
168 }
169 }
170 return result;
171 }
172
173 @Override
174 public Set<CdmBase> getReferencingObjects(CdmBase referencedCdmBase){
175 Set<CdmBase> result = new HashSet<CdmBase>();
176 try {
177 referencedCdmBase = (CdmBase)HibernateProxyHelper.deproxy(referencedCdmBase);
178 Class<? extends CdmBase> referencedClass = referencedCdmBase.getClass();
179
180 Set<ReferenceHolder> holderSet = referenceMap.get(referencedClass);
181 if (holderSet == null){
182 holderSet = makeHolderSet(referencedClass);
183 referenceMap.put(referencedClass, holderSet);
184 }
185 for (ReferenceHolder refHolder: holderSet){
186 handleReferenceHolder(referencedCdmBase, result, refHolder);
187 }
188 return result;
189 } catch (Exception e) {
190 e.printStackTrace();
191 throw new RuntimeException(e);
192 }
193
194 }
195
196 /**
197 * @param referencedCdmBase
198 * @param result
199 * @param refHolder
200 */
201 private void handleReferenceHolder(CdmBase referencedCdmBase,
202 Set<CdmBase> result, ReferenceHolder refHolder) {
203 boolean isCollection = refHolder.isCollection();
204 if (isCollection){
205 result.addAll(getCdmBasesWithItemInCollection(refHolder.itemClass, refHolder.otherClass, refHolder.propertyName, referencedCdmBase));
206 }else{
207 result.addAll(getCdmBasesByFieldAndClass(refHolder.otherClass, refHolder.propertyName, referencedCdmBase));
208 }
209 }
210
211
212 /**
213 * @param referencedClass
214 * @return
215 * @throws NoSuchFieldException
216 * @throws ClassNotFoundException
217 */
218 private Set<ReferenceHolder> makeHolderSet(Class<?> referencedClass) throws ClassNotFoundException, NoSuchFieldException {
219 Set<ReferenceHolder> result = new HashSet<ReferenceHolder>();
220
221 //init
222 if (allCdmClasses == null){
223 allCdmClasses = getAllCdmClasses(false); //findAllCdmClasses();
224 }
225 //referencedCdmBase = (CdmBase)HibernateProxyHelper.deproxy(referencedCdmBase);
226 SessionFactory sessionFactory = getSession().getSessionFactory();
227
228
229 for (Class<? extends CdmBase> cdmClass : allCdmClasses){
230 ClassMetadata classMetadata = sessionFactory.getClassMetadata(cdmClass);
231 Type[] propertyTypes = classMetadata.getPropertyTypes();
232 int propertyNr = 0;
233 for (Type propertyType: propertyTypes){
234 String propertyName = classMetadata.getPropertyNames()[propertyNr];
235 makePropertyType(result, referencedClass, sessionFactory, cdmClass, propertyType, propertyName, false);
236 propertyNr++;
237 }
238
239 }
240 return result;
241 }
242
243 /**
244 * @param referencedCdmBase
245 * @param result
246 * @param referencedClass
247 * @param sessionFactory
248 * @param cdmClass
249 * @param propertyType
250 * @param propertyName
251 * @throws ClassNotFoundException
252 * @throws NoSuchFieldException
253 */
254 private void makePropertyType(
255 // CdmBase referencedCdmBase,
256 Set<ReferenceHolder> result,
257 Class<?> referencedClass,
258 SessionFactory sessionFactory, Class<? extends CdmBase> cdmClass,
259 Type propertyType, String propertyName, boolean isCollection)
260 throws ClassNotFoundException, NoSuchFieldException {
261
262
263 if (propertyType.isEntityType()){
264 EntityType entityType = (EntityType)propertyType;
265 String associatedEntityName = entityType.getAssociatedEntityName();
266 Class<?> entityClass = Class.forName(associatedEntityName);
267 if (entityClass.isInterface()){
268 logger.debug("There is an interface");
269 }
270 if (entityClass.isAssignableFrom(referencedClass)){
271 makeSingleProperty(referencedClass, entityClass, propertyName, cdmClass, result, isCollection);
272 }
273 }else if (propertyType.isCollectionType()){
274 CollectionType collectionType = (CollectionType)propertyType;
275 //String role = collectionType.getRole();
276 Type elType = collectionType.getElementType((SessionFactoryImplementor)sessionFactory);
277 makePropertyType(result, referencedClass, sessionFactory, cdmClass, elType, propertyName, true);
278 }else if (propertyType.isAnyType()){
279 // AnyType anyType = (AnyType)propertyType;
280 Field field = cdmClass.getDeclaredField(propertyName);
281 Class<?> returnType = field.getType();
282 if (returnType.isInterface()){
283 logger.debug("There is an interface");
284 }
285 if (returnType.isAssignableFrom(referencedClass)){
286 makeSingleProperty(referencedClass, returnType, propertyName, cdmClass, result, isCollection);
287 }
288 }else if (propertyType.isComponentType()){
289 ComponentType componentType = (ComponentType)propertyType;
290 Type[] subTypes = componentType.getSubtypes();
291 // Field field = cdmClass.getDeclaredField(propertyName);
292 // Class returnType = field.getType();
293 int propertyNr = 0;
294 for (Type subType: subTypes){
295 String subPropertyName = componentType.getPropertyNames()[propertyNr];
296 if (!isNoDoType(subType)){
297 logger.warn("SubType not yet handled: " + subType);
298 }
299 // handlePropertyType(referencedCdmBase, result, referencedClass,
300 // sessionFactory, cdmClass, subType, subPropertyName, isCollection);
301 propertyNr++;
302 }
303 }else if (isNoDoType(propertyType)){
304 //do nothing
305 }else{
306 logger.warn("propertyType not yet handled: " + propertyType.getName());
307 }
308 //OLD:
309 // if (! type.isInterface()){
310 // if (referencedClass.isAssignableFrom(type)||
311 // type.isAssignableFrom(referencedClass) && CdmBase.class.isAssignableFrom(type)){
312 // handleSingleClass(referencedClass, type, field, cdmClass, result, referencedCdmBase, false);
313 // }
314 // //interface
315 // }else if (type.isAssignableFrom(referencedClass)){
316 // handleSingleClass(referencedClass, type, field, cdmClass, result, referencedCdmBase, false);
317
318 }
319
320 private boolean makeSingleProperty(Class itemClass, Class<?> type, String propertyName, Class cdmClass, Set<ReferenceHolder> result,/*CdmBase item,*/ boolean isCollection){
321 String fieldName = StringUtils.rightPad(propertyName, 30);
322 String className = StringUtils.rightPad(cdmClass.getSimpleName(), 30);
323 String returnTypeName = StringUtils.rightPad(type.getSimpleName(), 30);
324
325 // logger.debug(fieldName + "\t\t" + className + "\t\t" + returnTypeName);
326 ReferenceHolder refHolder = new ReferenceHolder();
327 refHolder.propertyName = propertyName;
328 refHolder.otherClass = cdmClass;
329 refHolder.itemClass = (isCollection ? itemClass : null) ;
330 result.add(refHolder);
331 return true;
332 }
333
334 /**
335 * @param propertyType
336 * @return
337 */
338 private boolean isNoDoType(Type propertyType) {
339 boolean result = false;
340 Class<?>[] classes = new Class[]{
341 PersistentDateTime.class,
342 WSDLDefinitionUserType.class,
343 UUIDUserType.class,
344 PartialUserType.class,
345 StringType.class,
346 BooleanType.class,
347 IntegerType.class,
348 MaterializedClobType.class,
349 LongType.class,
350 FloatType.class,
351 SerializableType.class,
352 DoubleType.class,
353 URIUserType.class,
354 EnumType.class,
355 EnumUserType.class,
356 DOIUserType.class
357 };
358 Set<String> classNames = new HashSet<String>();
359 for (Class<?> clazz: classes){
360 classNames.add(clazz.getCanonicalName());
361 if (clazz == propertyType.getClass()){
362 return true;
363 }
364 }
365 String propertyTypeClassName = propertyType.getName();
366 if (classNames.contains(propertyTypeClassName)){
367 return true;
368 }
369 return result;
370 }
371
372 @Override
373 public List<CdmBase> getHqlResult(String hqlQuery){
374 Query query = getSession().createQuery(hqlQuery);
375 List<CdmBase> result = query.list();
376 return result;
377 }
378
379 @Override
380 public Query getHqlQuery(String hqlQuery){
381 Query query = getSession().createQuery(hqlQuery);
382 return query;
383 }
384
385 @Override
386 public <T extends CdmBase> void merge(T cdmBase1, T cdmBase2, IMergeStrategy mergeStrategy) throws MergeException {
387 Class<T> clazz = (Class<T>)cdmBase1.getClass();
388 SessionImpl session = (SessionImpl) getSession();
389 SessionFactory sessionFactory = session.getSessionFactory();
390 if (mergeStrategy == null){
391 mergeStrategy = DefaultMergeStrategy.NewInstance(cdmBase1.getClass());
392 }
393 try {
394 //test null and types
395 testMergeValid(cdmBase1, cdmBase2);
396
397 //merge objects
398 //externel impl
399 //internal impl
400 session.flush();
401 Set<ICdmBase> deleteSet = new HashSet<ICdmBase>();
402 Set<ICdmBase> cloneSet = new HashSet<ICdmBase>();
403 if (cdmBase1 instanceof IMergable){
404 IMergable mergable1 = (IMergable)cdmBase1;
405 IMergable mergable2 = (IMergable)cdmBase2;
406 deleteSet = mergeStrategy.invoke(mergable1, mergable2, cloneSet);
407 //session.saveOrUpdate(mergable1);
408
409 session.flush();
410 //((IMergable)cdmBase1).mergeInto(cdmBase2, DefaultMergeStrategy.NewInstance(cdmBase1.getClass()));
411 }else{
412 mergeExternal(cdmBase1, cdmBase2, clazz, session);
413 }
414
415
416 if (cdmBase2.getId() > 0){
417 session.saveOrUpdate(cdmBase2);
418 //rearrange references to cdmBase2
419 reallocateReferences(cdmBase1, cdmBase2, sessionFactory, clazz, cloneSet);
420 }
421
422 //remove deleted objects
423
424 //session.delete(null, mergable2, true, null);
425 session.delete(cdmBase2);
426 for (ICdmBase toBeDeleted : deleteSet){
427 logger.debug("Delete " + toBeDeleted);
428 if (toBeDeleted != cdmBase2){
429 session.delete(toBeDeleted);
430 }
431
432 }
433
434 //flush
435 session.flush();
436
437 } catch (Exception e) {
438 throw new MergeException(e);
439 }
440 }
441
442
443 /**
444 * @param <T>
445 * @param cdmBase1
446 * @param cdmBase2
447 * @param clazz
448 * @param sessionFactory
449 * @throws MergeException
450 * @throws ClassNotFoundException
451 * @throws NoSuchFieldException
452 */
453 private <T extends CdmBase> void mergeExternal(T cdmBase1, T cdmBase2, Class<T> clazz,
454 Session session) throws MergeException {
455 // handleAnnotations
456 logger.warn("Merge external");
457 handleAnnotationsEtc(cdmBase1, cdmBase2, session);
458
459 SessionFactoryImpl sessionFactory = (SessionFactoryImpl) session.getSessionFactory();
460
461 Map<String, ClassMetadata> allClassMetadata = sessionFactory.getAllClassMetadata();
462
463 //TODO cast
464 getCollectionRoles(clazz, sessionFactory);
465
466 TaxonNameBase name1 = BotanicalName.NewInstance(null);
467 name1.getTaxonBases();
468
469 Type propType = sessionFactory.getReferencedPropertyType(BotanicalName.class.getCanonicalName(), "taxonBases");
470 Map collMetadata = sessionFactory.getAllCollectionMetadata();
471 //roles = sessionFactory.getCollectionRolesByEntityParticipant("eu.etaxonomy.cdm.model.name.BotanicalName");
472 CollectionPersister collPersister;
473 try {
474 collPersister = sessionFactory.getCollectionPersister(TaxonNameBase.class.getCanonicalName()+".annotations");
475 } catch (MappingException e) {
476 // TODO Auto-generated catch block
477 e.printStackTrace();
478 }
479 // Statistics statistics = sessionFactory.getStatistics();
480 logger.debug("");
481 ClassMetadata taxonMetaData = sessionFactory.getClassMetadata(Taxon.class);
482 String ename = taxonMetaData.getEntityName();
483 try {
484 Reference ref = sessionFactory.getReference();
485 logger.debug("");
486 } catch (Exception e) {
487 // TODO Auto-generated catch block
488 e.printStackTrace();
489 }
490
491 //sessionFactory.get
492 ClassMetadata classMetadata = getSession().getSessionFactory().getClassMetadata(clazz);
493 Type[] propertyTypes = classMetadata.getPropertyTypes();
494 int propertyNr = 0;
495 for (Type propertyType: propertyTypes){
496 String propertyName = classMetadata.getPropertyNames()[propertyNr];
497 logger.debug(propertyName);
498 makeMergeProperty(cdmBase1, cdmBase2, propertyType, propertyName, sessionFactory, false);
499 propertyNr++;
500 }
501 Set<String> collectionRoles;
502 if (classMetadata instanceof AbstractEntityPersister){
503 AbstractEntityPersister persister = (AbstractEntityPersister)classMetadata;
504 String rootName = persister.getRootEntityName();
505 collectionRoles = sessionFactory.getCollectionRolesByEntityParticipant(rootName);
506 for (String collectionRole : collectionRoles){
507 CollectionMetadata collMetadata2 = sessionFactory.getCollectionMetadata(collectionRole);
508 String role = collMetadata2.getRole();
509 Type elType = collMetadata2.getElementType();
510 logger.debug(role);
511 }
512 }
513 }
514
515 /**
516 * @param <T>
517 * @param clazz
518 * @param sessionFactory
519 */
520 private <T> Set<String> getCollectionRoles(Class<T> clazz,
521 SessionFactoryImpl sessionFactory) {
522 Set<String> collectionRoles = null;
523 ClassMetadata classMetaData = sessionFactory.getClassMetadata(clazz);
524 if (classMetaData instanceof AbstractEntityPersister){
525 AbstractEntityPersister persister = (AbstractEntityPersister)classMetaData;
526 String rootName = persister.getRootEntityName();
527 collectionRoles = sessionFactory.getCollectionRolesByEntityParticipant(rootName);
528 for (String collectionRole : collectionRoles){
529 CollectionMetadata collMetadata = sessionFactory.getCollectionMetadata(collectionRole);
530 CollectionPersister collPersister = sessionFactory.getCollectionPersister(collectionRole);
531 logger.debug("");
532 }
533 }else{
534 logger.warn("Class metadata is not of type AbstractEntityPersister");
535 throw new UnhandledException("Class metadata is not of type AbstractEntityPersister", null);
536 }
537 return collectionRoles;
538 }
539
540
541 private <T extends CdmBase> void makeMergeProperty(T cdmBase1, T cdmBase2, Type propertyType, String propertyName, SessionFactoryImpl sessionFactory, boolean isCollection) throws MergeException
542 {
543
544 try {
545 Class<T> clazz = (Class<T>)cdmBase1.getClass();
546 if (isNoDoType(propertyType)){
547 //do nothing
548 }else if (propertyType.isEntityType()){
549 //Field field = clazz.getField(propertyName);
550 EntityType entityType = (EntityType)propertyType;
551 String associatedEntityName = entityType.getAssociatedEntityName();
552 Class entityClass = Class.forName(associatedEntityName);
553 // Type refPropType = sessionFactory.getReferencedPropertyType(entityClass.getCanonicalName(), propertyName);
554 Set<String> collectionRoles = getCollectionRoles(clazz, sessionFactory);
555 for (String collectionRole : collectionRoles){
556 CollectionMetadata collMetadata = sessionFactory.getCollectionMetadata(collectionRole);
557 String role = collMetadata.getRole();
558 logger.debug(role);
559
560 }
561
562 // if (entityClass.isInterface()){
563 // logger.debug("So ein interface");
564 // }
565 // if (entityClass.isAssignableFrom(clazz)){
566 // makeSingleProperty(referencedClass, entityClass, propertyName, cdmClass, result, isCollection);
567 // }
568 }else if (propertyType.isCollectionType()){
569 CollectionType collectionType = (CollectionType)propertyType;
570 String role = collectionType.getRole();
571 Type elType = collectionType.getElementType((SessionFactoryImplementor)sessionFactory);
572 String n = collectionType.getAssociatedEntityName(sessionFactory);
573 CollectionMetadata collMetadata = sessionFactory.getCollectionMetadata(role);
574 if (collMetadata instanceof OneToManyPersister){
575 OneToManyPersister oneManyPersister = (OneToManyPersister)collMetadata;
576 String className = oneManyPersister.getOwnerEntityName();
577 Class<?> myClass = Class.forName(className);
578 Field field = myClass.getDeclaredField(propertyName);
579 field.setAccessible(true);
580 try {
581 if (collectionType instanceof SetType){
582 Set set2 = (Set)field.get(cdmBase2);
583 Set<Object> set1 = (Set<Object>)field.get(cdmBase1);
584 for (Object obj2: set2){
585 set1.add(obj2);
586 }
587 }
588 } catch (IllegalArgumentException e) {
589 // TODO Auto-generated catch block
590 e.printStackTrace();
591 } catch (IllegalAccessException e) {
592 // TODO Auto-generated catch block
593 e.printStackTrace();
594 }
595
596 }
597 logger.debug("");
598
599 // makePropertyType(result, referencedClass, sessionFactory, cdmClass, elType, propertyName, true);
600 }else if (propertyType.isAnyType()){
601 AnyType anyType = (AnyType)propertyType;
602 Field field = clazz.getDeclaredField(propertyName);
603 Class returnType = field.getType();
604 // if (returnType.isInterface()){
605 // logger.debug("So ein interface");
606 // }
607 // if (returnType.isAssignableFrom(referencedClass)){
608 // makeSingleProperty(referencedClass, returnType, propertyName, cdmClass, result, isCollection);
609 // }
610 }else if (propertyType.isComponentType()){
611 ComponentType componentType = (ComponentType)propertyType;
612 Type[] subTypes = componentType.getSubtypes();
613 // Field field = cdmClass.getDeclaredField(propertyName);
614 // Class returnType = field.getType();
615 int propertyNr = 0;
616 for (Type subType: subTypes){
617 String subPropertyName = componentType.getPropertyNames()[propertyNr];
618 if (!isNoDoType(subType)){
619 logger.warn("SubType not yet handled: " + subType);
620 }
621 // handlePropertyType(referencedCdmBase, result, referencedClass,
622 // sessionFactory, cdmClass, subType, subPropertyName, isCollection);
623 propertyNr++;
624 }
625 }else{
626 logger.warn("propertyType not yet handled: " + propertyType.getName());
627 }
628 //OLD:
629 // if (! type.isInterface()){
630 // if (referencedClass.isAssignableFrom(type)||
631 // type.isAssignableFrom(referencedClass) && CdmBase.class.isAssignableFrom(type)){
632 // handleSingleClass(referencedClass, type, field, cdmClass, result, referencedCdmBase, false);
633 // }
634 // //interface
635 // }else if (type.isAssignableFrom(referencedClass)){
636 // handleSingleClass(referencedClass, type, field, cdmClass, result, referencedCdmBase, false);
637 } catch (Exception e) {
638 throw new MergeException(e);
639 }
640 }
641
642
643
644
645 private void reallocateReferences(CdmBase cdmBase1, CdmBase cdmBase2, SessionFactory sessionFactory, Class clazz, Set<ICdmBase> cloneSet){
646 try {
647 Set<ReferenceHolder> holderSet = referenceMap.get(clazz);
648 if (holderSet == null){
649 holderSet = makeHolderSet(clazz);
650 referenceMap.put(clazz, holderSet);
651 }
652 for (ReferenceHolder refHolder: holderSet){
653 reallocateByHolder(cdmBase1, cdmBase2, refHolder, cloneSet);
654 }
655 return;
656 } catch (Exception e) {
657 e.printStackTrace();
658 throw new RuntimeException(e);
659 }
660 }
661
662 /**
663 * @param cdmBase1
664 * @param cdmBase2
665 * @param refHolder
666 * @throws MergeException
667 */
668 private void reallocateByHolder(CdmBase cdmBase1, CdmBase cdmBase2, ReferenceHolder refHolder, Set<ICdmBase> cloneSet) throws MergeException {
669 try {
670 if (refHolder.isCollection()){
671 reallocateCollection(cdmBase1, cdmBase2, refHolder, cloneSet);
672 }else{
673 reallocateSingleItem(cdmBase1, cdmBase2, refHolder, cloneSet);
674 }
675 } catch (Exception e) {
676 throw new MergeException("Error during reallocation of references to merge object: " + cdmBase2, e);
677 }
678
679 }
680
681 /**
682 * @param cdmBase1
683 * @param cdmBase2
684 * @param refHolder
685 * @param cloneSet
686 * @throws MergeException
687 * @throws NoSuchFieldException
688 * @throws SecurityException
689 * @throws IllegalAccessException
690 * @throws IllegalArgumentException
691 * @throws InvocationTargetException
692 */
693 private void reallocateCollection(CdmBase cdmBase1, CdmBase cdmBase2,
694 ReferenceHolder refHolder, Set<ICdmBase> cloneSet) throws MergeException, SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
695 List<CdmBase> list = getCdmBasesWithItemInCollection(refHolder.itemClass, refHolder.otherClass, refHolder.propertyName, cdmBase2);
696 for (CdmBase referencingObject : list){
697 Field referencingField = getFieldRecursive(refHolder.otherClass, refHolder.propertyName);
698 referencingField.setAccessible(true);
699 Object collection = referencingField.get(referencingObject);
700 if (! (collection instanceof Collection)){
701 throw new MergeException ("Reallocation of collections for collection other than set and list not yet implemented");
702 }
703 Method addMethod = DefaultMergeStrategy.getAddMethod(referencingField, false);
704 Method removeMethod = DefaultMergeStrategy.getAddMethod(referencingField, true);
705 addMethod.invoke(referencingObject, cdmBase1);
706 removeMethod.invoke(referencingObject, cdmBase2);
707 }
708 }
709
710 private Field getFieldRecursive(Class clazz, String propertyName) throws NoSuchFieldException{
711 try {
712 return clazz.getDeclaredField(propertyName);
713 } catch (NoSuchFieldException e) {
714 Class superClass = clazz.getSuperclass();
715 if (CdmBase.class.isAssignableFrom(superClass)){
716 return getFieldRecursive(superClass, propertyName);
717 }else{
718 throw e;
719 }
720 }
721 }
722
723 /**
724 * @throws NoSuchFieldException
725 * @throws SecurityException
726 * @throws IllegalAccessException
727 * @throws IllegalArgumentException
728 *
729 */
730 private void reallocateSingleItem_Old(CdmBase cdmBase1, CdmBase cdmBase2, ReferenceHolder refHolder) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
731 List<CdmBase> referencingObjects = getCdmBasesByFieldAndClass(refHolder.otherClass, refHolder.propertyName, cdmBase2);
732 for (CdmBase referencingObject : referencingObjects){
733 Field referencingField = refHolder.otherClass.getDeclaredField(refHolder.propertyName);
734 referencingField.setAccessible(true);
735 Object test = referencingField.get(referencingObject);
736 assert(test.equals(cdmBase2));
737 referencingField.set(referencingObject, cdmBase1);
738 }
739 }
740
741 private void reallocateSingleItem(CdmBase cdmBase1, CdmBase cdmBase2, ReferenceHolder refHolder, Set<ICdmBase> cloneSet) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
742 List<CdmBase> referencingObjects = getCdmBasesByFieldAndClass(refHolder.otherClass, refHolder.propertyName, cdmBase2);
743 Session session = getSession();
744 for (CdmBase referencingObject : referencingObjects){
745 if (!cloneSet.contains(referencingObject)){
746 String className = refHolder.otherClass.getSimpleName();
747 String propertyName = refHolder.propertyName;
748 String hql = "update " + className + " c set c."+propertyName+" = :newValue where c.id = :id";
749 Query query = session.createQuery(hql);
750 query.setEntity("newValue", cdmBase1);
751 query.setInteger("id",referencingObject.getId());
752 int rowCount = query.executeUpdate();
753 logger.debug("Rows affected: " + rowCount);
754 session.refresh(referencingObject);
755 }
756 }
757 session.flush();
758 }
759
760
761
762 /**
763 * @param <T>
764 * @param cdmBase1
765 * @param cdmBase2
766 * @param session
767 */
768 private <T> void handleAnnotationsEtc(T cdmBase1, T cdmBase2, Session session) {
769 //when handling annotations and other elements linked via @Any an JDBC errors occurs
770 //due to the unique column constraint in the association table on the column referencing
771 //the annotation.
772 //For some reason not delete command is executed for the old collection
773 // Hibernate bug ??
774 session.flush(); //for debugging
775 if (cdmBase1 instanceof AnnotatableEntity){
776 AnnotatableEntity annotatableEntity1 = (AnnotatableEntity)cdmBase1;
777 AnnotatableEntity annotatableEntity2 = (AnnotatableEntity)cdmBase2;
778 //annotations
779 List<Annotation> removeListAnnotation = new ArrayList<Annotation>();
780 for (Annotation annotation : annotatableEntity2.getAnnotations()){
781 Annotation clone = null;
782 try {
783 clone = annotation.clone(annotatableEntity1);
784 } catch (CloneNotSupportedException e) {
785 e.printStackTrace();
786 }
787 annotatableEntity1.addAnnotation(clone);
788 removeListAnnotation.add(annotation);
789 }
790 for (Annotation annotation : removeListAnnotation){
791 annotatableEntity2.removeAnnotation(annotation);
792 getSession().delete(annotation);
793 }
794 //marker
795 List<Marker> removeListMarker = new ArrayList<Marker>();
796 for (Marker marker : annotatableEntity2.getMarkers()){
797 Marker clone = null;
798 try {
799 clone = marker.clone(annotatableEntity1);
800 } catch (CloneNotSupportedException e) {
801 e.printStackTrace();
802 }
803 annotatableEntity1.addMarker(clone);
804 removeListMarker.add(marker);
805 }
806 for (Marker marker : removeListMarker){
807 annotatableEntity2.removeMarker(marker);
808 getSession().delete(marker);
809 }
810 }
811 if (cdmBase1 instanceof IdentifiableEntity){
812 IdentifiableEntity identifiableEntity1 = (IdentifiableEntity)cdmBase1;
813 IdentifiableEntity identifiableEntity2 = (IdentifiableEntity)cdmBase2;
814 //annotations
815 List<Extension> removeListExtension = new ArrayList<Extension>();
816 for (Extension changeObject : (Set<Extension>)identifiableEntity2.getExtensions()){
817 try {
818 Extension clone = changeObject.clone(identifiableEntity1);
819 identifiableEntity1.addExtension(clone);
820 removeListExtension.add(changeObject);
821 } catch (CloneNotSupportedException e) {
822 e.printStackTrace();
823 }
824
825 }
826 for (Extension removeObject : removeListExtension){
827 identifiableEntity2.removeExtension(removeObject);
828 getSession().delete(removeObject);
829 }
830 }
831
832 session.saveOrUpdate(cdmBase1);
833 session.saveOrUpdate(cdmBase2);
834 session.flush();
835 }
836
837 private <T extends CdmBase> void testMergeValid(T cdmBase1, T cdmBase2)throws IllegalArgumentException, NullPointerException{
838 if (cdmBase1 == null || cdmBase2 == null){
839 throw new NullPointerException("Merge arguments must not be (null)");
840 }
841 cdmBase1 = (T)HibernateProxyHelper.deproxy(cdmBase1);
842 cdmBase2 = (T)HibernateProxyHelper.deproxy(cdmBase2);
843
844 if (cdmBase1.getClass() != cdmBase2.getClass()){
845 throw new IllegalArgumentException("Merge arguments must be of same type");
846 }
847 }
848
849 //TODO Move to test classes if still needed
850 private void test() {
851 SessionFactoryImpl factory = (SessionFactoryImpl)getSession().getSessionFactory();
852 Type propType = factory.getReferencedPropertyType(BotanicalName.class.getCanonicalName(), "titleCache");
853 Map collMetadata = factory.getAllCollectionMetadata();
854 Object roles = factory.getCollectionRolesByEntityParticipant("eu.etaxonomy.cdm.model.name.BotanicalName");
855 CollectionPersister collPersister;
856 try {
857 collPersister = factory.getCollectionPersister(TaxonNameBase.class.getCanonicalName()+".annotations");
858 } catch (MappingException e) {
859 // TODO Auto-generated catch block
860 e.printStackTrace();
861 }
862 Statistics statistics = factory.getStatistics();
863 Map allClassMetadata = factory.getAllClassMetadata();
864 logger.debug("");
865
866 }
867
868 @Override
869 public <T extends CdmBase> T find(Class<T> clazz, int id){
870 Session session;
871 session = getSession();
872 //session = getSession().getSessionFactory().getCurrentSession();
873 Object o = session.get(clazz, id);
874 return (T)o;
875 }
876
877 @Override
878 public <T extends IMatchable> List<T> findMatching(T objectToMatch,
879 IMatchStrategy matchStrategy) throws MatchException {
880 try {
881 List<T> result = new ArrayList<T>();
882 if(objectToMatch == null){
883 return result;
884 }
885 if (matchStrategy == null){
886 matchStrategy = DefaultMatchStrategy.NewInstance(objectToMatch.getClass());
887 }
888 result.addAll(findMatchingNullSafe(objectToMatch, matchStrategy));
889 return result;
890 } catch (IllegalArgumentException e) {
891 throw new MatchException(e);
892 } catch (IllegalAccessException e) {
893 throw new MatchException(e);
894 }
895 }
896
897 private <T extends IMatchable> List<T> findMatchingNullSafe(T objectToMatch, IMatchStrategy matchStrategy) throws IllegalArgumentException, IllegalAccessException, MatchException {
898 List<T> result = new ArrayList<T>();
899 Session session = getSession();
900 Class<?> matchClass = objectToMatch.getClass();
901 ClassMetadata classMetaData = session.getSessionFactory().getClassMetadata(matchClass.getCanonicalName());
902 Criteria criteria = session.createCriteria(matchClass);
903 boolean noMatch = makeCriteria(objectToMatch, matchStrategy, classMetaData, criteria);
904 logger.debug(criteria);
905 //session.flush();
906 if (noMatch == false){
907 List<T> matchCandidates = criteria.list();
908 matchCandidates.remove(objectToMatch);
909 for (T matchCandidate : matchCandidates ){
910 if (matchStrategy.invoke(objectToMatch, matchCandidate)){
911 result.add(matchCandidate);
912 }else{
913 logger.warn("Match candidate did not match: " + matchCandidate);
914 }
915 }
916 }
917 return result;
918 }
919
920 /**
921 * @param <T>
922 * @param objectToMatch
923 * @param matchStrategy
924 * @param classMetaData
925 * @param criteria
926 * @return
927 * @throws IllegalAccessException
928 * @throws MatchException
929 */
930 private <T> boolean makeCriteria(T objectToMatch,
931 IMatchStrategy matchStrategy, ClassMetadata classMetaData,
932 Criteria criteria) throws IllegalAccessException, MatchException {
933 Matching matching = matchStrategy.getMatching();
934 boolean noMatch = false;
935 Map<String, List<MatchMode>> replaceMatchers = new HashMap<String, List<MatchMode>>();
936 for (CacheMatcher cacheMatcher: matching.getCacheMatchers()){
937 boolean cacheProtected = (Boolean)cacheMatcher.getProtectedField(matching).get(objectToMatch);
938 if (cacheProtected == true){
939 String cacheValue = (String)cacheMatcher.getField().get(objectToMatch);
940 if (StringUtils.isBlank(cacheValue)){
941 return true; //no match
942 }else{
943 criteria.add(Restrictions.eq(cacheMatcher.getPropertyName(), cacheValue));
944 criteria.add(Restrictions.eq(cacheMatcher.getProtectedPropertyName(), cacheProtected));
945
946 List<DoubleResult<String, MatchMode>> replacementModes = cacheMatcher.getReplaceMatchModes(matching);
947 for (DoubleResult<String, MatchMode> replacementMode: replacementModes ){
948 String propertyName = replacementMode.getFirstResult();
949 List<MatchMode> replaceMatcherList = replaceMatchers.get(propertyName);
950 if (replaceMatcherList == null){
951 replaceMatcherList = new ArrayList<MatchMode>();
952 replaceMatchers.put(propertyName, replaceMatcherList);
953 }
954 replaceMatcherList.add(replacementMode.getSecondResult());
955 }
956
957 }
958 }
959 }
960 for (FieldMatcher fieldMatcher : matching.getFieldMatchers(false)){
961 String propertyName = fieldMatcher.getPropertyName();
962 Type propertyType = classMetaData.getPropertyType(propertyName);
963 Object value = fieldMatcher.getField().get(objectToMatch);
964 List<MatchMode> matchModes= new ArrayList<MatchMode>();
965 matchModes.add(fieldMatcher.getMatchMode());
966 if (replaceMatchers.get(propertyName) != null){
967 matchModes.addAll(replaceMatchers.get(propertyName));
968 }
969
970 boolean isIgnore = false;
971 for (MatchMode matchMode : matchModes){
972 isIgnore |= matchMode.isIgnore(value);
973 }
974 if (! isIgnore ){
975 if (propertyType.isComponentType()){
976 matchComponentType(criteria, fieldMatcher, propertyName, value, matchModes);
977 }else{
978 noMatch = matchNonComponentType(criteria, fieldMatcher, propertyName, value, matchModes, propertyType);
979 }
980 }
981 if (noMatch){
982 return noMatch;
983 }
984 }
985 return noMatch;
986 }
987
988 /**
989 * @param criteria
990 * @param fieldMatcher
991 * @param propertyName
992 * @param value
993 * @param matchMode
994 * @throws MatchException
995 * @throws IllegalAccessException
996 */
997 private void matchComponentType(Criteria criteria,
998 FieldMatcher fieldMatcher, String propertyName, Object value,
999 List<MatchMode> matchModes) throws MatchException, IllegalAccessException {
1000 if (value == null){
1001 boolean requiresSecondNull = requiresSecondNull(matchModes, value);
1002 if (requiresSecondNull){
1003 criteria.add(Restrictions.isNull(propertyName));
1004 }else{
1005 //TODO
1006 logger.warn("Component type not yet implemented for (null) value: " + propertyName);
1007 throw new MatchException("Component type not yet fully implemented for (null) value. Property: " + propertyName);
1008 }
1009 }else{
1010 Class<?> componentClass = fieldMatcher.getField().getType();
1011 Map<String, Field> fields = CdmUtils.getAllFields(componentClass, Object.class, false, false, true, false);
1012 for (String fieldName : fields.keySet()){
1013 String restrictionPath = propertyName +"."+fieldName;
1014 Object componentValue = fields.get(fieldName).get(value);
1015 //TODO diffentiate matchMode
1016 createCriterion(criteria, restrictionPath, componentValue, matchModes);
1017 }
1018 }
1019 }
1020
1021 private boolean matchNonComponentType(Criteria criteria,
1022 FieldMatcher fieldMatcher, String propertyName, Object value,
1023 List<MatchMode> matchModes, Type propertyType) throws HibernateException, DataAccessException, MatchException, IllegalAccessException{
1024 boolean noMatch = false;
1025 if (isRequired(matchModes) && value == null){
1026 noMatch = true;
1027 return noMatch;
1028 }else if (requiresSecondNull(matchModes,value)){
1029 criteria.add(Restrictions.isNull(propertyName));
1030 }else{
1031 if (isMatch(matchModes)){
1032 if (propertyType.isCollectionType()){
1033 //TODO collection not yet handled for match
1034 }else{
1035 int joinType = CriteriaSpecification.INNER_JOIN;
1036 if (! requiresSecondValue(matchModes,value)){
1037 joinType = CriteriaSpecification.LEFT_JOIN;
1038 }
1039 Criteria matchCriteria = criteria.createCriteria(propertyName, joinType).add(Restrictions.isNotNull("id"));
1040 Class matchClass = value.getClass();
1041 if (IMatchable.class.isAssignableFrom(matchClass)){
1042 IMatchStrategy valueMatchStrategy = DefaultMatchStrategy.NewInstance((Class<IMatchable>)matchClass);
1043 ClassMetadata valueClassMetaData = getSession().getSessionFactory().getClassMetadata(matchClass.getCanonicalName());;
1044 noMatch = makeCriteria(value, valueMatchStrategy, valueClassMetaData, matchCriteria);
1045 }else{
1046 logger.error("Class to match (" + matchClass + ") is not of type IMatchable");
1047 throw new MatchException("Class to match (" + matchClass + ") is not of type IMatchable");
1048 }
1049 }
1050 }else if (isEqual(matchModes)){
1051 createCriterion(criteria, propertyName, value, matchModes);
1052 }else {
1053 logger.warn("Unhandled match mode: " + matchModes + ", value: " + (value==null?"null":value));
1054 }
1055 }
1056 return noMatch;
1057 }
1058
1059 /**
1060 * @param criteria
1061 * @param propertyName
1062 * @param value
1063 * @param matchMode
1064 * @throws MatchException
1065 */
1066 private void createCriterion(Criteria criteria, String propertyName,
1067 Object value, List<MatchMode> matchModes) throws MatchException {
1068 Criterion finalRestriction = null;
1069 Criterion equalRestriction = Restrictions.eq(propertyName, value);
1070 Criterion nullRestriction = Restrictions.isNull(propertyName);
1071 if (this.requiresSecondValue(matchModes, value)){
1072 finalRestriction = equalRestriction;
1073 }else if (requiresSecondNull(matchModes, value) ){
1074 finalRestriction = nullRestriction;
1075 }else{
1076 finalRestriction = Restrictions.or(equalRestriction, nullRestriction);
1077 }
1078 //return finalRestriction;
1079 criteria.add(finalRestriction);
1080 }
1081
1082 /**
1083 * @param matchModes
1084 * @param value
1085 * @return
1086 * @throws MatchException
1087 */
1088 private boolean requiresSecondNull(List<MatchMode> matchModes, Object value) throws MatchException {
1089 boolean result = true;
1090 for (MatchMode matchMode: matchModes){
1091 result &= matchMode.requiresSecondNull(value);
1092 }
1093 return result;
1094 }
1095
1096 /**
1097 * @param matchModes
1098 * @param value
1099 * @return
1100 * @throws MatchException
1101 */
1102 private boolean requiresSecondValue(List<MatchMode> matchModes, Object value) throws MatchException {
1103 boolean result = true;
1104 for (MatchMode matchMode: matchModes){
1105 result &= matchMode.requiresSecondValue(value);
1106 }
1107 return result;
1108 }
1109
1110 /**
1111 * @param matchModes
1112 * @param value
1113 * @return
1114 * @throws MatchException
1115 */
1116 private boolean isRequired(List<MatchMode> matchModes) throws MatchException {
1117 boolean result = true;
1118 for (MatchMode matchMode: matchModes){
1119 result &= matchMode.isRequired();
1120 }
1121 return result;
1122 }
1123
1124 /**
1125 * Returns true if at least one match mode is of typ MATCH_XXX
1126 * @param matchModes
1127 * @param value
1128 * @return
1129 * @throws MatchException
1130 */
1131 private boolean isMatch(List<MatchMode> matchModes) throws MatchException {
1132 boolean result = false;
1133 for (MatchMode matchMode: matchModes){
1134 result |= matchMode.isMatch();
1135 }
1136 return result;
1137 }
1138
1139 /**
1140 * Returns true if at least one match mode is of typ EQUAL_XXX
1141 * @param matchModes
1142 * @param value
1143 * @return
1144 * @throws MatchException
1145 */
1146 private boolean isEqual(List<MatchMode> matchModes) throws MatchException {
1147 boolean result = false;
1148 for (MatchMode matchMode: matchModes){
1149 result |= matchMode.isEqual();
1150 }
1151 return result;
1152 }
1153
1154 /* (non-Javadoc)
1155 * @see eu.etaxonomy.cdm.persistence.dao.common.ICdmGenericDao#saveMetaData(eu.etaxonomy.cdm.model.common.CdmMetaData)
1156 */
1157 public void saveMetaData(CdmMetaData cdmMetaData) {
1158 getSession().saveOrUpdate(cdmMetaData);
1159 }
1160
1161 /* (non-Javadoc)
1162 * @see eu.etaxonomy.cdm.persistence.dao.common.ICdmGenericDao#getMetaData()
1163 */
1164 public List<CdmMetaData> getMetaData() {
1165 Session session = getSession();
1166 Criteria crit = session.createCriteria(CdmMetaData.class);
1167 List<CdmMetaData> results = crit.list();
1168 return results;
1169 }
1170
1171 @Override
1172 public PersistentCollection initializeCollection(PersistentCollection col) {
1173 Session session = getSession();
1174 col.setCurrentSession((SessionImplementor) session);
1175
1176 if(!((SessionImplementor)session).getPersistenceContext().getCollectionEntries().containsKey(col)) {
1177 ((SessionImplementor)session).getPersistenceContext().addUninitializedDetachedCollection(
1178 ((SessionImplementor)session).getFactory().getCollectionPersister( col.getRole() ),col);
1179 }
1180 col.forceInitialization();
1181 logger.debug("initialising persistent collection with with role : " + col.getRole() + " and key : " + col.getKey());
1182 return col;
1183 }
1184
1185 @Override
1186 public boolean isEmpty(PersistentCollection col) {
1187 return initializeCollection(col).empty();
1188 }
1189
1190 @Override
1191 public int size(PersistentCollection col) {
1192 logger.debug("remote size() - for role : " + col.getRole() + " and key : " + col.getKey());
1193 initializeCollection(col);
1194 SessionImplementor session = (SessionImplementor)getSession();
1195 CollectionEntry entry = session.getPersistenceContext().getCollectionEntry(col);
1196
1197 if ( entry != null ) {
1198
1199 CollectionPersister persister = entry.getLoadedPersister();
1200 return persister.getSize( entry.getLoadedKey(), session );
1201 }
1202 return -1;
1203 }
1204
1205 @Override
1206 public Object get(PersistentCollection col, int index) {
1207 logger.debug("remote get() - for role : " + col.getRole() + " and key : " + col.getKey());
1208 initializeCollection(col);
1209 SessionImplementor session = (SessionImplementor)getSession();
1210 CollectionEntry entry = session.getPersistenceContext().getCollectionEntry(col);
1211
1212 if ( entry != null ) {
1213
1214 CollectionPersister persister = entry.getLoadedPersister();
1215 return persister.getElementByIndex(entry.getLoadedKey(), index, session, col);
1216
1217 }
1218 //FIXME:Remoting Should we not be throwing an exception here ?
1219 return null;
1220 }
1221
1222 @Override
1223 public boolean contains(PersistentCollection col, Object element) {
1224 logger.debug("remote contains() - for role : " + col.getRole() + " and key : " + col.getKey());
1225 initializeCollection(col);
1226 SessionImplementor session = (SessionImplementor)getSession();
1227 CollectionEntry entry = session.getPersistenceContext().getCollectionEntry(col);
1228
1229 if ( entry != null ) {
1230
1231 CollectionPersister persister = entry.getLoadedPersister();
1232 return persister.elementExists(entry.getLoadedKey(), element, session);
1233 }
1234 //FIXME:Remoting Should we not be throwing an exception here ?
1235 return false;
1236 }
1237
1238 @Override
1239 public boolean containsKey(PersistentCollection col, Object key) {
1240 logger.debug("remote containsKey() - for role : " + col.getRole() + " and key : " + col.getKey());
1241 initializeCollection(col);
1242 SessionImplementor session = (SessionImplementor)getSession();
1243 CollectionEntry entry = session.getPersistenceContext().getCollectionEntry(col);
1244
1245 if ( entry != null ) {
1246
1247 CollectionPersister persister = entry.getLoadedPersister();
1248 return persister.indexExists(entry.getLoadedKey(), key, session);
1249 }
1250 //FIXME:Remoting Should we not be throwing an exception here ?
1251 return false;
1252
1253 }
1254
1255 @Override
1256 public boolean containsValue(PersistentCollection col, Object element) {
1257 return contains(col, element);
1258 }
1259
1260
1261 }
1262
1263