c04a1f417c3bf5a33cf064876a97853b4097ea51
[simantics/platform.git] / bundles / org.simantics.document.linking.ui / src / org / simantics / document / linking / function / SearchFunction.java
1 package org.simantics.document.linking.function;
2
3 import java.util.ArrayList;
4 import java.util.Collection;
5 import java.util.HashSet;
6 import java.util.List;
7 import java.util.Set;
8
9 import org.eclipse.core.runtime.IProgressMonitor;
10 import org.simantics.databoard.Bindings;
11 import org.simantics.db.ReadGraph;
12 import org.simantics.db.Resource;
13 import org.simantics.db.common.utils.Logger;
14 import org.simantics.db.common.utils.NameUtils;
15 import org.simantics.db.exception.DatabaseException;
16 import org.simantics.db.layer0.adapter.Instances;
17 import org.simantics.document.linking.ontology.DocumentLink;
18 import org.simantics.document.linking.utils.SourceLinkUtil;
19 import org.simantics.scl.runtime.function.FunctionImpl5;
20 import org.simantics.workbench.search.NamedResource;
21 import org.simantics.workbench.search.SearchQuery;
22 import org.simantics.workbench.search.SearchResult;
23 import org.simantics.workbench.search.SearchResultColumn;
24 import org.simantics.workbench.search.SearchResultRow;
25 import org.simantics.workbench.search.StringUtil;
26
27 public class SearchFunction extends FunctionImpl5<IProgressMonitor, ReadGraph, Resource, SearchQuery, Integer, SearchResult> {
28
29         public static List<SearchResultColumn> columns;
30         
31         static {
32                 columns = new ArrayList<SearchResultColumn>();
33                 columns.add(new SearchResultColumn("Name")); //$NON-NLS-1$
34                 columns.add(new SearchResultColumn("Comment")); //$NON-NLS-1$
35                 columns.add(new SearchResultColumn("Part Of")); //$NON-NLS-1$
36         }
37         
38         @Override
39         public SearchResult apply(IProgressMonitor monitor, ReadGraph graph, Resource model, SearchQuery query, Integer maxResults) {
40                  try {
41                                 DocumentLink sl = DocumentLink.getInstance(graph);
42                                 Instances instancesQuery = graph.adapt(sl.Source, Instances.class);
43                         Collection<Resource> found = instancesQuery.find(graph, model);
44                         return generateSearchResults(graph, found,query);
45                 } catch (DatabaseException e) {
46                     Logger.defaultLogError(e);
47                 }
48                 return null;
49         }
50         
51         
52         public static class NameComparator {
53                 private String name;
54                 int type = 0;
55                 
56                 public NameComparator(String query) {
57                 String parts[] = query.split(" OR "); //$NON-NLS-1$
58                 for (String s : parts) {
59                         if (s.startsWith("Name:")) { //$NON-NLS-1$
60                                  name = s.substring(5);
61                         }
62                 }
63                 if (name == null)
64                         return;
65                 name = name.trim();
66                 boolean freeStart = false;
67                 boolean freeEnd = false;
68                 if (name.endsWith("*")) { //$NON-NLS-1$
69                         name = name.substring(0,name.length()-1);
70                         freeEnd = true;
71                 }
72                 if (name.startsWith("*")) { //$NON-NLS-1$
73                         name = name.substring(1,name.length());
74                         freeStart = true;
75                 }
76                 if (freeStart && freeEnd)
77                         type = 1;
78                 else if (freeStart)
79                         type = 2;
80                 else if (freeEnd)
81                         type = 3;
82                 name = name.toLowerCase();
83                 }
84                 
85                 public boolean compare(String s) {
86                         switch (type) {
87                         case 0:
88                                 return s.toLowerCase().equals(name);
89                         case 1:
90                                 return s.toLowerCase().contains(name);
91                         case 2:
92                                 return s.toLowerCase().endsWith(name);
93                         case 3:
94                                 return s.toLowerCase().startsWith(name);
95                         }
96                         return false;
97                 }
98         }
99         
100     public static final SearchResult generateSearchResults(ReadGraph graph,
101                 Collection<Resource> results, SearchQuery query) throws DatabaseException {
102         DocumentLink sl = DocumentLink.getInstance(graph);
103
104         SearchResult result = new SearchResult(columns);
105         Set<Resource> processed = new HashSet<Resource>();
106
107        NameComparator c = new NameComparator(query.getQuery("Name")); //$NON-NLS-1$
108         
109         for (Resource source : results) {
110                   // Prevent index corruption from producing duplicate results.
111             if (!processed.add(source))
112                 continue;
113             
114             Resource reference = SourceLinkUtil.getReferredDocument(graph, source);
115             if (!SourceLinkUtil.isValidReference(graph, reference)) {
116                 // TODO: searching removed references
117                 continue;
118             }
119
120             Resource parent = (Resource) graph.getSingleObject(source, sl.hasSource_Inverse);
121             String name = NameUtils.getSafeLabel(graph,reference);
122             if (name.length() == 0)
123                 name = NameUtils.getSafeName(graph, reference);
124        
125             if (!c.compare(name))
126                 continue;
127             
128             String parentName = NameUtils.getSafeLabel(graph, parent);
129             if (parentName.length() == 0)
130                 parentName = NameUtils.getSafeName(graph, parent);
131             
132             if (graph.isInstanceOf(source, sl.FunctionalSource)) {
133                 Resource relation = graph.getSingleObject(source, sl.consernsRelation);
134                 String relationName = NameUtils.getSafeLabel(graph, relation);
135                 if (relationName.length() == 0)
136                         relationName = NameUtils.getSafeName(graph, relation);
137                 parentName = parentName +"#"+relationName; //$NON-NLS-1$
138             }
139             
140             DocumentLinkRow rst = new DocumentLinkRow();
141             rst.resource = NamedResource.of(graph, reference, name);
142             rst.parent = NamedResource.of(graph, parent,parentName);
143             rst.comment = graph.getPossibleRelatedValue(source, sl.hasSourceComment,Bindings.STRING);
144
145 //          Collection<Resource> typeResources = graph.getTypes(reference);
146 //            Collection<Resource> principalTypeResources = graph.getPrincipalTypes(reference);
147 //            if (!typeResources.isEmpty()) {
148 //                rst.types = new ArrayList<NamedResource>(typeResources.size());
149 //                rst.principalTypes = new ArrayList<NamedResource>(principalTypeResources.size());
150 //                for (Resource t : typeResources) {
151 //                    String oname = NameUtils.getSafeLabel(graph, t);
152 //                    NamedResource nr = NamedResource.of(graph, t, oname);
153 //                    rst.types.add(nr);
154 //                    if (principalTypeResources.contains(t))
155 //                        rst.principalTypes.add(nr);
156 //                }
157 //            }
158
159             result.addRow(rst);
160         }
161         return result;
162     }
163     
164     private static class DocumentLinkRow implements SearchResultRow {
165         public NamedResource             resource;
166         public NamedResource             parent;
167         public String comment;
168         @Override
169         public String getContent(int column) {
170                 switch (column) {
171                 case 0:
172                         return "<a class=\"small\" href=\"resource:"+ resource.getResource() +"\"" + (resource.getUri() == null ? "" : " title=\""+resource.getUri()+"\">")+StringUtil.escape(resource.getName())+"</a>"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$
173                 case 1:
174                         if (comment != null)
175                                 return comment;
176                         return ""; //$NON-NLS-1$
177                 case 2:
178                         if (parent != null)
179                                 return "<a class=\"small\" href=\"resource:"+ parent.getResource() +"\"" + (parent.getUri() == null ? "" : " title=\""+parent.getUri()+"\">")+StringUtil.escape(parent.getName())+"</a>"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$
180                         return ""; //$NON-NLS-1$
181                 default:
182                         return ""; //$NON-NLS-1$
183                 }
184         }
185     }
186         
187 }
188