| // Copyright (C) 2011 Chan Wai Shing |
| // |
| // 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 prettify.parser; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.TreeMap; |
| import java.util.regex.Matcher; |
| import java.util.regex.Pattern; |
| |
| /** |
| * Common Utilities. |
| * Some of the functions are port from JavaScript. |
| * |
| * @author Chan Wai Shing <cws1989@gmail.com> |
| */ |
| public class Util { |
| |
| protected Util() { |
| } |
| |
| /** |
| * Treat a variable as an integer in JavaScript style. Note this function can |
| * only handle integer and boolean currently. |
| * |
| * @param var the variable to get value from |
| * @return the integer value |
| * @throws IllegalArgumentException the data type of {@code var} is neither |
| * integer nor boolean. |
| */ |
| public static Integer getVariableValueAsInteger(Object var) { |
| if (var == null) { |
| throw new NullPointerException("argument 'var' cannot be null"); |
| } |
| |
| Integer returnResult = -1; |
| |
| if (var instanceof Integer) { |
| returnResult = (Integer) var; |
| } else if (var instanceof Boolean) { |
| // Javascript treat true as 1 |
| returnResult = (Boolean) var ? 1 : 0; |
| } else { |
| throw new IllegalArgumentException("'var' is neither integer nor boolean"); |
| } |
| |
| return returnResult; |
| } |
| |
| /** |
| * Get all the matches for {@code string} compiled by {@code pattern}. If |
| * {@code isGlobal} is true, the return results will only include the |
| * group 0 matches. It is similar to string.match(regexp) in JavaScript. |
| * |
| * @param pattern the regexp |
| * @param string the string |
| * @param isGlobal similar to JavaScript /g flag |
| * |
| * @return all matches |
| */ |
| public static String[] match(Pattern pattern, String string, boolean isGlobal) { |
| if (pattern == null) { |
| throw new NullPointerException("argument 'pattern' cannot be null"); |
| } |
| if (string == null) { |
| throw new NullPointerException("argument 'string' cannot be null"); |
| } |
| |
| List<String> matchesList = new ArrayList<String>(); |
| |
| Matcher matcher = pattern.matcher(string); |
| while (matcher.find()) { |
| matchesList.add(matcher.group(0)); |
| if (!isGlobal) { |
| for (int i = 1, iEnd = matcher.groupCount(); i <= iEnd; i++) { |
| matchesList.add(matcher.group(i)); |
| } |
| } |
| } |
| |
| return matchesList.toArray(new String[matchesList.size()]); |
| } |
| |
| /** |
| * Test whether the {@code string} has at least one match by |
| * {@code pattern}. |
| * |
| * @param pattern the regexp |
| * @param string the string to test |
| * |
| * @return true if at least one match, false if no match |
| */ |
| public static boolean test(Pattern pattern, String string) { |
| if (pattern == null) { |
| throw new NullPointerException("argument 'pattern' cannot be null"); |
| } |
| if (string == null) { |
| throw new NullPointerException("argument 'string' cannot be null"); |
| } |
| return pattern.matcher(string).find(); |
| } |
| |
| /** |
| * Join the {@code strings} into one string. |
| * |
| * @param strings the string list to join |
| * |
| * @return the joined string |
| */ |
| public static String join(List<String> strings) { |
| if (strings == null) { |
| throw new NullPointerException("argument 'strings' cannot be null"); |
| } |
| return join(strings.toArray(new String[strings.size()])); |
| } |
| |
| /** |
| * Join the {@code strings} into one string with {@code delimiter} in |
| * between. |
| * |
| * @param strings the string list to join |
| * @param delimiter the delimiter |
| * |
| * @return the joined string |
| */ |
| public static String join(List<String> strings, String delimiter) { |
| if (strings == null) { |
| throw new NullPointerException("argument 'strings' cannot be null"); |
| } |
| return join(strings.toArray(new String[strings.size()]), delimiter); |
| } |
| |
| /** |
| * Join the {@code strings} into one string. |
| * |
| * @param strings the string list to join |
| * |
| * @return the joined string |
| */ |
| public static String join(String[] strings) { |
| return join(strings, null); |
| } |
| |
| /** |
| * Join the {@code strings} into one string with {@code delimiter} in |
| * between. It is similar to RegExpObject.test(string) in JavaScript. |
| * |
| * @param strings the string list to join |
| * @param delimiter the delimiter |
| * |
| * @return the joined string |
| */ |
| public static String join(String[] strings, String delimiter) { |
| if (strings == null) { |
| throw new NullPointerException("argument 'strings' cannot be null"); |
| } |
| |
| StringBuilder sb = new StringBuilder(); |
| |
| if (strings.length != 0) { |
| sb.append(strings[0]); |
| for (int i = 1, iEnd = strings.length; i < iEnd; i++) { |
| if (delimiter != null) { |
| sb.append(delimiter); |
| } |
| sb.append(strings[i]); |
| } |
| } |
| |
| return sb.toString(); |
| } |
| |
| /** |
| * Remove identical adjacent tags from {@code decorations}. |
| * |
| * @param decorations see {@link prettify.parser.Job#decorations} |
| * @param source the source code |
| * |
| * @return the {@code decorations} after treatment |
| * |
| * @throws IllegalArgumentException the size of {@code decoration} is not |
| * a multiple of 2 |
| */ |
| public static List<Object> removeDuplicates(List<Object> decorations, String source) { |
| if (decorations == null) { |
| throw new NullPointerException("argument 'decorations' cannot be null"); |
| } |
| if (source == null) { |
| throw new NullPointerException("argument 'source' cannot be null"); |
| } |
| if ((decorations.size() & 0x1) != 0) { |
| throw new IllegalArgumentException("the size of argument 'decorations' should be a multiple of 2"); |
| } |
| |
| List<Object> returnList = new ArrayList<Object>(); |
| |
| // use TreeMap to remove entrys with same pos |
| Map<Integer, Object> orderedMap = new TreeMap<Integer, Object>(); |
| for (int i = 0, iEnd = decorations.size(); i < iEnd; i += 2) { |
| orderedMap.put((Integer) decorations.get(i), decorations.get(i + 1)); |
| } |
| |
| // remove adjacent style |
| String previousStyle = null; |
| for (Integer pos : orderedMap.keySet()) { |
| String style = (String) orderedMap.get(pos); |
| if (previousStyle != null && previousStyle.equals(style)) { |
| continue; |
| } |
| returnList.add(pos); |
| returnList.add(style); |
| previousStyle = style; |
| } |
| |
| // remove last zero length tag |
| int returnListSize = returnList.size(); |
| if (returnListSize >= 4 && returnList.get(returnListSize - 2).equals(source.length())) { |
| returnList.remove(returnListSize - 2); |
| returnList.remove(returnListSize - 2); |
| } |
| |
| return returnList; |
| } |
| } |