1 /* DurationType.java -- 2 Copyright (C) 2006 Free Software Foundation, Inc. 3 4 This file is part of GNU Classpath. 5 6 GNU Classpath is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2, or (at your option) 9 any later version. 10 11 GNU Classpath is distributed in the hope that it will be useful, but 12 WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with GNU Classpath; see the file COPYING. If not, write to the 18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19 02110-1301 USA. 20 21 Linking this library statically or dynamically with other modules is 22 making a combined work based on this library. Thus, the terms and 23 conditions of the GNU General Public License cover the whole 24 combination. 25 26 As a special exception, the copyright holders of this library give you 27 permission to link this library with independent modules to produce an 28 executable, regardless of the license terms of these independent 29 modules, and to copy and distribute the resulting executable under 30 terms of your choice, provided that you also meet, for each linked 31 independent module, the terms and conditions of the license of that 32 module. An independent module is a module which is not derived from 33 or based on this library. If you modify this library, you may extend 34 this exception to your version of the library, but you are not 35 obligated to do so. If you do not wish to do so, delete this 36 exception statement from your version. */ 37 38 package gnu.xml.validation.datatype; 39 40 import javax.xml.XMLConstants; 41 import javax.xml.namespace.QName; 42 import org.relaxng.datatype.DatatypeException; 43 import org.relaxng.datatype.ValidationContext; 44 45 /** 46 * The XML Schema duration type. 47 * 48 * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a> 49 */ 50 final class DurationType 51 extends AtomicSimpleType 52 { 53 54 static class Duration 55 implements Comparable 56 { 57 int years; 58 int months; 59 int days; 60 int minutes; 61 float seconds; 62 hashCode()63 public int hashCode() 64 { 65 int hc = years; 66 hc = hc * 31 + months; 67 hc = hc * 31 + days; 68 hc = hc * 31 + minutes; 69 hc = hc * 31 + new Float(seconds).hashCode(); 70 return hc; 71 } 72 equals(Object other)73 public boolean equals(Object other) 74 { 75 if (other instanceof Duration) 76 { 77 Duration duration = (Duration) other; 78 return duration.years ==years && 79 duration.months == months && 80 duration.days == days && 81 duration.minutes == minutes && 82 duration.seconds == seconds; 83 } 84 return false; 85 } 86 compareTo(Object other)87 public int compareTo(Object other) 88 { 89 if (other instanceof Duration) 90 { 91 Duration duration = (Duration) other; 92 if (duration.years != years) 93 return years - duration.years; 94 if (duration.months != months) 95 return months - duration.months; 96 if (duration.days != days) 97 return days - duration.days; 98 if (duration.minutes != minutes) 99 return minutes = duration.minutes; 100 if (duration.seconds == seconds) 101 return 0; 102 return (seconds < duration.seconds) ? -1 : 1; 103 } 104 return 0; 105 } 106 107 } 108 109 static final int[] CONSTRAINING_FACETS = { 110 Facet.PATTERN, 111 Facet.ENUMERATION, 112 Facet.WHITESPACE, 113 Facet.MAX_INCLUSIVE, 114 Facet.MAX_EXCLUSIVE, 115 Facet.MIN_INCLUSIVE, 116 Facet.MIN_EXCLUSIVE 117 }; 118 DurationType()119 DurationType() 120 { 121 super(new QName(XMLConstants.W3C_XML_SCHEMA_NS_URI, "duration"), 122 TypeLibrary.ANY_SIMPLE_TYPE); 123 } 124 getConstrainingFacets()125 public int[] getConstrainingFacets() 126 { 127 return CONSTRAINING_FACETS; 128 } 129 checkValid(String value, ValidationContext context)130 public void checkValid(String value, ValidationContext context) 131 throws DatatypeException 132 { 133 super.checkValid(value, context); 134 int len = value.length(); 135 char expect = 'P'; 136 boolean seenT = false; 137 for (int i = 0; i < len; i++) 138 { 139 char c = value.charAt(i); 140 if (c == '-' && expect == 'P') 141 continue; 142 if (c == expect) 143 { 144 if (c == 'P') 145 expect = 'Y'; 146 else if (c == 'Y') 147 expect = 'M'; 148 else if (c == 'M' && !seenT) 149 expect = 'D'; 150 else if (c == 'D') 151 expect = 'T'; 152 else if (c == 'T') 153 { 154 expect = 'H'; 155 seenT = true; 156 } 157 else if (c == 'H') 158 expect = 'M'; 159 else if (c == 'M' && seenT) 160 expect = 'S'; 161 else if (c == 'S') 162 { 163 if (i + 1 != len) 164 throw new DatatypeException(i, "illegal duration value"); 165 } 166 continue; 167 } 168 if (c >= 0x30 && c <= 0x39 && expect != 'P' && expect != 'T') 169 continue; 170 throw new DatatypeException(i, "illegal duration value"); 171 } 172 } 173 createValue(String value, ValidationContext context)174 public Object createValue(String value, ValidationContext context) { 175 boolean negative = false; 176 int days = 0, months = 0, years = 0; 177 int minutes = 0; 178 float seconds = 0.0f; 179 int len = value.length(); 180 char expect = 'P'; 181 boolean seenT = false; 182 int start = 0; 183 for (int i = 0; i < len; i++) 184 { 185 char c = value.charAt(i); 186 if (c == '-' && expect == 'P') 187 { 188 negative = true; 189 continue; 190 } 191 if (c == expect) 192 { 193 if (c == 'P') 194 expect = 'Y'; 195 else if (c == 'Y') 196 { 197 expect = 'M'; 198 years = Integer.parseInt(value.substring(start, i)); 199 } 200 else if (c == 'M' && !seenT) 201 expect = 'D'; 202 else if (c == 'D') 203 expect = 'T'; 204 else if (c == 'T') 205 { 206 expect = 'H'; 207 seenT = true; 208 } 209 else if (c == 'H') 210 expect = 'M'; 211 else if (c == 'M' && seenT) 212 expect = 'S'; 213 else if (c == 'S') 214 { 215 if (i + 1 != len) 216 return null; 217 } 218 start = i + 1; 219 continue; 220 } 221 if (c >= 0x30 && c <= 0x39 && expect != 'P' && expect != 'T') 222 continue; 223 return null; 224 } 225 if (negative) 226 { 227 days = days * -1; 228 minutes = minutes * -1; 229 seconds = seconds * -1.0f; 230 } 231 Duration duration = new Duration(); 232 duration.days = days; 233 duration.minutes = minutes; 234 duration.seconds = seconds; 235 return duration; 236 } 237 238 } 239