View Javadoc
1   package org.codehaus.mojo.jaxb2.schemageneration.postprocessing;
2   
3   import org.apache.maven.plugin.MojoExecutionException;
4   import org.codehaus.mojo.jaxb2.BufferingLog;
5   import org.codehaus.mojo.jaxb2.schemageneration.XsdGeneratorHelper;
6   import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.JavaDocExtractor;
7   import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.NoAuthorJavaDocRenderer;
8   import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.SearchableDocumentation;
9   import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.XsdEnumerationAnnotationProcessor;
10  import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.schemaenhancement.ChangeNamespacePrefixProcessor;
11  import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.schemaenhancement.SimpleNamespaceResolver;
12  import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.schemaenhancement.TransformSchema;
13  import org.codehaus.mojo.jaxb2.shared.FileSystemUtilities;
14  import org.codehaus.mojo.jaxb2.shared.filters.Filter;
15  import org.codehaus.mojo.jaxb2.shared.filters.Filters;
16  import org.codehaus.mojo.jaxb2.shared.filters.pattern.PatternFileFilter;
17  import org.custommonkey.xmlunit.Diff;
18  import org.custommonkey.xmlunit.ElementNameAndAttributeQualifier;
19  import org.custommonkey.xmlunit.XMLAssert;
20  import org.custommonkey.xmlunit.XMLUnit;
21  import org.junit.Assert;
22  import org.junit.Test;
23  import org.w3c.dom.Document;
24  import se.jguru.nazgul.test.xmlbinding.XmlTestUtils;
25  
26  import javax.xml.transform.TransformerFactory;
27  import java.io.File;
28  import java.io.StringReader;
29  import java.net.MalformedURLException;
30  import java.net.URL;
31  import java.util.ArrayList;
32  import java.util.Collections;
33  import java.util.List;
34  import java.util.Map;
35  
36  /**
37   * @author <a href="mailto:lj@jguru.se">Lennart J&ouml;relid</a>
38   */
39  public class XsdGeneratorHelperTest {
40  
41      private static final TransformerFactory FACTORY = TransformerFactory.newInstance();
42  
43      static {
44          // Configure XMLUnit.
45          XMLUnit.setIgnoreWhitespace(true);
46          XMLUnit.setIgnoreAttributeOrder(true);
47  
48          // Configure the TransformerFactory
49          FACTORY.setAttribute("indent-number", 2);
50      }
51  
52      @Test(expected = MojoExecutionException.class)
53      public void validateExceptionThrownOnDuplicateURIs() throws MojoExecutionException {
54  
55          // Assemble
56          final TransformSchema transformSchema1 = new TransformSchema("foo", "foo", "foo");
57          final TransformSchema transformSchema2 = new TransformSchema("foo", "bar", "bar");
58  
59          final List<TransformSchema> transformSchemas = new ArrayList<TransformSchema>();
60          transformSchemas.add(transformSchema1);
61          transformSchemas.add(transformSchema2);
62  
63          // Act & Assert
64          XsdGeneratorHelper.validateSchemasInPluginConfiguration(transformSchemas);
65          Assert.fail("Two schemas with same URIs should yield a MojoExecutionException.");
66      }
67  
68      @Test(expected = MojoExecutionException.class)
69      public void validateExceptionThrownOnDuplicatePrefixes()
70              throws MojoExecutionException {
71  
72          // Assemble
73          final TransformSchema transformSchema1 = new TransformSchema("foo", "foo", "foo");
74          final TransformSchema transformSchema2 = new TransformSchema("bar", "foo", "bar");
75  
76          final List<TransformSchema> transformSchemas = new ArrayList<TransformSchema>();
77          transformSchemas.add(transformSchema1);
78          transformSchemas.add(transformSchema2);
79  
80          // Act & Assert
81          XsdGeneratorHelper.validateSchemasInPluginConfiguration(transformSchemas);
82          Assert.fail("Two schemas with same Prefixes should yield a MojoExecutionException.");
83      }
84  
85      @Test
86      public void validateNoExceptionThrownOnDuplicateNullPrefixes() {
87          // Assemble
88          final TransformSchema transformSchema1 = new TransformSchema("foo", null, "foo");
89          final TransformSchema transformSchema2 = new TransformSchema("bar", null, "bar");
90  
91          final List<TransformSchema> transformSchemas = new ArrayList<TransformSchema>();
92          transformSchemas.add(transformSchema1);
93          transformSchemas.add(transformSchema2);
94  
95          // Act & Assert
96          try {
97              XsdGeneratorHelper.validateSchemasInPluginConfiguration(transformSchemas);
98          } catch (MojoExecutionException e) {
99              Assert.fail("Two schemas with null Prefix should not yield a MojoExecutionException.");
100         }
101     }
102 
103     @Test
104     public void validateExceptionThrownOnDuplicateFiles() {
105 
106         // Assemble
107         final TransformSchema transformSchema1 = new TransformSchema("foo", "foo", "foo.xsd");
108         final TransformSchema transformSchema2 = new TransformSchema("bar", "bar", "foo.xsd");
109 
110         final List<TransformSchema> transformSchemas = new ArrayList<TransformSchema>();
111         transformSchemas.add(transformSchema1);
112         transformSchemas.add(transformSchema2);
113 
114         // Act & Assert
115         try {
116             XsdGeneratorHelper.validateSchemasInPluginConfiguration(transformSchemas);
117             Assert.fail("Two schemas with same Files should yield a MojoExecutionException.");
118         } catch (MojoExecutionException e) {
119             // Validate the error message.
120             String expectedMessage = "Misconfiguration detected: Duplicate 'file' property with value [foo.xsd] "
121                     + "found in plugin configuration. Correct schema elements index (0) and (1), "
122                     + "to ensure that all 'file' values are unique.";
123             Assert.assertEquals(expectedMessage, e.getLocalizedMessage());
124         }
125     }
126 
127     @Test(expected = MojoExecutionException.class)
128     public void validateExceptionThrownOnOnlyUriGiven()
129             throws MojoExecutionException {
130         // Assemble
131         final TransformSchema transformSchema1 = new TransformSchema("foo", null, "");
132 
133         final List<TransformSchema> transformSchemas = new ArrayList<TransformSchema>();
134         transformSchemas.add(transformSchema1);
135 
136         // Act & Assert
137         XsdGeneratorHelper.validateSchemasInPluginConfiguration(transformSchemas);
138         Assert.fail("A schema definition with no prefix or file should yield a MojoExecutionException.");
139     }
140 
141     @Test(expected = MojoExecutionException.class)
142     public void validateExceptionThrownOnNullUri() throws MojoExecutionException {
143 
144         // Assemble
145         final TransformSchema transformSchema1 = new TransformSchema(null, "foo", "bar");
146 
147         final List<TransformSchema> transformSchemas = new ArrayList<TransformSchema>();
148         transformSchemas.add(transformSchema1);
149 
150         // Act & Assert
151         XsdGeneratorHelper.validateSchemasInPluginConfiguration(transformSchemas);
152         Assert.fail("A schema definition with null URI should yield a MojoExecutionException.");
153     }
154 
155     @Test(expected = MojoExecutionException.class)
156     public void validateExceptionThrownOnEmptyUri() throws MojoExecutionException {
157 
158         // Assemble
159         final TransformSchema transformSchema1 = new TransformSchema("", "foo", "bar");
160 
161         final List<TransformSchema> transformSchemas = new ArrayList<TransformSchema>();
162         transformSchemas.add(transformSchema1);
163 
164         // Act & Assert
165         XsdGeneratorHelper.validateSchemasInPluginConfiguration(transformSchemas);
166         Assert.fail("A schema definition with empty URI should yield a MojoExecutionException.");
167     }
168 
169     @Test
170     public void validateProcessingNodes() {
171 
172         // Assemble
173         final String newPrefix = "changedFoo";
174         final String oldPrefix = "foo";
175         final String originalXml = getXmlDocumentSample(oldPrefix);
176         final String changedXml = getXmlDocumentSample(newPrefix);
177         final NodeProcessor changeNamespacePrefixProcessor = new ChangeNamespacePrefixProcessor(oldPrefix, newPrefix);
178 
179         // Act
180         final Document processedDocument = XsdGeneratorHelper.parseXmlStream(new StringReader(originalXml));
181         XsdGeneratorHelper.process(processedDocument.getFirstChild(), true, changeNamespacePrefixProcessor);
182 
183         // Assert
184         final Document expectedDocument = XsdGeneratorHelper.parseXmlStream(new StringReader(changedXml));
185         final Diff diff = new Diff(expectedDocument, processedDocument, null, new ElementNameAndAttributeQualifier());
186         diff.overrideElementQualifier(new ElementNameAndAttributeQualifier());
187 
188         XMLAssert.assertXMLEqual(processedDocument, expectedDocument);
189     }
190 
191     @Test
192     public void validateProcessingXSDsWithEnumerations() throws Exception {
193 
194         // Assemble
195         final BufferingLog log = new BufferingLog();
196         final JavaDocExtractor extractor = new JavaDocExtractor(log);
197         extractor.setEncoding("UTF-8");
198 
199         final String parentPath = "testdata/schemageneration/javadoc/enums/";
200         final URL parentPathURL = getClass().getClassLoader().getResource(parentPath);
201         Assert.assertNotNull(parentPathURL);
202 
203         final File parentDir = new File(parentPathURL.getPath());
204         Assert.assertTrue(parentDir.exists() && parentDir.isDirectory());
205 
206         final List<Filter<File>> excludeFilesMatching = new ArrayList<Filter<File>>();
207         excludeFilesMatching.add(new PatternFileFilter(Collections.singletonList("\\.xsd")));
208         Filters.initialize(log, excludeFilesMatching);
209 
210         final List<File> allSourceFiles = FileSystemUtilities.filterFiles(parentDir,
211                 null,
212                 parentDir.getAbsolutePath(),
213                 log,
214                 "allJavaFiles",
215                 excludeFilesMatching);
216         Assert.assertEquals(2, allSourceFiles.size());
217 
218         final List<URL> urls = new ArrayList<URL>();
219         for (File current : allSourceFiles) {
220             try {
221                 urls.add(current.toURI().toURL());
222             } catch (MalformedURLException e) {
223                 throw new IllegalArgumentException("Could not convert file [" + current.getAbsolutePath()
224                         + "] to a URL", e);
225             }
226         }
227         Assert.assertEquals(2, urls.size());
228 
229         extractor.addSourceURLs(urls);
230         final SearchableDocumentation docs = extractor.process();
231 
232         // #1) The raw / un-processed XSD (containing the 'before' state)
233         // #2) The processed XSD (containing the 'expected' state)
234         final String rawEnumSchema = XmlTestUtils.readFully(parentPath + "rawEnumSchema.xsd");
235         final String processedEnumSchema = XmlTestUtils.readFully(parentPath + "processedEnumSchema.xsd");
236         final NodeProcessor enumProcessor = new XsdEnumerationAnnotationProcessor(docs, new NoAuthorJavaDocRenderer());
237 
238         // Act
239         final Document processedDocument = XsdGeneratorHelper.parseXmlStream(new StringReader(rawEnumSchema));
240         XsdGeneratorHelper.process(processedDocument.getFirstChild(), true, enumProcessor);
241 
242         // Assert
243         final Document expectedDocument = XsdGeneratorHelper.parseXmlStream(new StringReader(processedEnumSchema));
244         final Diff diff = new Diff(expectedDocument, processedDocument, null, new ElementNameAndAttributeQualifier());
245         diff.overrideElementQualifier(new ElementNameAndAttributeQualifier());
246 
247         XMLAssert.assertXMLEqual(processedDocument, expectedDocument);
248     }
249 
250     @Test
251     public void validateAcquiringFilenameToResolverMap() throws MojoExecutionException {
252 
253         // Assemble
254         final String[] expectedFilenames = {"schema1.xsd", "schema2.xsd", "schema3.xsd"};
255         final URL tmpUrl = getClass().getClassLoader().getResource("generated/schema/schema1.xsd");
256         final File directory = new File(tmpUrl.getFile()).getParentFile();
257 
258         // Act
259         final Map<String, SimpleNamespaceResolver> fileNameToResolverMap =
260                 XsdGeneratorHelper.getFileNameToResolverMap(directory);
261 
262         // Assert
263         Assert.assertEquals(3, fileNameToResolverMap.size());
264         for (String current : expectedFilenames) {
265             Assert.assertTrue(fileNameToResolverMap.keySet().contains(current));
266         }
267 
268         SimpleNamespaceResolver schema1Resolver = fileNameToResolverMap.get("schema1.xsd");
269         Assert.assertEquals("http://yet/another/namespace", schema1Resolver.getLocalNamespaceURI());
270         Assert.assertEquals("schema1.xsd", schema1Resolver.getSourceFilename());
271         final Map<String, String> schema1NamespaceURI2PrefixMap = schema1Resolver.getNamespaceURI2PrefixMap();
272         Assert.assertEquals(1, schema1NamespaceURI2PrefixMap.size());
273         Assert.assertEquals("xs", schema1NamespaceURI2PrefixMap.get("http://www.w3.org/2001/XMLSchema"));
274 
275         SimpleNamespaceResolver schema2Resolver = fileNameToResolverMap.get("schema2.xsd");
276         Assert.assertEquals("http://some/namespace", schema2Resolver.getLocalNamespaceURI());
277         Assert.assertEquals("schema2.xsd", schema2Resolver.getSourceFilename());
278         final Map<String, String> schema2NamespaceURI2PrefixMap = schema2Resolver.getNamespaceURI2PrefixMap();
279         Assert.assertEquals(2, schema2NamespaceURI2PrefixMap.size());
280         Assert.assertEquals("ns1", schema2NamespaceURI2PrefixMap.get("http://another/namespace"));
281         Assert.assertEquals("xs", schema2NamespaceURI2PrefixMap.get("http://www.w3.org/2001/XMLSchema"));
282 
283         SimpleNamespaceResolver schema3Resolver = fileNameToResolverMap.get("schema3.xsd");
284         Assert.assertEquals("http://another/namespace", schema3Resolver.getLocalNamespaceURI());
285         Assert.assertEquals("schema3.xsd", schema3Resolver.getSourceFilename());
286         final Map<String, String> schema3NamespaceURI2PrefixMap = schema3Resolver.getNamespaceURI2PrefixMap();
287         Assert.assertEquals(3, schema3NamespaceURI2PrefixMap.size());
288         Assert.assertEquals("ns2", schema3NamespaceURI2PrefixMap.get("http://yet/another/namespace"));
289         Assert.assertEquals("ns1", schema3NamespaceURI2PrefixMap.get("http://some/namespace"));
290         Assert.assertEquals("xs", schema3NamespaceURI2PrefixMap.get("http://www.w3.org/2001/XMLSchema"));
291     }
292 
293     //
294     // Private helpers
295     //
296 
297     private String getXmlDocumentSample(final String namespace) {
298         return "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n"
299                 + "<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"\n"
300                 + "           xmlns:" + namespace + "=\"http://the/foo/namespace\" \n"
301                 // + "           targetNamespace=\"http://yet/another/namespace\"\n"
302                 + "           version=\"1.0\">\n"
303                 + "    <xs:element name=\"aRequiredElementInYetAnotherNamespace\" type=\"xs:string\"/>\n"
304                 + "    <" + namespace + ":aBar name=\"aFooElement\" />\n"
305                 + "</xs:schema>\n";
306     }
307 }