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><xs:import namespace="http://some/namespace" schemaLocation="<strong>schema2.xsd</strong>"/> is
37 * altered to
38 * <xs:import namespace="http://some/namespace" schemaLocation="<strong>anotherFile.xsd</strong>"/></dd>
39 * </dl>
40 *
41 * @author <a href="mailto:lj@jguru.se">Lennart Jö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><xs:import namespace="http://a/registered/namespace" schemaLocation="schema1.xsd"/></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 }