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