=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/query/Criteria.java' --- dhis-2/dhis-api/src/main/java/org/hisp/dhis/query/Criteria.java 2015-06-03 03:42:15 +0000 +++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/query/Criteria.java 2015-06-04 09:25:32 +0000 @@ -70,8 +70,8 @@ continue; } - if ( restriction.getParameters().size() > restriction.getOperator().getMax() - || restriction.getParameters().size() < restriction.getOperator().getMin() ) + if ( (restriction.getOperator().getMax() != null && restriction.getParameters().size() > restriction.getOperator().getMax()) + || (restriction.getOperator().getMin() != null && restriction.getParameters().size() < restriction.getOperator().getMin()) ) { continue; } === modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/query/Operator.java' --- dhis-2/dhis-api/src/main/java/org/hisp/dhis/query/Operator.java 2015-02-23 11:17:55 +0000 +++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/query/Operator.java 2015-06-04 09:25:32 +0000 @@ -43,6 +43,7 @@ LT( Typed.from( String.class, Boolean.class, Number.class, Date.class ), 1 ), GE( Typed.from( String.class, Boolean.class, Number.class, Date.class ), 1 ), LE( Typed.from( String.class, Boolean.class, Number.class, Date.class ), 1 ), + NULL( Typed.from( String.class, Boolean.class, Number.class, Date.class ) ), BETWEEN( Typed.from( String.class, Number.class, Date.class ), 2 ), LIKE( Typed.from( String.class ), 1 ), ILIKE( Typed.from( String.class ), 1 ), === modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/query/Restrictions.java' --- dhis-2/dhis-api/src/main/java/org/hisp/dhis/query/Restrictions.java 2015-03-09 08:57:50 +0000 +++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/query/Restrictions.java 2015-06-04 09:25:32 +0000 @@ -91,6 +91,11 @@ return new Restriction( path, Operator.IN, values ); } + public static Restriction isNull( String path ) + { + return new Restriction( path, Operator.NULL ); + } + private Restrictions() { } === modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/query/CriteriaQueryEngine.java' --- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/query/CriteriaQueryEngine.java 2015-06-04 01:55:31 +0000 +++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/query/CriteriaQueryEngine.java 2015-06-04 09:25:32 +0000 @@ -146,7 +146,12 @@ if ( Restriction.class.isInstance( criterion ) ) { Restriction restriction = (Restriction) criterion; - junction.add( getHibernateCriterion( schema, restriction ) ); + Criterion hibernateCriterion = getHibernateCriterion( schema, restriction ); + + if ( hibernateCriterion != null ) + { + junction.add( hibernateCriterion ); + } } else if ( Junction.class.isInstance( criterion ) ) { @@ -175,7 +180,12 @@ if ( Restriction.class.isInstance( criterion ) ) { Restriction restriction = (Restriction) criterion; - criteria.add( getHibernateCriterion( schema, restriction ) ); + Criterion hibernateCriterion = getHibernateCriterion( schema, restriction ); + + if ( hibernateCriterion != null ) + { + criteria.add( hibernateCriterion ); + } } else if ( Junction.class.isInstance( criterion ) ) { @@ -199,6 +209,7 @@ } } + // TODO verify parameters length @SuppressWarnings( "unchecked" ) private Criterion getHibernateCriterion( Schema schema, Restriction restriction ) { @@ -216,11 +227,6 @@ parameters.add( QueryUtils.getValue( property.getKlass(), parameter ) ); } - if ( parameters.isEmpty() ) - { - return null; - } - switch ( restriction.getOperator() ) { case EQ: @@ -268,6 +274,10 @@ return Restrictions.in( property.getFieldName(), (Collection) parameters.get( 0 ) ); } + case NULL: + { + return Restrictions.isNull( property.getFieldName() ); + } } return null; === modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/query/DefaultQueryService.java' --- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/query/DefaultQueryService.java 2015-06-02 04:25:37 +0000 +++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/query/DefaultQueryService.java 2015-06-04 09:25:32 +0000 @@ -140,7 +140,7 @@ String[] split = filter.split( ":" ); - if ( split.length != 3 ) + if ( split.length < 3 ) { return null; } @@ -202,6 +202,10 @@ { return Restrictions.in( split[0], parseInOperator( split[2] ) ); } + case "null": + { + return Restrictions.isNull( split[0] ); + } } return null; === modified file 'dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/query/QueryServiceTest.java' --- dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/query/QueryServiceTest.java 2015-06-04 05:24:23 +0000 +++ dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/query/QueryServiceTest.java 2015-06-04 09:25:32 +0000 @@ -643,4 +643,40 @@ assertTrue( collectionContainsUid( result.getItems(), "deabcdefghC" ) ); assertTrue( collectionContainsUid( result.getItems(), "deabcdefghD" ) ); } + + @Test + public void testIsNull() + { + createDataElements(); + Query query = Query.from( schemaService.getDynamicSchema( DataElement.class ) ); + query.add( Restrictions.isNull( "categoryCombo" ) ); + + Result result = queryService.query( query ); + + assertEquals( 6, result.size() ); + + assertTrue( collectionContainsUid( result.getItems(), "deabcdefghA" ) ); + assertTrue( collectionContainsUid( result.getItems(), "deabcdefghB" ) ); + assertTrue( collectionContainsUid( result.getItems(), "deabcdefghC" ) ); + assertTrue( collectionContainsUid( result.getItems(), "deabcdefghD" ) ); + assertTrue( collectionContainsUid( result.getItems(), "deabcdefghE" ) ); + assertTrue( collectionContainsUid( result.getItems(), "deabcdefghF" ) ); + } + + @Test + public void testIsNullUrl() + { + createDataElements(); + Query query = queryService.getQueryFromUrl( DataElement.class, Lists.newArrayList( "categoryCombo:null" ), Lists.newArrayList() ); + Result result = queryService.query( query ); + + assertEquals( 6, result.size() ); + + assertTrue( collectionContainsUid( result.getItems(), "deabcdefghA" ) ); + assertTrue( collectionContainsUid( result.getItems(), "deabcdefghB" ) ); + assertTrue( collectionContainsUid( result.getItems(), "deabcdefghC" ) ); + assertTrue( collectionContainsUid( result.getItems(), "deabcdefghD" ) ); + assertTrue( collectionContainsUid( result.getItems(), "deabcdefghE" ) ); + assertTrue( collectionContainsUid( result.getItems(), "deabcdefghF" ) ); + } } === modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/objectfilter/Filters.java' --- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/objectfilter/Filters.java 2015-06-04 01:55:31 +0000 +++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/objectfilter/Filters.java 2015-06-04 09:25:32 +0000 @@ -57,6 +57,11 @@ { Op op = OpFactory.create( operator ); + if ( op == null ) + { + return; + } + if ( op.wantValue() ) { if ( value == null )