2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2019 Nordix Foundation.
4 * ================================================================================
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
17 * SPDX-License-Identifier: Apache-2.0
18 * ============LICENSE_END=========================================================
21 package org.onap.policy.models.base;
23 import java.util.ArrayList;
24 import java.util.List;
26 import javax.persistence.Column;
27 import javax.persistence.Embeddable;
30 import lombok.EqualsAndHashCode;
31 import lombok.NonNull;
33 import org.onap.policy.common.utils.validation.Assertions;
34 import org.onap.policy.models.base.PfValidationResult.ValidationResult;
37 * A reference key identifies entities in the system that are contained in other entities. Every contained concept in
38 * the system must have an {@link PfReferenceKey} to identify it. Non-contained first order concepts are identified
39 * using an {@link PfConceptKey} key.
41 * <p>An {@link PfReferenceKey} contains an {@link PfConceptKey} key reference to the first order entity that contains
42 * it. The local name of the reference key must uniquely identify the referenced concept among those concepts contained
43 * in the reference key's parent. In other words, if a parent concept has more than one child, the local name in the key
44 * of all its children must be unique.
46 * <p>If a reference key's parent is itself a reference key, then the parent's local name must be set in the reference
47 * key. If the parent is a first order concept, then the parent's local name in the key will be set to NULL.
49 * <p>Key validation checks that the parent name and parent version fields match the NAME_REGEXP and
50 * VERSION_REGEXP regular expressions respectively and that the local name fields match the
51 * LOCAL_NAME_REGEXP regular expression.
55 @EqualsAndHashCode(callSuper = false)
56 public class PfReferenceKey extends PfKey {
57 private static final String PARENT_KEY_NAME = "parentKeyName";
58 private static final String PARENT_KEY_VERSION = "parentKeyVersion";
59 private static final String PARENT_LOCAL_NAME = "parentLocalName";
60 private static final String LOCAL_NAME = "localName";
62 private static final long serialVersionUID = 8932717618579392561L;
64 /** Regular expression to specify the structure of local names in reference keys. */
65 public static final String LOCAL_NAME_REGEXP = "[A-Za-z0-9\\-_\\.]+|^$";
67 /** Regular expression to specify the structure of IDs in reference keys. */
68 public static final String REFERENCE_KEY_ID_REGEXP =
69 "[A-Za-z0-9\\-_]+:[0-9].[0-9].[0-9]:[A-Za-z0-9\\-_]+:[A-Za-z0-9\\-_]+";
71 private static final int PARENT_NAME_FIELD = 0;
72 private static final int PARENT_VERSION_FIELD = 1;
73 private static final int PARENT_LOCAL_NAME_FIELD = 2;
74 private static final int LOCAL_NAME_FIELD = 3;
76 @Column(name = PARENT_KEY_NAME, length = 120)
77 private String parentKeyName;
79 @Column(name = PARENT_KEY_VERSION, length = 15)
80 private String parentKeyVersion;
82 @Column(name = PARENT_LOCAL_NAME, length = 120)
83 private String parentLocalName;
85 @Column(name = LOCAL_NAME, length = 120)
86 private String localName;
89 * The default constructor creates a null reference key.
91 public PfReferenceKey() {
92 this(NULL_KEY_NAME, NULL_KEY_VERSION, NULL_KEY_NAME, NULL_KEY_NAME);
96 * The Copy Constructor creates a key by copying another key.
99 * the reference key to copy from
101 public PfReferenceKey(final PfReferenceKey referenceKey) {
102 this(referenceKey.getParentKeyName(), referenceKey.getParentKeyVersion(), referenceKey.getParentLocalName(),
103 referenceKey.getLocalName());
107 * Constructor to create a null reference key for the specified parent concept key.
109 * @param pfConceptKey
110 * the parent concept key of this reference key
112 public PfReferenceKey(final PfConceptKey pfConceptKey) {
113 this(pfConceptKey.getName(), pfConceptKey.getVersion(), NULL_KEY_NAME, NULL_KEY_NAME);
117 * Constructor to create a reference key for the given parent concept key with the given local name.
119 * @param pfConceptKey
120 * the parent concept key of this reference key
122 * the local name of this reference key
124 public PfReferenceKey(final PfConceptKey pfConceptKey, final String localName) {
125 this(pfConceptKey, NULL_KEY_NAME, localName);
129 * Constructor to create a reference key for the given parent reference key with the given local name.
131 * @param parentReferenceKey
132 * the parent reference key of this reference key
134 * the local name of this reference key
136 public PfReferenceKey(final PfReferenceKey parentReferenceKey, final String localName) {
137 this(parentReferenceKey.getParentConceptKey(), parentReferenceKey.getLocalName(), localName);
141 * Constructor to create a reference key for the given parent reference key (specified by the parent reference key's
142 * concept key and local name) with the given local name.
144 * @param pfConceptKey
145 * the concept key of the parent reference key of this reference key
146 * @param parentLocalName
147 * the local name of the parent reference key of this reference key
149 * the local name of this reference key
151 public PfReferenceKey(final PfConceptKey pfConceptKey, final String parentLocalName, final String localName) {
152 this(pfConceptKey.getName(), pfConceptKey.getVersion(), parentLocalName, localName);
156 * Constructor to create a reference key for the given parent concept key (specified by the parent concept key's
157 * name and version) with the given local name.
159 * @param parentKeyName
160 * the name of the parent concept key of this reference key
161 * @param parentKeyVersion
162 * the version of the parent concept key of this reference key
164 * the local name of this reference key
166 public PfReferenceKey(final String parentKeyName, final String parentKeyVersion, final String localName) {
167 this(parentKeyName, parentKeyVersion, NULL_KEY_NAME, localName);
171 * Constructor to create a reference key for the given parent key (specified by the parent key's name, version nad
172 * local name) with the given local name.
174 * @param parentKeyName
175 * the parent key name of this reference key
176 * @param parentKeyVersion
177 * the parent key version of this reference key
178 * @param parentLocalName
179 * the parent local name of this reference key
181 * the local name of this reference key
183 public PfReferenceKey(final String parentKeyName, final String parentKeyVersion, final String parentLocalName,
184 final String localName) {
186 this.parentKeyName = Assertions.validateStringParameter(PARENT_KEY_NAME, parentKeyName, NAME_REGEXP);
187 this.parentKeyVersion = Assertions.validateStringParameter(PARENT_KEY_VERSION, parentKeyVersion,
189 this.parentLocalName = Assertions.validateStringParameter(PARENT_LOCAL_NAME, parentLocalName,
191 this.localName = Assertions.validateStringParameter(LOCAL_NAME, localName, LOCAL_NAME_REGEXP);
195 * Constructor to create a key from the specified key ID.
198 * the key ID in a format that respects the KEY_ID_REGEXP
200 public PfReferenceKey(final String id) {
201 final String conditionedId = Assertions.validateStringParameter("id", id, REFERENCE_KEY_ID_REGEXP);
203 // Split on colon, if the id passes the regular expression test above
204 // it'll have just three colons separating the parent name,
205 // parent version, parent local name, and and local name
206 // No need for range checks or size checks on the array
207 final String[] nameVersionNameArray = conditionedId.split(":");
209 // Initiate the new key
210 parentKeyName = Assertions.validateStringParameter(PARENT_KEY_NAME, nameVersionNameArray[PARENT_NAME_FIELD],
212 parentKeyVersion = Assertions.validateStringParameter(PARENT_KEY_VERSION,
213 nameVersionNameArray[PARENT_VERSION_FIELD], VERSION_REGEXP);
214 parentLocalName = Assertions.validateStringParameter(PARENT_LOCAL_NAME,
215 nameVersionNameArray[PARENT_LOCAL_NAME_FIELD], LOCAL_NAME_REGEXP);
216 localName = Assertions.validateStringParameter(LOCAL_NAME, nameVersionNameArray[LOCAL_NAME_FIELD],
221 * Get a null reference key.
223 * @return a null reference key
225 public static PfReferenceKey getNullKey() {
226 return new PfReferenceKey(PfKey.NULL_KEY_NAME, PfKey.NULL_KEY_VERSION, PfKey.NULL_KEY_NAME,
227 PfKey.NULL_KEY_NAME);
231 public PfReferenceKey getKey() {
236 public List<PfKey> getKeys() {
237 final List<PfKey> keyList = new ArrayList<>();
238 keyList.add(getKey());
243 public String getId() {
244 return parentKeyName + ':' + parentKeyVersion + ':' + parentLocalName + ':' + localName;
248 public boolean isNullKey() {
249 return this.equals(PfReferenceKey.getNullKey());
253 * Gets the parent concept key of this reference key.
255 * @return the parent concept key of this reference key
257 public PfConceptKey getParentConceptKey() {
258 return new PfConceptKey(parentKeyName, parentKeyVersion);
262 * Gets the parent reference key of this reference key.
264 * @return the parent reference key of this reference key
266 public PfReferenceKey getParentReferenceKey() {
267 return new PfReferenceKey(parentKeyName, parentKeyVersion, parentLocalName);
271 * Sets the parent concept key of this reference key.
274 * the parent concept key of this reference key
276 public void setParentConceptKey(final PfConceptKey parentKey) {
277 Assertions.argumentNotNull(parentKey, "parentKey may not be null");
279 parentKeyName = parentKey.getName();
280 parentKeyVersion = parentKey.getVersion();
281 parentLocalName = NULL_KEY_NAME;
285 * Sets the parent reference key of this reference key.
288 * the parent reference key of this reference key
290 public void setParentReferenceKey(final PfReferenceKey parentKey) {
291 Assertions.argumentNotNull(parentKey, "parentKey may not be null");
293 parentKeyName = parentKey.getParentKeyName();
294 parentKeyVersion = parentKey.getParentKeyVersion();
295 parentLocalName = parentKey.getLocalName();
299 public PfKey.Compatibility getCompatibility(final PfKey otherKey) {
300 if (!(otherKey instanceof PfReferenceKey)) {
301 return Compatibility.DIFFERENT;
303 final PfReferenceKey otherReferenceKey = (PfReferenceKey) otherKey;
305 return this.getParentConceptKey().getCompatibility(otherReferenceKey.getParentConceptKey());
309 public boolean isCompatible(@NonNull final PfKey otherKey) {
310 if (!(otherKey instanceof PfReferenceKey)) {
313 final PfReferenceKey otherReferenceKey = (PfReferenceKey) otherKey;
315 return this.getParentConceptKey().isCompatible(otherReferenceKey.getParentConceptKey());
319 public int getMajorVersion() {
320 return this.getParentConceptKey().getMajorVersion();
324 public int getMinorVersion() {
325 return this.getParentConceptKey().getMinorVersion();
329 public int getPatchVersion() {
330 return this.getParentConceptKey().getPatchVersion();
335 public boolean isNewerThan(@NonNull final PfKey otherKey) {
336 Assertions.instanceOf(otherKey, PfReferenceKey.class);
338 final PfReferenceKey otherReferenceKey = (PfReferenceKey) otherKey;
340 return this.getParentConceptKey().isNewerThan(otherReferenceKey.getParentConceptKey());
344 public PfValidationResult validate(final PfValidationResult result) {
345 final String parentNameValidationErrorMessage = Assertions.getStringParameterValidationMessage(PARENT_KEY_NAME,
346 parentKeyName, NAME_REGEXP);
347 if (parentNameValidationErrorMessage != null) {
348 result.addValidationMessage(new PfValidationMessage(this, this.getClass(), ValidationResult.INVALID,
349 "parentKeyName invalid-" + parentNameValidationErrorMessage));
352 final String parentKeyVersionValidationErrorMessage = Assertions
353 .getStringParameterValidationMessage(PARENT_KEY_VERSION, parentKeyVersion, VERSION_REGEXP);
354 if (parentKeyVersionValidationErrorMessage != null) {
355 result.addValidationMessage(new PfValidationMessage(this, this.getClass(), ValidationResult.INVALID,
356 "parentKeyVersion invalid-" + parentKeyVersionValidationErrorMessage));
359 final String parentLocalNameValidationErrorMessage = Assertions
360 .getStringParameterValidationMessage(PARENT_LOCAL_NAME, parentLocalName, LOCAL_NAME_REGEXP);
361 if (parentLocalNameValidationErrorMessage != null) {
362 result.addValidationMessage(new PfValidationMessage(this, this.getClass(), ValidationResult.INVALID,
363 "parentLocalName invalid-" + parentLocalNameValidationErrorMessage));
366 final String localNameValidationErrorMessage = Assertions.getStringParameterValidationMessage(LOCAL_NAME,
367 localName, LOCAL_NAME_REGEXP);
368 if (localNameValidationErrorMessage != null) {
369 result.addValidationMessage(new PfValidationMessage(this, this.getClass(), ValidationResult.INVALID,
370 "localName invalid-" + localNameValidationErrorMessage));
377 public void clean() {
378 parentKeyName = Assertions.validateStringParameter(PARENT_KEY_NAME, parentKeyName, NAME_REGEXP);
379 parentKeyVersion = Assertions.validateStringParameter(PARENT_KEY_VERSION, parentKeyVersion, VERSION_REGEXP);
380 parentLocalName = Assertions.validateStringParameter(PARENT_LOCAL_NAME, parentLocalName, LOCAL_NAME_REGEXP);
381 localName = Assertions.validateStringParameter(LOCAL_NAME, localName, LOCAL_NAME_REGEXP);
385 public PfConcept copyTo(final PfConcept target) {
386 Assertions.argumentNotNull(target, "target may not be null");
388 final Object copyObject = target;
389 Assertions.instanceOf(copyObject, PfReferenceKey.class);
391 final PfReferenceKey copy = ((PfReferenceKey) copyObject);
392 copy.setParentKeyName(parentKeyName);
393 copy.setParentKeyVersion(parentKeyVersion);
394 copy.setLocalName(localName);
395 copy.setParentLocalName(parentLocalName);
401 public int compareTo(final PfConcept otherObj) {
402 Assertions.argumentNotNull(otherObj, "comparison object may not be null");
404 if (this == otherObj) {
407 if (getClass() != otherObj.getClass()) {
408 return this.hashCode() - otherObj.hashCode();
411 final PfReferenceKey other = (PfReferenceKey) otherObj;
412 if (!parentKeyName.equals(other.parentKeyName)) {
413 return parentKeyName.compareTo(other.parentKeyName);
415 if (!parentKeyVersion.equals(other.parentKeyVersion)) {
416 return parentKeyVersion.compareTo(other.parentKeyVersion);
418 if (!parentLocalName.equals(other.parentLocalName)) {
419 return parentLocalName.compareTo(other.parentLocalName);
421 return localName.compareTo(other.localName);