From 1a87ab847d70db032edc260096121c7016ee50d7 Mon Sep 17 00:00:00 2001 From: Pamela Dragosh Date: Sun, 8 Sep 2019 17:04:49 -0400 Subject: Add metadata to properties Properties should support metadata - adding it in. Added junit tests for the new metadata field. Issue-ID: POLICY-2060 Change-Id: I2e1933ca4260fe5989f36a098108893a366f657a Signed-off-by: Pamela Dragosh Signed-off-by: Jim Hahn --- .../policytypes/onap.policies.Optimization.yaml | 14 +- .../tosca/authorative/concepts/ToscaProperty.java | 3 + .../tosca/simple/concepts/JpaToscaProperty.java | 23 +++ .../simple/concepts/JpaToscaPropertyTest.java | 60 +++++++ .../OptimizationPolicyTypeSerializationTest.java | 174 +++++++++++++++++++++ 5 files changed, 270 insertions(+), 4 deletions(-) create mode 100644 models-tosca/src/test/java/org/onap/policy/models/tosca/simple/serialization/OptimizationPolicyTypeSerializationTest.java diff --git a/models-examples/src/main/resources/policytypes/onap.policies.Optimization.yaml b/models-examples/src/main/resources/policytypes/onap.policies.Optimization.yaml index 49470ba3b..f88239d73 100644 --- a/models-examples/src/main/resources/policytypes/onap.policies.Optimization.yaml +++ b/models-examples/src/main/resources/policytypes/onap.policies.Optimization.yaml @@ -8,26 +8,32 @@ policy_types: scope: description: Scope for the policy - could be for a specific release. type: list - matchable: true + metadata: + matchable: true required: true + entry_schema: + type: string services: description: One or more services that the policy applies to. type: list - matchable: true + metadata: + matchable: true required: true entry_schema: type: string resources: description: One or more VNF resources that the policy applies to. type: list - matchable: true + metadata: + matchable: true required: true entry_schema: type: string geography: description: One or more geographic regions type: list - matchable: true + metadata: + matchable: true required: true entry_schema: type: string diff --git a/models-tosca/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaProperty.java b/models-tosca/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaProperty.java index 00005f2f8..fd8a86a0d 100644 --- a/models-tosca/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaProperty.java +++ b/models-tosca/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaProperty.java @@ -26,6 +26,7 @@ package org.onap.policy.models.tosca.authorative.concepts; import com.google.gson.annotations.SerializedName; import io.swagger.annotations.ApiModelProperty; import java.util.List; +import java.util.Map; import lombok.Data; /** @@ -60,4 +61,6 @@ public class ToscaProperty { @ApiModelProperty(name = "entry_schema") @SerializedName("entry_schema") private ToscaEntrySchema entrySchema; + + private Map metadata; } diff --git a/models-tosca/src/main/java/org/onap/policy/models/tosca/simple/concepts/JpaToscaProperty.java b/models-tosca/src/main/java/org/onap/policy/models/tosca/simple/concepts/JpaToscaProperty.java index 93da035a5..0e8201f0f 100644 --- a/models-tosca/src/main/java/org/onap/policy/models/tosca/simple/concepts/JpaToscaProperty.java +++ b/models-tosca/src/main/java/org/onap/policy/models/tosca/simple/concepts/JpaToscaProperty.java @@ -24,7 +24,10 @@ package org.onap.policy.models.tosca.simple.concepts; import java.util.ArrayList; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; +import java.util.Map.Entry; import javax.persistence.Column; import javax.persistence.ElementCollection; import javax.persistence.EmbeddedId; @@ -87,6 +90,9 @@ public class JpaToscaProperty extends PfConcept implements PfAuthorative metadata; + /** * The Default Constructor creates a {@link JpaToscaProperty} object with a null key. */ @@ -130,6 +136,7 @@ public class JpaToscaProperty extends PfConcept implements PfAuthorative(copyConcept.constraints) : null); this.entrySchema = (copyConcept.entrySchema != null ? new JpaToscaEntrySchema(copyConcept.entrySchema) : null); + this.metadata = (copyConcept.metadata != null ? new LinkedHashMap<>(copyConcept.metadata) : null); } /** @@ -169,6 +176,10 @@ public class JpaToscaProperty extends PfConcept implements PfAuthorative(metadata)); + } + return toscaProperty; } @@ -199,6 +210,12 @@ public class JpaToscaProperty extends PfConcept implements PfAuthorative(toscaProperty.getMetadata()); + } + } @Override @@ -231,6 +248,12 @@ public class JpaToscaProperty extends PfConcept implements PfAuthorative metadataEntry : metadata.entrySet()) { + metadataEntry.setValue(metadataEntry.getValue().trim()); + } + } } @Override diff --git a/models-tosca/src/test/java/org/onap/policy/models/tosca/simple/concepts/JpaToscaPropertyTest.java b/models-tosca/src/test/java/org/onap/policy/models/tosca/simple/concepts/JpaToscaPropertyTest.java index 2da2090de..18837d45d 100644 --- a/models-tosca/src/test/java/org/onap/policy/models/tosca/simple/concepts/JpaToscaPropertyTest.java +++ b/models-tosca/src/test/java/org/onap/policy/models/tosca/simple/concepts/JpaToscaPropertyTest.java @@ -25,10 +25,12 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import java.util.ArrayList; import java.util.List; +import java.util.TreeMap; import org.junit.Test; import org.onap.policy.models.base.PfConceptKey; import org.onap.policy.models.base.PfReferenceKey; @@ -68,6 +70,8 @@ public class JpaToscaPropertyTest { PfConceptKey ptypeKey = new PfConceptKey("TTypeKey", VERSION_001); JpaToscaProperty tp = new JpaToscaProperty(pkey, ptypeKey); + assertEquals(tp, new JpaToscaProperty(tp)); + tp.setDescription(A_DESCRIPTION); assertEquals(A_DESCRIPTION, tp.getDescription()); @@ -88,10 +92,18 @@ public class JpaToscaPropertyTest { JpaToscaEntrySchema tes = new JpaToscaEntrySchema(typeKey); tp.setEntrySchema(tes); + TreeMap metadata = new TreeMap<>(); + metadata.put("metaA", "dataA"); + metadata.put("metaB", "dataB"); + tp.setMetadata(metadata); + assertSame(metadata, tp.getMetadata()); + JpaToscaProperty tdtClone0 = new JpaToscaProperty(tp); assertEquals(tp, tdtClone0); assertEquals(0, tp.compareTo(tdtClone0)); + assertTrue(tdtClone0.getMetadata() != tp.getMetadata()); + JpaToscaProperty tdtClone1 = new JpaToscaProperty(tp); assertEquals(tp, tdtClone1); assertEquals(0, tp.compareTo(tdtClone1)); @@ -174,6 +186,54 @@ public class JpaToscaPropertyTest { tp.getConstraints().remove(null); assertTrue(tp.validate(new PfValidationResult()).isValid()); + tp.setMetadata(null); + assertTrue(tp.validate(new PfValidationResult()).isValid()); + assertThatThrownBy(() -> tp.validate(null)).hasMessage("resultIn is marked @NonNull but is null"); } + + @Test + public void testToAuthorative_testFromAuthorative() { + // check with empty structure + JpaToscaProperty tp = new JpaToscaProperty(); + ToscaProperty auth = tp.toAuthorative(); + JpaToscaProperty tp2 = new JpaToscaProperty(); + tp2.fromAuthorative(auth); + assertEquals(tp, tp2); + + // populate and try again + PfConceptKey pparentKey = new PfConceptKey("tParentKey", VERSION_001); + PfReferenceKey pkey = new PfReferenceKey(pparentKey, "trigger0"); + PfConceptKey ptypeKey = new PfConceptKey("TTypeKey", VERSION_001); + tp = new JpaToscaProperty(pkey, ptypeKey); + + tp.setDescription(A_DESCRIPTION); + tp.setRequired(true); + tp.setDefaultValue(DEFAULT_KEY); + tp.setStatus(ToscaProperty.Status.SUPPORTED); + + List constraints = new ArrayList<>(); + JpaToscaConstraintLogical lsc = new JpaToscaConstraintLogical(JpaToscaConstraintOperation.EQ, "hello"); + constraints.add(lsc); + tp.setConstraints(constraints); + + PfConceptKey typeKey = new PfConceptKey("type", VERSION_001); + JpaToscaEntrySchema tes = new JpaToscaEntrySchema(typeKey); + tp.setEntrySchema(tes); + + TreeMap metadata = new TreeMap<>(); + metadata.put("metaA", "dataA"); + metadata.put("metaB", "dataB"); + tp.setMetadata(metadata); + + auth = tp.toAuthorative(); + tp2 = new JpaToscaProperty(); + tp2.fromAuthorative(auth); + + // note: parent key info is not copied, so we manually copy it + tp2.getKey().setParentConceptKey(tp.getKey().getParentConceptKey()); + + assertEquals(tp.toString(), tp2.toString()); + assertEquals(tp, tp2); + } } diff --git a/models-tosca/src/test/java/org/onap/policy/models/tosca/simple/serialization/OptimizationPolicyTypeSerializationTest.java b/models-tosca/src/test/java/org/onap/policy/models/tosca/simple/serialization/OptimizationPolicyTypeSerializationTest.java new file mode 100644 index 000000000..9f9906930 --- /dev/null +++ b/models-tosca/src/test/java/org/onap/policy/models/tosca/simple/serialization/OptimizationPolicyTypeSerializationTest.java @@ -0,0 +1,174 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2019 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.onap.policy.models.tosca.simple.serialization; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import java.util.List; +import java.util.Map; +import org.junit.Before; +import org.junit.Test; +import org.onap.policy.common.utils.coder.CoderException; +import org.onap.policy.common.utils.coder.StandardCoder; +import org.onap.policy.common.utils.resources.ResourceUtils; +import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate; +import org.onap.policy.models.tosca.simple.concepts.JpaToscaConstraint; +import org.onap.policy.models.tosca.simple.concepts.JpaToscaConstraintValidValues; +import org.onap.policy.models.tosca.simple.concepts.JpaToscaPolicyType; +import org.onap.policy.models.tosca.simple.concepts.JpaToscaPolicyTypes; +import org.onap.policy.models.tosca.simple.concepts.JpaToscaProperty; +import org.onap.policy.models.tosca.simple.concepts.JpaToscaServiceTemplate; +import org.yaml.snakeyaml.Yaml; + +public class OptimizationPolicyTypeSerializationTest { + + private static final String TYPE_ROOT = "tosca.policies.Root"; + private static final String VERSION = "1.0.0"; + + private static final String INPUT_YAML = "policytypes/onap.policies.Optimization.yaml"; + + private StandardCoder coder; + + @Before + public void setUp() { + coder = new StandardCoder(); + } + + @Test + public void test() throws CoderException { + JpaToscaServiceTemplate svctmpl = loadYaml(INPUT_YAML); + validate("initial object", svctmpl); + + String ser = serialize(svctmpl); + JpaToscaServiceTemplate svctmpl2 = deserialize(ser); + validate("copy", svctmpl2); + + assertEquals(svctmpl, svctmpl2); + } + + private JpaToscaServiceTemplate loadYaml(String yamlFileName) throws CoderException { + Yaml yaml = new Yaml(); + String policyTypeYaml = ResourceUtils.getResourceAsString(yamlFileName); + Object yamlObject = yaml.load(policyTypeYaml); + String yamlAsJsonString = coder.encode(yamlObject); + return deserialize(yamlAsJsonString); + } + + private JpaToscaServiceTemplate deserialize(String json) throws CoderException { + ToscaServiceTemplate auth = coder.decode(json, ToscaServiceTemplate.class); + + JpaToscaServiceTemplate svctmpl = new JpaToscaServiceTemplate(); + svctmpl.fromAuthorative(auth); + return svctmpl; + } + + private String serialize(JpaToscaServiceTemplate svctmpl) throws CoderException { + ToscaServiceTemplate auth = svctmpl.toAuthorative(); + return coder.encode(auth); + } + + private void validate(String testnm, JpaToscaServiceTemplate svctmpl) { + JpaToscaPolicyTypes policyTypes = svctmpl.getPolicyTypes(); + + assertEquals(testnm + " type count", 1, policyTypes.getConceptMap().size()); + JpaToscaPolicyType policyType = policyTypes.getConceptMap().values().iterator().next(); + + assertEquals(testnm + " name", "onap.policies.Optimization", policyType.getName()); + assertEquals(testnm + " version", VERSION, policyType.getVersion()); + + assertNotNull(testnm + " derived from", policyType.getDerivedFrom()); + assertEquals(testnm + " derived from name", TYPE_ROOT, policyType.getDerivedFrom().getName()); + + assertEquals(testnm + " description", "The base policy type for all policies that govern optimization", + policyType.getDescription()); + + Map props = policyType.getProperties(); + assertNotNull(testnm + " properties", props); + + validateScope(testnm, props.get("scope")); + validateServices(testnm, props.get("services")); + validateResources(testnm, props.get("resources")); + validateGeography(testnm, props.get("geography")); + validateIdentity(testnm, props.get("identity")); + } + + // only need to validate deep match of one of these; geography is the most interesting + + private void validateScope(String testName, JpaToscaProperty prop) { + String testnm = testName + " scope"; + + assertNotNull(testnm, prop); + validateMatchable(testnm, prop.getMetadata()); + } + + private void validateServices(String testName, JpaToscaProperty prop) { + String testnm = testName + " services"; + + assertNotNull(testnm, prop); + validateMatchable(testnm, prop.getMetadata()); + } + + private void validateResources(String testName, JpaToscaProperty prop) { + String testnm = testName + " resources"; + + assertNotNull(testnm, prop); + validateMatchable(testnm, prop.getMetadata()); + } + + private void validateGeography(String testName, JpaToscaProperty prop) { + String testnm = testName + " geography"; + + assertNotNull(testnm, prop); + + // this line results in a stack overflow + // assertEquals(testnm + " name", "geography", prop.getName()); + + assertEquals(testnm + " description", "One or more geographic regions", prop.getDescription()); + assertEquals(testnm + " type", "list", prop.getType().getName()); + validateMatchable(testnm, prop.getMetadata()); + assertTrue(testnm + " required", prop.isRequired()); + assertEquals(testnm + " entry_schema", "string", prop.getEntrySchema().getType().getName()); + + List constraints = prop.getEntrySchema().getConstraints(); + assertNotNull(testnm + " constraints", constraints); + + assertEquals(testnm + " constraint size", 1, constraints.size()); + assertTrue(testnm + " constraint type", constraints.get(0) instanceof JpaToscaConstraintValidValues); + JpaToscaConstraintValidValues constraint = (JpaToscaConstraintValidValues) constraints.get(0); + + assertEquals(testnm + " valid values", "[US, International]", constraint.getValidValues().toString()); + } + + private void validateIdentity(String testName, JpaToscaProperty prop) { + String testnm = testName + " identity"; + + assertNotNull(testnm, prop); + assertNull(testnm + " metadata", prop.getMetadata()); + } + + private void validateMatchable(String testName, Map metadata) { + String testnm = testName + " matchable"; + + assertNotNull(testnm + " metadata", metadata); + assertEquals(testnm + " value", "true", metadata.get("matchable")); + } +} -- cgit 1.2.3-korg