ref #9905 fix exception when matching TeamOrPersonBase
authorAndreas Müller <a.mueller@bgbm.org>
Thu, 3 Mar 2022 10:51:00 +0000 (11:51 +0100)
committerAndreas Müller <a.mueller@bgbm.org>
Thu, 3 Mar 2022 10:51:00 +0000 (11:51 +0100)
cdmlib-persistence/src/main/java/eu/etaxonomy/cdm/persistence/dao/hibernate/common/CdmGenericDaoImpl.java
cdmlib-persistence/src/test/java/eu/etaxonomy/cdm/persistence/dao/hibernate/common/CdmGenericDaoImplTest.java

index 5005d6837ca14a149a6b8a87f54a9bf78c3ca303..791f86608726b39c35c188f232e08e6423326a7a 100644 (file)
@@ -666,7 +666,7 @@ public class CdmGenericDaoImpl
                Class<?> matchClass = objectToMatch.getClass();
                ClassMetadata classMetaData = session.getSessionFactory().getClassMetadata(matchClass.getCanonicalName());
                Criteria criteria = session.createCriteria(matchClass);
-               boolean noMatch = makeCriteria(objectToMatch, matchStrategy, classMetaData, criteria);
+               boolean noMatch = makeCriteria(objectToMatch, matchStrategy, classMetaData, criteria, 1);
                if (logger.isDebugEnabled()){logger.debug(criteria);}
                //session.flush();
                if (noMatch == false){
@@ -692,12 +692,13 @@ public class CdmGenericDaoImpl
         * @param matchStrategy the match strategy used
         * @param classMetaData the precomputed class metadata
         * @param criteria the criteria to fill
+        * @param level recursion level
         * @return <code>true</code> if definitely no matching object will be found,
         *         <code>false</code> if nothing is known on the existence of a matching result
         */
        private boolean makeCriteria(Object objectToMatch,
                        IMatchStrategy matchStrategy, ClassMetadata classMetaData,
-                       Criteria criteria) throws IllegalAccessException, MatchException {
+                       Criteria criteria, int level) throws IllegalAccessException, MatchException {
 
            Matching matching = matchStrategy.getMatching((IMatchable)objectToMatch);
                boolean noMatch = false;
@@ -745,7 +746,7 @@ public class CdmGenericDaoImpl
                                if (propertyType.isComponentType()){
                                        matchComponentType(criteria, fieldMatcher, propertyName, value, matchModes);
                                }else{
-                                       noMatch = matchNonComponentType(criteria, fieldMatcher, propertyName, value, matchModes, propertyType);
+                                       noMatch = matchNonComponentType(criteria, fieldMatcher, propertyName, value, matchModes, propertyType, level);
                                }
                        }
                        if (noMatch){
@@ -779,12 +780,15 @@ public class CdmGenericDaoImpl
                }
        }
 
+    /**
+     * @param level the recursion level
+     */
     private boolean matchNonComponentType(Criteria criteria,
                        FieldMatcher fieldMatcher,
                        String propertyName,
                        Object value,
                        List<MatchMode> matchModes,
-                       Type propertyType)
+                       Type propertyType, int level)
                        throws HibernateException, DataAccessException, MatchException, IllegalAccessException{
 
            boolean noMatch = false;
@@ -798,7 +802,7 @@ public class CdmGenericDaoImpl
                                if (propertyType.isCollectionType()){
                                    if (value instanceof Collection) {
                                        //TODO fieldMatcher?
-                           matchCollection(criteria, propertyName, (Collection<?>)value);
+                           matchCollection(criteria, propertyName, (Collection<?>)value, level);
 
                                    }else if (value instanceof Map) {
                                        //TODO map not yet handled for match
@@ -816,7 +820,7 @@ public class CdmGenericDaoImpl
                                        if (IMatchable.class.isAssignableFrom(matchClass)){
                                                IMatchStrategy valueMatchStrategy = fieldMatcher.getMatchStrategy() != null? fieldMatcher.getMatchStrategy() : DefaultMatchStrategy.NewInstance(matchClass);
                                                ClassMetadata valueClassMetaData = getSession().getSessionFactory().getClassMetadata(matchClass.getCanonicalName());
-                                               noMatch = makeCriteria(value, valueMatchStrategy, valueClassMetaData, matchCriteria);
+                                               noMatch = makeCriteria(value, valueMatchStrategy, valueClassMetaData, matchCriteria, level+1);
                                        }else{
                                                logger.error("Class to match (" + matchClass + ") is not of type IMatchable");
                                                throw new MatchException("Class to match (" + matchClass + ") is not of type IMatchable");
@@ -839,9 +843,17 @@ public class CdmGenericDaoImpl
      * class Person it checks that there is at least 1 person matching in
      * nomenclaturalTitle, no matter at which position.
      * See #9905 and #9964
+     *
+     * @param level recursion level
      */
-    private void matchCollection(Criteria criteria, String propertyName, Collection<?> collection) {
+    private void matchCollection(Criteria criteria, String propertyName, Collection<?> collection, int level) {
         int i = 0;
+        //this is a workaround to avoid handling TeamOrPersonBase e.g. in references.
+        //TeamOrPersonBase does not have a property 'teamMembers' and therefore an
+        //according restriction can not be added
+        if (level > 1) {
+            return;
+        }
 
         criteria.add(Restrictions.sizeEq(propertyName, collection.size()));
 
@@ -849,6 +861,7 @@ public class CdmGenericDaoImpl
 //        criteria.createAlias(propertyName, propertyAlias);
         //In future (hibernate >5.1 JPA will allow using index joins: https://www.logicbig.com/tutorials/java-ee-tutorial/jpa/criteria-api-collection-operations.html
 //        Criteria subCriteria = criteria.createCriteria(propertyName+"[1]");
+
         Criteria subCriteria = criteria.createCriteria(propertyName);
 
         for (Object single : collection) {
index cf7500511879ddcf3890b4811d662828b3abbc78..2020c3932c39b0cfeb4ff409f571623cc858b481 100644 (file)
@@ -103,6 +103,7 @@ import eu.etaxonomy.cdm.model.name.NameRelationship;
 import eu.etaxonomy.cdm.model.name.NameRelationshipType;
 import eu.etaxonomy.cdm.model.name.NameTypeDesignation;
 import eu.etaxonomy.cdm.model.name.NameTypeDesignationStatus;
+import eu.etaxonomy.cdm.model.name.NomenclaturalCode;
 import eu.etaxonomy.cdm.model.name.NomenclaturalStatus;
 import eu.etaxonomy.cdm.model.name.NomenclaturalStatusType;
 import eu.etaxonomy.cdm.model.name.Rank;
@@ -153,11 +154,14 @@ import eu.etaxonomy.cdm.persistence.dao.reference.IReferenceDao;
 import eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao;
 import eu.etaxonomy.cdm.persistence.dto.ReferencingObjectDto;
 import eu.etaxonomy.cdm.strategy.match.DefaultMatchStrategy;
+import eu.etaxonomy.cdm.strategy.match.IMatchStrategy;
 import eu.etaxonomy.cdm.strategy.match.IMatchStrategyEqual;
 import eu.etaxonomy.cdm.strategy.match.MatchException;
+import eu.etaxonomy.cdm.strategy.match.MatchStrategyFactory;
 import eu.etaxonomy.cdm.strategy.merge.DefaultMergeStrategy;
 import eu.etaxonomy.cdm.strategy.merge.IMergeStrategy;
 import eu.etaxonomy.cdm.strategy.merge.MergeException;
+import eu.etaxonomy.cdm.strategy.parser.NonViralNameParserImpl;
 import eu.etaxonomy.cdm.test.integration.CdmTransactionalIntegrationTest;
 import eu.etaxonomy.cdm.test.unitils.CleanSweepInsertLoadStrategy;
 
@@ -1265,7 +1269,6 @@ public class CdmGenericDaoImplTest extends CdmTransactionalIntegrationTest {
             Assert.assertEquals(0, candidateMatchResult.size());
             person1.setNomenclaturalTitle("NomTitle1");  //set back
 
-            //TODO should not match in future
             Team teamDifferentOrder = Team.NewInstance();
             teamDifferentOrder.addTeamMember(person2);
             teamDifferentOrder.addTeamMember(person1);
@@ -1273,6 +1276,12 @@ public class CdmGenericDaoImplTest extends CdmTransactionalIntegrationTest {
             //TODO improve, should be 0 in best implementation
             Assert.assertEquals(1, candidateMatchResult.size());
 
+            //test that reference.authorTeam.* still works without throwing exceptions
+            TaxonName name = NonViralNameParserImpl.NewInstance().parseReferencedName("Abies alba Nyffeler & Eggli in Taxon 59: 232. 2010", NomenclaturalCode.ICNAFP, Rank.SPECIES());
+            Reference nomRef = name.getNomenclaturalReference();
+            IMatchStrategy referenceMatcher = MatchStrategyFactory.NewParsedReferenceInstance(nomRef);
+            List<Reference> matching = cdmGenericDao.findMatching(nomRef, referenceMatcher);
+            Assert.assertEquals("We don't expect matchings, only tested that no exceptions are thrown", 0, matching.size());
 
         } catch (IllegalArgumentException | MatchException e) {
             Assert.fail("No exception should be thrown");