Skip to content

Commit

Permalink
Identity merge, second step (MID-3460)
Browse files Browse the repository at this point in the history
  • Loading branch information
semancik committed Oct 11, 2016
1 parent 48c2cb2 commit 1336bd7
Show file tree
Hide file tree
Showing 10 changed files with 264 additions and 37 deletions.
Expand Up @@ -428,11 +428,11 @@ public static void assertNoItemDelta(ObjectDelta<?> objectDelta, ItemPath itemPa
assert !objectDelta.hasItemDelta(itemPath) : "Delta for item "+itemPath+" present while not expecting it";
}

public static ContainerDelta<?> assertContainerAdd(ObjectDelta<?> objectDelta, QName name) {
return assertContainerAdd(objectDelta, new ItemPath(name));
public static ContainerDelta<?> assertContainerAddGetContainerDelta(ObjectDelta<?> objectDelta, QName name) {
return assertContainerAddGetContainerDelta(objectDelta, new ItemPath(name));
}

public static ContainerDelta<?> assertContainerAdd(ObjectDelta<?> objectDelta, ItemPath propertyPath) {
public static ContainerDelta<?> assertContainerAddGetContainerDelta(ObjectDelta<?> objectDelta, ItemPath propertyPath) {
ContainerDelta<?> delta = objectDelta.findContainerDelta(propertyPath);
assertNotNull("Container delta for "+propertyPath+" not found",delta);
assert !delta.isEmpty() : "Container delta for "+propertyPath+" is empty";
Expand All @@ -441,11 +441,11 @@ public static ContainerDelta<?> assertContainerAdd(ObjectDelta<?> objectDelta, I
return delta;
}

public static ContainerDelta<?> assertContainerDelete(ObjectDelta<?> objectDelta, QName name) {
return assertContainerDelete(objectDelta, new ItemPath(name));
public static ContainerDelta<?> assertContainerDeleteGetContainerDelta(ObjectDelta<?> objectDelta, QName name) {
return assertContainerDeleteGetContainerDelta(objectDelta, new ItemPath(name));
}

public static ContainerDelta<?> assertContainerDelete(ObjectDelta<?> objectDelta, ItemPath propertyPath) {
public static ContainerDelta<?> assertContainerDeleteGetContainerDelta(ObjectDelta<?> objectDelta, ItemPath propertyPath) {
ContainerDelta<?> delta = objectDelta.findContainerDelta(propertyPath);
assertNotNull("Container delta for "+propertyPath+" not found",delta);
assert !delta.isEmpty() : "Container delta for "+propertyPath+" is empty";
Expand All @@ -454,6 +454,48 @@ public static ContainerDelta<?> assertContainerDelete(ObjectDelta<?> objectDelta
return delta;
}

public static <C extends Containerable> void assertContainerAdd(ObjectDelta<?> objectDelta, QName itemName, C... containerables) {
assertContainerAdd(objectDelta, new ItemPath(itemName), containerables);
}

public static <C extends Containerable> void assertContainerAdd(ObjectDelta<?> objectDelta, ItemPath propertyPath, C... containerables) {
List<PrismContainerValue<C>> expectedCVals = new ArrayList<>();
for (C expectedContainerable: containerables) {
expectedCVals.add(expectedContainerable.asPrismContainerValue());
}
}

public static <C extends Containerable> void assertContainerAdd(ObjectDelta<?> objectDelta, QName itemName,
PrismContainerValue<C>... expectedCVals) {
assertContainerAdd(objectDelta, new ItemPath(itemName), expectedCVals);
}

public static <C extends Containerable> void assertContainerAdd(ObjectDelta<?> objectDelta, ItemPath propertyPath,
PrismContainerValue<C>... expectedCVals) {
ContainerDelta<C> delta = objectDelta.findContainerDelta(propertyPath);
assertNotNull("Container delta for "+propertyPath+" not found",delta);
assert !delta.isEmpty() : "Container delta for "+propertyPath+" is empty";
assert delta.getValuesToAdd() != null : "Container delta for "+propertyPath+" has null values to add";
assert !delta.getValuesToAdd().isEmpty() : "Container delta for "+propertyPath+" has empty values to add";
assertEquivalentContainerValues("Wrong values in container delta for "+propertyPath,
delta.getValuesToAdd(), expectedCVals);
}

private static <C extends Containerable> void assertEquivalentContainerValues(String message, Collection<PrismContainerValue<C>> haveValues,
PrismContainerValue<C>[] expectedCVals) {
List<PrismContainerValue<C>> expectedValues = Arrays.asList(expectedCVals);
Comparator<PrismContainerValue<C>> comparator = new Comparator<PrismContainerValue<C>>() {
@Override
public int compare(PrismContainerValue<C> a, PrismContainerValue<C> b) {
if (a.equivalent(b)) {
return 0;
}
return 1;
}
};
assert MiscUtil.unorderedCollectionEquals(haveValues, expectedValues, comparator) : message;
}

public static <T> void assertOrigin(ObjectDelta<?> objectDelta, final OriginType... expectedOriginTypes) {
assertOrigin(objectDelta, null, expectedOriginTypes);
}
Expand Down
Expand Up @@ -156,7 +156,7 @@ public void testDiffJack() throws SchemaException, SAXException, IOException {
new NameItemPathSegment(USER_DESCRIPTION_QNAME)),
"Assignment II");

ContainerDelta<?> assignment3Delta = PrismAsserts.assertContainerAdd(jackDelta, new ItemPath(USER_ASSIGNMENT_QNAME));
ContainerDelta<?> assignment3Delta = PrismAsserts.assertContainerAddGetContainerDelta(jackDelta, new ItemPath(USER_ASSIGNMENT_QNAME));
PrismContainerValue<?> assignment3DeltaAddValue = assignment3Delta.getValuesToAdd().iterator().next();
assertEquals("Assignment 3 wrong ID", USER_ASSIGNMENT_3_ID, assignment3DeltaAddValue.getId());

Expand Down
@@ -0,0 +1,47 @@
/**
* Copyright (c) 2016 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.evolveum.midpoint.schema.util;

import javax.xml.namespace.QName;

import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.OrgType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.RoleType;

/**
* @author semancik
*
*/
public class FocusTypeUtil {

public static AssignmentType createRoleAssignment(String roleOid) {
return createTargetAssignment(roleOid, RoleType.COMPLEX_TYPE);
}

public static AssignmentType createOrgAssignment(String roleOid) {
return createTargetAssignment(roleOid, OrgType.COMPLEX_TYPE);
}

public static AssignmentType createTargetAssignment(String targetOid, QName type) {
AssignmentType assignmentType = new AssignmentType();
ObjectReferenceType targetRef = new ObjectReferenceType();
targetRef.setOid(targetOid);
targetRef.setType(type);
assignmentType.setTargetRef(targetRef);
return assignmentType;
}
}
Expand Up @@ -346,7 +346,7 @@ public void testTask() throws SchemaException, SAXException, IOException, JAXBEx
Collection<? extends ItemDelta> modifications = diffDelta.getModifications();
assertEquals("Unexpected number of modifications", 1, modifications.size());
// there is only one property in the container. after deleting this property, all container will be deleted, isn't it right?
PrismAsserts.assertContainerDelete(diffDelta, new ItemPath(TaskType.F_EXTENSION));
PrismAsserts.assertContainerDeleteGetContainerDelta(diffDelta, new ItemPath(TaskType.F_EXTENSION));
// PrismAsserts.assertPropertyDelete(diffDelta, new ItemPath(TaskType.F_EXTENSION,
// new QName("http://midpoint.evolveum.com/xml/ns/public/provisioning/liveSync-1.xsd","token")), 480);

Expand Down Expand Up @@ -430,7 +430,7 @@ public void testResource() throws SchemaException, SAXException, IOException, JA
assertEquals("Wrong change type", ChangeType.MODIFY, resourceDelta.getChangeType());
Collection<? extends ItemDelta> modifications = resourceDelta.getModifications();
assertEquals("Unexpected number of modifications", 7, modifications.size());
PrismAsserts.assertContainerDelete(resourceDelta, ResourceType.F_SCHEMA);
PrismAsserts.assertContainerDeleteGetContainerDelta(resourceDelta, ResourceType.F_SCHEMA);
PrismAsserts.assertPropertyReplace(resourceDelta, pathTimeouts("update"), 3);
PrismAsserts.assertPropertyReplace(resourceDelta, pathTimeouts("scriptOnResource"), 4);
PrismAsserts.assertPropertyDelete(resourceDelta,
Expand Down
Expand Up @@ -19,6 +19,7 @@
import static org.testng.AssertJUnit.assertTrue;
import static org.testng.AssertJUnit.assertNotNull;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

Expand Down Expand Up @@ -129,6 +130,28 @@ public static <F extends FocusType> void assertAssignedRole(PrismObject<F> user,
public static <F extends FocusType> void assertNotAssignedRole(PrismObject<F> user, String roleOid) {
assertNotAssigned(user, roleOid, RoleType.COMPLEX_TYPE);
}

public static <F extends FocusType> void assertAssignedRoles(PrismObject<F> user, String... roleOids) {
assertAssignedTargets(user, "roles", RoleType.COMPLEX_TYPE, roleOids);
}

public static <F extends FocusType> void assertAssignedOrgs(PrismObject<F> user, String... orgOids) {
assertAssignedTargets(user, "orgs", OrgType.COMPLEX_TYPE, orgOids);
}

public static <F extends FocusType> void assertAssignedTargets(PrismObject<F> user, String typeDesc, QName type, String... expectedTargetOids) {
F userType = user.asObjectable();
List<String> haveTagetOids = new ArrayList<>();
for (AssignmentType assignmentType: userType.getAssignment()) {
ObjectReferenceType targetRef = assignmentType.getTargetRef();
if (targetRef != null) {
if (type.equals(targetRef.getType())) {
haveTagetOids.add(targetRef.getOid());
}
}
}
PrismAsserts.assertSets("Wrong "+typeDesc+" in "+user, haveTagetOids, expectedTargetOids);
}

public static <F extends FocusType> void assertNotAssignedResource(PrismObject<F> user, String resourceOid) {
F userType = user.asObjectable();
Expand Down
Expand Up @@ -28,14 +28,17 @@
import com.evolveum.midpoint.prism.Item;
import com.evolveum.midpoint.prism.ItemDefinition;
import com.evolveum.midpoint.prism.PrismContainer;
import com.evolveum.midpoint.prism.PrismContainerValue;
import com.evolveum.midpoint.prism.PrismContext;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.PrismObjectDefinition;
import com.evolveum.midpoint.prism.PrismValue;
import com.evolveum.midpoint.prism.Visitable;
import com.evolveum.midpoint.prism.Visitor;
import com.evolveum.midpoint.prism.delta.ItemDelta;
import com.evolveum.midpoint.prism.delta.ObjectDelta;
import com.evolveum.midpoint.prism.path.ItemPath;
import com.evolveum.midpoint.prism.path.ItemPath.CompareResult;
import com.evolveum.midpoint.schema.ObjectDeltaOperation;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.schema.util.MiscSchemaUtil;
Expand Down Expand Up @@ -157,10 +160,11 @@ public void visit(Visitable visitable) {

boolean found = false;
for (ItemPath processedPath: processedPaths) {
// TODO: We might need to check for super-paths here.
// Need to check for super-paths here.
// E.g. if we have already processed metadata, we do not want to process
// metadata/modifyTimestamp
if (processedPath.equivalent(itemPath)) {
CompareResult compareResult = processedPath.compareComplex(itemPath);
if (compareResult == CompareResult.EQUIVALENT || compareResult == CompareResult.SUBPATH) {
found = true;
break;
}
Expand Down Expand Up @@ -225,6 +229,11 @@ private <O extends ObjectType, I extends Item> ItemDelta mergeItem(PrismObject<O
} else {
itemDefinition = itemRight.getDefinition();
}
if (itemDefinition.isOperational()) {
// Skip operational attributes. There are automatically computed,
// we do not want to modify them explicitly.
return null;
}
ItemDelta itemDelta = itemDefinition.createEmptyDelta(itemPath);
MergeStategyType leftStrategy = itemMergeConfig.getLeft();
MergeStategyType rightStrategy = itemMergeConfig.getRight();
Expand Down Expand Up @@ -262,8 +271,24 @@ private <O extends ObjectType, I extends Item> ItemDelta mergeItem(PrismObject<O
return null;
}
} else {
itemDelta.addValuesToAdd(itemRight.getClonedValues());
return itemDelta;
if (itemLeft == null) {
itemDelta.addValuesToAdd(itemRight.getClonedValues());
return itemDelta;
} else {
// We want to add only those values that are not yet there.
// E.g. adding assignments that are there can cause unneccesary churn
List<PrismValue> valuesRight = itemRight.getValues();
for (PrismValue valueRight: valuesRight) {
if (!itemLeft.containsEquivalentValue(valueRight)) {
PrismValue clonedValue = valueRight.clone();
if (clonedValue instanceof PrismContainerValue<?>) {
((PrismContainerValue)clonedValue).setId(null);
}
itemDelta.addValueToAdd(clonedValue);
}
}
return itemDelta;
}
}
}
}
Expand Down

0 comments on commit 1336bd7

Please sign in to comment.