Adding apex context-model module 81/48981/5
authorwaqas.ikram <waqas.ikram@ericsson.com>
Thu, 24 May 2018 16:00:47 +0000 (17:00 +0100)
committerwaqas.ikram <waqas.ikram@ericsson.com>
Thu, 24 May 2018 16:30:18 +0000 (17:30 +0100)
Change-Id: Ia80b2caa0f76ecd7a80ece79e5cf88ac9de048ac
Issue-ID: POLICY-856
Signed-off-by: waqas.ikram <waqas.ikram@ericsson.com>
20 files changed:
model/context-model/pom.xml [new file with mode: 0644]
model/context-model/src/main/java/org/onap/apex/model/contextmodel/concepts/AxContextAlbum.java [new file with mode: 0644]
model/context-model/src/main/java/org/onap/apex/model/contextmodel/concepts/AxContextAlbums.java [new file with mode: 0644]
model/context-model/src/main/java/org/onap/apex/model/contextmodel/concepts/AxContextModel.java [new file with mode: 0644]
model/context-model/src/main/java/org/onap/apex/model/contextmodel/concepts/AxContextSchema.java [new file with mode: 0644]
model/context-model/src/main/java/org/onap/apex/model/contextmodel/concepts/AxContextSchemas.java [new file with mode: 0644]
model/context-model/src/main/java/org/onap/apex/model/contextmodel/concepts/package-info.java [new file with mode: 0644]
model/context-model/src/main/java/org/onap/apex/model/contextmodel/handling/ContextComparer.java [new file with mode: 0644]
model/context-model/src/main/java/org/onap/apex/model/contextmodel/handling/package-info.java [new file with mode: 0644]
model/context-model/src/test/java/org/onap/apex/model/contextmodel/concepts/TestContextAlbums.java [new file with mode: 0644]
model/context-model/src/test/java/org/onap/apex/model/contextmodel/concepts/TestContextModel.java [new file with mode: 0644]
model/context-model/src/test/java/org/onap/apex/model/contextmodel/concepts/TestContextSchemas.java [new file with mode: 0644]
model/context-model/src/test/java/org/onap/apex/model/contextmodel/handling/TestApexContextModel.java [new file with mode: 0644]
model/context-model/src/test/java/org/onap/apex/model/contextmodel/handling/TestApexContextModelCreator.java [new file with mode: 0644]
model/context-model/src/test/java/org/onap/apex/model/contextmodel/handling/TestContextComparison.java [new file with mode: 0644]
model/context-model/src/test/java/org/onap/apex/model/contextmodel/handling/TestContextComparisonFactory.java [new file with mode: 0644]
model/context-model/src/test/resources/META-INF/persistence.xml [new file with mode: 0644]
model/context-model/src/test/resources/json/ContextModel.json [new file with mode: 0644]
model/context-model/src/test/resources/logback-test.xml [new file with mode: 0644]
model/pom.xml

diff --git a/model/context-model/pom.xml b/model/context-model/pom.xml
new file mode 100644 (file)
index 0000000..9f7766c
--- /dev/null
@@ -0,0 +1,72 @@
+<!--
+  ============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=========================================================
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.onap.policy.apex-pdp.model</groupId>
+        <artifactId>model</artifactId>
+        <version>2.0.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>context-model</artifactId>
+    <name>${project.artifactId}</name>
+    <description>Context Models used in Apex</description>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.onap.policy.apex-pdp.model</groupId>
+            <artifactId>basic-model</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.derby</groupId>
+            <artifactId>derby</artifactId>
+            <version>10.13.1.1</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>exec-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>generate-xml-schema</id>
+                        <phase>process-classes</phase>
+                        <goals>
+                            <goal>java</goal>
+                        </goals>
+                        <configuration>
+                            <mainClass>org.onap.apex.model.basicmodel.handling.ApexSchemaGenerator</mainClass>
+                            <classpathScope>compile</classpathScope>
+                            <arguments>
+                                <argument>org.onap.apex.model.contextmodel.concepts.AxContextModel</argument>
+                                <argument>${project.build.directory}/model/xml/apex-context-model.xsd</argument>
+                            </arguments>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
\ No newline at end of file
diff --git a/model/context-model/src/main/java/org/onap/apex/model/contextmodel/concepts/AxContextAlbum.java b/model/context-model/src/main/java/org/onap/apex/model/contextmodel/concepts/AxContextAlbum.java
new file mode 100644 (file)
index 0000000..045ea0a
--- /dev/null
@@ -0,0 +1,426 @@
+/*-
+ * ============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.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.apex.model.basicmodel.concepts.AxArtifactKey;
+import org.onap.apex.model.basicmodel.concepts.AxConcept;
+import org.onap.apex.model.basicmodel.concepts.AxKey;
+import org.onap.apex.model.basicmodel.concepts.AxKeyUse;
+import org.onap.apex.model.basicmodel.concepts.AxValidationMessage;
+import org.onap.apex.model.basicmodel.concepts.AxValidationResult;
+import org.onap.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.ericsson.com/apex")
+@XmlType(name = "AxContextAlbum", namespace = "http://www.ericsson.com/apex",
+        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 com.ericsson.apex.model.basicmodel.concepts.AxConcept#getKey()
+     */
+    @Override
+    public AxArtifactKey getKey() {
+        return key;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see com.ericsson.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 com.ericsson.apex.model.basicmodel.concepts.AxConcept#validate(com.ericsson.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 com.ericsson.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 com.ericsson.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 com.ericsson.apex.model.basicmodel.concepts.AxConcept#copyTo(com.ericsson.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 com.ericsson.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 com.ericsson.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/apex/model/contextmodel/concepts/AxContextAlbums.java b/model/context-model/src/main/java/org/onap/apex/model/contextmodel/concepts/AxContextAlbums.java
new file mode 100644 (file)
index 0000000..e48d064
--- /dev/null
@@ -0,0 +1,427 @@
+/*-
+ * ============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.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.apex.model.basicmodel.concepts.AxArtifactKey;
+import org.onap.apex.model.basicmodel.concepts.AxConcept;
+import org.onap.apex.model.basicmodel.concepts.AxConceptGetter;
+import org.onap.apex.model.basicmodel.concepts.AxConceptGetterImpl;
+import org.onap.apex.model.basicmodel.concepts.AxKey;
+import org.onap.apex.model.basicmodel.concepts.AxValidationMessage;
+import org.onap.apex.model.basicmodel.concepts.AxValidationResult;
+import org.onap.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.ericsson.com/apex", 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 com.ericsson.apex.model.basicmodel.concepts.AxConcept#getKey()
+     */
+    @Override
+    public AxArtifactKey getKey() {
+        return key;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see com.ericsson.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 com.ericsson.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 com.ericsson.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 com.ericsson.apex.model.basicmodel.concepts.AxConcept#validate(com.ericsson.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 com.ericsson.apex.model.basicmodel.concepts.AxConcept#copyTo(com.ericsson.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 com.ericsson.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 com.ericsson.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 com.ericsson.apex.model.basicmodel.concepts.AxConceptGetter#get(com.ericsson.apex.model.
+     * basicmodel.concepts.AxArtifactKey)
+     */
+    @Override
+    public AxContextAlbum get(final AxArtifactKey conceptKey) {
+        return new AxConceptGetterImpl<>((NavigableMap<AxArtifactKey, AxContextAlbum>) albums).get(conceptKey);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see com.ericsson.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 com.ericsson.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 com.ericsson.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 com.ericsson.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/apex/model/contextmodel/concepts/AxContextModel.java b/model/context-model/src/main/java/org/onap/apex/model/contextmodel/concepts/AxContextModel.java
new file mode 100644 (file)
index 0000000..dcd3818
--- /dev/null
@@ -0,0 +1,346 @@
+/*-
+ * ============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.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.apex.model.basicmodel.concepts.AxArtifactKey;
+import org.onap.apex.model.basicmodel.concepts.AxConcept;
+import org.onap.apex.model.basicmodel.concepts.AxKey;
+import org.onap.apex.model.basicmodel.concepts.AxKeyInformation;
+import org.onap.apex.model.basicmodel.concepts.AxModel;
+import org.onap.apex.model.basicmodel.concepts.AxValidationResult;
+import org.onap.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.ericsson.com/apex")
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "AxContextModel", namespace = "http://www.ericsson.com/apex", 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 com.ericsson.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 com.ericsson.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 com.ericsson.apex.model.basicmodel.concepts.AxModel#validate(com.ericsson.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 com.ericsson.apex.model.basicmodel.concepts.AxModel#clean()
+     */
+    @Override
+    public void clean() {
+        super.clean();
+        schemas.clean();
+        albums.clean();
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see com.ericsson.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 com.ericsson.apex.model.basicmodel.concepts.AxConcept#copyTo(com.ericsson.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 com.ericsson.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 com.ericsson.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 com.ericsson.apex.model.basicmodel.concepts.AxModel#compareTo(com.ericsson.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/apex/model/contextmodel/concepts/AxContextSchema.java b/model/context-model/src/main/java/org/onap/apex/model/contextmodel/concepts/AxContextSchema.java
new file mode 100644 (file)
index 0000000..852e3f5
--- /dev/null
@@ -0,0 +1,383 @@
+/*-
+ * ============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.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.apex.model.basicmodel.concepts.AxArtifactKey;
+import org.onap.apex.model.basicmodel.concepts.AxConcept;
+import org.onap.apex.model.basicmodel.concepts.AxKey;
+import org.onap.apex.model.basicmodel.concepts.AxValidationMessage;
+import org.onap.apex.model.basicmodel.concepts.AxValidationResult;
+import org.onap.apex.model.basicmodel.concepts.AxValidationResult.ValidationResult;
+import org.onap.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.ericsson.com/apex")
+@XmlType(name = "AxContextSchema", namespace = "http://www.ericsson.com/apex",
+        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 com.ericsson.apex.model.basicmodel.concepts.AxConcept#getKey()
+     */
+    @Override
+    public AxArtifactKey getKey() {
+        return key;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see com.ericsson.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 com.ericsson.apex.model.basicmodel.concepts.AxConcept#validate(com.ericsson.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 com.ericsson.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 com.ericsson.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 com.ericsson.apex.model.basicmodel.concepts.AxConcept#copyTo(com.ericsson.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 com.ericsson.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 com.ericsson.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/apex/model/contextmodel/concepts/AxContextSchemas.java b/model/context-model/src/main/java/org/onap/apex/model/contextmodel/concepts/AxContextSchemas.java
new file mode 100644 (file)
index 0000000..b4a7e4a
--- /dev/null
@@ -0,0 +1,424 @@
+/*-
+ * ============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.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.apex.model.basicmodel.concepts.AxArtifactKey;
+import org.onap.apex.model.basicmodel.concepts.AxConcept;
+import org.onap.apex.model.basicmodel.concepts.AxConceptGetter;
+import org.onap.apex.model.basicmodel.concepts.AxConceptGetterImpl;
+import org.onap.apex.model.basicmodel.concepts.AxKey;
+import org.onap.apex.model.basicmodel.concepts.AxValidationMessage;
+import org.onap.apex.model.basicmodel.concepts.AxValidationResult;
+import org.onap.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.ericsson.com/apex", 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 com.ericsson.apex.model.basicmodel.concepts.AxConcept#getKey()
+     */
+    @Override
+    public AxArtifactKey getKey() {
+        return key;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see com.ericsson.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 com.ericsson.apex.model.basicmodel.concepts.AxConcept#validate(com.ericsson.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 com.ericsson.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 com.ericsson.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 com.ericsson.apex.model.basicmodel.concepts.AxConcept#copyTo(com.ericsson.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 com.ericsson.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 com.ericsson.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 com.ericsson.apex.core.basicmodel.concepts.AxConceptGetter#get(com.ericsson.apex.core.
+     * basicmodel.concepts.AxArtifactKey)
+     */
+    @Override
+    public AxContextSchema get(final AxArtifactKey conceptKey) {
+        return new AxConceptGetterImpl<>((NavigableMap<AxArtifactKey, AxContextSchema>) schemas).get(conceptKey);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see com.ericsson.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 com.ericsson.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 com.ericsson.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 com.ericsson.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/apex/model/contextmodel/concepts/package-info.java b/model/context-model/src/main/java/org/onap/apex/model/contextmodel/concepts/package-info.java
new file mode 100644 (file)
index 0000000..f89f2f8
--- /dev/null
@@ -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=========================================================
+ */
+
+/**
+ * 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.apex.model.contextmodel.concepts;
diff --git a/model/context-model/src/main/java/org/onap/apex/model/contextmodel/handling/ContextComparer.java b/model/context-model/src/main/java/org/onap/apex/model/contextmodel/handling/ContextComparer.java
new file mode 100644 (file)
index 0000000..8d654be
--- /dev/null
@@ -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.apex.model.contextmodel.handling;
+
+import org.onap.apex.model.basicmodel.concepts.AxArtifactKey;
+import org.onap.apex.model.contextmodel.concepts.AxContextAlbum;
+import org.onap.apex.model.contextmodel.concepts.AxContextAlbums;
+import org.onap.apex.model.contextmodel.concepts.AxContextSchema;
+import org.onap.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/apex/model/contextmodel/handling/package-info.java b/model/context-model/src/main/java/org/onap/apex/model/contextmodel/handling/package-info.java
new file mode 100644 (file)
index 0000000..bfc44f7
--- /dev/null
@@ -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.apex.model.contextmodel.handling;
diff --git a/model/context-model/src/test/java/org/onap/apex/model/contextmodel/concepts/TestContextAlbums.java b/model/context-model/src/test/java/org/onap/apex/model/contextmodel/concepts/TestContextAlbums.java
new file mode 100644 (file)
index 0000000..476cda9
--- /dev/null
@@ -0,0 +1,210 @@
+/*-
+ * ============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.apex.model.contextmodel.concepts;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import org.junit.Test;
+import org.onap.apex.model.basicmodel.concepts.AxArtifactKey;
+import org.onap.apex.model.basicmodel.concepts.AxValidationResult;
+import org.onap.apex.model.basicmodel.concepts.AxValidationResult.ValidationResult;
+import org.onap.apex.model.contextmodel.concepts.AxContextAlbum;
+import org.onap.apex.model.contextmodel.concepts.AxContextAlbums;
+
+/**
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class TestContextAlbums {
+
+    @Test
+    public void testContextAlbums() {
+        assertNotNull(new AxContextAlbum());
+        assertNotNull(new AxContextAlbum(new AxArtifactKey()));
+        assertNotNull(new AxContextAlbum(new AxArtifactKey(), "AlbumScope", false, new AxArtifactKey()));
+
+        final AxArtifactKey albumKey = new AxArtifactKey("AlbumName", "0.0.1");
+        final AxArtifactKey albumSchemaKey = new AxArtifactKey("AlbumSchemaName", "0.0.1");
+
+        final AxContextAlbum album = new AxContextAlbum(albumKey, "AlbumScope", false, albumSchemaKey);
+        assertNotNull(album);
+
+        final AxArtifactKey newKey = new AxArtifactKey("NewAlbumName", "0.0.1");
+        album.setKey(newKey);
+        assertEquals("NewAlbumName:0.0.1", album.getKey().getID());
+        assertEquals("NewAlbumName:0.0.1", album.getKeys().get(0).getID());
+        album.setKey(albumKey);
+
+        try {
+            album.setScope("");
+            fail("test should throw an exception here");
+        } catch (final Exception e) {
+            assertEquals("parameter \"scope\": value \"\", does not match regular expression \"[A-Za-z0-9\\-_]+\"",
+                    e.getMessage());
+        }
+
+        album.setScope("NewAlbumScope");
+        assertEquals("NewAlbumScope", album.getScope());
+
+        assertEquals(false, album.isWritable());
+        album.setWritable(true);
+        assertEquals(true, album.isWritable());
+
+        final AxArtifactKey newSchemaKey = new AxArtifactKey("NewAlbumSchemaName", "0.0.1");
+        album.setItemSchema(newSchemaKey);
+        assertEquals("NewAlbumSchemaName:0.0.1", album.getItemSchema().getID());
+        album.setItemSchema(albumSchemaKey);
+
+        AxValidationResult result = new AxValidationResult();
+        result = album.validate(result);
+        assertEquals(ValidationResult.VALID, result.getValidationResult());
+
+        album.setKey(AxArtifactKey.getNullKey());
+        result = new AxValidationResult();
+        result = album.validate(result);
+        assertEquals(ValidationResult.INVALID, result.getValidationResult());
+
+        album.setKey(newKey);
+        result = new AxValidationResult();
+        result = album.validate(result);
+        assertEquals(ValidationResult.VALID, result.getValidationResult());
+
+        album.setScope("UNDEFINED");
+        result = new AxValidationResult();
+        result = album.validate(result);
+        assertEquals(ValidationResult.INVALID, result.getValidationResult());
+
+        album.setScope("NewAlbumScope");
+        result = new AxValidationResult();
+        result = album.validate(result);
+        assertEquals(ValidationResult.VALID, result.getValidationResult());
+
+        album.setItemSchema(AxArtifactKey.getNullKey());
+        result = new AxValidationResult();
+        result = album.validate(result);
+        assertEquals(ValidationResult.INVALID, result.getValidationResult());
+
+        album.setItemSchema(albumSchemaKey);
+        result = new AxValidationResult();
+        result = album.validate(result);
+        assertEquals(ValidationResult.VALID, result.getValidationResult());
+
+        album.clean();
+
+        final AxContextAlbum clonedAlbum = new AxContextAlbum(album);
+        assertEquals(
+                "AxContextAlbum:(key=AxArtifactKey:(name=NewAlbumName,version=0.0.1),scope=NewAlbumScope,isWritable=true,itemSchema=AxArtifactKey:(name=AlbumSchemaName,version=0.0.1))",
+                clonedAlbum.toString());
+
+        assertFalse(album.hashCode() == 0);
+
+        assertTrue(album.equals(album));
+        assertTrue(album.equals(clonedAlbum));
+        assertFalse(album.equals(null));
+        assertFalse(album.equals("Hello"));
+        assertFalse(album.equals(new AxContextAlbum(new AxArtifactKey(), "Scope", false, AxArtifactKey.getNullKey())));
+        assertFalse(album.equals(new AxContextAlbum(newKey, "Scope", false, AxArtifactKey.getNullKey())));
+        assertFalse(album.equals(new AxContextAlbum(newKey, "NewAlbumScope", false, AxArtifactKey.getNullKey())));
+        assertFalse(album.equals(new AxContextAlbum(newKey, "NewAlbumScope", true, AxArtifactKey.getNullKey())));
+        assertTrue(album.equals(new AxContextAlbum(newKey, "NewAlbumScope", true, albumSchemaKey)));
+
+        assertEquals(0, album.compareTo(album));
+        assertEquals(0, album.compareTo(clonedAlbum));
+        assertNotEquals(0, album.compareTo(null));
+        assertNotEquals(0, album.compareTo(new AxArtifactKey()));
+        assertNotEquals(0,
+                album.compareTo(new AxContextAlbum(new AxArtifactKey(), "Scope", false, AxArtifactKey.getNullKey())));
+        assertNotEquals(0, album.compareTo(new AxContextAlbum(newKey, "Scope", false, AxArtifactKey.getNullKey())));
+        assertNotEquals(0,
+                album.compareTo(new AxContextAlbum(newKey, "NewAlbumScope", false, AxArtifactKey.getNullKey())));
+        assertNotEquals(0,
+                album.compareTo(new AxContextAlbum(newKey, "NewAlbumScope", true, AxArtifactKey.getNullKey())));
+        assertEquals(0, album.compareTo(new AxContextAlbum(newKey, "NewAlbumScope", true, albumSchemaKey)));
+
+        final AxContextAlbums albums = new AxContextAlbums();
+        result = new AxValidationResult();
+        result = albums.validate(result);
+        assertEquals(ValidationResult.INVALID, result.getValidationResult());
+
+        // Observation, no albums in album map
+        albums.setKey(new AxArtifactKey("AlbumsKey", "0.0.1"));
+        result = new AxValidationResult();
+        result = albums.validate(result);
+        assertEquals(ValidationResult.OBSERVATION, result.getValidationResult());
+
+        albums.getAlbumsMap().put(newKey, album);
+        result = new AxValidationResult();
+        result = albums.validate(result);
+        assertEquals(ValidationResult.VALID, result.getValidationResult());
+
+        albums.getAlbumsMap().put(AxArtifactKey.getNullKey(), null);
+        result = new AxValidationResult();
+        result = albums.validate(result);
+        assertEquals(ValidationResult.INVALID, result.getValidationResult());
+
+        albums.getAlbumsMap().remove(AxArtifactKey.getNullKey());
+        result = new AxValidationResult();
+        result = albums.validate(result);
+        assertEquals(ValidationResult.VALID, result.getValidationResult());
+
+        albums.getAlbumsMap().put(new AxArtifactKey("NullValueKey", "0.0.1"), null);
+        result = new AxValidationResult();
+        result = albums.validate(result);
+        assertEquals(ValidationResult.INVALID, result.getValidationResult());
+
+        albums.getAlbumsMap().remove(new AxArtifactKey("NullValueKey", "0.0.1"));
+        result = new AxValidationResult();
+        result = albums.validate(result);
+        assertEquals(ValidationResult.VALID, result.getValidationResult());
+
+        albums.clean();
+
+        final AxContextAlbums clonedAlbums = new AxContextAlbums(albums);
+        assertTrue(clonedAlbums.toString()
+                .startsWith("AxContextAlbums:(AxContextAlbums:(key=AxArtifactKey:(name=AlbumsKey,version=0.0.1)"));
+
+        assertFalse(albums.hashCode() == 0);
+
+        assertTrue(albums.equals(albums));
+        assertTrue(albums.equals(clonedAlbums));
+        assertFalse(albums.equals(null));
+        assertFalse(albums.equals("Hello"));
+        assertFalse(albums.equals(new AxContextAlbums(new AxArtifactKey())));
+
+        assertEquals(0, albums.compareTo(albums));
+        assertEquals(0, albums.compareTo(clonedAlbums));
+        assertNotEquals(0, albums.compareTo(null));
+        assertNotEquals(0, albums.compareTo(new AxArtifactKey()));
+        assertNotEquals(0, albums.compareTo(new AxContextAlbums(new AxArtifactKey())));
+
+        clonedAlbums.get(newKey).setScope("YetAnotherScope");
+        assertNotEquals(0, albums.compareTo(clonedAlbums));
+
+        assertEquals("NewAlbumName", albums.get("NewAlbumName").getKey().getName());
+        assertEquals("NewAlbumName", albums.get("NewAlbumName", "0.0.1").getKey().getName());
+        assertEquals(1, albums.getAll("NewAlbumName", "0.0.1").size());
+        assertEquals(0, albums.getAll("NonExistantAlbumName").size());
+    }
+}
diff --git a/model/context-model/src/test/java/org/onap/apex/model/contextmodel/concepts/TestContextModel.java b/model/context-model/src/test/java/org/onap/apex/model/contextmodel/concepts/TestContextModel.java
new file mode 100644 (file)
index 0000000..cab40f3
--- /dev/null
@@ -0,0 +1,82 @@
+/*-
+ * ============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.apex.model.contextmodel.concepts;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+import org.onap.apex.model.basicmodel.concepts.AxArtifactKey;
+import org.onap.apex.model.basicmodel.concepts.AxKeyInformation;
+import org.onap.apex.model.contextmodel.concepts.AxContextAlbums;
+import org.onap.apex.model.contextmodel.concepts.AxContextModel;
+import org.onap.apex.model.contextmodel.concepts.AxContextSchemas;
+
+/**
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class TestContextModel {
+
+    @Test
+    public void test() {
+        assertNotNull(new AxContextModel());
+        assertNotNull(new AxContextModel(new AxArtifactKey()));
+        assertNotNull(new AxContextModel(new AxArtifactKey(), new AxContextSchemas(), new AxKeyInformation()));
+        assertNotNull(new AxContextModel(new AxArtifactKey(), new AxContextSchemas(), new AxContextAlbums(), new AxKeyInformation()));
+        
+        final AxArtifactKey modelKey = new AxArtifactKey("ModelKey", "0.0.1");
+        final AxArtifactKey schemasKey = new AxArtifactKey("SchemasKey", "0.0.1");
+        final AxArtifactKey albumsKey = new AxArtifactKey("SchemasKey", "0.0.1");
+        final AxArtifactKey keyInfoKey = new AxArtifactKey("SchemasKey", "0.0.1");
+        final AxContextModel model = new AxContextModel(modelKey, new AxContextSchemas(schemasKey), new AxContextAlbums(albumsKey), new AxKeyInformation(keyInfoKey));
+        model.register();
+        
+        model.clean();
+        assertNotNull(model);
+        assertEquals("AxContextModel:(AxContextModel:(key=AxArtifactKey:", model.toString().substring(0, 50));
+        
+        final AxContextModel clonedModel = new AxContextModel(model);
+
+        assertFalse(model.hashCode() == 0);
+
+        assertTrue(model.equals(model));
+        assertTrue(model.equals(clonedModel));
+        assertFalse(model.equals("Hello"));
+        assertFalse(model.equals(new AxContextModel(new AxArtifactKey())));
+        assertFalse(model.equals(new AxContextModel(new AxArtifactKey(), new AxContextSchemas(), new AxContextAlbums(), new AxKeyInformation())));
+        assertFalse(model.equals(new AxContextModel(modelKey, new AxContextSchemas(), new AxContextAlbums(), new AxKeyInformation())));
+        assertFalse(model.equals(new AxContextModel(modelKey, new AxContextSchemas(), new AxContextAlbums(), new AxKeyInformation(keyInfoKey))));
+        assertFalse(model.equals(new AxContextModel(modelKey, new AxContextSchemas(schemasKey), new AxContextAlbums(), new AxKeyInformation(keyInfoKey))));
+        assertTrue(model.equals(new AxContextModel(modelKey, new AxContextSchemas(schemasKey), new AxContextAlbums(albumsKey), new AxKeyInformation(keyInfoKey))));
+
+        assertEquals(0, model.compareTo(model));
+        assertEquals(0, model.compareTo(clonedModel));
+        assertNotEquals(0, model.compareTo(new AxArtifactKey()));
+        assertNotEquals(0, model.compareTo(new AxContextModel(new AxArtifactKey(), new AxContextSchemas(), new AxContextAlbums(), new AxKeyInformation())));
+        assertNotEquals(0, model.compareTo(new AxContextModel(modelKey, new AxContextSchemas(), new AxContextAlbums(), new AxKeyInformation())));
+        assertNotEquals(0, model.compareTo(new AxContextModel(modelKey, new AxContextSchemas(), new AxContextAlbums(), new AxKeyInformation(keyInfoKey))));
+        assertNotEquals(0, model.compareTo(new AxContextModel(modelKey, new AxContextSchemas(schemasKey), new AxContextAlbums(), new AxKeyInformation(keyInfoKey))));
+        assertEquals(0, model.compareTo(new AxContextModel(modelKey, new AxContextSchemas(schemasKey), new AxContextAlbums(albumsKey), new AxKeyInformation(keyInfoKey))));
+    }
+}
diff --git a/model/context-model/src/test/java/org/onap/apex/model/contextmodel/concepts/TestContextSchemas.java b/model/context-model/src/test/java/org/onap/apex/model/contextmodel/concepts/TestContextSchemas.java
new file mode 100644 (file)
index 0000000..1e81c5a
--- /dev/null
@@ -0,0 +1,196 @@
+/*-
+ * ============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.apex.model.contextmodel.concepts;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import org.junit.Test;
+import org.onap.apex.model.basicmodel.concepts.AxArtifactKey;
+import org.onap.apex.model.basicmodel.concepts.AxValidationResult;
+import org.onap.apex.model.basicmodel.concepts.AxValidationResult.ValidationResult;
+import org.onap.apex.model.contextmodel.concepts.AxContextSchema;
+import org.onap.apex.model.contextmodel.concepts.AxContextSchemas;
+
+/**
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class TestContextSchemas {
+
+    @Test
+    public void testContextSchemas() {
+        assertNotNull(new AxContextSchema());
+        assertNotNull(new AxContextSchema(new AxArtifactKey(), "SchemaFlavour", "SchemaDefinition"));
+
+        final AxContextSchema schema =
+                new AxContextSchema(new AxArtifactKey("SchemaName", "0.0.1"), "SchemaFlavour", "SchemaDefinition");
+        assertNotNull(schema);
+
+        final AxArtifactKey newKey = new AxArtifactKey("NewSchemaName", "0.0.1");
+        schema.setKey(newKey);
+        assertEquals("NewSchemaName:0.0.1", schema.getKey().getID());
+        assertEquals("NewSchemaName:0.0.1", schema.getKeys().get(0).getID());
+
+        try {
+            schema.setSchemaFlavour("");
+            fail("test should throw an exception here");
+        } catch (final Exception e) {
+            assertEquals(
+                    "parameter \"schemaFlavour\": value \"\", does not match regular expression \"[A-Za-z0-9\\-_]+\"",
+                    e.getMessage());
+        }
+
+        schema.setSchemaFlavour("NewSchemaFlavour");
+        assertEquals("NewSchemaFlavour", schema.getSchemaFlavour());
+
+        schema.setSchema("NewSchemaDefinition");
+        assertEquals("NewSchemaDefinition", schema.getSchema());
+
+        AxValidationResult result = new AxValidationResult();
+        result = schema.validate(result);
+        assertEquals(ValidationResult.VALID, result.getValidationResult());
+
+        schema.setKey(AxArtifactKey.getNullKey());
+        result = new AxValidationResult();
+        result = schema.validate(result);
+        assertEquals(ValidationResult.INVALID, result.getValidationResult());
+
+        schema.setKey(newKey);
+        result = new AxValidationResult();
+        result = schema.validate(result);
+        assertEquals(ValidationResult.VALID, result.getValidationResult());
+
+        schema.setSchemaFlavour("UNDEFINED");
+        result = new AxValidationResult();
+        result = schema.validate(result);
+        assertEquals(ValidationResult.INVALID, result.getValidationResult());
+
+        schema.setSchemaFlavour("NewSchemaFlavour");
+        result = new AxValidationResult();
+        result = schema.validate(result);
+        assertEquals(ValidationResult.VALID, result.getValidationResult());
+
+        schema.setSchema("");
+        result = new AxValidationResult();
+        result = schema.validate(result);
+        assertEquals(ValidationResult.INVALID, result.getValidationResult());
+
+        schema.setSchema("NewSchemaDefinition");
+        result = new AxValidationResult();
+        result = schema.validate(result);
+        assertEquals(ValidationResult.VALID, result.getValidationResult());
+
+        schema.clean();
+
+        final AxContextSchema clonedSchema = new AxContextSchema(schema);
+        assertEquals(
+                "AxContextSchema:(key=AxArtifactKey:(name=NewSchemaName,version=0.0.1),schemaFlavour=NewSchemaFlavour,schemaDefinition=NewSchemaDefinition)",
+                clonedSchema.toString());
+
+        assertFalse(schema.hashCode() == 0);
+
+        assertTrue(schema.equals(schema));
+        assertTrue(schema.equals(clonedSchema));
+        assertFalse(schema.equals(null));
+        assertFalse(schema.equals("Hello"));
+        assertFalse(schema.equals(new AxContextSchema(new AxArtifactKey(), "Flavour", "Def")));
+        assertFalse(schema.equals(new AxContextSchema(newKey, "Flavour", "Def")));
+        assertFalse(schema.equals(new AxContextSchema(newKey, "NewSchemaFlavour", "Def")));
+        assertTrue(schema.equals(new AxContextSchema(newKey, "NewSchemaFlavour", "NewSchemaDefinition")));
+
+        assertEquals(0, schema.compareTo(schema));
+        assertEquals(0, schema.compareTo(clonedSchema));
+        assertNotEquals(0, schema.compareTo(null));
+        assertNotEquals(0, schema.compareTo(new AxArtifactKey()));
+        assertNotEquals(0, schema.compareTo(new AxContextSchema(new AxArtifactKey(), "Flavour", "Def")));
+        assertNotEquals(0, schema.compareTo(new AxContextSchema(newKey, "Flavour", "Def")));
+        assertNotEquals(0, schema.compareTo(new AxContextSchema(newKey, "NewSchemaFlavour", "Def")));
+        assertEquals(0, schema.compareTo(new AxContextSchema(newKey, "NewSchemaFlavour", "NewSchemaDefinition")));
+
+        final AxContextSchemas schemas = new AxContextSchemas();
+        result = new AxValidationResult();
+        result = schemas.validate(result);
+        assertEquals(ValidationResult.INVALID, result.getValidationResult());
+
+        // Still invalid, no schemas in schema map
+        schemas.setKey(new AxArtifactKey("SchemasKey", "0.0.1"));
+        result = new AxValidationResult();
+        result = schemas.validate(result);
+        assertEquals(ValidationResult.INVALID, result.getValidationResult());
+
+        schemas.getSchemasMap().put(newKey, schema);
+        result = new AxValidationResult();
+        result = schemas.validate(result);
+        assertEquals(ValidationResult.VALID, result.getValidationResult());
+
+        schemas.getSchemasMap().put(AxArtifactKey.getNullKey(), null);
+        result = new AxValidationResult();
+        result = schemas.validate(result);
+        assertEquals(ValidationResult.INVALID, result.getValidationResult());
+
+        schemas.getSchemasMap().remove(AxArtifactKey.getNullKey());
+        result = new AxValidationResult();
+        result = schemas.validate(result);
+        assertEquals(ValidationResult.VALID, result.getValidationResult());
+
+        schemas.getSchemasMap().put(new AxArtifactKey("NullValueKey", "0.0.1"), null);
+        result = new AxValidationResult();
+        result = schemas.validate(result);
+        assertEquals(ValidationResult.INVALID, result.getValidationResult());
+
+        schemas.getSchemasMap().remove(new AxArtifactKey("NullValueKey", "0.0.1"));
+        result = new AxValidationResult();
+        result = schemas.validate(result);
+        assertEquals(ValidationResult.VALID, result.getValidationResult());
+
+        schemas.clean();
+
+        final AxContextSchemas clonedSchemas = new AxContextSchemas(schemas);
+        assertTrue(clonedSchemas.toString()
+                .startsWith("AxContextSchemas:(key=AxArtifactKey:(name=SchemasKey,version=0.0.1),"));
+
+        assertFalse(schemas.hashCode() == 0);
+
+        assertTrue(schemas.equals(schemas));
+        assertTrue(schemas.equals(clonedSchemas));
+        assertFalse(schemas.equals(null));
+        assertFalse(schemas.equals("Hello"));
+        assertFalse(schemas.equals(new AxContextSchemas(new AxArtifactKey())));
+
+        assertEquals(0, schemas.compareTo(schemas));
+        assertEquals(0, schemas.compareTo(clonedSchemas));
+        assertNotEquals(0, schemas.compareTo(null));
+        assertNotEquals(0, schemas.compareTo(new AxArtifactKey()));
+        assertNotEquals(0, schemas.compareTo(new AxContextSchemas(new AxArtifactKey())));
+
+        clonedSchemas.get(newKey).setSchemaFlavour("YetAnotherFlavour");
+        assertNotEquals(0, schemas.compareTo(clonedSchemas));
+
+        assertEquals("NewSchemaName", schemas.get("NewSchemaName").getKey().getName());
+        assertEquals("NewSchemaName", schemas.get("NewSchemaName", "0.0.1").getKey().getName());
+        assertEquals(1, schemas.getAll("NewSchemaName", "0.0.1").size());
+        assertEquals(0, schemas.getAll("NonExistantSchemaName").size());
+    }
+}
diff --git a/model/context-model/src/test/java/org/onap/apex/model/contextmodel/handling/TestApexContextModel.java b/model/context-model/src/test/java/org/onap/apex/model/contextmodel/handling/TestApexContextModel.java
new file mode 100644 (file)
index 0000000..0723a68
--- /dev/null
@@ -0,0 +1,127 @@
+/*-
+ * ============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.apex.model.contextmodel.handling;
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.sql.Connection;
+import java.sql.DriverManager;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.apex.model.basicmodel.concepts.AxValidationResult;
+import org.onap.apex.model.basicmodel.dao.DAOParameters;
+import org.onap.apex.model.basicmodel.test.TestApexModel;
+import org.onap.apex.model.contextmodel.concepts.AxContextModel;
+
+public class TestApexContextModel {
+    private Connection connection;
+    TestApexModel<AxContextModel> testApexModel;
+
+    @Before
+    public void setup() throws Exception {
+        Class.forName("org.apache.derby.jdbc.EmbeddedDriver").newInstance();
+        connection = DriverManager.getConnection("jdbc:derby:memory:apex_test;create=true");
+
+        testApexModel = new TestApexModel<AxContextModel>(AxContextModel.class, new TestApexContextModelCreator());
+    }
+
+    @After
+    public void teardown() throws Exception {
+        connection.close();
+        new File("derby.log").delete();
+    }
+
+    @Test
+    public void testModelValid() throws Exception {
+        final AxValidationResult result = testApexModel.testApexModelValid();
+        assertTrue(result.toString().equals(VALID_MODEL_STRING));
+    }
+
+    @Test
+    public void testApexModelVaidateObservation() throws Exception {
+        final AxValidationResult result = testApexModel.testApexModelVaidateObservation();
+        assertTrue(result.toString().equals(OBSERVATION_MODEL_STRING));
+    }
+
+    @Test
+    public void testApexModelVaidateWarning() throws Exception {
+        final AxValidationResult result = testApexModel.testApexModelVaidateWarning();
+        assertTrue(result.toString().equals(WARNING_MODEL_STRING));
+    }
+
+    @Test
+    public void testModelVaidateInvalidModel() throws Exception {
+        final AxValidationResult result = testApexModel.testApexModelVaidateInvalidModel();
+        assertTrue(result.toString().equals(INVALID_MODEL_STRING));
+    }
+
+    @Test
+    public void testModelVaidateMalstructured() throws Exception {
+        final AxValidationResult result = testApexModel.testApexModelVaidateMalstructured();
+        assertTrue(result.toString().equals(INVALID_MODEL_MALSTRUCTURED_STRING));
+    }
+
+    @Test
+    public void testModelWriteReadXML() throws Exception {
+        testApexModel.testApexModelWriteReadXML();
+    }
+
+    @Test
+    public void testModelWriteReadJSON() throws Exception {
+        testApexModel.testApexModelWriteReadJSON();
+    }
+
+    @Test
+    public void testModelWriteReadJPA() throws Exception {
+        final DAOParameters daoParameters = new DAOParameters();
+        daoParameters.setPluginClass("org.onap.apex.model.basicmodel.dao.impl.DefaultApexDao");
+        daoParameters.setPersistenceUnit("DAOTest");
+
+        testApexModel.testApexModelWriteReadJPA(daoParameters);
+    }
+
+    private static final String VALID_MODEL_STRING = "***validation of model successful***";
+
+    private static final String OBSERVATION_MODEL_STRING =
+            "\n" + "***observations noted during validation of model***\n"
+                    + "AxArtifactKey:(name=contextAlbum1,version=0.0.1):org.onap.apex.model.basicmodel.concepts.AxKeyInfo:OBSERVATION:description is blank\n"
+                    + "********************************";
+
+    private static final String WARNING_MODEL_STRING = "\n" + "***warnings issued during validation of model***\n"
+            + "AxArtifactKey:(name=contextAlbum1,version=0.0.1):org.onap.apex.model.basicmodel.concepts.AxKeyInfo:WARNING:UUID is a zero UUID: 00000000-0000-0000-0000-000000000000\n"
+            + "********************************";
+
+    private static final String INVALID_MODEL_STRING = "\n" + "***validation of model failed***\n"
+            + "AxArtifactKey:(name=StringType,version=0.0.1):org.onap.apex.model.contextmodel.concepts.AxContextSchema:INVALID:no schemaDefinition specified, schemaDefinition may not be blank\n"
+            + "AxArtifactKey:(name=contextAlbum0,version=0.0.1):org.onap.apex.model.contextmodel.concepts.AxContextAlbum:INVALID:scope is not defined\n"
+            + "********************************";
+
+    private static final String INVALID_MODEL_MALSTRUCTURED_STRING = "\n" + "***validation of model failed***\n"
+            + "AxArtifactKey:(name=ContextModel,version=0.0.1):org.onap.apex.model.contextmodel.concepts.AxContextModel:INVALID:key information not found for key AxArtifactKey:(name=contextAlbum1,version=0.0.2)\n"
+            + "AxArtifactKey:(name=contextAlbum1,version=0.0.1):org.onap.apex.model.contextmodel.concepts.AxContextModel:WARNING:key not found for key information entry\n"
+            + "AxArtifactKey:(name=ContextSchemas,version=0.0.1):org.onap.apex.model.contextmodel.concepts.AxContextSchemas:INVALID:key on schemas entry AxArtifactKey:(name=MapType,version=0.0.1) does not equal entry key AxArtifactKey:(name=MapType,version=0.0.2)\n"
+            + "AxArtifactKey:(name=contextAlbums,version=0.0.1):org.onap.apex.model.contextmodel.concepts.AxContextAlbums:INVALID:key on context album entry key AxArtifactKey:(name=contextAlbum1,version=0.0.1) does not equal context album value key AxArtifactKey:(name=contextAlbum1,version=0.0.2)\n"
+            + "********************************";
+
+}
diff --git a/model/context-model/src/test/java/org/onap/apex/model/contextmodel/handling/TestApexContextModelCreator.java b/model/context-model/src/test/java/org/onap/apex/model/contextmodel/handling/TestApexContextModelCreator.java
new file mode 100644 (file)
index 0000000..b53d8d0
--- /dev/null
@@ -0,0 +1,106 @@
+/*-
+ * ============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.apex.model.contextmodel.handling;
+
+import java.util.UUID;
+
+import org.onap.apex.model.basicmodel.concepts.AxArtifactKey;
+import org.onap.apex.model.basicmodel.concepts.AxKeyInfo;
+import org.onap.apex.model.basicmodel.concepts.AxKeyInformation;
+import org.onap.apex.model.basicmodel.test.TestApexModelCreator;
+import org.onap.apex.model.contextmodel.concepts.AxContextAlbum;
+import org.onap.apex.model.contextmodel.concepts.AxContextAlbums;
+import org.onap.apex.model.contextmodel.concepts.AxContextModel;
+import org.onap.apex.model.contextmodel.concepts.AxContextSchema;
+import org.onap.apex.model.contextmodel.concepts.AxContextSchemas;
+
+public class TestApexContextModelCreator implements TestApexModelCreator<AxContextModel> {
+
+       @Override
+       public AxContextModel getModel() {
+               final AxContextSchema schema0 = new AxContextSchema(new AxArtifactKey("StringType", "0.0.1"), "Java", "com.ericsson.apex.concept.TestContextItem000");
+               final AxContextSchema schema1 = new AxContextSchema(new AxArtifactKey("MapType", "0.0.1"),    "Java", "com.ericsson.apex.concept.TestContextItem00A");
+
+               final AxContextSchemas contextSchemas = new AxContextSchemas(new AxArtifactKey("ContextSchemas", "0.0.1"));
+               contextSchemas.getSchemasMap().put(schema0.getKey(), schema0);
+               contextSchemas.getSchemasMap().put(schema1.getKey(), schema1);
+
+               final AxContextAlbum contextAlbum0 = new AxContextAlbum(new AxArtifactKey("contextAlbum0", "0.0.1"), "APPLICATION", true,  schema0.getKey());
+               final AxContextAlbum contextAlbum1 = new AxContextAlbum(new AxArtifactKey("contextAlbum1", "0.0.1"), "GLOBAL"     , false, schema1.getKey());
+
+               final AxContextAlbums axContext = new AxContextAlbums(new AxArtifactKey("contextAlbums", "0.0.1"));
+               axContext.getAlbumsMap().put(contextAlbum0.getKey(), contextAlbum0);
+               axContext.getAlbumsMap().put(contextAlbum1.getKey(), contextAlbum1);
+
+               final AxKeyInformation keyInformation = new AxKeyInformation(new AxArtifactKey("KeyInfoMapKey", "0.0.1"));
+               final AxContextModel contextModel = new AxContextModel(new AxArtifactKey("ContextModel", "0.0.1"), contextSchemas, axContext, keyInformation);
+
+               contextModel.setKeyInformation(keyInformation);
+               contextModel.getKeyInformation().getKeyInfoMap().put(schema0       .getKey(), new AxKeyInfo(schema0       .getKey(), UUID.fromString("00000000-0000-0000-0000-000000000001"), "axContextSchema0"));
+               contextModel.getKeyInformation().getKeyInfoMap().put(schema1       .getKey(), new AxKeyInfo(schema1       .getKey(), UUID.fromString("00000000-0000-0000-0000-000000000002"), "axContextSchema1"));
+               contextModel.getKeyInformation().getKeyInfoMap().put(contextSchemas.getKey(), new AxKeyInfo(contextSchemas.getKey(), UUID.fromString("00000000-0000-0000-0000-000000000003"), "ContextSchemas"));
+               contextModel.getKeyInformation().getKeyInfoMap().put(contextAlbum0 .getKey(), new AxKeyInfo(contextAlbum0 .getKey(), UUID.fromString("00000000-0000-0000-0000-000000000004"), "contextAlbum0"));
+               contextModel.getKeyInformation().getKeyInfoMap().put(contextAlbum1 .getKey(), new AxKeyInfo(contextAlbum1 .getKey(), UUID.fromString("00000000-0000-0000-0000-000000000005"), "contextAlbum1"));
+               contextModel.getKeyInformation().getKeyInfoMap().put(axContext     .getKey(), new AxKeyInfo(axContext     .getKey(), UUID.fromString("00000000-0000-0000-0000-000000000006"), "axContext"));
+               contextModel.getKeyInformation().getKeyInfoMap().put(contextModel  .getKey(), new AxKeyInfo(contextModel  .getKey(), UUID.fromString("00000000-0000-0000-0000-000000000007"), "contextModel"));
+               contextModel.getKeyInformation().getKeyInfoMap().put(keyInformation.getKey(), new AxKeyInfo(keyInformation.getKey(), UUID.fromString("00000000-0000-0000-0000-000000000008"), "keyInformation"));
+
+               return contextModel;
+       }
+
+       @Override
+       public AxContextModel getInvalidModel() {
+               final AxContextModel contextModel = getModel();
+               
+               contextModel.getAlbums().get(new AxArtifactKey("contextAlbum0", "0.0.1")).setScope("UNDEFINED");
+
+               contextModel.getSchemas().get(new AxArtifactKey("StringType", "0.0.1")).setSchema("");
+
+               return contextModel;
+       }
+
+       public AxContextModel getMalstructuredModel() {
+               final AxContextModel contextModel = getModel();
+               
+               contextModel.getAlbums().get(new AxArtifactKey("contextAlbum1", "0.0.1")).setKey(new AxArtifactKey("contextAlbum1", "0.0.2"));;
+               contextModel.getSchemas().get(new AxArtifactKey("MapType", "0.0.1")).setKey(new AxArtifactKey("MapType", "0.0.2"));;
+
+               return contextModel;
+       }
+
+       @Override
+       public AxContextModel getObservationModel() {
+               final AxContextModel contextModel = getModel();
+               
+               contextModel.getKeyInformation().get("contextAlbum1", "0.0.1").setDescription("");
+
+               return contextModel;
+       }
+
+       @Override
+       public AxContextModel getWarningModel() {
+               final AxContextModel contextModel = getModel();
+               
+               contextModel.getKeyInformation().get("contextAlbum1", "0.0.1").setUuid(UUID.fromString("00000000-0000-0000-0000-000000000000"));
+
+               return contextModel;
+       }
+}
diff --git a/model/context-model/src/test/java/org/onap/apex/model/contextmodel/handling/TestContextComparison.java b/model/context-model/src/test/java/org/onap/apex/model/contextmodel/handling/TestContextComparison.java
new file mode 100644 (file)
index 0000000..fe87509
--- /dev/null
@@ -0,0 +1,164 @@
+/*-
+ * ============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.apex.model.contextmodel.handling;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.apex.model.basicmodel.concepts.AxArtifactKey;
+import org.onap.apex.model.contextmodel.concepts.AxContextAlbum;
+import org.onap.apex.model.contextmodel.concepts.AxContextModel;
+import org.onap.apex.model.contextmodel.concepts.AxContextSchema;
+import org.onap.apex.model.contextmodel.handling.ContextComparer;
+import org.onap.policy.apex.model.utilities.comparison.KeyedMapDifference;
+
+/**
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class TestContextComparison {
+    private AxContextModel emptyModel;
+    private AxContextModel fullModel;
+    private AxContextModel noGlobalContextModel;
+    private AxContextModel shellModel;
+    private AxContextModel singleEntryModel;
+
+    @Before
+    public void getContext() {
+        final TestContextComparisonFactory factory = new TestContextComparisonFactory();
+        emptyModel           = factory.getEmptyModel();
+        fullModel            = factory.getFullModel();
+        noGlobalContextModel = factory.getNoGlobalContextModel();
+        shellModel           = factory.getShellModel();
+        singleEntryModel     = factory.getSingleEntryModel();
+    }
+    
+    @Test
+    public void testEmptyEmpty() {
+        final KeyedMapDifference<AxArtifactKey, AxContextSchema> schemaResult = new ContextComparer().compare(emptyModel.getSchemas(), emptyModel.getSchemas());
+        assertNotNull(schemaResult);
+        assertTrue(emptyModel.getSchemas().getSchemasMap().equals(schemaResult.getIdenticalValues()));
+
+        final KeyedMapDifference<AxArtifactKey, AxContextAlbum> albumResult = new ContextComparer().compare(emptyModel.getAlbums(), emptyModel.getAlbums());
+        assertNotNull(albumResult);
+        assertTrue(emptyModel.getAlbums().getAlbumsMap().equals(albumResult.getIdenticalValues()));
+    }
+    
+    @Test
+    public void testEmptyFull() {
+        final KeyedMapDifference<AxArtifactKey, AxContextSchema> schemaResult = new ContextComparer().compare(emptyModel.getSchemas(), fullModel.getSchemas());
+        assertNotNull(schemaResult);
+        assertTrue(fullModel.getSchemas().getSchemasMap().equals(schemaResult.getRightOnly()));
+
+        final KeyedMapDifference<AxArtifactKey, AxContextAlbum> albumResult = new ContextComparer().compare(emptyModel.getAlbums(), fullModel.getAlbums());
+        assertNotNull(albumResult);
+        assertTrue(fullModel.getAlbums().getAlbumsMap().equals(albumResult.getRightOnly()));
+    }
+    
+    @Test
+    public void testFullEmpty() {
+        final KeyedMapDifference<AxArtifactKey, AxContextSchema> schemaResult = new ContextComparer().compare(fullModel.getSchemas(), emptyModel.getSchemas());
+        assertNotNull(schemaResult);
+        assertTrue(fullModel.getSchemas().getSchemasMap().equals(schemaResult.getLeftOnly()));
+
+        final KeyedMapDifference<AxArtifactKey, AxContextAlbum> albumResult = new ContextComparer().compare(fullModel.getAlbums(), emptyModel.getAlbums());
+        assertNotNull(albumResult);
+        assertTrue(fullModel.getAlbums().getAlbumsMap().equals(albumResult.getLeftOnly()));
+    }
+    
+    @Test
+    public void testEmptyNoGlobalContext() {
+        final KeyedMapDifference<AxArtifactKey, AxContextSchema> schemaResult = new ContextComparer().compare(emptyModel.getSchemas(), noGlobalContextModel.getSchemas());
+        assertNotNull(schemaResult);
+        assertTrue(noGlobalContextModel.getSchemas().getSchemasMap().equals(schemaResult.getRightOnly()));
+
+        final KeyedMapDifference<AxArtifactKey, AxContextAlbum> albumResult = new ContextComparer().compare(emptyModel.getAlbums(), noGlobalContextModel.getAlbums());
+        assertNotNull(albumResult);
+        assertTrue(noGlobalContextModel.getAlbums().getAlbumsMap().equals(albumResult.getRightOnly()));
+    }
+    
+    @Test
+    public void testNoGlobalContextEmpty() {
+        final KeyedMapDifference<AxArtifactKey, AxContextSchema> schemaResult = new ContextComparer().compare(noGlobalContextModel.getSchemas(), emptyModel.getSchemas());
+        assertNotNull(schemaResult);
+        assertTrue(noGlobalContextModel.getSchemas().getSchemasMap().equals(schemaResult.getLeftOnly()));
+
+        final KeyedMapDifference<AxArtifactKey, AxContextAlbum> albumResult = new ContextComparer().compare(noGlobalContextModel.getAlbums(), emptyModel.getAlbums());
+        assertNotNull(albumResult);
+        assertTrue(noGlobalContextModel.getAlbums().getAlbumsMap().equals(albumResult.getLeftOnly()));
+    }
+    
+    @Test
+    public void testEmptyShell() {
+        final KeyedMapDifference<AxArtifactKey, AxContextSchema> schemaResult = new ContextComparer().compare(emptyModel.getSchemas(), shellModel.getSchemas());
+        assertNotNull(schemaResult);
+        assertTrue(shellModel.getSchemas().getSchemasMap().equals(schemaResult.getRightOnly()));
+
+        final KeyedMapDifference<AxArtifactKey, AxContextAlbum> albumResult = new ContextComparer().compare(emptyModel.getAlbums(), shellModel.getAlbums());
+        assertNotNull(albumResult);
+        assertTrue(shellModel.getAlbums().getAlbumsMap().equals(albumResult.getRightOnly()));
+    }
+    
+    @Test
+    public void testShellEmpty() {
+        final KeyedMapDifference<AxArtifactKey, AxContextSchema> schemaResult = new ContextComparer().compare(shellModel.getSchemas(), emptyModel.getSchemas());
+        assertNotNull(schemaResult);
+        assertTrue(shellModel.getSchemas().getSchemasMap().equals(schemaResult.getLeftOnly()));
+
+        final KeyedMapDifference<AxArtifactKey, AxContextAlbum> albumResult = new ContextComparer().compare(shellModel.getAlbums(), emptyModel.getAlbums());
+        assertNotNull(albumResult);
+        assertTrue(shellModel.getAlbums().getAlbumsMap().equals(albumResult.getLeftOnly()));
+    }
+    
+    @Test
+    public void testEmptySingleEntry() {
+        final KeyedMapDifference<AxArtifactKey, AxContextSchema> schemaResult = new ContextComparer().compare(emptyModel.getSchemas(), singleEntryModel.getSchemas());
+        assertNotNull(schemaResult);
+        assertTrue(singleEntryModel.getSchemas().getSchemasMap().equals(schemaResult.getRightOnly()));
+
+        final KeyedMapDifference<AxArtifactKey, AxContextAlbum> albumResult = new ContextComparer().compare(emptyModel.getAlbums(), singleEntryModel.getAlbums());
+        assertNotNull(albumResult);
+        assertTrue(singleEntryModel.getAlbums().getAlbumsMap().equals(albumResult.getRightOnly()));
+    }
+    
+    @Test
+    public void testSingleEntryEmpty() {
+        final KeyedMapDifference<AxArtifactKey, AxContextSchema> schemaResult = new ContextComparer().compare(singleEntryModel.getSchemas(), emptyModel.getSchemas());
+        assertNotNull(schemaResult);
+        assertTrue(singleEntryModel.getSchemas().getSchemasMap().equals(schemaResult.getLeftOnly()));
+
+        final KeyedMapDifference<AxArtifactKey, AxContextAlbum> albumResult = new ContextComparer().compare(singleEntryModel.getAlbums(), emptyModel.getAlbums());
+        assertNotNull(albumResult);
+        assertTrue(singleEntryModel.getAlbums().getAlbumsMap().equals(albumResult.getLeftOnly()));
+    }
+    
+    @Test
+    public void testFullFull() {
+        final KeyedMapDifference<AxArtifactKey, AxContextSchema> schemaResult = new ContextComparer().compare(fullModel.getSchemas(), fullModel.getSchemas());
+        assertNotNull(schemaResult);
+        assertTrue(fullModel.getSchemas().getSchemasMap().equals(schemaResult.getIdenticalValues()));
+
+        final KeyedMapDifference<AxArtifactKey, AxContextAlbum> albumResult = new ContextComparer().compare(fullModel.getAlbums(), fullModel.getAlbums());
+        assertNotNull(albumResult);
+        assertTrue(fullModel.getAlbums().getAlbumsMap().equals(albumResult.getIdenticalValues()));
+    }
+}
diff --git a/model/context-model/src/test/java/org/onap/apex/model/contextmodel/handling/TestContextComparisonFactory.java b/model/context-model/src/test/java/org/onap/apex/model/contextmodel/handling/TestContextComparisonFactory.java
new file mode 100644 (file)
index 0000000..1850c22
--- /dev/null
@@ -0,0 +1,122 @@
+/*-
+ * ============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.apex.model.contextmodel.handling;
+
+import org.onap.apex.model.basicmodel.concepts.AxArtifactKey;
+import org.onap.apex.model.contextmodel.concepts.AxContextAlbum;
+import org.onap.apex.model.contextmodel.concepts.AxContextModel;
+import org.onap.apex.model.contextmodel.concepts.AxContextSchema;
+
+/**
+ * This class creates sample Policy Models
+ * 
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class TestContextComparisonFactory {
+
+    public AxContextModel getFullModel() {
+        final AxContextSchema testContextSchema000 = new AxContextSchema(new AxArtifactKey("TestContextSchema000", "0.0.1"), "JAVA",
+                "com.ericsson.apex.concept.TestContextSchema000");
+        final AxContextSchema testContextSchema00A = new AxContextSchema(new AxArtifactKey("TestContextSchema00A", "0.0.1"), "JAVA",
+                "com.ericsson.apex.concept.TestContextSchema00A");
+        final AxContextSchema testContextSchema00C = new AxContextSchema(new AxArtifactKey("TestContextSchema00C", "0.0.1"), "JAVA",
+                "com.ericsson.apex.concept.TestContextSchema00C");
+
+        final AxContextAlbum externalContextAlbum = new AxContextAlbum(new AxArtifactKey("ExternalContextAlbum", "0.0.1"), "EXTERNAL", false,
+                testContextSchema000.getKey());
+        final AxContextAlbum globalContextAlbum = new AxContextAlbum(new AxArtifactKey("GlobalContextAlbum", "0.0.1"), "GLOBAL", true, testContextSchema00A.getKey());
+        final AxContextAlbum policy0ContextAlbum = new AxContextAlbum(new AxArtifactKey("Policy0ContextAlbum", "0.0.1"), "APPLICATION", true,
+                testContextSchema00C.getKey());
+        final AxContextAlbum policy1ContextAlbum = new AxContextAlbum(new AxArtifactKey("Policy1ContextAlbum ", "0.0.1"), "APPLICATION", true,
+                testContextSchema00C.getKey());
+
+        final AxContextModel contextModel = new AxContextModel(new AxArtifactKey("ContextModel", "0.0.1"));
+        contextModel.getSchemas().getSchemasMap().put(testContextSchema000.getKey(), testContextSchema000);
+        contextModel.getSchemas().getSchemasMap().put(testContextSchema00A.getKey(), testContextSchema00A);
+        contextModel.getSchemas().getSchemasMap().put(testContextSchema00C.getKey(), testContextSchema00C);
+
+        contextModel.getAlbums().getAlbumsMap().put(externalContextAlbum.getKey(), externalContextAlbum);
+        contextModel.getAlbums().getAlbumsMap().put(globalContextAlbum.getKey(), globalContextAlbum);
+        contextModel.getAlbums().getAlbumsMap().put(policy0ContextAlbum.getKey(), policy0ContextAlbum);
+        contextModel.getAlbums().getAlbumsMap().put(policy1ContextAlbum.getKey(), policy1ContextAlbum);
+
+        return contextModel;
+    }
+
+    public AxContextModel getEmptyModel() {
+        return new AxContextModel(new AxArtifactKey("Context", "0.0.1"));
+    }
+
+    public AxContextModel getShellModel() {
+        final AxContextSchema testContextSchema000 = new AxContextSchema(new AxArtifactKey("TestContextSchema000", "0.0.1"), "JAVA",
+                "com.ericsson.apex.concept.TestContextSchema000");
+        final AxContextSchema testContextSchema00A = new AxContextSchema(new AxArtifactKey("TestContextSchema00A", "0.0.1"), "JAVA",
+                "com.ericsson.apex.concept.TestContextSchema00A");
+        final AxContextSchema testContextSchema00C = new AxContextSchema(new AxArtifactKey("TestContextSchema00C", "0.0.1"), "JAVA",
+                "com.ericsson.apex.concept.TestContextSchema00C");
+
+        final AxContextModel contextModel = new AxContextModel(new AxArtifactKey("ContextModel", "0.0.1"));
+        contextModel.getSchemas().getSchemasMap().put(testContextSchema000.getKey(), testContextSchema000);
+        contextModel.getSchemas().getSchemasMap().put(testContextSchema00A.getKey(), testContextSchema00A);
+        contextModel.getSchemas().getSchemasMap().put(testContextSchema00C.getKey(), testContextSchema00C);
+
+        return contextModel;
+    }
+
+    public AxContextModel getSingleEntryModel() {
+        final AxContextSchema testContextSchema000 = new AxContextSchema(new AxArtifactKey("TestContextSchema000", "0.0.1"), "JAVA",
+                "com.ericsson.apex.concept.TestContextSchema000");
+
+        final AxContextAlbum policy1ContextAlbum = new AxContextAlbum(new AxArtifactKey("Policy1ContextAlbum ", "0.0.1"), "APPLICATION", true,
+                testContextSchema000.getKey());
+
+        final AxContextModel contextModel = new AxContextModel(new AxArtifactKey("ContextModel", "0.0.1"));
+        contextModel.getSchemas().getSchemasMap().put(testContextSchema000.getKey(), testContextSchema000);
+
+        contextModel.getAlbums().getAlbumsMap().put(policy1ContextAlbum.getKey(), policy1ContextAlbum);
+
+        return contextModel;
+    }
+
+    public AxContextModel getNoGlobalContextModel() {
+        final AxContextSchema testContextSchema000 = new AxContextSchema(new AxArtifactKey("TestContextSchema000", "0.0.1"), "JAVA",
+                "com.ericsson.apex.concept.TestContextSchema000");
+        final AxContextSchema testContextSchema00C = new AxContextSchema(new AxArtifactKey("TestContextSchema00C", "0.0.1"), "JAVA",
+                "com.ericsson.apex.concept.TestContextSchema00C");
+
+        final AxContextAlbum externalContextAlbum = new AxContextAlbum(new AxArtifactKey("ExternalContextAlbum", "0.0.1"), "EXTERNAL", false,
+                testContextSchema000.getKey());
+        final AxContextAlbum policy0ContextAlbum = new AxContextAlbum(new AxArtifactKey("Policy0ContextAlbum", "0.0.1"), "APPLICATION", true,
+                testContextSchema00C.getKey());
+        final AxContextAlbum policy1ContextAlbum = new AxContextAlbum(new AxArtifactKey("Policy1ContextAlbum ", "0.0.1"), "APPLICATION", true,
+                testContextSchema00C.getKey());
+
+        final AxContextModel contextModel = new AxContextModel(new AxArtifactKey("ContextModel", "0.0.1"));
+        contextModel.getSchemas().getSchemasMap().put(testContextSchema000.getKey(), testContextSchema000);
+        contextModel.getSchemas().getSchemasMap().put(testContextSchema00C.getKey(), testContextSchema00C);
+
+        contextModel.getAlbums().getAlbumsMap().put(externalContextAlbum.getKey(), externalContextAlbum);
+        contextModel.getAlbums().getAlbumsMap().put(policy0ContextAlbum.getKey(), policy0ContextAlbum);
+        contextModel.getAlbums().getAlbumsMap().put(policy1ContextAlbum.getKey(), policy1ContextAlbum);
+
+        return contextModel;
+    }
+}
diff --git a/model/context-model/src/test/resources/META-INF/persistence.xml b/model/context-model/src/test/resources/META-INF/persistence.xml
new file mode 100644 (file)
index 0000000..d9203b4
--- /dev/null
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ============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=========================================================
+-->
+
+<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
+    <persistence-unit name="DAOTest" transaction-type="RESOURCE_LOCAL">
+        <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
+
+        <class>org.onap.apex.model.basicmodel.dao.converters.CDATAConditioner</class>
+        <class>org.onap.apex.model.basicmodel.dao.converters.UUID2String</class>
+        <class>org.onap.apex.model.basicmodel.concepts.AxArtifactKey</class>
+        <class>org.onap.apex.model.basicmodel.concepts.AxConcept</class>
+        <class>org.onap.apex.model.basicmodel.concepts.AxKeyInfo</class>
+        <class>org.onap.apex.model.basicmodel.concepts.AxKeyInformation</class>
+        <class>org.onap.apex.model.basicmodel.concepts.AxModel</class>
+        <class>org.onap.apex.model.basicmodel.concepts.TestEntity</class>
+        <class>org.onap.apex.model.contextmodel.concepts.AxContextSchema</class>
+        <class>org.onap.apex.model.contextmodel.concepts.AxContextSchemas</class>
+        <class>org.onap.apex.model.contextmodel.concepts.AxContextAlbum</class>
+        <class>org.onap.apex.model.contextmodel.concepts.AxContextAlbums</class>
+        <class>org.onap.apex.model.contextmodel.concepts.AxContextModel</class>
+
+        <properties>
+            <property name="javax.persistence.jdbc.url" value="jdbc:derby:memory:apex_test" />
+            <property name="javax.persistence.target-database" value="Derby" />
+            <property name="javax.persistence.jdbc.driver" value="org.apache.derby.jdbc.EmbeddedDriver" />
+
+            <property name="eclipselink.ddl-generation" value="drop-and-create-tables" />
+            <property name="eclipselink.ddl-generation.output-mode" value="database" />
+            <property name="eclipselink.logging.level" value="INFO" />
+        </properties>
+    </persistence-unit>
+</persistence>
diff --git a/model/context-model/src/test/resources/json/ContextModel.json b/model/context-model/src/test/resources/json/ContextModel.json
new file mode 100644 (file)
index 0000000..cbaabc6
--- /dev/null
@@ -0,0 +1,156 @@
+{
+   "apexContextModel" : {
+      "key" : {
+         "name" : "contextModel",
+         "version" : "0.0.1"
+      },
+      "keyInformation" : {
+         "key" : {
+            "name" : "KeyInfoMapKey",
+            "version" : "0.0.1"
+         },
+         "keyInfoMap" : {
+            "keyInfoEntry" : [ {
+               "key" : {
+                  "name" : "StringType",
+                  "version" : "0.0.1"
+               },
+               "UUID" : "00000000-0000-0000-0000-000000000000",
+               "description" : "axContextType0"
+            }, {
+               "key" : {
+                  "name" : "MapType",
+                  "version" : "0.0.1"
+               },
+               "UUID" : "00000000-0000-0000-0000-000000000001",
+               "description" : "axContextType1"
+            }, {
+               "key" : {
+                  "name" : "contextMap0",
+                  "version" : "0.0.1"
+               },
+               "UUID" : "00000000-0000-0000-0000-000000000002",
+               "description" : "contextMap0"
+            }, {
+               "key" : {
+                  "name" : "contextMap1",
+                  "version" : "0.0.1"
+               },
+               "UUID" : "00000000-0000-0000-0000-000000000003",
+               "description" : "contextMap1"
+            }, {
+               "key" : {
+                  "name" : "context",
+                  "version" : "0.0.1"
+               },
+               "UUID" : "00000000-0000-0000-0000-000000000004",
+               "description" : "axContext"
+            }, {
+               "key" : {
+                  "name" : "contextModel",
+                  "version" : "0.0.1"
+               },
+               "UUID" : "00000000-0000-0000-0000-000000000005",
+               "description" : "contextModel"
+            }, {
+               "key" : {
+                  "name" : "KeyInfoMapKey",
+                  "version" : "0.0.1"
+               },
+               "UUID" : "00000000-0000-0000-0000-000000000006",
+               "description" : "keyInformation"
+            } ]
+         }
+      },
+      "context" : {
+         "key" : {
+            "name" : "context",
+            "version" : "0.0.1"
+         },
+         "contextMaps" : {
+            "entry" : [ {
+               "key" : "contextMap0",
+               "value" : {
+                  "key" : {
+                     "name" : "contextMap0",
+                     "version" : "0.0.1"
+                  },
+                  "scope" : "APPLICATION",
+                  "mapType" : "BAG",
+                  "contextMap" : {
+                     "contextItem" : [ {
+                        "key" : "axContextItem0_0",
+                        "contextType" : {
+                           "key" : {
+                              "name" : "StringType",
+                              "version" : "0.0.1"
+                           },
+                           "javaType" : "com.ericsson.apex.core.contextmodel.concepts.TestContextItem000"
+                        },
+                        "isWritable" : true,
+                        "valueString" : ""
+                     }, {
+                        "key" : "axContextItem0_1",
+                        "contextType" : {
+                           "key" : {
+                              "name" : "MapType",
+                              "version" : "0.0.1"
+                           },
+                           "javaType" : "com.ericsson.apex.core.contextmodel.concepts.TestContextItem00A"
+                        },
+                        "isWritable" : true,
+                        "valueString" : ""
+                     }, {
+                        "key" : "axContextItem0_2",
+                        "contextType" : {
+                           "key" : {
+                              "name" : "StringType",
+                              "version" : "0.0.1"
+                           },
+                           "javaType" : "com.ericsson.apex.core.contextmodel.concepts.TestContextItem000"
+                        },
+                        "isWritable" : true,
+                        "valueString" : ""
+                     }, {
+                        "key" : "axContextItem0_3",
+                        "contextType" : {
+                           "key" : {
+                              "name" : "MapType",
+                              "version" : "0.0.1"
+                           },
+                           "javaType" : "com.ericsson.apex.core.contextmodel.concepts.TestContextItem00A"
+                        },
+                        "isWritable" : true,
+                        "valueString" : ""
+                     } ]
+                  }
+               }
+            }, {
+               "key" : "contextMap1",
+               "value" : {
+                  "key" : {
+                     "name" : "contextMap1",
+                     "version" : "0.0.1"
+                  },
+                  "scope" : "GLOBAL",
+                  "mapType" : "SAMETYPE",
+                  "templateContextItem" : {
+                     "key" : "axTemplateContextItem",
+                     "contextType" : {
+                        "key" : {
+                           "name" : "MapType",
+                           "version" : "0.0.1"
+                        },
+                        "javaType" : "com.ericsson.apex.core.contextmodel.concepts.TestContextItem00A"
+                     },
+                     "isWritable" : true
+                  },
+                  "contextMap" : {
+                     "contextItem" : [ ]
+                  }
+               }
+            } ]
+         }
+      }
+   }
+}
\ No newline at end of file
diff --git a/model/context-model/src/test/resources/logback-test.xml b/model/context-model/src/test/resources/logback-test.xml
new file mode 100644 (file)
index 0000000..07bc025
--- /dev/null
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ============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=========================================================
+-->
+
+<configuration>
+
+    <contextName>Apex</contextName>
+    <statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" />
+    <property name="LOG_DIR" value="${java.io.tmpdir}/apex_logging/" />
+
+    <!-- USE FOR STD OUT ONLY -->
+    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+        <encoder>
+            <Pattern>%d %contextName [%t] %level %logger{36} - %msg%n</Pattern>
+        </encoder>
+    </appender>
+
+    <root level="INFO">
+        <appender-ref ref="STDOUT" />
+    </root>
+
+    <logger name="org.infinispan" level="INFO" additivity="false">
+        <appender-ref ref="STDOUT" />
+    </logger>
+
+    <logger name="com.ericsson.apex.core.contextmodel" level="TRACE" additivity="false">
+        <appender-ref ref="STDOUT" />
+    </logger>
+
+    <logger name="org.apache.zookeeper.ClientCnxn" level="OFF" additivity="false">
+        <appender-ref ref="STDOUT" />
+    </logger>
+
+    <logger name="com.ericsson.apex.core" level="TRACE" additivity="false">
+        <appender-ref ref="STDOUT" />
+    </logger>
+
+    <appender name="FILE" class="ch.qos.logback.core.FileAppender">
+        <file>${LOG_DIR}/apex.log</file>
+        <encoder>
+            <pattern>%d %-5relative [procId=${processId}] [%thread] %-5level
+                %logger{26} - %msg %n %ex{full}</pattern>
+        </encoder>
+    </appender>
+
+    <appender name="CTXT_FILE" class="ch.qos.logback.core.FileAppender">
+        <file>${LOG_DIR}/apex_ctxt.log</file>
+        <encoder>
+            <pattern>%d %-5relative [procId=${processId}] [%thread] %-5level
+                %logger{26} - %msg %n %ex{full}</pattern>
+        </encoder>
+    </appender>
+
+    <logger name="com.ericsson.apex.core.context.impl.monitoring" level="TRACE" additivity="false">
+        <appender-ref ref="CTXT_FILE" />
+    </logger>
+
+    <logger name="com.ericsson.apex.core.context" level="INFO" additivity="false">
+        <appender-ref ref="STDOUT" />
+    </logger>
+</configuration>
index 61fd87b..722a442 100644 (file)
@@ -36,5 +36,6 @@
     <modules>
         <module>utilities</module>
         <module>basic-model</module>
+        <module>context-model</module>
     </modules>
 </project>
\ No newline at end of file