This is an automated email from the ASF dual-hosted git repository.

aradzinski pushed a commit to branch NLPCRAFT-356
in repository https://gitbox.apache.org/repos/asf/incubator-nlpcraft.git


The following commit(s) were added to refs/heads/NLPCRAFT-356 by this push:
     new b36f012  WIP on NLPCRAFT-356.
b36f012 is described below

commit b36f0120830235683490c05ad802938cbabf4bb0
Author: Aaron Radzinski <[email protected]>
AuthorDate: Sat Jul 3 12:04:43 2021 -0700

    WIP on NLPCRAFT-356.
---
 .../nlpcraft/model/tools/cmdline/NCCli.scala       | 81 ++++++++++++++--------
 .../model/tools/cmdline/NCCliCommands.scala        | 11 +--
 .../tools/cmdline/NCCliModelClassCompleter.java    | 23 +++---
 .../cmdline/NCCliModelClassCompleterTest.scala     | 48 +++++++++++++
 4 files changed, 120 insertions(+), 43 deletions(-)

diff --git 
a/nlpcraft/src/main/scala/org/apache/nlpcraft/model/tools/cmdline/NCCli.scala 
b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/tools/cmdline/NCCli.scala
index bcab344..c7bfb79 100644
--- 
a/nlpcraft/src/main/scala/org/apache/nlpcraft/model/tools/cmdline/NCCli.scala
+++ 
b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/tools/cmdline/NCCli.scala
@@ -178,7 +178,7 @@ object NCCli extends NCCliBase {
      */
     @throws[InvalidParameter]
     private def getIntParam(cmd: Command, args: Seq[Argument], id: String, 
dflt: Int): Int = {
-        getParamOpt(cmd, args, id) match {
+        getParamOpt(args, id) match {
             case Some(num) =>
                 try
                     Integer.parseInt(num)
@@ -200,7 +200,7 @@ object NCCli extends NCCliBase {
      */
     @throws[InvalidParameter]
     private def getDoubleParam(cmd: Command, args: Seq[Argument], id: String, 
dflt: Double): Double = {
-        getParamOpt(cmd, args, id) match {
+        getParamOpt(args, id) match {
             case Some(num) =>
                 try
                     java.lang.Double.parseDouble(num)
@@ -213,11 +213,10 @@ object NCCli extends NCCliBase {
     }
 
     /**
-     * @param cmd
      * @param args
      * @param id
      */
-    private def getParamOpt(cmd: Command, args: Seq[Argument], id: String): 
Option[String] =
+    private def getParamOpt(args: Seq[Argument], id: String): Option[String] =
         args.find(_.parameter.id == id).flatMap(_.value)
 
     /**
@@ -229,24 +228,45 @@ object NCCli extends NCCliBase {
         args.exists(_.parameter.id == id)
 
     /**
-     * @param cmd
      * @param args
      * @param id
      */
-    private def getParamOrNull(cmd: Command, args: Seq[Argument], id: String): 
String =
+    private def getParamOrNull(args: Seq[Argument], id: String): String =
         args.find(_.parameter.id == id) match {
             case Some(arg) => U.trimQuotes(arg.value.get)
             case None => null
         }
 
     /**
+     * @param args
+     * @param id
+     */
+    private def getParams(args: Seq[Argument], id: String): Seq[String] =
+        args.filter(_.parameter.id == id).map(arg => 
U.trimQuotes(arg.value.getOrElse("")))
+
+    /**
+     *
+     * @param args
+     * @return
+     */
+    private def getModelsParams(args: Seq[Argument]): String =
+        U.splitTrimFilter(getParams( args, "models").mkString(","), 
",").mkString(",")
+
+    /**
+     *
+     * @param args
+     * @return
+     */
+    private def getCpParams(args: Seq[Argument]): String =
+        U.splitTrimFilter(getParams( args, "cp").mkString(CP_SEP), 
CP_SEP).mkString(CP_SEP)
+
+    /**
      *
-     * @param cmd
      * @param args
      * @param id
      * @return
      */
-    private def getFlagParam(cmd: Command, args: Seq[Argument], id: String, 
dflt: Boolean): Boolean =
+    private def getFlagParam(args: Seq[Argument], id: String, dflt: Boolean): 
Boolean =
         args.find(_.parameter.id == id) match {
             case Some(_) => true
             case None => dflt
@@ -268,7 +288,7 @@ object NCCli extends NCCliBase {
      * @return
      */
     private def getCpParamOpt(cmd: Command, args: Seq[Argument]): String =
-        getParamOpt(cmd, args, "cp") match {
+        getParamOpt(args, "cp") match {
             case Some(path) => normalizeCp(U.trimQuotes(path))
             case None => null
         }
@@ -289,7 +309,7 @@ object NCCli extends NCCliBase {
             normPath
         }
 
-        getParamOpt(cmd, args, id) match {
+        getParamOpt(args, id) match {
             case Some(path) => makePath(path)
             case None => if (dflt == null) null else makePath(dflt)
         }
@@ -381,9 +401,9 @@ object NCCli extends NCCliBase {
     private [cmdline] def cmdStartServer(cmd: Command, args: Seq[Argument], 
repl: Boolean): Unit = {
         val cfgPath = getPathParam(cmd, args, "config")
         val igniteCfgPath = getPathParam(cmd, args, "igniteConfig")
-        val noWait = getFlagParam(cmd, args, "noWait", dflt = false)
+        val noWait = getFlagParam(args, "noWait", dflt = false)
         val timeoutMins = getIntParam(cmd, args, "timeoutMins", 2)
-        val jvmOpts = getParamOpt(cmd, args, "jvmopts") match {
+        val jvmOpts = getParamOpt(args, "jvmopts") match {
             case Some(opts) => U.splitTrimFilter(U.trimQuotes(opts), " ")
             case None => Seq("-ea", "-Xms2048m", "-XX:+UseG1GC")
         }
@@ -576,8 +596,8 @@ object NCCli extends NCCliBase {
 
         val cfgPath = getPathParam(cmd, args, "config")
         val addCp = getCpParam(cmd, args)
-        val mdls = getParamOrNull(cmd, args, "models")
-        val jvmOpts = getParamOpt(cmd, args, "jvmopts") match {
+        val mdls = getModelsParams(args)
+        val jvmOpts = getParamOpt(args, "jvmopts") match {
             case Some(opts) => U.splitTrimFilter(U.trimQuotes(opts), " ")
             case None => Seq("-ea", "-Xms1024m")
         }
@@ -593,7 +613,7 @@ object NCCli extends NCCliBase {
         if (cfgPath != null)
             jvmArgs += s"-DNLPCRAFT_PROBE_CONFIG=$cfgPath"
 
-        if (mdls != null)
+        if (mdls.nonEmpty)
             jvmArgs += s"-DNLPCRAFT_TEST_MODELS=$mdls"
 
         if (!NCAnsi.isEnabled)
@@ -684,11 +704,11 @@ object NCCli extends NCCliBase {
         }
 
         val cfgPath = getPathParam(cmd, args, "config")
-        val noWait = getFlagParam(cmd, args, "noWait", dflt = false)
+        val noWait = getFlagParam(args, "noWait", dflt = false)
         val addCp = getCpParam(cmd, args)
         val timeoutMins = getIntParam(cmd, args, "timeoutMins", 1)
-        val mdls = getParamOrNull(cmd, args, "models")
-        val jvmOpts = getParamOpt(cmd, args, "jvmopts") match {
+        val mdls = getModelsParams(args)
+        val jvmOpts = getParamOpt(args, "jvmopts") match {
             case Some(opts) => U.splitTrimFilter(U.trimQuotes(opts), " ")
             case None => Seq("-ea", "-Xms1024m")
         }
@@ -711,7 +731,7 @@ object NCCli extends NCCliBase {
 
         prbArgs += "-DNLPCRAFT_ANSI_COLOR_DISABLED=true" // No ANSI colors for 
text log output to the file.
 
-        if (mdls != null)
+        if (mdls.nonEmpty)
             prbArgs += "-Dconfig.override_with_env_vars=true"
 
         prbArgs += "-cp"
@@ -724,7 +744,8 @@ object NCCli extends NCCliBase {
 
         val prbPb = new ProcessBuilder(prbArgs.asJava)
 
-        if (mdls != null)
+        if (mdls.nonEmpty)
+            // Combine multiple '--mdls' parameter into one comma-separate 
string.
             prbPb.environment().put("CONFIG_FORCE_nlpcraft_probe_models", mdls)
 
         prbPb.directory(new File(USR_WORK_DIR))
@@ -746,7 +767,7 @@ object NCCli extends NCCliBase {
             logln(s"  ${y("|--")} Log: ${c(output.getAbsolutePath)}")
             logln(s"  ${y("|--")} Probe config: ${if (cfgPath == null) 
y("<default>") else c(cfgPath)}")
 
-            if (mdls != null)
+            if (mdls.nonEmpty)
                 logln(s"  ${y("|--")} Environment variables: \n        
${c("CONFIG_FORCE_nlpcraft_probe_models=")}${c(mdls)}")
 
             logln(s"  ${y("+--")} Command: \n        ${c(prbArgs.mkString("\n  
      "))}")
@@ -1680,7 +1701,7 @@ object NCCli extends NCCliBase {
         }
 
         val addCp = getCpParamOpt(cmd, args)
-        val jvmOpts = getParamOpt(cmd, args, "jvmopts") match {
+        val jvmOpts = getParamOpt(args, "jvmopts") match {
             case Some(opts) => U.splitTrimFilter(U.trimQuotes(opts), " ")
             case None => Seq("-ea", "-Xms1024m")
         }
@@ -1738,7 +1759,7 @@ object NCCli extends NCCliBase {
     private [cmdline] def cmdSugSyn(cmd: Command, args: Seq[Argument], repl: 
Boolean): Unit =
         state.accessToken match {
             case Some(acsTok) =>
-                val mdlId = getParamOpt(cmd, args, "mdlId") match {
+                val mdlId = getParamOpt(args, "mdlId") match {
                     case Some(id) => id
                     case None =>
                         if (state.probes.size == 1 && 
state.probes.head.models.length == 1)
@@ -1772,7 +1793,7 @@ object NCCli extends NCCliBase {
     private [cmdline] def cmdAsk(cmd: Command, args: Seq[Argument], repl: 
Boolean): Unit =
         state.accessToken match {
             case Some(acsTok) =>
-                val mdlId = getParamOpt(cmd, args, "mdlId") match {
+                val mdlId = getParamOpt(args, "mdlId") match {
                     case Some(id) => id
                     case None =>
                         if (state.probes.size == 1 && 
state.probes.head.models.length == 1)
@@ -1781,8 +1802,8 @@ object NCCli extends NCCliBase {
                             throw MissingOptionalParameter(cmd, "mdlId")
                 }
                 val txt = getParam(cmd, args, "txt")
-                val data = getParamOrNull(cmd, args, "data")
-                val enableLog = getFlagParam(cmd, args, "enableLog", dflt = 
false)
+                val data = getParamOrNull(args, "data")
+                val enableLog = getFlagParam(args, "enableLog", dflt = false)
 
                 httpRest(
                     cmd,
@@ -2002,7 +2023,7 @@ object NCCli extends NCCliBase {
       */
     private [cmdline] def cmdGenModel(cmd: Command, args: Seq[Argument], repl: 
Boolean): Unit = {
         val filePath = replacePathTilda(getParam(cmd, args, "filePath"))
-        val overrideFlag = getFlagParam(cmd, args, "override", dflt = false)
+        val overrideFlag = getFlagParam(args, "override", dflt = false)
         val mdlId = getParam(cmd, args, "modelId")
 
         val out = new File(filePath)
@@ -2055,7 +2076,7 @@ object NCCli extends NCCliBase {
         val buildTool = getParam(cmd, args, "buildTool", "mvn").toLowerCase
         val pkgName = getParam(cmd, args, "packageName", 
"org.apache.nlpcraft.demo").toLowerCase
         val fileType = getParam(cmd, args, "modelType", "yaml").toLowerCase
-        val overrideFlag = getFlagParam(cmd, args, "override", dflt = false)
+        val overrideFlag = getFlagParam(args, "override", dflt = false)
 
         val dst = new File(outputDir, baseName)
         val pkgDir = pkgName.replaceAll("\\.", "/")
@@ -2747,8 +2768,8 @@ object NCCli extends NCCliBase {
      * @param repl Whether or not executing from REPL.
      */
     private [cmdline] def cmdVersion(cmd: Command, args: Seq[Argument], repl: 
Boolean): Unit = {
-        val isS = getFlagParam(cmd, args, "semver", dflt = false)
-        val isD = getFlagParam(cmd, args, "reldate", dflt = false)
+        val isS = getFlagParam(args, "semver", dflt = false)
+        val isD = getFlagParam(args, "reldate", dflt = false)
 
         if (!isS && !isD)
             logln((
diff --git 
a/nlpcraft/src/main/scala/org/apache/nlpcraft/model/tools/cmdline/NCCliCommands.scala
 
b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/tools/cmdline/NCCliCommands.scala
index c9e1486..ed88e0a 100644
--- 
a/nlpcraft/src/main/scala/org/apache/nlpcraft/model/tools/cmdline/NCCliCommands.scala
+++ 
b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/tools/cmdline/NCCliCommands.scala
@@ -762,13 +762,14 @@ private [cmdline] object NCCliCommands {
                 Parameter(
                     id = "models",
                     names = Seq("--mdls", "-m"),
-                    value = Some("<model list>"),
+                    value = Some("my.Model1,my.Model2"),
                     optional = true,
                     desc =
                         s"Comma separated list of fully qualified class names 
for models to deploy. This will override " +
                         s"${y("'nlpcraft.probe.models'")} configuration 
property from either default configuration file " +
                         s"or the one provided by ${c("--cfg")} parameter. Note 
that you also must provide the additional " +
-                        s"classpath in this case via ${c("--cp")} parameter."
+                        s"classpath in this case via ${c("--cp")} parameter. 
Note also that you can have multiple '${c("--mdls")} " +
+                        s"parameters - each specifying one or more model class 
names - and they will be automatically combined together."
                 ),
                 Parameter(
                     id = "jvmopts",
@@ -872,12 +873,14 @@ private [cmdline] object NCCliCommands {
                 Parameter(
                     id = "models",
                     names = Seq("--mdls", "-m"),
-                    value = Some("<model list>"),
+                    value = Some("my.Model1,my.Model2"),
                     optional = true,
                     desc =
                         s"Comma separated list of fully qualified class names 
for models to deploy and test. Note that you also " +
                         s"must provide the additional classpath via 
${c("--cp")} parameter. If not provided, the models " +
-                        s"specified in configuration file (${c("--cfg")} 
parameter) will be used instead."
+                        s"specified in configuration file (${c("--cfg")} 
parameter) will be used instead. Note that " +
+                        s"you can have multiple '${c("--mdls")} parameters - 
each specifying one or more model class " +
+                        s"names - and they will be automatically combined 
together."
                 ),
                 Parameter(
                     id = "jvmopts",
diff --git 
a/nlpcraft/src/main/scala/org/apache/nlpcraft/model/tools/cmdline/NCCliModelClassCompleter.java
 
b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/tools/cmdline/NCCliModelClassCompleter.java
index 6e6db2b..497c360 100644
--- 
a/nlpcraft/src/main/scala/org/apache/nlpcraft/model/tools/cmdline/NCCliModelClassCompleter.java
+++ 
b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/tools/cmdline/NCCliModelClassCompleter.java
@@ -37,8 +37,8 @@ class NCCliModelClassCompleter {
      * @return Set of class names from the given JAR file.
      * @throws IOException Thrown in case of any I/O errors.
      */
-    private Set<String> getClassNamesFromJar(String jarPath) throws 
IOException {
-        assert jarPath != null && jarPath.toLowerCase().endsWith(".jar");
+    private Set<String> getClassNamesFromJar(File jarPath) throws IOException {
+        assert jarPath != null && 
jarPath.getAbsolutePath().toLowerCase().endsWith(".jar");
 
         Set<String> classNames = new HashSet<>();
 
@@ -65,10 +65,10 @@ class NCCliModelClassCompleter {
      * @return Set of model class name for the given classpath.
      * @throws IOException Thrown in case of any I/O errors.
      */
-    public Set<String> getModelClassNamesFromClasspath(List<String> cp) throws 
IOException, ClassNotFoundException {
+    public Set<String> getModelClassNamesFromClasspath(List<String> cp) throws 
IOException {
         Set<URL> urls = cp.stream().map(entry -> {
             try {
-                return new URL("jar:file" + entry + "!/");
+                return new URL("jar:file:" + entry + "!/");
             }
             catch (MalformedURLException e) {
                 return null;
@@ -84,13 +84,18 @@ class NCCliModelClassCompleter {
         try (URLClassLoader clsLdr = URLClassLoader.newInstance(urlsArr)) {
             for (String cpEntry : cp) {
                 try {
-                    Set<String> classNames = getClassNamesFromJar(cpEntry);
+                    Set<String> classNames = getClassNamesFromJar(new 
File(cpEntry));
 
                     for (String name : classNames) {
-                        Class<?> clazz = clsLdr.loadClass(name);
-
-                        if (NCModel.class.isAssignableFrom(clazz))
-                            mdlClasses.add(clazz.getName());
+                        try {
+                            Class<?> clazz = clsLdr.loadClass(name);
+
+                            if (NCModel.class.isAssignableFrom(clazz))
+                                mdlClasses.add(clazz.getName());
+                        }
+                        catch (Throwable e) {
+                            // Ignoring.
+                        }
                     }
                 }
                 catch (Exception e) {
diff --git 
a/nlpcraft/src/test/scala/org/apache/nlpcraft/model/tools/cmdline/NCCliModelClassCompleterTest.scala
 
b/nlpcraft/src/test/scala/org/apache/nlpcraft/model/tools/cmdline/NCCliModelClassCompleterTest.scala
new file mode 100644
index 0000000..6061df4
--- /dev/null
+++ 
b/nlpcraft/src/test/scala/org/apache/nlpcraft/model/tools/cmdline/NCCliModelClassCompleterTest.scala
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ *      https://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.apache.nlpcraft.model.tools.cmdline
+
+import org.apache.nlpcraft.common.version.NCVersion
+import org.junit.jupiter.api.Test
+
+import java.util
+import scala.jdk.CollectionConverters.SetHasAsScala
+
+/**
+ * Unit test for the classpath completer. Note that working directory must be 
set
+ * properly for this test to work.
+ */
+class NCCliModelClassCompleterTest {
+    @Test
+    def testClasspathCompleter(): Unit = {
+        val cp = new util.ArrayList[String]()
+        val completer = new NCCliModelClassCompleter()
+        val ver = NCVersion.getCurrent.version
+
+        // NOTE: make sure to properly set the current working directory for 
the runtime configuration
+        // when running this test.
+        
cp.add(s".\\nlpcraft-examples\\lightswitch\\target\\nlpcraft-example-lightswitch-$ver.jar")
+        
cp.add(s".\\nlpcraft-examples\\alarm\\target\\nlpcraft-example-alarm-$ver.jar")
+        
cp.add(s".\\nlpcraft-examples\\weather\\target\\nlpcraft-example-weather-$ver.jar")
+        
cp.add(s".\\nlpcraft-examples\\time\\target\\nlpcraft-example-time-$ver.jar")
+
+        val mdlClasses = completer.getModelClassNamesFromClasspath(cp).asScala
+
+        mdlClasses.foreach(println)
+    }
+}

Reply via email to