/*
* 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.common;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.xml.bind.JAXBElement;
import javax.xml.namespace.QName;
import com.evolveum.midpoint.prism.Item;
import com.evolveum.midpoint.prism.ItemDefinition;
import com.evolveum.midpoint.prism.PrismContext;
import com.evolveum.midpoint.prism.PrismProperty;
import com.evolveum.midpoint.prism.PrismPropertyDefinition;
import com.evolveum.midpoint.prism.PrismValue;
import com.evolveum.midpoint.prism.xnode.RootXNode;
import com.evolveum.midpoint.prism.xnode.XNode;
import com.evolveum.midpoint.schema.constants.SchemaConstants;
import com.evolveum.midpoint.util.JAXBUtil;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ExpressionReturnMultiplicityType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ExpressionType;
import com.evolveum.prism.xml.ns._public.types_3.RawType;
/**
* Utility class for manipulation of static values in expressions. This is not
* intended for a general public usage. It is used to set and get pre-computed
* values in expressions and mappings, e.g. when used between model and provisioning
* in provisioning scripts.
*
* @author Radovan Semancik
*
*/
public class StaticExpressionUtil {
/**
* Returns either Object (if result is supposed to be single-value) or Collection<X> (if result is supposed to be multi-value)
*/
public static Object getStaticOutput(ExpressionType expressionType, PrismPropertyDefinition outputDefinition,
String contextDescription, ExpressionReturnMultiplicityType preferredMultiplicity, PrismContext prismContext) throws SchemaException {
PrismProperty<?> output = getPropertyStatic(expressionType, outputDefinition, contextDescription, prismContext);
ExpressionReturnMultiplicityType multiplicity = preferredMultiplicity;
if (expressionType.getReturnMultiplicity() != null) {
multiplicity = expressionType.getReturnMultiplicity();
} else if (output != null && output.size() > 1) {
multiplicity = ExpressionReturnMultiplicityType.MULTI;
}
if (output == null) {
switch (multiplicity) {
case MULTI: return new ArrayList<Object>(0);
case SINGLE: return null;
default: throw new IllegalStateException("Unknown return type "+multiplicity);
}
} else {
switch (multiplicity) {
case MULTI: return output.getRealValues();
case SINGLE: return output.getRealValue();
default: throw new IllegalStateException("Unknown return type "+multiplicity);
}
}
}
public static <X> PrismProperty<X> getPropertyStatic(ExpressionType expressionType, PrismPropertyDefinition outputDefinition,
String contextDescription, PrismContext prismContext) throws SchemaException {
Collection<JAXBElement<?>> expressionEvaluatorElement = expressionType.getExpressionEvaluator();
return (PrismProperty) parseValueElements(expressionEvaluatorElement, outputDefinition, contextDescription, prismContext);
}
/**
* Always returns collection, even for single-valued results.
*/
public static <X> Collection<X> getPropertyStaticRealValues(ExpressionType expressionType, PrismPropertyDefinition outputDefinition,
String contextDescription, PrismContext prismContext) throws SchemaException {
PrismProperty<X> output = getPropertyStatic(expressionType, outputDefinition, contextDescription, prismContext);
return output.getRealValues();
}
public static <IV extends PrismValue,ID extends ItemDefinition> Item<IV,ID> parseValueElements(Collection<?> valueElements, ID outputDefinition,
String contextDescription, PrismContext prismContext) throws SchemaException {
Item<IV,ID> output = null;
for (Object valueElement: valueElements) {
if (!(valueElement instanceof JAXBElement<?>)) {
throw new SchemaException("Literal expression cannot handle element "+valueElement+" "+valueElement.getClass().getName()+" in "
+contextDescription);
}
QName valueElementName = JAXBUtil.getElementQName(valueElement);
if (!valueElementName.equals(SchemaConstants.C_VALUE)) {
throw new SchemaException("Literal expression cannot handle element <"+valueElementName + "> in "+ contextDescription);
}
JAXBElement<?> jaxbElement = (JAXBElement<?>)valueElement;
// not checking declaredType because it may be Object.class instead ... but actual type must be of RawType
if (jaxbElement.getValue() != null && !(jaxbElement.getValue() instanceof RawType)) {
throw new SchemaException("Literal expression cannot handle JAXBElement value type "+jaxbElement.getValue().getClass()+" in "
+contextDescription);
}
RawType rawType = (RawType)jaxbElement.getValue();
//Item<V> elementItem = xnodeProcessor.parseItem(rawType.getXnode(), outputDefinition.getName(), outputDefinition);
Item<IV,ID> elementItem = rawType.getParsedItem(outputDefinition);
if (output == null) {
output = elementItem;
} else {
output.addAll(elementItem.getClonedValues());
}
}
return output;
}
public static <IV extends PrismValue,ID extends ItemDefinition> List<JAXBElement<RawType>> serializeValueElements(Item<IV,ID> item, String contextDescription) throws SchemaException {
if (item == null) {
return null;
}
List<JAXBElement<RawType>> elements = new ArrayList<>(item.size());
for (PrismValue value : item.getValues()) {
RootXNode xnode = item.getPrismContext().xnodeSerializer().serialize(value);
RawType rawType = new RawType(xnode.getSubnode(), item.getPrismContext());
JAXBElement<RawType> jaxbElement = new JAXBElement<>(SchemaConstants.C_VALUE, RawType.class, rawType);
elements.add(jaxbElement);
}
return elements;
}
}