/* * Copyright (c) 2010-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.common.refinery; import static org.testng.AssertJUnit.assertEquals; import static org.testng.AssertJUnit.assertFalse; import static org.testng.AssertJUnit.assertNotNull; import static org.testng.AssertJUnit.assertTrue; import static com.evolveum.midpoint.prism.util.PrismTestUtil.*; import java.io.File; import java.io.IOException; import java.util.Collection; import java.util.Iterator; import java.util.List; import javax.xml.bind.JAXBException; import javax.xml.namespace.QName; import com.evolveum.midpoint.prism.ConsistencyCheckScope; import com.evolveum.midpoint.prism.util.PrismTestUtil; import com.evolveum.midpoint.schema.processor.*; import org.testng.Assert; import org.testng.AssertJUnit; import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; import org.xml.sax.SAXException; import com.evolveum.midpoint.common.ResourceObjectPattern; import com.evolveum.midpoint.prism.Containerable; import com.evolveum.midpoint.prism.ItemDefinition; 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.PrismObjectDefinition; import com.evolveum.midpoint.prism.util.PrismAsserts; import com.evolveum.midpoint.schema.MidPointPrismContextFactory; import com.evolveum.midpoint.schema.constants.MidPointConstants; import com.evolveum.midpoint.schema.constants.SchemaConstants; import com.evolveum.midpoint.schema.util.ResourceTypeUtil; import com.evolveum.midpoint.schema.util.SchemaTestConstants; import com.evolveum.midpoint.schema.util.ShadowUtil; import com.evolveum.midpoint.test.util.TestUtil; import com.evolveum.midpoint.util.DOMUtil; import com.evolveum.midpoint.util.PrettyPrinter; import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.xml.ns._public.common.common_3.LayerType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowAttributesType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowKindType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType; /** * @author semancik */ public class TestRefinedSchema { public static final String TEST_DIR_NAME = "src/test/resources/refinery"; private static final File RESOURCE_COMPLEX_FILE = new File(TEST_DIR_NAME, "resource-complex.xml"); private static final File RESOURCE_SIMPLE_FILE = new File(TEST_DIR_NAME, "resource-simple.xml"); private static final File RESOURCE_POSIX_FILE = new File(TEST_DIR_NAME, "resource-ldap-posix.xml"); private static final String ENTITLEMENT_GROUP_INTENT = "group"; private static final String ENTITLEMENT_LDAP_GROUP_INTENT = "ldapGroup"; private static final String ENTITLEMENT_UNIX_GROUP_INTENT = "unixGroup"; private static final QName OBJECT_CLASS_INETORGPERSON_QNAME = new QName(MidPointConstants.NS_RI, "inetOrgPerson"); @BeforeSuite public void setup() throws SchemaException, SAXException, IOException { PrettyPrinter.setDefaultNamespacePrefix(MidPointConstants.NS_MIDPOINT_PUBLIC_PREFIX); resetPrismContext(MidPointPrismContextFactory.FACTORY); } @Test public void testParseFromResourceComplex() throws Exception { final String TEST_NAME = "testParseFromResourceComplex"; TestUtil.displayTestTile(TEST_NAME); // GIVEN PrismContext prismContext = createInitializedPrismContext(); PrismObject<ResourceType> resource = prismContext.parseObject(RESOURCE_COMPLEX_FILE); ResourceType resourceType = resource.asObjectable(); // WHEN TestUtil.displayWhen(TEST_NAME); RefinedResourceSchema rSchema = RefinedResourceSchemaImpl.parse(resourceType, prismContext); // THEN TestUtil.displayThen(TEST_NAME); assertNotNull("Refined schema is null", rSchema); System.out.println("Refined schema"); System.out.println(rSchema.debugDump()); assertRefinedSchema(resourceType, rSchema, null, LayerType.MODEL, true); assertLayerRefinedSchema(resourceType, rSchema, LayerType.SCHEMA, LayerType.SCHEMA, true); assertLayerRefinedSchema(resourceType, rSchema, LayerType.MODEL, LayerType.MODEL, true); assertLayerRefinedSchema(resourceType, rSchema, LayerType.PRESENTATION, LayerType.PRESENTATION, true); RefinedObjectClassDefinition rAccount = rSchema.getRefinedDefinition(ShadowKindType.ACCOUNT, (String)null); RefinedAttributeDefinition userPasswordAttribute = rAccount.findAttributeDefinition("userPassword"); assertNotNull("No userPassword attribute", userPasswordAttribute); assertTrue("userPassword not ignored", userPasswordAttribute.isIgnored()); } private void assertLayerRefinedSchema(ResourceType resourceType, RefinedResourceSchema rSchema, LayerType sourceLayer, LayerType validationLayer, boolean assertEntitlements) { System.out.println("Refined schema: layer="+sourceLayer); LayerRefinedResourceSchema lrSchema = rSchema.forLayer(sourceLayer); System.out.println(lrSchema.debugDump()); assertRefinedSchema(resourceType, lrSchema, sourceLayer, validationLayer, assertEntitlements); } @Test public void testParseFromResourceSimple() throws JAXBException, SchemaException, SAXException, IOException { System.out.println("\n===[ testParseFromResourceSimple ]===\n"); // GIVEN PrismContext prismContext = createInitializedPrismContext(); PrismObject<ResourceType> resource = prismContext.parseObject(RESOURCE_SIMPLE_FILE); ResourceType resourceType = resource.asObjectable(); // WHEN RefinedResourceSchema rSchema = RefinedResourceSchemaImpl.parse(resourceType, prismContext); // THEN assertNotNull("Refined schema is null", rSchema); System.out.println("Refined schema"); System.out.println(rSchema.debugDump()); assertRefinedSchema(resourceType, rSchema, null, LayerType.SCHEMA, false); } private void assertRefinedSchema(ResourceType resourceType, RefinedResourceSchema rSchema, LayerType sourceLayer, LayerType validationLayer, boolean assertEntitlements) { assertFalse("No account definitions", rSchema.getRefinedDefinitions(ShadowKindType.ACCOUNT).isEmpty()); RefinedObjectClassDefinition rAccountDef = rSchema.getRefinedDefinition(ShadowKindType.ACCOUNT, (String)null); RefinedObjectClassDefinition accountDefByNullObjectclass = rSchema.findRefinedDefinitionByObjectClassQName(ShadowKindType.ACCOUNT, null); assertEquals("findAccountDefinitionByObjectClass(null) returned wrong value", rAccountDef, accountDefByNullObjectclass); RefinedObjectClassDefinition accountDefByIcfAccountObjectclass = rSchema.findRefinedDefinitionByObjectClassQName(ShadowKindType.ACCOUNT, new QName(resourceType.getNamespace(), SchemaTestConstants.ICF_ACCOUNT_OBJECT_CLASS_LOCAL_NAME)); assertEquals("findAccountDefinitionByObjectClass(ICF account) returned wrong value", rAccountDef, accountDefByIcfAccountObjectclass); assertRObjectClassDef(rAccountDef, resourceType, sourceLayer, validationLayer); System.out.println("Refined account definitionn:"); System.out.println(rAccountDef.debugDump()); assertEquals("Wrong kind", ShadowKindType.ACCOUNT, rAccountDef.getKind()); Collection<? extends RefinedAttributeDefinition> accAttrsDef = rAccountDef.getAttributeDefinitions(); assertNotNull("Null attributeDefinitions", accAttrsDef); assertFalse("Empty attributeDefinitions", accAttrsDef.isEmpty()); assertEquals("Unexpected number of attributeDefinitions", 55, accAttrsDef.size()); RefinedAttributeDefinition disabledAttribute = rAccountDef.findAttributeDefinition("ds-pwp-account-disabled"); assertNotNull("No ds-pwp-account-disabled attribute", disabledAttribute); assertTrue("ds-pwp-account-disabled not ignored", disabledAttribute.isIgnored()); RefinedAttributeDefinition<?> displayNameAttributeDef = rAccountDef.getDisplayNameAttribute(); assertNotNull("No account displayNameAttribute", displayNameAttributeDef); assertEquals("Wrong account displayNameAttribute", new QName(resourceType.getNamespace(), "uid"), displayNameAttributeDef.getName()); // This is compatibility with PrismContainerDefinition, it should work well Collection<? extends ItemDefinition> propertyDefinitions = rAccountDef.getDefinitions(); assertNotNull("Null propertyDefinitions", propertyDefinitions); assertFalse("Empty propertyDefinitions", propertyDefinitions.isEmpty()); assertEquals("Unexpected number of propertyDefinitions", 55, propertyDefinitions.size()); if (assertEntitlements) { assertFalse("No entitlement definitions", rSchema.getRefinedDefinitions(ShadowKindType.ENTITLEMENT).isEmpty()); RefinedObjectClassDefinition rEntDef = rSchema.getRefinedDefinition(ShadowKindType.ENTITLEMENT, (String)null); assertNotNull("No entitlement definition for null intent", rEntDef); RefinedObjectClassDefinition rEntDefGroup = rSchema.getRefinedDefinition(ShadowKindType.ENTITLEMENT, ENTITLEMENT_GROUP_INTENT); assertNotNull("No entitlement for intent '"+ENTITLEMENT_GROUP_INTENT+"'", rEntDefGroup); assertEquals("Wrong kind", ShadowKindType.ENTITLEMENT, rEntDef.getKind()); Collection<? extends RefinedAttributeDefinition> entAttrDefs = rEntDef.getAttributeDefinitions(); assertNotNull("Null attributeDefinitions", entAttrDefs); assertFalse("Empty attributeDefinitions", entAttrDefs.isEmpty()); assertEquals("Unexpected number of attributeDefinitions", 11, entAttrDefs.size()); // TODO RefinedAttributeDefinition<?> entDisplayNameAttributeDef = rEntDef.getDisplayNameAttribute(); assertNotNull("No entitlement displayNameAttribute", entDisplayNameAttributeDef); assertEquals("Wrong entitlement displayNameAttribute", new QName(resourceType.getNamespace(), "cn"), entDisplayNameAttributeDef.getName()); assertEquals("Unexpected number of entitlement associations", 1, rAccountDef.getEntitlementAssociationDefinitions().size()); } assertRefinedToLayer(rAccountDef, sourceLayer); ResourceAttributeContainerDefinition resAttrContainerDef = rAccountDef.toResourceAttributeContainerDefinition(); assertNotNull("No ResourceAttributeContainerDefinition", resAttrContainerDef); System.out.println("\nResourceAttributeContainerDefinition ("+sourceLayer+")"); System.out.println(resAttrContainerDef.debugDump()); ObjectClassComplexTypeDefinition rComplexTypeDefinition = resAttrContainerDef.getComplexTypeDefinition(); System.out.println("\nResourceAttributeContainerDefinition ComplexTypeDefinition ("+sourceLayer+")"); System.out.println(rComplexTypeDefinition.debugDump()); assertRefinedToLayer(rComplexTypeDefinition, sourceLayer); ResourceAttributeDefinition riUidAttrDef = resAttrContainerDef.findAttributeDefinition(new QName(resourceType.getNamespace(), "uid")); assertNotNull("No ri:uid def in ResourceAttributeContainerDefinition", riUidAttrDef); System.out.println("\nri:uid def "+riUidAttrDef.getClass()+" ("+sourceLayer+")"); System.out.println(riUidAttrDef.debugDump()); assertRefinedToLayer(riUidAttrDef, sourceLayer); if (validationLayer == LayerType.PRESENTATION) { assertFalse("Can update "+riUidAttrDef+" from ResourceAttributeContainerDefinition ("+sourceLayer+")", riUidAttrDef.canModify()); } else { assertTrue("Cannot update "+riUidAttrDef+" from ResourceAttributeContainerDefinition ("+sourceLayer+")", riUidAttrDef.canModify()); } Collection<? extends ResourceAttributeDefinition> definitionsFromResAttrContainerDef = resAttrContainerDef.getDefinitions(); for (ResourceAttributeDefinition definitionFromResAttrContainerDef: definitionsFromResAttrContainerDef) { assertRefinedToLayer(definitionFromResAttrContainerDef, sourceLayer); } } private void assertRefinedToLayer( ObjectClassComplexTypeDefinition ocDef, LayerType expectedLayer) { if (expectedLayer == null) { // This is OK, it may not be layer-bound. return; } if (!(ocDef instanceof LayerRefinedObjectClassDefinition)) { AssertJUnit.fail("Expected that definition of objectclass "+ocDef.getTypeName()+" in layer "+expectedLayer +" will be LayerRefinedObjectClassDefinition, but it is "+ocDef.getClass()+": "+ocDef); } assertEquals("Wrong layer in "+ocDef, expectedLayer, ((LayerRefinedObjectClassDefinition)ocDef).getLayer()); } private void assertRefinedToLayer(ResourceAttributeDefinition attrDef, LayerType expectedLayer) { if (expectedLayer == null) { // This is OK, it may not be layer-bound. return; } if (!(attrDef instanceof LayerRefinedAttributeDefinition)) { AssertJUnit.fail("Expected that definition of attribute "+attrDef.getName()+" in layer "+expectedLayer +" will be LayerRefinedAttributeDefinition, but it is "+attrDef.getClass()+": "+attrDef); } assertEquals("Wrong layer in "+attrDef, expectedLayer, ((LayerRefinedAttributeDefinition)attrDef).getLayer()); } @Test public void testParseAccount() throws JAXBException, SchemaException, SAXException, IOException { System.out.println("\n===[ testParseAccount ]===\n"); // GIVEN PrismContext prismContext = createInitializedPrismContext(); PrismObject<ResourceType> resource = prismContext.parseObject(RESOURCE_COMPLEX_FILE); ResourceType resourceType = resource.asObjectable(); RefinedResourceSchema rSchema = RefinedResourceSchemaImpl.parse(resourceType, prismContext); RefinedObjectClassDefinition defaultAccountDefinition = rSchema.getDefaultRefinedDefinition(ShadowKindType.ACCOUNT); assertNotNull("No refined default account definition in "+rSchema, defaultAccountDefinition); PrismObject<ShadowType> accObject = prismContext.parseObject(new File(TEST_DIR_NAME, "account-jack.xml")); // WHEN PrismObjectDefinition<ShadowType> objectDefinition = defaultAccountDefinition.getObjectDefinition(); System.out.println("Refined account definition:"); System.out.println(objectDefinition.debugDump()); accObject.applyDefinition(objectDefinition); // THEN System.out.println("Parsed account:"); System.out.println(accObject.debugDump()); assertAccountShadow(accObject, resource, prismContext); } @Test public void testApplyAttributeDefinition() throws JAXBException, SchemaException, SAXException, IOException { System.out.println("\n===[ testApplyAttributeDefinition ]===\n"); // GIVEN PrismContext prismContext = createInitializedPrismContext(); PrismObject<ResourceType> resource = prismContext.parseObject(RESOURCE_COMPLEX_FILE); RefinedResourceSchema rSchema = RefinedResourceSchemaImpl.parse(resource, prismContext); RefinedObjectClassDefinition defaultAccountDefinition = rSchema.getDefaultRefinedDefinition(ShadowKindType.ACCOUNT); assertNotNull("No refined default account definition in "+rSchema, defaultAccountDefinition); System.out.println("Refined account definition:"); System.out.println(defaultAccountDefinition.debugDump()); PrismObject<ShadowType> accObject = prismContext.parseObject(new File(TEST_DIR_NAME, "account-jack.xml")); PrismContainer<Containerable> attributesContainer = accObject.findContainer(ShadowType.F_ATTRIBUTES); System.out.println("Attributes container:"); System.out.println(attributesContainer.debugDump()); // WHEN attributesContainer.applyDefinition((PrismContainerDefinition)defaultAccountDefinition.toResourceAttributeContainerDefinition(), true); // THEN System.out.println("Parsed account:"); System.out.println(accObject.debugDump()); assertAccountShadow(accObject, resource, prismContext); } private void assertAccountShadow(PrismObject<ShadowType> accObject, PrismObject<ResourceType> resource, PrismContext prismContext) throws SchemaException, JAXBException { ResourceType resourceType = resource.asObjectable(); QName objectClassQName = new QName(ResourceTypeUtil.getResourceNamespace(resourceType), "AccountObjectClass"); PrismAsserts.assertPropertyValue(accObject, ShadowType.F_NAME, createPolyString("jack")); PrismAsserts.assertPropertyValue(accObject, ShadowType.F_OBJECT_CLASS, objectClassQName); PrismAsserts.assertPropertyValue(accObject, ShadowType.F_INTENT, SchemaConstants.INTENT_DEFAULT); PrismContainer<?> attributes = accObject.findOrCreateContainer(SchemaConstants.C_ATTRIBUTES); assertEquals("Wrong type of <attributes> definition in account", ResourceAttributeContainerDefinitionImpl.class, attributes.getDefinition().getClass()); ResourceAttributeContainerDefinition attrDef = (ResourceAttributeContainerDefinition)attributes.getDefinition(); assertAttributeDefs(attrDef, resourceType, null, LayerType.MODEL); PrismAsserts.assertPropertyValue(attributes, SchemaTestConstants.ICFS_NAME, "uid=jack,ou=People,dc=example,dc=com"); PrismAsserts.assertPropertyValue(attributes, getAttrQName(resource, "cn"), "Jack Sparrow"); PrismAsserts.assertPropertyValue(attributes, getAttrQName(resource, "givenName"), "Jack"); PrismAsserts.assertPropertyValue(attributes, getAttrQName(resource, "sn"), "Sparrow"); PrismAsserts.assertPropertyValue(attributes, getAttrQName(resource, "uid"), "jack"); assertEquals("JAXB class name doesn't match (1)", ShadowType.class, accObject.getCompileTimeClass()); accObject.checkConsistence(); ShadowType accObjectType = accObject.asObjectable(); assertEquals("Wrong JAXB name", createPolyStringType("jack"), accObjectType.getName()); assertEquals("Wrong JAXB objectClass", objectClassQName, accObjectType.getObjectClass()); ShadowAttributesType attributesType = accObjectType.getAttributes(); assertNotNull("null ResourceObjectShadowAttributesType (JAXB)", attributesType); List<Object> attributeElements = attributesType.getAny(); TestUtil.assertElement(attributeElements, SchemaTestConstants.ICFS_NAME, "uid=jack,ou=People,dc=example,dc=com"); TestUtil.assertElement(attributeElements, getAttrQName(resource, "cn"), "Jack Sparrow"); TestUtil.assertElement(attributeElements, getAttrQName(resource, "givenName"), "Jack"); TestUtil.assertElement(attributeElements, getAttrQName(resource, "sn"), "Sparrow"); TestUtil.assertElement(attributeElements, getAttrQName(resource, "uid"), "jack"); String accString = PrismTestUtil.serializeObjectToString(accObjectType.asPrismObject()); System.out.println("Result of JAXB marshalling:\n"+accString); accObject.checkConsistence(true, true, ConsistencyCheckScope.THOROUGH); } private QName getAttrQName(PrismObject<ResourceType> resource, String localPart) { return new QName(ResourceTypeUtil.getResourceNamespace(resource), localPart); } @Test public void testCreateShadow() throws JAXBException, SchemaException, SAXException, IOException { System.out.println("\n===[ testCreateShadow ]===\n"); // GIVEN PrismContext prismContext = createInitializedPrismContext(); PrismObject<ResourceType> resource = prismContext.parseObject(RESOURCE_COMPLEX_FILE); ResourceType resourceType = resource.asObjectable(); RefinedResourceSchema rSchema = RefinedResourceSchemaImpl.parse(resourceType, prismContext); assertNotNull("Refined schema is null", rSchema); assertFalse("No account definitions", rSchema.getRefinedDefinitions(ShadowKindType.ACCOUNT).isEmpty()); RefinedObjectClassDefinition rAccount = rSchema.getRefinedDefinition(ShadowKindType.ACCOUNT, (String)null); // WHEN PrismObject<ShadowType> blankShadow = rAccount.createBlankShadow(); // THEN assertNotNull("No blank shadow", blankShadow); assertNotNull("No prism context in blank shadow", blankShadow.getPrismContext()); PrismObjectDefinition<ShadowType> objectDef = blankShadow.getDefinition(); assertNotNull("Blank shadow has no definition", objectDef); PrismContainerDefinition<?> attrDef = objectDef.findContainerDefinition(ShadowType.F_ATTRIBUTES); assertNotNull("Blank shadow has no definition for attributes", attrDef); assertTrue("Wrong class for attributes definition: "+attrDef.getClass(), attrDef instanceof ResourceAttributeContainerDefinition); } @Test public void testProtectedAccount() throws JAXBException, SchemaException, SAXException, IOException { System.out.println("\n===[ testProtectedAccount ]===\n"); // GIVEN PrismContext prismContext = createInitializedPrismContext(); PrismObject<ResourceType> resource = prismContext.parseObject(RESOURCE_COMPLEX_FILE); ResourceType resourceType = resource.asObjectable(); RefinedResourceSchema rSchema = RefinedResourceSchemaImpl.parse(resourceType, prismContext); assertNotNull("Refined schema is null", rSchema); assertFalse("No account definitions", rSchema.getRefinedDefinitions(ShadowKindType.ACCOUNT).isEmpty()); RefinedObjectClassDefinition rAccount = rSchema.getRefinedDefinition(ShadowKindType.ACCOUNT, (String)null); // WHEN Collection<ResourceObjectPattern> protectedAccounts = rAccount.getProtectedObjectPatterns(); // THEN assertNotNull("Null protectedAccounts", protectedAccounts); assertFalse("Empty protectedAccounts", protectedAccounts.isEmpty()); assertEquals("Unexpected number of protectedAccounts", 2, protectedAccounts.size()); Iterator<ResourceObjectPattern> iterator = protectedAccounts.iterator(); assertDeprecatedProtectedAccount("first protected account", iterator.next(), "uid=idm,ou=Administrators,dc=example,dc=com", rAccount); assertDeprecatedProtectedAccount("second protected account", iterator.next(), "uid=root,ou=Administrators,dc=example,dc=com", rAccount); } private void assertAttributeDefs(ResourceAttributeContainerDefinition attrsDef, ResourceType resourceType, LayerType sourceLayer, LayerType validationLayer) { assertNotNull("Null account definition", attrsDef); assertEquals(SchemaConstants.INTENT_DEFAULT, attrsDef.getIntent()); assertEquals("AccountObjectClass", attrsDef.getComplexTypeDefinition().getTypeName().getLocalPart()); assertEquals("Wrong objectclass in the definition of <attributes> definition in account", RefinedObjectClassDefinitionImpl.class, attrsDef.getComplexTypeDefinition().getClass()); RefinedObjectClassDefinition rAccount = (RefinedObjectClassDefinition) attrsDef.getComplexTypeDefinition(); assertRObjectClassDef(rAccount, resourceType, sourceLayer, validationLayer); } private void assertRObjectClassDef(RefinedObjectClassDefinition rAccount, ResourceType resourceType, LayerType sourceLayer, LayerType validationLayer) { assertTrue(rAccount.isDefault()); Collection<? extends RefinedAttributeDefinition> attrs = rAccount.getAttributeDefinitions(); assertFalse(attrs.isEmpty()); assertAttributeDef(attrs, SchemaTestConstants.ICFS_NAME, DOMUtil.XSD_STRING, 1, 1, "Distinguished Name", 110, true, false, true, true, validationLayer == LayerType.SCHEMA, // Access: create, read, update sourceLayer, validationLayer); assertAttributeDef(attrs, SchemaTestConstants.ICFS_UID, DOMUtil.XSD_STRING, 1, 1, "Entry UUID", 100, false, false, false, true, false, // Access: create, read, update sourceLayer, validationLayer); assertAttributeDef(attrs, new QName(ResourceTypeUtil.getResourceNamespace(resourceType), "cn"), DOMUtil.XSD_STRING, 1, (validationLayer == LayerType.MODEL || validationLayer == LayerType.PRESENTATION) ? 1 : -1, "Common Name", 1, true, validationLayer == LayerType.PRESENTATION, true, true, true, // Access: create, read, update sourceLayer, validationLayer); assertAttributeDef(attrs, new QName(ResourceTypeUtil.getResourceNamespace(resourceType), "uid"), DOMUtil.XSD_STRING, validationLayer == LayerType.SCHEMA ? 0 : 1 , // minOccurs validationLayer == LayerType.SCHEMA ? -1 : 1, // maxOccurs "Login Name", 2, true, false, true, true, validationLayer != LayerType.PRESENTATION, // Access: create, read, update sourceLayer, validationLayer); assertAttributeDef(attrs, new QName(ResourceTypeUtil.getResourceNamespace(resourceType), "employeeNumber"), DOMUtil.XSD_STRING, 0, 1, null, null, false, false, true, true, true, // Access: create, read, update sourceLayer, validationLayer); } private void assertAttributeDef(Collection<? extends RefinedAttributeDefinition> attrDefs, QName name, QName typeName, int minOccurs, int maxOccurs, String displayName, Integer displayOrder, boolean hasOutbound, boolean ignore, boolean canCreate, boolean canRead, boolean canUpdate, LayerType sourceLayer, LayerType validationLayer) { for (RefinedAttributeDefinition def : attrDefs) { if (def.getName().equals(name)) { assertEquals("Attribute " + name + " ("+sourceLayer+") type mismatch", typeName, def.getTypeName()); assertEquals("Attribute " + name + " ("+sourceLayer+") minOccurs mismatch", minOccurs, def.getMinOccurs()); assertEquals("Attribute " + name + " ("+sourceLayer+") maxOccurs mismatch", maxOccurs, def.getMaxOccurs()); if (validationLayer == LayerType.MODEL || validationLayer == LayerType.PRESENTATION) { assertEquals("Attribute " + name + " ("+sourceLayer+") displayName mismatch", displayName, def.getDisplayName()); assertEquals("Attribute " + name + " ("+sourceLayer+") displayOrder mismatch", displayOrder, def.getDisplayOrder()); assertEquals("Attribute " + name + " ("+sourceLayer+") outbound mismatch", hasOutbound, def.getOutboundMappingType() != null); } assertEquals("Attribute " + name + " ("+sourceLayer+") ignored flag mismatch", ignore, def.isIgnored()); assertEquals("Attribute " + name + " ("+sourceLayer+") canCreate mismatch", canCreate, def.canAdd()); assertEquals("Attribute " + name + " ("+sourceLayer+") canRead mismatch", canRead, def.canRead()); assertEquals("Attribute " + name + " ("+sourceLayer+") canUpdate mismatch", canUpdate, def.canModify()); return; } } Assert.fail("Attribute " + name + " not found"); } private void assertDeprecatedProtectedAccount(String message, ResourceObjectPattern protectedPattern, String identifierValue, RefinedObjectClassDefinition rAccount) throws SchemaException { Collection<ResourceAttribute<?>> identifiers = protectedPattern.getIdentifiers(); assertNotNull("Null identifiers in "+message, identifiers); assertEquals("Wrong number identifiers in "+message, 1, identifiers.size()); ResourceAttribute<?> identifier = identifiers.iterator().next(); assertNotNull("Null identifier in "+message, identifier); assertEquals("Wrong identifier value in "+message, identifier.getRealValue(), identifierValue); // Try matching PrismObject<ShadowType> shadow = rAccount.getObjectDefinition().instantiate(); ResourceAttributeContainer attributesContainer = ShadowUtil.getOrCreateAttributesContainer(shadow, rAccount); ResourceAttribute<String> confusingAttr1 = createStringAttribute(new QName("http://whatever.com","confuseMe"), "HowMuchWoodWouldWoodchuckChuckIfWoodchuckCouldChudkWood"); attributesContainer.add(confusingAttr1); ResourceAttribute<String> nameAttr = createStringAttribute(SchemaTestConstants.ICFS_NAME, identifierValue); attributesContainer.add(nameAttr); ResourceAttribute<String> confusingAttr2 = createStringAttribute(new QName("http://whatever.com","confuseMeAgain"), "WoodchuckWouldChuckNoWoodAsWoodchuckCannotChuckWood"); attributesContainer.add(confusingAttr2); assertTrue("Test attr not matched in "+message, protectedPattern.matches(shadow, null)); nameAttr.setRealValue("huhulumululul"); assertFalse("Test attr nonsense was matched in "+message, protectedPattern.matches(shadow, null)); } private ResourceAttribute<String> createStringAttribute(QName attrName, String value) { ResourceAttributeDefinition testAttrDef = new ResourceAttributeDefinitionImpl(attrName, DOMUtil.XSD_STRING, getPrismContext()); ResourceAttribute<String> testAttr = testAttrDef.instantiate(); testAttr.setRealValue(value); return testAttr; } @Test public void testParseFromResourcePosix() throws Exception { final String TEST_NAME = "testParseFromResourcePosix"; TestUtil.displayTestTile(TEST_NAME); // GIVEN PrismContext prismContext = createInitializedPrismContext(); PrismObject<ResourceType> resource = prismContext.parseObject(RESOURCE_POSIX_FILE); ResourceType resourceType = resource.asObjectable(); // WHEN TestUtil.displayWhen(TEST_NAME); RefinedResourceSchema rSchema = RefinedResourceSchemaImpl.parse(resourceType, prismContext); // THEN TestUtil.displayThen(TEST_NAME); assertNotNull("Refined schema is null", rSchema); System.out.println("Refined schema"); System.out.println(rSchema.debugDump()); assertFalse("No account definitions", rSchema.getRefinedDefinitions(ShadowKindType.ACCOUNT).isEmpty()); // ### default account objectType RefinedObjectClassDefinition rAccountDef = rSchema.getRefinedDefinition(ShadowKindType.ACCOUNT, (String)null); assertNotNull("No default account definition", rAccountDef); RefinedObjectClassDefinition accountDefByIcfAccountObjectclass = rSchema.findRefinedDefinitionByObjectClassQName(ShadowKindType.ACCOUNT, OBJECT_CLASS_INETORGPERSON_QNAME); assertTrue("findAccountDefinitionByObjectClass("+OBJECT_CLASS_INETORGPERSON_QNAME+") returned wrong value", rAccountDef.equals(accountDefByIcfAccountObjectclass)); assertTrue(rAccountDef.isDefault()); Collection<? extends RefinedAttributeDefinition> rAccountAttrs = rAccountDef.getAttributeDefinitions(); assertFalse(rAccountAttrs.isEmpty()); assertAttributeDef(rAccountAttrs, new QName(ResourceTypeUtil.getResourceNamespace(resourceType), "dn"), DOMUtil.XSD_STRING, 1, 1, "Distinguished Name", 110, true, false, true, true, true, // Access: create, read, update LayerType.SCHEMA, LayerType.PRESENTATION); assertAttributeDef(rAccountAttrs, new QName(ResourceTypeUtil.getResourceNamespace(resourceType), "entryUUID"), DOMUtil.XSD_STRING, 0, 1, null, 100, false, false, false, true, false, // Access: create, read, update LayerType.SCHEMA, LayerType.PRESENTATION); assertAttributeDef(rAccountAttrs, new QName(ResourceTypeUtil.getResourceNamespace(resourceType), "cn"), DOMUtil.XSD_STRING, 1, -1, "Common Name", 590, true, false, true, true, true, // Access: create, read, update LayerType.SCHEMA, LayerType.PRESENTATION); assertAttributeDef(rAccountAttrs, new QName(ResourceTypeUtil.getResourceNamespace(resourceType), "uid"), DOMUtil.XSD_STRING, 0, -1, "Login Name", 300, true, false, true, true, true, // Access: create, read, update LayerType.SCHEMA, LayerType.PRESENTATION); assertAttributeDef(rAccountAttrs, new QName(ResourceTypeUtil.getResourceNamespace(resourceType), "employeeNumber"), DOMUtil.XSD_STRING, 0, 1, null, 140, false, false, true, true, true, // Access: create, read, update LayerType.SCHEMA, LayerType.PRESENTATION); System.out.println("Refined account definitionn:"); System.out.println(rAccountDef.debugDump()); assertEquals("Wrong kind", ShadowKindType.ACCOUNT, rAccountDef.getKind()); Collection<? extends RefinedAttributeDefinition> accAttrsDef = rAccountDef.getAttributeDefinitions(); assertNotNull("Null attributeDefinitions", accAttrsDef); assertFalse("Empty attributeDefinitions", accAttrsDef.isEmpty()); assertEquals("Unexpected number of attributeDefinitions", 53, accAttrsDef.size()); RefinedAttributeDefinition disabledAttribute = rAccountDef.findAttributeDefinition("ds-pwp-account-disabled"); assertNotNull("No ds-pwp-account-disabled attribute", disabledAttribute); assertTrue("ds-pwp-account-disabled not ignored", disabledAttribute.isIgnored()); RefinedAttributeDefinition<?> displayNameAttributeDef = rAccountDef.getDisplayNameAttribute(); assertNotNull("No account displayNameAttribute", displayNameAttributeDef); assertEquals("Wrong account displayNameAttribute", new QName(ResourceTypeUtil.getResourceNamespace(resourceType), "dn"), displayNameAttributeDef.getName()); // This is compatibility with PrismContainerDefinition, it should work well Collection<? extends ItemDefinition> propertyDefinitions = rAccountDef.getDefinitions(); assertNotNull("Null propertyDefinitions", propertyDefinitions); assertFalse("Empty propertyDefinitions", propertyDefinitions.isEmpty()); assertEquals("Unexpected number of propertyDefinitions", 53, propertyDefinitions.size()); assertFalse("No entitlement definitions", rSchema.getRefinedDefinitions(ShadowKindType.ENTITLEMENT).isEmpty()); RefinedObjectClassDefinition rEntDef = rSchema.getRefinedDefinition(ShadowKindType.ENTITLEMENT, (String)null); assertNotNull("No entitlement definition for null intent", rEntDef); RefinedObjectClassDefinition rEntDefGroup = rSchema.getRefinedDefinition(ShadowKindType.ENTITLEMENT, ENTITLEMENT_LDAP_GROUP_INTENT); assertNotNull("No entitlement for intent '"+ENTITLEMENT_LDAP_GROUP_INTENT+"'", rEntDefGroup); assertEquals("Wrong kind", ShadowKindType.ENTITLEMENT, rEntDef.getKind()); Collection<? extends RefinedAttributeDefinition> entAttrDefs = rEntDef.getAttributeDefinitions(); assertNotNull("Null attributeDefinitions", entAttrDefs); assertFalse("Empty attributeDefinitions", entAttrDefs.isEmpty()); assertEquals("Unexpected number of attributeDefinitions", 12, entAttrDefs.size()); RefinedAttributeDefinition<?> entDisplayNameAttributeDef = rEntDef.getDisplayNameAttribute(); assertNotNull("No entitlement displayNameAttribute", entDisplayNameAttributeDef); assertEquals("Wrong entitlement displayNameAttribute", new QName(ResourceTypeUtil.getResourceNamespace(resourceType), "dn"), entDisplayNameAttributeDef.getName()); assertEquals("Unexpected number of entitlement associations", 1, rAccountDef.getEntitlementAssociationDefinitions().size()); ResourceAttributeContainerDefinition resAttrContainerDef = rAccountDef.toResourceAttributeContainerDefinition(); assertNotNull("No ResourceAttributeContainerDefinition", resAttrContainerDef); System.out.println("\nResourceAttributeContainerDefinition"); System.out.println(resAttrContainerDef.debugDump()); ObjectClassComplexTypeDefinition rComplexTypeDefinition = resAttrContainerDef.getComplexTypeDefinition(); System.out.println("\nResourceAttributeContainerDefinition ComplexTypeDefinition"); System.out.println(rComplexTypeDefinition.debugDump()); ResourceAttributeDefinition<String> riUidAttrDef = resAttrContainerDef.findAttributeDefinition(new QName(resourceType.getNamespace(), "uid")); assertNotNull("No ri:uid def in ResourceAttributeContainerDefinition", riUidAttrDef); System.out.println("\nri:uid def "+riUidAttrDef.getClass()); System.out.println(riUidAttrDef.debugDump()); } }