=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/organisationunit/OrganisationUnit.java' --- dhis-2/dhis-api/src/main/java/org/hisp/dhis/organisationunit/OrganisationUnit.java 2015-12-14 09:19:58 +0000 +++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/organisationunit/OrganisationUnit.java 2015-12-14 16:33:02 +0000 @@ -560,7 +560,7 @@ public String getAncestorNames() { - List units = getParents(); + List units = getAncestors(); StringBuilder builder = new StringBuilder(); @@ -581,7 +581,7 @@ @JsonView( { DetailedView.class } ) @JacksonXmlElementWrapper( localName = "parents", namespace = DxfNamespaces.DXF_2_0 ) @JacksonXmlProperty( localName = "organisationUnit", namespace = DxfNamespaces.DXF_2_0 ) - public List getParents() + public List getAncestors() { List units = new ArrayList<>(); === modified file 'dhis-2/dhis-api/src/test/java/org/hisp/dhis/organisationunit/OrganisationUnitTest.java' --- dhis-2/dhis-api/src/test/java/org/hisp/dhis/organisationunit/OrganisationUnitTest.java 2015-12-14 09:19:58 +0000 +++ dhis-2/dhis-api/src/test/java/org/hisp/dhis/organisationunit/OrganisationUnitTest.java 2015-12-14 16:33:02 +0000 @@ -104,7 +104,7 @@ List expected = new ArrayList<>( Arrays.asList( unitA, unitB, unitC ) ); - assertEquals( expected, unitD.getParents() ); + assertEquals( expected, unitD.getAncestors() ); } @Test === modified file 'dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/data/DefaultAnalyticsService.java' --- dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/data/DefaultAnalyticsService.java 2015-12-14 09:19:58 +0000 +++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/data/DefaultAnalyticsService.java 2015-12-14 16:33:02 +0000 @@ -942,7 +942,7 @@ { OrganisationUnit unit = (OrganisationUnit) object; - map.putAll( NameableObjectUtils.getUidDisplayPropertyMap( unit.getParents(), params.getDisplayProperty() ) ); + map.putAll( NameableObjectUtils.getUidDisplayPropertyMap( unit.getAncestors(), params.getDisplayProperty() ) ); } } === modified file 'dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/data/DefaultEventAnalyticsService.java' --- dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/data/DefaultEventAnalyticsService.java 2015-12-14 09:19:58 +0000 +++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/data/DefaultEventAnalyticsService.java 2015-12-14 16:33:02 +0000 @@ -384,7 +384,7 @@ if ( hierarchy ) { OrganisationUnit unit = (OrganisationUnit) object; - objects.addAll( unit.getParents() ); + objects.addAll( unit.getAncestors() ); } map.putAll( NameableObjectUtils.getUidDisplayPropertyMap( objects, displayProperty ) ); === modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/schema/Jackson2PropertyIntrospectorService.java' --- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/schema/Jackson2PropertyIntrospectorService.java 2015-10-19 08:29:13 +0000 +++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/schema/Jackson2PropertyIntrospectorService.java 2015-12-14 16:33:02 +0000 @@ -32,22 +32,32 @@ import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; -import com.google.common.collect.Lists; +import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Maps; +import com.google.common.collect.Multimap; import com.google.common.primitives.Primitives; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.hisp.dhis.common.IdentifiableObject; import org.hisp.dhis.common.NameableObject; import org.hisp.dhis.common.annotation.Description; import org.hisp.dhis.system.util.ReflectionUtils; +import org.springframework.core.annotation.AnnotationUtils; import org.springframework.util.StringUtils; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; +import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +import static org.springframework.util.ReflectionUtils.getUniqueDeclaredMethods; /** * Default PropertyIntrospectorService implementation that uses Reflection and Jackson annotations @@ -58,6 +68,8 @@ public class Jackson2PropertyIntrospectorService extends AbstractPropertyIntrospectorService { + private static final Log log = LogFactory.getLog( AbstractPropertyIntrospectorService.class ); + @Override protected Map scanClass( Class clazz ) { @@ -70,7 +82,7 @@ { Property property = new Property(); - JacksonXmlRootElement jacksonXmlRootElement = clazz.getAnnotation( JacksonXmlRootElement.class ); + JacksonXmlRootElement jacksonXmlRootElement = AnnotationUtils.findAnnotation( clazz, JacksonXmlRootElement.class ); if ( !StringUtils.isEmpty( jacksonXmlRootElement.localName() ) ) { @@ -90,7 +102,13 @@ for ( Property property : properties ) { Method getterMethod = property.getGetterMethod(); - JsonProperty jsonProperty = getterMethod.getAnnotation( JsonProperty.class ); + JsonProperty jsonProperty = AnnotationUtils.findAnnotation( getterMethod, JsonProperty.class ); + + if ( jsonProperty == null ) + { + System.err.println( "NO JSON PROPERTY on Property : " + property.getName() + ", method: " + getterMethod ); + continue; + } String fieldName = getFieldName( getterMethod ); property.setName( !StringUtils.isEmpty( jsonProperty.value() ) ? jsonProperty.value() : fieldName ); @@ -133,15 +151,15 @@ property.setSetterMethod( hibernateProperty.getSetterMethod() ); } - if ( property.getGetterMethod().isAnnotationPresent( Description.class ) ) + if ( AnnotationUtils.findAnnotation( property.getGetterMethod(), Description.class ) != null ) { - Description description = property.getGetterMethod().getAnnotation( Description.class ); + Description description = AnnotationUtils.findAnnotation( property.getGetterMethod(), Description.class ); property.setDescription( description.value() ); } - if ( property.getGetterMethod().isAnnotationPresent( JacksonXmlProperty.class ) ) + if ( AnnotationUtils.findAnnotation( property.getGetterMethod(), JacksonXmlProperty.class ) != null ) { - JacksonXmlProperty jacksonXmlProperty = getterMethod.getAnnotation( JacksonXmlProperty.class ); + JacksonXmlProperty jacksonXmlProperty = AnnotationUtils.findAnnotation( getterMethod, JacksonXmlProperty.class ); if ( StringUtils.isEmpty( jacksonXmlProperty.localName() ) ) { @@ -202,9 +220,9 @@ if ( property.isCollection() ) { - if ( property.getGetterMethod().isAnnotationPresent( JacksonXmlElementWrapper.class ) ) + if ( AnnotationUtils.findAnnotation( property.getGetterMethod(), JacksonXmlElementWrapper.class ) != null ) { - JacksonXmlElementWrapper jacksonXmlElementWrapper = getterMethod.getAnnotation( JacksonXmlElementWrapper.class ); + JacksonXmlElementWrapper jacksonXmlElementWrapper = AnnotationUtils.findAnnotation( getterMethod, JacksonXmlElementWrapper.class ); property.setCollectionWrapping( jacksonXmlElementWrapper.useWrapping() ); // TODO what if element-wrapper have different namespace? @@ -261,23 +279,58 @@ return StringUtils.uncapitalize( name ); } + private Multimap getMultimap( Class klass ) + { + Multimap methods = ArrayListMultimap.create(); + Arrays.asList( getUniqueDeclaredMethods( klass ) ).forEach( method -> methods.put( method.getName(), method ) ); + return methods; + } + private List collectProperties( Class klass ) { - Map methodMap = ReflectionUtils.getMethodMap( klass ); - List properties = Lists.newArrayList(); - - methodMap.values().stream() - .filter( method -> method.isAnnotationPresent( JsonProperty.class ) && method.getGenericParameterTypes().length == 0 ) - .forEach( method -> { - String fieldName = getFieldName( method ); - String setterName = "set" + StringUtils.capitalize( fieldName ); - - Property property = new Property( klass, method, null ); - property.setFieldName( fieldName ); - property.setSetterMethod( methodMap.get( setterName ) ); - - properties.add( property ); - } ); + Multimap multimap = getMultimap( klass ); + List properties = new ArrayList<>(); + + Map methodMap = multimap.keySet().stream() + .filter( key -> { + List methods = multimap.get( key ).stream() + .filter( method -> AnnotationUtils.findAnnotation( method, JsonProperty.class ) != null && method.getParameterTypes().length == 0 ) + .collect( Collectors.toList() ); + + if ( methods.size() > 1 ) + { + log.error( "More than one web-api exposed method with name '" + key + "' found on class '" + klass.getName() + + "' please fix as this is known to cause issues with Schema / Query services." ); + + log.debug( "Methods found: " + methods ); + } + + return methods.size() == 1; + } ) + .collect( Collectors.toMap( Function.identity(), key -> { + List collect = multimap.get( key ).stream() + .filter( method -> AnnotationUtils.findAnnotation( method, JsonProperty.class ) != null && method.getParameterTypes().length == 0 ) + .collect( Collectors.toList() ); + + return collect.get( 0 ); + } ) ); + + methodMap.keySet().forEach( key -> { + String fieldName = getFieldName( methodMap.get( key ) ); + String setterName = "set" + StringUtils.capitalize( fieldName ); + + Property property = new Property( klass, methodMap.get( key ), null ); + property.setFieldName( fieldName ); + + Iterator methodIterator = multimap.get( setterName ).iterator(); + + if ( methodIterator.hasNext() ) + { + property.setSetterMethod( methodIterator.next() ); + } + + properties.add( property ); + } ); return properties; } === modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/validation/DefaultValidationRuleService.java' --- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/validation/DefaultValidationRuleService.java 2015-12-14 09:19:58 +0000 +++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/validation/DefaultValidationRuleService.java 2015-12-14 16:33:02 +0000 @@ -525,7 +525,7 @@ { for ( OrganisationUnit o : user.getOrganisationUnits() ) { - if ( source == o || source.getParents().contains( o ) ) + if ( source == o || source.getAncestors().contains( o ) ) { return true; } === modified file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/organisationunit/OrganisationUnitController.java' --- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/organisationunit/OrganisationUnitController.java 2015-12-14 09:19:58 +0000 +++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/organisationunit/OrganisationUnitController.java 2015-12-14 16:33:02 +0000 @@ -159,7 +159,7 @@ { options.getOptions().put( "useWrapper", "true" ); organisationUnits.add( organisationUnit ); - List ancestors = organisationUnit.getParents(); + List ancestors = organisationUnit.getAncestors(); Collections.reverse( ancestors ); organisationUnits.addAll( ancestors ); } === modified file 'dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/commons/action/GetOrganisationUnitTreeAction.java' --- dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/commons/action/GetOrganisationUnitTreeAction.java 2015-12-14 09:19:58 +0000 +++ dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/commons/action/GetOrganisationUnitTreeAction.java 2015-12-14 16:33:02 +0000 @@ -218,7 +218,7 @@ organisationUnits.add( leaf ); organisationUnits.addAll( leaf.getChildren() ); - for ( OrganisationUnit organisationUnit : leaf.getParents() ) + for ( OrganisationUnit organisationUnit : leaf.getAncestors() ) { organisationUnits.add( organisationUnit ); organisationUnits.addAll( organisationUnit.getChildren() );