acbebf959b97ec5334d6de804f56a1be3a0e703b
[policy/models.git] / models-base / src / main / java / org / onap / policy / models / base / PfReferenceKey.java
1 /*-
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2019,2021 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 java.util.ArrayList;
25 import java.util.List;
26 import javax.persistence.Column;
27 import javax.persistence.Embeddable;
28 import lombok.Data;
29 import lombok.EqualsAndHashCode;
30 import lombok.NonNull;
31 import org.onap.policy.common.parameters.annotations.NotNull;
32 import org.onap.policy.common.parameters.annotations.Pattern;
33 import org.onap.policy.common.utils.validation.Assertions;
34
35 /**
36  * A reference key identifies entities in the system that are contained in other entities. Every contained concept in
37  * the system must have an {@link PfReferenceKey} to identify it. Non-contained first order concepts are identified
38  * using an {@link PfConceptKey} key.
39  *
40  * <p>An {@link PfReferenceKey} contains an {@link PfConceptKey} key reference to the first order entity that contains
41  * it. The local name of the reference key must uniquely identify the referenced concept among those concepts contained
42  * in the reference key's parent. In other words, if a parent concept has more than one child, the local name in the key
43  * of all its children must be unique.
44  *
45  * <p>If a reference key's parent is itself a reference key, then the parent's local name must be set in the reference
46  * key. If the parent is a first order concept, then the parent's local name in the key will be set to NULL.
47  *
48  * <p>Key validation checks that the parent name and parent version fields match the NAME_REGEXP and
49  * VERSION_REGEXP regular expressions respectively and that the local name fields match the
50  * LOCAL_NAME_REGEXP regular expression.
51  */
52 @Embeddable
53 @Data
54 @EqualsAndHashCode(callSuper = false)
55 public class PfReferenceKey extends PfKey {
56     private static final String PARENT_KEY_NAME = "parentKeyName";
57     private static final String PARENT_KEY_VERSION = "parentKeyVersion";
58     private static final String PARENT_LOCAL_NAME = "parentLocalName";
59     private static final String LOCAL_NAME = "localName";
60
61     private static final long serialVersionUID = 8932717618579392561L;
62
63     /** Regular expression to specify the structure of local names in reference keys. */
64     public static final String LOCAL_NAME_REGEXP = "[A-Za-z0-9\\-_\\.]+|^$";
65
66     /** Regular expression to specify the structure of IDs in reference keys. */
67     public static final String REFERENCE_KEY_ID_REGEXP =
68                     "[A-Za-z0-9\\-_]+:[0-9].[0-9].[0-9]:[A-Za-z0-9\\-_]+:[A-Za-z0-9\\-_]+";
69
70     private static final int PARENT_NAME_FIELD = 0;
71     private static final int PARENT_VERSION_FIELD = 1;
72     private static final int PARENT_LOCAL_NAME_FIELD = 2;
73     private static final int LOCAL_NAME_FIELD = 3;
74
75     @Column(name = PARENT_KEY_NAME, length = 120)
76     @NotNull
77     @Pattern(regexp = NAME_REGEXP)
78     private String parentKeyName;
79
80     @Column(name = PARENT_KEY_VERSION, length = 15)
81     @NotNull
82     @Pattern(regexp = VERSION_REGEXP)
83     private String parentKeyVersion;
84
85     @Column(name = PARENT_LOCAL_NAME, length = 120)
86     @NotNull
87     @Pattern(regexp = LOCAL_NAME_REGEXP)
88     private String parentLocalName;
89
90     @Column(name = LOCAL_NAME, length = 120)
91     @NotNull
92     @Pattern(regexp = LOCAL_NAME_REGEXP)
93     private String localName;
94
95     /**
96      * The default constructor creates a null reference key.
97      */
98     public PfReferenceKey() {
99         this(NULL_KEY_NAME, NULL_KEY_VERSION, NULL_KEY_NAME, NULL_KEY_NAME);
100     }
101
102     /**
103      * The Copy Constructor creates a key by copying another key.
104      *
105      * @param referenceKey
106      *        the reference key to copy from
107      */
108     public PfReferenceKey(final PfReferenceKey referenceKey) {
109         this(referenceKey.getParentKeyName(), referenceKey.getParentKeyVersion(), referenceKey.getParentLocalName(),
110                         referenceKey.getLocalName());
111     }
112
113     /**
114      * Constructor to create a null reference key for the specified parent concept key.
115      *
116      * @param pfConceptKey
117      *        the parent concept key of this reference key
118      */
119     public PfReferenceKey(final PfConceptKey pfConceptKey) {
120         this(pfConceptKey.getName(), pfConceptKey.getVersion(), NULL_KEY_NAME, NULL_KEY_NAME);
121     }
122
123     /**
124      * Constructor to create a reference key for the given parent concept key with the given local name.
125      *
126      * @param pfConceptKey
127      *        the parent concept key of this reference key
128      * @param localName
129      *        the local name of this reference key
130      */
131     public PfReferenceKey(final PfConceptKey pfConceptKey, final String localName) {
132         this(pfConceptKey, NULL_KEY_NAME, localName);
133     }
134
135     /**
136      * Constructor to create a reference key for the given parent reference key with the given local name.
137      *
138      * @param parentReferenceKey
139      *        the parent reference key of this reference key
140      * @param localName
141      *        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
152      *        the concept key of the parent reference key of this reference key
153      * @param parentLocalName
154      *        the local name of the parent reference key of this reference key
155      * @param localName
156      *        the local name of this reference key
157      */
158     public PfReferenceKey(final PfConceptKey pfConceptKey, final String parentLocalName, final String localName) {
159         this(pfConceptKey.getName(), pfConceptKey.getVersion(), parentLocalName, localName);
160     }
161
162     /**
163      * Constructor to create a reference key for the given parent concept key (specified by the parent concept key's
164      * name and version) with the given local name.
165      *
166      * @param parentKeyName
167      *        the name of the parent concept key of this reference key
168      * @param parentKeyVersion
169      *        the version of the parent concept key of this reference key
170      * @param localName
171      *        the local name of this reference key
172      */
173     public PfReferenceKey(final String parentKeyName, final String parentKeyVersion, final String localName) {
174         this(parentKeyName, parentKeyVersion, NULL_KEY_NAME, localName);
175     }
176
177     /**
178      * Constructor to create a reference key for the given parent key (specified by the parent key's name, version nad
179      * local name) with the given local name.
180      *
181      * @param parentKeyName
182      *        the parent key name of this reference key
183      * @param parentKeyVersion
184      *        the parent key version of this reference key
185      * @param parentLocalName
186      *        the parent local name of this reference key
187      * @param localName
188      *        the local name of this reference key
189      */
190     public PfReferenceKey(final String parentKeyName, final String parentKeyVersion, final String parentLocalName,
191                     final String localName) {
192         super();
193         this.parentKeyName = Assertions.validateStringParameter(PARENT_KEY_NAME, parentKeyName, NAME_REGEXP);
194         this.parentKeyVersion = Assertions.validateStringParameter(PARENT_KEY_VERSION, parentKeyVersion,
195                         VERSION_REGEXP);
196         this.parentLocalName = Assertions.validateStringParameter(PARENT_LOCAL_NAME, parentLocalName,
197                         LOCAL_NAME_REGEXP);
198         this.localName = Assertions.validateStringParameter(LOCAL_NAME, localName, LOCAL_NAME_REGEXP);
199     }
200
201     /**
202      * Constructor to create a key from the specified key ID.
203      *
204      * @param id
205      *        the key ID in a format that respects the KEY_ID_REGEXP
206      */
207     public PfReferenceKey(final String id) {
208         final var conditionedId = Assertions.validateStringParameter("id", id, REFERENCE_KEY_ID_REGEXP);
209
210         // Split on colon, if the id passes the regular expression test above
211         // it'll have just three colons separating the parent name,
212         // parent version, parent local name, and and local name
213         // No need for range checks or size checks on the array
214         final String[] nameVersionNameArray = conditionedId.split(":");
215
216         // Initiate the new key
217         parentKeyName = Assertions.validateStringParameter(PARENT_KEY_NAME, nameVersionNameArray[PARENT_NAME_FIELD],
218                         NAME_REGEXP);
219         parentKeyVersion = Assertions.validateStringParameter(PARENT_KEY_VERSION,
220                         nameVersionNameArray[PARENT_VERSION_FIELD], VERSION_REGEXP);
221         parentLocalName = Assertions.validateStringParameter(PARENT_LOCAL_NAME,
222                         nameVersionNameArray[PARENT_LOCAL_NAME_FIELD], LOCAL_NAME_REGEXP);
223         localName = Assertions.validateStringParameter(LOCAL_NAME, nameVersionNameArray[LOCAL_NAME_FIELD],
224                         LOCAL_NAME_REGEXP);
225     }
226
227     /**
228      * Get a null reference key.
229      *
230      * @return a null reference key
231      */
232     public static PfReferenceKey getNullKey() {
233         return new PfReferenceKey(PfKey.NULL_KEY_NAME, PfKey.NULL_KEY_VERSION, PfKey.NULL_KEY_NAME,
234                         PfKey.NULL_KEY_NAME);
235     }
236
237     @Override
238     public PfReferenceKey getKey() {
239         return this;
240     }
241
242     @Override
243     public List<PfKey> getKeys() {
244         final List<PfKey> keyList = new ArrayList<>();
245         keyList.add(getKey());
246         return keyList;
247     }
248
249     @Override
250     public String getId() {
251         return parentKeyName + ':' + parentKeyVersion + ':' + parentLocalName + ':' + localName;
252     }
253
254     @Override
255     public boolean isNullKey() {
256         return (PfKey.NULL_KEY_NAME.equals(this.getParentKeyName()) && PfKey.NULL_KEY_VERSION
257             .equals(this.getParentKeyVersion()) && PfKey.NULL_KEY_NAME.equals(this.getParentLocalName())
258             && PfKey.NULL_KEY_NAME.equals(this.getLocalName()));
259     }
260
261     /**
262      * Gets the parent concept key of this reference key.
263      *
264      * @return the parent concept key of this reference key
265      */
266     public PfConceptKey getParentConceptKey() {
267         return new PfConceptKey(parentKeyName, parentKeyVersion);
268     }
269
270     /**
271      * Gets the parent reference key of this reference key.
272      *
273      * @return the parent reference key of this reference key
274      */
275     public PfReferenceKey getParentReferenceKey() {
276         return new PfReferenceKey(parentKeyName, parentKeyVersion, parentLocalName);
277     }
278
279     /**
280      * Sets the parent concept key of this reference key.
281      *
282      * @param parentKey
283      *        the parent concept key of this reference key
284      */
285     public void setParentConceptKey(final PfConceptKey parentKey) {
286         Assertions.argumentNotNull(parentKey, "parentKey may not be null");
287
288         parentKeyName = parentKey.getName();
289         parentKeyVersion = parentKey.getVersion();
290         parentLocalName = NULL_KEY_NAME;
291     }
292
293     /**
294      * Sets the parent reference key of this reference key.
295      *
296      * @param parentKey
297      *        the parent reference key of this reference key
298      */
299     public void setParentReferenceKey(final PfReferenceKey parentKey) {
300         Assertions.argumentNotNull(parentKey, "parentKey may not be null");
301
302         parentKeyName = parentKey.getParentKeyName();
303         parentKeyVersion = parentKey.getParentKeyVersion();
304         parentLocalName = parentKey.getLocalName();
305     }
306
307     @Override
308     public PfKey.Compatibility getCompatibility(final PfKey otherKey) {
309         if (!(otherKey instanceof PfReferenceKey)) {
310             return Compatibility.DIFFERENT;
311         }
312         final PfReferenceKey otherReferenceKey = (PfReferenceKey) otherKey;
313
314         return this.getParentConceptKey().getCompatibility(otherReferenceKey.getParentConceptKey());
315     }
316
317     @Override
318     public boolean isCompatible(@NonNull final PfKey otherKey) {
319         if (!(otherKey instanceof PfReferenceKey)) {
320             return false;
321         }
322         final PfReferenceKey otherReferenceKey = (PfReferenceKey) otherKey;
323
324         return this.getParentConceptKey().isCompatible(otherReferenceKey.getParentConceptKey());
325     }
326
327     @Override
328     public int getMajorVersion() {
329         return this.getParentConceptKey().getMajorVersion();
330     }
331
332     @Override
333     public int getMinorVersion() {
334         return this.getParentConceptKey().getMinorVersion();
335     }
336
337     @Override
338     public int getPatchVersion() {
339         return this.getParentConceptKey().getPatchVersion();
340     }
341
342
343     @Override
344     public boolean isNewerThan(@NonNull final PfKey otherKey) {
345         Assertions.instanceOf(otherKey, PfReferenceKey.class);
346
347         final PfReferenceKey otherReferenceKey = (PfReferenceKey) otherKey;
348
349         return this.getParentConceptKey().isNewerThan(otherReferenceKey.getParentConceptKey());
350     }
351
352     @Override
353     public void clean() {
354         parentKeyName = Assertions.validateStringParameter(PARENT_KEY_NAME, parentKeyName, NAME_REGEXP);
355         parentKeyVersion = Assertions.validateStringParameter(PARENT_KEY_VERSION, parentKeyVersion, VERSION_REGEXP);
356         parentLocalName = Assertions.validateStringParameter(PARENT_LOCAL_NAME, parentLocalName, LOCAL_NAME_REGEXP);
357         localName = Assertions.validateStringParameter(LOCAL_NAME, localName, LOCAL_NAME_REGEXP);
358     }
359
360     @Override
361     public int compareTo(final PfConcept otherObj) {
362         Assertions.argumentNotNull(otherObj, "comparison object may not be null");
363
364         if (this == otherObj) {
365             return 0;
366         }
367         if (getClass() != otherObj.getClass()) {
368             return getClass().getName().compareTo(otherObj.getClass().getName());
369         }
370
371         final PfReferenceKey other = (PfReferenceKey) otherObj;
372         if (!parentKeyName.equals(other.parentKeyName)) {
373             return parentKeyName.compareTo(other.parentKeyName);
374         }
375         if (!parentKeyVersion.equals(other.parentKeyVersion)) {
376             return parentKeyVersion.compareTo(other.parentKeyVersion);
377         }
378         if (!parentLocalName.equals(other.parentLocalName)) {
379             return parentLocalName.compareTo(other.parentLocalName);
380         }
381         return localName.compareTo(other.localName);
382     }
383 }