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 }