summaryrefslogtreecommitdiffstats
path: root/models-base/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'models-base/src/main/java')
-rw-r--r--models-base/src/main/java/org/onap/policy/models/base/PfConcept.java10
-rw-r--r--models-base/src/main/java/org/onap/policy/models/base/PfConceptGetter.java76
-rw-r--r--models-base/src/main/java/org/onap/policy/models/base/PfConceptGetterImpl.java129
-rw-r--r--models-base/src/main/java/org/onap/policy/models/base/PfConceptKey.java133
-rw-r--r--models-base/src/main/java/org/onap/policy/models/base/PfKey.java16
-rw-r--r--models-base/src/main/java/org/onap/policy/models/base/PfKeyUse.java153
-rw-r--r--models-base/src/main/java/org/onap/policy/models/base/PfModel.java303
-rw-r--r--models-base/src/main/java/org/onap/policy/models/base/PfModelService.java104
-rw-r--r--models-base/src/main/java/org/onap/policy/models/base/PfReferenceKey.java392
9 files changed, 1190 insertions, 126 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
index 99eee8d7f..b74b0374d 100644
--- 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
@@ -23,17 +23,13 @@ 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.
+ * This class is the base class for all Policy Framework 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;
@@ -63,7 +59,7 @@ public abstract class PfConcept implements Serializable, Comparable<PfConcept> {
* 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
+ * @return the keys used by this concept and its contained concepts
*/
public abstract List<PfKey> getKeys();
diff --git a/models-base/src/main/java/org/onap/policy/models/base/PfConceptGetter.java b/models-base/src/main/java/org/onap/policy/models/base/PfConceptGetter.java
new file mode 100644
index 000000000..b1b8984f9
--- /dev/null
+++ b/models-base/src/main/java/org/onap/policy/models/base/PfConceptGetter.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;
+
+import java.util.Set;
+
+/**
+ * This interface is used to allow get methods to be placed on concepts that have embedded maps.
+ *
+ * <p>It forces those concepts with maps to implement the get methods specified on this interface as convenience methods
+ * to avoid concept users having to use a second level of referencing to access concepts in the maps.
+ *
+ * @param <C> the type of concept on which the interface is applied.
+ */
+public interface PfConceptGetter<C> {
+
+ /**
+ * Get the latest version for a concept with the given key.
+ *
+ * @param conceptKey The key of the concept
+ * @return The concept
+ */
+ C get(PfConceptKey conceptKey);
+
+ /**
+ * Get the latest version for a concept with the given key name.
+ *
+ * @param conceptKeyName The name of the concept
+ * @return The concept
+ */
+ C get(String conceptKeyName);
+
+ /**
+ * Get the latest version for a concept with the given key name and version.
+ *
+ * @param conceptKeyName The name of the concept
+ * @param conceptKeyVersion The version of the concept
+ * @return The concept
+ */
+ C get(String conceptKeyName, String conceptKeyVersion);
+
+ /**
+ * Get the all versions for a concept with the given key name.
+ *
+ * @param conceptKeyName The name of the concept
+ * @return The concepts
+ */
+ Set<C> getAll(String conceptKeyName);
+
+ /**
+ * Get the all versions for a concept with the given key name and starting version.
+ *
+ * @param conceptKeyName The name of the concept
+ * @param conceptKeyVersion The first version version of the concept to get
+ * @return The concepts
+ */
+ Set<C> getAll(String conceptKeyName, String conceptKeyVersion);
+}
diff --git a/models-base/src/main/java/org/onap/policy/models/base/PfConceptGetterImpl.java b/models-base/src/main/java/org/onap/policy/models/base/PfConceptGetterImpl.java
new file mode 100644
index 000000000..f07713a1e
--- /dev/null
+++ b/models-base/src/main/java/org/onap/policy/models/base/PfConceptGetterImpl.java
@@ -0,0 +1,129 @@
+/*-
+ * ============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.NavigableMap;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.onap.policy.common.utils.validation.Assertions;
+
+/**
+ * Implements concept getting from navigable maps.
+ *
+ * @param <C> the type of concept on which the interface implementation is applied.
+ */
+public class PfConceptGetterImpl<C> implements PfConceptGetter<C> {
+
+ // The map from which to get concepts
+ private final NavigableMap<PfConceptKey, C> conceptMap;
+
+ /**
+ * Constructor that sets the concept map on which the getter methods in the interface will operate..
+ *
+ * @param conceptMap the concept map on which the method will operate
+ */
+ public PfConceptGetterImpl(final NavigableMap<PfConceptKey, C> conceptMap) {
+ this.conceptMap = conceptMap;
+ }
+
+ @Override
+ public C get(final PfConceptKey conceptKey) {
+ return conceptMap.get(conceptKey);
+ }
+
+ @Override
+ public C get(final String conceptKeyName) {
+ Assertions.argumentNotNull(conceptKeyName, "conceptKeyName may not be null");
+
+ // The very fist key that could have this name
+ final PfConceptKey lowestArtifactKey = new PfConceptKey(conceptKeyName, "0.0.1");
+
+ // Check if we found a key for our name
+ PfConceptKey foundKey = conceptMap.ceilingKey(lowestArtifactKey);
+ if (foundKey == null || !foundKey.getName().equals(conceptKeyName)) {
+ return null;
+ }
+
+ // Look for higher versions of the key
+ do {
+ final PfConceptKey nextkey = conceptMap.higherKey(foundKey);
+ if (nextkey == null || !nextkey.getName().equals(conceptKeyName)) {
+ break;
+ }
+ foundKey = nextkey;
+ }
+ while (true);
+
+ return conceptMap.get(foundKey);
+ }
+
+ @Override
+ public C get(final String conceptKeyName, final String conceptKeyVersion) {
+ Assertions.argumentNotNull(conceptKeyName, "conceptKeyName may not be null");
+
+ if (conceptKeyVersion != null) {
+ return conceptMap.get(new PfConceptKey(conceptKeyName, conceptKeyVersion));
+ } else {
+ return this.get(conceptKeyName);
+ }
+ }
+
+ @Override
+ public Set<C> getAll(final String conceptKeyName) {
+ return getAll(conceptKeyName, null);
+ }
+
+ @Override
+ public Set<C> getAll(final String conceptKeyName, final String conceptKeyVersion) {
+ final Set<C> returnSet = new TreeSet<>();
+
+ if (conceptKeyName == null) {
+ returnSet.addAll(conceptMap.values());
+ return returnSet;
+ }
+
+ // The very fist key that could have this name
+ final PfConceptKey lowestArtifactKey = new PfConceptKey(conceptKeyName, "0.0.1");
+ if (conceptKeyVersion != null) {
+ lowestArtifactKey.setVersion(conceptKeyVersion);
+ }
+
+ // Check if we found a key for our name
+ PfConceptKey foundKey = conceptMap.ceilingKey(lowestArtifactKey);
+ if (foundKey == null || !foundKey.getName().equals(conceptKeyName)) {
+ return returnSet;
+ }
+ returnSet.add(conceptMap.get(foundKey));
+
+ // Look for higher versions of the key
+ do {
+ foundKey = conceptMap.higherKey(foundKey);
+ if (foundKey == null || !foundKey.getName().equals(conceptKeyName)) {
+ break;
+ }
+ returnSet.add(conceptMap.get(foundKey));
+ }
+ while (true);
+
+ return returnSet;
+ }
+}
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
index 6ebb8886a..efcbe392c 100644
--- 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
@@ -25,29 +25,24 @@ 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 lombok.Data;
+import lombok.EqualsAndHashCode;
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.
+ * An concept 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 PfReferenceKey} 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"})
-
+@Data
+@EqualsAndHashCode(callSuper = false)
public class PfConceptKey extends PfKey {
private static final long serialVersionUID = 8932717618579392561L;
@@ -55,15 +50,13 @@ public class PfConceptKey extends PfKey {
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.
+ * The default constructor creates a null concept key.
*/
public PfConceptKey() {
this(NULL_KEY_NAME, NULL_KEY_VERSION);
@@ -112,9 +105,9 @@ public class PfConceptKey extends PfKey {
}
/**
- * Get a null artifact key.
+ * Get a null concept key.
*
- * @return a null artifact key
+ * @return a null concept key
*/
public static final PfConceptKey getNullKey() {
return new PfConceptKey(PfKey.NULL_KEY_NAME, PfKey.NULL_KEY_VERSION);
@@ -137,58 +130,22 @@ public class PfConceptKey extends PfKey {
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;
+ final PfConceptKey otherConceptKey = (PfConceptKey) otherKey;
- if (this.equals(otherArtifactKey)) {
+ if (this.equals(otherConceptKey)) {
return Compatibility.IDENTICAL;
}
- if (!this.getName().equals(otherArtifactKey.getName())) {
+ if (!this.getName().equals(otherConceptKey.getName())) {
return Compatibility.DIFFERENT;
}
final String[] thisVersionArray = getVersion().split("\\.");
- final String[] otherVersionArray = otherArtifactKey.getVersion().split("\\.");
+ final String[] otherVersionArray = otherConceptKey.getVersion().split("\\.");
// There must always be at least one element in each version
if (!thisVersionArray[0].equals(otherVersionArray[0])) {
@@ -196,7 +153,7 @@ public class PfConceptKey extends PfKey {
}
if (thisVersionArray.length >= 2 && otherVersionArray.length >= 2
- && !thisVersionArray[1].equals(otherVersionArray[1])) {
+ && !thisVersionArray[1].equals(otherVersionArray[1])) {
return Compatibility.MINOR;
}
@@ -208,27 +165,27 @@ public class PfConceptKey extends PfKey {
if (!(otherKey instanceof PfConceptKey)) {
return false;
}
- final PfConceptKey otherArtifactKey = (PfConceptKey) otherKey;
+ final PfConceptKey otherConceptKey = (PfConceptKey) otherKey;
- final Compatibility compatibility = this.getCompatibility(otherArtifactKey);
+ final Compatibility compatibility = this.getCompatibility(otherConceptKey);
return !(compatibility == Compatibility.DIFFERENT || compatibility == Compatibility.MAJOR);
}
@Override
public PfValidationResult validate(final PfValidationResult result) {
- final String nameValidationErrorMessage =
- Assertions.getStringParameterValidationMessage(NAME_TOKEN, name, NAME_REGEXP);
+ 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));
+ "name invalid-" + nameValidationErrorMessage));
}
- final String versionValidationErrorMessage =
- Assertions.getStringParameterValidationMessage(VERSION_TOKEN, version, VERSION_REGEXP);
+ 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));
+ "version invalid-" + versionValidationErrorMessage));
}
return result;
@@ -241,19 +198,6 @@ public class PfConceptKey extends PfKey {
}
@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");
@@ -268,35 +212,6 @@ public class PfConceptKey extends PfKey {
}
@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");
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
index 16e70a2c0..dda4cdc03 100644
--- 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
@@ -21,8 +21,8 @@
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.
+ * 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;
@@ -49,18 +49,15 @@ public abstract class PfKey extends PfConcept {
/** 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).
+ * 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).
+ * 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).
+ * 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. */
@@ -95,8 +92,7 @@ public abstract class PfKey extends PfConcept {
public abstract Compatibility getCompatibility(PfKey otherKey);
/**
- * Check if two keys are compatible, that is the keys are IDENTICAL or have only MINOR, PATCH
- * differences.
+ * 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
diff --git a/models-base/src/main/java/org/onap/policy/models/base/PfKeyUse.java b/models-base/src/main/java/org/onap/policy/models/base/PfKeyUse.java
new file mode 100644
index 000000000..0eb55a711
--- /dev/null
+++ b/models-base/src/main/java/org/onap/policy/models/base/PfKeyUse.java
@@ -0,0 +1,153 @@
+/*-
+ * ============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.List;
+
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+import org.onap.policy.common.utils.validation.Assertions;
+import org.onap.policy.models.base.PfValidationResult.ValidationResult;
+
+/**
+ * This class records a usage of a key in the system. When the list of keys being used by a concept is built using the
+ * getKeys() method of the {@link PfConcept} class, an instance of this class is created for every key occurrence. The
+ * list of keys returned by the getKeys() method is a list of {@link PfKeyUse} objects.
+ *
+ * <p>Validation checks that each key is valid.
+ */
+@EqualsAndHashCode(callSuper = false)
+@ToString
+public class PfKeyUse extends PfKey {
+ private static final long serialVersionUID = 2007147220109881705L;
+
+ private PfKey usedKey;
+
+ /**
+ * The Default Constructor creates this concept with a null key.
+ */
+ public PfKeyUse() {
+ this(new PfConceptKey());
+ }
+
+ /**
+ * Copy constructor.
+ *
+ * @param copyConcept the concept to copy from
+ */
+ public PfKeyUse(final PfKeyUse copyConcept) {
+ super(copyConcept);
+ }
+
+ /**
+ * This constructor creates an instance of this class, and holds a reference to a used key.
+ *
+ * @param usedKey a used key
+ */
+ public PfKeyUse(final PfKey usedKey) {
+ Assertions.argumentNotNull(usedKey, "usedKey may not be null");
+ this.usedKey = usedKey;
+ }
+
+ @Override
+ public PfKey getKey() {
+ return usedKey;
+ }
+
+ @Override
+ public List<PfKey> getKeys() {
+ return usedKey.getKeys();
+ }
+
+ @Override
+ public String getId() {
+ return usedKey.getId();
+ }
+
+ /**
+ * Sets the key.
+ *
+ * @param key the key
+ */
+ public void setKey(final PfKey key) {
+ Assertions.argumentNotNull(key, "usedKey may not be null");
+ this.usedKey = key;
+ }
+
+ @Override
+ public PfKey.Compatibility getCompatibility(final PfKey otherKey) {
+ return usedKey.getCompatibility(otherKey);
+ }
+
+ @Override
+ public boolean isCompatible(final PfKey otherKey) {
+ return usedKey.isCompatible(otherKey);
+ }
+
+ @Override
+ public PfValidationResult validate(final PfValidationResult result) {
+ if (usedKey.equals(PfConceptKey.getNullKey())) {
+ result.addValidationMessage(new PfValidationMessage(usedKey, this.getClass(), ValidationResult.INVALID,
+ "usedKey is a null key"));
+ }
+ return usedKey.validate(result);
+ }
+
+ @Override
+ public void clean() {
+ usedKey.clean();
+ }
+
+ @Override
+ public PfConcept copyTo(final PfConcept target) {
+ Assertions.argumentNotNull(target, "target may not be null");
+
+ final Object copyObject = target;
+ Assertions.instanceOf(copyObject, PfKeyUse.class);
+
+ final PfKeyUse copy = ((PfKeyUse) copyObject);
+ try {
+ copy.usedKey = usedKey.getClass().newInstance();
+ } catch (final Exception e) {
+ throw new PfModelRuntimeException("error copying concept key: " + e.getMessage(), e);
+ }
+ usedKey.copyTo(copy.usedKey);
+
+ return copy;
+ }
+
+ @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 PfKeyUse other = (PfKeyUse) otherObj;
+
+ return usedKey.compareTo(other.usedKey);
+ }
+}
diff --git a/models-base/src/main/java/org/onap/policy/models/base/PfModel.java b/models-base/src/main/java/org/onap/policy/models/base/PfModel.java
new file mode 100644
index 000000000..c9174bde8
--- /dev/null
+++ b/models-base/src/main/java/org/onap/policy/models/base/PfModel.java
@@ -0,0 +1,303 @@
+/*-
+ * ============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.List;
+import java.util.Set;
+import java.util.TreeSet;
+
+import javax.persistence.EmbeddedId;
+import javax.persistence.Entity;
+import javax.persistence.Inheritance;
+import javax.persistence.InheritanceType;
+import javax.persistence.Table;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NonNull;
+
+import org.onap.policy.common.utils.validation.Assertions;
+import org.onap.policy.models.base.PfValidationResult.ValidationResult;
+
+/**
+ * This class is the base class for all models in the Policy Framework. All model classes inherit
+ * from this model so all models must have a key and have key information.
+ *
+ * <p>Validation checks that the model key is valid. It goes on to check for null keys and checks
+ * each key for uniqueness in the model. A check is carried out to ensure that an {@link PfKeyInfo}
+ * instance exists for every {@link PfConceptKey} key. For each {@link PfReferenceKey} instance, a
+ * check is made that its parent and local name are nut null and that a {@link PfKeyInfo} entry
+ * exists for its parent. Then a check is made that each used {@link PfConceptKey} and
+ * {@link PfReferenceKey} usage references a key that exists. Finally, a check is made to ensure
+ * that an {@link PfConceptKey} instance exists for every {@link PfKeyInfo} instance.
+ *
+ * @param <C> the type of concept on which the interface is applied.
+ */
+
+@Entity
+@Table(name = "PfModel")
+@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
+@Data
+@EqualsAndHashCode(callSuper = false)
+public abstract class PfModel extends PfConcept {
+ private static final String IS_A_NULL_KEY = " is a null key";
+
+ private static final long serialVersionUID = -771659065637205430L;
+
+ @EmbeddedId
+ @NonNull
+ private PfConceptKey key = PfConceptKey.getNullKey();
+
+ /**
+ * The Default Constructor creates this concept with a NULL artifact key.
+ */
+ public PfModel() {
+ this(new PfConceptKey());
+ }
+
+ /**
+ * Copy constructor.
+ *
+ * @param copyConcept the concept to copy from
+ */
+ public PfModel(final PfModel copyConcept) {
+ super(copyConcept);
+ }
+
+ /**
+ * Constructor to create this concept with the specified key.
+ *
+ * @param key the key of this concept
+ */
+ public PfModel(final PfConceptKey key) {
+ super();
+ Assertions.argumentNotNull(key, "key may not be null");
+
+ this.key = key;
+ }
+
+ /**
+ * Registers this model with the {@link PfModelService}. All models are registered with the
+ * model service so that models can be references from anywhere in the Policy Framework system
+ * without being passed as references through deep call chains.
+ */
+ public abstract void register();
+
+ @Override
+ public List<PfKey> getKeys() {
+ return key.getKeys();
+ }
+
+ @Override
+ public PfValidationResult validate(final PfValidationResult resultIn) {
+ PfValidationResult result = resultIn;
+
+ if (key.equals(PfConceptKey.getNullKey())) {
+ result.addValidationMessage(
+ new PfValidationMessage(key, this.getClass(), ValidationResult.INVALID, "key is a null key"));
+ }
+
+ result = key.validate(result);
+
+ // Key consistency check
+ final Set<PfConceptKey> artifactKeySet = new TreeSet<>();
+ final Set<PfReferenceKey> referenceKeySet = new TreeSet<>();
+ final Set<PfKeyUse> usedKeySet = new TreeSet<>();
+
+ for (final PfKey pfKey : this.getKeys()) {
+ // Check for the two type of keys we have
+ if (pfKey instanceof PfConceptKey) {
+ result = validateArtifactKeyInModel((PfConceptKey) pfKey, artifactKeySet, result);
+ } else if (pfKey instanceof PfReferenceKey) {
+ result = validateReferenceKeyInModel((PfReferenceKey) pfKey, referenceKeySet, result);
+ }
+ // It must be an PfKeyUse, nothing else is legal
+ else {
+ usedKeySet.add((PfKeyUse) pfKey);
+ }
+ }
+
+ // Check all reference keys have correct parent keys
+ for (final PfReferenceKey referenceKey : referenceKeySet) {
+ if (!artifactKeySet.contains(referenceKey.getParentConceptKey())) {
+ result.addValidationMessage(new PfValidationMessage(key, this.getClass(), ValidationResult.INVALID,
+ "parent artifact key not found for reference key " + referenceKey));
+ }
+ }
+
+ result = validateKeyUses(usedKeySet, artifactKeySet, referenceKeySet, result);
+
+ return result;
+ }
+
+ /**
+ * Check for consistent usage of an artifact key in the model.
+ *
+ * @param artifactKey The artifact key to check
+ * @param artifactKeySet The set of artifact keys encountered so far, this key is appended to
+ * the set
+ * @param result The validation result to append to
+ * @return the result of the validation
+ */
+ private PfValidationResult validateArtifactKeyInModel(final PfConceptKey artifactKey,
+ final Set<PfConceptKey> artifactKeySet, final PfValidationResult result) {
+ // Null key check
+ if (artifactKey.equals(PfConceptKey.getNullKey())) {
+ result.addValidationMessage(new PfValidationMessage(key, this.getClass(), ValidationResult.INVALID,
+ "key " + artifactKey + IS_A_NULL_KEY));
+ }
+
+ // Null key name start check
+ if (artifactKey.getName().toUpperCase().startsWith(PfKey.NULL_KEY_NAME)) {
+ result.addValidationMessage(new PfValidationMessage(key, this.getClass(), ValidationResult.INVALID,
+ "key " + artifactKey + " name starts with keyword " + PfKey.NULL_KEY_NAME));
+ }
+
+ // Unique key check
+ if (artifactKeySet.contains(artifactKey)) {
+ result.addValidationMessage(new PfValidationMessage(key, this.getClass(), ValidationResult.INVALID,
+ "duplicate key " + artifactKey + " found"));
+ } else {
+ artifactKeySet.add(artifactKey);
+ }
+
+ return result;
+ }
+
+ /**
+ * Check for consistent usage of a reference key in the model.
+ *
+ * @param artifactKey The reference key to check
+ * @param referenceKeySet The set of reference keys encountered so far, this key is appended to
+ * the set
+ * @param result The validation result to append to
+ * @return the result of the validation
+ */
+ private PfValidationResult validateReferenceKeyInModel(final PfReferenceKey referenceKey,
+ final Set<PfReferenceKey> referenceKeySet, final PfValidationResult result) {
+ // Null key check
+ if (referenceKey.equals(PfReferenceKey.getNullKey())) {
+ result.addValidationMessage(new PfValidationMessage(key, this.getClass(), ValidationResult.INVALID,
+ "key " + referenceKey + IS_A_NULL_KEY));
+ }
+
+ // Null parent key check
+ if (referenceKey.getParentConceptKey().equals(PfConceptKey.getNullKey())) {
+ result.addValidationMessage(new PfValidationMessage(key, this.getClass(), ValidationResult.INVALID,
+ "parent artifact key of key " + referenceKey + IS_A_NULL_KEY));
+ }
+
+ // Null local name check
+ if (referenceKey.getLocalName().equals(PfKey.NULL_KEY_NAME)) {
+ result.addValidationMessage(new PfValidationMessage(key, this.getClass(), ValidationResult.INVALID,
+ "key " + referenceKey + " has a null local name"));
+ }
+
+ // Null key name start check
+ if (referenceKey.getParentConceptKey().getName().toUpperCase().startsWith(PfKey.NULL_KEY_NAME)) {
+ result.addValidationMessage(new PfValidationMessage(key, this.getClass(), ValidationResult.INVALID,
+ "key " + referenceKey + " parent name starts with keyword " + PfKey.NULL_KEY_NAME));
+ }
+
+ // Unique key check
+ if (referenceKeySet.contains(referenceKey)) {
+ result.addValidationMessage(new PfValidationMessage(key, this.getClass(), ValidationResult.INVALID,
+ "duplicate key " + referenceKey + " found"));
+ } else {
+ referenceKeySet.add(referenceKey);
+ }
+
+ return result;
+ }
+
+ /**
+ * Check for consistent usage of cross-key references in the model.
+ *
+ * @param usedKeySet The set of all keys used in the model
+ * @param artifactKeySet The set of artifact keys encountered so far, this key is appended to
+ * the set
+ * @param referenceKeySet The set of reference keys encountered so far, this key is appended to
+ * the set
+ * @param result The validation result to append to
+ * @return the result of the validation
+ */
+ private PfValidationResult validateKeyUses(final Set<PfKeyUse> usedKeySet, final Set<PfConceptKey> artifactKeySet,
+ final Set<PfReferenceKey> referenceKeySet, final PfValidationResult result) {
+ // Check all key uses
+ for (final PfKeyUse usedKey : usedKeySet) {
+ if (usedKey.getKey() instanceof PfConceptKey) {
+ // PfConceptKey usage, check the key exists
+ if (!artifactKeySet.contains(usedKey.getKey())) {
+ result.addValidationMessage(new PfValidationMessage(usedKey.getKey(), this.getClass(),
+ ValidationResult.INVALID, "an artifact key used in the model is not defined"));
+ }
+ } else {
+ // PfReferenceKey usage, check the key exists
+ if (!referenceKeySet.contains(usedKey.getKey())) {
+ result.addValidationMessage(new PfValidationMessage(usedKey.getKey(), this.getClass(),
+ ValidationResult.INVALID, "a reference key used in the model is not defined"));
+ }
+ }
+ }
+
+ return result;
+ }
+
+ @Override
+ public void clean() {
+ key.clean();
+ }
+
+ @Override
+ public PfConcept copyTo(final PfConcept target) {
+ Assertions.argumentNotNull(target, "target may not be null");
+
+ final Object copyObject = target;
+ Assertions.instanceOf(copyObject, PfModel.class);
+
+ final PfModel copy = ((PfModel) copyObject);
+ copy.setKey(new PfConceptKey(key));
+
+ return copy;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Comparable#compareTo(java.lang.Object)
+ */
+ @Override
+ public int compareTo(final PfConcept otherObj) {
+ if (otherObj == null) {
+ return -1;
+ }
+ if (this == otherObj) {
+ return 0;
+ }
+ if (getClass() != otherObj.getClass()) {
+ return this.hashCode() - otherObj.hashCode();
+ }
+
+ final PfModel other = (PfModel) otherObj;
+
+ return key.compareTo(other.key);
+ }
+}
diff --git a/models-base/src/main/java/org/onap/policy/models/base/PfModelService.java b/models-base/src/main/java/org/onap/policy/models/base/PfModelService.java
new file mode 100644
index 000000000..c02de6aa7
--- /dev/null
+++ b/models-base/src/main/java/org/onap/policy/models/base/PfModelService.java
@@ -0,0 +1,104 @@
+/*-
+ * ============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.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * The model service makes Policy Framework models available to all classes in a JVM.
+ *
+ * <p>The reason for having a model service is to avoid having to pass concept and model definitions
+ * down long call chains in modules such as the Policy Framework engine and editor. The model
+ * service makes the model and concept definitions available statically.
+ *
+ * <p>Note that the use of the model service means that only a single Policy Framework model of a
+ * particular type may exist in Policy Framework (particularly the engine) at any time. Of course
+ * the model in a JVM can be changed at any time provided all users of the model are stopped and
+ * restarted in an orderly manner.
+ */
+public abstract class PfModelService {
+ // The map holding the models
+ private static Map<Class<?>, PfConcept> modelMap = new ConcurrentHashMap<>();
+
+ /**
+ * This class is an abstract static class that cannot be extended.
+ */
+ private PfModelService() {}
+
+ /**
+ * Register a model with the model service.
+ *
+ * @param <M> the generic type
+ * @param modelClass the class of the model, used to index the model
+ * @param model The model
+ */
+ public static <M extends PfConcept> void registerModel(final Class<M> modelClass, final M model) {
+ modelMap.put(modelClass, model);
+ }
+
+ /**
+ * Remove a model from the model service.
+ *
+ * @param <M> the generic type
+ * @param modelClass the class of the model, used to index the model
+ */
+ public static <M extends PfConcept> void deregisterModel(final Class<M> modelClass) {
+ modelMap.remove(modelClass);
+ }
+
+ /**
+ * Get a model from the model service.
+ *
+ * @param <M> the generic type
+ * @param modelClass the class of the model, used to index the model
+ * @return The model
+ */
+ @SuppressWarnings("unchecked")
+ public static <M extends PfConcept> M getModel(final Class<M> modelClass) {
+ final M model = (M) modelMap.get(modelClass);
+
+ if (model == null) {
+ throw new PfModelRuntimeException(
+ "Model for " + modelClass.getCanonicalName() + " not found in model service");
+ }
+
+ return model;
+ }
+
+ /**
+ * Check if a model is defined on the model service.
+ *
+ * @param <M> the generic type
+ * @param modelClass the class of the model, used to index the model
+ * @return true if the model is defined
+ */
+ public static <M extends PfConcept> boolean existsModel(final Class<M> modelClass) {
+ return modelMap.get(modelClass) != null;
+ }
+
+ /**
+ * Clear all models in the model service.
+ */
+ public static void clear() {
+ modelMap.clear();
+ }
+}
diff --git a/models-base/src/main/java/org/onap/policy/models/base/PfReferenceKey.java b/models-base/src/main/java/org/onap/policy/models/base/PfReferenceKey.java
new file mode 100644
index 000000000..e3b92c0e9
--- /dev/null
+++ b/models-base/src/main/java/org/onap/policy/models/base/PfReferenceKey.java
@@ -0,0 +1,392 @@
+/*-
+ * ============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 lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import org.onap.policy.common.utils.validation.Assertions;
+import org.onap.policy.models.base.PfValidationResult.ValidationResult;
+
+/**
+ * A reference key identifies entities in the system that are contained in other entities. Every contained concept in
+ * the system must have an {@link PfReferenceKey} to identify it. Non-contained first order concepts are identified
+ * using an {@link PfConceptKey} key.
+ *
+ * <p>An {@link PfReferenceKey} contains an {@link PfConceptKey} key reference to the first order entity that contains
+ * it. The local name of the reference key must uniquely identify the referenced concept among those concepts contained
+ * in the reference key's parent. In other words, if a parent concept has more than one child, the local name in the key
+ * of all its children must be unique.
+ *
+ * <p>If a reference key's parent is itself a reference key, then the parent's local name must be set in the reference
+ * key. If the parent is a first order concept, then the parent's local name in the key will be set to NULL.
+ *
+ * <p>Key validation checks that the parent name and parent version fields match the NAME_REGEXP and
+ * VERSION_REGEXP regular expressions respectively and that the local name fields match the
+ * LOCAL_NAME_REGEXP regular expression.
+ */
+@Embeddable
+@Data
+@EqualsAndHashCode(callSuper = false)
+public class PfReferenceKey extends PfKey {
+ private static final String PARENT_KEY_NAME = "parentKeyName";
+ private static final String PARENT_KEY_VERSION = "parentKeyVersion";
+ private static final String PARENT_LOCAL_NAME = "parentLocalName";
+ private static final String LOCAL_NAME = "localName";
+
+ private static final long serialVersionUID = 8932717618579392561L;
+
+ /** Regular expression to specify the structure of local names in reference keys. */
+ public static final String LOCAL_NAME_REGEXP = "[A-Za-z0-9\\-_\\.]+|^$";
+
+ /** Regular expression to specify the structure of IDs in reference keys. */
+ public static final String REFERENCE_KEY_ID_REGEXP =
+ "[A-Za-z0-9\\-_]+:[0-9].[0-9].[0-9]:[A-Za-z0-9\\-_]+:[A-Za-z0-9\\-_]+";
+
+ private static final int PARENT_NAME_FIELD = 0;
+ private static final int PARENT_VERSION_FIELD = 1;
+ private static final int PARENT_LOCAL_NAME_FIELD = 2;
+ private static final int LOCAL_NAME_FIELD = 3;
+
+ @Column(name = PARENT_KEY_NAME)
+ private String parentKeyName;
+
+ @Column(name = PARENT_KEY_VERSION)
+ private String parentKeyVersion;
+
+ @Column(name = PARENT_LOCAL_NAME)
+ private String parentLocalName;
+
+ @Column(name = LOCAL_NAME)
+ private String localName;
+
+ /**
+ * The default constructor creates a null reference key.
+ */
+ public PfReferenceKey() {
+ this(NULL_KEY_NAME, NULL_KEY_VERSION, NULL_KEY_NAME, NULL_KEY_NAME);
+ }
+
+ /**
+ * The Copy Constructor creates a key by copying another key.
+ *
+ * @param referenceKey
+ * the reference key to copy from
+ */
+ public PfReferenceKey(final PfReferenceKey referenceKey) {
+ this(referenceKey.getParentKeyName(), referenceKey.getParentKeyVersion(), referenceKey.getParentLocalName(),
+ referenceKey.getLocalName());
+ }
+
+ /**
+ * Constructor to create a null reference key for the specified parent concept key.
+ *
+ * @param pfConceptKey
+ * the parent concept key of this reference key
+ */
+ public PfReferenceKey(final PfConceptKey pfConceptKey) {
+ this(pfConceptKey.getName(), pfConceptKey.getVersion(), NULL_KEY_NAME, NULL_KEY_NAME);
+ }
+
+ /**
+ * Constructor to create a reference key for the given parent concept key with the given local name.
+ *
+ * @param pfConceptKey
+ * the parent concept key of this reference key
+ * @param localName
+ * the local name of this reference key
+ */
+ public PfReferenceKey(final PfConceptKey pfConceptKey, final String localName) {
+ this(pfConceptKey, NULL_KEY_NAME, localName);
+ }
+
+ /**
+ * Constructor to create a reference key for the given parent reference key with the given local name.
+ *
+ * @param parentReferenceKey
+ * the parent reference key of this reference key
+ * @param localName
+ * the local name of this reference key
+ */
+ public PfReferenceKey(final PfReferenceKey parentReferenceKey, final String localName) {
+ this(parentReferenceKey.getParentConceptKey(), parentReferenceKey.getLocalName(), localName);
+ }
+
+ /**
+ * Constructor to create a reference key for the given parent reference key (specified by the parent reference key's
+ * concept key and local name) with the given local name.
+ *
+ * @param pfConceptKey
+ * the concept key of the parent reference key of this reference key
+ * @param parentLocalName
+ * the local name of the parent reference key of this reference key
+ * @param localName
+ * the local name of this reference key
+ */
+ public PfReferenceKey(final PfConceptKey pfConceptKey, final String parentLocalName, final String localName) {
+ this(pfConceptKey.getName(), pfConceptKey.getVersion(), parentLocalName, localName);
+ }
+
+ /**
+ * Constructor to create a reference key for the given parent concept key (specified by the parent concept key's
+ * name and version) with the given local name.
+ *
+ * @param parentKeyName
+ * the name of the parent concept key of this reference key
+ * @param parentKeyVersion
+ * the version of the parent concept key of this reference key
+ * @param localName
+ * the local name of this reference key
+ */
+ public PfReferenceKey(final String parentKeyName, final String parentKeyVersion, final String localName) {
+ this(parentKeyName, parentKeyVersion, NULL_KEY_NAME, localName);
+ }
+
+ /**
+ * Constructor to create a reference key for the given parent key (specified by the parent key's name, version nad
+ * local name) with the given local name.
+ *
+ * @param parentKeyName
+ * the parent key name of this reference key
+ * @param parentKeyVersion
+ * the parent key version of this reference key
+ * @param parentLocalName
+ * the parent local name of this reference key
+ * @param localName
+ * the local name of this reference key
+ */
+ public PfReferenceKey(final String parentKeyName, final String parentKeyVersion, final String parentLocalName,
+ final String localName) {
+ super();
+ this.parentKeyName = Assertions.validateStringParameter(PARENT_KEY_NAME, parentKeyName, NAME_REGEXP);
+ this.parentKeyVersion = Assertions.validateStringParameter(PARENT_KEY_VERSION, parentKeyVersion,
+ VERSION_REGEXP);
+ this.parentLocalName = Assertions.validateStringParameter(PARENT_LOCAL_NAME, parentLocalName,
+ LOCAL_NAME_REGEXP);
+ this.localName = Assertions.validateStringParameter(LOCAL_NAME, localName, LOCAL_NAME_REGEXP);
+ }
+
+ /**
+ * Constructor to create a key from the specified key ID.
+ *
+ * @param id
+ * the key ID in a format that respects the KEY_ID_REGEXP
+ */
+ public PfReferenceKey(final String id) {
+ final String conditionedId = Assertions.validateStringParameter("id", id, REFERENCE_KEY_ID_REGEXP);
+
+ // Split on colon, if the id passes the regular expression test above
+ // it'll have just three colons separating the parent name,
+ // parent version, parent local name, and and local name
+ // No need for range checks or size checks on the array
+ final String[] nameVersionNameArray = conditionedId.split(":");
+
+ // Initiate the new key
+ parentKeyName = Assertions.validateStringParameter(PARENT_KEY_NAME, nameVersionNameArray[PARENT_NAME_FIELD],
+ NAME_REGEXP);
+ parentKeyVersion = Assertions.validateStringParameter(PARENT_KEY_VERSION,
+ nameVersionNameArray[PARENT_VERSION_FIELD], VERSION_REGEXP);
+ parentLocalName = Assertions.validateStringParameter(PARENT_LOCAL_NAME,
+ nameVersionNameArray[PARENT_LOCAL_NAME_FIELD], LOCAL_NAME_REGEXP);
+ localName = Assertions.validateStringParameter(LOCAL_NAME, nameVersionNameArray[LOCAL_NAME_FIELD],
+ LOCAL_NAME_REGEXP);
+ }
+
+ /**
+ * Get a null reference key.
+ *
+ * @return a null reference key
+ */
+ public static PfReferenceKey getNullKey() {
+ return new PfReferenceKey(PfKey.NULL_KEY_NAME, PfKey.NULL_KEY_VERSION, PfKey.NULL_KEY_NAME,
+ PfKey.NULL_KEY_NAME);
+ }
+
+ @Override
+ public PfReferenceKey getKey() {
+ return this;
+ }
+
+ @Override
+ public List<PfKey> getKeys() {
+ final List<PfKey> keyList = new ArrayList<>();
+ keyList.add(getKey());
+ return keyList;
+ }
+
+ @Override
+ public String getId() {
+ return parentKeyName + ':' + parentKeyVersion + ':' + parentLocalName + ':' + localName;
+ }
+
+ /**
+ * Gets the parent concept key of this reference key.
+ *
+ * @return the parent concept key of this reference key
+ */
+ public PfConceptKey getParentConceptKey() {
+ return new PfConceptKey(parentKeyName, parentKeyVersion);
+ }
+
+ /**
+ * Gets the parent reference key of this reference key.
+ *
+ * @return the parent reference key of this reference key
+ */
+ public PfReferenceKey getParentReferenceKey() {
+ return new PfReferenceKey(parentKeyName, parentKeyVersion, parentLocalName);
+ }
+
+ /**
+ * Sets the parent concept key of this reference key.
+ *
+ * @param parentKey
+ * the parent concept key of this reference key
+ */
+ public void setParentConceptKey(final PfConceptKey parentKey) {
+ Assertions.argumentNotNull(parentKey, "parentKey may not be null");
+
+ parentKeyName = parentKey.getName();
+ parentKeyVersion = parentKey.getVersion();
+ parentLocalName = NULL_KEY_NAME;
+ }
+
+ /**
+ * Sets the parent reference key of this reference key.
+ *
+ * @param parentKey
+ * the parent reference key of this reference key
+ */
+ public void setParentReferenceKey(final PfReferenceKey parentKey) {
+ Assertions.argumentNotNull(parentKey, "parentKey may not be null");
+
+ parentKeyName = parentKey.getParentKeyName();
+ parentKeyVersion = parentKey.getParentKeyVersion();
+ parentLocalName = parentKey.getLocalName();
+ }
+
+ @Override
+ public PfKey.Compatibility getCompatibility(final PfKey otherKey) {
+ if (!(otherKey instanceof PfReferenceKey)) {
+ return Compatibility.DIFFERENT;
+ }
+ final PfReferenceKey otherReferenceKey = (PfReferenceKey) otherKey;
+
+ return this.getParentConceptKey().getCompatibility(otherReferenceKey.getParentConceptKey());
+ }
+
+ @Override
+ public boolean isCompatible(final PfKey otherKey) {
+ if (!(otherKey instanceof PfReferenceKey)) {
+ return false;
+ }
+ final PfReferenceKey otherReferenceKey = (PfReferenceKey) otherKey;
+
+ return this.getParentConceptKey().isCompatible(otherReferenceKey.getParentConceptKey());
+ }
+
+ @Override
+ public PfValidationResult validate(final PfValidationResult result) {
+ final String parentNameValidationErrorMessage = Assertions.getStringParameterValidationMessage(PARENT_KEY_NAME,
+ parentKeyName, NAME_REGEXP);
+ if (parentNameValidationErrorMessage != null) {
+ result.addValidationMessage(new PfValidationMessage(this, this.getClass(), ValidationResult.INVALID,
+ "parentKeyName invalid-" + parentNameValidationErrorMessage));
+ }
+
+ final String parentKeyVersionValidationErrorMessage = Assertions
+ .getStringParameterValidationMessage(PARENT_KEY_VERSION, parentKeyVersion, VERSION_REGEXP);
+ if (parentKeyVersionValidationErrorMessage != null) {
+ result.addValidationMessage(new PfValidationMessage(this, this.getClass(), ValidationResult.INVALID,
+ "parentKeyVersion invalid-" + parentKeyVersionValidationErrorMessage));
+ }
+
+ final String parentLocalNameValidationErrorMessage = Assertions
+ .getStringParameterValidationMessage(PARENT_LOCAL_NAME, parentLocalName, LOCAL_NAME_REGEXP);
+ if (parentLocalNameValidationErrorMessage != null) {
+ result.addValidationMessage(new PfValidationMessage(this, this.getClass(), ValidationResult.INVALID,
+ "parentLocalName invalid-" + parentLocalNameValidationErrorMessage));
+ }
+
+ final String localNameValidationErrorMessage = Assertions.getStringParameterValidationMessage(LOCAL_NAME,
+ localName, LOCAL_NAME_REGEXP);
+ if (localNameValidationErrorMessage != null) {
+ result.addValidationMessage(new PfValidationMessage(this, this.getClass(), ValidationResult.INVALID,
+ "localName invalid-" + localNameValidationErrorMessage));
+ }
+
+ return result;
+ }
+
+ @Override
+ public void clean() {
+ parentKeyName = Assertions.validateStringParameter(PARENT_KEY_NAME, parentKeyName, NAME_REGEXP);
+ parentKeyVersion = Assertions.validateStringParameter(PARENT_KEY_VERSION, parentKeyVersion, VERSION_REGEXP);
+ parentLocalName = Assertions.validateStringParameter(PARENT_LOCAL_NAME, parentLocalName, LOCAL_NAME_REGEXP);
+ localName = Assertions.validateStringParameter(LOCAL_NAME, localName, LOCAL_NAME_REGEXP);
+ }
+
+ @Override
+ public PfConcept copyTo(final PfConcept target) {
+ Assertions.argumentNotNull(target, "target may not be null");
+
+ final Object copyObject = target;
+ Assertions.instanceOf(copyObject, PfReferenceKey.class);
+
+ final PfReferenceKey copy = ((PfReferenceKey) copyObject);
+ copy.setParentKeyName(parentKeyName);
+ copy.setParentKeyVersion(parentKeyVersion);
+ copy.setLocalName(localName);
+ copy.setParentLocalName(parentLocalName);
+
+ return copy;
+ }
+
+ @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 PfReferenceKey other = (PfReferenceKey) otherObj;
+ if (!parentKeyName.equals(other.parentKeyName)) {
+ return parentKeyName.compareTo(other.parentKeyName);
+ }
+ if (!parentKeyVersion.equals(other.parentKeyVersion)) {
+ return parentKeyVersion.compareTo(other.parentKeyVersion);
+ }
+ if (!parentLocalName.equals(other.parentLocalName)) {
+ return parentLocalName.compareTo(other.parentLocalName);
+ }
+ return localName.compareTo(other.localName);
+ }
+}