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