Adding tools module to apex-pdp 15/56515/3
authorramverma <ram.krishna.verma@ericsson.com>
Mon, 16 Jul 2018 14:23:45 +0000 (15:23 +0100)
committerramverma <ram.krishna.verma@ericsson.com>
Mon, 16 Jul 2018 15:44:19 +0000 (16:44 +0100)
The tools module contains the utility applications for apex
like converting policy model to cli, generating json events from policy
model, simple websocket client example etc.
The tools are defined to work in console and hence contain sysouts which
are actually needed.

Change-Id: Ia6d40fa7d3f6609ef86abd91a438d6ccbcd1f277
Issue-ID: POLICY-863
Signed-off-by: ramverma <ram.krishna.verma@ericsson.com>
28 files changed:
pom.xml
tools/model-generator/pom.xml [new file with mode: 0644]
tools/model-generator/src/main/java/org/onap/policy/apex/tools/model/generator/KeyInfoGetter.java [new file with mode: 0644]
tools/model-generator/src/main/java/org/onap/policy/apex/tools/model/generator/SchemaUtils.java [new file with mode: 0644]
tools/model-generator/src/main/java/org/onap/policy/apex/tools/model/generator/model2cli/Application.java [new file with mode: 0644]
tools/model-generator/src/main/java/org/onap/policy/apex/tools/model/generator/model2cli/Model2Cli.java [new file with mode: 0644]
tools/model-generator/src/main/java/org/onap/policy/apex/tools/model/generator/model2cli/package-info.java [new file with mode: 0644]
tools/model-generator/src/main/java/org/onap/policy/apex/tools/model/generator/model2event/Application.java [new file with mode: 0644]
tools/model-generator/src/main/java/org/onap/policy/apex/tools/model/generator/model2event/Model2JsonEventSchema.java [new file with mode: 0644]
tools/model-generator/src/main/java/org/onap/policy/apex/tools/model/generator/model2event/package-info.java [new file with mode: 0644]
tools/model-generator/src/main/java/org/onap/policy/apex/tools/model/generator/package-info.java [new file with mode: 0644]
tools/model-generator/src/main/resources/org/onap/policy/apex/tools/model/generator/event-json.stg [new file with mode: 0644]
tools/pom.xml [new file with mode: 0644]
tools/simple-wsclient/pom.xml [new file with mode: 0644]
tools/simple-wsclient/src/main/java/org/onap/policy/apex/tools/simple/wsclient/Application.java [new file with mode: 0644]
tools/simple-wsclient/src/main/java/org/onap/policy/apex/tools/simple/wsclient/SimpleConsole.java [new file with mode: 0644]
tools/simple-wsclient/src/main/java/org/onap/policy/apex/tools/simple/wsclient/SimpleEcho.java [new file with mode: 0644]
tools/simple-wsclient/src/main/java/org/onap/policy/apex/tools/simple/wsclient/package-info.java [new file with mode: 0644]
tools/tools-common/pom.xml [new file with mode: 0644]
tools/tools-common/src/main/java/org/onap/policy/apex/tools/common/CliOptions.java [new file with mode: 0644]
tools/tools-common/src/main/java/org/onap/policy/apex/tools/common/CliParser.java [new file with mode: 0644]
tools/tools-common/src/main/java/org/onap/policy/apex/tools/common/Console.java [new file with mode: 0644]
tools/tools-common/src/main/java/org/onap/policy/apex/tools/common/OutputFile.java [new file with mode: 0644]
tools/tools-common/src/main/java/org/onap/policy/apex/tools/common/package-info.java [new file with mode: 0644]
tools/tools-common/src/main/resources/app-version.txt [new file with mode: 0644]
tools/tools-common/src/test/java/org/onap/policy/apex/tools/common/TestCliParser.java [new file with mode: 0644]
tools/tools-common/src/test/java/org/onap/policy/apex/tools/common/docs/ExampleAppVersion.java [new file with mode: 0644]
tools/tools-common/src/test/java/org/onap/policy/apex/tools/common/docs/ExampleCliParser.java [new file with mode: 0644]

diff --git a/pom.xml b/pom.xml
index 2b545b6..ad9f12f 100644 (file)
--- a/pom.xml
+++ b/pom.xml
         <module>packages</module>
         <module>testsuites</module>
         <module>client</module>
+        <module>tools</module>
     </modules>
 </project>
diff --git a/tools/model-generator/pom.xml b/tools/model-generator/pom.xml
new file mode 100644 (file)
index 0000000..2cdc7c2
--- /dev/null
@@ -0,0 +1,60 @@
+<!--
+  ============LICENSE_START=======================================================
+   Copyright (C) 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.tools</groupId>
+        <artifactId>tools</artifactId>
+        <version>2.0.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>model-generator</artifactId>
+    <name>${project.artifactId}</name>
+    <description>[${project.parent.artifactId}] Apex generators from policy model</description>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.onap.policy.apex-pdp.tools</groupId>
+            <artifactId>tools-common</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.onap.policy.apex-pdp.model</groupId>
+            <artifactId>model-api</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.onap.policy.apex-pdp.services</groupId>
+            <artifactId>services-engine</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.onap.policy.apex-pdp.plugins.plugins-context.context-schema</groupId>
+            <artifactId>context-schema-avro</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.onap.policy.apex-pdp.auth</groupId>
+            <artifactId>cli-codegen</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+    </dependencies>
+</project>
\ No newline at end of file
diff --git a/tools/model-generator/src/main/java/org/onap/policy/apex/tools/model/generator/KeyInfoGetter.java b/tools/model-generator/src/main/java/org/onap/policy/apex/tools/model/generator/KeyInfoGetter.java
new file mode 100644 (file)
index 0000000..a04ed49
--- /dev/null
@@ -0,0 +1,153 @@
+/*-
+ * ============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.tools.model.generator;
+
+import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
+import org.onap.policy.apex.model.basicmodel.concepts.AxKeyInfo;
+import org.onap.policy.apex.model.basicmodel.concepts.AxReferenceKey;
+import org.onap.policy.apex.model.policymodel.concepts.AxPolicyModel;
+
+/**
+ * Getter methods for policy keys.
+ *
+ * @author John Keeney (john.keeney@ericsson.com)
+ */
+
+public class KeyInfoGetter {
+
+    /** The policy model for the getters. */
+    private final AxPolicyModel model;
+
+    /**
+     * Creates a new key getter.
+     *
+     * @param model the policy model to use
+     */
+    public KeyInfoGetter(final AxPolicyModel model) {
+        this.model = model;
+    }
+
+    /**
+     * Returns the key name as string.
+     *
+     * @param key the key to transform
+     * @return key name as string, null if key was null
+     */
+    public String getName(final AxArtifactKey key) {
+        if (key == null) {
+            return null;
+        }
+        return key.getName();
+    }
+
+    /**
+     * Returns the version of an artifact key.
+     *
+     * @param key the key to extract version from
+     * @return version of the key, null if key was null
+     */
+    public String getVersion(final AxArtifactKey key) {
+        if (key == null) {
+            return null;
+        }
+        return key.getVersion();
+    }
+
+    /**
+     * Returns the parent name for the key.
+     *
+     * @param key the key to process
+     * @return parent name, null if key was null
+     */
+    public String getPName(final AxReferenceKey key) {
+        if (key == null) {
+            return null;
+        }
+        return key.getParentKeyName();
+    }
+
+    /**
+     * Returns the parent version for the key.
+     *
+     * @param key the key to process
+     * @return parent version, null if key was null
+     */
+    public String getPVersion(final AxReferenceKey key) {
+        if (key == null) {
+            return null;
+        }
+        return key.getParentKeyVersion();
+    }
+
+    /**
+     * Returns the local name for the key.
+     *
+     * @param key the key to process
+     * @return local name, null if key was null
+     */
+    public String getLName(final AxReferenceKey key) {
+        if (key == null) {
+            return null;
+        }
+        return key.getLocalName();
+    }
+
+    /**
+     * Returns the local name of the parent for the key.
+     *
+     * @param key the key to process
+     * @return local name of the parent, null if key was null
+     */
+    public String getPLName(final AxReferenceKey key) {
+        if (key == null) {
+            return null;
+        }
+        return key.getParentLocalName();
+    }
+
+    /**
+     * Returns the UUID of an artifact key.
+     *
+     * @param key the key to extract version from
+     * @return UUID of the key, null if key was null
+     */
+    public String getUUID(final AxArtifactKey key) {
+        final AxKeyInfo ki = model.getKeyInformation().get(key);
+        if (ki == null || ki.getUUID() == null) {
+            return null;
+        }
+        return ki.getUUID().toString();
+    }
+
+    /**
+     * Returns the description of an artifact key.
+     *
+     * @param key the key to extract version from
+     * @return description of the key, null if key was null
+     */
+    public String getDesc(final AxArtifactKey key) {
+        final AxKeyInfo ki = model.getKeyInformation().get(key);
+        if (ki == null || ki.getDescription() == null) {
+            return null;
+        }
+        return ki.getDescription().toString();
+    }
+}
diff --git a/tools/model-generator/src/main/java/org/onap/policy/apex/tools/model/generator/SchemaUtils.java b/tools/model-generator/src/main/java/org/onap/policy/apex/tools/model/generator/SchemaUtils.java
new file mode 100644 (file)
index 0000000..3a4feb0
--- /dev/null
@@ -0,0 +1,175 @@
+/*-
+ * ============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.tools.model.generator;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.avro.AvroRuntimeException;
+import org.apache.avro.Schema;
+import org.apache.avro.Schema.Field;
+import org.apache.avro.reflect.ReflectData;
+import org.onap.policy.apex.context.SchemaHelper;
+import org.onap.policy.apex.context.impl.schema.SchemaHelperFactory;
+import org.onap.policy.apex.model.eventmodel.concepts.AxEvent;
+import org.onap.policy.apex.model.eventmodel.concepts.AxField;
+import org.onap.policy.apex.plugins.context.schema.avro.AvroSchemaHelper;
+import org.onap.policy.apex.service.engine.event.ApexEventException;
+
+/**
+ * Utility methods for schema handling.
+ *
+ * @author John Keeney (john.keeney@ericsson.com)
+ */
+public final class SchemaUtils {
+
+    /**
+     * Private constructor to avoid instantiation.
+     */
+    private SchemaUtils() {}
+
+    /**
+     * Returns the schema for an event.
+     *
+     * @param event the event to process
+     * @return the schema of the event
+     * @throws ApexEventException in any error case
+     */
+    public static Schema getEventSchema(final AxEvent event) throws ApexEventException {
+        final Schema skeletonSchema = Schema.createRecord(event.getKey().getName(), event.getNameSpace(),
+                "org.onap.policy.apex.model.eventmodel.events", false);
+
+        // Get the schema field for each parameter
+        final List<Field> fields = new ArrayList<>(getSkeletonEventSchemaFields());
+
+        final Map<String, Schema> preExistingParamSchemas = new LinkedHashMap<>();
+        for (final AxField parameter : event.getParameterMap().values()) {
+            final Schema fieldSchema = getEventParameterSchema(parameter, preExistingParamSchemas);
+            final Field f = new Field(parameter.getKey().getLocalName(), fieldSchema, (String) null, (Object) null);
+            fields.add(f);
+        }
+        skeletonSchema.setFields(fields);
+
+        return skeletonSchema;
+    }
+
+    /**
+     * Returns the schema fields as an array.
+     *
+     * @return an array with schema fields in the following order: nameSpace, name, version, source, target
+     */
+    public static List<Field> getSkeletonEventSchemaFields() {
+        // Fixed fields
+        final Field f1 = new Field("nameSpace", Schema.create(Schema.Type.STRING), (String) null, (Object) null);
+        final Field f2 = new Field("name", Schema.create(Schema.Type.STRING), (String) null, (Object) null);
+        final Field f3 = new Field("version", Schema.create(Schema.Type.STRING), (String) null, (Object) null);
+        final Field f4 = new Field("source", Schema.create(Schema.Type.STRING), (String) null, (Object) null);
+        final Field f5 = new Field("target", Schema.create(Schema.Type.STRING), (String) null, (Object) null);
+
+        return Arrays.asList(f1, f2, f3, f4, f5);
+    }
+
+    /**
+     * Returns the schema for an event parameter.
+     *
+     * @param parameter the parameter to process
+     * @param preexistingParamSchemas map of pre-existing schemas
+     * @return the schema for the event parameter
+     * @throws ApexEventException in case of any error
+     */
+    public static Schema getEventParameterSchema(final AxField parameter,
+            final Map<String, Schema> preexistingParamSchemas) throws ApexEventException {
+        final SchemaHelper schemaHelper =
+                new SchemaHelperFactory().createSchemaHelper(parameter.getKey(), parameter.getSchema().getKey());
+
+        Schema parameterSchema = null;
+        try {
+            if (schemaHelper instanceof AvroSchemaHelper) {
+                parameterSchema = ((AvroSchemaHelper) schemaHelper).getAvroSchema();
+            } else {
+                parameterSchema = ReflectData.get().getSchema(schemaHelper.getSchemaClass());
+            }
+        } catch (final AvroRuntimeException e) {
+            throw new ApexEventException("failed to decode a schema for parameter " + parameter.getKey().getLocalName()
+                    + " of type " + parameter.getSchema().getID() + " with Java type " + schemaHelper.getSchemaClass(),
+                    e);
+        }
+        final String schemaname = parameterSchema.getFullName();
+
+        // Get the Avro schema for this parameter, we need to keep track of sub-schemas for records because Avro does
+        // not
+        // allow re-declaration of sub-schema records of the same type. You simply reference the first sub-schema.
+        final Schema alreadyseen = preexistingParamSchemas.get(schemaname);
+
+        try {
+            processSubSchemas(parameterSchema, preexistingParamSchemas);
+        } catch (AvroRuntimeException | ApexEventException e) {
+            throw new ApexEventException("failed to decode a schema for parameter " + parameter.getKey().getLocalName()
+                    + " of type " + parameter.getSchema().getID() + " using Schema type " + schemaname, e);
+        }
+        if (alreadyseen != null) {
+            // logger.warn("parameter "+ parameter.getKey().getLocalName() + " of type " + parameter.getSchema().getID()
+            // + " tries to redfine AVRO type
+            // "+schemaname+", but it was previously defined. This parameter will use the previously defined version
+            // because AVRO does not support redefinition
+            // of types that have already been defined");
+            parameterSchema = alreadyseen;
+        }
+
+        return parameterSchema;
+    }
+
+    /**
+     * Processes a sub-schema.
+     *
+     * @param avroParameterSchema an AVRO schema to process
+     * @param map mapping of strings to schemas
+     * @throws ApexEventException in case of any error
+     */
+    public static void processSubSchemas(final Schema avroParameterSchema, final Map<String, Schema> map)
+            throws ApexEventException {
+        if (avroParameterSchema.getType() == Schema.Type.RECORD) {
+            final String schematypename = avroParameterSchema.getFullName();
+            final Schema alreadyregistered = map.get(schematypename);
+            if (alreadyregistered != null && !avroParameterSchema.equals(alreadyregistered)) {
+                throw new ApexEventException(
+                        "Parameter attempts to redefine type " + schematypename + " when it has already been defined");
+            }
+            map.put(schematypename, avroParameterSchema);
+            for (final Schema.Field f : avroParameterSchema.getFields()) {
+                final Schema fieldschema = f.schema();
+                processSubSchemas(fieldschema, map);
+            }
+        } else if (avroParameterSchema.getType() == Schema.Type.ARRAY) {
+            processSubSchemas(avroParameterSchema.getElementType(), map);
+        } else if (avroParameterSchema.getType() == Schema.Type.MAP) {
+            processSubSchemas(avroParameterSchema.getValueType(), map);
+        } else if (avroParameterSchema.getType() == Schema.Type.UNION) {
+            for (final Schema s : avroParameterSchema.getTypes()) {
+                processSubSchemas(s, map);
+            }
+        }
+    }
+
+}
diff --git a/tools/model-generator/src/main/java/org/onap/policy/apex/tools/model/generator/model2cli/Application.java b/tools/model-generator/src/main/java/org/onap/policy/apex/tools/model/generator/model2cli/Application.java
new file mode 100644 (file)
index 0000000..2367503
--- /dev/null
@@ -0,0 +1,124 @@
+/*-
+ * ============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.tools.model.generator.model2cli;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.HelpFormatter;
+import org.onap.policy.apex.model.basicmodel.concepts.ApexException;
+import org.onap.policy.apex.tools.common.CliOptions;
+import org.onap.policy.apex.tools.common.CliParser;
+import org.onap.policy.apex.tools.common.OutputFile;
+
+/**
+ * Process an Apex Policy Model file to generate the CLI commands to generate an equivalent Apex Policy Model.
+ *
+ * @author Sven van der Meer &lt;sven.van.der.meer@ericsson.com&gt;
+ */
+public final class Application {
+
+    /** The name of the application. */
+    public static final String APP_NAME = "gen-model2cli";
+
+    /** The description 1-liner of the application. */
+    public static final String APP_DESCRIPTION = "generates CLI Editor Commands from a policy model";
+
+    /**
+     * Private constructor to prevent instantiation.
+     */
+    private Application() {}
+
+    /**
+     * Main method to start the application.
+     *
+     * @param args the command line arguments
+     */
+    public static void main(final String[] args) {
+        final CliParser cli = new CliParser();
+        cli.addOption(CliOptions.HELP);
+        cli.addOption(CliOptions.VERSION);
+        cli.addOption(CliOptions.SKIPVALIDATION);
+        cli.addOption(CliOptions.MODELFILE);
+        cli.addOption(CliOptions.FILEOUT);
+        cli.addOption(CliOptions.OVERWRITE);
+
+        final CommandLine cmd = cli.parseCli(args);
+
+        // help is an exit option, print usage and exit
+        if (cmd.hasOption(CliOptions.HELP.getOpt())) {
+            final HelpFormatter formatter = new HelpFormatter();
+            System.out.println(APP_NAME + " v" + cli.getAppVersion() + " - " + APP_DESCRIPTION);
+            formatter.printHelp(APP_NAME, cli.getOptions());
+            System.out.println();
+            return;
+        }
+
+        // version is an exit option, print version and exit
+        if (cmd.hasOption(CliOptions.VERSION.getOpt())) {
+            System.out.println(APP_NAME + " " + cli.getAppVersion());
+            System.out.println();
+            return;
+        }
+
+        String modelFile = cmd.getOptionValue(CliOptions.MODELFILE.getOpt());
+        if (modelFile != null) {
+            modelFile = cmd.getOptionValue("model");
+        }
+        if (modelFile == null) {
+            System.err.println(APP_NAME + ": no '-" + CliOptions.MODELFILE.getOpt()
+                    + "' model file given, cannot proceed (try -h for help)");
+            return;
+        }
+
+        OutputFile outfile = null;
+        final String of = cmd.getOptionValue(CliOptions.FILEOUT.getOpt());
+        final boolean overwrite = cmd.hasOption(CliOptions.OVERWRITE.getOpt());
+        if (overwrite && of == null) {
+            System.err.println(APP_NAME + ": error with '-" + CliOptions.OVERWRITE.getOpt()
+                    + "' option. This option is only valid if a '-" + CliOptions.FILEOUT.getOpt()
+                    + "' option is also used. Cannot proceed (try -h for help)");
+            return;
+        }
+        if (of != null) {
+            outfile = new OutputFile(of, overwrite);
+            final String isoutfileok = outfile.validate();
+            if (isoutfileok != null) {
+                System.err.println(APP_NAME + ": error with '-" + CliOptions.FILEOUT.getOpt() + "' option: \""
+                        + isoutfileok + "\". Cannot proceed (try -h for help)");
+                return;
+            }
+        }
+
+        if (outfile == null) {
+            System.out.println();
+            System.out.println(APP_NAME + ": starting CLI generator");
+            System.out.println(" --> model file: " + modelFile);
+            System.out.println();
+            System.out.println();
+        }
+
+        try {
+            final Model2Cli app = new Model2Cli(modelFile, outfile, !cmd.hasOption("sv"), APP_NAME);
+            app.runApp();
+        } catch (final ApexException aex) {
+            System.err.println(APP_NAME + ": caught APEX exception with message: " + aex.getMessage());
+        }
+    }
+}
diff --git a/tools/model-generator/src/main/java/org/onap/policy/apex/tools/model/generator/model2cli/Model2Cli.java b/tools/model-generator/src/main/java/org/onap/policy/apex/tools/model/generator/model2cli/Model2Cli.java
new file mode 100644 (file)
index 0000000..5117a2e
--- /dev/null
@@ -0,0 +1,463 @@
+/*-
+ * ============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.tools.model.generator.model2cli;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Properties;
+
+import org.apache.commons.lang3.Validate;
+import org.onap.policy.apex.auth.clicodegen.CGCliEditor;
+import org.onap.policy.apex.model.basicmodel.concepts.ApexException;
+import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
+import org.onap.policy.apex.model.basicmodel.concepts.AxReferenceKey;
+import org.onap.policy.apex.model.basicmodel.concepts.AxValidationResult;
+import org.onap.policy.apex.model.contextmodel.concepts.AxContextAlbum;
+import org.onap.policy.apex.model.contextmodel.concepts.AxContextSchema;
+import org.onap.policy.apex.model.eventmodel.concepts.AxEvent;
+import org.onap.policy.apex.model.eventmodel.concepts.AxField;
+import org.onap.policy.apex.model.modelapi.ApexAPIResult;
+import org.onap.policy.apex.model.modelapi.ApexModel;
+import org.onap.policy.apex.model.modelapi.ApexModelFactory;
+import org.onap.policy.apex.model.policymodel.concepts.AxPolicy;
+import org.onap.policy.apex.model.policymodel.concepts.AxPolicyModel;
+import org.onap.policy.apex.model.policymodel.concepts.AxState;
+import org.onap.policy.apex.model.policymodel.concepts.AxStateFinalizerLogic;
+import org.onap.policy.apex.model.policymodel.concepts.AxStateOutput;
+import org.onap.policy.apex.model.policymodel.concepts.AxStateTaskReference;
+import org.onap.policy.apex.model.policymodel.concepts.AxTask;
+import org.onap.policy.apex.model.policymodel.concepts.AxTaskLogic;
+import org.onap.policy.apex.model.policymodel.concepts.AxTaskParameter;
+import org.onap.policy.apex.model.policymodel.concepts.AxTaskSelectionLogic;
+import org.onap.policy.apex.tools.common.OutputFile;
+import org.onap.policy.apex.tools.model.generator.KeyInfoGetter;
+import org.stringtemplate.v4.ST;
+
+/**
+ * Takes a model and generates the JSON event schemas.
+ *
+ * @author Sven van der Meer (sven.van.der.meer@ericsson.com)
+ */
+public class Model2Cli {
+
+    /** Application name, used as prompt. */
+    private final String appName;
+
+    /** The file name of the policy model. */
+    private final String modelFile;
+
+    /** The output file, if any. */
+    private final OutputFile outFile;
+
+    /** Pre-validate the model. */
+    private final boolean validate;
+
+    /** utility for getting key information and parsing keys etc.. */
+    private KeyInfoGetter kig = null;
+
+    /**
+     * Creates a new model to CLI commands generator.
+     *
+     * @param modelFile the model file to be used
+     * @param outFile the out file
+     * @param validate true for model validation, false otherwise
+     * @param appName application name for printouts
+     */
+    public Model2Cli(final String modelFile, final OutputFile outFile, final boolean validate, final String appName) {
+        Validate.notNull(modelFile, "Model2Cli: given model file name was blank");
+        Validate.notNull(appName, "Model2Cli: given application name was blank");
+        this.modelFile = modelFile;
+        this.outFile = outFile;
+        this.appName = appName;
+        this.validate = validate;
+    }
+
+    /**
+     * Runs the application.
+     *
+     * @return status of the application execution, 0 for success, positive integer for exit condition (such as help or
+     *         version), negative integer for errors
+     * @throws ApexException if any problem occurred in the model
+     */
+    public int runApp() throws ApexException {
+        final CGCliEditor codeGen = new CGCliEditor();
+
+        final ApexModelFactory factory = new ApexModelFactory();
+        final ApexModel model = factory.createApexModel(new Properties(), true);
+
+        final ApexAPIResult result = model.loadFromFile(modelFile);
+        if (result.isNOK()) {
+            System.err.println(appName + ": " + result.getMessage());
+            return -1;
+        }
+
+        final AxPolicyModel policyModel = model.getPolicyModel();
+        policyModel.register();
+
+        if (validate) {
+            final AxValidationResult val = new AxValidationResult();
+            policyModel.validate(val);
+            if (!val.isOK()) {
+                System.err.println("Cannot translate the model. The model is not valid: \n" + val.toString());
+                return -1;
+            }
+        }
+
+        kig = new KeyInfoGetter(policyModel);
+
+        // Order is important. 0: model, 1: context schemas, 2: tasks, 3: events, 4: ContextAlbums, 5: Policies
+        // 0: model
+        final AxArtifactKey pmkey = policyModel.getKey();
+        codeGen.addModelParams(kig.getName(pmkey), kig.getVersion(pmkey), kig.getUUID(pmkey), kig.getDesc(pmkey));
+
+        // 1: Context Schemas
+        for (final AxContextSchema s : policyModel.getSchemas().getSchemasMap().values()) {
+            final AxArtifactKey key = s.getKey();
+
+            codeGen.addSchemaDeclaration(kig.getName(key), kig.getVersion(key), kig.getUUID(key), kig.getDesc(key),
+                    s.getSchemaFlavour(), s.getSchema());
+        }
+
+        // 2: tasks
+        for (final AxTask t : policyModel.getTasks().getTaskMap().values()) {
+            final AxArtifactKey key = t.getKey();
+            final List<ST> infields = getInfieldsForTask(codeGen, t);
+            final List<ST> outfields = getOutfieldsForTask(codeGen, t);
+            final ST logic = getLogicForTask(codeGen, t);
+            final List<ST> parameters = getParametersForTask(codeGen, t);
+            final List<ST> contextRefs = getCtxtRefsForTask(codeGen, t);
+
+            codeGen.addTaskDeclaration(kig.getName(key), kig.getVersion(key), kig.getUUID(key), kig.getDesc(key),
+                    infields, outfields, logic, parameters, contextRefs);
+        }
+
+        // 3: events
+        for (final AxEvent e : policyModel.getEvents().getEventMap().values()) {
+            final AxArtifactKey key = e.getKey();
+            final List<ST> fields = getParametersForEvent(codeGen, e);
+
+            codeGen.addEventDeclaration(kig.getName(key), kig.getVersion(key), kig.getUUID(key), kig.getDesc(key),
+                    e.getNameSpace(), e.getSource(), e.getTarget(), fields);
+        }
+
+        // 4: context albums
+        for (final AxContextAlbum a : policyModel.getAlbums().getAlbumsMap().values()) {
+            final AxArtifactKey key = a.getKey();
+
+            codeGen.addContextAlbumDeclaration(kig.getName(key), kig.getVersion(key), kig.getUUID(key),
+                    kig.getDesc(key), a.getScope(), a.isWritable(), kig.getName(a.getItemSchema()),
+                    kig.getVersion(a.getItemSchema()));
+        }
+
+        // 5: policies
+        for (final AxPolicy p : policyModel.getPolicies().getPolicyMap().values()) {
+            final AxArtifactKey key = p.getKey();
+            final List<ST> states = getStatesForPolicy(codeGen, p);
+            codeGen.addPolicyDefinition(kig.getName(key), kig.getVersion(key), kig.getUUID(key), kig.getDesc(key),
+                    p.getTemplate(), p.getFirstState(), states);
+        }
+
+        final String out = codeGen.getModel().render();
+        if (outFile != null) {
+            try {
+                final Writer w = outFile.toWriter();
+                if (w == null) {
+                    System.err.println("Error writing output to file " + outFile);
+                    return -1;
+                }
+                w.write(out);
+                w.close();
+            } catch (final IOException e) {
+                System.err.println("Error writing output to file " + outFile + ": " + e.getMessage());
+                return -1;
+            }
+        } else {
+            System.err.println(out);
+        }
+        return 0;
+    }
+
+    /**
+     * Gets the parameters for event.
+     *
+     * @param cg the code generator
+     * @param e the event
+     * @return the parameters for event
+     */
+    private List<ST> getParametersForEvent(final CGCliEditor cg, final AxEvent e) {
+        final Collection<AxField> fields = e.getFields();
+        final List<ST> ret = new ArrayList<>(fields.size());
+        for (final AxField f : fields) {
+            final AxReferenceKey fkey = f.getKey();
+
+            final ST val = cg.createEventFieldDefinition(kig.getPName(fkey), kig.getPVersion(fkey), kig.getLName(fkey),
+                    kig.getName(f.getSchema()), kig.getVersion(f.getSchema()), f.getOptional());
+
+            ret.add(val);
+        }
+        return ret;
+    }
+
+    /**
+     * Gets the context references for task.
+     *
+     * @param cg the code generator
+     * @param t the task
+     * @return the context references for task
+     */
+    private List<ST> getCtxtRefsForTask(final CGCliEditor cg, final AxTask t) {
+        final Collection<AxArtifactKey> ctxs = t.getContextAlbumReferences();
+        final List<ST> ret = new ArrayList<>(ctxs.size());
+        final AxArtifactKey tkey = t.getKey();
+        for (final AxArtifactKey ckey : ctxs) {
+
+            final ST val = cg.createTaskDefinitionContextRef(kig.getName(tkey), kig.getVersion(tkey), kig.getName(ckey),
+                    kig.getVersion(ckey));
+
+            ret.add(val);
+        }
+        return ret;
+    }
+
+    /**
+     * Gets the parameters for task.
+     *
+     * @param cg the code generator
+     * @param t the task
+     * @return the parameters for task
+     */
+    private List<ST> getParametersForTask(final CGCliEditor cg, final AxTask t) {
+        final Collection<AxTaskParameter> pars = t.getTaskParameters().values();
+        final List<ST> ret = new ArrayList<>(pars.size());
+        for (final AxTaskParameter p : pars) {
+            final AxReferenceKey pkey = p.getKey();
+
+            final ST val = cg.createTaskDefinitionParameters(kig.getPName(pkey), kig.getPVersion(pkey),
+                    kig.getLName(pkey), p.getTaskParameterValue());
+
+            ret.add(val);
+        }
+        return ret;
+    }
+
+    /**
+     * Gets the logic for task.
+     *
+     * @param cg the code generator
+     * @param t the task
+     * @return the logic for task
+     */
+    private ST getLogicForTask(final CGCliEditor cg, final AxTask t) {
+        final AxArtifactKey tkey = t.getKey();
+        final AxTaskLogic tl = t.getTaskLogic();
+
+        final ST val =
+                cg.createTaskDefLogic(kig.getName(tkey), kig.getVersion(tkey), tl.getLogicFlavour(), tl.getLogic());
+
+        return val;
+    }
+
+    /**
+     * Gets the output fields for task.
+     *
+     * @param cg the code generator
+     * @param t the task
+     * @return the output fields for task
+     */
+    private List<ST> getOutfieldsForTask(final CGCliEditor cg, final AxTask t) {
+        final Collection<? extends AxField> fields = t.getOutputFields().values();
+        final List<ST> ret = new ArrayList<>(fields.size());
+        for (final AxField f : fields) {
+            final AxReferenceKey fkey = f.getKey();
+
+            final ST val = cg.createTaskDefinitionOutfields(kig.getPName(fkey), kig.getPVersion(fkey),
+                    kig.getLName(fkey), kig.getName(f.getSchema()), kig.getVersion(f.getSchema()));
+
+            ret.add(val);
+        }
+        return ret;
+    }
+
+    /**
+     * Gets the input fields for task.
+     *
+     * @param cg the code generator
+     * @param t the task
+     * @return the input fields for task
+     */
+    private List<ST> getInfieldsForTask(final CGCliEditor cg, final AxTask t) {
+        final Collection<? extends AxField> fields = t.getInputFields().values();
+        final List<ST> ret = new ArrayList<>(fields.size());
+        for (final AxField f : fields) {
+            final AxReferenceKey fkey = f.getKey();
+
+            final ST val = cg.createTaskDefinitionInfields(kig.getPName(fkey), kig.getPVersion(fkey),
+                    kig.getLName(fkey), kig.getName(f.getSchema()), kig.getVersion(f.getSchema()));
+
+            ret.add(val);
+        }
+        return ret;
+    }
+
+    /**
+     * Gets the states for policy.
+     *
+     * @param cg the code generator
+     * @param p the policy
+     * @return the states for policy
+     */
+    private List<ST> getStatesForPolicy(final CGCliEditor cg, final AxPolicy p) {
+        final Collection<AxState> states = p.getStateMap().values();
+        final List<ST> ret = new ArrayList<>(states.size());
+        for (final AxState st : states) {
+            final AxReferenceKey skey = st.getKey();
+            final List<ST> outputs = getStateOutputsForState(cg, st);
+            final List<ST> finalizerLogics = getFinalizersForState(cg, st);
+            final List<ST> tasks = getTaskRefsForState(cg, st);
+            final List<ST> tsLogic = getTSLForState(cg, st);
+            final List<ST> ctxRefs = getCtxtRefsForState(cg, st);
+
+            final ST val = cg.createPolicyStateDef(kig.getPName(skey), kig.getPVersion(skey), kig.getLName(skey),
+                    kig.getName(st.getTrigger()), kig.getVersion(st.getTrigger()), kig.getName(st.getDefaultTask()),
+                    kig.getVersion(st.getDefaultTask()), outputs, tasks, tsLogic, finalizerLogics, ctxRefs);
+
+            ret.add(val);
+        }
+        return ret;
+    }
+
+    /**
+     * Gets the finalizers for state.
+     *
+     * @param cg the code generator
+     * @param st the state
+     * @return the finalizers for state
+     */
+    private List<ST> getFinalizersForState(final CGCliEditor cg, final AxState st) {
+        final Collection<AxStateFinalizerLogic> fins = st.getStateFinalizerLogicMap().values();
+        final List<ST> ret = new ArrayList<>(fins.size());
+        final AxReferenceKey skey = st.getKey();
+        for (final AxStateFinalizerLogic fin : fins) {
+            final AxReferenceKey finkey = fin.getKey();
+
+            final ST val = cg.createPolicyStateDefFinalizerLogic(kig.getPName(skey), kig.getPVersion(skey),
+                    kig.getLName(skey), kig.getLName(finkey), fin.getLogicFlavour(), fin.getLogic());
+
+            ret.add(val);
+        }
+        return ret;
+    }
+
+    /**
+     * Gets the context references for state.
+     *
+     * @param cg the code generator
+     * @param st the state
+     * @return the context references for state
+     */
+    private List<ST> getCtxtRefsForState(final CGCliEditor cg, final AxState st) {
+        final Collection<AxArtifactKey> ctxs = st.getContextAlbumReferences();
+        final List<ST> ret = new ArrayList<>(ctxs.size());
+        final AxReferenceKey skey = st.getKey();
+        for (final AxArtifactKey ctx : ctxs) {
+
+            final ST val = cg.createPolicyStateDefContextRef(kig.getPName(skey), kig.getPVersion(skey),
+                    kig.getLName(skey), kig.getName(ctx), kig.getVersion(ctx));
+
+            ret.add(val);
+        }
+        return ret;
+    }
+
+    /**
+     * Gets the Task Selection Logic for state.
+     *
+     * @param cg the code generator
+     * @param st the state
+     * @return the TSL for state (if any) in a list
+     */
+    private List<ST> getTSLForState(final CGCliEditor cg, final AxState st) {
+        final AxReferenceKey skey = st.getKey();
+        if (st.checkSetTaskSelectionLogic()) {
+            final AxTaskSelectionLogic tsl = st.getTaskSelectionLogic();
+            final ST val = cg.createPolicyStateDefTaskSelLogic(kig.getPName(skey), kig.getPVersion(skey),
+                    kig.getLName(skey), tsl.getLogicFlavour(), tsl.getLogic());
+            return Collections.singletonList(val);
+        } else {
+            return Collections.emptyList();
+        }
+    }
+
+    /**
+     * Gets the task references for state.
+     *
+     * @param cg the code generator
+     * @param st the state
+     * @return the task references for state
+     */
+    private List<ST> getTaskRefsForState(final CGCliEditor cg, final AxState st) {
+        final Map<AxArtifactKey, AxStateTaskReference> taskrefs = st.getTaskReferences();
+        final List<ST> ret = new ArrayList<>(taskrefs.size());
+        final AxReferenceKey skey = st.getKey();
+        for (final Entry<AxArtifactKey, AxStateTaskReference> e : taskrefs.entrySet()) {
+            final AxArtifactKey tkey = e.getKey();
+            final AxStateTaskReference tr = e.getValue();
+            final AxReferenceKey trkey = tr.getKey();
+
+            final ST val = cg.createPolicyStateTask(kig.getPName(skey), kig.getPVersion(skey), kig.getLName(skey),
+                    kig.getLName(trkey), kig.getName(tkey), kig.getVersion(tkey), tr.getStateTaskOutputType().name(),
+                    kig.getLName(tr.getOutput()));
+
+            ret.add(val);
+        }
+        return ret;
+    }
+
+    /**
+     * Gets the state outputs for state.
+     *
+     * @param cg the code generator
+     * @param st the state
+     * @return the state outputs for state
+     */
+    private List<ST> getStateOutputsForState(final CGCliEditor cg, final AxState st) {
+        final Collection<AxStateOutput> outs = st.getStateOutputs().values();
+        final List<ST> ret = new ArrayList<>(outs.size());
+        final AxReferenceKey skey = st.getKey();
+        for (final AxStateOutput out : outs) {
+            final AxReferenceKey outkey = out.getKey();
+
+            final ST val = cg.createPolicyStateOutput(kig.getPName(skey), kig.getPVersion(skey), kig.getLName(skey),
+                    kig.getLName(outkey), kig.getName(out.getOutgingEvent()), kig.getVersion(out.getOutgingEvent()),
+                    kig.getLName(out.getNextState()));
+
+            ret.add(val);
+        }
+        return ret;
+    }
+
+}
diff --git a/tools/model-generator/src/main/java/org/onap/policy/apex/tools/model/generator/model2cli/package-info.java b/tools/model-generator/src/main/java/org/onap/policy/apex/tools/model/generator/model2cli/package-info.java
new file mode 100644 (file)
index 0000000..b8b3ffa
--- /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=========================================================
+ */
+
+/**
+ * An application generating CLI editor commands from a policy model.
+ *
+ * @author Sven van der Meer (sven.van.der.meer@ericsson.com)
+ */
+
+package org.onap.policy.apex.tools.model.generator.model2cli;
diff --git a/tools/model-generator/src/main/java/org/onap/policy/apex/tools/model/generator/model2event/Application.java b/tools/model-generator/src/main/java/org/onap/policy/apex/tools/model/generator/model2event/Application.java
new file mode 100644 (file)
index 0000000..2bc70f6
--- /dev/null
@@ -0,0 +1,111 @@
+/*-
+ * ============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.tools.model.generator.model2event;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.HelpFormatter;
+import org.onap.policy.apex.model.basicmodel.concepts.ApexException;
+import org.onap.policy.apex.tools.common.CliOptions;
+import org.onap.policy.apex.tools.common.CliParser;
+
+/**
+ * Model 2 event generator with main method.
+ *
+ * @author Sven van der Meer (sven.van.der.meer@ericsson.com)
+ */
+public final class Application {
+
+    /** The name of the application. */
+    public static final String APP_NAME = "gen-model2event";
+
+    /** The description 1-liner of the application. */
+    public static final String APP_DESCRIPTION = "generates JSON templates for events generated from a policy model";
+
+    /** Private constructor to prevent instantiation. */
+    private Application() {}
+
+    /**
+     * Main method to start the application.
+     *
+     * @param args the command line arguments
+     */
+    public static void main(final String[] args) {
+        final CliParser cli = new CliParser();
+        cli.addOption(CliOptions.HELP);
+        cli.addOption(CliOptions.VERSION);
+        cli.addOption(CliOptions.MODELFILE);
+        cli.addOption(CliOptions.TYPE);
+
+        final CommandLine cmd = cli.parseCli(args);
+
+        // help is an exit option, print usage and exit
+        if (cmd.hasOption('h') || cmd.hasOption("help")) {
+            final HelpFormatter formatter = new HelpFormatter();
+            System.out.println(APP_NAME + " v" + cli.getAppVersion() + " - " + APP_DESCRIPTION);
+            formatter.printHelp(APP_NAME, cli.getOptions());
+            System.out.println();
+            return;
+        }
+
+        // version is an exit option, print version and exit
+        if (cmd.hasOption('v') || cmd.hasOption("version")) {
+            System.out.println(APP_NAME + " " + cli.getAppVersion());
+            System.out.println();
+            return;
+        }
+
+        String modelFile = cmd.getOptionValue('m');
+        if (modelFile == null) {
+            modelFile = cmd.getOptionValue("model");
+        }
+        if (modelFile == null) {
+            System.err.println(APP_NAME + ": no model file given, cannot proceed (try -h for help)");
+            return;
+        }
+
+        String type = cmd.getOptionValue('t');
+        if (type == null) {
+            type = cmd.getOptionValue("type");
+        }
+        if (type == null) {
+            System.err.println(APP_NAME + ": no event type given, cannot proceed (try -h for help)");
+            return;
+        }
+        if (!type.equals("stimuli") && !type.equals("response") && !type.equals("internal")) {
+            System.err.println(APP_NAME + ": unknown type <" + type + ">, cannot proceed (try -h for help)");
+            return;
+        }
+
+        System.out.println();
+        System.out.println(APP_NAME + ": starting Event generator");
+        System.out.println(" --> model file: " + modelFile);
+        System.out.println(" --> type: " + type);
+        System.out.println();
+        System.out.println();
+
+        try {
+            final Model2JsonEventSchema app = new Model2JsonEventSchema(modelFile, type, APP_NAME);
+            app.runApp();
+        } catch (final ApexException aex) {
+            System.err.println(APP_NAME + ": caught APEX exception with message: " + aex.getMessage());
+        }
+    }
+}
diff --git a/tools/model-generator/src/main/java/org/onap/policy/apex/tools/model/generator/model2event/Model2JsonEventSchema.java b/tools/model-generator/src/main/java/org/onap/policy/apex/tools/model/generator/model2event/Model2JsonEventSchema.java
new file mode 100644 (file)
index 0000000..ec6d72c
--- /dev/null
@@ -0,0 +1,265 @@
+/*-
+ * ============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.tools.model.generator.model2event;
+
+import java.util.HashSet;
+import java.util.Properties;
+import java.util.Set;
+
+import org.apache.avro.Schema;
+import org.apache.avro.Schema.Field;
+import org.apache.commons.lang3.Validate;
+import org.onap.policy.apex.context.parameters.SchemaParameters;
+import org.onap.policy.apex.model.basicmodel.concepts.ApexException;
+import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
+import org.onap.policy.apex.model.eventmodel.concepts.AxEvent;
+import org.onap.policy.apex.model.modelapi.ApexAPIResult;
+import org.onap.policy.apex.model.modelapi.ApexModel;
+import org.onap.policy.apex.model.modelapi.ApexModelFactory;
+import org.onap.policy.apex.model.policymodel.concepts.AxPolicies;
+import org.onap.policy.apex.model.policymodel.concepts.AxPolicy;
+import org.onap.policy.apex.model.policymodel.concepts.AxPolicyModel;
+import org.onap.policy.apex.model.policymodel.concepts.AxState;
+import org.onap.policy.apex.model.policymodel.concepts.AxStateOutput;
+import org.onap.policy.apex.plugins.context.schema.avro.AvroSchemaHelperParameters;
+import org.onap.policy.apex.tools.model.generator.SchemaUtils;
+import org.stringtemplate.v4.ST;
+import org.stringtemplate.v4.STGroup;
+import org.stringtemplate.v4.STGroupFile;
+
+/**
+ * Takes a model and generates the JSON event schemas.
+ *
+ * @author Sven van der Meer (sven.van.der.meer@ericsson.com)
+ */
+public class Model2JsonEventSchema {
+
+    /** Application name, used as prompt. */
+    private final String appName;
+
+    /** The file name of the policy model. */
+    private final String modelFile;
+
+    /** The type of events to generate: stimuli, response, internal. */
+    private final String type;
+
+    /**
+     * Creates a new model to event schema generator.
+     *
+     * @param modelFile the model file to be used
+     * @param type the type of events to generate, one of: stimuli, response, internal
+     * @param appName application name for printouts
+     */
+    public Model2JsonEventSchema(final String modelFile, final String type, final String appName) {
+        Validate.notNull(modelFile, "Model2JsonEvent: given model file name was blank");
+        Validate.notNull(type, "Model2JsonEvent: given type was blank");
+        Validate.notNull(appName, "Model2JsonEvent: given application name was blank");
+        this.modelFile = modelFile;
+        this.type = type;
+        this.appName = appName;
+    }
+
+    /**
+     * Adds a type to a field for a given schema.
+     *
+     * @param schema the schema to add a type for
+     * @param stg the STG
+     * @return a template with the type
+     */
+    protected ST addFieldType(final Schema schema, final STGroup stg) {
+        ST ret = null;
+        switch (schema.getType()) {
+            case BOOLEAN:
+            case BYTES:
+            case DOUBLE:
+            case FIXED:
+            case FLOAT:
+            case INT:
+            case LONG:
+            case STRING:
+                ret = stg.getInstanceOf("fieldTypeAtomic");
+                ret.add("type", schema.getType());
+                break;
+
+            case ARRAY:
+                ret = stg.getInstanceOf("fieldTypeArray");
+                ret.add("array", this.addFieldType(schema.getElementType(), stg));
+                break;
+            case ENUM:
+                ret = stg.getInstanceOf("fieldTypeEnum");
+                ret.add("symbols", schema.getEnumSymbols());
+                break;
+
+            case MAP:
+                ret = stg.getInstanceOf("fieldTypeMap");
+                ret.add("map", this.addFieldType(schema.getValueType(), stg));
+                break;
+
+            case RECORD:
+                ret = stg.getInstanceOf("fieldTypeRecord");
+                for (final Field field : schema.getFields()) {
+                    final ST st = stg.getInstanceOf("field");
+                    st.add("name", field.name());
+                    st.add("type", this.addFieldType(field.schema(), stg));
+                    ret.add("fields", st);
+                }
+                break;
+
+            case NULL:
+                break;
+            case UNION:
+                break;
+            default:
+                break;
+        }
+        return ret;
+    }
+
+    /**
+     * Runs the application.
+     *
+     * @throws ApexException if any problem occurred in the model
+     * @return status of the application execution, 0 for success, positive integer for exit condition (such as help or
+     *         version), negative integer for errors
+     */
+    public int runApp() throws ApexException {
+        final STGroupFile stg = new STGroupFile("org/onap/policy/apex/tools/model/generator/event-json.stg");
+        final ST stEvents = stg.getInstanceOf("events");
+
+        final ApexModelFactory factory = new ApexModelFactory();
+        final ApexModel model = factory.createApexModel(new Properties(), true);
+
+        final ApexAPIResult result = model.loadFromFile(modelFile);
+        if (result.isNOK()) {
+            System.err.println(appName + ": " + result.getMessage());
+            return -1;
+        }
+
+        final AxPolicyModel policyModel = model.getPolicyModel();
+        policyModel.register();
+        new SchemaParameters().getSchemaHelperParameterMap().put("Avro", new AvroSchemaHelperParameters());
+
+        final Set<AxEvent> events = new HashSet<>();
+        final Set<AxArtifactKey> eventKeys = new HashSet<>();
+        final AxPolicies policies = policyModel.getPolicies();
+        switch (type) {
+            case "stimuli":
+                for (final AxPolicy policy : policies.getPolicyMap().values()) {
+                    final String firsState = policy.getFirstState();
+                    for (final AxState state : policy.getStateMap().values()) {
+                        if (state.getKey().getLocalName().equals(firsState)) {
+                            eventKeys.add(state.getTrigger());
+                        }
+                    }
+                }
+                break;
+            case "response":
+                for (final AxPolicy policy : policies.getPolicyMap().values()) {
+                    for (final AxState state : policy.getStateMap().values()) {
+                        if (state.getNextStateSet().iterator().next().equals("NULL")) {
+                            for (final AxStateOutput output : state.getStateOutputs().values()) {
+                                eventKeys.add(output.getOutgingEvent());
+                            }
+                        }
+                    }
+                }
+                break;
+            case "internal":
+                for (final AxPolicy policy : policies.getPolicyMap().values()) {
+                    final String firsState = policy.getFirstState();
+                    for (final AxState state : policy.getStateMap().values()) {
+                        if (state.getKey().getLocalName().equals(firsState)) {
+                            continue;
+                        }
+                        if (state.getNextStateSet().iterator().next().equals("NULL")) {
+                            continue;
+                        }
+                        for (final AxStateOutput output : state.getStateOutputs().values()) {
+                            eventKeys.add(output.getOutgingEvent());
+                        }
+                    }
+                }
+                break;
+            default:
+                System.err.println(appName + ": unknown type <" + type + ">, cannot proceed");
+                return -1;
+        }
+
+        for (final AxEvent event : policyModel.getEvents().getEventMap().values()) {
+            for (final AxArtifactKey key : eventKeys) {
+                if (event.getKey().equals(key)) {
+                    events.add(event);
+                }
+            }
+        }
+
+        for (final AxEvent event : events) {
+            final ST stEvent = stg.getInstanceOf("event");
+            stEvent.add("name", event.getKey().getName());
+            stEvent.add("nameSpace", event.getNameSpace());
+            stEvent.add("version", event.getKey().getVersion());
+            stEvent.add("source", event.getSource());
+            stEvent.add("target", event.getTarget());
+
+            final Schema avro = SchemaUtils.getEventSchema(event);
+            for (final Field field : avro.getFields()) {
+                // filter magic names
+                switch (field.name()) {
+                    case "name":
+                    case "nameSpace":
+                    case "version":
+                    case "source":
+                    case "target":
+                        break;
+                    default:
+                        stEvent.add("fields", this.setField(field, stg));
+                }
+            }
+            stEvents.add("event", stEvent);
+        }
+        System.err.println(stEvents.render());
+        return 0;
+    }
+
+    /**
+     * Adds a field to the output.
+     *
+     * @param field the field from the event
+     * @param stg the STG
+     * @return a template for the field
+     */
+    protected ST setField(final Field field, final STGroup stg) {
+        final ST st = stg.getInstanceOf("field");
+        switch (field.name()) {
+            case "name":
+            case "nameSpace":
+            case "version":
+            case "source":
+            case "target":
+                break;
+            default:
+                st.add("name", field.name());
+                st.add("type", this.addFieldType(field.schema(), stg));
+        }
+        return st;
+    }
+
+}
diff --git a/tools/model-generator/src/main/java/org/onap/policy/apex/tools/model/generator/model2event/package-info.java b/tools/model-generator/src/main/java/org/onap/policy/apex/tools/model/generator/model2event/package-info.java
new file mode 100644 (file)
index 0000000..602b4e9
--- /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=========================================================
+ */
+
+/**
+ * An application generating input/output event templates from a policy model.
+ *
+ * @author Sven van der Meer (sven.van.der.meer@ericsson.com)
+ */
+
+package org.onap.policy.apex.tools.model.generator.model2event;
diff --git a/tools/model-generator/src/main/java/org/onap/policy/apex/tools/model/generator/package-info.java b/tools/model-generator/src/main/java/org/onap/policy/apex/tools/model/generator/package-info.java
new file mode 100644 (file)
index 0000000..1f60a18
--- /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=========================================================
+ */
+
+/**
+ * Applications that generate events and commands from policy models.
+ *
+ * @author Sven van der Meer (sven.van.der.meer@ericsson.com)
+ */
+
+package org.onap.policy.apex.tools.model.generator;
diff --git a/tools/model-generator/src/main/resources/org/onap/policy/apex/tools/model/generator/event-json.stg b/tools/model-generator/src/main/resources/org/onap/policy/apex/tools/model/generator/event-json.stg
new file mode 100644 (file)
index 0000000..9a6b858
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * ============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=========================================================
+ */
+
+/*
+ * Template for creating a template JSON event.
+ *
+ * @package    org.onap.policy.apex.tool.model.generator
+ * @author     Sven van der Meer &lt;sven.van.der.meer@ericsson.com&gt;
+ */
+
+typeMap ::= [
+       "BOOLEAN":"###boolean: true, false###",
+       "BYTES":"###bytes###",
+       "DOUBLE":"###double: 0.0###",
+       "FLOAT":"###float: 0.0###",
+       "INT":"###integer: 0###",
+       "LONG":"###long: 0###",
+       "STRING":"\"###string###\"",
+       default:key
+]
+
+events(event) ::= <<
+<event:{e|<e>}; separator="\n\n">
+>>
+
+event(name, nameSpace, version, source, target, fields) ::= <<
+{
+       "name" : "<name>",
+       "nameSpace" : "<nameSpace>",
+       "version" : "<version>",
+       "source" : "<source>",
+       "target" : "<target>",
+       <fields:{field|<field>}; separator=",\n">
+}
+>>
+
+field(name, type) ::= <<
+"<name>" : <type>
+>>
+
+fieldTypeAtomic(type) ::= <<
+<typeMap.(type)>
+>>
+
+fieldTypeArray(array) ::= <<
+[
+       <typeMap.(array)>,
+       <typeMap.(array)>
+]
+>>
+
+fieldTypeEnum(symbols) ::= <<
+###Enum, one of <symbols>###
+>>
+
+fieldTypeMap(map) ::= <<
+{
+       "ID#1":
+               <map>,
+       "ID#n":
+               <map>
+}
+>>
+
+fieldTypeRecord(fields) ::= <<
+{
+       <fields:{field|<field>}; separator=",\n">
+}
+>>
\ No newline at end of file
diff --git a/tools/pom.xml b/tools/pom.xml
new file mode 100644 (file)
index 0000000..d824f3d
--- /dev/null
@@ -0,0 +1,41 @@
+<!--
+  ============LICENSE_START=======================================================
+   Copyright (C) 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</groupId>
+        <artifactId>apex-pdp</artifactId>
+        <version>2.0.0-SNAPSHOT</version>
+    </parent>
+
+    <groupId>org.onap.policy.apex-pdp.tools</groupId>
+    <artifactId>tools</artifactId>
+
+    <packaging>pom</packaging>
+    <name>${project.artifactId}</name>
+    <description>The Apex applications, implementation dependent wrappers and mediation for Apex in various technologies.</description>
+
+    <modules>
+        <module>tools-common</module>
+        <module>simple-wsclient</module>
+        <module>model-generator</module>
+    </modules>
+</project>
\ No newline at end of file
diff --git a/tools/simple-wsclient/pom.xml b/tools/simple-wsclient/pom.xml
new file mode 100644 (file)
index 0000000..2a49b95
--- /dev/null
@@ -0,0 +1,76 @@
+<!--
+  ============LICENSE_START=======================================================
+   Copyright (C) 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.tools</groupId>
+        <artifactId>tools</artifactId>
+        <version>2.0.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>simple-wsclient</artifactId>
+    <name>${project.artifactId}</name>
+    <description>[${project.parent.artifactId}] Simple Websocket client (console and echo)</description>
+
+    <properties>
+        <apex-apps-wsclients-simple-dir>${project.basedir}/src</apex-apps-wsclients-simple-dir>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.java-websocket</groupId>
+            <artifactId>Java-WebSocket</artifactId>
+            <version>1.3.4</version>
+        </dependency>
+        <dependency>
+            <groupId>org.onap.policy.apex-pdp.tools</groupId>
+            <artifactId>tools-common</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>console-client</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>single</goal>
+                        </goals>
+                        <configuration>
+                            <descriptorRefs>
+                                <descriptorRef>jar-with-dependencies</descriptorRef>
+                            </descriptorRefs>
+                            <archive>
+                                <manifest>
+                                    <mainClass>org.onap.policy.apex.tools.simple.wsclients.Application</mainClass>
+                                </manifest>
+                            </archive>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
\ No newline at end of file
diff --git a/tools/simple-wsclient/src/main/java/org/onap/policy/apex/tools/simple/wsclient/Application.java b/tools/simple-wsclient/src/main/java/org/onap/policy/apex/tools/simple/wsclient/Application.java
new file mode 100644 (file)
index 0000000..bfd6573
--- /dev/null
@@ -0,0 +1,181 @@
+/*-
+ * ============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.tools.simple.wsclient;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.nio.channels.NotYetConnectedException;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.HelpFormatter;
+import org.apache.commons.lang3.Validate;
+import org.onap.policy.apex.tools.common.CliOptions;
+import org.onap.policy.apex.tools.common.CliParser;
+
+/**
+ * Simple console application with main method.
+ *
+ * @author Sven van der Meer (sven.van.der.meer@ericsson.com)
+ */
+public final class Application {
+
+    /**
+     * Private constructor prevents subclassing.
+     */
+    private Application() {}
+
+    /**
+     * The main method for the WS applications.
+     *
+     * @param args command line argument s
+     */
+    public static void main(final String[] args) {
+        String appName = "ws-simple-echo";
+        String appDescr = "receives events from APEX via WS and prints them to standard out";
+        boolean console = false;
+
+        final CliParser cli = new CliParser();
+        cli.addOption(CliOptions.HELP);
+        cli.addOption(CliOptions.VERSION);
+        cli.addOption(CliOptions.CONSOLE);
+        cli.addOption(CliOptions.SERVER);
+        cli.addOption(CliOptions.PORT);
+
+        final CommandLine cmd = cli.parseCli(args);
+
+        if (cmd.hasOption('c') || cmd.hasOption("console")) {
+            appName = "ws-simple-console";
+            appDescr = "takes events from stdin and sends via WS to APEX";
+            console = true;
+        }
+
+        // help is an exit option, print usage and exit
+        if (cmd.hasOption('h') || cmd.hasOption("help")) {
+            final HelpFormatter formatter = new HelpFormatter();
+            System.out.println(appName + " v" + cli.getAppVersion() + " - " + appDescr);
+            formatter.printHelp(appName, cli.getOptions());
+            System.out.println();
+            return;
+        }
+
+        // version is an exit option, print version and exit
+        if (cmd.hasOption('v') || cmd.hasOption("version")) {
+            System.out.println(appName + " " + cli.getAppVersion());
+            System.out.println();
+            return;
+        }
+
+        String server = cmd.getOptionValue('s');
+        if (server == null) {
+            server = cmd.getOptionValue("server");
+        }
+        if (server == null) {
+            server = "localhost";
+        }
+
+        String port = cmd.getOptionValue('p');
+        if (port == null) {
+            port = cmd.getOptionValue("port");
+        }
+        if (port == null) {
+            port = "8887";
+        }
+
+        if (console) {
+            runConsole(server, port, appName);
+        } else {
+            runEcho(server, port, appName);
+        }
+
+    }
+
+    /**
+     * Runs the simple echo client.
+     *
+     * @param server the server, must not be blank
+     * @param port the port, must not be blank
+     * @param appName the application name, must not be blank
+     */
+    public static void runEcho(final String server, final String port, final String appName) {
+        Validate.notBlank(server);
+        Validate.notBlank(port);
+        Validate.notBlank(appName);
+
+        System.out.println();
+        System.out.println(appName + ": starting simple event echo");
+        System.out.println(" --> server: " + server);
+        System.out.println(" --> port: " + port);
+        System.out.println();
+        System.out.println("Once started, the application will simply print out all received events to standard out.");
+        System.out.println("Each received event will be prefixed by '---' and suffixed by '===='");
+        System.out.println();
+        System.out.println();
+
+        try {
+            final SimpleEcho simpleEcho = new SimpleEcho(server, port, appName);
+            simpleEcho.connect();
+        } catch (final URISyntaxException uex) {
+            System.err.println(appName + ": URI exception, could not create URI from server and port settings");
+        } catch (final NullPointerException nex) {
+            System.err.println(appName + ": null pointer, server or port were null");
+        } catch (final IllegalArgumentException iex) {
+            System.err.println(appName + ": illegal argument, server or port were blank");
+        }
+    }
+
+    /**
+     * Runs the simple console.
+     *
+     * @param server the server, must not be blank
+     * @param port the port, must not be blank
+     * @param appName the application name, must not be blank
+     */
+    public static void runConsole(final String server, final String port, final String appName) {
+        Validate.notBlank(server);
+        Validate.notBlank(port);
+        Validate.notBlank(appName);
+
+        System.out.println();
+        System.out.println(appName + ": starting simple event console");
+        System.out.println(" --> server: " + server);
+        System.out.println(" --> port: " + port);
+        System.out.println();
+        System.out.println(" - terminate the application typing 'exit<enter>' or using 'CTRL+C'");
+        System.out.println(" - events are created by a non-blank starting line and terminated by a blank line");
+        System.out.println();
+        System.out.println();
+
+        try {
+            final SimpleConsole simpleConsole = new SimpleConsole(server, port, appName);
+            simpleConsole.runClient();
+        } catch (final URISyntaxException uex) {
+            System.err.println(appName + ": URI exception, could not create URI from server and port settings");
+        } catch (final NullPointerException nex) {
+            System.err.println(appName + ": null pointer, server or port were null");
+        } catch (final IllegalArgumentException iex) {
+            System.err.println(appName + ": illegal argument, server or port were blank");
+        } catch (final NotYetConnectedException nex) {
+            System.err.println(appName + ": not yet connected, connection to server took too long");
+        } catch (final IOException ioe) {
+            System.err.println(appName + ": IO exception, something went wrong on the standard input");
+        }
+    }
+}
diff --git a/tools/simple-wsclient/src/main/java/org/onap/policy/apex/tools/simple/wsclient/SimpleConsole.java b/tools/simple-wsclient/src/main/java/org/onap/policy/apex/tools/simple/wsclient/SimpleConsole.java
new file mode 100644 (file)
index 0000000..810c74d
--- /dev/null
@@ -0,0 +1,145 @@
+/*-
+ * ============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.tools.simple.wsclient;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.channels.NotYetConnectedException;
+
+import org.apache.commons.lang3.Validate;
+import org.java_websocket.client.WebSocketClient;
+import org.java_websocket.framing.CloseFrame;
+import org.java_websocket.handshake.ServerHandshake;
+
+/**
+ * Simple WS client with a console for events.
+ *
+ * @author Sven van der Meer (sven.van.der.meer@ericsson.com)
+ */
+public class SimpleConsole extends WebSocketClient {
+
+    /** Application name, used as prompt. */
+    private final String appName;
+
+    /**
+     * Creates a new simple echo object.
+     *
+     * @param server the name of the server as either IP address or fully qualified host name, must not be blank
+     * @param port the port to be used, must not be blank
+     * @param appName the application name, used as prompt, must not be blank
+     * @throws URISyntaxException is URI could not be created from server/port settings
+     * @throws RuntimeException if server or port where blank
+     */
+    public SimpleConsole(final String server, final String port, final String appName) throws URISyntaxException {
+        super(new URI("ws://" + server + ":" + port));
+        Validate.notBlank(appName, "SimpleConsole: given application name was blank");
+        this.appName = appName;
+    }
+
+    @Override
+    public void onClose(final int code, final String reason, final boolean remote) {
+        System.out.println(this.appName + ": Connection closed by " + (remote ? "APEX" : "me"));
+        System.out.print(" ==-->> ");
+        switch (code) {
+            case CloseFrame.NORMAL:
+                System.out.println("normal");
+                break;
+            case CloseFrame.GOING_AWAY:
+                System.out.println("APEX going away");
+                break;
+            case CloseFrame.PROTOCOL_ERROR:
+                System.out.println("some protocol error");
+                break;
+            case CloseFrame.REFUSE:
+                System.out.println("received unacceptable type of data");
+                break;
+            case CloseFrame.NO_UTF8:
+                System.out.println("expected UTF-8, found something else");
+                break;
+            case CloseFrame.TOOBIG:
+                System.out.println("message too big");
+                break;
+            case CloseFrame.UNEXPECTED_CONDITION:
+                System.out.println("unexpected server condition");
+                break;
+            default:
+                System.out.println("unkown close frame code");
+                break;
+        }
+        System.out.print(" ==-->> " + reason);
+    }
+
+    @Override
+    public void onError(final Exception ex) {
+        System.err.println(this.appName + ": " + ex.getMessage());
+    }
+
+    @Override
+    public void onMessage(final String message) {
+        // this client does not expect messages
+    }
+
+    @Override
+    public void onOpen(final ServerHandshake handshakedata) {
+        System.out.println(this.appName + ": opened connection to APEX (" + handshakedata.getHttpStatusMessage() + ")");
+    }
+
+    /**
+     * Runs the console client. In particular, it starts a new thread for the Websocket connection and then reads from
+     * standard input.
+     *
+     * @throws NotYetConnectedException if not connected to server when sending events
+     * @throws IOException on an IO problem on standard in
+     */
+    public void runClient() throws NotYetConnectedException, IOException {
+        final Thread thread = new Thread() {
+            @Override
+            public void run() {
+                connect();
+            }
+        };
+        thread.start();
+
+        final BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
+        String event = "";
+        String line;
+        while ((line = in.readLine()) != null) {
+            if (line.equals("exit")) {
+                break;
+            }
+
+            final String current = line.trim();
+            if ("".equals(current)) {
+                this.send(event);
+                event = "";
+            } else {
+                event += current;
+            }
+        }
+
+        thread.interrupt();
+        this.close(CloseFrame.NORMAL);
+    }
+
+}
diff --git a/tools/simple-wsclient/src/main/java/org/onap/policy/apex/tools/simple/wsclient/SimpleEcho.java b/tools/simple-wsclient/src/main/java/org/onap/policy/apex/tools/simple/wsclient/SimpleEcho.java
new file mode 100644 (file)
index 0000000..4b67cb8
--- /dev/null
@@ -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.tools.simple.wsclient;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import org.apache.commons.lang3.Validate;
+import org.java_websocket.client.WebSocketClient;
+import org.java_websocket.framing.CloseFrame;
+import org.java_websocket.handshake.ServerHandshake;
+
+/**
+ * Simple WS client as an echo.
+ *
+ * @author Sven van der Meer (sven.van.der.meer@ericsson.com)
+ */
+public class SimpleEcho extends WebSocketClient {
+
+    /** Application name, used as prompt. */
+    private final String appName;
+
+    /**
+     * Creates a new simple echo object.
+     *
+     * @param server the name of the server as either IP address or fully qualified host name, must not be blank
+     * @param port the port to be used, must not be blank
+     * @param appName the application name, used as prompt, must not be blank
+     * @throws URISyntaxException is URI could not be created from server/port settings
+     * @throws RuntimeException if server or port where blank
+     */
+    public SimpleEcho(final String server, final String port, final String appName) throws URISyntaxException {
+        super(new URI("ws://" + server + ":" + port));
+        Validate.notBlank(appName, "SimpleEcho: given application name was blank");
+        this.appName = appName;
+    }
+
+    @Override
+    public void onClose(final int code, final String reason, final boolean remote) {
+        System.out.println(this.appName + ": Connection closed by " + (remote ? "APEX" : "me"));
+        System.out.print(" ==-->> ");
+        switch (code) {
+            case CloseFrame.NORMAL:
+                System.out.println("normal");
+                break;
+            case CloseFrame.GOING_AWAY:
+                System.out.println("APEX going away");
+                break;
+            case CloseFrame.PROTOCOL_ERROR:
+                System.out.println("some protocol error");
+                break;
+            case CloseFrame.REFUSE:
+                System.out.println("received unacceptable type of data");
+                break;
+            case CloseFrame.NO_UTF8:
+                System.out.println("expected UTF-8, found something else");
+                break;
+            case CloseFrame.TOOBIG:
+                System.out.println("message too big");
+                break;
+            case CloseFrame.UNEXPECTED_CONDITION:
+                System.out.println("unexpected server condition");
+                break;
+            default:
+                System.out.println("unkown close frame code");
+                break;
+        }
+        System.out.print(" ==-->> " + reason);
+    }
+
+    @Override
+    public void onError(final Exception ex) {
+        System.err.println(this.appName + ": " + ex.getMessage());
+    }
+
+    @Override
+    public void onMessage(final String message) {
+        System.out.println(this.appName + ": received");
+        System.out.println("---------------------------------");
+        System.out.println(message);
+        System.out.println("=================================");
+        System.out.println();
+    }
+
+    @Override
+    public void onOpen(final ServerHandshake handshakedata) {
+        System.out.println(this.appName + ": opened connection to APEX (" + handshakedata.getHttpStatusMessage() + ")");
+    }
+
+}
diff --git a/tools/simple-wsclient/src/main/java/org/onap/policy/apex/tools/simple/wsclient/package-info.java b/tools/simple-wsclient/src/main/java/org/onap/policy/apex/tools/simple/wsclient/package-info.java
new file mode 100644 (file)
index 0000000..ea30f93
--- /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=========================================================
+ */
+
+/**
+ * A simple Websocket client, runs as console or echo client.
+ *
+ * @author Sven van der Meer (sven.van.der.meer@ericsson.com)
+ */
+
+package org.onap.policy.apex.tools.simple.wsclient;
diff --git a/tools/tools-common/pom.xml b/tools/tools-common/pom.xml
new file mode 100644 (file)
index 0000000..e4d0c40
--- /dev/null
@@ -0,0 +1,73 @@
+<!--
+  ============LICENSE_START=======================================================
+   Copyright (C) 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.tools</groupId>
+        <artifactId>tools</artifactId>
+        <version>2.0.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>tools-common</artifactId>
+    <name>${project.artifactId}</name>
+    <description>[${project.parent.artifactId}] Utilities for APEX tools</description>
+
+    <properties>
+        <apex-apps-utilities-dir>${project.basedir}/src</apex-apps-utilities-dir>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+            <version>3.6</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-text</artifactId>
+            <version>1.1</version>
+        </dependency>
+        <dependency>
+            <groupId>commons-cli</groupId>
+            <artifactId>commons-cli</artifactId>
+            <version>${version.commons-cli}</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <resources>
+            <resource>
+                <directory>src/main/resources</directory>
+                <filtering>true</filtering>
+                <includes>
+                    <include>**/app-version.txt</include>
+                </includes>
+            </resource>
+            <resource>
+                <directory>src/main/resources</directory>
+                <filtering>false</filtering>
+                <excludes>
+                    <exclude>**/app-version.txt</exclude>
+                </excludes>
+            </resource>
+        </resources>
+    </build>
+</project>
\ No newline at end of file
diff --git a/tools/tools-common/src/main/java/org/onap/policy/apex/tools/common/CliOptions.java b/tools/tools-common/src/main/java/org/onap/policy/apex/tools/common/CliOptions.java
new file mode 100644 (file)
index 0000000..277769b
--- /dev/null
@@ -0,0 +1,105 @@
+/*-
+ * ============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.tools.common;
+
+import org.apache.commons.cli.Option;
+
+/**
+ * Standard application CLI options.
+ *
+ * @author Sven van der Meer (sven.van.der.meer@ericsson.com)
+ */
+public final class CliOptions {
+
+    /** Private constructor to prevent instantiation. */
+    private CliOptions() {}
+
+    /** A console option with "-c" and "--console". */
+    public static final Option CONSOLE =
+            Option.builder("c").longOpt("console").desc("application as console with input from standard in").build();
+
+    /** A help option with "-h" and "--help". */
+    public static final Option HELP =
+            Option.builder("h").longOpt("help").desc("prints this help and usage screen").build();
+
+    /** A version option with "-v" and "--version". */
+    public static final Option VERSION =
+            Option.builder("v").longOpt("version").desc("prints the application version").build();
+
+    /** A print-stacktrace option with "--print-stacktrace". */
+    public static final Option PRINTSTACKTRACE =
+            Option.builder().longOpt("print-stacktrace").desc("prints stack traces for any exception").build();
+
+    /** A check-java-class option with "--check-java-class". */
+    public static final Option CHECKJAVACLASS = Option.builder("j").longOpt("check-java-class")
+            .desc("switch on checking of Java class references, requires JAR in class path").build();
+
+    /** A quiet option with "-q" and "--quiet". */
+    public static final Option QUIET =
+            Option.builder("q").longOpt("quiet").desc("application in quiet mode, no output at all").build();
+
+    /** A no-warning option with "--no-warnings". */
+    public static final Option NOWARNINGS =
+            Option.builder().longOpt("no-warnings").desc("switch off all warnings").build();
+
+    /** A no-error option with "--no-errors". */
+    public static final Option NOERRORS =
+            Option.builder().longOpt("no-errors").desc("switch off error messages").build();
+
+    /** A no-progress option with "--no-progress". */
+    public static final Option SHOWPROGRESS =
+            Option.builder().longOpt("no-progress").desc("switch off progress information").build();
+
+    /** A file-in option with "-f" and "--input-file". */
+    public static final Option FILEIN =
+            Option.builder("f").hasArg().argName("FILE").longOpt("input-file").desc("set the input file").build();
+
+    /** A file-out option with "-o" and "--output-file". */
+    public static final Option FILEOUT = Option.builder("o").hasArg().argName("FILE").longOpt("output-file")
+            .desc("set the output file").required(false).build();
+
+    /** An overwrite option with "-ow" and "--overwrite". */
+    public static final Option OVERWRITE = Option.builder("ow").required(false).longOpt("overwrite")
+            .desc("overwrite the output file if it exists. This option can only be used with the -" + FILEOUT.getOpt()
+                    + " option")
+            .build();
+
+    /** An option for the policy model file with "-m" and "--model". */
+    public static final Option MODELFILE = Option.builder("m").hasArg().argName("MODEL-FILE").longOpt("model")
+            .desc("set the input policy model file").build();
+
+    /** A type option defining what type is used for events with "-t" and "--type". */
+    public static final Option TYPE = Option.builder("t").hasArg().argName("TYPE").longOpt("type").desc(
+            "set the event type for generation, one of: stimuli (trigger events), response (action events), internal (events between states)")
+            .build();
+
+    /** A server option with "-s" and "--server". */
+    public static final Option SERVER = Option.builder("s").hasArg().argName("HOSTNAME").longOpt("server")
+            .desc("set the Websocket server hostname, default: localhost").build();
+
+    /** A port option with "-p" and "--port". */
+    public static final Option PORT = Option.builder("p").hasArg().argName("PORT").longOpt("port")
+            .desc("set the Websocket server port, default: 8887").build();
+
+    /** A skip validation option with "-sv" and "--skip-validation". */
+    public static final Option SKIPVALIDATION = Option.builder("sv").longOpt("skip-validation")
+            .desc("switch of validation of the input file").required(false).type(boolean.class).build();
+}
diff --git a/tools/tools-common/src/main/java/org/onap/policy/apex/tools/common/CliParser.java b/tools/tools-common/src/main/java/org/onap/policy/apex/tools/common/CliParser.java
new file mode 100644 (file)
index 0000000..588abfc
--- /dev/null
@@ -0,0 +1,119 @@
+/*-
+ * ============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.tools.common;
+
+////
+//// NOTE: This file contains tags for ASCIIDOC
+//// DO NOT REMOVE any of those tag lines, e.g.
+////// tag::**
+////// end::**
+////
+
+import java.util.Scanner;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.CommandLineParser;
+import org.apache.commons.cli.DefaultParser;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
+
+/**
+ * Application CLI parser.
+ *
+ * @author Sven van der Meer (sven.van.der.meer@ericsson.com)
+ */
+public class CliParser {
+
+    /** The local set of CLI options. */
+    private final Options options;
+
+    /** The command line, null on start, not null after successful parse. */
+    private CommandLine cmd;
+
+    /**
+     * Creates a new CLI parser.
+     */
+    public CliParser() {
+        options = new Options();
+    }
+
+    /**
+     * Adds an option to the parser.
+     *
+     * @param option the new option, must not be null
+     * @return self to allow chaining
+     */
+    public CliParser addOption(final Option option) {
+        if (option == null) {
+            throw new IllegalStateException("CLI parser: given option was null");
+        }
+        options.addOption(option);
+        return this;
+    }
+
+    /**
+     * Parses the arguments with the set options.
+     *
+     * @param args the arguments to parse
+     * @return a command line with parsed arguments, null on parse errors.
+     */
+    public CommandLine parseCli(final String[] args) {
+        final CommandLineParser parser = new DefaultParser();
+        try {
+            cmd = parser.parse(options, args);
+        } catch (final ParseException ex) {
+            System.err.println("Parsing failed.  Reason: " + ex.getMessage());
+            ex.printStackTrace();
+        }
+        return cmd;
+    }
+
+    /**
+     * Returns the parsed command line.
+     *
+     * @return the parsed command line, null if nothing parsed
+     */
+    public CommandLine getCommandLine() {
+        return cmd;
+    }
+
+    /**
+     * Returns the CLI options.
+     *
+     * @return CLI options
+     */
+    public Options getOptions() {
+        return options;
+    }
+
+    /**
+     * Returns the version for an application as set by Maven.
+     *
+     * @return version, null if version file <code>/app-version.txt</code> was not found
+     */
+    @SuppressWarnings("resource")
+    // tag::cliParserVersion[]
+    public String getAppVersion() {
+        return new Scanner(CliParser.class.getResourceAsStream("/app-version.txt"), "UTF-8").useDelimiter("\\A").next();
+    }
+    // end::cliParserVersion[]
+}
diff --git a/tools/tools-common/src/main/java/org/onap/policy/apex/tools/common/Console.java b/tools/tools-common/src/main/java/org/onap/policy/apex/tools/common/Console.java
new file mode 100644 (file)
index 0000000..5713331
--- /dev/null
@@ -0,0 +1,352 @@
+/*-
+ * ============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.tools.common;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.text.StrBuilder;
+import org.slf4j.helpers.MessageFormatter;
+
+/**
+ * A console for printing messages with functionality similar to loggers. The class provides a static instance for all
+ * parts of an application. The default configuration is to not collect errors or warnings. The default types being
+ * activated are errors, warnings, and info messages.
+ *
+ * @author Sven van der Meer (sven.van.der.meer@ericsson.com)
+ */
+public final class Console {
+
+    /** The console as static object. */
+    public static final Console CONSOLE = new Console();
+
+    /** Type for a quiet console, no messages being printed. */
+    public static final int TYPE_QUIET = 0;
+
+    /** Type for printing error messages. */
+    public static final int TYPE_ERROR = 0b0001;
+
+    /** Type for printing warning messages. */
+    public static final int TYPE_WARNING = 0b0010;
+
+    /** Type for printing information messages. */
+    public static final int TYPE_INFO = 0b0100;
+
+    /** Type for printing progress messages. */
+    public static final int TYPE_PROGRESS = 0b1000;
+
+    /** Type for printing debug messages. */
+    public static final int TYPE_DEBUG = 0b001_0000;
+
+    /** Type for printing trace messages. */
+    public static final int TYPE_TRACE = 0b010_0000;
+
+    /** Type for printing stack traces of caught exceptions. */
+    public static final int TYPE_STACKTRACE = 0b110_0000;
+
+    /** Type for a verbose console, activating all message types. */
+    public static final int TYPE_VERBOSE = 0b111_1111;
+
+    /** Configuration for a collecting error messages. */
+    public static final int CONFIG_COLLECT_ERRORS = 0b0001;
+
+    /** Configuration for a collecting warning messages. */
+    public static final int CONFIG_COLLECT_WARNINGS = 0b0010;
+
+    /** The setting for message types, set using type flags. */
+    private int types;
+
+    /** The console configuration, set using configuration flags. */
+    private int configuration;
+
+    /** A name for the application, if set used as prefix for messages. */
+    private String appName;
+
+    /** The list of errors, filled if error collection is activates. */
+    private final List<String> errors;
+
+    /** The list of warnings, filled if warning collection is activates. */
+    private final List<String> warnings;
+
+    /**
+     * Creates a new console. The constructor is private since the class provides static access to an instance. The
+     * default for types is verbose.
+     */
+    private Console() {
+        types = TYPE_VERBOSE;
+
+        configuration = 0;
+        errors = new ArrayList<>();
+        warnings = new ArrayList<>();
+    }
+
+    /**
+     * Sets the application name.
+     *
+     * @param appName new application name, use <code>null</code> to reset the application name, a non-blank string for
+     *        a new name, blank strings are ignored
+     */
+    public void setAppName(final String appName) {
+        if (appName == null) {
+            this.appName = null;
+        } else if (!StringUtils.isBlank(appName)) {
+            this.appName = appName;
+        }
+    }
+
+    /**
+     * Returns the application name.
+     *
+     * @return application name, null if not set, non-blank string otherwise
+     */
+    public String getAppName() {
+        return appName;
+    }
+
+    /**
+     * Activates a type.
+     *
+     * @param type the type to activate
+     */
+    public void activate(final int type) {
+        types = types | type;
+    }
+
+    /**
+     * Deactivates a type.
+     *
+     * @param type type to deactivate
+     */
+    public void deActivate(final int type) {
+        types = types & ~type;
+    }
+
+    /**
+     * Sets the type to the given type, effectively deactivating all other types.
+     *
+     * @param type new type
+     */
+    public void set(final int type) {
+        types = type;
+    }
+
+    /**
+     * Configures the console. Use the configuration flags in combination for the required configuration. For instance,
+     * to collect errors and warnings use <code>CONFIG_COLLECT_ERRORS | CONFIG_COLLECT_WARNINGS</code>.
+     *
+     * @param config the new configuration, overwrites the current configuration, 0 deactivates all settings
+     */
+    public void configure(final int config) {
+        this.configuration = config;
+    }
+
+    /**
+     * Sets the type to the given types, effectively deactivating all other types.
+     *
+     * @param ts array of types to set
+     */
+    public void set(final int... ts) {
+        this.types = 0;
+        for (final int type : ts) {
+            this.activate(type);
+        }
+    }
+
+    /**
+     * Prints an error message with message and objects if {@link #TYPE_ERROR} is set; and increases the error count.
+     * Errors are collected (if configuration is set) and the error counter is increased regardless of the console error
+     * type settings.
+     *
+     * @param message the error message, using the same format as the SLF4J MessageFormatter, nothing done if
+     *        <code>blank</code>
+     * @param objects the objects for substitution in the message
+     */
+    public void error(final String message, final Object... objects) {
+        if (StringUtils.isBlank(message)) {
+            return;
+        }
+
+        final StrBuilder err = new StrBuilder();
+        if (appName != null) {
+            err.append(this.getAppName()).append(": ");
+        }
+        err.append("error: ");
+        err.append(MessageFormatter.arrayFormat(message, objects).getMessage());
+
+        if ((types & TYPE_ERROR) == TYPE_ERROR) {
+            System.err.println(err.build());
+        }
+        if ((configuration & CONFIG_COLLECT_ERRORS) == CONFIG_COLLECT_ERRORS) {
+            errors.add(err.build());
+        }
+    }
+
+    /**
+     * Prints a warning message with message and objects if {@link #TYPE_WARNING} is set; and increases the warning
+     * count. Warnings are collected (if configuration is set) and the warning counter is increased regardless of the
+     * console warning type settings.
+     *
+     * @param message the warning message, using the same format as the SLF4J MessageFormatter, nothing done if
+     *        <code>blank</code>
+     * @param objects the objects for substitution in the message
+     */
+    public void warn(final String message, final Object... objects) {
+        if (StringUtils.isBlank(message)) {
+            return;
+        }
+
+        final StrBuilder warn = new StrBuilder();
+        if (appName != null) {
+            warn.append(this.getAppName()).append(": ");
+        }
+        warn.append("warning: ");
+        warn.append(MessageFormatter.arrayFormat(message, objects).getMessage());
+
+        if ((types & TYPE_WARNING) == TYPE_WARNING) {
+            System.err.println(warn.build());
+        }
+        if ((configuration & CONFIG_COLLECT_WARNINGS) == CONFIG_COLLECT_WARNINGS) {
+            warnings.add(warn.build());
+        }
+    }
+
+    /**
+     * Prints an info message with message and objects if {@link #TYPE_INFO} is set.
+     *
+     * @param message the warning message, using the same format as the SLF4J MessageFormatter, nothing done if
+     *        <code>blank</code>
+     * @param objects the objects for substitution in the message
+     */
+    public void info(final String message, final Object... objects) {
+        if (StringUtils.isBlank(message)) {
+            return;
+        }
+
+        if ((types & TYPE_INFO) == TYPE_INFO) {
+            if (appName != null) {
+                System.err.print(appName + ": ");
+            }
+            System.err.println(MessageFormatter.arrayFormat(message, objects).getMessage());
+        }
+    }
+
+    /**
+     * Prints a progress message with message and objects if {@link #TYPE_PROGRESS} is set.
+     *
+     * @param message the warning message, using the same format as the SLF4J MessageFormatter, nothing done if
+     *        <code>blank</code>
+     * @param objects the objects for substitution in the message
+     */
+    public void progress(final String message, final Object... objects) {
+        if (StringUtils.isBlank(message)) {
+            return;
+        }
+
+        if ((types & TYPE_PROGRESS) == TYPE_PROGRESS) {
+            if (appName != null) {
+                System.err.print(appName + ": ");
+            }
+            System.err.print("progress: ");
+            System.err.println(MessageFormatter.arrayFormat(message, objects).getMessage());
+        }
+    }
+
+    /**
+     * Prints a debug message with message and objects if {@link #TYPE_DEBUG} is set.
+     *
+     * @param message the warning message, using the same format as the SLF4J MessageFormatter, nothing done if
+     *        <code>blank</code>
+     * @param objects the objects for substitution in the message
+     */
+    public void debug(final String message, final Object... objects) {
+        if (StringUtils.isBlank(message)) {
+            return;
+        }
+
+        if ((types & TYPE_DEBUG) == TYPE_DEBUG) {
+            if (appName != null) {
+                System.err.print(appName + ": ");
+            }
+            System.err.print("debug: ");
+            System.err.println(MessageFormatter.arrayFormat(message, objects).getMessage());
+        }
+    }
+
+    /**
+     * Prints a trace message with message and objects if {@link #TYPE_TRACE} is set.
+     *
+     * @param message the warning message, using the same format as the SLF4J MessageFormatter, nothing done if
+     *        <code>blank</code>
+     * @param objects the objects for substitution in the message
+     */
+    public void trace(final String message, final Object... objects) {
+        if (StringUtils.isBlank(message)) {
+            return;
+        }
+
+        if ((types & TYPE_TRACE) == TYPE_TRACE) {
+            if (appName != null) {
+                System.err.print(appName + ": ");
+            }
+            System.err.print("trace: ");
+            System.err.println(MessageFormatter.arrayFormat(message, objects).getMessage());
+        }
+    }
+
+    /**
+     * Prints message, cause, and stack trace for a given exception if {@link #TYPE_STACKTRACE} is set.
+     *
+     * @param exception the exception to print, ignored if <code>null</code>
+     */
+    public void stacktrace(final Exception exception) {
+        if (exception == null) {
+            return;
+        }
+
+        if ((types & TYPE_STACKTRACE) == TYPE_STACKTRACE) {
+            if (appName != null) {
+                System.err.print(appName + ": ");
+            }
+            System.err.println("exception stack trace: ");
+            System.err.println(" - message: " + exception.getMessage());
+            if (exception.getCause() != null) {
+                System.err.println(" - cause: " + exception.getCause());
+            }
+            exception.printStackTrace();
+        }
+    }
+
+    /**
+     * Resets the error counter and the list of errors.
+     */
+    public void resetErrors() {
+        errors.clear();
+    }
+
+    /**
+     * Resets the warning counter and the list of warnings.
+     */
+    public void resetWarnings() {
+        warnings.clear();
+    }
+
+}
diff --git a/tools/tools-common/src/main/java/org/onap/policy/apex/tools/common/OutputFile.java b/tools/tools-common/src/main/java/org/onap/policy/apex/tools/common/OutputFile.java
new file mode 100644 (file)
index 0000000..b529a7e
--- /dev/null
@@ -0,0 +1,136 @@
+/*-
+ * ============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.tools.common;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.Writer;
+import java.nio.file.FileSystems;
+import java.nio.file.Path;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.Validate;
+
+/**
+ * Standard output file handling and tests.
+ *
+ * @author Sven van der Meer (sven.van.der.meer@ericsson.com)
+ */
+public class OutputFile {
+
+    /** The output file name. */
+    private final String fileName;
+
+    /** The output file name. */
+    private final boolean overwrite;
+
+    /**
+     * Creates a new object for a given file name.
+     *
+     * @param fileName the file name
+     */
+    public OutputFile(final String fileName) {
+        this(fileName, false);
+    }
+
+    /**
+     * Creates a new object for a given file name.
+     *
+     * @param fileName the file name
+     * @param overwrite if the file already exists, can it be overwritten, or should an error be raised
+     */
+    public OutputFile(final String fileName, final boolean overwrite) {
+        Validate.notBlank(fileName);
+        this.fileName = fileName;
+        this.overwrite = overwrite;
+    }
+
+    /**
+     * Get a File object for this output file.
+     *
+     * @return a File object for this output file
+     */
+    public File toFile() {
+        final Path fp = FileSystems.getDefault().getPath(fileName);
+        return fp.toFile();
+    }
+
+    /**
+     * Get a Writer object for this output file.
+     *
+     * @return a Writer object for this output file
+     */
+    public Writer toWriter() {
+        try {
+            return new BufferedWriter(new FileWriter(toFile()));
+        } catch (final IOException e) {
+            return null;
+        }
+    }
+
+    /**
+     * Get a OutputStream object for this output file.
+     *
+     * @return an OutputStream object for this output file
+     */
+    public OutputStream toOutputStream() {
+        try {
+            return new FileOutputStream(toFile());
+        } catch (final IOException e) {
+            return null;
+        }
+    }
+
+    /**
+     * Validates the output file. Validation tests for file name being blank, file existing, creation, and finally
+     * can-write.
+     *
+     * @return null on success, an error message on error
+     */
+    public String validate() {
+        if (StringUtils.isBlank(fileName)) {
+            return "file name was blank";
+        }
+
+        final File file = toFile();
+        if (file.exists()) {
+            if (!overwrite) {
+                return "file already exists";
+            }
+        } else {
+            try {
+                file.createNewFile();
+            } catch (final IOException e) {
+                return "could not create output file: " + e.getMessage();
+            }
+        }
+
+        if (!file.canWrite()) {
+            return "cannot write to file";
+        }
+
+        return null;
+    }
+}
diff --git a/tools/tools-common/src/main/java/org/onap/policy/apex/tools/common/package-info.java b/tools/tools-common/src/main/java/org/onap/policy/apex/tools/common/package-info.java
new file mode 100644 (file)
index 0000000..e193aac
--- /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=========================================================
+ */
+
+/**
+ * Utilities for APEX related applications, such as CLI parser and application console.
+ *
+ * @author Sven van der Meer (sven.van.der.meer@ericsson.com)
+ */
+
+package org.onap.policy.apex.tools.common;
diff --git a/tools/tools-common/src/main/resources/app-version.txt b/tools/tools-common/src/main/resources/app-version.txt
new file mode 100644 (file)
index 0000000..f2ab45c
--- /dev/null
@@ -0,0 +1 @@
+${project.version}
\ No newline at end of file
diff --git a/tools/tools-common/src/test/java/org/onap/policy/apex/tools/common/TestCliParser.java b/tools/tools-common/src/test/java/org/onap/policy/apex/tools/common/TestCliParser.java
new file mode 100644 (file)
index 0000000..bf14cfe
--- /dev/null
@@ -0,0 +1,43 @@
+/*-
+ * ============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.tools.common;
+
+import org.junit.Test;
+import org.onap.policy.apex.tools.common.CliParser;
+import org.slf4j.ext.XLogger;
+import org.slf4j.ext.XLoggerFactory;
+
+/**
+ * Tests for {@link CliParser}.
+ *
+ * @author Sven van der Meer (sven.van.der.meer@ericsson.com)
+ */
+public class TestCliParser {
+
+    private static final XLogger LOGGER = XLoggerFactory.getXLogger(TestCliParser.class);
+
+    /** Testapp version. */
+    @Test
+    public void testappVersion() {
+        final CliParser cli = new CliParser();
+        LOGGER.info(cli.getAppVersion());
+    }
+}
diff --git a/tools/tools-common/src/test/java/org/onap/policy/apex/tools/common/docs/ExampleAppVersion.java b/tools/tools-common/src/test/java/org/onap/policy/apex/tools/common/docs/ExampleAppVersion.java
new file mode 100644 (file)
index 0000000..6d6fa9c
--- /dev/null
@@ -0,0 +1,65 @@
+/*-
+ * ============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.tools.common.docs;
+
+////
+//// NOTE: This file contains tags for ASCIIDOC
+//// DO NOT REMOVE any of those tag lines, e.g.
+////// tag::**
+////// end::**
+////
+
+import org.apache.commons.cli.CommandLine;
+import org.junit.Test;
+import org.onap.policy.apex.tools.common.CliOptions;
+import org.onap.policy.apex.tools.common.CliParser;
+import org.slf4j.ext.XLogger;
+import org.slf4j.ext.XLoggerFactory;
+
+/**
+ * Examples for documentation using {@link CliParser#getAppVersion()}.
+ *
+ * @author Sven van der Meer (sven.van.der.meer@ericsson.com)
+ */
+public class ExampleAppVersion {
+
+    private static final XLogger LOGGER = XLoggerFactory.getXLogger(ExampleAppVersion.class);
+
+    /** Test example app version. */
+    @Test
+    public void testExampleAppVersion() {
+        final String[] args = new String[] { "-v" };
+
+        // tag::setupParser[]
+        final CliParser cli = new CliParser();
+        cli.addOption(CliOptions.VERSION);
+        final CommandLine cmd = cli.parseCli(args);
+        // end::setupParser[]
+
+        // tag::processCliVersion[]
+        // version is an exit option, print version and exit
+        if (cmd.hasOption('v') || cmd.hasOption("version")) {
+            LOGGER.info("myApp" + " " + cli.getAppVersion());
+            return;
+        }
+        // end::processCliVersion[]
+    }
+}
diff --git a/tools/tools-common/src/test/java/org/onap/policy/apex/tools/common/docs/ExampleCliParser.java b/tools/tools-common/src/test/java/org/onap/policy/apex/tools/common/docs/ExampleCliParser.java
new file mode 100644 (file)
index 0000000..487bed2
--- /dev/null
@@ -0,0 +1,116 @@
+/*-
+ * ============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.tools.common.docs;
+
+////
+//// NOTE: This file contains tags for ASCIIDOC
+//// DO NOT REMOVE any of those tag lines, e.g.
+//// //tag::**
+//// //end::**
+////
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.HelpFormatter;
+import org.junit.Test;
+import org.onap.policy.apex.tools.common.CliOptions;
+import org.onap.policy.apex.tools.common.CliParser;
+import org.slf4j.ext.XLogger;
+import org.slf4j.ext.XLoggerFactory;
+
+/**
+ * Examples for documentation using {@link CliParser}.
+ *
+ * @author Sven van der Meer (sven.van.der.meer@ericsson.com)
+ */
+public class ExampleCliParser {
+
+    private static final XLogger LOGGER = XLoggerFactory.getXLogger(ExampleCliParser.class);
+
+    /**
+     * Test example parser.
+     */
+    @Test
+    public void testExampleParser() {
+        final String[] args = new String[] { "-h" };
+
+        // tag::setApp[]
+        final String appName = "test-app";
+        final String appDescription = "a test app for documenting how to use the CLI utilities";
+        // end::setApp[]
+
+        // tag::setCli[]
+        final CliParser cli = new CliParser();
+        cli.addOption(CliOptions.HELP);
+        cli.addOption(CliOptions.VERSION);
+        cli.addOption(CliOptions.MODELFILE);
+        // end::setCli[]
+
+        // tag::parseCli[]
+        final CommandLine cmd = cli.parseCli(args);
+        // end::parseCli[]
+
+        // tag::processCliHelp[]
+        // help is an exit option, print usage and exit
+        if (cmd.hasOption('h') || cmd.hasOption("help")) {
+            final HelpFormatter formatter = new HelpFormatter();
+            LOGGER.info(appName + " v" + cli.getAppVersion() + " - " + appDescription);
+            formatter.printHelp(appName, cli.getOptions());
+            return;
+        }
+        // end::processCliHelp[]
+
+        // tag::processCliVersion[]
+        // version is an exit option, print version and exit
+        if (cmd.hasOption('v') || cmd.hasOption("version")) {
+            LOGGER.info(appName + " " + cli.getAppVersion());
+            return;
+        }
+        // end::processCliVersion[]
+
+        // tag::processCliModel[]
+        String modelFile = cmd.getOptionValue('m');
+        if (modelFile == null) {
+            modelFile = cmd.getOptionValue("model");
+        }
+        if (modelFile == null) {
+            LOGGER.error(appName + ": no model file given, cannot proceed (try -h for help)");
+            return;
+        }
+        // end::processCliModel[]
+
+        // tag::someStartPrint[]
+        LOGGER.info(appName + ": starting");
+        LOGGER.info(" --> model file: " + modelFile);
+        // end::someStartPrint[]
+
+        // tag::yourApp[]
+        // your code for the application here
+        // e.g.
+        // try {
+        // Model2Cli app = new Model2Cli(modelFile, !cmd.hasOption("sv"), appName);
+        // app.runApp();
+        // }
+        // catch(ApexException aex) {
+        // LOGGER.error(appName + ": caught APEX exception with message: " + aex.getMessage());
+        // }
+        // end::yourApp[]
+    }
+}