/*
* Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
* Copyright (C) 2015 - Marcos CARDINOT
+ * Copyright (C) 2017 - Scilab Enterprises - Clement DAVID
*
* This file must be used under the terms of the CeCILL.
* This source file is licensed as described in the file COPYING, which
* http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
*
*/
-
package org.scilab.modules.xcos.palette;
import java.io.BufferedReader;
import java.io.File;
-import java.io.FileInputStream;
-import java.io.FilenameFilter;
import java.io.IOException;
-import java.io.InputStream;
import java.io.InputStreamReader;
-import java.nio.charset.StandardCharsets;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Hashtable;
import java.util.List;
-import java.util.Set;
-import java.util.Map.Entry;
-
+import java.util.Map;
+import java.util.Optional;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.logging.Level;
+import java.util.logging.Logger;
import org.apache.lucene.document.Document;
+
import org.apache.lucene.document.Field;
import org.apache.lucene.document.StringField;
import org.apache.lucene.document.TextField;
/**
* Index the help pages of all blocks.
+ *
* @author Marcos Cardinot <mcardinot@gmail.com>
*/
public final class PaletteIndexer {
private PaletteSearchManager mgr;
- private List<String> roots;
+ private List<File> roots;
/**
* Default constructor
+ *
* @param psm PaletteSearchManager
*/
public PaletteIndexer(PaletteSearchManager psm) {
mgr = psm;
// javaHelp directories
- roots = new ArrayList<String>();
- roots.add(ScilabConstants.SCI.getAbsolutePath() + "/modules/helptools/javaHelp");
+ roots = new ArrayList<>();
+
+ // for local builds
+ roots.add(new File(ScilabConstants.SCI.getAbsolutePath() + "/modules/helptools/javaHelp"));
+
+ // for binary version
+ roots.add(new File(ScilabConstants.SCI.getAbsolutePath() + "/modules/helptools/jar"));
}
- /**
- * @param ht Hashtable
- */
- public void createIndex(Hashtable<String, List<PaletteBlock>> ht) {
+ public void createIndex(Map<String, PaletteBlock> blockNameToPalette) {
try {
mgr.getIndexWriter().deleteAll();
- Set< Entry<String, List<PaletteBlock>> > treePaths = ht.entrySet();
- for (Entry<String, List<PaletteBlock>> entry : treePaths) {
- String treePath = entry.getKey();
- List<PaletteBlock> blocks = entry.getValue();
- for (PaletteBlock block : blocks) {
- indexBlock(treePath, block.getName());
+
+ // insert all block names
+ for (String blk : blockNameToPalette.keySet()) {
+ index(blk);
+ }
+
+ // insert all help pages
+ for (File r : roots) {
+ if (!r.exists()) {
+ continue;
}
+
+ Files.walkFileTree(r.toPath(), new SimpleFileVisitor<Path>() {
+ @Override
+ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+ String fname = file.getFileName().toString();
+ int dot = fname.lastIndexOf('.');
+ if (dot <= 0) {
+ return FileVisitResult.CONTINUE;
+ }
+
+ String basename = fname.substring(0, dot);
+ if (fname.endsWith(".jar")) {
+ try (JarFile jf = new JarFile(file.toFile())) {
+ index(file.toAbsolutePath().toUri().toString(), basename, jf, blockNameToPalette);
+ }
+ } else if (fname.endsWith(".html")) {
+ // this is a regular file
+ if (blockNameToPalette.containsKey(basename)) {
+ index(basename, file.toUri().toURL());
+ }
+ }
+
+ return FileVisitResult.CONTINUE;
+ }
+ });
}
+
mgr.getIndexWriter().commit();
- } catch (IOException e) {
- e.printStackTrace();
+ } catch (IOException ex) {
+ Logger.getLogger(PaletteIndexer.class.getName()).log(Level.SEVERE, null, ex);
}
}
- /**
- * @param treePath tree path
- * @param blockName block name
- * @throws IOException If there is a low-level I/O error
- */
- private void indexBlock(String treePath, String blockName) throws IOException {
- Document doc = new Document();
- doc.add(new StringField("blockName", blockName, Field.Store.YES));
- doc.add(new StringField("treePath", treePath, Field.Store.YES));
-
- List<File> helpPages = findHelpPages(blockName);
- if (helpPages.isEmpty()) {
- doc.add(new TextField("helpPage", blockName, Field.Store.YES));
- } else {
- for (File helpPage : helpPages) {
- InputStream stream = new FileInputStream(helpPage);
- doc.add(new StringField("filePath", helpPage.getAbsolutePath(), Field.Store.YES));
- doc.add(new TextField("helpPage", new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8))));
+ private void index(String fileURI, String basename, JarFile jf, Map<String, PaletteBlock> blockNameToTreePath) {
+ class Entry {
+
+ Entry(JarEntry jarEntry) {
+ je = jarEntry;
}
- }
- mgr.getIndexWriter().addDocument(doc);
- }
+ JarEntry je;
+ String blk;
+ URL url;
- /**
- * @param blockName block name
- * @return File[]
- */
- private List<File> findHelpPages(final String blockName) {
- List<String> subdirs = new ArrayList<String>();
- for (String root : roots) {
- File r = new File(root);
- if (!r.exists()) {
- continue;
+ boolean block() {
+ int slash = je.getName().lastIndexOf('/') + 1;
+ int dot = je.getName().lastIndexOf('.');
+ if (slash < 0 || dot < 0) {
+ return false;
+ }
+
+ blk = je.getName().substring(slash, dot);
+ return true;
}
- String[] ss = r.list(new FilenameFilter() {
- @Override
- public boolean accept(File current, String name) {
- return new File(current, name).isDirectory();
+ boolean url() {
+ try {
+ // we have to generate a url in the form before indexing
+ // jar:file:/modules/helptools/jar/scilab_en_US_help.jar!/scilab_en_US_help/blockName.html
+ url = new URL("jar:" + fileURI + "!/" + basename + '/' + blk + ".html");
+ } catch (MalformedURLException ex) {
+ Logger.getLogger(PaletteIndexer.class.getName()).log(Level.SEVERE, null, ex);
}
- });
- for (int i = 0; i < ss.length; ++i) {
- ss[i] = root + File.separator + ss[i];
+ return true;
}
- subdirs.addAll(Arrays.asList(ss));
}
- List<File> helpPages = new ArrayList<File>();
- for (String dir : subdirs) {
- File file = new File(dir + File.separator + blockName + ".html");
- if (file.exists()) {
- helpPages.add(file);
+ jf.stream()
+ .map(je -> new Entry(je))
+ .filter(e -> e.block())
+ .filter(e -> blockNameToTreePath.containsKey(e.blk))
+ .filter(e -> e.url())
+ .forEach(e -> index(e.blk, e.url));
+ }
+
+ private void index(String basename, URL url) {
+ try {
+ Document doc = new Document();
+
+ // add the block name
+ Field refname = new TextField("refname", basename, Field.Store.YES);
+ refname.setBoost(100f);
+ doc.add(refname);
+
+ // add the refpurpose
+ try (BufferedReader r = new BufferedReader(new InputStreamReader(url.openStream()))) {
+ Optional<String> found = r.lines().filter(l -> l.contains("refpurpose")).findFirst();
+
+ Field refpurpose;
+ if (found.isPresent()) {
+ refpurpose = new TextField("refpurpose", found.get(), Field.Store.YES);
+ } else {
+ refpurpose = new TextField("refpurpose", "", Field.Store.YES);
+ }
+
+ refpurpose.setBoost(10f);
+ doc.add(refpurpose);
}
+
+ // add the html content
+ try (BufferedReader r = new BufferedReader(new InputStreamReader(url.openStream()))) {
+ doc.add(new TextField("content", r));
+ }
+
+ mgr.getIndexWriter().addDocument(doc);
+ } catch (IOException e) {
+ Logger.getLogger(PaletteIndexer.class.getName()).log(Level.SEVERE, null, e);
+ }
+ }
+
+ private void index(String block) {
+ try {
+ Document doc = new Document();
+ doc.add(new StringField("refname", block, Field.Store.YES));
+ doc.add(new StringField("refpurpose", block, Field.Store.YES));
+ doc.add(new TextField("content", block, Field.Store.YES));
+
+ mgr.getIndexWriter().addDocument(doc);
+ } catch (IOException e) {
+ Logger.getLogger(PaletteIndexer.class.getName()).log(Level.SEVERE, null, e);
}
- return helpPages;
}
}
/*
* Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
* Copyright (C) 2015 - Marcos CARDINOT
+ * Copyright (C) 2017 - Scilab Enterprises - Clement DAVID
*
* This file must be used under the terms of the CeCILL.
* This source file is licensed as described in the file COPYING, which
import java.io.File;
import java.io.IOException;
-import java.util.Hashtable;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
import javax.swing.JScrollPane;
import javax.swing.tree.TreeModel;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
+import org.apache.lucene.document.Document;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.IndexWriterConfig.OpenMode;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.RAMDirectory;
-import org.scilab.modules.xcos.palette.PaletteIndexer;
-import org.scilab.modules.xcos.palette.PaletteSearcher;
-import org.scilab.modules.xcos.palette.model.PaletteBlock;
import org.scilab.modules.xcos.palette.model.PaletteBlock;
import org.scilab.modules.xcos.palette.model.PaletteNode;
import org.scilab.modules.xcos.palette.model.PreLoaded;
private PaletteIndexer paletteIndexer;
private PaletteSearcher paletteSearcher;
private PaletteSearchView view;
- private Hashtable<String, List<PaletteBlock>> ht;
+ private Map<String, PaletteBlock> nameToPalette;
/** Default constructor */
public PaletteSearchManager() {
IndexWriterConfig config = new IndexWriterConfig(analyzer);
config.setOpenMode(OpenMode.CREATE);
writer = new IndexWriter(ramDir, config);
- } catch (IOException e) {
- e.printStackTrace();
+ } catch (IOException ex) {
+ Logger.getLogger(PaletteSearchManager.class.getName()).log(Level.SEVERE, null, ex);
}
+ nameToPalette = new HashMap<>();
view = new PaletteSearchView();
paletteIndexer = new PaletteIndexer(this);
paletteSearcher = new PaletteSearcher(this);
- ht = new Hashtable<String, List<PaletteBlock>>();
}
/**
indexIsOutdated = false;
}
- List<String> blockPaths = paletteSearcher.search(query);
- for (String blockPath : blockPaths) {
- PaletteBlock block = getBlock(blockPath);
+ List<Document> found = paletteSearcher.search(query);
+ for (Document doc : found) {
+ PaletteBlock block = nameToPalette.get(doc.get("refname"));
if (block != null) {
view.addBlock(block);
}
}
- view.setText(queryLabel + blockPaths.size() + " " + XcosMessages.MATCHES);
+ view.setText(queryLabel + found.size() + " " + XcosMessages.MATCHES);
view.revalidate();
scrollPane.revalidate();
}
TreeModel model = PaletteManagerView.get().getTree().getModel();
if (model != null) {
loadHashTable(model, model.getRoot(), "");
- paletteIndexer.createIndex(ht);
+ paletteIndexer.createIndex(nameToPalette);
}
}
for (int i = 0; i < cc; ++i) {
PaletteNode node = (PaletteNode) model.getChild(obj, i);
if (node instanceof PreLoaded) {
- ht.put(treePath + File.separator + node.getName(),
- ((PreLoaded) node).getBlock());
+ for (PaletteBlock b : ((PreLoaded) node).getBlock()) {
+ nameToPalette.put(b.getName(), b);
+ }
} else {
- loadHashTable(model,
- node,
- treePath + File.separator + node.toString());
+ loadHashTable(model, node, treePath + File.separator + node.toString());
}
}
}
public IndexWriter getIndexWriter() {
return writer;
}
-
- /**
- * Get block
- * @param blockPath the block path
- * @return PaletteBlock
- */
- public PaletteBlock getBlock(String blockPath) {
- int lastSeparator = blockPath.lastIndexOf(File.separator);
- String treePath = blockPath.substring(0, lastSeparator);
- String blockName = blockPath.substring(lastSeparator + 1);
- List<PaletteBlock> blocks = ht.get(treePath);
- if (blocks == null) {
- return null;
- }
-
- for (PaletteBlock block : blocks) {
- if (blockName.equals(block.getName())) {
- return block;
- }
- }
- return null;
- }
}
/*
* Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
* Copyright (C) 2015 - Marcos CARDINOT
+ * Copyright (C) 2017 - Scilab Enterprises - Clement DAVID
*
* This file must be used under the terms of the CeCILL.
* This source file is licensed as described in the file COPYING, which
package org.scilab.modules.xcos.palette;
-import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
-import org.apache.lucene.queryparser.classic.ParseException;
-import org.apache.lucene.queryparser.classic.QueryParser;
+import org.apache.lucene.queryparser.flexible.core.QueryNodeException;
+import org.apache.lucene.queryparser.flexible.standard.StandardQueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
public final class PaletteSearcher {
private PaletteSearchManager mgr;
- private QueryParser parser;
/**
- * Default constructor
+ * Default constructor
* @param psm PaletteSearchManager
*/
public PaletteSearcher(PaletteSearchManager psm) {
mgr = psm;
- parser = new QueryParser("helpPage", mgr.getAnalyzer());
- parser.setAllowLeadingWildcard(true);
}
/**
* @param str Query
* @return paths to the found blocks
*/
- public List<String> search(String str) {
- List<String> blockPaths = new ArrayList<String>();
- try {
- IndexReader reader = DirectoryReader.open(mgr.getIndexWriter(), true);
+ public List<Document> search(String str) {
+ List<Document> found = new ArrayList<>();
+ try (IndexReader reader = DirectoryReader.open(mgr.getIndexWriter(), true)) {
IndexSearcher searcher = new IndexSearcher(reader);
- // escape special characters -- except *
- String escaped = QueryParser.escape(str);
- escaped = escaped.replaceAll("\\\\\\*", "*");
+ StandardQueryParser queryParserHelper = new StandardQueryParser();
+ queryParserHelper.setAllowLeadingWildcard(true);
+ queryParserHelper.setLowercaseExpandedTerms(true);
+ queryParserHelper.setAnalyzer(mgr.getAnalyzer());
+ queryParserHelper.setMultiFields(new String[] {"refname", "refpurpose", "content"});
- Query query = parser.parse(escaped);
+ Query query = queryParserHelper.parse(str, null);
TopDocs results = searcher.search(query, XcosConstants.MAX_HITS);
ScoreDoc[] hits = results.scoreDocs;
- if (hits.length == 0 && !str.contains("*")) {
- escaped = "*" + escaped + "*";
- query = parser.parse(escaped);
+ if (hits.length == 0) {
+ query = queryParserHelper.parse("*" + str + "*", null);
results = searcher.search(query, XcosConstants.MAX_HITS);
hits = results.scoreDocs;
}
for (int i = 0; i < hits.length; i++) {
Document doc = searcher.doc(hits[i].doc);
- blockPaths.add(doc.get("treePath") + File.separator + doc.get("blockName"));
+ found.add(doc);
}
- reader.close();
- } catch (IOException e) {
- e.printStackTrace();
- } catch (ParseException e) {
- e.printStackTrace();
+ } catch (IOException | QueryNodeException e) {
+ Logger.getLogger(PaletteSearcher.class.getName()).log(Level.SEVERE, null, e);
}
- return blockPaths;
+ return found;
}
}