use of com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowAssociationType in project midpoint by Evolveum.
the class EntitlementConverter method collectEntitlementToAttrDelta.
/**
* Collects entitlement changes from the shadow to entitlement section into attribute operations.
* Collects a single value.
* NOTE: only collects SUBJECT_TO_ENTITLEMENT entitlement direction.
*/
private <T> void collectEntitlementToAttrDelta(ProvisioningContext ctx, Map<QName, PropertyModificationOperation> operationMap, PrismContainerValue<ShadowAssociationType> associationCVal, ModificationType modificationType) throws SchemaException, ConfigurationException, ObjectNotFoundException, CommunicationException, ExpressionEvaluationException {
RefinedObjectClassDefinition objectClassDefinition = ctx.getObjectClassDefinition();
ShadowAssociationType associationType = associationCVal.asContainerable();
QName associationName = associationType.getName();
if (associationName == null) {
throw new SchemaException("No name in entitlement association " + associationCVal);
}
RefinedAssociationDefinition assocDefType = objectClassDefinition.findAssociationDefinition(associationName);
if (assocDefType == null) {
throw new SchemaException("No association with name " + associationName + " in " + objectClassDefinition + " in schema of " + ctx.getResource());
}
ResourceObjectAssociationDirectionType direction = assocDefType.getResourceObjectAssociationType().getDirection();
if (direction != ResourceObjectAssociationDirectionType.SUBJECT_TO_OBJECT) {
// therefore will be processed later
return;
}
QName assocAttrName = assocDefType.getResourceObjectAssociationType().getAssociationAttribute();
if (assocAttrName == null) {
throw new SchemaException("No association attribute definied in entitlement association '" + associationName + "' in " + ctx.getResource());
}
RefinedAttributeDefinition assocAttrDef = objectClassDefinition.findAttributeDefinition(assocAttrName);
if (assocAttrDef == null) {
throw new SchemaException("Association attribute '" + assocAttrName + "'definied in entitlement association '" + associationName + "' was not found in schema for " + ctx.getResource());
}
PropertyModificationOperation attributeOperation = operationMap.get(assocAttrName);
if (attributeOperation == null) {
attributeOperation = new PropertyModificationOperation(assocAttrDef.createEmptyDelta(new ItemPath(ShadowType.F_ATTRIBUTES, assocAttrName)));
attributeOperation.setMatchingRuleQName(assocDefType.getMatchingRule());
operationMap.put(assocAttrName, attributeOperation);
}
QName valueAttrName = assocDefType.getResourceObjectAssociationType().getValueAttribute();
if (valueAttrName == null) {
throw new SchemaException("No value attribute defined in entitlement association '" + associationName + "' in " + ctx.getResource());
}
ResourceAttributeContainer identifiersContainer = ShadowUtil.getAttributesContainer(associationCVal, ShadowAssociationType.F_IDENTIFIERS);
PrismProperty<T> valueAttr = identifiersContainer.findProperty(valueAttrName);
if (valueAttr == null) {
throw new SchemaException("No value attribute " + valueAttrName + " present in entitlement association '" + associationName + "' in shadow for " + ctx.getResource());
}
if (modificationType == ModificationType.ADD) {
attributeOperation.getPropertyDelta().addValuesToAdd(valueAttr.getClonedValues());
} else if (modificationType == ModificationType.DELETE) {
attributeOperation.getPropertyDelta().addValuesToDelete(valueAttr.getClonedValues());
} else if (modificationType == ModificationType.REPLACE) {
// TODO: check if already exists
attributeOperation.getPropertyDelta().setValuesToReplace(valueAttr.getClonedValues());
}
}
use of com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowAssociationType in project midpoint by Evolveum.
the class ReconciliationProcessor method recordAssociationDelta.
private void recordAssociationDelta(ValueMatcher valueMatcher, LensProjectionContext accCtx, RefinedAssociationDefinition assocDef, ModificationType changeType, ShadowAssociationType value, ObjectType originObject, String reason) throws SchemaException {
ItemDelta existingDelta = null;
if (accCtx.getSecondaryDelta() != null) {
existingDelta = accCtx.getSecondaryDelta().findItemDelta(SchemaConstants.PATH_ASSOCIATION);
}
LOGGER.trace("Reconciliation will {} value of association {}: {} because {}", changeType, assocDef, value, reason);
// todo initialize only once
PrismContainerDefinition<ShadowAssociationType> associationDefinition = prismContext.getSchemaRegistry().findObjectDefinitionByCompileTimeClass(ShadowType.class).findContainerDefinition(ShadowType.F_ASSOCIATION);
ContainerDelta assocDelta = new ContainerDelta(SchemaConstants.PATH_ASSOCIATION, associationDefinition, prismContext);
PrismContainerValue cValue = value.asPrismContainerValue().clone();
cValue.setOriginType(OriginType.RECONCILIATION);
cValue.setOriginObject(originObject);
if (changeType == ModificationType.ADD) {
assocDelta.addValueToAdd(cValue);
} else if (changeType == ModificationType.DELETE) {
if (!isToBeDeleted(existingDelta, valueMatcher, value)) {
LOGGER.trace("Adding association value to delete {} ", cValue);
assocDelta.addValueToDelete(cValue);
}
} else if (changeType == ModificationType.REPLACE) {
assocDelta.setValueToReplace(cValue);
} else {
throw new IllegalArgumentException("Unknown change type " + changeType);
}
accCtx.swallowToSecondaryDelta(assocDelta);
}
use of com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowAssociationType in project midpoint by Evolveum.
the class ReconciliationProcessor method isInCvwoAssociationValues.
private boolean isInCvwoAssociationValues(ValueMatcher valueMatcher, ShadowAssociationType value, Collection<ItemValueWithOrigin<PrismContainerValue<ShadowAssociationType>, PrismContainerDefinition<ShadowAssociationType>>> shouldBeCvwos) {
if (shouldBeCvwos == null || shouldBeCvwos.isEmpty()) {
return false;
}
for (ItemValueWithOrigin<? extends PrismContainerValue<ShadowAssociationType>, PrismContainerDefinition<ShadowAssociationType>> shouldBeCvwo : shouldBeCvwos) {
if (!shouldBeCvwo.isValid()) {
continue;
}
PrismContainerValue<ShadowAssociationType> shouldBePCValue = shouldBeCvwo.getItemValue();
ShadowAssociationType shouldBeValue = shouldBePCValue.getValue();
if (matchValue(value, shouldBeValue, valueMatcher)) {
return true;
}
}
return false;
}
use of com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowAssociationType in project midpoint by Evolveum.
the class ReconciliationProcessor method reconcileProjectionAssociations.
private void reconcileProjectionAssociations(LensProjectionContext projCtx, Map<QName, DeltaSetTriple<ItemValueWithOrigin<PrismContainerValue<ShadowAssociationType>, PrismContainerDefinition<ShadowAssociationType>>>> squeezedAssociations, RefinedObjectClassDefinition accountDefinition, Task task, OperationResult result) throws SchemaException, ConfigurationException, ObjectNotFoundException, CommunicationException, SecurityViolationException, ExpressionEvaluationException {
PrismObject<ShadowType> shadowNew = projCtx.getObjectNew();
PrismContainer associationsContainer = shadowNew.findContainer(ShadowType.F_ASSOCIATION);
Collection<QName> associationNames = squeezedAssociations != null ? MiscUtil.union(squeezedAssociations.keySet(), accountDefinition.getNamesOfAssociations()) : accountDefinition.getNamesOfAssociations();
for (QName assocName : associationNames) {
LOGGER.trace("Association reconciliation processing association {}", assocName);
RefinedAssociationDefinition associationDefinition = accountDefinition.findAssociationDefinition(assocName);
if (associationDefinition == null) {
throw new SchemaException("No definition for association " + assocName + " in " + projCtx.getResourceShadowDiscriminator());
}
DeltaSetTriple<ItemValueWithOrigin<PrismContainerValue<ShadowAssociationType>, PrismContainerDefinition<ShadowAssociationType>>> cvwoTriple = squeezedAssociations != null ? squeezedAssociations.get(assocName) : null;
// note: actually isIgnored is not implemented yet
if (associationDefinition.isIgnored()) {
LOGGER.trace("Skipping reconciliation of association {} because it is ignored", assocName);
continue;
}
// TODO implement limitations
// PropertyLimitations limitations = associationDefinition.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);
// continue;
// }
// if (projCtx.isModify() && (access.isModify() == null || !access.isModify())) {
// LOGGER.trace("Skipping reconciliation of attribute {} because it is non-updateable",
// attrName);
// continue;
// }
// }
// }
Collection<ItemValueWithOrigin<PrismContainerValue<ShadowAssociationType>, PrismContainerDefinition<ShadowAssociationType>>> shouldBeCValues;
if (cvwoTriple == null) {
shouldBeCValues = new HashSet<>();
} else {
shouldBeCValues = new HashSet<>(cvwoTriple.getNonNegativeValues());
}
// TODO what about equality checks? There will be probably duplicates there.
// We consider values explicitly requested by user to be among "should be values".
addContainerValuesFromDelta(shouldBeCValues, projCtx.getPrimaryDelta(), assocName);
// 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).
// values in shouldBeCValues are parent-less
// to be able to make Containerable out of them, we provide them a (fake) parent
// (and we clone them not to mess anything)
PrismContainer<ShadowAssociationType> fakeParent = prismContext.getSchemaRegistry().findContainerDefinitionByCompileTimeClass(ShadowAssociationType.class).instantiate();
for (ItemValueWithOrigin<PrismContainerValue<ShadowAssociationType>, PrismContainerDefinition<ShadowAssociationType>> cvwo : shouldBeCValues) {
PrismContainerValue<ShadowAssociationType> cvalue = cvwo.getItemValue().clone();
cvalue.setParent(fakeParent);
cvwo.setItemValue(cvalue);
}
boolean hasStrongShouldBeCValue = false;
for (ItemValueWithOrigin<PrismContainerValue<ShadowAssociationType>, PrismContainerDefinition<ShadowAssociationType>> shouldBeCValue : shouldBeCValues) {
if (shouldBeCValue.getMapping() != null && shouldBeCValue.getMapping().getStrength() == MappingStrengthType.STRONG) {
hasStrongShouldBeCValue = true;
break;
}
}
Collection<PrismContainerValue<ShadowAssociationType>> areCValues = new HashSet<>();
if (associationsContainer != null) {
for (Object o : associationsContainer.getValues()) {
PrismContainerValue<ShadowAssociationType> existingAssocValue = (PrismContainerValue<ShadowAssociationType>) o;
if (existingAssocValue.getValue().getName().equals(assocName)) {
areCValues.add(existingAssocValue);
}
}
} else {
areCValues = new HashSet<>();
}
// todo comment this logging code out eventually
// if (LOGGER.isTraceEnabled()) {
// StringBuilder sb = new StringBuilder();
// sb.append("Reconciliation\nASSOCIATION: ").append(PrettyPrinter.prettyPrint(assocName));
// sb.append("\n Should be:");
// for (ItemValueWithOrigin<PrismContainerValue<ShadowAssociationType>,PrismContainerDefinition<ShadowAssociationType>> shouldBeCValue : shouldBeCValues) {
// sb.append("\n ");
// sb.append(shouldBeCValue.getItemValue());
// PrismValueDeltaSetTripleProducer<?,?> shouldBeMapping = shouldBeCValue.getMapping();
// if (shouldBeMapping != null && shouldBeMapping.getStrength() == MappingStrengthType.STRONG) {
// sb.append(" STRONG");
// }
// if (shouldBeMapping != null && shouldBeMapping.getStrength() == MappingStrengthType.WEAK) {
// sb.append(" WEAK");
// }
// if (!shouldBeCValue.isValid()) {
// sb.append(" INVALID");
// }
// }
// sb.append("\n Is:");
// for (PrismContainerValue<ShadowAssociationType> isCVal : areCValues) {
// sb.append("\n ");
// sb.append(isCVal);
// }
// LOGGER.trace("{}", sb.toString());
// }
ValueMatcher associationValueMatcher = new ValueMatcher(null) {
// todo is this correct? [med]
@Override
public boolean match(Object realA, Object realB) {
checkType(realA);
checkType(realB);
if (realA == null) {
return realB == null;
} else if (realB == null) {
return false;
} else {
ShadowAssociationType a = (ShadowAssociationType) realA;
ShadowAssociationType b = (ShadowAssociationType) realB;
checkName(a);
checkName(b);
if (!a.getName().equals(b.getName())) {
return false;
}
if (a.getShadowRef() != null && a.getShadowRef().getOid() != null && b.getShadowRef() != null && b.getShadowRef().getOid() != null) {
return a.getShadowRef().getOid().equals(b.getShadowRef().getOid());
}
LOGGER.warn("Comparing association values without shadowRefs: {} and {}", a, b);
return false;
}
}
private void checkName(ShadowAssociationType s) {
if (s.getName() == null) {
throw new IllegalStateException("No name for association " + s);
}
}
@Override
public boolean matches(Object realValue, String regex) {
throw new UnsupportedOperationException();
}
@Override
public boolean hasRealValue(PrismProperty property, PrismPropertyValue pValue) {
throw new UnsupportedOperationException();
}
@Override
public boolean isRealValueToAdd(PropertyDelta delta, PrismPropertyValue pValue) {
throw new UnsupportedOperationException();
}
private void checkType(Object o) {
if (o != null && !(o instanceof ShadowAssociationType)) {
throw new IllegalStateException("Object is not a ShadowAssociationType, it is " + o.getClass() + " instead");
}
}
};
for (ItemValueWithOrigin<PrismContainerValue<ShadowAssociationType>, PrismContainerDefinition<ShadowAssociationType>> shouldBeCvwo : shouldBeCValues) {
PrismValueDeltaSetTripleProducer<?, ?> shouldBeMapping = shouldBeCvwo.getMapping();
if (shouldBeMapping == null) {
continue;
}
if (shouldBeMapping.getStrength() != MappingStrengthType.STRONG && (!areCValues.isEmpty() || hasStrongShouldBeCValue)) {
// changed directly on the projection resource object
continue;
}
ShadowAssociationType shouldBeRealValue = shouldBeCvwo.getItemValue().getValue();
if (shouldBeCvwo.isValid() && !isInAssociationValues(associationValueMatcher, shouldBeRealValue, areCValues)) {
recordAssociationDelta(associationValueMatcher, projCtx, associationDefinition, ModificationType.ADD, shouldBeRealValue, shouldBeCvwo.getSource(), "it is given by a mapping");
}
}
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Before decideIfTolerateAssociation:");
LOGGER.trace("areCValues:\n{}", DebugUtil.debugDump(areCValues));
LOGGER.trace("shouldBeCValues:\n{}", DebugUtil.debugDump(shouldBeCValues));
}
decideIfTolerateAssociation(projCtx, associationDefinition, areCValues, shouldBeCValues, associationValueMatcher, task, result);
}
}
Aggregations