Merge "Add classes for PDP "simple" REST APIs"
[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     @Override
247     public boolean isNullKey() {
248         return this.equals(PfReferenceKey.getNullKey());
249     }
250
251     /**
252      * Gets the parent concept key of this reference key.
253      *
254      * @return the parent concept key of this reference key
255      */
256     public PfConceptKey getParentConceptKey() {
257         return new PfConceptKey(parentKeyName, parentKeyVersion);
258     }
259
260     /**
261      * Gets the parent reference key of this reference key.
262      *
263      * @return the parent reference key of this reference key
264      */
265     public PfReferenceKey getParentReferenceKey() {
266         return new PfReferenceKey(parentKeyName, parentKeyVersion, parentLocalName);
267     }
268
269     /**
270      * Sets the parent concept key of this reference key.
271      *
272      * @param parentKey
273      *        the parent concept key of this reference key
274      */
275     public void setParentConceptKey(final PfConceptKey parentKey) {
276         Assertions.argumentNotNull(parentKey, "parentKey may not be null");
277
278         parentKeyName = parentKey.getName();
279         parentKeyVersion = parentKey.getVersion();
280         parentLocalName = NULL_KEY_NAME;
281     }
282
283     /**
284      * Sets the parent reference key of this reference key.
285      *
286      * @param parentKey
287      *        the parent reference key of this reference key
288      */
289     public void setParentReferenceKey(final PfReferenceKey parentKey) {
290         Assertions.argumentNotNull(parentKey, "parentKey may not be null");
291
292         parentKeyName = parentKey.getParentKeyName();
293         parentKeyVersion = parentKey.getParentKeyVersion();
294         parentLocalName = parentKey.getLocalName();
295     }
296
297     @Override
298     public PfKey.Compatibility getCompatibility(final PfKey otherKey) {
299         if (!(otherKey instanceof PfReferenceKey)) {
300             return Compatibility.DIFFERENT;
301         }
302         final PfReferenceKey otherReferenceKey = (PfReferenceKey) otherKey;
303
304         return this.getParentConceptKey().getCompatibility(otherReferenceKey.getParentConceptKey());
305     }
306
307     @Override
308     public boolean isCompatible(final PfKey otherKey) {
309         if (!(otherKey instanceof PfReferenceKey)) {
310             return false;
311         }
312         final PfReferenceKey otherReferenceKey = (PfReferenceKey) otherKey;
313
314         return this.getParentConceptKey().isCompatible(otherReferenceKey.getParentConceptKey());
315     }
316
317     @Override
318     public PfValidationResult validate(final PfValidationResult result) {
319         final String parentNameValidationErrorMessage = Assertions.getStringParameterValidationMessage(PARENT_KEY_NAME,
320                         parentKeyName, NAME_REGEXP);
321         if (parentNameValidationErrorMessage != null) {
322             result.addValidationMessage(new PfValidationMessage(this, this.getClass(), ValidationResult.INVALID,
323                             "parentKeyName invalid-" + parentNameValidationErrorMessage));
324         }
325
326         final String parentKeyVersionValidationErrorMessage = Assertions
327                         .getStringParameterValidationMessage(PARENT_KEY_VERSION, parentKeyVersion, VERSION_REGEXP);
328         if (parentKeyVersionValidationErrorMessage != null) {
329             result.addValidationMessage(new PfValidationMessage(this, this.getClass(), ValidationResult.INVALID,
330                             "parentKeyVersion invalid-" + parentKeyVersionValidationErrorMessage));
331         }
332
333         final String parentLocalNameValidationErrorMessage = Assertions
334                         .getStringParameterValidationMessage(PARENT_LOCAL_NAME, parentLocalName, LOCAL_NAME_REGEXP);
335         if (parentLocalNameValidationErrorMessage != null) {
336             result.addValidationMessage(new PfValidationMessage(this, this.getClass(), ValidationResult.INVALID,
337                             "parentLocalName invalid-" + parentLocalNameValidationErrorMessage));
338         }
339
340         final String localNameValidationErrorMessage = Assertions.getStringParameterValidationMessage(LOCAL_NAME,
341                         localName, LOCAL_NAME_REGEXP);
342         if (localNameValidationErrorMessage != null) {
343             result.addValidationMessage(new PfValidationMessage(this, this.getClass(), ValidationResult.INVALID,
344                             "localName invalid-" + localNameValidationErrorMessage));
345         }
346
347         return result;
348     }
349
350     @Override
351     public void clean() {
352         parentKeyName = Assertions.validateStringParameter(PARENT_KEY_NAME, parentKeyName, NAME_REGEXP);
353         parentKeyVersion = Assertions.validateStringParameter(PARENT_KEY_VERSION, parentKeyVersion, VERSION_REGEXP);
354         parentLocalName = Assertions.validateStringParameter(PARENT_LOCAL_NAME, parentLocalName, LOCAL_NAME_REGEXP);
355         localName = Assertions.validateStringParameter(LOCAL_NAME, localName, LOCAL_NAME_REGEXP);
356     }
357
358     @Override
359     public PfConcept copyTo(final PfConcept target) {
360         Assertions.argumentNotNull(target, "target may not be null");
361
362         final Object copyObject = target;
363         Assertions.instanceOf(copyObject, PfReferenceKey.class);
364
365         final PfReferenceKey copy = ((PfReferenceKey) copyObject);
366         copy.setParentKeyName(parentKeyName);
367         copy.setParentKeyVersion(parentKeyVersion);
368         copy.setLocalName(localName);
369         copy.setParentLocalName(parentLocalName);
370
371         return copy;
372     }
373
374     @Override
375     public int compareTo(final PfConcept otherObj) {
376         Assertions.argumentNotNull(otherObj, "comparison object may not be null");
377
378         if (this == otherObj) {
379             return 0;
380         }
381         if (getClass() != otherObj.getClass()) {
382             return this.hashCode() - otherObj.hashCode();
383         }
384
385         final PfReferenceKey other = (PfReferenceKey) otherObj;
386         if (!parentKeyName.equals(other.parentKeyName)) {
387             return parentKeyName.compareTo(other.parentKeyName);
388         }
389         if (!parentKeyVersion.equals(other.parentKeyVersion)) {
390             return parentKeyVersion.compareTo(other.parentKeyVersion);
391         }
392         if (!parentLocalName.equals(other.parentLocalName)) {
393             return parentLocalName.compareTo(other.parentLocalName);
394         }
395         return localName.compareTo(other.localName);
396     }
397 }