KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > jga > fn > property > SetField


1 // ============================================================================
2
// $Id: SetField.java,v 1.9 2006/08/05 21:44:48 davidahall Exp $
3
// Copyright (c) 2002-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.property;
34
35 import java.lang.reflect.InvocationTargetException JavaDoc;
36 import java.lang.reflect.Field JavaDoc;
37 import java.text.MessageFormat JavaDoc;
38 import net.sf.jga.fn.BinaryFunctor;
39 import net.sf.jga.fn.EvaluationException;
40
41 /**
42  * Binary Functor that sets the named field of the first argument to the
43  * value. The field name and type are set at construction. The return
44  * value will be null.
45  * <p>
46  * Note that declaring the return type incorrectly can result in
47  * ClassCastExceptions being thrown when the functor is invoked: the compiler
48  * cannot check the return type of a reflectively loaded field.
49  * <p>
50  * Copyright &copy; 2002-2005 David A. Hall
51  *
52  * @author <a HREF="mailto:davidahall@users.sourceforge.net">David A. Hall</a>
53  **/

54
55 // NOTE: compiling this class yields one unchecked cast warning. It is really
56
// up to the user to declare this class properly (the return type must be
57
// correctly specified)
58

59 public class SetField<T,R> extends BinaryFunctor<T,R,R> {
60
61     static final long serialVersionUID = -5051261348109487737L;
62     
63     // The field class, used to find the correct Field using reflection
64
private Class JavaDoc<R> _fieldType;
65
66     // The name of the field
67
private String JavaDoc _fieldName;
68
69     // The field to set
70
private transient Field JavaDoc _field;
71
72     /**
73      * Builds a SetField that will update the value of the given field
74      * @throws IllegalArgumentException if either argument is omitted, or if
75      * there is no such setter field in type argType.
76      */

77     public SetField(Field JavaDoc field) {
78         this((Class JavaDoc<T>) field.getDeclaringClass(), field, (Class JavaDoc<R>) field.getType());
79     }
80     
81
82     /**
83      * Builds a SetField that will update the value of the given field
84      * @throws IllegalArgumentException if either argument is omitted, or if
85      * there is no such setter field in type argType.
86      */

87     public SetField(Class JavaDoc<T> argType, Field JavaDoc field) {
88         this(argType, field, (Class JavaDoc<R>)field.getType());
89     }
90     
91
92     /**
93      * Builds a SetField that will update the value of the given field
94      * @throws IllegalArgumentException if either argument is omitted, or if
95      * there is no such setter field in type argType.
96      */

97     public SetField(Class JavaDoc<T> argType, Field JavaDoc field, Class JavaDoc<R> fieldType) {
98         if (field == null) {
99             throw new IllegalArgumentException JavaDoc("Must supply field");
100         }
101         
102         if (!field.getDeclaringClass().isAssignableFrom(argType)) {
103             throw new IllegalArgumentException JavaDoc(buildNoSuchFieldMessage(field.getName(), argType));
104         }
105
106         _fieldName = field.getName();
107         _fieldType = fieldType;
108         _field = checkFieldType(field, fieldType);
109     }
110     
111
112     /**
113      * Builds a SetField that will update the value of the named field
114      * of an instance of type argType. The field will be of type propType.
115      * @throws IllegalArgumentException if either argument is omitted, or if
116      * there is no such setter field in type argType.
117      */

118     public SetField(Class JavaDoc<T> argType, String JavaDoc fieldName, Class JavaDoc<R> fieldType) {
119         if (fieldName == null || fieldName.length() == 0) {
120             throw new IllegalArgumentException JavaDoc("Must supply field name");
121         }
122         if (fieldType == null) {
123             throw new IllegalArgumentException JavaDoc("Must supply field type");
124         }
125         
126         _fieldName = fieldName;
127         _fieldType = fieldType;
128         
129         try {
130             _field = checkFieldType(argType.getField(_fieldName), fieldType);
131         }
132         catch (NoSuchFieldException JavaDoc x) {
133             IllegalArgumentException JavaDoc iax =
134                 new IllegalArgumentException JavaDoc(buildNoSuchFieldMessage(fieldName, argType));
135             iax.initCause(x);
136             throw iax;
137         }
138     }
139     
140
141     private Field JavaDoc checkFieldType(Field JavaDoc field, Class JavaDoc<R> fieldType) throws IllegalArgumentException JavaDoc {
142         if (!field.getType().isAssignableFrom(fieldType)) {
143             String JavaDoc msg = "Field {0} is of the wrong type: is {1}, expected {2}";
144             Object JavaDoc[] args = new Object JavaDoc[] { field.getName(), field.getType().getName(),
145                                                fieldType.getName() };
146             throw new IllegalArgumentException JavaDoc(MessageFormat.format(msg, args));
147         }
148
149         return field;
150     }
151
152     
153     /**
154      * Returns the name of the field that this functor sets.
155      */

156     public String JavaDoc getFieldName() {
157         return _fieldName;
158     }
159
160     // Binary interface
161

162     /**
163      * Sets the designated field of the argument to the given value and returns
164      * null.
165      * <p>
166      * @return null
167      * @throws EvaluationException if the argument does not have the designated
168      * public field, or if it is accept the given value.
169      */

170     public R fn(T arg, R val) {
171         try {
172             getField(arg).set(arg, val);
173             return null;
174         }
175         catch (ClassCastException JavaDoc x) {
176             String JavaDoc msg = "{0}.{1} is of type {2}";
177             Field JavaDoc f = getField(arg);
178             Object JavaDoc[] args = new Object JavaDoc[]{ arg.getClass().getName(), f.getName(),
179                                           f.getType().getName() };
180             throw new EvaluationException(MessageFormat.format(msg,args), x);
181         }
182         catch (IllegalAccessException JavaDoc x) {
183             String JavaDoc msg = "{0}.{1} is not accessible";
184             Object JavaDoc[] args = new Object JavaDoc[]{ arg.getClass().getName(), getField(arg).getName()};
185             throw new EvaluationException(MessageFormat.format(msg,args), x);
186         }
187     }
188
189     private Field JavaDoc getField(T arg) {
190         if (_field == null) {
191             try {
192                 _field = arg.getClass().getField(_fieldName);
193             }
194             catch (NoSuchFieldException JavaDoc x) {
195                 throw new EvaluationException(x);}
196         }
197
198         return _field;
199     }
200
201     private String JavaDoc buildNoSuchFieldMessage(String JavaDoc fieldname, Class JavaDoc clasz) {
202         String JavaDoc msg = "class {0} does not have field {1}";
203         Object JavaDoc[] args = new Object JavaDoc[]{ clasz.getName(), fieldname };
204         return MessageFormat.format(msg,args);
205     }
206
207     /**
208      * Calls the Visitor's <code>visit(etField)</code> field, if it
209      * implements the nested Visitor interface.
210      */

211     public void accept(net.sf.jga.fn.Visitor v) {
212         if (v instanceof SetField.Visitor)
213             ((SetField.Visitor)v).visit(this);
214         else
215             v.visit(this);
216     }
217     
218     // Object overrides
219

220     public String JavaDoc toString() {
221         return "SetField("+_fieldName+")";
222     }
223     
224     // AcyclicVisitor
225

226     /**
227      * Interface for classes that may interpret a <b>SetField</b>
228      * function.
229      */

230     public interface Visitor extends net.sf.jga.fn.Visitor {
231         public void visit(SetField host);
232     }
233 }
234
Popular Tags