KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > beehive > netui > script > el > tokens > ExpressionToken


1 /*
2  * Copyright 2004 The Apache Software Foundation.
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  * $Header:$
17  */

18 package org.apache.beehive.netui.script.el.tokens;
19
20 import java.lang.reflect.Array JavaDoc;
21 import java.lang.reflect.Field JavaDoc;
22 import java.lang.reflect.Method JavaDoc;
23 import java.util.List JavaDoc;
24 import java.util.Map JavaDoc;
25
26 import org.apache.beehive.netui.util.internal.cache.PropertyCache;
27 import org.apache.beehive.netui.util.logging.Logger;
28 import org.apache.beehive.netui.script.el.util.ParseUtils;
29
30 /**
31  *
32  */

33 public abstract class ExpressionToken {
34
35     private static final Logger LOGGER = Logger.getInstance(ArrayIndexToken.class);
36
37     private static final PropertyCache PROPERTY_CACHE = new PropertyCache();
38
39     public abstract Object JavaDoc evaluate(Object JavaDoc value);
40
41     public abstract void update(Object JavaDoc root, Object JavaDoc newValue);
42
43     public abstract String JavaDoc getTokenString();
44
45
46     /*
47      *
48      * Property Lookup
49      *
50      */

51     protected final Object JavaDoc mapLookup(Map JavaDoc map, Object JavaDoc identifier) {
52         if(LOGGER.isDebugEnabled())
53             LOGGER.debug("mapLookup: " + identifier);
54         return map.get(identifier);
55     }
56
57     protected final Object JavaDoc beanLookup(Object JavaDoc bean, Object JavaDoc identifier) {
58         if(LOGGER.isDebugEnabled())
59             LOGGER.debug("beanLookup: " + identifier);
60
61         return ParseUtils.getProperty(bean, identifier.toString(), PROPERTY_CACHE);
62     }
63
64     protected final Object JavaDoc listLookup(List JavaDoc list, int index) {
65         if(LOGGER.isDebugEnabled())
66             LOGGER.debug("listLookup: " + index);
67
68         return list.get(index);
69     }
70
71     protected final Object JavaDoc arrayLookup(Object JavaDoc array, int index) {
72         if(LOGGER.isDebugEnabled())
73             LOGGER.debug("arrayLookup: " + index);
74
75         return Array.get(array, index);
76     }
77
78     protected final void mapUpdate(Map JavaDoc map, Object JavaDoc identifier, Object JavaDoc value) {
79         Object JavaDoc converted = value;
80
81         Object JavaDoc o = map.get(identifier);
82         if(o != null) {
83             Class JavaDoc type = o.getClass();
84             value = ParseUtils.convertType(value, type);
85         }
86
87         map.put(identifier, value);
88     }
89
90     protected final void arrayUpdate(Object JavaDoc array, int index, Object JavaDoc value) {
91         Object JavaDoc converted = value;
92
93         Class JavaDoc elementType = array.getClass().getComponentType();
94         if(!elementType.isAssignableFrom(value.getClass())) {
95             converted = ParseUtils.convertType(value, elementType);
96         }
97
98         try {
99             Array.set(array, index, converted);
100         } catch(Exception JavaDoc e) {
101             String JavaDoc msg = "An error occurred setting a value at index \"" + index + "\" on an array with component types \"" +
102                 elementType + "\". Cause: " + e.toString();
103
104             if(LOGGER.isErrorEnabled()) LOGGER.error(msg);
105             throw new RuntimeException JavaDoc(msg);
106         }
107     }
108
109     protected final void listUpdate(List JavaDoc list, int index, Object JavaDoc value) {
110         Object JavaDoc converted = value;
111
112         if(list.size() > index) {
113             Object JavaDoc o = list.get(index);
114             // can only convert types when there is an item in the currently requested place
115
if(o != null) {
116                 Class JavaDoc itemType = o.getClass();
117                 converted = ParseUtils.convertType(value, itemType);
118             }
119
120             list.set(index, value);
121         } else {
122             // @note: not sure that this is the right thing. Question is whether or not to insert nulls here to fill list up to "index"
123
// @update: List doesn't guarantee that implementations will accept nulls. So, we can't rely on that as a solution.
124
// @update: this is an unfortunate but necessary solution...unless the List has enough elements to
125
// accomodate the new item at a particular index, this must be an error case. The reasons are this:
126
// 1) can't fill the list with nulls, List implementations are allowed to disallow them
127
// 2) can't just do an "add" to the list -- in processing [0] and [1] on an empty list, [1] may get processed first.
128
// this will go into list slot [0]. then, [0] gets processed and simply overwrites the previous because it's
129
// already in the list
130
// 3) can't go to a mixed approach because there's no metadata about what has been done and no time to build
131
// something that is apt to be complicated and exposed to the user
132
// so...
133
// the ultimate 8.1sp2 functionality is to simply disallow updating a value in a list that doesn't exist. that
134
// being said, it is still possible to simply add to the list. if {actionForm.list[42]} inserts into the 42'nd
135
// item, {actionForm.list} will just do an append on POST since there is no index specified. this fix does
136
// not break backwards compatability because it will work on full lists and is completely broken now on empty
137
// lists, so changing this just gives a better exception message that "ArrayIndexOutOfBounds". :)
138
//
139
// September 2, 2003
140
// ekoneil@bea.com
141
//
142
String JavaDoc msg = "An error occurred setting a value at index \"" + index + "\" because the list is " +
143                 (list != null ? (" of size " + list.size()) : "null") + ". " +
144                 "Be sure to allocate enough items in the List to accomodate any updates which may occur against the list.";
145
146             if(LOGGER.isErrorEnabled()) LOGGER.error(msg);
147
148             throw new RuntimeException JavaDoc(msg);
149         }
150     }
151
152     protected final void beanUpdate(Object JavaDoc bean, Object JavaDoc identifier, Object JavaDoc value) {
153         if(LOGGER.isDebugEnabled()) LOGGER.debug("Update \"" + bean + "\" type property \"" + identifier + "\"");
154
155         String JavaDoc id = identifier.toString();
156         Class JavaDoc beanType = bean.getClass();
157         Class JavaDoc propType = PROPERTY_CACHE.getPropertyType(beanType, id);
158         if(propType != null) {
159             try {
160                 if(java.util.List JavaDoc.class.isAssignableFrom(propType)) {
161                     Method JavaDoc lm = PROPERTY_CACHE.getPropertyGetter(beanType, id);
162                     if(lm != null) {
163                         List JavaDoc list = (List JavaDoc)lm.invoke(bean, (Object JavaDoc[])null);
164                         applyValuesToList(value, list);
165                         return;
166                     }
167                 } else {
168                     Method JavaDoc m = PROPERTY_CACHE.getPropertySetter(beanType, id);
169
170                     if(m != null) {
171                         if(LOGGER.isDebugEnabled())
172                             LOGGER.debug("Apply value to property via method: " + m);
173
174                         Class JavaDoc targetType = m.getParameterTypes()[0];
175                         Object JavaDoc converted = ParseUtils.convertType(value, targetType);
176
177                         m.invoke(bean, new Object JavaDoc[]{converted});
178                         return;
179                     }
180                 }
181             } catch(Exception JavaDoc e) {
182                 String JavaDoc msg = "Could not update proprety named \"" + id + "\" on bean of type \"" + beanType + "\". Cause: " + e;
183                 if(LOGGER.isErrorEnabled())
184                     LOGGER.error(msg, e);
185                 throw new RuntimeException JavaDoc(msg, e);
186             }
187         }
188
189         String JavaDoc msg = "Could not update expression because a public JavaBean setter for the property \"" + identifier + "\" could not be found.";
190         LOGGER.error(msg);
191         throw new RuntimeException JavaDoc(msg);
192     }
193
194     protected final int parseIndex(String JavaDoc identifier) {
195         try {
196             return Integer.parseInt(identifier);
197         } catch(Exception JavaDoc e) {
198             String JavaDoc msg = "Error performing an array look-up with the index \"" + identifier + "\". Cause: " + e;
199
200             if(LOGGER.isDebugEnabled())
201                 LOGGER.debug(msg, e);
202
203             throw new RuntimeException JavaDoc(msg, e);
204         }
205     }
206
207     private static final void applyValuesToList(Object JavaDoc value, List JavaDoc list) {
208         if(list == null) {
209             String JavaDoc msg = "Can not add a value to a null java.util.List";
210             LOGGER.error(msg);
211             throw new RuntimeException JavaDoc(msg);
212         }
213
214         if(value instanceof String JavaDoc[]) {
215             String JavaDoc[] ary = (String JavaDoc[])value;
216             for(int i = 0; i < ary.length; i++) {
217                 list.add(ary[i]);
218             }
219         } else if(value instanceof String JavaDoc) {
220             list.add(value);
221         }
222         // types that are not String[] or String are just set on the object
223
else list.add(value);
224     }
225 }
226
Popular Tags