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