/* * 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.schema.parser; import com.evolveum.midpoint.prism.*; import com.evolveum.midpoint.prism.delta.ItemDelta; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.path.ItemPathSegment; import com.evolveum.midpoint.prism.path.NameItemPathSegment; import com.evolveum.midpoint.prism.util.PrismAsserts; import com.evolveum.midpoint.prism.util.PrismTestUtil; import com.evolveum.midpoint.prism.xnode.XNode; import com.evolveum.midpoint.schema.MidPointPrismContextFactory; import com.evolveum.midpoint.schema.SchemaConstantsGenerated; import com.evolveum.midpoint.schema.constants.MidPointConstants; import com.evolveum.midpoint.util.PrettyPrinter; import com.evolveum.midpoint.util.QNameUtil; import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType; import com.evolveum.prism.xml.ns._public.types_3.RawType; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeSuite; import org.testng.annotations.Optional; import org.testng.annotations.Parameters; import org.xml.sax.SAXException; import javax.xml.namespace.QName; import java.io.File; import java.io.IOException; import java.util.Collection; import static com.evolveum.midpoint.schema.TestConstants.COMMON_DIR_PATH; import static org.testng.AssertJUnit.*; /** * @author mederly */ public abstract class AbstractParserTest<T extends PrismValue> { protected String language; protected boolean namespaces; @BeforeSuite public void setup() throws SchemaException, SAXException, IOException { PrettyPrinter.setDefaultNamespacePrefix(MidPointConstants.NS_MIDPOINT_PUBLIC_PREFIX); PrismTestUtil.resetPrismContext(MidPointPrismContextFactory.FACTORY); } @BeforeClass @Parameters({ "language", "namespaces" }) public void temp(@Optional String language, @Optional Boolean namespaces) { this.language = language != null ? language : "xml"; this.namespaces = namespaces != null ? namespaces : Boolean.TRUE; System.out.println("Testing with language = " + this.language + ", namespaces = " + this.namespaces); } protected File getFile(String baseName) { return new File(COMMON_DIR_PATH + "/" + language + "/" + (namespaces ? "ns":"no-ns"), baseName + "." + language); } protected void displayTestTitle(String testName) { PrismTestUtil.displayTestTitle(testName + " (" + language + ", " + (namespaces ? "with" : "no") + " namespaces)"); } protected void assertPropertyDefinition(PrismContainer<?> container, String propName, QName xsdType, int minOccurs, int maxOccurs) { QName propQName = new QName(SchemaConstantsGenerated.NS_COMMON, propName); PrismAsserts.assertPropertyDefinition(container, propQName, xsdType, minOccurs, maxOccurs); } protected void assertPropertyValue(PrismContainer<?> container, String propName, Object propValue) { QName propQName = new QName(SchemaConstantsGenerated.NS_COMMON, propName); PrismAsserts.assertPropertyValue(container, propQName, propValue); } protected <T> void assertPropertyValues(PrismContainer<?> container, String propName, T... expectedValues) { QName propQName = new QName(SchemaConstantsGenerated.NS_COMMON, propName); PrismAsserts.assertPropertyValue(container, propQName, expectedValues); } protected void assertContainerDefinition(PrismContainer container, String contName, QName xsdType, int minOccurs, int maxOccurs) { QName qName = new QName(SchemaConstantsGenerated.NS_COMMON, contName); PrismAsserts.assertDefinition(container.getDefinition(), qName, xsdType, minOccurs, maxOccurs); } // partly covers the same functionality as item.assertDefinitions (TODO clean this) protected void assertDefinitions(Visitable value) { value.accept(v -> { if (v instanceof Item) { Item item = (Item) v; String label = item.getPath() + ": " + v; //System.out.println("Checking " + label); if (item.getDefinition() == null) { assertTrue("No definition in " + label, isDynamic(item.getPath())); } else { assertNotNull("No prism context in definition of " + label, item.getDefinition().getPrismContext()); } } else if (v instanceof PrismContainerValue) { PrismContainerValue pcv = (PrismContainerValue) v; String label = pcv.getPath() + ": " + v; //System.out.println("Checking " + label); if (pcv.getComplexTypeDefinition() == null) { fail("No complex type definition in " + label); } else { assertNotNull("No prism context in definition of " + label, pcv.getComplexTypeDefinition().getPrismContext()); } } }); } protected void assertResolvableRawValues(Visitable value) { value.accept(v -> { // TODO in RawTypes in beans? if (v instanceof PrismPropertyValue) { PrismPropertyValue ppv = (PrismPropertyValue) v; XNode raw = ppv.getRawElement(); if (raw != null && raw.getTypeQName() != null) { String label = ppv.getPath() + ": " + v; fail("Resolvable raw value of " + raw + " in " + label + " (type: " + raw.getTypeQName() + ")"); } } }); } protected void assertPrismContext(Visitable value) { value.accept(v -> { if (v instanceof Item) { Item item = (Item) v; String label = item.getPath() + ": " + v; assertNotNull("No prism context in " + label, item.getPrismContextLocal()); } else if (v instanceof PrismContainerValue) { PrismContainerValue pcv = (PrismContainerValue) v; String label = pcv.getPath() + ": " + v; assertNotNull("No prism context in " + label, pcv.getPrismContextLocal()); } }); } private boolean isDynamic(ItemPath path) { for (ItemPathSegment segment : path.getSegments()) { if (segment instanceof NameItemPathSegment) { QName name = ((NameItemPathSegment) segment).getName(); if (QNameUtil.match(name, ShadowType.F_ATTRIBUTES) || QNameUtil.match(name, ObjectType.F_EXTENSION)) { return true; } } } return false; } @FunctionalInterface interface ParsingFunction<V> { V apply(PrismParser prismParser) throws Exception; } @FunctionalInterface interface SerializingFunction<V> { String apply(V value) throws Exception; } protected void process(String desc, ParsingFunction<T> parser, SerializingFunction<T> serializer, String serId) throws Exception { PrismContext prismContext = getPrismContext(); System.out.println("================== Starting test for '" + desc + "' (serializer: " + serId + ") =================="); T value = parser.apply(prismContext.parserFor(getFile())); assertResolvableRawValues(value); // should be right here, before any getValue is called (TODO reconsider) System.out.println("Parsed value: " + desc); System.out.println(value.debugDump()); assertPrismValue(value); if (serializer != null) { String serialized = serializer.apply(value); System.out.println("Serialized:\n" + serialized); T reparsed = parser.apply(prismContext.parserFor(serialized)); assertResolvableRawValues(reparsed); // should be right here, before any getValue is called (TODO reconsider) System.out.println("Reparsed: " + desc); System.out.println(reparsed.debugDump()); assertPrismValue(reparsed); Collection<? extends ItemDelta> deltas = value.diff(reparsed); assertTrue("Deltas not empty", deltas.isEmpty()); assertTrue("Values not equal", value.equals(reparsed)); } } protected abstract File getFile(); protected abstract void assertPrismValue(T value) throws SchemaException; protected boolean isContainer() { return false; } protected PrismContext getPrismContext() { return PrismTestUtil.getPrismContext(); } }