Return List<Artifact> in ArtifactDownloadManager
[aai/model-loader.git] / src / main / java / org / onap / aai / modelloader / notification / ArtifactDownloadManager.java
index bdd101e..e2c5e27 100644 (file)
@@ -1,52 +1,55 @@
 /**
- * ============LICENSE_START==========================================
+ * ============LICENSE_START=======================================================
  * org.onap.aai
- * ===================================================================
+ * ================================================================================
  * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
- * Copyright © 2017-2018 Amdocs
- * ===================================================================
+ * 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
+ *       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============================================
+ * ============LICENSE_END=========================================================
  */
 package org.onap.aai.modelloader.notification;
 
 import java.time.ZonedDateTime;
 import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
 import java.util.Base64;
 import java.util.List;
-import java.util.Map;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
-import org.onap.aai.babel.service.data.BabelArtifact;
-import org.onap.aai.babel.service.data.BabelArtifact.ArtifactType;
+import org.onap.aai.babel.service.data.BabelRequest;
 import org.onap.aai.cl.api.Logger;
 import org.onap.aai.cl.eelf.LoggerFactory;
 import org.onap.aai.cl.mdc.MdcContext;
 import org.onap.aai.cl.mdc.MdcOverride;
-import org.onap.aai.modelloader.config.ModelLoaderConfig;
+import org.onap.aai.modelloader.babel.BabelArtifactService;
 import org.onap.aai.modelloader.entity.Artifact;
+import org.onap.aai.modelloader.entity.ArtifactType;
+import org.onap.aai.modelloader.entity.catalog.VnfCatalogArtifact;
 import org.onap.aai.modelloader.entity.model.BabelArtifactParsingException;
 import org.onap.aai.modelloader.entity.model.IModelParser;
 import org.onap.aai.modelloader.entity.model.NamedQueryArtifactParser;
 import org.onap.aai.modelloader.extraction.InvalidArchiveException;
-import org.onap.aai.modelloader.restclient.BabelServiceClient;
+import org.onap.aai.modelloader.extraction.VnfCatalogExtractor;
 import org.onap.aai.modelloader.service.ModelLoaderMsgs;
-import org.openecomp.sdc.api.IDistributionClient;
-import org.openecomp.sdc.api.notification.IArtifactInfo;
-import org.openecomp.sdc.api.notification.INotificationData;
-import org.openecomp.sdc.api.results.IDistributionClientDownloadResult;
-import org.openecomp.sdc.utils.ArtifactTypeEnum;
-import org.openecomp.sdc.utils.DistributionActionResultEnum;
+import org.onap.sdc.api.IDistributionClient;
+import org.onap.sdc.api.notification.IArtifactInfo;
+import org.onap.sdc.api.notification.INotificationData;
+import org.onap.sdc.api.results.IDistributionClientDownloadResult;
+import org.onap.sdc.utils.ArtifactTypeEnum;
+import org.onap.sdc.utils.DistributionActionResultEnum;
+import org.springframework.stereotype.Component;
 
 /**
  * This class is responsible for downloading the artifacts from the ASDC.
@@ -58,18 +61,22 @@ import org.openecomp.sdc.utils.DistributionActionResultEnum;
  *
  * TOSCA_CSAR file artifacts will be converted into XML and returned as model artifacts.
  */
+@Component
 public class ArtifactDownloadManager {
 
     private static Logger logger = LoggerFactory.getInstance().getLogger(ArtifactDownloadManager.class);
 
-    private IDistributionClient client;
-    private NotificationPublisher notificationPublisher;
-    private BabelArtifactConverter babelArtifactConverter;
-    private ModelLoaderConfig config;
+    private final IDistributionClient client;
+    private final NotificationPublisher notificationPublisher;
+    private final VnfCatalogExtractor vnfCatalogExtractor;
+    private final BabelArtifactService babelArtifactService;
 
-    public ArtifactDownloadManager(IDistributionClient client, ModelLoaderConfig config) {
+    public ArtifactDownloadManager(IDistributionClient client,
+            NotificationPublisher notificationPublisher, VnfCatalogExtractor vnfCatalogExtractor, BabelArtifactService babelArtifactService) {
         this.client = client;
-        this.config = config;
+        this.notificationPublisher = notificationPublisher;
+        this.vnfCatalogExtractor = vnfCatalogExtractor;
+        this.babelArtifactService = babelArtifactService;
     }
 
     /**
@@ -80,29 +87,25 @@ public class ArtifactDownloadManager {
      * @param modelArtifacts collection of artifacts for model query specs
      * @param catalogArtifacts collection of artifacts that represent vnf catalog files
      * @return boolean <code>true</code> if the download process was successful otherwise <code>false</code>
+     * @throws Exception 
      */
-    boolean downloadArtifacts(INotificationData data, List<IArtifactInfo> artifacts, List<Artifact> modelArtifacts,
-            List<Artifact> catalogArtifacts) {
-        boolean success = true;
+    List<Artifact> downloadArtifacts(INotificationData data, List<IArtifactInfo> artifacts) throws Exception {
 
+        List<Artifact> allArtifacts = new ArrayList<>();
         for (IArtifactInfo artifact : artifacts) {
             try {
                 IDistributionClientDownloadResult downloadResult = downloadIndividualArtifacts(data, artifact);
-                processDownloadedArtifacts(modelArtifacts, catalogArtifacts, artifact, downloadResult, data);
+                List<Artifact> processedArtifacts = processDownloadedArtifacts(artifact, downloadResult, data);
+                allArtifacts.addAll(processedArtifacts);
             } catch (DownloadFailureException e) {
-                getNotificationPublisher().publishDownloadFailure(client, data, artifact, e.getMessage());
-                success = false;
-            } catch (Exception e) {
-                getNotificationPublisher().publishDeployFailure(client, data, artifact);
-                success = false;
-            }
-
-            if (!success) {
-                break;
+                notificationPublisher.publishDownloadFailure(client, data, artifact, e.getMessage());
+                throw e;
+            } catch (ProcessToscaArtifactsException | InvalidArchiveException | BabelArtifactParsingException e) {
+                notificationPublisher.publishDeployFailure(client, data, artifact);
+                throw e;
             }
         }
-
-        return success;
+        return allArtifacts;
     }
 
     private IDistributionClientDownloadResult downloadIndividualArtifacts(INotificationData data,
@@ -120,7 +123,7 @@ public class ArtifactDownloadManager {
 
         if (DistributionActionResultEnum.SUCCESS.equals(downloadResult.getDistributionActionResult())) {
             logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, "Downloaded artifact: " + artifact.getArtifactName());
-            getNotificationPublisher().publishDownloadSuccess(client, data, artifact);
+            notificationPublisher.publishDownloadSuccess(client, data, artifact);
         } else {
             throw new DownloadFailureException(downloadResult.getDistributionMessageResult());
         }
@@ -128,91 +131,59 @@ public class ArtifactDownloadManager {
         return downloadResult;
     }
 
-    private void processDownloadedArtifacts(List<Artifact> modelArtifacts, List<Artifact> catalogArtifacts,
+    private List<Artifact> processDownloadedArtifacts(
             IArtifactInfo artifactInfo, IDistributionClientDownloadResult downloadResult, INotificationData data)
             throws ProcessToscaArtifactsException, InvalidArchiveException, BabelArtifactParsingException {
+        List<Artifact> artifacts = new ArrayList<>();
+        List<Artifact> querySpecArtifacts = new ArrayList<>();
         if ("TOSCA_CSAR".equalsIgnoreCase(artifactInfo.getArtifactType())) {
-            processToscaArtifacts(modelArtifacts, catalogArtifacts, downloadResult.getArtifactPayload(), artifactInfo,
+            artifacts = processToscaArtifacts(downloadResult.getArtifactPayload(), artifactInfo,
                     data.getDistributionID(), data.getServiceVersion());
+            
         } else if (ArtifactTypeEnum.MODEL_QUERY_SPEC.toString().equalsIgnoreCase(artifactInfo.getArtifactType())) {
-            processModelQuerySpecArtifact(modelArtifacts, downloadResult);
+            querySpecArtifacts = processModelQuerySpecArtifact(downloadResult);
         } else {
             logger.info(ModelLoaderMsgs.UNSUPPORTED_ARTIFACT_TYPE, artifactInfo.getArtifactName(),
                     artifactInfo.getArtifactType());
             throw new InvalidArchiveException("Unsupported artifact type: " + artifactInfo.getArtifactType());
         }
+        return Stream
+            .concat(artifacts.stream(), querySpecArtifacts.stream())
+            .collect(Collectors.toList());
     }
 
-    public void processToscaArtifacts(List<Artifact> modelArtifacts, List<Artifact> catalogArtifacts, byte[] payload,
-            IArtifactInfo artifactInfo, String distributionId, String serviceVersion)
-            throws ProcessToscaArtifactsException {
-        try {
-            BabelServiceClient babelClient = createBabelServiceClient(artifactInfo, serviceVersion);
-
-            logger.debug(ModelLoaderMsgs.DISTRIBUTION_EVENT,
-                    "Posting artifact: " + artifactInfo.getArtifactName() + ", version: " + serviceVersion);
-
-            List<BabelArtifact> babelArtifacts =
-                    babelClient.postArtifact(payload, artifactInfo.getArtifactName(), serviceVersion, distributionId);
-
-            // Sort Babel artifacts based on type
-            Map<ArtifactType, List<BabelArtifact>> artifactMap =
-                    babelArtifacts.stream().collect(Collectors.groupingBy(BabelArtifact::getType));
-
-            if (artifactMap.containsKey(BabelArtifact.ArtifactType.MODEL)) {
-                modelArtifacts.addAll(
-                        getBabelArtifactConverter().convertToModel(artifactMap.get(BabelArtifact.ArtifactType.MODEL)));
-                artifactMap.remove(BabelArtifact.ArtifactType.MODEL);
-            }
-
-            if (artifactMap.containsKey(BabelArtifact.ArtifactType.VNFCATALOG)) {
-                catalogArtifacts.addAll(getBabelArtifactConverter()
-                        .convertToCatalog(artifactMap.get(BabelArtifact.ArtifactType.VNFCATALOG)));
-                artifactMap.remove(BabelArtifact.ArtifactType.VNFCATALOG);
-            }
-
-            // Log unexpected artifact types
-            if (!artifactMap.isEmpty()) {
-                logger.warn(ModelLoaderMsgs.ARTIFACT_PARSE_ERROR,
-                        artifactInfo.getArtifactName() + " " + serviceVersion
-                                + ". Unexpected artifact types returned by the babel service: "
-                                + artifactMap.keySet().toString());
-            }
-
-        } catch (BabelArtifactParsingException e) {
-            logger.error(ModelLoaderMsgs.ARTIFACT_PARSE_ERROR,
-                    "Error for artifact " + artifactInfo.getArtifactName() + " " + serviceVersion + e);
-            throw new ProcessToscaArtifactsException(
-                    "An error occurred while trying to parse the Babel artifacts: " + e.getLocalizedMessage());
-        } catch (Exception e) {
-            logger.error(ModelLoaderMsgs.BABEL_REST_REQUEST_ERROR, e, "POST", config.getBabelBaseUrl(),
-                    "Error posting artifact " + artifactInfo.getArtifactName() + " " + serviceVersion + " to Babel: "
-                            + e.getLocalizedMessage());
-            throw new ProcessToscaArtifactsException(
-                    "An error occurred while calling the Babel service: " + e.getLocalizedMessage());
+    public List<Artifact> processToscaArtifacts(byte[] payload, IArtifactInfo artifactInfo, String distributionId, String serviceVersion)
+            throws ProcessToscaArtifactsException, InvalidArchiveException {
+        // Get translated artifacts from Babel Service
+        BabelRequest babelRequest = new BabelRequest();
+        babelRequest.setArtifactName(artifactInfo.getArtifactName());
+        babelRequest.setCsar(Base64.getEncoder().encodeToString(payload));
+        babelRequest.setArtifactVersion(serviceVersion);
+        List<Artifact> artifacts = babelArtifactService.invokeBabelService(babelRequest, distributionId);
+
+        // Get VNF Catalog artifacts directly from CSAR
+        List<Artifact> csarCatalogArtifacts = vnfCatalogExtractor.extract(payload, artifactInfo.getArtifactName());
+
+        // Throw an error if VNF Catalog data is present in the Babel payload and directly in the CSAR
+        if (isDuplicateVnfCatalogData(artifacts, csarCatalogArtifacts)) {
+            logger.error(ModelLoaderMsgs.DUPLICATE_VNFC_DATA_ERROR, artifactInfo.getArtifactName());
+            throw new InvalidArchiveException("CSAR: " + artifactInfo.getArtifactName()
+                    + " contains VNF Catalog data in the format of both TOSCA and XML files. Only one format can be used for each CSAR file.");
         }
-    }
+        return Stream
+                .concat(artifacts.stream(), csarCatalogArtifacts.stream())
+                .collect(Collectors.toList());
 
-    private BabelServiceClient createBabelServiceClient(IArtifactInfo artifact, String serviceVersion)
-            throws ProcessToscaArtifactsException {
-        BabelServiceClient babelClient;
-        try {
-            logger.debug(ModelLoaderMsgs.DISTRIBUTION_EVENT, "Creating Babel client");
-            babelClient = new BabelServiceClient(config);
-        } catch (Exception e) {
-            logger.error(ModelLoaderMsgs.BABEL_REST_REQUEST_ERROR, e, "POST", config.getBabelBaseUrl(),
-                    "Error posting artifact " + artifact.getArtifactName() + " " + serviceVersion + " to Babel: "
-                            + e.getLocalizedMessage());
-            throw new ProcessToscaArtifactsException(
-                    "An error occurred tyring to convert the tosca artifacts to xml artifacts: "
-                            + e.getLocalizedMessage());
-        }
+    }
 
-        return babelClient;
+    private boolean isDuplicateVnfCatalogData(List<Artifact> babelArtifacts, List<Artifact> csarCatalogArtifacts) {
+        boolean babelIsEmpty = babelArtifacts.stream()
+            .filter(VnfCatalogArtifact.class::isInstance)
+            .findAny().isEmpty();
+        return !csarCatalogArtifacts.isEmpty() && !babelIsEmpty;
     }
 
-    private void processModelQuerySpecArtifact(List<Artifact> modelArtifacts,
-            IDistributionClientDownloadResult downloadResult) throws BabelArtifactParsingException {
+    private List<Artifact> processModelQuerySpecArtifact(IDistributionClientDownloadResult downloadResult) throws BabelArtifactParsingException {
         logger.debug(ModelLoaderMsgs.DISTRIBUTION_EVENT, "Processing named query artifact.");
 
         IModelParser parser = new NamedQueryArtifactParser();
@@ -220,31 +191,11 @@ public class ArtifactDownloadManager {
         List<Artifact> parsedArtifacts =
                 parser.parse(new String(downloadResult.getArtifactPayload()), downloadResult.getArtifactFilename());
 
-        if (parsedArtifactsExist(parsedArtifacts)) {
-            modelArtifacts.addAll(parsedArtifacts);
+        if (parsedArtifacts != null && !parsedArtifacts.isEmpty()) {
+            return parsedArtifacts;
         } else {
             throw new BabelArtifactParsingException(
                     "Could not parse generated XML: " + new String(downloadResult.getArtifactPayload()));
         }
     }
-
-    private boolean parsedArtifactsExist(List<Artifact> parsedArtifacts) {
-        return parsedArtifacts != null && !parsedArtifacts.isEmpty();
-    }
-
-    private NotificationPublisher getNotificationPublisher() {
-        if (notificationPublisher == null) {
-            notificationPublisher = new NotificationPublisher();
-        }
-
-        return notificationPublisher;
-    }
-
-    private BabelArtifactConverter getBabelArtifactConverter() {
-        if (babelArtifactConverter == null) {
-            babelArtifactConverter = new BabelArtifactConverter();
-        }
-
-        return babelArtifactConverter;
-    }
 }