com.evolveum.midpoint.test.IntegrationTestTools.java Source code

Java tutorial

Introduction

Here is the source code for com.evolveum.midpoint.test.IntegrationTestTools.java

Source

/*
 * Copyright (c) 2010-2015 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.test;

import com.evolveum.icf.dummy.resource.DummyGroup;
import com.evolveum.icf.dummy.resource.ScriptHistoryEntry;
import com.evolveum.midpoint.common.refinery.RefinedResourceSchema;
import com.evolveum.midpoint.prism.ConsistencyCheckScope;
import com.evolveum.midpoint.prism.PrismContainer;
import com.evolveum.midpoint.prism.PrismContainerDefinition;
import com.evolveum.midpoint.prism.PrismContext;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.PrismProperty;
import com.evolveum.midpoint.prism.PrismPropertyDefinition;
import com.evolveum.midpoint.prism.PrismPropertyValue;
import com.evolveum.midpoint.prism.PrismReferenceDefinition;
import com.evolveum.midpoint.prism.delta.ObjectDelta;
import com.evolveum.midpoint.prism.match.MatchingRule;
import com.evolveum.midpoint.prism.path.ItemPath;
import com.evolveum.midpoint.prism.polystring.PolyString;
import com.evolveum.midpoint.prism.query.AndFilter;
import com.evolveum.midpoint.prism.query.EqualFilter;
import com.evolveum.midpoint.prism.query.ObjectFilter;
import com.evolveum.midpoint.prism.query.ObjectQuery;
import com.evolveum.midpoint.prism.query.RefFilter;
import com.evolveum.midpoint.prism.util.PrismAsserts;
import com.evolveum.midpoint.prism.util.PrismTestUtil;
import com.evolveum.midpoint.prism.util.PrismUtil;
import com.evolveum.midpoint.repo.api.RepositoryService;
import com.evolveum.midpoint.repo.cache.RepositoryCache;
import com.evolveum.midpoint.schema.SearchResultList;
import com.evolveum.midpoint.schema.constants.ConnectorTestOperation;
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.ResourceAttributeContainer;
import com.evolveum.midpoint.schema.processor.ResourceAttributeContainerDefinition;
import com.evolveum.midpoint.schema.processor.ResourceAttributeDefinition;
import com.evolveum.midpoint.schema.processor.ResourceSchema;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.schema.result.OperationResultStatus;
import com.evolveum.midpoint.schema.util.ObjectTypeUtil;
import com.evolveum.midpoint.schema.util.ShadowUtil;
import com.evolveum.midpoint.schema.util.ResourceTypeUtil;
import com.evolveum.midpoint.schema.util.SchemaDebugUtil;
import com.evolveum.midpoint.schema.util.SchemaTestConstants;
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.test.util.TestUtil;
import com.evolveum.midpoint.util.DOMUtil;
import com.evolveum.midpoint.util.DebugDumpable;
import com.evolveum.midpoint.util.DebugUtil;
import com.evolveum.midpoint.util.exception.*;
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;
import com.evolveum.midpoint.xml.ns._public.common.common_3.*;
import com.evolveum.prism.xml.ns._public.types_3.PolyStringType;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.opends.server.types.Entry;
import org.opends.server.types.SearchResultEntry;
import org.testng.AssertJUnit;
import org.w3c.dom.Element;

import javax.xml.namespace.QName;

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

import static org.testng.AssertJUnit.*;

/**
 * @author Radovan Semancik
 *
 */
public class IntegrationTestTools {

    public static final String DUMMY_CONNECTOR_TYPE = "com.evolveum.icf.dummy.connector.DummyConnector";
    public static final String DBTABLE_CONNECTOR_TYPE = "org.identityconnectors.databasetable.DatabaseTableConnector";

    public static final String NS_RESOURCE_DUMMY_CONFIGURATION = "http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/bundle/com.evolveum.icf.dummy/com.evolveum.icf.dummy.connector.DummyConnector";
    public static final QName RESOURCE_DUMMY_CONFIGURATION_USELESS_STRING_ELEMENT_NAME = new QName(
            NS_RESOURCE_DUMMY_CONFIGURATION, "uselessString");

    // public and not final - to allow changing it in tests
    public static Trace LOGGER = TraceManager.getTrace(IntegrationTestTools.class);

    private static final String OBJECT_TITLE_OUT_PREFIX = "\n*** ";
    private static final String OBJECT_TITLE_LOG_PREFIX = "*** ";
    private static final String LOG_MESSAGE_PREFIX = "";
    private static final String OBJECT_LIST_SEPARATOR = "---";
    private static final long WAIT_FOR_LOOP_SLEEP_MILIS = 500;

    public static void assertTestResourceSuccess(OperationResult testResult, ConnectorTestOperation operation) {
        OperationResult opResult = testResult.findSubresult(operation.getOperation());
        assertNotNull("No result for " + operation, opResult);
        TestUtil.assertSuccess("Test resource failed (result): " + operation, opResult, 1);
    }

    public static void assertTestResourceFailure(OperationResult testResult, ConnectorTestOperation operation) {
        OperationResult opResult = testResult.findSubresult(operation.getOperation());
        assertNotNull("No result for " + operation, opResult);
        TestUtil.assertFailure("Test resource succeeded while expected failure (result): " + operation, opResult);
    }

    public static void assertTestResourceNotApplicable(OperationResult testResult,
            ConnectorTestOperation operation) {
        OperationResult opResult = testResult.findSubresult(operation.getOperation());
        assertNotNull("No result for " + operation, opResult);
        assertEquals(
                "Test resource status is not 'not applicable', it is " + opResult.getStatus() + ": " + operation,
                OperationResultStatus.NOT_APPLICABLE, opResult.getStatus());
    }

    public static void assertNotEmpty(String message, String s) {
        assertNotNull(message, s);
        assertFalse(message, s.isEmpty());
    }

    public static void assertNotEmpty(PolyString ps) {
        assertNotNull(ps);
        assertFalse(ps.isEmpty());
    }

    public static void assertNotEmpty(PolyStringType ps) {
        assertNotNull(ps);
        assertFalse(PrismUtil.isEmpty(ps));
    }

    public static void assertNotEmpty(String message, PolyString ps) {
        assertNotNull(message, ps);
        assertFalse(message, ps.isEmpty());
    }

    public static void assertNotEmpty(String message, PolyStringType ps) {
        assertNotNull(message, ps);
        assertFalse(message, PrismUtil.isEmpty(ps));
    }

    public static void assertNotEmpty(String s) {
        assertNotNull(s);
        assertFalse(s.isEmpty());
    }

    public static void assertNotEmpty(String message, QName qname) {
        assertNotNull(message, qname);
        assertNotEmpty(message, qname.getNamespaceURI());
        assertNotEmpty(message, qname.getLocalPart());
    }

    public static void assertNotEmpty(QName qname) {
        assertNotNull(qname);
        assertNotEmpty(qname.getNamespaceURI());
        assertNotEmpty(qname.getLocalPart());
    }

    public static <T> void assertAttribute(ShadowType shadow, ResourceType resource, String name,
            T... expectedValues) {
        assertAttribute("Wrong attribute " + name + " in " + shadow, shadow,
                new QName(ResourceTypeUtil.getResourceNamespace(resource), name), expectedValues);
    }

    public static <T> void assertAttribute(PrismObject<? extends ShadowType> shadow, ResourceType resource,
            String name, T... expectedValues) {
        assertAttribute("Wrong attribute " + name + " in " + shadow, shadow,
                new QName(ResourceTypeUtil.getResourceNamespace(resource), name), expectedValues);
    }

    public static <T> void assertAttribute(ShadowType shadowType, QName name, T... expectedValues) {
        assertAttribute(shadowType.asPrismObject(), name, expectedValues);
    }

    public static <T> void assertAttribute(PrismObject<? extends ShadowType> shadow, QName name,
            T... expectedValues) {
        Collection<T> values = getAttributeValues(shadow, name);
        assertEqualsCollection("Wrong value for attribute " + name + " in " + shadow, expectedValues, values);
    }

    public static <T> void assertAttribute(String message, ShadowType repoShadow, QName name, T... expectedValues) {
        Collection<T> values = getAttributeValues(repoShadow, name);
        assertEqualsCollection(message, expectedValues, values);
    }

    public static <T> void assertAttribute(String message, PrismObject<? extends ShadowType> repoShadow, QName name,
            T... expectedValues) {
        Collection<T> values = getAttributeValues(repoShadow, name);
        assertEqualsCollection(message, expectedValues, values);
    }

    public static <T> void assertNoAttribute(PrismObject<? extends ShadowType> shadow, QName name) {
        assertNull("Found attribute " + name + " in " + shadow + " while not expecting it",
                getAttributeValues(shadow, name));
    }

    public static <T> void assertEqualsCollection(String message, Collection<T> expectedValues,
            Collection<T> actualValues) {
        if (expectedValues == null && actualValues == null) {
            return;
        }
        assert !(expectedValues == null && actualValues != null) : "Expecting null values but got " + actualValues;
        assert actualValues != null : message + ": Expecting " + expectedValues + " but got null";
        assertEquals(message + ": Wrong number of values in " + actualValues, expectedValues.size(),
                actualValues.size());
        for (T actualValue : actualValues) {
            boolean found = false;
            for (T value : expectedValues) {
                if (value.equals(actualValue)) {
                    found = true;
                }
            }
            if (!found) {
                fail(message + ": Unexpected value " + actualValue + "; expected " + expectedValues + "; has "
                        + actualValues);
            }
        }
    }

    public static <T> void assertEqualsCollection(String message, Collection<T> expectedValues, T[] actualValues) {
        assertEqualsCollection(message, expectedValues, Arrays.asList(actualValues));
    }

    public static <T> void assertEqualsCollection(String message, T[] expectedValues, Collection<T> actualValues) {
        assertEqualsCollection(message, Arrays.asList(expectedValues), actualValues);
    }

    public static String getIcfsNameAttribute(PrismObject<ShadowType> shadow) {
        return getIcfsNameAttribute(shadow.asObjectable());
    }

    public static String getIcfsNameAttribute(ShadowType shadowType) {
        return getAttributeValue(shadowType, SchemaTestConstants.ICFS_NAME);
    }

    public static String getSecondaryIdentifier(PrismObject<ShadowType> shadow) {
        Collection<ResourceAttribute<?>> secondaryIdentifiers = ShadowUtil.getSecondaryIdentifiers(shadow);
        if (secondaryIdentifiers == null || secondaryIdentifiers.isEmpty()) {
            return null;
        }
        if (secondaryIdentifiers.size() > 1) {
            throw new IllegalArgumentException("Too many secondary indentifiers in " + shadow);
        }
        return (String) secondaryIdentifiers.iterator().next().getRealValue();
    }

    public static void assertSecondaryIdentifier(PrismObject<ShadowType> repoShadow, String value) {
        assertEquals("Wrong secondary indetifier in " + repoShadow, value, getSecondaryIdentifier(repoShadow));
    }

    public static void assertIcfsNameAttribute(ShadowType repoShadow, String value) {
        assertAttribute(repoShadow, SchemaTestConstants.ICFS_NAME, value);
    }

    public static void assertIcfsNameAttribute(PrismObject<ShadowType> repoShadow, String value) {
        assertAttribute(repoShadow, SchemaTestConstants.ICFS_NAME, value);
    }

    public static void assertAttributeNotNull(PrismObject<ShadowType> repoShadow, QName name) {
        Collection<String> values = getAttributeValues(repoShadow, name);
        assertFalse("No values for " + name + " in " + repoShadow, values == null || values.isEmpty());
        assertEquals(1, values.size());
        assertNotNull(values.iterator().next());
    }

    public static void assertAttributeNotNull(ShadowType repoShadow, QName name) {
        Collection<String> values = getAttributeValues(repoShadow, name);
        assertFalse("No values for " + name + " in " + repoShadow, values == null || values.isEmpty());
        assertEquals(1, values.size());
        assertNotNull(values.iterator().next());
    }

    public static void assertAttributeNotNull(String message, ShadowType repoShadow, QName name) {
        Collection<String> values = getAttributeValues(repoShadow, name);
        assertFalse("No values for " + name + " in " + repoShadow, values == null || values.isEmpty());
        assertEquals(message, 1, values.size());
        assertNotNull(message, values.iterator().next());
    }

    public static void assertAttributeDefinition(ResourceAttribute<?> attr, QName expectedType, int minOccurs,
            int maxOccurs, boolean canRead, boolean canCreate, boolean canUpdate,
            Class<?> expetcedAttributeDefinitionClass) {
        ResourceAttributeDefinition definition = attr.getDefinition();
        QName attrName = attr.getElementName();
        assertNotNull("No definition for attribute " + attrName, definition);
        assertEquals("Wrong class of definition for attribute" + attrName, expetcedAttributeDefinitionClass,
                definition.getClass());
        assertEquals("Wrong type in definition for attribute" + attrName, expectedType, definition.getTypeName());
        assertEquals("Wrong minOccurs in definition for attribute" + attrName, minOccurs,
                definition.getMinOccurs());
        assertEquals("Wrong maxOccurs in definition for attribute" + attrName, maxOccurs,
                definition.getMaxOccurs());
        assertEquals("Wrong canRead in definition for attribute" + attrName, canRead, definition.canRead());
        assertEquals("Wrong canCreate in definition for attribute" + attrName, canCreate, definition.canAdd());
        assertEquals("Wrong canUpdate in definition for attribute" + attrName, canUpdate, definition.canModify());
    }

    public static void assertProvisioningAccountShadow(PrismObject<ShadowType> account, ResourceType resourceType,
            Class<?> expetcedAttributeDefinitionClass) {

        assertProvisioningShadow(account, resourceType, expetcedAttributeDefinitionClass,
                new QName(ResourceTypeUtil.getResourceNamespace(resourceType),
                        SchemaTestConstants.ICF_ACCOUNT_OBJECT_CLASS_LOCAL_NAME));
    }

    public static void assertProvisioningShadow(PrismObject<ShadowType> account, ResourceType resourceType,
            Class<?> expetcedAttributeDefinitionClass, QName objectClass) {
        // Check attribute definition
        PrismContainer attributesContainer = account.findContainer(ShadowType.F_ATTRIBUTES);
        assertEquals("Wrong attributes container class", ResourceAttributeContainer.class,
                attributesContainer.getClass());
        ResourceAttributeContainer rAttributesContainer = (ResourceAttributeContainer) attributesContainer;
        PrismContainerDefinition attrsDef = attributesContainer.getDefinition();
        assertNotNull("No attributes container definition", attrsDef);
        assertTrue("Wrong attributes definition class " + attrsDef.getClass().getName(),
                attrsDef instanceof ResourceAttributeContainerDefinition);
        ResourceAttributeContainerDefinition rAttrsDef = (ResourceAttributeContainerDefinition) attrsDef;
        ObjectClassComplexTypeDefinition objectClassDef = rAttrsDef.getComplexTypeDefinition();
        assertNotNull("No object class definition in attributes definition", objectClassDef);
        assertEquals("Wrong object class in attributes definition", objectClass, objectClassDef.getTypeName());
        ResourceAttributeDefinition primaryIdDef = objectClassDef.getIdentifiers().iterator().next();
        ResourceAttribute<?> primaryIdAttr = rAttributesContainer.findAttribute(primaryIdDef.getName());
        assertNotNull("No primary ID " + primaryIdDef.getName() + " in " + account, primaryIdAttr);
        assertAttributeDefinition(primaryIdAttr, DOMUtil.XSD_STRING, 0, 1, true, false, false,
                expetcedAttributeDefinitionClass);

        ResourceAttributeDefinition secondaryIdDef = objectClassDef.getSecondaryIdentifiers().iterator().next();
        ResourceAttribute<Object> secondaryIdAttr = rAttributesContainer.findAttribute(secondaryIdDef.getName());
        assertNotNull("No secondary ID " + secondaryIdDef.getName() + " in " + account, secondaryIdAttr);
        assertAttributeDefinition(secondaryIdAttr, DOMUtil.XSD_STRING, 1, 1, true, true, true,
                expetcedAttributeDefinitionClass);
    }

    public static <T> Collection<T> getAttributeValues(ShadowType shadowType, QName name) {
        return getAttributeValues(shadowType.asPrismObject(), name);
    }

    public static <T> Collection<T> getAttributeValues(PrismObject<? extends ShadowType> shadow, QName name) {
        if (shadow == null) {
            throw new IllegalArgumentException("No shadow");
        }
        PrismContainer<?> attrCont = shadow.findContainer(ShadowType.F_ATTRIBUTES);
        if (attrCont == null) {
            return null;
        }
        PrismProperty<T> attrProp = attrCont.findProperty(name);
        if (attrProp == null) {
            return null;
        }
        return attrProp.getRealValues();
    }

    public static String getAttributeValue(ShadowType repoShadow, QName name) {

        Collection<String> values = getAttributeValues(repoShadow, name);
        if (values == null || values.isEmpty()) {
            AssertJUnit
                    .fail("Attribute " + name + " not found in shadow " + ObjectTypeUtil.toShortString(repoShadow));
        }
        if (values.size() > 1) {
            AssertJUnit.fail("Too many values for attribute " + name + " in shadow "
                    + ObjectTypeUtil.toShortString(repoShadow));
        }
        return values.iterator().next();
    }

    public static void waitFor(String message, Checker checker, int timeoutInterval) throws Exception {
        waitFor(message, checker, timeoutInterval, WAIT_FOR_LOOP_SLEEP_MILIS);
    }

    public static void waitFor(String message, Checker checker, int timeoutInterval, long sleepInterval)
            throws Exception {
        System.out.println(message);
        LOGGER.debug(LOG_MESSAGE_PREFIX + message);
        long startTime = System.currentTimeMillis();
        while (System.currentTimeMillis() < startTime + timeoutInterval) {
            boolean done = checker.check();
            if (done) {
                System.out.println("... done");
                LOGGER.trace(LOG_MESSAGE_PREFIX + "... done " + message);
                return;
            }
            Thread.sleep(sleepInterval);
        }
        // we have timeout
        System.out.println("Timeout while " + message);
        LOGGER.error(LOG_MESSAGE_PREFIX + "Timeout while " + message);
        // Invoke callback
        checker.timeout();
        throw new RuntimeException("Timeout while " + message);
    }

    public static void displayJaxb(String title, Object o, QName defaultElementName) throws SchemaException {
        String serialized = PrismTestUtil.serializeAnyData(o, defaultElementName);
        System.out.println(OBJECT_TITLE_OUT_PREFIX + title);
        System.out.println(serialized);
        LOGGER.debug(OBJECT_TITLE_LOG_PREFIX + title + "\n" + serialized);
    }

    public static void display(String message) {
        System.out.println(OBJECT_TITLE_OUT_PREFIX + message);
        LOGGER.debug(OBJECT_TITLE_LOG_PREFIX + message);
    }

    public static void display(String message, SearchResultEntry response) {
        System.out.println(OBJECT_TITLE_OUT_PREFIX + message);
        LOGGER.debug(OBJECT_TITLE_LOG_PREFIX + message);
        display(response);
    }

    public static void display(Entry response) {
        System.out.println(response == null ? "null" : response.toLDIFString());
        LOGGER.debug(response == null ? "null" : response.toLDIFString());
    }

    public static void display(String message, Task task) {
        System.out.println(OBJECT_TITLE_OUT_PREFIX + message);
        System.out.println(task.debugDump());
        LOGGER.debug(OBJECT_TITLE_LOG_PREFIX + message + "\n" + task.debugDump());
    }

    public static void display(String message, ObjectType o) {
        System.out.println(OBJECT_TITLE_OUT_PREFIX + message);
        System.out.println(ObjectTypeUtil.dump(o));
        LOGGER.debug(OBJECT_TITLE_LOG_PREFIX + message + "\n" + ObjectTypeUtil.dump(o));
    }

    public static void display(String message, Collection collection) {
        String dump = DebugUtil.dump(collection);
        System.out.println(OBJECT_TITLE_OUT_PREFIX + message + "\n" + dump);
        LOGGER.debug(OBJECT_TITLE_LOG_PREFIX + message + "\n" + dump);
    }

    public static void displayObjectTypeCollection(String message, Collection<? extends ObjectType> collection) {
        System.out.println(OBJECT_TITLE_OUT_PREFIX + message);
        LOGGER.debug(OBJECT_TITLE_LOG_PREFIX + message);
        for (ObjectType o : collection) {
            System.out.println(ObjectTypeUtil.dump(o));
            LOGGER.debug(ObjectTypeUtil.dump(o));
            System.out.println(OBJECT_LIST_SEPARATOR);
            LOGGER.debug(OBJECT_LIST_SEPARATOR);
        }
    }

    public static void display(String title, Entry entry) {
        System.out.println(OBJECT_TITLE_OUT_PREFIX + title);
        String ldif = null;
        if (entry != null) {
            ldif = entry.toLDIFString();
        }
        System.out.println(ldif);
        LOGGER.debug(OBJECT_TITLE_LOG_PREFIX + title + "\n" + ldif);
    }

    public static void display(String message, PrismContainer<?> propertyContainer) {
        System.out.println(OBJECT_TITLE_OUT_PREFIX + message);
        System.out.println(propertyContainer == null ? "null" : propertyContainer.debugDump());
        LOGGER.debug(OBJECT_TITLE_LOG_PREFIX + message + "\n"
                + (propertyContainer == null ? "null" : propertyContainer.debugDump()));
    }

    public static void display(OperationResult result) {
        display("Result of " + result.getOperation(), result);
    }

    public static void display(String title, OperationResult result) {
        System.out.println(OBJECT_TITLE_OUT_PREFIX + title);
        System.out.println(result.debugDump());
        LOGGER.debug(OBJECT_TITLE_LOG_PREFIX + title + "\n" + result.debugDump());
    }

    public static void display(String title, OperationResultType result) throws SchemaException {
        displayJaxb(title, result, SchemaConstants.C_RESULT);
    }

    public static void display(String title, List<Element> elements) {
        System.out.println(OBJECT_TITLE_OUT_PREFIX + title);
        LOGGER.debug(OBJECT_TITLE_LOG_PREFIX + title);
        for (Element e : elements) {
            String s = DOMUtil.serializeDOMToString(e);
            System.out.println(s);
            LOGGER.debug(s);
        }
    }

    public static void display(String title, DebugDumpable dumpable) {
        System.out.println(OBJECT_TITLE_OUT_PREFIX + title);
        System.out.println(dumpable == null ? "null" : dumpable.debugDump());
        LOGGER.debug(OBJECT_TITLE_LOG_PREFIX + title + "\n" + (dumpable == null ? "null" : dumpable.debugDump()));
    }

    public static void display(String title, String value) {
        System.out.println(OBJECT_TITLE_OUT_PREFIX + title);
        System.out.println(value);
        LOGGER.debug(OBJECT_TITLE_LOG_PREFIX + title + "\n" + value);
    }

    public static void display(String title, Object value) {
        System.out.println(OBJECT_TITLE_OUT_PREFIX + title);
        System.out.println(SchemaDebugUtil.prettyPrint(value));
        LOGGER.debug(OBJECT_TITLE_LOG_PREFIX + title + "\n" + SchemaDebugUtil.prettyPrint(value));
    }

    public static void display(String title, Throwable e) {
        String stackTrace = ExceptionUtils.getStackTrace(e);
        System.out.println(OBJECT_TITLE_OUT_PREFIX + title + ": " + e.getClass() + " " + e.getMessage());
        System.out.println(stackTrace);
        LOGGER.debug("{}{}: {} {}\n{}",
                new Object[] { OBJECT_TITLE_LOG_PREFIX, title, e.getClass(), e.getMessage(), stackTrace });
    }

    public static <O extends ObjectType> void assertSearchResultNames(SearchResultList<PrismObject<O>> resultList,
            MatchingRule<String> matchingRule, String... expectedNames) throws SchemaException {
        List<String> names = new ArrayList<>(expectedNames.length);
        for (PrismObject<O> obj : resultList) {
            names.add(obj.asObjectable().getName().getOrig());
        }
        PrismAsserts.assertSets("Unexpected search result", matchingRule, names, expectedNames);
    }

    public static <O extends ObjectType> void assertSearchResultNames(SearchResultList<PrismObject<O>> resultList,
            String... expectedNames) {
        List<String> names = new ArrayList<>(expectedNames.length);
        for (PrismObject<O> obj : resultList) {
            names.add(obj.asObjectable().getName().getOrig());
        }
        PrismAsserts.assertSets("Unexpected search result", names, expectedNames);
    }

    public static void checkAllShadows(ResourceType resourceType, RepositoryService repositoryService,
            ObjectChecker<ShadowType> checker, PrismContext prismContext)
            throws SchemaException, ObjectNotFoundException, CommunicationException, ConfigurationException {
        OperationResult result = new OperationResult(IntegrationTestTools.class.getName() + ".checkAllShadows");

        ObjectQuery query = createAllShadowsQuery(resourceType, prismContext);

        List<PrismObject<ShadowType>> allShadows = repositoryService.searchObjects(ShadowType.class, query, null,
                result);
        LOGGER.trace("Checking {} shadows, query:\n{}", allShadows.size(), query.debugDump());

        for (PrismObject<ShadowType> shadow : allShadows) {
            checkShadow(shadow.asObjectable(), resourceType, repositoryService, checker, prismContext, result);
        }
    }

    public static ObjectQuery createAllShadowsQuery(ResourceType resourceType, PrismContext prismContext)
            throws SchemaException {
        RefFilter equal = RefFilter.createReferenceEqual(ShadowType.F_RESOURCE_REF, ShadowType.class, prismContext,
                resourceType.getOid());
        ObjectQuery query = ObjectQuery.createObjectQuery(equal);
        return query;
    }

    public static ObjectQuery createAllShadowsQuery(ResourceType resourceType, QName objectClass,
            PrismContext prismContext) throws SchemaException {
        AndFilter and = AndFilter.createAnd(
                RefFilter.createReferenceEqual(ShadowType.F_RESOURCE_REF, ShadowType.class, prismContext,
                        resourceType.getOid()),
                EqualFilter.createEqual(ShadowType.F_OBJECT_CLASS, ShadowType.class, prismContext, null,
                        objectClass));
        ObjectQuery query = ObjectQuery.createObjectQuery(and);
        return query;
    }

    public static ObjectQuery createAllShadowsQuery(ResourceType resourceType, String objectClassLocalName,
            PrismContext prismContext) throws SchemaException {
        return createAllShadowsQuery(resourceType,
                new QName(ResourceTypeUtil.getResourceNamespace(resourceType), objectClassLocalName), prismContext);
    }

    public static void checkAccountShadow(ShadowType shadowType, ResourceType resourceType,
            RepositoryService repositoryService, ObjectChecker<ShadowType> checker, PrismContext prismContext,
            OperationResult parentResult) throws SchemaException {
        checkAccountShadow(shadowType, resourceType, repositoryService, checker, null, prismContext, parentResult);
    }

    public static void checkAccountShadow(ShadowType shadowType, ResourceType resourceType,
            RepositoryService repositoryService, ObjectChecker<ShadowType> checker,
            MatchingRule<String> uidMatchingRule, PrismContext prismContext, OperationResult parentResult)
            throws SchemaException {
        checkShadow(shadowType, resourceType, repositoryService, checker, uidMatchingRule, prismContext,
                parentResult);
        assertEquals(new QName(ResourceTypeUtil.getResourceNamespace(resourceType),
                SchemaTestConstants.ICF_ACCOUNT_OBJECT_CLASS_LOCAL_NAME), shadowType.getObjectClass());
    }

    public static void checkEntitlementShadow(ShadowType shadowType, ResourceType resourceType,
            RepositoryService repositoryService, ObjectChecker<ShadowType> checker, String objectClassLocalName,
            PrismContext prismContext, OperationResult parentResult) throws SchemaException {
        checkEntitlementShadow(shadowType, resourceType, repositoryService, checker, objectClassLocalName, null,
                prismContext, parentResult);
    }

    public static void checkEntitlementShadow(ShadowType shadowType, ResourceType resourceType,
            RepositoryService repositoryService, ObjectChecker<ShadowType> checker, String objectClassLocalName,
            MatchingRule<String> uidMatchingRule, PrismContext prismContext, OperationResult parentResult)
            throws SchemaException {
        checkShadow(shadowType, resourceType, repositoryService, checker, uidMatchingRule, prismContext,
                parentResult);
        assertEquals(new QName(ResourceTypeUtil.getResourceNamespace(resourceType), objectClassLocalName),
                shadowType.getObjectClass());
    }

    public static void checkShadow(ShadowType shadowType, ResourceType resourceType,
            RepositoryService repositoryService, ObjectChecker<ShadowType> checker, PrismContext prismContext,
            OperationResult parentResult) throws SchemaException {
        checkShadow(shadowType, resourceType, repositoryService, checker, null, prismContext, parentResult);
    }

    public static void checkShadow(ShadowType shadowType, ResourceType resourceType,
            RepositoryService repositoryService, ObjectChecker<ShadowType> checker,
            MatchingRule<String> uidMatchingRule, PrismContext prismContext, OperationResult parentResult)
            throws SchemaException {
        LOGGER.trace("Checking shadow:\n{}", shadowType.asPrismObject().debugDump());
        shadowType.asPrismObject().checkConsistence(true, true, ConsistencyCheckScope.THOROUGH);
        assertNotNull("no OID", shadowType.getOid());
        assertNotNull("no name", shadowType.getName());
        assertEquals(resourceType.getOid(), shadowType.getResourceRef().getOid());
        PrismContainer<?> attrs = shadowType.asPrismObject().findContainer(ShadowType.F_ATTRIBUTES);
        assertNotNull("no attributes", attrs);
        assertFalse("empty attributes", attrs.isEmpty());

        RefinedResourceSchema rschema = RefinedResourceSchema.getRefinedSchema(resourceType);
        ObjectClassComplexTypeDefinition objectClassDef = rschema.findObjectClassDefinition(shadowType);
        assertNotNull("cannot determine object class for " + shadowType, objectClassDef);

        String icfUid = ShadowUtil.getSingleStringAttributeValue(shadowType, SchemaTestConstants.ICFS_UID);
        if (icfUid == null) {
            Collection<? extends ResourceAttributeDefinition> identifierDefs = objectClassDef.getIdentifiers();
            assertFalse("No identifiers for " + objectClassDef, identifierDefs == null || identifierDefs.isEmpty());
            for (ResourceAttributeDefinition idDef : identifierDefs) {
                String id = ShadowUtil.getSingleStringAttributeValue(shadowType, idDef.getName());
                assertNotNull("No identifier " + idDef.getName() + " in " + shadowType, id);
            }
        }

        String resourceOid = ShadowUtil.getResourceOid(shadowType);
        assertNotNull("No resource OID in " + shadowType, resourceOid);

        assertNotNull("Null OID in " + shadowType, shadowType.getOid());
        PrismObject<ShadowType> repoShadow = null;
        try {
            repoShadow = repositoryService.getObject(ShadowType.class, shadowType.getOid(), null, parentResult);
        } catch (Exception e) {
            AssertJUnit.fail("Got exception while trying to read " + shadowType + ": " + e.getCause() + ": "
                    + e.getMessage());
        }

        checkShadowUniqueness(shadowType, objectClassDef, repositoryService, uidMatchingRule, prismContext,
                parentResult);

        String repoResourceOid = ShadowUtil.getResourceOid(repoShadow.asObjectable());
        assertNotNull("No resource OID in the repository shadow " + repoShadow);
        assertEquals("Resource OID mismatch", resourceOid, repoResourceOid);

        try {
            repositoryService.getObject(ResourceType.class, resourceOid, null, parentResult);
        } catch (Exception e) {
            AssertJUnit.fail("Got exception while trying to read resource " + resourceOid
                    + " as specified in current shadow " + shadowType + ": " + e.getCause() + ": "
                    + e.getMessage());
        }

        if (checker != null) {
            checker.check(shadowType);
        }
    }

    /**
     * Checks i there is only a single shadow in repo for this account.
     */
    private static void checkShadowUniqueness(ShadowType resourceShadow,
            ObjectClassComplexTypeDefinition objectClassDef, RepositoryService repositoryService,
            MatchingRule<String> uidMatchingRule, PrismContext prismContext, OperationResult parentResult) {
        try {
            ObjectQuery query = createShadowQuery(resourceShadow, objectClassDef, uidMatchingRule, prismContext);
            List<PrismObject<ShadowType>> results = repositoryService.searchObjects(ShadowType.class, query, null,
                    parentResult);
            LOGGER.trace("Shadow check with filter\n{}\n found {} objects", query.debugDump(), results.size());
            if (results.size() == 0) {
                AssertJUnit.fail("No shadow found with query:\n" + query.debugDump());
            }
            if (results.size() == 1) {
                return;
            }
            if (results.size() > 1) {
                for (PrismObject<ShadowType> result : results) {
                    LOGGER.trace("Search result:\n{}", result.debugDump());
                }
                LOGGER.error("More than one shadows found for " + resourceShadow);
                // TODO: Better error handling later
                throw new IllegalStateException("More than one shadows found for " + resourceShadow);
            }
        } catch (SchemaException e) {
            throw new SystemException(e);
        }
    }

    private static ObjectQuery createShadowQuery(ShadowType resourceShadow,
            ObjectClassComplexTypeDefinition objectClassDef, MatchingRule<String> uidMatchingRule,
            PrismContext prismContext) throws SchemaException {

        PrismContainer<?> attributesContainer = resourceShadow.asPrismObject()
                .findContainer(ShadowType.F_ATTRIBUTES);
        QName identifierName = objectClassDef.getIdentifiers().iterator().next().getName();
        PrismProperty<String> identifier = attributesContainer.findProperty(identifierName);
        if (identifier == null) {
            throw new SchemaException("No identifier in " + resourceShadow);
        }
        String identifierValue = identifier.getRealValue();
        if (uidMatchingRule != null) {
            identifierValue = uidMatchingRule.normalize(identifierValue);
        }

        ObjectFilter filter;
        PrismPropertyDefinition<String> identifierDef = identifier.getDefinition();
        filter = AndFilter.createAnd(
                RefFilter.createReferenceEqual(ShadowType.F_RESOURCE_REF, ShadowType.class, prismContext,
                        ShadowUtil.getResourceOid(resourceShadow)),
                EqualFilter.createEqual(new ItemPath(ShadowType.F_ATTRIBUTES, identifierDef.getName()),
                        identifierDef, new PrismPropertyValue<String>(identifierValue)));

        ObjectQuery query = ObjectQuery.createObjectQuery(filter);

        return query;

    }

    public static void applyResourceSchema(ShadowType accountType, ResourceType resourceType,
            PrismContext prismContext) throws SchemaException {
        ResourceSchema resourceSchema = RefinedResourceSchema.getResourceSchema(resourceType, prismContext);
        ShadowUtil.applyResourceSchema(accountType.asPrismObject(), resourceSchema);
    }

    public static void assertInMessageRecursive(Throwable e, String substring) {
        assert hasInMessageRecursive(e, substring) : "The substring '" + substring
                + "' was NOT found in the message of exception " + e + " (including cause exceptions)";
    }

    public static boolean hasInMessageRecursive(Throwable e, String substring) {
        if (e.getMessage().contains(substring)) {
            return true;
        }
        if (e.getCause() != null) {
            return hasInMessageRecursive(e.getCause(), substring);
        }
        return false;
    }

    public static void assertNotInMessageRecursive(Throwable e, String substring) {
        assert !e.getMessage().contains(substring) : "The substring '" + substring
                + "' was found in the message of exception " + e + ": " + e.getMessage();
        if (e.getCause() != null) {
            assertNotInMessageRecursive(e.getCause(), substring);
        }
    }

    public static void assertNoRepoCache() {
        if (RepositoryCache.exists()) {
            AssertJUnit.fail("Cache exists! " + RepositoryCache.debugDump());
        }
    }

    public static void assertScripts(List<ScriptHistoryEntry> scriptsHistory,
            ProvisioningScriptSpec... expectedScripts) {
        displayScripts(scriptsHistory);
        assertEquals("Wrong number of scripts executed", expectedScripts.length, scriptsHistory.size());
        Iterator<ScriptHistoryEntry> historyIter = scriptsHistory.iterator();
        for (ProvisioningScriptSpec expecedScript : expectedScripts) {
            ScriptHistoryEntry actualScript = historyIter.next();
            assertEquals("Wrong script code", expecedScript.getCode(), actualScript.getCode());
            if (expecedScript.getLanguage() == null) {
                assertEquals("We talk only gibberish here", "Gibberish", actualScript.getLanguage());
            } else {
                assertEquals("Wrong script language", expecedScript.getLanguage(), actualScript.getLanguage());
            }
            assertEquals("Wrong number of arguments", expecedScript.getArgs().size(),
                    actualScript.getParams().size());
            for (java.util.Map.Entry<String, Object> expectedEntry : expecedScript.getArgs().entrySet()) {
                Object expectedValue = expectedEntry.getValue();
                Object actualVal = actualScript.getParams().get(expectedEntry.getKey());
                assertEquals("Wrong value for argument '" + expectedEntry.getKey() + "'", expectedValue, actualVal);
            }
        }
    }

    public static void displayScripts(List<ScriptHistoryEntry> scriptsHistory) {
        for (ScriptHistoryEntry script : scriptsHistory) {
            display("Script", script);
        }
    }

    public static <T> void assertExtensionProperty(PrismObject<? extends ObjectType> object, QName propertyName,
            T... expectedValues) {
        PrismContainer<?> extension = object.getExtension();
        PrismAsserts.assertPropertyValue(extension, propertyName, expectedValues);
    }

    public static <T> void assertNoExtensionProperty(PrismObject<? extends ObjectType> object, QName propertyName) {
        PrismContainer<?> extension = object.getExtension();
        PrismAsserts.assertNoItem(extension, propertyName);
    }

    public static void assertIcfResourceSchemaSanity(ResourceSchema resourceSchema, ResourceType resourceType) {
        assertNotNull("No resource schema in " + resourceType, resourceSchema);
        QName objectClassQname = new QName(ResourceTypeUtil.getResourceNamespace(resourceType),
                "AccountObjectClass");
        ObjectClassComplexTypeDefinition accountDefinition = resourceSchema
                .findObjectClassDefinition(objectClassQname);
        assertNotNull("No object class definition for " + objectClassQname + " in resource schema",
                accountDefinition);
        ObjectClassComplexTypeDefinition accountDef = resourceSchema
                .findDefaultObjectClassDefinition(ShadowKindType.ACCOUNT);
        assertTrue("Mismatched account definition: " + accountDefinition + " <-> " + accountDef,
                accountDefinition == accountDef);

        assertNotNull("No object class definition " + objectClassQname, accountDefinition);
        assertEquals("Object class " + objectClassQname + " is not account", ShadowKindType.ACCOUNT,
                accountDefinition.getKind());
        assertTrue("Object class " + objectClassQname + " is not default account",
                accountDefinition.isDefaultInAKind());
        assertFalse("Object class " + objectClassQname + " is empty", accountDefinition.isEmpty());
        assertFalse("Object class " + objectClassQname + " is empty", accountDefinition.isIgnored());

        Collection<? extends ResourceAttributeDefinition> identifiers = accountDefinition.getIdentifiers();
        assertNotNull("Null identifiers for " + objectClassQname, identifiers);
        assertFalse("Empty identifiers for " + objectClassQname, identifiers.isEmpty());

        ResourceAttributeDefinition uidAttributeDefinition = accountDefinition
                .findAttributeDefinition(SchemaTestConstants.ICFS_UID);
        assertNotNull("No definition for attribute " + SchemaTestConstants.ICFS_UID, uidAttributeDefinition);
        assertTrue("Attribute " + SchemaTestConstants.ICFS_UID + " in not an identifier",
                uidAttributeDefinition.isIdentifier(accountDefinition));
        assertTrue("Attribute " + SchemaTestConstants.ICFS_UID + " in not in identifiers list",
                identifiers.contains(uidAttributeDefinition));
        assertEquals("Wrong displayName for attribute " + SchemaTestConstants.ICFS_UID, "ConnId UID",
                uidAttributeDefinition.getDisplayName());
        assertEquals("Wrong displayOrder for attribute " + SchemaTestConstants.ICFS_UID, (Integer) 100,
                uidAttributeDefinition.getDisplayOrder());

        Collection<? extends ResourceAttributeDefinition> secondaryIdentifiers = accountDefinition
                .getSecondaryIdentifiers();
        assertNotNull("Null secondary identifiers for " + objectClassQname, secondaryIdentifiers);
        assertFalse("Empty secondary identifiers for " + objectClassQname, secondaryIdentifiers.isEmpty());

        ResourceAttributeDefinition nameAttributeDefinition = accountDefinition
                .findAttributeDefinition(SchemaTestConstants.ICFS_NAME);
        assertNotNull("No definition for attribute " + SchemaTestConstants.ICFS_NAME, nameAttributeDefinition);
        assertTrue("Attribute " + SchemaTestConstants.ICFS_NAME + " in not an identifier",
                nameAttributeDefinition.isSecondaryIdentifier(accountDefinition));
        assertTrue("Attribute " + SchemaTestConstants.ICFS_NAME + " in not in identifiers list",
                secondaryIdentifiers.contains(nameAttributeDefinition));
        assertEquals("Wrong displayName for attribute " + SchemaTestConstants.ICFS_NAME, "ConnId Name",
                nameAttributeDefinition.getDisplayName());
        assertEquals("Wrong displayOrder for attribute " + SchemaTestConstants.ICFS_NAME, (Integer) 110,
                nameAttributeDefinition.getDisplayOrder());

        assertNotNull("Null identifiers in account", accountDef.getIdentifiers());
        assertFalse("Empty identifiers in account", accountDef.getIdentifiers().isEmpty());
        assertNotNull("Null secondary identifiers in account", accountDef.getSecondaryIdentifiers());
        assertFalse("Empty secondary identifiers in account", accountDef.getSecondaryIdentifiers().isEmpty());
        assertNotNull("No naming attribute in account", accountDef.getNamingAttribute());
        assertFalse("No nativeObjectClass in account", StringUtils.isEmpty(accountDef.getNativeObjectClass()));

        ResourceAttributeDefinition uidDef = accountDef.findAttributeDefinition(SchemaTestConstants.ICFS_UID);
        assertEquals(1, uidDef.getMaxOccurs());
        assertEquals(0, uidDef.getMinOccurs());
        assertFalse("No UID display name", StringUtils.isBlank(uidDef.getDisplayName()));
        assertFalse("UID has create", uidDef.canAdd());
        assertFalse("UID has update", uidDef.canModify());
        assertTrue("No UID read", uidDef.canRead());
        assertTrue("UID definition not in identifiers", accountDef.getIdentifiers().contains(uidDef));
        assertEquals("Wrong refined displayName for attribute " + SchemaTestConstants.ICFS_UID, "ConnId UID",
                uidDef.getDisplayName());
        assertEquals("Wrong refined displayOrder for attribute " + SchemaTestConstants.ICFS_UID, (Integer) 100,
                uidDef.getDisplayOrder());

        ResourceAttributeDefinition nameDef = accountDef.findAttributeDefinition(SchemaTestConstants.ICFS_NAME);
        assertEquals(1, nameDef.getMaxOccurs());
        assertEquals(1, nameDef.getMinOccurs());
        assertFalse("No NAME displayName", StringUtils.isBlank(nameDef.getDisplayName()));
        assertTrue("No NAME create", nameDef.canAdd());
        assertTrue("No NAME update", nameDef.canModify());
        assertTrue("No NAME read", nameDef.canRead());
        assertTrue("NAME definition not in identifiers", accountDef.getSecondaryIdentifiers().contains(nameDef));
        assertEquals("Wrong refined displayName for attribute " + SchemaTestConstants.ICFS_NAME, "ConnId Name",
                nameDef.getDisplayName());
        assertEquals("Wrong refined displayOrder for attribute " + SchemaTestConstants.ICFS_NAME, (Integer) 110,
                nameDef.getDisplayOrder());

        assertNull("The _PASSSWORD_ attribute sneaked into schema",
                accountDef.findAttributeDefinition(new QName(SchemaTestConstants.NS_ICFS, "password")));
    }

    //TODO: add language parameter..for now, use xml serialization
    public static void displayXml(String message, PrismObject<? extends ObjectType> object) throws SchemaException {
        String xml = PrismTestUtil.serializeObjectToString(object, PrismContext.LANG_XML);
        display(message, xml);
    }

    public static ObjectDelta<ShadowType> createEntitleDelta(String accountOid, QName associationName,
            String groupOid, PrismContext prismContext) throws SchemaException {
        ShadowAssociationType association = new ShadowAssociationType();
        association.setName(associationName);
        ObjectReferenceType shadowRefType = new ObjectReferenceType();
        shadowRefType.setOid(groupOid);
        shadowRefType.setType(ShadowType.COMPLEX_TYPE);
        association.setShadowRef(shadowRefType);
        ItemPath entitlementAssociationPath = new ItemPath(ShadowType.F_ASSOCIATION);
        ObjectDelta<ShadowType> delta = ObjectDelta.createModificationAddContainer(ShadowType.class, accountOid,
                entitlementAssociationPath, prismContext, association);
        return delta;
    }

    public static ObjectDelta<ShadowType> createDetitleDelta(String accountOid, QName associationName,
            String groupOid, PrismContext prismContext) throws SchemaException {
        ShadowAssociationType association = new ShadowAssociationType();
        association.setName(associationName);
        ObjectReferenceType shadowRefType = new ObjectReferenceType();
        shadowRefType.setOid(groupOid);
        shadowRefType.setType(ShadowType.COMPLEX_TYPE);
        association.setShadowRef(shadowRefType);
        ItemPath entitlementAssociationPath = new ItemPath(ShadowType.F_ASSOCIATION);
        ObjectDelta<ShadowType> delta = ObjectDelta.createModificationDeleteContainer(ShadowType.class, accountOid,
                entitlementAssociationPath, prismContext, association);
        return delta;
    }

    public static void assertGroupMember(DummyGroup group, String accountId) {
        assertGroupMember(group, accountId, false);
    }

    public static void assertGroupMember(DummyGroup group, String accountId, boolean caseIgnore) {
        Collection<String> members = group.getMembers();
        assertNotNull("No members in group " + group.getName() + ", expected that " + accountId + " will be there",
                members);
        if (caseIgnore) {
            for (String member : members) {
                if (StringUtils.equalsIgnoreCase(accountId, member)) {
                    return;
                }
            }
            AssertJUnit.fail("Account " + accountId + " is not member of group " + group.getName() + ", members: "
                    + members);
        } else {
            assertTrue(
                    "Account " + accountId + " is not member of group " + group.getName() + ", members: " + members,
                    members.contains(accountId));
        }
    }

    public static void assertNoGroupMember(DummyGroup group, String accountId) {
        Collection<String> members = group.getMembers();
        if (members == null) {
            return;
        }
        assertFalse("Account " + accountId + " IS member of group " + group.getName()
                + " while not expecting it, members: " + members, members.contains(accountId));
    }

    public static void assertNoGroupMembers(DummyGroup group) {
        Collection<String> members = group.getMembers();
        assertTrue("Group " + group.getName() + " has members while not expecting it, members: " + members,
                members == null || members.isEmpty());
    }

    public static void assertAssociation(PrismObject<ShadowType> shadow, QName associationName,
            String entitlementOid) {
        ShadowType accountType = shadow.asObjectable();
        List<ShadowAssociationType> associations = accountType.getAssociation();
        assertNotNull("Null associations in " + shadow, associations);
        assertFalse("Empty associations in " + shadow, associations.isEmpty());
        for (ShadowAssociationType association : associations) {
            if (associationName.equals(association.getName())
                    && entitlementOid.equals(association.getShadowRef().getOid())) {
                return;
            }
        }
        AssertJUnit.fail("No association for entitlement " + entitlementOid + " in " + shadow);
    }

    public static void assertNoAssociation(PrismObject<ShadowType> shadow, QName associationName,
            String entitlementOid) {
        ShadowType accountType = shadow.asObjectable();
        List<ShadowAssociationType> associations = accountType.getAssociation();
        if (associations == null) {
            return;
        }
        for (ShadowAssociationType association : associations) {
            if (associationName.equals(association.getName())
                    && entitlementOid.equals(association.getShadowRef().getOid())) {
                AssertJUnit.fail("Unexpected association for entitlement " + entitlementOid + " in " + shadow);
            }
        }
    }

    public static void assertNoSchema(ResourceType resourceType) {
        assertNoSchema("Found schema in resource " + resourceType + " while not expecting it", resourceType);
    }

    public static void assertNoSchema(String message, ResourceType resourceType) {
        Element resourceXsdSchema = ResourceTypeUtil.getResourceXsdSchema(resourceType);
        AssertJUnit.assertNull(message, resourceXsdSchema);
    }
}