diff --git a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/ArchetypeManager.java b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/ArchetypeManager.java index 35dbc795d71..e287edecb55 100644 --- a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/ArchetypeManager.java +++ b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/ArchetypeManager.java @@ -105,7 +105,11 @@ public ObjectPolicyConfigurationType determineObjectPolic if (object == null) { return null; } - return determineObjectPolicyConfiguration(object, systemObjectCache.getSystemConfiguration(result).asObjectable()); + PrismObject systemConfiguration = systemObjectCache.getSystemConfiguration(result); + if (systemConfiguration == null) { + return null; + } + return determineObjectPolicyConfiguration(object, systemConfiguration.asObjectable()); } public ExpressionProfile determineExpressionProfile(PrismObject object, OperationResult result) throws SchemaException, ConfigurationException { diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/AssignmentCollector.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/AssignmentCollector.java index 3a298caca36..d877354b72d 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/AssignmentCollector.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/AssignmentCollector.java @@ -151,7 +151,12 @@ private Collection> ev try { ItemDeltaItem,PrismContainerDefinition> assignmentIdi = new ItemDeltaItem<>(); assignmentIdi.setItemOld(LensUtil.createAssignmentSingleValueContainerClone(assignmentType)); - assignmentIdi.setDefinition(assignmentType.asPrismContainerValue().getDefinition()); + PrismContainerDefinition definition = assignmentType.asPrismContainerValue().getDefinition(); + if (definition == null) { + // TODO: optimize + definition = prismContext.getSchemaRegistry().findObjectDefinitionByCompileTimeClass(AssignmentHolderType.class).findContainerDefinition(AssignmentHolderType.F_ASSIGNMENT); + } + assignmentIdi.setDefinition(definition); assignmentIdi.recompute(); EvaluatedAssignment assignment = assignmentEvaluator.evaluate(assignmentIdi, PlusMinusZero.ZERO, false, assignmentHolder, assignmentHolder.toString(), virtual, task, result); evaluatedAssignments.add(assignment); diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/Construction.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/Construction.java index e860f236109..ab428dff10e 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/Construction.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/Construction.java @@ -463,7 +463,9 @@ private MappingImpl, ResourceAttributeDefinition> e } catch (SchemaException e) { throw new SchemaException(getAttributeEvaluationErrorMesssage(attrName, e), e); } catch (ExpressionEvaluationException e) { - throw new ExpressionEvaluationException(getAttributeEvaluationErrorMesssage(attrName, e), e); + // No need to specially handle this here. It was already handled in the expression-processing + // code and it has proper description. + throw e; } catch (ObjectNotFoundException e) { throw new ObjectNotFoundException(getAttributeEvaluationErrorMesssage(attrName, e), e); } catch (SecurityViolationException e) { diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/focus/AssignmentTripleEvaluator.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/focus/AssignmentTripleEvaluator.java index 646e3e07dfe..ca4ca3c54ae 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/focus/AssignmentTripleEvaluator.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/focus/AssignmentTripleEvaluator.java @@ -476,11 +476,15 @@ private void processAssignment(DeltaSetTriple> evalu } } - private ItemDeltaItem, PrismContainerDefinition> createAssignmentIdiNoChange( - PrismContainerValue cval) throws SchemaException { + private ItemDeltaItem, PrismContainerDefinition> createAssignmentIdiNoChange(PrismContainerValue cval) throws SchemaException { ItemDeltaItem, PrismContainerDefinition> idi = new ItemDeltaItem<>(); idi.setItemOld(LensUtil.createAssignmentSingleValueContainerClone(cval.asContainerable())); - idi.setDefinition(cval.getDefinition()); + PrismContainerDefinition definition = cval.getDefinition(); + if (definition == null) { + // TODO: optimize + definition = prismContext.getSchemaRegistry().findObjectDefinitionByCompileTimeClass(AssignmentHolderType.class).findContainerDefinition(AssignmentHolderType.F_ASSIGNMENT); + } + idi.setDefinition(definition); idi.recompute(); return idi; } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/focus/InboundProcessor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/focus/InboundProcessor.java index 0e5f347bac3..0c44182d43b 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/focus/InboundProcessor.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/focus/InboundProcessor.java @@ -93,6 +93,7 @@ import com.evolveum.midpoint.xml.ns._public.common.common_3.PropertyAccessType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceBidirectionalMappingAndDefinitionType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceBidirectionalMappingType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceObjectAssociationType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowAssociationType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType; @@ -125,6 +126,8 @@ public class InboundProcessor { @Autowired private Protector protector; @Autowired private ProvisioningService provisioningService; + private PrismContainerDefinition associationContainerDefinition; + // private Map>> mappingsToTarget; void processInbound(LensContext context, XMLGregorianCalendar now, Task task, OperationResult result) throws SchemaException, ExpressionEvaluationException, ObjectNotFoundException, ConfigurationException, CommunicationException, SecurityViolationException { @@ -380,7 +383,7 @@ private bo if (projCurrent != null) { oldAccountProperty = projCurrent.findProperty(accountAttributePath); } - collectMappingsForTargets(context, projContext, inboundMappingType, accountAttributeName, oldAccountProperty, attributeAPrioriDelta, focus, null, mappingsToTarget, task, result); + collectMappingsForTargets(context, projContext, inboundMappingType, accountAttributeName, oldAccountProperty, attributeAPrioriDelta, (D)attrDef, focus, null, mappingsToTarget, task, result); } else if (projCurrent != null) { @@ -391,7 +394,7 @@ private bo PrismProperty oldAccountProperty = projCurrent.findProperty(accountAttributePath); LOGGER.trace("Processing inbound from account sync absolute state (currentAccount): {}", oldAccountProperty); - collectMappingsForTargets(context, projContext, inboundMappingType, accountAttributeName, oldAccountProperty, null, + collectMappingsForTargets(context, projContext, inboundMappingType, accountAttributeName, (Item)oldAccountProperty, null, (D)attrDef, focus, null, mappingsToTarget, task, result); } } @@ -399,7 +402,7 @@ private bo return true; } - private boolean processAssociationInbound(QName accountAttributeName, + private boolean processAssociationInbound(QName associationQName, ObjectDelta aPrioriProjectionDelta, final LensProjectionContext projContext, RefinedObjectClassDefinition projectionDefinition, final LensContext context, XMLGregorianCalendar now, Map>> mappingsToTarget, @@ -408,40 +411,40 @@ private bo PrismObject projCurrent = projContext.getObjectCurrent(); PrismObject projNew = projContext.getObjectNew(); - final ItemDelta attributeAPrioriDelta; + final ItemDelta associationAPrioriDelta; if (aPrioriProjectionDelta != null) { - attributeAPrioriDelta = aPrioriProjectionDelta.findItemDelta(ShadowType.F_ASSOCIATION); - if (attributeAPrioriDelta == null && !projContext.isFullShadow() && !LensUtil.hasDependentContext(context, projContext)) { + associationAPrioriDelta = aPrioriProjectionDelta.findItemDelta(ShadowType.F_ASSOCIATION); + if (associationAPrioriDelta == null && !projContext.isFullShadow() && !LensUtil.hasDependentContext(context, projContext)) { LOGGER.trace("Skipping inbound for {} in {}: Not a full shadow and account a priori delta exists, but doesn't have change for processed property.", - accountAttributeName, projContext.getResourceShadowDiscriminator()); + associationQName, projContext.getResourceShadowDiscriminator()); return true; } } else { - attributeAPrioriDelta = null; + associationAPrioriDelta = null; } - RefinedAssociationDefinition associationDef = projectionDefinition.findAssociationDefinition(accountAttributeName); + RefinedAssociationDefinition associationRefinedDef = projectionDefinition.findAssociationDefinition(associationQName); //TODO: - if (associationDef.isIgnored(LayerType.MODEL)) { + if (associationRefinedDef.isIgnored(LayerType.MODEL)) { LOGGER.trace("Skipping inbound for association {} in {} because the association is ignored", - PrettyPrinter.prettyPrint(accountAttributeName), projContext.getResourceShadowDiscriminator()); + PrettyPrinter.prettyPrint(associationQName), projContext.getResourceShadowDiscriminator()); return true; } - List inboundMappingTypes = associationDef.getInboundMappingTypes(); + List inboundMappingTypes = associationRefinedDef.getInboundMappingTypes(); if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Processing inbound for {} in {}; ({} mappings)", PrettyPrinter.prettyPrint(accountAttributeName), + LOGGER.trace("Processing inbound for {} in {}; ({} mappings)", PrettyPrinter.prettyPrint(associationQName), projContext.getResourceShadowDiscriminator(), inboundMappingTypes.size()); } - PropertyLimitations limitations = associationDef.getLimitations(LayerType.MODEL); + PropertyLimitations limitations = associationRefinedDef.getLimitations(LayerType.MODEL); if (limitations != null) { PropertyAccessType access = limitations.getAccess(); if (access != null) { if (access.isRead() == null || !access.isRead()) { LOGGER.warn("Inbound mapping for non-readable association {} in {}, skipping", - accountAttributeName, projContext.getHumanReadableName()); + associationQName, projContext.getHumanReadableName()); return true; } } @@ -451,6 +454,8 @@ private bo return true; } + PrismContainerDefinition associationContainerDef = getAssociationContainerDefinition(); + for (MappingType inboundMappingType : inboundMappingTypes) { // There are two processing options: @@ -473,9 +478,9 @@ private bo } } - if (attributeAPrioriDelta == null && !projContext.isFullShadow() && !LensUtil.hasDependentContext(context, projContext)) { + if (associationAPrioriDelta == null && !projContext.isFullShadow() && !LensUtil.hasDependentContext(context, projContext)) { LOGGER.trace("Skipping association inbound for {} in {}: Not a full shadow and account a priori delta exists, but doesn't have change for processed property.", - accountAttributeName, projContext.getResourceShadowDiscriminator()); + associationQName, projContext.getResourceShadowDiscriminator()); continue; } @@ -487,8 +492,8 @@ private bo } ItemDelta focusItemDelta = null; - if (attributeAPrioriDelta != null) { - LOGGER.trace("Processing association inbound from a priori delta: {}", attributeAPrioriDelta); + if (associationAPrioriDelta != null) { + LOGGER.trace("Processing association inbound from a priori delta: {}", associationAPrioriDelta); PrismContainer oldShadowAssociation = projCurrent.findContainer(ShadowType.F_ASSOCIATION); @@ -496,20 +501,20 @@ private bo if (oldShadowAssociation != null) { filteredAssociations = oldShadowAssociation.getDefinition().instantiate(); Collection> filteredAssociationValues = oldShadowAssociation.getValues().stream() - .filter(rVal -> accountAttributeName.equals(rVal.asContainerable().getName())) + .filter(rVal -> associationQName.equals(rVal.asContainerable().getName())) .map(val -> val.clone()) .collect(Collectors.toCollection(ArrayList::new)); prismContext.adopt(filteredAssociations); filteredAssociations.addAll(filteredAssociationValues); } - resolveEntitlementsIfNeeded((ContainerDelta) attributeAPrioriDelta, filteredAssociations, projContext, task, result); + resolveEntitlementsIfNeeded((ContainerDelta) associationAPrioriDelta, filteredAssociations, projContext, task, result); VariableProducer> entitlementVariable = (value, variables) -> resolveEntitlement(value, projContext, variables); - collectMappingsForTargets(context, projContext, inboundMappingType, accountAttributeName, (Item) oldShadowAssociation, - attributeAPrioriDelta, focus, (VariableProducer) entitlementVariable, mappingsToTarget, task, result); + collectMappingsForTargets(context, projContext, inboundMappingType, associationQName, (Item) oldShadowAssociation, + associationAPrioriDelta, (D)associationContainerDef, focus, (VariableProducer) entitlementVariable, mappingsToTarget, task, result); } else if (projCurrent != null) { @@ -528,20 +533,22 @@ private bo PrismContainer filteredAssociations = oldShadowAssociation.getDefinition().instantiate(); Collection> filteredAssociationValues = oldShadowAssociation.getValues().stream() - .filter(rVal -> accountAttributeName.equals(rVal.asContainerable().getName())) + .filter(rVal -> associationQName.equals(rVal.asContainerable().getName())) .map(val -> val.clone()) .collect(Collectors.toCollection(ArrayList::new)); - prismContext.adopt(filteredAssociations); filteredAssociations.addAll(filteredAssociationValues); - - resolveEntitlementsIfNeeded((ContainerDelta) attributeAPrioriDelta, filteredAssociations, projContext, task, result); + // Make sure all the modified/cloned associations have proper definition + filteredAssociations.applyDefinition(oldShadowAssociation.getDefinition(), false); + + resolveEntitlementsIfNeeded((ContainerDelta) associationAPrioriDelta, filteredAssociations, projContext, task, result); VariableProducer> entitlementVariable = - (value, variables) -> resolveEntitlement(value, projContext, variables);; + (value, variables) -> resolveEntitlement(value, projContext, variables); + LOGGER.trace("Processing association inbound from account sync absolute state (currentAccount): {}", filteredAssociations); - collectMappingsForTargets(context, projContext, inboundMappingType, accountAttributeName, filteredAssociations, - null, focus, entitlementVariable, mappingsToTarget, task, result); + collectMappingsForTargets(context, projContext, inboundMappingType, associationQName, (Item)filteredAssociations, + null, (D)associationContainerDef, focus, (VariableProducer)entitlementVariable, mappingsToTarget, task, result); } } @@ -604,6 +611,8 @@ private void processAuxiliaryObjectClassInbound( } else { focus = context.getFocusContext().getObjectNew(); } + + PrismPropertyDefinition auxiliaryObjectClassPropertyDefinition = prismContext.getSchemaRegistry().findObjectDefinitionByCompileTimeClass(ShadowType.class).findPropertyDefinition(ShadowType.F_AUXILIARY_OBJECT_CLASS); for (MappingType inboundMappingType : inboundMappingTypes) { @@ -611,7 +620,7 @@ private void processAuxiliaryObjectClassInbound( PrismProperty oldAccountProperty = projCurrent.findProperty(ShadowType.F_AUXILIARY_OBJECT_CLASS); LOGGER.trace("Processing inbound from account sync absolute state (currentAccount): {}", oldAccountProperty); - collectMappingsForTargets(context, projContext, inboundMappingType, ShadowType.F_AUXILIARY_OBJECT_CLASS, oldAccountProperty, null, focus, null, mappingsToTarget, task, result); + collectMappingsForTargets(context, projContext, inboundMappingType, ShadowType.F_AUXILIARY_OBJECT_CLASS, oldAccountProperty, null, auxiliaryObjectClassPropertyDefinition, focus, null, mappingsToTarget, task, result); } } @@ -711,10 +720,14 @@ private boolean checkWeakSkip(MappingImpl inbound, P return false; } + /** + * Note: in this case "attribute" may also be an association + */ private void collectMappingsForTargets(final LensContext context, LensProjectionContext projectionCtx, MappingType inboundMappingType, - QName accountAttributeName, Item oldAccountProperty, + QName accountAttributeQName, Item oldAccountProperty, ItemDelta attributeAPrioriDelta, + D attributeDefinition, PrismObject focusNew, VariableProducer variableProducer, Map>> mappingsToTarget, Task task, OperationResult result) throws ObjectNotFoundException, SchemaException, ConfigurationException, CommunicationException, SecurityViolationException, ExpressionEvaluationException { @@ -725,7 +738,7 @@ private vo ResourceType resource = projectionCtx.getResource(); MappingImpl.Builder builder = mappingFactory.createMappingBuilder(inboundMappingType, - "inbound expression for "+accountAttributeName+" in "+resource); + "inbound expression for "+accountAttributeQName+" in "+resource); if (!builder.isApplicableToChannel(context.getChannel())) { return; @@ -748,7 +761,6 @@ private vo variables.put(ExpressionConstants.VAR_CONFIGURATION, context.getSystemConfiguration(), context.getSystemConfiguration().getDefinition()); variables.put(ExpressionConstants.VAR_OPERATION, context.getFocusContext().getOperation().getValue(), String.class); - RefinedAttributeDefinition attributeDefinition = projectionCtx.findAttributeDefinition(accountAttributeName); Source defaultSource = new Source<>(oldAccountProperty, attributeAPrioriDelta, null, ExpressionConstants.VAR_INPUT_QNAME, (D)attributeDefinition); defaultSource.recompute(); builder = builder.defaultSource(defaultSource) @@ -1435,6 +1447,14 @@ private void processSpecialPropertyInbound(Collection getAssociationContainerDefinition() { + if (associationContainerDefinition == null) { + associationContainerDefinition = prismContext.getSchemaRegistry().findObjectDefinitionByCompileTimeClass(ShadowType.class).findContainerDefinition(ShadowType.F_ASSOCIATION); + } + return associationContainerDefinition; + } + // private Collection getMappingApplicableToChannel( // Collection inboundMappingTypes, String description, String channelUri) {