35010bf4b702f2244d28f9f2e7940f8da8a36e92
[policy/apex-pdp.git] / model / basic-model / src / main / java / org / onap / policy / apex / model / basicmodel / concepts / AxKeyInfo.java
1 /*-
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2016-2018 Ericsson. All rights reserved.
4  *  Modifications Copyright (C) 2019 Nordix Foundation.
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.apex.model.basicmodel.concepts;
23
24 import java.util.List;
25 import java.util.Random;
26 import java.util.UUID;
27
28 import javax.persistence.Column;
29 import javax.persistence.Convert;
30 import javax.persistence.EmbeddedId;
31 import javax.persistence.Entity;
32 import javax.persistence.Table;
33 import javax.xml.bind.annotation.XmlAccessType;
34 import javax.xml.bind.annotation.XmlAccessorType;
35 import javax.xml.bind.annotation.XmlElement;
36 import javax.xml.bind.annotation.XmlRootElement;
37 import javax.xml.bind.annotation.XmlType;
38 import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
39
40 import org.apache.commons.lang3.StringUtils;
41 import org.onap.policy.apex.model.basicmodel.concepts.AxValidationResult.ValidationResult;
42 import org.onap.policy.apex.model.basicmodel.dao.converters.CDataConditioner;
43 import org.onap.policy.apex.model.basicmodel.dao.converters.Uuid2String;
44 import org.onap.policy.common.utils.validation.Assertions;
45
46 /**
47  * The key information on an {@link AxArtifactKey} key in an Apex policy model. Each {@link AxArtifactKey} must have an
48  * {@link AxKeyInfo} object. THe information held is the key's UUID and it's description.
49  *
50  * <p>Validation checks that all fields are defined and that the key is valid. It also observes that descriptions are
51  * blank and warns if the UUID is a zero UUID.
52  */
53
54 @Entity
55 @Table(name = "AxKeyInfo")
56
57 @XmlAccessorType(XmlAccessType.FIELD)
58 @XmlRootElement(name = "apexKeyInfo", namespace = "http://www.onap.org/policy/apex-pdp")
59 @XmlType(name = "AxKeyInfo", namespace = "http://www.onap.org/policy/apex-pdp",
60         propOrder = { "key", "uuid", "description" })
61
62 public class AxKeyInfo extends AxConcept {
63     private static final long serialVersionUID = -4023935924068914308L;
64
65     private static final int MAX_DESCRIPTION_LENGTH_8192 = 8192;
66     private static final int UUID_BYTE_LENGTH_16 = 16;
67
68     private static final Random sharedRandom = new Random();
69
70     @EmbeddedId
71     @XmlElement(name = "key", required = true)
72     private AxArtifactKey key;
73
74     @Column(name = "uuid")
75     @Convert(converter = Uuid2String.class)
76     @XmlJavaTypeAdapter(value = Uuid2String.class)
77     @XmlElement(name = "UUID", required = true)
78     private UUID uuid;
79
80     @Column(name = "description", length = MAX_DESCRIPTION_LENGTH_8192)
81     @Convert(converter = CDataConditioner.class)
82     @XmlJavaTypeAdapter(value = CDataConditioner.class)
83     @XmlElement(required = true)
84     private String description;
85
86     /**
87      * The Default Constructor creates this concept with a NULL artifact key.
88      */
89     public AxKeyInfo() {
90         this(new AxArtifactKey());
91     }
92
93     /**
94      * Copy constructor.
95      *
96      * @param copyConcept the concept to copy from
97      */
98     public AxKeyInfo(final AxKeyInfo copyConcept) {
99         super(copyConcept);
100     }
101
102     /**
103      * Constructor to create this concept with the specified key.
104      *
105      * @param key the key of the concept
106      */
107     public AxKeyInfo(final AxArtifactKey key) {
108         this(key, UUID.randomUUID(), "Generated description for concept referred to by key \"" + key.getId() + "\"");
109     }
110
111     /**
112      * Constructor to create this concept and set all its fields.
113      *
114      * @param key the key of the concept
115      * @param uuid the UUID of the concept
116      * @param description the description of the concept
117      */
118     public AxKeyInfo(final AxArtifactKey key, final UUID uuid, final String description) {
119         super();
120         Assertions.argumentNotNull(key, "key may not be null");
121         Assertions.argumentNotNull(uuid, "uuid may not be null");
122         Assertions.argumentNotNull(description, "description may not be null");
123
124         this.key = key;
125         this.uuid = uuid;
126         this.description = description.trim();
127     }
128
129     /**
130      * {@inheritDoc}.
131      */
132     @Override
133     public AxArtifactKey getKey() {
134         return key;
135     }
136
137     /**
138      * {@inheritDoc}.
139      */
140     @Override
141     public List<AxKey> getKeys() {
142         return key.getKeys();
143     }
144
145     /**
146      * Sets the key of the concept.
147      *
148      * @param key the concept key
149      */
150     public void setKey(final AxArtifactKey key) {
151         Assertions.argumentNotNull(key, "key may not be null");
152         this.key = key;
153     }
154
155     /**
156      * Gets the UUID of the concept.
157      *
158      * @return the uuid of the concept
159      */
160     public UUID getUuid() {
161         return uuid;
162     }
163
164     /**
165      * Sets the UUID of the concept.
166      *
167      * @param uuid the uuid of the concept
168      */
169     public void setUuid(final UUID uuid) {
170         Assertions.argumentNotNull(uuid, "uuid may not be null");
171         this.uuid = uuid;
172     }
173
174     /**
175      * Gets the description of the concept.
176      *
177      * @return the description of the concept
178      */
179     public String getDescription() {
180         return description;
181     }
182
183     /**
184      * Sets the description of the concept.
185      *
186      * @param description the description of the concept
187      */
188     public void setDescription(final String description) {
189         Assertions.argumentNotNull(description, "description may not be null");
190         this.description = description.trim();
191     }
192
193     /**
194      * {@inheritDoc}.
195      */
196     @Override
197     public AxValidationResult validate(final AxValidationResult resultIn) {
198         AxValidationResult result = resultIn;
199
200         if (key.equals(AxArtifactKey.getNullKey())) {
201             result.addValidationMessage(
202                     new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID, "key is a null key"));
203         }
204
205         result = key.validate(result);
206
207         if (description.trim().length() == 0) {
208             result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.OBSERVATION,
209                     "description is blank"));
210         }
211
212         if (uuid.equals(new UUID(0, 0))) {
213             result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.WARNING,
214                     "UUID is a zero UUID: " + new UUID(0, 0)));
215         }
216
217         return result;
218     }
219
220     /**
221      * {@inheritDoc}.
222      */
223     @Override
224     public void clean() {
225         key.clean();
226         description = description.trim();
227     }
228
229     /**
230      * {@inheritDoc}.
231      */
232     @Override
233     public String toString() {
234         final StringBuilder builder = new StringBuilder();
235         builder.append(this.getClass().getSimpleName());
236         builder.append(":(");
237         builder.append("artifactId=");
238         builder.append(key);
239         builder.append(",uuid=");
240         builder.append(uuid);
241         builder.append(",description=");
242         builder.append(description);
243         builder.append(")");
244         return builder.toString();
245     }
246
247     /**
248      * {@inheritDoc}.
249      */
250     @Override
251     public AxConcept copyTo(final AxConcept target) {
252         Assertions.argumentNotNull(target, "target may not be null");
253
254         final Object copyObject = target;
255         Assertions.instanceOf(copyObject, AxKeyInfo.class);
256
257         final AxKeyInfo copy = ((AxKeyInfo) copyObject);
258         copy.setKey(new AxArtifactKey(key));
259         copy.setUuid(UUID.fromString(uuid.toString()));
260         copy.setDescription(description);
261
262         return copy;
263     }
264
265     /**
266      * {@inheritDoc}.
267      */
268     @Override
269     public int hashCode() {
270         final int prime = 31;
271         int result = 1;
272         result = prime * result + key.hashCode();
273         result = prime * result + uuid.hashCode();
274         result = prime * result + description.hashCode();
275         return result;
276     }
277
278     /**
279      * {@inheritDoc}.
280      */
281     @Override
282     public boolean equals(final Object obj) {
283         if (obj == null) {
284             return false;
285         }
286         if (this == obj) {
287             return true;
288         }
289         if (getClass() != obj.getClass()) {
290             return false;
291         }
292
293         final AxKeyInfo other = (AxKeyInfo) obj;
294         if (!key.equals(other.key)) {
295             return false;
296         }
297         if (!uuid.equals(other.uuid)) {
298             return false;
299         }
300         final String thisdesc = CDataConditioner.clean(description);
301         final String otherdesc = CDataConditioner.clean(other.description);
302         return thisdesc.equals(otherdesc);
303     }
304
305     /**
306      * {@inheritDoc}.
307      */
308     @Override
309     public int compareTo(final AxConcept otherObj) {
310         if (otherObj == null) {
311             return -1;
312         }
313         if (this == otherObj) {
314             return 0;
315         }
316         if (getClass() != otherObj.getClass()) {
317             return this.hashCode() - otherObj.hashCode();
318         }
319
320         final AxKeyInfo other = (AxKeyInfo) otherObj;
321         if (!key.equals(other.key)) {
322             return key.compareTo(other.key);
323         }
324         if (!uuid.equals(other.uuid)) {
325             return uuid.compareTo(other.uuid);
326         }
327         return description.compareTo(other.description);
328     }
329
330     /**
331      * Generate a reproducible UUID for a given string seed.
332      *
333      * @param seed the seed
334      * @return the uuid
335      */
336     public static UUID generateReproducibleUuid(final String seed) {
337         Random random = sharedRandom;
338         if (!StringUtils.isEmpty(seed)) {
339             random = new Random(seed.hashCode());
340         }
341         final byte[] array = new byte[UUID_BYTE_LENGTH_16];
342         random.nextBytes(array);
343         return UUID.nameUUIDFromBytes(array);
344     }
345 }