use of com.evolveum.midpoint.model.impl.lens.ItemValueWithOrigin in project midpoint by Evolveum.
the class ConsolidationProcessor method sqeezeAttributesFromConstructionNonminusToPlus.
private <V extends PrismValue, D extends ItemDefinition, F extends FocusType> void sqeezeAttributesFromConstructionNonminusToPlus(Map<QName, DeltaSetTriple<ItemValueWithOrigin<V, D>>> squeezedMap, Construction<F> construction, MappingExtractor<V, D, F> extractor) {
for (PrismValueDeltaSetTripleProducer<V, D> mapping : extractor.getMappings(construction)) {
PrismValueDeltaSetTriple<V> vcTriple = mapping.getOutputTriple();
if (vcTriple == null) {
continue;
}
QName name = mapping.getMappingQName();
DeltaSetTriple<ItemValueWithOrigin<V, D>> squeezeTriple = getSqueezeMapTriple(squeezedMap, name);
convertSqueezeSet(vcTriple.getZeroSet(), squeezeTriple.getPlusSet(), mapping, construction);
convertSqueezeSet(vcTriple.getPlusSet(), squeezeTriple.getPlusSet(), mapping, construction);
// Ignore minus set
}
}
use of com.evolveum.midpoint.model.impl.lens.ItemValueWithOrigin in project midpoint by Evolveum.
the class ConsolidationProcessor method hasActiveWeakMapping.
private <V extends PrismValue, D extends ItemDefinition> boolean hasActiveWeakMapping(Map<QName, DeltaSetTriple<ItemValueWithOrigin<V, D>>> squeezedAttributes, LensProjectionContext accCtx) throws SchemaException {
for (Map.Entry<QName, DeltaSetTriple<ItemValueWithOrigin<V, D>>> entry : squeezedAttributes.entrySet()) {
DeltaSetTriple<ItemValueWithOrigin<V, D>> ivwoTriple = entry.getValue();
boolean hasWeak = false;
for (ItemValueWithOrigin<V, D> ivwo : ivwoTriple.getAllValues()) {
PrismValueDeltaSetTripleProducer<V, D> mapping = ivwo.getMapping();
if (mapping.getStrength() == MappingStrengthType.WEAK) {
// We only care about mappings that change something. If the weak mapping is not
// changing anything then it will not be applied in this step anyway. Therefore
// there is no point in loading the real values just because there is such mapping.
// Note: we can be sure that we are NOT doing reconciliation. If we do reconciliation
// then we cannot get here in the first place (the projection is already loaded).
PrismValueDeltaSetTriple<?> outputTriple = mapping.getOutputTriple();
if (outputTriple != null && !outputTriple.isEmpty() && !outputTriple.isZeroOnly()) {
return true;
}
hasWeak = true;
}
}
if (hasWeak) {
// unless we fetch the real values.
if (ivwoTriple.hasMinusSet()) {
for (ItemValueWithOrigin<V, D> ivwo : ivwoTriple.getMinusSet()) {
PrismValueDeltaSetTripleProducer<V, D> mapping = ivwo.getMapping();
PrismValueDeltaSetTriple<?> outputTriple = mapping.getOutputTriple();
if (outputTriple != null && !outputTriple.isEmpty()) {
return true;
}
}
}
for (ItemValueWithOrigin<V, D> ivwo : ivwoTriple.getNonNegativeValues()) {
PrismValueDeltaSetTripleProducer<V, D> mapping = ivwo.getMapping();
PrismValueDeltaSetTriple<?> outputTriple = mapping.getOutputTriple();
if (outputTriple != null && outputTriple.hasMinusSet()) {
return true;
}
}
ObjectDelta<ShadowType> projectionDelta = accCtx.getDelta();
if (projectionDelta != null) {
PropertyDelta<?> aPrioriAttributeDelta = projectionDelta.findPropertyDelta(new ItemPath(ShadowType.F_ATTRIBUTES, entry.getKey()));
if (aPrioriAttributeDelta != null && aPrioriAttributeDelta.isDelete()) {
return true;
}
if (aPrioriAttributeDelta != null && aPrioriAttributeDelta.isReplace() && aPrioriAttributeDelta.getValuesToReplace().isEmpty()) {
return true;
}
}
}
}
return false;
}
use of com.evolveum.midpoint.model.impl.lens.ItemValueWithOrigin in project midpoint by Evolveum.
the class ConsolidationProcessor method sqeezeAttributesFromConstruction.
private <V extends PrismValue, D extends ItemDefinition, F extends FocusType> void sqeezeAttributesFromConstruction(Map<QName, DeltaSetTriple<ItemValueWithOrigin<V, D>>> squeezedMap, Construction<F> construction, MappingExtractor<V, D, F> extractor) {
for (PrismValueDeltaSetTripleProducer<V, D> mapping : extractor.getMappings(construction)) {
PrismValueDeltaSetTriple<V> vcTriple = mapping.getOutputTriple();
if (vcTriple == null) {
continue;
}
QName name = mapping.getMappingQName();
DeltaSetTriple<ItemValueWithOrigin<V, D>> squeezeTriple = getSqueezeMapTriple(squeezedMap, name);
convertSqueezeSet(vcTriple.getZeroSet(), squeezeTriple.getZeroSet(), mapping, construction);
convertSqueezeSet(vcTriple.getPlusSet(), squeezeTriple.getPlusSet(), mapping, construction);
convertSqueezeSet(vcTriple.getMinusSet(), squeezeTriple.getMinusSet(), mapping, construction);
}
}
use of com.evolveum.midpoint.model.impl.lens.ItemValueWithOrigin in project midpoint by Evolveum.
the class AssignmentProcessor method evaluateFocusMappings.
private <AH extends AssignmentHolderType> void evaluateFocusMappings(LensContext<AH> context, XMLGregorianCalendar now, LensFocusContext<AH> focusContext, DeltaSetTriple<EvaluatedAssignmentImpl<AH>> evaluatedAssignmentTriple, Task task, OperationResult parentResult) throws SchemaException, ExpressionEvaluationException, PolicyViolationException, ConfigurationException, SecurityViolationException, ObjectNotFoundException, CommunicationException {
OperationResult result = parentResult.subresult(OP_EVALUATE_FOCUS_MAPPINGS).setMinor().build();
try {
LOGGER.trace("Starting evaluation of assignment-held mappings");
ObjectDeltaObject<AH> focusOdoRelative = focusContext.getObjectDeltaObjectRelative();
List<AssignedFocusMappingEvaluationRequest> allRequests = new ArrayList<>();
for (EvaluatedAssignmentImpl<AH> evaluatedAssignment : evaluatedAssignmentTriple.getAllValues()) {
allRequests.addAll(evaluatedAssignment.getFocusMappingEvaluationRequests());
}
FocalMappingSetEvaluation.TripleCustomizer<?, ?> customizer = (triple, abstractRequest) -> {
if (triple == null) {
return null;
}
DeltaSetTriple<ItemValueWithOrigin<PrismValue, ItemDefinition<?>>> rv = prismContext.deltaFactory().createDeltaSetTriple();
AssignedFocusMappingEvaluationRequest request = (AssignedFocusMappingEvaluationRequest) abstractRequest;
// noinspection unchecked
EvaluatedAssignmentImpl<AH> evaluatedAssignment = (EvaluatedAssignmentImpl<AH>) request.getEvaluatedAssignment();
PlusMinusZero relativeMode = request.getRelativeMode();
Set<PlusMinusZero> presence = new HashSet<>();
PlusMinusZero resultingMode = null;
if (evaluatedAssignmentTriple.presentInPlusSet(evaluatedAssignment)) {
resultingMode = PlusMinusZero.compute(PlusMinusZero.PLUS, relativeMode);
presence.add(PlusMinusZero.PLUS);
}
if (evaluatedAssignmentTriple.presentInMinusSet(evaluatedAssignment)) {
resultingMode = PlusMinusZero.compute(PlusMinusZero.MINUS, relativeMode);
presence.add(PlusMinusZero.MINUS);
}
if (evaluatedAssignmentTriple.presentInZeroSet(evaluatedAssignment)) {
resultingMode = PlusMinusZero.compute(PlusMinusZero.ZERO, relativeMode);
presence.add(PlusMinusZero.ZERO);
}
LOGGER.trace("triple customizer: presence = {}, relativeMode = {}, resultingMode = {}", presence, relativeMode, resultingMode);
if (presence.isEmpty()) {
throw new IllegalStateException("Evaluated assignment is not present in any of plus/minus/zero sets " + "of the triple. Assignment = " + evaluatedAssignment + ", triple = " + triple);
} else if (presence.size() > 1) {
// TODO think about this
throw new IllegalStateException("Evaluated assignment is present in more than one plus/minus/zero sets " + "of the triple: " + presence + ". Assignment = " + evaluatedAssignment + ", triple = " + triple);
}
if (resultingMode != null) {
switch(resultingMode) {
case PLUS:
// MID-6403
rv.addAllToPlusSet(triple.getNonNegativeValues());
break;
case MINUS:
// MID-6403
rv.addAllToMinusSet(triple.getNonPositiveValues());
break;
case ZERO:
rv = triple;
break;
}
}
return rv;
};
FocalMappingSetEvaluation.EvaluatedMappingConsumer mappingConsumer = (mapping, abstractRequest) -> {
AssignedFocusMappingEvaluationRequest request = (AssignedFocusMappingEvaluationRequest) abstractRequest;
request.getEvaluatedAssignment().addFocusMapping(mapping);
};
TargetObjectSpecification<AH> targetSpecification = new FixedTargetSpecification<>(focusOdoRelative.getNewObject(), true);
MappingEvaluationEnvironment env = new MappingEvaluationEnvironment("focus mappings in assignments of " + focusContext.getHumanReadableName(), now, task);
FocalMappingSetEvaluation<AH, AH> mappingSetEvaluation = new FocalMappingSetEvaluationBuilder<AH, AH>().context(context).evaluationRequests(allRequests).phase(null).focusOdo(focusOdoRelative).targetSpecification(targetSpecification).tripleCustomizer(customizer).mappingConsumer(mappingConsumer).iteration(focusContext.getIteration()).iterationToken(focusContext.getIterationToken()).beans(beans).env(env).result(result).build();
mappingSetEvaluation.evaluateMappingsToTriples();
PathKeyedMap<DeltaSetTriple<ItemValueWithOrigin<?, ?>>> focusOutputTripleMap = mappingSetEvaluation.getOutputTripleMap();
logOutputTripleMap(focusOutputTripleMap);
DeltaSetTripleMapConsolidation<AH> consolidation = new DeltaSetTripleMapConsolidation<>(focusOutputTripleMap, focusOdoRelative.getNewObject(), focusOdoRelative.getObjectDelta(), context::primaryFocusItemDeltaExists, null, null, focusContext.getObjectDefinition(), env, beans, context, result);
consolidation.computeItemDeltas();
Collection<ItemDelta<?, ?>> focusDeltas = consolidation.getItemDeltas();
LOGGER.trace("Computed focus deltas: {}", focusDeltas);
focusContext.swallowToSecondaryDelta(focusDeltas);
focusContext.recompute();
} catch (Throwable t) {
result.recordFatalError(t.getMessage(), t);
throw t;
} finally {
result.computeStatusIfUnknown();
}
}
use of com.evolveum.midpoint.model.impl.lens.ItemValueWithOrigin 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;
}
Aggregations