use of com.evolveum.midpoint.model.common.mapping.Mapping in project midpoint by Evolveum.
the class Construction method debugDump.
@Override
public String debugDump(int indent) {
StringBuilder sb = new StringBuilder();
DebugUtil.debugDumpLabel(sb, "Construction", indent);
if (refinedObjectClassDefinition == null) {
sb.append(" (no object class definition)");
if (getConstructionType() != null && getConstructionType().getResourceRef() != null) {
// should
// be
// always
// the
// case
sb.append("\n");
DebugUtil.debugDumpLabel(sb, "resourceRef / kind / intent", indent + 1);
sb.append(" ");
sb.append(ObjectTypeUtil.toShortString(getConstructionType().getResourceRef()));
sb.append(" / ");
sb.append(getConstructionType().getKind());
sb.append(" / ");
sb.append(getConstructionType().getIntent());
}
} else {
sb.append(refinedObjectClassDefinition.getShadowDiscriminator());
}
if (getConstructionType() != null && getConstructionType().getStrength() == ConstructionStrengthType.WEAK) {
sb.append(" weak");
}
sb.append("\n");
DebugUtil.debugDumpWithLabel(sb, "isValid", isValid(), indent + 1);
sb.append("\n");
DebugUtil.debugDumpLabel(sb, "auxiliary object classes", indent + 1);
if (auxiliaryObjectClassDefinitions == null) {
sb.append(" (null)");
} else if (auxiliaryObjectClassDefinitions.isEmpty()) {
sb.append(" (empty)");
} else {
for (RefinedObjectClassDefinition auxiliaryObjectClassDefinition : auxiliaryObjectClassDefinitions) {
sb.append("\n");
DebugUtil.indentDebugDump(sb, indent + 2);
sb.append(auxiliaryObjectClassDefinition.getTypeName());
}
}
if (getConstructionType() != null && getConstructionType().getDescription() != null) {
sb.append("\n");
DebugUtil.debugDumpLabel(sb, "description", indent + 1);
sb.append(" ").append(getConstructionType().getDescription());
}
if (attributeMappings != null && !attributeMappings.isEmpty()) {
sb.append("\n");
DebugUtil.debugDumpLabel(sb, "attribute mappings", indent + 1);
for (Mapping mapping : attributeMappings) {
sb.append("\n");
sb.append(mapping.debugDump(indent + 2));
}
}
if (associationMappings != null && !associationMappings.isEmpty()) {
sb.append("\n");
DebugUtil.debugDumpLabel(sb, "association mappings", indent + 1);
for (Mapping mapping : associationMappings) {
sb.append("\n");
sb.append(mapping.debugDump(indent + 2));
}
}
if (getAssignmentPath() != null) {
sb.append("\n");
sb.append(getAssignmentPath().debugDump(indent + 1));
}
return sb.toString();
}
use of com.evolveum.midpoint.model.common.mapping.Mapping in project midpoint by Evolveum.
the class OutboundProcessor method processOutbound.
public <F extends FocusType> void processOutbound(LensContext<F> context, LensProjectionContext projCtx, Task task, OperationResult result) throws SchemaException, ExpressionEvaluationException, ObjectNotFoundException {
ResourceShadowDiscriminator discr = projCtx.getResourceShadowDiscriminator();
ObjectDelta<ShadowType> projectionDelta = projCtx.getDelta();
if (projectionDelta != null && projectionDelta.getChangeType() == ChangeType.DELETE) {
LOGGER.trace("Processing outbound expressions for {} skipped, DELETE account delta", discr);
// No point in evaluating outbound
return;
}
LOGGER.trace("Processing outbound expressions for {} starting", discr);
RefinedObjectClassDefinition rOcDef = projCtx.getStructuralObjectClassDefinition();
if (rOcDef == null) {
LOGGER.error("Definition for {} not found in the context, but it should be there, dumping context:\n{}", discr, context.debugDump());
throw new IllegalStateException("Definition for " + discr + " not found in the context, but it should be there");
}
ObjectDeltaObject<F> focusOdo = context.getFocusContext().getObjectDeltaObject();
ObjectDeltaObject<ShadowType> projectionOdo = projCtx.getObjectDeltaObject();
Construction<F> outboundConstruction = new Construction<>(null, projCtx.getResource());
outboundConstruction.setRefinedObjectClassDefinition(rOcDef);
Collection<RefinedObjectClassDefinition> auxiliaryObjectClassDefinitions = rOcDef.getAuxiliaryObjectClassDefinitions();
if (auxiliaryObjectClassDefinitions != null) {
for (RefinedObjectClassDefinition auxiliaryObjectClassDefinition : auxiliaryObjectClassDefinitions) {
outboundConstruction.addAuxiliaryObjectClassDefinition(auxiliaryObjectClassDefinition);
}
}
String operation = projCtx.getOperation().getValue();
for (QName attributeName : rOcDef.getNamesOfAttributesWithOutboundExpressions()) {
RefinedAttributeDefinition<?> refinedAttributeDefinition = rOcDef.findAttributeDefinition(attributeName);
final MappingType outboundMappingType = refinedAttributeDefinition.getOutboundMappingType();
if (outboundMappingType == null) {
continue;
}
if (refinedAttributeDefinition.isIgnored(LayerType.MODEL)) {
LOGGER.trace("Skipping processing outbound mapping for attribute {} because it is ignored", attributeName);
continue;
}
Mapping.Builder<PrismPropertyValue<?>, RefinedAttributeDefinition<?>> builder = mappingFactory.createMappingBuilder(outboundMappingType, "outbound mapping for " + PrettyPrinter.prettyPrint(refinedAttributeDefinition.getName()) + " in " + rOcDef.getResourceType());
builder = builder.originObject(rOcDef.getResourceType()).originType(OriginType.OUTBOUND);
Mapping<PrismPropertyValue<?>, RefinedAttributeDefinition<?>> evaluatedMapping = evaluateMapping(builder, attributeName, refinedAttributeDefinition, focusOdo, projectionOdo, operation, rOcDef, null, context, projCtx, task, result);
if (evaluatedMapping != null) {
outboundConstruction.addAttributeMapping(evaluatedMapping);
}
}
for (QName assocName : rOcDef.getNamesOfAssociationsWithOutboundExpressions()) {
RefinedAssociationDefinition associationDefinition = rOcDef.findAssociationDefinition(assocName);
final MappingType outboundMappingType = associationDefinition.getOutboundMappingType();
if (outboundMappingType == null) {
continue;
}
// if (associationDefinition.isIgnored(LayerType.MODEL)) {
// LOGGER.trace("Skipping processing outbound mapping for attribute {} because it is ignored", assocName);
// continue;
// }
Mapping.Builder<PrismContainerValue<ShadowAssociationType>, PrismContainerDefinition<ShadowAssociationType>> mappingBuilder = mappingFactory.createMappingBuilder(outboundMappingType, "outbound mapping for " + PrettyPrinter.prettyPrint(associationDefinition.getName()) + " in " + rOcDef.getResourceType());
PrismContainerDefinition<ShadowAssociationType> outputDefinition = getAssociationContainerDefinition();
Mapping<PrismContainerValue<ShadowAssociationType>, PrismContainerDefinition<ShadowAssociationType>> evaluatedMapping = (Mapping) evaluateMapping(mappingBuilder, assocName, outputDefinition, focusOdo, projectionOdo, operation, rOcDef, associationDefinition.getAssociationTarget(), context, projCtx, task, result);
if (evaluatedMapping != null) {
outboundConstruction.addAssociationMapping(evaluatedMapping);
}
}
projCtx.setOutboundConstruction(outboundConstruction);
}
use of com.evolveum.midpoint.model.common.mapping.Mapping in project midpoint by Evolveum.
the class AssignmentProcessor method collectFocusTripleFromMappings.
private <V extends PrismValue, D extends ItemDefinition, F extends FocusType> XMLGregorianCalendar collectFocusTripleFromMappings(Collection<EvaluatedAssignmentImpl<F>> evaluatedAssignments, Map<ItemPath, DeltaSetTriple<? extends ItemValueWithOrigin<?, ?>>> outputTripleMap, PlusMinusZero plusMinusZero) throws SchemaException {
XMLGregorianCalendar nextRecomputeTime = null;
for (EvaluatedAssignmentImpl<F> ea : evaluatedAssignments) {
Collection<Mapping<V, D>> focusMappings = (Collection) ea.getFocusMappings();
for (Mapping<V, D> mapping : focusMappings) {
ItemPath itemPath = mapping.getOutputPath();
DeltaSetTriple<ItemValueWithOrigin<V, D>> outputTriple = ItemValueWithOrigin.createOutputTriple(mapping);
if (outputTriple == null) {
continue;
}
if (plusMinusZero == PlusMinusZero.PLUS) {
outputTriple.addAllToPlusSet(outputTriple.getZeroSet());
outputTriple.clearZeroSet();
outputTriple.clearMinusSet();
} else if (plusMinusZero == PlusMinusZero.MINUS) {
outputTriple.addAllToMinusSet(outputTriple.getZeroSet());
outputTriple.clearZeroSet();
outputTriple.clearPlusSet();
}
DeltaSetTriple<ItemValueWithOrigin<V, D>> mapTriple = (DeltaSetTriple<ItemValueWithOrigin<V, D>>) outputTripleMap.get(itemPath);
if (mapTriple == null) {
outputTripleMap.put(itemPath, outputTriple);
} else {
mapTriple.merge(outputTriple);
}
}
}
return nextRecomputeTime;
}
use of com.evolveum.midpoint.model.common.mapping.Mapping in project midpoint by Evolveum.
the class InboundProcessor method evaluateInboundMapping.
private <A, F extends FocusType, V extends PrismValue, D extends ItemDefinition> ItemDelta<V, D> evaluateInboundMapping(final LensContext<F> context, MappingType inboundMappingType, QName accountAttributeName, PrismProperty<A> oldAccountProperty, PropertyDelta<A> attributeAPrioriDelta, PrismObject<F> focusNew, PrismObject<ShadowType> account, ResourceType resource, Task task, OperationResult result) throws ExpressionEvaluationException, ObjectNotFoundException, SchemaException, ConfigurationException {
if (oldAccountProperty != null && oldAccountProperty.hasRaw()) {
throw new SystemException("Property " + oldAccountProperty + " has raw parsing state, such property cannot be used in inbound expressions");
}
Mapping.Builder<V, D> builder = mappingFactory.createMappingBuilder(inboundMappingType, "inbound expression for " + accountAttributeName + " in " + resource);
if (!builder.isApplicableToChannel(context.getChannel())) {
return null;
}
Source<PrismPropertyValue<A>, PrismPropertyDefinition<A>> defaultSource = new Source<>(oldAccountProperty, attributeAPrioriDelta, null, ExpressionConstants.VAR_INPUT);
defaultSource.recompute();
Mapping<V, D> mapping = builder.defaultSource(defaultSource).targetContext(LensUtil.getFocusDefinition(context)).addVariableDefinition(ExpressionConstants.VAR_USER, focusNew).addVariableDefinition(ExpressionConstants.VAR_FOCUS, focusNew).addVariableDefinition(ExpressionConstants.VAR_ACCOUNT, account).addVariableDefinition(ExpressionConstants.VAR_SHADOW, account).addVariableDefinition(ExpressionConstants.VAR_RESOURCE, resource).stringPolicyResolver(createStringPolicyResolver(context, task, result)).originType(OriginType.INBOUND).originObject(resource).build();
if (checkWeakSkip(mapping, focusNew)) {
LOGGER.trace("Skipping because of mapping is weak and focus property has already a value");
return null;
}
ItemPath targetFocusItemPath = mapping.getOutputPath();
if (ItemPath.isNullOrEmpty(targetFocusItemPath)) {
throw new ConfigurationException("Empty target path in " + mapping.getContextDescription());
}
Item targetFocusItem = null;
if (focusNew != null) {
targetFocusItem = focusNew.findItem(targetFocusItemPath);
}
PrismObjectDefinition<F> focusDefinition = context.getFocusContext().getObjectDefinition();
ItemDefinition targetItemDef = focusDefinition.findItemDefinition(targetFocusItemPath);
if (targetItemDef == null) {
throw new SchemaException("No definition for focus property " + targetFocusItemPath + ", cannot process inbound expression in " + resource);
}
final ItemDelta outputFocusItemDelta = targetItemDef.createEmptyDelta(targetFocusItemPath);
mappingEvaluator.evaluateMapping(mapping, context, task, result);
PrismValueDeltaSetTriple<V> triple = mapping.getOutputTriple();
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Inbound mapping for {} returned triple:\n{}", accountAttributeName, triple == null ? "null" : triple.debugDump());
}
if (triple != null) {
if (triple.hasPlusSet()) {
boolean alreadyReplaced = false;
for (V value : triple.getPlusSet()) {
if (targetFocusItem != null && targetFocusItem.hasRealValue(value)) {
continue;
}
//if property is not multi value replace existing attribute
if (targetFocusItem != null && !targetFocusItem.getDefinition().isMultiValue() && !targetFocusItem.isEmpty()) {
Collection<V> replace = new ArrayList<V>();
replace.add((V) value.clone());
outputFocusItemDelta.setValuesToReplace(replace);
if (alreadyReplaced) {
LOGGER.warn("Multiple values for a single-valued property {}; duplicate value = {}", targetFocusItem, value);
} else {
alreadyReplaced = true;
}
} else {
outputFocusItemDelta.addValueToAdd(value.clone());
}
}
}
if (triple.hasMinusSet()) {
LOGGER.trace("Checking account sync property delta values to delete");
for (V value : triple.getMinusSet()) {
if (targetFocusItem == null || targetFocusItem.hasRealValue(value)) {
if (!outputFocusItemDelta.isReplace()) {
// This is not needed if we are going to replace. In fact it might cause an error.
outputFocusItemDelta.addValueToDelete(value);
}
}
}
}
Item shouldBeItem = targetItemDef.instantiate();
shouldBeItem.addAll(PrismValue.cloneCollection(triple.getZeroSet()));
shouldBeItem.addAll(PrismValue.cloneCollection(triple.getPlusSet()));
if (targetFocusItem != null) {
ItemDelta diffDelta = targetFocusItem.diff(shouldBeItem);
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Comparing focus item:\n{}\nto should be item:\n{}\ndiff:\n{} ", DebugUtil.debugDump(targetFocusItem, 1), DebugUtil.debugDump(shouldBeItem, 1), DebugUtil.debugDump(diffDelta, 1));
}
if (diffDelta != null) {
if (mapping.isTolerant() == Boolean.TRUE) {
// this is probably not correct, as the default for inbounds should be TRUE
if (diffDelta.isReplace()) {
if (diffDelta.getValuesToReplace().isEmpty()) {
diffDelta.resetValuesToReplace();
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Removing empty replace part of the diff delta because mapping is tolerant:\n{}", diffDelta.debugDump());
}
} else {
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Making sure that the replace part of the diff contains old values delta because mapping is tolerant:\n{}", diffDelta.debugDump());
}
for (Object shouldBeValueObj : shouldBeItem.getValues()) {
PrismValue shouldBeValue = (PrismValue) shouldBeValueObj;
if (!PrismValue.containsRealValue(diffDelta.getValuesToReplace(), shouldBeValue)) {
diffDelta.addValueToReplace(shouldBeValue.clone());
}
}
}
} else {
diffDelta.resetValuesToDelete();
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Removing delete part of the diff delta because mapping is tolerant:\n{}", diffDelta.debugDump());
}
}
}
diffDelta.setElementName(ItemPath.getName(targetFocusItemPath.last()));
diffDelta.setParentPath(targetFocusItemPath.allExceptLast());
outputFocusItemDelta.merge(diffDelta);
}
} else {
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Adding user property because inbound say so (account doesn't contain that value):\n{}", shouldBeItem.getValues());
}
//if user property doesn't exist we have to add it (as delta), because inbound say so
outputFocusItemDelta.addValuesToAdd(shouldBeItem.getClonedValues());
}
} else {
// triple == null
// the mapping is not applicable. Nothing to do.
}
// if no changes were generated return null
return outputFocusItemDelta.isEmpty() ? null : outputFocusItemDelta;
}
use of com.evolveum.midpoint.model.common.mapping.Mapping in project midpoint by Evolveum.
the class Construction method evaluateAssociation.
private Mapping<PrismContainerValue<ShadowAssociationType>, PrismContainerDefinition<ShadowAssociationType>> evaluateAssociation(ResourceObjectAssociationType associationDefinitionType, Task task, OperationResult result) throws ExpressionEvaluationException, ObjectNotFoundException, SchemaException {
QName assocName = ItemPathUtil.getOnlySegmentQName(associationDefinitionType.getRef());
if (assocName == null) {
throw new SchemaException("Missing 'ref' in association in construction in " + getSource());
}
MappingType outboundMappingType = associationDefinitionType.getOutbound();
if (outboundMappingType == null) {
throw new SchemaException("No outbound section in definition of association " + assocName + " in construction in " + getSource());
}
PrismContainerDefinition<ShadowAssociationType> outputDefinition = getAssociationContainerDefinition();
Mapping.Builder<PrismContainerValue<ShadowAssociationType>, PrismContainerDefinition<ShadowAssociationType>> mappingBuilder = mappingFactory.<PrismContainerValue<ShadowAssociationType>, PrismContainerDefinition<ShadowAssociationType>>createMappingBuilder().mappingType(outboundMappingType).contextDescription("for association " + PrettyPrinter.prettyPrint(assocName) + " in " + getSource()).originType(OriginType.ASSIGNMENTS).originObject(getSource());
RefinedAssociationDefinition rAssocDef = refinedObjectClassDefinition.findAssociationDefinition(assocName);
if (rAssocDef == null) {
throw new SchemaException("No association " + assocName + " in object class " + refinedObjectClassDefinition.getHumanReadableName() + " in construction in " + getSource());
}
Mapping<PrismContainerValue<ShadowAssociationType>, PrismContainerDefinition<ShadowAssociationType>> evaluatedMapping = evaluateMapping(mappingBuilder, assocName, outputDefinition, rAssocDef.getAssociationTarget(), task, result);
LOGGER.trace("Evaluated mapping for association " + assocName + ": " + evaluatedMapping);
return evaluatedMapping;
}
Aggregations