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