View Javadoc
1   package org.codehaus.mojo.jaxb2.schemageneration.postprocessing.schemaenhancement;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.NodeProcessor;
23  import org.codehaus.mojo.jaxb2.shared.Validate;
24  import org.w3c.dom.Attr;
25  import org.w3c.dom.Element;
26  import org.w3c.dom.Node;
27  
28  import javax.xml.XMLConstants;
29  import java.util.Map;
30  
31  /**
32   * <p>NodeProcessor which alters the filename for generated XML schema files.
33   * The ChangeNamespacePrefixProcessor alters the following:</p>
34   * <dl>
35   * <dt>Schema Import Definitions</dt>
36   * <dd>&lt;xs:import namespace="http://some/namespace" schemaLocation="<strong>schema2.xsd</strong>"/&gt; is
37   * altered to
38   * &lt;xs:import namespace="http://some/namespace" schemaLocation="<strong>anotherFile.xsd</strong>"/&gt;</dd>
39   * </dl>
40   *
41   * @author <a href="mailto:lj@jguru.se">Lennart J&ouml;relid</a>
42   * @since 1.4
43   */
44  public class ChangeFilenameProcessor implements NodeProcessor {
45  
46      // Constants
47      private static final String SCHEMA_LOCATION = "schemaLocation";
48      private static final String IMPORT = "import";
49      private static final String NAMESPACE = "namespace";
50  
51      // Internal state
52      private Map<String, String> namespaceUriToNewFilenameMap;
53  
54      /**
55       * <p>Creates a new ChangeFilenameProcessor using the provided map relating namespace URIs
56       * to desired new file names.</p>
57       *
58       * @param namespaceUriToNewFilenameMap A map relating namespace URIs [key] to
59       *                                     new/desired schema filenames [value].
60       */
61      public ChangeFilenameProcessor(final Map<String, String> namespaceUriToNewFilenameMap) {
62  
63          // Check sanity
64          Validate.notNull(namespaceUriToNewFilenameMap, "namespaceUriToNewFilenameMap");
65  
66          // Assign internal state
67          this.namespaceUriToNewFilenameMap = namespaceUriToNewFilenameMap;
68      }
69  
70      /**
71       * {@inheritDoc}
72       */
73      public boolean accept(final Node aNode) {
74          return aNode instanceof Attr && isSchemaLocationAttributeForKnownNamespaceUri((Attr) aNode);
75      }
76  
77      /**
78       * {@inheritDoc}
79       */
80      public void process(final Node aNode) {
81  
82          // Only attributes are permitted here.
83          Attr attribute = (Attr) aNode;
84  
85          // Change the fileName.
86          String newFilename = namespaceUriToNewFilenameMap.get(getNamespace(attribute));
87          attribute.setValue(newFilename);
88      }
89  
90      //
91      // Private helpers
92      //
93  
94      /**
95       * Discovers if the provided attribute is a schemaLocation definition, which should
96       * be changed by this ChangeFilenameProcessor. Such an attribute is on the form
97       * <code>&lt;xs:import namespace="http://a/registered/namespace" schemaLocation="schema1.xsd"/&gt;</code>.
98       *
99       * @param attribute the attribute to test.
100      * @return <code>true</code> if the provided attribute is a schemaLocation definition
101      * whose namespace is known to this ChangeFilenameProcessor.
102      */
103     private boolean isSchemaLocationAttributeForKnownNamespaceUri(final Attr attribute) {
104 
105         final Element parent = attribute.getOwnerElement();
106 
107         // <xs:import namespace="http://yet/another/namespace" schemaLocation="schema1.xsd"/>
108         return XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(parent.getNamespaceURI())
109                 && IMPORT.equalsIgnoreCase(parent.getLocalName())
110                 && namespaceUriToNewFilenameMap.containsKey(getNamespace(attribute))
111                 && SCHEMA_LOCATION.equals(attribute.getName());
112     }
113 
114     /**
115      * Retrieves the value of the "namespace" attribute found within the parent element of the provided attribute.
116      *
117      * @param attribute An attribute defined within the parent holding the "namespace" attribute.
118      * @return The value of the "namespace" attribute.
119      */
120     private String getNamespace(final Attr attribute) {
121         final Element parent = attribute.getOwnerElement();
122         return parent.getAttribute(NAMESPACE);
123     }
124 }