You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2015/12/23 12:45:25 UTC

[5/8] camel git commit: CAMEL-9434: camel-catalog - did you mean

CAMEL-9434: camel-catalog - did you mean


Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/a6589904
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/a6589904
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/a6589904

Branch: refs/heads/camel-2.16.x
Commit: a658990433aa86ee92d3857bb9425dfc903f0f5d
Parents: c450a47
Author: Claus Ibsen <da...@apache.org>
Authored: Wed Dec 23 12:23:26 2015 +0100
Committer: Claus Ibsen <da...@apache.org>
Committed: Wed Dec 23 12:44:45 2015 +0100

----------------------------------------------------------------------
 platforms/catalog/pom.xml                       | 14 +++++
 .../org/apache/camel/catalog/CamelCatalog.java  |  6 ++
 .../camel/catalog/DefaultCamelCatalog.java      | 19 +++++++
 .../camel/catalog/EndpointValidationResult.java | 24 +++++++-
 .../apache/camel/catalog/JSonSchemaHelper.java  | 13 ++++-
 .../org/apache/camel/catalog/Suggestion.java    | 34 +++++++++++
 .../camel/catalog/lucene/LuceneSuggestion.java  | 59 ++++++++++++++++++++
 .../catalog/lucene/CamelCatalogLuceneTest.java  | 48 ++++++++++++++++
 8 files changed, 215 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/a6589904/platforms/catalog/pom.xml
----------------------------------------------------------------------
diff --git a/platforms/catalog/pom.xml b/platforms/catalog/pom.xml
index 9f62f73..9e94701 100644
--- a/platforms/catalog/pom.xml
+++ b/platforms/catalog/pom.xml
@@ -39,6 +39,20 @@
 
     <!-- no dependency -->
 
+    <!-- lucene optional dependency for did you mean -->
+    <dependency>
+      <groupId>org.apache.lucene</groupId>
+      <artifactId>lucene-core</artifactId>
+      <version>${lucene-version}</version>
+      <optional>true</optional>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.lucene</groupId>
+      <artifactId>lucene-suggest</artifactId>
+      <version>${lucene-version}</version>
+      <optional>true</optional>
+    </dependency>
+
     <!-- testing -->
     <dependency>
       <groupId>com.fasterxml.jackson.core</groupId>

http://git-wip-us.apache.org/repos/asf/camel/blob/a6589904/platforms/catalog/src/main/java/org/apache/camel/catalog/CamelCatalog.java
----------------------------------------------------------------------
diff --git a/platforms/catalog/src/main/java/org/apache/camel/catalog/CamelCatalog.java b/platforms/catalog/src/main/java/org/apache/camel/catalog/CamelCatalog.java
index eeafe6c..eb14c80 100644
--- a/platforms/catalog/src/main/java/org/apache/camel/catalog/CamelCatalog.java
+++ b/platforms/catalog/src/main/java/org/apache/camel/catalog/CamelCatalog.java
@@ -36,6 +36,12 @@ public interface CamelCatalog {
     void enableCache();
 
     /**
+     * Enables did you mean functionality using Apache Lucene to provide a list of suggested option names
+     * when {@link #validateEndpointProperties(String)} fails due unknown or mistyped option names.
+     */
+    void enableLuceneSuggestion();
+
+    /**
      * The version of this Camel Catalog
      */
     String getCatalogVersion();

http://git-wip-us.apache.org/repos/asf/camel/blob/a6589904/platforms/catalog/src/main/java/org/apache/camel/catalog/DefaultCamelCatalog.java
----------------------------------------------------------------------
diff --git a/platforms/catalog/src/main/java/org/apache/camel/catalog/DefaultCamelCatalog.java b/platforms/catalog/src/main/java/org/apache/camel/catalog/DefaultCamelCatalog.java
index d9aebec..4813a9b 100644
--- a/platforms/catalog/src/main/java/org/apache/camel/catalog/DefaultCamelCatalog.java
+++ b/platforms/catalog/src/main/java/org/apache/camel/catalog/DefaultCamelCatalog.java
@@ -41,6 +41,7 @@ import javax.xml.xpath.XPathFactory;
 import org.w3c.dom.Document;
 
 import static org.apache.camel.catalog.CatalogHelper.after;
+import static org.apache.camel.catalog.JSonSchemaHelper.getNames;
 import static org.apache.camel.catalog.JSonSchemaHelper.getPropertyDefaultValue;
 import static org.apache.camel.catalog.JSonSchemaHelper.getPropertyEnum;
 import static org.apache.camel.catalog.JSonSchemaHelper.getRow;
@@ -78,6 +79,7 @@ public class DefaultCamelCatalog implements CamelCatalog {
     private final Map<String, Object> cache = new HashMap<String, Object>();
 
     private boolean caching;
+    private Suggestion suggestion;
 
     /**
      * Creates the {@link CamelCatalog} without caching enabled.
@@ -100,6 +102,17 @@ public class DefaultCamelCatalog implements CamelCatalog {
     }
 
     @Override
+    public void enableLuceneSuggestion() {
+        // must be optional so create the class using forName
+        try {
+            Class clazz = Class.forName("org.apache.camel.catalog.lucene.LuceneSuggestion");
+            suggestion = (Suggestion) clazz.newInstance();
+        } catch (Throwable e) {
+            // ignore
+        }
+    }
+
+    @Override
     public String getCatalogVersion() {
         return version.getVersion();
     }
@@ -679,6 +692,12 @@ public class DefaultCamelCatalog implements CamelCatalog {
             if (row == null) {
                 // unknown option
                 result.addUnknown(name);
+                if (suggestion != null) {
+                    String[] suggestions = suggestion.suggestEndpointOptions(getNames(rows), name);
+                    if (suggestions != null) {
+                        result.addUnknownSuggestions(name, suggestions);
+                    }
+                }
             } else {
                 // is required but the value is empty
                 boolean required = isPropertyRequired(rows, name);

http://git-wip-us.apache.org/repos/asf/camel/blob/a6589904/platforms/catalog/src/main/java/org/apache/camel/catalog/EndpointValidationResult.java
----------------------------------------------------------------------
diff --git a/platforms/catalog/src/main/java/org/apache/camel/catalog/EndpointValidationResult.java b/platforms/catalog/src/main/java/org/apache/camel/catalog/EndpointValidationResult.java
index 8f463fd..c6b25ba 100644
--- a/platforms/catalog/src/main/java/org/apache/camel/catalog/EndpointValidationResult.java
+++ b/platforms/catalog/src/main/java/org/apache/camel/catalog/EndpointValidationResult.java
@@ -37,6 +37,7 @@ public class EndpointValidationResult implements Serializable {
 
     // options
     private Set<String> unknown;
+    private Map<String, String[]> unknownSuggestions;
     private Set<String> required;
     private Map<String, String> invalidEnum;
     private Map<String, String[]> invalidEnumChoices;
@@ -87,6 +88,13 @@ public class EndpointValidationResult implements Serializable {
         }
     }
 
+    public void addUnknownSuggestions(String name, String[] suggestions) {
+        if (unknownSuggestions == null) {
+            unknownSuggestions = new LinkedHashMap<String, String[]>();
+        }
+        unknownSuggestions.put(name, suggestions);
+    }
+
     public void addRequired(String name) {
         if (required == null) {
             required = new LinkedHashSet<String>();
@@ -162,6 +170,10 @@ public class EndpointValidationResult implements Serializable {
         return unknown;
     }
 
+    public Map<String, String[]> getUnknownSuggestions() {
+        return unknownSuggestions;
+    }
+
     public String getUnknownComponent() {
         return unknownComponent;
     }
@@ -174,6 +186,10 @@ public class EndpointValidationResult implements Serializable {
         return invalidEnum;
     }
 
+    public Map<String, String[]> getInvalidEnumChoices() {
+        return invalidEnumChoices;
+    }
+
     public Map<String, String> getInvalidReference() {
         return invalidReference;
     }
@@ -210,7 +226,13 @@ public class EndpointValidationResult implements Serializable {
         Map<String, String> options = new LinkedHashMap<String, String>();
         if (unknown != null) {
             for (String name : unknown) {
-                options.put(name, "Unknown field");
+                if (unknownSuggestions != null && unknownSuggestions.containsKey(unknown)) {
+                    String[] suggestions = unknownSuggestions.get(unknown);
+                    String str = Arrays.asList(suggestions).toString();
+                    options.put(name, "Unknown field. Did you mean: " + str);
+                } else {
+                    options.put(name, "Unknown field.");
+                }
             }
         }
         if (required != null) {

http://git-wip-us.apache.org/repos/asf/camel/blob/a6589904/platforms/catalog/src/main/java/org/apache/camel/catalog/JSonSchemaHelper.java
----------------------------------------------------------------------
diff --git a/platforms/catalog/src/main/java/org/apache/camel/catalog/JSonSchemaHelper.java b/platforms/catalog/src/main/java/org/apache/camel/catalog/JSonSchemaHelper.java
index f0755ef..d262b6c 100644
--- a/platforms/catalog/src/main/java/org/apache/camel/catalog/JSonSchemaHelper.java
+++ b/platforms/catalog/src/main/java/org/apache/camel/catalog/JSonSchemaHelper.java
@@ -18,8 +18,10 @@ package org.apache.camel.catalog;
 
 import java.util.ArrayList;
 import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -217,7 +219,6 @@ public final class JSonSchemaHelper {
     public static String getPropertyEnum(List<Map<String, String>> rows, String name) {
         for (Map<String, String> row : rows) {
             String enums = null;
-            String defaultValue = null;
             boolean found = false;
             if (row.containsKey("name")) {
                 found = name.equals(row.get("name"));
@@ -241,4 +242,14 @@ public final class JSonSchemaHelper {
         return null;
     }
 
+    public static Set<String> getNames(List<Map<String, String>> rows) {
+        Set<String> answer = new LinkedHashSet<String>();
+        for (Map<String, String> row : rows) {
+            if (row.containsKey("name")) {
+                answer.add(row.get("name"));
+            }
+        }
+        return answer;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/a6589904/platforms/catalog/src/main/java/org/apache/camel/catalog/Suggestion.java
----------------------------------------------------------------------
diff --git a/platforms/catalog/src/main/java/org/apache/camel/catalog/Suggestion.java b/platforms/catalog/src/main/java/org/apache/camel/catalog/Suggestion.java
new file mode 100644
index 0000000..80602a7
--- /dev/null
+++ b/platforms/catalog/src/main/java/org/apache/camel/catalog/Suggestion.java
@@ -0,0 +1,34 @@
+/**
+ * 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
+ *
+ *      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.apache.camel.catalog;
+
+import java.util.Set;
+
+/**
+ * To provide suggestions for unknown endpoint options
+ */
+public interface Suggestion {
+
+    /**
+     * Provides a list of valid option names for a did you mean function.
+     *
+     * @param names  valid names
+     * @param option unknown option name
+     * @return a list of suggested names (did you mean)
+     */
+    String[] suggestEndpointOptions(Set<String> names, String option);
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a6589904/platforms/catalog/src/main/java/org/apache/camel/catalog/lucene/LuceneSuggestion.java
----------------------------------------------------------------------
diff --git a/platforms/catalog/src/main/java/org/apache/camel/catalog/lucene/LuceneSuggestion.java b/platforms/catalog/src/main/java/org/apache/camel/catalog/lucene/LuceneSuggestion.java
new file mode 100644
index 0000000..41ac28a
--- /dev/null
+++ b/platforms/catalog/src/main/java/org/apache/camel/catalog/lucene/LuceneSuggestion.java
@@ -0,0 +1,59 @@
+/**
+ * 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
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * 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.camel.catalog.lucene;
+
+import java.io.StringReader;
+import java.util.Set;
+
+import org.apache.camel.catalog.Suggestion;
+import org.apache.lucene.analysis.standard.StandardAnalyzer;
+import org.apache.lucene.index.IndexWriterConfig;
+import org.apache.lucene.search.spell.PlainTextDictionary;
+import org.apache.lucene.search.spell.SpellChecker;
+import org.apache.lucene.store.RAMDirectory;
+
+/**
+ * Apache Lucene based {@link Suggestion}.
+ */
+public class LuceneSuggestion implements Suggestion {
+
+    @Override
+    public String[] suggestEndpointOptions(Set<String> names, String option) {
+        StringBuilder sb = new StringBuilder();
+        for (String name : names) {
+            sb.append(name);
+            sb.append("\n");
+        }
+        StringReader reader = new StringReader(sb.toString());
+
+        try {
+            PlainTextDictionary words = new PlainTextDictionary(reader);
+
+            RAMDirectory dir = new RAMDirectory();
+            SpellChecker checker = new SpellChecker(dir);
+            checker.indexDictionary(words, new IndexWriterConfig(new StandardAnalyzer()), false);
+
+            // suggest up to 5 names
+            return checker.suggestSimilar(option, 5);
+        } catch (Exception e) {
+            // ignore
+        }
+
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a6589904/platforms/catalog/src/test/java/org/apache/camel/catalog/lucene/CamelCatalogLuceneTest.java
----------------------------------------------------------------------
diff --git a/platforms/catalog/src/test/java/org/apache/camel/catalog/lucene/CamelCatalogLuceneTest.java b/platforms/catalog/src/test/java/org/apache/camel/catalog/lucene/CamelCatalogLuceneTest.java
new file mode 100644
index 0000000..b1410ea
--- /dev/null
+++ b/platforms/catalog/src/test/java/org/apache/camel/catalog/lucene/CamelCatalogLuceneTest.java
@@ -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
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * 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.camel.catalog.lucene;
+
+import org.apache.camel.catalog.CamelCatalog;
+import org.apache.camel.catalog.DefaultCamelCatalog;
+import org.apache.camel.catalog.EndpointValidationResult;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class CamelCatalogLuceneTest {
+
+    private CamelCatalog catalog;
+
+    @Before
+    public void createCamelCatalog() {
+        catalog = new DefaultCamelCatalog();
+        catalog.enableLuceneSuggestion();
+    }
+
+    @Test
+    public void validateProperties() throws Exception {
+        // spell typo error
+        EndpointValidationResult result = catalog.validateEndpointProperties("log:mylog?levl=WARN");
+        assertFalse(result.isSuccess());
+        assertTrue(result.getUnknown().contains("levl"));
+        assertEquals("level", result.getUnknownSuggestions().get("levl")[0]);
+        assertEquals(1, result.getNumberOfErrors());
+    }
+}