001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: package com.sun.rave.web.ui.component.util.event;
042:
043: import com.sun.rave.web.ui.component.util.Util;
044: import com.sun.rave.web.ui.util.TypeConverter;
045:
046: import java.lang.reflect.InvocationTargetException;
047: import java.lang.reflect.Method;
048: import java.util.EventObject;
049: import java.util.HashMap;
050: import java.util.Map;
051:
052: import javax.faces.component.UIComponent;
053:
054: /**
055: * <P> This class contains the information necessary to invoke a Handler. The
056: * {@link HandlerDefinition} class provides a definition of how to invoke
057: * a Handler, this class uses that information with in conjuction with
058: * information provided in this class to execute the <strong>handler
059: * method</strong>. This class typically will hold input values and
060: * specify where output should be stored.</P>
061: *
062: * <P> The <strong>handler method</strong> to be invoked must have the
063: * following method signature:</P>
064: *
065: * <P> <BLOCKQUOTE>
066: * </CODE>
067: * public void beginDisplay(HandlerContext handlerCtx)
068: * </CODE>
069: * </BLOCKQUOTE></P>
070: *
071: * <P> <code>void</code> above can return a value. Depending on the type of
072: * event, return values may be handled differently.</P>
073: *
074: * @author Ken Paulsen (ken.paulsen@sun.com)
075: */
076: public class Handler implements java.io.Serializable {
077:
078: /**
079: * Constructor
080: */
081: public Handler(HandlerDefinition handlerDef) {
082: setHandlerDefinition(handlerDef);
083: }
084:
085: /**
086: *
087: */
088: public HandlerDefinition getHandlerDefinition() {
089: return _handlerDef;
090: }
091:
092: /**
093: * <P> This method sets the HandlerDefinition used by this Handler.</P>
094: */
095: protected void setHandlerDefinition(HandlerDefinition handler) {
096: _handlerDef = handler;
097: }
098:
099: /**
100: *
101: */
102: public void setInputValue(String name, Object value) {
103: _inputs.put(name, value);
104: }
105:
106: /**
107: * <P> This method returns a Map of NVPs representing the input to this
108: * handler.</P>
109: */
110: protected Map getInputMap() {
111: return _inputs;
112: }
113:
114: /**
115: * <P> This method simply returns the named input value, null if not
116: * found. It will not attempt to resolve $...{...} expressions or
117: * do modifications of any kind. If you are looking for a method to
118: * do these types of operations, try:</P>
119: *
120: * getInputValue(FacesContext, String).
121: *
122: * @param name The name used to identify the input value.
123: */
124: public Object getInputValue(String name) {
125: return _inputs.get(name);
126: }
127:
128: /**
129: * <P> This method returns the value for the named input. Input values
130: * are not stored in this HandlerContext itself, but in the Handler.
131: * If you are trying to set input values for a handler, you must
132: * create a new Handler object and set its input values.</P>
133: *
134: * <P> This method attempts to resolve $...{...} expressions. It also
135: * will return the default value if the value is null. If you don't
136: * want these things to happen, look at
137: * Handler.getInputValue(String).</P>
138: *
139: * @param name The input name
140: *
141: * @return The value of the input (null if not found)
142: */
143: public Object getInputValue(HandlerContext ctx, String name) {
144: // Make sure the requested name is valid
145: IODescriptor inDesc = getHandlerDefinition().getInputDef(name);
146: if (inDesc == null) {
147: throw new RuntimeException(
148: "Attempted to get input value '"
149: + name
150: + "', however, this is not a declared input parameter in "
151: + "handler definition '"
152: + getHandlerDefinition().getId()
153: + "'! Check your handler and/or the XML (near LayoutElement '"
154: + ctx.getLayoutElement().getId(
155: ctx.getFacesContext(), null) + "')");
156: }
157:
158: // Get the value, and parse it
159: Object value = getInputValue(name);
160: if (value == null) {
161: if (inDesc.isRequired()) {
162: throw new RuntimeException("'" + name
163: + "' is required for handler '"
164: + getHandlerDefinition().getId() + "'!");
165: }
166: value = inDesc.getDefault();
167: }
168:
169: // Resolve any expressions
170: EventObject event = ctx.getEventObject();
171: UIComponent component = null;
172: if (event instanceof UIComponentHolder) {
173: component = ((UIComponentHolder) event).getUIComponent();
174: }
175: if ((value != null) && (value instanceof String)) {
176: value = Util.resolveValue(ctx.getFacesContext(), ctx
177: .getLayoutElement(), component, "" + value);
178: }
179:
180: // Make sure the value is the correct type...
181: value = TypeConverter.asType(inDesc.getType(), value);
182:
183: return value;
184: }
185:
186: /**
187: * <P> This method retrieves an output value. Output values are stored
188: * in the location specified by the OutputType in the Handler.</P>
189: *
190: * @param context The HandlerContext
191: * @param name The output name
192: *
193: * @return The value of the output (null if not set)
194: */
195: public Object getOutputValue(HandlerContext context, String name) {
196: // Make sure the requested name is valid
197: HandlerDefinition handlerDef = getHandlerDefinition();
198: IODescriptor outIODesc = handlerDef.getOutputDef(name);
199: if (outIODesc == null) {
200: throw new RuntimeException(
201: "Attempted to get output value '"
202: + name
203: + "' from handler '"
204: + handlerDef.getId()
205: + "', however, this is not a declared output parameter! "
206: + "Check your handler and/or the XML.");
207: }
208:
209: // Get the OutputMapping that describes how to store this output
210: OutputMapping outputDesc = getOutput(name);
211:
212: // Return the value
213: return outputDesc.getOutputType().getValue(context, outIODesc,
214: outputDesc.getOutputKey());
215: }
216:
217: /**
218: * <P> This method stores an output value. Output values are stored
219: * as specified by the OutputType in the Handler.</P>
220: *
221: * @param context The HandlerContext
222: * @param name The name the Handler uses for the output
223: * @param value The value to set
224: */
225: public void setOutputValue(HandlerContext context, String name,
226: Object value) {
227: // Make sure the requested name is valid
228: HandlerDefinition handlerDef = getHandlerDefinition();
229: IODescriptor outIODesc = handlerDef.getOutputDef(name);
230: if (outIODesc == null) {
231: throw new RuntimeException(
232: "Attempted to set output value '"
233: + name
234: + "' from handler '"
235: + handlerDef.getId()
236: + "', however, this is not a declared output parameter! "
237: + "Check your handler and/or the XML.");
238: }
239:
240: // Get the OutputMapping that describes how to store this output
241: OutputMapping outputMapping = getOutput(name);
242: if (outputMapping == null) {
243: // They did not Map the output, do nothing...
244: return;
245: }
246:
247: // Make sure the value is the correct type...
248: value = TypeConverter.asType(outIODesc.getType(), value);
249:
250: // Set the value
251: EventObject event = context.getEventObject();
252: UIComponent component = null;
253: if (event instanceof UIComponentHolder) {
254: component = ((UIComponentHolder) event).getUIComponent();
255: }
256: outputMapping.getOutputType().setValue(
257: context,
258: outIODesc,
259: ""
260: + Util.resolveValue(context.getFacesContext(),
261: context.getLayoutElement(), component,
262: outputMapping.getOutputKey()), value);
263: }
264:
265: /**
266: * <P> This method adds a new OutputMapping to this handler. An
267: * OutputMapping allows the handler to return a value and have it
268: * "mapped" to the location of your choice. The "outputType"
269: * corresponds to a registered OutputType (see OutputTypeManager).</P>
270: *
271: * @param outputName The Handler's name for the output value
272: * @param targetKey The 'key' the OutputType uses to store the output
273: * @param targetType The OutputType implementation map the output
274: */
275: public void setOutputMapping(String outputName, String targetKey,
276: String targetType) {
277: // Ensure the data is trim
278: if (targetKey != null) {
279: targetKey = targetKey.trim();
280: if (targetKey.length() == 0) {
281: targetKey = null;
282: }
283: }
284: targetType = targetType.trim();
285:
286: try {
287: _outputs.put(outputName, new OutputMapping(outputName,
288: targetKey, targetType));
289: } catch (IllegalArgumentException ex) {
290: throw new RuntimeException(
291: "Unable to create OutputMapping with given information: "
292: + "outputName='" + outputName
293: + "', targetKey='" + targetKey
294: + "', targetType=" + targetType + "'", ex);
295: }
296: }
297:
298: /**
299: *
300: */
301: public OutputMapping getOutput(String name) {
302: return (OutputMapping) _outputs.get(name);
303: }
304:
305: /**
306: * <p> This method determines if the handler is static.</p>
307: */
308: public boolean isStatic() {
309: return getHandlerDefinition().isStatic();
310: }
311:
312: /**
313: *
314: */
315: public Object invoke(HandlerContext handlerContext)
316: throws InstantiationException, IllegalAccessException,
317: InvocationTargetException {
318: Object retVal = null;
319: HandlerDefinition handlerDef = getHandlerDefinition();
320: Method method = handlerDef.getHandlerMethod();
321:
322: // First execute all child handlers
323: // A copy is provided of the HandlerContext to avoid the Handler being
324: // changed before we execute this Handler.
325: Object result = handlerContext.getLayoutElement()
326: .dispatchHandlers(
327: new HandlerContextImpl(handlerContext),
328: handlerDef.getChildHandlers());
329:
330: // Only attempt to do this if there is a handler method, there
331: // might only be child handlers
332: if (method != null) {
333: Object instance = null;
334: if (!isStatic()) {
335: // Get the class that contains the method
336: instance = method.getDeclaringClass().newInstance();
337: }
338:
339: // Invoke the Method
340: retVal = method.invoke(instance,
341: new Object[] { handlerContext });
342: if (retVal != null) {
343: result = retVal;
344: }
345: }
346:
347: // Return the result (null if no result)
348: return result;
349: }
350:
351: private HandlerDefinition _handlerDef = null;
352: private Map _inputs = new HashMap();
353: private Map _outputs = new HashMap();
354: }
|