001 /* 002 * Copyright (c) 2006 Henri Sivonen 003 * 004 * Permission is hereby granted, free of charge, to any person obtaining a 005 * copy of this software and associated documentation files (the "Software"), 006 * to deal in the Software without restriction, including without limitation 007 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 008 * and/or sell copies of the Software, and to permit persons to whom the 009 * Software is furnished to do so, subject to the following conditions: 010 * 011 * The above copyright notice and this permission notice shall be included in 012 * all copies or substantial portions of the Software. 013 * 014 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 015 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 016 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 017 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 018 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 019 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 020 * DEALINGS IN THE SOFTWARE. 021 */ 022 023 package fi.iki.hsivonen.xml; 024 025 import java.util.LinkedList; 026 import java.util.List; 027 import java.util.regex.Matcher; 028 import java.util.regex.Pattern; 029 030 /** 031 * Static utilities for working with (X)HTML5 attribute values. 032 * 033 * @version $Id: AttributeUtil.java,v 1.4 2006/11/29 18:13:33 hsivonen Exp $ 034 * @author hsivonen 035 */ 036 public class AttributeUtil { 037 038 /** 039 * An empty string array instance. 040 */ 041 private final static String[] EMPTY_STRING_ARRAY = {}; 042 043 /** 044 * The pattern for extracting an integer by skipping white space and ignoring 045 * trailing garbage. 046 */ 047 private static Pattern INTEGER_PATTERN = Pattern.compile("^[ \t\n\r]*(-?[0-9]+)"); 048 049 /** 050 * Private constructor to prevent instantiation. 051 */ 052 private AttributeUtil() { 053 super(); 054 } 055 056 /** 057 * Returns the integer represented by <code>attrVal</code> or 058 * <code>Integer.MIN_VALUE</code> on error. 059 * 060 * @param attrVal a string representing an integer attribute 061 * value (can be <code>null</code>) 062 * @return the integer represented by <code>attrVal</code> or 063 * <code>Integer.MIN_VALUE</code> on error 064 */ 065 public static int parseInteger(String attrVal) { 066 if (attrVal == null) { 067 return Integer.MIN_VALUE; 068 } 069 Matcher m = INTEGER_PATTERN.matcher(attrVal); 070 if (!m.matches()) { 071 return Integer.MIN_VALUE; 072 } 073 try { 074 return Integer.parseInt(m.group(1)); 075 } catch (NumberFormatException e) { 076 return Integer.MIN_VALUE; 077 } 078 } 079 080 /** 081 * Returns the non-negative integer represented by 082 * <code>attrVal</code> or -1 on error. 083 * 084 * @param attrVal a string representing a non-negative 085 * integer attribute value (can be <code>null</code>) 086 * @return the integer represented by <code>attrVal</code> or 087 * -1 on error 088 */ 089 public static int parseNonNegativeInteger(String attrVal) { 090 int rv = parseInteger(attrVal); 091 if (rv < 0) { 092 return -1; 093 } else { 094 return rv; 095 } 096 } 097 098 /** 099 * Returns the positive integer represented by 100 * <code>attrVal</code> or -1 on error. 101 * 102 * @param attrVal a string representing a positive 103 * integer attribute value (can be <code>null</code>) 104 * @return the integer represented by <code>attrVal</code> or 105 * -1 on error 106 */ 107 public static int parsePositiveInteger(String attrVal) { 108 int rv = parseInteger(attrVal); 109 if (rv < 1) { 110 return -1; 111 } else { 112 return rv; 113 } 114 } 115 116 /** 117 * Splits the argument on white space. 118 * 119 * @param value the attribute value 120 * @return a string array with zero or more strings none of which 121 * is the empty string and none of which contains white space characters. 122 */ 123 public static String[] split(String value) { 124 if (value == null || "".equals(value)) { 125 return EMPTY_STRING_ARRAY; 126 } 127 int len = value.length(); 128 List<String> list = new LinkedList<String>(); 129 boolean collectingSpace = true; 130 int start = 0; 131 for (int i = 0; i < len; i++) { 132 char c = value.charAt(i); 133 if (c == ' ' || c == '\t' || c == '\n' || c == '\r') { 134 if (!collectingSpace) { 135 list.add(value.substring(start, i)); 136 collectingSpace = true; 137 } 138 } else { 139 if (collectingSpace) { 140 start = i; 141 collectingSpace = false; 142 } 143 } 144 } 145 if (start < len) { 146 list.add(value.substring(start, len)); 147 } 148 return list.toArray(EMPTY_STRING_ARRAY); 149 } 150 151 }