]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.browsing.ui.common/src/org/simantics/browsing/ui/common/processors/FilterSelectionRequestQueryProcessor.java
Fixed all line endings of the repository
[simantics/platform.git] / bundles / org.simantics.browsing.ui.common / src / org / simantics / browsing / ui / common / processors / FilterSelectionRequestQueryProcessor.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  *******************************************************************************/
12 package org.simantics.browsing.ui.common.processors;
13
14 import java.util.Collection;
15 import java.util.Collections;
16 import java.util.HashMap;
17 import java.util.Map;
18 import java.util.regex.Matcher;
19 import java.util.regex.Pattern;
20
21 import org.eclipse.core.runtime.Assert;
22 import org.simantics.browsing.ui.BuiltinKeys;
23 import org.simantics.browsing.ui.GraphExplorer;
24 import org.simantics.browsing.ui.NodeContext;
25 import org.simantics.browsing.ui.NodeContext.PrimitiveQueryKey;
26 import org.simantics.browsing.ui.NodeQueryManager;
27 import org.simantics.browsing.ui.PrimitiveQueryUpdater;
28 import org.simantics.browsing.ui.SelectionRequest;
29 import org.simantics.browsing.ui.common.views.DefaultFilterStrategy;
30 import org.simantics.browsing.ui.common.views.IFilterStrategy;
31 import org.simantics.browsing.ui.content.Labeler;
32 import org.simantics.utils.datastructures.Pair;
33
34 /**
35  */
36 public class FilterSelectionRequestQueryProcessor extends AbstractPrimitiveQueryProcessor<Collection<SelectionRequest>>
37         implements ProcessorLifecycle {
38
39     HashMap<NodeContext, String> filters = new HashMap<NodeContext, String>();
40     HashMap<NodeContext, Pair<PrimitiveQueryKey<?>, PrimitiveQueryUpdater>> updaters = new HashMap<NodeContext, Pair<PrimitiveQueryKey<?>, PrimitiveQueryUpdater>>();
41
42     IFilterStrategy filterStrategy;
43
44     public FilterSelectionRequestQueryProcessor() {
45         this(new DefaultFilterStrategy());
46     }
47
48     public FilterSelectionRequestQueryProcessor(IFilterStrategy filterStrategy) {
49         Assert.isNotNull(filterStrategy, "null filter strategy not allowed");
50         this.filterStrategy = filterStrategy;
51     }
52
53     public IFilterStrategy getFilterStrategy() {
54         return filterStrategy;
55     }
56
57     public void setFilterStrategy(IFilterStrategy filterStrategy) {
58         this.filterStrategy = filterStrategy;
59     }
60
61     @Override
62     public String toString() {
63         return "SelectionRequestProcessor";
64     }
65
66     @Override
67     public Object getIdentifier() {
68         return BuiltinKeys.SELECTION_REQUESTS;
69     }
70
71     @Override
72     public Collection<SelectionRequest> query(PrimitiveQueryUpdater updater, NodeContext context,
73             PrimitiveQueryKey<Collection<SelectionRequest>> key) {
74         updaters.put(context, new Pair<PrimitiveQueryKey<?>, PrimitiveQueryUpdater>(key, updater));
75         return makeFilterRequest(updater, context, filters.get(context));
76     }
77
78     // TODO: evaluate still if this is ok
79     private String adjustFilter(String filter) {
80         String[] tokens = filter.split(" ");
81 //      System.out.println("FilterSelectionRequestQueryProcessor.adjustFilter=" + filter);
82         StringBuilder b = new StringBuilder();
83         boolean first = true;
84         for(String token : tokens) {
85 //            System.out.println("FilterSelectionRequestQueryProcessor.token=" + token);
86             if(!token.startsWith("$")) {
87                 if(first) first = false;
88                 else b.append(" ");
89                 b.append(token);
90             }
91         }
92
93         String result = b.toString();
94         if(result.isEmpty()) return "*";
95         else return result;
96     }
97
98     private Collection<SelectionRequest> makeFilterRequest(PrimitiveQueryUpdater updater, NodeContext context, final String filter_) {
99         if (filter_ == null || filter_.isEmpty())
100             return null;
101
102         final String filter = adjustFilter(filter_);
103         
104 //        System.out.println("filter for reg exp = " + filter_ + " -> " + filter);
105         
106         final String regExFilter = filterStrategy.toPatternString(filter);
107         if (regExFilter == null)
108             return null;
109
110         final Pattern pattern = Pattern.compile(regExFilter);
111         final Matcher matcher = pattern.matcher("");
112
113         return Collections.singletonList((SelectionRequest) new SelectionRequest() {
114             @Override
115             public Request getRequest() {
116                 return Request.FILTER;
117             }
118
119             @Override
120             public boolean isIncluded(NodeQueryManager manager, Object object) {
121                 NodeContext context = (NodeContext)object;
122                 Labeler labeler = manager.query(context, BuiltinKeys.SELECTED_LABELER);
123
124                 if (labeler == null)
125                     return false;
126                 Map<String, String> labels = labeler.getLabels();
127                 if (labels.isEmpty())
128                     return false;
129
130                 // TODO: only visible columns!
131                 for(String s : labels.values()) {
132                     //System.out.println("matching " + s);
133                     if (s == null)
134                         continue;
135                     // TODO: remove forced lowercase and leave the case-insensitiveness up to the pattern
136                     matcher.reset(s.toLowerCase());
137                     if (matcher.matches()) {
138                         return false;
139                     }
140                 }
141
142                 return true;
143             }
144
145             @SuppressWarnings("unchecked")
146             @Override
147             public <T> T getData() {
148                 return (T)filter_;
149             }
150
151         });
152     }
153
154     public String getFilter(NodeContext context) {
155         return filters.get(context);
156     }
157
158     /**
159      * @param context
160      * @param filter a regular expression adhering to {@link Pattern} or
161      *        <code>null</code> to disable filtering for the specified context
162      */
163     @SuppressWarnings("unchecked")
164     public void setFilter(NodeContext context, String filter) {
165         if (filter == null) {
166             filters.remove(context);
167         } else {
168             filters.put(context, filter);
169         }
170         Pair<PrimitiveQueryKey<?>, PrimitiveQueryUpdater> p = updaters.get(context);
171
172         // FIXME: this is not valid or anything, but prevents NPE crashboombangs for now.
173         if (p == null)
174             return;
175
176         if (p.second == null)
177             throw new IllegalArgumentException("context not found in cache");
178         p.second.scheduleReplace(context, (PrimitiveQueryKey<Collection<SelectionRequest>>) p.first, makeFilterRequest(p.second, context, filter));
179     }
180
181     @Override
182     public void attached(GraphExplorer explorer) {
183     }
184
185     @Override
186     public void detached(GraphExplorer explorer) {
187     }
188
189     @Override
190     public void clear() {
191         filters.clear();
192         updaters.clear();
193     }
194
195 }