2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2019, 2021, 2023 Nordix Foundation.
4 * Modifications Copyright (C) 2019-2021 AT&T Intellectual Property. All rights reserved.
5 * ================================================================================
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
18 * SPDX-License-Identifier: Apache-2.0
19 * ============LICENSE_END=========================================================
22 package org.onap.policy.models.base;
24 import jakarta.persistence.Column;
25 import jakarta.persistence.Embeddable;
26 import java.io.Serial;
27 import java.util.ArrayList;
28 import java.util.List;
30 import lombok.EqualsAndHashCode;
31 import lombok.NonNull;
32 import org.onap.policy.common.parameters.annotations.NotNull;
33 import org.onap.policy.common.parameters.annotations.Pattern;
34 import org.onap.policy.common.utils.validation.Assertions;
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";
63 private static final long serialVersionUID = 8932717618579392561L;
66 * Regular expression to specify the structure of local names in reference keys.
68 public static final String LOCAL_NAME_REGEXP = "[A-Za-z0-9\\-_\\.]+|^$";
71 * Regular expression to specify the structure of IDs in reference keys.
73 public static final String REFERENCE_KEY_ID_REGEXP =
74 "[A-Za-z0-9\\-_]+:[0-9].[0-9].[0-9]:[A-Za-z0-9\\-_]+:[A-Za-z0-9\\-_]+";
76 private static final int PARENT_NAME_FIELD = 0;
77 private static final int PARENT_VERSION_FIELD = 1;
78 private static final int PARENT_LOCAL_NAME_FIELD = 2;
79 private static final int LOCAL_NAME_FIELD = 3;
81 @Column(name = PARENT_KEY_NAME, length = 120)
83 @Pattern(regexp = NAME_REGEXP)
84 private String parentKeyName;
86 @Column(name = PARENT_KEY_VERSION, length = 15)
88 @Pattern(regexp = VERSION_REGEXP)
89 private String parentKeyVersion;
91 @Column(name = PARENT_LOCAL_NAME, length = 120)
93 @Pattern(regexp = LOCAL_NAME_REGEXP)
94 private String parentLocalName;
96 @Column(name = LOCAL_NAME, length = 120)
98 @Pattern(regexp = LOCAL_NAME_REGEXP)
99 private String localName;
102 * The default constructor creates a null reference key.
104 public PfReferenceKey() {
105 this(NULL_KEY_NAME, NULL_KEY_VERSION, NULL_KEY_NAME, NULL_KEY_NAME);
109 * The Copy Constructor creates a key by copying another key.
111 * @param referenceKey the reference key to copy from
113 public PfReferenceKey(final PfReferenceKey referenceKey) {
114 this(referenceKey.getParentKeyName(), referenceKey.getParentKeyVersion(), referenceKey.getParentLocalName(),
115 referenceKey.getLocalName());
119 * Constructor to create a null reference key for the specified parent concept key.
121 * @param pfConceptKey the parent concept key of this reference key
123 public PfReferenceKey(final PfConceptKey pfConceptKey) {
124 this(pfConceptKey.getName(), pfConceptKey.getVersion(), NULL_KEY_NAME, NULL_KEY_NAME);
128 * Constructor to create a reference key for the given parent concept key with the given local name.
130 * @param pfConceptKey the parent concept key of this reference key
131 * @param localName the local name of this reference key
133 public PfReferenceKey(final PfConceptKey pfConceptKey, final String localName) {
134 this(pfConceptKey, NULL_KEY_NAME, localName);
138 * Constructor to create a reference key for the given parent reference key with the given local name.
140 * @param parentReferenceKey the parent reference key of this reference key
141 * @param localName the local name of this reference key
143 public PfReferenceKey(final PfReferenceKey parentReferenceKey, final String localName) {
144 this(parentReferenceKey.getParentConceptKey(), parentReferenceKey.getLocalName(), localName);
148 * Constructor to create a reference key for the given parent reference key (specified by the parent reference key's
149 * concept key and local name) with the given local name.
151 * @param pfConceptKey the concept key of the parent reference key of this reference key
152 * @param parentLocalName the local name of the parent reference key of this reference key
153 * @param localName the local name of this reference key
155 public PfReferenceKey(final PfConceptKey pfConceptKey, final String parentLocalName, final String localName) {
156 this(pfConceptKey.getName(), pfConceptKey.getVersion(), parentLocalName, localName);
160 * Constructor to create a reference key for the given parent concept key (specified by the parent concept key's
161 * name and version) with the given local name.
163 * @param parentKeyName the name of the parent concept key of this reference key
164 * @param parentKeyVersion the version of the parent concept key of this reference key
165 * @param localName the local name of this reference key
167 public PfReferenceKey(final String parentKeyName, final String parentKeyVersion, final String localName) {
168 this(parentKeyName, parentKeyVersion, NULL_KEY_NAME, localName);
172 * Constructor to create a reference key for the given parent key (specified by the parent key's name, version nad
173 * local name) with the given local name.
175 * @param parentKeyName the parent key name of this reference key
176 * @param parentKeyVersion the parent key version of this reference key
177 * @param parentLocalName the parent local name of this reference key
178 * @param localName the local name of this reference key
180 public PfReferenceKey(final String parentKeyName, final String parentKeyVersion, final String parentLocalName,
181 final String localName) {
183 this.parentKeyName = Assertions.validateStringParameter(PARENT_KEY_NAME, parentKeyName, NAME_REGEXP);
184 this.parentKeyVersion = Assertions.validateStringParameter(PARENT_KEY_VERSION, parentKeyVersion,
186 this.parentLocalName = Assertions.validateStringParameter(PARENT_LOCAL_NAME, parentLocalName,
188 this.localName = Assertions.validateStringParameter(LOCAL_NAME, localName, LOCAL_NAME_REGEXP);
192 * Constructor to create a key from the specified key ID.
194 * @param id the key ID in a format that respects the KEY_ID_REGEXP
196 public PfReferenceKey(final String id) {
197 final var conditionedId = Assertions.validateStringParameter("id", id, REFERENCE_KEY_ID_REGEXP);
199 // Split on colon, if the id passes the regular expression test above
200 // it'll have just three colons separating the parent name,
201 // parent version, parent local name, and and local name
202 // No need for range checks or size checks on the array
203 final String[] nameVersionNameArray = conditionedId.split(":");
205 // Initiate the new key
206 parentKeyName = Assertions.validateStringParameter(PARENT_KEY_NAME, nameVersionNameArray[PARENT_NAME_FIELD],
208 parentKeyVersion = Assertions.validateStringParameter(PARENT_KEY_VERSION,
209 nameVersionNameArray[PARENT_VERSION_FIELD], VERSION_REGEXP);
210 parentLocalName = Assertions.validateStringParameter(PARENT_LOCAL_NAME,
211 nameVersionNameArray[PARENT_LOCAL_NAME_FIELD], LOCAL_NAME_REGEXP);
212 localName = Assertions.validateStringParameter(LOCAL_NAME, nameVersionNameArray[LOCAL_NAME_FIELD],
217 * Get a null reference key.
219 * @return a null reference key
221 public static PfReferenceKey getNullKey() {
222 return new PfReferenceKey(PfKey.NULL_KEY_NAME, PfKey.NULL_KEY_VERSION, PfKey.NULL_KEY_NAME,
223 PfKey.NULL_KEY_NAME);
227 public PfReferenceKey getKey() {
232 public List<PfKey> getKeys() {
233 final List<PfKey> keyList = new ArrayList<>();
234 keyList.add(getKey());
239 public String getId() {
240 return parentKeyName + ':' + parentKeyVersion + ':' + parentLocalName + ':' + localName;
244 public boolean isNullKey() {
245 return (PfKey.NULL_KEY_NAME.equals(this.getParentKeyName()) && PfKey.NULL_KEY_VERSION
246 .equals(this.getParentKeyVersion()) && PfKey.NULL_KEY_NAME.equals(this.getParentLocalName())
247 && PfKey.NULL_KEY_NAME.equals(this.getLocalName()));
251 * Gets the parent concept key of this reference key.
253 * @return the parent concept key of this reference key
255 public PfConceptKey getParentConceptKey() {
256 return new PfConceptKey(parentKeyName, parentKeyVersion);
260 * Gets the parent reference key of this reference key.
262 * @return the parent reference key of this reference key
264 public PfReferenceKey getParentReferenceKey() {
265 return new PfReferenceKey(parentKeyName, parentKeyVersion, parentLocalName);
269 * Sets the parent concept key of this reference key.
271 * @param parentKey the parent concept key of this reference key
273 public void setParentConceptKey(final PfConceptKey parentKey) {
274 Assertions.argumentNotNull(parentKey, "parentKey may not be null");
276 parentKeyName = parentKey.getName();
277 parentKeyVersion = parentKey.getVersion();
278 parentLocalName = NULL_KEY_NAME;
282 * Sets the parent reference key of this reference key.
284 * @param parentKey the parent reference key of this reference key
286 public void setParentReferenceKey(final PfReferenceKey parentKey) {
287 Assertions.argumentNotNull(parentKey, "parentKey may not be null");
289 parentKeyName = parentKey.getParentKeyName();
290 parentKeyVersion = parentKey.getParentKeyVersion();
291 parentLocalName = parentKey.getLocalName();
295 public PfKey.Compatibility getCompatibility(@NonNull final PfKey otherKey) {
296 if (!(otherKey instanceof PfReferenceKey otherReferenceKey)) {
297 return Compatibility.DIFFERENT;
300 return this.getParentConceptKey().getCompatibility(otherReferenceKey.getParentConceptKey());
304 public boolean isCompatible(@NonNull final PfKey otherKey) {
305 if (!(otherKey instanceof PfReferenceKey otherReferenceKey)) {
309 return this.getParentConceptKey().isCompatible(otherReferenceKey.getParentConceptKey());
313 public int getMajorVersion() {
314 return this.getParentConceptKey().getMajorVersion();
318 public int getMinorVersion() {
319 return this.getParentConceptKey().getMinorVersion();
323 public int getPatchVersion() {
324 return this.getParentConceptKey().getPatchVersion();
329 public boolean isNewerThan(@NonNull final PfKey otherKey) {
330 Assertions.instanceOf(otherKey, PfReferenceKey.class);
332 final PfReferenceKey otherReferenceKey = (PfReferenceKey) otherKey;
334 return this.getParentConceptKey().isNewerThan(otherReferenceKey.getParentConceptKey());
338 public void clean() {
339 parentKeyName = Assertions.validateStringParameter(PARENT_KEY_NAME, parentKeyName, NAME_REGEXP);
340 parentKeyVersion = Assertions.validateStringParameter(PARENT_KEY_VERSION, parentKeyVersion, VERSION_REGEXP);
341 parentLocalName = Assertions.validateStringParameter(PARENT_LOCAL_NAME, parentLocalName, LOCAL_NAME_REGEXP);
342 localName = Assertions.validateStringParameter(LOCAL_NAME, localName, LOCAL_NAME_REGEXP);
346 public int compareTo(@NonNull final PfConcept otherObj) {
347 Assertions.argumentNotNull(otherObj, "comparison object may not be null");
349 if (this == otherObj) {
352 if (getClass() != otherObj.getClass()) {
353 return getClass().getName().compareTo(otherObj.getClass().getName());
356 final PfReferenceKey other = (PfReferenceKey) otherObj;
357 if (!parentKeyName.equals(other.parentKeyName)) {
358 return parentKeyName.compareTo(other.parentKeyName);
360 if (!parentKeyVersion.equals(other.parentKeyVersion)) {
361 return parentKeyVersion.compareTo(other.parentKeyVersion);
363 if (!parentLocalName.equals(other.parentLocalName)) {
364 return parentLocalName.compareTo(other.parentLocalName);
366 return localName.compareTo(other.localName);