[ONOS-7063]Validation of modelId for valid syntax

Change-Id: Ic2e991b3e9abcaab97985882a8292fa48bd43827
diff --git a/compiler/base/utils/src/main/java/org/onosproject/yang/compiler/utils/UtilConstants.java b/compiler/base/utils/src/main/java/org/onosproject/yang/compiler/utils/UtilConstants.java
index b165204..811c8b6 100644
--- a/compiler/base/utils/src/main/java/org/onosproject/yang/compiler/utils/UtilConstants.java
+++ b/compiler/base/utils/src/main/java/org/onosproject/yang/compiler/utils/UtilConstants.java
@@ -1964,6 +1964,9 @@
     public static final String IDENTITY = "_identity";
     public static final String TYPEDEF = "_typedef";
 
+    // Regex for model id validation
+    public static final String REGEX = "[A-Za-z0-9_\\-.@]+";
+
     // No instantiation.
     private UtilConstants() {
     }
diff --git a/compiler/plugin/buck/pom.xml b/compiler/plugin/buck/pom.xml
index 3613f71..de898e2 100644
--- a/compiler/plugin/buck/pom.xml
+++ b/compiler/plugin/buck/pom.xml
@@ -34,6 +34,11 @@
             <version>0.1-SNAPSHOT</version>
             <scope>provided</scope>
         </dependency>
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-yang-compiler-plugin-utils</artifactId>
+            <version>2.3-SNAPSHOT</version>
+        </dependency>
     </dependencies>
 
     <build>
diff --git a/compiler/plugin/buck/src/main/java/org/onosproject/yang/compiler/plugin/buck/YangLibraryDescription.java b/compiler/plugin/buck/src/main/java/org/onosproject/yang/compiler/plugin/buck/YangLibraryDescription.java
index 3a92ced..a048694 100644
--- a/compiler/plugin/buck/src/main/java/org/onosproject/yang/compiler/plugin/buck/YangLibraryDescription.java
+++ b/compiler/plugin/buck/src/main/java/org/onosproject/yang/compiler/plugin/buck/YangLibraryDescription.java
@@ -56,6 +56,8 @@
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 
+import static org.onosproject.yang.compiler.plugin.utils.PluginUtils.getValidModelId;
+
 /**
  * Description of a Buck Yang Library.
  */
@@ -100,7 +102,8 @@
 
         BuildRule yangLib = resolver.getRuleOptional(yangParams.getBuildTarget())
                 .or(() -> resolver.addToIndex(new YangLibrary(
-                        yangParams, pathResolver, args.srcs, args.modelId.get())));
+                        yangParams, pathResolver, args.srcs,
+                        getValidModelId(args.modelId.get()))));
 
         if (params.getBuildTarget().getFlavors().contains(SOURCES)) {
             return yangLib;
@@ -183,5 +186,4 @@
 
         //TODO other params here
     }
-
 }
diff --git a/compiler/plugin/maven/pom.xml b/compiler/plugin/maven/pom.xml
index 98fc106..a85cbde 100644
--- a/compiler/plugin/maven/pom.xml
+++ b/compiler/plugin/maven/pom.xml
@@ -84,6 +84,11 @@
             <version>4.12</version>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-yang-compiler-plugin-utils</artifactId>
+            <version>2.3-SNAPSHOT</version>
+        </dependency>
     </dependencies>
 
     <build>
diff --git a/compiler/plugin/maven/src/main/java/org/onosproject/yang/compiler/plugin/maven/YangUtilManager.java b/compiler/plugin/maven/src/main/java/org/onosproject/yang/compiler/plugin/maven/YangUtilManager.java
index cb0c828..42e24c8 100644
--- a/compiler/plugin/maven/src/main/java/org/onosproject/yang/compiler/plugin/maven/YangUtilManager.java
+++ b/compiler/plugin/maven/src/main/java/org/onosproject/yang/compiler/plugin/maven/YangUtilManager.java
@@ -42,6 +42,7 @@
 import static org.onosproject.yang.compiler.plugin.maven.YangPluginUtils.addToCompilationRoot;
 import static org.onosproject.yang.compiler.plugin.maven.YangPluginUtils.addToProjectResource;
 import static org.onosproject.yang.compiler.plugin.maven.YangPluginUtils.resolveInterJarDependencies;
+import static org.onosproject.yang.compiler.plugin.utils.PluginUtils.getValidModelId;
 import static org.onosproject.yang.compiler.utils.UtilConstants.DEFAULT_BASE_PKG;
 import static org.onosproject.yang.compiler.utils.UtilConstants.DEFAULT_JAR_RES_PATH;
 import static org.onosproject.yang.compiler.utils.UtilConstants.EMPTY_STRING;
@@ -183,7 +184,7 @@
             }
 
             if (modelId != null) {
-                bldr.setModelId(modelId);
+                bldr.setModelId(getValidModelId(modelId));
             } else {
                 bldr.setModelId(project.getArtifactId());
             }
diff --git a/compiler/plugin/pom.xml b/compiler/plugin/pom.xml
index 045f5b6..2f49fb0 100644
--- a/compiler/plugin/pom.xml
+++ b/compiler/plugin/pom.xml
@@ -34,6 +34,7 @@
     <modules>
         <module>maven</module>
         <module>buck</module>
+        <module>utils</module>
     </modules>
 
     <dependencies>
diff --git a/compiler/plugin/utils/pom.xml b/compiler/plugin/utils/pom.xml
new file mode 100644
index 0000000..6d30023
--- /dev/null
+++ b/compiler/plugin/utils/pom.xml
@@ -0,0 +1,36 @@
+<!--
+  ~ Copyright 2016-present Open Networking Foundation
+  ~
+  ~ 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.
+  -->
+<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>
+    <dependencies>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>4.12</version>
+        </dependency>
+    </dependencies>
+
+    <parent>
+        <groupId>org.onosproject</groupId>
+        <artifactId>onos-yang-compiler-plugin</artifactId>
+        <version>2.3-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>onos-yang-compiler-plugin-utils</artifactId>
+    <packaging>bundle</packaging>
+</project>
diff --git a/compiler/plugin/utils/src/main/java/org/onosproject/yang/compiler/plugin/utils/PluginUtils.java b/compiler/plugin/utils/src/main/java/org/onosproject/yang/compiler/plugin/utils/PluginUtils.java
new file mode 100644
index 0000000..b806b84
--- /dev/null
+++ b/compiler/plugin/utils/src/main/java/org/onosproject/yang/compiler/plugin/utils/PluginUtils.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.
+ */
+
+package org.onosproject.yang.compiler.plugin.utils;
+
+/**
+ * Representation of model id validation util.
+ */
+public final class PluginUtils {
+
+    // Forbid construction.
+    private PluginUtils() {
+    }
+
+    /**
+     * Returns the valid model id by removing the special character with
+     * underscore.
+     *
+     * @param id user given model id
+     * @return model id
+     * @throws IllegalArgumentException if user defined model id does not
+     *                                  contain at least a alphanumeric character
+     */
+    public static String getValidModelId(String id) throws
+            IllegalArgumentException {
+        // checking weather modelId contains the alphanumeric character or not.
+        if (id.matches(".*[A-Za-z0-9].*")) {
+            // replacing special characters with '_'
+            id = id.replaceAll("[\\s\\/:*?\"\\[\\]<>|$@!#%&(){}';,]", "_");
+            // remove leading and trailing underscore
+            id = id.replaceAll("^_+|_+$", "");
+            // replacing the consecutive underscores '_' to single _
+            id = id.replaceAll("_+", "_");
+            return id;
+        } else {
+            throw new IllegalArgumentException("Invalid model id " + id);
+        }
+    }
+}
diff --git a/compiler/plugin/utils/src/main/java/org/onosproject/yang/compiler/plugin/utils/package-info.java b/compiler/plugin/utils/src/main/java/org/onosproject/yang/compiler/plugin/utils/package-info.java
new file mode 100644
index 0000000..3ed076c
--- /dev/null
+++ b/compiler/plugin/utils/src/main/java/org/onosproject/yang/compiler/plugin/utils/package-info.java
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
+ * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
+ * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
+ * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
+ * Vestibulum commodo. Ut rhoncus gravida arcu.
+ */
+
+/**
+ * File system utilities.
+ */
+package org.onosproject.yang.compiler.plugin.utils;
diff --git a/compiler/plugin/utils/src/test/java/org/onosproject/yang/compiler/plugin/utils/ModelIdValidatorTest.java b/compiler/plugin/utils/src/test/java/org/onosproject/yang/compiler/plugin/utils/ModelIdValidatorTest.java
new file mode 100644
index 0000000..f3e3c60
--- /dev/null
+++ b/compiler/plugin/utils/src/test/java/org/onosproject/yang/compiler/plugin/utils/ModelIdValidatorTest.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
+ * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
+ * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
+ * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
+ * Vestibulum commodo. Ut rhoncus gravida arcu.
+ */
+
+package org.onosproject.yang.compiler.plugin.utils;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.onosproject.yang.compiler.plugin.utils.PluginUtils.getValidModelId;
+import static org.onosproject.yang.compiler.utils.UtilConstants.REGEX;
+
+public final class ModelIdValidatorTest {
+
+    private static final String E_INVAL = "ERROR: Model Id validation not " +
+            "working";
+    /*
+     * Reference for string values array to provide modelId value for
+     * different-different scenario.
+     */
+    String[] nA = {
+            "list Any data $doller @rate < arrow>end |or (copy)",
+            "onos-yang-runtime",
+            "Logistic.manager.1.",
+            "list Any data []{}",
+            "onos-yang     runtime      ",
+            "[]   xyz  []",
+            "onos_ yang_ runtime",
+            "onos_yang_runtime",
+            "org.onosproject.runtime"
+    };
+
+    private static final String[] EXPECTED = {
+            "list_Any_data_doller_rate_arrow_end_or_copy",
+            "onos-yang-runtime",
+            "Logistic.manager.1.",
+            "list_Any_data",
+            "onos-yang_runtime",
+            "xyz",
+            "onos_yang_runtime",
+            "onos_yang_runtime",
+            "org.onosproject.runtime"
+    };
+
+    /*
+     * Invalid values for testing the negative scenario for getValidModelId.
+     */
+    String[] invalidVal = {
+            ".",
+            "-",
+            "_"
+    };
+
+    /*
+     * Invalid values for testing the negative scenario for user given
+     * model id at the time of registration.
+     */
+    String[] invalidVal1 = {
+            "list Any data $doller @rate < arrow>end |or (copy)",
+            "list Any data []{}",
+            "onos-yang     runtime      ",
+            "[]   xyz  []",
+            "onos_ yang_ runtime",
+    };
+
+    /**
+     * Test positive scenario for getValidModelId functionality.
+     */
+    @Test
+    public void validateGetModelIdTest() {
+        for (int i = 0; i < EXPECTED.length; i++) {
+            assertEquals(EXPECTED[i], getValidModelId(nA[i]));
+        }
+    }
+
+    /**
+     * Test negative scenario for getValidModelId functionality.
+     */
+    @Test
+    public void validateNegativeScenarioGetModelIdTest() {
+        int i = 0;
+        for (; i < invalidVal.length; i++) {
+            try {
+                getValidModelId(invalidVal[i]);
+            } catch (IllegalArgumentException e) {
+                assertEquals(e.getMessage(), "Invalid model id " +
+                        invalidVal[i]);
+            }
+        }
+
+        if (i != invalidVal.length) {
+            throw new RuntimeException(E_INVAL);
+        }
+    }
+
+    /**
+     * Test positive scenario for user supplied model id functionality.
+     */
+    @Test
+    public void validateSuppliedModelIdTest() {
+        for (int i = 0; i < EXPECTED.length; i++) {
+            if (!EXPECTED[i].matches(REGEX)) {
+                throw new RuntimeException(E_INVAL);
+            }
+        }
+    }
+
+    /**
+     * Test negative scenario for user supplied model id functionality.
+     */
+    @Test
+    public void validateNegativeScenarioSuppliedModelIdTest() {
+        for (int i = 0; i < invalidVal1.length; i++) {
+            if (invalidVal1[i].matches(REGEX)) {
+                throw new RuntimeException(E_INVAL);
+            }
+        }
+    }
+}
diff --git a/compiler/plugin/utils/src/test/resources/CopyrightHeader.txt b/compiler/plugin/utils/src/test/resources/CopyrightHeader.txt
new file mode 100644
index 0000000..2cbed45
--- /dev/null
+++ b/compiler/plugin/utils/src/test/resources/CopyrightHeader.txt
@@ -0,0 +1,14 @@
+ *
+ * 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.
+ */
+
diff --git a/runtime/src/main/java/org/onosproject/yang/runtime/YangModelRegistry.java b/runtime/src/main/java/org/onosproject/yang/runtime/YangModelRegistry.java
index 6532634..ea15b12 100644
--- a/runtime/src/main/java/org/onosproject/yang/runtime/YangModelRegistry.java
+++ b/runtime/src/main/java/org/onosproject/yang/runtime/YangModelRegistry.java
@@ -33,7 +33,8 @@
      * @param param parameters having model to be registered with additional
      *              information provided by app
      * @throws IllegalArgumentException when requested model with provided
-     *                                  identifier is already registered
+     *                                  identifier is already registered or
+     *                                  not valid
      */
     void registerModel(ModelRegistrationParam param)
             throws IllegalArgumentException;
diff --git a/runtime/src/main/java/org/onosproject/yang/runtime/impl/DefaultYangModelRegistry.java b/runtime/src/main/java/org/onosproject/yang/runtime/impl/DefaultYangModelRegistry.java
index 097360b..b428030 100644
--- a/runtime/src/main/java/org/onosproject/yang/runtime/impl/DefaultYangModelRegistry.java
+++ b/runtime/src/main/java/org/onosproject/yang/runtime/impl/DefaultYangModelRegistry.java
@@ -49,6 +49,7 @@
 import static java.util.Collections.unmodifiableSet;
 import static org.onosproject.yang.compiler.datamodel.utils.DataModelUtils.getDateInStringFormat;
 import static org.onosproject.yang.compiler.datamodel.utils.DataModelUtils.getNodeIdFromSchemaId;
+import static org.onosproject.yang.compiler.utils.UtilConstants.REGEX;
 import static org.onosproject.yang.model.DataNode.Type.SINGLE_INSTANCE_NODE;
 import static org.onosproject.yang.runtime.RuntimeHelper.getInterfaceClassName;
 import static org.onosproject.yang.runtime.RuntimeHelper.getNodes;
@@ -67,6 +68,8 @@
     private static final String E_MEXIST =
             "Model with given modelId already exist";
     private static final String E_NULL = "Model must not be null";
+    private static final String E_NOT_VAL = "Model id is invalid";
+
     /*
      * Map for storing YANG schema nodes. Key will be the schema name of
      * module node defined in YANG file.
@@ -133,9 +136,15 @@
             }
         }
 
-        if (!modelIdStore.containsKey(model.getYangModelId())) {
+        // Validating the model Id
+        String id = model.getYangModelId();
+        if (!id.matches(REGEX)) {
+            throw new IllegalArgumentException(E_NOT_VAL);
+        }
+
+        if (!modelIdStore.containsKey(id)) {
             updateRegClassStore(param);
-            modelIdStore.put(model.getYangModelId(), model);
+            modelIdStore.put(id, model);
         } else if ((info != null) && (!registerClassStore
                 .containsKey(info.getModuleClass()))) {
             updateRegClassStore(param);