use of com.evolveum.midpoint.model.impl.lens.ItemValueWithOrigin in project midpoint by Evolveum.
the class ObjectTemplateProcessor method processTemplate.
/**
* Process focus template: application of object template where focus is both source and target.
*/
public <F extends FocusType> void processTemplate(LensContext<F> context, ObjectTemplateMappingEvaluationPhaseType phase, XMLGregorianCalendar now, Task task, OperationResult result) throws ExpressionEvaluationException, ObjectNotFoundException, SchemaException, PolicyViolationException, ObjectAlreadyExistsException {
LensFocusContext<F> focusContext = context.getFocusContext();
if (focusContext.isDelete()) {
LOGGER.trace("Skipping processing of object template: focus delete");
return;
}
ObjectTemplateType objectTemplate = context.getFocusTemplate();
if (objectTemplate == null) {
// No applicable template
LOGGER.trace("Skipping processing of object template: no object template");
return;
}
int iteration = focusContext.getIteration();
String iterationToken = focusContext.getIterationToken();
ObjectDeltaObject<F> focusOdo = focusContext.getObjectDeltaObject();
PrismObjectDefinition<F> focusDefinition = getObjectDefinition(focusContext.getObjectTypeClass());
LOGGER.trace("Applying {} to {}, iteration {} ({}), phase {}", objectTemplate, focusContext.getObjectNew(), iteration, iterationToken, phase);
Map<ItemPath, DeltaSetTriple<? extends ItemValueWithOrigin<?, ?>>> outputTripleMap = new HashMap<>();
Map<ItemPath, ObjectTemplateItemDefinitionType> itemDefinitionsMap = collectItemDefinitionsFromTemplate(objectTemplate, objectTemplate.toString(), task, result);
XMLGregorianCalendar nextRecomputeTime = collectTripleFromTemplate(context, objectTemplate, phase, focusOdo, focusOdo.getNewObject(), outputTripleMap, iteration, iterationToken, now, objectTemplate.toString(), task, result);
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("outputTripleMap before item delta computation:\n{}", DebugUtil.debugDumpMapMultiLine(outputTripleMap));
}
String contextDesc = "object template " + objectTemplate + " for focus " + focusOdo.getAnyObject();
Collection<ItemDelta<?, ?>> itemDeltas = computeItemDeltas(outputTripleMap, itemDefinitionsMap, focusOdo.getObjectDelta(), focusOdo.getNewObject(), focusDefinition, contextDesc);
focusContext.applyProjectionWaveSecondaryDeltas(itemDeltas);
if (nextRecomputeTime != null) {
boolean alreadyHasTrigger = false;
PrismObject<F> objectCurrent = focusContext.getObjectCurrent();
if (objectCurrent != null) {
for (TriggerType trigger : objectCurrent.asObjectable().getTrigger()) {
if (RecomputeTriggerHandler.HANDLER_URI.equals(trigger.getHandlerUri()) && nextRecomputeTime.equals(trigger.getTimestamp())) {
alreadyHasTrigger = true;
break;
}
}
}
if (!alreadyHasTrigger) {
PrismObjectDefinition<F> objectDefinition = focusContext.getObjectDefinition();
PrismContainerDefinition<TriggerType> triggerContDef = objectDefinition.findContainerDefinition(ObjectType.F_TRIGGER);
ContainerDelta<TriggerType> triggerDelta = triggerContDef.createEmptyDelta(new ItemPath(ObjectType.F_TRIGGER));
PrismContainerValue<TriggerType> triggerCVal = triggerContDef.createValue();
triggerDelta.addValueToAdd(triggerCVal);
TriggerType triggerType = triggerCVal.asContainerable();
triggerType.setTimestamp(nextRecomputeTime);
triggerType.setHandlerUri(RecomputeTriggerHandler.HANDLER_URI);
focusContext.swallowToProjectionWaveSecondaryDelta(triggerDelta);
}
}
}
use of com.evolveum.midpoint.model.impl.lens.ItemValueWithOrigin in project midpoint by Evolveum.
the class ObjectTemplateProcessor method collectTripleFromMappings.
private <V extends PrismValue, D extends ItemDefinition, F extends FocusType, T extends FocusType> XMLGregorianCalendar collectTripleFromMappings(Collection<ObjectTemplateMappingType> mappings, ObjectTemplateMappingEvaluationPhaseType phase, LensContext<F> context, ObjectTemplateType objectTemplateType, ObjectDeltaObject<F> focusOdo, PrismObject<T> target, Map<ItemPath, DeltaSetTriple<? extends ItemValueWithOrigin<?, ?>>> outputTripleMap, int iteration, String iterationToken, XMLGregorianCalendar now, String contextDesc, Task task, OperationResult result) throws SchemaException, ExpressionEvaluationException, ObjectNotFoundException, PolicyViolationException {
XMLGregorianCalendar nextRecomputeTime = null;
for (ObjectTemplateMappingType mappingType : mappings) {
ObjectTemplateMappingEvaluationPhaseType mappingPhase = mappingType.getEvaluationPhase();
if (mappingPhase == null) {
mappingPhase = ObjectTemplateMappingEvaluationPhaseType.BEFORE_ASSIGNMENTS;
}
if (phase != null && mappingPhase != phase) {
continue;
}
LOGGER.trace("Starting evaluation of mapping '{}' in {}", mappingType.getName(), contextDesc);
// for mapping chaining
ObjectDeltaObject<F> updatedFocusOdo = getUpdatedFocusOdo(context, focusOdo, outputTripleMap, mappingType, contextDesc);
Mapping<V, D> mapping = mappingEvaluator.createFocusMapping(mappingFactory, context, mappingType, objectTemplateType, updatedFocusOdo, target, null, iteration, iterationToken, context.getSystemConfiguration(), now, contextDesc, task, result);
if (mapping == null) {
continue;
}
Boolean timeConstraintValid = mapping.evaluateTimeConstraintValid(task, result);
if (timeConstraintValid != null && !timeConstraintValid) {
// Delayed mapping. Just schedule recompute time
XMLGregorianCalendar mappingNextRecomputeTime = mapping.getNextRecomputeTime();
LOGGER.trace("Evaluation of mapping {} delayed to {}", mapping, mappingNextRecomputeTime);
if (mappingNextRecomputeTime != null) {
if (nextRecomputeTime == null || nextRecomputeTime.compare(mappingNextRecomputeTime) == DatatypeConstants.GREATER) {
nextRecomputeTime = mappingNextRecomputeTime;
}
}
continue;
}
mappingEvaluator.evaluateMapping(mapping, context, task, result);
ItemPath itemPath = mapping.getOutputPath();
if (itemPath == null) {
continue;
}
DeltaSetTriple<ItemValueWithOrigin<V, D>> outputTriple = ItemValueWithOrigin.createOutputTriple(mapping);
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Output triple for {}:\n{}", mapping, DebugUtil.debugDump(outputTriple));
}
if (outputTriple == null) {
continue;
}
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.impl.lens.ItemValueWithOrigin in project midpoint by Evolveum.
the class AssignmentProcessor method processAssignmentsProjectionsWithFocus.
/**
* Processing focus-projection assignments (including roles).
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
private <F extends FocusType> void processAssignmentsProjectionsWithFocus(LensContext<F> context, XMLGregorianCalendar now, Task task, OperationResult result) throws SchemaException, ObjectNotFoundException, ExpressionEvaluationException, PolicyViolationException, CommunicationException, ConfigurationException, SecurityViolationException {
// PREPARE ASSIGNMENT DELTA
LensFocusContext<F> focusContext = context.getFocusContext();
ObjectDelta<F> focusDelta = focusContext.getDelta();
if (focusDelta != null && focusDelta.isDelete()) {
processFocusDelete(context, result);
return;
}
checkAssignmentDeltaSanity(context);
// ASSIGNMENT EVALUATION
// Initializing assignment evaluator. This will be used later to process all the assignments including the nested
// assignments (roles).
AssignmentEvaluator<F> assignmentEvaluator = createAssignmentEvaluator(context, now);
ObjectType source = determineSource(focusContext);
AssignmentTripleEvaluator<F> assignmentTripleEvaluator = new AssignmentTripleEvaluator<>();
assignmentTripleEvaluator.setActivationComputer(activationComputer);
assignmentTripleEvaluator.setAssignmentEvaluator(assignmentEvaluator);
assignmentTripleEvaluator.setContext(context);
assignmentTripleEvaluator.setNow(now);
assignmentTripleEvaluator.setPrismContext(prismContext);
assignmentTripleEvaluator.setResult(result);
assignmentTripleEvaluator.setSource(source);
assignmentTripleEvaluator.setTask(task);
// Normal processing. The enforcement policy requires that assigned accounts should be added, so we need to figure out
// which assignments were added. Do a complete recompute for all the enforcement modes. We can do that because this does
// not create deltas, it just creates the triples. So we can decide what to do later when we convert triples to deltas.
// Evaluates all assignments and sorts them to triple: added, removed and untouched assignments.
// This is where most of the assignment-level action happens.
DeltaSetTriple<EvaluatedAssignmentImpl<F>> evaluatedAssignmentTriple = assignmentTripleEvaluator.processAllAssignments();
policyRuleProcessor.addGlobalPoliciesToAssignments(context, evaluatedAssignmentTriple, task, result);
context.setEvaluatedAssignmentTriple((DeltaSetTriple) evaluatedAssignmentTriple);
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("evaluatedAssignmentTriple:\n{}", evaluatedAssignmentTriple.debugDump());
}
// PROCESSING POLICIES
policyRuleProcessor.processPolicies(context, evaluatedAssignmentTriple, result);
boolean needToReevaluateAssignments = policyRuleProcessor.processPruning(context, evaluatedAssignmentTriple, result);
if (needToReevaluateAssignments) {
LOGGER.debug("Re-evaluating assignments because exclusion pruning rule was triggered");
evaluatedAssignmentTriple = assignmentTripleEvaluator.processAllAssignments();
context.setEvaluatedAssignmentTriple((DeltaSetTriple) evaluatedAssignmentTriple);
policyRuleProcessor.addGlobalPoliciesToAssignments(context, evaluatedAssignmentTriple, task, result);
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("re-evaluatedAssignmentTriple:\n{}", evaluatedAssignmentTriple.debugDump());
}
policyRuleProcessor.processPolicies(context, evaluatedAssignmentTriple, result);
}
//policyRuleProcessor.storeAssignmentPolicySituation(context, evaluatedAssignmentTriple, result);
// PROCESSING FOCUS
Map<ItemPath, DeltaSetTriple<? extends ItemValueWithOrigin<?, ?>>> focusOutputTripleMap = new HashMap<>();
collectFocusTripleFromMappings(evaluatedAssignmentTriple.getPlusSet(), focusOutputTripleMap, PlusMinusZero.PLUS);
collectFocusTripleFromMappings(evaluatedAssignmentTriple.getMinusSet(), focusOutputTripleMap, PlusMinusZero.MINUS);
collectFocusTripleFromMappings(evaluatedAssignmentTriple.getZeroSet(), focusOutputTripleMap, PlusMinusZero.ZERO);
ObjectDeltaObject<F> focusOdo = focusContext.getObjectDeltaObject();
Collection<ItemDelta<?, ?>> focusDeltas = objectTemplateProcessor.computeItemDeltas(focusOutputTripleMap, null, focusOdo.getObjectDelta(), focusOdo.getNewObject(), focusContext.getObjectDefinition(), "focus mappings in assignments of " + focusContext.getHumanReadableName());
LOGGER.trace("Computed focus deltas: {}", focusDeltas);
focusContext.applyProjectionWaveSecondaryDeltas(focusDeltas);
focusContext.recompute();
// PROCESSING PROJECTIONS
// Evaluate the constructions in assignements now. These were not evaluated in the first pass of AssignmentEvaluator
// because there may be interaction from focusMappings of some roles to outbound mappings of other roles.
// Now we have complete focus with all the focusMappings so we can evaluate the constructions
evaluateConstructions(context, evaluatedAssignmentTriple, task, result);
ComplexConstructionConsumer<ResourceShadowDiscriminator, Construction<F>> consumer = new ComplexConstructionConsumer<ResourceShadowDiscriminator, Construction<F>>() {
private boolean processOnlyExistingProjCxts;
@Override
public boolean before(ResourceShadowDiscriminator rat) {
if (rat.getResourceOid() == null) {
throw new IllegalStateException("Resource OID null in ResourceAccountType during assignment processing");
}
if (rat.getIntent() == null) {
throw new IllegalStateException("Account type is null in ResourceAccountType during assignment processing");
}
processOnlyExistingProjCxts = false;
if (ModelExecuteOptions.isLimitPropagation(context.getOptions())) {
if (context.getTriggeredResourceOid() != null && !rat.getResourceOid().equals(context.getTriggeredResourceOid())) {
LOGGER.trace("Skipping processing construction for shadow identified by {} because of limitation to propagate changes only for resource {}", rat, context.getTriggeredResourceOid());
return false;
}
if (SchemaConstants.CHANGE_CHANNEL_DISCOVERY.equals(QNameUtil.uriToQName(context.getChannel()))) {
// TODO is this message OK? [med]
LOGGER.trace("Processing of shadow identified by {} will be skipped because of limitation for discovery channel.");
processOnlyExistingProjCxts = true;
}
}
return true;
}
@Override
public void onAssigned(ResourceShadowDiscriminator rat, String desc) {
LensProjectionContext projectionContext = LensUtil.getOrCreateProjectionContext(context, rat);
projectionContext.setAssigned(true);
projectionContext.setAssignedOld(false);
projectionContext.setLegalOld(false);
AssignmentPolicyEnforcementType assignmentPolicyEnforcement = projectionContext.getAssignmentPolicyEnforcementType();
if (assignmentPolicyEnforcement != AssignmentPolicyEnforcementType.NONE) {
LOGGER.trace("Projection {} legal: assigned (valid)", desc);
projectionContext.setLegal(true);
}
}
@Override
public void onUnchangedValid(ResourceShadowDiscriminator key, String desc) {
LensProjectionContext projectionContext = context.findProjectionContext(key);
if (projectionContext == null) {
if (processOnlyExistingProjCxts) {
return;
}
// The projection should exist before the change but it does not
// This happens during reconciliation if there is an inconsistency.
// Pretend that the assignment was just added. That should do.
projectionContext = LensUtil.getOrCreateProjectionContext(context, key);
}
LOGGER.trace("Projection {} legal: unchanged (valid)", desc);
projectionContext.setLegal(true);
projectionContext.setLegalOld(true);
projectionContext.setAssigned(true);
projectionContext.setAssignedOld(true);
}
@Override
public void onUnchangedInvalid(ResourceShadowDiscriminator rat, String desc) {
LensProjectionContext projectionContext = context.findProjectionContext(rat);
if (projectionContext == null) {
if (processOnlyExistingProjCxts) {
return;
}
// The projection should exist before the change but it does not
// This happens during reconciliation if there is an inconsistency.
// Pretend that the assignment was just added. That should do.
projectionContext = LensUtil.getOrCreateProjectionContext(context, rat);
}
LOGGER.trace("Projection {} illegal: unchanged (invalid)", desc);
projectionContext.setLegal(false);
projectionContext.setLegalOld(false);
projectionContext.setAssigned(false);
projectionContext.setAssignedOld(false);
}
@Override
public void onUnassigned(ResourceShadowDiscriminator rat, String desc) {
if (accountExists(context, rat)) {
LensProjectionContext projectionContext = context.findProjectionContext(rat);
if (projectionContext == null) {
if (processOnlyExistingProjCxts) {
return;
}
projectionContext = LensUtil.getOrCreateProjectionContext(context, rat);
}
projectionContext.setAssigned(false);
projectionContext.setAssignedOld(true);
projectionContext.setLegalOld(true);
AssignmentPolicyEnforcementType assignmentPolicyEnforcement = projectionContext.getAssignmentPolicyEnforcementType();
// TODO: check for MARK and LEGALIZE enforcement policies ....add delete laso for relative enforcemenet
if (assignmentPolicyEnforcement == AssignmentPolicyEnforcementType.FULL || assignmentPolicyEnforcement == AssignmentPolicyEnforcementType.RELATIVE) {
LOGGER.trace("Projection {} illegal: unassigned", desc);
projectionContext.setLegal(false);
} else {
LOGGER.trace("Projection {} legal: unassigned, but allowed by policy ({})", desc, assignmentPolicyEnforcement);
projectionContext.setLegal(true);
}
} else {
LOGGER.trace("Projection {} nothing: unassigned (valid->invalid) but not there", desc);
// We have to delete something that is not there. Nothing to do.
}
}
@Override
public void after(ResourceShadowDiscriminator rat, String desc, DeltaMapTriple<ResourceShadowDiscriminator, ConstructionPack<Construction<F>>> constructionMapTriple) {
PrismValueDeltaSetTriple<PrismPropertyValue<Construction>> projectionConstructionDeltaSetTriple = new PrismValueDeltaSetTriple<>(getConstructions(constructionMapTriple.getZeroMap().get(rat), true), getConstructions(constructionMapTriple.getPlusMap().get(rat), true), getConstructions(constructionMapTriple.getMinusMap().get(rat), false));
LensProjectionContext projectionContext = context.findProjectionContext(rat);
if (projectionContext != null) {
// This can be null in a exotic case if we delete already deleted account
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Construction delta set triple for {}:\n{}", rat, projectionConstructionDeltaSetTriple.debugDump(1));
}
projectionContext.setConstructionDeltaSetTriple(projectionConstructionDeltaSetTriple);
if (isForceRecon(constructionMapTriple.getZeroMap().get(rat)) || isForceRecon(constructionMapTriple.getPlusMap().get(rat)) || isForceRecon(constructionMapTriple.getMinusMap().get(rat))) {
projectionContext.setDoReconciliation(true);
}
}
}
};
constructionProcessor.processConstructions(context, evaluatedAssignmentTriple, evaluatedAssignment -> evaluatedAssignment.getConstructionTriple(), construction -> getConstructionMapKey(context, construction, task, result), consumer, task, result);
removeIgnoredContexts(context);
finishLegalDecisions(context);
}
use of com.evolveum.midpoint.model.impl.lens.ItemValueWithOrigin 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.impl.lens.ItemValueWithOrigin in project midpoint by Evolveum.
the class ReconciliationProcessor method reconcileProjectionAttribute.
private <T> void reconcileProjectionAttribute(QName attrName, LensProjectionContext projCtx, Map<QName, DeltaSetTriple<ItemValueWithOrigin<PrismPropertyValue<?>, PrismPropertyDefinition<?>>>> squeezedAttributes, RefinedObjectClassDefinition rOcDef, PrismObject<ShadowType> shadowNew, PrismContainer attributesContainer) throws SchemaException {
// LOGGER.trace("Attribute reconciliation processing attribute {}",attrName);
RefinedAttributeDefinition<T> attributeDefinition = projCtx.findAttributeDefinition(attrName);
if (attributeDefinition == null) {
String msg = "No definition for attribute " + attrName + " in " + projCtx.getResourceShadowDiscriminator();
throw new SchemaException(msg);
}
DeltaSetTriple<ItemValueWithOrigin<PrismPropertyValue<T>, PrismPropertyDefinition<T>>> pvwoTriple = squeezedAttributes != null ? (DeltaSetTriple) squeezedAttributes.get(attrName) : null;
if (attributeDefinition.isIgnored(LayerType.MODEL)) {
LOGGER.trace("Skipping reconciliation of attribute {} because it is ignored", attrName);
return;
}
PropertyLimitations limitations = attributeDefinition.getLimitations(LayerType.MODEL);
if (limitations != null) {
PropertyAccessType access = limitations.getAccess();
if (access != null) {
if (projCtx.isAdd() && (access.isAdd() == null || !access.isAdd())) {
LOGGER.trace("Skipping reconciliation of attribute {} because it is non-createable", attrName);
return;
}
if (projCtx.isModify() && (access.isModify() == null || !access.isModify())) {
LOGGER.trace("Skipping reconciliation of attribute {} because it is non-updateable", attrName);
return;
}
}
}
Collection<ItemValueWithOrigin<PrismPropertyValue<T>, PrismPropertyDefinition<T>>> shouldBePValues;
if (pvwoTriple == null) {
shouldBePValues = new HashSet<>();
} else {
shouldBePValues = new HashSet<>(pvwoTriple.getNonNegativeValues());
}
// We consider values explicitly requested by user to be among "should be values".
addPropValuesFromDelta(shouldBePValues, projCtx.getPrimaryDelta(), attrName);
// But we DO NOT take values from sync delta (because they just reflect what's on the resource),
// nor from secondary delta (because these got there from mappings).
boolean hasStrongShouldBePValue = false;
for (ItemValueWithOrigin<? extends PrismPropertyValue<T>, PrismPropertyDefinition<T>> shouldBePValue : shouldBePValues) {
if (shouldBePValue.getMapping() != null && shouldBePValue.getMapping().getStrength() == MappingStrengthType.STRONG) {
hasStrongShouldBePValue = true;
break;
}
}
PrismProperty<T> attribute = attributesContainer.findProperty(attrName);
Collection<PrismPropertyValue<T>> arePValues;
if (attribute != null) {
arePValues = attribute.getValues();
} else {
arePValues = new HashSet<>();
}
// Too loud :-)
// if (LOGGER.isTraceEnabled()) {
// StringBuilder sb = new StringBuilder();
// sb.append("Reconciliation\nATTR: ").append(PrettyPrinter.prettyPrint(attrName));
// sb.append("\n Should be:");
// for (ItemValueWithOrigin<?,?> shouldBePValue : shouldBePValues) {
// sb.append("\n ");
// sb.append(shouldBePValue.getItemValue());
// PrismValueDeltaSetTripleProducer<?, ?> shouldBeMapping = shouldBePValue.getMapping();
// if (shouldBeMapping.getStrength() == MappingStrengthType.STRONG) {
// sb.append(" STRONG");
// }
// if (shouldBeMapping.getStrength() == MappingStrengthType.WEAK) {
// sb.append(" WEAK");
// }
// if (!shouldBePValue.isValid()) {
// sb.append(" INVALID");
// }
// }
// sb.append("\n Is:");
// for (PrismPropertyValue<Object> isPVal : arePValues) {
// sb.append("\n ");
// sb.append(isPVal);
// }
// LOGGER.trace("{}", sb.toString());
// }
ValueMatcher<T> valueMatcher = ValueMatcher.createMatcher(attributeDefinition, matchingRuleRegistry);
boolean hasValue = false;
for (ItemValueWithOrigin<? extends PrismPropertyValue<T>, PrismPropertyDefinition<T>> shouldBePvwo : shouldBePValues) {
PrismValueDeltaSetTripleProducer<?, ?> shouldBeMapping = shouldBePvwo.getMapping();
if (shouldBeMapping == null) {
continue;
}
T shouldBeRealValue = shouldBePvwo.getItemValue().getValue();
if (shouldBeMapping.getStrength() != MappingStrengthType.STRONG && (!arePValues.isEmpty() || hasStrongShouldBePValue)) {
// weak or normal value and the attribute already has a
// value. Skip it.
// we cannot override it as it might have been legally
// changed directly on the projection resource object
LOGGER.trace("Skipping reconciliation of value {} of the attribute {}: the mapping is not strong", shouldBeRealValue, attributeDefinition.getName().getLocalPart());
continue;
}
if (!isInValues(valueMatcher, shouldBeRealValue, arePValues)) {
if (attributeDefinition.isSingleValue()) {
if (hasValue) {
throw new SchemaException("Attempt to set more than one value for single-valued attribute " + attrName + " in " + projCtx.getResourceShadowDiscriminator());
}
recordDelta(valueMatcher, projCtx, SchemaConstants.PATH_ATTRIBUTES, attributeDefinition, ModificationType.REPLACE, shouldBeRealValue, shouldBePvwo.getSource(), "it is given by a mapping");
} else {
recordDelta(valueMatcher, projCtx, SchemaConstants.PATH_ATTRIBUTES, attributeDefinition, ModificationType.ADD, shouldBeRealValue, shouldBePvwo.getSource(), "it is given by a mapping");
}
hasValue = true;
}
}
decideIfTolerate(projCtx, attributeDefinition, arePValues, shouldBePValues, valueMatcher);
}
Aggregations