Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian W. Damus2013-09-05 23:20:02 +0000
committerChristian W. Damus2013-09-06 18:39:03 +0000
commitf1cc4b5280be5bf1100807d2b560457c29a7955e (patch)
tree1e013f65a627303826fc1fff99791223c6c67012 /extraplugins
parent2d5a1263f36097baafa147b5d661222f8abcbe22 (diff)
downloadorg.eclipse.papyrus-f1cc4b5280be5bf1100807d2b560457c29a7955e.tar.gz
org.eclipse.papyrus-f1cc4b5280be5bf1100807d2b560457c29a7955e.tar.xz
org.eclipse.papyrus-f1cc4b5280be5bf1100807d2b560457c29a7955e.zip
415371: [CDO] Post-process search results to create attribute matches
https://bugs.eclipse.org/bugs/show_bug.cgi?id=415371
Diffstat (limited to 'extraplugins')
-rw-r--r--extraplugins/cdo/org.eclipse.papyrus.cdo.uml.search.ui/src/org/eclipse/papyrus/cdo/uml/search/internal/ui/query/AttributeMatchStrategy.java169
-rw-r--r--extraplugins/cdo/org.eclipse.papyrus.cdo.uml.search.ui/src/org/eclipse/papyrus/cdo/uml/search/internal/ui/query/CDOPapyrusQuery.java25
-rw-r--r--extraplugins/cdo/org.eclipse.papyrus.cdo.uml.search.ui/src/org/eclipse/papyrus/cdo/uml/search/internal/ui/query/CDOSearchQueryProvider.java12
-rw-r--r--extraplugins/cdo/org.eclipse.papyrus.cdo.uml.search.ui/src/org/eclipse/papyrus/cdo/uml/search/internal/ui/query/PatternUtil.java36
4 files changed, 233 insertions, 9 deletions
diff --git a/extraplugins/cdo/org.eclipse.papyrus.cdo.uml.search.ui/src/org/eclipse/papyrus/cdo/uml/search/internal/ui/query/AttributeMatchStrategy.java b/extraplugins/cdo/org.eclipse.papyrus.cdo.uml.search.ui/src/org/eclipse/papyrus/cdo/uml/search/internal/ui/query/AttributeMatchStrategy.java
new file mode 100644
index 00000000000..e08035635a0
--- /dev/null
+++ b/extraplugins/cdo/org.eclipse.papyrus.cdo.uml.search.ui/src/org/eclipse/papyrus/cdo/uml/search/internal/ui/query/AttributeMatchStrategy.java
@@ -0,0 +1,169 @@
+/*****************************************************************************
+ * Copyright (c) 2013 CEA LIST.
+ *
+ * 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:
+ * CEA LIST - Initial API and implementation
+ *****************************************************************************/
+package org.eclipse.papyrus.cdo.uml.search.internal.ui.query;
+
+import static java.util.regex.Pattern.quote;
+import static org.eclipse.papyrus.cdo.uml.search.internal.ui.query.CDOSearchQueryProvider.isString;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.eclipse.emf.ecore.EAttribute;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.papyrus.uml.search.ui.query.QueryInfo;
+import org.eclipse.papyrus.views.search.results.AbstractResultEntry;
+import org.eclipse.papyrus.views.search.results.AttributeMatch;
+import org.eclipse.uml2.uml.NamedElement;
+import org.eclipse.uml2.uml.UMLPackage;
+
+import com.google.common.collect.Multimap;
+import com.google.common.collect.Sets;
+
+
+/**
+ * This is the AttributeMatchStrategy type. Enjoy.
+ */
+public abstract class AttributeMatchStrategy {
+
+ protected final Matcher matcher;
+
+ protected AttributeMatchStrategy(QueryInfo info) {
+ super();
+
+ final String pattern = info.isRegularExpression() ? info.getQueryText() : quote(info.getQueryText());
+ int flags = info.isCaseSensitive() ? 0 : Pattern.CASE_INSENSITIVE;
+ matcher = Pattern.compile(pattern, flags).matcher(""); //$NON-NLS-1$
+ }
+
+ public static AttributeMatchStrategy create(QueryInfo info) {
+ AttributeMatchStrategy result;
+
+ if(info.isSearchAllStringAttributes()) {
+ result = new AnyStringAttribute(info);
+ } else {
+ result = new NameOnly(info);
+ }
+
+ return result;
+ }
+
+ public static AttributeMatchStrategy create(QueryInfo info, Multimap<EClass, EAttribute> attributes) {
+ return new SpecificAttributes(info, attributes);
+ }
+
+ public abstract void apply(AbstractResultEntry parentMatch, EObject element, Collection<? super AttributeMatch> results);
+
+ protected void match(String value, EAttribute attribute, AbstractResultEntry parentMatch, EObject element, Collection<? super AttributeMatch> results) {
+ matcher.reset(value);
+ while(matcher.find()) {
+ results.add(new AttributeMatch(parentMatch, matcher.start(), matcher.end() - matcher.start(), element, attribute, null));
+ }
+ }
+
+ //
+ // Nested types
+ //
+
+ private static class NameOnly extends AttributeMatchStrategy {
+
+ NameOnly(QueryInfo info) {
+ super(info);
+ }
+
+ @Override
+ public void apply(AbstractResultEntry parentMatch, EObject element, Collection<? super AttributeMatch> results) {
+ String name = (element instanceof NamedElement) ? ((NamedElement)element).getName() : null;
+
+ if(name != null) {
+ match(name, UMLPackage.Literals.NAMED_ELEMENT__NAME, parentMatch, element, results);
+ }
+ }
+ }
+
+ private static class AnyStringAttribute extends AttributeMatchStrategy {
+
+ AnyStringAttribute(QueryInfo info) {
+ super(info);
+ }
+
+ @Override
+ public void apply(AbstractResultEntry parentMatch, EObject element, Collection<? super AttributeMatch> results) {
+ for(EAttribute next : element.eClass().getEAllAttributes()) {
+ if(isString(next)) {
+ if(!next.isMany()) {
+ String value = (String)element.eGet(next);
+ if(value != null) {
+ match(value, next, parentMatch, element, results);
+ }
+ } else {
+ // FIXME: Using list's string representation as in core Papyrus, but it doesn't make sense
+ List<?> value = (List<?>)element.eGet(next);
+ match(value.toString(), next, parentMatch, element, results);
+ }
+ }
+ }
+ }
+ }
+
+ private static class SpecificAttributes extends AttributeMatchStrategy {
+
+ private final Multimap<EClass, EAttribute> attributes;
+
+ private final Set<EAttribute> seen = Sets.newHashSet();
+
+ SpecificAttributes(QueryInfo info, Multimap<EClass, EAttribute> attributes) {
+ super(info);
+
+ this.attributes = attributes;
+ }
+
+ @Override
+ public void apply(AbstractResultEntry parentMatch, EObject element, Collection<? super AttributeMatch> results) {
+ seen.clear();
+
+ apply(element.eClass(), parentMatch, element, results);
+
+ for(EClass next : element.eClass().getEAllSuperTypes()) {
+ apply(next, parentMatch, element, results);
+ }
+ }
+
+ protected void apply(EClass eclass, AbstractResultEntry parentMatch, EObject element, Collection<? super AttributeMatch> results) {
+ if(this.attributes.containsKey(eclass)) {
+ Collection<EAttribute> attributes = this.attributes.get(eclass);
+ if(attributes.isEmpty()) {
+ attributes = eclass.getEAllAttributes();
+ }
+
+ for(EAttribute next : attributes) {
+ // don't repeat any attributes because of inheritance
+ if(seen.add(next)) {
+ if(!next.isMany()) {
+ Object value = element.eGet(next);
+ if(value != null) {
+ match(value.toString(), next, parentMatch, element, results);
+ }
+ } else {
+ // FIXME: Using list's string representation as in core Papyrus, but it doesn't make sense
+ List<?> value = (List<?>)element.eGet(next);
+ match(value.toString(), next, parentMatch, element, results);
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/extraplugins/cdo/org.eclipse.papyrus.cdo.uml.search.ui/src/org/eclipse/papyrus/cdo/uml/search/internal/ui/query/CDOPapyrusQuery.java b/extraplugins/cdo/org.eclipse.papyrus.cdo.uml.search.ui/src/org/eclipse/papyrus/cdo/uml/search/internal/ui/query/CDOPapyrusQuery.java
index 9487934eae4..f7b8541313d 100644
--- a/extraplugins/cdo/org.eclipse.papyrus.cdo.uml.search.ui/src/org/eclipse/papyrus/cdo/uml/search/internal/ui/query/CDOPapyrusQuery.java
+++ b/extraplugins/cdo/org.eclipse.papyrus.cdo.uml.search.ui/src/org/eclipse/papyrus/cdo/uml/search/internal/ui/query/CDOPapyrusQuery.java
@@ -31,12 +31,16 @@ import org.eclipse.papyrus.infra.core.services.ServicesRegistry;
import org.eclipse.papyrus.infra.emf.utils.ServiceUtilsForResourceSet;
import org.eclipse.papyrus.uml.search.ui.query.AbstractPapyrusQuery;
import org.eclipse.papyrus.uml.search.ui.results.PapyrusSearchResult;
+import org.eclipse.papyrus.views.search.results.AbstractResultEntry;
import org.eclipse.papyrus.views.search.results.ModelElementMatch;
import org.eclipse.papyrus.views.search.scope.ScopeEntry;
import org.eclipse.search.ui.ISearchResult;
+import org.eclipse.search.ui.text.Match;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.UMLPackage;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
@@ -53,12 +57,15 @@ public class CDOPapyrusQuery extends AbstractPapyrusQuery {
private final PapyrusSearchResult searchResult = new PapyrusSearchResult(this);
- public CDOPapyrusQuery(String searchText, CDOView view, CDOQuery query) {
+ private final AttributeMatchStrategy attributeMatchStrategy;
+
+ public CDOPapyrusQuery(String searchText, CDOView view, CDOQuery query, AttributeMatchStrategy attributeMatchStrategy) {
super();
this.searchText = searchText;
this.view = view;
this.query = query;
+ this.attributeMatchStrategy = attributeMatchStrategy;
view.addListener(createViewClosedListener());
}
@@ -113,8 +120,11 @@ public class CDOPapyrusQuery extends AbstractPapyrusQuery {
scopeEntries.put(resource.getURI(), scopeEntry);
}
- // TODO: Post-process query results to determine attribute matches?
- searchResult.addMatch(new ModelElementMatch(next, scopeEntry));
+ AbstractResultEntry elementMatch = new ModelElementMatch(next, scopeEntry);
+ searchResult.addMatch(elementMatch);
+
+ // post-process the query result to determine specific attribute matches
+ postProcessAttributeMatches(searchResult, elementMatch, next);
} catch (Exception e) {
// can get "node not found" exceptions on incompletely
// deleted resources
@@ -127,6 +137,15 @@ public class CDOPapyrusQuery extends AbstractPapyrusQuery {
return result;
}
+ protected void postProcessAttributeMatches(PapyrusSearchResult searchResult, AbstractResultEntry elementMatch, Element element) {
+ List<Match> attributeMatches = Lists.newArrayListWithExpectedSize(1);
+ attributeMatchStrategy.apply(elementMatch, element, attributeMatches);
+
+ if(!attributeMatches.isEmpty()) {
+ searchResult.addMatches(Iterables.toArray(attributeMatches, Match.class));
+ }
+ }
+
@Override
public ISearchResult getSearchResult() {
return searchResult;
diff --git a/extraplugins/cdo/org.eclipse.papyrus.cdo.uml.search.ui/src/org/eclipse/papyrus/cdo/uml/search/internal/ui/query/CDOSearchQueryProvider.java b/extraplugins/cdo/org.eclipse.papyrus.cdo.uml.search.ui/src/org/eclipse/papyrus/cdo/uml/search/internal/ui/query/CDOSearchQueryProvider.java
index 34500a34f11..4c7627bcaa2 100644
--- a/extraplugins/cdo/org.eclipse.papyrus.cdo.uml.search.ui/src/org/eclipse/papyrus/cdo/uml/search/internal/ui/query/CDOSearchQueryProvider.java
+++ b/extraplugins/cdo/org.eclipse.papyrus.cdo.uml.search.ui/src/org/eclipse/papyrus/cdo/uml/search/internal/ui/query/CDOSearchQueryProvider.java
@@ -83,7 +83,7 @@ public class CDOSearchQueryProvider implements IPapyrusQueryProvider {
final String searchPattern = _searchPattern.getElement1();
final boolean isRegexMatch = _searchPattern.getElement2();
- return createOCLSearchQuery(queryInfo, new Function<Triplet<QueryInfo, CDOView, Collection<URI>>, CDOQuery>() {
+ return createOCLSearchQuery(queryInfo, AttributeMatchStrategy.create(queryInfo), new Function<Triplet<QueryInfo, CDOView, Collection<URI>>, CDOQuery>() {
@Override
public CDOQuery apply(Triplet<QueryInfo, CDOView, Collection<URI>> input) {
@@ -126,7 +126,7 @@ public class CDOSearchQueryProvider implements IPapyrusQueryProvider {
}
}
- return createOCLSearchQuery(queryInfo, new Function<Triplet<QueryInfo, CDOView, Collection<URI>>, CDOQuery>() {
+ return createOCLSearchQuery(queryInfo, AttributeMatchStrategy.create(queryInfo, attributes), new Function<Triplet<QueryInfo, CDOView, Collection<URI>>, CDOQuery>() {
@Override
public CDOQuery apply(Triplet<QueryInfo, CDOView, Collection<URI>> input) {
@@ -154,7 +154,7 @@ public class CDOSearchQueryProvider implements IPapyrusQueryProvider {
return Pair.create(searchPattern, isRegexMatch);
}
- protected AbstractPapyrusQuery createOCLSearchQuery(QueryInfo queryInfo, Function<Triplet<QueryInfo, CDOView, Collection<URI>>, CDOQuery> queryFunction) {
+ protected AbstractPapyrusQuery createOCLSearchQuery(QueryInfo queryInfo, AttributeMatchStrategy attributeMatcheStrategy, Function<Triplet<QueryInfo, CDOView, Collection<URI>>, CDOQuery> queryFunction) {
IServiceRegistryTracker tracker = new DefaultServiceRegistryTracker();
Multimap<CDOView, URI> views = getViews(queryInfo.getScope());
@@ -165,7 +165,7 @@ public class CDOSearchQueryProvider implements IPapyrusQueryProvider {
// parameters for the server-side OCL query handler
query.setParameter("cdoImplicitRootClass", EcorePackage.Literals.EOBJECT);
- AbstractPapyrusQuery searchQuery = new CDOPapyrusQuery(queryInfo.getQueryText(), view, query);
+ AbstractPapyrusQuery searchQuery = new CDOPapyrusQuery(queryInfo.getQueryText(), view, query, attributeMatcheStrategy);
result.add(searchQuery);
try {
@@ -340,7 +340,7 @@ public class CDOSearchQueryProvider implements IPapyrusQueryProvider {
if(isRegexMatch) {
result.append(".matches(searchPattern)"); //$NON-NLS-1$
} else {
- result.append(" = searchPattern"); //$NON-NLS-1$
+ result.append(".indexOf(searchPattern) > 0"); //$NON-NLS-1$
}
// close the exists iterator (many case) or 'and' group (scalar case)
@@ -353,7 +353,7 @@ public class CDOSearchQueryProvider implements IPapyrusQueryProvider {
if(isRegexMatch) {
result.append(".matches(searchPattern)"); //$NON-NLS-1$
} else {
- result.append(" = searchPattern"); //$NON-NLS-1$
+ result.append(".indexOf(searchPattern) > 0"); //$NON-NLS-1$
}
// close the exists iterator
diff --git a/extraplugins/cdo/org.eclipse.papyrus.cdo.uml.search.ui/src/org/eclipse/papyrus/cdo/uml/search/internal/ui/query/PatternUtil.java b/extraplugins/cdo/org.eclipse.papyrus.cdo.uml.search.ui/src/org/eclipse/papyrus/cdo/uml/search/internal/ui/query/PatternUtil.java
index e9e857bb730..5a7514bf70b 100644
--- a/extraplugins/cdo/org.eclipse.papyrus.cdo.uml.search.ui/src/org/eclipse/papyrus/cdo/uml/search/internal/ui/query/PatternUtil.java
+++ b/extraplugins/cdo/org.eclipse.papyrus.cdo.uml.search.ui/src/org/eclipse/papyrus/cdo/uml/search/internal/ui/query/PatternUtil.java
@@ -13,6 +13,8 @@ package org.eclipse.papyrus.cdo.uml.search.internal.ui.query;
import static java.util.regex.Pattern.quote;
+import java.util.regex.Matcher;
+
/**
* Utilities for working with regex patterns in CDO OCL queries.
@@ -72,4 +74,38 @@ public class PatternUtil {
}
return result;
}
+
+ /**
+ * Local post-processing of element matches uses {@link Matcher#find()} to gather up all applicable attribute matches. This method converts
+ * the user's search criteria into an appropriate regular expression.
+ *
+ * @param searchText
+ * the user's search text
+ * @param caseSensitive
+ * whether the search is case-sensitive
+ * @param regularExpression
+ * whether the search tex is to be interpreted as a regular expression
+ *
+ * @return the appropriately modified string specifying the regular expression search term, never {@code null}
+ */
+ public static String wrapForFind(String searchText, boolean caseSensitive, boolean regularExpression) {
+ String result;
+
+ if(caseSensitive) {
+ if(!regularExpression) {
+ result = quote(searchText); // simple sub-string search
+ } else {
+ result = searchText; // already a regex
+ }
+ } else {
+ if(!regularExpression) {
+ // make a case-insensitive regex matching the literal text
+ result = String.format("(?i)%s", quote(searchText));
+ } else {
+ result = String.format("(?i)%s", searchText);
+ }
+ }
+
+ return result;
+ }
}

Back to the top