Add instructions to invoke the linter and code formatter plugins to the README and...
[aai/schema-service.git] / aai-schema-gen / src / main / java / org / onap / aai / schemagen / genxsd / HTMLfromOXM.java
1 /**
2  * ============LICENSE_START=======================================================
3  * org.onap.aai
4  * ================================================================================
5  * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * <p>
11  * http://www.apache.org/licenses/LICENSE-2.0
12  * <p>
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.aai.schemagen.genxsd;
22
23 import java.io.File;
24 import java.io.FileNotFoundException;
25 import java.io.IOException;
26 import java.util.ArrayList;
27 import java.util.HashMap;
28 import java.util.List;
29
30 import javax.xml.parsers.ParserConfigurationException;
31
32 import org.onap.aai.edges.EdgeIngestor;
33 import org.onap.aai.edges.exceptions.EdgeRuleNotFoundException;
34 import org.onap.aai.nodes.NodeIngestor;
35 import org.onap.aai.setup.SchemaVersion;
36 import org.onap.aai.setup.SchemaVersions;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
39 import org.w3c.dom.Attr;
40 import org.w3c.dom.Element;
41 import org.w3c.dom.NamedNodeMap;
42 import org.w3c.dom.NodeList;
43 import org.xml.sax.SAXException;
44
45 public class HTMLfromOXM extends OxmFileProcessor {
46
47     private static final Logger logger = LoggerFactory.getLogger("HTMLfromOXM.class");
48
49     private String maxOccurs;
50
51     public HTMLfromOXM(String maxOccurs, SchemaVersions schemaVersions, NodeIngestor ni,
52         EdgeIngestor ei) {
53         super(schemaVersions, ni, ei);
54         this.maxOccurs = maxOccurs;
55     }
56
57     public void setOxmVersion(File oxmFile, SchemaVersion v) {
58         super.setOxmVersion(oxmFile, v);
59         this.v = v;
60     }
61
62     public void setXmlVersion(String xml, SchemaVersion v) {
63         super.setXmlVersion(xml, v);
64         this.v = v;
65     }
66
67     public void setVersion(SchemaVersion v) {
68         super.setVersion(v);
69         this.v = v;
70     }
71
72     @Override
73     public String getDocumentHeader() {
74         StringBuilder sb = new StringBuilder();
75         logger.trace("processing starts");
76         sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>")
77             .append(LINE_SEPARATOR);
78         String namespace = "org.onap";
79         if (v.compareTo(getSchemaVersions().getNamespaceChangeVersion()) < 0) {
80             namespace = "org.openecomp";
81         }
82         sb.append(
83             "<xs:schema elementFormDefault=\"qualified\" version=\"1.0\" targetNamespace=\"http://")
84             .append(namespace).append(".aai.inventory/").append(v.toString())
85             .append("\" xmlns:tns=\"http://").append(namespace).append(".aai.inventory/")
86             .append(v.toString()).append("\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"")
87             .append(LINE_SEPARATOR).append("xmlns:jaxb=\"http://java.sun.com/xml/ns/jaxb\"")
88             .append(LINE_SEPARATOR).append("    jaxb:version=\"2.1\"").append(LINE_SEPARATOR)
89             .append("    xmlns:annox=\"http://annox.dev.java.net\"").append(LINE_SEPARATOR)
90             .append("    jaxb:extensionBindingPrefixes=\"annox\">").append(DOUBLE_LINE_SEPARATOR);
91         return sb.toString();
92     }
93
94     @Override
95     public String process() throws ParserConfigurationException, SAXException, IOException,
96         FileNotFoundException, EdgeRuleNotFoundException {
97         StringBuilder sb = new StringBuilder();
98
99         try {
100             init();
101         } catch (Exception e) {
102             logger.error("Error initializing " + this.getClass());
103             throw e;
104         }
105         sb.append(getDocumentHeader());
106         StringBuilder sbInventory = new StringBuilder();
107         Element elem;
108         String javaTypeName;
109         combinedJavaTypes = new HashMap();
110         for (int i = 0; i < javaTypeNodes.getLength(); ++i) {
111             elem = (Element) javaTypeNodes.item(i);
112             javaTypeName = elem.getAttribute("name");
113             if (!"Inventory".equals(javaTypeName)) {
114                 if (generatedJavaType.containsKey(javaTypeName)) {
115                     continue;
116                 }
117                 // will combine all matching java-types
118                 elem = getJavaTypeElement(javaTypeName, false);
119             }
120             XSDElement javaTypeElement = new XSDElement(elem, maxOccurs);
121             // javaTypeName = javaTypeElement.name();
122             if (javaTypeName == null) {
123                 String msg = "Invalid OXM file: <java-type> has no name attribute in " + oxmFile;
124                 logger.error(msg);
125                 throw new SAXException(msg);
126             }
127             if ("Nodes".equals(javaTypeName)) {
128                 logger.debug("skipping Nodes entry (temporary feature)");
129                 continue;
130             }
131             logger.debug(getXmlRootElementName(javaTypeName) + " vs " + javaTypeName + ":"
132                 + generatedJavaType.containsKey(getXmlRootElementName(javaTypeName)));
133
134             if (!"Inventory".equals(javaTypeName)) {
135                 generatedJavaType.put(javaTypeName, null);
136             }
137             sb.append(processJavaTypeElement(javaTypeName, javaTypeElement, sbInventory));
138         }
139         sb.append(sbInventory);
140         sb.append("      </xs:sequence>" + LINE_SEPARATOR);
141         sb.append("    </xs:complexType>" + LINE_SEPARATOR);
142         sb.append("  </xs:element>" + LINE_SEPARATOR);
143         sb.append("</xs:schema>" + LINE_SEPARATOR);
144         return sb.toString();
145     }
146
147     protected boolean isValidName(String name) {
148         if (name == null || name.length() == 0) {
149             return false;
150         }
151         String pattern = "^[a-z0-9-]*$";
152         return name.matches(pattern);
153     }
154
155     protected boolean skipCheck(String javaAttribute) {
156         if (javaAttribute.equals("model") || javaAttribute.equals("eventHeader")) {
157             return true;
158         }
159         return false;
160     }
161
162     public String processJavaTypeElement(String javaTypeName, Element javaType_Element,
163         StringBuilder sbInventory) {
164         String xmlRootElementName = getXMLRootElementName(javaType_Element);
165
166         NodeList parentNodes = javaType_Element.getElementsByTagName("java-attributes");
167         StringBuilder sb = new StringBuilder();
168         if (parentNodes.getLength() == 0) {
169             logger.trace("no java-attributes for java-type " + javaTypeName);
170             return "";
171         }
172
173         Element parentElement = (Element) parentNodes.item(0);
174         NodeList xmlElementNodes = parentElement.getElementsByTagName("xml-element");
175         // support for multiple inventory elements across oxm files
176         boolean processingInventory = false;
177         boolean hasPreviousInventory = false;
178         if ("inventory".equals(xmlRootElementName) && sbInventory != null) {
179             processingInventory = true;
180             if (sbInventory.toString().contains("xs:complexType")) {
181                 hasPreviousInventory = true;
182             }
183         }
184
185         StringBuilder sb1 = new StringBuilder();
186         if (xmlElementNodes.getLength() > 0) {
187
188             if (!processingInventory || !hasPreviousInventory) {
189                 sb1.append("  <xs:element name=\"").append(xmlRootElementName).append("\">")
190                     .append(LINE_SEPARATOR);
191                 sb1.append("    <xs:complexType>").append(LINE_SEPARATOR);
192
193                 XSDElement javaTypeElement = new XSDElement(javaType_Element, maxOccurs);
194                 logger.debug("XSDElement name: " + javaTypeElement.name());
195                 sb1.append(javaTypeElement.getHTMLAnnotation("class", "      "));
196                 sb1.append("      <xs:sequence>").append(LINE_SEPARATOR);
197             }
198             Element javatypeElement;
199             for (int i = 0; i < xmlElementNodes.getLength(); ++i) {
200
201                 XSDElement xmlElementElement =
202                     new XSDElement((Element) xmlElementNodes.item(i), maxOccurs);
203
204                 // String elementName = xmlElementElement.getAttribute("name");
205                 String elementType = xmlElementElement.getAttribute("type");
206                 // No simple types; only AAI custom types
207                 String addType = elementType.contains("." + v.toString() + ".")
208                     ? elementType.substring(elementType.lastIndexOf('.') + 1)
209                     : null;
210                 if (elementType.contains("." + v.toString() + ".")
211                     && !generatedJavaType.containsKey(addType)) {
212                     generatedJavaType.put(addType, elementType);
213                     javatypeElement = getJavaTypeElement(addType, processingInventory);
214                     sb.append(processJavaTypeElement(addType, javatypeElement, null));
215                 }
216                 if ("Nodes".equals(addType)) {
217                     logger.trace("Skipping nodes, temporary testing");
218                     continue;
219                 }
220                 // assembles the basic <element>
221                 sb1.append(xmlElementElement.getHTMLElement(v, true, this));
222             }
223             if (!processingInventory) {
224                 sb1.append("      </xs:sequence>" + LINE_SEPARATOR);
225                 sb1.append("    </xs:complexType>" + LINE_SEPARATOR);
226                 sb1.append("  </xs:element>" + LINE_SEPARATOR);
227             }
228         }
229
230         if (xmlElementNodes.getLength() < 1) {
231             sb.append("  <xs:element name=\"" + xmlRootElementName + "\">" + LINE_SEPARATOR);
232             sb.append("    <xs:complexType>" + LINE_SEPARATOR);
233             sb.append("      <xs:sequence/>" + LINE_SEPARATOR);
234             sb.append("    </xs:complexType>" + LINE_SEPARATOR);
235             sb.append("  </xs:element>" + LINE_SEPARATOR);
236             generatedJavaType.put(javaTypeName, null);
237             return sb.toString();
238         }
239         if (processingInventory && sbInventory != null) {
240             sbInventory.append(sb1);
241         } else {
242             sb.append(sb1);
243         }
244         return sb.toString();
245     }
246
247     private Element getJavaTypeElement(String javaTypeName, boolean processingInventory) {
248         String attrName, attrValue;
249         Attr attr;
250         Element javaTypeElement;
251
252         List<Element> combineElementList = new ArrayList<Element>();
253         for (int i = 0; i < javaTypeNodes.getLength(); ++i) {
254             javaTypeElement = (Element) javaTypeNodes.item(i);
255             NamedNodeMap attributes = javaTypeElement.getAttributes();
256             for (int j = 0; j < attributes.getLength(); ++j) {
257                 attr = (Attr) attributes.item(j);
258                 attrName = attr.getNodeName();
259                 attrValue = attr.getNodeValue();
260                 if (attrName.equals("name") && attrValue.equals(javaTypeName)) {
261                     if (processingInventory) {
262                         return javaTypeElement;
263                     } else {
264                         combineElementList.add(javaTypeElement);
265                     }
266                 }
267             }
268         }
269         if (combineElementList.size() == 0) {
270             logger.error("oxm file format error, missing java-type " + javaTypeName);
271             return (Element) null;
272         } else if (combineElementList.size() > 1) {
273             // need to combine java-attributes
274             return combineElements(javaTypeName, combineElementList);
275         }
276         return combineElementList.get(0);
277
278     }
279
280 }