diff options
author | ramverma <ram.krishna.verma@ericsson.com> | 2018-05-25 11:55:45 +0100 |
---|---|---|
committer | ramverma <ram.krishna.verma@ericsson.com> | 2018-05-25 16:25:25 +0100 |
commit | 6029d25f5f3ad43fe02ffe1a4beb1eda0a6ae5e3 (patch) | |
tree | 489296a005ced47a3a4acffc6ce64b65f5367d77 /model/context-model/src/main/java/org/onap/policy | |
parent | 5abd3063949496c231ed8d3013c2ab17fc9288bb (diff) |
Adding apex event-model module
- Adding apex event-model module
- Fixing namespaces
Change-Id: If37a1773000ca99eb5d97703fdeb5788ce55365c
Issue-ID: POLICY-856
Signed-off-by: ramverma <ram.krishna.verma@ericsson.com>
Diffstat (limited to 'model/context-model/src/main/java/org/onap/policy')
8 files changed, 2116 insertions, 0 deletions
diff --git a/model/context-model/src/main/java/org/onap/policy/apex/model/contextmodel/concepts/AxContextAlbum.java b/model/context-model/src/main/java/org/onap/policy/apex/model/contextmodel/concepts/AxContextAlbum.java new file mode 100644 index 000000000..27f9b8b9b --- /dev/null +++ b/model/context-model/src/main/java/org/onap/policy/apex/model/contextmodel/concepts/AxContextAlbum.java @@ -0,0 +1,425 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2016-2018 Ericsson. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.apex.model.contextmodel.concepts; + +import java.util.List; + +import javax.persistence.AttributeOverride; +import javax.persistence.AttributeOverrides; +import javax.persistence.Column; +import javax.persistence.Embedded; +import javax.persistence.EmbeddedId; +import javax.persistence.Entity; +import javax.persistence.Table; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; + +import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey; +import org.onap.policy.apex.model.basicmodel.concepts.AxConcept; +import org.onap.policy.apex.model.basicmodel.concepts.AxKey; +import org.onap.policy.apex.model.basicmodel.concepts.AxKeyUse; +import org.onap.policy.apex.model.basicmodel.concepts.AxValidationMessage; +import org.onap.policy.apex.model.basicmodel.concepts.AxValidationResult; +import org.onap.policy.apex.model.basicmodel.concepts.AxValidationResult.ValidationResult; +import org.onap.policy.apex.model.utilities.Assertions; + +/** + * This class is used to define an album of context. + * <p> + * A context album is a distributed map of context that will be distributed across all process instances that require + * access to it. This class defines the schema (structure) of the items in the context album, whether the items on the + * context album are writable or not, and what the scope of the context album is. + * <p> + * The structure of items (objects) the context album is defined as a schema, which is understood by whatever schema + * implementation is being used for the context album. + * <p> + * The scope of a context album is a string field, understood by whatever distribution mechanism is being used for the + * context album. The distribution mechanism uses the scope of the context album to decide to which executable entities + * a given context album is distributed. + * <p> + * The writable flag on a context album defines whether users of a context album can write to the context album or just + * read objects from the context album. + * <p> + * Validation checks that the album key and the context schema key are not null and that the scope field is not + * undefined and matches the regular expression {@link SCOPE_REGEXP}. + */ +@Entity +@Table(name = "AxContextAlbum") + +@XmlAccessorType(XmlAccessType.FIELD) +@XmlRootElement(name = "apexContextAlbum", namespace = "http://www.onap.org/policy/apex-pdp") +@XmlType(name = "AxContextAlbum", namespace = "http://www.onap.org/policy/apex-pdp", + propOrder = { "key", "scope", "isWritable", "itemSchema" }) + +public class AxContextAlbum extends AxConcept { + private static final String SCOPE_STRING = "scope"; + + private static final long serialVersionUID = 4290442590545820316L; + + /** + * The legal values for the scope of a context album is constrained by this regular expression. + */ + public static final String SCOPE_REGEXP = "[A-Za-z0-9\\-_]+"; + + /** The value of scope for a context album for which a scope has not been specified. */ + public static final String SCOPE_UNDEFINED = "UNDEFINED"; + + private static final int HASH_PRIME_0 = 1231; + private static final int HASH_PRIME_1 = 1237; + + @EmbeddedId + @XmlElement(name = "key", required = true) + private AxArtifactKey key; + + @Column(name = SCOPE_STRING) + @XmlElement(name = SCOPE_STRING, required = true) + private String scope; + + @Column(name = "isWritable") + @XmlElement(name = "isWritable", required = true) + private boolean isWritable; + + // @formatter:off + @Embedded + @AttributeOverrides({ + @AttributeOverride(name = "name", column = @Column(name = "itemSchemaName")), + @AttributeOverride(name = "version", column = @Column(name = "itemSchemaVersion")) + }) + @Column(name = "itemSchema") + @XmlElement(name = "itemSchema", required = true) + private AxArtifactKey itemSchema; + // @formatter:on + + /** + * The default constructor creates a context album with a null artifact key. The scope of the context album is set + * as {@link SCOPE_UNDEFINED}, the album is writable, and the artifact key of the context schema is set to the null + * artifact key. + */ + public AxContextAlbum() { + this(new AxArtifactKey()); + scope = SCOPE_UNDEFINED; + isWritable = true; + itemSchema = AxArtifactKey.getNullKey(); + } + + /** + * Copy constructor + * + * @param copyConcept the concept to copy from + */ + public AxContextAlbum(final AxContextAlbum copyConcept) { + super(copyConcept); + } + + /** + * The keyed constructor creates a context album with the specified artifact key. The scope of the context album is + * set as {@link SCOPE_UNDEFINED}, the album is writable, and the artifact key of the context schema is set to the + * null artifact key. + * + * @param key the key of the context album + */ + public AxContextAlbum(final AxArtifactKey key) { + this(key, SCOPE_UNDEFINED, true, AxArtifactKey.getNullKey()); + } + + /** + * Constructor that sets all the fields of the context album. + * + * @param key the key of the context album + * @param scope the scope field, must match the regular expression {@link SCOPE_REGEXP} + * @param isWritable specifies whether the context album will be writable or not + * @param itemSchema the artifact key of the context schema to use for this context album + */ + public AxContextAlbum(final AxArtifactKey key, final String scope, final boolean isWritable, + final AxArtifactKey itemSchema) { + super(); + Assertions.argumentNotNull(key, "key may not be null"); + Assertions.argumentNotNull(scope, "scope may not be null"); + Assertions.argumentNotNull(itemSchema, "itemSchema may not be null"); + + this.key = key; + this.scope = Assertions.validateStringParameter(SCOPE_STRING, scope, SCOPE_REGEXP); + this.isWritable = isWritable; + this.itemSchema = itemSchema; + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.model.basicmodel.concepts.AxConcept#getKey() + */ + @Override + public AxArtifactKey getKey() { + return key; + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.model.basicmodel.concepts.AxConcept#getKeys() + */ + @Override + public List<AxKey> getKeys() { + final List<AxKey> keyList = key.getKeys(); + keyList.add(new AxKeyUse(itemSchema.getKey())); + + return keyList; + } + + /** + * Sets the key of the context album. + * + * @param key the context album key + */ + public void setKey(final AxArtifactKey key) { + Assertions.argumentNotNull(key, "key may not be null"); + this.key = key; + } + + /** + * Gets the scope of the context album. + * + * @return the context album scope + */ + public String getScope() { + return scope; + } + + /** + * Sets the scope of the context album. + * + * @param scope the context album scope + */ + public void setScope(final String scope) { + Assertions.argumentNotNull(scope, "scope may not be null"); + this.scope = Assertions.validateStringParameter(SCOPE_STRING, scope, SCOPE_REGEXP); + } + + /** + * Sets whether the album is writable or not. + * + * @param writable the writable flag value + */ + public void setWritable(final boolean writable) { + this.isWritable = writable; + } + + /** + * Checks if the album is writable. + * + * @return true, if the album is writable + */ + public boolean isWritable() { + return isWritable; + } + + /** + * Gets the artifact key of the item schema of this context album. + * + * @return the item schema key + */ + public AxArtifactKey getItemSchema() { + return itemSchema; + } + + /** + * Sets the artifact key of the item schema of this context album. + * + * @param itemSchema the item schema key + */ + public void setItemSchema(final AxArtifactKey itemSchema) { + Assertions.argumentNotNull(itemSchema, "itemSchema key may not be null"); + this.itemSchema = itemSchema; + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.model.basicmodel.concepts.AxConcept#validate(org.onap.policy.apex.model. + * basicmodel.concepts.AxValidationResult) + */ + @Override + public AxValidationResult validate(final AxValidationResult resultIn) { + AxValidationResult result = resultIn; + + if (key.equals(AxArtifactKey.getNullKey())) { + result.addValidationMessage( + new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID, "key is a null key")); + } + result = key.validate(result); + + if (scope.replaceAll("\\s+$", "").length() == 0 || scope.equals(SCOPE_UNDEFINED)) { + result.addValidationMessage( + new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID, "scope is not defined")); + } + + try { + Assertions.validateStringParameter(SCOPE_STRING, scope, SCOPE_REGEXP); + } catch (final IllegalArgumentException e) { + result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID, + "scope invalid-" + e.getMessage())); + } + + if (itemSchema.equals(AxArtifactKey.getNullKey())) { + result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID, + "itemSchema reference is a null key, an item schema must be specified")); + } + result = itemSchema.validate(result); + + return result; + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.model.basicmodel.concepts.AxConcept#clean() + */ + @Override + public void clean() { + key.clean(); + scope = Assertions.validateStringParameter(SCOPE_STRING, scope, SCOPE_REGEXP); + itemSchema.clean(); + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.model.basicmodel.concepts.AxConcept#toString() + */ + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + builder.append(":("); + builder.append("key="); + builder.append(key); + builder.append(",scope="); + builder.append(scope); + builder.append(",isWritable="); + builder.append(isWritable); + builder.append(",itemSchema="); + builder.append(itemSchema); + builder.append(")"); + return builder.toString(); + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.model.basicmodel.concepts.AxConcept#copyTo(org.onap.policy.apex.model. + * basicmodel.concepts.AxConcept) + */ + @Override + public AxConcept copyTo(final AxConcept target) { + Assertions.argumentNotNull(target, "targetObject may not be null"); + + final Object copyObject = target; + Assertions.instanceOf(copyObject, AxContextAlbum.class); + + final AxContextAlbum copy = ((AxContextAlbum) copyObject); + copy.setKey(new AxArtifactKey(key)); + copy.setScope(scope); + copy.setWritable(isWritable); + copy.setItemSchema(new AxArtifactKey(itemSchema)); + + return copy; + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.model.basicmodel.concepts.AxConcept#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + key.hashCode(); + result = prime * result + scope.hashCode(); + result = prime * result + (isWritable ? HASH_PRIME_0 : HASH_PRIME_1); + result = prime * result + itemSchema.hashCode(); + return result; + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.model.basicmodel.concepts.AxConcept#equals(java.lang.Object) + */ + @Override + public boolean equals(final Object obj) { + if (obj == null) { + return false; + } + if (this == obj) { + return true; + } + + if (getClass() != obj.getClass()) { + return false; + } + + final AxContextAlbum other = (AxContextAlbum) obj; + if (!key.equals(other.key)) { + return false; + } + if (!scope.equals(other.scope)) { + return false; + } + if (isWritable != other.isWritable) { + return (false); + } + return itemSchema.equals(other.itemSchema); + } + + /* + * (non-Javadoc) + * + * @see java.lang.Comparable#compareTo(java.lang.Object) + */ + @Override + public int compareTo(final AxConcept otherObj) { + if (otherObj == null) { + return -1; + } + if (this == otherObj) { + return 0; + } + if (getClass() != otherObj.getClass()) { + return this.hashCode() - otherObj.hashCode(); + } + + final AxContextAlbum other = (AxContextAlbum) otherObj; + if (!key.equals(other.key)) { + return key.compareTo(other.key); + } + if (!scope.equals(other.scope)) { + return scope.compareTo(other.scope); + } + if (isWritable != other.isWritable) { + return (isWritable ? 1 : -1); + } + return itemSchema.compareTo(other.itemSchema); + } +} diff --git a/model/context-model/src/main/java/org/onap/policy/apex/model/contextmodel/concepts/AxContextAlbums.java b/model/context-model/src/main/java/org/onap/policy/apex/model/contextmodel/concepts/AxContextAlbums.java new file mode 100644 index 000000000..f9d34cef6 --- /dev/null +++ b/model/context-model/src/main/java/org/onap/policy/apex/model/contextmodel/concepts/AxContextAlbums.java @@ -0,0 +1,423 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2016-2018 Ericsson. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.apex.model.contextmodel.concepts; + +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.NavigableMap; +import java.util.Set; +import java.util.TreeMap; + +import javax.persistence.CascadeType; +import javax.persistence.EmbeddedId; +import javax.persistence.Entity; +import javax.persistence.JoinColumn; +import javax.persistence.JoinTable; +import javax.persistence.OneToMany; +import javax.persistence.Table; +import javax.xml.bind.Unmarshaller; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + +import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey; +import org.onap.policy.apex.model.basicmodel.concepts.AxConcept; +import org.onap.policy.apex.model.basicmodel.concepts.AxConceptGetter; +import org.onap.policy.apex.model.basicmodel.concepts.AxConceptGetterImpl; +import org.onap.policy.apex.model.basicmodel.concepts.AxKey; +import org.onap.policy.apex.model.basicmodel.concepts.AxValidationMessage; +import org.onap.policy.apex.model.basicmodel.concepts.AxValidationResult; +import org.onap.policy.apex.model.basicmodel.concepts.AxValidationResult.ValidationResult; +import org.onap.policy.apex.model.utilities.Assertions; + +/** + * This class is a context album container and holds a map of the context albums for an entire Apex model. All Apex + * models that use context albums must have an {@link AxContextAlbums} field. The {@link AxContextAlbums} class + * implements the helper methods of the {@link AxConceptGetter} interface to allow {@link AxContextAlbum} instances to + * be retrieved by calling methods directly on this class without referencing the contained map. + * <p> + * Validation checks that the container key is not null. An observation is issued if no context albums are defined in + * the container. If context albums do exist, they are checked to ensure that keys and values are not null and that the + * map key matches the key in the map value for all album entries. Each context album entry is then validated + * individually. + */ +@Entity +@Table(name = "AxContextAlbums") + +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "AxContextAlbums", namespace = "http://www.onap.org/policy/apex-pdp", propOrder = { "key", "albums" }) + +public final class AxContextAlbums extends AxConcept implements AxConceptGetter<AxContextAlbum> { + private static final long serialVersionUID = -4844259809024470975L; + + @EmbeddedId + @XmlElement(name = "key", required = true) + private AxArtifactKey key; + + // @formatter:off + @OneToMany(cascade = CascadeType.ALL) + @JoinTable(joinColumns = {@JoinColumn(name = "contextName", referencedColumnName = "name"), + @JoinColumn(name = "contextVersion", referencedColumnName = "version")}) + @XmlElement(name = "albums", required = true) + private Map<AxArtifactKey, AxContextAlbum> albums; + // @formatter:on + + /** + * The Default Constructor creates a {@link AxContextAlbums} object with a null artifact key and creates an empty + * context album map. + */ + public AxContextAlbums() { + this(new AxArtifactKey()); + } + + /** + * Copy constructor + * + * @param copyConcept the concept to copy from + */ + public AxContextAlbums(final AxContextAlbums copyConcept) { + super(copyConcept); + } + + /** + * The Key Constructor creates a {@link AxContextAlbums} object with the given artifact key and creates an empty + * context album map. + * + * @param key the key of the context album container + */ + public AxContextAlbums(final AxArtifactKey key) { + this(key, new TreeMap<AxArtifactKey, AxContextAlbum>()); + } + + /** + * Constructor that creates the context album map with the given albums and key. + * + * @param key the key of the context album container + * @param albums the context albums to place in this context album container + */ + public AxContextAlbums(final AxArtifactKey key, final Map<AxArtifactKey, AxContextAlbum> albums) { + super(); + Assertions.argumentNotNull(key, "key may not be null"); + Assertions.argumentNotNull(albums, "albums may not be null"); + + this.key = key; + this.albums = new TreeMap<>(); + this.albums.putAll(albums); + } + + /** + * When a model is unmarshalled from disk or from the database, the context album map is returned as a raw hash map. + * This method is called by JAXB after unmarshaling and is used to convert the hash map to a {@link NavigableMap} so + * that it will work with the {@link AxConceptGetter} interface. + * + * @param u the unmarshaler that is unmarshaling the model + * @param parent the parent object of this object in the unmarshaler + */ + public void afterUnmarshal(final Unmarshaller u, final Object parent) { + // The map must be navigable to allow name and version searching, unmarshaling returns a + // hash map + final NavigableMap<AxArtifactKey, AxContextAlbum> navigableAlbums = new TreeMap<>(); + navigableAlbums.putAll(albums); + albums = navigableAlbums; + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.model.basicmodel.concepts.AxConcept#getKey() + */ + @Override + public AxArtifactKey getKey() { + return key; + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.model.basicmodel.concepts.AxConcept#getKeys() + */ + @Override + public List<AxKey> getKeys() { + final List<AxKey> keyList = key.getKeys(); + + for (final AxContextAlbum contextAlbum : albums.values()) { + keyList.addAll(contextAlbum.getKeys()); + } + + return keyList; + } + + /** + * Sets the key of the context album container. + * + * @param key the context album container key + */ + public void setKey(final AxArtifactKey key) { + Assertions.argumentNotNull(key, "key may not be null"); + this.key = key; + } + + /** + * Gets the map of context albums from the context album container. + * + * @return the context album map + */ + public Map<AxArtifactKey, AxContextAlbum> getAlbumsMap() { + return albums; + } + + /** + * Sets the map of context albums from the context album container. + * + * @param albumsMap the map of context albums to place in the container + */ + public void setAlbumsMap(final Map<AxArtifactKey, AxContextAlbum> albumsMap) { + Assertions.argumentNotNull(albumsMap, "albums may not be null"); + this.albums = new TreeMap<>(); + this.albums.putAll(albumsMap); + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.model.basicmodel.concepts.AxConcept#clean() + */ + @Override + public void clean() { + key.clean(); + for (final Entry<AxArtifactKey, AxContextAlbum> contextAlbumEntry : albums.entrySet()) { + contextAlbumEntry.getKey().clean(); + contextAlbumEntry.getValue().clean(); + } + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.model.basicmodel.concepts.AxConcept#toString() + */ + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + builder.append(":("); + builder.append(this.getClass().getSimpleName()); + builder.append(":("); + builder.append("key="); + builder.append(key); + builder.append(",albums="); + builder.append(albums); + builder.append(")"); + return builder.toString(); + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.model.basicmodel.concepts.AxConcept#validate(org.onap.policy.apex.model. + * basicmodel.concepts.AxValidationResult) + */ + @Override + public AxValidationResult validate(final AxValidationResult resultIn) { + AxValidationResult result = resultIn; + + if (key.equals(AxArtifactKey.getNullKey())) { + result.addValidationMessage( + new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID, "key is a null key")); + } + + result = key.validate(result); + + if (albums.size() == 0) { + result.addValidationMessage( + new AxValidationMessage(key, this.getClass(), ValidationResult.OBSERVATION, "albums are empty")); + } else { + for (final Entry<AxArtifactKey, AxContextAlbum> contextAlbumEntry : albums.entrySet()) { + if (contextAlbumEntry.getKey().equals(AxArtifactKey.getNullKey())) { + result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID, + "key on context album entry " + contextAlbumEntry.getKey() + " may not be the null key")); + } else if (contextAlbumEntry.getValue() == null) { + result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID, + "value on context album entry " + contextAlbumEntry.getKey() + " may not be null")); + } else { + if (!contextAlbumEntry.getKey().equals(contextAlbumEntry.getValue().getKey())) { + result.addValidationMessage( + new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID, + "key on context album entry key " + contextAlbumEntry.getKey() + + " does not equal context album value key " + + contextAlbumEntry.getValue().getKey())); + } + + result = contextAlbumEntry.getValue().validate(result); + } + } + } + + return result; + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.model.basicmodel.concepts.AxConcept#copyTo(org.onap.policy.apex.model. + * basicmodel.concepts.AxConcept) + */ + @Override + public AxConcept copyTo(final AxConcept target) { + Assertions.argumentNotNull(target, "target may not be null"); + + final Object copyObject = target; + Assertions.instanceOf(copyObject, AxContextAlbums.class); + + final AxContextAlbums copy = ((AxContextAlbums) copyObject); + copy.setKey(key); + final Map<AxArtifactKey, AxContextAlbum> newContextAlbum = new TreeMap<>(); + for (final Entry<AxArtifactKey, AxContextAlbum> contextAlbumEntry : albums.entrySet()) { + newContextAlbum.put(new AxArtifactKey(contextAlbumEntry.getKey()), + new AxContextAlbum(contextAlbumEntry.getValue())); + } + copy.setAlbumsMap(newContextAlbum); + + return copy; + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.model.basicmodel.concepts.AxConcept#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + key.hashCode(); + result = prime * result + albums.hashCode(); + return result; + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.model.basicmodel.concepts.AxConcept#equals(java.lang.Object) + */ + @Override + public boolean equals(final Object obj) { + if (obj == null) { + return false; + } + if (this == obj) { + return true; + } + + if (getClass() != obj.getClass()) { + return false; + } + + final AxContextAlbums other = (AxContextAlbums) obj; + if (!key.equals(other.key)) { + return false; + } + return albums.equals(other.albums); + } + + /* + * (non-Javadoc) + * + * @see java.lang.Comparable#compareTo(java.lang.Object) + */ + @Override + public int compareTo(final AxConcept otherObj) { + if (otherObj == null) { + return -1; + } + if (this == otherObj) { + return 0; + } + if (getClass() != otherObj.getClass()) { + return this.hashCode() - otherObj.hashCode(); + } + + final AxContextAlbums other = (AxContextAlbums) otherObj; + if (!key.equals(other.key)) { + return key.compareTo(other.key); + } + if (!albums.equals(other.albums)) { + return (albums.hashCode() - other.albums.hashCode()); + } + + return 0; + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.model.basicmodel.concepts.AxConceptGetter#get(org.onap.policy.apex.model. + * basicmodel.concepts.AxArtifactKey) + */ + @Override + public AxContextAlbum get(final AxArtifactKey conceptKey) { + return new AxConceptGetterImpl<>((NavigableMap<AxArtifactKey, AxContextAlbum>) albums).get(conceptKey); + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.model.basicmodel.concepts.AxConceptGetter#get(java.lang.String) + */ + @Override + public AxContextAlbum get(final String conceptKeyName) { + return new AxConceptGetterImpl<>((NavigableMap<AxArtifactKey, AxContextAlbum>) albums).get(conceptKeyName); + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.model.basicmodel.concepts.AxConceptGetter#get(java.lang.String, java.lang.String) + */ + @Override + public AxContextAlbum get(final String conceptKeyName, final String conceptKeyVersion) { + return new AxConceptGetterImpl<>((NavigableMap<AxArtifactKey, AxContextAlbum>) albums).get(conceptKeyName, + conceptKeyVersion); + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.model.basicmodel.concepts.AxConceptGetter#getAll(java.lang.String) + */ + @Override + public Set<AxContextAlbum> getAll(final String conceptKeyName) { + return new AxConceptGetterImpl<>((NavigableMap<AxArtifactKey, AxContextAlbum>) albums).getAll(conceptKeyName); + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.model.basicmodel.concepts.AxConceptGetter#getAll(java.lang.String, java.lang.String) + */ + @Override + public Set<AxContextAlbum> getAll(final String conceptKeyName, final String conceptKeyVersion) { + return new AxConceptGetterImpl<>((NavigableMap<AxArtifactKey, AxContextAlbum>) albums).getAll(conceptKeyName, + conceptKeyVersion); + } +} diff --git a/model/context-model/src/main/java/org/onap/policy/apex/model/contextmodel/concepts/AxContextModel.java b/model/context-model/src/main/java/org/onap/policy/apex/model/contextmodel/concepts/AxContextModel.java new file mode 100644 index 000000000..2aa6fc70a --- /dev/null +++ b/model/context-model/src/main/java/org/onap/policy/apex/model/contextmodel/concepts/AxContextModel.java @@ -0,0 +1,345 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2016-2018 Ericsson. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.apex.model.contextmodel.concepts; + +import java.util.List; + +import javax.persistence.CascadeType; +import javax.persistence.Entity; +import javax.persistence.JoinColumn; +import javax.persistence.JoinColumns; +import javax.persistence.OneToOne; +import javax.persistence.Table; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; + +import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey; +import org.onap.policy.apex.model.basicmodel.concepts.AxConcept; +import org.onap.policy.apex.model.basicmodel.concepts.AxKey; +import org.onap.policy.apex.model.basicmodel.concepts.AxKeyInformation; +import org.onap.policy.apex.model.basicmodel.concepts.AxModel; +import org.onap.policy.apex.model.basicmodel.concepts.AxValidationResult; +import org.onap.policy.apex.model.basicmodel.service.ModelService; +import org.onap.policy.apex.model.utilities.Assertions; + +/** + * A container class for an Apex context model. This class is a container class that allows an Apex model to be + * constructed that just contains context and the key information for that context. The model contains schema + * definitions and the definitions of context albums that use those schemas. In the case where Apex context is being + * used without policy or independent of policy, an Apex context model is sufficient to get Apex context working. + * <p> + * Validation runs {@link AxModel} validation on the model. In addition, the {@link AxContextSchemas} and + * {@link AxContextAlbums} validation is run on the context schemas and albums in the model. + */ +@Entity +@Table(name = "AxContextModel") + +@XmlRootElement(name = "apexContextModel", namespace = "http://www.onap.org/policy/apex-pdp") +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "AxContextModel", namespace = "http://www.onap.org/policy/apex-pdp", + propOrder = { "schemas", "albums" }) + +public class AxContextModel extends AxModel { + private static final long serialVersionUID = 8800599637708309945L; + + // @formatter:off + @OneToOne(cascade = CascadeType.ALL) + @JoinColumns({ + @JoinColumn(name = "schemasName", referencedColumnName = "name"), + @JoinColumn(name = "schemasVersion", referencedColumnName = "version") + }) + @XmlElement(name = "schemas", required = true) + private AxContextSchemas schemas; + + @OneToOne(cascade = CascadeType.ALL) + @JoinColumns({ + @JoinColumn(name = "albumsName", referencedColumnName = "name"), + @JoinColumn(name = "albumsVersion", referencedColumnName = "version") + }) + @XmlElement(name = "albums", required = true) + private AxContextAlbums albums; + // @formatter:on + + /** + * The Default Constructor creates a {@link AxContextModel} object with a null artifact key and creates an empty + * context model. + */ + public AxContextModel() { + this(new AxArtifactKey()); + } + + /** + * The Key Constructor creates a {@link AxContextModel} object with the given artifact key and creates an empty + * context model. + * + * @param key the key of the context model + */ + public AxContextModel(final AxArtifactKey key) { + this(key, new AxContextSchemas(new AxArtifactKey(key.getName() + "_Schemas", key.getVersion())), + new AxContextAlbums(new AxArtifactKey(key.getName() + "_Albums", key.getVersion())), + new AxKeyInformation(new AxArtifactKey(key.getName() + "_KeyInfo", key.getVersion()))); + } + + /** + * Copy constructor + * + * @param copyConcept the concept to copy from + */ + public AxContextModel(final AxContextModel copyConcept) { + super(copyConcept); + } + + /** + * Constructor that initiates a {@link AxContextModel} with schemas and keys for those schemas. An empty + * {@link AxContextAlbums} container is created. + * + * @param key the key of the context model + * @param schemas the context schema definitions + * @param keyInformation the key information for those context schemas + */ + public AxContextModel(final AxArtifactKey key, final AxContextSchemas schemas, + final AxKeyInformation keyInformation) { + this(key, schemas, new AxContextAlbums(new AxArtifactKey(key.getName() + "_Albums", key.getVersion())), + keyInformation); + } + + /** + * Constructor that initiates a {@link AxContextModel} with all its fields. + * + * @param key the key of the context model + * @param schemas the context schema definitions + * @param albums the context album container containing context albums + * @param keyInformation the key information for those context schemas + */ + public AxContextModel(final AxArtifactKey key, final AxContextSchemas schemas, final AxContextAlbums albums, + final AxKeyInformation keyInformation) { + super(key, keyInformation); + Assertions.argumentNotNull(schemas, "schemas may not be null"); + Assertions.argumentNotNull(albums, "albums may not be null"); + this.schemas = schemas; + this.albums = albums; + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.model.basicmodel.concepts.AxModel#register() + */ + @Override + public void register() { + super.register(); + ModelService.registerModel(AxContextSchemas.class, getSchemas()); + ModelService.registerModel(AxContextAlbums.class, getAlbums()); + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.model.basicmodel.concepts.AxModel#getKeys() + */ + @Override + public List<AxKey> getKeys() { + final List<AxKey> keyList = super.getKeys(); + + keyList.addAll(schemas.getKeys()); + keyList.addAll(albums.getKeys()); + + return keyList; + } + + /** + * Gets the context schemas from the model. + * + * @return the context schemas + */ + public AxContextSchemas getSchemas() { + return schemas; + } + + /** + * Sets the context schemas on the model. + * + * @param schemas the context schemas + */ + public void setSchemas(final AxContextSchemas schemas) { + Assertions.argumentNotNull(schemas, "schemas may not be null"); + this.schemas = schemas; + } + + /** + * Gets the context albums from the model. + * + * @return the context albums + */ + public AxContextAlbums getAlbums() { + return albums; + } + + /** + * Sets the context albums on the model. + * + * @param albums the context albums + */ + public void setAlbums(final AxContextAlbums albums) { + Assertions.argumentNotNull(albums, "albums may not be null"); + this.albums = albums; + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.model.basicmodel.concepts.AxModel#validate(org.onap.policy.apex.model. + * basicmodel.concepts.AxValidationResult) + */ + @Override + public AxValidationResult validate(final AxValidationResult resultIn) { + AxValidationResult result = resultIn; + + result = super.validate(result); + result = schemas.validate(result); + return albums.validate(result); + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.model.basicmodel.concepts.AxModel#clean() + */ + @Override + public void clean() { + super.clean(); + schemas.clean(); + albums.clean(); + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.model.basicmodel.concepts.AxModel#toString() + */ + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + builder.append(":("); + builder.append(super.toString()); + builder.append(",schemas="); + builder.append(schemas); + builder.append(",albums="); + builder.append(albums); + builder.append(")"); + return builder.toString(); + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.model.basicmodel.concepts.AxConcept#copyTo(org.onap.policy.apex.model. + * basicmodel.concepts.AxConcept) + */ + @Override + public AxConcept copyTo(final AxConcept target) { + Assertions.argumentNotNull(target, "target may not be null"); + + final Object copyObject = target; + Assertions.instanceOf(copyObject, AxContextModel.class); + + final AxContextModel copy = ((AxContextModel) copyObject); + super.copyTo(target); + copy.setSchemas(new AxContextSchemas(schemas)); + copy.setAlbums(new AxContextAlbums(albums)); + + return copy; + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.model.basicmodel.concepts.AxModel#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + super.hashCode(); + result = prime * result + schemas.hashCode(); + result = prime * result + albums.hashCode(); + return result; + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.model.basicmodel.concepts.AxModel#equals(java.lang.Object) + */ + @Override + public boolean equals(final Object obj) { + if (obj == null) { + throw new IllegalArgumentException("comparison object may not be null"); + } + + if (this == obj) { + return true; + } + if (getClass() != obj.getClass()) { + return false; + } + + final AxContextModel other = (AxContextModel) obj; + if (!super.equals(other)) { + return false; + } + if (!schemas.equals(other.schemas)) { + return false; + } + return albums.equals(other.albums); + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.model.basicmodel.concepts.AxModel#compareTo(org.onap.policy.apex.model. + * basicmodel.concepts.AxConcept) + */ + @Override + public int compareTo(final AxConcept otherObj) { + Assertions.argumentNotNull(otherObj, "comparison object may not be null"); + + if (this == otherObj) { + return 0; + } + if (getClass() != otherObj.getClass()) { + return this.hashCode() - otherObj.hashCode(); + } + + final AxContextModel other = (AxContextModel) otherObj; + if (!super.equals(other)) { + return super.compareTo(other); + } + if (!schemas.equals(other.schemas)) { + return schemas.compareTo(other.schemas); + } + return albums.compareTo(other.albums); + } +} diff --git a/model/context-model/src/main/java/org/onap/policy/apex/model/contextmodel/concepts/AxContextSchema.java b/model/context-model/src/main/java/org/onap/policy/apex/model/contextmodel/concepts/AxContextSchema.java new file mode 100644 index 000000000..3abcebee9 --- /dev/null +++ b/model/context-model/src/main/java/org/onap/policy/apex/model/contextmodel/concepts/AxContextSchema.java @@ -0,0 +1,379 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2016-2018 Ericsson. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.apex.model.contextmodel.concepts; + +import java.util.List; + +import javax.persistence.Column; +import javax.persistence.Convert; +import javax.persistence.EmbeddedId; +import javax.persistence.Entity; +import javax.persistence.Table; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; + +import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey; +import org.onap.policy.apex.model.basicmodel.concepts.AxConcept; +import org.onap.policy.apex.model.basicmodel.concepts.AxKey; +import org.onap.policy.apex.model.basicmodel.concepts.AxValidationMessage; +import org.onap.policy.apex.model.basicmodel.concepts.AxValidationResult; +import org.onap.policy.apex.model.basicmodel.concepts.AxValidationResult.ValidationResult; +import org.onap.policy.apex.model.basicmodel.dao.converters.CDATAConditioner; +import org.onap.policy.apex.model.utilities.Assertions; + +/** + * This class holds a data schema definition in Apex. A data schema describes the structure of a single atom of data + * 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 + * complex data type such as a Java object or an object described using a data definition language such as Avro. The + * schema flavour defines the type of schema being defined and the schema itself defines the schema. The schema flavour + * is used by Apex to look up and load a plugin class that understands and interprets the schema definition and can + * create instances of classes for the schema. + * <p> + * An {@link AxContextSchema} is used to define each parameter in Apex events, the messages that enter, exit, and are + * passed internally in Apex. In addition, an Apex {@link AxContextAlbum} instances hold a map of + * {@link AxContextSchema} instances to represent the context being managed as an {@link AxContextAlbum}. For example, + * the state of all cells in a mobile network might be represented as an {@link AxContextAlbum} with its + * {@link AxContextSchema} being defined as @code cell} objects. + * <p> + * Validation checks that the schema key is not null. It also checks that the schema flavour is defined and matches the + * regular expression {@link SCHEMA_FLAVOUR_REGEXP}. Finally, validation checks that the defined schema is not a blank + * or empty string. + */ +@Entity +@Table(name = "AxContextSchema") + +@XmlAccessorType(XmlAccessType.FIELD) +@XmlRootElement(name = "apexContextSchema", namespace = "http://www.onap.org/policy/apex-pdp") +@XmlType(name = "AxContextSchema", namespace = "http://www.onap.org/policy/apex-pdp", + propOrder = { "key", "schemaFlavour", "schemaDefinition" }) + +public class AxContextSchema extends AxConcept { + private static final String SCHEMA_FLAVOUR = "schemaFlavour"; + private static final String WHITESPACE_REGEXP = "\\s+$"; + + private static final long serialVersionUID = -6443016863162692288L; + + /** Regular expression that constrains what values a schema flavour can have. */ + public static final String SCHEMA_FLAVOUR_REGEXP = "[A-Za-z0-9\\-_]+"; + + /** An undefined schema flavour has this value. */ + public static final String SCHEMA_FLAVOUR_UNDEFINED = "UNDEFINED"; + + /** The maximum permissible size of a schema definition. */ + public static final int MAX_SCHEMA_SIZE = 32672; // The maximum size supported by Apache Derby + + @EmbeddedId + @XmlElement(name = "key", required = true) + private AxArtifactKey key; + + @Column(name = SCHEMA_FLAVOUR) + @XmlElement(required = true) + private String schemaFlavour; + + @Column(name = "schemaDefinition", length = MAX_SCHEMA_SIZE) + @Convert(converter = CDATAConditioner.class) + @XmlJavaTypeAdapter(value = CDATAConditioner.class) + @XmlElement(name = "schemaDefinition", required = true) + private String schemaDefinition; + + /** + * The default constructor creates a context schema with a null artifact key. The flavour of the context album is + * set as {@link SCHEMA_FLAVOUR_UNDEFINED} and the schema itself is defined as an empty string. + */ + public AxContextSchema() { + this(new AxArtifactKey()); + schemaFlavour = SCHEMA_FLAVOUR_UNDEFINED; + } + + /** + * Copy constructor + * + * @param copyConcept the concept to copy from + */ + public AxContextSchema(final AxContextSchema copyConcept) { + super(copyConcept); + } + + /** + * The key constructor creates a context schema with the given artifact key. The flavour of the context album is set + * as {@link SCHEMA_FLAVOUR_UNDEFINED} and the schema itself is defined as an empty string. + * + * @param key the key + */ + public AxContextSchema(final AxArtifactKey key) { + this(key, SCHEMA_FLAVOUR_UNDEFINED, ""); + } + + /** + * This Constructor creates a context schema with all of its fields defined. + * + * @param key the key + * @param schemaFlavour the schema flavour + * @param schemaDefinition the schema definition + */ + public AxContextSchema(final AxArtifactKey key, final String schemaFlavour, final String schemaDefinition) { + super(); + Assertions.argumentNotNull(key, "key may not be null"); + Assertions.argumentNotNull(schemaFlavour, "schemaFlavour may not be null"); + Assertions.argumentNotNull(schemaDefinition, "schemaDefinition may not be null"); + + this.key = key; + this.schemaFlavour = Assertions.validateStringParameter(SCHEMA_FLAVOUR, schemaFlavour, SCHEMA_FLAVOUR_REGEXP); + this.schemaDefinition = schemaDefinition.replaceAll(WHITESPACE_REGEXP, ""); + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.model.basicmodel.concepts.AxConcept#getKey() + */ + @Override + public AxArtifactKey getKey() { + return key; + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.model.basicmodel.concepts.AxConcept#getKeys() + */ + @Override + public List<AxKey> getKeys() { + return key.getKeys(); + } + + /** + * Sets the key of the context schema. + * + * @param key the key of the context schema + */ + public void setKey(final AxArtifactKey key) { + Assertions.argumentNotNull(key, "key may not be null"); + this.key = key; + } + + /** + * Gets the schema flavour, which defines the schema definition type being used. + * + * @return the schema flavour + */ + public String getSchemaFlavour() { + return schemaFlavour; + } + + /** + * Sets the schema flavour, which defines the type of schema definition being used. + * + * @param schemaFlavour the schema flavour + */ + public void setSchemaFlavour(final String schemaFlavour) { + this.schemaFlavour = Assertions.validateStringParameter(SCHEMA_FLAVOUR, schemaFlavour, SCHEMA_FLAVOUR_REGEXP); + } + + /** + * Gets the schema, which defines the structure of this data schema atom. + * + * @return the schema definition + */ + public String getSchema() { + return schemaDefinition; + } + + /** + * Sets the schema, which defines the structure of this data schema atom. + * + * @param schema the schema definition + */ + public void setSchema(final String schema) { + Assertions.argumentNotNull(schema, "schema may not be null"); + this.schemaDefinition = schema.replaceAll(WHITESPACE_REGEXP, ""); + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.model.basicmodel.concepts.AxConcept#validate(org.onap.policy.apex.model. + * basicmodel.concepts.AxValidationResult) + */ + @Override + public AxValidationResult validate(final AxValidationResult resultIn) { + AxValidationResult result = resultIn; + + if (key.equals(AxArtifactKey.getNullKey())) { + result.addValidationMessage( + new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID, "key is a null key")); + } + + result = key.validate(result); + + if (schemaFlavour.replaceAll(WHITESPACE_REGEXP, "").length() == 0 + || schemaFlavour.equals(SCHEMA_FLAVOUR_UNDEFINED)) { + result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID, + "schema flavour is not defined")); + } + + try { + Assertions.validateStringParameter(SCHEMA_FLAVOUR, schemaFlavour, SCHEMA_FLAVOUR_REGEXP); + } catch (final IllegalArgumentException e) { + result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID, + "schema flavour invalid-" + e.getMessage())); + } + + if (schemaDefinition.replaceAll(WHITESPACE_REGEXP, "").length() == 0) { + result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID, + "no schemaDefinition specified, schemaDefinition may not be blank")); + } + + return result; + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.model.basicmodel.concepts.AxConcept#clean() + */ + @Override + public void clean() { + key.clean(); + schemaFlavour = Assertions.validateStringParameter(SCHEMA_FLAVOUR, schemaFlavour, SCHEMA_FLAVOUR_REGEXP); + schemaDefinition = schemaDefinition.replaceAll(WHITESPACE_REGEXP, ""); + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.model.basicmodel.concepts.AxConcept#toString() + */ + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + builder.append(":("); + builder.append("key="); + builder.append(key); + builder.append(",schemaFlavour="); + builder.append(schemaFlavour); + builder.append(",schemaDefinition="); + builder.append(schemaDefinition); + builder.append(")"); + return builder.toString(); + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.model.basicmodel.concepts.AxConcept#copyTo(org.onap.policy.apex.model. + * basicmodel.concepts.AxConcept) + */ + @Override + public AxConcept copyTo(final AxConcept target) { + Assertions.argumentNotNull(target, "target may not be null"); + + final Object copyObject = target; + Assertions.instanceOf(copyObject, AxContextSchema.class); + + final AxContextSchema copy = ((AxContextSchema) copyObject); + copy.setKey(new AxArtifactKey(key)); + copy.setSchemaFlavour(schemaFlavour); + copy.setSchema(schemaDefinition); + + return copy; + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.model.basicmodel.concepts.AxConcept#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + key.hashCode(); + result = prime * result + schemaFlavour.hashCode(); + result = prime * result + schemaDefinition.hashCode(); + return result; + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.model.basicmodel.concepts.AxConcept#equals(java.lang.Object) + */ + @Override + public boolean equals(final Object obj) { + if (obj == null) { + return false; + } + if (this == obj) { + return true; + } + + if (getClass() != obj.getClass()) { + return false; + } + + final AxContextSchema other = (AxContextSchema) obj; + + if (!key.equals(other.key)) { + return false; + } + if (!schemaFlavour.equals(other.schemaFlavour)) { + return false; + } + final String thisSchema = CDATAConditioner.clean(schemaDefinition).replaceAll("\n", ""); + final String otherSchema = CDATAConditioner.clean(other.schemaDefinition).replaceAll("\n", ""); + return thisSchema.equals(otherSchema); + } + + /* + * (non-Javadoc) + * + * @see java.lang.Comparable#compareTo(java.lang.Object) + */ + @Override + public int compareTo(final AxConcept otherObj) { + if (otherObj == null) { + return -1; + } + if (this == otherObj) { + return 0; + } + if (getClass() != otherObj.getClass()) { + return this.hashCode() - otherObj.hashCode(); + } + + final AxContextSchema other = (AxContextSchema) otherObj; + if (!key.equals(other.key)) { + return key.compareTo(other.key); + } + if (!schemaFlavour.equals(other.schemaFlavour)) { + return schemaFlavour.compareTo(other.schemaFlavour); + } + final String thisSchema = CDATAConditioner.clean(schemaDefinition).replaceAll("\n", ""); + final String otherSchema = CDATAConditioner.clean(other.schemaDefinition).replaceAll("\n", ""); + return thisSchema.compareTo(otherSchema); + } +} diff --git a/model/context-model/src/main/java/org/onap/policy/apex/model/contextmodel/concepts/AxContextSchemas.java b/model/context-model/src/main/java/org/onap/policy/apex/model/contextmodel/concepts/AxContextSchemas.java new file mode 100644 index 000000000..df94a87a9 --- /dev/null +++ b/model/context-model/src/main/java/org/onap/policy/apex/model/contextmodel/concepts/AxContextSchemas.java @@ -0,0 +1,419 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2016-2018 Ericsson. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.apex.model.contextmodel.concepts; + +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.NavigableMap; +import java.util.Set; +import java.util.TreeMap; + +import javax.persistence.CascadeType; +import javax.persistence.EmbeddedId; +import javax.persistence.Entity; +import javax.persistence.JoinColumn; +import javax.persistence.JoinTable; +import javax.persistence.ManyToMany; +import javax.persistence.Table; +import javax.xml.bind.Unmarshaller; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + +import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey; +import org.onap.policy.apex.model.basicmodel.concepts.AxConcept; +import org.onap.policy.apex.model.basicmodel.concepts.AxConceptGetter; +import org.onap.policy.apex.model.basicmodel.concepts.AxConceptGetterImpl; +import org.onap.policy.apex.model.basicmodel.concepts.AxKey; +import org.onap.policy.apex.model.basicmodel.concepts.AxValidationMessage; +import org.onap.policy.apex.model.basicmodel.concepts.AxValidationResult; +import org.onap.policy.apex.model.basicmodel.concepts.AxValidationResult.ValidationResult; +import org.onap.policy.apex.model.utilities.Assertions; + +/** + * This class is a context schema container and holds a map of the context schemas for an entire Apex model. All Apex + * models that use context schemas must have an {@link AxContextSchemas} field. The {@link AxContextSchemas} class + * implements the helper methods of the {@link AxConceptGetter} interface to allow {@link AxContextSchema} instances to + * be retrieved by calling methods directly on this class without referencing the contained map. + * <p> + * Validation checks that the container key is not null. An error is issued if no context schemas are defined in the + * container. Each context schema entry is checked to ensure that its key and value are not null and that the key + * matches the key in the map value. Each context schema entry is then validated individually. + */ +@Entity +@Table(name = "AxContextSchemas") + +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "AxContextSchemas", namespace = "http://www.onap.org/policy/apex-pdp", propOrder = { "key", "schemas" }) + +public class AxContextSchemas extends AxConcept implements AxConceptGetter<AxContextSchema> { + private static final long serialVersionUID = -3203734282886453582L; + + @EmbeddedId + @XmlElement(name = "key", required = true) + private AxArtifactKey key; + + // @formatter:off + @ManyToMany(cascade = CascadeType.ALL) + @JoinTable( + joinColumns = {@JoinColumn(name = "contextSchemasName", referencedColumnName = "name"), + @JoinColumn(name = "contextSchemasVersion", referencedColumnName = "version")}, + inverseJoinColumns = {@JoinColumn(name = "contextSchemaName", referencedColumnName = "name"), + @JoinColumn(name = "contextSchemaVersion", referencedColumnName = "version")}) + @XmlElement(name = "schemas", required = true) + private Map<AxArtifactKey, AxContextSchema> schemas; + // @formatter:on + + /** + * The Default Constructor creates a {@link AxContextSchemas} object with a null artifact key and creates an empty + * context schemas map. + */ + public AxContextSchemas() { + this(new AxArtifactKey()); + } + + /** + * Copy constructor + * + * @param copyConcept the concept to copy from + */ + public AxContextSchemas(final AxContextSchemas copyConcept) { + super(copyConcept); + } + + /** + * The Key Constructor creates a {@link AxContextSchemas} object with the given artifact key and creates an empty + * context schemas map. + * + * @param key the key of the context album container + */ + public AxContextSchemas(final AxArtifactKey key) { + this(key, new TreeMap<AxArtifactKey, AxContextSchema>()); + } + + /** + * This Constructor creates a {@link AxContextSchemas} object with all its fields defined. + * + * @param key the key of the context schema container + * @param schemas a map of the schemas to insert in the context schema container + */ + public AxContextSchemas(final AxArtifactKey key, final Map<AxArtifactKey, AxContextSchema> schemas) { + super(); + Assertions.argumentNotNull(key, "key may not be null"); + Assertions.argumentNotNull(schemas, "schemas may not be null"); + + this.key = key; + this.schemas = new TreeMap<>(); + this.schemas.putAll(schemas); + } + + /** + * When a model is unmarshalled from disk or from the database, the context schema map is returned as a raw hash + * map. This method is called by JAXB after unmarshaling and is used to convert the hash map to a + * {@link NavigableMap} so that it will work with the {@link AxConceptGetter} interface. + * + * @param u the unmarshaler that is unmarshaling the model + * @param parent the parent object of this object in the unmarshaler + */ + public void afterUnmarshal(final Unmarshaller u, final Object parent) { + // The map must be navigable to allow name and version searching, unmarshaling returns a + // hash map + final NavigableMap<AxArtifactKey, AxContextSchema> navigableContextSchemas = new TreeMap<>(); + navigableContextSchemas.putAll(schemas); + schemas = navigableContextSchemas; + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.model.basicmodel.concepts.AxConcept#getKey() + */ + @Override + public AxArtifactKey getKey() { + return key; + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.model.basicmodel.concepts.AxConcept#getKeys() + */ + @Override + public List<AxKey> getKeys() { + final List<AxKey> keyList = key.getKeys(); + keyList.addAll(schemas.keySet()); + + return keyList; + } + + /** + * Sets the key of the context schema container. + * + * @param key the key of the container + */ + public void setKey(final AxArtifactKey key) { + Assertions.argumentNotNull(key, "key may not be null"); + this.key = key; + } + + /** + * Gets the map of context schemas in this container. + * + * @return the map of schemas + */ + public Map<AxArtifactKey, AxContextSchema> getSchemasMap() { + return schemas; + } + + /** + * Sets the map of context schemas in this container. + * + * @param schemasMap the map of schemas + */ + public void setSchemasMap(final Map<AxArtifactKey, AxContextSchema> schemasMap) { + Assertions.argumentNotNull(schemasMap, "schemasMap may not be null"); + + this.schemas = new TreeMap<>(); + this.schemas.putAll(schemasMap); + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.model.basicmodel.concepts.AxConcept#validate(org.onap.policy.apex.model. + * basicmodel.concepts.AxValidationResult) + */ + @Override + public AxValidationResult validate(final AxValidationResult resultIn) { + AxValidationResult result = resultIn; + + if (key.equals(AxArtifactKey.getNullKey())) { + result.addValidationMessage( + new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID, "key is a null key")); + } + + result = key.validate(result); + + if (schemas.size() == 0) { + result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID, + "contextSchemas may not be empty")); + } else { + for (final Entry<AxArtifactKey, AxContextSchema> contextSchemaEntry : schemas.entrySet()) { + if (contextSchemaEntry.getKey().equals(AxArtifactKey.getNullKey())) { + result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID, + "key on schemas entry " + contextSchemaEntry.getKey() + " may not be the null key")); + } else if (contextSchemaEntry.getValue() == null) { + result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID, + "value on schemas entry " + contextSchemaEntry.getKey() + " may not be null")); + } else { + if (!contextSchemaEntry.getKey().equals(contextSchemaEntry.getValue().getKey())) { + result.addValidationMessage(new AxValidationMessage(key, this.getClass(), + ValidationResult.INVALID, "key on schemas entry " + contextSchemaEntry.getKey() + + " does not equal entry key " + contextSchemaEntry.getValue().getKey())); + } + + result = contextSchemaEntry.getValue().validate(result); + } + } + } + + return result; + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.model.basicmodel.concepts.AxConcept#clean() + */ + @Override + public void clean() { + key.clean(); + for (final Entry<AxArtifactKey, AxContextSchema> contextSchemaEntry : schemas.entrySet()) { + contextSchemaEntry.getKey().clean(); + contextSchemaEntry.getValue().clean(); + } + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.model.basicmodel.concepts.AxConcept#toString() + */ + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + builder.append(":("); + builder.append("key="); + builder.append(key); + builder.append(",schemas="); + builder.append(schemas); + builder.append(")"); + return builder.toString(); + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.model.basicmodel.concepts.AxConcept#copyTo(org.onap.policy.apex.model. + * basicmodel.concepts.AxConcept) + */ + @Override + public AxConcept copyTo(final AxConcept target) { + Assertions.argumentNotNull(target, "target may not be null"); + + final Object copyObject = target; + Assertions.instanceOf(copyObject, AxContextSchemas.class); + + final AxContextSchemas copy = ((AxContextSchemas) copyObject); + copy.setKey(new AxArtifactKey(key)); + + final Map<AxArtifactKey, AxContextSchema> newcontextSchemas = new TreeMap<>(); + for (final Entry<AxArtifactKey, AxContextSchema> contextSchemasEntry : schemas.entrySet()) { + newcontextSchemas.put(new AxArtifactKey(contextSchemasEntry.getKey()), + new AxContextSchema(contextSchemasEntry.getValue())); + } + copy.setSchemasMap(newcontextSchemas); + + return copy; + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.model.basicmodel.concepts.AxConcept#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + key.hashCode(); + result = prime * result + schemas.hashCode(); + return result; + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.model.basicmodel.concepts.AxConcept#equals(java.lang.Object) + */ + @Override + public boolean equals(final Object obj) { + if (obj == null) { + return false; + } + if (this == obj) { + return true; + } + if (getClass() != obj.getClass()) { + return false; + } + + final AxContextSchemas other = (AxContextSchemas) obj; + if (!key.equals(other.key)) { + return false; + } + return schemas.equals(other.schemas); + } + + /* + * (non-Javadoc) + * + * @see java.lang.Comparable#compareTo(java.lang.Object) + */ + @Override + public int compareTo(final AxConcept otherObj) { + if (otherObj == null) { + return -1; + } + if (this == otherObj) { + return 0; + } + if (getClass() != otherObj.getClass()) { + return this.hashCode() - otherObj.hashCode(); + } + + final AxContextSchemas other = (AxContextSchemas) otherObj; + if (!key.equals(other.key)) { + return key.compareTo(other.key); + } + if (!schemas.equals(other.schemas)) { + return (schemas.hashCode() - other.schemas.hashCode()); + } + + return 0; + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.core.basicmodel.concepts.AxConceptGetter#get(org.onap.policy.apex.core. + * basicmodel.concepts.AxArtifactKey) + */ + @Override + public AxContextSchema get(final AxArtifactKey conceptKey) { + return new AxConceptGetterImpl<>((NavigableMap<AxArtifactKey, AxContextSchema>) schemas).get(conceptKey); + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.core.basicmodel.concepts.AxConceptGetter#get(java.lang.String) + */ + @Override + public AxContextSchema get(final String conceptKeyName) { + return new AxConceptGetterImpl<>((NavigableMap<AxArtifactKey, AxContextSchema>) schemas).get(conceptKeyName); + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.core.basicmodel.concepts.AxConceptGetter#get(java.lang.String, java.lang.String) + */ + @Override + public AxContextSchema get(final String conceptKeyName, final String conceptKeyVersion) { + return new AxConceptGetterImpl<>((NavigableMap<AxArtifactKey, AxContextSchema>) schemas).get(conceptKeyName, + conceptKeyVersion); + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.core.basicmodel.concepts.AxConceptGetter#getAll(java.lang.String) + */ + @Override + public Set<AxContextSchema> getAll(final String conceptKeyName) { + return new AxConceptGetterImpl<>((NavigableMap<AxArtifactKey, AxContextSchema>) schemas).getAll(conceptKeyName); + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.core.basicmodel.concepts.AxConceptGetter#getAll(java.lang.String, java.lang.String) + */ + @Override + public Set<AxContextSchema> getAll(final String conceptKeyName, final String conceptKeyVersion) { + return new AxConceptGetterImpl<>((NavigableMap<AxArtifactKey, AxContextSchema>) schemas).getAll(conceptKeyName, + conceptKeyVersion); + } +} diff --git a/model/context-model/src/main/java/org/onap/policy/apex/model/contextmodel/concepts/package-info.java b/model/context-model/src/main/java/org/onap/policy/apex/model/contextmodel/concepts/package-info.java new file mode 100644 index 000000000..a7aa3a5ad --- /dev/null +++ b/model/context-model/src/main/java/org/onap/policy/apex/model/contextmodel/concepts/package-info.java @@ -0,0 +1,28 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2016-2018 Ericsson. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +/** + * Contains the concepts required to manage context in APEX. It defines the main APEX concepts of Context Schemas and + * Context Albums. + * + * @author Liam Fallon (liam.fallon@ericsson.com) + */ + +package org.onap.policy.apex.model.contextmodel.concepts; diff --git a/model/context-model/src/main/java/org/onap/policy/apex/model/contextmodel/handling/ContextComparer.java b/model/context-model/src/main/java/org/onap/policy/apex/model/contextmodel/handling/ContextComparer.java new file mode 100644 index 000000000..7a5ebfd22 --- /dev/null +++ b/model/context-model/src/main/java/org/onap/policy/apex/model/contextmodel/handling/ContextComparer.java @@ -0,0 +1,70 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2016-2018 Ericsson. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.apex.model.contextmodel.handling; + +import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey; +import org.onap.policy.apex.model.contextmodel.concepts.AxContextAlbum; +import org.onap.policy.apex.model.contextmodel.concepts.AxContextAlbums; +import org.onap.policy.apex.model.contextmodel.concepts.AxContextSchema; +import org.onap.policy.apex.model.contextmodel.concepts.AxContextSchemas; +import org.onap.policy.apex.model.utilities.comparison.KeyedMapComparer; +import org.onap.policy.apex.model.utilities.comparison.KeyedMapDifference; + +/** + * This class compares the context in two AxContext objects and returns the differences. The + * differences are returned in a {@link KeyedMapDifference} object that contains the left, equal, + * and right context schemas or albums. + * + * @author Liam Fallon (liam.fallon@ericsson.com) + */ +public class ContextComparer { + + /** + * Compare two {@link AxContextAlbums} objects, comparing their context albums one after + * another. + * + * @param left the left context + * @param right the right context + * @return the difference + */ + public KeyedMapDifference<AxArtifactKey, AxContextAlbum> compare(final AxContextAlbums left, + final AxContextAlbums right) { + // Find the difference between the AxContext objects + return new KeyedMapComparer<AxArtifactKey, AxContextAlbum>().compareMaps(left.getAlbumsMap(), + right.getAlbumsMap()); + } + + /** + * Compare two {@link AxContextSchema} objects, comparing their context schemas one after + * another. + * + * @param left the left context + * @param right the right context + * @return the difference + */ + public KeyedMapDifference<AxArtifactKey, AxContextSchema> compare(final AxContextSchemas left, + final AxContextSchemas right) { + // Find the difference between the AxContext objects + return new KeyedMapComparer<AxArtifactKey, AxContextSchema>().compareMaps(left.getSchemasMap(), + right.getSchemasMap()); + } + +} diff --git a/model/context-model/src/main/java/org/onap/policy/apex/model/contextmodel/handling/package-info.java b/model/context-model/src/main/java/org/onap/policy/apex/model/contextmodel/handling/package-info.java new file mode 100644 index 000000000..ec1fa893f --- /dev/null +++ b/model/context-model/src/main/java/org/onap/policy/apex/model/contextmodel/handling/package-info.java @@ -0,0 +1,27 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2016-2018 Ericsson. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +/** + * Provides some helper classes for handling context, including a utility class for comparing two + * context objects. + * + * @author Liam Fallon (liam.fallon@ericsson.com) + */ +package org.onap.policy.apex.model.contextmodel.handling; |