KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > joda > time > format > PeriodFormatter


1 /*
2  * Copyright 2001-2005 Stephen Colebourne
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.joda.time.format;
17
18 import java.io.IOException JavaDoc;
19 import java.io.Writer JavaDoc;
20 import java.util.Locale JavaDoc;
21
22 import org.joda.time.MutablePeriod;
23 import org.joda.time.Period;
24 import org.joda.time.PeriodType;
25 import org.joda.time.ReadWritablePeriod;
26 import org.joda.time.ReadablePeriod;
27
28 /**
29  * Controls the printing and parsing of a time period to and from a string.
30  * <p>
31  * This class is the main API for printing and parsing used by most applications.
32  * Instances of this class are created via one of three factory classes:
33  * <ul>
34  * <li>{@link PeriodFormat} - formats by pattern and style</li>
35  * <li>{@link ISOPeriodFormat} - ISO8601 formats</li>
36  * <li>{@link PeriodFormatterBuilder} - complex formats created via method calls</li>
37  * </ul>
38  * <p>
39  * An instance of this class holds a reference internally to one printer and
40  * one parser. It is possible that one of these may be null, in which case the
41  * formatter cannot print/parse. This can be checked via the {@link #isPrinter()}
42  * and {@link #isParser()} methods.
43  * <p>
44  * The underlying printer/parser can be altered to behave exactly as required
45  * by using a decorator modifier:
46  * <ul>
47  * <li>{@link #withLocale(Locale)} - returns a new formatter that uses the specified locale</li>
48  * </ul>
49  * This returns a new formatter (instances of this class are immutable).
50  * <p>
51  * The main methods of the class are the <code>printXxx</code> and
52  * <code>parseXxx</code> methods. These are used as follows:
53  * <pre>
54  * // print using the default locale
55  * String periodStr = formatter.print(period);
56  * // print using the French locale
57  * String periodStr = formatter.withLocale(Locale.FRENCH).print(period);
58  *
59  * // parse using the French locale
60  * Period date = formatter.withLocale(Locale.FRENCH).parsePeriod(str);
61  * </pre>
62  *
63  * @author Brian S O'Neill
64  * @author Stephen Colebourne
65  * @since 1.0
66  */

67 public class PeriodFormatter {
68
69     /** The internal printer used to output the datetime. */
70     private final PeriodPrinter iPrinter;
71     /** The internal parser used to output the datetime. */
72     private final PeriodParser iParser;
73     /** The locale to use for printing and parsing. */
74     private final Locale JavaDoc iLocale;
75     /** The period type used in parsing. */
76     private final PeriodType iParseType;
77
78     /**
79      * Creates a new formatter, however you will normally use the factory
80      * or the builder.
81      *
82      * @param printer the internal printer, null if cannot print
83      * @param parser the internal parser, null if cannot parse
84      */

85     public PeriodFormatter(
86             PeriodPrinter printer, PeriodParser parser) {
87         super();
88         iPrinter = printer;
89         iParser = parser;
90         iLocale = null;
91         iParseType = null;
92     }
93
94     /**
95      * Constructor.
96      *
97      * @param printer the internal printer, null if cannot print
98      * @param parser the internal parser, null if cannot parse
99      * @param locale the locale to use
100      * @param type the parse period type
101      */

102     private PeriodFormatter(
103             PeriodPrinter printer, PeriodParser parser,
104             Locale JavaDoc locale, PeriodType type) {
105         super();
106         iPrinter = printer;
107         iParser = parser;
108         iLocale = locale;
109         iParseType = type;
110     }
111
112     //-----------------------------------------------------------------------
113
/**
114      * Is this formatter capable of printing.
115      *
116      * @return true if this is a printer
117      */

118     public boolean isPrinter() {
119         return (iPrinter != null);
120     }
121
122     /**
123      * Gets the internal printer object that performs the real printing work.
124      *
125      * @return the internal printer
126      */

127     public PeriodPrinter getPrinter() {
128         return iPrinter;
129     }
130
131     /**
132      * Is this formatter capable of parsing.
133      *
134      * @return true if this is a parser
135      */

136     public boolean isParser() {
137         return (iParser != null);
138     }
139
140     /**
141      * Gets the internal parser object that performs the real parsing work.
142      *
143      * @return the internal parser
144      */

145     public PeriodParser getParser() {
146         return iParser;
147     }
148
149     //-----------------------------------------------------------------------
150
/**
151      * Returns a new formatter with a different locale that will be used
152      * for printing and parsing.
153      * <p>
154      * A PeriodFormatter is immutable, so a new instance is returned,
155      * and the original is unaltered and still usable.
156      *
157      * @param locale the locale to use
158      * @return the new formatter
159      */

160     public PeriodFormatter withLocale(Locale JavaDoc locale) {
161         if (locale == getLocale() || (locale != null && locale.equals(getLocale()))) {
162             return this;
163         }
164         return new PeriodFormatter(iPrinter, iParser, locale, iParseType);
165     }
166
167     /**
168      * Gets the locale that will be used for printing and parsing.
169      *
170      * @return the locale to use
171      */

172     public Locale JavaDoc getLocale() {
173         return iLocale;
174     }
175
176     //-----------------------------------------------------------------------
177
/**
178      * Returns a new formatter with a different PeriodType for parsing.
179      * <p>
180      * A PeriodFormatter is immutable, so a new instance is returned,
181      * and the original is unaltered and still usable.
182      *
183      * @param type the type to use in parsing
184      * @return the new formatter
185      */

186     public PeriodFormatter withParseType(PeriodType type) {
187         if (type == iParseType) {
188             return this;
189         }
190         return new PeriodFormatter(iPrinter, iParser, iLocale, type);
191     }
192
193     /**
194      * Gets the PeriodType that will be used for parsing.
195      *
196      * @return the parse type to use
197      */

198     public PeriodType getParseType() {
199         return iParseType;
200     }
201
202     //-----------------------------------------------------------------------
203
/**
204      * Prints a ReadablePeriod to a StringBuffer.
205      *
206      * @param buf the formatted period is appended to this buffer
207      * @param period the period to format, not null
208      */

209     public void printTo(StringBuffer JavaDoc buf, ReadablePeriod period) {
210         checkPrinter();
211         checkPeriod(period);
212         
213         getPrinter().printTo(buf, period, iLocale);
214     }
215
216     /**
217      * Prints a ReadablePeriod to a Writer.
218      *
219      * @param out the formatted period is written out
220      * @param period the period to format, not null
221      */

222     public void printTo(Writer JavaDoc out, ReadablePeriod period) throws IOException JavaDoc {
223         checkPrinter();
224         checkPeriod(period);
225         
226         getPrinter().printTo(out, period, iLocale);
227     }
228
229     /**
230      * Prints a ReadablePeriod to a new String.
231      *
232      * @param period the period to format, not null
233      * @return the printed result
234      */

235     public String JavaDoc print(ReadablePeriod period) {
236         checkPrinter();
237         checkPeriod(period);
238         
239         PeriodPrinter printer = getPrinter();
240         StringBuffer JavaDoc buf = new StringBuffer JavaDoc(printer.calculatePrintedLength(period, iLocale));
241         printer.printTo(buf, period, iLocale);
242         return buf.toString();
243     }
244
245     /**
246      * Checks whether printing is supported.
247      *
248      * @throws UnsupportedOperationException if printing is not supported
249      */

250     private void checkPrinter() {
251         if (iPrinter == null) {
252             throw new UnsupportedOperationException JavaDoc("Printing not supported");
253         }
254     }
255
256     /**
257      * Checks whether the period is non-null.
258      *
259      * @throws IllegalArgumentException if the period is null
260      */

261     private void checkPeriod(ReadablePeriod period) {
262         if (period == null) {
263             throw new IllegalArgumentException JavaDoc("Period must not be null");
264         }
265     }
266
267     //-----------------------------------------------------------------------
268
/**
269      * Parses a period from the given text, at the given position, saving the
270      * result into the fields of the given ReadWritablePeriod. If the parse
271      * succeeds, the return value is the new text position. Note that the parse
272      * may succeed without fully reading the text.
273      * <p>
274      * The parse type of the formatter is not used by this method.
275      * <p>
276      * If it fails, the return value is negative, but the period may still be
277      * modified. To determine the position where the parse failed, apply the
278      * one's complement operator (~) on the return value.
279      *
280      * @param period a period that will be modified
281      * @param text text to parse
282      * @param position position to start parsing from
283      * @return new position, if negative, parse failed. Apply complement
284      * operator (~) to get position of failure
285      * @throws IllegalArgumentException if any field is out of range
286      */

287     public int parseInto(ReadWritablePeriod period, String JavaDoc text, int position) {
288         checkParser();
289         checkPeriod(period);
290         
291         return getParser().parseInto(period, text, position, iLocale);
292     }
293
294     /**
295      * Parses a period from the given text, returning a new Period.
296      *
297      * @param text text to parse
298      * @return parsed value in a Period object
299      * @throws IllegalArgumentException if any field is out of range
300      */

301     public Period parsePeriod(String JavaDoc text) {
302         checkParser();
303         
304         return parseMutablePeriod(text).toPeriod();
305     }
306
307     /**
308      * Parses a period from the given text, returning a new MutablePeriod.
309      *
310      * @param text text to parse
311      * @return parsed value in a MutablePeriod object
312      * @throws IllegalArgumentException if any field is out of range
313      */

314     public MutablePeriod parseMutablePeriod(String JavaDoc text) {
315         checkParser();
316         
317         MutablePeriod period = new MutablePeriod(0, iParseType);
318         int newPos = getParser().parseInto(period, text, 0, iLocale);
319         if (newPos >= 0) {
320             if (newPos >= text.length()) {
321                 return period;
322             }
323         } else {
324             newPos = ~newPos;
325         }
326         throw new IllegalArgumentException JavaDoc(FormatUtils.createErrorMessage(text, newPos));
327     }
328
329     /**
330      * Checks whether parsing is supported.
331      *
332      * @throws UnsupportedOperationException if parsing is not supported
333      */

334     private void checkParser() {
335         if (iParser == null) {
336             throw new UnsupportedOperationException JavaDoc("Parsing not supported");
337         }
338     }
339
340 }
341
Popular Tags