Add support for InstanceGroup resource models 59/65559/1
authormark.j.leonard <mark.j.leonard@gmail.com>
Mon, 10 Sep 2018 14:53:13 +0000 (15:53 +0100)
committermark.j.leonard <mark.j.leonard@gmail.com>
Mon, 10 Sep 2018 14:56:03 +0000 (15:56 +0100)
Generate models for Instance Groups (for specific supported types).
Process groups with a metadata type of CR or Configuration.
Add InstanceGroup Widget to the supported Widgets.

Add support for a group filter properties resource/file (with the
single property key "AAI.instance-group-types" which provides a
comma-separated list of supported types).
Add the System Propery groupfilter.config to define the file path.

Change-Id: I6153e6284965c57ae43291b1dc3ee4a1d11e6583
Issue-ID: AAI-1579
Signed-off-by: mark.j.leonard <mark.j.leonard@gmail.com>
16 files changed:
README.md
src/main/bin/start.sh
src/main/java/org/onap/aai/babel/parser/ArtifactGeneratorToscaParser.java
src/main/java/org/onap/aai/babel/xml/generator/api/AaiArtifactGenerator.java
src/main/java/org/onap/aai/babel/xml/generator/data/WidgetConfigurationUtil.java
src/main/java/org/onap/aai/babel/xml/generator/model/InstanceGroup.java [new file with mode: 0644]
src/main/java/org/onap/aai/babel/xml/generator/model/InstanceGroupWidget.java [new file with mode: 0644]
src/main/java/org/onap/aai/babel/xml/generator/model/Model.java
src/main/java/org/onap/aai/babel/xml/generator/model/VfModule.java
src/main/java/org/onap/aai/babel/xml/generator/model/Widget.java
src/test/java/org/onap/aai/babel/parser/TestToscaParser.java
src/test/java/org/onap/aai/babel/service/CsarToXmlConverterTest.java
src/test/java/org/onap/aai/babel/service/TestGenerateArtifactsServiceImpl.java
src/test/java/org/onap/aai/babel/xml/generator/model/TestModel.java
src/test/resources/artifact-generator.properties
src/test/resources/filter-types.properties [new file with mode: 0644]

index 9943c93..30f2dec 100644 (file)
--- a/README.md
+++ b/README.md
@@ -1,40 +1,36 @@
 # ONAP aai/babel
 
 ## Introduction
-Babel is a microservice in the AAI project that can be used by clients that work with TOSCA CSAR files.
+Babel is a microservice in the AAI project which can be used by clients that work with TOSCA CSAR files.
 
-It parses the TOSCA CSAR to generate xml files from a set of YAML files found in the TOSCA CSAR file.
+It parses TOSCA YAML files extracted from a CSAR payload and generates XML files containing AAI Model data.
 
-## Compiling Babel
-Babel service can be compiled easily using maven command `mvn clean install`  
+## Building Babel
+The Babel service can be built with Maven, e.g. by issuing the command `mvn clean install`  
 
-The compiled results will be the following artifacts in the "target" folder:
+Maven will produce the following artifacts in the "target" folder:
 
-* babel_v{major-version}.zip
-* babel_v{major-version}_props.zip
-* babel-{version}.jar
-* babel-{version}-client.jar
-* babel-{version}-runtimeEnvironment.zip
+* babel.jar
+* babel-client.jar
 * Dockerfile
 * start.sh
 
 Maven will install the following artifacts in the local repository:
 * babel-{version}.jar
 * babel-{version}-client.jar
-* babel-{version}-runtimeEnvironment.zip 
 
-Create the docker image:
+To create the docker image run:
 docker build -t aai/babel target
 
 ## Babel Client
-The project will build a client jar that can be used by clients when using the Babel service.   
+The project will build a client jar which can be used by clients invoking the Babel service.   
 
 The client jar contains two objects that are used in the Babel service API.
 
 BabelRequest is used to supply the inputs into the Babel service.
 BabelArtifact is the response artifact in the list of artifacts returned from the Babel service.
 
-### Deploying The Micro Service 
+### Deploying The Microservice 
 
 Push the Docker image that you have built to your Docker repository and pull it down to the location that you will be running Babel from.
 
index b91c396..c71acca 100644 (file)
@@ -19,8 +19,7 @@
 # limitations under the License.
 # ============LICENSE_END=========================================================
 
-BASEDIR="/opt/app/babel"
-APP_HOME="${BASEDIR}"
+APP_HOME="${APP_HOME:-/opt/app/babel}"
 
 if [ -z "${CONFIG_HOME}" ]; then
        echo "CONFIG_HOME must be set in order to start up process"
@@ -35,7 +34,8 @@ fi
 PROPS="-DAPP_HOME=${APP_HOME}"
 PROPS="${PROPS} -DCONFIG_HOME=${CONFIG_HOME}"
 PROPS="${PROPS} -Dartifactgenerator.config=${CONFIG_HOME}/artifact-generator.properties"
+PROPS="${PROPS} -Dgroupfilter.config=${CONFIG_HOME}/filter-types.properties"
 PROPS="${PROPS} -DKEY_STORE_PASSWORD=${KEY_STORE_PASSWORD}"
 JVM_MAX_HEAP=${MAX_HEAP:-1024}
 
-exec java -Xmx${JVM_MAX_HEAP}m ${PROPS} -jar ${APP_HOME}/babel.jar
\ No newline at end of file
+exec java -Xmx${JVM_MAX_HEAP}m ${PROPS} -jar ${APP_HOME}/babel.jar
index 24e8199..b85ffab 100644 (file)
@@ -24,6 +24,7 @@ package org.onap.aai.babel.parser;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
@@ -33,6 +34,7 @@ import org.onap.aai.babel.logging.ApplicationMsgs;
 import org.onap.aai.babel.logging.LogHelper;
 import org.onap.aai.babel.xml.generator.data.WidgetConfigurationUtil;
 import org.onap.aai.babel.xml.generator.model.AllotedResource;
+import org.onap.aai.babel.xml.generator.model.InstanceGroup;
 import org.onap.aai.babel.xml.generator.model.L3NetworkWidget;
 import org.onap.aai.babel.xml.generator.model.Model;
 import org.onap.aai.babel.xml.generator.model.ProvidingService;
@@ -54,11 +56,12 @@ public class ArtifactGeneratorToscaParser {
     private static Logger log = LogHelper.INSTANCE;
 
     public static final String PROPERTY_ARTIFACT_GENERATOR_CONFIG_FILE = "artifactgenerator.config";
+    public static final String PROPERTY_GROUP_FILTERS_CONFIG_FILE = "groupfilter.config";
 
     private static final String GENERATOR_AAI_CONFIGFILE_NOT_FOUND =
             "Cannot generate artifacts. Artifact Generator Configuration file not found at %s";
     private static final String GENERATOR_AAI_CONFIGLOCATION_NOT_FOUND =
-            "Cannot generate artifacts. artifactgenerator.config system property not configured";
+            "Cannot generate artifacts. System property %s not configured";
     private static final String GENERATOR_AAI_PROVIDING_SERVICE_METADATA_MISSING =
             "Cannot generate artifacts. Providing Service Metadata is missing for allotted resource %s";
     private static final String GENERATOR_AAI_PROVIDING_SERVICE_MISSING =
@@ -117,7 +120,31 @@ public class ArtifactGeneratorToscaParser {
                 throw new IllegalArgumentException(String.format(GENERATOR_AAI_CONFIGFILE_NOT_FOUND, configLocation));
             }
         } else {
-            throw new IllegalArgumentException(GENERATOR_AAI_CONFIGLOCATION_NOT_FOUND);
+            throw new IllegalArgumentException(
+                    String.format(GENERATOR_AAI_CONFIGLOCATION_NOT_FOUND, PROPERTY_ARTIFACT_GENERATOR_CONFIG_FILE));
+        }
+    }
+
+    /**
+     * Initialises the group filter configuration.
+     *
+     * @throws IOException
+     */
+    public static void initGroupFilterConfiguration() throws IOException {
+        log.debug("Getting Filter Tyoes Configuration");
+        String configLocation = System.getProperty(PROPERTY_GROUP_FILTERS_CONFIG_FILE);
+        if (configLocation != null) {
+            File file = new File(configLocation);
+            if (file.exists()) {
+                Properties properties = new Properties();
+                properties.load(new FileInputStream(file));
+                WidgetConfigurationUtil.setFilterConfig(properties);
+            } else {
+                throw new IllegalArgumentException(String.format(GENERATOR_AAI_CONFIGFILE_NOT_FOUND, configLocation));
+            }
+        } else {
+            throw new IllegalArgumentException(
+                    String.format(GENERATOR_AAI_CONFIGLOCATION_NOT_FOUND, PROPERTY_GROUP_FILTERS_CONFIG_FILE));
         }
     }
 
@@ -142,20 +169,20 @@ public class ArtifactGeneratorToscaParser {
         }
     }
 
-
     /**
      * Generates a Resource List using input Service Node Templates.
      *
      * @param serviceNodes input Service Node Templates
      * @param idTypeStore ID->Type mapping
+     *
      * @return the processed resource models
      */
     public List<Resource> processResourceToscas(List<NodeTemplate> serviceNodes, Map<String, String> idTypeStore) {
         List<Resource> resources = new LinkedList<>();
         for (NodeTemplate serviceNode : serviceNodes) {
             if (serviceNode.getMetaData() != null) {
-                List<NodeTemplate> resourceNodes = csarHelper.getNodeTemplateChildren(serviceNode);
-                processResourceTosca(idTypeStore, resources, serviceNode, resourceNodes);
+                resources.addAll(processResourceTosca(idTypeStore, serviceNode,
+                        csarHelper.getNodeTemplateChildren(serviceNode)));
             } else {
                 log.warn(ApplicationMsgs.MISSING_SERVICE_METADATA, serviceNode.getName());
             }
@@ -163,31 +190,96 @@ public class ArtifactGeneratorToscaParser {
         return resources;
     }
 
-    private void processResourceTosca(Map<String, String> idTypeStore, List<Resource> resources,
-            NodeTemplate serviceNode, List<NodeTemplate> resourceNodes) {
+    /**
+     * @param idTypeStore ID->Type mapping
+     * @param serviceNode
+     * @param resourceNodes
+     * @return the processed resource models
+     */
+    private List<Resource> processResourceTosca(Map<String, String> idTypeStore, NodeTemplate serviceNode,
+            List<NodeTemplate> resourceNodes) {
+        List<Resource> resources = new LinkedList<>();
         String resourceUuId = serviceNode.getMetaData().getValue("UUID");
-        String resourceType = idTypeStore.get(resourceUuId);
-        if (resourceType != null) {
-            Model model = Model.getModelFor(resourceType);
+        String nodeTypeName = idTypeStore.get(resourceUuId);
+        if (nodeTypeName != null) {
+            Model resourceModel = Model.getModelFor(nodeTypeName, serviceNode.getMetaData().getValue("type"));
 
-            log.debug("Inside Resource artifact generation for resource");
+            log.debug("Processing resource " + nodeTypeName + ": " + resourceUuId);
             Map<String, String> serviceMetadata = serviceNode.getMetaData().getAllProperties();
-            model.populateModelIdentificationInformation(serviceMetadata);
+            resourceModel.populateModelIdentificationInformation(serviceMetadata);
 
-            // Found model from the type store so removing the same
-            idTypeStore.remove(model.getModelNameVersionId());
-            processVfTosca(idTypeStore, model, resourceNodes);
+            idTypeStore.remove(resourceModel.getModelNameVersionId());
+            processVfTosca(idTypeStore, resourceModel, resourceNodes);
 
-            // Process group information from tosca for vfModules
             if (csarHelper.getServiceVfList() != null) {
-                processVfModules(resources, model, serviceNode);
+                processVfModules(resources, resourceModel, serviceNode);
             }
 
             if (hasSubCategoryTunnelXConnect(serviceMetadata) && hasAllottedResource(serviceMetadata)) {
-                model.addWidget(new TunnelXconnectWidget());
+                resourceModel.addWidget(new TunnelXconnectWidget());
+            }
+
+            resources.addAll(processInstanceGroups(resourceModel, serviceNode));
+            resources.add((Resource) resourceModel);
+        }
+        return resources;
+    }
+
+    /**
+     * Process groups for this service node, according to the defined filter.
+     *
+     * @param resourceModel
+     * @param serviceNode
+     * @return resources for which XML Models should be generated
+     */
+    private List<Resource> processInstanceGroups(Model resourceModel, NodeTemplate serviceNode) {
+        List<Resource> resources = new ArrayList<>();
+        if (csarHelper.getNodeTemplateByName(serviceNode.getName()).getSubMappingToscaTemplate() != null) {
+            List<Group> serviceGroups = csarHelper.getGroupsOfOriginOfNodeTemplate(serviceNode);
+            for (Group group : serviceGroups) {
+                if (WidgetConfigurationUtil.isSupportedInstanceGroup(group.getType())) {
+                    resources.addAll(processInstanceGroup(resourceModel, group));
+                }
+            }
+        }
+        return resources;
+    }
+
+    /**
+     * Create an Instance Group Model for the supplied Service Group and relate this to the supplied resource Model.
+     *
+     * @param resourceModel the Resource node template Model
+     * @param group the Service Group
+     * @return the Instance Group and Member resource models
+     */
+    private List<Resource> processInstanceGroup(Model resourceModel, Group group) {
+        List<Resource> resources = new ArrayList<>();
+
+        Resource groupModel = new InstanceGroup();
+        groupModel.populateModelIdentificationInformation(group.getMetadata().getAllProperties());
+        groupModel.populateModelIdentificationInformation(populateStringProperties(group.getProperties()));
+
+        resourceModel.addResource(groupModel);
+        resources.add(groupModel);
+
+        List<NodeTemplate> members = group.getMemberNodes();
+        if (members != null && !members.isEmpty()) {
+            for (NodeTemplate nodeTemplate : members) {
+                String nodeTypeName = normaliseNodeTypeName(nodeTemplate);
+                Model memberModel = Model.getModelFor(nodeTypeName, nodeTemplate.getMetaData().getValue("type"));
+                memberModel.populateModelIdentificationInformation(nodeTemplate.getMetaData().getAllProperties());
+                if (memberModel instanceof Resource) {
+                    log.debug("Generating grouped Resource " + nodeTypeName);
+                    groupModel.addResource((Resource) memberModel);
+                    resources.add((Resource) memberModel);
+                } else {
+                    log.debug("Generating grouped Widget " + nodeTypeName);
+                    groupModel.addWidget((Widget) memberModel);
+                }
             }
-            resources.add((Resource) model);
         }
+
+        return resources;
     }
 
     /**
@@ -200,7 +292,7 @@ public class ArtifactGeneratorToscaParser {
      */
     private void addNodeToService(Map<String, String> nodesById, Service service, NodeTemplate nodeTemplate) {
         String nodeTypeName = normaliseNodeTypeName(nodeTemplate);
-        Model model = Model.getModelFor(nodeTypeName);
+        Model model = Model.getModelFor(nodeTypeName, nodeTemplate.getMetaData().getValue("type"));
         if (model != null) {
             if (nodeTemplate.getMetaData() != null) {
                 model.populateModelIdentificationInformation(nodeTemplate.getMetaData().getAllProperties());
@@ -215,6 +307,13 @@ public class ArtifactGeneratorToscaParser {
         }
     }
 
+    /**
+     * Process TOSCA Group information for VF Modules.
+     *
+     * @param resources
+     * @param model
+     * @param serviceNode
+     */
     private void processVfModules(List<Resource> resources, Model resourceModel, NodeTemplate serviceNode) {
         // Get the customisation UUID for each VF node and use it to get its Groups
         String uuid = csarHelper.getNodeTemplateCustomizationUuid(serviceNode);
@@ -237,7 +336,11 @@ public class ArtifactGeneratorToscaParser {
         Map<String, Property> groupProperties = groupDefinition.getProperties();
         Map<String, String> properties = populateStringProperties(groupProperties);
         groupModel.populateModelIdentificationInformation(properties);
+        processVfModuleGroup(resources, model, groupDefinition, serviceNode, groupModel);
+    }
 
+    private void processVfModuleGroup(List<Resource> resources, Model model, Group groupDefinition,
+            NodeTemplate serviceNode, VfModule groupModel) {
         // Get names of the members of the service group
         List<NodeTemplate> members = csarHelper.getMembersOfVfModule(serviceNode, groupDefinition);
         if (members != null && !members.isEmpty()) {
@@ -306,13 +409,13 @@ public class ArtifactGeneratorToscaParser {
 
     private void processVfTosca(Map<String, String> idTypeStore, Model resourceModel,
             List<NodeTemplate> resourceNodes) {
-        boolean providingServiceFound = false;
+        boolean foundProvidingService = false;
 
         for (NodeTemplate resourceNodeTemplate : resourceNodes) {
             String nodeTypeName = normaliseNodeTypeName(resourceNodeTemplate);
             Model resourceNode = Model.getModelFor(nodeTypeName);
             if (resourceNode instanceof ProvidingService) {
-                providingServiceFound = true;
+                foundProvidingService = true;
                 Map<String, Property> nodeProperties = resourceNodeTemplate.getProperties();
                 if (nodeProperties.get("providing_service_uuid") == null
                         || nodeProperties.get("providing_service_invariant_uuid") == null) {
@@ -329,9 +432,10 @@ public class ArtifactGeneratorToscaParser {
             }
         }
 
-        if (resourceModel instanceof AllotedResource && !providingServiceFound) {
+        if (resourceModel instanceof AllotedResource && !foundProvidingService) {
             throw new IllegalArgumentException(
                     String.format(GENERATOR_AAI_PROVIDING_SERVICE_MISSING, resourceModel.getModelId()));
         }
     }
+
 }
index 79c7492..ca4cfa2 100644 (file)
@@ -64,6 +64,7 @@ public class AaiArtifactGenerator implements ArtifactGenerator {
 
         try {
             ArtifactGeneratorToscaParser.initWidgetConfiguration();
+            ArtifactGeneratorToscaParser.initGroupFilterConfiguration();
             String serviceVersion = validateServiceVersion(additionalParams);
             GenerationData generationData = new GenerationData();
 
@@ -100,10 +101,10 @@ public class AaiArtifactGenerator implements ArtifactGenerator {
 
                 // Generate AAI XML resource model
                 for (Resource res : resources) {
+                    log.info(ApplicationMsgs.DISTRIBUTION_EVENT, "Generating resource model");
                     MDC.put(MDC_PARAM_MODEL_INFO, res.getModelName() + "," + getArtifactLabel(res));
                     String aaiResourceModel = modelGenerator.generateModelFor(res);
                     generationData.add(getResourceArtifact(res, aaiResourceModel));
-
                 }
             }
             return generationData;
@@ -237,8 +238,7 @@ public class AaiArtifactGenerator implements ArtifactGenerator {
         } else {
             String versionRegex = "^[1-9]\\d*(\\.0)$";
             if (!(serviceVersion.matches(versionRegex))) {
-                throw new IllegalArgumentException(
-                        String.format(GENERATOR_AAI_INVALID_SERVICE_VERSION));
+                throw new IllegalArgumentException(String.format(GENERATOR_AAI_INVALID_SERVICE_VERSION));
             }
         }
         return serviceVersion;
index d36982d..9f8cbf8 100644 (file)
  */
 package org.onap.aai.babel.xml.generator.data;
 
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
 import java.util.Properties;
 
 public class WidgetConfigurationUtil {
 
     private static Properties config;
+    private static List<String> instanceGroups = Collections.emptyList();
 
     /*
      * Private constructor to prevent instantiation
@@ -40,4 +44,15 @@ public class WidgetConfigurationUtil {
     public static void setConfig(Properties config) {
         WidgetConfigurationUtil.config = config;
     }
+
+    public static void setFilterConfig(Properties properties) {
+        String instanceGroupsList = (String) properties.get("AAI.instance-group-types");
+        if (instanceGroupsList != null) {
+            instanceGroups = Arrays.asList(instanceGroupsList.split(","));
+        }
+    }
+
+    public static boolean isSupportedInstanceGroup(String groupType) {
+        return instanceGroups.contains(groupType);
+    }
 }
diff --git a/src/main/java/org/onap/aai/babel/xml/generator/model/InstanceGroup.java b/src/main/java/org/onap/aai/babel/xml/generator/model/InstanceGroup.java
new file mode 100644 (file)
index 0000000..f312064
--- /dev/null
@@ -0,0 +1,28 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * Copyright © 2017-2018 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.model;
+
+import org.onap.aai.babel.xml.generator.types.Cardinality;
+import org.onap.aai.babel.xml.generator.types.Model;
+
+@Model(widget = Widget.Type.INSTANCE_GROUP, cardinality = Cardinality.UNBOUNDED, dataDeleteFlag = true)
+public class InstanceGroup extends Resource {
+}
diff --git a/src/main/java/org/onap/aai/babel/xml/generator/model/InstanceGroupWidget.java b/src/main/java/org/onap/aai/babel/xml/generator/model/InstanceGroupWidget.java
new file mode 100644 (file)
index 0000000..dabce34
--- /dev/null
@@ -0,0 +1,31 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * Copyright © 2017-2018 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.model;
+
+import org.onap.aai.babel.xml.generator.types.Cardinality;
+import org.onap.aai.babel.xml.generator.types.ModelType;
+import org.onap.aai.babel.xml.generator.types.ModelWidget;
+
+@org.onap.aai.babel.xml.generator.types.Model(widget = Widget.Type.INSTANCE_GROUP, cardinality = Cardinality.UNBOUNDED,
+        dataDeleteFlag = true)
+@ModelWidget(type = ModelType.WIDGET, name = "instance-group")
+public class InstanceGroupWidget extends Widget {
+}
index 8e9c062..7b2fc42 100644 (file)
@@ -20,7 +20,6 @@
  */
 package org.onap.aai.babel.xml.generator.model;
 
-import java.lang.reflect.InvocationTargetException;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -159,14 +158,33 @@ public abstract class Model {
         if (clazz != null) {
             try {
                 modelToBeReturned = Optional.ofNullable(clazz.getConstructor().newInstance());
-            } catch (InstantiationException | java.lang.IllegalAccessException | IllegalArgumentException
-                    | InvocationTargetException | NoSuchMethodException | SecurityException e) {
+            } catch (Exception e) {
                 log.error(ApplicationMsgs.INVALID_CSAR_FILE, e);
             }
         }
         return modelToBeReturned;
     }
 
+    /**
+     * Gets the object (model) corresponding to the supplied TOSCA type information, prioritising the metadata
+     * information.
+     *
+     * @param toscaType
+     *            the TOSCA type
+     * @param metaDataType
+     *            the type from the TOSCA metadata
+     * @return the model for the type, or null
+     */
+    public static Model getModelFor(String toscaType, String metaDataType) {
+        if ("Configuration".equals(metaDataType)) {
+            return new Configuration();
+        } else if ("CR".equals(metaDataType)) {
+            return new CR();
+        } else {
+            return getModelFor(toscaType);
+        }
+    }
+
     public abstract boolean addResource(Resource resource);
 
     public abstract boolean addWidget(Widget resource);
@@ -291,4 +309,5 @@ public abstract class Model {
             throw new IllegalAccessException(GENERATOR_AAI_ERROR_UNSUPPORTED_WIDGET_OPERATION);
         }
     }
+
 }
index 8b8913d..d6d3a2d 100644 (file)
@@ -38,7 +38,7 @@ public class VfModule extends Resource {
     }
 
     /**
-     * Adds Widget.
+     * Adds Widget.
      *
      * @param widget the widget
      * @return the boolean
index 49e3811..d78e2e6 100644 (file)
@@ -38,10 +38,28 @@ import org.onap.aai.cl.api.Logger;
 
 public abstract class Widget extends Model {
 
-    public static final String GENERATOR_AAI_CONFIGLPROP_NOT_FOUND = "Cannot generate artifacts. Widget configuration not found for %s";
+    public static final String GENERATOR_AAI_CONFIGLPROP_NOT_FOUND =
+            "Cannot generate artifacts. Widget configuration not found for %s";
 
     public enum Type {
-        SERVICE, VF, VFC, VSERVER, VOLUME, FLAVOR, TENANT, VOLUME_GROUP, LINT, L3_NET, VFMODULE, IMAGE, OAM_NETWORK, ALLOTTED_RESOURCE, TUNNEL_XCONNECT, CONFIGURATION, CR;
+        SERVICE,
+        VF,
+        VFC,
+        VSERVER,
+        VOLUME,
+        FLAVOR,
+        TENANT,
+        VOLUME_GROUP,
+        LINT,
+        L3_NET,
+        VFMODULE,
+        IMAGE,
+        OAM_NETWORK,
+        ALLOTTED_RESOURCE,
+        TUNNEL_XCONNECT,
+        CONFIGURATION,
+        CR,
+        INSTANCE_GROUP;
     }
 
     private static Logger log = LogHelper.INSTANCE;
@@ -67,13 +85,13 @@ public abstract class Widget extends Model {
         typeToWidget.put(Type.TUNNEL_XCONNECT, TunnelXconnectWidget.class);
         typeToWidget.put(Type.CONFIGURATION, ConfigurationWidget.class);
         typeToWidget.put(Type.CR, CRWidget.class);
+        typeToWidget.put(Type.INSTANCE_GROUP, InstanceGroupWidget.class);
     }
 
     /**
      * Gets widget.
      *
-     * @param type
-     *            the type
+     * @param type the type
      * @return the widget
      */
     public static Widget getWidget(Type type) {
@@ -139,8 +157,7 @@ public abstract class Widget extends Model {
     /**
      * Equals method that compares Widget IDs.
      *
-     * @param obj
-     *            the Widget object to compare
+     * @param obj the Widget object to compare
      * @return whether or not obj is equal to this Widget
      */
     @Override
@@ -163,8 +180,7 @@ public abstract class Widget extends Model {
     /**
      * Determine whether one or more keys belonging to this Widget appear in the specified Collection.
      *
-     * @param keys
-     *            the keys
+     * @param keys the keys
      * @return the boolean
      */
     public boolean memberOf(Collection<String> keys) {
@@ -183,5 +199,4 @@ public abstract class Widget extends Model {
     public boolean addWidget(Widget widget) {
         return true;
     }
-
 }
index f340132..3bab915 100644 (file)
@@ -54,12 +54,16 @@ public class TestToscaParser {
     }
 
     private static final String ARTIFACT_GENERATOR_CONFIG = "artifact-generator.properties";
+    private static final String FILTER_TYPES_CONFIG = "filter-types.properties";
 
     @Before
     public void setup() throws FileNotFoundException, IOException {
         System.setProperty(ArtifactGeneratorToscaParser.PROPERTY_ARTIFACT_GENERATOR_CONFIG_FILE,
                 new ArtifactTestUtils().getResourcePath(ARTIFACT_GENERATOR_CONFIG));
 
+        System.setProperty(ArtifactGeneratorToscaParser.PROPERTY_GROUP_FILTERS_CONFIG_FILE,
+                new ArtifactTestUtils().getResourcePath(FILTER_TYPES_CONFIG));
+
         InputStream in = TestToscaParser.class.getClassLoader().getResourceAsStream("artifact-generator.properties");
         Properties properties = new Properties();
         properties.load(in);
index 67539bb..bf970a6 100644 (file)
@@ -52,6 +52,8 @@ import org.onap.aai.babel.xml.generator.XmlArtifactGenerationException;
 public class CsarToXmlConverterTest {
 
     private static final String ARTIFACT_GENERATOR_CONFIG = "artifact-generator.properties";
+    private static final String FILTER_TYPES_CONFIG = "filter-types.properties";
+
     private static final String INCORRECT_CSAR_NAME = "the_name_of_the_csar_file.csar";
     private static final String SERVICE_VERSION = "1.0";
 
@@ -71,6 +73,10 @@ public class CsarToXmlConverterTest {
     public void setup() {
         System.setProperty(ArtifactGeneratorToscaParser.PROPERTY_ARTIFACT_GENERATOR_CONFIG_FILE,
                 new ArtifactTestUtils().getResourcePath(ARTIFACT_GENERATOR_CONFIG));
+
+        System.setProperty(ArtifactGeneratorToscaParser.PROPERTY_GROUP_FILTERS_CONFIG_FILE,
+                new ArtifactTestUtils().getResourcePath(FILTER_TYPES_CONFIG));
+
         converter = new CsarToXmlConverter();
     }
 
@@ -110,15 +116,14 @@ public class CsarToXmlConverterTest {
      *
      * @throws CsarConverterException if there is an error either extracting the YAML files or generating XML artifacts
      * @throws IOException if an I/O exception occurs loading the test CSAR file
+     * @throws IOException
+     * @throws XmlArtifactGenerationException
+     * @throws CsarConverterException
      */
     @Test
     public void testArtifactGeneratorConfigMissing() throws CsarConverterException, IOException {
         exception.expect(CsarConverterException.class);
-        exception.expectMessage(
-                "An error occurred trying to generate XML files from a collection of YAML files :"
-                        + " org.onap.aai.babel.xml.generator.XmlArtifactGenerationException: "
-                        + "Error occurred during artifact generation: "
-                        + "{AAI=[Cannot generate artifacts. artifactgenerator.config system property not configured]}");
+        exception.expectMessage("Cannot generate artifacts. System property artifactgenerator.config not configured");
 
         // Unset the required system property
         System.clearProperty(ArtifactGeneratorToscaParser.PROPERTY_ARTIFACT_GENERATOR_CONFIG_FILE);
@@ -126,6 +131,25 @@ public class CsarToXmlConverterTest {
                 SERVICE_VERSION);
     }
 
+    /**
+     * Test that an Exception is thrown when the Artifact Generator's Group Filter properties are not present.
+     *
+     * @throws IOException
+     * @throws XmlArtifactGenerationException
+     * @throws CsarConverterException
+     */
+    @Test
+    public void generateXmlFromCsarFilterTypesSystemPropertyNotSet()
+            throws IOException, XmlArtifactGenerationException, CsarConverterException {
+        exception.expect(CsarConverterException.class);
+        exception.expectMessage("Cannot generate artifacts. System property groupfilter.config not configured");
+
+        // Unset the required system property
+        System.clearProperty(ArtifactGeneratorToscaParser.PROPERTY_GROUP_FILTERS_CONFIG_FILE);
+        converter.generateXmlFromCsar(CsarTest.SD_WAN_CSAR_FILE.getContent(), CsarTest.SD_WAN_CSAR_FILE.getName(),
+                SERVICE_VERSION);
+    }
+
     @Test
     public void testServiceMetadataMissing()
             throws IOException, XmlArtifactGenerationException, CsarConverterException {
index 599b3ff..78e02f4 100644 (file)
@@ -55,7 +55,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
  *
  */
 @RunWith(SpringJUnit4ClassRunner.class)
-@ContextConfiguration(locations = {"classpath:/babel-beans.xml"})
+@ContextConfiguration(locations = { "classpath:/babel-beans.xml" })
 public class TestGenerateArtifactsServiceImpl {
 
     static {
@@ -66,6 +66,7 @@ public class TestGenerateArtifactsServiceImpl {
     }
 
     private static final String ARTIFACT_GENERATOR_CONFIG = "artifact-generator.properties";
+    private static final String FILTER_TYPES_CONFIG = "filter-types.properties";
 
     @Inject
     private AAIMicroServiceAuth auth;
@@ -74,6 +75,8 @@ public class TestGenerateArtifactsServiceImpl {
     public static void setup() {
         System.setProperty(ArtifactGeneratorToscaParser.PROPERTY_ARTIFACT_GENERATOR_CONFIG_FILE,
                 new ArtifactTestUtils().getResourcePath(ARTIFACT_GENERATOR_CONFIG));
+        System.setProperty(ArtifactGeneratorToscaParser.PROPERTY_GROUP_FILTERS_CONFIG_FILE,
+                new ArtifactTestUtils().getResourcePath(FILTER_TYPES_CONFIG));
     }
 
     @Test
@@ -148,8 +151,10 @@ public class TestGenerateArtifactsServiceImpl {
      *
      * @param csar
      * @return the Response from the HTTP API
-     * @throws URISyntaxException if the URI cannot be created
-     * @throws IOException if the resource cannot be loaded
+     * @throws URISyntaxException
+     *             if the URI cannot be created
+     * @throws IOException
+     *             if the resource cannot be loaded
      */
     private Response processJsonRequest(CsarTest csar) throws IOException, URISyntaxException {
         String jsonString = csar.getJsonRequest();
@@ -159,9 +164,11 @@ public class TestGenerateArtifactsServiceImpl {
     /**
      * Create a (mocked) HTTPS request and invoke the Babel generate artifacts API.
      *
-     * @param jsonString the JSON request
+     * @param jsonString
+     *            the JSON request
      * @return the Response from the HTTP API
-     * @throws URISyntaxException if the URI cannot be created
+     * @throws URISyntaxException
+     *             if the URI cannot be created
      */
     private Response invokeService(String jsonString) throws URISyntaxException {
         UriInfo mockUriInfo = Mockito.mock(UriInfo.class);
@@ -192,7 +199,7 @@ public class TestGenerateArtifactsServiceImpl {
         Mockito.when(mockCertificate.getSubjectX500Principal())
                 .thenReturn(new X500Principal("CN=test, OU=qa, O=Test Ltd, L=London, ST=London, C=GB"));
 
-        servletRequest.setAttribute("javax.servlet.request.X509Certificate", new X509Certificate[] {mockCertificate});
+        servletRequest.setAttribute("javax.servlet.request.X509Certificate", new X509Certificate[] { mockCertificate });
         servletRequest.setAttribute("javax.servlet.request.cipher_suite", "");
 
         GenerateArtifactsServiceImpl service = new GenerateArtifactsServiceImpl(auth);
index 2bd6fc7..9b5700d 100644 (file)
@@ -45,7 +45,7 @@ import org.onap.aai.babel.xml.generator.types.ModelType;
 public class TestModel {
 
     private Service serviceModel = new Service();
-    private List<Resource> resourceModels = Arrays.asList(new VirtualFunction());
+    private List<Resource> resourceModels = Arrays.asList(new VirtualFunction(), new InstanceGroup());
     private Widget widgetModel = new OamNetwork();
     private Model anonymousModel;
 
@@ -109,6 +109,13 @@ public class TestModel {
         assertThat(Model.getModelFor("org.openecomp.resource.vfc.nodes.heat.cinder"), instanceOf(VolumeWidget.class));
         assertThat(Model.getModelFor("org.openecomp.nodes.PortMirroringConfiguration"),
                 instanceOf(Configuration.class));
+        assertThat(Model.getModelFor("org.openecomp.nodes.PortMirroringConfiguration", "Configuration"),
+                instanceOf(Configuration.class));
+        assertThat(Model.getModelFor("any.string", "Configuration"), instanceOf(Configuration.class));
+        assertThat(Model.getModelFor("org.openecomp.resource.cr.Kk1806Cr1", "CR"), instanceOf(CR.class));
+        assertThat(Model.getModelFor("any.string", "CR"), instanceOf(CR.class));
+
+        assertThat(Model.getModelFor("org.openecomp.resource.vfc", "an.unknown.type"), instanceOf(VServerWidget.class));
     }
 
     @Test
index ba207cf..1a905b6 100644 (file)
@@ -1,4 +1,4 @@
-#action widget details
+#action widget details
 AAI.model-version-id.action=action-version-id
 AAI.model-invariant-id.action=action-invariant-id
 #action-data widget details
@@ -265,3 +265,6 @@ AAI.model-version-id.vpn-binding=vpn-binding-version-id
 #vserver widget details
 AAI.model-invariant-id.vserver=vserver-invariant-id
 AAI.model-version-id.vserver=vserver-version-id
+#cr (Collection Resource) widget details
+AAI.model-version-id.cr=collection-resource-version-id
+AAI.model-invariant-id.cr=collection-resource-invariant-id
diff --git a/src/test/resources/filter-types.properties b/src/test/resources/filter-types.properties
new file mode 100644 (file)
index 0000000..fcf139f
--- /dev/null
@@ -0,0 +1 @@
+AAI.instance-group-types=org.openecomp.groups.NetworkCollection,org.openecomp.groups.VfcInstanceGroup