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