use of com.evolveum.midpoint.prism.path.UniformItemPath in project midpoint by Evolveum.
the class ActivationProcessor method reconcileOutboundValue.
/**
* TODO: can we align this with ReconciliationProcessor?
*/
private <T, F extends FocusType> void reconcileOutboundValue(LensContext<F> context, LensProjectionContext projCtx, Map<UniformItemPath, MappingOutputStruct<PrismPropertyValue<T>>> outputTripleMap, String desc) throws SchemaException {
for (Entry<UniformItemPath, MappingOutputStruct<PrismPropertyValue<T>>> entry : outputTripleMap.entrySet()) {
UniformItemPath mappingOutputPath = entry.getKey();
MappingOutputStruct<PrismPropertyValue<T>> mappingOutputStruct = entry.getValue();
if (mappingOutputStruct.isWeakMappingWasUsed()) {
// Thing to do. All deltas should already be in context
LOGGER.trace("Skip reconciliation of {} in {} because of weak", mappingOutputPath, desc);
continue;
}
if (!mappingOutputStruct.isStrongMappingWasUsed()) {
// Normal mappings are not processed for reconciliation
LOGGER.trace("Skip reconciliation of {} in {} because not strong", mappingOutputPath, desc);
continue;
}
LOGGER.trace("reconciliation of {} for {}", mappingOutputPath, desc);
PrismObjectDefinition<ShadowType> targetObjectDefinition = projCtx.getObjectDefinition();
PrismPropertyDefinition<T> targetItemDefinition = targetObjectDefinition.findPropertyDefinition(mappingOutputPath);
if (targetItemDefinition == null) {
throw new SchemaException("No definition for item " + mappingOutputPath + " in " + targetObjectDefinition);
}
PropertyDelta<T> targetItemDelta = targetItemDefinition.createEmptyDelta(mappingOutputPath);
PrismValueDeltaSetTriple<PrismPropertyValue<T>> outputTriple = mappingOutputStruct.getOutputTriple();
PrismProperty<T> currentTargetItem = null;
PrismObject<ShadowType> shadowCurrent = projCtx.getObjectCurrent();
if (shadowCurrent != null) {
currentTargetItem = shadowCurrent.findProperty(mappingOutputPath);
}
Collection<PrismPropertyValue<T>> hasValues = new ArrayList<>();
if (currentTargetItem != null) {
hasValues.addAll(currentTargetItem.getValues());
}
Collection<PrismPropertyValue<T>> shouldHaveValues = outputTriple.getNonNegativeValues();
LOGGER.trace("Reconciliation of {}:\n hasValues:\n{}\n shouldHaveValues\n{}", mappingOutputPath, DebugUtil.debugDumpLazily(hasValues, 2), DebugUtil.debugDumpLazily(shouldHaveValues, 2));
for (PrismPropertyValue<T> shouldHaveValue : shouldHaveValues) {
if (!PrismValueCollectionsUtil.containsRealValue(hasValues, shouldHaveValue)) {
if (targetItemDefinition.isSingleValue()) {
targetItemDelta.setValueToReplace(shouldHaveValue.clone());
} else {
targetItemDelta.addValueToAdd(shouldHaveValue.clone());
}
}
}
if (targetItemDefinition.isSingleValue()) {
if (!targetItemDelta.isReplace() && shouldHaveValues.isEmpty()) {
targetItemDelta.setValueToReplace();
}
} else {
for (PrismPropertyValue<T> hasValue : hasValues) {
if (!PrismValueCollectionsUtil.containsRealValue(shouldHaveValues, hasValue)) {
targetItemDelta.addValueToDelete(hasValue.clone());
}
}
}
if (!targetItemDelta.isEmpty()) {
LOGGER.trace("Reconciliation delta:\n{}", targetItemDelta.debugDumpLazily(1));
projCtx.swallowToSecondaryDelta(targetItemDelta);
}
}
}
use of com.evolveum.midpoint.prism.path.UniformItemPath in project midpoint by Evolveum.
the class ProjectionMappingSetEvaluator method evaluateMappingsToTriples.
public <V extends PrismValue, D extends ItemDefinition<?>, T extends ObjectType, F extends FocusType> Map<UniformItemPath, MappingOutputStruct<V>> evaluateMappingsToTriples(MappingEvaluatorParams<V, D, T, F> params, Task task, OperationResult result) throws ExpressionEvaluationException, ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException, SecurityViolationException {
String mappingDesc = params.getMappingDesc();
LensElementContext<T> targetContext = params.getTargetContext();
PrismObjectDefinition<T> targetObjectDefinition = targetContext.getObjectDefinition();
ItemPath defaultTargetItemPath = params.getDefaultTargetItemPath();
Map<UniformItemPath, MappingOutputStruct<V>> outputTripleMap = new HashMap<>();
XMLGregorianCalendar nextRecomputeTime = null;
String triggerOriginDescription = null;
Collection<MappingType> mappingBeans = params.getMappingTypes();
Collection<MappingImpl<V, D>> mappings = new ArrayList<>(mappingBeans.size());
for (MappingType mappingBean : mappingBeans) {
MappingBuilder<V, D> mappingBuilder = mappingFactory.createMappingBuilder(mappingBean, mappingDesc);
String mappingName = mappingBean.getName();
if (!mappingBuilder.isApplicableToChannel(params.getContext().getChannel())) {
LOGGER.trace("Mapping {} not applicable to channel, skipping {}", mappingName, params.getContext().getChannel());
continue;
}
mappingBuilder.now(params.getNow());
if (defaultTargetItemPath != null && targetObjectDefinition != null) {
mappingBuilder.defaultTargetDefinition(targetObjectDefinition.findItemDefinition(defaultTargetItemPath));
} else {
mappingBuilder.defaultTargetDefinition(params.getTargetItemDefinition());
}
mappingBuilder.defaultTargetPath(defaultTargetItemPath);
mappingBuilder.targetContext(targetObjectDefinition);
mappingBuilder.sourceContext(params.getSourceContext());
// Initialize mapping (using Inversion of Control)
MappingBuilder<V, D> initializedMappingBuilder = params.getInitializer().initialize(mappingBuilder);
MappingImpl<V, D> mapping = initializedMappingBuilder.build();
mapping.evaluateTimeValidity(task, result);
boolean timeConstraintValid = mapping.isTimeConstraintValid();
if (params.getEvaluateCurrent() == MappingTimeEval.CURRENT && !timeConstraintValid) {
LOGGER.trace("Mapping {} is non-current, but evaluating current mappings, skipping {}", mappingName, params.getContext().getChannel());
} else if (params.getEvaluateCurrent() == MappingTimeEval.FUTURE && timeConstraintValid) {
LOGGER.trace("Mapping {} is current, but evaluating non-current mappings, skipping {}", mappingName, params.getContext().getChannel());
} else {
mappings.add(mapping);
}
}
boolean hasFullTargetObject = params.hasFullTargetObject();
PrismObject<T> aPrioriTargetObject = params.getAPrioriTargetObject();
LOGGER.trace("Going to process {} mappings for {}", mappings.size(), mappingDesc);
for (MappingImpl<V, D> mapping : mappings) {
if (mapping.getStrength() == MappingStrengthType.WEAK) {
// Evaluate weak mappings in a second run.
continue;
}
UniformItemPath mappingOutputPathUniform = prismContext.toUniformPathKeepNull(mapping.getOutputPath());
if (params.isFixTarget() && mappingOutputPathUniform != null && defaultTargetItemPath != null && !mappingOutputPathUniform.equivalent(defaultTargetItemPath)) {
throw new ExpressionEvaluationException("Target cannot be overridden in " + mappingDesc);
}
if (params.getAPrioriTargetDelta() != null && mappingOutputPathUniform != null) {
ItemDelta<?, ?> aPrioriItemDelta = params.getAPrioriTargetDelta().findItemDelta(mappingOutputPathUniform);
if (mapping.getStrength() != MappingStrengthType.STRONG) {
if (aPrioriItemDelta != null && !aPrioriItemDelta.isEmpty()) {
continue;
}
}
}
mappingEvaluator.evaluateMapping(mapping, params.getContext(), task, result);
PrismValueDeltaSetTriple<V> mappingOutputTriple = mapping.getOutputTriple();
LOGGER.trace("Output triple of mapping {}\n{}", mapping.getContextDescription(), mappingOutputTriple == null ? null : mappingOutputTriple.debugDumpLazily(1));
if (isMeaningful(mappingOutputTriple)) {
MappingOutputStruct<V> mappingOutputStruct = outputTripleMap.get(mappingOutputPathUniform);
if (mappingOutputStruct == null) {
mappingOutputStruct = new MappingOutputStruct<>();
outputTripleMap.put(mappingOutputPathUniform, mappingOutputStruct);
}
if (mapping.getStrength() == MappingStrengthType.STRONG) {
mappingOutputStruct.setStrongMappingWasUsed(true);
if (!hasFullTargetObject && params.getTargetLoader() != null && aPrioriTargetObject != null && aPrioriTargetObject.getOid() != null) {
if (!params.getTargetLoader().isLoaded()) {
aPrioriTargetObject = params.getTargetLoader().load("strong mapping", task, result);
LOGGER.trace("Loaded object because of strong mapping: {}", aPrioriTargetObject);
hasFullTargetObject = true;
}
}
}
// experimental
if (mapping.isPushChanges()) {
mappingOutputStruct.setPushChanges(true);
// (but it looks like we have to!)
if (!hasFullTargetObject && params.getTargetLoader() != null && aPrioriTargetObject != null && aPrioriTargetObject.getOid() != null) {
if (!params.getTargetLoader().isLoaded()) {
aPrioriTargetObject = params.getTargetLoader().load("pushing changes", task, result);
LOGGER.trace("Loaded object because of pushing changes: {}", aPrioriTargetObject);
hasFullTargetObject = true;
}
}
}
PrismValueDeltaSetTriple<V> outputTriple = mappingOutputStruct.getOutputTriple();
if (outputTriple == null) {
mappingOutputStruct.setOutputTriple(mappingOutputTriple);
} else {
outputTriple.merge(mappingOutputTriple);
}
} else {
LOGGER.trace("Output triple of mapping {} is NOT meaningful", mapping.getContextDescription());
}
}
if (params.isEvaluateWeak()) {
// Second pass, evaluate only weak mappings
for (MappingImpl<V, D> mapping : mappings) {
if (mapping.getStrength() != MappingStrengthType.WEAK) {
continue;
}
UniformItemPath mappingOutputPath = prismContext.toUniformPathKeepNull(mapping.getOutputPath());
if (params.isFixTarget() && mappingOutputPath != null && defaultTargetItemPath != null && !mappingOutputPath.equivalent(defaultTargetItemPath)) {
throw new ExpressionEvaluationException("Target cannot be overridden in " + mappingDesc);
}
MappingOutputStruct<V> mappingOutputStruct = outputTripleMap.get(mappingOutputPath);
if (mappingOutputStruct == null) {
mappingOutputStruct = new MappingOutputStruct<>();
outputTripleMap.put(mappingOutputPath, mappingOutputStruct);
}
PrismValueDeltaSetTriple<V> outputTriple = mappingOutputStruct.getOutputTriple();
if (outputTriple != null && !outputTriple.getNonNegativeValues().isEmpty()) {
// MID-3847
continue;
}
Item<V, D> aPrioriTargetItem = null;
if (aPrioriTargetObject != null && mappingOutputPath != null) {
aPrioriTargetItem = aPrioriTargetObject.findItem(mappingOutputPath);
}
if (hasNoValue(aPrioriTargetItem)) {
mappingOutputStruct.setWeakMappingWasUsed(true);
mappingEvaluator.evaluateMapping(mapping, params.getContext(), task, result);
PrismValueDeltaSetTriple<V> mappingOutputTriple = mapping.getOutputTriple();
if (mappingOutputTriple != null) {
// This is all not right. See MID-3847
if (!hasFullTargetObject && params.getTargetLoader() != null && aPrioriTargetObject != null && aPrioriTargetObject.getOid() != null) {
if (!params.getTargetLoader().isLoaded()) {
aPrioriTargetObject = params.getTargetLoader().load("weak mapping", task, result);
LOGGER.trace("Loaded object because of weak mapping: {}", aPrioriTargetObject);
hasFullTargetObject = true;
}
}
if (aPrioriTargetObject != null && mappingOutputPath != null) {
aPrioriTargetItem = aPrioriTargetObject.findItem(mappingOutputPath);
}
if (!hasNoValue(aPrioriTargetItem)) {
continue;
}
if (outputTriple == null) {
// this is currently always true (see above)
mappingOutputStruct.setOutputTriple(mappingOutputTriple);
} else {
outputTriple.merge(mappingOutputTriple);
}
}
}
}
}
MappingOutputProcessor<V> processor = params.getProcessor();
for (Map.Entry<UniformItemPath, MappingOutputStruct<V>> outputTripleMapEntry : outputTripleMap.entrySet()) {
UniformItemPath mappingOutputPath = outputTripleMapEntry.getKey();
MappingOutputStruct<V> mappingOutputStruct = outputTripleMapEntry.getValue();
PrismValueDeltaSetTriple<V> outputTriple = mappingOutputStruct.getOutputTriple();
boolean defaultProcessing;
if (processor != null) {
LOGGER.trace("Executing processor to process mapping evaluation results: {}", processor);
defaultProcessing = processor.process(mappingOutputPath, mappingOutputStruct);
} else {
defaultProcessing = true;
}
if (defaultProcessing) {
if (outputTriple == null) {
LOGGER.trace("{} expression resulted in null triple for {}, skipping", mappingDesc, targetContext);
continue;
}
ItemDefinition targetItemDefinition;
if (mappingOutputPath != null) {
targetItemDefinition = targetObjectDefinition.findItemDefinition(mappingOutputPath);
if (targetItemDefinition == null) {
throw new SchemaException("No definition for item " + mappingOutputPath + " in " + targetObjectDefinition);
}
} else {
targetItemDefinition = params.getTargetItemDefinition();
}
// noinspection unchecked
ItemDelta<V, D> targetItemDelta = targetItemDefinition.createEmptyDelta(mappingOutputPath);
Item<V, D> aPrioriTargetItem;
if (aPrioriTargetObject != null) {
aPrioriTargetItem = aPrioriTargetObject.findItem(mappingOutputPath);
} else {
aPrioriTargetItem = null;
}
if (targetContext.isAdd()) {
Collection<V> nonNegativeValues = outputTriple.getNonNegativeValues();
if (nonNegativeValues.isEmpty()) {
LOGGER.trace("{} resulted in null or empty value for {}, skipping", mappingDesc, targetContext);
continue;
}
targetItemDelta.setValuesToReplace(PrismValueCollectionsUtil.cloneCollection(nonNegativeValues));
} else {
// if we have fresh information (full shadow) AND the mapping used to derive the information was strong,
// we will consider all values (zero & plus sets) -- otherwise, we take only the "plus" (i.e. changed) set
// the first case is necessary, because in some situations (e.g. when mapping is changed)
// the evaluator sees no differences w.r.t. real state, even if there is a difference
// - and we must have a way to push new information onto the resource
Collection<V> valuesToReplace;
if (hasFullTargetObject && (mappingOutputStruct.isStrongMappingWasUsed() || mappingOutputStruct.isPushChanges())) {
valuesToReplace = outputTriple.getNonNegativeValues();
} else {
valuesToReplace = outputTriple.getPlusSet();
}
LOGGER.trace("{}: hasFullTargetObject={}, isStrongMappingWasUsed={}, pushingChange={}, valuesToReplace={}", mappingDesc, hasFullTargetObject, mappingOutputStruct.isStrongMappingWasUsed(), mappingOutputStruct.isPushChanges(), valuesToReplace);
if (!valuesToReplace.isEmpty()) {
if (hasFullTargetObject && targetContext.isFresh() && aPrioriTargetItem != null) {
Collection<V> valuesPresent = aPrioriTargetItem.getValues();
if (PrismValueCollectionsUtil.equalsRealValues(valuesPresent, valuesToReplace)) {
LOGGER.trace("{} resulted in existing values for {}, skipping creation of a delta", mappingDesc, targetContext);
continue;
}
}
targetItemDelta.setValuesToReplace(PrismValueCollectionsUtil.cloneCollection(valuesToReplace));
applyEstematedOldValueInReplaceCase(targetItemDelta, outputTriple);
} else if (outputTriple.hasMinusSet()) {
LOGGER.trace("{} resulted in null or empty value for {} and there is a minus set, resetting it (replace with empty)", mappingDesc, targetContext);
targetItemDelta.setValueToReplace();
applyEstematedOldValueInReplaceCase(targetItemDelta, outputTriple);
} else {
LOGGER.trace("{} resulted in null or empty value for {}, skipping", mappingDesc, targetContext);
}
}
if (targetItemDelta.isEmpty()) {
continue;
}
LOGGER.trace("{} adding new delta for {}: {}", mappingDesc, targetContext, targetItemDelta);
targetContext.swallowToSecondaryDelta(targetItemDelta);
}
}
for (MappingImpl<V, D> mapping : mappings) {
XMLGregorianCalendar mappingNextRecomputeTime = mapping.getNextRecomputeTime();
if (mappingNextRecomputeTime != null) {
if (mapping.isConditionSatisfied() && (nextRecomputeTime == null || nextRecomputeTime.compare(mappingNextRecomputeTime) == DatatypeConstants.GREATER)) {
nextRecomputeTime = mappingNextRecomputeTime;
// TODO: maybe better description? But consider storage requirements. We do not want to store too much.
triggerOriginDescription = mapping.getIdentifier();
}
}
}
if (nextRecomputeTime != null) {
NextRecompute nextRecompute = new NextRecompute(nextRecomputeTime, triggerOriginDescription);
nextRecompute.createTrigger(params.getAPrioriTargetObject(), targetObjectDefinition, targetContext);
}
return outputTripleMap;
}
use of com.evolveum.midpoint.prism.path.UniformItemPath in project midpoint by Evolveum.
the class TemplateMappingsEvaluation method collectLocalItemDefinitions.
private void collectLocalItemDefinitions(ObjectTemplateType objectTemplate) {
for (ObjectTemplateItemDefinitionType def : objectTemplate.getItem()) {
if (def.getRef() == null) {
throw new IllegalStateException("Item definition with null ref in " + env.contextDescription);
}
UniformItemPath itemPath = beans.prismContext.toUniformPath(def.getRef());
LensUtil.rejectNonTolerantSettingIfPresent(def, itemPath, env.contextDescription);
// TODO check for incompatible overrides
itemDefinitionsMap.put(itemPath, def);
}
}
use of com.evolveum.midpoint.prism.path.UniformItemPath in project midpoint by Evolveum.
the class NameResolutionHelper method getPathsToResolve.
@NotNull
private List<? extends ItemPath> getPathsToResolve(Collection<SelectorOptions<GetOperationOptions>> options) {
final UniformItemPath emptyPath = prismContext.emptyPath();
List<UniformItemPath> rv = new ArrayList<>();
for (SelectorOptions<GetOperationOptions> option : CollectionUtils.emptyIfNull(options)) {
if (GetOperationOptions.isResolveNames(option.getOptions())) {
rv.add(option.getItemPath(emptyPath));
}
}
return rv;
}
use of com.evolveum.midpoint.prism.path.UniformItemPath in project midpoint by Evolveum.
the class QAccessCertificationCampaignMapping method isRetrieveAllCases.
private boolean isRetrieveAllCases(SelectorOptions<GetOperationOptions> option) {
GetOperationOptions getOp = option.getOptions();
if (getOp == null) {
return false;
}
UniformItemPath path = option.getSelector() != null ? option.getSelector().getPath() : null;
return RetrieveOption.INCLUDE.equals(getOp.getRetrieve()) && (path == null || path.isEmpty() || F_CASE.equivalent(path));
}
Aggregations