created Api for closed loop managing 05/79605/9
authorKrysiak Adam <adam.krysiak@nokia.com>
Fri, 1 Mar 2019 14:32:19 +0000 (15:32 +0100)
committerKrysiak Adam <adam.krysiak@nokia.com>
Thu, 7 Mar 2019 12:08:41 +0000 (13:08 +0100)
Change-Id: Ib6bd92d1ae3119a857c5a63df10e8f9bb130f75f
Issue-ID: CLAMP-301
Signed-off-by: Krysiak Adam <adam.krysiak@nokia.com>
26 files changed:
src/main/java/org/onap/clamp/clds/Application.java
src/main/java/org/onap/clamp/clds/config/AAFConfiguration.java
src/main/java/org/onap/clamp/clds/config/CamelConfiguration.java
src/main/java/org/onap/clamp/configuration/CamelGsonConfiguration.java [new file with mode: 0644]
src/main/java/org/onap/clamp/loop/Loop.java [moved from src/main/java/org/onap/clamp/dao/model/Loop.java with 79% similarity]
src/main/java/org/onap/clamp/loop/LoopController.java [new file with mode: 0644]
src/main/java/org/onap/clamp/loop/LoopService.java [new file with mode: 0644]
src/main/java/org/onap/clamp/loop/LoopState.java [moved from src/main/java/org/onap/clamp/dao/model/LoopState.java with 97% similarity]
src/main/java/org/onap/clamp/loop/LoopsRepository.java [moved from src/main/java/org/onap/clamp/dao/MicroServicePolicyRepository.java with 82% similarity]
src/main/java/org/onap/clamp/loop/log/LogType.java [moved from src/main/java/org/onap/clamp/dao/model/LogType.java with 97% similarity]
src/main/java/org/onap/clamp/loop/log/LoopLog.java [moved from src/main/java/org/onap/clamp/dao/model/LoopLog.java with 98% similarity]
src/main/java/org/onap/clamp/loop/log/LoopLogRepository.java [moved from src/main/java/org/onap/clamp/dao/LoopLogRepository.java with 94% similarity]
src/main/java/org/onap/clamp/policy/Policy.java [new file with mode: 0644]
src/main/java/org/onap/clamp/policy/PolicyService.java [new file with mode: 0644]
src/main/java/org/onap/clamp/policy/microservice/MicroServicePolicy.java [moved from src/main/java/org/onap/clamp/dao/model/MicroServicePolicy.java with 88% similarity]
src/main/java/org/onap/clamp/policy/microservice/MicroServicePolicyRepository.java [moved from src/main/java/org/onap/clamp/dao/LoopsRepository.java with 89% similarity]
src/main/java/org/onap/clamp/policy/microservice/MicroservicePolicyService.java [new file with mode: 0644]
src/main/java/org/onap/clamp/policy/operational/OperationalPolicy.java [moved from src/main/java/org/onap/clamp/dao/model/OperationalPolicy.java with 84% similarity]
src/main/java/org/onap/clamp/policy/operational/OperationalPolicyRepository.java [moved from src/main/java/org/onap/clamp/dao/OperationalPolicyRepository.java with 87% similarity]
src/main/java/org/onap/clamp/policy/operational/OperationalPolicyService.java [new file with mode: 0644]
src/main/resources/clds/camel/rest/clamp-api-v2.xml [new file with mode: 0644]
src/main/resources/clds/camel/rest/clds-services.xml
src/test/java/org/onap/clamp/clds/it/HttpsItCase.java
src/test/java/org/onap/clamp/loop/LoopRepositoriesItCase.java [moved from src/test/java/org/onap/clamp/it/dao/model/LoopRepositoriesItCase.java with 79% similarity]
src/test/java/org/onap/clamp/loop/LoopServiceTestItCase.java [new file with mode: 0644]
src/test/java/org/onap/clamp/loop/LoopToJsonTest.java [moved from src/test/java/org/onap/clamp/dao/model/LoopToJsonTest.java with 80% similarity]

index 920b0f2..7e78504 100644 (file)
@@ -108,7 +108,7 @@ public class Application extends SpringBootServletInitializer {
         eelfLogger.info(ResourceFileUtil.getResourceAsString("boot-message.txt") + "(v"
             + ClampVersioning.getCldsVersionFromProps() + ")" + System.getProperty("line.separator"));
         ServletRegistrationBean registration = new ServletRegistrationBean(new ClampServlet(),
-            "/restservices/clds/v1/*");
+            "/restservices/clds/*");
         registration.setName("CamelServlet");
         return registration;
     }
index 8bc6f69..c91494d 100644 (file)
@@ -58,6 +58,7 @@ public class AAFConfiguration {
         registration.addUrlPatterns("/restservices/clds/v1/tosca/*");
         registration.addUrlPatterns("/restservices/clds/v1/dictionary/*");
         registration.addUrlPatterns("/restservices/clds/v1/user/*");
+        registration.addUrlPatterns("/restservices/clds/v2/loop/*");
         //registration.addUrlPatterns("*");
         registration.setName("cadiFilter");
         registration.setOrder(0);
index 45c945c..f105650 100644 (file)
@@ -36,7 +36,7 @@ public class CamelConfiguration extends RouteBuilder {
             // turn on swagger api-doc
             .apiContextPath("api-doc").apiVendorExtension(true).apiProperty("api.title", "Clamp Rest API")
             .apiProperty("api.version", ClampVersioning.getCldsVersionFromProps())
-            .apiProperty("base.path", "/restservices/clds/v1/");
+            .apiProperty("base.path", "/restservices/clds/");
         // .apiProperty("cors", "true");
     }
 }
diff --git a/src/main/java/org/onap/clamp/configuration/CamelGsonConfiguration.java b/src/main/java/org/onap/clamp/configuration/CamelGsonConfiguration.java
new file mode 100644 (file)
index 0000000..f71d2f0
--- /dev/null
@@ -0,0 +1,63 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 Nokia 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.onap.clamp.configuration;
+
+import com.google.gson.ExclusionStrategy;
+import com.google.gson.FieldAttributes;
+import com.google.gson.annotations.Expose;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import org.apache.camel.component.gson.GsonDataFormat;
+import org.apache.camel.spi.DataFormatCustomizer;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class CamelGsonConfiguration {
+
+    @Bean
+    public List<DataFormatCustomizer<GsonDataFormat>> provideGsonCustomizers() {
+        DataFormatCustomizer<GsonDataFormat> dataFormatCustomizer = dataformat ->
+            dataformat.setExclusionStrategies(
+                Collections.singletonList(new ExcludeFieldsWithoutExposedAnnotation())
+            );
+        return Collections.singletonList(dataFormatCustomizer);
+    }
+
+    private static class ExcludeFieldsWithoutExposedAnnotation implements ExclusionStrategy {
+
+        @Override
+        public boolean shouldSkipField(FieldAttributes f) {
+            return Optional.ofNullable(f.getAnnotation(Expose.class))
+                .map(expose -> !expose.serialize())
+                .orElse(true);
+        }
+
+        @Override
+        public boolean shouldSkipClass(Class<?> clazz) {
+            return false;
+        }
+    }
+}
@@ -21,7 +21,7 @@
  *
  */
 
-package org.onap.clamp.dao.model;
+package org.onap.clamp.loop;
 
 import com.google.gson.JsonObject;
 import com.google.gson.annotations.Expose;
@@ -46,6 +46,9 @@ import javax.persistence.Table;
 import org.hibernate.annotations.Type;
 import org.hibernate.annotations.TypeDef;
 import org.hibernate.annotations.TypeDefs;
+import org.onap.clamp.loop.log.LoopLog;
+import org.onap.clamp.policy.microservice.MicroServicePolicy;
+import org.onap.clamp.policy.operational.OperationalPolicy;
 import org.onap.clamp.dao.model.jsontype.StringJsonUserType;
 
 @Entity
@@ -75,7 +78,6 @@ public class Loop implements Serializable {
     @Column(name = "dcae_blueprint_id")
     private String dcaeBlueprintId;
 
-    @Expose
     @Column(name = "svg_representation")
     private String svgRepresentation;
 
@@ -84,7 +86,6 @@ public class Loop implements Serializable {
     @Column(columnDefinition = "json", name = "global_properties_json")
     private JsonObject globalPropertiesJson;
 
-    @Expose
     @Column(nullable = false, name = "blueprint_yaml")
     private String blueprint;
 
@@ -106,11 +107,22 @@ public class Loop implements Serializable {
     @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "loop")
     private Set<LoopLog> loopLogs = new HashSet<>();
 
+    public Loop() {
+    }
+
+    public Loop(String name, String blueprint, String svgRepresentation) {
+        this.name = name;
+        this.svgRepresentation = svgRepresentation;
+        this.blueprint = blueprint;
+        this.lastComputedState = LoopState.DESIGN;
+        this.globalPropertiesJson = new JsonObject();
+    }
+
     public String getName() {
         return name;
     }
 
-    public void setName(String name) {
+    void setName(String name) {
         this.name = name;
     }
 
@@ -118,7 +130,7 @@ public class Loop implements Serializable {
         return dcaeDeploymentId;
     }
 
-    public void setDcaeDeploymentId(String dcaeDeploymentId) {
+    void setDcaeDeploymentId(String dcaeDeploymentId) {
         this.dcaeDeploymentId = dcaeDeploymentId;
     }
 
@@ -126,7 +138,7 @@ public class Loop implements Serializable {
         return dcaeDeploymentStatusUrl;
     }
 
-    public void setDcaeDeploymentStatusUrl(String dcaeDeploymentStatusUrl) {
+    void setDcaeDeploymentStatusUrl(String dcaeDeploymentStatusUrl) {
         this.dcaeDeploymentStatusUrl = dcaeDeploymentStatusUrl;
     }
 
@@ -134,7 +146,7 @@ public class Loop implements Serializable {
         return svgRepresentation;
     }
 
-    public void setSvgRepresentation(String svgRepresentation) {
+    void setSvgRepresentation(String svgRepresentation) {
         this.svgRepresentation = svgRepresentation;
     }
 
@@ -142,61 +154,61 @@ public class Loop implements Serializable {
         return blueprint;
     }
 
-    public void setBlueprint(String blueprint) {
+    void setBlueprint(String blueprint) {
         this.blueprint = blueprint;
     }
 
-    public LoopState getLastComputedState() {
+    LoopState getLastComputedState() {
         return lastComputedState;
     }
 
-    public void setLastComputedState(LoopState lastComputedState) {
+    void setLastComputedState(LoopState lastComputedState) {
         this.lastComputedState = lastComputedState;
     }
 
-    public Set<OperationalPolicy> getOperationalPolicies() {
+    Set<OperationalPolicy> getOperationalPolicies() {
         return operationalPolicies;
     }
 
-    public void setOperationalPolicies(Set<OperationalPolicy> operationalPolicies) {
+    void setOperationalPolicies(Set<OperationalPolicy> operationalPolicies) {
         this.operationalPolicies = operationalPolicies;
     }
 
-    public Set<MicroServicePolicy> getMicroServicePolicies() {
+    Set<MicroServicePolicy> getMicroServicePolicies() {
         return microServicePolicies;
     }
 
-    public void setMicroServicePolicies(Set<MicroServicePolicy> microServicePolicies) {
+    void setMicroServicePolicies(Set<MicroServicePolicy> microServicePolicies) {
         this.microServicePolicies = microServicePolicies;
     }
 
-    public JsonObject getGlobalPropertiesJson() {
+    JsonObject getGlobalPropertiesJson() {
         return globalPropertiesJson;
     }
 
-    public void setGlobalPropertiesJson(JsonObject globalPropertiesJson) {
+    void setGlobalPropertiesJson(JsonObject globalPropertiesJson) {
         this.globalPropertiesJson = globalPropertiesJson;
     }
 
-    public Set<LoopLog> getLoopLogs() {
+    Set<LoopLog> getLoopLogs() {
         return loopLogs;
     }
 
-    public void setLoopLogs(Set<LoopLog> loopLogs) {
+    void setLoopLogs(Set<LoopLog> loopLogs) {
         this.loopLogs = loopLogs;
     }
 
-    public void addOperationalPolicy(OperationalPolicy opPolicy) {
-        opPolicy.setLoop(this);
+    void addOperationalPolicy(OperationalPolicy opPolicy) {
         operationalPolicies.add(opPolicy);
+        opPolicy.setLoop(this);
     }
 
-    public void addMicroServicePolicy(MicroServicePolicy microServicePolicy) {
+    void addMicroServicePolicy(MicroServicePolicy microServicePolicy) {
         microServicePolicies.add(microServicePolicy);
         microServicePolicy.getUsedByLoops().add(this);
     }
 
-    public void addLog(LoopLog log) {
+    void addLog(LoopLog log) {
         loopLogs.add(log);
         log.setLoop(this);
     }
diff --git a/src/main/java/org/onap/clamp/loop/LoopController.java b/src/main/java/org/onap/clamp/loop/LoopController.java
new file mode 100644 (file)
index 0000000..eeb6105
--- /dev/null
@@ -0,0 +1,70 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 Nokia 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.onap.clamp.loop;
+
+import com.google.gson.JsonArray;
+import com.google.gson.reflect.TypeToken;
+import java.lang.reflect.Type;
+import java.util.List;
+import org.onap.clamp.clds.util.JsonUtils;
+import org.onap.clamp.policy.microservice.MicroServicePolicy;
+import org.onap.clamp.policy.operational.OperationalPolicy;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+
+
+@Controller
+public class LoopController {
+
+    private final LoopService loopService;
+    private static final Type OPERATIONAL_POLICY_TYPE = new TypeToken<List<OperationalPolicy>>() {
+    }.getType();
+    private static final Type MICROSERVICE_POLICY_TYPE = new TypeToken<List<MicroServicePolicy>>() {
+    }.getType();
+
+    @Autowired
+    public LoopController(LoopService loopService) {
+        this.loopService = loopService;
+    }
+
+    public List<String> getLoopNames() {
+        return loopService.getClosedLoopNames();
+    }
+
+    public Loop getLoop(String loopName) {
+        return loopService.getLoop(loopName);
+    }
+
+    public Loop updateOperationalPolicies(String loopName, JsonArray operationalPoliciesJson) {
+        List<OperationalPolicy> operationalPolicies = JsonUtils.GSON
+            .fromJson(operationalPoliciesJson, OPERATIONAL_POLICY_TYPE);
+        return loopService.updateOperationalPolicies(loopName, operationalPolicies);
+    }
+
+    public Loop updateMicroservicePolicies(String loopName, JsonArray microServicePoliciesJson) {
+        List<MicroServicePolicy> microservicePolicies = JsonUtils.GSON
+            .fromJson(microServicePoliciesJson, MICROSERVICE_POLICY_TYPE);
+        return loopService.updateMicroservicePolicies(loopName, microservicePolicies);
+    }
+}
diff --git a/src/main/java/org/onap/clamp/loop/LoopService.java b/src/main/java/org/onap/clamp/loop/LoopService.java
new file mode 100644 (file)
index 0000000..7b79c11
--- /dev/null
@@ -0,0 +1,91 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 Nokia 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.onap.clamp.loop;
+
+import java.util.List;
+import java.util.Set;
+import javax.persistence.EntityNotFoundException;
+import org.onap.clamp.policy.microservice.MicroservicePolicyService;
+import org.onap.clamp.policy.operational.OperationalPolicyService;
+import org.onap.clamp.policy.microservice.MicroServicePolicy;
+import org.onap.clamp.policy.operational.OperationalPolicy;
+import org.springframework.stereotype.Service;
+
+@Service
+public class LoopService {
+
+    private final LoopsRepository loopsRepository;
+    private final MicroservicePolicyService microservicePolicyService;
+    private final OperationalPolicyService operationalPolicyService;
+
+    public LoopService(LoopsRepository loopsRepository,
+        MicroservicePolicyService microservicePolicyService,
+        OperationalPolicyService operationalPolicyService) {
+        this.loopsRepository = loopsRepository;
+        this.microservicePolicyService = microservicePolicyService;
+        this.operationalPolicyService = operationalPolicyService;
+    }
+
+    Loop addNewLoop(Loop loop) {
+        return loopsRepository.save(loop);
+    }
+
+    List<String> getClosedLoopNames() {
+        return loopsRepository.getAllLoopNames();
+    }
+
+    Loop getLoop(String loopName){
+        return loopsRepository
+            .findById(loopName)
+            .orElse(null);
+    }
+
+    String getClosedLoopModelSVG(String loopName) {
+        Loop closedLoopByName = findClosedLoopByName(loopName);
+        return closedLoopByName.getSvgRepresentation();
+    }
+
+    Loop updateOperationalPolicies(String loopName, List<OperationalPolicy> newOperationalPolicies) {
+        Loop loop = findClosedLoopByName(loopName);
+        Set<OperationalPolicy> newPolicies = operationalPolicyService
+            .updatePolicies(loop, newOperationalPolicies);
+
+        loop.setOperationalPolicies(newPolicies);
+        return loopsRepository.save(loop);
+    }
+
+    Loop updateMicroservicePolicies(String loopName, List<MicroServicePolicy> newMicroservicePolicies) {
+        Loop loop = findClosedLoopByName(loopName);
+        Set<MicroServicePolicy> newPolicies = microservicePolicyService
+            .updatePolicies(loop, newMicroservicePolicies);
+
+        loop.setMicroServicePolicies(newPolicies);
+        return loopsRepository.save(loop);
+    }
+
+    private Loop findClosedLoopByName(String loopName) {
+        return loopsRepository.findById(loopName)
+            .orElseThrow(() -> new EntityNotFoundException("Couldn't find closed loop named: " + loopName));
+    }
+}
@@ -21,7 +21,7 @@
  *
  */
 
-package org.onap.clamp.dao.model;
+package org.onap.clamp.loop;
 
 public enum LoopState {
     DESIGN, SUBMITTED, DEPLOYED, RUNNING, STOPPED, IN_ERROR, WAITING;
  *
  */
 
-package org.onap.clamp.dao;
+package org.onap.clamp.loop;
 
-import org.onap.clamp.dao.model.MicroServicePolicy;
+import java.util.List;
+import org.springframework.data.jpa.repository.Query;
 import org.springframework.data.repository.CrudRepository;
 import org.springframework.stereotype.Repository;
 
 @Repository
-public interface MicroServicePolicyRepository extends CrudRepository<MicroServicePolicy, String> {
+public interface LoopsRepository extends CrudRepository<Loop, String> {
 
+    @Query("SELECT loop.name FROM Loop as loop")
+    List<String> getAllLoopNames();
 }
@@ -21,7 +21,7 @@
  *
  */
 
-package org.onap.clamp.dao.model;
+package org.onap.clamp.loop.log;
 
 public enum LogType {
     INFO, WARNING, ERROR;
@@ -21,7 +21,7 @@
  *
  */
 
-package org.onap.clamp.dao.model;
+package org.onap.clamp.loop.log;
 
 import com.google.gson.annotations.Expose;
 
@@ -40,6 +40,7 @@ import javax.persistence.Id;
 import javax.persistence.JoinColumn;
 import javax.persistence.ManyToOne;
 import javax.persistence.Table;
+import org.onap.clamp.loop.Loop;
 
 /**
  *
@@ -21,9 +21,8 @@
  *
  */
 
-package org.onap.clamp.dao;
+package org.onap.clamp.loop.log;
 
-import org.onap.clamp.dao.model.LoopLog;
 import org.springframework.data.repository.CrudRepository;
 import org.springframework.stereotype.Repository;
 
diff --git a/src/main/java/org/onap/clamp/policy/Policy.java b/src/main/java/org/onap/clamp/policy/Policy.java
new file mode 100644 (file)
index 0000000..13ba1a9
--- /dev/null
@@ -0,0 +1,35 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 Nokia 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.onap.clamp.policy;
+
+import com.google.gson.JsonObject;
+
+public interface Policy {
+
+    String getName();
+
+    JsonObject getJsonRepresentation();
+
+}
diff --git a/src/main/java/org/onap/clamp/policy/PolicyService.java b/src/main/java/org/onap/clamp/policy/PolicyService.java
new file mode 100644 (file)
index 0000000..05785c0
--- /dev/null
@@ -0,0 +1,36 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 Nokia 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.onap.clamp.policy;
+
+import java.util.List;
+import java.util.Set;
+import org.onap.clamp.loop.Loop;
+
+public interface PolicyService<T extends Policy> {
+
+    Set<T> updatePolicies(Loop loop,
+        List<T> newMicroservicePolicies);
+
+    boolean isExisting(String policyName);
+}
@@ -21,7 +21,7 @@
  *
  */
 
-package org.onap.clamp.dao.model;
+package org.onap.clamp.policy.microservice;
 
 import com.google.gson.JsonObject;
 import com.google.gson.annotations.Expose;
@@ -39,12 +39,14 @@ import javax.persistence.Table;
 import org.hibernate.annotations.Type;
 import org.hibernate.annotations.TypeDef;
 import org.hibernate.annotations.TypeDefs;
+import org.onap.clamp.loop.Loop;
+import org.onap.clamp.policy.Policy;
 import org.onap.clamp.dao.model.jsontype.StringJsonUserType;
 
 @Entity
 @Table(name = "micro_service_policies")
 @TypeDefs({ @TypeDef(name = "json", typeClass = StringJsonUserType.class) })
-public class MicroServicePolicy implements Serializable {
+public class MicroServicePolicy implements Serializable, Policy {
     /**
      *
      */
@@ -76,12 +78,21 @@ public class MicroServicePolicy implements Serializable {
     @ManyToMany(mappedBy = "microServicePolicies")
     private Set<Loop> usedByLoops = new HashSet<>();
 
-    public String getName() {
-        return name;
+    public MicroServicePolicy() {
+        //serialization
     }
 
-    public void setName(String name) {
+    public MicroServicePolicy(String name, String policyTosca, Boolean shared, JsonObject jsonRepresentation,
+        Set<Loop> usedByLoops) {
         this.name = name;
+        this.policyTosca = policyTosca;
+        this.shared = shared;
+        this.jsonRepresentation = jsonRepresentation;
+        this.usedByLoops = usedByLoops;
+    }
+
+    public String getName() {
+        return name;
     }
 
     public JsonObject getProperties() {
  *
  */
 
-package org.onap.clamp.dao;
+package org.onap.clamp.policy.microservice;
 
-import org.onap.clamp.dao.model.Loop;
 import org.springframework.data.repository.CrudRepository;
 import org.springframework.stereotype.Repository;
 
 @Repository
-public interface LoopsRepository extends CrudRepository<Loop, String> {
+interface MicroServicePolicyRepository extends CrudRepository<MicroServicePolicy, String> {
 
 }
diff --git a/src/main/java/org/onap/clamp/policy/microservice/MicroservicePolicyService.java b/src/main/java/org/onap/clamp/policy/microservice/MicroservicePolicyService.java
new file mode 100644 (file)
index 0000000..91794b7
--- /dev/null
@@ -0,0 +1,79 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 Nokia 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.onap.clamp.policy.microservice;
+
+import com.google.common.collect.Sets;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.onap.clamp.policy.PolicyService;
+import org.onap.clamp.loop.Loop;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+@Service
+public class MicroservicePolicyService implements PolicyService<MicroServicePolicy> {
+
+    private final MicroServicePolicyRepository repository;
+
+    @Autowired
+    public MicroservicePolicyService(MicroServicePolicyRepository repository) {
+        this.repository = repository;
+    }
+
+    @Override
+    @Transactional
+    public Set<MicroServicePolicy> updatePolicies(Loop loop,
+        List<MicroServicePolicy> newMicroservicePolicies) {
+        return newMicroservicePolicies
+            .stream()
+            .map(policy ->
+                getAndUpdateMicroServicePolicy(loop, policy))
+            .collect(Collectors.toSet());
+    }
+
+    @Override
+    public boolean isExisting(String policyName) {
+        return repository.existsById(policyName);
+    }
+
+    private MicroServicePolicy getAndUpdateMicroServicePolicy(Loop loop, MicroServicePolicy policy) {
+        return repository
+            .findById(policy.getName())
+            .map(p -> updateMicroservicePolicyProperties(p, policy, loop))
+            .orElse(new MicroServicePolicy(policy.getName(), policy.getPolicyTosca(),
+                policy.getShared(), policy.getJsonRepresentation(),
+                Sets.newHashSet(loop)));
+    }
+
+    private MicroServicePolicy updateMicroservicePolicyProperties(MicroServicePolicy oldPolicy,
+        MicroServicePolicy newPolicy, Loop loop) {
+        oldPolicy.setJsonRepresentation(newPolicy.getJsonRepresentation());
+        if (oldPolicy.getUsedByLoops().contains(loop)) {
+            oldPolicy.getUsedByLoops().add(loop);
+        }
+        return oldPolicy;
+    }
+}
  *
  */
 
-package org.onap.clamp.dao.model;
+package org.onap.clamp.policy.operational;
 
 import com.google.gson.JsonObject;
 import com.google.gson.annotations.Expose;
-
 import java.io.Serializable;
 
 import javax.persistence.Column;
+import javax.persistence.Convert;
 import javax.persistence.Entity;
 import javax.persistence.FetchType;
 import javax.persistence.Id;
 import javax.persistence.JoinColumn;
 import javax.persistence.ManyToOne;
 import javax.persistence.Table;
-
 import org.hibernate.annotations.Type;
 import org.hibernate.annotations.TypeDef;
 import org.hibernate.annotations.TypeDefs;
+import org.onap.clamp.loop.Loop;
+import org.onap.clamp.policy.Policy;
 import org.onap.clamp.dao.model.jsontype.StringJsonUserType;
 
 @Entity
 @Table(name = "operational_policies")
 @TypeDefs({ @TypeDef(name = "json", typeClass = StringJsonUserType.class) })
-public class OperationalPolicy implements Serializable {
+public class OperationalPolicy implements Serializable, Policy {
     /**
      *
      */
     private static final long serialVersionUID = 6117076450841538255L;
 
-    @Expose
     @Id
+    @Expose
     @Column(nullable = false, name = "name", unique = true)
     private String name;
 
@@ -64,20 +65,31 @@ public class OperationalPolicy implements Serializable {
     @JoinColumn(name = "loop_id", nullable = false)
     private Loop loop;
 
-    public Loop getLoop() {
-        return loop;
+    public OperationalPolicy() {
+        //Serialization
     }
 
-    public void setLoop(Loop loop) {
+    public OperationalPolicy(String name, Loop loop, JsonObject configurationsJson) {
+        this.name = name;
         this.loop = loop;
+        this.configurationsJson = configurationsJson;
     }
 
     public String getName() {
         return name;
     }
 
-    public void setName(String name) {
-        this.name = name;
+    public void setLoop(Loop loopName) {
+        this.loop = loopName;
+    }
+
+    public Loop getLoop(){
+        return loop;
+    }
+
+    @Override
+    public JsonObject getJsonRepresentation() {
+        return configurationsJson;
     }
 
     public JsonObject getConfigurationsJson() {
  *
  */
 
-package org.onap.clamp.dao;
+package org.onap.clamp.policy.operational;
 
-import org.onap.clamp.dao.model.OperationalPolicy;
 import org.springframework.data.repository.CrudRepository;
 import org.springframework.stereotype.Repository;
 
 @Repository
-public interface OperationalPolicyRepository extends CrudRepository<OperationalPolicy, String> {
-
+interface OperationalPolicyRepository extends CrudRepository<OperationalPolicy, String> {
+    void deleteByName(String policyName);
 }
diff --git a/src/main/java/org/onap/clamp/policy/operational/OperationalPolicyService.java b/src/main/java/org/onap/clamp/policy/operational/OperationalPolicyService.java
new file mode 100644 (file)
index 0000000..b24a2db
--- /dev/null
@@ -0,0 +1,66 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 Nokia 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.onap.clamp.policy.operational;
+
+import com.google.gson.JsonObject;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.onap.clamp.policy.PolicyService;
+import org.onap.clamp.loop.Loop;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class OperationalPolicyService implements PolicyService<OperationalPolicy> {
+
+    private final OperationalPolicyRepository repository;
+
+    @Autowired
+    public OperationalPolicyService(OperationalPolicyRepository repository) {
+        this.repository = repository;
+    }
+
+    @Override
+    public Set<OperationalPolicy> updatePolicies(Loop loop, List<OperationalPolicy> operationalPolicies) {
+        return operationalPolicies
+            .stream()
+            .map(policy ->
+                repository
+                    .findById(policy.getName())
+                    .map(p -> setConfigurationJson(p, policy.getConfigurationsJson()))
+                    .orElse(new OperationalPolicy(policy.getName(), loop, policy.getConfigurationsJson())))
+            .collect(Collectors.toSet());
+    }
+
+    @Override
+    public boolean isExisting(String policyName) {
+        return repository.existsById(policyName);
+    }
+
+    private OperationalPolicy setConfigurationJson(OperationalPolicy policy, JsonObject configurationsJson) {
+        policy.setConfigurationsJson(configurationsJson);
+        return policy;
+    }
+}
diff --git a/src/main/resources/clds/camel/rest/clamp-api-v2.xml b/src/main/resources/clds/camel/rest/clamp-api-v2.xml
new file mode 100644 (file)
index 0000000..0a72a0c
--- /dev/null
@@ -0,0 +1,34 @@
+<rests xmlns="http://camel.apache.org/schema/spring" >
+    <rest >
+        <get uri="/v2/loop/getAllNames"
+            outType="java.lang.String[]"
+            produces="application/json">
+            <to
+                uri="bean:org.onap.clamp.loop.LoopController?method=getLoopNames()" />
+        </get>
+        <get uri="/v2/loop/{loopName}"
+            outType="org.onap.clamp.loop.Loop"
+
+            produces="application/json">
+            <to
+                uri="bean:org.onap.clamp.loop.LoopController?method=getLoop(${header.loopName})" />
+        </get>
+        <post uri="/v2/loop/updateOperationalPolicies/{loopName}"
+            type="com.google.gson.JsonArray"
+            consumes="application/json"
+            outType="org.onap.clamp.loop.Loop"
+            produces="application/json">
+            <to
+                uri="bean:org.onap.clamp.loop.LoopController?method=updateOperationalPolicies(${header.loopName},${body})" />
+        </post>
+        <post uri="/v2/loop/updateMicroservicePolicies/{loopName}"
+            type="com.google.gson.JsonArray"
+            consumes="application/json"
+            outType="org.onap.clamp.loop.Loop"
+            produces="application/json">
+            <to
+                uri="bean:org.onap.clamp.loop.LoopController?method=updateMicroservicePolicies(${header.loopName},${body})" />
+        </post>
+    </rest>
+</rests>
+
index 7abffd3..d4baa09 100644 (file)
@@ -1,36 +1,36 @@
 <rests xmlns="http://camel.apache.org/schema/spring">
-       <rest>
-               <get uri="/clds/cldsDetails"
+       <rest >
+               <get uri="/v1/clds/cldsDetails"
                        outType="org.onap.clamp.clds.model.CldsMonitoringDetails"
                        produces="application/json">
                        <to
                                uri="bean:org.onap.clamp.clds.service.CldsService?method=getCldsDetails()" />
                </get>
-               <get uri="/clds/cldsInfo"
+               <get uri="/v1/clds/cldsInfo"
                        outType="org.onap.clamp.clds.model.CldsInfo"
                        produces="application/json">
                        <to
                                uri="bean:org.onap.clamp.clds.service.CldsService?method=getCldsInfo()" />
                </get>
-               <get uri="/healthcheck" produces="application/json">
+               <get uri="/v1/healthcheck" produces="application/json">
                        <to
                                uri="bean:org.onap.clamp.clds.service.CldsHealthcheckService?method=gethealthcheck()" />
                </get>
-               <get uri="/clds/model/bpmn/{modelName}" produces="text/xml">
+               <get uri="/v1/clds/model/bpmn/{modelName}" produces="text/xml">
                        <to
                                uri="bean:org.onap.clamp.clds.service.CldsService?method=getBpmnXml(${header.modelName})" />
                </get>
-               <get uri="/clds/model/image/{modelName}" produces="text/xml">
+               <get uri="/v1/clds/model/image/{modelName}" produces="text/xml">
                        <to
                                uri="bean:org.onap.clamp.clds.service.CldsService?method=getImageXml(${header.modelName})" />
                </get>
-               <get uri="/clds/model/{modelName}"
+               <get uri="/v1/clds/model/{modelName}"
                        outType="org.onap.clamp.clds.model.CldsModel"
                        produces="application/json">
                        <to
                                uri="bean:org.onap.clamp.clds.service.CldsService?method=getModel(${header.modelName})" />
                </get>
-               <put uri="/clds/model/{modelName}"
+               <put uri="/v1/clds/model/{modelName}"
                        type="org.onap.clamp.clds.model.CldsModel"
                        consumes="application/json"
                        outType="org.onap.clamp.clds.model.CldsModel"
                        <to
                                uri="bean:org.onap.clamp.clds.service.CldsService?method=putModel(${header.modelName},${body})" />
                </put>
-               <get uri="/clds/model-names"
+               <get uri="/v1/clds/model-names"
                        outType="org.onap.clamp.clds.model.ValueItem"
                        produces="application/json">
                        <to
                                uri="bean:org.onap.clamp.clds.service.CldsService?method=getModelNames()" />
                </get>
-               <put uri="/clds/action/{action}/{modelName}?test={test}"
+               <put uri="/v1/clds/action/{action}/{modelName}?test={test}"
                        type="org.onap.clamp.clds.model.CldsModel"
                        consumes="application/json" produces="application/json">
                        <to
                                uri="bean:org.onap.clamp.clds.service.CldsService?method=putModelAndProcessAction(${header.action},${header.modelName},${header.test},${body})" />
                </put>
-               <post uri="/clds/dcae/event?test={test}"
+               <post uri="/v1/clds/dcae/event?test={test}"
                        type="org.onap.clamp.clds.model.DcaeEvent"
                        consumes="application/json" produces="application/json">
                        <to
                                uri="bean:org.onap.clamp.clds.service.CldsService?method=postDcaeEvent(${header.test},${body})" />
                </post>
-               <get uri="/clds/properties" produces="application/json">
+               <get uri="/v1/clds/properties" produces="application/json">
                        <to
                                uri="bean:org.onap.clamp.clds.service.CldsService?method=getSdcProperties()" />
                </get>
-               <put uri="/clds/deploy/{modelName}"
+               <put uri="/v1/clds/deploy/{modelName}"
                        type="org.onap.clamp.clds.model.CldsModel"
                        consumes="application/json" produces="application/json">
                        <to
                                uri="bean:org.onap.clamp.clds.service.CldsService?method=deployModel(${header.modelName},${body})" />
                </put>
-               <put uri="/clds/undeploy/{modelName}"
+               <put uri="/v1/clds/undeploy/{modelName}"
                        type="org.onap.clamp.clds.model.CldsModel"
                        consumes="application/json" produces="application/json">
                        <to
 
 
 
-               <get uri="/cldsTempate/template/bpmn/{templateName}"
+               <get uri="/v1/cldsTempate/template/bpmn/{templateName}"
                        produces="text/xml">
                        <to
                                uri="bean:org.onap.clamp.clds.service.CldsTemplateService?method=getBpmnTemplate(${header.templateName})" />
                </get>
-               <get uri="/cldsTempate/template/image/{templateName}"
+               <get uri="/v1/cldsTempate/template/image/{templateName}"
                        produces="text/xml">
                        <to
                                uri="bean:org.onap.clamp.clds.service.CldsTemplateService?method=getImageXml(${header.templateName})" />
                </get>
-               <get uri="/cldsTempate/template/{templateName}"
+               <get uri="/v1/cldsTempate/template/{templateName}"
                        outType="org.onap.clamp.clds.model.CldsTemplate"
                        produces="application/json">
                        <to
                                uri="bean:org.onap.clamp.clds.service.CldsTemplateService?method=getTemplate(${header.templateName})" />
                </get>
-               <put uri="/cldsTempate/template/{templateName}"
+               <put uri="/v1/cldsTempate/template/{templateName}"
                        type="org.onap.clamp.clds.model.CldsTemplate"
                        consumes="application/json"
                        outType="org.onap.clamp.clds.model.CldsTemplate"
                        <to
                                uri="bean:org.onap.clamp.clds.service.CldsTemplateService?method=putTemplate(${header.templateName},${body})" />
                </put>
-               <get uri="/cldsTempate/template-names"
+               <get uri="/v1/cldsTempate/template-names"
                        outType="org.onap.clamp.clds.model.ValueItem"
                        produces="application/json">
                        <to
                </get>
 
 
-               <put uri="/tosca/models/{toscaModelName}"
+               <put uri="/v1/tosca/models/{toscaModelName}"
                        type="org.onap.clamp.clds.model.CldsToscaModel"
                        consumes="application/json" produces="application/json">
                        <to
                                uri="bean:org.onap.clamp.clds.service.CldsToscaService?method=parseToscaModelAndSave(${header.toscaModelName},${body})" />
                </put>
-               <get uri="/tosca/models/policyType/{policyType}"
+               <get uri="/v1/tosca/models/policyType/{policyType}"
                outType="org.onap.clamp.clds.model.CldsToscaModel"
                        produces="application/json">
                        <to
                                uri="bean:org.onap.clamp.clds.service.CldsToscaService?method=getToscaModelsByPolicyType(${header.policyType})" />
                </get>
-               <get uri="/tosca/models"
+               <get uri="/v1/tosca/models"
                        outType="org.onap.clamp.clds.model.CldsToscaModel"
                        produces="application/json">
                        <to
                                uri="bean:org.onap.clamp.clds.service.CldsToscaService?method=getAllToscaModels()" />
                </get>
-               <get uri="/tosca/models/{toscaModelName}"
+               <get uri="/v1/tosca/models/{toscaModelName}"
                        outType="org.onap.clamp.clds.model.CldsToscaModel"
                        produces="application/json">
                        <to
                </get>
 
 
-               <put uri="/dictionary/{dictionaryName}"
+               <put uri="/v1/dictionary/{dictionaryName}"
                        type="org.onap.clamp.clds.model.CldsDictionary"
                        outType="org.onap.clamp.clds.model.CldsDictionary"
                        consumes="application/json" produces="application/json">
                                uri="bean:org.onap.clamp.clds.service.CldsDictionaryService?method=createOrUpdateDictionary(${header.dictionaryName},${body})" />
                </put>
 
-               <get uri="/dictionary"
+               <get uri="/v1/dictionary"
                        outType="org.onap.clamp.clds.model.CldsDictionary"
                        produces="application/json">
                        <to
                                uri="bean:org.onap.clamp.clds.service.CldsDictionaryService?method=getAllDictionaryNames()" />
                </get>
 
-               <put uri="/dictionary/{dictionaryName}/items"
+               <put uri="/v1/dictionary/{dictionaryName}/items"
                        type="org.onap.clamp.clds.model.CldsDictionaryItem"
                        outType="org.onap.clamp.clds.model.CldsDictionaryItem"
                        consumes="application/json" produces="application/json">
                                uri="bean:org.onap.clamp.clds.service.CldsDictionaryService?method=createOrUpdateDictionaryElements(${header.dictionaryName},${body})" />
                </put>
 
-               <get uri="/dictionary/{dictionaryName}/items"
+               <get uri="/v1/dictionary/{dictionaryName}/items"
                        outType="org.onap.clamp.clds.model.CldsDictionary"
                        produces="application/json">
                        <to
                                uri="bean:org.onap.clamp.clds.service.CldsDictionaryService?method=getDictionaryElementsByName(${header.dictionaryName})" />
                </get>
 
-               <get uri="/user/getUser" produces="text/plain">
+               <get uri="/v1/user/getUser" produces="text/plain">
                        <to
                                uri="bean:org.onap.clamp.clds.service.UserService?method=getUser()" />
                </get>
index 81b6b83..57dbcf7 100644 (file)
@@ -130,7 +130,7 @@ public class HttpsItCase {
         });
         template.setRequestFactory(factory);
         ResponseEntity<String> httpsEntity = template
-            .getForEntity("https://localhost:" + this.httpsPort + "/restservices/clds/v1/api-doc", String.class);
+            .getForEntity("https://localhost:" + this.httpsPort + "/restservices/clds/api-doc", String.class);
         assertThat(httpsEntity.getStatusCode()).isEqualTo(HttpStatus.OK);
         assertThat(httpsEntity.getBody()).contains("swagger");
         FileUtils.writeStringToFile(
@@ -21,7 +21,7 @@
  *
  */
 
-package org.onap.clamp.it.dao.model;
+package org.onap.clamp.loop;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
@@ -31,19 +31,17 @@ import com.google.gson.JsonObject;
 
 import java.time.Instant;
 
+import java.util.HashSet;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.onap.clamp.clds.Application;
-import org.onap.clamp.dao.LoopLogRepository;
-import org.onap.clamp.dao.LoopsRepository;
-import org.onap.clamp.dao.MicroServicePolicyRepository;
-import org.onap.clamp.dao.OperationalPolicyRepository;
-import org.onap.clamp.dao.model.LogType;
-import org.onap.clamp.dao.model.Loop;
-import org.onap.clamp.dao.model.LoopLog;
-import org.onap.clamp.dao.model.LoopState;
-import org.onap.clamp.dao.model.MicroServicePolicy;
-import org.onap.clamp.dao.model.OperationalPolicy;
+import org.onap.clamp.loop.log.LogType;
+import org.onap.clamp.loop.log.LoopLog;
+import org.onap.clamp.loop.log.LoopLogRepository;
+import org.onap.clamp.policy.microservice.MicroServicePolicy;
+import org.onap.clamp.policy.microservice.MicroservicePolicyService;
+import org.onap.clamp.policy.operational.OperationalPolicy;
+import org.onap.clamp.policy.operational.OperationalPolicyService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -59,19 +57,16 @@ public class LoopRepositoriesItCase {
     private LoopsRepository loopRepository;
 
     @Autowired
-    private MicroServicePolicyRepository microServicePolicyRepository;
+    private MicroservicePolicyService microServicePolicyService;
 
     @Autowired
-    private OperationalPolicyRepository operationalPolicyRepository;
+    private OperationalPolicyService operationalPolicyService;
 
     @Autowired
     private LoopLogRepository loopLogRepository;
 
     private OperationalPolicy getOperationalPolicy(String configJson, String name) {
-        OperationalPolicy opPolicy = new OperationalPolicy();
-        opPolicy.setName(name);
-        opPolicy.setConfigurationsJson(new Gson().fromJson(configJson, JsonObject.class));
-        return opPolicy;
+        return new OperationalPolicy(name, null, new Gson().fromJson(configJson, JsonObject.class));
     }
 
     private Loop getLoop(String name, String svgRepresentation, String blueprint, String globalPropertiesJson,
@@ -90,13 +85,9 @@ public class LoopRepositoriesItCase {
 
     private MicroServicePolicy getMicroServicePolicy(String name, String jsonRepresentation, String policyTosca,
         String jsonProperties, boolean shared) {
-        MicroServicePolicy µService = new MicroServicePolicy();
-        µService.setJsonRepresentation(new Gson().fromJson(jsonRepresentation, JsonObject.class));
-        µService.setPolicyTosca(policyTosca);
+        MicroServicePolicy µService = new MicroServicePolicy(name, policyTosca, shared,
+            gson.fromJson(jsonRepresentation, JsonObject.class), new HashSet<>());
         µService.setProperties(new Gson().fromJson(jsonProperties, JsonObject.class));
-        µService.setShared(shared);
-
-        µService.setName(name);
         return µService;
     }
 
@@ -129,8 +120,8 @@ public class LoopRepositoriesItCase {
 
         assertThat(loopInDb).isEqualToComparingFieldByField(loopTest);
         assertThat(loopRepository.existsById(loopTest.getName())).isEqualTo(true);
-        assertThat(operationalPolicyRepository.existsById(opPolicy.getName())).isEqualTo(true);
-        assertThat(microServicePolicyRepository.existsById(microServicePolicy.getName())).isEqualTo(true);
+        assertThat(operationalPolicyService.isExisting(opPolicy.getName())).isEqualTo(true);
+        assertThat(microServicePolicyService.isExisting(microServicePolicy.getName())).isEqualTo(true);
         assertThat(loopLogRepository.existsById(loopLog.getId())).isEqualTo(true);
 
         // Now attempt to read from database
@@ -152,8 +143,8 @@ public class LoopRepositoriesItCase {
         // Attempt to delete the object and check it has well been cascaded
         loopRepository.delete(loopInDbRetrieved);
         assertThat(loopRepository.existsById(loopTest.getName())).isEqualTo(false);
-        assertThat(operationalPolicyRepository.existsById(opPolicy.getName())).isEqualTo(false);
-        assertThat(microServicePolicyRepository.existsById(microServicePolicy.getName())).isEqualTo(false);
+        assertThat(operationalPolicyService.isExisting(opPolicy.getName())).isEqualTo(false);
+        assertThat(microServicePolicyService.isExisting(microServicePolicy.getName())).isEqualTo(false);
         assertThat(loopLogRepository.existsById(loopLog.getId())).isEqualTo(false);
 
     }
diff --git a/src/test/java/org/onap/clamp/loop/LoopServiceTestItCase.java b/src/test/java/org/onap/clamp/loop/LoopServiceTestItCase.java
new file mode 100644 (file)
index 0000000..a9c3087
--- /dev/null
@@ -0,0 +1,270 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 Nokia 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.onap.clamp.loop;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import com.google.gson.JsonObject;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.assertj.core.util.Lists;
+import org.junit.After;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.onap.clamp.clds.Application;
+import org.onap.clamp.clds.util.JsonUtils;
+import org.onap.clamp.policy.microservice.MicroServicePolicy;
+import org.onap.clamp.policy.operational.OperationalPolicy;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.transaction.annotation.Transactional;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@SpringBootTest(classes = Application.class)
+public class LoopServiceTestItCase {
+
+    private static final String EXAMPLE_LOOP_NAME = "ClosedLoopTest";
+    private static final String EXAMPLE_JSON = "{\"testName\":\"testValue\"}";
+
+    @Autowired
+    LoopService loopService;
+
+    @Autowired
+    LoopsRepository loopsRepository;
+
+    @After
+    public void tearDown() {
+        loopsRepository.deleteAll();
+    }
+
+    @Test
+    public void shouldCreateEmptyLoop() {
+        //given
+        String loopBlueprint = "blueprint";
+        String loopSvg = "representation";
+        Loop testLoop = createTestLoop(EXAMPLE_LOOP_NAME, loopBlueprint, loopSvg);
+        testLoop.setGlobalPropertiesJson(JsonUtils.GSON.fromJson(EXAMPLE_JSON, JsonObject.class));
+        testLoop.setLastComputedState(LoopState.DESIGN);
+
+        //when
+        Loop actualLoop = loopService.addNewLoop(testLoop);
+
+        //then
+        assertThat(actualLoop).isNotNull();
+        assertThat(actualLoop).isEqualTo(loopsRepository.findById(actualLoop.getName()).get());
+        assertThat(actualLoop.getName()).isEqualTo(EXAMPLE_LOOP_NAME);
+        assertThat(actualLoop.getBlueprint()).isEqualTo(loopBlueprint);
+        assertThat(actualLoop.getSvgRepresentation()).isEqualTo(loopSvg);
+        assertThat(actualLoop.getGlobalPropertiesJson().getAsJsonPrimitive("testName").getAsString())
+            .isEqualTo("testValue");
+    }
+
+    @Test
+    public void shouldAddOperationalPolicyToLoop() {
+        //given
+        saveTestLoopToDb();
+        JsonObject confJson = JsonUtils.GSON.fromJson(EXAMPLE_JSON, JsonObject.class);
+        String policyName = "policyName";
+        OperationalPolicy operationalPolicy = new OperationalPolicy(policyName, null, confJson);
+
+        //when
+        Loop actualLoop = loopService
+            .updateOperationalPolicies(EXAMPLE_LOOP_NAME, Lists.newArrayList(operationalPolicy));
+
+        //then
+        assertThat(actualLoop).isNotNull();
+        assertThat(actualLoop.getName()).isEqualTo(EXAMPLE_LOOP_NAME);
+        Set<OperationalPolicy> savedPolicies = actualLoop.getOperationalPolicies();
+        assertThat(savedPolicies).hasSize(1);
+        assertThat(savedPolicies)
+            .usingElementComparatorIgnoringFields("loop")
+            .contains(operationalPolicy);
+        OperationalPolicy savedPolicy = savedPolicies.iterator().next();
+        assertThat(savedPolicy.getLoop().getName()).isEqualTo(EXAMPLE_LOOP_NAME);
+
+    }
+
+    @Test
+    public void shouldAddMicroservicePolicyToLoop() {
+        //given
+        saveTestLoopToDb();
+        JsonObject confJson = JsonUtils.GSON.fromJson(EXAMPLE_JSON, JsonObject.class);
+        String policyName = "policyName";
+        String policyTosca = "policyTosca";
+        MicroServicePolicy microServicePolicy = new MicroServicePolicy(policyName, policyTosca, false, confJson, null);
+
+        //when
+        Loop actualLoop = loopService
+            .updateMicroservicePolicies(EXAMPLE_LOOP_NAME, Lists.newArrayList(microServicePolicy));
+
+        //then
+        assertThat(actualLoop).isNotNull();
+        assertThat(actualLoop.getName()).isEqualTo(EXAMPLE_LOOP_NAME);
+        Set<MicroServicePolicy> savedPolicies = actualLoop.getMicroServicePolicies();
+        assertThat(savedPolicies).hasSize(1);
+        assertThat(savedPolicies).usingElementComparatorIgnoringFields("usedByLoops")
+            .containsExactly(microServicePolicy);
+        assertThat(savedPolicies).extracting("usedByLoops")
+            .hasSize(1);
+
+    }
+
+    @Test
+    @Transactional
+    public void shouldCreateNewMicroservicePolicyAndUpdateJsonRepresentationOfOldOne() {
+        //given
+        saveTestLoopToDb();
+        String firstPolicyName = "firstPolicyName";
+        JsonObject newJsonRepresentation = JsonUtils.GSON.fromJson("{}", JsonObject.class);
+        String secondPolicyName = "secondPolicyName";
+        String secondPolicyTosca = "secondPolicyTosca";
+        MicroServicePolicy firstMicroServicePolicy = new MicroServicePolicy(firstPolicyName, "policyTosca",
+            false, JsonUtils.GSON.fromJson(EXAMPLE_JSON, JsonObject.class), null);
+        loopService.updateMicroservicePolicies(EXAMPLE_LOOP_NAME, Lists.newArrayList(firstMicroServicePolicy));
+
+        MicroServicePolicy secondMicroServicePolicy = new MicroServicePolicy(secondPolicyName, secondPolicyTosca, true,
+            newJsonRepresentation, null);
+
+        //when
+        firstMicroServicePolicy.setJsonRepresentation(newJsonRepresentation);
+        Loop actualLoop = loopService.updateMicroservicePolicies(EXAMPLE_LOOP_NAME,
+            Lists.newArrayList(firstMicroServicePolicy, secondMicroServicePolicy));
+
+        //then
+        assertThat(actualLoop).isNotNull();
+        assertThat(actualLoop.getName()).isEqualTo(EXAMPLE_LOOP_NAME);
+        Set<MicroServicePolicy> savedPolicies = actualLoop.getMicroServicePolicies();
+        assertThat(savedPolicies).hasSize(2);
+        assertThat(savedPolicies).usingElementComparatorIgnoringFields("usedByLoops")
+            .containsExactlyInAnyOrder(firstMicroServicePolicy, secondMicroServicePolicy);
+
+    }
+
+    private void saveTestLoopToDb() {
+        Loop testLoop = createTestLoop(EXAMPLE_LOOP_NAME, "blueprint", "representation");
+        testLoop.setGlobalPropertiesJson(JsonUtils.GSON.fromJson(EXAMPLE_JSON, JsonObject.class));
+        loopService.addNewLoop(testLoop);
+    }
+
+    @Test
+    public void shouldRemoveOldMicroservicePolicyIfNotInUpdatedList() {
+        //given
+        saveTestLoopToDb();
+
+        JsonObject jsonRepresentation = JsonUtils.GSON.fromJson("{}", JsonObject.class);
+        String firstPolicyName = "firstPolicyName";
+        String secondPolicyName = "policyName";
+        String secondPolicyTosca = "secondPolicyTosca";
+        MicroServicePolicy firstMicroServicePolicy = new MicroServicePolicy(firstPolicyName, "policyTosca",
+            false, JsonUtils.GSON.fromJson(EXAMPLE_JSON, JsonObject.class), null);
+        loopService.updateMicroservicePolicies(EXAMPLE_LOOP_NAME, Lists.newArrayList(firstMicroServicePolicy));
+
+        MicroServicePolicy secondMicroServicePolicy = new MicroServicePolicy(secondPolicyName, secondPolicyTosca, true,
+            jsonRepresentation, null);
+
+        //when
+        Loop actualLoop = loopService
+            .updateMicroservicePolicies(EXAMPLE_LOOP_NAME, Lists.newArrayList(secondMicroServicePolicy));
+
+        //then
+        assertThat(actualLoop).isNotNull();
+        assertThat(actualLoop.getName()).isEqualTo(EXAMPLE_LOOP_NAME);
+        Set<MicroServicePolicy> savedPolicies = actualLoop.getMicroServicePolicies();
+        assertThat(savedPolicies).hasSize(1);
+        assertThat(savedPolicies).usingElementComparatorIgnoringFields("usedByLoops")
+            .containsExactly(secondMicroServicePolicy);
+
+    }
+
+    @Test
+    @Transactional
+    public void shouldCreateNewOperationalPolicyAndUpdateJsonRepresentationOfOldOne() {
+        //given
+        saveTestLoopToDb();
+
+        String firstPolicyName = "firstPolicyName";
+        JsonObject newJsonConfiguration = JsonUtils.GSON.fromJson("{}", JsonObject.class);
+        String secondPolicyName = "secondPolicyName";
+        OperationalPolicy firstOperationalPolicy = new OperationalPolicy(firstPolicyName, null,
+            JsonUtils.GSON.fromJson(EXAMPLE_JSON, JsonObject.class));
+        loopService.updateOperationalPolicies(EXAMPLE_LOOP_NAME, Lists.newArrayList(firstOperationalPolicy));
+
+        OperationalPolicy secondOperationalPolicy = new OperationalPolicy(secondPolicyName, null, newJsonConfiguration);
+
+        //when
+        firstOperationalPolicy.setConfigurationsJson(newJsonConfiguration);
+        Loop actualLoop = loopService.updateOperationalPolicies(EXAMPLE_LOOP_NAME,
+            Lists.newArrayList(firstOperationalPolicy, secondOperationalPolicy));
+
+        //then
+        assertThat(actualLoop).isNotNull();
+        assertThat(actualLoop.getName()).isEqualTo(EXAMPLE_LOOP_NAME);
+        Set<OperationalPolicy> savedPolicies = actualLoop.getOperationalPolicies();
+        assertThat(savedPolicies).hasSize(2);
+        assertThat(savedPolicies).usingElementComparatorIgnoringFields("loop")
+            .containsExactlyInAnyOrder(firstOperationalPolicy, secondOperationalPolicy);
+        Set<String> policiesLoops = Lists.newArrayList(savedPolicies).stream()
+            .map(OperationalPolicy::getLoop)
+            .map(Loop::getName)
+            .collect(Collectors.toSet());
+        assertThat(policiesLoops)
+            .containsExactly(EXAMPLE_LOOP_NAME);
+    }
+
+    @Test
+    public void shouldRemoveOldOperationalPolicyIfNotInUpdatedList() {
+        //given
+        saveTestLoopToDb();
+
+        JsonObject jsonRepresentation = JsonUtils.GSON.fromJson("{}", JsonObject.class);
+        String firstPolicyName = "firstPolicyName";
+        String secondPolicyName = "policyName";
+        OperationalPolicy firstOperationalPolicy = new OperationalPolicy(firstPolicyName, null,
+            JsonUtils.GSON.fromJson(EXAMPLE_JSON, JsonObject.class));
+        loopService.updateOperationalPolicies(EXAMPLE_LOOP_NAME, Lists.newArrayList(firstOperationalPolicy));
+
+        OperationalPolicy secondOperationalPolicy = new OperationalPolicy(secondPolicyName, null, jsonRepresentation);
+
+        //when
+        Loop actualLoop = loopService
+            .updateOperationalPolicies(EXAMPLE_LOOP_NAME, Lists.newArrayList(secondOperationalPolicy));
+
+        //then
+        assertThat(actualLoop).isNotNull();
+        assertThat(actualLoop.getName()).isEqualTo(EXAMPLE_LOOP_NAME);
+        Set<OperationalPolicy> savedPolicies = actualLoop.getOperationalPolicies();
+        assertThat(savedPolicies).hasSize(1);
+        assertThat(savedPolicies).usingElementComparatorIgnoringFields("loop")
+            .containsExactly(secondOperationalPolicy);
+        OperationalPolicy savedPolicy = savedPolicies.iterator().next();
+        assertThat(savedPolicy.getLoop().getName()).isEqualTo(EXAMPLE_LOOP_NAME);
+
+    }
+
+    private Loop createTestLoop(String loopName, String loopBlueprint, String loopSvg) {
+        return new Loop(loopName, loopBlueprint, loopSvg);
+    }
+}
\ No newline at end of file
@@ -21,7 +21,7 @@
  *
  */
 
-package org.onap.clamp.dao.model;
+package org.onap.clamp.loop;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.junit.Assert.assertNotNull;
@@ -29,26 +29,27 @@ import static org.junit.Assert.assertNotNull;
 import com.google.gson.Gson;
 import com.google.gson.JsonObject;
 
+import java.util.HashSet;
 import java.util.Random;
 
 import org.junit.Test;
+import org.onap.clamp.loop.log.LogType;
+import org.onap.clamp.loop.log.LoopLog;
+import org.onap.clamp.policy.microservice.MicroServicePolicy;
+import org.onap.clamp.policy.operational.OperationalPolicy;
 import org.onap.clamp.clds.util.JsonUtils;
 
 public class LoopToJsonTest {
 
+    private Gson gson = new Gson();
+
     private OperationalPolicy getOperationalPolicy(String configJson, String name) {
-        OperationalPolicy opPolicy = new OperationalPolicy();
-        opPolicy.setName(name);
-        opPolicy.setConfigurationsJson(new Gson().fromJson(configJson, JsonObject.class));
-        return opPolicy;
+        return new OperationalPolicy(name, null, gson.fromJson(configJson, JsonObject.class));
     }
 
     private Loop getLoop(String name, String svgRepresentation, String blueprint, String globalPropertiesJson,
         String dcaeId, String dcaeUrl, String dcaeBlueprintId) {
-        Loop loop = new Loop();
-        loop.setName(name);
-        loop.setSvgRepresentation(svgRepresentation);
-        loop.setBlueprint(blueprint);
+        Loop loop = new Loop(name, blueprint, svgRepresentation);
         loop.setGlobalPropertiesJson(new Gson().fromJson(globalPropertiesJson, JsonObject.class));
         loop.setLastComputedState(LoopState.DESIGN);
         loop.setDcaeDeploymentId(dcaeId);
@@ -59,13 +60,10 @@ public class LoopToJsonTest {
 
     private MicroServicePolicy getMicroServicePolicy(String name, String jsonRepresentation, String policyTosca,
         String jsonProperties, boolean shared) {
-        MicroServicePolicy µService = new MicroServicePolicy();
-        µService.setJsonRepresentation(new Gson().fromJson(jsonRepresentation, JsonObject.class));
-        µService.setPolicyTosca(policyTosca);
+        MicroServicePolicy µService = new MicroServicePolicy(name, policyTosca, shared,
+            gson.fromJson(jsonRepresentation, JsonObject.class), new HashSet<>());
         µService.setProperties(new Gson().fromJson(jsonProperties, JsonObject.class));
-        µService.setShared(shared);
 
-        µService.setName(name);
         return µService;
     }
 
@@ -94,7 +92,12 @@ public class LoopToJsonTest {
         System.out.println(jsonSerialized);
         Loop loopTestDeserialized = JsonUtils.GSON_JPA_MODEL.fromJson(jsonSerialized, Loop.class);
         assertNotNull(loopTestDeserialized);
-        assertThat(loopTestDeserialized).isEqualToComparingFieldByField(loopTest);
+        assertThat(loopTestDeserialized).isEqualToIgnoringGivenFields(loopTest, "svgRepresentation", "blueprint");
+
+        //svg and blueprint not exposed so wont be deserialized
+        assertThat(loopTestDeserialized.getBlueprint()).isEqualTo(null);
+        assertThat(loopTestDeserialized.getSvgRepresentation()).isEqualTo(null);
+
         assertThat(loopTestDeserialized.getOperationalPolicies()).containsExactly(opPolicy);
         assertThat(loopTestDeserialized.getMicroServicePolicies()).containsExactly(microServicePolicy);
         assertThat(loopTestDeserialized.getLoopLogs()).containsExactly(loopLog);