]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.workbench.search/src/org/simantics/workbench/search/Searching.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.workbench.search / src / org / simantics / workbench / search / Searching.java
diff --git a/bundles/org.simantics.workbench.search/src/org/simantics/workbench/search/Searching.java b/bundles/org.simantics.workbench.search/src/org/simantics/workbench/search/Searching.java
new file mode 100644 (file)
index 0000000..00d5de7
--- /dev/null
@@ -0,0 +1,280 @@
+package org.simantics.workbench.search;\r
+\r
+import java.io.CharArrayWriter;\r
+import java.io.File;\r
+import java.io.IOException;\r
+import java.net.URL;\r
+import java.net.URLDecoder;\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.HashSet;\r
+import java.util.List;\r
+import java.util.Map;\r
+import java.util.Set;\r
+\r
+import org.eclipse.core.runtime.FileLocator;\r
+import org.eclipse.core.runtime.Path;\r
+import org.eclipse.core.runtime.Platform;\r
+import org.osgi.framework.Bundle;\r
+import org.simantics.NameLabelMode;\r
+import org.simantics.NameLabelUtil;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.scl.runtime.function.Function;\r
+import org.simantics.scl.runtime.function.Function4;\r
+import org.simantics.utils.datastructures.MapList;\r
+import org.simantics.utils.datastructures.Pair;\r
+\r
+import freemarker.template.Configuration;\r
+import freemarker.template.DefaultObjectWrapper;\r
+import freemarker.template.Template;\r
+import freemarker.template.TemplateException;\r
+\r
+/**\r
+ * @author Tuukka Lehtonen\r
+ * @author Marko Luukkainen\r
+ */\r
+public final class Searching {\r
+       \r
+       static final boolean USE_PAGING = false; // create multipage results (currently paging is handled by DataTables (JavaScript)) \r
+    static final int MAX_PER_PAGE = 100;\r
+    \r
+\r
+    /**\r
+     * @param graph\r
+     * @param query\r
+     * @throws DatabaseException\r
+     */\r
+    public static Collection<Map<String, Object>> performSearch(ReadGraph graph, Resource searchFunction, Resource model, String query, int maxResults)\r
+            throws DatabaseException {\r
+        @SuppressWarnings("unchecked")\r
+        Function4<ReadGraph, Resource, String, Integer, Collection<Map<String, Object>>> f = graph.adapt(searchFunction, Function.class);\r
+        Collection<Map<String, Object>> results = f.apply(graph, model, query, maxResults);\r
+        return results;\r
+    }\r
+\r
+    /**\r
+     * @param graph\r
+     * @param query\r
+     * @param maxResultsPerModel\r
+     * @param results\r
+     * @return\r
+     * @throws IOException\r
+     * @throws TemplateException\r
+     * @throws DatabaseException\r
+     */\r
+    public static List<QueryResult> generatePage(ReadGraph graph, Collection<SearchEngine> searchEngines, SearchQuery query, int maxResultsPerModel, \r
+            MapList<Resource, Pair<SearchEngine,SearchResult>> results) throws IOException, TemplateException, DatabaseException {\r
+        URL fileUrl = getSearchFileURL();\r
+        File dataDir = getAbsoluteFile(fileUrl);\r
+\r
+        SearchData data = new SearchData();\r
+        data.dataUrl = fileUrl.toString();\r
+        data.dataDirectory = dataDir;\r
+        data.query = query;\r
+        data.maxResults = maxResultsPerModel;\r
+        data.model = null;\r
+        data.results = new SearchResult();\r
+        data.resultCount = 0;\r
+        data.searchEngines = searchEngines;\r
+\r
+      \r
+        int resultCount = 0;\r
+        int resultNumber = 0;\r
+        \r
+        int itemsOnPreviousPage = 0;\r
+\r
+        \r
+        List<QueryResult> result = new ArrayList<QueryResult>();\r
+        \r
+        QueryResult header = applyTemplate(graph, "header.ftl", data);\r
+        QueryResult footer = applyTemplate(graph, "footer.ftl", data);\r
+        StringBuilder body = new StringBuilder(1024 * 80);\r
+        \r
+        if (USE_PAGING) {\r
+               List<Pair<SearchEngine, SearchResult>> allResults = results.getAllValuesSnapshot();\r
+               for (Pair<SearchEngine,SearchResult> entry : allResults) {\r
+                        List<SearchResultRow> items = entry.second.rows;\r
+                        resultCount += items.size();\r
+               }\r
+               data.resultCount = resultCount;\r
+               \r
+               \r
+               for (Resource model : results.getKeys()) {\r
+                       List<Pair<SearchEngine,SearchResult>> modelResults = results.getValues(model);\r
+                       for (Pair<SearchEngine,SearchResult> entry : modelResults) {\r
+                       \r
+                       \r
+                               List<SearchResultRow> items = entry.second.rows;\r
+                               int start = 0;\r
+                               int count = items.size();\r
+                               \r
+                               while (count + itemsOnPreviousPage > MAX_PER_PAGE) {\r
+                                       int toPage = MAX_PER_PAGE-itemsOnPreviousPage;\r
+                                       QueryResult content = generateResultTable(graph, query, maxResultsPerModel, data, resultNumber, resultCount, model, entry.first,entry.second.subset(start, start+toPage));\r
+                                       body.append( content.getHtml() );\r
+                                       result.add( new QueryResult(header.getHtml(),body.toString(),footer.getHtml(), resultCount));\r
+                                       start += toPage;\r
+                                       count -= toPage;\r
+                                       itemsOnPreviousPage = 0;\r
+                                       body = new StringBuilder(1024 * 80);\r
+                               }\r
+                               if (count > 0) {\r
+                                       QueryResult content = generateResultTable(graph, query, maxResultsPerModel, data, resultNumber, resultCount, model, entry.first,entry.second.subset(start, start+count));       \r
+                                       body.append( content.getHtml() );\r
+                                       itemsOnPreviousPage += count;\r
+                               }\r
+\r
+                           ++resultNumber;\r
+                 \r
+                   \r
+                       }\r
+               }\r
+               if (body.length() > 0)\r
+                       result.add( new QueryResult(header.getHtml(),body.toString(),footer.getHtml(), resultCount));\r
+        } else {\r
+               List<Pair<SearchEngine, SearchResult>> allResults = results.getAllValuesSnapshot();\r
+               for (Pair<SearchEngine,SearchResult> entry : allResults) {\r
+                        List<SearchResultRow> items = entry.second.rows;\r
+                        resultCount += items.size();\r
+               }\r
+               data.resultCount = resultCount;\r
+               \r
+                for (Resource model : results.getKeys()) {\r
+                        List<Pair<SearchEngine,SearchResult>> modelResults = results.getValues(model);\r
+                        for (Pair<SearchEngine,SearchResult> entry : modelResults) {\r
+                                QueryResult content = generateResultTable(graph, query, maxResultsPerModel, data, resultNumber, resultCount, model, entry.first, entry.second);        \r
+                                body.append( content.getHtml() );\r
+                                ++resultNumber;\r
+                       }\r
+                }\r
+                result.add( new QueryResult(header.getHtml(),body.toString(),footer.getHtml(), resultCount));\r
+        }\r
+        if (result.size() == 0) {\r
+               result.add( new QueryResult(header.getHtml(),body.toString(),footer.getHtml(), resultCount));\r
+        }\r
+\r
+        return result;\r
+\r
+        \r
+    }\r
+\r
+    /**\r
+     * @param graph\r
+     * @param query\r
+     * @param maxResultsPerModel\r
+     * @param resultNumber \r
+     * @param results\r
+     * @return\r
+     * @throws IOException\r
+     * @throws TemplateException\r
+     * @throws DatabaseException\r
+     */\r
+    public static QueryResult generateResultTable(ReadGraph graph, SearchQuery query, int maxResultsPerModel,\r
+            SearchData template, int resultNumber, int resultCount, Resource model, SearchEngine searchEngine, SearchResult results)\r
+                    throws IOException, TemplateException, DatabaseException {\r
+        SearchData data = template.clone();\r
+        data.resultNumber = resultNumber;\r
+        data.query = query;\r
+        data.maxResults = maxResultsPerModel;\r
+        data.model = NamedResource.of(graph, model);\r
+        data.results = results;\r
+        data.searchEngine = searchEngine;\r
+\r
+        return applyTemplate(graph, "searchtable.ftl", data);\r
+    }\r
+\r
+    /**\r
+     * @return\r
+     * @throws IOException\r
+     */\r
+    private static URL getSearchFileURL() throws IOException {\r
+        Bundle b = Platform.getBundle(Activator.PLUGIN_ID);\r
+        URL dataUrl = FileLocator.find(b, new Path("search"), null);\r
+        if (dataUrl == null)\r
+            throw new IOException("Could not find search template data");\r
+\r
+        URL fileUrl = FileLocator.toFileURL(dataUrl);\r
+        return fileUrl;\r
+    }\r
+\r
+    /**\r
+     * @return\r
+     * @throws IOException\r
+     */\r
+    private static File getAbsoluteFile(URL fileUrl) throws IOException {\r
+        File dataDir = new File(URLDecoder.decode(fileUrl.getPath(), "UTF-8")).getAbsoluteFile();\r
+        return dataDir;\r
+    }\r
+\r
+    \r
+    /**\r
+     * @param graph\r
+     * @param templateName\r
+     * @param data\r
+     * @return\r
+     * @throws IOException\r
+     * @throws TemplateException\r
+     * @throws DatabaseException\r
+     */\r
+    public static QueryResult applyTemplate(ReadGraph graph, String templateName, SearchData data)\r
+            throws IOException, TemplateException, DatabaseException {\r
+        Configuration cfg = new Configuration();\r
+        cfg.setDirectoryForTemplateLoading(data.getDataDirectory());\r
+        cfg.setObjectWrapper(new DefaultObjectWrapper());\r
+\r
+        Template temp = cfg.getTemplate(templateName);\r
+        CharArrayWriter writer = new CharArrayWriter(1024 * 128);\r
+        temp.process(data, writer);\r
+\r
+        return new QueryResult(writer.toString(), data.results.rows.size());\r
+    }\r
+\r
+    /**\r
+     * @param graph\r
+     * @param results\r
+     * @return map: model -> SearchResult\r
+     * @throws DatabaseException\r
+     */\r
+    public static final SearchResult generateDependenciesSearchResult(ReadGraph graph,\r
+            Collection<Map<String, Object>> results) throws DatabaseException {\r
+        Set<Resource> processed = new HashSet<Resource>();\r
+        SearchResult result = new SearchResult(NameAndTypeRow.columns);\r
+\r
+        NameLabelMode mode = NameLabelUtil.getNameLabelMode(graph);\r
+\r
+        for (Map<String, Object> r : results) {\r
+            Resource resource = (Resource) r.get("Resource");\r
+\r
+            // Prevent index corruption from producing duplicate results.\r
+            if (!processed.add(resource))\r
+                continue;\r
+\r
+            Resource parent = (Resource) r.get("Parent");\r
+            String name = (String) r.get("Name");\r
+\r
+            NameAndTypeRow rst = new NameAndTypeRow();\r
+            rst.resource = NamedResource.of(graph, resource, name);\r
+            rst.parent = NamedResource.of(graph, parent, NameLabelUtil.modalName(graph, parent, mode));\r
+\r
+            Collection<Resource> typeResources = graph.getTypes(resource);\r
+            Collection<Resource> principalTypeResources = graph.getPrincipalTypes(resource);\r
+            if (!typeResources.isEmpty()) {\r
+                rst.types = new ArrayList<NamedResource>(typeResources.size());\r
+                rst.principalTypes = new ArrayList<NamedResource>(principalTypeResources.size());\r
+                for (Resource t : typeResources) {\r
+                    NamedResource nr = NamedResource.of(graph, t);\r
+                    rst.types.add(nr);\r
+                    if (principalTypeResources.contains(t))\r
+                        rst.principalTypes.add(nr);\r
+                }\r
+            }\r
+\r
+            result.addRow(rst);\r
+        }\r
+\r
+        return result;\r
+    }\r
+\r
+}\r