KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > jga > fn > string > ParseFormat


1 // ============================================================================
2
// $Id: ParseFormat.java,v 1.13 2006/04/26 03:41:38 davidahall Exp $
3
// Copyright (c) 2003-2005 David A. Hall
4
// ============================================================================
5
// The contents of this file are subject to the Common Development and
6
// Distribution License (CDDL), Version 1.0 (the License); you may not use this
7
// file except in compliance with the License. You should have received a copy
8
// of the the License along with this file: if not, a copy of the License is
9
// available from Sun Microsystems, Inc.
10
//
11
// http://www.sun.com/cddl/cddl.html
12
//
13
// From time to time, the license steward (initially Sun Microsystems, Inc.) may
14
// publish revised and/or new versions of the License. You may not use,
15
// distribute, or otherwise make this file available under subsequent versions
16
// of the License.
17
//
18
// Alternatively, the contents of this file may be used under the terms of the
19
// GNU Lesser General Public License Version 2.1 or later (the "LGPL"), in which
20
// case the provisions of the LGPL are applicable instead of those above. If you
21
// wish to allow use of your version of this file only under the terms of the
22
// LGPL, and not to allow others to use your version of this file under the
23
// terms of the CDDL, indicate your decision by deleting the provisions above
24
// and replace them with the notice and other provisions required by the LGPL.
25
// If you do not delete the provisions above, a recipient may use your version
26
// of this file under the terms of either the CDDL or the LGPL.
27
//
28
// This library is distributed in the hope that it will be useful,
29
// but WITHOUT ANY WARRANTY; without even the implied warranty of
30
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
31
// ============================================================================
32

33 package net.sf.jga.fn.string;
34
35 import java.text.DateFormat JavaDoc;
36 import java.text.Format JavaDoc;
37 import java.text.MessageFormat JavaDoc;
38 import java.text.NumberFormat JavaDoc;
39 import java.text.ParseException JavaDoc;
40 import java.util.Date JavaDoc;
41 import net.sf.jga.fn.EvaluationException;
42 import net.sf.jga.fn.UnaryFunctor;
43 import net.sf.jga.fn.adaptor.Identity;
44 import net.sf.jga.fn.arithmetic.ValueOf;
45 import net.sf.jga.fn.property.Cast;
46 import net.sf.jga.fn.property.ConstructUnary;
47 import net.sf.jga.fn.property.GetProperty;
48
49 /**
50  * Unary Functor that parses a given Format.
51  * <p>
52  * <p>
53  * Copyright &copy; 2003-2005 David A. Hall
54  * @author <a HREF="mailto:davidahall@users.sourceforge.net">David A. Hall</a>
55  **/

56
57 public class ParseFormat<R> extends UnaryFunctor<String JavaDoc,R> {
58
59     static final long serialVersionUID = 6590747028326789147L;
60
61     // The java.text.Format object that controls parsing.
62
private Format JavaDoc _format;
63
64     // A functor that converts the object from the type returned by the format's
65
// parse() method to the parameter type
66
private UnaryFunctor<Object JavaDoc, R> _converter;
67
68     /**
69      * Builds the ParseFormat given a text Format and a functor that can convert
70      * Objects returned by the Format's parse(Object) method and the desired
71      * type of this functor.
72      */

73     protected ParseFormat(Format JavaDoc format, UnaryFunctor<Object JavaDoc,R> conv) {
74         if (format == null) {
75             String JavaDoc msg = "Format must be specified";
76             throw new IllegalArgumentException JavaDoc(msg);
77         }
78         
79         _format = format;
80         _converter = conv;
81     }
82
83     /**
84      * @return the format used to parse values
85      */

86
87     public Format JavaDoc getFormat() {
88         return _format;
89     }
90     
91     // UnaryFunctor interface
92

93     /**
94      * Parses the value from the given string, using the java.text.Format object
95      * passed at construction.
96      * <p>
97      * @param arg formatted string to be parsed
98      * @throws java.text.ParseException when the string cannot be parsed to the
99      * correct type
100      * @return the value that the string represented
101      */

102
103     public R fn(String JavaDoc arg) {
104         
105         try {
106             Object JavaDoc obj = _format.parseObject(arg);
107             // @SuppressWarnings
108
// This line causes an unchecked cast warning: we can't do anything
109
// about this other than warn the user not to use improper formats.
110
// It would help if java.text.Format was generic, but it isn't. If
111
// the user gives us a converter, we're OK, otherwise all we can do
112
// is cast and hope for the best
113
R val = (_converter == null) ? (R) obj : _converter.fn(obj);
114             return val;
115         }
116         catch (ParseException JavaDoc x) {
117             String JavaDoc msg = "Unable to parse \"{0}\"";
118             Object JavaDoc[] args = new Object JavaDoc[]{ arg };
119             throw new EvaluationException(MessageFormat.format(msg,args), x);
120         }
121         catch (ClassCastException JavaDoc x) {
122             String JavaDoc msg = "Unable to convert \"{0}\" to correct type";
123             Object JavaDoc[] args = new Object JavaDoc[]{ arg };
124             throw new EvaluationException(MessageFormat.format(msg,args), x);
125         }
126     }
127     
128     /**
129      * Calls the Visitor's <code>visit(ParseFormat)</code> method, if it
130      * implements the nested Visitor interface.
131      */

132     public void accept(net.sf.jga.fn.Visitor v) {
133         if (v instanceof ParseFormat.Visitor)
134             ((ParseFormat.Visitor)v).visit(this);
135         else
136             v.visit(this);
137     }
138
139     // Object overrides
140

141     public String JavaDoc toString() {
142         return "ParseFormat["+_format+"]";
143     }
144     
145     // Acyclic Visitor
146

147     /**
148      * Interface for classes that may interpret a <b>ParseFormat</b>
149      * predicate.
150      */

151     public interface Visitor extends net.sf.jga.fn.Visitor {
152         public void visit(ParseFormat host);
153     }
154
155     /**
156      * ParseFormat functor for use with Dates. This class exists
157      * as an implementation detail that works around a limit in the javac
158      * inferencer -- in all substantive ways, this is simply a ParseFormat functor.
159      */

160
161     static public class Date<T extends java.util.Date JavaDoc> extends ParseFormat<T> {
162         static final long serialVersionUID = 6959869794482290044L;
163         public Date(Class JavaDoc<T> type, DateFormat JavaDoc format) {
164             super(format, (UnaryFunctor<Object JavaDoc,T>)
165                   // If we want to return java.util.Date, then we can simply cast it.
166
// Otherwise, we return [ new D(((Date)arg).getTime()) ]
167
// since we know that All Date subclasses have a constructor that
168
// takes a long (and this will break if a Date subclass is used that
169
// does not have such a constructor.
170
// The other possibility is to build a date using a default constructor
171
// and set its time property [ new D().setTime(((Date)arg).getTime()) ]
172
// but that functor is even scarier
173

174                   // @SupressWarnings
175
//
176
((type.equals(java.util.Date JavaDoc.class))
177                      ? new Cast<Object JavaDoc,java.util.Date JavaDoc>(java.util.Date JavaDoc.class)
178                      : new ConstructUnary<Long JavaDoc,T>(Long.TYPE, type)
179                          .compose(new GetProperty<java.util.Date JavaDoc,Long JavaDoc>(java.util.Date JavaDoc.class,"Time"))
180                            .compose(new Cast<Object JavaDoc,java.util.Date JavaDoc>(java.util.Date JavaDoc.class))));
181         }
182     }
183
184     /**
185      * ParseFormat functor for use with Numbers. This class exists
186      * as an implementation detail that works around a limit in the javac
187      * inferencer -- in all substantive ways, this is simply a ParseFormat functor.
188      */

189
190     static public class Number<T extends java.lang.Number JavaDoc> extends ParseFormat<T> {
191         static final long serialVersionUID = -5365953713327551298L;
192         public Number(Class JavaDoc<T> type, NumberFormat JavaDoc format) {
193             super(format, //(UnaryFunctor<Object,R>)
194
new ValueOf<java.lang.Number JavaDoc,T>(type)
195                      .compose(new Cast<Object JavaDoc,java.lang.Number JavaDoc>(java.lang.Number JavaDoc.class)));
196         }
197     }
198 }
199
Popular Tags