001 package org.whattf.checker;
002
003
004 import java.util.LinkedList;
005 import java.util.List;
006 import java.util.regex.Matcher;
007 import java.util.regex.Pattern;
008
009 /**
010 * Static utilities for working with (X)HTML5 attribute values.
011 *
012 * @version $Id: AttributeUtil.java 169 2007-05-25 07:21:55Z hsivonen $
013 * @author hsivonen
014 */
015 public class AttributeUtil {
016
017 /**
018 * An empty string array instance.
019 */
020 private final static String[] EMPTY_STRING_ARRAY = {};
021
022 /**
023 * The pattern for extracting an integer by skipping white space and ignoring
024 * trailing garbage.
025 */
026 private static Pattern INTEGER_PATTERN = Pattern.compile("^[ \t\n\r]*(-?[0-9]+)");
027
028 /**
029 * Private constructor to prevent instantiation.
030 */
031 private AttributeUtil() {
032 super();
033 }
034
035 /**
036 * Returns the integer represented by <code>attrVal</code> or
037 * <code>Integer.MIN_VALUE</code> on error.
038 *
039 * @param attrVal a string representing an integer attribute
040 * value (can be <code>null</code>)
041 * @return the integer represented by <code>attrVal</code> or
042 * <code>Integer.MIN_VALUE</code> on error
043 */
044 public static int parseInteger(String attrVal) {
045 if (attrVal == null) {
046 return Integer.MIN_VALUE;
047 }
048 Matcher m = INTEGER_PATTERN.matcher(attrVal);
049 if (!m.matches()) {
050 return Integer.MIN_VALUE;
051 }
052 try {
053 return Integer.parseInt(m.group(1));
054 } catch (NumberFormatException e) {
055 return Integer.MIN_VALUE;
056 }
057 }
058
059 /**
060 * Returns the non-negative integer represented by
061 * <code>attrVal</code> or -1 on error.
062 *
063 * @param attrVal a string representing a non-negative
064 * integer attribute value (can be <code>null</code>)
065 * @return the integer represented by <code>attrVal</code> or
066 * -1 on error
067 */
068 public static int parseNonNegativeInteger(String attrVal) {
069 int rv = parseInteger(attrVal);
070 if (rv < 0) {
071 return -1;
072 } else {
073 return rv;
074 }
075 }
076
077 /**
078 * Returns the positive integer represented by
079 * <code>attrVal</code> or -1 on error.
080 *
081 * @param attrVal a string representing a positive
082 * integer attribute value (can be <code>null</code>)
083 * @return the integer represented by <code>attrVal</code> or
084 * -1 on error
085 */
086 public static int parsePositiveInteger(String attrVal) {
087 int rv = parseInteger(attrVal);
088 if (rv < 1) {
089 return -1;
090 } else {
091 return rv;
092 }
093 }
094
095 /**
096 * Splits the argument on white space.
097 *
098 * @param value the attribute value
099 * @return a string array with zero or more strings none of which
100 * is the empty string and none of which contains white space characters.
101 */
102 public static String[] split(String value) {
103 if (value == null || "".equals(value)) {
104 return EMPTY_STRING_ARRAY;
105 }
106 int len = value.length();
107 List<String> list = new LinkedList<String>();
108 boolean collectingSpace = true;
109 int start = 0;
110 for (int i = 0; i < len; i++) {
111 char c = value.charAt(i);
112 if (c == ' ' || c == '\t' || c == '\n' || c == '\r') {
113 if (!collectingSpace) {
114 list.add(value.substring(start, i));
115 collectingSpace = true;
116 }
117 } else {
118 if (collectingSpace) {
119 start = i;
120 collectingSpace = false;
121 }
122 }
123 }
124 if (start < len) {
125 list.add(value.substring(start, len));
126 }
127 return list.toArray(EMPTY_STRING_ARRAY);
128 }
129
130 }