Java 17 Upgrade
[policy/models.git] / models-base / src / main / java / org / onap / policy / models / base / PfReferenceKey.java
1 /*-
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
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  *
18  * SPDX-License-Identifier: Apache-2.0
19  * ============LICENSE_END=========================================================
20  */
21
22 package org.onap.policy.models.base;
23
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;
29 import lombok.Data;
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;
35
36 /**
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.
40  *
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.
45  *
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.
48  *
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.
52  */
53 @Embeddable
54 @Data
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";
61
62     @Serial
63     private static final long serialVersionUID = 8932717618579392561L;
64
65     /**
66      * Regular expression to specify the structure of local names in reference keys.
67      */
68     public static final String LOCAL_NAME_REGEXP = "[A-Za-z0-9\\-_\\.]+|^$";
69
70     /**
71      * Regular expression to specify the structure of IDs in reference keys.
72      */
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\\-_]+";
75
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;
80
81     @Column(name = PARENT_KEY_NAME, length = 120)
82     @NotNull
83     @Pattern(regexp = NAME_REGEXP)
84     private String parentKeyName;
85
86     @Column(name = PARENT_KEY_VERSION, length = 15)
87     @NotNull
88     @Pattern(regexp = VERSION_REGEXP)
89     private String parentKeyVersion;
90
91     @Column(name = PARENT_LOCAL_NAME, length = 120)
92     @NotNull
93     @Pattern(regexp = LOCAL_NAME_REGEXP)
94     private String parentLocalName;
95
96     @Column(name = LOCAL_NAME, length = 120)
97     @NotNull
98     @Pattern(regexp = LOCAL_NAME_REGEXP)
99     private String localName;
100
101     /**
102      * The default constructor creates a null reference key.
103      */
104     public PfReferenceKey() {
105         this(NULL_KEY_NAME, NULL_KEY_VERSION, NULL_KEY_NAME, NULL_KEY_NAME);
106     }
107
108     /**
109      * The Copy Constructor creates a key by copying another key.
110      *
111      * @param referenceKey the reference key to copy from
112      */
113     public PfReferenceKey(final PfReferenceKey referenceKey) {
114         this(referenceKey.getParentKeyName(), referenceKey.getParentKeyVersion(), referenceKey.getParentLocalName(),
115             referenceKey.getLocalName());
116     }
117
118     /**
119      * Constructor to create a null reference key for the specified parent concept key.
120      *
121      * @param pfConceptKey the parent concept key of this reference key
122      */
123     public PfReferenceKey(final PfConceptKey pfConceptKey) {
124         this(pfConceptKey.getName(), pfConceptKey.getVersion(), NULL_KEY_NAME, NULL_KEY_NAME);
125     }
126
127     /**
128      * Constructor to create a reference key for the given parent concept key with the given local name.
129      *
130      * @param pfConceptKey the parent concept key of this reference key
131      * @param localName    the local name of this reference key
132      */
133     public PfReferenceKey(final PfConceptKey pfConceptKey, final String localName) {
134         this(pfConceptKey, NULL_KEY_NAME, localName);
135     }
136
137     /**
138      * Constructor to create a reference key for the given parent reference key with the given local name.
139      *
140      * @param parentReferenceKey the parent reference key of this reference key
141      * @param localName          the local name of this reference key
142      */
143     public PfReferenceKey(final PfReferenceKey parentReferenceKey, final String localName) {
144         this(parentReferenceKey.getParentConceptKey(), parentReferenceKey.getLocalName(), localName);
145     }
146
147     /**
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.
150      *
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
154      */
155     public PfReferenceKey(final PfConceptKey pfConceptKey, final String parentLocalName, final String localName) {
156         this(pfConceptKey.getName(), pfConceptKey.getVersion(), parentLocalName, localName);
157     }
158
159     /**
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.
162      *
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
166      */
167     public PfReferenceKey(final String parentKeyName, final String parentKeyVersion, final String localName) {
168         this(parentKeyName, parentKeyVersion, NULL_KEY_NAME, localName);
169     }
170
171     /**
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.
174      *
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
179      */
180     public PfReferenceKey(final String parentKeyName, final String parentKeyVersion, final String parentLocalName,
181                           final String localName) {
182         super();
183         this.parentKeyName = Assertions.validateStringParameter(PARENT_KEY_NAME, parentKeyName, NAME_REGEXP);
184         this.parentKeyVersion = Assertions.validateStringParameter(PARENT_KEY_VERSION, parentKeyVersion,
185             VERSION_REGEXP);
186         this.parentLocalName = Assertions.validateStringParameter(PARENT_LOCAL_NAME, parentLocalName,
187             LOCAL_NAME_REGEXP);
188         this.localName = Assertions.validateStringParameter(LOCAL_NAME, localName, LOCAL_NAME_REGEXP);
189     }
190
191     /**
192      * Constructor to create a key from the specified key ID.
193      *
194      * @param id the key ID in a format that respects the KEY_ID_REGEXP
195      */
196     public PfReferenceKey(final String id) {
197         final var conditionedId = Assertions.validateStringParameter("id", id, REFERENCE_KEY_ID_REGEXP);
198
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(":");
204
205         // Initiate the new key
206         parentKeyName = Assertions.validateStringParameter(PARENT_KEY_NAME, nameVersionNameArray[PARENT_NAME_FIELD],
207             NAME_REGEXP);
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],
213             LOCAL_NAME_REGEXP);
214     }
215
216     /**
217      * Get a null reference key.
218      *
219      * @return a null reference key
220      */
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);
224     }
225
226     @Override
227     public PfReferenceKey getKey() {
228         return this;
229     }
230
231     @Override
232     public List<PfKey> getKeys() {
233         final List<PfKey> keyList = new ArrayList<>();
234         keyList.add(getKey());
235         return keyList;
236     }
237
238     @Override
239     public String getId() {
240         return parentKeyName + ':' + parentKeyVersion + ':' + parentLocalName + ':' + localName;
241     }
242
243     @Override
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()));
248     }
249
250     /**
251      * Gets the parent concept key of this reference key.
252      *
253      * @return the parent concept key of this reference key
254      */
255     public PfConceptKey getParentConceptKey() {
256         return new PfConceptKey(parentKeyName, parentKeyVersion);
257     }
258
259     /**
260      * Gets the parent reference key of this reference key.
261      *
262      * @return the parent reference key of this reference key
263      */
264     public PfReferenceKey getParentReferenceKey() {
265         return new PfReferenceKey(parentKeyName, parentKeyVersion, parentLocalName);
266     }
267
268     /**
269      * Sets the parent concept key of this reference key.
270      *
271      * @param parentKey the parent concept key of this reference key
272      */
273     public void setParentConceptKey(final PfConceptKey parentKey) {
274         Assertions.argumentNotNull(parentKey, "parentKey may not be null");
275
276         parentKeyName = parentKey.getName();
277         parentKeyVersion = parentKey.getVersion();
278         parentLocalName = NULL_KEY_NAME;
279     }
280
281     /**
282      * Sets the parent reference key of this reference key.
283      *
284      * @param parentKey the parent reference key of this reference key
285      */
286     public void setParentReferenceKey(final PfReferenceKey parentKey) {
287         Assertions.argumentNotNull(parentKey, "parentKey may not be null");
288
289         parentKeyName = parentKey.getParentKeyName();
290         parentKeyVersion = parentKey.getParentKeyVersion();
291         parentLocalName = parentKey.getLocalName();
292     }
293
294     @Override
295     public PfKey.Compatibility getCompatibility(@NonNull final PfKey otherKey) {
296         if (!(otherKey instanceof PfReferenceKey otherReferenceKey)) {
297             return Compatibility.DIFFERENT;
298         }
299
300         return this.getParentConceptKey().getCompatibility(otherReferenceKey.getParentConceptKey());
301     }
302
303     @Override
304     public boolean isCompatible(@NonNull final PfKey otherKey) {
305         if (!(otherKey instanceof PfReferenceKey otherReferenceKey)) {
306             return false;
307         }
308
309         return this.getParentConceptKey().isCompatible(otherReferenceKey.getParentConceptKey());
310     }
311
312     @Override
313     public int getMajorVersion() {
314         return this.getParentConceptKey().getMajorVersion();
315     }
316
317     @Override
318     public int getMinorVersion() {
319         return this.getParentConceptKey().getMinorVersion();
320     }
321
322     @Override
323     public int getPatchVersion() {
324         return this.getParentConceptKey().getPatchVersion();
325     }
326
327
328     @Override
329     public boolean isNewerThan(@NonNull final PfKey otherKey) {
330         Assertions.instanceOf(otherKey, PfReferenceKey.class);
331
332         final PfReferenceKey otherReferenceKey = (PfReferenceKey) otherKey;
333
334         return this.getParentConceptKey().isNewerThan(otherReferenceKey.getParentConceptKey());
335     }
336
337     @Override
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);
343     }
344
345     @Override
346     public int compareTo(@NonNull final PfConcept otherObj) {
347         Assertions.argumentNotNull(otherObj, "comparison object may not be null");
348
349         if (this == otherObj) {
350             return 0;
351         }
352         if (getClass() != otherObj.getClass()) {
353             return getClass().getName().compareTo(otherObj.getClass().getName());
354         }
355
356         final PfReferenceKey other = (PfReferenceKey) otherObj;
357         if (!parentKeyName.equals(other.parentKeyName)) {
358             return parentKeyName.compareTo(other.parentKeyName);
359         }
360         if (!parentKeyVersion.equals(other.parentKeyVersion)) {
361             return parentKeyVersion.compareTo(other.parentKeyVersion);
362         }
363         if (!parentLocalName.equals(other.parentLocalName)) {
364             return parentLocalName.compareTo(other.parentLocalName);
365         }
366         return localName.compareTo(other.localName);
367     }
368 }