diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ExistsFilter.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ExistsFilter.java index dc7fdf59de6..36cbb54b65f 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ExistsFilter.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ExistsFilter.java @@ -61,7 +61,11 @@ public ObjectFilter getFilter() { return filter; } - public static ExistsFilter createExists(ItemPath itemPath, PrismContainerDefinition containerDef, + public void setFilter(ObjectFilter filter) { + this.filter = filter; + } + + public static ExistsFilter createExists(ItemPath itemPath, PrismContainerDefinition containerDef, ObjectFilter filter) throws SchemaException { ItemDefinition itemDefinition = FilterUtils.findItemDefinition(itemPath, containerDef); return new ExistsFilter(itemPath, itemDefinition, filter); @@ -79,7 +83,11 @@ public ObjectFilter clone() { return new ExistsFilter(fullPath, definition, f); } - @Override + public ExistsFilter cloneEmpty() { + return new ExistsFilter(fullPath, definition, null); + } + + @Override public boolean match(PrismContainerValue value, MatchingRuleRegistry matchingRuleRegistry) throws SchemaException { throw new UnsupportedOperationException(); } diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/TypeFilter.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/TypeFilter.java index 155fbb46bdd..49b98cc0154 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/TypeFilter.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/TypeFilter.java @@ -64,7 +64,11 @@ public ObjectFilter clone() { return new TypeFilter(type, f); } - // untested; TODO test this method + public TypeFilter cloneEmpty() { + return new TypeFilter(type, null); + } + + // untested; TODO test this method @Override public boolean match(PrismContainerValue value, MatchingRuleRegistry matchingRuleRegistry) throws SchemaException { if (value == null) { diff --git a/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/ObjectQueryUtil.java b/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/ObjectQueryUtil.java index b2d5ad201a1..3b55250a75e 100644 --- a/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/ObjectQueryUtil.java +++ b/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/ObjectQueryUtil.java @@ -21,6 +21,8 @@ import javax.xml.namespace.QName; import com.evolveum.midpoint.prism.*; +import com.evolveum.midpoint.prism.query.*; +import com.evolveum.midpoint.prism.query.Visitor; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.Validate; import org.apache.commons.lang.mutable.MutableBoolean; @@ -31,21 +33,6 @@ import com.evolveum.midpoint.prism.polystring.PolyString; import com.evolveum.midpoint.prism.polystring.PolyStringNormalizer; import com.evolveum.midpoint.prism.polystring.PrismDefaultPolyStringNormalizer; -import com.evolveum.midpoint.prism.query.AllFilter; -import com.evolveum.midpoint.prism.query.AndFilter; -import com.evolveum.midpoint.prism.query.EqualFilter; -import com.evolveum.midpoint.prism.query.NaryLogicalFilter; -import com.evolveum.midpoint.prism.query.NoneFilter; -import com.evolveum.midpoint.prism.query.NotFilter; -import com.evolveum.midpoint.prism.query.ObjectFilter; -import com.evolveum.midpoint.prism.query.ObjectQuery; -import com.evolveum.midpoint.prism.query.OrFilter; -import com.evolveum.midpoint.prism.query.OrgFilter; -import com.evolveum.midpoint.prism.query.RefFilter; -import com.evolveum.midpoint.prism.query.TypeFilter; -import com.evolveum.midpoint.prism.query.UndefinedFilter; -import com.evolveum.midpoint.prism.query.ValueFilter; -import com.evolveum.midpoint.prism.query.Visitor; import com.evolveum.midpoint.schema.ResourceShadowDiscriminator; import com.evolveum.midpoint.util.DOMUtil; import com.evolveum.midpoint.util.exception.SchemaException; @@ -317,9 +304,11 @@ public static boolean isAll(ObjectFilter filter) { } public static boolean isNone(ObjectFilter filter) { - return filter != null && filter instanceof NoneFilter; + return filter instanceof NoneFilter; } + // returns ALL, NONE only at the top level (never inside the filter) + // never returns UNDEFINED public static ObjectFilter simplify(ObjectFilter filter) { if (filter == null) { return null; @@ -335,19 +324,23 @@ public static ObjectFilter simplify(ObjectFilter filter) { // AND with "true", just skip it } else { ObjectFilter simplifiedSubfilter = simplify(subfilter); - simplifiedFilter.addCondition(simplifiedSubfilter); + if (simplifiedSubfilter instanceof NoneFilter) { + return NoneFilter.createNone(); + } else if (simplifiedSubfilter == null || simplifiedSubfilter instanceof AllFilter) { + // skip + } else { + simplifiedFilter.addCondition(simplifiedSubfilter); + } } } if (simplifiedFilter.isEmpty()) { return AllFilter.createAll(); - } - - if (simplifiedFilter.getConditions().size() == 1){ + } else if (simplifiedFilter.getConditions().size() == 1) { return simplifiedFilter.getConditions().iterator().next(); + } else { + return simplifiedFilter; } - return simplifiedFilter; - } else if (filter instanceof OrFilter) { List conditions = ((OrFilter)filter).getConditions(); OrFilter simplifiedFilter = ((OrFilter)filter).cloneEmpty(); @@ -359,27 +352,29 @@ public static ObjectFilter simplify(ObjectFilter filter) { return AllFilter.createAll(); } else { ObjectFilter simplifiedSubfilter = simplify(subfilter); - simplifiedFilter.addCondition(simplifiedSubfilter); + if (simplifiedSubfilter instanceof NoneFilter) { + // skip + } else if (simplifiedSubfilter == null || simplifiedSubfilter instanceof AllFilter) { + return NoneFilter.createNone(); + } else { + simplifiedFilter.addCondition(simplifiedSubfilter); + } } } if (simplifiedFilter.isEmpty()) { - return AllFilter.createAll(); - } - - if (simplifiedFilter.getConditions().size() == 1){ + return NoneFilter.createNone(); + } else if (simplifiedFilter.getConditions().size() == 1) { return simplifiedFilter.getConditions().iterator().next(); + } else { + return simplifiedFilter; } - - return simplifiedFilter; - + } else if (filter instanceof NotFilter) { ObjectFilter subfilter = ((NotFilter)filter).getFilter(); ObjectFilter simplifiedSubfilter = simplify(subfilter); - if (subfilter instanceof UndefinedFilter){ - return null; - } else if (subfilter instanceof NoneFilter) { + if (simplifiedSubfilter instanceof NoneFilter) { return AllFilter.createAll(); - } else if (subfilter instanceof AllFilter) { + } else if (simplifiedSubfilter == null || simplifiedSubfilter instanceof AllFilter) { return NoneFilter.createNone(); } else { NotFilter simplifiedFilter = ((NotFilter)filter).cloneEmpty(); @@ -389,7 +384,23 @@ public static ObjectFilter simplify(ObjectFilter filter) { } else if (filter instanceof TypeFilter) { ObjectFilter subFilter = ((TypeFilter) filter).getFilter(); ObjectFilter simplifiedSubfilter = simplify(subFilter); - TypeFilter simplifiedFilter = (TypeFilter) ((TypeFilter) filter).clone(); + if (simplifiedSubfilter instanceof AllFilter) { + simplifiedSubfilter = null; + } else if (simplifiedSubfilter instanceof NoneFilter) { + return NoneFilter.createNone(); + } + TypeFilter simplifiedFilter = ((TypeFilter) filter).cloneEmpty(); + simplifiedFilter.setFilter(simplifiedSubfilter); + return simplifiedFilter; + } else if (filter instanceof ExistsFilter) { + ObjectFilter subFilter = ((ExistsFilter) filter).getFilter(); + ObjectFilter simplifiedSubfilter = simplify(subFilter); + if (simplifiedSubfilter instanceof AllFilter) { + simplifiedSubfilter = null; + } else if (simplifiedSubfilter instanceof NoneFilter) { + return NoneFilter.createNone(); + } + ExistsFilter simplifiedFilter = ((ExistsFilter) filter).cloneEmpty(); simplifiedFilter.setFilter(simplifiedSubfilter); return simplifiedFilter; } else if (filter instanceof UndefinedFilter || filter instanceof AllFilter) { diff --git a/infra/schema/src/test/java/com/evolveum/midpoint/schema/TestFilterSimplifier.java b/infra/schema/src/test/java/com/evolveum/midpoint/schema/TestFilterSimplifier.java new file mode 100644 index 00000000000..510f72a329c --- /dev/null +++ b/infra/schema/src/test/java/com/evolveum/midpoint/schema/TestFilterSimplifier.java @@ -0,0 +1,495 @@ +/* + * Copyright (c) 2010-2016 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.evolveum.midpoint.schema; + +import com.evolveum.midpoint.prism.PrismContext; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.prism.query.*; +import com.evolveum.midpoint.prism.query.builder.QueryBuilder; +import com.evolveum.midpoint.prism.util.PrismTestUtil; +import com.evolveum.midpoint.schema.constants.MidPointConstants; +import com.evolveum.midpoint.schema.util.ObjectQueryUtil; +import com.evolveum.midpoint.util.DebugUtil; +import com.evolveum.midpoint.util.PrettyPrinter; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; +import org.testng.annotations.BeforeSuite; +import org.testng.annotations.Test; +import org.xml.sax.SAXException; + +import java.io.IOException; + +import static org.testng.AssertJUnit.assertEquals; +import static org.testng.AssertJUnit.assertTrue; + +/** + * @author mederly + * + */ +public class TestFilterSimplifier { + + @BeforeSuite + public void setup() throws SchemaException, SAXException, IOException { + PrettyPrinter.setDefaultNamespacePrefix(MidPointConstants.NS_MIDPOINT_PUBLIC_PREFIX); + PrismTestUtil.resetPrismContext(MidPointPrismContextFactory.FACTORY); + } + + @Test + public void test010All() throws Exception { + System.out.println("===[ test010All ]==="); + + // GIVEN + PrismContext prismContext = PrismTestUtil.getPrismContext(); + + // WHEN + ObjectFilter filter = QueryBuilder.queryFor(UserType.class, prismContext) + .all().buildFilter(); + System.out.println("Original filter:\n" + filter.debugDump()); + + // THEN + ObjectFilter simplified = ObjectQueryUtil.simplify(filter); + System.out.println("Simplified filter:\n" + DebugUtil.debugDump(simplified)); + assertTrue("Wrong simplified filter: " + simplified, simplified == null || simplified instanceof AllFilter); + } + + @Test + public void test020None() throws Exception { + System.out.println("===[ test020None ]==="); + + // GIVEN + PrismContext prismContext = PrismTestUtil.getPrismContext(); + + // WHEN + ObjectFilter filter = QueryBuilder.queryFor(UserType.class, prismContext) + .none().buildFilter(); + System.out.println("Original filter:\n" + filter.debugDump()); + + // THEN + ObjectFilter simplified = ObjectQueryUtil.simplify(filter); + System.out.println("Simplified filter:\n" + DebugUtil.debugDump(simplified)); + assertTrue("Wrong simplified filter: " + simplified, simplified instanceof NoneFilter); + } + + @Test + public void test030Undefined() throws Exception { + System.out.println("===[ test030Undefined ]==="); + + // GIVEN + PrismContext prismContext = PrismTestUtil.getPrismContext(); + + // WHEN + ObjectFilter filter = QueryBuilder.queryFor(UserType.class, prismContext) + .undefined().buildFilter(); + System.out.println("Original filter:\n" + filter.debugDump()); + + // THEN + ObjectFilter simplified = ObjectQueryUtil.simplify(filter); + System.out.println("Simplified filter:\n" + DebugUtil.debugDump(simplified)); + assertTrue("Wrong simplified filter: " + simplified, simplified == null || simplified instanceof AllFilter); + } + + @Test + public void test100AndLevel1() throws Exception { + System.out.println("===[ test100AndLevel1 ]==="); + + // GIVEN + PrismContext prismContext = PrismTestUtil.getPrismContext(); + + // WHEN + ObjectFilter filter = QueryBuilder.queryFor(UserType.class, prismContext) + .all() + .and().none() + .and().undefined() + .buildFilter(); + System.out.println("Original filter:\n" + filter.debugDump()); + + // THEN + ObjectFilter simplified = ObjectQueryUtil.simplify(filter); + System.out.println("Simplified filter:\n" + DebugUtil.debugDump(simplified)); + assertTrue("Wrong simplified filter: " + simplified, simplified instanceof NoneFilter); + } + + @Test + public void test110AndLevel1WithoutNone() throws Exception { + System.out.println("===[ test110AndLevel1WithoutNone ]==="); + + // GIVEN + PrismContext prismContext = PrismTestUtil.getPrismContext(); + + // WHEN + ObjectFilter filter = QueryBuilder.queryFor(UserType.class, prismContext) + .all() + .and().undefined() + .buildFilter(); + System.out.println("Original filter:\n" + filter.debugDump()); + + // THEN + ObjectFilter simplified = ObjectQueryUtil.simplify(filter); + System.out.println("Simplified filter:\n" + DebugUtil.debugDump(simplified)); + assertTrue("Wrong simplified filter: " + simplified, simplified == null || simplified instanceof AllFilter); + } + + @Test + public void test120AndEmpty() throws Exception { + System.out.println("===[ test120AndEmpty ]==="); + + // GIVEN + PrismContext prismContext = PrismTestUtil.getPrismContext(); + + // WHEN + ObjectFilter filter = AndFilter.createAnd(); + System.out.println("Original filter:\n" + filter.debugDump()); + + // THEN + ObjectFilter simplified = ObjectQueryUtil.simplify(filter); + System.out.println("Simplified filter:\n" + DebugUtil.debugDump(simplified)); + assertTrue("Wrong simplified filter: " + simplified, simplified == null || simplified instanceof AllFilter); + } + + @Test + public void test150OrLevel1() throws Exception { + System.out.println("===[ test150OrLevel1 ]==="); + + // GIVEN + PrismContext prismContext = PrismTestUtil.getPrismContext(); + + // WHEN + ObjectFilter filter = QueryBuilder.queryFor(UserType.class, prismContext) + .all() + .or().none() + .or().undefined() + .buildFilter(); + System.out.println("Original filter:\n" + filter.debugDump()); + + // THEN + ObjectFilter simplified = ObjectQueryUtil.simplify(filter); + System.out.println("Simplified filter:\n" + DebugUtil.debugDump(simplified)); + assertTrue("Wrong simplified filter: " + simplified, simplified == null || simplified instanceof AllFilter); + } + + @Test + public void test160OrLevel1WithoutAll() throws Exception { + System.out.println("===[ test160OrLevel1WithoutAll ]==="); + + // GIVEN + PrismContext prismContext = PrismTestUtil.getPrismContext(); + + // WHEN + ObjectFilter filter = QueryBuilder.queryFor(UserType.class, prismContext) + .none() + .or().undefined() + .buildFilter(); + System.out.println("Original filter:\n" + filter.debugDump()); + + // THEN + ObjectFilter simplified = ObjectQueryUtil.simplify(filter); + System.out.println("Simplified filter:\n" + DebugUtil.debugDump(simplified)); + assertTrue("Wrong simplified filter: " + simplified, simplified instanceof NoneFilter); + } + + @Test + public void test170OrLevel1Undefined() throws Exception { + System.out.println("===[ test170OrLevel1Undefined ]==="); + + // GIVEN + PrismContext prismContext = PrismTestUtil.getPrismContext(); + + // WHEN + ObjectFilter filter = OrFilter.createOr(UndefinedFilter.createUndefined()); + System.out.println("Original filter:\n" + filter.debugDump()); + + // THEN + ObjectFilter simplified = ObjectQueryUtil.simplify(filter); + System.out.println("Simplified filter:\n" + DebugUtil.debugDump(simplified)); + assertTrue("Wrong simplified filter: " + simplified, simplified instanceof NoneFilter); + } + + @Test + public void test180OrEmpty() throws Exception { + System.out.println("===[ test180OrEmpty ]==="); + + // GIVEN + PrismContext prismContext = PrismTestUtil.getPrismContext(); + + // WHEN + ObjectFilter filter = OrFilter.createOr(); + System.out.println("Original filter:\n" + filter.debugDump()); + + // THEN + ObjectFilter simplified = ObjectQueryUtil.simplify(filter); + System.out.println("Simplified filter:\n" + DebugUtil.debugDump(simplified)); + assertTrue("Wrong simplified filter: " + simplified, simplified instanceof NoneFilter); + } + + @Test + public void test200AndLevel2() throws Exception { + System.out.println("===[ test200AndLevel2 ]==="); + + // GIVEN + PrismContext prismContext = PrismTestUtil.getPrismContext(); + + // WHEN + ObjectFilter filter = QueryBuilder.queryFor(UserType.class, prismContext) + .all() + .and().undefined() + .and() + .block() + .none().or().none() + .endBlock() + .and() + .block() + .none().or().none() + .endBlock() + .buildFilter(); + System.out.println("Original filter:\n" + filter.debugDump()); + + // THEN + ObjectFilter simplified = ObjectQueryUtil.simplify(filter); + System.out.println("Simplified filter:\n" + DebugUtil.debugDump(simplified)); + assertTrue("Wrong simplified filter: " + simplified, simplified instanceof NoneFilter); + } + + @Test + public void test210OrLevel2() throws Exception { + System.out.println("===[ test210OrLevel2 ]==="); + + // GIVEN + PrismContext prismContext = PrismTestUtil.getPrismContext(); + + // WHEN + ObjectFilter filter = QueryBuilder.queryFor(UserType.class, prismContext) + .none() + .or().undefined() + .or() + .block() + .none().or().none() + .endBlock() + .or() + .block() + .none().or().none() + .endBlock() + .buildFilter(); + System.out.println("Original filter:\n" + filter.debugDump()); + + // THEN + ObjectFilter simplified = ObjectQueryUtil.simplify(filter); + System.out.println("Simplified filter:\n" + DebugUtil.debugDump(simplified)); + assertTrue("Wrong simplified filter: " + simplified, simplified instanceof NoneFilter); + } + + @Test + public void test300NotAll() throws Exception { + System.out.println("===[ test300NotAll ]==="); + + // GIVEN + PrismContext prismContext = PrismTestUtil.getPrismContext(); + + // WHEN + ObjectFilter filter = QueryBuilder.queryFor(UserType.class, prismContext) + .not().all() + .buildFilter(); + System.out.println("Original filter:\n" + filter.debugDump()); + + // THEN + ObjectFilter simplified = ObjectQueryUtil.simplify(filter); + System.out.println("Simplified filter:\n" + DebugUtil.debugDump(simplified)); + assertTrue("Wrong simplified filter: " + simplified, simplified instanceof NoneFilter); + } + + @Test + public void test310NotNone() throws Exception { + System.out.println("===[ test310NotNone ]==="); + + // GIVEN + PrismContext prismContext = PrismTestUtil.getPrismContext(); + + // WHEN + ObjectFilter filter = QueryBuilder.queryFor(UserType.class, prismContext) + .not().none() + .buildFilter(); + System.out.println("Original filter:\n" + filter.debugDump()); + + // THEN + ObjectFilter simplified = ObjectQueryUtil.simplify(filter); + System.out.println("Simplified filter:\n" + DebugUtil.debugDump(simplified)); + assertTrue("Wrong simplified filter: " + simplified, simplified == null || simplified instanceof AllFilter); + } + + @Test + public void test320NotNotAll() throws Exception { + System.out.println("===[ test320NotNotAll ]==="); + + // GIVEN + PrismContext prismContext = PrismTestUtil.getPrismContext(); + + // WHEN + ObjectFilter filter = QueryBuilder.queryFor(UserType.class, prismContext) + .not().block().not().all().endBlock() + .buildFilter(); + System.out.println("Original filter:\n" + filter.debugDump()); + + // THEN + ObjectFilter simplified = ObjectQueryUtil.simplify(filter); + System.out.println("Simplified filter:\n" + DebugUtil.debugDump(simplified)); + assertTrue("Wrong simplified filter: " + simplified, simplified == null || simplified instanceof AllFilter); + } + + @Test + public void test330NotNotNone() throws Exception { + System.out.println("===[ test330NotNotNone ]==="); + + // GIVEN + PrismContext prismContext = PrismTestUtil.getPrismContext(); + + // WHEN + ObjectFilter filter = QueryBuilder.queryFor(UserType.class, prismContext) + .not().block().not().none().endBlock() + .buildFilter(); + System.out.println("Original filter:\n" + filter.debugDump()); + + // THEN + ObjectFilter simplified = ObjectQueryUtil.simplify(filter); + System.out.println("Simplified filter:\n" + DebugUtil.debugDump(simplified)); + assertTrue("Wrong simplified filter: " + simplified, simplified instanceof NoneFilter); + } + + @Test + public void test400TypeAll() throws Exception { + System.out.println("===[ test400TypeAll ]==="); + + // GIVEN + PrismContext prismContext = PrismTestUtil.getPrismContext(); + + // WHEN + ObjectFilter filter = QueryBuilder.queryFor(UserType.class, prismContext) + .type(UserType.class).all() + .buildFilter(); + System.out.println("Original filter:\n" + filter.debugDump()); + + // THEN + ObjectFilter simplified = ObjectQueryUtil.simplify(filter); + System.out.println("Simplified filter:\n" + DebugUtil.debugDump(simplified)); + assertTrue("Wrong simplified filter: " + simplified, simplified instanceof TypeFilter); + TypeFilter typeSimplified = (TypeFilter) simplified; + assertEquals("Wrong simplified filter type", UserType.COMPLEX_TYPE, typeSimplified.getType()); + assertTrue("Wrong simplified filter subfilter: " + typeSimplified.getFilter(), ObjectQueryUtil.isAll(typeSimplified.getFilter())); + } + + @Test + public void test410TypeNone() throws Exception { + System.out.println("===[ test410TypeNone ]==="); + + // GIVEN + PrismContext prismContext = PrismTestUtil.getPrismContext(); + + // WHEN + ObjectFilter filter = QueryBuilder.queryFor(UserType.class, prismContext) + .type(UserType.class).none() + .buildFilter(); + System.out.println("Original filter:\n" + filter.debugDump()); + + // THEN + ObjectFilter simplified = ObjectQueryUtil.simplify(filter); + System.out.println("Simplified filter:\n" + DebugUtil.debugDump(simplified)); + assertTrue("Wrong simplified filter: " + simplified, simplified instanceof NoneFilter); + } + + @Test + public void test420TypeUndefined() throws Exception { + System.out.println("===[ test420TypeUndefined ]==="); + + // GIVEN + PrismContext prismContext = PrismTestUtil.getPrismContext(); + + // WHEN + ObjectFilter filter = QueryBuilder.queryFor(UserType.class, prismContext) + .type(UserType.class).undefined() + .buildFilter(); + System.out.println("Original filter:\n" + filter.debugDump()); + + // THEN + ObjectFilter simplified = ObjectQueryUtil.simplify(filter); + System.out.println("Simplified filter:\n" + DebugUtil.debugDump(simplified)); + assertTrue("Wrong simplified filter: " + simplified, simplified instanceof TypeFilter); + TypeFilter typeSimplified = (TypeFilter) simplified; + assertEquals("Wrong simplified filter type", UserType.COMPLEX_TYPE, typeSimplified.getType()); + assertTrue("Wrong simplified filter subfilter: " + typeSimplified.getFilter(), ObjectQueryUtil.isAll(typeSimplified.getFilter())); + } + + @Test + public void test500ExistsAll() throws Exception { + System.out.println("===[ test500ExistsAll ]==="); + + // GIVEN + PrismContext prismContext = PrismTestUtil.getPrismContext(); + + // WHEN + ObjectFilter filter = QueryBuilder.queryFor(UserType.class, prismContext) + .exists(UserType.F_ASSIGNMENT).all() + .buildFilter(); + System.out.println("Original filter:\n" + filter.debugDump()); + + // THEN + ObjectFilter simplified = ObjectQueryUtil.simplify(filter); + System.out.println("Simplified filter:\n" + DebugUtil.debugDump(simplified)); + assertTrue("Wrong simplified filter: " + simplified, simplified instanceof ExistsFilter); + ExistsFilter existsSimplified = (ExistsFilter) simplified; + assertEquals("Wrong simplified filter path", new ItemPath(UserType.F_ASSIGNMENT), existsSimplified.getFullPath()); + assertTrue("Wrong simplified filter subfilter: " + existsSimplified.getFilter(), ObjectQueryUtil.isAll(existsSimplified.getFilter())); + } + + @Test + public void test510ExistsNone() throws Exception { + System.out.println("===[ test510ExistsNone ]==="); + + // GIVEN + PrismContext prismContext = PrismTestUtil.getPrismContext(); + + // WHEN + ObjectFilter filter = QueryBuilder.queryFor(UserType.class, prismContext) + .exists(UserType.F_ASSIGNMENT).none() + .buildFilter(); + System.out.println("Original filter:\n" + filter.debugDump()); + + // THEN + ObjectFilter simplified = ObjectQueryUtil.simplify(filter); + System.out.println("Simplified filter:\n" + DebugUtil.debugDump(simplified)); + assertTrue("Wrong simplified filter: " + simplified, simplified instanceof NoneFilter); + } + + @Test + public void test520ExistsUndefined() throws Exception { + System.out.println("===[ test520ExistsUndefined ]==="); + + // GIVEN + PrismContext prismContext = PrismTestUtil.getPrismContext(); + + // WHEN + ObjectFilter filter = QueryBuilder.queryFor(UserType.class, prismContext) + .exists(UserType.F_ASSIGNMENT).undefined() + .buildFilter(); + System.out.println("Original filter:\n" + filter.debugDump()); + + // THEN + ObjectFilter simplified = ObjectQueryUtil.simplify(filter); + System.out.println("Simplified filter:\n" + DebugUtil.debugDump(simplified)); + assertTrue("Wrong simplified filter: " + simplified, simplified instanceof ExistsFilter); + ExistsFilter existsSimplified = (ExistsFilter) simplified; + assertEquals("Wrong simplified filter path", new ItemPath(UserType.F_ASSIGNMENT), existsSimplified.getFullPath()); + assertTrue("Wrong simplified filter subfilter: " + existsSimplified.getFilter(), ObjectQueryUtil.isAll(existsSimplified.getFilter())); + } + +} diff --git a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java index cde1909158e..45712b0bd69 100644 --- a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java +++ b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java @@ -757,6 +757,38 @@ public void test080QueryExistsAssignment() throws Exception { } } + @Test(expectedExceptions = UnsupportedOperationException.class) + public void test080QueryExistsAssignmentAll() throws Exception { + Session session = open(); + + try { + ObjectQuery query = QueryBuilder.queryFor(UserType.class, prismContext) + .exists(F_ASSIGNMENT).all() + .asc(F_NAME) + .build(); + + query.setFilter(ObjectQueryUtil.simplify(query.getFilter())); + + String real = getInterpretedQuery2(session, UserType.class, query); + // this doesn't work as expected ... maybe inner join would be better! Until implemented, we should throw UOO + String expected = "select\n" + + " u.fullObject,\n" + + " u.stringsCount,\n" + + " u.longsCount,\n" + + " u.datesCount,\n" + + " u.referencesCount,\n" + + " u.polysCount,\n" + + " u.booleansCount\n" + + "from\n" + + " RUser u\n" + + " left join u.assignments a with a.assignmentOwner = :assignmentOwner\n" + + "order by u.name.orig asc\n"; + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + @Test public void test090QuerySingleAssignmentWithTargetAndTenant() throws Exception { Session session = open(); diff --git a/repo/repo-sql-impl/pom.xml b/repo/repo-sql-impl/pom.xml index d7a4ade29f8..daa82dcca64 100644 --- a/repo/repo-sql-impl/pom.xml +++ b/repo/repo-sql-impl/pom.xml @@ -68,7 +68,11 @@ audit-api 3.5-SNAPSHOT - + + + org.jetbrains + annotations-java5 + commons-lang commons-lang diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryServiceImpl.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryServiceImpl.java index 7911c74192e..2eecad43bb2 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryServiceImpl.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryServiceImpl.java @@ -61,6 +61,7 @@ import org.hibernate.SessionFactory; import org.hibernate.internal.SessionFactoryImpl; import org.hibernate.jdbc.Work; +import org.jetbrains.annotations.NotNull; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Repository; @@ -225,15 +226,10 @@ public SearchResultList> searchObjects(Cla if (filter instanceof NoneFilter) { subResult.recordSuccess(); return new SearchResultList(new ArrayList>(0)); - } else if (filter instanceof AllFilter) { - query = query.cloneEmpty(); - query.setFilter(null); } else { - query = query.cloneEmpty(); - query.setFilter(filter); - } - - } + query = replaceSimplifiedFilter(query, filter); + } + } SqlPerformanceMonitor pm = getPerformanceMonitor(); long opHandle = pm.registerOperationStart("searchObjects"); @@ -254,7 +250,14 @@ public SearchResultList> searchObjects(Cla } } - @Override + @NotNull + private ObjectQuery replaceSimplifiedFilter(ObjectQuery query, ObjectFilter filter) { + query = query.cloneEmpty(); + query.setFilter(filter instanceof AllFilter ? null : filter); + return query; + } + + @Override public SearchResultList searchContainers(Class type, ObjectQuery query, Collection> options, OperationResult parentResult) throws SchemaException { @@ -273,14 +276,10 @@ public SearchResultList searchContainers(Class t if (filter instanceof NoneFilter) { result.recordSuccess(); return new SearchResultList(new ArrayList(0)); - } else if (filter instanceof AllFilter) { - query = query.cloneEmpty(); - query.setFilter(null); } else { - query = query.cloneEmpty(); - query.setFilter(filter); - } - } + query = replaceSimplifiedFilter(query, filter); + } + } SqlPerformanceMonitor pm = getPerformanceMonitor(); long opHandle = pm.registerOperationStart("searchContainers"); @@ -747,15 +746,10 @@ public SearchResultMetadata searchObjectsIterative(Class< if (filter instanceof NoneFilter) { subResult.recordSuccess(); return null; - //shouldn't be this in ObjectQueryUtil.simplify? - } else if (filter instanceof AllFilter){ - query = query.cloneEmpty(); - query.setFilter(null); } else { - query = query.cloneEmpty(); - query.setFilter(filter); - } - } + query = replaceSimplifiedFilter(query, filter); + } + } if (getConfiguration().isIterativeSearchByPaging()) { if (strictlySequential) { diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java index 7dbd0d8eb71..744caeacacd 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java @@ -21,32 +21,12 @@ import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.polystring.PolyString; -import com.evolveum.midpoint.prism.query.AllFilter; -import com.evolveum.midpoint.prism.query.AndFilter; -import com.evolveum.midpoint.prism.query.ExistsFilter; -import com.evolveum.midpoint.prism.query.InOidFilter; -import com.evolveum.midpoint.prism.query.NoneFilter; -import com.evolveum.midpoint.prism.query.NotFilter; -import com.evolveum.midpoint.prism.query.ObjectFilter; -import com.evolveum.midpoint.prism.query.ObjectOrdering; -import com.evolveum.midpoint.prism.query.ObjectPaging; -import com.evolveum.midpoint.prism.query.ObjectQuery; -import com.evolveum.midpoint.prism.query.OrFilter; -import com.evolveum.midpoint.prism.query.OrderDirection; -import com.evolveum.midpoint.prism.query.OrgFilter; -import com.evolveum.midpoint.prism.query.PropertyValueFilter; -import com.evolveum.midpoint.prism.query.RefFilter; -import com.evolveum.midpoint.prism.query.TypeFilter; -import com.evolveum.midpoint.prism.query.UndefinedFilter; +import com.evolveum.midpoint.prism.query.*; +import com.evolveum.midpoint.repo.sql.ObjectPagingAfterOid; import com.evolveum.midpoint.repo.sql.SqlRepositoryConfiguration; import com.evolveum.midpoint.repo.sql.data.common.embedded.RPolyString; import com.evolveum.midpoint.repo.sql.query.QueryException; -import com.evolveum.midpoint.repo.sql.query2.definition.JpaAnyContainerDefinition; -import com.evolveum.midpoint.repo.sql.query2.definition.JpaAnyPropertyDefinition; -import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; -import com.evolveum.midpoint.repo.sql.query2.definition.JpaPropertyDefinition; -import com.evolveum.midpoint.repo.sql.query2.definition.JpaReferenceDefinition; -import com.evolveum.midpoint.repo.sql.query2.definition.JpaDataNodeDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.*; import com.evolveum.midpoint.repo.sql.query2.hqm.ProjectionElement; import com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; @@ -56,17 +36,7 @@ import com.evolveum.midpoint.repo.sql.query2.matcher.StringMatcher; import com.evolveum.midpoint.repo.sql.query2.resolution.ItemPathResolver; import com.evolveum.midpoint.repo.sql.query2.resolution.ProperDataSearchResult; -import com.evolveum.midpoint.repo.sql.query2.restriction.AndRestriction; -import com.evolveum.midpoint.repo.sql.query2.restriction.AnyPropertyRestriction; -import com.evolveum.midpoint.repo.sql.query2.restriction.ExistsRestriction; -import com.evolveum.midpoint.repo.sql.query2.restriction.InOidRestriction; -import com.evolveum.midpoint.repo.sql.query2.restriction.NotRestriction; -import com.evolveum.midpoint.repo.sql.query2.restriction.OrRestriction; -import com.evolveum.midpoint.repo.sql.query2.restriction.OrgRestriction; -import com.evolveum.midpoint.repo.sql.query2.restriction.PropertyRestriction; -import com.evolveum.midpoint.repo.sql.query2.restriction.ReferenceRestriction; -import com.evolveum.midpoint.repo.sql.query2.restriction.Restriction; -import com.evolveum.midpoint.repo.sql.query2.restriction.TypeRestriction; +import com.evolveum.midpoint.repo.sql.query2.restriction.*; import com.evolveum.midpoint.repo.sql.util.GetContainerableResult; import com.evolveum.midpoint.repo.sql.util.GetObjectResult; import com.evolveum.midpoint.schema.GetOperationOptions; @@ -81,8 +51,6 @@ import java.util.HashMap; import java.util.Map; -import com.evolveum.midpoint.repo.sql.ObjectPagingAfterOid; - /** * Interprets midPoint queries by translating them to hibernate (HQL) ones. *

@@ -180,7 +148,7 @@ public RootHibernateQuery interpret(ObjectQuery query, Class