diff options
Diffstat (limited to 'models-base')
14 files changed, 1571 insertions, 0 deletions
diff --git a/models-base/pom.xml b/models-base/pom.xml new file mode 100644 index 000000000..d2f8d87d4 --- /dev/null +++ b/models-base/pom.xml @@ -0,0 +1,45 @@ +<!-- + ============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========================================================= +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.onap.policy.models</groupId> + <artifactId>policy-models</artifactId> + <version>2.0.0-SNAPSHOT</version> + </parent> + + <artifactId>policy-models-base</artifactId> + <name>${project.artifactId}</name> + <description>[${project.parent.artifactId}] module provides basic model handling for the ONAP Policy Framework</description> + + <dependencies> + <dependency> + <groupId>org.onap.policy.common</groupId> + <artifactId>utils</artifactId> + </dependency> + + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + </dependency> + </dependencies> +</project> 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; diff --git a/models-base/src/test/java/org/onap/policy/models/base/ExceptionsTest.java b/models-base/src/test/java/org/onap/policy/models/base/ExceptionsTest.java new file mode 100644 index 000000000..92e928e2e --- /dev/null +++ b/models-base/src/test/java/org/onap/policy/models/base/ExceptionsTest.java @@ -0,0 +1,56 @@ +/* + * ============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 static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.io.IOException; + +import org.junit.Test; + +public class ExceptionsTest { + + @Test + public void test() { + assertNotNull(new PfModelException("Message")); + assertNotNull(new PfModelException("Message", "String")); + assertNotNull(new PfModelException("Message", new IOException())); + assertNotNull(new PfModelException("Message", new IOException(), "String")); + + String key = "A String"; + PfModelException ae = new PfModelException("Message", new IOException("IO exception message"), key); + assertEquals("Message\ncaused by: Message\ncaused by: IO exception message", ae.getCascadedMessage()); + assertEquals(key, ae.getObject()); + + assertNotNull(new PfModelRuntimeException("Message")); + assertNotNull(new PfModelRuntimeException("Message", "String")); + assertNotNull(new PfModelRuntimeException("Message", new IOException())); + assertNotNull(new PfModelRuntimeException("Message", new IOException(), "String")); + + String rkey = "A String"; + PfModelRuntimeException re = new PfModelRuntimeException("Runtime Message", + new IOException("IO runtime exception message"), rkey); + assertEquals("Runtime Message\ncaused by: Runtime Message\ncaused by: IO runtime exception message", + re.getCascadedMessage()); + assertEquals(key, re.getObject()); + } +} diff --git a/models-base/src/test/java/org/onap/policy/models/base/PfKeyTest.java b/models-base/src/test/java/org/onap/policy/models/base/PfKeyTest.java new file mode 100644 index 000000000..dd28f33ba --- /dev/null +++ b/models-base/src/test/java/org/onap/policy/models/base/PfKeyTest.java @@ -0,0 +1,172 @@ +/* + * ============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 static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.lang.reflect.Field; + +import org.junit.Test; + +import org.onap.policy.models.base.PfKey.Compatibility; +import org.onap.policy.models.base.testpojos.DummyPfConcept; +import org.onap.policy.models.base.testpojos.DummyPfKey; + +public class PfKeyTest { + + @Test + public void testArtifactKey() { + try { + new PfConceptKey("some bad key id"); + fail("This test should throw an exception"); + } catch (IllegalArgumentException e) { + assertEquals("parameter \"id\": value \"some bad key id\", " + + "does not match regular expression \"[A-Za-z0-9\\-_\\.]+:[0-9].[0-9].[0-9]\"", + e.getMessage()); + } + + PfConceptKey someKey0 = new PfConceptKey(); + assertEquals(PfConceptKey.getNullKey(), someKey0); + + PfConceptKey someKey1 = new PfConceptKey("name", "0.0.1"); + PfConceptKey someKey2 = new PfConceptKey(someKey1); + PfConceptKey someKey3 = new PfConceptKey(someKey1.getId()); + assertEquals(someKey1, someKey2); + assertEquals(someKey1, someKey3); + + assertEquals(someKey2, someKey1.getKey()); + assertEquals(1, someKey1.getKeys().size()); + + someKey0.setName("zero"); + someKey0.setVersion("0.0.2"); + + someKey3.setVersion("0.0.2"); + + PfConceptKey someKey4 = new PfConceptKey(someKey1); + someKey4.setVersion("0.1.2"); + + PfConceptKey someKey5 = new PfConceptKey(someKey1); + someKey5.setVersion("1.2.2"); + + PfConceptKey someKey6 = new PfConceptKey(someKey1); + someKey6.setVersion("3"); + + assertEquals("name:0.1.2", someKey4.getId()); + + PfConcept pfc = new DummyPfConcept(); + assertEquals(PfConceptKey.getNullKey().getId(), pfc.getId()); + assertTrue(PfConceptKey.getNullKey().matchesId(pfc.getId())); + + assertEquals(Compatibility.DIFFERENT, someKey0.getCompatibility(new DummyPfKey())); + assertEquals(Compatibility.DIFFERENT, someKey0.getCompatibility(someKey1)); + assertEquals(Compatibility.IDENTICAL, someKey2.getCompatibility(someKey1)); + assertEquals(Compatibility.PATCH, someKey3.getCompatibility(someKey1)); + assertEquals(Compatibility.MINOR, someKey4.getCompatibility(someKey1)); + assertEquals(Compatibility.MAJOR, someKey5.getCompatibility(someKey1)); + assertEquals(Compatibility.MAJOR, someKey6.getCompatibility(someKey1)); + + assertTrue(someKey1.isCompatible(someKey2)); + assertTrue(someKey1.isCompatible(someKey3)); + assertTrue(someKey1.isCompatible(someKey4)); + assertFalse(someKey1.isCompatible(someKey0)); + assertFalse(someKey1.isCompatible(someKey5)); + assertFalse(someKey1.isCompatible(new DummyPfKey())); + + assertEquals(PfValidationResult.ValidationResult.VALID, + someKey0.validate(new PfValidationResult()).getValidationResult()); + assertEquals(PfValidationResult.ValidationResult.VALID, + someKey1.validate(new PfValidationResult()).getValidationResult()); + assertEquals(PfValidationResult.ValidationResult.VALID, + someKey2.validate(new PfValidationResult()).getValidationResult()); + assertEquals(PfValidationResult.ValidationResult.VALID, + someKey3.validate(new PfValidationResult()).getValidationResult()); + assertEquals(PfValidationResult.ValidationResult.VALID, + someKey4.validate(new PfValidationResult()).getValidationResult()); + assertEquals(PfValidationResult.ValidationResult.VALID, + someKey5.validate(new PfValidationResult()).getValidationResult()); + assertEquals(PfValidationResult.ValidationResult.VALID, + someKey6.validate(new PfValidationResult()).getValidationResult()); + + someKey0.clean(); + assertNotNull(someKey0.toString()); + + PfConceptKey someKey7 = new PfConceptKey(someKey1); + assertEquals(150332875, someKey7.hashCode()); + assertEquals(0, someKey7.compareTo(someKey1)); + assertEquals(-12, someKey7.compareTo(someKey0)); + + try { + someKey0.compareTo(null); + } catch (IllegalArgumentException e) { + assertEquals("comparison object may not be null", e.getMessage()); + } + + assertEquals(0, someKey0.compareTo(someKey0)); + assertEquals(161539407, someKey0.compareTo(new DummyPfKey())); + + assertFalse(someKey0.equals(null)); + assertTrue(someKey0.equals(someKey0)); + assertFalse(((PfKey) someKey0).equals(new DummyPfKey())); + } + + + @Test + public void testValidation() { + PfConceptKey testKey = new PfConceptKey("TheKey", "0.0.1"); + assertEquals("TheKey:0.0.1", testKey.getId()); + + try { + Field nameField = testKey.getClass().getDeclaredField("name"); + nameField.setAccessible(true); + nameField.set(testKey, "Key Name"); + PfValidationResult validationResult = new PfValidationResult(); + testKey.validate(validationResult); + nameField.set(testKey, "TheKey"); + nameField.setAccessible(false); + assertEquals( + "name invalid-parameter name with value Key Name " + + "does not match regular expression [A-Za-z0-9\\-_\\.]+", + validationResult.getMessageList().get(0).getMessage()); + } catch (Exception validationException) { + fail("test should not throw an exception"); + } + + try { + Field versionField = testKey.getClass().getDeclaredField("version"); + versionField.setAccessible(true); + versionField.set(testKey, "Key Version"); + PfValidationResult validationResult = new PfValidationResult(); + testKey.validate(validationResult); + versionField.set(testKey, "0.0.1"); + versionField.setAccessible(false); + assertEquals( + "version invalid-parameter version with value Key Version " + + "does not match regular expression [A-Za-z0-9.]+", + validationResult.getMessageList().get(0).getMessage()); + } catch (Exception validationException) { + fail("test should not throw an exception"); + } + } +} diff --git a/models-base/src/test/java/org/onap/policy/models/base/ValidationTest.java b/models-base/src/test/java/org/onap/policy/models/base/ValidationTest.java new file mode 100644 index 000000000..385039c5b --- /dev/null +++ b/models-base/src/test/java/org/onap/policy/models/base/ValidationTest.java @@ -0,0 +1,90 @@ +/* + * ============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 static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; +import org.onap.policy.models.base.PfValidationResult.ValidationResult; + +public class ValidationTest { + + @Test + public void test() { + PfValidationResult result = new PfValidationResult(); + PfConceptKey pfKeyey = new PfConceptKey("PK", "0.0.1"); + result = pfKeyey.validate(result); + + assertNotNull(result); + assertTrue(result.isOk()); + assertTrue(result.isValid()); + assertEquals(PfValidationResult.ValidationResult.VALID, result.getValidationResult()); + assertNotNull(result.getMessageList()); + + PfValidationMessage vmess0 = new PfValidationMessage(PfConceptKey.getNullKey(), PfConceptKey.class, + ValidationResult.VALID, "Some message"); + result.addValidationMessage(vmess0); + + assertTrue(result.isOk()); + assertTrue(result.isValid()); + assertEquals(PfValidationResult.ValidationResult.VALID, result.getValidationResult()); + assertNotNull(result.getMessageList()); + assertNotNull("hello", result.toString()); + + PfValidationMessage vmess1 = new PfValidationMessage(PfConceptKey.getNullKey(), PfConceptKey.class, + ValidationResult.OBSERVATION, "Some message"); + result.addValidationMessage(vmess1); + + assertTrue(result.isOk()); + assertTrue(result.isValid()); + assertEquals(PfValidationResult.ValidationResult.OBSERVATION, result.getValidationResult()); + assertNotNull(result.getMessageList()); + assertNotNull("hello", result.toString()); + + PfValidationMessage vmess2 = new PfValidationMessage(PfConceptKey.getNullKey(), PfConceptKey.class, + ValidationResult.WARNING, "Some message"); + result.addValidationMessage(vmess2); + + assertFalse(result.isOk()); + assertTrue(result.isValid()); + assertEquals(PfValidationResult.ValidationResult.WARNING, result.getValidationResult()); + assertNotNull(result.getMessageList()); + assertNotNull("hello", result.toString()); + + PfValidationMessage vmess3 = new PfValidationMessage(PfConceptKey.getNullKey(), PfConceptKey.class, + ValidationResult.INVALID, "Some message"); + result.addValidationMessage(vmess3); + + assertFalse(result.isOk()); + assertFalse(result.isValid()); + assertEquals(PfValidationResult.ValidationResult.INVALID, result.getValidationResult()); + assertNotNull(result.getMessageList()); + assertNotNull("hello", result.toString()); + + assertEquals(PfValidationResult.ValidationResult.INVALID, result.getMessageList().get(3).getValidationResult()); + assertEquals("Some message", result.getMessageList().get(3).getMessage()); + assertEquals(PfConceptKey.class.getCanonicalName(), result.getMessageList().get(3).getObservedClass()); + assertEquals(PfConceptKey.getNullKey(), result.getMessageList().get(3).getObservedKey()); + } +} diff --git a/models-base/src/test/java/org/onap/policy/models/base/testpojos/DummyPfConcept.java b/models-base/src/test/java/org/onap/policy/models/base/testpojos/DummyPfConcept.java new file mode 100644 index 000000000..85727f45e --- /dev/null +++ b/models-base/src/test/java/org/onap/policy/models/base/testpojos/DummyPfConcept.java @@ -0,0 +1,76 @@ +/*- + * ============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.testpojos; + +import java.util.List; + +import org.onap.policy.models.base.PfConcept; +import org.onap.policy.models.base.PfConceptKey; +import org.onap.policy.models.base.PfKey; +import org.onap.policy.models.base.PfValidationResult; + +public class DummyPfConcept extends PfConcept { + private static final long serialVersionUID = 1L; + + @Override + public int compareTo(PfConcept concept) { + return 0; + } + + @Override + public PfKey getKey() { + return new PfConceptKey(); + } + + @Override + public List<PfKey> getKeys() { + return null; + } + + @Override + public PfValidationResult validate(PfValidationResult result) { + return null; + } + + @Override + public void clean() { + } + + @Override + public boolean equals(Object otherObject) { + return false; + } + + @Override + public String toString() { + return null; + } + + @Override + public int hashCode() { + return 0; + } + + @Override + public PfConcept copyTo(PfConcept target) { + return null; + } +} diff --git a/models-base/src/test/java/org/onap/policy/models/base/testpojos/DummyPfKey.java b/models-base/src/test/java/org/onap/policy/models/base/testpojos/DummyPfKey.java new file mode 100644 index 000000000..19358a1de --- /dev/null +++ b/models-base/src/test/java/org/onap/policy/models/base/testpojos/DummyPfKey.java @@ -0,0 +1,91 @@ +/*- + * ============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.testpojos; + +import java.util.List; + +import org.onap.policy.models.base.PfConcept; +import org.onap.policy.models.base.PfKey; +import org.onap.policy.models.base.PfValidationResult; + +public class DummyPfKey extends PfKey { + private static final long serialVersionUID = 1L; + + @Override + public int compareTo(PfConcept arg0) { + return 0; + } + + @Override + public String getId() { + return null; + } + + @Override + public Compatibility getCompatibility(PfKey otherKey) { + return null; + } + + @Override + public boolean isCompatible(PfKey otherKey) { + return false; + } + + @Override + public PfKey getKey() { + return null; + } + + @Override + public List<PfKey> getKeys() { + return null; + } + + @Override + public PfValidationResult validate(PfValidationResult result) { + return null; + } + + @Override + public void clean() { + + } + + @Override + public boolean equals(Object otherObject) { + return false; + } + + @Override + public String toString() { + return null; + } + + @Override + public int hashCode() { + return 0; + } + + @Override + public PfConcept copyTo(PfConcept target) { + return null; + } +} |