2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2016-2018 Ericsson. All rights reserved.
4 * Modifications Copyright (C) 2019-2022 Nordix Foundation.
5 * Modifications Copyright (C) 2021 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
19 * SPDX-License-Identifier: Apache-2.0
20 * ============LICENSE_END=========================================================
23 package org.onap.policy.apex.model.contextmodel.concepts;
25 import java.util.List;
26 import lombok.AccessLevel;
28 import lombok.ToString;
29 import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
30 import org.onap.policy.apex.model.basicmodel.concepts.AxConcept;
31 import org.onap.policy.apex.model.basicmodel.concepts.AxKey;
32 import org.onap.policy.apex.model.basicmodel.concepts.AxValidationMessage;
33 import org.onap.policy.apex.model.basicmodel.concepts.AxValidationResult;
34 import org.onap.policy.apex.model.basicmodel.concepts.AxValidationResult.ValidationResult;
35 import org.onap.policy.common.utils.validation.Assertions;
38 * This class holds a data schema definition in Apex. A data schema describes the structure of a single atom of data
39 * 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
40 * complex data type such as a Java object or an object described using a data definition language such as Avro. The
41 * schema flavour defines the type of schema being defined and the schema itself defines the schema. The schema flavour
42 * is used by Apex to look up and load a plugin class that understands and interprets the schema definition and can
43 * create instances of classes for the schema.
45 * <p>An {@link AxContextSchema} is used to define each parameter in Apex events, the messages that enter, exit, and are
46 * passed internally in Apex. In addition, an Apex {@link AxContextAlbum} instances hold a map of
47 * {@link AxContextSchema} instances to represent the context being managed as an {@link AxContextAlbum}. For example,
48 * the state of all cells in a mobile network might be represented as an {@link AxContextAlbum} with its
49 * {@link AxContextSchema} being defined as @code cell} objects.
51 * <p>Validation checks that the schema key is not null. It also checks that the schema flavour is defined and matches
52 * the regular expression SCHEMA_FLAVOUR_REGEXP. Finally, validation checks that the defined schema is not a blank or
57 public class AxContextSchema extends AxConcept {
58 private static final String SCHEMA_FLAVOUR = "schemaFlavour";
59 private static final String WHITESPACE_REGEXP = "\\s+$";
61 private static final long serialVersionUID = -6443016863162692288L;
63 /** Regular expression that constrains what values a schema flavour can have. */
64 public static final String SCHEMA_FLAVOUR_REGEXP = "[A-Za-z0-9\\-_]+";
66 /** An undefined schema flavour has this value. */
67 public static final String SCHEMA_FLAVOUR_UNDEFINED = "UNDEFINED";
69 /** The maximum permissible size of a schema definition. */
70 public static final int MAX_SCHEMA_SIZE = 32672; // The maximum size supported by Apache Derby
72 private AxArtifactKey key;
73 private String schemaFlavour;
75 @Getter(AccessLevel.NONE)
76 private String schemaDefinition;
79 * The default constructor creates a context schema with a null artifact key. The flavour of the context album is
80 * set as SCHEMA_FLAVOUR_UNDEFINED and the schema itself is defined as an empty string.
82 public AxContextSchema() {
83 this(new AxArtifactKey());
84 schemaFlavour = SCHEMA_FLAVOUR_UNDEFINED;
90 * @param copyConcept the concept to copy from
92 public AxContextSchema(final AxContextSchema copyConcept) {
97 * The key constructor creates a context schema with the given artifact key. The flavour of the context album is set
98 * as SCHEMA_FLAVOUR_UNDEFINED and the schema itself is defined as an empty string.
102 public AxContextSchema(final AxArtifactKey key) {
103 this(key, SCHEMA_FLAVOUR_UNDEFINED, "");
107 * This Constructor creates a context schema with all of its fields defined.
110 * @param schemaFlavour the schema flavour
111 * @param schemaDefinition the schema definition
113 public AxContextSchema(final AxArtifactKey key, final String schemaFlavour, final String schemaDefinition) {
115 Assertions.argumentNotNull(key, "key may not be null");
116 Assertions.argumentNotNull(schemaFlavour, "schemaFlavour may not be null");
117 Assertions.argumentNotNull(schemaDefinition, "schemaDefinition may not be null");
120 this.schemaFlavour = Assertions.validateStringParameter(SCHEMA_FLAVOUR, schemaFlavour, SCHEMA_FLAVOUR_REGEXP);
121 this.schemaDefinition = schemaDefinition.replaceAll(WHITESPACE_REGEXP, "");
128 public List<AxKey> getKeys() {
129 return key.getKeys();
133 * Sets the key of the context schema.
135 * @param key the key of the context schema
137 public void setKey(final AxArtifactKey key) {
138 Assertions.argumentNotNull(key, "key may not be null");
143 * Sets the schema flavour, which defines the type of schema definition being used.
145 * @param schemaFlavour the schema flavour
147 public void setSchemaFlavour(final String schemaFlavour) {
148 this.schemaFlavour = Assertions.validateStringParameter(SCHEMA_FLAVOUR, schemaFlavour, SCHEMA_FLAVOUR_REGEXP);
152 * Gets the schema, which defines the structure of this data schema atom.
154 * @return the schema definition
156 public String getSchema() {
157 return schemaDefinition;
161 * Sets the schema, which defines the structure of this data schema atom.
163 * @param schema the schema definition
165 public void setSchema(final String schema) {
166 Assertions.argumentNotNull(schema, "schema may not be null");
167 this.schemaDefinition = schema.replaceAll(WHITESPACE_REGEXP, "");
174 public AxValidationResult validate(final AxValidationResult resultIn) {
175 AxValidationResult result = resultIn;
177 if (key.equals(AxArtifactKey.getNullKey())) {
178 result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID,
179 "key is a null key"));
182 result = key.validate(result);
184 if (schemaFlavour.replaceAll(WHITESPACE_REGEXP, "").length() == 0
185 || schemaFlavour.equals(SCHEMA_FLAVOUR_UNDEFINED)) {
186 result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID,
187 "schema flavour is not defined"));
190 var flavourValidationResult = Assertions.getStringParameterValidationMessage(SCHEMA_FLAVOUR, schemaFlavour,
191 SCHEMA_FLAVOUR_REGEXP);
192 if (flavourValidationResult != null) {
193 result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID,
194 "schema flavour invalid-" + flavourValidationResult));
197 if (schemaDefinition.replaceAll(WHITESPACE_REGEXP, "").length() == 0) {
198 result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID,
199 "no schemaDefinition specified, schemaDefinition may not be blank"));
209 public void clean() {
211 schemaFlavour = Assertions.validateStringParameter(SCHEMA_FLAVOUR, schemaFlavour, SCHEMA_FLAVOUR_REGEXP);
212 schemaDefinition = schemaDefinition.replaceAll(WHITESPACE_REGEXP, "");
219 public AxConcept copyTo(final AxConcept target) {
220 Assertions.argumentNotNull(target, "target may not be null");
222 final Object copyObject = target;
223 Assertions.instanceOf(copyObject, AxContextSchema.class);
225 final AxContextSchema copy = ((AxContextSchema) copyObject);
226 copy.setKey(new AxArtifactKey(key));
227 copy.setSchemaFlavour(schemaFlavour);
228 copy.setSchema(schemaDefinition);
237 public int hashCode() {
238 final var prime = 31;
240 result = prime * result + key.hashCode();
241 result = prime * result + schemaFlavour.hashCode();
243 final String thisSchema = schemaDefinition.replace("\n", "");
244 result = prime * result + thisSchema.hashCode();
252 public boolean equals(final Object obj) {
260 if (getClass() != obj.getClass()) {
264 final AxContextSchema other = (AxContextSchema) obj;
266 if (!key.equals(other.key)) {
269 if (!schemaFlavour.equals(other.schemaFlavour)) {
272 return schemaDefinition.equals(other.schemaDefinition);
279 public int compareTo(final AxConcept otherObj) {
280 if (otherObj == null) {
283 if (this == otherObj) {
286 if (getClass() != otherObj.getClass()) {
287 return this.hashCode() - otherObj.hashCode();
290 final AxContextSchema other = (AxContextSchema) otherObj;
291 if (!key.equals(other.key)) {
292 return key.compareTo(other.key);
294 if (!schemaFlavour.equals(other.schemaFlavour)) {
295 return schemaFlavour.compareTo(other.schemaFlavour);
297 return schemaDefinition.compareTo(other.schemaDefinition);