/** * ============LICENSE_START======================================================= * org.onap.aai * ================================================================================ * Copyright © 2017-2019 AT&T Intellectual Property. All rights reserved. * Copyright © 2017-2019 European Software Marketing Ltd. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ============LICENSE_END========================================================= */ package org.onap.aai.babel.xml.generator.api; import java.io.StringWriter; import java.util.List; import java.util.Set; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import org.onap.aai.babel.logging.ApplicationMsgs; import org.onap.aai.babel.logging.LogHelper; import org.onap.aai.babel.xml.generator.XmlArtifactGenerationException; import org.onap.aai.babel.xml.generator.model.Resource; import org.onap.aai.babel.xml.generator.model.Service; import org.onap.aai.babel.xml.generator.model.Widget; import org.onap.aai.babel.xml.generator.xsd.Model; import org.onap.aai.babel.xml.generator.xsd.ModelElement; import org.onap.aai.babel.xml.generator.xsd.ModelElements; import org.onap.aai.babel.xml.generator.xsd.ModelVer; import org.onap.aai.babel.xml.generator.xsd.ModelVers; import org.onap.aai.babel.xml.generator.xsd.Relationship; import org.onap.aai.babel.xml.generator.xsd.RelationshipData; import org.onap.aai.babel.xml.generator.xsd.RelationshipList; import org.onap.aai.cl.api.Logger; import org.w3c.dom.DOMException; /** * Implementation of the {@link AaiModelGenerator} which generates the XML models from the Service/Resource/Widget java * models. */ public class AaiModelGeneratorImpl implements AaiModelGenerator { private static Logger log = LogHelper.INSTANCE; /** * Method to generate the AAI model for a Service. * * @param service * Java object model representing an AAI {@link Service} model * @return XML representation of the service model in String format * @throws XmlArtifactGenerationException */ @Override public String generateModelFor(Service service) throws XmlArtifactGenerationException { // Create a JAXB Model for AAI service model Model aaiServiceModel = new Model(); log.debug("Generating Model for Service with ModelName: " + service.getModelName()); // after new model aaiServiceModel.setModelInvariantId(service.getModelId()); aaiServiceModel.setModelVers(new ModelVers()); ModelVer modelVer = new ModelVer(); modelVer.setModelDescription(service.getModelDescription()); modelVer.setModelName(service.getModelName()); modelVer.setModelVersion(service.getModelVersion()); modelVer.setModelVersionId(service.getModelNameVersionId()); modelVer.setModelElements(new ModelElements()); ModelElements modelElements = modelVer.getModelElements(); // Populate basic model details aaiServiceModel.setModelType(service.getModelType().name().toLowerCase()); // Using enum name as model type List modelElementList = modelElements.getModelElement(); // Add service base widget model element ModelElement serviceWidgetModelRelationshipElement = createRelationshipModelElement( getNewDataDelFlagValue(service.getDeleteFlag()), service.getWidgetId(), service.getWidgetInvariantId()); modelElementList.add(serviceWidgetModelRelationshipElement); // Add the resource model elements ModelElements serviceModelElements = serviceWidgetModelRelationshipElement.getModelElements(); List serviceModelElementList = serviceModelElements.getModelElement(); Set serviceResources = service.getResources(); if (serviceResources != null && !serviceResources.isEmpty()) { for (Resource resourceModel : serviceResources) { ModelElement aaiResourceModelElement = createRelationshipModelElement(getNewDataDelFlagValue(resourceModel.getDeleteFlag()), resourceModel.getModelNameVersionId(), resourceModel.getModelId()); serviceModelElementList.add(aaiResourceModelElement); } } // Add the widget model elements Set serviceWidgets = service.getWidgets(); if (serviceWidgets != null && !serviceWidgets.isEmpty()) { for (Widget widgetModel : serviceWidgets) { ModelElement widgetModelElement = createRelationshipModelElement(getNewDataDelFlagValue(widgetModel.getDeleteFlag()), widgetModel.getId(), widgetModel.getWidgetId()); serviceModelElementList.add(widgetModelElement); } } ModelVers modelVers = aaiServiceModel.getModelVers(); List modelVerList = modelVers.getModelVer(); modelVerList.add(modelVer); return getModelAsString(aaiServiceModel); } /** * Method to generate the AAI model for a Resource. * * @param resource * Java object model representing an AAI {@link Resource} model * @return XML representation of the resource model in String format * @throws XmlArtifactGenerationException */ @Override public String generateModelFor(Resource resource) throws XmlArtifactGenerationException { // Create a JAXB Model for AAI Resource model Model aaiResourceModel = new Model(); log.debug("Generating Model for Resource with ModelName: " + resource.getModelName()); aaiResourceModel.setModelInvariantId(resource.getModelId()); aaiResourceModel.setModelVers(new ModelVers()); ModelVer modelVer = new ModelVer(); modelVer.setModelDescription(resource.getModelDescription()); modelVer.setModelName(resource.getModelName()); modelVer.setModelVersion(resource.getModelVersion()); modelVer.setModelVersionId(resource.getModelNameVersionId()); modelVer.setModelElements(new ModelElements()); ModelElements modelElements = modelVer.getModelElements(); aaiResourceModel.setModelType(resource.getModelType().name().toLowerCase()); // Using enum name as model type List modelElementList = modelElements.getModelElement(); // Add resource base widget model element ModelElement resourceWidgetModelRelationshipElement = createRelationshipModelElement(getNewDataDelFlagValue(resource.getDeleteFlag()), resource.getWidgetId(), resource.getWidgetInvariantId()); modelElementList.add(resourceWidgetModelRelationshipElement); // Add the child resources to the base widget model element list ModelElements baseResourceWidgetModelElements = resourceWidgetModelRelationshipElement.getModelElements(); List baseResourceWidgetModelElementList = baseResourceWidgetModelElements.getModelElement(); Set childResources = resource.getResources(); if (childResources != null && !childResources.isEmpty()) { for (Resource childResourceModel : childResources) { ModelElement aaiChildResourceModelElement = createRelationshipModelElement(getNewDataDelFlagValue(childResourceModel.getDeleteFlag()), childResourceModel.getModelNameVersionId(), childResourceModel.getModelId()); baseResourceWidgetModelElementList.add(aaiChildResourceModelElement); } } // Add resource widgets/resources to the resource widget model relationship element Set resourceWidgets = resource.getWidgets(); if (resourceWidgets != null && !resourceWidgets.isEmpty()) { generateWidgetChildren(resourceWidgetModelRelationshipElement, resourceWidgets); } ModelVers modelVers = aaiResourceModel.getModelVers(); List modelVerList = modelVers.getModelVer(); modelVerList.add(modelVer); return getModelAsString(aaiResourceModel); } /** * Method to create the holding the relationship value for a resource/widget model. * * @param newDataDelFlag * Value of the attribute for a widget/resource in the model xml * @param relationshipValue * Value of the attribute for the widget/resource in the model * xml * @return Java object representation for the holding the relationship */ private ModelElement createRelationshipModelElement(String newDataDelFlag, String modelVersionId, String modelInvariantId) { ModelElement relationshipModelElement = new ModelElement(); relationshipModelElement.setNewDataDelFlag(newDataDelFlag); // Set new-data-del-flag value relationshipModelElement.setCardinality("unbounded"); RelationshipList relationShipList = new RelationshipList(); final List relationships = relationShipList.getRelationship(); Relationship relationship = new Relationship(); relationship.setRelatedTo("model-ver"); List relationshipDataList = relationship.getRelationshipData(); RelationshipData modelVersionRelationshipData = new RelationshipData(); modelVersionRelationshipData.setRelationshipKey("model-ver.model-version-id"); modelVersionRelationshipData.setRelationshipValue(modelVersionId); // Set the widget/resource name-version-uuid // as value relationshipDataList.add(modelVersionRelationshipData); RelationshipData modelInvariantRelationshipData = new RelationshipData(); modelInvariantRelationshipData.setRelationshipKey("model.model-invariant-id"); modelInvariantRelationshipData.setRelationshipValue(modelInvariantId); relationshipDataList.add(modelInvariantRelationshipData); relationships.add(relationship); relationshipModelElement.setRelationshipList(relationShipList); relationshipModelElement.setModelElements(new ModelElements()); return relationshipModelElement; } /** * Method to create the child model elements of the widget. Handles the generation of recursive child widget * elements (if any) * * @param parent * Reference to the parent widget model element * @param widgetChildrenSet * Set of children obtained from the tosca/widget definition */ private void generateWidgetChildren(ModelElement parent, Set widgetChildrenSet) { for (Widget widget : widgetChildrenSet) { Set widgetSubChildren = widget.getWidgets(); if (widgetSubChildren != null && !widgetSubChildren.isEmpty()) { ModelElement widgetChildRelationshipElement = createRelationshipModelElement( getNewDataDelFlagValue(widget.getDeleteFlag()), widget.getId(), widget.getWidgetId()); // Recursive call for getting the children of widgets (if any) generateWidgetChildren(widgetChildRelationshipElement, widgetSubChildren); parent.getModelElements().getModelElement().add(widgetChildRelationshipElement); } else { ModelElement widgetChildRelationshipElement = createRelationshipModelElement( getNewDataDelFlagValue(widget.getDeleteFlag()), widget.getId(), widget.getWidgetId()); parent.getModelElements().getModelElement().add(widgetChildRelationshipElement); } } } /** * Converts the data delete flag value from boolean to String as per AAI model. * * @param delFlag * Boolean value as true/false from the annotation * @return Converted value to a flag as per AAI model */ private String getNewDataDelFlagValue(boolean delFlag) { return delFlag ? "T" : "F"; } /** * JAXB marshalling helper method to convert the Java object model to XML String. * * @param model * Java Object model of a service/widget/resource * @return XML representation of the Java model in String format */ private String getModelAsString(Model model) { JAXBContext jaxbContext; StringWriter modelStringWriter = new StringWriter(); try { jaxbContext = JAXBContext.newInstance(Model.class); Marshaller jaxbMarshaller = jaxbContext.createMarshaller(); jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); jaxbMarshaller.setProperty(Marshaller.JAXB_ENCODING, "US-ASCII"); jaxbMarshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE); jaxbMarshaller.marshal(model, modelStringWriter); } catch (JAXBException jaxbException) { log.error(ApplicationMsgs.INVALID_CSAR_FILE, jaxbException); throw new DOMException(DOMException.SYNTAX_ERR, jaxbException.getMessage()); } return modelStringWriter.toString(); } }