package org.simantics.document.linking.function; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set; import org.eclipse.core.runtime.IProgressMonitor; import org.simantics.databoard.Bindings; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.common.utils.Logger; import org.simantics.db.common.utils.NameUtils; import org.simantics.db.exception.DatabaseException; import org.simantics.db.layer0.adapter.Instances; import org.simantics.db.layer0.genericrelation.Dependencies; import org.simantics.document.linking.ontology.DocumentLink; import org.simantics.document.linking.utils.SourceLinkUtil; import org.simantics.scl.runtime.function.FunctionImpl5; import org.simantics.workbench.search.NamedResource; import org.simantics.workbench.search.SearchQuery; import org.simantics.workbench.search.SearchResult; import org.simantics.workbench.search.SearchResultColumn; import org.simantics.workbench.search.SearchResultRow; import org.simantics.workbench.search.StringUtil; public class SearchFunction extends FunctionImpl5 { public static List columns; static { columns = new ArrayList(); columns.add(new SearchResultColumn("Name")); //$NON-NLS-1$ columns.add(new SearchResultColumn("Comment")); //$NON-NLS-1$ columns.add(new SearchResultColumn("Part Of")); //$NON-NLS-1$ } @Override public SearchResult apply(IProgressMonitor monitor, ReadGraph graph, Resource model, SearchQuery query, Integer maxResults) { try { DocumentLink sl = DocumentLink.getInstance(graph); Instances instancesQuery = graph.adapt(sl.Source, Instances.class); Collection found = instancesQuery.find(graph, model); return generateSearchResults(graph, found,query); } catch (DatabaseException e) { Logger.defaultLogError(e); } return null; } public static class NameComparator { private String name; int type = 0; public NameComparator(String query) { String parts[] = query.split(" OR "); //$NON-NLS-1$ for (String s : parts) { if (s.startsWith("Name:")) { //$NON-NLS-1$ name = s.substring(5); } } if (name == null) return; name = name.trim(); boolean freeStart = false; boolean freeEnd = false; if (name.endsWith("*")) { //$NON-NLS-1$ name = name.substring(0,name.length()-1); freeEnd = true; } if (name.startsWith("*")) { //$NON-NLS-1$ name = name.substring(1,name.length()); freeStart = true; } if (freeStart && freeEnd) type = 1; else if (freeStart) type = 2; else if (freeEnd) type = 3; name = name.toLowerCase(); } public boolean compare(String s) { switch (type) { case 0: return s.toLowerCase().equals(name); case 1: return s.toLowerCase().contains(name); case 2: return s.toLowerCase().endsWith(name); case 3: return s.toLowerCase().startsWith(name); } return false; } } public static final SearchResult generateSearchResults(ReadGraph graph, Collection results, SearchQuery query) throws DatabaseException { DocumentLink sl = DocumentLink.getInstance(graph); SearchResult result = new SearchResult(columns); Set processed = new HashSet(); NameComparator c = new NameComparator(query.getQuery(Dependencies.FIELD_NAME_SEARCH)); for (Resource source : results) { // Prevent index corruption from producing duplicate results. if (!processed.add(source)) continue; Resource reference = SourceLinkUtil.getReferredDocument(graph, source); if (!SourceLinkUtil.isValidReference(graph, reference)) { // TODO: searching removed references continue; } Resource parent = (Resource) graph.getSingleObject(source, sl.hasSource_Inverse); String name = NameUtils.getSafeLabel(graph,reference); if (name.length() == 0) name = NameUtils.getSafeName(graph, reference); if (!c.compare(name)) continue; String parentName = NameUtils.getSafeLabel(graph, parent); if (parentName.length() == 0) parentName = NameUtils.getSafeName(graph, parent); if (graph.isInstanceOf(source, sl.FunctionalSource)) { Resource relation = graph.getSingleObject(source, sl.consernsRelation); String relationName = NameUtils.getSafeLabel(graph, relation); if (relationName.length() == 0) relationName = NameUtils.getSafeName(graph, relation); parentName = parentName +"#"+relationName; //$NON-NLS-1$ } DocumentLinkRow rst = new DocumentLinkRow(); rst.resource = NamedResource.of(graph, reference, name); rst.parent = NamedResource.of(graph, parent,parentName); rst.comment = graph.getPossibleRelatedValue(source, sl.hasSourceComment,Bindings.STRING); // Collection typeResources = graph.getTypes(reference); // Collection principalTypeResources = graph.getPrincipalTypes(reference); // if (!typeResources.isEmpty()) { // rst.types = new ArrayList(typeResources.size()); // rst.principalTypes = new ArrayList(principalTypeResources.size()); // for (Resource t : typeResources) { // String oname = NameUtils.getSafeLabel(graph, t); // NamedResource nr = NamedResource.of(graph, t, oname); // rst.types.add(nr); // if (principalTypeResources.contains(t)) // rst.principalTypes.add(nr); // } // } result.addRow(rst); } return result; } private static class DocumentLinkRow implements SearchResultRow { public NamedResource resource; public NamedResource parent; public String comment; @Override public String getContent(int column) { switch (column) { case 0: return "")+StringUtil.escape(resource.getName())+""; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ case 1: if (comment != null) return comment; return ""; //$NON-NLS-1$ case 2: if (parent != null) return "")+StringUtil.escape(parent.getName())+""; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ return ""; //$NON-NLS-1$ default: return ""; //$NON-NLS-1$ } } } }