]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.debug.ui/src/org/simantics/debug/ui/ResourceSearch.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.debug.ui / src / org / simantics / debug / ui / ResourceSearch.java
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
3  * in Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *     Semantum Oy - index based searching (#4255)\r
12  *******************************************************************************/\r
13 package org.simantics.debug.ui;\r
14 \r
15 import java.util.ArrayList;\r
16 import java.util.Collection;\r
17 import java.util.Collections;\r
18 import java.util.HashSet;\r
19 import java.util.LinkedList;\r
20 import java.util.List;\r
21 import java.util.Set;\r
22 import java.util.regex.Pattern;\r
23 \r
24 import org.simantics.db.ReadGraph;\r
25 import org.simantics.db.Resource;\r
26 import org.simantics.db.Statement;\r
27 import org.simantics.db.common.request.Queries;\r
28 import org.simantics.db.common.request.ReadRequest;\r
29 import org.simantics.db.common.utils.NameUtils;\r
30 import org.simantics.db.exception.DatabaseException;\r
31 import org.simantics.db.request.Read;\r
32 import org.simantics.layer0.Layer0;\r
33 import org.simantics.utils.strings.EString;\r
34 import org.simantics.utils.threads.IThreadWorkQueue;\r
35 \r
36 public class ResourceSearch extends ReadRequest {\r
37 \r
38     public static final IResourceFilter FILTER_ALL = new IResourceFilter() {\r
39         @Override\r
40         public boolean acceptResource(ReadGraph g, Resource r) {\r
41             return true;\r
42         }\r
43     };\r
44 \r
45     public static final IResourceFilter FILTER_RELATIONS = new IResourceFilter() {\r
46         @Override\r
47         public boolean acceptResource(ReadGraph g, Resource r) throws DatabaseException {\r
48             return g.isInstanceOf(r, Layer0.getInstance(g).Relation);\r
49         }\r
50     };\r
51 \r
52     public static final IResourceFilter FILTER_TYPES = new IResourceFilter() {\r
53         @Override\r
54         public boolean acceptResource(ReadGraph g, Resource r) throws DatabaseException {\r
55             Layer0 L0 = Layer0.getInstance(g);\r
56             return g.isInstanceOf(r, L0.Type) && !g.isInstanceOf(r, L0.Relation);\r
57         }\r
58     };\r
59 \r
60     /**\r
61      * Create filter that matches URI, ID and NAME using wildcard compare\r
62      * @param txt\r
63      * @return\r
64      */\r
65     public static final IResourceFilter createFilter(String txt) {\r
66         final Pattern p = EString.compileSimplePattern(txt);\r
67         return new IResourceFilter() {\r
68             @Override\r
69             public boolean acceptResource(ReadGraph g, Resource r) {\r
70                 try {\r
71                     String uri = g.syncRequest(Queries.possibleUri(r));\r
72                     if (uri != null && p.matcher(uri).matches())\r
73                         return true;\r
74                 } catch (Throwable t) {}\r
75 \r
76                 try {\r
77                     String name = NameUtils.getSafeName(g, r);\r
78                     if (p.matcher(name).matches())\r
79                         return true;\r
80                 } catch (Throwable t) {}\r
81 \r
82                 String id = Long.toString(r.getResourceId());\r
83                 if (p.matcher(id).matches())\r
84                     return true;\r
85 \r
86                 return false;\r
87             }\r
88         };\r
89     }\r
90 \r
91     public interface IResourceFilter {\r
92         boolean acceptResource(ReadGraph g, Resource r) throws DatabaseException;\r
93     }\r
94 \r
95     public interface SearchListener {\r
96         /**\r
97          * \r
98          * @param s\r
99          * @param r\r
100          * @param g graph if listening is not async, if so then null\r
101          */\r
102         void onResourceFound(Read<?> s, Collection<Resource> r, ReadGraph g) throws DatabaseException;\r
103         void onSearchComplete(Read<?> s);\r
104         void onError(Read<?> s, Throwable e);\r
105     }\r
106 \r
107     boolean canceled = false;\r
108     IResourceFilter filter;\r
109     SearchListener listener;\r
110     IThreadWorkQueue listenerThread;\r
111     ResFoundQueue resFoundQueue;\r
112     boolean asyncListening;\r
113 \r
114     public ResourceSearch(IResourceFilter f, SearchListener l, IThreadWorkQueue listenerThread, boolean asyncListening)\r
115     {\r
116         assert(f!=null && l!=null);\r
117         this.filter = f;\r
118         this.listener = l;\r
119         this.listenerThread = listenerThread;\r
120         this.asyncListening = asyncListening;\r
121         if (listenerThread!=null)\r
122             resFoundQueue = new ResFoundQueue();\r
123     }\r
124 \r
125     public void cancel() {\r
126         canceled = true;\r
127     }\r
128 \r
129     public boolean isCanceled() {\r
130         return canceled;\r
131     }\r
132 \r
133     private class ResFoundQueue implements Runnable {\r
134         ReadGraph g;\r
135         List<Resource> list = new ArrayList<Resource>();\r
136         /**\r
137          * add res to queue\r
138          * @param r\r
139          * @return true if other resources are still unhandled\r
140          */\r
141         synchronized boolean addResource(Resource r) {\r
142             list.add(r);\r
143             return list.size()>1;\r
144         }\r
145         @Override\r
146         public void run() {\r
147             try {\r
148                 Collection<Resource> l = null;\r
149                 synchronized(this) {\r
150                     if (list.size()==0) return;\r
151                     if (list.size()<10) {\r
152                         listener.onResourceFound(ResourceSearch.this, list, g);\r
153                         list.clear();\r
154                         return;\r
155                     }\r
156                     l = new ArrayList<Resource>(list);\r
157                     list.clear();\r
158                 }\r
159                 listener.onResourceFound(ResourceSearch.this, l, g);\r
160             } catch (DatabaseException e) {\r
161 \r
162             }\r
163         }\r
164     }\r
165 \r
166     @Override\r
167     public void run(ReadGraph g) {\r
168         try {\r
169             if (!asyncListening && resFoundQueue!=null) resFoundQueue.g = g;\r
170             Resource root = g.getResource("http:/");\r
171             Layer0 L0 = Layer0.getInstance(g);\r
172             LinkedList<Resource> queue = new LinkedList<Resource>();\r
173             queue.add(root);\r
174             Set<Resource> queued = new HashSet<Resource>();\r
175             while(!queue.isEmpty() && !canceled) {\r
176                 Resource r = queue.removeFirst();\r
177                 if (filter.acceptResource(g, r)) {\r
178                     if (listenerThread==null)\r
179                         listener.onResourceFound(ResourceSearch.this, Collections.singletonList(r), g);\r
180                     else {\r
181                         if (!resFoundQueue.addResource(r)) {\r
182                             if (asyncListening)\r
183                                 listenerThread.asyncExec(resFoundQueue);\r
184                             else\r
185                                 listenerThread.syncExec(resFoundQueue);\r
186                         }\r
187                     }\r
188                 }\r
189                 for (Statement stm : g.getStatements(r, L0.IsWeaklyRelatedTo))\r
190                 {\r
191                     Resource n = stm.getPredicate();\r
192                     if (!queued.contains(n)) {\r
193                         queue.add(n);\r
194                         queued.add(n);\r
195                     }\r
196 \r
197                     n = stm.getObject();\r
198                     if (!queued.contains(n)) {\r
199                         queue.add(n);\r
200                         queued.add(n);\r
201                     }\r
202                 }\r
203                 if (listenerThread==null)\r
204                     listener.onSearchComplete(ResourceSearch.this);\r
205                 else {\r
206                     Runnable run = new Runnable() {\r
207                         @Override\r
208                         public void run() {\r
209                             ResourceSearch.this.listener.onSearchComplete(ResourceSearch.this);\r
210                         }};\r
211                         if (asyncListening)\r
212                             listenerThread.asyncExec(run);\r
213                         else\r
214                             listenerThread.syncExec(run);\r
215                 }\r
216             }\r
217         } catch (final Throwable e) {\r
218             if (listenerThread==null)\r
219                 listener.onError(ResourceSearch.this, e);\r
220             else {\r
221                 Runnable r = new Runnable() {\r
222                     @Override\r
223                     public void run() {\r
224                         listener.onError(ResourceSearch.this, e);\r
225                     }};\r
226                     if (asyncListening)\r
227                         listenerThread.asyncExec(r);\r
228                     else\r
229                         listenerThread.syncExec(r);\r
230             }\r
231         }\r
232     }\r
233 \r
234 }\r