package org.codehaus.mojo.jaxb2.schemageneration.postprocessing; import org.apache.maven.plugin.MojoExecutionException; import org.codehaus.mojo.jaxb2.BufferingLog; import org.codehaus.mojo.jaxb2.schemageneration.XsdGeneratorHelper; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.AbstractSourceCodeAwareNodeProcessingTest; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.JavaDocExtractor; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.NoAuthorJavaDocRenderer; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.SearchableDocumentation; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.XsdAnnotationProcessor; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.XsdEnumerationAnnotationProcessor; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.schemaenhancement.ChangeNamespacePrefixProcessor; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.schemaenhancement.SimpleNamespaceResolver; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.schemaenhancement.TransformSchema; import org.codehaus.mojo.jaxb2.shared.FileSystemUtilities; import org.codehaus.mojo.jaxb2.shared.filters.Filter; import org.codehaus.mojo.jaxb2.shared.filters.Filters; import org.codehaus.mojo.jaxb2.shared.filters.pattern.PatternFileFilter; import org.custommonkey.xmlunit.Diff; import org.custommonkey.xmlunit.ElementNameAndAttributeQualifier; import org.custommonkey.xmlunit.XMLAssert; import org.custommonkey.xmlunit.XMLUnit; import org.junit.Assert; import org.junit.Test; import org.w3c.dom.Document; import se.jguru.nazgul.test.xmlbinding.XmlTestUtils; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.TransformerFactory; import java.io.File; import java.io.StringReader; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; /** * @author <a href="mailto:lj@jguru.se">Lennart Jörelid</a> */ public class XsdGeneratorHelperTest { private static final TransformerFactory FACTORY = TransformerFactory.newInstance(); static { // Configure XMLUnit. XMLUnit.setIgnoreWhitespace(true); XMLUnit.setIgnoreAttributeOrder(true); // Configure the TransformerFactory FACTORY.setAttribute("indent-number", 2); } @Test(expected = MojoExecutionException.class) public void validateExceptionThrownOnDuplicateURIs() throws MojoExecutionException { // Assemble final TransformSchema transformSchema1 = new TransformSchema("foo", "foo", "foo"); final TransformSchema transformSchema2 = new TransformSchema("foo", "bar", "bar"); final List<TransformSchema> transformSchemas = new ArrayList<TransformSchema>(); transformSchemas.add(transformSchema1); transformSchemas.add(transformSchema2); // Act & Assert XsdGeneratorHelper.validateSchemasInPluginConfiguration(transformSchemas); Assert.fail("Two schemas with same URIs should yield a MojoExecutionException."); } @Test(expected = MojoExecutionException.class) public void validateExceptionThrownOnDuplicatePrefixes() throws MojoExecutionException { // Assemble final TransformSchema transformSchema1 = new TransformSchema("foo", "foo", "foo"); final TransformSchema transformSchema2 = new TransformSchema("bar", "foo", "bar"); final List<TransformSchema> transformSchemas = new ArrayList<TransformSchema>(); transformSchemas.add(transformSchema1); transformSchemas.add(transformSchema2); // Act & Assert XsdGeneratorHelper.validateSchemasInPluginConfiguration(transformSchemas); Assert.fail("Two schemas with same Prefixes should yield a MojoExecutionException."); } @Test public void validateNoExceptionThrownOnDuplicateNullPrefixes() { // Assemble final TransformSchema transformSchema1 = new TransformSchema("foo", null, "foo"); final TransformSchema transformSchema2 = new TransformSchema("bar", null, "bar"); final List<TransformSchema> transformSchemas = new ArrayList<TransformSchema>(); transformSchemas.add(transformSchema1); transformSchemas.add(transformSchema2); // Act & Assert try { XsdGeneratorHelper.validateSchemasInPluginConfiguration(transformSchemas); } catch (MojoExecutionException e) { Assert.fail("Two schemas with null Prefix should not yield a MojoExecutionException."); } } @Test public void validateExceptionThrownOnDuplicateFiles() { // Assemble final TransformSchema transformSchema1 = new TransformSchema("foo", "foo", "foo.xsd"); final TransformSchema transformSchema2 = new TransformSchema("bar", "bar", "foo.xsd"); final List<TransformSchema> transformSchemas = new ArrayList<TransformSchema>(); transformSchemas.add(transformSchema1); transformSchemas.add(transformSchema2); // Act & Assert try { XsdGeneratorHelper.validateSchemasInPluginConfiguration(transformSchemas); Assert.fail("Two schemas with same Files should yield a MojoExecutionException."); } catch (MojoExecutionException e) { // Validate the error message. String expectedMessage = "Misconfiguration detected: Duplicate 'file' property with value [foo.xsd] " + "found in plugin configuration. Correct schema elements index (0) and (1), " + "to ensure that all 'file' values are unique."; Assert.assertEquals(expectedMessage, e.getLocalizedMessage()); } } @Test(expected = MojoExecutionException.class) public void validateExceptionThrownOnOnlyUriGiven() throws MojoExecutionException { // Assemble final TransformSchema transformSchema1 = new TransformSchema("foo", null, ""); final List<TransformSchema> transformSchemas = new ArrayList<TransformSchema>(); transformSchemas.add(transformSchema1); // Act & Assert XsdGeneratorHelper.validateSchemasInPluginConfiguration(transformSchemas); Assert.fail("A schema definition with no prefix or file should yield a MojoExecutionException."); } @Test(expected = MojoExecutionException.class) public void validateExceptionThrownOnNullUri() throws MojoExecutionException { // Assemble final TransformSchema transformSchema1 = new TransformSchema(null, "foo", "bar"); final List<TransformSchema> transformSchemas = new ArrayList<TransformSchema>(); transformSchemas.add(transformSchema1); // Act & Assert XsdGeneratorHelper.validateSchemasInPluginConfiguration(transformSchemas); Assert.fail("A schema definition with null URI should yield a MojoExecutionException."); } @Test(expected = MojoExecutionException.class) public void validateExceptionThrownOnEmptyUri() throws MojoExecutionException { // Assemble final TransformSchema transformSchema1 = new TransformSchema("", "foo", "bar"); final List<TransformSchema> transformSchemas = new ArrayList<TransformSchema>(); transformSchemas.add(transformSchema1); // Act & Assert XsdGeneratorHelper.validateSchemasInPluginConfiguration(transformSchemas); Assert.fail("A schema definition with empty URI should yield a MojoExecutionException."); } @Test public void validateProcessingNodes() { // Assemble final String newPrefix = "changedFoo"; final String oldPrefix = "foo"; final String originalXml = getXmlDocumentSample(oldPrefix); final String changedXml = getXmlDocumentSample(newPrefix); final NodeProcessor changeNamespacePrefixProcessor = new ChangeNamespacePrefixProcessor(oldPrefix, newPrefix); // Act final Document processedDocument = XsdGeneratorHelper.parseXmlStream(new StringReader(originalXml)); XsdGeneratorHelper.process(processedDocument.getFirstChild(), true, changeNamespacePrefixProcessor); // Assert final Document expectedDocument = XsdGeneratorHelper.parseXmlStream(new StringReader(changedXml)); final Diff diff = new Diff(expectedDocument, processedDocument, null, new ElementNameAndAttributeQualifier()); diff.overrideElementQualifier(new ElementNameAndAttributeQualifier()); XMLAssert.assertXMLEqual(processedDocument, expectedDocument); } @Test public void validateProcessingXSDsWithEnumerations() throws Exception { // Assemble final BufferingLog log = new BufferingLog(); final JavaDocExtractor extractor = new JavaDocExtractor(log); extractor.setEncoding("UTF-8"); final String parentPath = "testdata/schemageneration/javadoc/enums/"; final URL parentPathURL = getClass().getClassLoader().getResource(parentPath); Assert.assertNotNull(parentPathURL); final File parentDir = new File(parentPathURL.getPath()); Assert.assertTrue(parentDir.exists() && parentDir.isDirectory()); final List<Filter<File>> excludeFilesMatching = new ArrayList<Filter<File>>(); excludeFilesMatching.add(new PatternFileFilter(Collections.singletonList("\\.xsd"))); Filters.initialize(log, excludeFilesMatching); final List<File> allSourceFiles = FileSystemUtilities.filterFiles(parentDir, null, parentDir.getAbsolutePath(), log, "allJavaFiles", excludeFilesMatching); Assert.assertEquals(3, allSourceFiles.size()); final List<URL> urls = new ArrayList<URL>(); for (File current : allSourceFiles) { try { urls.add(current.toURI().toURL()); } catch (MalformedURLException e) { throw new IllegalArgumentException("Could not convert file [" + current.getAbsolutePath() + "] to a URL", e); } } Assert.assertEquals(3, urls.size()); extractor.addSourceURLs(urls); final SearchableDocumentation docs = extractor.process(); // #1) The raw / un-processed XSD (containing the 'before' state) // #2) The processed XSD (containing the 'expected' state) final String rawEnumSchema = XmlTestUtils.readFully(parentPath + "rawEnumSchema.xsd"); final String processedEnumSchema = XmlTestUtils.readFully(parentPath + "processedEnumSchema.xsd"); final NodeProcessor enumProcessor = new XsdEnumerationAnnotationProcessor(docs, new NoAuthorJavaDocRenderer()); // Act final Document processedDocument = XsdGeneratorHelper.parseXmlStream(new StringReader(rawEnumSchema)); XsdGeneratorHelper.process(processedDocument.getFirstChild(), true, enumProcessor); // System.out.println("Got: " + AbstractSourceCodeAwareNodeProcessingTest.printDocument(processedDocument)); // Assert final Document expectedDocument = XsdGeneratorHelper.parseXmlStream(new StringReader(processedEnumSchema)); final Diff diff = new Diff(expectedDocument, processedDocument, null, new ElementNameAndAttributeQualifier()); diff.overrideElementQualifier(new ElementNameAndAttributeQualifier()); XMLAssert.assertXMLEqual(processedDocument, expectedDocument); } @Test public void validateXmlDocumentationForWrappers() throws Exception { // Assemble final BufferingLog log = new BufferingLog(); final JavaDocExtractor extractor = new JavaDocExtractor(log); extractor.setEncoding("UTF-8"); final String parentPath = "testdata/schemageneration/javadoc/xmlwrappers/"; final URL parentPathURL = getClass().getClassLoader().getResource(parentPath); Assert.assertNotNull(parentPathURL); final String schemaGenCreatedSchema = XmlTestUtils.readFully(parentPath + "expectedRawXmlWrappers.xsd"); final File parentDir = new File(parentPathURL.getPath()); Assert.assertTrue(parentDir.exists() && parentDir.isDirectory()); final List<Filter<File>> excludeFilesMatching = new ArrayList<Filter<File>>(); excludeFilesMatching.add(new PatternFileFilter(Collections.singletonList("\\.xsd"))); Filters.initialize(log, excludeFilesMatching); final List<File> allSourceFiles = FileSystemUtilities.filterFiles(parentDir, null, parentDir.getAbsolutePath(), log, "allJavaFiles", excludeFilesMatching); Assert.assertEquals(2, allSourceFiles.size()); final List<URL> urls = new ArrayList<URL>(); for (File current : allSourceFiles) { try { urls.add(current.toURI().toURL()); } catch (MalformedURLException e) { throw new IllegalArgumentException("Could not convert file [" + current.getAbsolutePath() + "] to a URL", e); } } Assert.assertEquals(2, urls.size()); // Act extractor.addSourceURLs(urls); final SearchableDocumentation docs = extractor.process(); final XsdAnnotationProcessor processor = new XsdAnnotationProcessor(docs, new NoAuthorJavaDocRenderer()); final Document schemaGenCreatedDocument = XsdGeneratorHelper.parseXmlStream( new StringReader(schemaGenCreatedSchema)); XsdGeneratorHelper.process(schemaGenCreatedDocument.getFirstChild(), true, processor); System.out.println("Got: " + AbstractSourceCodeAwareNodeProcessingTest.printDocument(schemaGenCreatedDocument)); // Assert } @Test public void validateAcquiringFilenameToResolverMap() throws MojoExecutionException { // Assemble final String[] expectedFilenames = {"schema1.xsd", "schema2.xsd", "schema3.xsd"}; final URL tmpUrl = getClass().getClassLoader().getResource("generated/schema/schema1.xsd"); final File directory = new File(tmpUrl.getFile()).getParentFile(); // Act final Map<String, SimpleNamespaceResolver> fileNameToResolverMap = XsdGeneratorHelper.getFileNameToResolverMap(directory); // Assert Assert.assertEquals(3, fileNameToResolverMap.size()); for (String current : expectedFilenames) { Assert.assertTrue(fileNameToResolverMap.keySet().contains(current)); } SimpleNamespaceResolver schema1Resolver = fileNameToResolverMap.get("schema1.xsd"); Assert.assertEquals("http://yet/another/namespace", schema1Resolver.getLocalNamespaceURI()); Assert.assertEquals("schema1.xsd", schema1Resolver.getSourceFilename()); final Map<String, String> schema1NamespaceURI2PrefixMap = schema1Resolver.getNamespaceURI2PrefixMap(); Assert.assertEquals(1, schema1NamespaceURI2PrefixMap.size()); Assert.assertEquals("xs", schema1NamespaceURI2PrefixMap.get("http://www.w3.org/2001/XMLSchema")); SimpleNamespaceResolver schema2Resolver = fileNameToResolverMap.get("schema2.xsd"); Assert.assertEquals("http://some/namespace", schema2Resolver.getLocalNamespaceURI()); Assert.assertEquals("schema2.xsd", schema2Resolver.getSourceFilename()); final Map<String, String> schema2NamespaceURI2PrefixMap = schema2Resolver.getNamespaceURI2PrefixMap(); Assert.assertEquals(2, schema2NamespaceURI2PrefixMap.size()); Assert.assertEquals("ns1", schema2NamespaceURI2PrefixMap.get("http://another/namespace")); Assert.assertEquals("xs", schema2NamespaceURI2PrefixMap.get("http://www.w3.org/2001/XMLSchema")); SimpleNamespaceResolver schema3Resolver = fileNameToResolverMap.get("schema3.xsd"); Assert.assertEquals("http://another/namespace", schema3Resolver.getLocalNamespaceURI()); Assert.assertEquals("schema3.xsd", schema3Resolver.getSourceFilename()); final Map<String, String> schema3NamespaceURI2PrefixMap = schema3Resolver.getNamespaceURI2PrefixMap(); Assert.assertEquals(3, schema3NamespaceURI2PrefixMap.size()); Assert.assertEquals("ns2", schema3NamespaceURI2PrefixMap.get("http://yet/another/namespace")); Assert.assertEquals("ns1", schema3NamespaceURI2PrefixMap.get("http://some/namespace")); Assert.assertEquals("xs", schema3NamespaceURI2PrefixMap.get("http://www.w3.org/2001/XMLSchema")); } // // Private helpers // private static DocumentBuilderFactory getDocumentBuilderFactory() { final DocumentBuilderFactory toReturn = DocumentBuilderFactory.newInstance(); toReturn.setNamespaceAware(true); return toReturn; } private static DocumentBuilder getDocumentBuilder() { try { return getDocumentBuilderFactory().newDocumentBuilder(); } catch (ParserConfigurationException e) { throw new IllegalStateException("Could not create DocumentBuilder", e); } } private static Document createEmptyDocument(final DocumentBuilder builder) { return builder.newDocument(); } private String getXmlDocumentSample(final String namespace) { return "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n" + "<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"\n" + " xmlns:" + namespace + "=\"http://the/foo/namespace\" \n" // + " targetNamespace=\"http://yet/another/namespace\"\n" + " version=\"1.0\">\n" + " <xs:element name=\"aRequiredElementInYetAnotherNamespace\" type=\"xs:string\"/>\n" + " <" + namespace + ":aBar name=\"aFooElement\" />\n" + "</xs:schema>\n"; } }