use of com.evolveum.midpoint.common.refinery.RefinedAttributeDefinition 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.common.refinery.RefinedAttributeDefinition in project midpoint by Evolveum.
the class InboundProcessor method processInboundExpressionsForProjection.
private <F extends FocusType> void processInboundExpressionsForProjection(LensContext<F> context, LensProjectionContext projContext, RefinedObjectClassDefinition accountDefinition, ObjectDelta<ShadowType> aPrioriDelta, Task task, XMLGregorianCalendar now, OperationResult result) throws SchemaException, ExpressionEvaluationException, ObjectNotFoundException, ConfigurationException, CommunicationException, SecurityViolationException {
if (aPrioriDelta == null && projContext.getObjectCurrent() == null) {
LOGGER.trace("Nothing to process in inbound, both a priori delta and current account were null.");
return;
}
PrismObject<ShadowType> accountCurrent = projContext.getObjectCurrent();
PrismObject<ShadowType> accountNew = projContext.getObjectNew();
if (hasAnyStrongMapping(accountDefinition) && !projContext.isFullShadow() && !projContext.isThombstone()) {
LOGGER.trace("There are strong inbound mapping, but the shadow hasn't be fully loaded yet. Trying to load full shadow now.");
accountCurrent = loadProjection(context, projContext, task, result, accountCurrent);
if (projContext.getSynchronizationPolicyDecision() == SynchronizationPolicyDecision.BROKEN) {
return;
}
}
for (QName accountAttributeName : accountDefinition.getNamesOfAttributesWithInboundExpressions()) {
final PropertyDelta<?> attributeAPrioriDelta;
if (aPrioriDelta != null) {
attributeAPrioriDelta = aPrioriDelta.findPropertyDelta(new ItemPath(SchemaConstants.C_ATTRIBUTES), accountAttributeName);
if (attributeAPrioriDelta == 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());
continue;
}
} else {
attributeAPrioriDelta = null;
}
RefinedAttributeDefinition attrDef = accountDefinition.findAttributeDefinition(accountAttributeName);
if (attrDef.isIgnored(LayerType.MODEL)) {
LOGGER.trace("Skipping inbound for attribute {} in {} because the attribute is ignored", PrettyPrinter.prettyPrint(accountAttributeName), projContext.getResourceShadowDiscriminator());
continue;
}
List<MappingType> inboundMappingTypes = attrDef.getInboundMappingTypes();
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Processing inbound for {} in {}; ({} mappings)", PrettyPrinter.prettyPrint(accountAttributeName), projContext.getResourceShadowDiscriminator(), inboundMappingTypes.size());
}
if (!inboundMappingTypes.isEmpty()) {
PropertyLimitations limitations = attrDef.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 attribute {} in {}, skipping", accountAttributeName, projContext.getHumanReadableName());
continue;
}
}
}
for (MappingType inboundMappingType : inboundMappingTypes) {
// we want to reconcile also the existing attribute value? This probably would not work.
if (inboundMappingType.getStrength() == MappingStrengthType.STRONG) {
LOGGER.trace("There is an inbound mapping with strength == STRONG, trying to load full account now.");
if (!projContext.isFullShadow() && !projContext.isDelete()) {
accountCurrent = loadProjection(context, projContext, task, result, accountCurrent);
if (projContext.getSynchronizationPolicyDecision() == SynchronizationPolicyDecision.BROKEN) {
return;
}
}
}
if (attributeAPrioriDelta == 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());
continue;
}
PrismObject<F> focus;
if (context.getFocusContext().getObjectCurrent() != null) {
focus = context.getFocusContext().getObjectCurrent();
} else {
focus = context.getFocusContext().getObjectNew();
}
ItemDelta focusItemDelta = null;
if (attributeAPrioriDelta != null) {
LOGGER.trace("Processing inbound from a priori delta: {}", aPrioriDelta);
focusItemDelta = evaluateInboundMapping(context, inboundMappingType, accountAttributeName, null, attributeAPrioriDelta, focus, accountNew, projContext.getResource(), task, result);
} else if (accountCurrent != null) {
if (!projContext.isFullShadow()) {
// todo change to trace level eventually
LOGGER.warn("Attempted to execute inbound expression on account shadow {} WITHOUT full account. Trying to load the account now.", projContext.getOid());
accountCurrent = loadProjection(context, projContext, task, result, accountCurrent);
if (projContext.getSynchronizationPolicyDecision() == SynchronizationPolicyDecision.BROKEN) {
return;
}
if (!projContext.isFullShadow()) {
if (projContext.getResourceShadowDiscriminator().getOrder() > 0) {
// higher-order context. It is OK not to load this
LOGGER.trace("Skipped load of higher-order account with shadow OID {} skipping inbound processing on it", projContext.getOid());
return;
}
// TODO: is it good to mark as broken? what is
// the resorce is down?? if there is no
// assignment and the account was added directly
// it can cause that the account will be
// unlinked from the user FIXME
LOGGER.warn("Couldn't load account with shadow OID {}, setting context as broken and skipping inbound processing on it", projContext.getOid());
projContext.setSynchronizationPolicyDecision(SynchronizationPolicyDecision.BROKEN);
return;
}
}
PrismProperty<?> oldAccountProperty = accountCurrent.findProperty(new ItemPath(ShadowType.F_ATTRIBUTES, accountAttributeName));
LOGGER.trace("Processing inbound from account sync absolute state (currentAccount): {}", oldAccountProperty);
focusItemDelta = evaluateInboundMapping(context, inboundMappingType, accountAttributeName, oldAccountProperty, null, focus, accountNew, projContext.getResource(), task, result);
}
if (focusItemDelta != null && !focusItemDelta.isEmpty()) {
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Created delta (from inbound expression for {} on {})\n{}", accountAttributeName, projContext.getResource(), focusItemDelta.debugDump(1));
}
context.getFocusContext().swallowToProjectionWaveSecondaryDelta(focusItemDelta);
context.recomputeFocus();
} else {
LOGGER.trace("Created delta (from inbound expression for {} on {}) was null or empty.", accountAttributeName, projContext.getResource());
}
}
}
}
if (isDeleteAccountDelta(projContext)) {
// we don't need to do inbound if account was deleted
return;
}
processSpecialPropertyInbound(accountDefinition.getPasswordInbound(), SchemaConstants.PATH_PASSWORD_VALUE, context.getFocusContext().getObjectNew(), projContext, accountDefinition, context, task, now, result);
processSpecialPropertyInbound(accountDefinition.getActivationBidirectionalMappingType(ActivationType.F_ADMINISTRATIVE_STATUS), SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS, context.getFocusContext().getObjectNew(), projContext, accountDefinition, context, task, now, result);
processSpecialPropertyInbound(accountDefinition.getActivationBidirectionalMappingType(ActivationType.F_VALID_FROM), SchemaConstants.PATH_ACTIVATION_VALID_FROM, context.getFocusContext().getObjectNew(), projContext, accountDefinition, context, task, now, result);
processSpecialPropertyInbound(accountDefinition.getActivationBidirectionalMappingType(ActivationType.F_VALID_TO), SchemaConstants.PATH_ACTIVATION_VALID_TO, context.getFocusContext().getObjectNew(), projContext, accountDefinition, context, task, now, result);
}
use of com.evolveum.midpoint.common.refinery.RefinedAttributeDefinition in project midpoint by Evolveum.
the class ProjectionValuesProcessor method checkSchemaAndPolicies.
/**
* Check that the primary deltas do not violate schema and policies
* TODO: implement schema check
*/
public <F extends ObjectType> void checkSchemaAndPolicies(LensContext<F> context, LensProjectionContext accountContext, String activityDescription, OperationResult result) throws SchemaException, PolicyViolationException {
ObjectDelta<ShadowType> primaryDelta = accountContext.getPrimaryDelta();
if (primaryDelta == null || primaryDelta.isDelete()) {
return;
}
RefinedObjectClassDefinition rAccountDef = accountContext.getCompositeObjectClassDefinition();
if (rAccountDef == null) {
throw new SchemaException("No definition for account type '" + accountContext.getResourceShadowDiscriminator() + "' in " + accountContext.getResource());
}
if (primaryDelta.isAdd()) {
PrismObject<ShadowType> accountToAdd = primaryDelta.getObjectToAdd();
ResourceAttributeContainer attributesContainer = ShadowUtil.getAttributesContainer(accountToAdd);
if (attributesContainer != null) {
for (ResourceAttribute<?> attribute : attributesContainer.getAttributes()) {
RefinedAttributeDefinition rAttrDef = rAccountDef.findAttributeDefinition(attribute.getElementName());
if (!rAttrDef.isTolerant()) {
throw new PolicyViolationException("Attempt to add object with non-tolerant attribute " + attribute.getElementName() + " in " + "account " + accountContext.getResourceShadowDiscriminator() + " during " + activityDescription);
}
}
}
} else if (primaryDelta.isModify()) {
for (ItemDelta<?, ?> modification : primaryDelta.getModifications()) {
if (modification.getParentPath().equivalent(SchemaConstants.PATH_ATTRIBUTES)) {
PropertyDelta<?> attrDelta = (PropertyDelta<?>) modification;
RefinedAttributeDefinition rAttrDef = rAccountDef.findAttributeDefinition(attrDelta.getElementName());
if (!rAttrDef.isTolerant()) {
throw new PolicyViolationException("Attempt to modify non-tolerant attribute " + attrDelta.getElementName() + " in " + "account " + accountContext.getResourceShadowDiscriminator() + " during " + activityDescription);
}
}
}
} else {
throw new IllegalStateException("Whoops!");
}
}
use of com.evolveum.midpoint.common.refinery.RefinedAttributeDefinition in project midpoint by Evolveum.
the class ResourceObjectPattern method matches.
private boolean matches(ResourceAttribute<?> identifier, ResourceAttribute<?> attributeToMatch, MatchingRuleRegistry matchingRuleRegistry) throws SchemaException {
if (!identifier.getElementName().equals(attributeToMatch.getElementName())) {
return false;
}
RefinedAttributeDefinition rAttrDef = rOcDef.findAttributeDefinition(identifier.getElementName());
QName matchingRuleQName = rAttrDef.getMatchingRuleQName();
if (matchingRuleQName == null || matchingRuleRegistry == null) {
return identifier.equalsRealValue(attributeToMatch);
}
MatchingRule<Object> matchingRule = matchingRuleRegistry.getMatchingRule(matchingRuleQName, rAttrDef.getTypeName());
return matchingRule.match(identifier.getRealValue(), attributeToMatch.getRealValue());
}
use of com.evolveum.midpoint.common.refinery.RefinedAttributeDefinition in project midpoint by Evolveum.
the class AbstractModelImplementationIntegrationTest method createAccountDelta.
protected <T> ObjectDelta<ShadowType> createAccountDelta(LensProjectionContext accCtx, String accountOid, String attributeLocalName, T... propertyValues) throws SchemaException {
ResourceType resourceType = accCtx.getResource();
QName attrQName = new QName(ResourceTypeUtil.getResourceNamespace(resourceType), attributeLocalName);
ItemPath attrPath = new ItemPath(ShadowType.F_ATTRIBUTES, attrQName);
RefinedObjectClassDefinition refinedAccountDefinition = accCtx.getCompositeObjectClassDefinition();
RefinedAttributeDefinition attrDef = refinedAccountDefinition.findAttributeDefinition(attrQName);
assertNotNull("No definition of attribute " + attrQName + " in account def " + refinedAccountDefinition, attrDef);
ObjectDelta<ShadowType> accountDelta = ObjectDelta.createEmptyModifyDelta(ShadowType.class, accountOid, prismContext);
PropertyDelta<T> attrDelta = new PropertyDelta<T>(attrPath, attrDef, prismContext);
attrDelta.setValuesToReplace(PrismPropertyValue.createCollection(propertyValues));
accountDelta.addModification(attrDelta);
return accountDelta;
}
Aggregations