Extend service model
[aai/babel.git] / src / main / java / org / onap / aai / babel / xml / generator / api / AaiModelGenerator.java
1 /**
2  * ============LICENSE_START=======================================================
3  * org.onap.aai
4  * ================================================================================
5  * Copyright (c) 2017-2019 AT&T Intellectual Property. All rights reserved.
6  * Copyright (c) 2017-2019 European Software Marketing Ltd.
7  * ================================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * 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, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END=========================================================
20  */
21
22 package org.onap.aai.babel.xml.generator.api;
23
24 import java.io.StringWriter;
25 import java.util.Collection;
26 import java.util.List;
27 import javax.xml.bind.JAXBContext;
28 import javax.xml.bind.JAXBException;
29 import javax.xml.bind.Marshaller;
30 import org.onap.aai.babel.logging.ApplicationMsgs;
31 import org.onap.aai.babel.logging.LogHelper;
32 import org.onap.aai.babel.xml.generator.XmlArtifactGenerationException;
33 import org.onap.aai.babel.xml.generator.model.Model;
34 import org.onap.aai.babel.xml.generator.model.Resource;
35 import org.onap.aai.babel.xml.generator.model.Service;
36 import org.onap.aai.babel.xml.generator.model.Widget;
37 import org.onap.aai.babel.xml.generator.xsd.ModelElement;
38 import org.onap.aai.babel.xml.generator.xsd.ModelElements;
39 import org.onap.aai.babel.xml.generator.xsd.ModelVer;
40 import org.onap.aai.babel.xml.generator.xsd.ModelVers;
41 import org.onap.aai.babel.xml.generator.xsd.Relationship;
42 import org.onap.aai.babel.xml.generator.xsd.RelationshipData;
43 import org.onap.aai.babel.xml.generator.xsd.RelationshipList;
44 import org.onap.aai.cl.api.Logger;
45 import org.w3c.dom.DOMException;
46
47 /**
48  * Generates the A&AI XML models from the Service/Resource/Widget Java models.
49  */
50 public class AaiModelGenerator {
51
52     private static Logger log = LogHelper.INSTANCE;
53
54     /**
55      * Method to generate the AAI model for a Service or Resource.
56      *
57      * @param model
58      *            Java object model representing an AAI {@link Service} or {@link Resource} model
59      * @return XML representation of the model in String format
60      * @throws XmlArtifactGenerationException
61      */
62     public String generateModelFor(Model model) throws XmlArtifactGenerationException {
63         org.onap.aai.babel.xml.generator.xsd.Model aaiModel = createJaxbModel(model);
64         ModelElement baseWidget = addBaseWidgetRelation(model, aaiModel);
65         generateWidgetChildren(baseWidget, model.getWidgets());
66         return getModelAsString(aaiModel);
67     }
68
69     /**
70      * Create a JAXB Model from the supplied Service or Resource.
71      *
72      * @param model
73      *            the Service or Resource containing the model details
74      * @return a new Model object based on the A&AI schema
75      */
76     private org.onap.aai.babel.xml.generator.xsd.Model createJaxbModel(Model model) {
77         log.debug(model.toString());
78
79         org.onap.aai.babel.xml.generator.xsd.Model aaiModel = new org.onap.aai.babel.xml.generator.xsd.Model();
80         aaiModel.setModelInvariantId(model.getModelId());
81         aaiModel.setModelType(model.getModelTypeName());
82
83         aaiModel.setModelVers(new ModelVers());
84         aaiModel.getModelVers().getModelVer().add(createModelVersion(model));
85
86         return aaiModel;
87     }
88
89     /**
90      * Create a new JAXB object representing the model-ver complex type, and populate this with the Model Version
91      * information.
92      * 
93      * @param model
94      *            the Service or Resource containing the version details
95      * @return a new ModelVer object
96      */
97     private ModelVer createModelVersion(Model model) {
98         ModelVer modelVer = new ModelVer();
99         modelVer.setModelDescription(model.getModelDescription());
100         modelVer.setModelName(model.getModelName());
101         modelVer.setModelVersion(model.getModelVersion());
102         modelVer.setModelVersionId(model.getModelNameVersionId());
103         modelVer.setModelElements(new ModelElements());
104         modelVer.setOrchestrationType(model.getInstantiationType());
105         return modelVer;
106     }
107
108     /**
109      * Add base widget model element for the Service or Resource.
110      * 
111      * @param model
112      *            the Service or Resource containing the Model and child resources
113      * @param aaiModel
114      *            the JAXB Model to populate
115      * @return a new ModelElement for the relationship to the base Widget
116      * @throws XmlArtifactGenerationException
117      */
118     private ModelElement addBaseWidgetRelation(Model model, org.onap.aai.babel.xml.generator.xsd.Model aaiModel)
119             throws XmlArtifactGenerationException {
120         ModelElement widgetElement = createWidgetRelationshipModelElement(model);
121         ModelVer modelVer = aaiModel.getModelVers().getModelVer().get(0);
122         modelVer.getModelElements().getModelElement().add(widgetElement);
123
124         // Add the child resources to the base widget model element list
125         List<ModelElement> modelElements = widgetElement.getModelElements().getModelElement();
126         for (Resource resource : model.getResources()) {
127             modelElements.add(createRelationshipModelElement(resource));
128         }
129
130         return widgetElement;
131     }
132
133     /**
134      * Create a model-element complex type storing the relationship to a Service or Resource model's base Widget.
135      * 
136      * @param model
137      *            the Service or Resource model storing the widget's relationship data
138      * @return a new Java object for the model-element type storing the Widget relationship
139      * @throws XmlArtifactGenerationException
140      */
141     private ModelElement createWidgetRelationshipModelElement(Model model) throws XmlArtifactGenerationException {
142         return createRelationshipModelElement(model.getDeleteFlag(), model.getWidgetId(), model.getWidgetInvariantId());
143     }
144
145     /**
146      * Create a model-element complex type storing the relationship to a Resource model.
147      * 
148      * @param resource
149      *            the Resource model storing the relationship data
150      * @return a new Java object for the model-element type storing the relationship
151      * @throws XmlArtifactGenerationException
152      */
153     private ModelElement createRelationshipModelElement(Resource resource) {
154         return createRelationshipModelElement(resource.getDeleteFlag(), resource.getModelNameVersionId(),
155                 resource.getModelId());
156     }
157
158     /**
159      * Create a model-element complex type storing the relationship to a Widget model.
160      * 
161      * @param widget
162      *            the Widget model storing the relationship data
163      * @return a new Java object for the model-element type storing the Widget relationship
164      */
165     private ModelElement createRelationshipModelElement(Widget widget) {
166         return createRelationshipModelElement(widget.getDeleteFlag(), widget.getId(), widget.getWidgetId());
167     }
168
169     /**
170      * Method to create the <model-element></model-element> holding the relationship value for a resource/widget model.
171      *
172      * @param newDataDelFlag
173      *            new-data-del-flag (mapped from boolean to the string T or F)
174      * @param modelVersionId
175      *            model-version-id
176      * @param modelInvariantId
177      *            model-invariant-id
178      * @return a new Java object for the model-element type storing the relationship
179      */
180     private ModelElement createRelationshipModelElement(boolean newDataDelFlag, String modelVersionId,
181             String modelInvariantId) {
182         ModelElement relationshipModelElement = new ModelElement();
183         relationshipModelElement.setNewDataDelFlag(newDataDelFlag ? "T" : "F");
184         relationshipModelElement.setCardinality("unbounded");
185         relationshipModelElement.setModelElements(new ModelElements());
186         relationshipModelElement.setRelationshipList(createModelRelationship(modelVersionId, modelInvariantId));
187         return relationshipModelElement;
188     }
189
190     /**
191      * Create the Model Version relationship data.
192      * 
193      * @param modelVersionId
194      *            model-version-id
195      * @param modelInvariantId
196      *            model-invariant-id
197      * @return a new RelationshipList object containing the model-ver relationships
198      */
199     private RelationshipList createModelRelationship(String modelVersionId, String modelInvariantId) {
200         Relationship relationship = new Relationship();
201         relationship.setRelatedTo("model-ver");
202         List<RelationshipData> relationshipDataList = relationship.getRelationshipData();
203         relationshipDataList.add(createRelationshipData("model-ver.model-version-id", modelVersionId));
204         relationshipDataList.add(createRelationshipData("model.model-invariant-id", modelInvariantId));
205
206         RelationshipList relationShipList = new RelationshipList();
207         relationShipList.getRelationship().add(relationship);
208         return relationShipList;
209     }
210
211     /**
212      * Create a new RelationshipData element for the given key/value pair.
213      * 
214      * @param key
215      *            relationship key
216      * @param value
217      *            relationship value
218      * @return a new Java object representing the relationship-data complex type
219      */
220     private RelationshipData createRelationshipData(String key, String value) {
221         RelationshipData data = new RelationshipData();
222         data.setRelationshipKey(key);
223         data.setRelationshipValue(value);
224         return data;
225     }
226
227     /**
228      * Method to create the child model elements of the widget. Handles the generation of recursive child widget
229      * elements (if any).
230      * 
231      * @param parent
232      *            Reference to the parent widget model element
233      * @param widgets
234      *            Set of child widgets obtained from the tosca/widget definition
235      */
236     private void generateWidgetChildren(ModelElement parent, Collection<Widget> widgets) {
237         for (Widget widget : widgets) {
238             ModelElement childRelation = createRelationshipModelElement(widget);
239             parent.getModelElements().getModelElement().add(childRelation);
240             // Recursive call to create any child widgets.
241             generateWidgetChildren(childRelation, widget.getWidgets());
242         }
243     }
244
245     /**
246      * JAXB marshalling helper method to convert the Java object model to XML String.
247      *
248      * @param model
249      *            Java Object model of a service/widget/resource
250      * @return XML representation of the Java model in String format
251      */
252     private String getModelAsString(org.onap.aai.babel.xml.generator.xsd.Model model) {
253         JAXBContext jaxbContext;
254         StringWriter modelStringWriter = new StringWriter();
255         try {
256             jaxbContext = JAXBContext.newInstance(org.onap.aai.babel.xml.generator.xsd.Model.class);
257             Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
258             jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
259             jaxbMarshaller.setProperty(Marshaller.JAXB_ENCODING, "US-ASCII");
260             jaxbMarshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
261             jaxbMarshaller.marshal(model, modelStringWriter);
262         } catch (JAXBException jaxbException) {
263             log.error(ApplicationMsgs.INVALID_CSAR_FILE, jaxbException);
264             throw new DOMException(DOMException.SYNTAX_ERR, jaxbException.getMessage());
265         }
266
267         return modelStringWriter.toString();
268     }
269 }