aboutsummaryrefslogtreecommitdiffstats
path: root/model/utilities/src/main
diff options
context:
space:
mode:
authorwaqas.ikram <waqas.ikram@ericsson.com>2018-05-24 14:39:38 +0100
committerwaqas.ikram <waqas.ikram@ericsson.com>2018-05-24 14:49:48 +0100
commit8e424a8db287f180c65b5e5fc32a6f23b4b2011f (patch)
tree80bab5706b2d3277e455558adfc5a75500ebc20c /model/utilities/src/main
parenta94302f0e4af0d6136d1c694cfae12abc175dc55 (diff)
Fixing typo in utilities module name
Change-Id: I7bae55aa9c9064fc4aea32bacba3baee196c10a0 Issue-ID: POLICY-855 Signed-off-by: waqas.ikram <waqas.ikram@ericsson.com>
Diffstat (limited to 'model/utilities/src/main')
-rw-r--r--model/utilities/src/main/antlr4/org/onap/policy/apex/model/utilities/typeutils/ParametrizedType.g458
-rw-r--r--model/utilities/src/main/java/org/onap/policy/apex/model/utilities/Assertions.java154
-rw-r--r--model/utilities/src/main/java/org/onap/policy/apex/model/utilities/CollectionUtils.java108
-rw-r--r--model/utilities/src/main/java/org/onap/policy/apex/model/utilities/DirectoryUtils.java138
-rw-r--r--model/utilities/src/main/java/org/onap/policy/apex/model/utilities/PropertyUtils.java78
-rw-r--r--model/utilities/src/main/java/org/onap/policy/apex/model/utilities/ResourceUtils.java226
-rw-r--r--model/utilities/src/main/java/org/onap/policy/apex/model/utilities/TextFileUtils.java117
-rw-r--r--model/utilities/src/main/java/org/onap/policy/apex/model/utilities/TreeMapUtils.java80
-rw-r--r--model/utilities/src/main/java/org/onap/policy/apex/model/utilities/comparison/KeyComparer.java42
-rw-r--r--model/utilities/src/main/java/org/onap/policy/apex/model/utilities/comparison/KeyDifference.java100
-rw-r--r--model/utilities/src/main/java/org/onap/policy/apex/model/utilities/comparison/KeyedMapComparer.java95
-rw-r--r--model/utilities/src/main/java/org/onap/policy/apex/model/utilities/comparison/KeyedMapDifference.java206
-rw-r--r--model/utilities/src/main/java/org/onap/policy/apex/model/utilities/comparison/package-info.java26
-rw-r--r--model/utilities/src/main/java/org/onap/policy/apex/model/utilities/package-info.java26
-rw-r--r--model/utilities/src/main/java/org/onap/policy/apex/model/utilities/typeutils/ClassBuilder.java99
-rw-r--r--model/utilities/src/main/java/org/onap/policy/apex/model/utilities/typeutils/TypeBuilder.java114
-rw-r--r--model/utilities/src/main/java/org/onap/policy/apex/model/utilities/typeutils/package-info.java26
17 files changed, 1693 insertions, 0 deletions
diff --git a/model/utilities/src/main/antlr4/org/onap/policy/apex/model/utilities/typeutils/ParametrizedType.g4 b/model/utilities/src/main/antlr4/org/onap/policy/apex/model/utilities/typeutils/ParametrizedType.g4
new file mode 100644
index 000000000..3a37d4043
--- /dev/null
+++ b/model/utilities/src/main/antlr4/org/onap/policy/apex/model/utilities/typeutils/ParametrizedType.g4
@@ -0,0 +1,58 @@
+//-------------------------------------------------------------------------------
+// ============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=========================================================
+//-------------------------------------------------------------------------------
+
+grammar ParametrizedType;
+
+//For more information see:
+// http://stackoverflow.com/questions/39401083/class-forname-equivalent-for-creating-parameterizedtypes-from-string
+// https://github.com/KetothXupack/stackoverflow-answers/tree/master/q39401083
+
+@parser::header {
+ //For more information see:
+ // http://stackoverflow.com/questions/39401083/class-forname-equivalent-for-creating-parameterizedtypes-from-string
+ // https://github.com/KetothXupack/stackoverflow-answers/tree/master/q39401083
+
+
+ //Note: Unused Imports
+ //Since this is generated code compile warnings are to be expected and cannot always be suppressed
+ //See https://github.com/antlr/antlr4/issues/1192
+ import org.onap.policy.apex.model.utilities.typeutils.ClassBuilder;
+}
+
+type returns[ClassBuilder value]
+ : cls=CLASS { $value = ClassBuilder.parse($cls.text); }
+ | cls=CLASS { $value = ClassBuilder.parse($cls.text); }
+ LT head=type { $value.add($head.value); }
+ (COMMA tail=type { $value.add($tail.value); })* GT
+ ;
+
+GT : '>'
+ ;
+
+LT : '<'
+ ;
+
+COMMA
+ : ','
+ ;
+
+CLASS
+ : ('a'..'z'|'A'..'Z') ('a'..'z'|'A'..'Z'|'0'..'9'|'$'|'.'|'_')*
+ ;
diff --git a/model/utilities/src/main/java/org/onap/policy/apex/model/utilities/Assertions.java b/model/utilities/src/main/java/org/onap/policy/apex/model/utilities/Assertions.java
new file mode 100644
index 000000000..c215f3fee
--- /dev/null
+++ b/model/utilities/src/main/java/org/onap/policy/apex/model/utilities/Assertions.java
@@ -0,0 +1,154 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2016-2018 Ericsson. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.model.utilities;
+
+/**
+ * The Class Assertions is a template class that is used as a shorthand for assertions in the source code.
+ *
+ * @author Sajeevan Achuthan (sajeevan.achuthan@ericsson.com)
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public final class Assertions {
+ /**
+ * Private constructor used to prevent sub class instantiation.
+ */
+ private Assertions() {
+ }
+
+ /**
+ * Checks if a string parameter matches a regular expression.
+ *
+ * @param parameterName the string parameter name
+ * @param parameterValue the string parameter value
+ * @param pattern The regular expression
+ * @return the trimmed string
+ */
+ public static String validateStringParameter(final String parameterName, final String parameterValue, final String pattern) {
+ argumentNotNull(parameterName, "parameter name is null");
+ argumentNotNull(parameterValue, "parameter \"" + parameterName + "\" is null");
+ argumentNotNull(pattern, "parameter pattern is null");
+
+ final String trimmedValue = parameterValue.trim();
+ if (trimmedValue.matches(pattern)) {
+ return trimmedValue;
+ }
+ else {
+ throw new IllegalArgumentException(
+ "parameter \"" + parameterName + "\": value \"" + parameterValue + "\", does not match regular expression \"" + pattern + "\"");
+ }
+ }
+
+ /**
+ * Used as a shorthand to check that method arguments are not null, throws IllegalArgumentException on error.
+ *
+ * @param <T> the generic type of the argument to check
+ * @param value the value of the type
+ * @param message the error message to issue
+ */
+ public static <T> void argumentNotNull(final T value, final String message) {
+ if (value == null) {
+ throw new IllegalArgumentException(message);
+ }
+ }
+
+ /**
+ * Used as a shorthand to check that method arguments are not false, throws IllegalArgumentException on error.
+ *
+ * @param value the value to check if false
+ * @param message the error message to issue
+ */
+ public static void argumentNotFalse(final boolean value, final String message) {
+ if (!value) {
+ throw new IllegalArgumentException(message);
+ }
+ }
+
+ /**
+ * Used as a shorthand to check that method arguments are not null, throws an exception of the specified type on error.
+ *
+ * @param <T> the generic type of the argument to check
+ * @param <E> the exception to throw if incoming value is null
+ * @param value the value of the type
+ * @param exceptionClass the class of exception to return an instance of
+ * @param message the error message to issue
+ * @throws E an instance of the passed Exception Class
+ */
+ public static <T, E extends Exception> void argumentNotNull(final T value, final Class<E> exceptionClass, final String message) throws E {
+ if (value == null) {
+ // Instantiate the exception and throw it
+ try {
+ throw exceptionClass.getConstructor(String.class).newInstance(message);
+ }
+ catch (final Exception errorException) {
+ throw new IllegalArgumentException(message, errorException);
+ }
+ }
+ }
+
+ /**
+ * Used as a shorthand to check that method argument is not false, throws an exception of the specified type on error.
+ *
+ * @param <E> the exception to throw if incoming value is false
+ * @param value the value to check if false
+ * @param exceptionClass the class of exception to return an instance of
+ * @param message the error message to issue
+ * @throws E an instance of the passed Exception Class
+ */
+ public static <E extends Exception> void argumentNotFalse(final boolean value, final Class<E> exceptionClass, final String message) throws E {
+ if (!value) {
+ // Instantiate the exception and throw it
+ try {
+ throw exceptionClass.getConstructor(String.class).newInstance(message);
+ }
+ catch (final Exception errorException) {
+ throw new IllegalArgumentException(message, errorException);
+ }
+ }
+ }
+
+ /**
+ * Used as a shorthand to check that an object is an instance of a given class, throws IllegalArgumentException on error.
+ *
+ * @param <T> the generic type of the argument to check
+ * @param objectInstance the object instance for which to check the class
+ * @param requiredClass the class that the object should be an instance of
+ * @throws IllegalArgumentException if the incoming object is not an instance of requiredClass
+ */
+ public static <T> void instanceOf(final Object objectInstance, final Class<T> requiredClass) {
+ if (!requiredClass.isAssignableFrom(objectInstance.getClass())) {
+ throw new IllegalArgumentException(objectInstance.getClass().getCanonicalName() + " is not an instance of " + requiredClass.getCanonicalName());
+ }
+ }
+
+ /**
+ * Used as a shorthand to check that an instance of a class can be an instance of a given class, throws IllegalArgumentException on error.
+ *
+ * @param <T> the generic type of the argument to check
+ * @param checkClass the class to check
+ * @param requiredClass the class that the object should be an instance of
+ * @throws IllegalArgumentException if the incoming object is not an instance of requiredClass
+ */
+ public static <T> void assignableFrom(final Class<?> checkClass, final Class<T> requiredClass) {
+ if (!requiredClass.isAssignableFrom(checkClass)) {
+ throw new IllegalArgumentException(checkClass.getCanonicalName() + " is not an instance of " + requiredClass.getCanonicalName());
+ }
+ }
+}
diff --git a/model/utilities/src/main/java/org/onap/policy/apex/model/utilities/CollectionUtils.java b/model/utilities/src/main/java/org/onap/policy/apex/model/utilities/CollectionUtils.java
new file mode 100644
index 000000000..fb7207e0b
--- /dev/null
+++ b/model/utilities/src/main/java/org/onap/policy/apex/model/utilities/CollectionUtils.java
@@ -0,0 +1,108 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2016-2018 Ericsson. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.model.utilities;
+
+import java.util.List;
+import java.util.ListIterator;
+
+/**
+ * This is common utility class with static methods for handling collections.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public abstract class CollectionUtils {
+ /**
+ * Private constructor used to prevent sub class instantiation.
+ */
+ private CollectionUtils() {
+ }
+
+ /**
+ * Compare two lists, checks for equality, then for equality on members.
+ *
+ * @param <T> The type of the lists being compared
+ * @param leftList The leftmost List
+ * @param rightList The rightmost list
+ * @return an integer indicating how different the lists are
+ */
+ public static <T> int compareLists(final List<? extends Comparable<T>> leftList, final List<? extends Comparable<T>> rightList) {
+ // Check for nulls
+ if (leftList == null && rightList == null) {
+ return 0;
+ }
+ if (leftList != null && rightList == null) {
+ return -1;
+ }
+ if (leftList == null) {
+ return 1;
+ }
+
+ // Check for equality
+ if (leftList.equals(rightList)) {
+ return 0;
+ }
+
+ return compareListEntries(leftList, rightList);
+ }
+
+ /**
+ * Compare two lists for equality on members.
+ *
+ * @param <T> The type of the lists being compared
+ * @param leftList The leftmost List
+ * @param rightList The rightmost list
+ * @return an integer indicating how different the lists are
+ */
+ private static <T> int compareListEntries(final List<? extends Comparable<T>> leftList, final List<? extends Comparable<T>> rightList) {
+
+ // Iterate down the lists till we find a difference
+ final ListIterator<?> leftIterator = leftList.listIterator();
+ final ListIterator<?> rightIterator = rightList.listIterator();
+
+ while (true) {
+ // Check the iterators
+ if (!leftIterator.hasNext() && !rightIterator.hasNext()) {
+ return 0;
+ }
+ if (leftIterator.hasNext() && !rightIterator.hasNext()) {
+ return -1;
+ }
+ if (!leftIterator.hasNext() && rightIterator.hasNext()) {
+ return 1;
+ }
+
+ // Get the next objects
+ @SuppressWarnings("unchecked")
+ final T leftObject = (T) leftIterator.next();
+ @SuppressWarnings("unchecked")
+ final T rightObject = (T) rightIterator.next();
+
+ // Compare the objects
+ @SuppressWarnings("unchecked")
+ final int comparisonResult = ((Comparable<T>) leftObject).compareTo(rightObject);
+
+ // Check the comparison result
+ if (comparisonResult != 0) {
+ return comparisonResult;
+ }
+ }
+ }
+}
diff --git a/model/utilities/src/main/java/org/onap/policy/apex/model/utilities/DirectoryUtils.java b/model/utilities/src/main/java/org/onap/policy/apex/model/utilities/DirectoryUtils.java
new file mode 100644
index 000000000..00e5cb4cf
--- /dev/null
+++ b/model/utilities/src/main/java/org/onap/policy/apex/model/utilities/DirectoryUtils.java
@@ -0,0 +1,138 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2016-2018 Ericsson. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.model.utilities;
+
+import java.io.File;
+
+import org.slf4j.ext.XLogger;
+import org.slf4j.ext.XLoggerFactory;
+
+/**
+ * This is common utility class with static methods for handling directories. It is an abstract class to prevent any direct instantiation and private
+ * constructor to prevent extending this class.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public abstract class DirectoryUtils {
+ // Get a reference to the logger
+ private static final XLogger LOGGER = XLoggerFactory.getXLogger(DirectoryUtils.class);
+
+ /**
+ * Private constructor used to prevent sub class instantiation.
+ */
+ private DirectoryUtils() {
+ }
+
+ /**
+ * Method to get an empty temporary directory in the system temporary directory on the local machine that will be deleted on (normal) shutdown.
+ *
+ * @param nameprefix The prefix of the filename. System.nanoTime() will be appended to the pattern to create a unique file pattern
+ * @return The temporary directory
+ */
+ public static File getLocalTempDirectory(final String nameprefix) {
+ try {
+ // Get the name of the temporary directory
+ final String tempDirName = System.getProperty("java.io.tmpdir") + "/" + nameprefix + System.nanoTime();
+ final File tempDir = new File(tempDirName);
+
+ // Delete the directory if it already exists
+ if (tempDir.exists()) {
+ return null;
+ }
+
+ // Make the directory
+ tempDir.mkdirs();
+
+ // Add a shutdown hook that deletes the directory contents when the JVM closes
+ Runtime.getRuntime().addShutdownHook(new DirectoryDeleteShutdownHook(tempDir));
+
+ LOGGER.trace("creating temp directory\"{}\" : ", tempDir.getAbsolutePath());
+ return tempDir;
+ }
+ catch (final Exception e) {
+ LOGGER.debug("error creating temp directory\"{}\" : " + e.getMessage(), e);
+ return null;
+ }
+ }
+
+ /**
+ * Method to recursively delete all the files in a directory.
+ *
+ * @param tempDir the directory to empty
+ * @return true if the operation succeeds, false otherwise
+ */
+ public static boolean emptyDirectory(final File tempDir) {
+ // Sanity check
+ if (!tempDir.exists() || !tempDir.isDirectory()) {
+ return false;
+ }
+
+ // Walk the directory structure deleting files as we go
+ final File[] files = tempDir.listFiles();
+ if (files != null) {
+ for (final File directoryFile : files) {
+ // Check if this is a directory itself
+ if (directoryFile.isDirectory()) {
+ // Recurse into the sub directory and empty it
+ emptyDirectory(directoryFile);
+ }
+
+ // Delete the directory entry
+ directoryFile.delete();
+ }
+ }
+
+ return true;
+ }
+}
+
+/**
+ * The Class DirectoryShutdownHook removes the contents of a directory and the directory itself at shutdown.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+final class DirectoryDeleteShutdownHook extends Thread {
+ // The directory we are acting on
+ private final File tempDir;
+
+ /**
+ * Constructor that defines the directory to act on at shutdown.
+ *
+ * @param tempDir The temporary directory to delete
+ */
+ DirectoryDeleteShutdownHook(final File tempDir) {
+ this.tempDir = tempDir;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Runnable#run()
+ */
+ @Override
+ public void run() {
+ if (tempDir.exists()) {
+ // Empty and delete the directory
+ DirectoryUtils.emptyDirectory(tempDir);
+ tempDir.delete();
+ }
+ }
+}
diff --git a/model/utilities/src/main/java/org/onap/policy/apex/model/utilities/PropertyUtils.java b/model/utilities/src/main/java/org/onap/policy/apex/model/utilities/PropertyUtils.java
new file mode 100644
index 000000000..72f85638b
--- /dev/null
+++ b/model/utilities/src/main/java/org/onap/policy/apex/model/utilities/PropertyUtils.java
@@ -0,0 +1,78 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2016-2018 Ericsson. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.model.utilities;
+
+import java.util.Map.Entry;
+
+/**
+ * Convenience methods for handling Java properties class instances.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public abstract class PropertyUtils {
+ /**
+ * Private constructor used to prevent sub class instantiation.
+ */
+ private PropertyUtils() {
+ }
+
+ /**
+ * Return all properties as a string.
+ *
+ * @return a string containing all the property values
+ */
+ public static String getAllProperties() {
+ final StringBuilder builder = new StringBuilder();
+
+ for (final Entry<Object, Object> property : System.getProperties().entrySet()) {
+ builder.append(property.getKey().toString());
+ builder.append('=');
+ builder.append(property.getValue().toString());
+ builder.append('\n');
+ }
+
+ return builder.toString();
+ }
+
+ /**
+ * Checks if a property is set. If the property is set with no value or with a value of "true", this method returns true. It returns "false" if the property
+ * is not set or is set to false
+ *
+ * @param propertyName The property to check
+ * @return true if the property is set to true, false otherwise
+ */
+ public static boolean propertySetOrTrue(final String propertyName) {
+ if (propertyName == null) {
+ return false;
+ }
+
+ final String propertyValue = System.getProperty(propertyName);
+ if (propertyValue == null) {
+ return false;
+ }
+
+ if (propertyValue.trim().length() == 0) {
+ return true;
+ }
+
+ return new Boolean(propertyValue);
+ }
+}
diff --git a/model/utilities/src/main/java/org/onap/policy/apex/model/utilities/ResourceUtils.java b/model/utilities/src/main/java/org/onap/policy/apex/model/utilities/ResourceUtils.java
new file mode 100644
index 000000000..588748dda
--- /dev/null
+++ b/model/utilities/src/main/java/org/onap/policy/apex/model/utilities/ResourceUtils.java
@@ -0,0 +1,226 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2016-2018 Ericsson. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.model.utilities;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+
+import org.slf4j.ext.XLogger;
+import org.slf4j.ext.XLoggerFactory;
+
+/**
+ * This is common utility class with static methods for handling Java resources on the class path. It is an abstract class to prevent any direct instantiation
+ * and private constructor to prevent extending this class.
+ *
+ * @author Sajeevan Achuthan (sajeevan.achuthan@ericsson.com)
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public abstract class ResourceUtils {
+ // Get a reference to the logger
+ private static final XLogger LOGGER = XLoggerFactory.getXLogger(ResourceUtils.class);
+
+ // The length of byte buffers used to read resources into strings
+ private static final int BYTE_BUFFER_LENGH = 1024;
+
+ /**
+ * Private constructor used to prevent sub class instantiation.
+ */
+ private ResourceUtils() {
+ }
+
+ /**
+ * Method to resolve a resource; the local file system is checked first and then the class path is checked.
+ *
+ * @param resourceName The resource name
+ * @return A URL to a resource
+ */
+ public static URL getURL4Resource(final String resourceName) {
+ // Check the local fine system first
+ final URL urlToResource = getLocalFile(resourceName);
+
+ // Check if this is a local file
+ if (urlToResource != null) {
+ return urlToResource;
+ }
+ else {
+ // Resort to the class path
+ return getURLResource(resourceName);
+ }
+ }
+
+ /**
+ * Method to return a resource as a string. The resource can be on the local file system or in the class path. The resource is resolved and loaded into a
+ * string.
+ *
+ * @param resourceName The resource name
+ * @return A string containing the resource
+ */
+ public static String getResourceAsString(final String resourceName) {
+ // Get the resource as a stream, we'll convert it to a string then
+ final InputStream resourceStream = getResourceAsStream(resourceName);
+ if (resourceStream == null) {
+ return null;
+ }
+
+ // Read the stream contents in to an output stream
+ final ByteArrayOutputStream resourceOutputStreamBuffer = new ByteArrayOutputStream();
+ final byte[] resourceBuffer = new byte[BYTE_BUFFER_LENGH];
+ int length;
+ try {
+ while ((length = resourceStream.read(resourceBuffer)) != -1) {
+ resourceOutputStreamBuffer.write(resourceBuffer, 0, length);
+ }
+ }
+ catch (final IOException e) {
+ LOGGER.debug("error reading resource stream \"{}\" : " + e.getMessage(), resourceName, e);
+ return null;
+ }
+
+ return resourceOutputStreamBuffer.toString();
+ }
+
+ /**
+ * Method to return a resource as a stream. The resource can be on the local file system or in the class path. The resource is resolved and returned as a
+ * stream.
+ *
+ * @param resourceName The resource name
+ * @return A stream attached to the resource
+ */
+ public static InputStream getResourceAsStream(final String resourceName) {
+ // Find a URL to the resource first
+ final URL urlToResource = getURL4Resource(resourceName);
+
+ // Check if the resource exists
+ if (urlToResource == null) {
+ // No resource found
+ LOGGER.debug("cound not find resource \"{}\" : ", resourceName);
+ return null;
+ }
+
+ // Read the resource into a string
+ try {
+ return urlToResource.openStream();
+ }
+ catch (final IOException e) {
+ // Any of many IO exceptions such as the resource is a directory
+ LOGGER.debug("error attaching resource \"{}\" to stream : " + e.getMessage(), resourceName, e);
+ return null;
+ }
+ }
+
+ /**
+ * Method to get a URL resource from the class path.
+ *
+ * @param resourceName The resource name
+ * @return The URL to the resource
+ */
+ public static URL getURLResource(final String resourceName) {
+ try {
+ final ClassLoader classLoader = ResourceUtils.class.getClassLoader();
+
+ final String[] fileParts = resourceName.split("/");
+ // Read the resource
+ URL url = classLoader.getResource(resourceName);
+
+ // Check if the resource is defined
+ if (url != null) {
+ // Return the resource as a file name
+ LOGGER.debug("found URL resource \"{}\" : ", url);
+ return url;
+ }
+ else {
+ url = classLoader.getResource(fileParts[fileParts.length - 1]);
+ if (url == null) {
+ LOGGER.debug("cound not find URL resource \"{}\" : ", resourceName);
+ return null;
+ }
+ LOGGER.debug("found URL resource \"{}\" : ", url);
+ return url;
+ }
+ }
+ catch (final Exception e) {
+ LOGGER.debug("error getting URL resource \"{}\" : " + e.getMessage(), e);
+ return null;
+ }
+ }
+
+ /**
+ * Method to get a URL resource from the local machine.
+ *
+ * @param resourceName The resource name
+ * @return The URL to the resource
+ */
+ public static URL getLocalFile(final String resourceName) {
+ try {
+ // Input might already be in URL format
+ final URL ret = new URL(resourceName);
+ final File f = new File(ret.toURI());
+ if (f.exists()) {
+ return ret;
+ }
+ }
+ catch (final Exception ignore) {
+ // We ignore exceptions here and catch them below
+ }
+
+ try {
+ final File f = new File(resourceName);
+ // Check if the file exists
+ if (f.exists()) {
+ final URL urlret = f.toURI().toURL();
+ LOGGER.debug("resource \"{}\" was found on the local file system", f.toURI().toURL());
+ return urlret;
+ }
+ else {
+ LOGGER.debug("resource \"{}\" does not exist on the local file system", resourceName);
+ return null;
+ }
+ }
+ catch (final Exception e) {
+ LOGGER.debug("error finding resource \"{}\" : " + e.getMessage(), e);
+ return null;
+ }
+ }
+
+ /**
+ * Gets the file path for a resource on the local file system or on the class path.
+ *
+ * @param resource the resource to the get the file path for
+ * @return the resource file path
+ */
+ public static String getFilePath4Resource(final String resource) {
+ if (resource == null) {
+ return null;
+ }
+
+ URL modelFileURL = getURL4Resource(resource);
+ if (modelFileURL != null) {
+ return modelFileURL.getPath();
+ }
+ else {
+ return resource;
+ }
+ }
+
+}
diff --git a/model/utilities/src/main/java/org/onap/policy/apex/model/utilities/TextFileUtils.java b/model/utilities/src/main/java/org/onap/policy/apex/model/utilities/TextFileUtils.java
new file mode 100644
index 000000000..d05245f23
--- /dev/null
+++ b/model/utilities/src/main/java/org/onap/policy/apex/model/utilities/TextFileUtils.java
@@ -0,0 +1,117 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2016-2018 Ericsson. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.model.utilities;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+/**
+ * The Class TextFileUtils is class that provides useful functions for handling text files. Functions to read and wrtie text files to strings and strings are
+ * provided.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public abstract class TextFileUtils {
+ private static final int READER_CHAR_BUFFER_SIZE_4096 = 4096;
+
+ private TextFileUtils() {
+ // This class cannot be initialized
+ }
+
+ /**
+ * Method to return the contents of a text file as a string.
+ *
+ * @param textFilePath The path to the file as a string
+ * @return A string containing the contents of the file
+ * @throws IOException on errors reading text from the file
+ */
+ public static String getTextFileAsString(final String textFilePath) throws IOException {
+ final File textFile = new File(textFilePath);
+ final FileInputStream textFileInputStream = new FileInputStream(textFile);
+ final byte[] textData = new byte[(int) textFile.length()];
+ textFileInputStream.read(textData);
+ textFileInputStream.close();
+ return new String(textData);
+ }
+
+ /**
+ * Method to write contents of a string to a text file.
+ *
+ * @param outString The string to write
+ * @param textFilePath The path to the file as a string
+ * @throws IOException on errors reading text from the file
+ */
+ public static void putStringAsTextFile(final String outString, final String textFilePath) throws IOException {
+ final File textFile = new File(textFilePath);
+ putStringAsFile(outString, textFile);
+ }
+
+ /**
+ * Method to write contents of a string to a text file.
+ *
+ * @param outString The string to write
+ * @param textFile The file to write the string to
+ * @throws IOException on errors reading text from the file
+ */
+ public static void putStringAsFile(final String outString, final File textFile) throws IOException {
+ final FileOutputStream textFileOutputStream = new FileOutputStream(textFile);
+ textFileOutputStream.write(outString.getBytes());
+ textFileOutputStream.close();
+ }
+
+ /**
+ * Method to return the contents of a text steam as a string.
+ *
+ * @param textStream The stream
+ * @return A string containing the output of the stream as text
+ * @throws IOException on errors reading text from the file
+ */
+ public static String getStreamAsString(final InputStream textStream) throws IOException {
+ return getReaderAsString(new BufferedReader(new InputStreamReader(textStream)));
+ }
+
+ /**
+ * Method to return the contents of a reader steam as a string. This closes the reader after use
+ *
+ * @param textReader The reader
+ * @return A string containing the output of the reader as text
+ * @throws IOException on errors reading text from the file
+ */
+ public static String getReaderAsString(final BufferedReader textReader) throws IOException {
+
+ final StringBuilder builder = new StringBuilder();
+ int charsRead = -1;
+ final char[] chars = new char[READER_CHAR_BUFFER_SIZE_4096];
+ do {
+ charsRead = textReader.read(chars, 0, chars.length);
+ if (charsRead > 0) {
+ builder.append(chars, 0, charsRead);
+ }
+ }
+ while (charsRead > 0);
+ return builder.toString();
+ }
+}
diff --git a/model/utilities/src/main/java/org/onap/policy/apex/model/utilities/TreeMapUtils.java b/model/utilities/src/main/java/org/onap/policy/apex/model/utilities/TreeMapUtils.java
new file mode 100644
index 000000000..02ab0dd24
--- /dev/null
+++ b/model/utilities/src/main/java/org/onap/policy/apex/model/utilities/TreeMapUtils.java
@@ -0,0 +1,80 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2016-2018 Ericsson. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.model.utilities;
+
+import java.util.AbstractMap.SimpleEntry;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.TreeMap;
+
+/**
+ * This class provides utility functions for tree maps. A function to find the nearest match in the tree map to an input string is provided.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public abstract class TreeMapUtils {
+
+ /**
+ * This class is a utility class that can't be instantiated.
+ */
+ private TreeMapUtils() {
+ }
+
+ /**
+ * Find the list of entries that matches a given word, for example "p" will match "put", "policy", and "push".
+ *
+ * @param <T> the generic type for the value of the tree map
+ * @param searchMap the map that the method operates on
+ * @param word the word to search for
+ * @return the list of entries in the {@code searchMap} that match the {@code word}
+ */
+ public static <T> List<Entry<String, T>> findMatchingEntries(final TreeMap<String, T> searchMap, final String word) {
+ final List<Entry<String, T>> foundNodes = new ArrayList<>();
+
+ // A straight match check
+ if (searchMap.containsKey(word)) {
+ foundNodes.add(new SimpleEntry<>(word, searchMap.get(word)));
+ return foundNodes;
+ }
+
+ // Set up the beginning point for our search for a list of near matches
+ String foundKeyword = searchMap.floorKey(word);
+ if (foundKeyword == null) {
+ foundKeyword = searchMap.firstKey();
+ }
+ else {
+ foundKeyword = searchMap.higherKey(foundKeyword);
+ }
+
+ // Find all the nodes that start with the word we are searching for
+ while (foundKeyword != null) {
+ if (foundKeyword.startsWith(word)) {
+ foundNodes.add(new SimpleEntry<>(foundKeyword, searchMap.get(foundKeyword)));
+ foundKeyword = searchMap.higherKey(foundKeyword);
+ }
+ else {
+ break;
+ }
+ }
+ return foundNodes;
+ }
+}
diff --git a/model/utilities/src/main/java/org/onap/policy/apex/model/utilities/comparison/KeyComparer.java b/model/utilities/src/main/java/org/onap/policy/apex/model/utilities/comparison/KeyComparer.java
new file mode 100644
index 000000000..8903ea803
--- /dev/null
+++ b/model/utilities/src/main/java/org/onap/policy/apex/model/utilities/comparison/KeyComparer.java
@@ -0,0 +1,42 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2016-2018 Ericsson. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.model.utilities.comparison;
+
+/**
+ * This class compares two keys and returns their differences. It is used in bulk comparisons in models where maps of keys are being compared. The
+ * {@link KeyComparer} that is returned does the actual comparison
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ * @param <K> the type of key being compared
+ */
+public class KeyComparer<K> {
+
+ /**
+ * Compare two keys and return their differences.
+ *
+ * @param leftKey The left key of the comparison
+ * @param rightKey The right key of the comparison
+ * @return The difference between the keys
+ */
+ public KeyDifference<K> compareKeys(final K leftKey, final K rightKey) {
+ return new KeyDifference<>(leftKey, rightKey);
+ }
+}
diff --git a/model/utilities/src/main/java/org/onap/policy/apex/model/utilities/comparison/KeyDifference.java b/model/utilities/src/main/java/org/onap/policy/apex/model/utilities/comparison/KeyDifference.java
new file mode 100644
index 000000000..43c44aefe
--- /dev/null
+++ b/model/utilities/src/main/java/org/onap/policy/apex/model/utilities/comparison/KeyDifference.java
@@ -0,0 +1,100 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2016-2018 Ericsson. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.model.utilities.comparison;
+
+/**
+ * This class is used to template key differences for bulk key comparisons in models. It performs a difference check between two keys.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ * @param <K> the generic type
+ */
+public class KeyDifference<K> {
+ // The keys being compared
+ private K leftKey;
+ private K rightKey;
+
+ /**
+ * Constructor used to set the keys being compared.
+ *
+ * @param leftKey the left key that is being compared
+ * @param rightKey the right key that is being compared
+ */
+ public KeyDifference(final K leftKey, final K rightKey) {
+ this.leftKey = leftKey;
+ this.rightKey = rightKey;
+ }
+
+ /**
+ * Gets the left key.
+ *
+ * @return the left key
+ */
+ public K getLeftKey() {
+ return leftKey;
+ }
+
+ /**
+ * Gets the right key.
+ *
+ * @return the right key
+ */
+ public K getRightKey() {
+ return rightKey;
+ }
+
+ /**
+ * Checks if the left and right keys are equal.
+ *
+ * @return true, if checks if is equal
+ */
+ public boolean isEqual() {
+ return leftKey.equals(rightKey);
+ }
+
+ /**
+ * Gets a string representation of the difference between the keys.
+ *
+ * @param diffsOnly if set, then a blank string is returned if the keys are equal
+ * @return the difference between the keys as a string
+ */
+ public String asString(final boolean diffsOnly) {
+ StringBuilder builder = new StringBuilder();
+
+ if (leftKey.equals(rightKey)) {
+ if (!diffsOnly) {
+ builder.append("left key ");
+ builder.append(leftKey);
+ builder.append(" equals right key ");
+ builder.append(rightKey);
+ builder.append('\n');
+ }
+ }
+ else {
+ builder.append("left key ");
+ builder.append(leftKey);
+ builder.append(" and right key ");
+ builder.append(rightKey);
+ builder.append(" differ\n");
+ }
+
+ return builder.toString();
+ }
+}
diff --git a/model/utilities/src/main/java/org/onap/policy/apex/model/utilities/comparison/KeyedMapComparer.java b/model/utilities/src/main/java/org/onap/policy/apex/model/utilities/comparison/KeyedMapComparer.java
new file mode 100644
index 000000000..b11f77a0f
--- /dev/null
+++ b/model/utilities/src/main/java/org/onap/policy/apex/model/utilities/comparison/KeyedMapComparer.java
@@ -0,0 +1,95 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2016-2018 Ericsson. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.model.utilities.comparison;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+/**
+ * Compare two maps and returns their differences. The types of the keys and the values in the two maps being comapred must be the same. The class returns
+ * entries that are only in the left map, only in the right map, entries that have identical keys and different values and entries that have different keys and
+ * different values in a {@link KeyedMapDifference} instance.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ * @param <K> the type of the keys in the maps being compared
+ * @param <V> the type of the values in the maps being compared
+ */
+public class KeyedMapComparer<K, V> {
+ /**
+ * Compare two maps and return their differences in a {@link KeyedMapDifference} instance.
+ *
+ * @param leftMap The left map to be compared
+ * @param rightMap The right map to be compared
+ * @return The common, left only, and right only maps in a {@link KeyedMapDifference} instance
+ */
+ public KeyedMapDifference<K, V> compareMaps(final Map<K, V> leftMap, final Map<K, V> rightMap) {
+ KeyedMapDifference<K, V> result = new KeyedMapDifference<>();
+
+ // Get the keys that are only in the left map
+ Set<K> leftOnlyKeys = new TreeSet<>(leftMap.keySet());
+ leftOnlyKeys.removeAll(rightMap.keySet());
+
+ // Get the keys that are only in the right map
+ Set<K> rightOnlyKeys = new TreeSet<>(rightMap.keySet());
+ rightOnlyKeys.removeAll(leftMap.keySet());
+
+ // Find the keys common across both maps
+ Set<K> commonKeys = new TreeSet<>(rightMap.keySet());
+ commonKeys.addAll(leftMap.keySet());
+ commonKeys.removeAll(leftOnlyKeys);
+ commonKeys.removeAll(rightOnlyKeys);
+
+ // Now save the left values
+ for (K key : leftOnlyKeys) {
+ result.getLeftOnly().put(key, leftMap.get(key));
+ }
+
+ // Now save the right values
+ for (K key : rightOnlyKeys) {
+ result.getRightOnly().put(key, rightMap.get(key));
+ }
+
+ // Save the common values to two maps, an identical and different map
+ for (K key : commonKeys) {
+ // Check if the values are identical in each map
+ V leftValue = leftMap.get(key);
+ V rightValue = rightMap.get(key);
+
+ // Store as appropriate
+ if (leftValue.equals(rightValue)) {
+ result.getIdenticalValues().put(key, leftValue);
+ }
+ else {
+ // Store the two values
+ List<V> valueList = new ArrayList<>();
+ valueList.add(leftValue);
+ valueList.add(rightValue);
+
+ result.getDifferentValues().put(key, valueList);
+ }
+ }
+
+ return result;
+ }
+}
diff --git a/model/utilities/src/main/java/org/onap/policy/apex/model/utilities/comparison/KeyedMapDifference.java b/model/utilities/src/main/java/org/onap/policy/apex/model/utilities/comparison/KeyedMapDifference.java
new file mode 100644
index 000000000..0f9d6ca50
--- /dev/null
+++ b/model/utilities/src/main/java/org/onap/policy/apex/model/utilities/comparison/KeyedMapDifference.java
@@ -0,0 +1,206 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2016-2018 Ericsson. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.model.utilities.comparison;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.TreeMap;
+
+/**
+ * This class holds the result of a difference check between two keyed maps. Four results are returned in the class. The {@code leftOnly} result is the entries
+ * that appear only in the left map. the {@code rightOnly} result is the entries that appear only in the right map. The {@code differentValues} result are the
+ * entries that have the same key but different values in the maps being compared. The {@code identicalValues} result are the entries with identical keys and
+ * values in both maps being compared.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ * @param <K> the generic type
+ * @param <V> the generic type
+ */
+public class KeyedMapDifference<K, V> {
+ private static final String KEY = "key=";
+ private static final String VALUE = ",value=";
+
+ // Three maps to hold the comparison result
+ private Map<K, V> leftOnly = new TreeMap<>();
+ private Map<K, V> rightOnly = new TreeMap<>();
+ private Map<K, V> identicalValues = new TreeMap<>();
+ private Map<K, List<V>> differentValues = new TreeMap<>();
+
+ /**
+ * Gets the entries that were found only in the left map.
+ *
+ * @return the entries only in the left map
+ */
+ public Map<K, V> getLeftOnly() {
+ return leftOnly;
+ }
+
+ /**
+ * Gets the entries that were found only in the right map.
+ *
+ * @return the entries only in the right map
+ */
+ public Map<K, V> getRightOnly() {
+ return rightOnly;
+ }
+
+ /**
+ * Gets the entries that were identical (keys and values the same) in both maps.
+ *
+ * @return the identical entries
+ */
+ public Map<K, V> getIdenticalValues() {
+ return identicalValues;
+ }
+
+ /**
+ * Gets the entries that had the same key but different values in both maps.
+ *
+ * @return the entries that were different. There are two values in the list of values for each entry. The first value is the value that was in the left map
+ * and the second value is the value that was in the right map.
+ */
+ public Map<K, List<V>> getDifferentValues() {
+ return differentValues;
+ }
+
+ /**
+ * Return a string representation of the differences.
+ *
+ * @param diffsOnly if set, then a blank string is returned if the maps are equal
+ * @param keysOnly if set, then a terse string that prints only the keys is returned, otherwise both keys and values are printed
+ * @return the string
+ */
+ public String asString(final boolean diffsOnly, final boolean keysOnly) {
+ StringBuilder builder = new StringBuilder();
+
+ if (leftOnly.isEmpty()) {
+ if (!diffsOnly) {
+ builder.append("*** all left keys in right\n");
+ }
+ }
+ else {
+ builder.append(getInOneSideOnlyAsString(leftOnly, "left", keysOnly));
+ }
+
+ if (leftOnly.isEmpty()) {
+ if (!diffsOnly) {
+ builder.append("*** all right keys in left\n");
+ }
+ }
+ else {
+ builder.append(getInOneSideOnlyAsString(rightOnly, "right", keysOnly));
+ }
+
+ if (differentValues.isEmpty()) {
+ if (!diffsOnly) {
+ builder.append("*** all values in left and right are identical\n");
+ }
+ }
+ else {
+ builder.append(getDifferencesAsString(keysOnly));
+ }
+
+ if (!diffsOnly) {
+ builder.append(getIdenticalsAsString(keysOnly));
+ }
+
+ return builder.toString();
+ }
+
+ /**
+ * Output the entries in a map with entries that are in one side only as a string
+ * @param sideMap the map for the side being checked
+ * @param sideMapString the string that represents the map in output strings
+ * @param keysOnly if true, just add key information and not entries
+ * @return the entries as a string
+ */
+ private Object getInOneSideOnlyAsString(final Map<K, V> sideMap, final String sideMapString, final boolean keysOnly) {
+ StringBuilder builder = new StringBuilder();
+
+ builder.append("*** list of keys on " + sideMapString + " only\n");
+ for (Entry<K, V> leftEntry : sideMap.entrySet()) {
+ builder.append(KEY);
+ builder.append(leftEntry.getKey());
+ if (!keysOnly) {
+ builder.append(VALUE);
+ builder.append(leftEntry.getValue());
+ }
+ builder.append('\n');
+ }
+
+ return builder.toString();
+ }
+
+ /**
+ * Output the differences between two the maps as a string
+ * @param keysOnly if true, just add key information and not entries
+ * @return the differences as a string
+ */
+ private String getDifferencesAsString(final boolean keysOnly) {
+ StringBuilder builder = new StringBuilder();
+
+ builder.append("*** list of differing entries between left and right\n");
+ for (Entry<K, List<V>> differentEntry : differentValues.entrySet()) {
+ builder.append(KEY);
+ builder.append(differentEntry.getKey());
+ if (!keysOnly) {
+ builder.append(",values={");
+ boolean first = true;
+ for (V differentEntryValue : differentEntry.getValue()) {
+ builder.append(differentEntryValue);
+ if (first) {
+ first = false;
+ }
+ else {
+ builder.append(',');
+ }
+ }
+ builder.append("}");
+ }
+ builder.append('\n');
+ }
+
+ return builder.toString();
+ }
+
+ /**
+ * Output the identical entries in the maps as a string
+ * @param keysOnly if true, just add key information and not entries
+ * @return the identical entries as a string
+ */
+ private String getIdenticalsAsString(final boolean keysOnly) {
+ StringBuilder builder = new StringBuilder();
+
+ builder.append("*** list of identical entries in left and right\n");
+ for (Entry<K, V> identicalEntry : identicalValues.entrySet()) {
+ builder.append(KEY);
+ builder.append(identicalEntry.getKey());
+ if (!keysOnly) {
+ builder.append(VALUE);
+ builder.append(identicalEntry.getValue());
+ }
+ builder.append('\n');
+ }
+
+ return builder.toString();
+ }
+}
diff --git a/model/utilities/src/main/java/org/onap/policy/apex/model/utilities/comparison/package-info.java b/model/utilities/src/main/java/org/onap/policy/apex/model/utilities/comparison/package-info.java
new file mode 100644
index 000000000..f0488eacd
--- /dev/null
+++ b/model/utilities/src/main/java/org/onap/policy/apex/model/utilities/comparison/package-info.java
@@ -0,0 +1,26 @@
+/*
+ * ============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 utility template classes that compare keys and maps of any type.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+package org.onap.policy.apex.model.utilities.comparison;
diff --git a/model/utilities/src/main/java/org/onap/policy/apex/model/utilities/package-info.java b/model/utilities/src/main/java/org/onap/policy/apex/model/utilities/package-info.java
new file mode 100644
index 000000000..446d009ba
--- /dev/null
+++ b/model/utilities/src/main/java/org/onap/policy/apex/model/utilities/package-info.java
@@ -0,0 +1,26 @@
+/*
+ * ============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 utility classes that are used in APEX models and indeed in other packages that use APEX models.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+package org.onap.policy.apex.model.utilities;
diff --git a/model/utilities/src/main/java/org/onap/policy/apex/model/utilities/typeutils/ClassBuilder.java b/model/utilities/src/main/java/org/onap/policy/apex/model/utilities/typeutils/ClassBuilder.java
new file mode 100644
index 000000000..e806bd7a0
--- /dev/null
+++ b/model/utilities/src/main/java/org/onap/policy/apex/model/utilities/typeutils/ClassBuilder.java
@@ -0,0 +1,99 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2016-2018 Ericsson. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.model.utilities.typeutils;
+
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.List;
+
+//CHECKSTYLE:OFF: checkstyle:IllegalImport
+import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl;
+//CHECKSTYLE:ON: checkstyle:IllegalImport
+
+/**
+ * This class is a utility class that builds a class with a set of user defined fields. It is used to get the Type of fields in Java schemas<br>
+ * For more information see:<br>
+ * <a href="http://stackoverflow.com/questions/39401083/class-forname-equivalent-for-creating-parameterizedtypes-from-string">
+ * http://stackoverflow.com/questions/39401083/class-forname-equivalent-for-creating-parameterizedtypes-from-string</a><br>
+ * <a href="https://github.com/KetothXupack/stackoverflow-answers/tree/master/q39401083">
+ * https://github.com/KetothXupack/stackoverflow-answers/tree/master/q39401083</a><br>
+ */
+@SuppressWarnings("restriction")
+public class ClassBuilder {
+ private final Class<?> clazz;
+ private final List<ClassBuilder> parameters = new ArrayList<>();
+
+ /**
+ * Constructor that sets the class for the class builder.
+ *
+ * @param clazz the class of the class builder
+ */
+ public ClassBuilder(final Class<?> clazz) {
+ this.clazz = clazz;
+ }
+
+ /**
+ * Creates a {@link ClassBuilder} instance for a class with the given class name.
+ *
+ * @param className the class name of the class builder to create
+ * @return the class builder that is created
+ */
+ public static ClassBuilder parse(final String className) {
+ try {
+ return new ClassBuilder(Class.forName(className));
+ }
+ catch (ClassNotFoundException e) {
+ try {
+ return new ClassBuilder(Class.forName("java.lang." + className));
+ }
+ catch (Exception ignore) {
+ throw new IllegalArgumentException("Class '" + className + "' not found. Also looked for a class called 'java.lang." + className + "'", e);
+ }
+ }
+ }
+
+ /**
+ * Adds a field to the class builder. Each field is itself a class builder.
+ *
+ * @param fieldBuilder the class builder for the field
+ */
+ public void add(final ClassBuilder fieldBuilder) {
+ parameters.add(fieldBuilder);
+ }
+
+ /**
+ * Builds the {@link Type} of the class.
+ *
+ * @return the {@link Type} of the class
+ */
+ public Type build() {
+ // class is not parameterized
+ if (parameters.isEmpty()) {
+ return clazz;
+ }
+ Type[] paramtypes = new Type[parameters.size()];
+ int i = 0;
+ for (ClassBuilder classBuilder : parameters) {
+ paramtypes[i++] = classBuilder.build();
+ }
+ return ParameterizedTypeImpl.make(clazz, paramtypes, null);
+ }
+}
diff --git a/model/utilities/src/main/java/org/onap/policy/apex/model/utilities/typeutils/TypeBuilder.java b/model/utilities/src/main/java/org/onap/policy/apex/model/utilities/typeutils/TypeBuilder.java
new file mode 100644
index 000000000..a3f22a446
--- /dev/null
+++ b/model/utilities/src/main/java/org/onap/policy/apex/model/utilities/typeutils/TypeBuilder.java
@@ -0,0 +1,114 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2016-2018 Ericsson. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.model.utilities.typeutils;
+
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+
+import org.antlr.v4.runtime.ANTLRInputStream;
+import org.antlr.v4.runtime.BailErrorStrategy;
+import org.antlr.v4.runtime.CharStream;
+import org.antlr.v4.runtime.CommonTokenStream;
+import org.antlr.v4.runtime.TokenStream;
+
+/**
+ * This class .
+ */
+public final class TypeBuilder {
+ /**
+ * Private constructor used to prevent sub class instantiation.
+ */
+ private TypeBuilder() {
+ }
+
+ /**
+ * Builds the Type of the Type string that was input.
+ *
+ * @param type the java Type as a string
+ * @return the Type of the string that was input
+ */
+ public static Type build(final String type) {
+ if (type == null || type.length() == 0) {
+ throw new IllegalArgumentException("Blank type string passed to " + TypeBuilder.class.getCanonicalName() + ".build(String type)");
+ }
+
+ try {
+ final CharStream stream = new ANTLRInputStream(type);
+ final TokenStream tokenStream = new CommonTokenStream(new ParametrizedTypeLexer(stream));
+
+ final ParametrizedTypeParser parser = new ParametrizedTypeParser(tokenStream);
+ parser.removeErrorListeners();
+ parser.setErrorHandler(new BailErrorStrategy());
+ parser.setBuildParseTree(true);
+ return parser.type().value.build();
+ }
+ catch (final Exception e) {
+ throw new IllegalArgumentException("Failed to build type '" + type + "': " + e, e);
+ }
+ }
+
+ /**
+ * Gets the class of Java Type.
+ *
+ * @param type the java Type as a string
+ * @return the java Type
+ */
+ public static Class<?> getJavaTypeClass(final String type) {
+ return getJavaTypeClass(build(type));
+ }
+
+ /**
+ * Gets the class of Java Type.
+ *
+ * @param type the java Type as a Type
+ * @return the java Type
+ */
+ public static Class<?> getJavaTypeClass(final Type type) {
+ if (type instanceof Class<?>) {
+ return (Class<?>) type;
+ }
+ else if (type instanceof ParameterizedType) {
+ final Type raw = ((ParameterizedType) type).getRawType();
+ if (!(raw instanceof Class<?>)) {
+ throw new IllegalArgumentException(
+ "The Parameterised javatype " + type + " with base type " + raw + " is not a Java 'Class' that can be instantiated");
+ }
+ return (Class<?>) raw;
+ }
+ throw new IllegalArgumentException("The Parameterised javatype " + type + " is not a Java 'Type' that has a 'Class'");
+ }
+
+ /**
+ * Gets the parameters of a Java Type.
+ *
+ * @param type the Java Type
+ * @return the parameters of the java Type
+ */
+ public static Type[] getJavaTypeParameters(final Type type) {
+ if (type instanceof Class<?>) {
+ return new Type[0];
+ }
+ else if (type instanceof ParameterizedType) {
+ return ((ParameterizedType) type).getActualTypeArguments();
+ }
+ throw new IllegalArgumentException("\"The Parameterised javatype \" + type + \" is not a Java 'Type' that has parameter types");
+ }
+}
diff --git a/model/utilities/src/main/java/org/onap/policy/apex/model/utilities/typeutils/package-info.java b/model/utilities/src/main/java/org/onap/policy/apex/model/utilities/typeutils/package-info.java
new file mode 100644
index 000000000..ed4b079bf
--- /dev/null
+++ b/model/utilities/src/main/java/org/onap/policy/apex/model/utilities/typeutils/package-info.java
@@ -0,0 +1,26 @@
+/*
+ * ============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 utility classes that operate on and work with Java Types.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+package org.onap.policy.apex.model.utilities.typeutils;