/* * Copyright 2003-2011 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package jetbrains.mps.util; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; /** * evgeny, 11/18/11 */ public class PatternUtil { private static enum State { NO_QUOTING, QUOTING, SEQUENCE_LETTERS } public static boolean matchesPattern(String pattern, String matchingText) { if (pattern == null || pattern.length() == 0) { return true; } if (matchingText == null || matchingText.length() == 0) { return false; } return matchingText.charAt(0) == pattern.charAt(0) && (matchingText.startsWith(pattern) || matchingText.matches(PatternUtil.getExactItemPatternBuilder(pattern, false, false).toString() + ".*")); } public static StringBuilder getExactItemPatternBuilder(String text, boolean useDots, boolean useStarAndQuestionMark) { StringBuilder b = new StringBuilder(); State state = State.NO_QUOTING; for (int i = 0; i < text.length(); i++) { char c = text.charAt(i); state = appendNextChar(c, state, b, useDots, useStarAndQuestionMark); } if (state == State.QUOTING) { b.append("\\E"); } return b; } private static State appendNextChar(char c, State state, StringBuilder b, boolean useDots, boolean useStarAndQuestionMark) { if (state == State.SEQUENCE_LETTERS && Character.isUpperCase(c)) { b.append("[a-z0-9_]*"); b.append("((").append(c).append(")|((\\s)+[").append(Character.toLowerCase(c)).append(c).append("]))"); return State.SEQUENCE_LETTERS; } if (c == '*' || c == '?' || c == '.' || c == '@' || Character.isLetterOrDigit(c) || c == '_') { if (state == State.QUOTING) { b.append("\\E"); } } else { if (state != State.QUOTING) { b.append("\\Q"); } } if (c == '*') { if (useStarAndQuestionMark) { b.append(".*"); } else { b.append("\\*"); } return State.NO_QUOTING; } else if (c == '?') { if (useStarAndQuestionMark) { b.append("."); } else { b.append("\\?"); } return State.NO_QUOTING; } else if (c == '.') { if (useDots) { b.append("[^\\.]*\\."); } else { b.append("\\."); } return State.NO_QUOTING; } else if (c == '@') { b.append("[^\\@\\.]*\\@"); return State.NO_QUOTING; } else if (Character.isLetterOrDigit(c) || c == '_') { b.append(c); return State.SEQUENCE_LETTERS; } else { b.append(c); return State.QUOTING; } } public static List<Integer> getIndexes(@NotNull String pattern, boolean useDots, @NotNull String matchingText) { List<Integer> indexList = new ArrayList<Integer>(); if (addIndexes(matchingText, indexList, pattern)) { return indexList; } else { indexList = new ArrayList<Integer>(); } StringBuilder nextSubstring = new StringBuilder(); for (int i = 0; i < pattern.length(); i++) { char c = pattern.charAt(i); if (c == '*' || c == '?') { if (!addIndexes(matchingText, indexList, nextSubstring.toString())) return new ArrayList<Integer>(); nextSubstring = new StringBuilder(); } else if (useDots && c == '.' || c == '@' || Character.isUpperCase(c)) { if (!addIndexes(matchingText, indexList, nextSubstring.toString())) return new ArrayList<Integer>(); String upperCase = new String(new char[]{c}); String spaceAndLowerCase = " " + Character.toLowerCase(c); if (!addIndexes(matchingText, indexList, upperCase) && !addIndexes(matchingText, indexList, spaceAndLowerCase)) return new ArrayList<Integer>(); nextSubstring = new StringBuilder(); } else { nextSubstring.append(c); } } if (!addIndexes(matchingText, indexList, nextSubstring.toString())) return new ArrayList<Integer>(); return indexList; } private static boolean addIndexes(String matchingText, List<Integer> indexList, String nextSubstring) { int curIndex = indexList.isEmpty() ? 0 : indexList.get(indexList.size() - 1) + 1; int indexOf = matchingText.indexOf(nextSubstring, curIndex); if (indexOf == -1) { return false; } for (int j = 0; j < nextSubstring.length(); ++j) { indexList.add(indexOf + j); } return true; } }