Revisions made to the Model Loader to use Babel
[aai/model-loader.git] / src / main / java / org / onap / aai / modelloader / entity / catalog / VnfCatalogArtifactHandler.java
index 9022516..b224407 100644 (file)
  */\r
 package org.onap.aai.modelloader.entity.catalog;\r
 \r
-import com.sun.jersey.api.client.ClientResponse;\r
-\r
-import generated.VnfCatalog;\r
-import generated.VnfCatalog.PartNumberList;\r
-\r
-import inventory.aai.openecomp.org.v8.VnfImage;\r
-\r
-import org.eclipse.persistence.jaxb.MarshallerProperties;\r
+import com.google.gson.Gson;\r
+import com.google.gson.reflect.TypeToken;\r
+import java.io.UnsupportedEncodingException;\r
+import java.util.List;\r
+import java.util.Map;\r
+import java.util.Map.Entry;\r
+import java.util.UUID;\r
+import javax.ws.rs.core.MediaType;\r
+import javax.ws.rs.core.Response;\r
+import org.apache.commons.text.StringEscapeUtils;\r
+import org.onap.aai.cl.api.Logger;\r
+import org.onap.aai.cl.eelf.LoggerFactory;\r
 import org.onap.aai.modelloader.config.ModelLoaderConfig;\r
 import org.onap.aai.modelloader.entity.Artifact;\r
 import org.onap.aai.modelloader.entity.ArtifactHandler;\r
 import org.onap.aai.modelloader.restclient.AaiRestClient;\r
-import org.onap.aai.modelloader.restclient.AaiRestClient.MimeType;\r
 import org.onap.aai.modelloader.service.ModelLoaderMsgs;\r
-import org.onap.aai.cl.api.Logger;\r
-import org.onap.aai.cl.eelf.LoggerFactory;\r
+import org.onap.aai.restclient.client.OperationResult;\r
 import org.springframework.web.util.UriUtils;\r
 \r
-import java.io.StringReader;\r
-import java.io.StringWriter;\r
-import java.io.UnsupportedEncodingException;\r
-import java.util.ArrayList;\r
-import java.util.List;\r
-import java.util.UUID;\r
-\r
-import javax.ws.rs.core.Response;\r
-import javax.xml.bind.JAXBContext;\r
-import javax.xml.bind.JAXBException;\r
-import javax.xml.bind.Marshaller;\r
-import javax.xml.bind.Unmarshaller;\r
-\r
-\r
+/**\r
+ * VNF Catalog specific handling\r
+ */\r
 public class VnfCatalogArtifactHandler extends ArtifactHandler {\r
 \r
-  private static Logger logger = LoggerFactory.getInstance()\r
-      .getLogger(VnfCatalogArtifactHandler.class.getName());\r
-\r
-  public VnfCatalogArtifactHandler(ModelLoaderConfig config) {\r
-    super(config);\r
-  }\r
+    private static Logger logger = LoggerFactory.getInstance().getLogger(VnfCatalogArtifactHandler.class.getName());\r
 \r
-  @Override\r
-  public boolean pushArtifacts(List<Artifact> artifacts, String distributionId) {\r
-    for (Artifact art : artifacts) {\r
-      VnfCatalogArtifact vnfCatalog = (VnfCatalogArtifact) art;\r
-      String artifactPayload = vnfCatalog.getPayload();\r
+    public static final String ATTR_UUID = "uuid";\r
 \r
-      AaiRestClient restClient = new AaiRestClient(this.config);\r
-      List<VnfImage> putImages = new ArrayList<VnfImage>();\r
-\r
-      try {\r
-        JAXBContext inputContext = JAXBContext.newInstance(VnfCatalog.class);\r
-        Unmarshaller unmarshaller = inputContext.createUnmarshaller();\r
-        StringReader reader = new StringReader(artifactPayload);\r
-        VnfCatalog cat = (VnfCatalog) unmarshaller.unmarshal(reader);\r
+    public VnfCatalogArtifactHandler(ModelLoaderConfig config) {\r
+        super(config);\r
+    }\r
 \r
-        int numParts = cat.getPartNumberList().size();\r
+    /*\r
+     * (non-Javadoc)\r
+     * \r
+     * @see org.openecomp.modelloader.entity.ArtifactHandler#pushArtifacts(java.util.List, java.lang.String)\r
+     */\r
+    @Override\r
+    public boolean pushArtifacts(List<Artifact> artifacts, String distributionId, List<Artifact> completedArtifacts,\r
+            AaiRestClient aaiClient) {\r
+        for (Artifact artifact : artifacts) {\r
+            try {\r
+                distributeVnfcData(aaiClient, distributionId, artifact, completedArtifacts);\r
+            } catch (VnfImageException e) {\r
+                if (e.getResultCode().isPresent()) {\r
+                    logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR,\r
+                            "Ingestion failed on vnf-image " + e.getImageId() + " with status "\r
+                                    + e.getResultCode().orElse(0) + ". Rolling back distribution.");\r
+                } else {\r
+                    logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR,\r
+                            "Ingestion failed on " + e.getImageId() + ". Rolling back distribution.");\r
+                }\r
+                return false;\r
+            }\r
+        }\r
 \r
-        for (int i = 0; i < numParts; i++) {\r
+        return true;\r
+    }\r
 \r
-          PartNumberList pnl = cat.getPartNumberList().get(i);\r
+    private void distributeVnfcData(AaiRestClient restClient, String distributionId, Artifact vnfcArtifact,\r
+            List<Artifact> completedArtifacts) throws VnfImageException {\r
 \r
-          String application = pnl.getVendorInfo().getVendorModel();\r
-          String applicationVendor = pnl.getVendorInfo().getVendorName();\r
+        List<Map<String, String>> vnfcData = unmarshallVnfcData(vnfcArtifact);\r
 \r
-          int numVersions = pnl.getSoftwareVersionList().size();\r
+        for (Map<String, String> dataItem : vnfcData) {\r
+            // If an empty dataItem is supplied, do nothing.\r
+            if (dataItem.isEmpty()) {\r
+                logger.warn(ModelLoaderMsgs.DISTRIBUTION_EVENT, "Empty image data supplied, skipping ingestion.");\r
+                return;\r
+            }\r
 \r
-          for (int j = 0; j < numVersions; j++) {\r
-            String applicationVersion = pnl.getSoftwareVersionList().get(j).getSoftwareVersion();\r
+            String urlParams;\r
+            StringBuilder imageId = new StringBuilder("vnf image");\r
 \r
-            String imageId = "vnf image " + applicationVendor + " " + application + " "\r
-                + applicationVersion;\r
+            try {\r
+                urlParams = buildUrlImgIdStrings(imageId, dataItem);\r
+            } catch (UnsupportedEncodingException e) {\r
+                throw new VnfImageException(e);\r
+            }\r
 \r
-                       String queryURI = "application-vendor=" + applicationVendor + "&application=" + application + "&application-version=" + applicationVersion;\r
-                       \r
-                       String getUrl = config.getAaiBaseUrl() + config.getAaiVnfImageUrl() + "?" + UriUtils.encodePath(queryURI, "UTF-8");\r
+            OperationResult tryGet =\r
+                    restClient.getResource(config.getAaiBaseUrl() + config.getAaiVnfImageUrl() + "?" + urlParams,\r
+                            distributionId, MediaType.APPLICATION_JSON_TYPE);\r
 \r
-            ClientResponse tryGet = restClient.getResource(getUrl, distributionId, MimeType.JSON);\r
             if (tryGet == null) {\r
-              logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR,\r
-                  "Ingestion failed on " + imageId + ". Rolling back distribution.");\r
-              failureCleanup(putImages, restClient, distributionId);\r
-              return false;\r
+                throw new VnfImageException(imageId.toString());\r
             }\r
-            if (tryGet.getStatus() == Response.Status.NOT_FOUND.getStatusCode()) {\r
-              // this vnf-image not already in the db, need to add\r
-              // only do this on 404 bc other error responses could mean there\r
-              // are problems that\r
-              // you might not want to try to PUT against\r
-\r
-              VnfImage image = new VnfImage();\r
-              image.setApplication(application);\r
-              image.setApplicationVendor(applicationVendor);\r
-              image.setApplicationVersion(applicationVersion);\r
-              String uuid = UUID.randomUUID().toString();\r
-              image.setUuid(uuid); // need to create uuid\r
-\r
-              System.setProperty("javax.xml.bind.context.factory",\r
-                  "org.eclipse.persistence.jaxb.JAXBContextFactory");\r
-              JAXBContext jaxbContext = JAXBContext.newInstance(VnfImage.class);\r
-              Marshaller marshaller = jaxbContext.createMarshaller();\r
-              marshaller.setProperty(MarshallerProperties.MEDIA_TYPE, "application/json");\r
-              marshaller.setProperty(MarshallerProperties.JSON_INCLUDE_ROOT, false);\r
-              marshaller.setProperty(MarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME, true);\r
-              marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, false);\r
-              StringWriter writer = new StringWriter();\r
-              marshaller.marshal(image, writer);\r
-              String payload = writer.toString();\r
-\r
-              String putUrl = config.getAaiBaseUrl() + config.getAaiVnfImageUrl() + "/vnf-image/"\r
-                  + uuid;\r
-\r
-              ClientResponse putResp = restClient.putResource(putUrl, payload, distributionId,\r
-                  MimeType.JSON);\r
-              if (putResp == null\r
-                  || putResp.getStatus() != Response.Status.CREATED.getStatusCode()) {\r
-                logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR,\r
-                    "Ingestion failed on vnf-image " + imageId + ". Rolling back distribution.");\r
-                failureCleanup(putImages, restClient, distributionId);\r
-                return false;\r
-              }\r
-              putImages.add(image);\r
-              logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, imageId + " successfully ingested.");\r
-            } else if (tryGet.getStatus() == Response.Status.OK.getStatusCode()) {\r
-              logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT,\r
-                  imageId + " already exists.  Skipping ingestion.");\r
+\r
+            int resultCode = tryGet.getResultCode();\r
+            if (resultCode == Response.Status.NOT_FOUND.getStatusCode()) {\r
+                // This vnf-image is missing, so add it\r
+                boolean success = putVnfImage(restClient, dataItem, distributionId);\r
+                if (!success) {\r
+                    throw new VnfImageException(imageId.toString());\r
+                }\r
+                completedArtifacts.add(vnfcArtifact);\r
+                logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, imageId + " successfully ingested.");\r
+            } else if (resultCode == Response.Status.OK.getStatusCode()) {\r
+                logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, imageId + " already exists. Skipping ingestion.");\r
             } else {\r
-              // if other than 404 or 200, something went wrong\r
-              logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR,\r
-                  "Ingestion failed on vnf-image " + imageId + " with status " + tryGet.getStatus()\r
-                      + ". Rolling back distribution.");\r
-              failureCleanup(putImages, restClient, distributionId);\r
-              return false;\r
+                // if other than 404 or 200, something went wrong\r
+                throw new VnfImageException(imageId.toString(), resultCode);\r
             }\r
-          }\r
         }\r
+    }\r
 \r
-      } catch (JAXBException e) {\r
-        logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR,\r
-            "Ingestion failed. " + e.getMessage() + ". Rolling back distribution.");\r
-        failureCleanup(putImages, restClient, distributionId);\r
-        return false;\r
-      } catch (UnsupportedEncodingException e) {\r
-         logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR, "Ingestion failed. " + e.getMessage() + ". Rolling back distribution.");\r
-         failureCleanup(putImages, restClient, distributionId);\r
-         return false;\r
-      }\r
+    private String buildUrlImgIdStrings(StringBuilder imageId, Map<String, String> dataItem)\r
+            throws UnsupportedEncodingException {\r
+        StringBuilder urlParams = new StringBuilder();\r
+        for (Entry<String, String> entry : dataItem.entrySet()) {\r
+            urlParams.append(entry.getKey()).append("=").append(UriUtils.encode(entry.getValue(), "UTF-8")).append("&");\r
+            imageId.append(" ").append(entry.getValue());\r
+        }\r
+        return urlParams.deleteCharAt(urlParams.length() - 1).toString();\r
+    }\r
+\r
+    private boolean putVnfImage(AaiRestClient restClient, Map<String, String> dataItem, String distributionId) {\r
+        // Generate a new UUID for the image data item\r
+        String uuid = UUID.randomUUID().toString();\r
+        dataItem.put(ATTR_UUID, uuid);\r
+\r
+        String payload = createVnfImagePayload(dataItem);\r
+        String putUrl = config.getAaiBaseUrl() + config.getAaiVnfImageUrl() + "/vnf-image/" + uuid;\r
+        OperationResult putResp =\r
+                restClient.putResource(putUrl, payload, distributionId, MediaType.APPLICATION_JSON_TYPE);\r
+        return putResp != null && putResp.getResultCode() == Response.Status.CREATED.getStatusCode();\r
+    }\r
+\r
+    private String createVnfImagePayload(Map<String, String> dataItem) {\r
+        dataItem.put(ATTR_UUID, UUID.randomUUID().toString());\r
+        return new Gson().toJson(dataItem);\r
+    }\r
+\r
+    private List<Map<String, String>> unmarshallVnfcData(Artifact vnfcArtifact) {\r
+        // Unmarshall Babel JSON payload into a List of Maps of JSON attribute name/values.\r
+        return new Gson().fromJson(StringEscapeUtils.unescapeJson(vnfcArtifact.getPayload()),\r
+                new TypeToken<List<Map<String, String>>>() {}.getType());\r
     }\r
 \r
-    return true;\r
-  }\r
-\r
-  /*\r
-   * if something fails in the middle of ingesting the catalog we want to\r
-   * rollback any changes to the db\r
-   */\r
-  private void failureCleanup(List<VnfImage> putImages, AaiRestClient restClient, String transId) {\r
-    for (VnfImage image : putImages) {\r
-      String url = config.getAaiBaseUrl() + config.getAaiVnfImageUrl() + "/vnf-image/"\r
-          + image.getUuid();\r
-      restClient.getAndDeleteResource(url, transId); // try to delete the image,\r
-                                                     // if something goes wrong\r
-                                                     // we can't really do\r
-                                                     // anything here\r
+    /*\r
+     * If something fails in the middle of ingesting the catalog we want to roll back any changes to the DB\r
+     */\r
+    @Override\r
+    public void rollback(List<Artifact> completedArtifacts, String distributionId, AaiRestClient aaiClient) {\r
+        for (Artifact completedArtifact : completedArtifacts) {\r
+            List<Map<String, String>> completedImageData = unmarshallVnfcData(completedArtifact);\r
+            for (Map<String, String> data : completedImageData) {\r
+                String url = config.getAaiBaseUrl() + config.getAaiVnfImageUrl() + "/vnf-image/" + data.get(ATTR_UUID);\r
+                // Try to delete the image. If something goes wrong we can't really do anything here\r
+                aaiClient.getAndDeleteResource(url, distributionId);\r
+            }\r
+        }\r
     }\r
-  }\r
 \r
 }\r