/* * Copyright 2001-2008 Geert Bevin <gbevin[remove] at uwyn dot com> * Licensed under the Apache License, Version 2.0 (the "License") * $Id: OutputValues.java 3918 2008-04-14 17:35:35Z gbevin $ */ package com.uwyn.rife.engine; import java.util.*; import com.uwyn.rife.engine.exceptions.ElementOutjectionException; import com.uwyn.rife.engine.exceptions.OutbeanOutjectionException; import com.uwyn.rife.engine.exceptions.OutputOutjectionException; import com.uwyn.rife.tools.ArrayUtils; import com.uwyn.rife.tools.BeanPropertyProcessor; import com.uwyn.rife.tools.BeanUtils; import com.uwyn.rife.tools.exceptions.BeanUtilsException; import com.uwyn.rife.tools.exceptions.LightweightError; import java.beans.PropertyDescriptor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; class OutputValues { private ElementContext mContext = null; private ElementAware mElement = null; private Map<String, String[]> mValues = null; private Map<String, String[]> mFallbackValues = null; private Map<String, Method> mOutputGetters = null; private Map<String, Method> mOutbeanGetters = null; private Set<String> mNonGetterOutputs = null; OutputValues(ElementContext context) { assert context != null; mContext = context; mElement = mContext.getElementSupport().getElementAware(); mValues = new LinkedHashMap<String, String[]>(); // try to obtain the output and outbean getters from the cache // if this wasn't possible, detect them and store them in the cache ElementInfo element_info = mContext.getElementInfo(); mOutputGetters = element_info.getSite().getCachedOutputGetters(element_info.getId()); mOutbeanGetters = element_info.getSite().getCachedOutbeanGetters(element_info.getId()); if (null == mOutputGetters || null == mOutbeanGetters) { mOutputGetters = null; mOutbeanGetters = null; try { BeanUtils.processProperties(BeanUtils.GETTERS, mElement.getClass(), null, null, null, new OutputValuesPropertyProcessor()); if (null == mOutputGetters) { mOutputGetters = Collections.EMPTY_MAP; } if (null == mOutbeanGetters) { mOutbeanGetters = Collections.EMPTY_MAP; } element_info.getSite().putCachedOutputGetters(element_info.getId(), mOutputGetters); element_info.getSite().putCachedOutbeanGetters(element_info.getId(), mOutbeanGetters); } catch (BeanUtilsException e) { throw new ElementOutjectionException(mContext.getElementInfo().getDeclarationName(), mElement.getClass(), e); } } } void processGetters() { Object value = null; if (mOutputGetters != null && mOutputGetters.size() > 0) { try { for (Map.Entry<String, Method> output_getter : mOutputGetters.entrySet()) { value = output_getter.getValue().invoke(mElement, (Object[])null); if (value != null) { mContext.fireOutputValueSet(output_getter.getKey(), ArrayUtils.createStringArray(value, null)); } } } catch (LightweightError e) { throw e; } catch (Exception e) { throw new OutputOutjectionException(mContext.getElementInfo().getDeclarationName(), mElement.getClass(), e); } } if (mOutbeanGetters != null && mOutbeanGetters.size() > 0) { BeanDeclaration bean = null; for (Map.Entry<String, Method> outbean_getter : mOutbeanGetters.entrySet()) { try { bean = mContext.getElementInfo().getNamedOutbeanInfo(outbean_getter.getKey()); value = outbean_getter.getValue().invoke(mElement, (Object[])null); if (value != null) { Map<String, String[]> bean_values = mContext.collectOutputBeanValues(value, bean.getPrefix(), null); for (Map.Entry<String, String[]> entry : bean_values.entrySet()) { if (entry.getValue() != null) { mContext.fireOutputValueSet(entry.getKey(), entry.getValue()); } } } } catch (LightweightError e) { throw e; } catch (Exception e) { throw new OutbeanOutjectionException(mContext.getElementInfo().getDeclarationName(), mElement.getClass(), outbean_getter.getKey(), e); } } } } void processGetterChildTriggers() { if (mContext.getElementState().inInheritanceStructure()) { Collection<String> childtrigger_names = mContext.getElementInfo().getChildTriggerNames(); Object value = null; if (mOutputGetters != null && mOutputGetters.size() > 0) { try { for (Map.Entry<String, Method> output_getter : mOutputGetters.entrySet()) { if (childtrigger_names.contains(output_getter.getKey())) { value = output_getter.getValue().invoke(mElement, (Object[])null); if (value != null) { mContext.triggerChild(output_getter.getKey(), ArrayUtils.createStringArray(value, null)); } } } } catch (LightweightError e) { throw e; } catch (Exception e) { throw new OutputOutjectionException(mContext.getElementInfo().getDeclarationName(), mElement.getClass(), e); } } if (mOutbeanGetters != null && mOutbeanGetters.size() > 0) { BeanDeclaration bean = null; for (Map.Entry<String, Method> outbean_getter : mOutbeanGetters.entrySet()) { try { bean = mContext.getElementInfo().getNamedOutbeanInfo(outbean_getter.getKey()); value = outbean_getter.getValue().invoke(mElement, (Object[])null); if (value != null) { Map<String, String[]> bean_values = mContext.collectOutputBeanValues(value, bean.getPrefix(), null); for (Map.Entry<String, String[]> entry : bean_values.entrySet()) { if (entry.getValue() != null) { mContext.triggerChild(entry.getKey(), entry.getValue()); } } } } catch (LightweightError e) { throw e; } catch (Exception e) { throw new OutbeanOutjectionException(mContext.getElementInfo().getDeclarationName(), mElement.getClass(), outbean_getter.getKey(), e); } } } } } void put(String name, String[] values) { if (null == name) return; if (mOutputGetters != null) { if (null == values) { if (mNonGetterOutputs != null) { mNonGetterOutputs.remove(name); } } else { if (null == mNonGetterOutputs) { mNonGetterOutputs = new HashSet<String>(); } mNonGetterOutputs.add(name); } } mValues.put(name, values); } void putFallback(String name, String[] values) { if (null == name) return; if (null == mFallbackValues) { mFallbackValues = new LinkedHashMap<String, String[]>(); } mFallbackValues.put(name, values); } String[] get(String name) { if (null == name) return null; String[] outputs = mValues.get(name); if (null == outputs && mContext.getElementInfo().hasOutputDefaults()) { outputs = mContext.getElementInfo().getOutputDefaultValues(name); } if (null == outputs && mOutputGetters != null && mOutputGetters.containsKey(name)) { try { Object value = mOutputGetters.get(name).invoke(mElement, (Object[])null); if (value != null) { outputs = ArrayUtils.createStringArray(value, null); } } catch (Exception e) { throw new OutputOutjectionException(mContext.getElementInfo().getDeclarationName(), mElement.getClass(), e); } } if (null == outputs && mFallbackValues != null) { outputs = mFallbackValues.get(name); } return outputs; } Map<String, String[]> aggregateValues() { Map<String, String[]> entry_map = null; // handle default output values if (mContext.getElementInfo().hasOutputDefaults()) { if (null == entry_map) { entry_map = new LinkedHashMap<String, String[]>(); } for (Map.Entry<String, String[]> output_defaults_entry : mContext.getElementInfo().getOutputEntries()) { if (output_defaults_entry.getValue() != null) { entry_map.put(output_defaults_entry.getKey(), output_defaults_entry.getValue()); } } } // handle outbeans getter outjection if (mOutbeanGetters != null && mOutbeanGetters.size() > 0) { BeanDeclaration bean = null; Object value = null; for (Map.Entry<String, Method> outbean_getter : mOutbeanGetters.entrySet()) { try { bean = mContext.getElementInfo().getNamedOutbeanInfo(outbean_getter.getKey()); value = outbean_getter.getValue().invoke(mElement, (Object[])null); if (value != null) { if (null == entry_map) { entry_map = new LinkedHashMap<String, String[]>(); } Map<String, String[]> bean_values = mContext.collectOutputBeanValues(value, bean.getPrefix(), null); entry_map.putAll(bean_values); } } catch (Exception e) { throw new OutbeanOutjectionException(mContext.getElementInfo().getDeclarationName(), mElement.getClass(), outbean_getter.getKey(), e); } } } // handle output getter outjection if (mOutputGetters != null && mOutputGetters.size() > 0) { Object value = null; try { for (Map.Entry<String, Method> output_getter : mOutputGetters.entrySet()) { if (mNonGetterOutputs != null && mNonGetterOutputs.contains(output_getter.getKey())) { continue; } value = output_getter.getValue().invoke(mElement, (Object[])null); if (value != null) { if (null == entry_map) { entry_map = new LinkedHashMap<String, String[]>(); } entry_map.put(output_getter.getKey(), ArrayUtils.createStringArray(value, null)); } } } catch (Exception e) { throw new OutputOutjectionException(mContext.getElementInfo().getDeclarationName(), mElement.getClass(), e); } } if (mFallbackValues != null && mFallbackValues.size() > 0) { if (null == entry_map) { entry_map = new LinkedHashMap<String, String[]>(); } for (Map.Entry<String, String[]> fallback_output : mFallbackValues.entrySet()) { if (!entry_map.containsKey(fallback_output.getKey())) { entry_map.put(fallback_output.getKey(), fallback_output.getValue()); } } } // handle outputs that have been explicitly set if (null == entry_map) { return Collections.unmodifiableMap(mValues); } else { entry_map.putAll(mValues); } return Collections.unmodifiableMap(entry_map); } private class OutputValuesPropertyProcessor implements BeanPropertyProcessor { private ElementInfo mElementInfo; private Collection<String> mNamesOutputs; private Collection<String> mNamesGlobalvars; private Collection<String> mNamesOutbeans; private Collection<String> mNamesGlobalbeans; OutputValuesPropertyProcessor() { mElementInfo = mContext.getElementInfo(); mNamesOutputs = mElementInfo.getOutputNames(); mNamesGlobalvars = mElementInfo.getGlobalVarNames(); mNamesOutbeans = mElementInfo.getNamedOutbeanNames(); mNamesGlobalbeans = mElementInfo.getNamedGlobalBeanNames(); } public boolean gotProperty(String name, PropertyDescriptor descriptor) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { Method method = descriptor.getReadMethod(); if (mNamesOutputs.contains(name) || mNamesGlobalvars.contains(name)) { if (null == mOutputGetters) { mOutputGetters = new LinkedHashMap<String, Method>(); } method.setAccessible(true); mOutputGetters.put(name, method); } else if (mNamesOutbeans.contains(name) || mNamesGlobalbeans.contains(name)) { if (null == mOutbeanGetters) { mOutbeanGetters = new LinkedHashMap<String, Method>(); } BeanDeclaration bean = mElementInfo.getNamedOutbeanInfo(name); try { if (bean.getBeanClass().isAssignableFrom(method.getReturnType())) { method.setAccessible(true); mOutbeanGetters.put(name, method); } } catch (ClassNotFoundException e) { throw new OutbeanOutjectionException(mContext.getElementInfo().getDeclarationName(), mElement.getClass(), name, e); } } return true; } } }