/* * Copyright (c) 2010-2015 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.prism.query.builder; import com.evolveum.midpoint.prism.*; import com.evolveum.midpoint.prism.match.PolyStringNormMatchingRule; import com.evolveum.midpoint.prism.match.PolyStringOrigMatchingRule; import com.evolveum.midpoint.prism.match.PolyStringStrictMatchingRule; import com.evolveum.midpoint.prism.match.StringIgnoreCaseMatchingRule; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.polystring.PolyString; import com.evolveum.midpoint.prism.query.*; import org.apache.commons.lang.Validate; import javax.xml.namespace.QName; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; /** * @author mederly */ public class R_AtomicFilter implements S_ConditionEntry, S_MatchingRuleEntry, S_RightHandItemEntry { final ItemPath itemPath; final PrismPropertyDefinition propertyDefinition; final PrismReferenceDefinition referenceDefinition; final ValueFilter filter; final R_Filter owner; final boolean expectingRightSide; R_AtomicFilter(ItemPath itemPath, ItemDefinition itemDefinition, R_Filter owner) { Validate.notNull(itemPath); Validate.notNull(itemDefinition); Validate.notNull(owner); this.itemPath = itemPath; if (itemDefinition instanceof PrismPropertyDefinition) { propertyDefinition = (PrismPropertyDefinition) itemDefinition; referenceDefinition = null; } else if (itemDefinition instanceof PrismReferenceDefinition) { propertyDefinition = null; referenceDefinition = (PrismReferenceDefinition) itemDefinition; } else { throw new IllegalStateException("Unsupported item definition: " + itemDefinition); } this.filter = null; this.owner = owner; this.expectingRightSide = false; } R_AtomicFilter(R_AtomicFilter original, ValueFilter filter, boolean expectingRightSide) { Validate.notNull(original); Validate.notNull(filter); this.itemPath = original.itemPath; this.propertyDefinition = original.propertyDefinition; this.referenceDefinition = original.referenceDefinition; this.filter = filter; this.owner = original.owner; this.expectingRightSide = expectingRightSide; } public R_AtomicFilter(R_AtomicFilter original, ValueFilter filter) { this(original, filter, false); } static R_AtomicFilter create(ItemPath itemPath, ItemDefinition itemDefinition, R_Filter owner) { return new R_AtomicFilter(itemPath, itemDefinition, owner); } @Override public S_AtomicFilterExit item(QName... names) { return item(new ItemPath(names), null); } @Override public S_AtomicFilterExit item(ItemPath itemPath, ItemDefinition itemDefinition) { if (!expectingRightSide) { throw new IllegalStateException("Unexpected item() call"); } if (filter == null) { throw new IllegalStateException("item() call with no filter"); } ValueFilter newFilter = filter.clone(); newFilter.setRightHandSidePath(itemPath); newFilter.setRightHandSideDefinition(itemDefinition); return new R_AtomicFilter(this, newFilter); } @Override public <T> S_MatchingRuleEntry eq(PrismProperty<T> property) { List<PrismPropertyValue<T>> clonedValues = (List<PrismPropertyValue<T>>) PrismPropertyValue.cloneCollection(property.getValues()); PrismPropertyDefinition<T> definition = this.propertyDefinition != null ? this.propertyDefinition : property.getDefinition(); return new R_AtomicFilter(this, EqualFilter.createEqual(itemPath, definition, null, owner.getPrismContext(), clonedValues)); } @Override public S_MatchingRuleEntry eq(Object... values) { return new R_AtomicFilter(this, EqualFilter.createEqual(itemPath, propertyDefinition, null, owner.getPrismContext(), values)); } @Override public S_RightHandItemEntry eq() { return new R_AtomicFilter(this, EqualFilter.createEqual(itemPath, propertyDefinition, null), true); } @Override public S_MatchingRuleEntry eqPoly(String orig, String norm) { return eq(new PolyString(orig, norm)); } @Override public S_MatchingRuleEntry eqPoly(String orig) { return eq(new PolyString(orig)); } @Override public S_MatchingRuleEntry gt(Object value) { return new R_AtomicFilter(this, GreaterFilter.createGreater(itemPath, propertyDefinition, false, owner.getPrismContext(), value)); } @Override public S_RightHandItemEntry gt() { return new R_AtomicFilter(this, GreaterFilter.createGreater(itemPath, propertyDefinition, false), true); } @Override public S_MatchingRuleEntry ge(Object value) { return new R_AtomicFilter(this, GreaterFilter.createGreater(itemPath, propertyDefinition, true, owner.getPrismContext(), value)); } @Override public S_RightHandItemEntry ge() { return new R_AtomicFilter(this, GreaterFilter.createGreater(itemPath, propertyDefinition, true), true); } @Override public S_MatchingRuleEntry lt(Object value) { return new R_AtomicFilter(this, LessFilter.createLess(itemPath, propertyDefinition, owner.getPrismContext(), value, false)); } @Override public S_RightHandItemEntry lt() { return new R_AtomicFilter(this, LessFilter.createLess(itemPath, propertyDefinition, false), true); } @Override public S_MatchingRuleEntry le(Object value) { return new R_AtomicFilter(this, LessFilter.createLess(itemPath, propertyDefinition, owner.getPrismContext(), value, true)); } @Override public S_RightHandItemEntry le() { return new R_AtomicFilter(this, LessFilter.createLess(itemPath, propertyDefinition, true), true); } @Override public S_MatchingRuleEntry startsWith(Object value) { return new R_AtomicFilter(this, SubstringFilter.createSubstring(itemPath, propertyDefinition, owner.getPrismContext(), null, value, true, false)); } @Override public S_MatchingRuleEntry startsWithPoly(String orig, String norm) { return startsWith(new PolyString(orig, norm)); } @Override public S_MatchingRuleEntry startsWithPoly(String orig) { return startsWith(new PolyString(orig)); } @Override public S_MatchingRuleEntry endsWith(Object value) { return new R_AtomicFilter(this, SubstringFilter.createSubstring(itemPath, propertyDefinition, owner.getPrismContext(), null, value, false, true)); } @Override public S_MatchingRuleEntry endsWithPoly(String orig, String norm) { return endsWith(new PolyString(orig, norm)); } @Override public S_MatchingRuleEntry endsWithPoly(String orig) { return endsWith(new PolyString(orig)); } @Override public S_MatchingRuleEntry contains(Object value) { return new R_AtomicFilter(this, SubstringFilter.createSubstring(itemPath, propertyDefinition, owner.getPrismContext(), null, value, false, false)); } @Override public S_MatchingRuleEntry containsPoly(String orig, String norm) { return contains(new PolyString(orig, norm)); } @Override public S_MatchingRuleEntry containsPoly(String orig) { return contains(new PolyString(orig)); } @Override public S_AtomicFilterExit ref(PrismReferenceValue... values) { if (values.length == 1 && values[0] == null) { return ref(Collections.emptyList()); } else { return ref(Arrays.asList(values)); } } @Override public S_AtomicFilterExit ref(Collection<PrismReferenceValue> values) { return new R_AtomicFilter(this, RefFilter.createReferenceEqual(itemPath, referenceDefinition, values)); } @Override public S_AtomicFilterExit ref(String... oids) { if (oids.length == 1 && oids[0] == null) { return ref(Collections.emptyList()); } else { return ref(Arrays.stream(oids).map(oid -> new PrismReferenceValue(oid)).collect(Collectors.toList())); } } @Override public S_AtomicFilterExit ref(String oid, QName targetTypeName) { if (oid != null) { return ref(new PrismReferenceValue(oid, targetTypeName)); } else { return ref(Collections.emptyList()); } } @Override public S_AtomicFilterExit isNull() { if (propertyDefinition != null) { return new R_AtomicFilter(this, EqualFilter.createEqual(itemPath, propertyDefinition, null, owner.getPrismContext())); } else if (referenceDefinition != null) { return new R_AtomicFilter(this, RefFilter.createReferenceEqual(itemPath, referenceDefinition, Collections.emptyList())); } else { throw new IllegalStateException("No definition"); } } @Override public S_AtomicFilterExit matching(QName matchingRuleName) { ValueFilter clone = filter.clone(); clone.setMatchingRule(matchingRuleName); return new R_AtomicFilter(this, clone); } @Override public S_AtomicFilterExit matchingOrig() { return matching(PolyStringOrigMatchingRule.NAME); } @Override public S_AtomicFilterExit matchingNorm() { return matching(PolyStringNormMatchingRule.NAME); } @Override public S_AtomicFilterExit matchingStrict() { return matching(PolyStringStrictMatchingRule.NAME); } @Override public S_AtomicFilterExit matchingCaseIgnore() { return matching(StringIgnoreCaseMatchingRule.NAME); } // ============================================================== // Methods which implement actions common with R_Filter @Override public S_FilterEntry or() { return finish().or(); } @Override public S_FilterEntry and() { return finish().and(); } @Override public ObjectQuery build() { return finish().build(); } @Override public ObjectFilter buildFilter() { return build().getFilter(); } @Override public S_FilterExit asc(QName... names) { return finish().asc(names); } @Override public S_FilterExit asc(ItemPath path) { return finish().asc(path); } @Override public S_FilterExit desc(QName... names) { return finish().desc(names); } @Override public S_FilterExit desc(ItemPath path) { return finish().desc(path); } @Override public S_FilterExit offset(Integer n) { return finish().offset(n); } @Override public S_FilterExit maxSize(Integer n) { return finish().maxSize(n); } @Override public S_AtomicFilterExit endBlock() { return finish().endBlock(); } private R_Filter finish() { if (filter == null) { throw new IllegalStateException("Filter is not yet created!"); } return owner.addSubfilter(filter); } }