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.AbstractSourceCodeAwareNodeProcessingTest;
7 import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.JavaDocExtractor;
8 import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.NoAuthorJavaDocRenderer;
9 import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.SearchableDocumentation;
10 import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.XsdAnnotationProcessor;
11 import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.XsdEnumerationAnnotationProcessor;
12 import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.schemaenhancement.ChangeNamespacePrefixProcessor;
13 import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.schemaenhancement.SimpleNamespaceResolver;
14 import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.schemaenhancement.TransformSchema;
15 import org.codehaus.mojo.jaxb2.shared.FileSystemUtilities;
16 import org.codehaus.mojo.jaxb2.shared.filters.Filter;
17 import org.codehaus.mojo.jaxb2.shared.filters.Filters;
18 import org.codehaus.mojo.jaxb2.shared.filters.pattern.PatternFileFilter;
19 import org.custommonkey.xmlunit.Diff;
20 import org.custommonkey.xmlunit.ElementNameAndAttributeQualifier;
21 import org.custommonkey.xmlunit.XMLAssert;
22 import org.custommonkey.xmlunit.XMLUnit;
23 import org.junit.Assert;
24 import org.junit.BeforeClass;
25 import org.junit.Test;
26 import org.w3c.dom.Document;
27 import se.jguru.shared.algorithms.api.resources.PropertyResources;
28
29 import javax.xml.parsers.DocumentBuilder;
30 import javax.xml.parsers.DocumentBuilderFactory;
31 import javax.xml.parsers.ParserConfigurationException;
32 import javax.xml.transform.TransformerFactory;
33 import java.io.File;
34 import java.io.StringReader;
35 import java.net.MalformedURLException;
36 import java.net.URL;
37 import java.security.CodeSource;
38 import java.util.ArrayList;
39 import java.util.Collections;
40 import java.util.List;
41 import java.util.Map;
42
43
44
45
46 public class XsdGeneratorHelperTest
47 {
48
49 private static TransformerFactory factory;
50
51 @BeforeClass
52 public static void setupSharedState()
53 {
54
55
56 XMLUnit.setIgnoreWhitespace( true );
57 XMLUnit.setIgnoreAttributeOrder( true );
58
59
60 try
61 {
62
63 factory = TransformerFactory.newInstance();
64 final CodeSource codeSource = factory.getClass().getProtectionDomain().getCodeSource();
65
66 System.out.println(
67 "-- Found TransformerFactory of type [" + factory.getClass().getName() + "] loaded from [" + codeSource.getLocation().toString() + "]" );
68
69 }
70 catch ( Exception ex )
71 {
72 ex.printStackTrace();
73 }
74 }
75
76 @Test( expected = MojoExecutionException.class )
77 public void validateExceptionThrownOnDuplicateURIs() throws MojoExecutionException
78 {
79
80
81 final TransformSchema transformSchema1 = new TransformSchema( "foo", "foo", "foo" );
82 final TransformSchema transformSchema2 = new TransformSchema( "foo", "bar", "bar" );
83
84 final List<TransformSchema> transformSchemas = new ArrayList<TransformSchema>();
85 transformSchemas.add( transformSchema1 );
86 transformSchemas.add( transformSchema2 );
87
88
89 XsdGeneratorHelper.validateSchemasInPluginConfiguration( transformSchemas );
90 Assert.fail( "Two schemas with same URIs should yield a MojoExecutionException." );
91 }
92
93 @Test( expected = MojoExecutionException.class )
94 public void validateExceptionThrownOnDuplicatePrefixes() throws MojoExecutionException
95 {
96
97
98 final TransformSchema transformSchema1 = new TransformSchema( "foo", "foo", "foo" );
99 final TransformSchema transformSchema2 = new TransformSchema( "bar", "foo", "bar" );
100
101 final List<TransformSchema> transformSchemas = new ArrayList<TransformSchema>();
102 transformSchemas.add( transformSchema1 );
103 transformSchemas.add( transformSchema2 );
104
105
106 XsdGeneratorHelper.validateSchemasInPluginConfiguration( transformSchemas );
107 Assert.fail( "Two schemas with same Prefixes should yield a MojoExecutionException." );
108 }
109
110 @Test
111 public void validateNoExceptionThrownOnDuplicateNullPrefixes()
112 {
113
114 final TransformSchema transformSchema1 = new TransformSchema( "foo", null, "foo" );
115 final TransformSchema transformSchema2 = new TransformSchema( "bar", null, "bar" );
116
117 final List<TransformSchema> transformSchemas = new ArrayList<TransformSchema>();
118 transformSchemas.add( transformSchema1 );
119 transformSchemas.add( transformSchema2 );
120
121
122 try
123 {
124 XsdGeneratorHelper.validateSchemasInPluginConfiguration( transformSchemas );
125 }
126 catch ( MojoExecutionException e )
127 {
128 Assert.fail( "Two schemas with null Prefix should not yield a MojoExecutionException." );
129 }
130 }
131
132 @Test
133 public void validateExceptionThrownOnDuplicateFiles()
134 {
135
136
137 final TransformSchema transformSchema1 = new TransformSchema( "foo", "foo", "foo.xsd" );
138 final TransformSchema transformSchema2 = new TransformSchema( "bar", "bar", "foo.xsd" );
139
140 final List<TransformSchema> transformSchemas = new ArrayList<TransformSchema>();
141 transformSchemas.add( transformSchema1 );
142 transformSchemas.add( transformSchema2 );
143
144
145 try
146 {
147 XsdGeneratorHelper.validateSchemasInPluginConfiguration( transformSchemas );
148 Assert.fail( "Two schemas with same Files should yield a MojoExecutionException." );
149 }
150 catch ( MojoExecutionException e )
151 {
152
153 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.";
154 Assert.assertEquals( expectedMessage, e.getLocalizedMessage() );
155 }
156 }
157
158 @Test( expected = MojoExecutionException.class )
159 public void validateExceptionThrownOnOnlyUriGiven() throws MojoExecutionException
160 {
161
162 final TransformSchema transformSchema1 = new TransformSchema( "foo", null, "" );
163
164 final List<TransformSchema> transformSchemas = new ArrayList<TransformSchema>();
165 transformSchemas.add( transformSchema1 );
166
167
168 XsdGeneratorHelper.validateSchemasInPluginConfiguration( transformSchemas );
169 Assert.fail( "A schema definition with no prefix or file should yield a MojoExecutionException." );
170 }
171
172 @Test( expected = MojoExecutionException.class )
173 public void validateExceptionThrownOnNullUri() throws MojoExecutionException
174 {
175
176
177 final TransformSchema transformSchema1 = new TransformSchema( null, "foo", "bar" );
178
179 final List<TransformSchema> transformSchemas = new ArrayList<TransformSchema>();
180 transformSchemas.add( transformSchema1 );
181
182
183 XsdGeneratorHelper.validateSchemasInPluginConfiguration( transformSchemas );
184 Assert.fail( "A schema definition with null URI should yield a MojoExecutionException." );
185 }
186
187 @Test( expected = MojoExecutionException.class )
188 public void validateExceptionThrownOnEmptyUri() throws MojoExecutionException
189 {
190
191
192 final TransformSchema transformSchema1 = new TransformSchema( "", "foo", "bar" );
193
194 final List<TransformSchema> transformSchemas = new ArrayList<TransformSchema>();
195 transformSchemas.add( transformSchema1 );
196
197
198 XsdGeneratorHelper.validateSchemasInPluginConfiguration( transformSchemas );
199 Assert.fail( "A schema definition with empty URI should yield a MojoExecutionException." );
200 }
201
202 @Test
203 public void validateProcessingNodes()
204 {
205
206
207 final String newPrefix = "changedFoo";
208 final String oldPrefix = "foo";
209 final String originalXml = getXmlDocumentSample( oldPrefix );
210 final String changedXml = getXmlDocumentSample( newPrefix );
211 final NodeProcessor changeNamespacePrefixProcessor = new ChangeNamespacePrefixProcessor( oldPrefix, newPrefix );
212
213
214 final Document processedDocument = XsdGeneratorHelper.parseXmlStream( new StringReader( originalXml ) );
215 XsdGeneratorHelper.process( processedDocument.getFirstChild(), true, changeNamespacePrefixProcessor );
216
217
218 final Document expectedDocument = XsdGeneratorHelper.parseXmlStream( new StringReader( changedXml ) );
219 final Diff diff = new Diff( expectedDocument, processedDocument, null, new ElementNameAndAttributeQualifier() );
220 diff.overrideElementQualifier( new ElementNameAndAttributeQualifier() );
221
222 XMLAssert.assertXMLEqual( processedDocument, expectedDocument );
223 }
224
225 @Test
226 public void validateProcessingXSDsWithEnumerations() throws Exception
227 {
228
229
230 final BufferingLog log = new BufferingLog();
231 final JavaDocExtractor extractor = new JavaDocExtractor( log );
232 extractor.setEncoding( "UTF-8" );
233
234 final String parentPath = "testdata/schemageneration/javadoc/enums/";
235 final URL parentPathURL = getClass().getClassLoader().getResource( parentPath );
236 Assert.assertNotNull( parentPathURL );
237
238 final File parentDir = new File( parentPathURL.getPath() );
239 Assert.assertTrue( parentDir.exists() && parentDir.isDirectory() );
240
241 final List<Filter<File>> excludeFilesMatching = new ArrayList<Filter<File>>();
242 excludeFilesMatching.add( new PatternFileFilter( Collections.singletonList( "\\.xsd" ) ) );
243 Filters.initialize( log, excludeFilesMatching );
244
245 final List<File> allSourceFiles = FileSystemUtilities.filterFiles( parentDir, null, parentDir.getAbsolutePath(),
246 log, "allJavaFiles", excludeFilesMatching );
247 Assert.assertEquals( 3, allSourceFiles.size() );
248
249 final List<URL> urls = new ArrayList<URL>();
250 for ( File current : allSourceFiles )
251 {
252 try
253 {
254 urls.add( current.toURI().toURL() );
255 }
256 catch ( MalformedURLException e )
257 {
258 throw new IllegalArgumentException(
259 "Could not convert file [" + current.getAbsolutePath() + "] to a URL", e );
260 }
261 }
262 Assert.assertEquals( 3, urls.size() );
263
264 extractor.addSourceURLs( urls );
265 final SearchableDocumentation docs = extractor.process();
266
267
268
269 final String rawEnumSchema = PropertyResources.readFully( parentPath + "rawEnumSchema.xsd" );
270 final String processedEnumSchema = PropertyResources.readFully( parentPath + "processedEnumSchema.xsd" );
271 final NodeProcessor enumProcessor = new XsdEnumerationAnnotationProcessor( docs,
272 new NoAuthorJavaDocRenderer() );
273
274
275 final Document processedDocument = XsdGeneratorHelper.parseXmlStream( new StringReader( rawEnumSchema ) );
276 XsdGeneratorHelper.process( processedDocument.getFirstChild(), true, enumProcessor );
277
278
279
280 final Document expectedDocument = XsdGeneratorHelper.parseXmlStream( new StringReader( processedEnumSchema ) );
281 final Diff diff = new Diff( expectedDocument, processedDocument, null, new ElementNameAndAttributeQualifier() );
282 diff.overrideElementQualifier( new ElementNameAndAttributeQualifier() );
283
284 XMLAssert.assertXMLEqual( processedDocument, expectedDocument );
285 }
286
287 @Test
288 public void validateXmlDocumentationForWrappers() throws Exception
289 {
290
291
292 final BufferingLog log = new BufferingLog();
293 final JavaDocExtractor extractor = new JavaDocExtractor( log );
294 extractor.setEncoding( "UTF-8" );
295
296 final String parentPath = "testdata/schemageneration/javadoc/xmlwrappers/";
297 final URL parentPathURL = getClass().getClassLoader().getResource( parentPath );
298 Assert.assertNotNull( parentPathURL );
299
300 final String schemaGenCreatedSchema = PropertyResources.readFully( parentPath + "expectedRawXmlWrappers.xsd" );
301
302 final File parentDir = new File( parentPathURL.getPath() );
303 Assert.assertTrue( parentDir.exists() && parentDir.isDirectory() );
304
305 final List<Filter<File>> excludeFilesMatching = new ArrayList<Filter<File>>();
306 excludeFilesMatching.add( new PatternFileFilter( Collections.singletonList( "\\.xsd" ) ) );
307 Filters.initialize( log, excludeFilesMatching );
308
309 final List<File> allSourceFiles = FileSystemUtilities.filterFiles( parentDir, null, parentDir.getAbsolutePath(),
310 log, "allJavaFiles", excludeFilesMatching );
311 Assert.assertEquals( 2, allSourceFiles.size() );
312
313 final List<URL> urls = new ArrayList<URL>();
314 for ( File current : allSourceFiles )
315 {
316 try
317 {
318 urls.add( current.toURI().toURL() );
319 }
320 catch ( MalformedURLException e )
321 {
322 throw new IllegalArgumentException(
323 "Could not convert file [" + current.getAbsolutePath() + "] to a URL", e );
324 }
325 }
326 Assert.assertEquals( 2, urls.size() );
327
328
329 extractor.addSourceURLs( urls );
330 final SearchableDocumentation docs = extractor.process();
331
332 final XsdAnnotationProcessor processor = new XsdAnnotationProcessor( docs, new NoAuthorJavaDocRenderer() );
333 final Document schemaGenCreatedDocument = XsdGeneratorHelper.parseXmlStream(
334 new StringReader( schemaGenCreatedSchema ) );
335 XsdGeneratorHelper.process( schemaGenCreatedDocument.getFirstChild(), true, processor );
336 System.out.println(
337 "Got: " + AbstractSourceCodeAwareNodeProcessingTest.printDocument( schemaGenCreatedDocument ) );
338
339
340 }
341
342 @Test
343 public void validateAcquiringFilenameToResolverMap() throws MojoExecutionException
344 {
345
346
347 final String[] expectedFilenames = {"schema1.xsd", "schema2.xsd", "schema3.xsd"};
348 final URL tmpUrl = getClass().getClassLoader().getResource( "generated/schema/schema1.xsd" );
349 final File directory = new File( tmpUrl.getFile() ).getParentFile();
350
351
352 final Map<String, SimpleNamespaceResolver> fileNameToResolverMap = XsdGeneratorHelper.getFileNameToResolverMap(
353 directory );
354
355
356 Assert.assertEquals( 3, fileNameToResolverMap.size() );
357 for ( String current : expectedFilenames )
358 {
359 Assert.assertTrue( fileNameToResolverMap.keySet().contains( current ) );
360 }
361
362 SimpleNamespaceResolver schema1Resolver = fileNameToResolverMap.get( "schema1.xsd" );
363 Assert.assertEquals( "http://yet/another/namespace", schema1Resolver.getLocalNamespaceURI() );
364 Assert.assertEquals( "schema1.xsd", schema1Resolver.getSourceFilename() );
365 final Map<String, String> schema1NamespaceURI2PrefixMap = schema1Resolver.getNamespaceURI2PrefixMap();
366 Assert.assertEquals( 1, schema1NamespaceURI2PrefixMap.size() );
367 Assert.assertEquals( "xs", schema1NamespaceURI2PrefixMap.get( "http://www.w3.org/2001/XMLSchema" ) );
368
369 SimpleNamespaceResolver schema2Resolver = fileNameToResolverMap.get( "schema2.xsd" );
370 Assert.assertEquals( "http://some/namespace", schema2Resolver.getLocalNamespaceURI() );
371 Assert.assertEquals( "schema2.xsd", schema2Resolver.getSourceFilename() );
372 final Map<String, String> schema2NamespaceURI2PrefixMap = schema2Resolver.getNamespaceURI2PrefixMap();
373 Assert.assertEquals( 2, schema2NamespaceURI2PrefixMap.size() );
374 Assert.assertEquals( "ns1", schema2NamespaceURI2PrefixMap.get( "http://another/namespace" ) );
375 Assert.assertEquals( "xs", schema2NamespaceURI2PrefixMap.get( "http://www.w3.org/2001/XMLSchema" ) );
376
377 SimpleNamespaceResolver schema3Resolver = fileNameToResolverMap.get( "schema3.xsd" );
378 Assert.assertEquals( "http://another/namespace", schema3Resolver.getLocalNamespaceURI() );
379 Assert.assertEquals( "schema3.xsd", schema3Resolver.getSourceFilename() );
380 final Map<String, String> schema3NamespaceURI2PrefixMap = schema3Resolver.getNamespaceURI2PrefixMap();
381 Assert.assertEquals( 3, schema3NamespaceURI2PrefixMap.size() );
382 Assert.assertEquals( "ns2", schema3NamespaceURI2PrefixMap.get( "http://yet/another/namespace" ) );
383 Assert.assertEquals( "ns1", schema3NamespaceURI2PrefixMap.get( "http://some/namespace" ) );
384 Assert.assertEquals( "xs", schema3NamespaceURI2PrefixMap.get( "http://www.w3.org/2001/XMLSchema" ) );
385 }
386
387
388
389
390
391 private static DocumentBuilderFactory getDocumentBuilderFactory()
392 {
393
394 final DocumentBuilderFactory toReturn = DocumentBuilderFactory.newInstance();
395 toReturn.setNamespaceAware( true );
396 return toReturn;
397 }
398
399 private static DocumentBuilder getDocumentBuilder()
400 {
401 try
402 {
403 return getDocumentBuilderFactory().newDocumentBuilder();
404 }
405 catch ( ParserConfigurationException e )
406 {
407 throw new IllegalStateException( "Could not create DocumentBuilder", e );
408 }
409 }
410
411 private static Document createEmptyDocument( final DocumentBuilder builder )
412 {
413 return builder.newDocument();
414 }
415
416 private String getXmlDocumentSample( final String namespace )
417 {
418 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"
419
420 + " version=\"1.0\">\n" + " <xs:element name=\"aRequiredElementInYetAnotherNamespace\" type=\"xs:string\"/>\n" + " <" + namespace + ":aBar name=\"aFooElement\" />\n" + "</xs:schema>\n";
421 }
422 }