/*
* 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.prism.query;
import com.evolveum.midpoint.prism.*;
import com.evolveum.midpoint.prism.match.MatchingRuleRegistry;
import com.evolveum.midpoint.prism.path.ItemPath;
import com.evolveum.midpoint.util.QNameUtil;
import com.evolveum.midpoint.util.exception.SchemaException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.xml.namespace.QName;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public class RefFilter extends ValueFilter<PrismReferenceValue, PrismReferenceDefinition> {
private static final long serialVersionUID = 1L;
public RefFilter(@NotNull ItemPath fullPath, @Nullable PrismReferenceDefinition definition,
@Nullable List<PrismReferenceValue> values, @Nullable ExpressionWrapper expression) {
super(fullPath, definition, null, values, expression, null, null);
}
public static RefFilter createReferenceEqual(ItemPath path, PrismReferenceDefinition definition, Collection<PrismReferenceValue> values) {
return new RefFilter(path, definition, values != null ? new ArrayList<>(values) : null, null);
}
public static RefFilter createReferenceEqual(ItemPath path, PrismReferenceDefinition definition, ExpressionWrapper expression) {
return new RefFilter(path, definition, null, expression);
}
@SuppressWarnings("CloneDoesntCallSuperClone")
@Override
public RefFilter clone() {
return new RefFilter(getFullPath(), getDefinition(), getClonedValues(), getExpression());
}
@Override
protected String getFilterName() {
return "REF";
}
@Override
public boolean match(PrismContainerValue value, MatchingRuleRegistry matchingRuleRegistry) throws SchemaException {
Item filterItem = getFilterItem();
Item objectItem = getObjectItem(value);
if (!super.match(value, matchingRuleRegistry)) {
return false;
}
boolean filterItemIsEmpty = getValues() == null || getValues().isEmpty();
boolean objectItemIsEmpty = objectItem == null || objectItem.isEmpty();
if (filterItemIsEmpty && objectItemIsEmpty) {
return true;
}
assert !filterItemIsEmpty; // if both are empty, the previous statement causes 'return true'
assert !objectItemIsEmpty; // if only one of them is empty, the super.match() returned false
List<Object> objectValues = objectItem.getValues();
for (Object v : objectValues) {
if (!(v instanceof PrismReferenceValue)) {
throw new IllegalArgumentException("Not supported prism value for ref equals filter. It must be an instance of PrismReferenceValue but it is " + v.getClass());
}
if (!isInFilterItem((PrismReferenceValue) v, filterItem)){
return false;
}
}
return true;
}
private boolean isInFilterItem(PrismReferenceValue v, Item filterItem) {
for (Object filterValue : filterItem.getValues()) {
if (!(filterValue instanceof PrismReferenceValue)) {
throw new IllegalArgumentException("Not supported prism value for ref equals filter. It must be an instance of PrismReferenceValue but it is " + v.getClass());
}
PrismReferenceValue filterRV = (PrismReferenceValue) filterValue;
if (valuesMatch(v, filterRV)) {
return true;
}
}
return false;
}
private boolean valuesMatch(PrismReferenceValue value, PrismReferenceValue filterValue) {
if (!value.getOid().equals(filterValue.getOid())) {
return false;
}
if (!QNameUtil.match(PrismConstants.Q_ANY, filterValue.getRelation())) {
// similar to relation-matching code in PrismReferenceValue (but awkward to unify, so keeping separate)
PrismContext prismContext = getPrismContext();
QName thisRelation = value.getRelation();
QName filterRelation = filterValue.getRelation();
if (prismContext != null) {
if (thisRelation == null) {
thisRelation = prismContext.getDefaultRelation();
}
if (filterRelation == null) {
filterRelation = prismContext.getDefaultRelation();
}
}
if (!QNameUtil.match(thisRelation, filterRelation)) {
return false;
}
}
// TODO treat also targetType (see ReferenceRestriction in repo)
return true;
}
@Override
public boolean equals(Object obj, boolean exact) {
return obj instanceof RefFilter && super.equals(obj, exact);
}
}