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