/*
* Copyright (c) 2010-2013 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;
import static com.evolveum.midpoint.prism.util.PrismTestUtil.getPrismContext;
import static org.testng.AssertJUnit.assertTrue;
import static org.testng.AssertJUnit.assertFalse;
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertNotNull;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import javax.xml.bind.JAXBException;
import javax.xml.namespace.QName;
import com.evolveum.midpoint.prism.*;
import com.evolveum.midpoint.prism.delta.builder.DeltaBuilder;
import com.evolveum.midpoint.prism.path.ItemPath;
import com.evolveum.midpoint.prism.polystring.PolyString;
import com.evolveum.midpoint.prism.xml.XmlTypeConverter;
import com.evolveum.midpoint.prism.xnode.RootXNode;
import com.evolveum.midpoint.prism.xnode.XNode;
import com.evolveum.midpoint.util.QNameUtil;
import com.evolveum.midpoint.xml.ns._public.common.api_types_3.ObjectModificationType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.*;
import com.evolveum.prism.xml.ns._public.types_3.ObjectDeltaType;
import org.testng.AssertJUnit;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.Test;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;
import com.evolveum.midpoint.prism.delta.ChangeType;
import com.evolveum.midpoint.prism.delta.DiffUtil;
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.util.PrismAsserts;
import com.evolveum.midpoint.prism.util.PrismTestUtil;
import com.evolveum.midpoint.schema.constants.MidPointConstants;
import com.evolveum.midpoint.schema.constants.SchemaConstants;
import com.evolveum.midpoint.schema.util.SchemaTestConstants;
import com.evolveum.midpoint.util.MiscUtil;
import com.evolveum.midpoint.util.PrettyPrinter;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.prism.xml.ns._public.types_3.ItemDeltaType;
import com.evolveum.prism.xml.ns._public.types_3.ModificationTypeType;
import com.evolveum.prism.xml.ns._public.types_3.PolyStringType;
import com.evolveum.prism.xml.ns._public.types_3.RawType;
/**
* @author semancik
*
*/
public class TestParseDiffPatch {
private static final String TEST_DIR = "src/test/resources/diff/";
@BeforeSuite
public void setup() throws SchemaException, SAXException, IOException {
PrettyPrinter.setDefaultNamespacePrefix(MidPointConstants.NS_MIDPOINT_PUBLIC_PREFIX);
PrismTestUtil.resetPrismContext(MidPointPrismContextFactory.FACTORY);
}
@Test
public void testUserCredentialsDiff() throws Exception {
System.out.println("===[ testUserCredentialsDiff ]===");
PrismObject<UserType> userBefore = PrismTestUtil.parseObject(
new File(TEST_DIR, "user-before.xml"));
userBefore.checkConsistence();
PrismObject<UserType> userAfter = PrismTestUtil.parseObject(
new File(TEST_DIR, "user-after.xml"));
userAfter.checkConsistence();
ObjectDelta<UserType> userDelta = userBefore.diff(userAfter);
System.out.println("DELTA:");
System.out.println(userDelta.debugDump());
userBefore.checkConsistence();
userAfter.checkConsistence();
userDelta.checkConsistence();
userDelta.assertDefinitions();
ItemPath path = new ItemPath(SchemaConstantsGenerated.C_CREDENTIALS,
CredentialsType.F_PASSWORD, PasswordType.F_FAILED_LOGINS);
PrismAsserts.assertPropertyAdd(userDelta, path, 1);
path = new ItemPath(SchemaConstantsGenerated.C_CREDENTIALS,
CredentialsType.F_PASSWORD, PasswordType.F_FAILED_LOGINS);
PropertyDelta propertyDelta = userDelta.findPropertyDelta(path);
assertNotNull("Property delta for "+path+" not found",propertyDelta);
assertEquals(1, propertyDelta.getValuesToAdd().size());
}
//@Test
public void testAssignmentActivationDiff() throws Exception {
System.out.println("===[ testUserCredentialsDiff ]===");
PrismObject<UserType> userBefore = PrismTestUtil.parseObject(
new File(TEST_DIR, "user-before.xml"));
PrismObject<UserType> userAfter = userBefore.clone();
AssignmentType assignmentBefore = new AssignmentType();
ActivationType activation = new ActivationType();
activation.setAdministrativeStatus(ActivationStatusType.DISABLED);
assignmentBefore.setActivation(activation);
userBefore.asObjectable().getAssignment().add(assignmentBefore);
AssignmentType assignmentAfter = new AssignmentType();
activation = new ActivationType();
activation.setAdministrativeStatus(ActivationStatusType.ENABLED);
assignmentAfter.setActivation(activation);
userAfter.asObjectable().getAssignment().add(assignmentAfter);
Collection<? extends ItemDelta> userDelta = assignmentBefore.asPrismContainerValue().diff(assignmentAfter.asPrismContainerValue());
// ObjectDelta<UserType> userDelta = userBefore.diff(userAfter);
System.out.println("DELTA:");
// System.out.println(userDelta.debugDump());
// userBefore.checkConsistence();
// userAfter.checkConsistence();
// userDelta.checkConsistence();
// userDelta.assertDefinitions();
ItemDelta assignmentDelta = userDelta.iterator().next();
System.out.println("Assignment delta: " + assignmentDelta);
System.out.println("Assignment delta: " + assignmentDelta.debugDump());
ItemPath path = new ItemPath(SchemaConstantsGenerated.C_ASSIGNMENT,
AssignmentType.F_ACTIVATION, ActivationType.F_ADMINISTRATIVE_STATUS);
// PrismAsserts.assertPropertyAdd(assignmentDelta, path, 1);
// path = new ItemPath(SchemaConstantsGenerated.C_CREDENTIALS,
// CredentialsType.F_PASSWORD, PasswordType.F_FAILED_LOGINS);
PropertyDelta propertyDelta = ItemDelta.findPropertyDelta(userDelta, path);
assertNotNull("Property delta for "+path+" not found",propertyDelta);
// assertEquals(1, propertyDelta.getValuesToAdd().size());
assignmentAfter = new AssignmentType();
activation = new ActivationType();
activation.setAdministrativeStatus(null);
assignmentAfter.setActivation(activation);
userDelta = assignmentBefore.asPrismContainerValue().diff(assignmentAfter.asPrismContainerValue());
// ObjectDelta<UserType> userDelta = userBefore.diff(userAfter);
System.out.println("DELTA:");
// System.out.println(userDelta.debugDump());
// userBefore.checkConsistence();
// userAfter.checkConsistence();
// userDelta.checkConsistence();
// userDelta.assertDefinitions();
assignmentDelta = userDelta.iterator().next();
System.out.println("Assignment delta: " + assignmentDelta);
System.out.println("Assignment delta: " + assignmentDelta.debugDump());
path = new ItemPath(SchemaConstantsGenerated.C_ASSIGNMENT,
AssignmentType.F_ACTIVATION, ActivationType.F_ADMINISTRATIVE_STATUS);
// PrismAsserts.assertPropertyAdd(assignmentDelta, path, 1);
// path = new ItemPath(SchemaConstantsGenerated.C_CREDENTIALS,
// CredentialsType.F_PASSWORD, PasswordType.F_FAILED_LOGINS);
propertyDelta = ItemDelta.findPropertyDelta(userDelta, path);
userDelta = assignmentAfter.asPrismContainerValue().diff(assignmentBefore.asPrismContainerValue());
// ObjectDelta<UserType> userDelta = userBefore.diff(userAfter);
System.out.println("DELTA:");
// System.out.println(userDelta.debugDump());
// userBefore.checkConsistence();
// userAfter.checkConsistence();
// userDelta.checkConsistence();
// userDelta.assertDefinitions();
assignmentDelta = userDelta.iterator().next();
System.out.println("Assignment delta: " + assignmentDelta);
System.out.println("Assignment delta: " + assignmentDelta.debugDump());
path = new ItemPath(SchemaConstantsGenerated.C_ASSIGNMENT,
AssignmentType.F_ACTIVATION, ActivationType.F_ADMINISTRATIVE_STATUS);
// PrismAsserts.assertPropertyAdd(assignmentDelta, path, 1);
// path = new ItemPath(SchemaConstantsGenerated.C_CREDENTIALS,
// CredentialsType.F_PASSWORD, PasswordType.F_FAILED_LOGINS);
propertyDelta = ItemDelta.findPropertyDelta(userDelta, path);
}
@Test
public void testUser() throws SchemaException, SAXException, IOException, JAXBException {
System.out.println("===[ testUser ]===");
PrismObject<UserType> userBefore = PrismTestUtil.parseObject(new File(TEST_DIR, "user-jack-before.xml"));
userBefore.checkConsistence();
PrismObject<UserType> userAfter = PrismTestUtil.parseObject(new File(TEST_DIR, "user-jack-after.xml"));
userAfter.checkConsistence();
// sanity
assertFalse("Equals does not work", userBefore.equals(userAfter));
// WHEN
ObjectDelta<UserType> userDelta = userBefore.diff(userAfter);
// THEN
System.out.println("DELTA:");
System.out.println(userDelta.debugDump());
userBefore.checkConsistence();
userAfter.checkConsistence();
userDelta.checkConsistence();
userDelta.assertDefinitions();
assertEquals("Wrong delta OID", userBefore.getOid(), userDelta.getOid());
assertEquals("Wrong change type", ChangeType.MODIFY, userDelta.getChangeType());
Collection<? extends ItemDelta> modifications = userDelta.getModifications();
assertEquals("Unexpected number of modifications", 3, modifications.size());
PrismAsserts.assertPropertyReplace(userDelta, new QName(SchemaConstants.NS_C,"fullName"),
new PolyString("Cpt. Jack Sparrow", "cpt jack sparrow"));
PrismAsserts.assertPropertyAdd(userDelta, new QName(SchemaConstants.NS_C,"honorificPrefix"),
new PolyString("Cpt.", "cpt"));
PrismAsserts.assertPropertyAdd(userDelta, new QName(SchemaConstants.NS_C,"locality"),
new PolyString("Tortuga", "tortuga"));
ObjectModificationType objectModificationType = DeltaConvertor.toObjectModificationType(userDelta);
System.out.println("Modification XML:");
System.out.println(PrismTestUtil.serializeAnyDataWrapped(objectModificationType));
assertEquals("Wrong delta OID", userBefore.getOid(), objectModificationType.getOid());
List<ItemDeltaType> propertyModifications = objectModificationType.getItemDelta();
assertEquals("Unexpected number of modifications", 3, propertyModifications.size());
PolyStringType polyString = new PolyStringType();
polyString.setOrig("Cpt. Jack Sparrow");
polyString.setNorm("cpt jack sparrow");
assertXmlPolyMod(objectModificationType, new QName(SchemaConstants.NS_C,"fullName"), ModificationTypeType.REPLACE, polyString);
polyString = new PolyStringType();
polyString.setOrig("Cpt.");
polyString.setNorm("cpt");
assertXmlPolyMod(objectModificationType, new QName(SchemaConstants.NS_C,"honorificPrefix"), ModificationTypeType.ADD, polyString);
polyString = new PolyStringType();
polyString.setOrig("Tortuga");
polyString.setNorm("tortuga");
assertXmlPolyMod(objectModificationType, new QName(SchemaConstants.NS_C,"locality"), ModificationTypeType.ADD, polyString);
userBefore.checkConsistence();
userAfter.checkConsistence();
userDelta.checkConsistence();
// ROUNDTRIP
userDelta.applyTo(userBefore);
userBefore.checkConsistence();
userAfter.checkConsistence();
userDelta.checkConsistence();
//assertEquals("Round trip failed", userAfter, userBefore);
assertTrue("Not equivalent",userBefore.equivalent(userAfter));
ObjectDelta<UserType> roundTripDelta = DiffUtil.diff(userBefore, userAfter);
System.out.println("roundtrip DELTA:");
System.out.println(roundTripDelta.debugDump());
assertTrue("Roundtrip delta is not empty",roundTripDelta.isEmpty());
}
@Test
public void testUserReal() throws SchemaException, SAXException, IOException, JAXBException {
System.out.println("===[ testUserReal ]===");
String userBeforeXml = MiscUtil.readFile(new File(TEST_DIR, "user-real-before.xml"));
String userAfterXml = MiscUtil.readFile(new File(TEST_DIR, "user-real-after.xml"));
// WHEN
ObjectDelta<UserType> userDelta = DiffUtil.diff(userBeforeXml, userAfterXml, UserType.class, getPrismContext());
// THEN
System.out.println("DELTA:");
System.out.println(userDelta.debugDump());
userDelta.checkConsistence();
assertEquals("Wrong delta OID", "2f9b9299-6f45-498f-bc8e-8d17c6b93b20", userDelta.getOid());
assertEquals("Wrong change type", ChangeType.MODIFY, userDelta.getChangeType());
Collection<? extends ItemDelta> modifications = userDelta.getModifications();
assertEquals("Unexpected number of modifications", 4, modifications.size());
PrismAsserts.assertPropertyReplace(userDelta, new QName(SchemaConstants.NS_C,"emailAddress"), "jack@blackpearl.com");
PrismAsserts.assertPropertyReplace(userDelta, new QName(SchemaConstants.NS_C,"locality"),
new PolyString("World's End", "worlds end"));
PrismAsserts.assertPropertyReplace(userDelta, SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS, ActivationStatusType.DISABLED);
PrismAsserts.assertPropertyAdd(userDelta, new QName(SchemaConstants.NS_C,"organizationalUnit"),
new PolyString("Brethren of the Coast", "brethren of the coast"));
}
@Test
public void testAddDelta() throws SchemaException, SAXException, IOException {
System.out.println("===[ testAddDelta ]===");
// WHEN
ObjectDelta<UserType> userDelta = DiffUtil.diff(null,new File(TEST_DIR, "user-jack-after.xml"), UserType.class, getPrismContext());
//THEN
System.out.println("DELTA:");
System.out.println(userDelta.debugDump());
userDelta.checkConsistence();
assertEquals("Wrong delta OID", "deadbeef-c001-f00d-1111-222233330001", userDelta.getOid());
assertEquals("Wrong change type", ChangeType.ADD, userDelta.getChangeType());
// TODO
}
@Test
public void testTask() throws SchemaException, SAXException, IOException, JAXBException {
System.out.println("===[ testTask ]===");
// WHEN
ObjectDelta<TaskType> diffDelta = DiffUtil.diff(new File(TEST_DIR, "task-before.xml"),
new File(TEST_DIR, "task-after.xml"), TaskType.class, getPrismContext());
// THEN
System.out.println("DELTA:");
System.out.println(diffDelta.debugDump());
diffDelta.checkConsistence();
assertEquals("Wrong delta OID", "91919191-76e0-59e2-86d6-3d4f02d3ffff", diffDelta.getOid());
assertEquals("Wrong change type", ChangeType.MODIFY, diffDelta.getChangeType());
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.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);
// Convert to XML form. This should include xsi:type to pass the type information
ObjectModificationType objectModificationType = DeltaConvertor.toObjectModificationType(diffDelta);
System.out.println("Modification XML:");
System.out.println(PrismTestUtil.serializeAnyDataWrapped(objectModificationType));
// Check for xsi:type
// Element tokenElement = (Element) objectModificationType.getModification().get(0).getValue().getAny().get(0);
// assertTrue("No xsi:type in token",DOMUtil.hasXsiType(tokenElement));
// parse back delta
// ObjectDelta<TaskType> patchDelta = DeltaConvertor.createObjectDelta(objectModificationType,
// TaskType.class, PrismTestUtil.getPrismContext());
// patchDelta.checkConsistence();
// ROUNDTRIP
PrismObject<TaskType> taskPatch = PrismTestUtil.parseObject(new File(TEST_DIR, "task-before.xml"));
taskPatch.checkConsistence();
// patch
diffDelta.applyTo(taskPatch);
System.out.println("Task after roundtrip patching");
System.out.println(taskPatch.debugDump());
diffDelta.checkConsistence();
taskPatch.checkConsistence();
PrismObject<TaskType> taskAfter = PrismTestUtil.parseObject(new File(TEST_DIR, "task-after.xml"));
taskAfter.checkConsistence();
assertTrue("Not equivalent",taskPatch.equivalent(taskAfter));
diffDelta.checkConsistence();
taskPatch.checkConsistence();
taskAfter.checkConsistence();
ObjectDelta<TaskType> roundTripDelta = DiffUtil.diff(taskPatch, taskAfter);
System.out.println("roundtrip DELTA:");
System.out.println(roundTripDelta.debugDump());
assertTrue("Roundtrip delta is not empty",roundTripDelta.isEmpty());
roundTripDelta.checkConsistence();
diffDelta.checkConsistence();
taskPatch.checkConsistence();
taskAfter.checkConsistence();
}
@Test
public void testResource() throws SchemaException, SAXException, IOException, JAXBException {
System.out.println("===[ testResource ]===");
PrismObject<ResourceType> resourceBefore = PrismTestUtil.parseObject(new File(TEST_DIR, "resource-before.xml"));
PrismObject<ResourceType> resourceAfter = PrismTestUtil.parseObject(new File(TEST_DIR, "resource-after.xml"));
resourceBefore.checkConsistence();
resourceAfter.checkConsistence();
// sanity
assertFalse("Equals does not work", resourceBefore.equals(resourceAfter));
// WHEN
ObjectDelta<ResourceType> resourceDelta = resourceBefore.diff(resourceAfter);
// THEN
System.out.println("DELTA:");
System.out.println(resourceDelta.debugDump());
resourceDelta.checkConsistence();
resourceDelta.assertDefinitions(true);
resourceBefore.checkConsistence();
resourceAfter.checkConsistence();
assertEquals("Wrong delta OID", "ef2bc95b-76e0-59e2-86d6-3d4f02d3ffff", resourceDelta.getOid());
assertEquals("Wrong change type", ChangeType.MODIFY, resourceDelta.getChangeType());
Collection<? extends ItemDelta> modifications = resourceDelta.getModifications();
assertEquals("Unexpected number of modifications", 7, modifications.size());
PrismAsserts.assertContainerDeleteGetContainerDelta(resourceDelta, ResourceType.F_SCHEMA);
PrismAsserts.assertPropertyReplace(resourceDelta, pathTimeouts("update"), 3);
PrismAsserts.assertPropertyReplace(resourceDelta, pathTimeouts("scriptOnResource"), 4);
PrismAsserts.assertPropertyDelete(resourceDelta,
new ItemPath(ResourceType.F_CONNECTOR_CONFIGURATION, new QName(SchemaTestConstants.NS_ICFC, "producerBufferSize")),
100);
PrismAsserts.assertPropertyReplaceSimple(resourceDelta, ResourceType.F_SYNCHRONIZATION);
// Configuration properties changes
assertConfigurationPropertyChange(resourceDelta, "principal");
assertConfigurationPropertyChange(resourceDelta, "credentials");
resourceDelta.checkConsistence();
resourceBefore.checkConsistence();
resourceAfter.checkConsistence();
}
private void assertConfigurationPropertyChange(ObjectDelta<ResourceType> resourceDelta, String propName) {
resourceDelta.checkConsistence();
PropertyDelta propertyDelta = resourceDelta.findPropertyDelta(pathConfigProperties(propName));
assertNotNull("No delta for configuration property "+propName, propertyDelta);
// TODO
resourceDelta.checkConsistence();
}
private ItemPath pathConfigProperties(String propName) {
return new ItemPath(ResourceType.F_CONNECTOR_CONFIGURATION, SchemaTestConstants.ICFC_CONFIGURATION_PROPERTIES,
new QName(SchemaTestConstants.NS_ICFC_LDAP, propName));
}
private ItemPath pathTimeouts(String last) {
return new ItemPath(ResourceType.F_CONNECTOR_CONFIGURATION, new QName(SchemaTestConstants.NS_ICFC, "timeouts"),
new QName(SchemaTestConstants.NS_ICFC, last));
}
@Test
public void testResourceRoundTrip() throws SchemaException, SAXException, IOException, JAXBException {
System.out.println("===[ testResourceRoundTrip ]===");
PrismObject<ResourceType> resourceBefore = PrismTestUtil.parseObject(new File(TEST_DIR, "resource-before.xml"));
PrismObject<ResourceType> resourceAfter = PrismTestUtil.parseObject(new File(TEST_DIR, "resource-after.xml"));
resourceBefore.checkConsistence();
resourceAfter.checkConsistence();
// sanity
assertFalse("Equals does not work", resourceBefore.equals(resourceAfter));
// WHEN
ObjectDelta<ResourceType> resourceDelta = resourceBefore.diff(resourceAfter);
// THEN
System.out.println("DELTA:");
System.out.println(resourceDelta.debugDump());
resourceDelta.checkConsistence();
resourceDelta.assertDefinitions(true);
resourceBefore.checkConsistence();
resourceAfter.checkConsistence();
// ROUNDTRIP
resourceDelta.applyTo(resourceBefore);
System.out.println("Resource after roundtrip:");
System.out.println(resourceBefore.debugDump());
resourceDelta.checkConsistence();
resourceDelta.assertDefinitions(true);
resourceBefore.checkConsistence();
resourceAfter.checkConsistence();
ObjectDelta<ResourceType> roundTripDelta1 = resourceBefore.diff(resourceAfter);
System.out.println("roundtrip DELTA 1:");
System.out.println(roundTripDelta1.debugDump());
assertTrue("Resource roundtrip 1 failed", roundTripDelta1.isEmpty());
roundTripDelta1.checkConsistence();
roundTripDelta1.assertDefinitions(true);
resourceDelta.checkConsistence();
resourceBefore.checkConsistence();
resourceAfter.checkConsistence();
ObjectDelta<ResourceType> roundTripDelta2 = resourceAfter.diff(resourceBefore);
System.out.println("roundtrip DELTA 2:");
System.out.println(roundTripDelta2.debugDump());
assertTrue("Resource roundtrip 2 failed", roundTripDelta2.isEmpty());
roundTripDelta2.checkConsistence();
roundTripDelta2.assertDefinitions(true);
resourceDelta.checkConsistence();
resourceBefore.checkConsistence();
resourceAfter.checkConsistence();
PrismAsserts.assertEquivalent("Resources after roundtrip not equivalent", resourceAfter, resourceBefore);
resourceDelta.checkConsistence();
resourceDelta.assertDefinitions(true);
resourceBefore.checkConsistence();
resourceAfter.checkConsistence();
}
@Test
public void testResourceNsChange() throws SchemaException, SAXException, IOException, JAXBException {
System.out.println("===[ testResourceNsChange ]===");
PrismObject<ResourceType> resourceBefore = PrismTestUtil.parseObject(new File(TEST_DIR, "resource-before.xml"));
PrismObject<ResourceType> resourceAfter = PrismTestUtil.parseObject(new File(TEST_DIR, "resource-after-ns-change.xml"));
resourceBefore.checkConsistence();
resourceAfter.checkConsistence();
// WHEN
ObjectDelta<ResourceType> resourceDelta = resourceBefore.diff(resourceAfter);
// THEN
System.out.println("DELTA:");
System.out.println(resourceDelta.debugDump());
resourceDelta.checkConsistence();
resourceDelta.assertDefinitions(true);
resourceBefore.checkConsistence();
resourceAfter.checkConsistence();
if (!resourceDelta.isEmpty()) {
AssertJUnit.fail("The delta is not empty; it is "+resourceDelta);
}
// "post" sanity
assertTrue("equals does not work", resourceBefore.equals(resourceAfter));
assertTrue("equivalent does not work", resourceBefore.equivalent(resourceAfter));
}
@Test
public void testResourceNsChangeLiteral() throws SchemaException, SAXException, IOException, JAXBException {
System.out.println("===[ testResourceNsChangeLiteral ]===");
PrismObject<ResourceType> resourceBefore = PrismTestUtil.parseObject(new File(TEST_DIR, "resource-before.xml"));
PrismObject<ResourceType> resourceAfter = PrismTestUtil.parseObject(new File(TEST_DIR, "resource-after-ns-change.xml"));
resourceBefore.checkConsistence();
resourceAfter.checkConsistence();
// WHEN
ObjectDelta<ResourceType> resourceDelta = resourceBefore.diff(resourceAfter, true, true);
// THEN
System.out.println("DELTA:");
System.out.println(resourceDelta.debugDump());
resourceDelta.checkConsistence();
resourceDelta.assertDefinitions(true);
resourceBefore.checkConsistence();
resourceAfter.checkConsistence();
assertFalse("The delta is empty", resourceDelta.isEmpty());
}
@Test
public void testResourceNsFixUndeclaredPrefixes() throws SchemaException, SAXException, IOException, JAXBException {
System.out.println("===[ testResourceNsFixUndeclaredPrefixes ]===");
boolean orig = QNameUtil.isTolerateUndeclaredPrefixes();
try {
QNameUtil.setTolerateUndeclaredPrefixes(true);
PrismObject<ResourceType> resourceBroken = PrismTestUtil.parseObject(new File(TEST_DIR, "resource2-broken.xml"));
PrismObject<ResourceType> resourceFixed = PrismTestUtil.parseObject(new File(TEST_DIR, "resource2-fixed.xml"));
resourceBroken.checkConsistence();
resourceFixed.checkConsistence();
// WHEN
String xmlBroken = getPrismContext().serializeObjectToString(resourceBroken, PrismContext.LANG_XML);
ObjectDelta<ResourceType> resourceDelta = resourceBroken.diff(resourceFixed, true, true);
// THEN
System.out.println("DELTA:");
System.out.println(resourceDelta.debugDump());
System.out.println("BROKEN RESOURCE:");
System.out.println(xmlBroken);
assertTrue("no __UNDECLARED__ flag in broken resource", xmlBroken.contains("__UNDECLARED__"));
resourceDelta.checkConsistence();
resourceDelta.assertDefinitions(true);
resourceBroken.checkConsistence();
resourceFixed.checkConsistence();
assertFalse("The delta is empty", resourceDelta.isEmpty());
PrismObject<ResourceType> resourceUpdated = resourceBroken.clone();
resourceDelta.applyTo(resourceUpdated);
String xmlUpdated = getPrismContext().serializeObjectToString(resourceUpdated, PrismContext.LANG_XML);
System.out.println("UPDATED RESOURCE:");
System.out.println(xmlUpdated);
assertFalse("__UNDECLARED__ flag in updated resource", xmlUpdated.contains("__UNDECLARED__"));
QNameUtil.setTolerateUndeclaredPrefixes(false);
getPrismContext().parseObject(xmlUpdated); //should be without exceptions
} finally {
QNameUtil.setTolerateUndeclaredPrefixes(orig);
}
}
/**
* This test illustrates MID-2174.
*
* We take a shadow having objectChange set.
* We delete it via asObjectable().setObjectChange(null).
* Then we compute the delta via diff.
* All these operations are done on a shadow that contains PARSED values in objectChange property.
*
* The problem of MID-2174 is that (in reality) we then try to apply the delta to the shadow as stored in repository,
* i.e. to shadow with RAW values in objectChange property.
*
* MidPoint uses an approximation there - it compares XNode serializations of values. Sometimes they match,
* sometimes they do not. In this particular case they fail to match on serialization of c:ObjectReferenceType,
* because BeanMarshaller is used, and ObjectReferenceType.getFilter() returns empty filter instead of null.
* This could be fixed; however, it would not help much, because it is almost sure that other similar problems
* would sooner or later emerge.
*/
@Test(enabled = false)
public void testShadowObjectChange() throws SchemaException, SAXException, IOException, JAXBException {
System.out.println("===[ testShadowObjectChange ]===");
// WHEN
PrismContext prismContext = getPrismContext();
PrismObject<ShadowType> oldObject = getParsedShadowBefore(prismContext);
PrismObject<ShadowType> newObject = getShadowAfter(oldObject);
ObjectDelta<ShadowType> diffDelta = DiffUtil.diff(oldObject, newObject);
// THEN
System.out.println("DELTA:");
System.out.println(diffDelta.debugDump());
diffDelta.checkConsistence();
assertEquals("Wrong delta OID", "19a27a9d-c7f0-4e41-bcbf-5fa9fc229b10", diffDelta.getOid());
assertEquals("Wrong change type", ChangeType.MODIFY, diffDelta.getChangeType());
// ... (not important now) ...
// ROUNDTRIP
// without resolving RawTypes!
PrismObject<ShadowType> shadow = getRawShadowBefore(prismContext);
shadow.checkConsistence();
PrismObject<ShadowType> shadowAfter = getShadowAfter(shadow);
shadowAfter.checkConsistence();
// patch
diffDelta.applyTo(shadow);
System.out.println("Shadow after roundtrip patching");
System.out.println(shadow.debugDump());
diffDelta.checkConsistence();
shadow.checkConsistence();
assertTrue("Not equivalent", shadow.equivalent(shadowAfter));
diffDelta.checkConsistence();
shadow.checkConsistence();
shadowAfter.checkConsistence();
ObjectDelta<ShadowType> roundTripDelta = DiffUtil.diff(shadow, shadowAfter);
System.out.println("roundtrip DELTA:");
System.out.println(roundTripDelta.debugDump());
assertTrue("Roundtrip delta is not empty", roundTripDelta.isEmpty());
roundTripDelta.checkConsistence();
diffDelta.checkConsistence();
shadow.checkConsistence();
shadowAfter.checkConsistence();
}
protected PrismObject<ShadowType> getShadowAfter(PrismObject<ShadowType> oldObject) {
PrismObject<ShadowType> newObject = oldObject.clone();
newObject.asObjectable().setObjectChange(null);
return newObject;
}
protected PrismObject<ShadowType> getParsedShadowBefore(PrismContext prismContext) throws SchemaException, IOException {
PrismObject<ShadowType> oldObject = getRawShadowBefore(prismContext);
// resolve rawtypes
ObjectDeltaType objectChange = oldObject.asObjectable().getObjectChange();
for (ItemDeltaType itemDeltaType : objectChange.getItemDelta()) {
for (RawType rawType : itemDeltaType.getValue()) {
rawType.getParsedItem(
new PrismPropertyDefinitionImpl(itemDeltaType.getPath().getItemPath().lastNamed().getName(),
rawType.getXnode().getTypeQName(),
prismContext));
}
}
return oldObject;
}
protected PrismObject<ShadowType> getRawShadowBefore(PrismContext prismContext) throws SchemaException, IOException {
PrismObject<ShadowType> oldObject = prismContext.parseObject(new File(TEST_DIR, "shadow-before.xml"));
return oldObject;
}
private void assertXmlPolyMod(ObjectModificationType objectModificationType, QName propertyName,
ModificationTypeType modType, PolyStringType... expectedValues) throws SchemaException {
//FIXME:
for (ItemDeltaType mod : objectModificationType.getItemDelta()) {
if (!propertyName.equals(mod.getPath().getItemPath().last())) {
continue;
}
assertEquals(modType, mod.getModificationType());
for (RawType val : mod.getValue()){
assertModificationPolyStringValue(val, expectedValues);
}
}
}
private void assertModificationPolyStringValue(RawType value, PolyStringType... expectedValues) throws SchemaException {
XNode xnode = value.serializeToXNode();
assertFalse(xnode.isEmpty());
PolyStringType valueAsPoly = value.getPrismContext().parserFor(new RootXNode(new QName("dummy"), xnode)).parseRealValue(PolyStringType.class);
boolean found = false;
for (PolyStringType expectedValue: expectedValues) {
if (expectedValue.getOrig().equals(valueAsPoly.getOrig()) && expectedValue.getNorm().equals(valueAsPoly.getNorm())) {
found = true;
}
}
assertTrue(found);
}
private boolean equal(String value, Element element) {
if (value == null && element == null) {
return true;
}
if ((value == null && element != null) || (value != null && element == null)) {
return false;
}
return value.equals(element.getTextContent());
}
// private void assertXmlMod(ObjectModificationType objectModificationType, QName propertyName,
// ModificationTypeType modType, String... expectedValues) {
// for (ItemDeltaType mod: objectModificationType.getItemDelta()) {
// assertEquals(modType, mod.getModificationType());
// for (RawType val : mod.getValue()){
// List<Object> elements = val.getContent();
// assertFalse(elements.isEmpty());
// Object first = elements.get(0);
//// QName elementQName = JAXBUtil.getElementQName(first);
// if (propertyName.equals(mod.getPath().getItemPath().last())) {
//
// assertEquals(expectedValues.length, elements.size());
// for (Object element: elements) {
// boolean found = false;
// for (String expectedValue: expectedValues) {
// Element domElement = (Element)element;
// if (expectedValue.equals(domElement.getTextContent())) {
// found = true;
// }
// }
// assertTrue(found);
// }
// }
// }
// }
// }
// this is a simple test of applying delta (don't know where to put it)
// MID-3828
@Test
public void testCampaign() throws SchemaException, SAXException, IOException, JAXBException {
System.out.println("===[ testCampaign ]===");
PrismObject<AccessCertificationCampaignType> campaign = PrismTestUtil.parseObject(new File(TEST_DIR, "campaign-1.xml"));
campaign.checkConsistence();
assertEquals("Wrong # of triggers", 2, campaign.asObjectable().getTrigger().size());
// WHEN
TriggerType triggerToDelete = new TriggerType(getPrismContext());
triggerToDelete.setId(3L); // non-existing ID
triggerToDelete.setTimestamp(XmlTypeConverter.createXMLGregorianCalendar("2017-03-17T23:43:49.705+01:00"));
triggerToDelete.setHandlerUri("http://midpoint.evolveum.com/xml/ns/public/certification/trigger/close-stage/handler-3");
@SuppressWarnings({"unchecked", "raw"})
ObjectDelta<AccessCertificationCampaignType> delta = (ObjectDelta<AccessCertificationCampaignType>)
DeltaBuilder.deltaFor(AccessCertificationCampaignType.class, getPrismContext())
.item(AccessCertificationCampaignType.F_TRIGGER).delete(triggerToDelete)
.asObjectDelta(campaign.getOid());
// THEN
delta.applyTo(campaign);
System.out.println("Campaign after:\n" + campaign.debugDump());
assertEquals("Wrong # of triggers", 2, campaign.asObjectable().getTrigger().size());
}
}