/*
* Copyright (c) 2010-2017 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.provisioning.ucf.impl.connid.query;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.xml.namespace.QName;
import com.evolveum.midpoint.prism.PrismPropertyValue;
import org.identityconnectors.framework.common.objects.Attribute;
import org.identityconnectors.framework.common.objects.AttributeBuilder;
import org.identityconnectors.framework.common.objects.OperationalAttributes;
import org.identityconnectors.framework.common.objects.filter.Filter;
import org.identityconnectors.framework.common.objects.filter.FilterBuilder;
import com.evolveum.midpoint.prism.PrismValue;
import com.evolveum.midpoint.prism.path.ItemPath;
import com.evolveum.midpoint.prism.query.EqualFilter;
import com.evolveum.midpoint.prism.query.ObjectFilter;
import com.evolveum.midpoint.prism.query.SubstringFilter;
import com.evolveum.midpoint.prism.query.ValueFilter;
import com.evolveum.midpoint.provisioning.ucf.impl.connid.ConnIdNameMapper;
import com.evolveum.midpoint.provisioning.ucf.impl.connid.ConnIdUtil;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ActivationStatusType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ActivationType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.LockoutStatusType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType;
public class ValueOperation extends Operation {
public ValueOperation(FilterInterpreter interpreter) {
super(interpreter);
}
@Override
public <T> Filter interpret(ObjectFilter objectFilter, ConnIdNameMapper icfNameMapper) throws SchemaException {
OperationResult parentResult = new OperationResult("interpret");
ValueFilter valueFilter= (ValueFilter) objectFilter;
if (valueFilter.getParentPath().isEmpty()) {
throw new UnsupportedOperationException("Empty path is not supported (filter: " + objectFilter+")");
}
if (valueFilter.getParentPath().equivalent(new ItemPath(ShadowType.F_ATTRIBUTES))) {
try {
QName propName = valueFilter.getDefinition().getName();
String icfName = icfNameMapper.convertAttributeNameToIcf(propName, getInterpreter()
.getObjectClassDefinition(), "(attribute in the filter)");
if (objectFilter instanceof EqualFilter) {
EqualFilter<T> eq = (EqualFilter<T>) objectFilter;
Collection<Object> convertedValues = convertValues(propName, eq.getValues());
if (convertedValues == null || convertedValues.isEmpty()) {
// See MID-1460
throw new UnsupportedOperationException("Equals filter with a null value is NOT supported by ICF");
} else {
Attribute attr = AttributeBuilder.build(icfName, convertedValues);
if (valueFilter.getDefinition().isSingleValue()) {
return FilterBuilder.equalTo(attr);
} else {
return FilterBuilder.containsAllValues(attr);
}
}
} else if (objectFilter instanceof SubstringFilter) {
SubstringFilter substring = (SubstringFilter) objectFilter;
Collection<Object> convertedValues = convertValues(propName, substring.getValues());
if (convertedValues.isEmpty()) {
throw new IllegalArgumentException("Substring filter with null value makes no sense");
} else {
if (convertedValues.size() != 1) {
throw new IllegalArgumentException("Substring filter with multiple values makes no sense");
//maybe it does, through OR clauses
}
return FilterBuilder.contains(AttributeBuilder.build(icfName, convertedValues.iterator().next()));
}
} else {
throw new UnsupportedOperationException("Unsupported filter type: " + objectFilter);
}
} catch (SchemaException ex) {
throw ex;
}
} else if (valueFilter.getParentPath().equivalent(new ItemPath(ShadowType.F_ACTIVATION))) {
if (objectFilter instanceof EqualFilter) {
QName propName = valueFilter.getDefinition().getName();
EqualFilter<T> eq = (EqualFilter<T>) objectFilter;
List<PrismPropertyValue<T>> values = eq.getValues();
if (values.size() != 1) {
throw new SchemaException("Unexpected number of values in filter "+objectFilter);
}
PrismPropertyValue<T> pval = values.get(0);
String icfName;
Object convertedValue;
if (propName.equals(ActivationType.F_ADMINISTRATIVE_STATUS)) {
icfName = OperationalAttributes.ENABLE_NAME;
convertedValue = pval.getValue() == ActivationStatusType.ENABLED;
} else if (propName.equals(ActivationType.F_LOCKOUT_STATUS)) {
icfName = OperationalAttributes.LOCK_OUT_NAME;
convertedValue = pval.getValue() == LockoutStatusType.LOCKED;
} else {
throw new UnsupportedOperationException("Unsupported activation property "+propName+" in filter: " + objectFilter);
}
Attribute attr = AttributeBuilder.build(icfName, convertedValue);
if (valueFilter.getDefinition().isSingleValue()) {
return FilterBuilder.equalTo(attr);
} else {
return FilterBuilder.containsAllValues(attr);
}
} else {
throw new UnsupportedOperationException("Unsupported filter type in filter: " + objectFilter);
}
} else {
throw new UnsupportedOperationException("Unsupported parent path "+valueFilter.getParentPath()+" in filter: " + objectFilter);
}
}
private <T> Collection<Object> convertValues(QName propName, List<PrismPropertyValue<T>> values) throws SchemaException {
if (values == null) {
return null;
}
Collection<Object> convertedValues = new ArrayList<>();
for (PrismValue value : values) {
Object converted = ConnIdUtil.convertValueToIcf(value, null, propName);
convertedValues.add(converted);
}
return convertedValues;
}
}