/*
* 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.
*/
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.evolveum.midpoint.schema.processor;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import com.evolveum.midpoint.prism.PrismConstants;
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.PrismPropertyDefinition;
import com.evolveum.midpoint.prism.util.PrismTestUtil;
import com.evolveum.midpoint.schema.CapabilityUtil;
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.ObjectTypeUtil;
import com.evolveum.midpoint.schema.util.ResourceTypeUtil;
import com.evolveum.midpoint.schema.util.SchemaTestConstants;
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.CredentialsType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowKindType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.XmlSchemaType;
import com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.ActivationCapabilityType;
import com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.CredentialsCapabilityType;
import com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.LiveSyncCapabilityType;
import com.evolveum.prism.xml.ns._public.types_3.ProtectedStringType;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;
import javax.xml.bind.JAXBException;
import javax.xml.namespace.QName;
import static org.testng.AssertJUnit.*;
/**
* @author semancik
*/
public class TestResourceSchema {
private static final String TEST_DIR = "src/test/resources/processor/";
private static final String RESOURCE_SCHEMA_SIMPLE_FILENAME = TEST_DIR + "resource-schema-simple.xsd";
private static final String RESOURCE_SCHEMA_SIMPLE_DEPRECATED_FILENAME = TEST_DIR + "resource-schema-simple-deprecated.xsd";
private static final String SCHEMA_NAMESPACE = "http://schema.foo.com/bar";
public TestResourceSchema() {
}
@BeforeSuite
public void setup() throws SchemaException, SAXException, IOException {
PrettyPrinter.setDefaultNamespacePrefix(MidPointConstants.NS_MIDPOINT_PUBLIC_PREFIX);
PrismTestUtil.resetPrismContext(MidPointPrismContextFactory.FACTORY);
}
@Test
public void testParseSchema() throws Exception {
System.out.println("===[ testParseSchema ]===");
// GIVEN
Document schemaDom = DOMUtil.parseFile(RESOURCE_SCHEMA_SIMPLE_FILENAME);
// WHEN
ResourceSchema schema = ResourceSchemaImpl.parse(DOMUtil.getFirstChildElement(schemaDom),
RESOURCE_SCHEMA_SIMPLE_FILENAME, PrismTestUtil.getPrismContext());
// THEN
assertSimpleSchema(schema, RESOURCE_SCHEMA_SIMPLE_FILENAME);
}
@Test
public void testParseSchemaDeprecated() throws Exception {
System.out.println("===[ testParseSchemaDeprecated ]===");
// GIVEN
Document schemaDom = DOMUtil.parseFile(RESOURCE_SCHEMA_SIMPLE_DEPRECATED_FILENAME);
// WHEN
ResourceSchema schema = ResourceSchemaImpl.parse(DOMUtil.getFirstChildElement(schemaDom),
RESOURCE_SCHEMA_SIMPLE_DEPRECATED_FILENAME, PrismTestUtil.getPrismContext());
// THEN
assertSimpleSchema(schema, RESOURCE_SCHEMA_SIMPLE_DEPRECATED_FILENAME);
}
private void assertSimpleSchema(ResourceSchema schema, String filename) {
assertNotNull(schema);
System.out.println("Parsed schema from " + filename + ":");
System.out.println(schema.debugDump());
ObjectClassComplexTypeDefinition accDef = schema.findObjectClassDefinition(new QName(SCHEMA_NAMESPACE, "AccountObjectClass"));
assertEquals("Wrong account objectclass", new QName(SCHEMA_NAMESPACE, "AccountObjectClass"), accDef.getTypeName());
assertEquals("Wrong account kind", ShadowKindType.ACCOUNT, accDef.getKind());
assertEquals("Wrong account intent", "admin", accDef.getIntent());
assertTrue("Not a default account", accDef.isDefaultInAKind());
PrismPropertyDefinition<String> loginAttrDef = accDef.findPropertyDefinition(new QName(SCHEMA_NAMESPACE, "login"));
assertEquals(new QName(SCHEMA_NAMESPACE, "login"), loginAttrDef.getName());
assertEquals(DOMUtil.XSD_STRING, loginAttrDef.getTypeName());
assertFalse("Ignored while it should not be", loginAttrDef.isIgnored());
PrismPropertyDefinition<Integer> groupAttrDef = accDef.findPropertyDefinition(new QName(SCHEMA_NAMESPACE, "group"));
assertEquals(new QName(SCHEMA_NAMESPACE, "group"), groupAttrDef.getName());
assertEquals(DOMUtil.XSD_INT, groupAttrDef.getTypeName());
assertFalse("Ignored while it should not be", groupAttrDef.isIgnored());
PrismPropertyDefinition<String> ufoAttrDef = accDef.findPropertyDefinition(new QName(SCHEMA_NAMESPACE, "ufo"));
assertEquals(new QName(SCHEMA_NAMESPACE, "ufo"), ufoAttrDef.getName());
assertTrue("Not ignored as it should be", ufoAttrDef.isIgnored());
ObjectClassComplexTypeDefinition groupDef = schema.findObjectClassDefinition(new QName(SCHEMA_NAMESPACE, "GroupObjectClass"));
assertEquals("Wrong group objectclass", new QName(SCHEMA_NAMESPACE, "GroupObjectClass"), groupDef.getTypeName());
assertEquals("Wrong group kind", ShadowKindType.ENTITLEMENT, groupDef.getKind());
assertEquals("Wrong group intent", null, groupDef.getIntent());
assertFalse("Default group but it should not be", groupDef.isDefaultInAKind());
}
// The support for the xsd:any properties is missing in JAXB generator. Otherwise this test should work.
@Test(enabled=false)
public void testResourceSchemaJaxbRoundTrip() throws SchemaException, JAXBException {
System.out.println("\n===[ testResourceSchemaJaxbRoundTrip ]=====");
// GIVEN
ResourceSchema schema = createResourceSchema();
System.out.println("Resource schema before serializing to XSD: ");
System.out.println(schema.debugDump());
System.out.println();
Document xsd = schema.serializeToXsd();
ResourceType resource = new ResourceType();
resource.setName(PrismTestUtil.createPolyStringType("JAXB With Dynamic Schemas Test"));
ResourceTypeUtil.setResourceXsdSchema(resource, DOMUtil.getFirstChildElement(xsd));
// WHEN
// JAXBElement<ResourceType> resourceElement = new JAXBElement<ResourceType>(SchemaConstants.C_RESOURCE, ResourceType.class, resource);
// String marshalledResource = PrismTestUtil.marshalElementToString(resourceElement);
String marshalledResource = PrismTestUtil.serializeObjectToString(resource.asPrismObject());
System.out.println("Marshalled resource");
System.out.println(marshalledResource);
ResourceType unmarshalledResource = (ResourceType) PrismTestUtil.parseObject(marshalledResource).asObjectable();
System.out.println("unmarshalled resource");
System.out.println(ObjectTypeUtil.dump(unmarshalledResource));
XmlSchemaType unXmlSchemaType = unmarshalledResource.getSchema();
Element unXsd = unXmlSchemaType.getDefinition().getAny().get(0);
ResourceSchema unSchema = ResourceSchemaImpl.parse(unXsd, "unmarshalled resource", PrismTestUtil.getPrismContext());
System.out.println("unmarshalled schema");
System.out.println(unSchema.debugDump());
// THEN
assertResourceSchema(unSchema);
}
@Test
public void testResourceSchemaPrismRoundTrip() throws SchemaException, JAXBException {
System.out.println("\n===[ testResourceSchemaPrismRoundTrip ]=====");
// GIVEN
ResourceSchema schema = createResourceSchema();
System.out.println("Resource schema before serializing to XSD: ");
System.out.println(schema.debugDump());
System.out.println();
PrismContext prismContext = PrismTestUtil.getPrismContext();
Document xsd = schema.serializeToXsd();
PrismObjectDefinition<ResourceType> resourceDefinition = prismContext.getSchemaRegistry().findObjectDefinitionByCompileTimeClass(ResourceType.class);
PrismObject<ResourceType> resource = resourceDefinition.instantiate();
ResourceType resourceType = resource.asObjectable();
resourceType.setName(PrismTestUtil.createPolyStringType("Prism With Dynamic Schemas Test"));
ResourceTypeUtil.setResourceXsdSchema(resource, DOMUtil.getFirstChildElement(xsd));
// WHEN
String marshalledResource = prismContext.serializeObjectToString(resource, PrismContext.LANG_XML);
System.out.println("Marshalled resource");
System.out.println(marshalledResource);
PrismObject<ResourceType> unmarshalledResource = PrismTestUtil.parseObject(marshalledResource);
System.out.println("unmarshalled resource");
System.out.println(unmarshalledResource.debugDump());
Element unXsd = ResourceTypeUtil.getResourceXsdSchema(unmarshalledResource);
System.out.println("unmarshalled resource schema");
System.out.println(DOMUtil.serializeDOMToString(unXsd));
ResourceSchema unSchema = ResourceSchemaImpl.parse(unXsd, "unmarshalled resource schema", PrismTestUtil.getPrismContext());
System.out.println("unmarshalled parsed schema");
System.out.println(unSchema.debugDump());
// THEN
assertResourceSchema(unSchema);
}
private void assertResourceSchema(ResourceSchema unSchema) {
ObjectClassComplexTypeDefinition objectClassDef = unSchema.findObjectClassDefinition(new QName(SCHEMA_NAMESPACE,"AccountObjectClass"));
assertEquals(new QName(SCHEMA_NAMESPACE,"AccountObjectClass"),objectClassDef.getTypeName());
assertEquals("AccountObjectClass class not an account", ShadowKindType.ACCOUNT, objectClassDef.getKind());
assertTrue("AccountObjectClass class not a DEFAULT account", objectClassDef.isDefaultInAKind());
PrismPropertyDefinition<String> loginDef = objectClassDef.findPropertyDefinition(new QName(SCHEMA_NAMESPACE,"login"));
assertEquals(new QName(SCHEMA_NAMESPACE,"login"), loginDef.getName());
assertEquals(DOMUtil.XSD_STRING, loginDef.getTypeName());
PrismPropertyDefinition<ProtectedStringType> passwdDef = objectClassDef.findPropertyDefinition(new QName(SCHEMA_NAMESPACE,"password"));
assertEquals(new QName(SCHEMA_NAMESPACE,"password"), passwdDef.getName());
assertEquals(ProtectedStringType.COMPLEX_TYPE, passwdDef.getTypeName());
// PrismContainerDefinition<CredentialsType> credDef = objectClassDef.findContainerDefinition(new QName(SchemaConstants.NS_C,"credentials"));
// assertEquals(new QName(SchemaConstants.NS_C,"credentials"), credDef.getName());
// assertEquals(new QName(SchemaConstants.NS_C,"CredentialsType"), credDef.getTypeName());
}
@Test
public void testResourceSchemaSerializationDom() throws SchemaException, JAXBException {
System.out.println("\n===[ testResourceSchemaSerializationDom ]=====");
// GIVEN
ResourceSchema schema = createResourceSchema();
// WHEN
Document xsdDocument = schema.serializeToXsd();
Element xsdElement = DOMUtil.getFirstChildElement(xsdDocument);
System.out.println("Serialized XSD schema");
System.out.println(DOMUtil.serializeDOMToString(xsdElement));
assertDomSchema(xsdElement);
}
@Test
public void testResourceSchemaSerializationInResource() throws SchemaException, JAXBException {
System.out.println("\n===[ testResourceSchemaSerializationInResource ]=====");
// GIVEN
ResourceSchema schema = createResourceSchema();
// WHEN
Document xsdDocument = schema.serializeToXsd();
Element xsdElement = DOMUtil.getFirstChildElement(xsdDocument);
PrismObject<ResourceType> resource = wrapInResource(xsdElement);
String resourceXmlString = PrismTestUtil.getPrismContext().serializeObjectToString(resource, PrismContext.LANG_XML);
System.out.println("Serialized resource");
System.out.println(resourceXmlString);
PrismObject<ResourceType> reparsedResource = PrismTestUtil.getPrismContext().parseObject(resourceXmlString);
System.out.println("Re-parsed resource");
System.out.println(reparsedResource.debugDump());
XmlSchemaType reparsedSchemaType = reparsedResource.asObjectable().getSchema();
Element reparsedXsdElement = ObjectTypeUtil.findXsdElement(reparsedSchemaType);
System.out.println("Reparsed XSD schema");
System.out.println(DOMUtil.serializeDOMToString(reparsedXsdElement));
assertDomSchema(reparsedXsdElement);
}
private PrismObject<ResourceType> wrapInResource(Element xsdElement) throws SchemaException {
PrismObjectDefinition<ResourceType> resourceDefinition =
PrismTestUtil.getPrismContext().getSchemaRegistry().findObjectDefinitionByCompileTimeClass(ResourceType.class);
PrismObject<ResourceType> resource = resourceDefinition.instantiate();
ResourceTypeUtil.setResourceXsdSchema(resource, xsdElement);
return resource;
}
private void assertDomSchema(Element xsdElement) {
assertPrefix("xsd", xsdElement);
Element displayNameAnnotationElement = DOMUtil.findElementRecursive(xsdElement, PrismConstants.A_DISPLAY_NAME);
assertPrefix(PrismConstants.PREFIX_NS_ANNOTATION, displayNameAnnotationElement);
Element kindAnnotationElement = DOMUtil.findElementRecursive(xsdElement, MidPointConstants.RA_KIND);
assertPrefix("ra", kindAnnotationElement);
assertEquals(ShadowKindType.ACCOUNT.value(), kindAnnotationElement.getTextContent());
Element identifierAnnotationElement = DOMUtil.findElementRecursive(xsdElement, MidPointConstants.RA_IDENTIFIER);
assertPrefix("ra", identifierAnnotationElement);
QName identifier = DOMUtil.getQNameValue(identifierAnnotationElement);
assertEquals("Wrong <a:identifier> value namespace", SchemaTestConstants.ICFS_UID.getNamespaceURI(), identifier.getNamespaceURI());
assertEquals("Wrong <a:identifier> value localname", SchemaTestConstants.ICFS_UID.getLocalPart(), identifier.getLocalPart());
assertEquals("Wrong <a:identifier> value prefix", "icfs", identifier.getPrefix());
Element dnaAnnotationElement = DOMUtil.findElementRecursive(xsdElement, MidPointConstants.RA_DISPLAY_NAME_ATTRIBUTE);
assertPrefix("ra", dnaAnnotationElement);
QName dna = DOMUtil.getQNameValue(dnaAnnotationElement);
assertEquals("Wrong <a:identifier> value prefix", "tns", dna.getPrefix());
assertEquals("Wrong 'tns' prefix declaration", SCHEMA_NAMESPACE, xsdElement.lookupNamespaceURI("tns"));
}
private ResourceSchema createResourceSchema() {
ResourceSchemaImpl schema = new ResourceSchemaImpl(SCHEMA_NAMESPACE, PrismTestUtil.getPrismContext());
// Property container
ObjectClassComplexTypeDefinitionImpl containerDefinition = (ObjectClassComplexTypeDefinitionImpl) schema.createObjectClassDefinition("AccountObjectClass");
containerDefinition.setKind(ShadowKindType.ACCOUNT);
containerDefinition.setDefaultInAKind(true);
containerDefinition.setDisplayName("The Account");
containerDefinition.setNativeObjectClass("ACCOUNT");
// ... in it ordinary attribute - an identifier
ResourceAttributeDefinition<String> icfUidDef = containerDefinition.createAttributeDefinition(
SchemaTestConstants.ICFS_UID, DOMUtil.XSD_STRING);
((Collection)containerDefinition.getPrimaryIdentifiers()).add(icfUidDef);
ResourceAttributeDefinitionImpl<String> xloginDef = containerDefinition.createAttributeDefinition("login", DOMUtil.XSD_STRING);
xloginDef.setNativeAttributeName("LOGIN");
containerDefinition.setDisplayNameAttribute(xloginDef.getName());
// ... and local property with a type from another schema
ResourceAttributeDefinitionImpl<String> xpasswdDef = containerDefinition.createAttributeDefinition("password", ProtectedStringType.COMPLEX_TYPE);
xpasswdDef.setNativeAttributeName("PASSWORD");
// ... property reference
// TODO this should not go here, as it is not a ResourceAttributeDefinition
//containerDefinition.createAttributeDefinition(SchemaConstants.C_CREDENTIALS, SchemaConstants.C_CREDENTIALS_TYPE);
return schema;
}
private void assertPrefix(String expectedPrefix, Element element) {
assertEquals("Wrong prefix on element "+DOMUtil.getQName(element), expectedPrefix, element.getPrefix());
}
@Test
public void testParseResource() throws Exception {
System.out.println("===[ testParseResource ]===");
// WHEN
PrismObject<ResourceType> resource = PrismTestUtil.parseObject(new File("src/test/resources/common/xml/ns/resource-opendj.xml"));
// THEN
assertCapabilities(resource.asObjectable());
}
@Test
public void testUnmarshallResource() throws Exception {
System.out.println("===[ testUnmarshallResource ]===");
// WHEN
ResourceType resourceType = (ResourceType) PrismTestUtil.parseObject(new File("src/test/resources/common/xml/ns/resource-opendj.xml")).asObjectable();
// THEN
assertCapabilities(resourceType);
}
private void assertCapabilities(ResourceType resourceType) throws SchemaException {
if (resourceType.getCapabilities() != null) {
if (resourceType.getCapabilities().getNative() != null) {
for (Object capability : resourceType.getCapabilities().getNative().getAny()) {
System.out.println("Native Capability: "+CapabilityUtil.getCapabilityDisplayName(capability)+" : "+capability);
}
}
if (resourceType.getCapabilities().getConfigured() != null) {
for (Object capability : resourceType.getCapabilities().getConfigured().getAny()) {
System.out.println("Configured Capability: "+CapabilityUtil.getCapabilityDisplayName(capability)+" : "+capability);
}
}
}
List<Object> effectiveCapabilities = ResourceTypeUtil.getEffectiveCapabilities(resourceType);
for (Object capability : effectiveCapabilities) {
System.out.println("Efective Capability: "+CapabilityUtil.getCapabilityDisplayName(capability)+" : "+capability);
}
assertNotNull("null native capabilities", resourceType.getCapabilities().getNative());
assertFalse("empty native capabilities", resourceType.getCapabilities().getNative().getAny().isEmpty());
assertEquals("Unexepected number of native capabilities", 3, resourceType.getCapabilities().getNative().getAny().size());
assertNotNull("null configured capabilities", resourceType.getCapabilities().getConfigured());
assertFalse("empty configured capabilities", resourceType.getCapabilities().getConfigured().getAny().isEmpty());
assertEquals("Unexepected number of configured capabilities", 2, resourceType.getCapabilities().getConfigured().getAny().size());
assertEquals("Unexepected number of effective capabilities", 3,effectiveCapabilities.size());
assertNotNull("No credentials effective capability",
ResourceTypeUtil.getEffectiveCapability(resourceType, CredentialsCapabilityType.class));
assertNotNull("No activation effective capability",
ResourceTypeUtil.getEffectiveCapability(resourceType, ActivationCapabilityType.class));
assertNull("Unexpected liveSync effective capability",
ResourceTypeUtil.getEffectiveCapability(resourceType, LiveSyncCapabilityType.class));
}
}