6e17ab94d559b8a151018af5cb70cccbc2251da3
[policy/apex-pdp.git] /
1 /*
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2016-2018 Ericsson. All rights reserved.
4  * ================================================================================
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  * 
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  * 
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  * 
17  * SPDX-License-Identifier: Apache-2.0
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.policy.apex.model.basicmodel.handling;
22
23 import java.io.File;
24 import java.io.IOException;
25 import java.io.PrintStream;
26 import java.io.StringWriter;
27
28 import javax.xml.bind.JAXBContext;
29 import javax.xml.bind.JAXBException;
30 import javax.xml.bind.SchemaOutputResolver;
31 import javax.xml.transform.Result;
32 import javax.xml.transform.stream.StreamResult;
33
34 import org.slf4j.ext.XLogger;
35 import org.slf4j.ext.XLoggerFactory;
36
37 /**
38  * This class generates the XML model schema from the given Apex concept classes.
39  *
40  * @author Liam Fallon (liam.fallon@ericsson.com)
41  */
42 public class ApexSchemaGenerator {
43     // Get a reference to the logger
44     private static final XLogger LOGGER = XLoggerFactory.getXLogger(ApexSchemaGenerator.class);
45
46     /**
47      * A Main method to allow schema generation from the command line or from maven or scripts.
48      *
49      * @param args the command line arguments, usage is {@code ApexSchemaGenerator apex-root-class [schema-file-name]}
50      */
51     public static void main(final String[] args) {
52         PrintStream printStream = null;
53
54         if (args.length == 1) {
55             printStream = System.out;
56         }
57         else if (args.length == 2) {
58             final File schemaFile = new File(args[1]);
59
60             try {
61                 schemaFile.getParentFile().mkdirs();
62                 printStream = new PrintStream(schemaFile);
63             }
64             catch (final Exception e) {
65                 LOGGER.error("error on Apex schema output", e);
66                 return;
67             }
68         }
69         else {
70             LOGGER.error("usage: ApexSchemaGenerator apex-root-class [schema-file-name]");
71             return;
72         }
73
74         // Get the schema
75         final String schema = new ApexSchemaGenerator().generate(args[0]);
76
77         // Output the schema
78         printStream.println(schema);
79
80         printStream.close();
81     }
82
83     /**
84      * Generates the XML schema (XSD) for the Apex model described using JAXB annotations.
85      *
86      * @param rootClassName the name of the root class for schema generation
87      * @return The schema
88      */
89     public String generate(final String rootClassName) {
90         JAXBContext jaxbContext;
91         try {
92             jaxbContext = JAXBContext.newInstance(Class.forName(rootClassName));
93         }
94         catch (final ClassNotFoundException e) {
95             LOGGER.error("could not create JAXB context, root class " + rootClassName + " not found", e);
96             return null;
97         }
98         catch (final JAXBException e) {
99             LOGGER.error("could not create JAXB context", e);
100             return null;
101         }
102
103         final ApexSchemaOutputResolver sor = new ApexSchemaOutputResolver();
104         try {
105             jaxbContext.generateSchema(sor);
106         }
107         catch (final IOException e) {
108             LOGGER.error("error generating the Apex schema (XSD) file", e);
109             return null;
110         }
111
112         String schemaString = sor.getSchema();
113         schemaString = fixForUnqualifiedBug(schemaString);
114
115         return schemaString;
116     }
117
118     /**
119      * There is a bug in schema generation that does not specify the elements from Java Maps as being unqualified. This method "hacks" those
120      * elements in the schema to fix this, the elements being {@code entry}, {@code key}, and {@code value}
121      *
122      * @param schemaString The schema in which elements should be fixed
123      * @return the string
124      */
125     private String fixForUnqualifiedBug(final String schemaString) {
126         // Fix the "entry" element
127         String newSchemaString = schemaString.replaceAll("<xs:element name=\"entry\" minOccurs=\"0\" maxOccurs=\"unbounded\">",
128                 "<xs:element name=\"entry\" minOccurs=\"0\" maxOccurs=\"unbounded\" form=\"unqualified\">");
129
130         // Fix the "key" element
131         newSchemaString = newSchemaString.replaceAll("<xs:element name=\"key\"", "<xs:element name=\"key\" form=\"unqualified\"");
132
133         // Fix the "value" element
134         newSchemaString = newSchemaString.replaceAll("<xs:element name=\"value\"", "<xs:element name=\"value\" form=\"unqualified\"");
135
136         return newSchemaString;
137     }
138
139     /**
140      * This inner class is used to receive the output of schema generation from the JAXB schema generator.
141      */
142     private class ApexSchemaOutputResolver extends SchemaOutputResolver {
143         private final StringWriter stringWriter = new StringWriter();
144
145         /*
146          * (non-Javadoc)
147          *
148          * @see javax.xml.bind.SchemaOutputResolver#createOutput(java.lang.String, java.lang.String)
149          */
150         @Override
151         public Result createOutput(final String namespaceURI, final String suggestedFileName) throws IOException {
152             final StreamResult result = new StreamResult(stringWriter);
153             result.setSystemId(suggestedFileName);
154             return result;
155         }
156
157         /**
158          * Get the schema from the string writer created in the {@link createOutput()} method.
159          *
160          * @return the schema generated by JAXB
161          */
162         public String getSchema() {
163             return stringWriter.toString();
164         }
165     }
166 }