Refactor CsarUtils::writeComponentInterface 40/108540/3
authorFrancis Toth <francis.toth@yoppworks.com>
Wed, 20 May 2020 16:19:26 +0000 (12:19 -0400)
committerOfir Sonsino <ofir.sonsino@intl.att.com>
Tue, 2 Jun 2020 07:53:20 +0000 (07:53 +0000)
This commit aims to decouple the zip file writing logic from the CsarUtils::writeComponentInterface function. This should provide a higher level of testability and maintenance thanks to inversion of control. An extra helper has also been added to help the migration from the FJ library to VAVR.

Signed-off-by: Francis Toth <francis.toth@yoppworks.com>
Change-Id: I4f2df4749cae3082906a80acc39045ac8887ec39
Issue-ID: SDC-2812

catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CsarUtils.java
catalog-be/src/main/java/org/openecomp/sdc/be/tosca/FJToVavrHelper.java [new file with mode: 0644]
catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ZipWriter.java [new file with mode: 0644]

index eaf6eb8..29efb1f 100644 (file)
@@ -24,6 +24,7 @@ package org.openecomp.sdc.be.tosca;
 import fj.F;
 import fj.data.Either;
 import io.vavr.Tuple2;
+import io.vavr.control.Try;
 import java.io.BufferedOutputStream;
 import java.io.ByteArrayInputStream;
 import java.io.File;
@@ -107,6 +108,8 @@ import org.openecomp.sdc.exception.ResponseFormat;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.yaml.snakeyaml.Yaml;
 
+import static org.openecomp.sdc.be.tosca.FJToVavrHelper.Try0.fromEither;
+
 /**
  * @author tg851x
  *
@@ -691,22 +694,34 @@ public class CsarUtils {
         String fileName,
         boolean isAssociatedComponent
     ) {
-        try {
-            Either<String, ToscaError> mainYaml = toscaExportUtils
-                .exportComponentInterface(component, isAssociatedComponent)
-                .left().map(ToscaRepresentation::getMainYaml);
+        // TODO: This should not be done but we need this to keep the refactoring small enough to be easily reviewable
+        return writeComponentInterface(component, fileName, isAssociatedComponent, ZipWriter.live(zip))
+            .map(void0 -> Either.<ZipOutputStream, ResponseFormat>left(zip))
+            .recover(th -> {
+                log.error("#writeComponentInterface - zip writing failed with error: ", th);
+                return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
+            }).get();
+    }
 
-            // TODO: This should be done outside this function to keep this testable.
-            // We can probably achieve this once the other refactorings related to SDC-2812 are merged
-            String interfaceFileName = DEFINITIONS_PATH + ToscaExportHandler.getInterfaceFilename(fileName);
-            zip.putNextEntry(new ZipEntry(interfaceFileName));
-            zip.write(mainYaml.left().value().getBytes());
+    private Try<Void> writeComponentInterface(
+        Component component,
+        String fileName,
+        boolean isAssociatedComponent,
+        ZipWriter zw
+    ) {
+        Either<String, ToscaError> yml = toscaExportUtils
+            .exportComponentInterface(component, isAssociatedComponent)
+            .left().map(ToscaRepresentation::getMainYaml);
 
-        } catch (Exception e) {
-            log.error("#writeComponentInterface - zip writing failed with error: ", e);
-            return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
+        return fromEither(yml, ToscaErrorException::new)
+            .flatMap(zw.write(DEFINITIONS_PATH + ToscaExportHandler.getInterfaceFilename(fileName)));
+    }
+
+    public static class ToscaErrorException extends Exception {
+
+        ToscaErrorException(ToscaError error) {
+            super("Error while exporting component's interface (toscaError:" + error + ")");
         }
-        return Either.left(zip);
     }
 
     private Either<byte[], ActionStatus> getEntryData(String cassandraId, Component childComponent) {
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/FJToVavrHelper.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/FJToVavrHelper.java
new file mode 100644 (file)
index 0000000..32b9957
--- /dev/null
@@ -0,0 +1,48 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.openecomp.sdc.be.tosca;
+
+import io.vavr.control.Try;
+import java.util.function.Function;
+
+/**
+ * Helper class providing facilities for migrating from FJ to VAVR
+ */
+public final class FJToVavrHelper {
+
+    private FJToVavrHelper() {}
+
+    public interface Try0 {
+        /**
+         * Converts a {@link fj.data.Either} to a {@link io.vavr.control.Try}
+         *
+         * @param e
+         * @param onError
+         * @return
+         */
+        static <L, R> Try<L> fromEither(fj.data.Either<L, R> e, Function<R, Throwable> onError) {
+            return e.either(
+                Try::success,
+                r -> Try.failure(onError.apply(r))
+            );
+        }
+    }
+}
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ZipWriter.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ZipWriter.java
new file mode 100644 (file)
index 0000000..4740fb2
--- /dev/null
@@ -0,0 +1,74 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.openecomp.sdc.be.tosca;
+
+import fj.data.Either;
+import io.vavr.control.Try;
+import java.util.function.Function;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+/**
+ * ZipWriter abstracts the Zip file writing logic.
+ */
+public interface ZipWriter {
+
+    /**
+     * Writes an entry provided with its name and its payload
+     *
+     * @param entryName The entry's name to use in the zip file
+     * @param payload The payload to write for this entry
+     */
+    Try<Void> write(String entryName, byte[] payload);
+
+    /**
+     * Writes an entry provided with its name and its payload
+     *
+     * @param entryName The entry's name to use in the zip file
+     * @param payload The payload to write for this entry
+     */
+    default Try<Void> write(String entryName, String payload) {
+        return write(entryName, payload.getBytes());
+    }
+
+    /**
+     * Alias for {@link org.openecomp.sdc.be.tosca.ZipWriter}
+     *
+     * @param entryName The entry's name to use in the zip file
+     */
+    default Function<String, Try<Void>> write(String entryName) {
+        return payload -> write(entryName, payload.getBytes());
+    }
+
+    /**
+     * Builds a ZipWriter that outputs the data on a {@link java.util.zip.ZipOutputStream}
+     * @param zos the target {@link java.util.zip.ZipOutputStream}
+     */
+    static ZipWriter live(ZipOutputStream zos) {
+        return (entryName, payload) -> Try.of(() -> {
+            zos.putNextEntry(new ZipEntry(entryName));
+            zos.write(payload);
+            // We can return null as a Void is expected;
+            return null;
+        });
+    }
+}
+