/******************************************************************************* * Copyright (c) 2007, 2010 Association for Decentralized Information Management * in Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ package org.simantics.browsing.ui.common.processors; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.eclipse.core.runtime.Assert; import org.simantics.browsing.ui.BuiltinKeys; import org.simantics.browsing.ui.GraphExplorer; import org.simantics.browsing.ui.NodeContext; import org.simantics.browsing.ui.NodeContext.PrimitiveQueryKey; import org.simantics.browsing.ui.NodeQueryManager; import org.simantics.browsing.ui.PrimitiveQueryUpdater; import org.simantics.browsing.ui.SelectionRequest; import org.simantics.browsing.ui.common.views.DefaultFilterStrategy; import org.simantics.browsing.ui.common.views.IFilterStrategy; import org.simantics.browsing.ui.content.Labeler; import org.simantics.utils.datastructures.Pair; /** */ public class FilterSelectionRequestQueryProcessor extends AbstractPrimitiveQueryProcessor> implements ProcessorLifecycle { HashMap filters = new HashMap(); HashMap, PrimitiveQueryUpdater>> updaters = new HashMap, PrimitiveQueryUpdater>>(); IFilterStrategy filterStrategy; public FilterSelectionRequestQueryProcessor() { this(new DefaultFilterStrategy()); } public FilterSelectionRequestQueryProcessor(IFilterStrategy filterStrategy) { Assert.isNotNull(filterStrategy, "null filter strategy not allowed"); this.filterStrategy = filterStrategy; } public IFilterStrategy getFilterStrategy() { return filterStrategy; } public void setFilterStrategy(IFilterStrategy filterStrategy) { this.filterStrategy = filterStrategy; } @Override public String toString() { return "SelectionRequestProcessor"; } @Override public Object getIdentifier() { return BuiltinKeys.SELECTION_REQUESTS; } @Override public Collection query(PrimitiveQueryUpdater updater, NodeContext context, PrimitiveQueryKey> key) { updaters.put(context, new Pair, PrimitiveQueryUpdater>(key, updater)); return makeFilterRequest(updater, context, filters.get(context)); } // TODO: evaluate still if this is ok private String adjustFilter(String filter) { String[] tokens = filter.split(" "); // System.out.println("FilterSelectionRequestQueryProcessor.adjustFilter=" + filter); StringBuilder b = new StringBuilder(); boolean first = true; for(String token : tokens) { // System.out.println("FilterSelectionRequestQueryProcessor.token=" + token); if(!token.startsWith("$")) { if(first) first = false; else b.append(" "); b.append(token); } } String result = b.toString(); if(result.isEmpty()) return "*"; else return result; } private Collection makeFilterRequest(PrimitiveQueryUpdater updater, NodeContext context, final String filter_) { if (filter_ == null || filter_.isEmpty()) return null; final String filter = adjustFilter(filter_); // System.out.println("filter for reg exp = " + filter_ + " -> " + filter); final String regExFilter = filterStrategy.toPatternString(filter); if (regExFilter == null) return null; final Pattern pattern = Pattern.compile(regExFilter); final Matcher matcher = pattern.matcher(""); return Collections.singletonList((SelectionRequest) new SelectionRequest() { @Override public Request getRequest() { return Request.FILTER; } @Override public boolean isIncluded(NodeQueryManager manager, Object object) { NodeContext context = (NodeContext)object; Labeler labeler = manager.query(context, BuiltinKeys.SELECTED_LABELER); if (labeler == null) return false; Map labels = labeler.getLabels(); if (labels.isEmpty()) return false; // TODO: only visible columns! for(String s : labels.values()) { //System.out.println("matching " + s); if (s == null) continue; // TODO: remove forced lowercase and leave the case-insensitiveness up to the pattern matcher.reset(s.toLowerCase()); if (matcher.matches()) { return false; } } return true; } @SuppressWarnings("unchecked") @Override public T getData() { return (T)filter_; } }); } public String getFilter(NodeContext context) { return filters.get(context); } /** * @param context * @param filter a regular expression adhering to {@link Pattern} or * null to disable filtering for the specified context */ @SuppressWarnings("unchecked") public void setFilter(NodeContext context, String filter) { if (filter == null) { filters.remove(context); } else { filters.put(context, filter); } Pair, PrimitiveQueryUpdater> p = updaters.get(context); // FIXME: this is not valid or anything, but prevents NPE crashboombangs for now. if (p == null) return; if (p.second == null) throw new IllegalArgumentException("context not found in cache"); p.second.scheduleReplace(context, (PrimitiveQueryKey>) p.first, makeFilterRequest(p.second, context, filter)); } @Override public void attached(GraphExplorer explorer) { } @Override public void detached(GraphExplorer explorer) { } @Override public void clear() { filters.clear(); updaters.clear(); } }