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

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


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

commit 38c1777dd363ed5bf68911f0ec2727c855650dc4
Author: Sergey Kamov <[email protected]>
AuthorDate: Fri Apr 2 15:45:25 2021 +0300

    WIP.
---
 .../examples/lightswitch/lightswitch_model.yaml    |   2 +
 .../nlpcraft/examples/sql/sql_model_init.yaml      |   4 +-
 .../model/intent/compiler/NCIdlCompilerBase.scala  |   1 +
 .../nlpcraft/probe/mgrs/NCProbeSynonym.scala       |  10 +-
 .../mgrs/nlp/enrichers/model/NCModelEnricher.scala |  56 ++++---
 .../model/properties/NCTokensPropertiesSpec.scala  | 167 +++++++--------------
 .../nlpcraft/model/synonyms/NCSynonymsSpec.scala   |  61 ++++++--
 7 files changed, 150 insertions(+), 151 deletions(-)

diff --git 
a/nlpcraft/src/main/scala/org/apache/nlpcraft/examples/lightswitch/lightswitch_model.yaml
 
b/nlpcraft/src/main/scala/org/apache/nlpcraft/examples/lightswitch/lightswitch_model.yaml
index c7f4fa6..6ad9b7e 100644
--- 
a/nlpcraft/src/main/scala/org/apache/nlpcraft/examples/lightswitch/lightswitch_model.yaml
+++ 
b/nlpcraft/src/main/scala/org/apache/nlpcraft/examples/lightswitch/lightswitch_model.yaml
@@ -33,6 +33,8 @@ macros:
   - name: "<LIGHT>"
     macro: "{all|_} {it|them|light|illumination|lamp|lamplight}"
 enabledBuiltInTokens: [] # This example doesn't use any built-in tokens.
+permutateSynonyms: true
+sparse: true
 elements:
   - id: "ls:loc"
     description: "Location of lights."
diff --git 
a/nlpcraft/src/main/scala/org/apache/nlpcraft/examples/sql/sql_model_init.yaml 
b/nlpcraft/src/main/scala/org/apache/nlpcraft/examples/sql/sql_model_init.yaml
index 9438cfa..d8cfc3e 100644
--- 
a/nlpcraft/src/main/scala/org/apache/nlpcraft/examples/sql/sql_model_init.yaml
+++ 
b/nlpcraft/src/main/scala/org/apache/nlpcraft/examples/sql/sql_model_init.yaml
@@ -1422,5 +1422,5 @@ swearWordsAllowed: false
 noNounsAllowed: true
 noUserTokensAllowed: true
 dupSynonymsAllowed: true
-permutateSynonyms: true
-sparse: true
+permutateSynonyms: false
+sparse: false
diff --git 
a/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/compiler/NCIdlCompilerBase.scala
 
b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/compiler/NCIdlCompilerBase.scala
index 8072532..8969121 100644
--- 
a/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/compiler/NCIdlCompilerBase.scala
+++ 
b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/compiler/NCIdlCompilerBase.scala
@@ -1091,6 +1091,7 @@ trait NCIdlCompilerBase {
             case "tok_lemma" ⇒ arg1Tok() match { case x ⇒ stack.push(() ⇒ { 
Z(toToken(x().value).getLemma, 1) }) }
             case "tok_stem" ⇒ arg1Tok() match { case x ⇒ stack.push(() ⇒ { 
Z(toToken(x().value).getStem, 1) }) }
             case "tok_pos" ⇒ arg1Tok() match { case x ⇒ stack.push(() ⇒ { 
Z(toToken(x().value).getPos, 1) }) }
+            case "tok_sparsity" ⇒ arg1Tok() match { case x ⇒ stack.push(() ⇒ { 
Z(toToken(x().value).getSparsity, 1) }) }
             case "tok_unid" ⇒ arg1Tok() match { case x ⇒ stack.push(() ⇒ { 
Z(toToken(x().value).getUnid, 1) }) }
             case "tok_is_abstract" ⇒ arg1Tok() match { case x ⇒ stack.push(() 
⇒ { Z(toToken(x().value).isAbstract, 1) }) }
             case "tok_is_bracketed" ⇒ arg1Tok() match { case x ⇒ stack.push(() 
⇒ { Z(toToken(x().value).isBracketed, 1) }) }
diff --git 
a/nlpcraft/src/main/scala/org/apache/nlpcraft/probe/mgrs/NCProbeSynonym.scala 
b/nlpcraft/src/main/scala/org/apache/nlpcraft/probe/mgrs/NCProbeSynonym.scala
index a611c0c..cddf6a2 100644
--- 
a/nlpcraft/src/main/scala/org/apache/nlpcraft/probe/mgrs/NCProbeSynonym.scala
+++ 
b/nlpcraft/src/main/scala/org/apache/nlpcraft/probe/mgrs/NCProbeSynonym.scala
@@ -131,13 +131,13 @@ class NCProbeSynonym(
 
             for (chunk ← this if ok)
                 sen.drop(lastIdx).find(tok ⇒ isMatch(tok, chunk)) match {
-                    case Some(tok) ⇒ buf += tok; lastIdx = tokIdxs(tok)
+                    case Some(tok) ⇒ buf += tok; lastIdx = tokIdxs(tok) + 1
                     case None ⇒ ok = false
                 }
         }
         else
             for (chunk ← this if ok)
-                sen.find(tok ⇒ isMatch(tok, chunk) && !buf.contains(tok)) 
match {
+                sen.find(tok ⇒ !buf.contains(tok) && isMatch(tok, chunk)) 
match {
                     case Some(tok) ⇒ buf += tok
                     case None ⇒ ok = false
                 }
@@ -206,14 +206,14 @@ class NCProbeSynonym(
 
             for (chunk ← this if ok)
                 sen.drop(lastIdx).find(tow ⇒ isMatch(tow, chunk, req)) match {
-                    case Some(t) ⇒ buf += t; lastIdx = tokIdxs(t)
+                    case Some(t) ⇒ buf += t; lastIdx = tokIdxs(t) + 1
                     case None ⇒ ok = false
                 }
         }
         else
             for (chunk ← this if ok)
-                sen.find(tow ⇒ isMatch(tow, chunk, req) && !buf.contains(tow)) 
match {
-                    case Some(t) ⇒ buf += t
+                sen.find(tow ⇒ !buf.contains(tow) && isMatch(tow, chunk, req)) 
match {
+                    case Some(tow) ⇒ buf += tow
                     case None ⇒ ok = false
                 }
 
diff --git 
a/nlpcraft/src/main/scala/org/apache/nlpcraft/probe/mgrs/nlp/enrichers/model/NCModelEnricher.scala
 
b/nlpcraft/src/main/scala/org/apache/nlpcraft/probe/mgrs/nlp/enrichers/model/NCModelEnricher.scala
index 0639e77..1e4c756 100644
--- 
a/nlpcraft/src/main/scala/org/apache/nlpcraft/probe/mgrs/nlp/enrichers/model/NCModelEnricher.scala
+++ 
b/nlpcraft/src/main/scala/org/apache/nlpcraft/probe/mgrs/nlp/enrichers/model/NCModelEnricher.scala
@@ -136,9 +136,7 @@ object NCModelEnricher extends NCProbeEnricher with 
DecorateAsScala {
 
         // Number of tokens.
         lazy val length: Int = tokens.size
-        private lazy val tokensSet: Set[NCNlpSentenceToken] = tokens.toSet
-
-        def isSubSet(toks: Set[NCNlpSentenceToken]): Boolean = 
toks.subsetOf(tokensSet)
+        lazy val tokensSet: Set[NCNlpSentenceToken] = tokens.toSet
 
         override def compare(that: ElementMatch): Int = {
             // Check synonym first, then length and then sparsity.
@@ -282,8 +280,31 @@ object NCModelEnricher extends NCProbeEnricher with 
DecorateAsScala {
             "mdlId" → mdl.model.getId,
             "txt" → ns.text) { span ⇒
             val cache = mutable.HashSet.empty[Seq[Int]]
-            val matches = ArrayBuffer.empty[ElementMatch]
             val req = NCRequestImpl(senMeta, ns.srvReqId)
+            val matches = ArrayBuffer.empty[ElementMatch]
+
+            def addMatch(
+                elm: NCElement,
+                toks: Seq[NCNlpSentenceToken],
+                syn: NCProbeSynonym,
+                parts: Seq[(NCToken, NCSynonymChunkKind)]
+            ): Boolean = {
+                val toksSet = toks.toSet
+
+                if (!matches.exists(m ⇒ m.element.getId == elm.getId && 
toksSet.subsetOf(m.tokensSet))) {
+                    matches += ElementMatch(elm, toks, syn, parts)
+
+                    true
+                }
+                else
+                    false
+            }
+
+            def getParts(comb: Seq[Complex], syn: NCProbeSynonym): 
Seq[(NCToken, NCSynonymChunkKind)] =
+                comb.zip(syn.map(_.kind)).flatMap {
+                    case (complex, kind) ⇒ if (complex.isToken) 
Some(complex.token → kind)
+                    else None
+                }
 
             /**
               * Gets synonyms sorted in descending order by their weight 
(already prepared),
@@ -351,7 +372,7 @@ object NCModelEnricher extends NCProbeEnricher with 
DecorateAsScala {
                             case None ⇒ None
                         }
                     ).headOption match {
-                        case Some((syn, toks)) ⇒ matches += 
ElementMatch(mdl.elements(elemId), toks, syn, Seq.empty)
+                        case Some((syn, toks)) ⇒ 
addMatch(mdl.elements(elemId), toks, syn, Seq.empty)
                         case None ⇒ // No-op.
                     }
                 }
@@ -379,7 +400,7 @@ object NCModelEnricher extends NCProbeEnricher with 
DecorateAsScala {
                                         )
                                     )
 
-                                matches += ElementMatch(mdl.elements(elemId), 
toks.sortBy(_.startCharIndex), syn, Seq.empty)
+                                addMatch(mdl.elements(elemId), 
toks.sortBy(_.startCharIndex), syn, getParts(comb, syn))
 
                                 found = true
                             case None ⇒ // No-op.
@@ -424,17 +445,14 @@ object NCModelEnricher extends NCProbeEnricher with 
DecorateAsScala {
                         for (elm ← mdl.elements.values if !alreadyMarked(toks, 
elm.getId)) {
                             var found = false
 
-                            def addMatch(
+                            def setFound(
                                 elm: NCElement,
                                 toks: Seq[NCNlpSentenceToken],
                                 syn: NCProbeSynonym,
                                 parts: Seq[(NCToken, NCSynonymChunkKind)]
-                            ): Unit = {
-                                found = true
-
-                                if (!matches.exists(m ⇒ m.element.getId == 
elm.getId && m.isSubSet(toks.toSet)))
-                                    matches += ElementMatch(elm, toks, syn, 
parts)
-                            }
+                            ): Unit =
+                                if (addMatch(elm, toks, syn, parts))
+                                    found = true
 
                             // 3. Simple, not sparse.
                             // Optimization - plain synonyms can be used only 
on first iteration
@@ -444,7 +462,7 @@ object NCModelEnricher extends NCProbeEnricher with 
DecorateAsScala {
                                         def tryMap(synsMap: Map[String, 
NCProbeSynonym], notFound: () ⇒ Unit): Unit =
                                             synsMap.get(tokStems) match {
                                                 case Some(syn) ⇒
-                                                    addMatch(elm, toks, syn, 
Seq.empty)
+                                                    setFound(elm, toks, syn, 
Seq.empty)
 
                                                     if (!found)
                                                         notFound()
@@ -454,7 +472,7 @@ object NCModelEnricher extends NCProbeEnricher with 
DecorateAsScala {
                                         def tryScan(synsSeq: 
Seq[NCProbeSynonym]): Unit =
                                             for (syn ← synsSeq if !found)
                                                 if (syn.isMatch(toks))
-                                                    addMatch(elm, toks, syn, 
Seq.empty)
+                                                    setFound(elm, toks, syn, 
Seq.empty)
 
                                         tryMap(
                                             h.txtDirectSynonyms,
@@ -472,12 +490,6 @@ object NCModelEnricher extends NCProbeEnricher with 
DecorateAsScala {
                                 }
 
                             if (mdl.nonSparseSynonymsDsl.nonEmpty) {
-                                def getParts(comb: Seq[Complex], syn: 
NCProbeSynonym): Seq[(NCToken, NCSynonymChunkKind)] =
-                                    comb.zip(syn.map(_.kind)).flatMap {
-                                        case (complex, kind) ⇒ if 
(complex.isToken) Some(complex.token → kind)
-                                        else None
-                                    }
-
                                 // 4. DSL, non sparse.
                                 for (
                                     (len, seq) ← dslCombs;
@@ -486,7 +498,7 @@ object NCModelEnricher extends NCProbeEnricher with 
DecorateAsScala {
                                     data = comb.map(_.data)
                                 )
                                     if (syn.isMatch(data, req))
-                                        addMatch(elm, toks, syn, 
getParts(comb, syn))
+                                        setFound(elm, toks, syn, 
getParts(comb, syn))
                             }
                         }
                     }
diff --git 
a/nlpcraft/src/test/scala/org/apache/nlpcraft/model/properties/NCTokensPropertiesSpec.scala
 
b/nlpcraft/src/test/scala/org/apache/nlpcraft/model/properties/NCTokensPropertiesSpec.scala
index c1cfce6..ff530cb 100644
--- 
a/nlpcraft/src/test/scala/org/apache/nlpcraft/model/properties/NCTokensPropertiesSpec.scala
+++ 
b/nlpcraft/src/test/scala/org/apache/nlpcraft/model/properties/NCTokensPropertiesSpec.scala
@@ -35,27 +35,28 @@ abstract class NCTokenPropertiesModelAbstract extends 
NCModelAdapter(
 
     @NCIntent("intent=onXY term(t)={tok_id() == 'xy'}")
     def onXY(ctx: NCIntentMatch): NCResult = NCResult.text("OK")
+
+    override def isPermutateSynonyms: Boolean = true
+    override def isSparse: Boolean = true
 }
 
 case class NCPropTestElement(
-    id: String, synonym: String, permFlag: Option[Boolean] = None, sparse: 
Option[Boolean] = None
+    id: String, synonym: String, perm: Option[Boolean] = None, sparse: 
Option[Boolean] = None
 ) extends NCElement {
     override def getId: String = id
     override def getSynonyms: util.List[String] = 
util.Collections.singletonList(synonym)
-    override def isPermutateSynonyms: Optional[lang.Boolean] =
-        permFlag match {
-            case Some(v) ⇒ Optional.of(v)
-            case None ⇒ super.isPermutateSynonyms
-        }
 
-    override def isSparse: Optional[lang.Boolean] =
-        sparse match {
+    private def get(opt: Option[Boolean], getSuper: () ⇒ 
Optional[lang.Boolean]): Optional[lang.Boolean] =
+        opt match {
             case Some(v) ⇒ Optional.of(v)
-            case None ⇒ super.isSparse
+            case None ⇒ getSuper()
         }
+
+    override def isPermutateSynonyms: Optional[lang.Boolean] = get(perm, () ⇒ 
super.isPermutateSynonyms)
+    override def isSparse: Optional[lang.Boolean] = get(sparse, () ⇒ 
super.isSparse)
 }
 
-// 1. Default model. Default behaviour with default sparse and permuted 
synonyms configuration values.
+// 1. All enabled.
 class NCTokenPropertiesModel1() extends NCTokenPropertiesModelAbstract
 
 @NCTestEnvironment(model = classOf[NCTokenPropertiesModel1], startClient = 
true)
@@ -76,6 +77,7 @@ class NCTokenPropertiesModel1Spec extends NCTestContext {
 // 2. Permutation turned off.
 class NCTokenPropertiesModel2 extends NCTokenPropertiesModelAbstract {
     override def isPermutateSynonyms: Boolean = false
+    override def isSparse: Boolean = true
 }
 
 @NCTestEnvironment(model = classOf[NCTokenPropertiesModel2], startClient = 
true)
@@ -100,16 +102,10 @@ class NCTokenPropertiesModel2Spec extends NCTestContext {
     }
 }
 
-// 3. Permutation turned off for `ab` but enabled by default for 'xy'
+// 3. Sparse turned off.
 class NCTokenPropertiesModel3 extends NCTokenPropertiesModelAbstract {
-    override def getElements: util.Set[NCElement] = {
-        val set: Set[NCElement] = Set(
-            NCPropTestElement("ab", "a b", permFlag = Some(false)),
-            NCTestElement("xy", "x y")
-        )
-
-        set.asJava
-    }
+    override def isPermutateSynonyms: Boolean = true
+    override def isSparse: Boolean = false
 }
 
 @NCTestEnvironment(model = classOf[NCTokenPropertiesModel3], startClient = 
true)
@@ -117,26 +113,6 @@ class NCTokenPropertiesModel3Spec extends NCTestContext {
     @Test
     def test(): Unit = {
         checkIntent("a b", "onAB")
-        checkIntent("a test test b", "onAB")
-        fail("b a")
-
-        checkIntent("x y", "onXY")
-        checkIntent("x test test y", "onXY")
-        checkIntent("y x", "onXY")
-        checkIntent("y test test x", "onXY")
-    }
-}
-
-// 4. Jiggle factor turned off.
-class NCTokenPropertiesModel4 extends NCTokenPropertiesModelAbstract {
-    override def isSparse: Boolean = false
-}
-
-@NCTestEnvironment(model = classOf[NCTokenPropertiesModel4], startClient = 
true)
-class NCTokenPropertiesModel4Spec extends NCTestContext {
-    @Test
-    def test(): Unit = {
-        checkIntent("a b", "onAB")
         checkIntent("b a", "onAB")
         checkIntent("y x", "onXY")
         checkIntent("x y", "onXY")
@@ -150,103 +126,82 @@ class NCTokenPropertiesModel4Spec extends NCTestContext {
             "b test test a",
             "x test test y",
             "y test test x"
+
         )
     }
 }
 
-// 5. Jiggle factor turned off for `ab` but enabled by default for 'xy'
-// Permutation for 'ab' is disabled.
-class NCTokenPropertiesModel5 extends NCTokenPropertiesModelAbstract {
-    override def getElements: util.Set[NCElement] = {
-        val set: Set[NCElement] = Set(
-            NCPropTestElement("ab", "a b", permFlag = Some(false), sparse = 
Some(false)),
-            NCTestElement("xy", "x y")
-        )
-
-        set.asJava
-    }
+// 4. Permutation and sparse turned off.
+class NCTokenPropertiesModel4 extends NCTokenPropertiesModelAbstract {
+    override def isPermutateSynonyms: Boolean = false
+    override def isSparse: Boolean = false
 }
 
-@NCTestEnvironment(model = classOf[NCTokenPropertiesModel5], startClient = 
true)
-class NCTokenPropertiesModel5Spec extends NCTestContext {
+@NCTestEnvironment(model = classOf[NCTokenPropertiesModel4], startClient = 
true)
+class NCTokenPropertiesModel4Spec extends NCTestContext {
     @Test
     def test(): Unit = {
         checkIntent("a b", "onAB")
-        fail("b a")
-        checkIntent("y x", "onXY")
-        checkIntent("x y", "onXY")
-
         fail(
+            "b a",
             "a test b",
             "b test a"
         )
-        checkIntent("y test x", "onXY")
-        checkIntent("x test y", "onXY")
-
-        fail(
-            "a test test b",
-            "b test test a"
-        )
-        checkIntent("y test test x", "onXY")
-        checkIntent("x test test y", "onXY")
     }
 }
 
-// 6. Jiggle factor restricted for `ab` but enabled by default for 'xy'.
-// Permutation for 'ab' is disabled.
-class NCTokenPropertiesModel6 extends NCTokenPropertiesModelAbstract {
+// 5. Permutation turned off for `ab` but enabled for 'xy'.
+// Sparse turned on for both of them.
+class NCTokenPropertiesModel5 extends NCTokenPropertiesModelAbstract {
+    override def isPermutateSynonyms: Boolean = true
+    override def isSparse: Boolean = true
+
     override def getElements: util.Set[NCElement] = {
         val set: Set[NCElement] = Set(
-            NCPropTestElement("ab", "a b", permFlag = Some(false), sparse = 
Some(true)),
-            NCTestElement("xy", "x y")
+            NCPropTestElement("ab", "a b", perm = Some(false)),
+            NCPropTestElement("xy", "x y", perm = Some(true))
         )
 
         set.asJava
     }
 }
 
-@NCTestEnvironment(model = classOf[NCTokenPropertiesModel6], startClient = 
true)
-class NCTokenPropertiesModel6Spec extends NCTestContext {
+@NCTestEnvironment(model = classOf[NCTokenPropertiesModel5], startClient = 
true)
+class NCTokenPropertiesModel5Spec extends NCTestContext {
     @Test
     def test(): Unit = {
         checkIntent("a b", "onAB")
+        checkIntent("a test test b", "onAB")
         fail("b a")
-        checkIntent("y x", "onXY")
-        checkIntent("x y", "onXY")
 
-        checkIntent("a test b", "onAB")
-        fail("b test a")
-        checkIntent("y test x", "onXY")
-        checkIntent("x test y", "onXY")
-
-        fail(
-            "a test test b",
-            "b test test a"
-        )
-        checkIntent("y test test x", "onXY")
+        checkIntent("x y", "onXY")
         checkIntent("x test test y", "onXY")
+        checkIntent("y x", "onXY")
+        checkIntent("y test test x", "onXY")
     }
 }
 
-// 7. Jiggle factor turned off for `ab` but enabled by default for 'xy'
-// Permutation for 'ab' - by default.
-class NCTokenPropertiesModel7 extends NCTokenPropertiesModelAbstract {
+// 6. Sparse factor and permutation are turned off for `ab` but enabled for 
'xy'.
+class NCTokenPropertiesModel6 extends NCTokenPropertiesModelAbstract {
+    override def isPermutateSynonyms: Boolean = true
+    override def isSparse: Boolean = true
+
     override def getElements: util.Set[NCElement] = {
         val set: Set[NCElement] = Set(
-            NCPropTestElement("ab", "a b", sparse = Some(false)),
-            NCTestElement("xy", "x y")
+            NCPropTestElement("ab", "a b", sparse = Some(false), perm = 
Some(false)),
+            NCPropTestElement("xy", "x y")
         )
 
         set.asJava
     }
 }
 
-@NCTestEnvironment(model = classOf[NCTokenPropertiesModel7], startClient = 
true)
-class NCTokenPropertiesModel7Spec extends NCTestContext {
+@NCTestEnvironment(model = classOf[NCTokenPropertiesModel6], startClient = 
true)
+class NCTokenPropertiesModel6Spec extends NCTestContext {
     @Test
     def test(): Unit = {
         checkIntent("a b", "onAB")
-        checkIntent("b a", "onAB")
+        fail("b a")
         checkIntent("y x", "onXY")
         checkIntent("x y", "onXY")
 
@@ -266,41 +221,33 @@ class NCTokenPropertiesModel7Spec extends NCTestContext {
     }
 }
 
+// 7. Sparse factor turned off for `ab` but enabled  for 'xy'.
+class NCTokenPropertiesModel7 extends NCTokenPropertiesModelAbstract {
+    override def isPermutateSynonyms: Boolean = true
+    override def isSparse: Boolean = true
 
-// 8. Jiggle factor restricted for `ab` but enabled by default for 'xy'
-// Permutation for 'ab' - by default.
-class NCTokenPropertiesModel8 extends NCTokenPropertiesModelAbstract {
     override def getElements: util.Set[NCElement] = {
         val set: Set[NCElement] = Set(
-            NCPropTestElement("ab", "a b", sparse = Some(true)),
-            NCTestElement("xy", "x y")
+            NCPropTestElement("ab", "a b", perm = Some(true), sparse = 
Some(false)),
+            NCPropTestElement("xy", "x y", perm = Some(true), sparse = 
Some(true))
         )
 
         set.asJava
     }
 }
 
-@NCTestEnvironment(model = classOf[NCTokenPropertiesModel8], startClient = 
true)
-class NCTokenPropertiesModel8Spec extends NCTestContext {
+@NCTestEnvironment(model = classOf[NCTokenPropertiesModel7], startClient = 
true)
+class NCTokenPropertiesModel7Spec extends NCTestContext {
     @Test
     def test(): Unit = {
         checkIntent("a b", "onAB")
         checkIntent("b a", "onAB")
+        fail("a test b")
+        fail("b test a")
         checkIntent("y x", "onXY")
         checkIntent("x y", "onXY")
-        checkIntent("a test b", "onAB")
-        checkIntent("b test a", "onAB")
-        checkIntent("y test x", "onXY")
-        checkIntent("x test y", "onXY")
-
-        fail(
-            "a test test b",
-            "b test test a"
-        )
         checkIntent("y test test x", "onXY")
         checkIntent("x test test y", "onXY")
     }
 }
 
-
-
diff --git 
a/nlpcraft/src/test/scala/org/apache/nlpcraft/model/synonyms/NCSynonymsSpec.scala
 
b/nlpcraft/src/test/scala/org/apache/nlpcraft/model/synonyms/NCSynonymsSpec.scala
index ada03fa..91c8eb6 100644
--- 
a/nlpcraft/src/test/scala/org/apache/nlpcraft/model/synonyms/NCSynonymsSpec.scala
+++ 
b/nlpcraft/src/test/scala/org/apache/nlpcraft/model/synonyms/NCSynonymsSpec.scala
@@ -23,11 +23,7 @@ import org.junit.jupiter.api.Test
 
 import java.util
 
-class NCSynonymsSpecModel extends NCModelAdapter("nlpcraft.syns.test.mdl", 
"Synonyms Test Model", "1.0") {
-    // Default values.
-    override def isPermutateSynonyms: Boolean = true
-    override def isSparse: Boolean = true
-
+abstract class NCSynonymsSpecModel extends 
NCModelAdapter("nlpcraft.syns.test.mdl", "Synonyms Test Model", "1.0") {
     override def getElements: util.Set[NCElement] =
         Set(
             NCTestElement("e1", "A"),
@@ -55,17 +51,58 @@ class NCSynonymsSpecModel extends 
NCModelAdapter("nlpcraft.syns.test.mdl", "Syno
     def onE4(ctx: NCIntentMatch): NCResult = NCResult.text("OK")
 }
 
-@NCTestEnvironment(model = classOf[NCSynonymsSpecModel], startClient = true)
 class NCSynonymsSpec extends NCTestContext {
-    @Test
-    def test(): Unit = {
+    def body(testNonDir: Boolean): Unit = {
         checkIntent("A", "onE1")
-
         checkIntent("X Y Z", "onE2") // Text direct.
-        checkIntent("Y X Z", "onE2") // Text not direct.
-
+        if (testNonDir)
+            checkIntent("Y X Z", "onE2") // Text not direct.
         checkIntent("AA AA AA", "onE3") // Regex.
-
         checkIntent("A A A", "onE4") // Nested.
     }
 }
+
+class NCSynonymsSpecModel1 extends NCSynonymsSpecModel {
+    override def isPermutateSynonyms: Boolean = true
+    override def isSparse: Boolean = true
+}
+
+@NCTestEnvironment(model = classOf[NCSynonymsSpecModel1], startClient = true)
+class NCSynonymsSpec1 extends NCSynonymsSpec {
+    @Test
+    def test(): Unit = body(testNonDir = true)
+}
+
+class NCSynonymsSpecModel2 extends NCSynonymsSpecModel {
+    override def isPermutateSynonyms: Boolean = false
+    override def isSparse: Boolean = true
+}
+
+@NCTestEnvironment(model = classOf[NCSynonymsSpecModel2], startClient = true)
+class NCSynonymsSpec2 extends NCSynonymsSpec {
+    @Test
+    def test(): Unit = body(testNonDir = false)
+}
+
+class NCSynonymsSpecModel3 extends NCSynonymsSpecModel {
+    override def isPermutateSynonyms: Boolean = true
+    override def isSparse: Boolean = false
+}
+
+@NCTestEnvironment(model = classOf[NCSynonymsSpecModel3], startClient = true)
+class NCSynonymsSpec3 extends NCSynonymsSpec {
+    @Test
+    def test(): Unit = body(testNonDir = true)
+}
+
+class NCSynonymsSpecModel4 extends NCSynonymsSpecModel {
+    override def isPermutateSynonyms: Boolean = false
+    override def isSparse: Boolean = false
+}
+
+@NCTestEnvironment(model = classOf[NCSynonymsSpecModel4], startClient = true)
+class NCSynonymsSpec4 extends NCSynonymsSpec {
+    @Test
+    def test(): Unit = body(testNonDir = false)
+}
+

Reply via email to