X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.workbench%2Fsrc%2Forg%2Fsimantics%2Fworkbench%2Finternal%2Fcontributions%2Fsearch%2FSearchServiceImpl.java;fp=bundles%2Forg.simantics.workbench%2Fsrc%2Forg%2Fsimantics%2Fworkbench%2Finternal%2Fcontributions%2Fsearch%2FSearchServiceImpl.java;h=0000000000000000000000000000000000000000;hp=733bebddf2fc6460723309bfef5a9837fc251395;hb=38d133f2a39bab76deed5d047fbabee4479b5373;hpb=a9e5abf29200550168557ae2c7e0a6e2442f6c2b diff --git a/bundles/org.simantics.workbench/src/org/simantics/workbench/internal/contributions/search/SearchServiceImpl.java b/bundles/org.simantics.workbench/src/org/simantics/workbench/internal/contributions/search/SearchServiceImpl.java deleted file mode 100644 index 733bebddf..000000000 --- a/bundles/org.simantics.workbench/src/org/simantics/workbench/internal/contributions/search/SearchServiceImpl.java +++ /dev/null @@ -1,671 +0,0 @@ -package org.simantics.workbench.internal.contributions.search; - -import java.io.File; -import java.io.IOException; -import java.net.MalformedURLException; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.URL; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.NullProgressMonitor; -import org.eclipse.core.runtime.Status; -import org.eclipse.core.runtime.SubMonitor; -import org.eclipse.core.runtime.jobs.Job; -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.jface.viewers.StructuredSelection; -import org.eclipse.swt.SWT; -import org.eclipse.swt.browser.LocationEvent; -import org.eclipse.swt.browser.LocationListener; -import org.eclipse.swt.events.DisposeEvent; -import org.eclipse.swt.events.DisposeListener; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.ui.IViewPart; -import org.eclipse.ui.IViewReference; -import org.eclipse.ui.IWorkbenchPage; -import org.eclipse.ui.IWorkbenchWindow; -import org.eclipse.ui.PartInitException; -import org.eclipse.ui.PlatformUI; -import org.simantics.ObjectIdentitySchedulingRule; -import org.simantics.Simantics; -import org.simantics.databoard.Bindings; -import org.simantics.db.ReadGraph; -import org.simantics.db.Resource; -import org.simantics.db.Session; -import org.simantics.db.exception.DatabaseException; -import org.simantics.db.layer0.adapter.Instances; -import org.simantics.db.layer0.genericrelation.Dependencies; -import org.simantics.db.layer0.request.ActiveModels; -import org.simantics.db.request.Read; -import org.simantics.db.service.SerialisationSupport; -import org.simantics.editors.Browser; -import org.simantics.editors.BrowserInput; -import org.simantics.layer0.Layer0; -import org.simantics.scl.runtime.function.Function; -import org.simantics.scl.runtime.function.Function5; -import org.simantics.ui.workbench.action.ChooseActionRequest; -import org.simantics.utils.FileUtils; -import org.simantics.utils.datastructures.MapList; -import org.simantics.utils.datastructures.Pair; -import org.simantics.utils.ui.ErrorLogger; -import org.simantics.utils.ui.ExceptionUtils; -import org.simantics.utils.ui.workbench.WorkbenchUtils; -import org.simantics.workbench.internal.Activator; -import org.simantics.workbench.ontology.WorkbenchResource; -import org.simantics.workbench.search.ISearchService; -import org.simantics.workbench.search.QueryResult; -import org.simantics.workbench.search.SearchEngine; -import org.simantics.workbench.search.SearchQuery; -import org.simantics.workbench.search.SearchResult; -import org.simantics.workbench.search.Searching; - -import freemarker.template.TemplateException; - -/** - * @author Tuukka Lehtonen - * @author Marko Luukkainen - */ -public class SearchServiceImpl implements ISearchService{ - - private static final String SEARCH_TEMP_FILE_SUFFIX = "search.html"; - private static final String SEARCH_TEMP_DIR = "search"; - private static final String BROWSER_VIEW = BrowserView.ID; - private static final Integer MAX_RESULTS = 1000; - - @Override - public void performQuery(SearchQuery query, ResultBrowser browserType, boolean activateResultBrowser) { - try { - Set searchEngines = getSearchEngines(); - - // if query does not define used engines, use all available engines. - boolean containsEngines = false; - for (SearchEngine e : searchEngines) { - if (query.getSearchFlags().containsKey(e.getId())) { - containsEngines = true; - break; - } - } - if (!containsEngines) { - for (SearchEngine e : searchEngines) - if (e.isEnabledByDefault()) - query.setSearchFlag(e.getId(), "on"); - } - } catch (DatabaseException e) { - ExceptionUtils.logError(e); - } - switch (browserType) { - case EDITOR: - performEditorQuery(query); - break; - case VIEW: - performViewQuery(query, activateResultBrowser); - break; - } - - } - - private void performViewQuery(SearchQuery query, boolean activateResultBrowser) { - try { - browserView = (BrowserView) showLocalView( - BROWSER_VIEW, - activateResultBrowser ? IWorkbenchPage.VIEW_ACTIVATE : IWorkbenchPage.VIEW_CREATE); - if (browserView.getBrowser() != browserViewBrowser) { - browserViewBrowser = browserView.getBrowser(); - browserViewTemporaryFiles = new ArrayList(); - browserViewTemporaryFiles.add(getNewTemporaryFile()); - browserView.getBrowser().addLocationListener(browserViewLocationListener); - browserView.getBrowser().addDisposeListener(new DisposeListener() { - @Override - public void widgetDisposed(DisposeEvent e) { - browserViewBrowser = null; - } - }); - } - browserView.setPartProperty(BrowserView.LAST_QUERY_PROPERTY, query.getOriginalQuery()); - updateViewQuery(browserView, browserViewTemporaryFiles, query); - } catch (IOException e1) { - ErrorLogger.defaultLogError(e1); - } catch (PartInitException e1) { - ErrorLogger.defaultLogError(e1); - } - } - - private IViewPart showLocalView(String id, int mode) throws PartInitException { - final IWorkbenchWindow wb = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); - if (wb == null) - return null; - - // Is view already created in the currently active workbench window? - IViewPart vp = findViewFromWindow(wb, id, false); - if (vp != null) { - if (mode == IWorkbenchPage.VIEW_CREATE) - return vp; - IWorkbenchPage page = vp.getViewSite().getPage(); - if (mode == IWorkbenchPage.VIEW_VISIBLE) { - page.bringToTop(vp); - } else if (mode == IWorkbenchPage.VIEW_ACTIVATE) { - page.activate(vp); - } - return vp; - } - - // Create the view on the active window's active page - IWorkbenchPage page = wb.getActivePage(); - if (page == null) { - IWorkbenchPage pages[] = wb.getPages(); - if (pages.length == 0) return null; - page = pages[0]; - } - return page.showView(id, null, mode); - } - - private static IViewPart findViewFromWindow(IWorkbenchWindow wb, String viewId, boolean restore) { - for (IWorkbenchPage page : wb.getPages()) { - IViewReference vr = page.findViewReference(viewId); - if (vr != null) { - IViewPart vp = vr.getView(restore); - if (vp != null) - return vp; - } - } - return null; - } - - /** - * There's always only one of these around. - */ - BrowserView browserView = null; - - org.eclipse.swt.browser.Browser browserViewBrowser = null; - - List browserViewTemporaryFiles = null; - - LocationListener browserViewLocationListener = new LocationListener() { - @Override - public void changing(LocationEvent event) { - //System.out.println("changing: " + event); - try { - URI newUri = new URI(event.location); - - // Handle resource links by opening an editor for them - if ("resource".equals(newUri.getScheme())) { - event.doit = false; - openResource(getShell(event), newUri.getSchemeSpecificPart()); - return; - } - } catch (URISyntaxException e) { - // This URI was not needed anyway, resource: URIs will always parse properly so let - // it go without logging. - } catch (DatabaseException e) { - ErrorLogger.defaultLogError(e); - } - } - - @Override - public void changed(LocationEvent event) { - // System.out.println("changed: " + event); - try { - URL newUrl = new URL(event.location); - String query = newUrl.getQuery(); - if (query != null) { - SearchQuery searchQuery = SearchQuery.decode(newUrl); - if (searchQuery.getOriginalQuery() != null) { - event.doit = updateViewQuery( - browserView, - browserViewTemporaryFiles, - searchQuery); - - } - } - } catch (IOException e) { - ErrorLogger.defaultLogError(e); - } - } - }; - - class ViewQueryJob extends Job { - - SearchQuery query; - - List temporaryFiles; - - BrowserView browserView; - - Display display; - - public ViewQueryJob(SearchQuery query, List temporaryFiles, BrowserView browserView) { - super("Search..."); - this.query = query; - this.temporaryFiles = temporaryFiles; - this.browserView = browserView; - this.display = browserView.getBrowser().getDisplay(); - } - - @Override - protected IStatus run(IProgressMonitor monitor) { - try { - SubMonitor mon = SubMonitor.convert(monitor); - monitor.beginTask("Performing search '" + query + "'", 10); - monitor.subTask("Querying index"); - final List result = createResultPage(mon.newChild(8), query, MAX_RESULTS); - if (result == null) { - return Status.CANCEL_STATUS; - } - monitor.worked(8); - monitor.subTask("Generating results"); - updatePages(result, temporaryFiles); - monitor.worked(2); - updateBrowser(browserView, result.get(0)); - return Status.OK_STATUS; - } catch (DatabaseException e1) { - return new Status(IStatus.ERROR, Activator.PLUGIN_ID, - "Unexpected database problems during search result processing, see exception.", e1); - } catch (IOException e1) { - return new Status(IStatus.ERROR, Activator.PLUGIN_ID, - "Unexpected I/O problems during search result processing, see exception.", e1); - } finally { - monitor.done(); - } - } - - void updateBrowser(final BrowserView browserView, final QueryResult result) { - if (display.isDisposed()) - return; - display.asyncExec(new Runnable() { - @Override - public void run() { - if (browserView.isDisposed()) - return; - - try { - long t1 = System.currentTimeMillis(); - browserView.setUrl(temporaryFiles.get(0).toURI().toURL()); - //browserView.setContentDescription("'" + query + "' - " + result.getHitCount() + " matches in active model"); - long t2 = System.currentTimeMillis(); - System.out.println("Updating UI " + (t2-t1) + " ms"); - } catch (MalformedURLException e) { - ErrorLogger.defaultLogError(e); - } - } - }); - } - } - - protected boolean updateViewQuery(BrowserView browserView, List temporaryFiles, SearchQuery query) { - ViewQueryJob job = new ViewQueryJob(query, temporaryFiles, browserView); - job.setRule(new ObjectIdentitySchedulingRule(browserView)); - job.schedule(); - return true; - } - - protected Shell getShell(LocationEvent event) { - if (event.widget instanceof Control) { - Control c = (Control) event.widget; - if (c.isDisposed()) - return null; - return c.getShell(); - } - return null; - } - - /** - * @param query - */ - protected void performEditorQuery(final SearchQuery query) { - try { - final List temporaryFiles = new ArrayList(); - temporaryFiles.add(getNewTemporaryFile()); - final BrowserInput input = createBrowserInput(temporaryFiles.get(0), query); - updateInput(input, temporaryFiles.get(0), query); - - final Browser browser = (Browser) WorkbenchUtils.openEditor("org.simantics.editors.browser", input); - - browser.getBrowser().addLocationListener(new LocationListener() { - @Override - public void changing(LocationEvent event) { - // System.out.println("changing: " + event); - try { - // TODO : is there a better way to escape location? - URI newUri = new URI(event.location.replaceAll(" ", "%20")); - // Handle resource links by opening an editor for them - if ("resource".equals(newUri.getScheme())) { - event.doit = false; - openResource(getShell(event), newUri.getSchemeSpecificPart()); - return; - } - } catch (URISyntaxException e) { - ErrorLogger.defaultLogError(e); - } catch (DatabaseException e) { - ErrorLogger.defaultLogError(e); - } - } - - @Override - public void changed(LocationEvent event) { - if (query != null) { - // OpenEditor does not seem to pass any parameters (anything after '?' character) - SearchQuery searchQuery = query; - if (searchQuery.getOriginalQuery() != null) { - event.doit = updateQuery(browser, input, temporaryFiles, searchQuery); - } - } - } - }); - } catch (IOException e1) { - ErrorLogger.defaultLogError(e1); - } catch (PartInitException e1) { - ErrorLogger.defaultLogError(e1); - } - } - - protected void openResource(Shell shell, String link) throws DatabaseException { - try { - Session session = Simantics.getSession(); - final long id = Long.parseLong(link); - - Resource resource = session.syncRequest(new Read() { - @Override - public Resource perform(ReadGraph graph) throws DatabaseException { - SerialisationSupport ss = graph.getService(SerialisationSupport.class); - return ss.getResource(id); - } - }); - - ISelection input = new StructuredSelection(resource); - String perspectiveId = WorkbenchUtils.getCurrentPerspectiveId(); - - // Try the doubleClick-extensions - session.asyncRequest(new ChooseActionRequest(shell, input, perspectiveId, false, true)); - } catch (NumberFormatException e) { - return; - } - } - - /** - * @param query - */ - protected static boolean updateQuery(Browser browser, BrowserInput input, List temporaryFiles, final SearchQuery query) { - try { - String url = browser.getBrowser().getUrl(); - String inputUrl = input.getUrl().toString(); - if (url.equals(inputUrl)) - return false; - - List result = createResultPage(new NullProgressMonitor(), query, MAX_RESULTS); - updateInput(input, temporaryFiles.get(0), query); - updatePages(result,temporaryFiles); - // browser.getBrowser().setUrl(inputUrl); - browser.getBrowser().refresh(); - // temporaryFile.delete(); - for (File temporaryFile : temporaryFiles) - temporaryFile.deleteOnExit(); - return true; - } catch (DatabaseException e1) { - ErrorLogger.defaultLogError(e1); - } catch (IOException e1) { - ErrorLogger.defaultLogError(e1); - } - return false; - } - - private static File ensureTemporaryDirectoryExists() throws IOException { - return Simantics.getTemporaryDirectory(SEARCH_TEMP_DIR); - } - - /** - * @param html - * @return - * @throws IOException - */ - private static File getNewTemporaryFile() throws IOException { - return Simantics.getTempfile(SEARCH_TEMP_DIR, SEARCH_TEMP_FILE_SUFFIX); - } - - /** - * @param query - * @param html - * @return - * @throws IOException - */ - private static BrowserInput createBrowserInput(File file, SearchQuery query) throws IOException { - // new BrowserInput(file.toURI().toURL() - return new BrowserInput(SearchQuery.encode(file, query), query.getOriginalQuery(), false, false, SWT.NONE); - } - - private static void updatePages(List result, List temporaryFiles) throws IOException{ - ensureTemporaryDirectoryExists(); - for (int i = temporaryFiles.size(); i < result.size(); i++) { - temporaryFiles.add(getNewTemporaryFile()); - } - if (result.size() > 1) { - createPageControls(result,temporaryFiles); - } - if (result.size() > 0) { - for (int i = 0; i < result.size(); i++) { - updatePage(temporaryFiles.get(i), result.get(i).getHtml()); - } - } else { - updatePage(temporaryFiles.get(0), ""); - } - } - - /** - * @param html - * @return - * @throws IOException - */ - private static void updatePage(File file, String html) throws IOException { - long t1 = System.currentTimeMillis(); - FileUtils.writeFile(file, html.getBytes("UTF-8")); - long t2 = System.currentTimeMillis(); - System.out.println("Writing html page took " + (t2-t1) + " ms"); - } - - private static void createPageControls(List result, List temporaryFiles) throws IOException{ - if (result.size() == 1) - return; - for (int i = 0; i < result.size(); i++) { - boolean first = i == 0; - boolean last = i == result.size() -1; - QueryResult current = result.get(i); - String pageContrtol = "
"; - pageContrtol += "Page " + (i+1) + " of "+ + result.size() + " "; - if (first) { - pageContrtol += "First"; - pageContrtol += " Previous"; - pageContrtol += " Next"; - pageContrtol += " Last"; - } else if (last) { - pageContrtol += "First"; - pageContrtol += " Previous"; - pageContrtol += " Next"; - pageContrtol += " Last"; - } else { - pageContrtol += "First"; - pageContrtol += " Previous"; - pageContrtol += " Next"; - pageContrtol += " Last"; - } - pageContrtol += "

"; - - result.set(i, new QueryResult(current.getHeader(), pageContrtol+current.getContent()+pageContrtol,current.getFooter(),current.getHitCount())); - } - - } - - - - /** - * @param html - * @return - * @throws IOException - */ - private static void updateInput(BrowserInput input, File file, SearchQuery query) throws IOException { - URL url = SearchQuery.encode(file, query); - input.setUrl(url); - input.setName(query.getOriginalQuery()); - // System.out.println("update input: " + url + " - " + query + " - " + input); - } - - private static Set getSearchEngines() throws DatabaseException{ - return Simantics.getSession().syncRequest(new Read>() { - @Override - public Set perform(ReadGraph graph) - throws DatabaseException { - Resource project = Simantics.peekProjectResource(); - if (project == null) - return Collections.emptySet(); - return getSearchEngines(graph, project); - } - }); - } - - private static Set getSearchEngines(ReadGraph graph, Resource project) throws DatabaseException{ - Set searchEngines = new HashSet(); - Map> result = getSearchEnginesByModel(graph, project); - for (Set set : result.values()) - searchEngines.addAll(set); - return searchEngines; - } - - - private static Map> getSearchEnginesByModel(ReadGraph graph, Resource project) throws DatabaseException{ - WorkbenchResource WB = WorkbenchResource.getInstance(graph); - Layer0 L0 = Layer0.getInstance(graph); - Map> result = new HashMap>(); - Collection activeModels = graph.syncRequest(new ActiveModels(project)); - for (Resource model : activeModels) { - Set searchEngines = new HashSet(); - - List searchFunctions = new ArrayList(); - searchFunctions.addAll(graph.getObjects(model, WB.HasWorkbenchSearchFunction)); - if (searchFunctions.size() == 0) { - searchEngines.addAll(findSearchContributions(graph, model)); - } - if (searchFunctions.isEmpty() && searchEngines.isEmpty()) { - // TODO : backwards compatibility, to be removed. - searchFunctions.addAll(graph.getObjects(project, WB.HasWorkbenchSearchFunction)); - } - if (searchFunctions.isEmpty() && searchEngines.isEmpty()) - searchFunctions.add( WB.DependenciesSearchFunction); - - for (Resource searchFunction : searchFunctions) { - @SuppressWarnings("rawtypes") - Function f = graph.adapt(searchFunction, Function.class); - String id = graph.getURI(searchFunction); - String name = graph.getPossibleRelatedValue2(searchFunction, L0.HasLabel); - @SuppressWarnings("unchecked") - SearchEngine engine = new SearchEngine(id,name,(Function5)f, true); - { - engine.addSupportedParam(Dependencies.FIELD_NAME_SEARCH, "Name"); - engine.addSupportedParam(Dependencies.FIELD_TYPES_SEARCH, "Types"); - } - searchEngines.add(engine); - } - result.put(model, searchEngines); - } - return result; - } - - - /** - * @param subMonitor - * @param query - * @param maxResults - * @return - * @throws DatabaseException - */ - private static List createResultPage(final IProgressMonitor monitor, final SearchQuery query, final int maxResults) throws DatabaseException { - return Simantics.getSession().syncRequest(new Read>() { - @Override - public List perform(ReadGraph graph) throws DatabaseException { - Resource project = Simantics.peekProjectResource(); - if (project == null) - return null; - - Collection activeModels = graph.syncRequest(new ActiveModels(project)); - //if (activeModels.isEmpty()) - // return null; - long t1 = System.currentTimeMillis(); - Set searchEngines = new HashSet(); - MapList> searchResults = new MapList>(); - Map> searchEngineMap = getSearchEnginesByModel(graph, project); - - for (Resource model : activeModels) { - for (SearchEngine engine : searchEngineMap.get(model)) { - - if (query.getBooleanFlag(engine.getId())) { - SearchResult result = engine.getSearchFunction().apply(monitor, graph, model, query, maxResults); - if (!result.isEmpty()) { - searchResults.add(model, new Pair(engine, result)); - } - } - searchEngines.add(engine); - } -// searchResults.put(model, result); - } - long t2 = System.currentTimeMillis(); - System.out.println("Running search queries took " + (t2-t1) + " ms for query '" + query + "'"); - - try { - return Searching.generatePage(graph, searchEngines,query, maxResults, searchResults); - } catch (IOException e) { - Activator.logError("I/O problem while generating search result page.", e); - } catch (TemplateException e) { - Activator.logError("Template definition problem in search result page generation. Please inform the developers.", e); - } - return null; - } - }); - } - - private static Collection findSearchContributions(ReadGraph graph, Resource model) throws DatabaseException { - WorkbenchResource WB = WorkbenchResource.getInstance(graph); - Instances contributionFinder = graph.adapt(WB.SearchContribution, Instances.class); - Resource index = model; - List result = new ArrayList(); - for (Resource r : contributionFinder.find(graph, index)) { - SearchEngine engine = contributionToEngine(graph, r); - if (engine != null) - result.add(engine); - } - return result; - } - - private static SearchEngine contributionToEngine(ReadGraph graph, Resource searchContribution) throws DatabaseException { - Layer0 L0 = Layer0.getInstance(graph); - WorkbenchResource WB = WorkbenchResource.getInstance(graph); - - Resource searchFunction = graph.getPossibleObject(searchContribution, WB.hasSearchFunction); - if (searchFunction == null) - return null; - - @SuppressWarnings("rawtypes") - Function f = graph.adapt(searchFunction, Function.class); - String id = graph.getURI(searchFunction); - String name = graph.getPossibleRelatedValue2(searchFunction, L0.HasLabel); - - Boolean enabledByDefault = graph.getPossibleRelatedValue2(searchContribution, WB.SearchContribution_isEnabledByDefault, Bindings.BOOLEAN); - boolean enabled = !Boolean.FALSE.equals(enabledByDefault); - - @SuppressWarnings("unchecked") - SearchEngine engine = new SearchEngine(id,name,(Function5)f, enabled); - { - engine.addSupportedParam(Dependencies.FIELD_NAME_SEARCH, "Name"); - engine.addSupportedParam(Dependencies.FIELD_TYPES_SEARCH, "Types"); - } - return engine; - } - -}