Skip to content

Commit

Permalink
Fixing auxiliary object class reconcilation: removing the extra attri…
Browse files Browse the repository at this point in the history
…butes (MID-2883)
  • Loading branch information
semancik committed May 9, 2016
1 parent b663401 commit f53f353
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 0 deletions.
13 changes: 13 additions & 0 deletions infra/util/src/main/java/com/evolveum/midpoint/util/QNameUtil.java
Expand Up @@ -18,6 +18,7 @@

import java.util.Arrays;
import java.util.Collection;
import java.util.Set;

import javax.xml.namespace.QName;

Expand Down Expand Up @@ -225,4 +226,16 @@ public static String getLocalPart(QName name) {
return name != null ? name.getLocalPart() : null;
}

public static boolean contains(Collection<QName> col, QName qname) {
if (col == null) {
return false;
}
for (QName element: col) {
if (match(element, qname)) {
return true;
}
}
return false;
}

}
Expand Up @@ -21,6 +21,7 @@
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.xml.namespace.QName;

Expand All @@ -32,14 +33,17 @@
import com.evolveum.midpoint.util.DOMUtil;
import com.evolveum.midpoint.util.DebugUtil;
import com.evolveum.midpoint.util.PrettyPrinter;
import com.evolveum.midpoint.util.QNameUtil;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowAssociationType;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.evolveum.midpoint.common.refinery.CompositeRefinedObjectClassDefinition;
import com.evolveum.midpoint.common.refinery.PropertyLimitations;
import com.evolveum.midpoint.common.refinery.RefinedAttributeDefinition;
import com.evolveum.midpoint.common.refinery.RefinedObjectClassDefinition;
import com.evolveum.midpoint.common.refinery.RefinedResourceSchema;
import com.evolveum.midpoint.model.api.context.SynchronizationPolicyDecision;
import com.evolveum.midpoint.model.common.mapping.Mapping;
import com.evolveum.midpoint.model.common.mapping.PrismValueDeltaSetTripleProducer;
Expand All @@ -56,17 +60,22 @@
import com.evolveum.midpoint.prism.PrismPropertyDefinition;
import com.evolveum.midpoint.prism.PrismPropertyValue;
import com.evolveum.midpoint.prism.PrismReferenceValue;
import com.evolveum.midpoint.prism.PrismValue;
import com.evolveum.midpoint.prism.delta.DeltaSetTriple;
import com.evolveum.midpoint.prism.delta.ItemDelta;
import com.evolveum.midpoint.prism.delta.ObjectDelta;
import com.evolveum.midpoint.prism.delta.PropertyDelta;
import com.evolveum.midpoint.prism.match.MatchingRuleRegistry;
import com.evolveum.midpoint.prism.path.ItemPath;
import com.evolveum.midpoint.provisioning.api.ProvisioningService;
import com.evolveum.midpoint.schema.GetOperationOptions;
import com.evolveum.midpoint.schema.SelectorOptions;
import com.evolveum.midpoint.schema.constants.SchemaConstants;
import com.evolveum.midpoint.schema.processor.ObjectClassComplexTypeDefinition;
import com.evolveum.midpoint.schema.processor.ResourceAttribute;
import com.evolveum.midpoint.schema.processor.ResourceAttributeDefinition;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.schema.util.ShadowUtil;
import com.evolveum.midpoint.util.MiscUtil;
import com.evolveum.midpoint.util.exception.CommunicationException;
import com.evolveum.midpoint.util.exception.ConfigurationException;
Expand Down Expand Up @@ -192,6 +201,8 @@ <F extends ObjectType> void processReconciliationFocus(LensContext<F> context,
}
reconcileProjectionAssociations(projCtx, squeezedAssociations, rOcDef);
}

reconcileMissingAuxiliaryObjectClassAttributes(projCtx);

} catch (RuntimeException e) {
subResult.recordFatalError(e);
Expand Down Expand Up @@ -261,6 +272,99 @@ private void reconcileAuxiliaryObjectClasses(LensProjectionContext projCtx) thro
}
}

/**
* If auxiliary object classes changed, there may still be some attributes that were defined by the aux objectclasses
* that were deleted. If these attributes are still around then delete them. Otherwise the delete of the aux object class
* may fail.
*/
private void reconcileMissingAuxiliaryObjectClassAttributes(LensProjectionContext projCtx) throws SchemaException {
ObjectDelta<ShadowType> delta = projCtx.getDelta();
if (delta == null) {
return;
}
PropertyDelta<QName> auxOcDelta = delta.findPropertyDelta(ShadowType.F_AUXILIARY_OBJECT_CLASS);
if (auxOcDelta == null || auxOcDelta.isEmpty()) {
return;
}
Collection<QName> deletedAuxObjectClassNames = null;
PrismObject<ShadowType> objectOld = projCtx.getObjectOld();
if (auxOcDelta.isReplace()) {
if (objectOld == null) {
return;
}
PrismProperty<QName> auxOcPropOld = objectOld.findProperty(ShadowType.F_AUXILIARY_OBJECT_CLASS);
if (auxOcPropOld == null) {
return;
}
Collection<QName> auxOcsOld = auxOcPropOld.getRealValues();
Set<QName> auxOcsToReplace = PrismPropertyValue.getRealValuesOfCollection(auxOcDelta.getValuesToReplace());
deletedAuxObjectClassNames = new ArrayList<>(auxOcsOld.size());
for (QName auxOcOld: auxOcsOld) {
if (!QNameUtil.contains(auxOcsToReplace, auxOcOld)) {
deletedAuxObjectClassNames.add(auxOcOld);
}
}
} else {
Collection<PrismPropertyValue<QName>> valuesToDelete = auxOcDelta.getValuesToDelete();
if (valuesToDelete == null || valuesToDelete.isEmpty()) {
return;
}
deletedAuxObjectClassNames = PrismPropertyValue.getRealValuesOfCollection(valuesToDelete);
}
LOGGER.trace("Deleted auxiliary object classes: {}", deletedAuxObjectClassNames);
if (deletedAuxObjectClassNames == null || deletedAuxObjectClassNames.isEmpty()) {
return;
}

List<QName> attributesToDelete = new ArrayList<>();
String projHumanReadableName = projCtx.getHumanReadableName();
RefinedResourceSchema refinedResourceSchema = projCtx.getRefinedResourceSchema();
RefinedObjectClassDefinition structuralObjectClassDefinition = projCtx.getStructuralObjectClassDefinition();
Collection<RefinedObjectClassDefinition> auxiliaryObjectClassDefinitions = projCtx.getAuxiliaryObjectClassDefinitions();
for (QName deleteAuxOcName: deletedAuxObjectClassNames) {
ObjectClassComplexTypeDefinition auxOcDef = refinedResourceSchema.findObjectClassDefinition(deleteAuxOcName);
for (ResourceAttributeDefinition auxAttrDef: auxOcDef.getAttributeDefinitions()) {
QName auxAttrName = auxAttrDef.getName();
if (attributesToDelete.contains(auxAttrName)) {
continue;
}
RefinedAttributeDefinition<Object> strucuralAttrDef = structuralObjectClassDefinition.findAttributeDefinition(auxAttrName);
if (strucuralAttrDef == null) {
boolean found = false;
for (RefinedObjectClassDefinition auxiliaryObjectClassDefinition: auxiliaryObjectClassDefinitions) {
if (QNameUtil.contains(deletedAuxObjectClassNames, auxiliaryObjectClassDefinition.getTypeName())) {
continue;
}
RefinedAttributeDefinition<Object> existingAuxAttrDef = auxiliaryObjectClassDefinition.findAttributeDefinition(auxAttrName);
if (existingAuxAttrDef != null) {
found = true;
break;
}
}
if (!found) {
LOGGER.trace("Removing attribute {} because it is in the deleted object class {} and it is not defined by any current object class for {}",
auxAttrName, deleteAuxOcName, projHumanReadableName);
attributesToDelete.add(auxAttrName);
}
}
}
}
LOGGER.trace("Attributes to delete: {}", attributesToDelete);
if (attributesToDelete.isEmpty()) {
return;
}

for (QName attrNameToDelete: attributesToDelete) {
ResourceAttribute<Object> attrToDelete = ShadowUtil.getAttribute(objectOld, attrNameToDelete);
if (attrToDelete == null || attrToDelete.isEmpty()) {
continue;
}
PropertyDelta<Object> attrDelta = attrToDelete.createDelta();
attrDelta.addValuesToDelete(PrismValue.cloneCollection(attrToDelete.getValues()));
projCtx.swallowToSecondaryDelta(attrDelta);
}
}

private void reconcileProjectionAttributes(
LensProjectionContext projCtx,
Map<QName, DeltaSetTriple<ItemValueWithOrigin<PrismPropertyValue<?>,PrismPropertyDefinition<?>>>> squeezedAttributes,
Expand Down

0 comments on commit f53f353

Please sign in to comment.