package com.mobilesorcery.sdk.profiling.filter; import java.util.ArrayList; import java.util.Locale; import java.util.regex.Pattern; import org.eclipse.core.runtime.Path; import com.mobilesorcery.sdk.core.IFilter; import com.mobilesorcery.sdk.core.MergeFilter; import com.mobilesorcery.sdk.core.ParseException; import com.mobilesorcery.sdk.core.PropertyUtil; import com.mobilesorcery.sdk.core.ReverseFilter; import com.mobilesorcery.sdk.profiling.CppFiltName; import com.mobilesorcery.sdk.profiling.FunctionDesc; import com.mobilesorcery.sdk.profiling.IInvocation; import com.mobilesorcery.sdk.profiling.filter.NameFilter.Criteria; public class NameFilter implements IFilter<IInvocation> { public enum MatchType { EXACT_MATCH, REGEXP, CONTAINS } public enum Criteria { NAME, FILE } private Pattern pattern; private String match; private final MatchType type; private final Criteria criteria; private final boolean include; public static IFilter<IInvocation> create(String match, Criteria criteria, MatchType matchType, boolean include) throws ParseException { String[] matchStrings = PropertyUtil.toStrings(match); ArrayList<IFilter<IInvocation>> result = new ArrayList<IFilter<IInvocation>>(); for (int i = 0; i < matchStrings.length; i++) { result.add(new NameFilter(matchStrings[i], criteria, matchType, true)); } IFilter<IInvocation> filter = MergeFilter.create(MergeFilter.OR, result.toArray(new IFilter[0])); return include || result.isEmpty() ? filter : new ReverseFilter<IInvocation>(filter); } private NameFilter(String match, Criteria criteria, MatchType matchType, boolean include) throws ParseException { switch (matchType) { case EXACT_MATCH: case CONTAINS: this.match = match; break; case REGEXP: try { pattern = Pattern.compile(match); } catch (Exception e) { throw new ParseException(String.format("Invalid regexp: %s", match)); } break; } this.criteria = criteria; this.type = matchType; this.include = include; } @Override public boolean accept(IInvocation obj) { if (obj != null && obj.getProfiledEntity() != null) { String matched = getNameToMatch(obj); if (pattern != null) { return pattern.matcher(matched).matches(); } else if (match != null) { return type == MatchType.EXACT_MATCH ? matched.equalsIgnoreCase(match) : // English locale will be fine for C identifiers. matched.toUpperCase(Locale.ENGLISH).contains(match.toUpperCase(Locale.ENGLISH)); } } boolean result = pattern == null && match == null; return include ? result : !result; } private String getNameToMatch(IInvocation invocation) { FunctionDesc fd = invocation.getProfiledEntity(); String matched = ""; switch (criteria) { case NAME: CppFiltName name = CppFiltName.parse(fd.getName()); matched = name.getFullName(); break; case FILE: matched = fd.getFileName(); if (matched != null) { matched = new Path(matched).lastSegment(); } break; } matched = matched == null ? "" : matched; return matched; } @Override public String toString() { // For debugging purposes. return match + "<" + criteria + "," + type + ">"; } }