Changes for checkstyle 8.32
[policy/apex-pdp.git] / model / context-model / src / main / java / org / onap / policy / apex / model / contextmodel / concepts / AxContextSchema.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.contextmodel.concepts;
23
24 import java.util.List;
25 import javax.persistence.Column;
26 import javax.persistence.Convert;
27 import javax.persistence.EmbeddedId;
28 import javax.persistence.Entity;
29 import javax.persistence.Table;
30 import javax.xml.bind.annotation.XmlAccessType;
31 import javax.xml.bind.annotation.XmlAccessorType;
32 import javax.xml.bind.annotation.XmlElement;
33 import javax.xml.bind.annotation.XmlRootElement;
34 import javax.xml.bind.annotation.XmlType;
35 import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
36 import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
37 import org.onap.policy.apex.model.basicmodel.concepts.AxConcept;
38 import org.onap.policy.apex.model.basicmodel.concepts.AxKey;
39 import org.onap.policy.apex.model.basicmodel.concepts.AxValidationMessage;
40 import org.onap.policy.apex.model.basicmodel.concepts.AxValidationResult;
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.common.utils.validation.Assertions;
44
45 /**
46  * This class holds a data schema definition in Apex. A data schema describes the structure of a single atom of data
47  * handled by Apex. This atom of data can be a primitive type such as an integer or a string, or it can be a more
48  * complex data type such as a Java object or an object described using a data definition language such as Avro. The
49  * schema flavour defines the type of schema being defined and the schema itself defines the schema. The schema flavour
50  * is used by Apex to look up and load a plugin class that understands and interprets the schema definition and can
51  * create instances of classes for the schema.
52  *
53  * <p>An {@link AxContextSchema} is used to define each parameter in Apex events, the messages that enter, exit, and are
54  * passed internally in Apex. In addition, an Apex {@link AxContextAlbum} instances hold a map of
55  * {@link AxContextSchema} instances to represent the context being managed as an {@link AxContextAlbum}. For example,
56  * the state of all cells in a mobile network might be represented as an {@link AxContextAlbum} with its
57  * {@link AxContextSchema} being defined as @code cell} objects.
58  *
59  * <p>Validation checks that the schema key is not null. It also checks that the schema flavour is defined and matches
60  * the regular expression SCHEMA_FLAVOUR_REGEXP. Finally, validation checks that the defined schema is not a blank or
61  * empty string.
62  */
63 @Entity
64 @Table(name = "AxContextSchema")
65
66 @XmlAccessorType(XmlAccessType.FIELD)
67 @XmlRootElement(name = "apexContextSchema", namespace = "http://www.onap.org/policy/apex-pdp")
68 @XmlType(name = "AxContextSchema", namespace = "http://www.onap.org/policy/apex-pdp", propOrder =
69     { "key", "schemaFlavour", "schemaDefinition" })
70
71 public class AxContextSchema extends AxConcept {
72     private static final String SCHEMA_FLAVOUR = "schemaFlavour";
73     private static final String WHITESPACE_REGEXP = "\\s+$";
74
75     private static final long serialVersionUID = -6443016863162692288L;
76
77     /** Regular expression that constrains what values a schema flavour can have. */
78     public static final String SCHEMA_FLAVOUR_REGEXP = "[A-Za-z0-9\\-_]+";
79
80     /** An undefined schema flavour has this value. */
81     public static final String SCHEMA_FLAVOUR_UNDEFINED = "UNDEFINED";
82
83     /** The maximum permissible size of a schema definition. */
84     public static final int MAX_SCHEMA_SIZE = 32672; // The maximum size supported by Apache Derby
85
86     @EmbeddedId
87     @XmlElement(name = "key", required = true)
88     private AxArtifactKey key;
89
90     @Column(name = SCHEMA_FLAVOUR)
91     @XmlElement(required = true)
92     private String schemaFlavour;
93
94     @Column(name = "schemaDefinition", length = MAX_SCHEMA_SIZE)
95     @Convert(converter = CDataConditioner.class)
96     @XmlJavaTypeAdapter(value = CDataConditioner.class)
97     @XmlElement(name = "schemaDefinition", required = true)
98     private String schemaDefinition;
99
100     /**
101      * The default constructor creates a context schema with a null artifact key. The flavour of the context album is
102      * set as SCHEMA_FLAVOUR_UNDEFINED and the schema itself is defined as an empty string.
103      */
104     public AxContextSchema() {
105         this(new AxArtifactKey());
106         schemaFlavour = SCHEMA_FLAVOUR_UNDEFINED;
107     }
108
109     /**
110      * Copy constructor.
111      *
112      * @param copyConcept the concept to copy from
113      */
114     public AxContextSchema(final AxContextSchema copyConcept) {
115         super(copyConcept);
116     }
117
118     /**
119      * The key constructor creates a context schema with the given artifact key. The flavour of the context album is set
120      * as SCHEMA_FLAVOUR_UNDEFINED and the schema itself is defined as an empty string.
121      *
122      * @param key the key
123      */
124     public AxContextSchema(final AxArtifactKey key) {
125         this(key, SCHEMA_FLAVOUR_UNDEFINED, "");
126     }
127
128     /**
129      * This Constructor creates a context schema with all of its fields defined.
130      *
131      * @param key the key
132      * @param schemaFlavour the schema flavour
133      * @param schemaDefinition the schema definition
134      */
135     public AxContextSchema(final AxArtifactKey key, final String schemaFlavour, final String schemaDefinition) {
136         super();
137         Assertions.argumentNotNull(key, "key may not be null");
138         Assertions.argumentNotNull(schemaFlavour, "schemaFlavour may not be null");
139         Assertions.argumentNotNull(schemaDefinition, "schemaDefinition may not be null");
140
141         this.key = key;
142         this.schemaFlavour = Assertions.validateStringParameter(SCHEMA_FLAVOUR, schemaFlavour, SCHEMA_FLAVOUR_REGEXP);
143         this.schemaDefinition = schemaDefinition.replaceAll(WHITESPACE_REGEXP, "");
144     }
145
146     /**
147      * {@inheritDoc}.
148      */
149     @Override
150     public AxArtifactKey getKey() {
151         return key;
152     }
153
154     /**
155      * {@inheritDoc}.
156      */
157     @Override
158     public List<AxKey> getKeys() {
159         return key.getKeys();
160     }
161
162     /**
163      * Sets the key of the context schema.
164      *
165      * @param key the key of the context schema
166      */
167     public void setKey(final AxArtifactKey key) {
168         Assertions.argumentNotNull(key, "key may not be null");
169         this.key = key;
170     }
171
172     /**
173      * Gets the schema flavour, which defines the schema definition type being used.
174      *
175      * @return the schema flavour
176      */
177     public String getSchemaFlavour() {
178         return schemaFlavour;
179     }
180
181     /**
182      * Sets the schema flavour, which defines the type of schema definition being used.
183      *
184      * @param schemaFlavour the schema flavour
185      */
186     public void setSchemaFlavour(final String schemaFlavour) {
187         this.schemaFlavour = Assertions.validateStringParameter(SCHEMA_FLAVOUR, schemaFlavour, SCHEMA_FLAVOUR_REGEXP);
188     }
189
190     /**
191      * Gets the schema, which defines the structure of this data schema atom.
192      *
193      * @return the schema definition
194      */
195     public String getSchema() {
196         return schemaDefinition;
197     }
198
199     /**
200      * Sets the schema, which defines the structure of this data schema atom.
201      *
202      * @param schema the schema definition
203      */
204     public void setSchema(final String schema) {
205         Assertions.argumentNotNull(schema, "schema may not be null");
206         this.schemaDefinition = schema.replaceAll(WHITESPACE_REGEXP, "");
207     }
208
209     /**
210      * {@inheritDoc}.
211      */
212     @Override
213     public AxValidationResult validate(final AxValidationResult resultIn) {
214         AxValidationResult result = resultIn;
215
216         if (key.equals(AxArtifactKey.getNullKey())) {
217             result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID,
218                             "key is a null key"));
219         }
220
221         result = key.validate(result);
222
223         if (schemaFlavour.replaceAll(WHITESPACE_REGEXP, "").length() == 0
224                         || schemaFlavour.equals(SCHEMA_FLAVOUR_UNDEFINED)) {
225             result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID,
226                             "schema flavour is not defined"));
227         }
228
229         String flavourValidationResult = Assertions.getStringParameterValidationMessage(SCHEMA_FLAVOUR, schemaFlavour,
230                         SCHEMA_FLAVOUR_REGEXP);
231         if (flavourValidationResult != null) {
232             result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID,
233                             "schema flavour invalid-" + flavourValidationResult));
234         }
235
236         if (schemaDefinition.replaceAll(WHITESPACE_REGEXP, "").length() == 0) {
237             result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID,
238                             "no schemaDefinition specified, schemaDefinition may not be blank"));
239         }
240
241         return result;
242     }
243
244     /**
245      * {@inheritDoc}.
246      */
247     @Override
248     public void clean() {
249         key.clean();
250         schemaFlavour = Assertions.validateStringParameter(SCHEMA_FLAVOUR, schemaFlavour, SCHEMA_FLAVOUR_REGEXP);
251         schemaDefinition = schemaDefinition.replaceAll(WHITESPACE_REGEXP, "");
252     }
253
254     /**
255      * {@inheritDoc}.
256      */
257     @Override
258     public String toString() {
259         final StringBuilder builder = new StringBuilder();
260         builder.append(this.getClass().getSimpleName());
261         builder.append(":(");
262         builder.append("key=");
263         builder.append(key);
264         builder.append(",schemaFlavour=");
265         builder.append(schemaFlavour);
266         builder.append(",schemaDefinition=");
267         builder.append(schemaDefinition);
268         builder.append(")");
269         return builder.toString();
270     }
271
272     /**
273      * {@inheritDoc}.
274      */
275     @Override
276     public AxConcept copyTo(final AxConcept target) {
277         Assertions.argumentNotNull(target, "target may not be null");
278
279         final Object copyObject = target;
280         Assertions.instanceOf(copyObject, AxContextSchema.class);
281
282         final AxContextSchema copy = ((AxContextSchema) copyObject);
283         copy.setKey(new AxArtifactKey(key));
284         copy.setSchemaFlavour(schemaFlavour);
285         copy.setSchema(schemaDefinition);
286
287         return copy;
288     }
289
290     /**
291      * {@inheritDoc}.
292      */
293     @Override
294     public int hashCode() {
295         final int prime = 31;
296         int result = 1;
297         result = prime * result + key.hashCode();
298         result = prime * result + schemaFlavour.hashCode();
299         result = prime * result + schemaDefinition.hashCode();
300         return result;
301     }
302
303     /**
304      * {@inheritDoc}.
305      */
306     @Override
307     public boolean equals(final Object obj) {
308         if (obj == null) {
309             return false;
310         }
311         if (this == obj) {
312             return true;
313         }
314
315         if (getClass() != obj.getClass()) {
316             return false;
317         }
318
319         final AxContextSchema other = (AxContextSchema) obj;
320
321         if (!key.equals(other.key)) {
322             return false;
323         }
324         if (!schemaFlavour.equals(other.schemaFlavour)) {
325             return false;
326         }
327         final String thisSchema = CDataConditioner.clean(schemaDefinition).replaceAll("\n", "");
328         final String otherSchema = CDataConditioner.clean(other.schemaDefinition).replaceAll("\n", "");
329         return thisSchema.equals(otherSchema);
330     }
331
332     /**
333      * {@inheritDoc}.
334      */
335     @Override
336     public int compareTo(final AxConcept otherObj) {
337         if (otherObj == null) {
338             return -1;
339         }
340         if (this == otherObj) {
341             return 0;
342         }
343         if (getClass() != otherObj.getClass()) {
344             return this.hashCode() - otherObj.hashCode();
345         }
346
347         final AxContextSchema other = (AxContextSchema) otherObj;
348         if (!key.equals(other.key)) {
349             return key.compareTo(other.key);
350         }
351         if (!schemaFlavour.equals(other.schemaFlavour)) {
352             return schemaFlavour.compareTo(other.schemaFlavour);
353         }
354         final String thisSchema = CDataConditioner.clean(schemaDefinition).replaceAll("\n", "");
355         final String otherSchema = CDataConditioner.clean(other.schemaDefinition).replaceAll("\n", "");
356         return thisSchema.compareTo(otherSchema);
357     }
358 }