Major Update to cdmlib-3.3
[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.criterion.CriteriaSpecification;
36 import org.hibernate.criterion.Criterion;
37 import org.hibernate.criterion.Restrictions;
38 import org.hibernate.engine.spi.SessionFactoryImplementor;
39 import org.hibernate.internal.SessionFactoryImpl;
40 import org.hibernate.internal.SessionImpl;
41 import org.hibernate.metadata.ClassMetadata;
42 import org.hibernate.metadata.CollectionMetadata;
43 import org.hibernate.persister.collection.CollectionPersister;
44 import org.hibernate.persister.collection.OneToManyPersister;
45 import org.hibernate.persister.entity.AbstractEntityPersister;
46 import org.hibernate.stat.Statistics;
47 import org.hibernate.type.AnyType;
48 import org.hibernate.type.BooleanType;
49 import org.hibernate.type.CollectionType;
50 import org.hibernate.type.ComponentType;
51 import org.hibernate.type.DoubleType;
52 import org.hibernate.type.EntityType;
53 import org.hibernate.type.EnumType;
54 import org.hibernate.type.FloatType;
55 import org.hibernate.type.IntegerType;
56 import org.hibernate.type.LongType;
57 import org.hibernate.type.MaterializedClobType;
58 import org.hibernate.type.SerializableType;
59 import org.hibernate.type.SetType;
60 import org.hibernate.type.StringType;
61 import org.hibernate.type.Type;
62 import org.jadira.usertype.dateandtime.joda.PersistentDateTime;
63 import org.springframework.dao.DataAccessException;
64 import org.springframework.stereotype.Repository;
65
66 import eu.etaxonomy.cdm.common.CdmUtils;
67 import eu.etaxonomy.cdm.common.DoubleResult;
68 import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
69 import eu.etaxonomy.cdm.hibernate.PartialUserType;
70 import eu.etaxonomy.cdm.hibernate.URIUserType;
71 import eu.etaxonomy.cdm.hibernate.UUIDUserType;
72 import eu.etaxonomy.cdm.hibernate.WSDLDefinitionUserType;
73 import eu.etaxonomy.cdm.model.common.AnnotatableEntity;
74 import eu.etaxonomy.cdm.model.common.Annotation;
75 import eu.etaxonomy.cdm.model.common.CdmBase;
76 import eu.etaxonomy.cdm.model.common.Extension;
77 import eu.etaxonomy.cdm.model.common.ICdmBase;
78 import eu.etaxonomy.cdm.model.common.IdentifiableEntity;
79 import eu.etaxonomy.cdm.model.common.Marker;
80 import eu.etaxonomy.cdm.model.metadata.CdmMetaData;
81 import eu.etaxonomy.cdm.model.name.BotanicalName;
82 import eu.etaxonomy.cdm.model.name.TaxonNameBase;
83 import eu.etaxonomy.cdm.model.taxon.Taxon;
84 import eu.etaxonomy.cdm.persistence.dao.common.ICdmGenericDao;
85 import eu.etaxonomy.cdm.strategy.match.CacheMatcher;
86 import eu.etaxonomy.cdm.strategy.match.DefaultMatchStrategy;
87 import eu.etaxonomy.cdm.strategy.match.FieldMatcher;
88 import eu.etaxonomy.cdm.strategy.match.IMatchStrategy;
89 import eu.etaxonomy.cdm.strategy.match.IMatchable;
90 import eu.etaxonomy.cdm.strategy.match.MatchException;
91 import eu.etaxonomy.cdm.strategy.match.MatchMode;
92 import eu.etaxonomy.cdm.strategy.match.Matching;
93 import eu.etaxonomy.cdm.strategy.merge.DefaultMergeStrategy;
94 import eu.etaxonomy.cdm.strategy.merge.IMergable;
95 import eu.etaxonomy.cdm.strategy.merge.IMergeStrategy;
96 import eu.etaxonomy.cdm.strategy.merge.MergeException;
97
98 @Repository
99 public class CdmGenericDaoImpl extends CdmEntityDaoBase<CdmBase> implements ICdmGenericDao{
100 private static final Logger logger = Logger.getLogger(CdmGenericDaoImpl.class);
101
102
103 private Set<Class<? extends CdmBase>> allCdmClasses = null;
104 private Map<Class<? extends CdmBase>, Set<ReferenceHolder>> referenceMap = new HashMap<Class<? extends CdmBase>, Set<ReferenceHolder>>();
105
106 private class ReferenceHolder{
107 String propertyName;
108 Class<? extends CdmBase> otherClass;
109 Class<? extends CdmBase> itemClass;
110 public boolean isCollection(){return itemClass != null;};
111 public String toString(){return otherClass.getSimpleName() + "." + propertyName ;};
112 }
113
114
115 public CdmGenericDaoImpl() {
116 super(CdmBase.class);
117 }
118
119 /* (non-Javadoc)
120 * @see eu.etaxonomy.cdm.persistence.dao.common.ICdmGenericDao#getCdmBasesByFieldAndClass(java.lang.Class, java.lang.String, eu.etaxonomy.cdm.model.common.CdmBase)
121 */
122
123 public List<CdmBase> getCdmBasesByFieldAndClass(Class clazz, String propertyName, CdmBase referencedCdmBase){
124 Session session = super.getSession();
125 Criteria criteria = session.createCriteria(clazz);
126 criteria.add(Restrictions.eq(propertyName, referencedCdmBase));
127 return criteria.list();
128 }
129
130 /* (non-Javadoc)
131 * @see eu.etaxonomy.cdm.persistence.dao.common.ICdmGenericDao#getCdmBasesByFieldAndClass(java.lang.Class, java.lang.String, eu.etaxonomy.cdm.model.common.CdmBase)
132 */
133 public List<CdmBase> getCdmBasesWithItemInCollection(Class itemClass, Class clazz, String propertyName, CdmBase item){
134 Session session = super.getSession();
135 String thisClassStr = itemClass.getSimpleName();
136 String otherClassStr = clazz.getSimpleName();
137 String queryStr = " SELECT other FROM "+ thisClassStr + " this, " + otherClassStr + " other " +
138 " WHERE this = :referencedObject AND this member of other."+propertyName ;
139 Query query = session.createQuery(queryStr).setEntity("referencedObject", item);
140 List<CdmBase> result = query.list();
141 return result;
142 }
143
144 /* (non-Javadoc)
145 * @see eu.etaxonomy.cdm.persistence.dao.common.ICdmGenericDao#getAllCdmClasses(boolean)
146 */
147 public Set<Class<? extends CdmBase>> getAllCdmClasses(boolean includeAbstractClasses){
148 Set<Class<? extends CdmBase>> result = new HashSet<Class<? extends CdmBase>>();
149
150 SessionFactory sessionFactory = getSession().getSessionFactory();
151 Map<?,?> allClassMetadata = sessionFactory.getAllClassMetadata();
152 Collection<?> keys = allClassMetadata.keySet();
153 for (Object oKey : keys){
154 if (oKey instanceof String){
155 String strKey = (String)oKey;
156 if (! strKey.endsWith("_AUD")){
157 try {
158 Class clazz = Class.forName(strKey);
159 boolean isAbstractClass = Modifier.isAbstract(clazz.getModifiers());
160 if (! isAbstractClass || includeAbstractClasses){
161 result.add(clazz);
162 }
163 } catch (ClassNotFoundException e) {
164 logger.warn("Class not found: " + strKey);
165 }
166 }
167 }else{
168 logger.warn("key is not of type String: " + oKey);
169 }
170 }
171 return result;
172 }
173
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 };
356 Set<String> classNames = new HashSet<String>();
357 for (Class clazz: classes){
358 classNames.add(clazz.getCanonicalName());
359 if (clazz == propertyType.getClass()){
360 return true;
361 }
362 }
363 String propertyTypeClassName = propertyType.getName();
364 if (classNames.contains(propertyTypeClassName)){
365 return true;
366 }
367 return result;
368 }
369
370 /* (non-Javadoc)
371 * @see eu.etaxonomy.cdm.persistence.dao.common.ICdmGenericDao#getHqlResult(java.lang.String)
372 */
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 public <T extends CdmBase> void merge(T cdmBase1, T cdmBase2, IMergeStrategy mergeStrategy) throws MergeException {
380 Class<T> clazz = (Class<T>)cdmBase1.getClass();
381 SessionImpl session = (SessionImpl) getSession();
382 SessionFactory sessionFactory = session.getSessionFactory();
383 if (mergeStrategy == null){
384 mergeStrategy = DefaultMergeStrategy.NewInstance(cdmBase1.getClass());
385 }
386 try {
387 //test null and types
388 testMergeValid(cdmBase1, cdmBase2);
389
390 //merge objects
391 //externel impl
392 //internal impl
393 session.flush();
394 Set<ICdmBase> deleteSet = new HashSet<ICdmBase>();
395 Set<ICdmBase> cloneSet = new HashSet<ICdmBase>();
396 if (cdmBase1 instanceof IMergable){
397 IMergable mergable1 = (IMergable)cdmBase1;
398 IMergable mergable2 = (IMergable)cdmBase2;
399 deleteSet = mergeStrategy.invoke(mergable1, mergable2, cloneSet);
400 //session.saveOrUpdate(mergable1);
401
402 session.flush();
403 //((IMergable)cdmBase1).mergeInto(cdmBase2, DefaultMergeStrategy.NewInstance(cdmBase1.getClass()));
404 }else{
405 mergeExternal(cdmBase1, cdmBase2, clazz, session);
406 }
407
408
409 if (cdmBase2.getId() > 0){
410 session.saveOrUpdate(cdmBase2);
411 //rearrange references to cdmBase2
412 reallocateReferences(cdmBase1, cdmBase2, sessionFactory, clazz, cloneSet);
413 }
414
415 //remove deleted objects
416
417 //session.delete(null, mergable2, true, null);
418 session.delete(cdmBase2);
419 for (ICdmBase toBeDeleted : deleteSet){
420 logger.debug("Delete " + toBeDeleted);
421 if (toBeDeleted != cdmBase2){
422 session.delete(toBeDeleted);
423 }
424
425 }
426
427 //flush
428 session.flush();
429
430 } catch (Exception e) {
431 throw new MergeException(e);
432 }
433 }
434
435
436 /**
437 * @param <T>
438 * @param cdmBase1
439 * @param cdmBase2
440 * @param clazz
441 * @param sessionFactory
442 * @throws MergeException
443 * @throws ClassNotFoundException
444 * @throws NoSuchFieldException
445 */
446 private <T extends CdmBase> void mergeExternal(T cdmBase1, T cdmBase2, Class<T> clazz,
447 Session session) throws MergeException {
448 // handleAnnotations
449 logger.warn("Merge external");
450 handleAnnotationsEtc(cdmBase1, cdmBase2, session);
451
452 SessionFactoryImpl sessionFactory = (SessionFactoryImpl) session.getSessionFactory();
453
454 Map allClassMetadata = sessionFactory.getAllClassMetadata();
455
456 //TODO cast
457 getCollectionRoles(clazz, sessionFactory);
458
459 TaxonNameBase name1 = BotanicalName.NewInstance(null);
460 name1.getTaxonBases();
461
462 Type propType = sessionFactory.getReferencedPropertyType(BotanicalName.class.getCanonicalName(), "taxonBases");
463 Map collMetadata = sessionFactory.getAllCollectionMetadata();
464 //roles = sessionFactory.getCollectionRolesByEntityParticipant("eu.etaxonomy.cdm.model.name.BotanicalName");
465 CollectionPersister collPersister;
466 try {
467 collPersister = sessionFactory.getCollectionPersister(TaxonNameBase.class.getCanonicalName()+".annotations");
468 } catch (MappingException e) {
469 // TODO Auto-generated catch block
470 e.printStackTrace();
471 }
472 Statistics statistics = sessionFactory.getStatistics();
473 logger.debug("");
474 ClassMetadata taxonMetaData = sessionFactory.getClassMetadata(Taxon.class);
475 String ename = taxonMetaData.getEntityName();
476 try {
477 Reference ref = sessionFactory.getReference();
478 logger.debug("");
479 } catch (Exception e) {
480 // TODO Auto-generated catch block
481 e.printStackTrace();
482 }
483
484 //sessionFactory.get
485 ClassMetadata classMetadata = getSession().getSessionFactory().getClassMetadata(clazz);
486 Type[] propertyTypes = classMetadata.getPropertyTypes();
487 int propertyNr = 0;
488 for (Type propertyType: propertyTypes){
489 String propertyName = classMetadata.getPropertyNames()[propertyNr];
490 logger.debug(propertyName);
491 makeMergeProperty(cdmBase1, cdmBase2, propertyType, propertyName, sessionFactory, false);
492 propertyNr++;
493 }
494 Set<String> collectionRoles;
495 if (classMetadata instanceof AbstractEntityPersister){
496 AbstractEntityPersister persister = (AbstractEntityPersister)classMetadata;
497 String rootName = persister.getRootEntityName();
498 collectionRoles = sessionFactory.getCollectionRolesByEntityParticipant(rootName);
499 for (String collectionRole : collectionRoles){
500 CollectionMetadata collMetadata2 = sessionFactory.getCollectionMetadata(collectionRole);
501 String role = collMetadata2.getRole();
502 Type elType = collMetadata2.getElementType();
503 logger.debug(role);
504 }
505 }
506 }
507
508 /**
509 * @param <T>
510 * @param clazz
511 * @param sessionFactory
512 */
513 private <T> Set<String> getCollectionRoles(Class<T> clazz,
514 SessionFactoryImpl sessionFactory) {
515 Set<String> collectionRoles = null;
516 ClassMetadata classMetaData = sessionFactory.getClassMetadata(clazz);
517 if (classMetaData instanceof AbstractEntityPersister){
518 AbstractEntityPersister persister = (AbstractEntityPersister)classMetaData;
519 String rootName = persister.getRootEntityName();
520 collectionRoles = sessionFactory.getCollectionRolesByEntityParticipant(rootName);
521 for (String collectionRole : collectionRoles){
522 CollectionMetadata collMetadata = sessionFactory.getCollectionMetadata(collectionRole);
523 CollectionPersister collPersister = sessionFactory.getCollectionPersister(collectionRole);
524 logger.debug("");
525 }
526 }else{
527 logger.warn("Class metadata is not of type AbstractEntityPersister");
528 throw new UnhandledException("Class metadata is not of type AbstractEntityPersister", null);
529 }
530 return collectionRoles;
531 }
532
533
534 private <T extends CdmBase> void makeMergeProperty(T cdmBase1, T cdmBase2, Type propertyType, String propertyName, SessionFactoryImpl sessionFactory, boolean isCollection) throws MergeException
535 {
536
537 try {
538 Class<T> clazz = (Class<T>)cdmBase1.getClass();
539 if (isNoDoType(propertyType)){
540 //do nothing
541 }else if (propertyType.isEntityType()){
542 //Field field = clazz.getField(propertyName);
543 EntityType entityType = (EntityType)propertyType;
544 String associatedEntityName = entityType.getAssociatedEntityName();
545 Class entityClass = Class.forName(associatedEntityName);
546 // Type refPropType = sessionFactory.getReferencedPropertyType(entityClass.getCanonicalName(), propertyName);
547 Set<String> collectionRoles = getCollectionRoles(clazz, sessionFactory);
548 for (String collectionRole : collectionRoles){
549 CollectionMetadata collMetadata = sessionFactory.getCollectionMetadata(collectionRole);
550 String role = collMetadata.getRole();
551 logger.debug(role);
552
553 }
554
555 // if (entityClass.isInterface()){
556 // logger.debug("So ein interface");
557 // }
558 // if (entityClass.isAssignableFrom(clazz)){
559 // makeSingleProperty(referencedClass, entityClass, propertyName, cdmClass, result, isCollection);
560 // }
561 }else if (propertyType.isCollectionType()){
562 CollectionType collectionType = (CollectionType)propertyType;
563 String role = collectionType.getRole();
564 Type elType = collectionType.getElementType((SessionFactoryImplementor)sessionFactory);
565 String n = collectionType.getAssociatedEntityName(sessionFactory);
566 CollectionMetadata collMetadata = sessionFactory.getCollectionMetadata(role);
567 if (collMetadata instanceof OneToManyPersister){
568 OneToManyPersister oneManyPersister = (OneToManyPersister)collMetadata;
569 String className = oneManyPersister.getOwnerEntityName();
570 Class<?> myClass = Class.forName(className);
571 Field field = myClass.getDeclaredField(propertyName);
572 field.setAccessible(true);
573 try {
574 if (collectionType instanceof SetType){
575 Set set2 = (Set)field.get(cdmBase2);
576 Set<Object> set1 = (Set<Object>)field.get(cdmBase1);
577 for (Object obj2: set2){
578 set1.add(obj2);
579 }
580 }
581 } catch (IllegalArgumentException e) {
582 // TODO Auto-generated catch block
583 e.printStackTrace();
584 } catch (IllegalAccessException e) {
585 // TODO Auto-generated catch block
586 e.printStackTrace();
587 }
588
589 }
590 logger.debug("");
591
592 // makePropertyType(result, referencedClass, sessionFactory, cdmClass, elType, propertyName, true);
593 }else if (propertyType.isAnyType()){
594 AnyType anyType = (AnyType)propertyType;
595 Field field = clazz.getDeclaredField(propertyName);
596 Class returnType = field.getType();
597 // if (returnType.isInterface()){
598 // logger.debug("So ein interface");
599 // }
600 // if (returnType.isAssignableFrom(referencedClass)){
601 // makeSingleProperty(referencedClass, returnType, propertyName, cdmClass, result, isCollection);
602 // }
603 }else if (propertyType.isComponentType()){
604 ComponentType componentType = (ComponentType)propertyType;
605 Type[] subTypes = componentType.getSubtypes();
606 // Field field = cdmClass.getDeclaredField(propertyName);
607 // Class returnType = field.getType();
608 int propertyNr = 0;
609 for (Type subType: subTypes){
610 String subPropertyName = componentType.getPropertyNames()[propertyNr];
611 if (!isNoDoType(subType)){
612 logger.warn("SubType not yet handled: " + subType);
613 }
614 // handlePropertyType(referencedCdmBase, result, referencedClass,
615 // sessionFactory, cdmClass, subType, subPropertyName, isCollection);
616 propertyNr++;
617 }
618 }else{
619 logger.warn("propertyType not yet handled: " + propertyType.getName());
620 }
621 //OLD:
622 // if (! type.isInterface()){
623 // if (referencedClass.isAssignableFrom(type)||
624 // type.isAssignableFrom(referencedClass) && CdmBase.class.isAssignableFrom(type)){
625 // handleSingleClass(referencedClass, type, field, cdmClass, result, referencedCdmBase, false);
626 // }
627 // //interface
628 // }else if (type.isAssignableFrom(referencedClass)){
629 // handleSingleClass(referencedClass, type, field, cdmClass, result, referencedCdmBase, false);
630 } catch (Exception e) {
631 throw new MergeException(e);
632 }
633 }
634
635
636
637
638 private void reallocateReferences(CdmBase cdmBase1, CdmBase cdmBase2, SessionFactory sessionFactory, Class clazz, Set<ICdmBase> cloneSet){
639 try {
640 Set<ReferenceHolder> holderSet = referenceMap.get(clazz);
641 if (holderSet == null){
642 holderSet = makeHolderSet(clazz);
643 referenceMap.put(clazz, holderSet);
644 }
645 for (ReferenceHolder refHolder: holderSet){
646 reallocateByHolder(cdmBase1, cdmBase2, refHolder, cloneSet);
647 }
648 return;
649 } catch (Exception e) {
650 e.printStackTrace();
651 throw new RuntimeException(e);
652 }
653 }
654
655 /**
656 * @param cdmBase1
657 * @param cdmBase2
658 * @param refHolder
659 * @throws MergeException
660 */
661 private void reallocateByHolder(CdmBase cdmBase1, CdmBase cdmBase2, ReferenceHolder refHolder, Set<ICdmBase> cloneSet) throws MergeException {
662 try {
663 if (refHolder.isCollection()){
664 reallocateCollection(cdmBase1, cdmBase2, refHolder, cloneSet);
665 }else{
666 reallocateSingleItem(cdmBase1, cdmBase2, refHolder, cloneSet);
667 }
668 } catch (Exception e) {
669 throw new MergeException("Error during reallocation of references to merge object: " + cdmBase2, e);
670 }
671
672 }
673
674 /**
675 * @param cdmBase1
676 * @param cdmBase2
677 * @param refHolder
678 * @param cloneSet
679 * @throws MergeException
680 * @throws NoSuchFieldException
681 * @throws SecurityException
682 * @throws IllegalAccessException
683 * @throws IllegalArgumentException
684 * @throws InvocationTargetException
685 */
686 private void reallocateCollection(CdmBase cdmBase1, CdmBase cdmBase2,
687 ReferenceHolder refHolder, Set<ICdmBase> cloneSet) throws MergeException, SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
688 List<CdmBase> list = getCdmBasesWithItemInCollection(refHolder.itemClass, refHolder.otherClass, refHolder.propertyName, cdmBase2);
689 for (CdmBase referencingObject : list){
690 Field referencingField = getFieldRecursive(refHolder.otherClass, refHolder.propertyName);
691 referencingField.setAccessible(true);
692 Object collection = referencingField.get(referencingObject);
693 if (! (collection instanceof Collection)){
694 throw new MergeException ("Reallocation of collections for collection other than set and list not yet implemented");
695 }
696 Method addMethod = DefaultMergeStrategy.getAddMethod(referencingField, false);
697 Method removeMethod = DefaultMergeStrategy.getAddMethod(referencingField, true);
698 addMethod.invoke(referencingObject, cdmBase1);
699 removeMethod.invoke(referencingObject, cdmBase2);
700 }
701 }
702
703 private Field getFieldRecursive(Class clazz, String propertyName) throws NoSuchFieldException{
704 try {
705 return clazz.getDeclaredField(propertyName);
706 } catch (NoSuchFieldException e) {
707 Class superClass = clazz.getSuperclass();
708 if (CdmBase.class.isAssignableFrom(superClass)){
709 return getFieldRecursive(superClass, propertyName);
710 }else{
711 throw e;
712 }
713 }
714 }
715
716 /**
717 * @throws NoSuchFieldException
718 * @throws SecurityException
719 * @throws IllegalAccessException
720 * @throws IllegalArgumentException
721 *
722 */
723 private void reallocateSingleItem_Old(CdmBase cdmBase1, CdmBase cdmBase2, ReferenceHolder refHolder) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
724 List<CdmBase> referencingObjects = getCdmBasesByFieldAndClass(refHolder.otherClass, refHolder.propertyName, cdmBase2);
725 for (CdmBase referencingObject : referencingObjects){
726 Field referencingField = refHolder.otherClass.getDeclaredField(refHolder.propertyName);
727 referencingField.setAccessible(true);
728 Object test = referencingField.get(referencingObject);
729 assert(test.equals(cdmBase2));
730 referencingField.set(referencingObject, cdmBase1);
731 }
732 }
733
734 private void reallocateSingleItem(CdmBase cdmBase1, CdmBase cdmBase2, ReferenceHolder refHolder, Set<ICdmBase> cloneSet) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
735 List<CdmBase> referencingObjects = getCdmBasesByFieldAndClass(refHolder.otherClass, refHolder.propertyName, cdmBase2);
736 Session session = getSession();
737 for (CdmBase referencingObject : referencingObjects){
738 if (!cloneSet.contains(referencingObject)){
739 String className = refHolder.otherClass.getSimpleName();
740 String propertyName = refHolder.propertyName;
741 String hql = "update " + className + " c set c."+propertyName+" = :newValue where c.id = :id";
742 Query query = session.createQuery(hql);
743 query.setEntity("newValue", cdmBase1);
744 query.setInteger("id",referencingObject.getId());
745 int rowCount = query.executeUpdate();
746 logger.debug("Rows affected: " + rowCount);
747 session.refresh(referencingObject);
748 }
749 }
750 session.flush();
751 }
752
753
754
755 /**
756 * @param <T>
757 * @param cdmBase1
758 * @param cdmBase2
759 * @param session
760 */
761 private <T> void handleAnnotationsEtc(T cdmBase1, T cdmBase2, Session session) {
762 //when handling annotations and other elements linked via @Any an JDBC errors occurs
763 //due to the unique column constraint in the association table on the column referencing
764 //the annotation.
765 //For some reason not delete command is executed for the old collection
766 // Hibernate bug ??
767 session.flush(); //for debugging
768 if (cdmBase1 instanceof AnnotatableEntity){
769 AnnotatableEntity annotatableEntity1 = (AnnotatableEntity)cdmBase1;
770 AnnotatableEntity annotatableEntity2 = (AnnotatableEntity)cdmBase2;
771 //annotations
772 List<Annotation> removeListAnnotation = new ArrayList<Annotation>();
773 for (Annotation annotation : annotatableEntity2.getAnnotations()){
774 Annotation clone = null;
775 try {
776 clone = annotation.clone(annotatableEntity1);
777 } catch (CloneNotSupportedException e) {
778 e.printStackTrace();
779 }
780 annotatableEntity1.addAnnotation(clone);
781 removeListAnnotation.add(annotation);
782 }
783 for (Annotation annotation : removeListAnnotation){
784 annotatableEntity2.removeAnnotation(annotation);
785 getSession().delete(annotation);
786 }
787 //marker
788 List<Marker> removeListMarker = new ArrayList<Marker>();
789 for (Marker marker : annotatableEntity2.getMarkers()){
790 Marker clone = null;
791 try {
792 clone = marker.clone(annotatableEntity1);
793 } catch (CloneNotSupportedException e) {
794 e.printStackTrace();
795 }
796 annotatableEntity1.addMarker(clone);
797 removeListMarker.add(marker);
798 }
799 for (Marker marker : removeListMarker){
800 annotatableEntity2.removeMarker(marker);
801 getSession().delete(marker);
802 }
803 }
804 if (cdmBase1 instanceof IdentifiableEntity){
805 IdentifiableEntity identifiableEntity1 = (IdentifiableEntity)cdmBase1;
806 IdentifiableEntity identifiableEntity2 = (IdentifiableEntity)cdmBase2;
807 //annotations
808 List<Extension> removeListExtension = new ArrayList<Extension>();
809 for (Extension changeObject : (Set<Extension>)identifiableEntity2.getExtensions()){
810 try {
811 Extension clone = changeObject.clone(identifiableEntity1);
812 identifiableEntity1.addExtension(clone);
813 removeListExtension.add(changeObject);
814 } catch (CloneNotSupportedException e) {
815 e.printStackTrace();
816 }
817
818 }
819 for (Extension removeObject : removeListExtension){
820 identifiableEntity2.removeExtension(removeObject);
821 getSession().delete(removeObject);
822 }
823 }
824
825 session.saveOrUpdate(cdmBase1);
826 session.saveOrUpdate(cdmBase2);
827 session.flush();
828 }
829
830 private <T extends CdmBase> void testMergeValid(T cdmBase1, T cdmBase2)throws IllegalArgumentException, NullPointerException{
831 if (cdmBase1 == null || cdmBase2 == null){
832 throw new NullPointerException("Merge arguments must not be (null)");
833 }
834 cdmBase1 = (T)HibernateProxyHelper.deproxy(cdmBase1);
835 cdmBase2 = (T)HibernateProxyHelper.deproxy(cdmBase2);
836
837 if (cdmBase1.getClass() != cdmBase2.getClass()){
838 throw new IllegalArgumentException("Merge arguments must be of same type");
839 }
840 }
841
842 /* (non-Javadoc)
843 * @see eu.etaxonomy.cdm.persistence.dao.common.ICdmGenericDao#test()
844 */
845 public void test() {
846 SessionFactoryImpl factory = (SessionFactoryImpl)getSession().getSessionFactory();
847 Type propType = factory.getReferencedPropertyType(BotanicalName.class.getCanonicalName(), "titleCache");
848 Map collMetadata = factory.getAllCollectionMetadata();
849 Object roles = factory.getCollectionRolesByEntityParticipant("eu.etaxonomy.cdm.model.name.BotanicalName");
850 CollectionPersister collPersister;
851 try {
852 collPersister = factory.getCollectionPersister(TaxonNameBase.class.getCanonicalName()+".annotations");
853 } catch (MappingException e) {
854 // TODO Auto-generated catch block
855 e.printStackTrace();
856 }
857 Statistics statistics = factory.getStatistics();
858 Map allClassMetadata = factory.getAllClassMetadata();
859 logger.debug("");
860
861 }
862
863 public <T extends CdmBase> T find(Class<T> clazz, int id){
864 Session session;
865 session = getSession();
866 //session = getSession().getSessionFactory().getCurrentSession();
867 return (T)session.get(clazz, id);
868 }
869
870 /* (non-Javadoc)
871 * @see eu.etaxonomy.cdm.persistence.dao.common.ICdmGenericDao#findMatching(eu.etaxonomy.cdm.strategy.match.IMatchable, eu.etaxonomy.cdm.strategy.match.IMatchStrategy)
872 */
873 public <T extends IMatchable> List<T> findMatching(T objectToMatch,
874 IMatchStrategy matchStrategy) throws MatchException {
875 try {
876 List<T> result = new ArrayList<T>();
877 if(objectToMatch == null){
878 return result;
879 }
880 if (matchStrategy == null){
881 matchStrategy = DefaultMatchStrategy.NewInstance(objectToMatch.getClass());
882 }
883 result.addAll(findMatchingNullSafe(objectToMatch, matchStrategy));
884 return result;
885 } catch (IllegalArgumentException e) {
886 throw new MatchException(e);
887 } catch (IllegalAccessException e) {
888 throw new MatchException(e);
889 }
890 }
891
892 public <T extends IMatchable> List<T> findMatchingNullSafe(T objectToMatch, IMatchStrategy matchStrategy) throws IllegalArgumentException, IllegalAccessException, MatchException {
893 List<T> result = new ArrayList<T>();
894 Session session = getSession();
895 Class matchClass = objectToMatch.getClass();
896 ClassMetadata classMetaData = session.getSessionFactory().getClassMetadata(matchClass.getCanonicalName());
897 Criteria criteria = session.createCriteria(matchClass);
898 boolean noMatch = makeCriteria(objectToMatch, matchStrategy, classMetaData, criteria);
899 logger.debug(criteria);
900 //session.flush();
901 if (noMatch == false){
902 List<T> matchCandidates = criteria.list();
903 matchCandidates.remove(objectToMatch);
904 for (T matchCandidate : matchCandidates ){
905 if (matchStrategy.invoke(objectToMatch, matchCandidate)){
906 result.add(matchCandidate);
907 }else{
908 logger.warn("Match candidate did not match: " + matchCandidate);
909 }
910 }
911 }
912 return result;
913 }
914
915 /**
916 * @param <T>
917 * @param objectToMatch
918 * @param matchStrategy
919 * @param classMetaData
920 * @param criteria
921 * @return
922 * @throws IllegalAccessException
923 * @throws MatchException
924 */
925 private <T> boolean makeCriteria(T objectToMatch,
926 IMatchStrategy matchStrategy, ClassMetadata classMetaData,
927 Criteria criteria) throws IllegalAccessException, MatchException {
928 Matching matching = matchStrategy.getMatching();
929 boolean noMatch = false;
930 Map<String, List<MatchMode>> replaceMatchers = new HashMap<String, List<MatchMode>>();
931 for (CacheMatcher cacheMatcher: matching.getCacheMatchers()){
932 boolean cacheProtected = (Boolean)cacheMatcher.getProtectedField(matching).get(objectToMatch);
933 if (cacheProtected == true){
934 String cacheValue = (String)cacheMatcher.getField().get(objectToMatch);
935 if (CdmUtils.isEmpty(cacheValue)){
936 return true; //no match
937 }else{
938 criteria.add(Restrictions.eq(cacheMatcher.getPropertyName(), cacheValue));
939 criteria.add(Restrictions.eq(cacheMatcher.getProtectedPropertyName(), cacheProtected));
940
941 List<DoubleResult<String, MatchMode>> replacementModes = cacheMatcher.getReplaceMatchModes(matching);
942 for (DoubleResult<String, MatchMode> replacementMode: replacementModes ){
943 String propertyName = replacementMode.getFirstResult();
944 List<MatchMode> replaceMatcherList = replaceMatchers.get(propertyName);
945 if (replaceMatcherList == null){
946 replaceMatcherList = new ArrayList<MatchMode>();
947 replaceMatchers.put(propertyName, replaceMatcherList);
948 }
949 replaceMatcherList.add(replacementMode.getSecondResult());
950 }
951
952 }
953 }
954 }
955 for (FieldMatcher fieldMatcher : matching.getFieldMatchers(false)){
956 String propertyName = fieldMatcher.getPropertyName();
957 Type propertyType = classMetaData.getPropertyType(propertyName);
958 Object value = fieldMatcher.getField().get(objectToMatch);
959 List<MatchMode> matchModes= new ArrayList<MatchMode>();
960 matchModes.add(fieldMatcher.getMatchMode());
961 if (replaceMatchers.get(propertyName) != null){
962 matchModes.addAll(replaceMatchers.get(propertyName));
963 }
964
965 boolean isIgnore = false;
966 for (MatchMode matchMode : matchModes){
967 isIgnore |= matchMode.isIgnore(value);
968 }
969 if (! isIgnore ){
970 if (propertyType.isComponentType()){
971 matchComponentType(criteria, fieldMatcher, propertyName, value, matchModes);
972 }else{
973 noMatch = matchNonComponentType(criteria, fieldMatcher, propertyName, value, matchModes, propertyType);
974 }
975 }
976 if (noMatch){
977 return noMatch;
978 }
979 }
980 return noMatch;
981 }
982
983 /**
984 * @param criteria
985 * @param fieldMatcher
986 * @param propertyName
987 * @param value
988 * @param matchMode
989 * @throws MatchException
990 * @throws IllegalAccessException
991 */
992 private void matchComponentType(Criteria criteria,
993 FieldMatcher fieldMatcher, String propertyName, Object value,
994 List<MatchMode> matchModes) throws MatchException, IllegalAccessException {
995 if (value == null){
996 boolean requiresSecondNull = requiresSecondNull(matchModes, value);
997 if (requiresSecondNull){
998 criteria.add(Restrictions.isNull(propertyName));
999 }else{
1000 //TODO
1001 logger.warn("Component type not yet implemented for (null) value: " + propertyName);
1002 throw new MatchException("Component type not yet fully implemented for (null) value. Property: " + propertyName);
1003 }
1004 }else{
1005 Class<?> componentClass = fieldMatcher.getField().getType();
1006 Map<String, Field> fields = CdmUtils.getAllFields(componentClass, Object.class, false, false, true, false);
1007 for (String fieldName : fields.keySet()){
1008 String restrictionPath = propertyName +"."+fieldName;
1009 Object componentValue = fields.get(fieldName).get(value);
1010 //TODO diffentiate matchMode
1011 createCriterion(criteria, restrictionPath, componentValue, matchModes);
1012 }
1013 }
1014 }
1015
1016 private boolean matchNonComponentType(Criteria criteria,
1017 FieldMatcher fieldMatcher, String propertyName, Object value,
1018 List<MatchMode> matchModes, Type propertyType) throws HibernateException, DataAccessException, MatchException, IllegalAccessException{
1019 boolean noMatch = false;
1020 if (isRequired(matchModes) && value == null){
1021 noMatch = true;
1022 return noMatch;
1023 }else if (requiresSecondNull(matchModes,value)){
1024 criteria.add(Restrictions.isNull(propertyName));
1025 }else{
1026 if (isMatch(matchModes)){
1027 if (propertyType.isCollectionType()){
1028 //TODO collection not yet handled for match
1029 }else{
1030 int joinType = CriteriaSpecification.INNER_JOIN;
1031 if (! requiresSecondValue(matchModes,value)){
1032 joinType = CriteriaSpecification.LEFT_JOIN;
1033 }
1034 Criteria matchCriteria = criteria.createCriteria(propertyName, joinType).add(Restrictions.isNotNull("id"));
1035 Class matchClass = value.getClass();
1036 if (IMatchable.class.isAssignableFrom(matchClass)){
1037 IMatchStrategy valueMatchStrategy = DefaultMatchStrategy.NewInstance((Class<IMatchable>)matchClass);
1038 ClassMetadata valueClassMetaData = getSession().getSessionFactory().getClassMetadata(matchClass.getCanonicalName());;
1039 noMatch = makeCriteria(value, valueMatchStrategy, valueClassMetaData, matchCriteria);
1040 }else{
1041 logger.error("Class to match (" + matchClass + ") is not of type IMatchable");
1042 throw new MatchException("Class to match (" + matchClass + ") is not of type IMatchable");
1043 }
1044 }
1045 }else if (isEqual(matchModes)){
1046 createCriterion(criteria, propertyName, value, matchModes);
1047 }else {
1048 logger.warn("Unhandled match mode: " + matchModes + ", value: " + (value==null?"null":value));
1049 }
1050 }
1051 return noMatch;
1052 }
1053
1054 /**
1055 * @param criteria
1056 * @param propertyName
1057 * @param value
1058 * @param matchMode
1059 * @throws MatchException
1060 */
1061 private void createCriterion(Criteria criteria, String propertyName,
1062 Object value, List<MatchMode> matchModes) throws MatchException {
1063 Criterion finalRestriction = null;
1064 Criterion equalRestriction = Restrictions.eq(propertyName, value);
1065 Criterion nullRestriction = Restrictions.isNull(propertyName);
1066 if (this.requiresSecondValue(matchModes, value)){
1067 finalRestriction = equalRestriction;
1068 }else if (requiresSecondNull(matchModes, value) ){
1069 finalRestriction = nullRestriction;
1070 }else{
1071 finalRestriction = Restrictions.or(equalRestriction, nullRestriction);
1072 }
1073 //return finalRestriction;
1074 criteria.add(finalRestriction);
1075 }
1076
1077 /**
1078 * @param matchModes
1079 * @param value
1080 * @return
1081 * @throws MatchException
1082 */
1083 private boolean requiresSecondNull(List<MatchMode> matchModes, Object value) throws MatchException {
1084 boolean result = true;
1085 for (MatchMode matchMode: matchModes){
1086 result &= matchMode.requiresSecondNull(value);
1087 }
1088 return result;
1089 }
1090
1091 /**
1092 * @param matchModes
1093 * @param value
1094 * @return
1095 * @throws MatchException
1096 */
1097 private boolean requiresSecondValue(List<MatchMode> matchModes, Object value) throws MatchException {
1098 boolean result = true;
1099 for (MatchMode matchMode: matchModes){
1100 result &= matchMode.requiresSecondValue(value);
1101 }
1102 return result;
1103 }
1104
1105 /**
1106 * @param matchModes
1107 * @param value
1108 * @return
1109 * @throws MatchException
1110 */
1111 private boolean isRequired(List<MatchMode> matchModes) throws MatchException {
1112 boolean result = true;
1113 for (MatchMode matchMode: matchModes){
1114 result &= matchMode.isRequired();
1115 }
1116 return result;
1117 }
1118
1119 /**
1120 * Returns true if at least one match mode is of typ MATCH_XXX
1121 * @param matchModes
1122 * @param value
1123 * @return
1124 * @throws MatchException
1125 */
1126 private boolean isMatch(List<MatchMode> matchModes) throws MatchException {
1127 boolean result = false;
1128 for (MatchMode matchMode: matchModes){
1129 result |= matchMode.isMatch();
1130 }
1131 return result;
1132 }
1133
1134 /**
1135 * Returns true if at least one match mode is of typ EQUAL_XXX
1136 * @param matchModes
1137 * @param value
1138 * @return
1139 * @throws MatchException
1140 */
1141 private boolean isEqual(List<MatchMode> matchModes) throws MatchException {
1142 boolean result = false;
1143 for (MatchMode matchMode: matchModes){
1144 result |= matchMode.isEqual();
1145 }
1146 return result;
1147 }
1148
1149 /* (non-Javadoc)
1150 * @see eu.etaxonomy.cdm.persistence.dao.common.ICdmGenericDao#saveMetaData(eu.etaxonomy.cdm.model.common.CdmMetaData)
1151 */
1152 public void saveMetaData(CdmMetaData cdmMetaData) {
1153 getSession().saveOrUpdate(cdmMetaData);
1154 }
1155
1156 /* (non-Javadoc)
1157 * @see eu.etaxonomy.cdm.persistence.dao.common.ICdmGenericDao#getMetaData()
1158 */
1159 public List<CdmMetaData> getMetaData() {
1160 Session session = getSession();
1161 Criteria crit = session.createCriteria(CdmMetaData.class);
1162 List<CdmMetaData> results = crit.list();
1163 return results;
1164 }
1165 }
1166
1167