Add DAO module for Models
[policy/models.git] / models-base / src / main / java / org / onap / policy / models / base / PfReferenceKey.java
1 /*-
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
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
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.
16  *
17  * SPDX-License-Identifier: Apache-2.0
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.policy.models.base;
22
23 import java.util.ArrayList;
24 import java.util.List;
25
26 import javax.persistence.Column;
27 import javax.persistence.Embeddable;
28
29 import lombok.Data;
30 import lombok.EqualsAndHashCode;
31
32 import org.onap.policy.common.utils.validation.Assertions;
33 import org.onap.policy.models.base.PfValidationResult.ValidationResult;
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)
76     private String parentKeyName;
77
78     @Column(name = PARENT_KEY_VERSION)
79     private String parentKeyVersion;
80
81     @Column(name = PARENT_LOCAL_NAME)
82     private String parentLocalName;
83
84     @Column(name = LOCAL_NAME)
85     private String localName;
86
87     /**
88      * The default constructor creates a null reference key.
89      */
90     public PfReferenceKey() {
91         this(NULL_KEY_NAME, NULL_KEY_VERSION, NULL_KEY_NAME, NULL_KEY_NAME);
92     }
93
94     /**
95      * The Copy Constructor creates a key by copying another key.
96      *
97      * @param referenceKey
98      *        the reference key to copy from
99      */
100     public PfReferenceKey(final PfReferenceKey referenceKey) {
101         this(referenceKey.getParentKeyName(), referenceKey.getParentKeyVersion(), referenceKey.getParentLocalName(),
102                         referenceKey.getLocalName());
103     }
104
105     /**
106      * Constructor to create a null reference key for the specified parent concept key.
107      *
108      * @param pfConceptKey
109      *        the parent concept key of this reference key
110      */
111     public PfReferenceKey(final PfConceptKey pfConceptKey) {
112         this(pfConceptKey.getName(), pfConceptKey.getVersion(), NULL_KEY_NAME, NULL_KEY_NAME);
113     }
114
115     /**
116      * Constructor to create a reference key for the given parent concept key with the given local name.
117      *
118      * @param pfConceptKey
119      *        the parent concept key of this reference key
120      * @param localName
121      *        the local name of this reference key
122      */
123     public PfReferenceKey(final PfConceptKey pfConceptKey, final String localName) {
124         this(pfConceptKey, NULL_KEY_NAME, localName);
125     }
126
127     /**
128      * Constructor to create a reference key for the given parent reference key with the given local name.
129      *
130      * @param parentReferenceKey
131      *        the parent reference key of this reference key
132      * @param localName
133      *        the local name of this reference key
134      */
135     public PfReferenceKey(final PfReferenceKey parentReferenceKey, final String localName) {
136         this(parentReferenceKey.getParentConceptKey(), parentReferenceKey.getLocalName(), localName);
137     }
138
139     /**
140      * Constructor to create a reference key for the given parent reference key (specified by the parent reference key's
141      * concept key and local name) with the given local name.
142      *
143      * @param pfConceptKey
144      *        the concept key of the parent reference key of this reference key
145      * @param parentLocalName
146      *        the local name of the parent reference key of this reference key
147      * @param localName
148      *        the local name of this reference key
149      */
150     public PfReferenceKey(final PfConceptKey pfConceptKey, final String parentLocalName, final String localName) {
151         this(pfConceptKey.getName(), pfConceptKey.getVersion(), parentLocalName, localName);
152     }
153
154     /**
155      * Constructor to create a reference key for the given parent concept key (specified by the parent concept key's
156      * name and version) with the given local name.
157      *
158      * @param parentKeyName
159      *        the name of the parent concept key of this reference key
160      * @param parentKeyVersion
161      *        the version of the parent concept key of this reference key
162      * @param localName
163      *        the local name of this reference key
164      */
165     public PfReferenceKey(final String parentKeyName, final String parentKeyVersion, final String localName) {
166         this(parentKeyName, parentKeyVersion, NULL_KEY_NAME, localName);
167     }
168
169     /**
170      * Constructor to create a reference key for the given parent key (specified by the parent key's name, version nad
171      * local name) with the given local name.
172      *
173      * @param parentKeyName
174      *        the parent key name of this reference key
175      * @param parentKeyVersion
176      *        the parent key version of this reference key
177      * @param parentLocalName
178      *        the parent local name of this reference key
179      * @param localName
180      *        the local name of this reference key
181      */
182     public PfReferenceKey(final String parentKeyName, final String parentKeyVersion, final String parentLocalName,
183                     final String localName) {
184         super();
185         this.parentKeyName = Assertions.validateStringParameter(PARENT_KEY_NAME, parentKeyName, NAME_REGEXP);
186         this.parentKeyVersion = Assertions.validateStringParameter(PARENT_KEY_VERSION, parentKeyVersion,
187                         VERSION_REGEXP);
188         this.parentLocalName = Assertions.validateStringParameter(PARENT_LOCAL_NAME, parentLocalName,
189                         LOCAL_NAME_REGEXP);
190         this.localName = Assertions.validateStringParameter(LOCAL_NAME, localName, LOCAL_NAME_REGEXP);
191     }
192
193     /**
194      * Constructor to create a key from the specified key ID.
195      *
196      * @param id
197      *        the key ID in a format that respects the KEY_ID_REGEXP
198      */
199     public PfReferenceKey(final String id) {
200         final String conditionedId = Assertions.validateStringParameter("id", id, REFERENCE_KEY_ID_REGEXP);
201
202         // Split on colon, if the id passes the regular expression test above
203         // it'll have just three colons separating the parent name,
204         // parent version, parent local name, and and local name
205         // No need for range checks or size checks on the array
206         final String[] nameVersionNameArray = conditionedId.split(":");
207
208         // Initiate the new key
209         parentKeyName = Assertions.validateStringParameter(PARENT_KEY_NAME, nameVersionNameArray[PARENT_NAME_FIELD],
210                         NAME_REGEXP);
211         parentKeyVersion = Assertions.validateStringParameter(PARENT_KEY_VERSION,
212                         nameVersionNameArray[PARENT_VERSION_FIELD], VERSION_REGEXP);
213         parentLocalName = Assertions.validateStringParameter(PARENT_LOCAL_NAME,
214                         nameVersionNameArray[PARENT_LOCAL_NAME_FIELD], LOCAL_NAME_REGEXP);
215         localName = Assertions.validateStringParameter(LOCAL_NAME, nameVersionNameArray[LOCAL_NAME_FIELD],
216                         LOCAL_NAME_REGEXP);
217     }
218
219     /**
220      * Get a null reference key.
221      *
222      * @return a null reference key
223      */
224     public static PfReferenceKey getNullKey() {
225         return new PfReferenceKey(PfKey.NULL_KEY_NAME, PfKey.NULL_KEY_VERSION, PfKey.NULL_KEY_NAME,
226                         PfKey.NULL_KEY_NAME);
227     }
228
229     @Override
230     public PfReferenceKey getKey() {
231         return this;
232     }
233
234     @Override
235     public List<PfKey> getKeys() {
236         final List<PfKey> keyList = new ArrayList<>();
237         keyList.add(getKey());
238         return keyList;
239     }
240
241     @Override
242     public String getId() {
243         return parentKeyName + ':' + parentKeyVersion + ':' + parentLocalName + ':' + localName;
244     }
245
246     /**
247      * Gets the parent concept key of this reference key.
248      *
249      * @return the parent concept key of this reference key
250      */
251     public PfConceptKey getParentConceptKey() {
252         return new PfConceptKey(parentKeyName, parentKeyVersion);
253     }
254
255     /**
256      * Gets the parent reference key of this reference key.
257      *
258      * @return the parent reference key of this reference key
259      */
260     public PfReferenceKey getParentReferenceKey() {
261         return new PfReferenceKey(parentKeyName, parentKeyVersion, parentLocalName);
262     }
263
264     /**
265      * Sets the parent concept key of this reference key.
266      *
267      * @param parentKey
268      *        the parent concept key of this reference key
269      */
270     public void setParentConceptKey(final PfConceptKey parentKey) {
271         Assertions.argumentNotNull(parentKey, "parentKey may not be null");
272
273         parentKeyName = parentKey.getName();
274         parentKeyVersion = parentKey.getVersion();
275         parentLocalName = NULL_KEY_NAME;
276     }
277
278     /**
279      * Sets the parent reference key of this reference key.
280      *
281      * @param parentKey
282      *        the parent reference key of this reference key
283      */
284     public void setParentReferenceKey(final PfReferenceKey parentKey) {
285         Assertions.argumentNotNull(parentKey, "parentKey may not be null");
286
287         parentKeyName = parentKey.getParentKeyName();
288         parentKeyVersion = parentKey.getParentKeyVersion();
289         parentLocalName = parentKey.getLocalName();
290     }
291
292     @Override
293     public PfKey.Compatibility getCompatibility(final PfKey otherKey) {
294         if (!(otherKey instanceof PfReferenceKey)) {
295             return Compatibility.DIFFERENT;
296         }
297         final PfReferenceKey otherReferenceKey = (PfReferenceKey) otherKey;
298
299         return this.getParentConceptKey().getCompatibility(otherReferenceKey.getParentConceptKey());
300     }
301
302     @Override
303     public boolean isCompatible(final PfKey otherKey) {
304         if (!(otherKey instanceof PfReferenceKey)) {
305             return false;
306         }
307         final PfReferenceKey otherReferenceKey = (PfReferenceKey) otherKey;
308
309         return this.getParentConceptKey().isCompatible(otherReferenceKey.getParentConceptKey());
310     }
311
312     @Override
313     public PfValidationResult validate(final PfValidationResult result) {
314         final String parentNameValidationErrorMessage = Assertions.getStringParameterValidationMessage(PARENT_KEY_NAME,
315                         parentKeyName, NAME_REGEXP);
316         if (parentNameValidationErrorMessage != null) {
317             result.addValidationMessage(new PfValidationMessage(this, this.getClass(), ValidationResult.INVALID,
318                             "parentKeyName invalid-" + parentNameValidationErrorMessage));
319         }
320
321         final String parentKeyVersionValidationErrorMessage = Assertions
322                         .getStringParameterValidationMessage(PARENT_KEY_VERSION, parentKeyVersion, VERSION_REGEXP);
323         if (parentKeyVersionValidationErrorMessage != null) {
324             result.addValidationMessage(new PfValidationMessage(this, this.getClass(), ValidationResult.INVALID,
325                             "parentKeyVersion invalid-" + parentKeyVersionValidationErrorMessage));
326         }
327
328         final String parentLocalNameValidationErrorMessage = Assertions
329                         .getStringParameterValidationMessage(PARENT_LOCAL_NAME, parentLocalName, LOCAL_NAME_REGEXP);
330         if (parentLocalNameValidationErrorMessage != null) {
331             result.addValidationMessage(new PfValidationMessage(this, this.getClass(), ValidationResult.INVALID,
332                             "parentLocalName invalid-" + parentLocalNameValidationErrorMessage));
333         }
334
335         final String localNameValidationErrorMessage = Assertions.getStringParameterValidationMessage(LOCAL_NAME,
336                         localName, LOCAL_NAME_REGEXP);
337         if (localNameValidationErrorMessage != null) {
338             result.addValidationMessage(new PfValidationMessage(this, this.getClass(), ValidationResult.INVALID,
339                             "localName invalid-" + localNameValidationErrorMessage));
340         }
341
342         return result;
343     }
344
345     @Override
346     public void clean() {
347         parentKeyName = Assertions.validateStringParameter(PARENT_KEY_NAME, parentKeyName, NAME_REGEXP);
348         parentKeyVersion = Assertions.validateStringParameter(PARENT_KEY_VERSION, parentKeyVersion, VERSION_REGEXP);
349         parentLocalName = Assertions.validateStringParameter(PARENT_LOCAL_NAME, parentLocalName, LOCAL_NAME_REGEXP);
350         localName = Assertions.validateStringParameter(LOCAL_NAME, localName, LOCAL_NAME_REGEXP);
351     }
352
353     @Override
354     public PfConcept copyTo(final PfConcept target) {
355         Assertions.argumentNotNull(target, "target may not be null");
356
357         final Object copyObject = target;
358         Assertions.instanceOf(copyObject, PfReferenceKey.class);
359
360         final PfReferenceKey copy = ((PfReferenceKey) copyObject);
361         copy.setParentKeyName(parentKeyName);
362         copy.setParentKeyVersion(parentKeyVersion);
363         copy.setLocalName(localName);
364         copy.setParentLocalName(parentLocalName);
365
366         return copy;
367     }
368
369     @Override
370     public int compareTo(final PfConcept otherObj) {
371         Assertions.argumentNotNull(otherObj, "comparison object may not be null");
372
373         if (this == otherObj) {
374             return 0;
375         }
376         if (getClass() != otherObj.getClass()) {
377             return this.hashCode() - otherObj.hashCode();
378         }
379
380         final PfReferenceKey other = (PfReferenceKey) otherObj;
381         if (!parentKeyName.equals(other.parentKeyName)) {
382             return parentKeyName.compareTo(other.parentKeyName);
383         }
384         if (!parentKeyVersion.equals(other.parentKeyVersion)) {
385             return parentKeyVersion.compareTo(other.parentKeyVersion);
386         }
387         if (!parentLocalName.equals(other.parentLocalName)) {
388             return parentLocalName.compareTo(other.parentLocalName);
389         }
390         return localName.compareTo(other.localName);
391     }
392 }