/*
* Copyright (c) 2010-2014 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.model.impl.scripting;
import com.evolveum.midpoint.model.api.ScriptExecutionException;
import com.evolveum.midpoint.prism.*;
import com.evolveum.midpoint.schema.constants.SchemaConstants;
import com.evolveum.midpoint.util.DOMUtil;
import com.evolveum.midpoint.util.DebugDumpable;
import com.evolveum.midpoint.util.DebugUtil;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.midpoint.xml.ns._public.common.common_3.EventHandlerType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType;
import com.evolveum.prism.xml.ns._public.types_3.ObjectDeltaType;
import org.jetbrains.annotations.NotNull;
import javax.xml.namespace.QName;
import java.util.*;
/**
* Data that are passed between individual scripting actions.
*
* The content passed between actions (expressions) is a list of prism values
* (object, container, reference, property).
*
* @author mederly
*/
public class Data implements DebugDumpable {
private final List<PrismValue> data = new ArrayList<>(); // all items are not null
// we want clients to use explicit constructors
private Data() {
}
public List<PrismValue> getData() {
return data;
}
@Override
public String debugDump() {
return debugDump(0);
}
@Override
public String debugDump(int indent) {
return DebugUtil.debugDump(data, indent);
}
public static Data create(Item data) {
Data d = createEmpty();
d.addItem(data);
return d;
}
public static Data createEmpty() {
return new Data();
}
public void addAllFrom(Data otherData) {
if (otherData != null) {
data.addAll(otherData.getData());
}
}
@Deprecated
public void addItem(@NotNull Item<?,?> item) {
data.addAll(item.getValues());
}
public void addValue(PrismValue value) {
data.add(value);
}
public void addValues(List<PrismValue> values) {
data.addAll(values);
}
public String getDataAsSingleString() throws ScriptExecutionException {
if (!data.isEmpty()) {
if (data.size() == 1) {
return (String) ((PrismPropertyValue) data.get(0)).getRealValue(); // todo implement some diagnostics when this would fail
} else {
throw new ScriptExecutionException("Multiple values where just one is expected");
}
} else {
return null;
}
}
public static Data createItem(PrismValue value, PrismContext prismContext) throws SchemaException {
Data data = createEmpty();
if (value != null) {
data.addValue(value);
}
return data;
// // TODO fix this temporary solution (haven't we somewhere universal method to do this?)
// if (value instanceof PrismReferenceValue) {
// PrismReference ref = new PrismReference(new QName("reference"));
// ref.add((PrismReferenceValue) value);
// return create(ref);
// } else if (value instanceof PrismContainerValue) {
// PrismContainerValue pcv = (PrismContainerValue) value;
// return create(pcv.asSingleValuedContainer(new QName("container")));
// } else if (value instanceof PrismPropertyValue) {
// if (value.isRaw()) {
// throw new IllegalArgumentException("Value cannot be raw at this point: " + value);
// }
// Class<?> clazz = value.getRealClass();
// assert clazz != null;
// PrismPropertyDefinition<?> propertyDefinition;
// List<PrismPropertyDefinition> defs = prismContext.getSchemaRegistry()
// .findItemDefinitionsByCompileTimeClass(clazz, PrismPropertyDefinition.class);
// if (defs.size() == 1) {
// propertyDefinition = defs.get(0);
// } else if (String.class.isAssignableFrom(clazz)) {
// propertyDefinition = new PrismPropertyDefinitionImpl<>(PLAIN_STRING_ELEMENT_NAME, DOMUtil.XSD_STRING, prismContext);
// } else if (ObjectDeltaType.class.isAssignableFrom(clazz)) {
// propertyDefinition = new PrismPropertyDefinitionImpl<>(SchemaConstants.T_OBJECT_DELTA, SchemaConstants.T_OBJECT_DELTA_TYPE, prismContext);
// } else if (EventHandlerType.class.isAssignableFrom(clazz)) {
// propertyDefinition = new PrismPropertyDefinitionImpl<>(SchemaConstants.C_EVENT_HANDLER, EventHandlerType.COMPLEX_TYPE, prismContext);
// } else {
// // maybe determine type from class would be sufficient
// TypeDefinition td = prismContext.getSchemaRegistry().findTypeDefinitionByCompileTimeClass(clazz, TypeDefinition.class);
// if (td != null) {
// propertyDefinition = new PrismPropertyDefinitionImpl<>(SchemaConstants.C_VALUE, td.getTypeName(), prismContext);
// } else {
// throw new IllegalStateException(
// "Unsupported data class (to be put into scripting data as property): " + clazz);
// }
// }
// PrismProperty<?> property = propertyDefinition.instantiate();
// property.add((PrismPropertyValue) value);
// return create(property);
// } else if (value == null) {
// return createEmpty();
// } else {
// throw new IllegalArgumentException("Unsupported prism value: " + value);
// }
}
public Collection<ObjectReferenceType> getDataAsReferences(QName defaultTargetType) throws ScriptExecutionException {
Collection<ObjectReferenceType> retval = new ArrayList<>(data.size());
for (PrismValue value : data) {
if (value instanceof PrismObjectValue) {
PrismObjectValue objectValue = (PrismObjectValue) value;
ObjectReferenceType ref = new ObjectReferenceType();
ref.setType(objectValue.asPrismObject().getDefinition().getTypeName()); // todo check the definition is present
ref.setOid(objectValue.getOid()); // todo check if oid is present
retval.add(ref);
} else if (value instanceof PrismPropertyValue) {
Object realValue = ((PrismPropertyValue) value).getRealValue();
if (realValue instanceof String) {
ObjectReferenceType ref = new ObjectReferenceType();
ref.setType(defaultTargetType);
ref.setOid((String) realValue); // todo implement search by name
retval.add(ref);
} else if (realValue instanceof ObjectReferenceType) {
retval.add((ObjectReferenceType) realValue);
} else {
throw new ScriptExecutionException("Unsupported reference type: " + value.getClass());
}
} else if (value instanceof PrismReferenceValue) {
PrismReferenceValue referenceValue = (PrismReferenceValue) value;
ObjectReferenceType ref = new ObjectReferenceType();
ref.setupReferenceValue(referenceValue);
retval.add(ref);
}
}
return retval;
}
}