001/* DatatypeFactory.java --
002   Copyright (C) 2004, 2005, 2006  Free Software Foundation, Inc.
003
004This file is part of GNU Classpath.
005
006GNU Classpath is free software; you can redistribute it and/or modify
007it under the terms of the GNU General Public License as published by
008the Free Software Foundation; either version 2, or (at your option)
009any later version.
010
011GNU Classpath is distributed in the hope that it will be useful, but
012WITHOUT ANY WARRANTY; without even the implied warranty of
013MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014General Public License for more details.
015
016You should have received a copy of the GNU General Public License
017along with GNU Classpath; see the file COPYING.  If not, write to the
018Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
01902110-1301 USA.
020
021Linking this library statically or dynamically with other modules is
022making a combined work based on this library.  Thus, the terms and
023conditions of the GNU General Public License cover the whole
024combination.
025
026As a special exception, the copyright holders of this library give you
027permission to link this library with independent modules to produce an
028executable, regardless of the license terms of these independent
029modules, and to copy and distribute the resulting executable under
030terms of your choice, provided that you also meet, for each linked
031independent module, the terms and conditions of the license of that
032module.  An independent module is a module which is not derived from
033or based on this library.  If you modify this library, you may extend
034this exception to your version of the library, but you are not
035obligated to do so.  If you do not wish to do so, delete this
036exception statement from your version. */
037
038package javax.xml.datatype;
039
040import java.io.File;
041import java.io.FileInputStream;
042import java.math.BigDecimal;
043import java.math.BigInteger;
044import java.util.GregorianCalendar;
045import java.util.Iterator;
046import java.util.Properties;
047import java.util.ServiceLoader;
048
049/**
050 * Factory class to create new datatype objects mapping XML to and from Java
051 * objects.
052 *
053 * @author Chris Burdess
054 * @since 1.5
055 */
056public abstract class DatatypeFactory
057{
058
059  /**
060   * JAXP 1.3 default property name.
061   */
062  public static final String DATATYPEFACTORY_PROPERTY = "javax.xml.datatype.DatatypeFactory";
063
064  /**
065   * JAXP 1.3 default implementation class name.
066   */
067  public static final String DATATYPEFACTORY_IMPLEMENTATION_CLASS = "gnu.xml.datatype.JAXPDatatypeFactory";
068
069  protected DatatypeFactory()
070  {
071  }
072
073  /**
074   * Returns a new factory instance.
075   */
076  public static DatatypeFactory newInstance()
077    throws DatatypeConfigurationException
078  {
079    try
080      {
081        // 1. system property
082        String className = System.getProperty(DATATYPEFACTORY_PROPERTY);
083        if (className != null)
084          return (DatatypeFactory) Class.forName(className).newInstance();
085        // 2. jaxp.properties property
086        File javaHome = new File(System.getProperty("java.home"));
087        File javaHomeLib = new File(javaHome, "lib");
088        File jaxpProperties = new File(javaHomeLib, "jaxp.properties");
089        if (jaxpProperties.exists())
090          {
091            FileInputStream in = new FileInputStream(jaxpProperties);
092            Properties p = new Properties();
093            p.load(in);
094            in.close();
095            className = p.getProperty(DATATYPEFACTORY_PROPERTY);
096            if (className != null)
097              return (DatatypeFactory) Class.forName(className).newInstance();
098          }
099        // 3. services
100        Iterator<DatatypeFactory> i = ServiceLoader.load(DatatypeFactory.class).iterator();
101        if (i.hasNext())
102          return i.next();
103        // 4. fallback
104        Class<?> t = Class.forName(DATATYPEFACTORY_IMPLEMENTATION_CLASS);
105        return (DatatypeFactory) t.newInstance();
106      }
107    catch (Exception e)
108      {
109        throw new DatatypeConfigurationException(e);
110      }
111  }
112
113  /**
114   * Returns a new duration from its string representation.
115   * @param lexicalRepresentation the lexical representation of the
116   * duration, as specified in XML Schema 1.0 section 3.2.6.1.
117   */
118  public abstract Duration newDuration(String lexicalRepresentation);
119
120  /**
121   * Returns a new duration.
122   * @param durationInMilliSeconds the duration in milliseconds
123   */
124  public abstract Duration newDuration(long durationInMilliSeconds);
125
126  /**
127   * Returns a new duration by specifying the individual components.
128   * @param isPositive whether the duration is positive
129   * @param years the number of years
130   * @param months the number of months
131   * @param days the number of days
132   * @param hours the number of hours
133   * @param minutes th number of minutes
134   * @param seconds the number of seconds
135   */
136  public abstract Duration newDuration(boolean isPositive,
137                                       BigInteger years,
138                                       BigInteger months,
139                                       BigInteger days,
140                                       BigInteger hours,
141                                       BigInteger minutes,
142                                       BigDecimal seconds);
143
144  /**
145   * Returns a new duration by specifying the individual components.
146   * @param isPositive whether the duration is positive
147   * @param years the number of years
148   * @param months the number of months
149   * @param days the number of days
150   * @param hours the number of hours
151   * @param minutes th number of minutes
152   * @param seconds the number of seconds
153   */
154  public Duration newDuration(boolean isPositive,
155                              int years,
156                              int months,
157                              int days,
158                              int hours,
159                              int minutes,
160                              int seconds)
161  {
162    return newDuration(isPositive,
163                       BigInteger.valueOf((long) years),
164                       BigInteger.valueOf((long) months),
165                       BigInteger.valueOf((long) days),
166                       BigInteger.valueOf((long) hours),
167                       BigInteger.valueOf((long) minutes),
168                       BigDecimal.valueOf((long) seconds));
169  }
170
171  /**
172   * Returns a new dayTimeDuration from its string representation.
173   * @param lexicalRepresentation the lexical representation of the
174   * duration, as specified in XML Schema 1.0 section 3.2.6.1.
175   */
176  public Duration newDurationDayTime(String lexicalRepresentation)
177  {
178    return newDuration(lexicalRepresentation);
179  }
180
181  /**
182   * Returns a new dayTimeDuration.
183   * @param durationInMilliseconds the duration in milliseconds
184   */
185  public Duration newDurationDayTime(long durationInMilliseconds)
186  {
187    // TODO xmlSchemaType
188    return newDuration(durationInMilliseconds);
189  }
190
191  /**
192   * Returns a new dayTimeDuration by specifying the individual components.
193   * @param isPositive whether the duration is positive
194   * @param days the number of days
195   * @param hours the number of hours
196   * @param minutes th number of minutes
197   * @param seconds the number of seconds
198   */
199  public Duration newDurationDayTime(boolean isPositive,
200                                     BigInteger days,
201                                     BigInteger hours,
202                                     BigInteger minutes,
203                                     BigInteger seconds)
204  {
205    return newDuration(isPositive,
206                       null,
207                       null,
208                       days,
209                       hours,
210                       minutes,
211                       new BigDecimal(seconds));
212  }
213
214  /**
215   * Returns a new dayTimeDuration by specifying the individual components.
216   * @param isPositive whether the duration is positive
217   * @param days the number of days
218   * @param hours the number of hours
219   * @param minutes th number of minutes
220   * @param seconds the number of seconds
221   */
222  public Duration newDurationDayTime(boolean isPositive,
223                                     int days,
224                                     int hours,
225                                     int minutes,
226                                     int seconds)
227  {
228    return newDuration(isPositive,
229                       null,
230                       null,
231                       BigInteger.valueOf((long) days),
232                       BigInteger.valueOf((long) hours),
233                       BigInteger.valueOf((long) minutes),
234                       BigDecimal.valueOf((long) seconds));
235  }
236
237  /**
238   * Returns a new yearMonthDuration from its string representation.
239   * @param lexicalRepresentation the lexical representation of the
240   * duration, as specified in XML Schema 1.0 section 3.2.6.1.
241   */
242  public Duration newDurationYearMonth(String lexicalRepresentation)
243  {
244    return newDuration(lexicalRepresentation);
245  }
246
247  /**
248   * Returns a new yearMonthDuration.
249   * @param durationInMilliseconds the duration in milliseconds
250   */
251  public Duration newDurationYearMonth(long durationInMilliseconds)
252  {
253    // TODO xmlSchemaType
254    return newDuration(durationInMilliseconds);
255  }
256
257  /**
258   * Returns a new yearMonthDuration by specifying the individual components.
259   * @param isPositive whether the duration is positive
260   * @param years the number of years
261   * @param months the number of months
262   */
263  public Duration newDurationYearMonth(boolean isPositive,
264                                       BigInteger years,
265                                       BigInteger months)
266  {
267    return newDuration(isPositive,
268                       years,
269                       months,
270                       null,
271                       null,
272                       null,
273                       null);
274  }
275
276  /**
277   * Returns a new yearMonthDuration by specifying the individual components.
278   * @param isPositive whether the duration is positive
279   * @param years the number of years
280   * @param months the number of months
281   */
282  public Duration newDurationYearMonth(boolean isPositive,
283                                       int years,
284                                       int months)
285  {
286    return newDuration(isPositive,
287                       BigInteger.valueOf((long) years),
288                       BigInteger.valueOf((long) months),
289                       null,
290                       null,
291                       null,
292                       null);
293  }
294
295  /**
296   * Returns a new XMLGregorianCalendar with no fields initialized.
297   */
298  public abstract XMLGregorianCalendar newXMLGregorianCalendar();
299
300  /**
301   * Returns a new XMLGregorianCalendar from a string representation.
302   * @param lexicalRepresentation the lexical representation as specified in
303   * XML Schema 1.0 Part 2, section 3.2.[7-14].1.
304   */
305  public abstract XMLGregorianCalendar newXMLGregorianCalendar(String lexicalRepresentation);
306
307  /**
308   * Returns a new XMLGregorianCalendar based on the specified Gregorian
309   * calendar.
310   */
311  public abstract XMLGregorianCalendar newXMLGregorianCalendar(GregorianCalendar cal);
312
313  /**
314   * Returns a new XMLGregorianCalendar with the specified components.
315   */
316  public abstract XMLGregorianCalendar newXMLGregorianCalendar(BigInteger year,
317                                                               int month,
318                                                               int day,
319                                                               int hour,
320                                                               int minute,
321                                                               int second,
322                                                               BigDecimal fractionalSecond,
323                                                               int timezone);
324
325  /**
326   * Returns a new XMLGregorianCalendar with the specified components.
327   */
328  public XMLGregorianCalendar newXMLGregorianCalendar(int year,
329                                                      int month,
330                                                      int day,
331                                                      int hour,
332                                                      int minute,
333                                                      int second,
334                                                      int millisecond,
335                                                      int timezone)
336  {
337    return newXMLGregorianCalendar(BigInteger.valueOf((long) year),
338                                   month,
339                                   day,
340                                   hour,
341                                   minute,
342                                   second,
343                                   new BigDecimal(((double) millisecond) / 1000.0),
344                                   timezone);
345  }
346
347  /**
348   * Returns a new XMLGregorianCalendar with the specified components.
349   */
350  public XMLGregorianCalendar newXMLGregorianCalendarDate(int year,
351                                                          int month,
352                                                          int day,
353                                                          int timezone)
354  {
355    return newXMLGregorianCalendar(BigInteger.valueOf((long) year),
356                                   month,
357                                   day,
358                                   DatatypeConstants.FIELD_UNDEFINED,
359                                   DatatypeConstants.FIELD_UNDEFINED,
360                                   DatatypeConstants.FIELD_UNDEFINED,
361                                   null,
362                                   timezone);
363  }
364
365  /**
366   * Returns a new XMLGregorianCalendar with the specified components.
367   */
368  public XMLGregorianCalendar newXMLGregorianCalendarTime(int hours,
369                                                          int minutes,
370                                                          int seconds,
371                                                          int timezone)
372  {
373    return newXMLGregorianCalendar(null,
374                                   DatatypeConstants.FIELD_UNDEFINED,
375                                   DatatypeConstants.FIELD_UNDEFINED,
376                                   hours,
377                                   minutes,
378                                   seconds,
379                                   null,
380                                   timezone);
381  }
382
383  /**
384   * Returns a new XMLGregorianCalendar with the specified components.
385   */
386  public XMLGregorianCalendar newXMLGregorianCalendarTime(int hours,
387                                                          int minutes,
388                                                          int seconds,
389                                                          BigDecimal fractionalSecond,
390                                                          int timezone)
391  {
392    return newXMLGregorianCalendar(null,
393                                   DatatypeConstants.FIELD_UNDEFINED,
394                                   DatatypeConstants.FIELD_UNDEFINED,
395                                   hours,
396                                   minutes,
397                                   seconds,
398                                   fractionalSecond,
399                                   timezone);
400  }
401
402  /**
403   * Returns a new XMLGregorianCalendar with the specified components.
404   */
405  public XMLGregorianCalendar newXMLGregorianCalendarTime(int hours,
406                                                          int minutes,
407                                                          int seconds,
408                                                          int milliseconds,
409                                                          int timezone)
410  {
411    return newXMLGregorianCalendar(null,
412                                   DatatypeConstants.FIELD_UNDEFINED,
413                                   DatatypeConstants.FIELD_UNDEFINED,
414                                   hours,
415                                   minutes,
416                                   seconds,
417                                   new BigDecimal(((double) milliseconds) / 1000.0),
418                                   timezone);
419  }
420
421}