001: /*
002: * Copyright 2001-2007 Geert Bevin <gbevin[remove] at uwyn dot com>
003: * Distributed under the terms of either:
004: * - the common development and distribution license (CDDL), v1.0; or
005: * - the GNU Lesser General Public License, v2.1 or later
006: * $Id: OutputValues.java 3784 2007-06-11 16:44:35Z gbevin $
007: */
008: package com.uwyn.rife.engine;
009:
010: import java.util.*;
011:
012: import com.uwyn.rife.engine.exceptions.ElementOutjectionException;
013: import com.uwyn.rife.engine.exceptions.OutbeanOutjectionException;
014: import com.uwyn.rife.engine.exceptions.OutputOutjectionException;
015: import com.uwyn.rife.tools.ArrayUtils;
016: import com.uwyn.rife.tools.BeanPropertyProcessor;
017: import com.uwyn.rife.tools.BeanUtils;
018: import com.uwyn.rife.tools.exceptions.BeanUtilsException;
019: import com.uwyn.rife.tools.exceptions.LightweightError;
020: import java.beans.PropertyDescriptor;
021: import java.lang.reflect.InvocationTargetException;
022: import java.lang.reflect.Method;
023:
024: class OutputValues {
025: private ElementContext mContext = null;
026: private ElementAware mElement = null;
027:
028: private Map<String, String[]> mValues = null;
029: private Map<String, String[]> mFallbackValues = null;
030: private Map<String, Method> mOutputGetters = null;
031: private Map<String, Method> mOutbeanGetters = null;
032: private Set<String> mNonGetterOutputs = null;
033:
034: OutputValues(ElementContext context) {
035: assert context != null;
036:
037: mContext = context;
038: mElement = mContext.getElementSupport().getElementAware();
039: mValues = new LinkedHashMap<String, String[]>();
040:
041: // try to obtain the output and outbean getters from the cache
042: // if this wasn't possible, detect them and store them in the cache
043: ElementInfo element_info = mContext.getElementInfo();
044: mOutputGetters = element_info.getSite().getCachedOutputGetters(
045: element_info.getId());
046: mOutbeanGetters = element_info.getSite()
047: .getCachedOutbeanGetters(element_info.getId());
048: if (null == mOutputGetters || null == mOutbeanGetters) {
049: mOutputGetters = null;
050: mOutbeanGetters = null;
051:
052: try {
053: BeanUtils.processProperties(BeanUtils.GETTERS, mElement
054: .getClass(), null, null, null,
055: new OutputValuesPropertyProcessor());
056:
057: if (null == mOutputGetters) {
058: mOutputGetters = Collections.EMPTY_MAP;
059: }
060: if (null == mOutbeanGetters) {
061: mOutbeanGetters = Collections.EMPTY_MAP;
062: }
063: element_info.getSite().putCachedOutputGetters(
064: element_info.getId(), mOutputGetters);
065: element_info.getSite().putCachedOutbeanGetters(
066: element_info.getId(), mOutbeanGetters);
067: } catch (BeanUtilsException e) {
068: throw new ElementOutjectionException(mContext
069: .getElementInfo().getDeclarationName(),
070: mElement.getClass(), e);
071: }
072: }
073: }
074:
075: void processGetters() {
076: Object value = null;
077: if (mOutputGetters != null && mOutputGetters.size() > 0) {
078: try {
079: for (Map.Entry<String, Method> output_getter : mOutputGetters
080: .entrySet()) {
081: value = output_getter.getValue().invoke(mElement,
082: (Object[]) null);
083: if (value != null) {
084: mContext.fireOutputValueSet(output_getter
085: .getKey(), ArrayUtils
086: .createStringArray(value, null));
087: }
088: }
089: } catch (LightweightError e) {
090: throw e;
091: } catch (Exception e) {
092: throw new OutputOutjectionException(mContext
093: .getElementInfo().getDeclarationName(),
094: mElement.getClass(), e);
095: }
096: }
097:
098: if (mOutbeanGetters != null && mOutbeanGetters.size() > 0) {
099: BeanDeclaration bean = null;
100: for (Map.Entry<String, Method> outbean_getter : mOutbeanGetters
101: .entrySet()) {
102: try {
103: bean = mContext.getElementInfo()
104: .getNamedOutbeanInfo(
105: outbean_getter.getKey());
106: value = outbean_getter.getValue().invoke(mElement,
107: (Object[]) null);
108: if (value != null) {
109: Map<String, String[]> bean_values = mContext
110: .getOutputBeanValues(value, bean
111: .getPrefix(), null);
112: for (Map.Entry<String, String[]> entry : bean_values
113: .entrySet()) {
114: if (entry.getValue() != null) {
115: mContext.fireOutputValueSet(entry
116: .getKey(), entry.getValue());
117: }
118: }
119: }
120: } catch (LightweightError e) {
121: throw e;
122: } catch (Exception e) {
123: throw new OutbeanOutjectionException(mContext
124: .getElementInfo().getDeclarationName(),
125: mElement.getClass(), outbean_getter
126: .getKey(), e);
127: }
128: }
129: }
130: }
131:
132: void processGetterChildTriggers() {
133: if (mContext.getElementState().inInheritanceStructure()) {
134: Collection<String> childtrigger_names = mContext
135: .getElementInfo().getChildTriggerNames();
136:
137: Object value = null;
138: if (mOutputGetters != null && mOutputGetters.size() > 0) {
139: try {
140: for (Map.Entry<String, Method> output_getter : mOutputGetters
141: .entrySet()) {
142: if (childtrigger_names.contains(output_getter
143: .getKey())) {
144: value = output_getter.getValue().invoke(
145: mElement, (Object[]) null);
146: if (value != null) {
147: mContext
148: .triggerChild(output_getter
149: .getKey(), ArrayUtils
150: .createStringArray(
151: value, null));
152: }
153: }
154: }
155: } catch (LightweightError e) {
156: throw e;
157: } catch (Exception e) {
158: throw new OutputOutjectionException(mContext
159: .getElementInfo().getDeclarationName(),
160: mElement.getClass(), e);
161: }
162: }
163:
164: if (mOutbeanGetters != null && mOutbeanGetters.size() > 0) {
165: BeanDeclaration bean = null;
166: for (Map.Entry<String, Method> outbean_getter : mOutbeanGetters
167: .entrySet()) {
168: try {
169: bean = mContext.getElementInfo()
170: .getNamedOutbeanInfo(
171: outbean_getter.getKey());
172: value = outbean_getter.getValue().invoke(
173: mElement, (Object[]) null);
174: if (value != null) {
175: Map<String, String[]> bean_values = mContext
176: .getOutputBeanValues(value, bean
177: .getPrefix(), null);
178: for (Map.Entry<String, String[]> entry : bean_values
179: .entrySet()) {
180: if (entry.getValue() != null) {
181: mContext
182: .triggerChild(entry
183: .getKey(), entry
184: .getValue());
185: }
186: }
187: }
188: } catch (LightweightError e) {
189: throw e;
190: } catch (Exception e) {
191: throw new OutbeanOutjectionException(mContext
192: .getElementInfo().getDeclarationName(),
193: mElement.getClass(), outbean_getter
194: .getKey(), e);
195: }
196: }
197: }
198: }
199: }
200:
201: void put(String name, String[] values) {
202: if (null == name)
203: return;
204:
205: if (mOutputGetters != null) {
206: if (null == values) {
207: if (mNonGetterOutputs != null) {
208: mNonGetterOutputs.remove(name);
209: }
210: } else {
211: if (null == mNonGetterOutputs) {
212: mNonGetterOutputs = new HashSet<String>();
213: }
214:
215: mNonGetterOutputs.add(name);
216: }
217: }
218:
219: mValues.put(name, values);
220: }
221:
222: void putFallback(String name, String[] values) {
223: if (null == name)
224: return;
225:
226: if (null == mFallbackValues) {
227: mFallbackValues = new LinkedHashMap<String, String[]>();
228: }
229:
230: mFallbackValues.put(name, values);
231: }
232:
233: String[] get(String name) {
234: if (null == name)
235: return null;
236:
237: String[] outputs = mValues.get(name);
238: if (null == outputs
239: && mContext.getElementInfo().hasOutputDefaults()) {
240: outputs = mContext.getElementInfo().getOutputDefaultValues(
241: name);
242: }
243:
244: if (null == outputs && mOutputGetters != null
245: && mOutputGetters.containsKey(name)) {
246: try {
247: Object value = mOutputGetters.get(name).invoke(
248: mElement, (Object[]) null);
249: if (value != null) {
250: outputs = ArrayUtils.createStringArray(value, null);
251: }
252: } catch (Exception e) {
253: throw new OutputOutjectionException(mContext
254: .getElementInfo().getDeclarationName(),
255: mElement.getClass(), e);
256: }
257: }
258:
259: if (null == outputs && mFallbackValues != null) {
260: outputs = mFallbackValues.get(name);
261: }
262:
263: return outputs;
264: }
265:
266: Map<String, String[]> aggregateValues() {
267: Map<String, String[]> entry_map = null;
268:
269: // handle default output values
270: if (mContext.getElementInfo().hasOutputDefaults()) {
271: if (null == entry_map) {
272: entry_map = new LinkedHashMap<String, String[]>();
273: }
274:
275: for (Map.Entry<String, String[]> output_defaults_entry : mContext
276: .getElementInfo().getOutputEntries()) {
277: if (output_defaults_entry.getValue() != null) {
278: entry_map.put(output_defaults_entry.getKey(),
279: output_defaults_entry.getValue());
280: }
281: }
282: }
283:
284: // handle outbeans getter outjection
285: if (mOutbeanGetters != null && mOutbeanGetters.size() > 0) {
286: BeanDeclaration bean = null;
287: Object value = null;
288: for (Map.Entry<String, Method> outbean_getter : mOutbeanGetters
289: .entrySet()) {
290: try {
291: bean = mContext.getElementInfo()
292: .getNamedOutbeanInfo(
293: outbean_getter.getKey());
294: value = outbean_getter.getValue().invoke(mElement,
295: (Object[]) null);
296: if (value != null) {
297: if (null == entry_map) {
298: entry_map = new LinkedHashMap<String, String[]>();
299: }
300:
301: Map<String, String[]> bean_values = mContext
302: .getOutputBeanValues(value, bean
303: .getPrefix(), null);
304: entry_map.putAll(bean_values);
305: }
306: } catch (Exception e) {
307: throw new OutbeanOutjectionException(mContext
308: .getElementInfo().getDeclarationName(),
309: mElement.getClass(), outbean_getter
310: .getKey(), e);
311: }
312: }
313: }
314:
315: // handle output getter outjection
316: if (mOutputGetters != null && mOutputGetters.size() > 0) {
317: Object value = null;
318: try {
319: for (Map.Entry<String, Method> output_getter : mOutputGetters
320: .entrySet()) {
321: if (mNonGetterOutputs != null
322: && mNonGetterOutputs.contains(output_getter
323: .getKey())) {
324: continue;
325: }
326:
327: value = output_getter.getValue().invoke(mElement,
328: (Object[]) null);
329: if (value != null) {
330: if (null == entry_map) {
331: entry_map = new LinkedHashMap<String, String[]>();
332: }
333:
334: entry_map.put(output_getter.getKey(),
335: ArrayUtils.createStringArray(value,
336: null));
337: }
338: }
339: } catch (Exception e) {
340: throw new OutputOutjectionException(mContext
341: .getElementInfo().getDeclarationName(),
342: mElement.getClass(), e);
343: }
344: }
345:
346: if (mFallbackValues != null && mFallbackValues.size() > 0) {
347: if (null == entry_map) {
348: entry_map = new LinkedHashMap<String, String[]>();
349: }
350:
351: for (Map.Entry<String, String[]> fallback_output : mFallbackValues
352: .entrySet()) {
353: if (!entry_map.containsKey(fallback_output.getKey())) {
354: entry_map.put(fallback_output.getKey(),
355: fallback_output.getValue());
356: }
357: }
358: }
359:
360: // handle outputs that have been explicitly set
361: if (null == entry_map) {
362: return Collections.unmodifiableMap(mValues);
363: } else {
364: entry_map.putAll(mValues);
365: }
366:
367: return Collections.unmodifiableMap(entry_map);
368: }
369:
370: private class OutputValuesPropertyProcessor implements
371: BeanPropertyProcessor {
372: private ElementInfo mElementInfo;
373: private Collection<String> mNamesOutputs;
374: private Collection<String> mNamesGlobalvars;
375: private Collection<String> mNamesOutbeans;
376: private Collection<String> mNamesGlobalbeans;
377:
378: OutputValuesPropertyProcessor() {
379: mElementInfo = mContext.getElementInfo();
380: mNamesOutputs = mElementInfo.getOutputNames();
381: mNamesGlobalvars = mElementInfo.getGlobalVarNames();
382: mNamesOutbeans = mElementInfo.getNamedOutbeanNames();
383: mNamesGlobalbeans = mElementInfo.getNamedGlobalBeanNames();
384: }
385:
386: public boolean gotProperty(String name,
387: PropertyDescriptor descriptor)
388: throws IllegalAccessException,
389: IllegalArgumentException, InvocationTargetException {
390: Method method = descriptor.getReadMethod();
391: if (mNamesOutputs.contains(name)
392: || mNamesGlobalvars.contains(name)) {
393: if (null == mOutputGetters) {
394: mOutputGetters = new LinkedHashMap<String, Method>();
395: }
396:
397: method.setAccessible(true);
398: mOutputGetters.put(name, method);
399: } else if (mNamesOutbeans.contains(name)
400: || mNamesGlobalbeans.contains(name)) {
401: if (null == mOutbeanGetters) {
402: mOutbeanGetters = new LinkedHashMap<String, Method>();
403: }
404:
405: BeanDeclaration bean = mElementInfo
406: .getNamedOutbeanInfo(name);
407: try {
408: if (bean.getBeanClass().isAssignableFrom(
409: method.getReturnType())) {
410: method.setAccessible(true);
411: mOutbeanGetters.put(name, method);
412: }
413: } catch (ClassNotFoundException e) {
414: throw new OutbeanOutjectionException(mContext
415: .getElementInfo().getDeclarationName(),
416: mElement.getClass(), name, e);
417: }
418: }
419:
420: return true;
421: }
422: }
423: }
|