summaryrefslogtreecommitdiffstats
path: root/models-base/src/main
diff options
context:
space:
mode:
authorliamfallon <liam.fallon@est.tech>2019-02-26 13:57:39 +0000
committerliamfallon <liam.fallon@est.tech>2019-02-28 10:32:01 +0000
commitf240fda5e8f7e940d6033b204c2dac48a9dc7c4e (patch)
tree98f16f96a2ef8ced0895ae1aaa09c021a96f15f0 /models-base/src/main
parent9ddbc872354eb5399bab9d9c23188b4be98d7dd7 (diff)
Add basic model object concepts
This review introduces the basic concepts that all model objects inherit from. Using this approach, all concepts that inherit from these types can use standardized DAO handling and marrshal/unmarshal handling This approach is a more generic version of the approach used in the APEX PDP for model handling. The APEX model handling will inherit this module. Issue-ID: POLICY-1264 Change-Id: I35b76659ab66cf3f33bee59a5528e49c7edf7796 Signed-off-by: liamfallon <liam.fallon@est.tech>
Diffstat (limited to 'models-base/src/main')
-rw-r--r--models-base/src/main/java/org/onap/policy/models/base/PfConcept.java139
-rw-r--r--models-base/src/main/java/org/onap/policy/models/base/PfConceptKey.java317
-rw-r--r--models-base/src/main/java/org/onap/policy/models/base/PfKey.java105
-rw-r--r--models-base/src/main/java/org/onap/policy/models/base/PfModelException.java109
-rw-r--r--models-base/src/main/java/org/onap/policy/models/base/PfModelRuntimeException.java92
-rw-r--r--models-base/src/main/java/org/onap/policy/models/base/PfValidationMessage.java103
-rw-r--r--models-base/src/main/java/org/onap/policy/models/base/PfValidationResult.java151
-rw-r--r--models-base/src/main/java/org/onap/policy/models/base/package-info.java25
8 files changed, 1041 insertions, 0 deletions
diff --git a/models-base/src/main/java/org/onap/policy/models/base/PfConcept.java b/models-base/src/main/java/org/onap/policy/models/base/PfConcept.java
new file mode 100644
index 000000000..99eee8d7f
--- /dev/null
+++ b/models-base/src/main/java/org/onap/policy/models/base/PfConcept.java
@@ -0,0 +1,139 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.base;
+
+import java.io.Serializable;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlType;
+
+import org.onap.policy.common.utils.validation.Assertions;
+
+/**
+ * This class is the base class for all model concept classes. It enforces implementation of
+ * abstract methods and interfaces on all concepts that are sub-classes of this class.
+ */
+
+@XmlType(name = "PfConcept", namespace = "http://www.onap.org/policy/models")
+
+public abstract class PfConcept implements Serializable, Comparable<PfConcept> {
+ private static final long serialVersionUID = -7434939557282697490L;
+
+ /**
+ * Default constructor.
+ */
+ public PfConcept() {}
+
+ /**
+ * Copy constructor.
+ *
+ * @param copyConcept the concept to copy from
+ */
+ public PfConcept(final PfConcept copyConcept) {
+ Assertions.argumentNotNull(copyConcept, "copy concept may not be null");
+ copyConcept.copyTo(this);
+ }
+
+ /**
+ * Gets the key of this concept.
+ *
+ * @return the concept key
+ */
+ public abstract PfKey getKey();
+
+ /**
+ * Gets a list of all keys for this concept and all concepts that are defined or referenced by
+ * this concept and its sub-concepts.
+ *
+ * @return the keys used by this concept and it's contained concepts
+ */
+ public abstract List<PfKey> getKeys();
+
+ /**
+ * Validate that this concept is structurally correct.
+ *
+ * @param result the parameter in which the result of the validation will be returned
+ * @return the validation result that was passed in in the @{link result} field with the result
+ * of this validation added
+ */
+ public abstract PfValidationResult validate(PfValidationResult result);
+
+ /**
+ * Clean this concept, tidy up any superfluous information such as leading and trailing white
+ * space.
+ */
+ public abstract void clean();
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public abstract boolean equals(Object otherObject);
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public abstract String toString();
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public abstract int hashCode();
+
+ /**
+ * Copy this concept to another object. The target object must have the same class as the source
+ * object.
+ *
+ * @param target the target object to which this object is copied
+ * @return the copied object
+ */
+ public abstract PfConcept copyTo(PfConcept target);
+
+ /**
+ * Gets the ID string of this concept.
+ *
+ * @return the ID string of this concept
+ */
+ public String getId() {
+ return getKey().getId();
+ }
+
+ /**
+ * Checks if this key matches the given key ID.
+ *
+ * @param id the key ID to match against
+ * @return true, if this key matches the ID
+ */
+ public final boolean matchesId(final String id) {
+ Assertions.argumentNotNull(id, "id may not be null");
+
+ // Check the ID
+ return getId().equals(id);
+ }
+}
diff --git a/models-base/src/main/java/org/onap/policy/models/base/PfConceptKey.java b/models-base/src/main/java/org/onap/policy/models/base/PfConceptKey.java
new file mode 100644
index 000000000..6ebb8886a
--- /dev/null
+++ b/models-base/src/main/java/org/onap/policy/models/base/PfConceptKey.java
@@ -0,0 +1,317 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.base;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.Column;
+import javax.persistence.Embeddable;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+import org.onap.policy.common.utils.validation.Assertions;
+import org.onap.policy.models.base.PfValidationResult.ValidationResult;
+
+/**
+ * An artifact key uniquely identifies every first order entity in the system. Every first order
+ * concept in the system must have an {@link PfConceptKey} to identify it. Concepts that are wholly
+ * contained in another concept are identified using a {@link AxReferenceKey} key.
+ *
+ * <p>Key validation checks that the name and version fields match the NAME_REGEXP and VERSION_REGEXP
+ * regular expressions respectively.
+ */
+@Embeddable
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlRootElement(name = "pfConceptKey", namespace = "http://www.onap.org/policy/models")
+
+@XmlType(name = "PfConceptKey", namespace = "http://www.onap.org/policy/models", propOrder = {"name", "version"})
+
+public class PfConceptKey extends PfKey {
+ private static final long serialVersionUID = 8932717618579392561L;
+
+ private static final String NAME_TOKEN = "name";
+ private static final String VERSION_TOKEN = "version";
+
+ @Column(name = NAME_TOKEN)
+ @XmlElement(required = true)
+ private String name;
+
+ @Column(name = VERSION_TOKEN)
+ @XmlElement(required = true)
+ private String version;
+
+ /**
+ * The default constructor creates a null artifact key.
+ */
+ public PfConceptKey() {
+ this(NULL_KEY_NAME, NULL_KEY_VERSION);
+ }
+
+ /**
+ * Copy constructor.
+ *
+ * @param copyConcept the concept to copy from
+ */
+ public PfConceptKey(final PfConceptKey copyConcept) {
+ super(copyConcept);
+ }
+
+ /**
+ * Constructor to create a key with the specified name and version.
+ *
+ * @param name the key name
+ * @param version the key version
+ */
+ public PfConceptKey(final String name, final String version) {
+ super();
+ this.name = Assertions.validateStringParameter(NAME_TOKEN, name, NAME_REGEXP);
+ this.version = Assertions.validateStringParameter(VERSION_TOKEN, version, VERSION_REGEXP);
+ }
+
+ /**
+ * Constructor to create a key using the key and version from the specified key ID.
+ *
+ * @param id the key ID in a format that respects the KEY_ID_REGEXP
+ */
+ public PfConceptKey(final String id) {
+ Assertions.argumentNotNull(id, "id may not be null");
+
+ // Check the incoming ID is valid
+ Assertions.validateStringParameter("id", id, KEY_ID_REGEXP);
+
+ // Split on colon, if the id passes the regular expression test above
+ // it'll have just one colon separating the name and version
+ // No need for range checks or size checks on the array
+ final String[] nameVersionArray = id.split(":");
+
+ // Return the new key
+ name = Assertions.validateStringParameter(NAME_TOKEN, nameVersionArray[0], NAME_REGEXP);
+ version = Assertions.validateStringParameter(VERSION_TOKEN, nameVersionArray[1], VERSION_REGEXP);
+ }
+
+ /**
+ * Get a null artifact key.
+ *
+ * @return a null artifact key
+ */
+ public static final PfConceptKey getNullKey() {
+ return new PfConceptKey(PfKey.NULL_KEY_NAME, PfKey.NULL_KEY_VERSION);
+ }
+
+ @Override
+ public PfConceptKey getKey() {
+ return this;
+ }
+
+ @Override
+ public List<PfKey> getKeys() {
+ final List<PfKey> keyList = new ArrayList<>();
+ keyList.add(getKey());
+ return keyList;
+ }
+
+ @Override
+ public String getId() {
+ return name + ':' + version;
+ }
+
+ /**
+ * Gets the key name.
+ *
+ * @return the key name
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Sets the key name.
+ *
+ * @param name the key name
+ */
+ public void setName(final String name) {
+ this.name = Assertions.validateStringParameter(NAME_TOKEN, name, NAME_REGEXP);
+ }
+
+ /**
+ * Gets the key version.
+ *
+ * @return the key version
+ */
+ public String getVersion() {
+ return version;
+ }
+
+ /**
+ * Sets the key version.
+ *
+ * @param version the key version
+ */
+ public void setVersion(final String version) {
+ this.version = Assertions.validateStringParameter(VERSION_TOKEN, version, VERSION_REGEXP);
+ }
+
+ @Override
+ public PfKey.Compatibility getCompatibility(final PfKey otherKey) {
+ if (!(otherKey instanceof PfConceptKey)) {
+ return Compatibility.DIFFERENT;
+ }
+ final PfConceptKey otherArtifactKey = (PfConceptKey) otherKey;
+
+ if (this.equals(otherArtifactKey)) {
+ return Compatibility.IDENTICAL;
+ }
+ if (!this.getName().equals(otherArtifactKey.getName())) {
+ return Compatibility.DIFFERENT;
+ }
+
+ final String[] thisVersionArray = getVersion().split("\\.");
+ final String[] otherVersionArray = otherArtifactKey.getVersion().split("\\.");
+
+ // There must always be at least one element in each version
+ if (!thisVersionArray[0].equals(otherVersionArray[0])) {
+ return Compatibility.MAJOR;
+ }
+
+ if (thisVersionArray.length >= 2 && otherVersionArray.length >= 2
+ && !thisVersionArray[1].equals(otherVersionArray[1])) {
+ return Compatibility.MINOR;
+ }
+
+ return Compatibility.PATCH;
+ }
+
+ @Override
+ public boolean isCompatible(final PfKey otherKey) {
+ if (!(otherKey instanceof PfConceptKey)) {
+ return false;
+ }
+ final PfConceptKey otherArtifactKey = (PfConceptKey) otherKey;
+
+ final Compatibility compatibility = this.getCompatibility(otherArtifactKey);
+
+ return !(compatibility == Compatibility.DIFFERENT || compatibility == Compatibility.MAJOR);
+ }
+
+ @Override
+ public PfValidationResult validate(final PfValidationResult result) {
+ final String nameValidationErrorMessage =
+ Assertions.getStringParameterValidationMessage(NAME_TOKEN, name, NAME_REGEXP);
+ if (nameValidationErrorMessage != null) {
+ result.addValidationMessage(new PfValidationMessage(this, this.getClass(), ValidationResult.INVALID,
+ "name invalid-" + nameValidationErrorMessage));
+ }
+
+ final String versionValidationErrorMessage =
+ Assertions.getStringParameterValidationMessage(VERSION_TOKEN, version, VERSION_REGEXP);
+ if (versionValidationErrorMessage != null) {
+ result.addValidationMessage(new PfValidationMessage(this, this.getClass(), ValidationResult.INVALID,
+ "version invalid-" + versionValidationErrorMessage));
+ }
+
+ return result;
+ }
+
+ @Override
+ public void clean() {
+ name = Assertions.validateStringParameter(NAME_TOKEN, name, NAME_REGEXP);
+ version = Assertions.validateStringParameter(VERSION_TOKEN, version, VERSION_REGEXP);
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append(this.getClass().getSimpleName());
+ builder.append(":(");
+ builder.append("name=");
+ builder.append(name);
+ builder.append(",version=");
+ builder.append(version);
+ builder.append(")");
+ return builder.toString();
+ }
+
+ @Override
+ public PfConcept copyTo(final PfConcept target) {
+ Assertions.argumentNotNull(target, "target may not be null");
+
+ final PfConcept copyObject = target;
+ Assertions.instanceOf(copyObject, PfConceptKey.class);
+
+ final PfConceptKey copy = ((PfConceptKey) copyObject);
+ copy.setName(name);
+ copy.setVersion(version);
+
+ return copyObject;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + name.hashCode();
+ result = prime * result + version.hashCode();
+ return result;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (this == obj) {
+ return true;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+
+ final PfConceptKey other = (PfConceptKey) obj;
+
+ if (!name.equals(other.name)) {
+ return false;
+ }
+ return version.equals(other.version);
+ }
+
+ @Override
+ public int compareTo(final PfConcept otherObj) {
+ Assertions.argumentNotNull(otherObj, "comparison object may not be null");
+
+ if (this == otherObj) {
+ return 0;
+ }
+ if (getClass() != otherObj.getClass()) {
+ return this.hashCode() - otherObj.hashCode();
+ }
+
+ final PfConceptKey other = (PfConceptKey) otherObj;
+
+ if (!name.equals(other.name)) {
+ return name.compareTo(other.name);
+ }
+ return version.compareTo(other.version);
+ }
+}
diff --git a/models-base/src/main/java/org/onap/policy/models/base/PfKey.java b/models-base/src/main/java/org/onap/policy/models/base/PfKey.java
new file mode 100644
index 000000000..16e70a2c0
--- /dev/null
+++ b/models-base/src/main/java/org/onap/policy/models/base/PfKey.java
@@ -0,0 +1,105 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.base;
+
+/**
+ * The key uniquely identifies every entity in the system. This class is an abstract class to give a
+ * common parent for all key types in the system.
+ */
+public abstract class PfKey extends PfConcept {
+ private static final long serialVersionUID = 6281159885962014041L;
+
+ /** Regular expression to specify the structure of key names. */
+ public static final String NAME_REGEXP = "[A-Za-z0-9\\-_\\.]+";
+
+ /** Regular expression to specify the structure of key versions. */
+ public static final String VERSION_REGEXP = "[A-Za-z0-9.]+";
+
+ /** Regular expression to specify the structure of key IDs. */
+ public static final String KEY_ID_REGEXP = "[A-Za-z0-9\\-_\\.]+:[0-9].[0-9].[0-9]";
+
+ /** Specifies the value for names in NULL keys. */
+ public static final String NULL_KEY_NAME = "NULL";
+
+ /** Specifies the value for versions in NULL keys. */
+ public static final String NULL_KEY_VERSION = "0.0.0";
+
+ /**
+ * This enumeration is returned on key compatibility checks.
+ */
+ public enum Compatibility {
+ /** The keys have different names. */
+ DIFFERENT,
+ /**
+ * The name of the key matches but the Major version number of the keys is different (x in
+ * x.y.z do not match).
+ */
+ MAJOR,
+ /**
+ * The name of the key matches but the Minor version number of the keys is different (y in
+ * x.y.z do not match).
+ */
+ MINOR,
+ /**
+ * The name of the key matches but the Patch version number of the keys is different (z in
+ * x.y.z do not match).
+ */
+ PATCH,
+ /** The keys match completely. */
+ IDENTICAL
+ }
+
+ /**
+ * Default constructor.
+ */
+ public PfKey() {
+ super();
+ }
+
+ /**
+ * Copy constructor.
+ *
+ * @param copyConcept the concept to copy from
+ */
+ public PfKey(final PfKey copyConcept) {
+ super(copyConcept);
+ }
+
+ @Override
+ public abstract String getId();
+
+ /**
+ * Return the result of a compatibility check of two keys.
+ *
+ * @param otherKey the key to check compatibility against
+ * @return the compatibility result of the check
+ */
+ public abstract Compatibility getCompatibility(PfKey otherKey);
+
+ /**
+ * Check if two keys are compatible, that is the keys are IDENTICAL or have only MINOR, PATCH
+ * differences.
+ *
+ * @param otherKey the key to check compatibility against
+ * @return true, if the keys are compatible
+ */
+ public abstract boolean isCompatible(PfKey otherKey);
+}
diff --git a/models-base/src/main/java/org/onap/policy/models/base/PfModelException.java b/models-base/src/main/java/org/onap/policy/models/base/PfModelException.java
new file mode 100644
index 000000000..3d1bb1794
--- /dev/null
+++ b/models-base/src/main/java/org/onap/policy/models/base/PfModelException.java
@@ -0,0 +1,109 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.base;
+
+/**
+ * This class is a base exception from which all model exceptions are sub classes.
+ */
+public class PfModelException extends Exception {
+ private static final long serialVersionUID = -8507246953751956974L;
+
+ // The object on which the exception was thrown
+ private final transient Object object;
+
+ /**
+ * Instantiates a new model exception.
+ *
+ * @param message the message on the exception
+ */
+ public PfModelException(final String message) {
+ this(message, null);
+ }
+
+ /**
+ * Instantiates a new model exception.
+ *
+ * @param message the message on the exception
+ * @param object the object that the exception was thrown on
+ */
+ public PfModelException(final String message, final Object object) {
+ super(message);
+ this.object = object;
+ }
+
+ /**
+ * Instantiates a new model exception.
+ *
+ * @param message the message on the exception
+ * @param exception the exception that caused this exception
+ */
+ public PfModelException(final String message, final Exception exception) {
+ this(message, exception, null);
+ }
+
+ /**
+ * Instantiates a new exception.
+ *
+ * @param message the message on the exception
+ * @param exception the exception that caused this exception
+ * @param object the object that the exception was thrown on
+ */
+ public PfModelException(final String message, final Exception exception, final Object object) {
+ super(message, exception);
+ this.object = object;
+ }
+
+ /**
+ * Get the message from this exception and its causes.
+ *
+ * @return the cascaded messages from this exception and the exceptions that caused it
+ */
+ public String getCascadedMessage() {
+ return buildCascadedMessage(this);
+ }
+
+ /**
+ * Build a cascaded message from an exception and all its nested exceptions.
+ *
+ * @param throwable the top level exception
+ * @return cascaded message string
+ */
+ public static String buildCascadedMessage(Throwable throwable) {
+ final StringBuilder builder = new StringBuilder();
+ builder.append(throwable.getMessage());
+
+ for (Throwable t = throwable; t != null; t = t.getCause()) {
+ builder.append("\ncaused by: ");
+ builder.append(t.getMessage());
+ }
+
+ return builder.toString();
+ }
+
+ /**
+ * Get the object on which the exception was thrown.
+ *
+ * @return The object on which the exception was thrown
+ */
+ public Object getObject() {
+ return object;
+ }
+}
diff --git a/models-base/src/main/java/org/onap/policy/models/base/PfModelRuntimeException.java b/models-base/src/main/java/org/onap/policy/models/base/PfModelRuntimeException.java
new file mode 100644
index 000000000..0780a9e20
--- /dev/null
+++ b/models-base/src/main/java/org/onap/policy/models/base/PfModelRuntimeException.java
@@ -0,0 +1,92 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.base;
+
+/**
+ * This class is a base model run time exception from which all model run time exceptions are sub
+ * classes.
+ */
+public class PfModelRuntimeException extends RuntimeException {
+ private static final long serialVersionUID = -8507246953751956974L;
+
+ // The object on which the exception was thrown
+ private final transient Object object;
+
+ /**
+ * Instantiates a new model runtime exception.
+ *
+ * @param message the message on the exception
+ */
+ public PfModelRuntimeException(final String message) {
+ this(message, null);
+ }
+
+ /**
+ * Instantiates a new model runtime exception.
+ *
+ * @param message the message on the exception
+ * @param object the object that the exception was thrown on
+ */
+ public PfModelRuntimeException(final String message, final Object object) {
+ super(message);
+ this.object = object;
+ }
+
+ /**
+ * Instantiates a new model runtime exception.
+ *
+ * @param message the message on the exception
+ * @param exception the exception that caused this model exception
+ */
+ public PfModelRuntimeException(final String message, final Exception exception) {
+ this(message, exception, null);
+ }
+
+ /**
+ * Instantiates a new model runtime exception.
+ *
+ * @param message the message on the exception
+ * @param exception the exception that caused this model exception
+ * @param object the object that the exception was thrown on
+ */
+ public PfModelRuntimeException(final String message, final Exception exception, final Object object) {
+ super(message, exception);
+ this.object = object;
+ }
+
+ /**
+ * Get the message from this exception and its causes.
+ *
+ * @return the message of this exception and all the exceptions that caused this exception
+ */
+ public String getCascadedMessage() {
+ return PfModelException.buildCascadedMessage(this);
+ }
+
+ /**
+ * Get the object on which the exception was thrown.
+ *
+ * @return The object
+ */
+ public Object getObject() {
+ return object;
+ }
+}
diff --git a/models-base/src/main/java/org/onap/policy/models/base/PfValidationMessage.java b/models-base/src/main/java/org/onap/policy/models/base/PfValidationMessage.java
new file mode 100644
index 000000000..708bfddfb
--- /dev/null
+++ b/models-base/src/main/java/org/onap/policy/models/base/PfValidationMessage.java
@@ -0,0 +1,103 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.base;
+
+import org.onap.policy.common.utils.validation.Assertions;
+import org.onap.policy.models.base.PfValidationResult.ValidationResult;
+
+/**
+ * A validation message is created for each validation observation observed during validation of a
+ * concept. The message holds the key and the class of the concept on which the observation was made
+ * as well as the type of observation and a message describing the observation.
+ */
+public class PfValidationMessage {
+ private final PfKey observedKey;
+ private ValidationResult validationResult = ValidationResult.VALID;
+ private final String observedClass;
+ private final String message;
+
+ /**
+ * Create an validation observation with the given fields.
+ *
+ * @param observedKey the key of the class on which the validation observation was made
+ * @param observedClass the class on which the validation observation was made
+ * @param validationResult the type of observation made
+ * @param message a message describing the observation
+ */
+ public PfValidationMessage(final PfKey observedKey, final Class<?> observedClass,
+ final ValidationResult validationResult, final String message) {
+ Assertions.argumentNotNull(observedKey, "observedKey may not be null");
+ Assertions.argumentNotNull(observedClass, "observedClass may not be null");
+ Assertions.argumentNotNull(validationResult, "validationResult may not be null");
+ Assertions.argumentNotNull(message, "message may not be null");
+
+ this.observedKey = observedKey;
+ this.observedClass = observedClass.getCanonicalName();
+ this.validationResult = validationResult;
+ this.message = message;
+ }
+
+ /**
+ * Gets the key of the observation.
+ *
+ * @return the key of the observation
+ */
+ public PfKey getObservedKey() {
+ return observedKey;
+ }
+
+ /**
+ * Gets the observed class.
+ *
+ * @return the observed class
+ */
+ public String getObservedClass() {
+ return observedClass;
+ }
+
+ /**
+ * Gets the type of observation made.
+ *
+ * @return the type of observation made
+ */
+ public ValidationResult getValidationResult() {
+ return validationResult;
+ }
+
+ /**
+ * Get a description of the observation.
+ *
+ * @return the observation description
+ */
+ public String getMessage() {
+ return message;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ return observedKey.toString() + ':' + observedClass + ':' + validationResult.name() + ':' + message;
+ }
+}
diff --git a/models-base/src/main/java/org/onap/policy/models/base/PfValidationResult.java b/models-base/src/main/java/org/onap/policy/models/base/PfValidationResult.java
new file mode 100644
index 000000000..284c11ac2
--- /dev/null
+++ b/models-base/src/main/java/org/onap/policy/models/base/PfValidationResult.java
@@ -0,0 +1,151 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.base;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * This class records the result of a validation and holds all validatino observation messages.
+ */
+public class PfValidationResult {
+ /**
+ * The ValidationResult enumeration describes the severity of a validation result.
+ */
+ public enum ValidationResult {
+ /** No problems or observations were detected during validation. */
+ VALID,
+ /**
+ * Observations were made on a concept (such as blank descriptions) of a nature that will not
+ * affect the use of the concept.
+ */
+ OBSERVATION,
+ /**
+ * Warnings were made on a concept (such as defined but unused concepts) of a nature that may
+ * affect the use of the concept.
+ */
+ WARNING,
+ /**
+ * Errors were detected on a concept (such as referenced but undefined concepts) of a nature
+ * that will affect the use of the concept.
+ */
+ INVALID
+ }
+
+ // The actual verification result
+ private ValidationResult validationResult = ValidationResult.VALID;
+
+ // Messages collected during the verification process
+ private final List<PfValidationMessage> messageList = new LinkedList<>();
+
+ /**
+ * Check if a validation reported a valid concept, returns true if the model is usable (that is,
+ * even if the model has warnings or observations).
+ *
+ * @return true, if the concept is reported as valid and can be used
+ */
+ public boolean isValid() {
+ return validationResult != ValidationResult.INVALID;
+ }
+
+ /**
+ * Check if a validation reported a concept with no errors or warnings, returns true if the
+ * model is OK to use.
+ *
+ * @return true, if the concept has no warnings or errors
+ */
+ public boolean isOk() {
+ return validationResult == ValidationResult.VALID || validationResult == ValidationResult.OBSERVATION;
+ }
+
+ /**
+ * Gets the validation result.
+ *
+ * @return the validation result on a concept
+ */
+ public ValidationResult getValidationResult() {
+ return validationResult;
+ }
+
+ /**
+ * Gets the list of validation results on the concept.
+ *
+ * @return the list of validaiton results
+ */
+ public List<PfValidationMessage> getMessageList() {
+ return messageList;
+ }
+
+ /**
+ * Adds a validation message to the validation result, used by validate() implementations on
+ * {@link PfConcept} subclasses to report validaiton observations.
+ *
+ * @param validationMessage the validation message
+ */
+ public void addValidationMessage(final PfValidationMessage validationMessage) {
+ messageList.add(validationMessage);
+
+ // Check if the incoming message has a more sever status than the
+ // current one on the overall validation result,
+ // if so, the overall result goes to that level
+ if (validationMessage.getValidationResult().ordinal() > validationResult.ordinal()) {
+ validationResult = validationMessage.getValidationResult();
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+
+ switch (validationResult) {
+ case VALID:
+
+ builder.append("***validation of model successful***");
+ return builder.toString();
+ case OBSERVATION:
+
+ builder.append("\n***observations noted during validation of model***\n");
+ break;
+ case WARNING:
+
+ builder.append("\n***warnings issued during validation of model***\n");
+ break;
+ case INVALID:
+ builder.append("\n***validation of model failed***\n");
+ break;
+ default:
+ break;
+ }
+
+ for (final PfValidationMessage message : messageList) {
+ builder.append(message);
+ builder.append("\n");
+ }
+
+ builder.append("********************************");
+ return builder.toString();
+ }
+}
diff --git a/models-base/src/main/java/org/onap/policy/models/base/package-info.java b/models-base/src/main/java/org/onap/policy/models/base/package-info.java
new file mode 100644
index 000000000..a71dce6ff
--- /dev/null
+++ b/models-base/src/main/java/org/onap/policy/models/base/package-info.java
@@ -0,0 +1,25 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+/**
+ * Defines and implements the basic concepts for all models in the Policy Framework.
+ */
+
+package org.onap.policy.models.base;