=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/organisationunit/OrganisationUnitQueryParams.java' --- dhis-2/dhis-api/src/main/java/org/hisp/dhis/organisationunit/OrganisationUnitQueryParams.java 2015-09-17 06:53:33 +0000 +++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/organisationunit/OrganisationUnitQueryParams.java 2015-09-17 12:25:32 +0000 @@ -40,6 +40,8 @@ */ public class OrganisationUnitQueryParams { + private static final int CODE_SEP_LENGTH = CodeGenerator.CODESIZE + 1; + /** * Query string to match like name and exactly on UID and code. */ @@ -56,7 +58,12 @@ private Set groups = new HashSet<>(); /** - * The maximum number of organisation unit levels to fetch, relative to the + * The levels of organisation units to include. + */ + private Set levels = new HashSet<>(); + + /** + * The maximum number of organisation unit levels to include, relative to the * real root of the hierarchy. */ private Integer maxLevels; @@ -93,9 +100,19 @@ return groups != null && !groups.isEmpty(); } + public boolean hasLevels() + { + return levels != null && !levels.isEmpty(); + } + public int getMaxLevelsPathLength() { - return maxLevels != null ? ( ( CodeGenerator.CODESIZE + 1 ) * maxLevels ) : -1; + return maxLevels != null ? ( CODE_SEP_LENGTH * maxLevels ) : -1; + } + + public int getLevelPathLength( int level ) + { + return CODE_SEP_LENGTH * level; } @Override @@ -105,6 +122,7 @@ add( "query", query ). add( "parents", parents ). add( "groups", groups ). + add( "levels", levels ). add( "maxLevels", maxLevels ). add( "first", first ). add( "max", max ).toString(); @@ -144,6 +162,16 @@ this.groups = groups; } + public Set getLevels() + { + return levels; + } + + public void setLevels( Set levels ) + { + this.levels = levels; + } + public Integer getMaxLevels() { return maxLevels; === modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/organisationunit/hibernate/HibernateOrganisationUnitStore.java' --- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/organisationunit/hibernate/HibernateOrganisationUnitStore.java 2015-09-11 19:29:32 +0000 +++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/organisationunit/hibernate/HibernateOrganisationUnitStore.java 2015-09-17 12:25:32 +0000 @@ -163,6 +163,18 @@ hql += hlp.whereAnd() + " (lower(o.name) like :queryLower or o.code = :query or o.uid = :query) " ; } + if ( params.hasParents() ) + { + hql += hlp.whereAnd() + " ("; + + for ( OrganisationUnit parent : params.getParents() ) + { + hql += "o.path like :" + parent.getUid() + " or "; + } + + hql = TextUtils.removeLastOr( hql ) + ") "; + } + if ( params.hasGroups() ) { for ( OrganisationUnitGroup group : params.getGroups() ) @@ -171,13 +183,13 @@ } } - if ( params.hasParents() ) + if ( params.hasLevels() ) { hql += hlp.whereAnd() + " ("; - for ( OrganisationUnit parent : params.getParents() ) + for ( Integer level : params.getLevels() ) { - hql += "o.path like :" + parent.getUid() + " or "; + hql += " length(o.path) = :levelPathLength" + level + " or "; } hql = TextUtils.removeLastOr( hql ) + ") "; @@ -197,6 +209,14 @@ query.setString( "queryLower", "%" + params.getQuery().toLowerCase() + "%" ); query.setString( "query", params.getQuery() ); } + + if ( params.hasParents() ) + { + for ( OrganisationUnit parent : params.getParents() ) + { + query.setString( parent.getUid(), "%" + parent.getUid() + "%" ); + } + } if ( params.hasGroups() ) { @@ -206,11 +226,11 @@ } } - if ( params.hasParents() ) + if ( params.hasLevels() ) { - for ( OrganisationUnit parent : params.getParents() ) + for ( Integer level : params.getLevels() ) { - query.setString( parent.getUid(), "%" + parent.getUid() + "%" ); + query.setInteger( "levelPathLength" + level, level ); } } === modified file 'dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/organisationunit/OrganisationUnitStoreTest.java' --- dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/organisationunit/OrganisationUnitStoreTest.java 2015-09-11 19:29:32 +0000 +++ dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/organisationunit/OrganisationUnitStoreTest.java 2015-09-17 12:25:32 +0000 @@ -64,13 +64,13 @@ @Test public void testGetOrganisationUnits() { - OrganisationUnit ouA = createOrganisationUnit( 'A' ); - OrganisationUnit ouB = createOrganisationUnit( 'B', ouA ); - OrganisationUnit ouC = createOrganisationUnit( 'C', ouA ); - OrganisationUnit ouD = createOrganisationUnit( 'D', ouB ); - OrganisationUnit ouE = createOrganisationUnit( 'E', ouB ); - OrganisationUnit ouF = createOrganisationUnit( 'F', ouC ); - OrganisationUnit ouG = createOrganisationUnit( 'G', ouC ); + OrganisationUnit ouA = createOrganisationUnit( 'A' ); // 1 + OrganisationUnit ouB = createOrganisationUnit( 'B', ouA ); // 2 + OrganisationUnit ouC = createOrganisationUnit( 'C', ouA ); // 2 + OrganisationUnit ouD = createOrganisationUnit( 'D', ouB ); // 3 + OrganisationUnit ouE = createOrganisationUnit( 'E', ouB ); // 3 + OrganisationUnit ouF = createOrganisationUnit( 'F', ouC ); // 4 + OrganisationUnit ouG = createOrganisationUnit( 'G', ouC ); // 4 orgUnitStore.save( ouA ); orgUnitStore.save( ouB ); @@ -88,6 +88,8 @@ orgUnitGroupStore.save( ogA ); orgUnitGroupStore.save( ogB ); + // Query + OrganisationUnitQueryParams params = new OrganisationUnitQueryParams(); params.setQuery( "UnitC" ); @@ -95,6 +97,8 @@ assertEquals( 1, ous.size() ); assertTrue( ous.contains( ouC ) ); + + // Query params = new OrganisationUnitQueryParams(); params.setQuery( "OrganisationUnitCodeA" ); @@ -104,6 +108,8 @@ assertTrue( ous.contains( ouA ) ); assertEquals( 1, ous.size() ); + // Parents + params = new OrganisationUnitQueryParams(); params.setParents( Sets.newHashSet( ouC, ouF ) ); @@ -112,6 +118,8 @@ assertEquals( 3, ous.size() ); assertTrue( ous.containsAll( Sets.newHashSet( ouC, ouF, ouG ) ) ); + // Groups + params = new OrganisationUnitQueryParams(); params.setGroups( Sets.newHashSet( ogA ) ); @@ -120,6 +128,39 @@ assertEquals( 2, ous.size() ); assertTrue( ous.containsAll( Sets.newHashSet( ouD, ouF ) ) ); + // Levels + + params = new OrganisationUnitQueryParams(); + params.setLevels( Sets.newHashSet( 2 ) ); + + ous = orgUnitStore.getOrganisationUnits( params ); + + assertEquals( 2, ous.size() ); + assertTrue( ous.containsAll( Sets.newHashSet( ouB, ouC ) ) ); + + // Levels + + params = new OrganisationUnitQueryParams(); + params.setLevels( Sets.newHashSet( 2, 3 ) ); + + ous = orgUnitStore.getOrganisationUnits( params ); + + assertEquals( 4, ous.size() ); + assertTrue( ous.containsAll( Sets.newHashSet( ouB, ouC, ouD, ouE ) ) ); + + // Levels and groups + + params = new OrganisationUnitQueryParams(); + params.setLevels( Sets.newHashSet( 4 ) ); + params.setGroups( Sets.newHashSet( ogA ) ); + + ous = orgUnitStore.getOrganisationUnits( params ); + + assertEquals( 1, ous.size() ); + assertTrue( ous.containsAll( Sets.newHashSet( ouF ) ) ); + + // Parents and groups + params = new OrganisationUnitQueryParams(); params.setParents( Sets.newHashSet( ouC ) ); params.setGroups( Sets.newHashSet( ogB ) ); @@ -128,6 +169,8 @@ assertEquals( 1, ous.size() ); assertTrue( ous.containsAll( Sets.newHashSet( ouG ) ) ); + + // Parents and max levels params = new OrganisationUnitQueryParams(); params.setParents( Sets.newHashSet( ouA ) ); @@ -138,6 +181,8 @@ assertEquals( 3, ous.size() ); assertTrue( ous.containsAll( Sets.newHashSet( ouA, ouB, ouC ) ) ); + // Parents and max levels + params = new OrganisationUnitQueryParams(); params.setParents( Sets.newHashSet( ouA ) ); params.setMaxLevels( 3 ); @@ -147,6 +192,8 @@ assertEquals( 7, ous.size() ); assertTrue( ous.containsAll( Sets.newHashSet( ouA, ouB, ouC, ouD, ouE, ouF, ouG ) ) ); + // Parents and max levels + params = new OrganisationUnitQueryParams(); params.setParents( Sets.newHashSet( ouA ) ); params.setMaxLevels( 1 ); @@ -156,6 +203,8 @@ assertEquals( 1, ous.size() ); assertTrue( ous.containsAll( Sets.newHashSet( ouA ) ) ); + // Parents and max levels + params = new OrganisationUnitQueryParams(); params.setParents( Sets.newHashSet( ouB ) ); params.setMaxLevels( 3 );