Java 17 / Spring 6 / Spring Boot 3 Upgrade
[policy/api.git] / main / src / main / java / org / onap / policy / api / main / service / ToscaServiceTemplateService.java
index ba61dd4..9ec28d1 100644 (file)
@@ -1,6 +1,7 @@
 /*-
  * ============LICENSE_START=======================================================
  *  Copyright (C) 2022 Bell Canada. All rights reserved.
+ *  Modifications Copyright (C) 2022-2023 Nordix Foundation.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 
 package org.onap.policy.api.main.service;
 
+import jakarta.ws.rs.core.Response;
+import java.util.ArrayList;
 import java.util.List;
-import javax.ws.rs.core.Response;
+import java.util.Optional;
 import lombok.NonNull;
 import lombok.RequiredArgsConstructor;
 import org.apache.commons.collections4.CollectionUtils;
@@ -32,10 +35,14 @@ import org.onap.policy.models.base.PfConceptKey;
 import org.onap.policy.models.base.PfModelException;
 import org.onap.policy.models.base.PfModelRuntimeException;
 import org.onap.policy.models.tosca.authorative.concepts.ToscaEntityFilter;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeTemplate;
 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyType;
 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
 import org.onap.policy.models.tosca.authorative.concepts.ToscaTypedEntityFilter;
+import org.onap.policy.models.tosca.simple.concepts.JpaToscaNodeTemplate;
+import org.onap.policy.models.tosca.simple.concepts.JpaToscaNodeTemplates;
+import org.onap.policy.models.tosca.simple.concepts.JpaToscaNodeTypes;
 import org.onap.policy.models.tosca.simple.concepts.JpaToscaPolicies;
 import org.onap.policy.models.tosca.simple.concepts.JpaToscaPolicyTypes;
 import org.onap.policy.models.tosca.simple.concepts.JpaToscaServiceTemplate;
@@ -62,6 +69,7 @@ public class ToscaServiceTemplateService {
     public static final String DO_NOT_EXIST_MSG = " do not exist";
 
     private final ToscaServiceTemplateRepository toscaServiceTemplateRepository;
+    private final NodeTemplateService nodeTemplateService;
     private final PdpGroupService pdpGroupService;
     private final PolicyTypeService policyTypeService;
     private final PolicyService policyService;
@@ -75,7 +83,9 @@ public class ToscaServiceTemplateService {
      */
     public ToscaServiceTemplate fetchPolicyTypes(final String policyTypeName, final String policyTypeVersion)
         throws PfModelException {
-        return getFilteredPolicyTypes(policyTypeName, policyTypeVersion);
+        final var policyTypeFilter =
+            ToscaEntityFilter.<ToscaPolicyType>builder().name(policyTypeName).version(policyTypeVersion).build();
+        return getFilteredPolicyTypes(policyTypeFilter);
     }
 
     /**
@@ -85,7 +95,9 @@ public class ToscaServiceTemplateService {
      * @return the ToscaServiceTemplate object
      */
     public ToscaServiceTemplate fetchLatestPolicyTypes(final String policyTypeName) throws PfModelException {
-        return getFilteredPolicyTypes(policyTypeName, ToscaEntityFilter.LATEST_VERSION);
+        final var policyTypeFilter = ToscaEntityFilter.<ToscaPolicyType>builder()
+            .name(policyTypeName).version(ToscaEntityFilter.LATEST_VERSION).build();
+        return getFilteredPolicyTypes(policyTypeFilter);
     }
 
     /**
@@ -104,8 +116,11 @@ public class ToscaServiceTemplateService {
         ToscaUtils.assertPolicyTypesExist(incomingServiceTemplate);
 
         // append the incoming fragment to the DB TOSCA service template
-        final var serviceTemplateToWrite =
-            ToscaServiceTemplateUtils.addFragment(getDefaultJpaToscaServiceTemplate(), incomingServiceTemplate);
+        var dbServiceTemplateOpt = getDefaultJpaToscaServiceTemplateOpt();
+        JpaToscaServiceTemplate serviceTemplateToWrite;
+        serviceTemplateToWrite = dbServiceTemplateOpt.map(
+            jpaToscaServiceTemplate -> ToscaServiceTemplateUtils.addFragment(jpaToscaServiceTemplate,
+                incomingServiceTemplate)).orElse(incomingServiceTemplate);
 
         final var result = serviceTemplateToWrite.validate("service template");
         if (!result.isValid()) {
@@ -244,8 +259,11 @@ public class ToscaServiceTemplateService {
         ToscaUtils.assertPoliciesExist(incomingServiceTemplate);
 
         // append the incoming fragment to the DB TOSCA service template
-        final var serviceTemplateToWrite =
-            ToscaServiceTemplateUtils.addFragment(getDefaultJpaToscaServiceTemplate(), incomingServiceTemplate);
+        var dbServiceTemplateOpt = getDefaultJpaToscaServiceTemplateOpt();
+        JpaToscaServiceTemplate serviceTemplateToWrite;
+        serviceTemplateToWrite = dbServiceTemplateOpt.map(
+            jpaToscaServiceTemplate -> ToscaServiceTemplateUtils.addFragment(jpaToscaServiceTemplate,
+                incomingServiceTemplate)).orElse(incomingServiceTemplate);
 
         final var result = serviceTemplateToWrite.validate("Policies CRUD service template.");
         if (!result.isValid()) {
@@ -254,7 +272,7 @@ public class ToscaServiceTemplateService {
 
         toscaServiceTemplateRepository.save(serviceTemplateToWrite);
 
-        LOGGER.debug("<-appendServiceTemplateFragment: returnServiceTempalate={}", serviceTemplateToWrite);
+        LOGGER.debug("<-appendServiceTemplateFragment: returnServiceTemplate={}", serviceTemplateToWrite);
         return body;
     }
 
@@ -308,16 +326,13 @@ public class ToscaServiceTemplateService {
     /**
      * Retrieves TOSCA service template with the specified version of the policy type.
      *
-     * @param policyTypeName the name of the policy type
-     * @param policyTypeVersion the version of the policy type
+     * @param policyTypeFilter the policy type filter containing name and version of the policy type
      * @return the TOSCA service template containing the specified version of the policy type
      * @throws PfModelException on errors getting the policy type
      */
-    private ToscaServiceTemplate getFilteredPolicyTypes(final String policyTypeName, final String policyTypeVersion)
+    public ToscaServiceTemplate getFilteredPolicyTypes(final ToscaEntityFilter<ToscaPolicyType> policyTypeFilter)
         throws PfModelException {
         final var dbServiceTemplate = getDefaultJpaToscaServiceTemplate();
-        final var policyTypeFilter =
-            ToscaEntityFilter.<ToscaPolicyType>builder().name(policyTypeName).version(policyTypeVersion).build();
         LOGGER.debug("->getFilteredPolicyTypes: filter={}, serviceTemplate={}", policyTypeFilter, dbServiceTemplate);
 
         // validate that policyTypes exist in db
@@ -326,9 +341,11 @@ public class ToscaServiceTemplateService {
                 "policy types for filter " + policyTypeFilter + DO_NOT_EXIST_MSG);
         }
 
+        var version = ToscaTypedEntityFilter.LATEST_VERSION
+            .equals(policyTypeFilter.getVersion()) ? null : policyTypeFilter.getVersion();
         // fetch all polices and filter by policyType, policy name and version
         final var serviceTemplate = new SimpleToscaProvider()
-            .getCascadedPolicyTypes(dbServiceTemplate, policyTypeName, policyTypeVersion);
+            .getCascadedPolicyTypes(dbServiceTemplate, policyTypeFilter.getName(), version);
         var simpleToscaProvider = new SimpleToscaProvider();
 
         List<ToscaPolicyType> filteredPolicyTypes = serviceTemplate.getPolicyTypes().toAuthorativeList();
@@ -412,17 +429,163 @@ public class ToscaServiceTemplateService {
         return returnServiceTemplate.toAuthorative();
     }
 
+    /**
+     * Write a node template to the database.
+     *
+     * @param serviceTemplate the service template to be written
+     * @return the service template created by this method
+     * @throws PfModelException on errors writing the metadataSets
+     */
+    public ToscaServiceTemplate createToscaNodeTemplates(@NonNull final ToscaServiceTemplate serviceTemplate)
+        throws PfModelException {
+
+        LOGGER.debug("->write: tosca nodeTemplates={}", serviceTemplate);
+        final var incomingServiceTemplate = new JpaToscaServiceTemplate(serviceTemplate);
+
+        ToscaUtils.assertNodeTemplatesExist(incomingServiceTemplate);
+
+        Optional<JpaToscaNodeTypes> nodeTypes = Optional.ofNullable(incomingServiceTemplate.getNodeTypes());
+        for (JpaToscaNodeTemplate nodeTemplate : incomingServiceTemplate.getTopologyTemplate().getNodeTemplates()
+            .getAll(null)) {
+            // verify node types in the db if mismatch/empty entities in the template
+            if (! (nodeTypes.isPresent() && nodeTypes.get().getKeys().contains(nodeTemplate.getType()))) {
+                nodeTemplateService.verifyNodeTypeInDbTemplate(nodeTemplate);
+            }
+        }
+        // append the incoming fragment to the DB TOSCA service template
+        final var serviceTemplateToWrite =
+            ToscaServiceTemplateUtils.addFragment(getDefaultJpaToscaServiceTemplate(), incomingServiceTemplate);
+
+        final var result = serviceTemplateToWrite.validate("service template.");
+        if (!result.isValid()) {
+            throw new PfModelRuntimeException(Response.Status.NOT_ACCEPTABLE, result.getResult());
+        }
+        toscaServiceTemplateRepository.save(serviceTemplateToWrite);
+        LOGGER.debug("<-createdToscaNodeTemplates: writtenServiceTemplate={}", serviceTemplateToWrite);
+
+        return serviceTemplate;
+    }
+
+    /**
+     * Update tosca node template.
+     *
+     * @param serviceTemplate the service template containing the definitions of the node templates to be updated.
+     * @return the TOSCA service template containing the node templates that were updated
+     * @throws PfModelRuntimeException on errors updating node templates
+     */
+    public ToscaServiceTemplate updateToscaNodeTemplates(@NonNull final ToscaServiceTemplate serviceTemplate)
+        throws PfModelException {
+        LOGGER.debug("->updateToscaNodeTemplates: serviceTemplate={}", serviceTemplate);
+        final var incomingServiceTemplate = new JpaToscaServiceTemplate(serviceTemplate);
+
+        ToscaUtils.assertNodeTemplatesExist(incomingServiceTemplate);
+        nodeTemplateService.updateToscaNodeTemplates(incomingServiceTemplate);
+
+        LOGGER.debug("<-updatedToscaNodeTemplates: serviceTemplate={}", serviceTemplate);
+        return incomingServiceTemplate.toAuthorative();
+    }
+
+
+    /**
+     * Delete a tosca node template.
+     *
+     * @param name the name of node template
+     * @param version the version of node template
+     * @return the TOSCA service template containing the node template that were deleted
+     * @throws PfModelException on errors deleting node templates
+     */
+    public ToscaServiceTemplate deleteToscaNodeTemplate(@NonNull final String name, @NonNull final String version)
+        throws PfModelException {
+        LOGGER.debug("->deleteToscaNodeTemplate: name={}, version={}", name, version);
+
+        JpaToscaServiceTemplate dbServiceTemplate = getDefaultJpaToscaServiceTemplate();
+        final var nodeTemplateKey = new PfConceptKey(name, version);
+
+        if (!ToscaUtils.doNodeTemplatesExist(dbServiceTemplate)) {
+            throw new PfModelRuntimeException(Response.Status.NOT_FOUND, "no node templates found");
+        }
+        JpaToscaNodeTemplate nodeTemplate4Deletion = dbServiceTemplate.getTopologyTemplate().getNodeTemplates()
+            .get(new PfConceptKey(name, version));
+        if (nodeTemplate4Deletion == null) {
+            throw new PfModelRuntimeException(Response.Status.NOT_FOUND, "node template " + name + ":" + version
+                + NOT_FOUND);
+        }
+        //Verify if the node template is referenced in the metadata of created policies
+        nodeTemplateService.assertNodeTemplateNotUsedInPolicy(name, version, dbServiceTemplate);
+
+        dbServiceTemplate.getTopologyTemplate().getNodeTemplates().getConceptMap().remove(nodeTemplateKey);
+        toscaServiceTemplateRepository.save(dbServiceTemplate);
+
+        // remove the entry from the tosca node template table
+        nodeTemplateService.deleteNodeTemplate(nodeTemplateKey);
+
+        // prepare the return service template
+        var deletedServiceTemplate = new JpaToscaServiceTemplate();
+        deletedServiceTemplate.setTopologyTemplate(new JpaToscaTopologyTemplate());
+        deletedServiceTemplate.getTopologyTemplate().setNodeTemplates(new JpaToscaNodeTemplates());
+        deletedServiceTemplate.getTopologyTemplate().getNodeTemplates().getConceptMap()
+            .put(nodeTemplateKey, nodeTemplate4Deletion);
+
+        LOGGER.debug("<-deleteToscaNodeTemplate: key={}, serviceTemplate={}", nodeTemplateKey, deletedServiceTemplate);
+        return deletedServiceTemplate.toAuthorative();
+    }
+
+
+    /**
+     * Get tosca node templates.
+     *
+     * @param name the name of the node template to get, set to null to get all node templates
+     * @param version the version of the node template to get, set to null to get all versions
+     * @return the node templates with the specified key
+     * @throws PfModelException on errors getting node templates
+     */
+    public List<ToscaNodeTemplate> fetchToscaNodeTemplates(final String name, final String version)
+        throws PfModelException {
+        LOGGER.debug("->getNodeTemplate: name={}, version={}", name, version);
+        List<ToscaNodeTemplate> nodeTemplates = new ArrayList<>();
+
+        var dbServiceTemplate = getDefaultJpaToscaServiceTemplate();
+        //Return empty if no nodeTemplates present in db
+        if (!ToscaUtils.doNodeTemplatesExist(dbServiceTemplate)) {
+            return nodeTemplates;
+        }
+        var jpaNodeTemplates = new JpaToscaNodeTemplates(dbServiceTemplate.getTopologyTemplate().getNodeTemplates());
+
+        //Filter specific nodeTemplates
+        if (name != null && version != null) {
+            var filterKey = new PfConceptKey(name, version);
+            jpaNodeTemplates.getConceptMap().entrySet().removeIf(entity -> !entity.getKey().equals(filterKey));
+        }
+        jpaNodeTemplates.getConceptMap().forEach((key, value) -> nodeTemplates.add(value.toAuthorative()));
+        LOGGER.debug("<-getNodeTemplateMetadataSet: name={}, version={}, nodeTemplates={}", name, version,
+            nodeTemplates);
+
+        return nodeTemplates;
+    }
+
+
     /**
      * Get Service Template.
+     *
      * @return the Service Template read from the database
+     * @throws PfModelRuntimeException if service template if not found in database.
      */
-    private JpaToscaServiceTemplate getDefaultJpaToscaServiceTemplate() {
-        final var defaultServiceTemplateOpt = toscaServiceTemplateRepository
-            .findById(new PfConceptKey(JpaToscaServiceTemplate.DEFAULT_NAME, JpaToscaServiceTemplate.DEFAULT_VERSION));
+    public JpaToscaServiceTemplate getDefaultJpaToscaServiceTemplate() throws PfModelRuntimeException {
+        final var defaultServiceTemplateOpt = getDefaultJpaToscaServiceTemplateOpt();
         if (defaultServiceTemplateOpt.isEmpty()) {
             throw new PfModelRuntimeException(Response.Status.NOT_FOUND, SERVICE_TEMPLATE_NOT_FOUND_MSG);
         }
         LOGGER.debug("<-getDefaultJpaToscaServiceTemplate: serviceTemplate={}", defaultServiceTemplateOpt.get());
         return defaultServiceTemplateOpt.get();
     }
+
+    /**
+     * Get Service Template Optional object.
+     *
+     * @return the Optional object for Service Template read from the database
+     */
+    private Optional<JpaToscaServiceTemplate> getDefaultJpaToscaServiceTemplateOpt() {
+        return toscaServiceTemplateRepository
+            .findById(new PfConceptKey(JpaToscaServiceTemplate.DEFAULT_NAME, JpaToscaServiceTemplate.DEFAULT_VERSION));
+    }
 }
\ No newline at end of file