use of com.evolveum.midpoint.prism.delta.PrismValueDeltaSetTriple in project midpoint by Evolveum.
the class WfExpressionEvaluationHelper method evaluateExpression.
@SuppressWarnings("unchecked")
@NotNull
public <T> List<T> evaluateExpression(ExpressionType expressionType, ExpressionVariables variables, String contextDescription, Class<T> clazz, QName typeName, Function<Object, Object> additionalConvertor, Task task, OperationResult result) throws ObjectNotFoundException, SchemaException, ExpressionEvaluationException {
ExpressionFactory expressionFactory = getExpressionFactory();
PrismContext prismContext = expressionFactory.getPrismContext();
PrismPropertyDefinition<String> resultDef = new PrismPropertyDefinitionImpl<>(new QName(SchemaConstants.NS_C, "result"), typeName, prismContext);
Expression<PrismPropertyValue<String>, PrismPropertyDefinition<String>> expression = expressionFactory.makeExpression(expressionType, resultDef, contextDescription, task, result);
ExpressionEvaluationContext context = new ExpressionEvaluationContext(null, variables, contextDescription, task, result);
context.setAdditionalConvertor(additionalConvertor);
PrismValueDeltaSetTriple<PrismPropertyValue<String>> exprResultTriple = ModelExpressionThreadLocalHolder.evaluateExpressionInContext(expression, context, task, result);
return exprResultTriple.getZeroSet().stream().map(ppv -> (T) ppv.getRealValue()).collect(Collectors.toList());
}
use of com.evolveum.midpoint.prism.delta.PrismValueDeltaSetTriple in project midpoint by Evolveum.
the class ConsolidationProcessor method consolidateValuesToModifyDelta.
private <F extends FocusType> ObjectDelta<ShadowType> consolidateValuesToModifyDelta(LensContext<F> context, LensProjectionContext projCtx, boolean addUnchangedValues, Task task, OperationResult result) throws SchemaException, ExpressionEvaluationException, ObjectNotFoundException, CommunicationException, ConfigurationException, SecurityViolationException, PolicyViolationException {
// "Squeeze" all the relevant mappings into a data structure that we can process conveniently. We want to have all the
// (meta)data about relevant for a specific attribute in one data structure, not spread over several account constructions.
Map<QName, DeltaSetTriple<ItemValueWithOrigin<PrismPropertyValue<?>, PrismPropertyDefinition<?>>>> squeezedAttributes = sqeeze(projCtx, construction -> (Collection) construction.getAttributeMappings());
projCtx.setSqueezedAttributes(squeezedAttributes);
Map<QName, DeltaSetTriple<ItemValueWithOrigin<PrismContainerValue<ShadowAssociationType>, PrismContainerDefinition<ShadowAssociationType>>>> squeezedAssociations = sqeeze(projCtx, construction -> construction.getAssociationMappings());
projCtx.setSqueezedAssociations(squeezedAssociations);
// So, we do it here - once and for all.
if (!squeezedAssociations.isEmpty()) {
fillInAssociationNames(squeezedAssociations);
}
MappingExtractor<PrismPropertyValue<QName>, PrismPropertyDefinition<QName>, F> auxiliaryObjectClassExtractor = construction -> {
PrismValueDeltaSetTripleProducer<PrismPropertyValue<QName>, PrismPropertyDefinition<QName>> prod = new PrismValueDeltaSetTripleProducer<PrismPropertyValue<QName>, PrismPropertyDefinition<QName>>() {
@Override
public QName getMappingQName() {
return ShadowType.F_AUXILIARY_OBJECT_CLASS;
}
@Override
public PrismValueDeltaSetTriple<PrismPropertyValue<QName>> getOutputTriple() {
PrismValueDeltaSetTriple<PrismPropertyValue<QName>> triple = new PrismValueDeltaSetTriple<>();
if (construction.getAuxiliaryObjectClassDefinitions() != null) {
for (RefinedObjectClassDefinition auxiliaryObjectClassDefinition : construction.getAuxiliaryObjectClassDefinitions()) {
triple.addToZeroSet(new PrismPropertyValue<QName>(auxiliaryObjectClassDefinition.getTypeName()));
}
}
return triple;
}
@Override
public MappingStrengthType getStrength() {
return MappingStrengthType.STRONG;
}
@Override
public PrismValueDeltaSetTripleProducer<PrismPropertyValue<QName>, PrismPropertyDefinition<QName>> clone() {
return this;
}
@Override
public boolean isExclusive() {
return false;
}
@Override
public boolean isAuthoritative() {
return true;
}
@Override
public boolean isSourceless() {
return false;
}
};
Collection<PrismValueDeltaSetTripleProducer<PrismPropertyValue<QName>, PrismPropertyDefinition<QName>>> col = new ArrayList<>(1);
col.add(prod);
return col;
};
Map<QName, DeltaSetTriple<ItemValueWithOrigin<PrismPropertyValue<QName>, PrismPropertyDefinition<QName>>>> squeezedAuxiliaryObjectClasses = sqeeze(projCtx, auxiliaryObjectClassExtractor);
projCtx.setSqueezedAuxiliaryObjectClasses(squeezedAuxiliaryObjectClasses);
ResourceShadowDiscriminator discr = projCtx.getResourceShadowDiscriminator();
ObjectDelta<ShadowType> objectDelta = new ObjectDelta<ShadowType>(ShadowType.class, ChangeType.MODIFY, prismContext);
objectDelta.setOid(projCtx.getOid());
// Let's be very very lazy about fetching the account from the resource.
if (!projCtx.hasFullShadow() && (hasActiveWeakMapping(squeezedAttributes, projCtx) || hasActiveWeakMapping(squeezedAssociations, projCtx) || (hasActiveStrongMapping(squeezedAttributes, projCtx) || hasActiveStrongMapping(squeezedAssociations, projCtx)))) {
// Full account was not yet loaded. This will cause problems as
// the weak mapping may be applied even though it should not be
// applied
// and also same changes may be discarded because of unavailability
// of all
// account's attributes.Therefore load the account now, but with
// doNotDiscovery options..
// We also need to get account if there are strong mappings. Strong mappings
// should always be applied. So reading the account now will indirectly
// trigger reconciliation which makes sure that the strong mappings are
// applied.
// By getting accounts from provisioning, there might be a problem with
// resource availability. We need to know, if the account was read full
// or we have only the shadow from the repository. If we have only
// shadow, the weak mappings may applied even if they should not be.
contextLoader.loadFullShadow(context, projCtx, "weak or strong mapping", task, result);
if (projCtx.getSynchronizationPolicyDecision() == SynchronizationPolicyDecision.BROKEN) {
return null;
}
}
boolean completeAccount = projCtx.hasFullShadow();
ObjectDelta<ShadowType> existingDelta = projCtx.getDelta();
// AUXILIARY OBJECT CLASSES
ItemPath auxiliaryObjectClassItemPath = new ItemPath(ShadowType.F_AUXILIARY_OBJECT_CLASS);
PrismPropertyDefinition<QName> auxiliaryObjectClassPropertyDef = projCtx.getObjectDefinition().findPropertyDefinition(auxiliaryObjectClassItemPath);
PropertyDelta<QName> auxiliaryObjectClassAPrioriDelta = null;
RefinedResourceSchema refinedSchema = projCtx.getRefinedResourceSchema();
List<QName> auxOcNames = new ArrayList<>();
List<RefinedObjectClassDefinition> auxOcDefs = new ArrayList<>();
ObjectDelta<ShadowType> projDelta = projCtx.getDelta();
if (projDelta != null) {
auxiliaryObjectClassAPrioriDelta = projDelta.findPropertyDelta(auxiliaryObjectClassItemPath);
}
for (Entry<QName, DeltaSetTriple<ItemValueWithOrigin<PrismPropertyValue<QName>, PrismPropertyDefinition<QName>>>> entry : squeezedAuxiliaryObjectClasses.entrySet()) {
DeltaSetTriple<ItemValueWithOrigin<PrismPropertyValue<QName>, PrismPropertyDefinition<QName>>> ivwoTriple = entry.getValue();
LOGGER.trace("CONSOLIDATE auxiliary object classes ({})", new Object[] { discr });
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Auxiliary object class triple:\n{}", ivwoTriple.debugDump());
}
for (ItemValueWithOrigin<PrismPropertyValue<QName>, PrismPropertyDefinition<QName>> ivwo : ivwoTriple.getAllValues()) {
QName auxObjectClassName = ivwo.getItemValue().getValue();
if (auxOcNames.contains(auxObjectClassName)) {
continue;
}
auxOcNames.add(auxObjectClassName);
RefinedObjectClassDefinition auxOcDef = refinedSchema.getRefinedDefinition(auxObjectClassName);
if (auxOcDef == null) {
LOGGER.error("Auxiliary object class definition {} for {} not found in the schema, but it should be there, dumping context:\n{}", auxObjectClassName, discr, context.debugDump());
throw new IllegalStateException("Auxiliary object class definition " + auxObjectClassName + " for " + discr + " not found in the context, but it should be there");
}
auxOcDefs.add(auxOcDef);
}
ItemDelta<PrismPropertyValue<QName>, PrismPropertyDefinition<QName>> itemDelta = LensUtil.consolidateTripleToDelta(auxiliaryObjectClassItemPath, ivwoTriple, auxiliaryObjectClassPropertyDef, auxiliaryObjectClassAPrioriDelta, projCtx.getObjectNew(), null, null, addUnchangedValues, completeAccount, false, discr.toHumanReadableDescription(), false);
PropertyDelta<QName> propDelta = (PropertyDelta) itemDelta;
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Auxiliary object class delta:\n{}", propDelta.debugDump());
}
if (!propDelta.isEmpty()) {
objectDelta.addModification(propDelta);
}
}
RefinedObjectClassDefinition structuralObjectClassDefinition = projCtx.getStructuralObjectClassDefinition();
if (structuralObjectClassDefinition == null) {
LOGGER.error("Structural object class definition for {} not found in the context, but it should be there, dumping context:\n{}", discr, context.debugDump());
throw new IllegalStateException("Structural object class definition for " + discr + " not found in the context, but it should be there");
}
RefinedObjectClassDefinition rOcDef = new CompositeRefinedObjectClassDefinitionImpl(structuralObjectClassDefinition, auxOcDefs);
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Object class definition for {} consolidation:\n{}", discr, rOcDef.debugDump());
}
// with the data in ItemValueWithOrigin triples.
for (Map.Entry<QName, DeltaSetTriple<ItemValueWithOrigin<PrismPropertyValue<?>, PrismPropertyDefinition<?>>>> entry : squeezedAttributes.entrySet()) {
QName attributeName = entry.getKey();
DeltaSetTriple<ItemValueWithOrigin<PrismPropertyValue<?>, PrismPropertyDefinition<?>>> triple = entry.getValue();
PropertyDelta<?> propDelta = consolidateAttribute(rOcDef, discr, existingDelta, projCtx, addUnchangedValues, completeAccount, attributeName, (DeltaSetTriple) triple);
if (propDelta != null) {
objectDelta.addModification(propDelta);
}
}
// ASSOCIATIONS
for (Entry<QName, DeltaSetTriple<ItemValueWithOrigin<PrismContainerValue<ShadowAssociationType>, PrismContainerDefinition<ShadowAssociationType>>>> entry : squeezedAssociations.entrySet()) {
QName associationName = entry.getKey();
DeltaSetTriple<ItemValueWithOrigin<PrismContainerValue<ShadowAssociationType>, PrismContainerDefinition<ShadowAssociationType>>> triple = entry.getValue();
ContainerDelta<ShadowAssociationType> containerDelta = consolidateAssociation(rOcDef, discr, existingDelta, projCtx, addUnchangedValues, completeAccount, associationName, triple);
if (containerDelta != null) {
objectDelta.addModification(containerDelta);
}
}
return objectDelta;
}
use of com.evolveum.midpoint.prism.delta.PrismValueDeltaSetTriple in project midpoint by Evolveum.
the class AbstractValueTransformationExpressionEvaluator method evaluateRelativeExpression.
private PrismValueDeltaSetTriple<V> evaluateRelativeExpression(final List<SourceTriple<?, ?>> sourceTriples, final ExpressionVariables variables, final boolean skipEvaluationMinus, final boolean skipEvaluationPlus, final Boolean includeNulls, final ExpressionEvaluationContext evaluationContext, final String contextDescription, final Task task, final OperationResult result) throws ExpressionEvaluationException, ObjectNotFoundException, SchemaException {
List<Collection<? extends PrismValue>> valueCollections = new ArrayList<>(sourceTriples.size());
for (SourceTriple<?, ?> sourceTriple : sourceTriples) {
Collection<? extends PrismValue> values = sourceTriple.union();
if (values.isEmpty()) {
// No values for this source. Add null instead. It will make sure that the expression will
// be evaluate at least once.
values.add(null);
}
valueCollections.add(values);
}
final PrismValueDeltaSetTriple<V> outputTriple = new PrismValueDeltaSetTriple<>();
Processor<Collection<? extends PrismValue>> processor = pvalues -> {
if (includeNulls != null && !includeNulls && MiscUtil.isAllNull(pvalues)) {
return;
}
Map<QName, Object> sourceVariables = new HashMap<>();
Iterator<SourceTriple<PrismValue, ?>> sourceTriplesIterator = (Iterator) sourceTriples.iterator();
boolean hasMinus = false;
boolean hasZero = false;
boolean hasPlus = false;
for (PrismValue pval : pvalues) {
SourceTriple<PrismValue, ?> sourceTriple = sourceTriplesIterator.next();
QName name = sourceTriple.getName();
sourceVariables.put(name, getRealContent(pval, sourceTriple.getResidualPath()));
if (sourceTriple.presentInPlusSet(pval)) {
hasPlus = true;
} else if (sourceTriple.presentInZeroSet(pval)) {
hasZero = true;
} else if (sourceTriple.presentInMinusSet(pval)) {
hasMinus = true;
}
}
if (!hasPlus && !hasMinus && !hasZero && !MiscUtil.isAllNull(pvalues)) {
throw new IllegalStateException("Internal error! The impossible has happened! pvalues=" + pvalues + "; source triples: " + sourceTriples + "; in " + contextDescription);
}
if (hasPlus && hasMinus) {
return;
}
if (hasPlus && skipEvaluationPlus) {
return;
} else if (hasMinus && skipEvaluationMinus) {
return;
}
ExpressionVariables scriptVariables = new ExpressionVariables();
scriptVariables.addVariableDefinitions(sourceVariables);
PlusMinusZero valueDestination = null;
boolean useNew = false;
if (hasPlus) {
scriptVariables.addVariableDefinitionsNew(variables);
valueDestination = PlusMinusZero.PLUS;
useNew = true;
} else if (hasMinus) {
scriptVariables.addVariableDefinitionsOld(variables);
valueDestination = PlusMinusZero.MINUS;
} else {
scriptVariables.addVariableDefinitionsNew(variables);
valueDestination = PlusMinusZero.ZERO;
useNew = true;
}
List<V> scriptResults;
try {
scriptResults = transformSingleValue(scriptVariables, valueDestination, useNew, evaluationContext, contextDescription, task, result);
} catch (ExpressionEvaluationException e) {
throw new TunnelException(new ExpressionEvaluationException(e.getMessage() + "(" + dumpSourceValues(sourceVariables) + ") in " + contextDescription, e));
} catch (ObjectNotFoundException e) {
throw new TunnelException(new ObjectNotFoundException(e.getMessage() + "(" + dumpSourceValues(sourceVariables) + ") in " + contextDescription, e));
} catch (SchemaException e) {
throw new TunnelException(new SchemaException(e.getMessage() + "(" + dumpSourceValues(sourceVariables) + ") in " + contextDescription, e));
} catch (RuntimeException e) {
throw new TunnelException(new RuntimeException(e.getMessage() + "(" + dumpSourceValues(sourceVariables) + ") in " + contextDescription, e));
}
outputTriple.addAllToSet(valueDestination, scriptResults);
};
try {
MiscUtil.carthesian((Collection) valueCollections, (Processor) processor);
} catch (TunnelException e) {
Throwable originalException = e.getCause();
if (originalException instanceof ExpressionEvaluationException) {
throw (ExpressionEvaluationException) originalException;
} else if (originalException instanceof ObjectNotFoundException) {
throw (ObjectNotFoundException) originalException;
} else if (originalException instanceof SchemaException) {
throw (SchemaException) originalException;
} else if (originalException instanceof RuntimeException) {
throw (RuntimeException) originalException;
} else {
throw new IllegalStateException("Unexpected exception: " + e + ": " + e.getMessage(), e);
}
}
cleanupTriple(outputTriple);
return outputTriple;
}
Aggregations