001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.cocoon.forms.formmodel;
018:
019: import org.apache.cocoon.environment.Request;
020: import org.apache.cocoon.forms.FormContext;
021: import org.apache.cocoon.forms.event.*;
022:
023: /**
024: * An Action widget. An Action widget can cause an {@link ActionEvent} to be triggered
025: * on the server side, which will be handled by either the event handlers defined in the
026: * form definition, and/or by the {@link org.apache.cocoon.forms.event.FormHandler FormHandler}
027: * registered with the form, if any. An Action widget can e.g. be rendered as a button,
028: * or as a hidden field which gets its value set by javascript. The Action widget will generate its associated
029: * ActionEvent when a requestparameter is present with as name the id of this Action widget, and as
030: * value a non-empty value.
031: *
032: * @version $Id: Action.java 449149 2006-09-23 03:58:05Z crossley $
033: */
034: public class Action extends AbstractWidget implements
035: ActionListenerEnabled {
036:
037: private final ActionDefinition definition;
038: /** Additional listeners to those defined as part of the widget definition (if any). */
039: private ActionListener listener;
040:
041: public Action(ActionDefinition definition) {
042: super (definition);
043: this .definition = definition;
044: }
045:
046: public WidgetDefinition getDefinition() {
047: return this .definition;
048: }
049:
050: public void readFromRequest(final FormContext formContext) {
051: if (!getCombinedState().isAcceptingInputs()) {
052: return;
053: }
054:
055: Form form = getForm();
056:
057: // Set the submit widget if we can determine it from the request
058: String fullId = getRequestParameterName();
059: Request request = formContext.getRequest();
060:
061: if (request.getParameter(fullId) != null
062: || fullId.equals(request
063: .getParameter(Form.SUBMIT_ID_PARAMETER))) {
064: form.setSubmitWidget(this );
065:
066: } else {
067: // Special workaround an IE bug for <input type="image" name="foo"> :
068: // in that case, IE only sends "foo.x" and "foo.y" and not "foo" whereas
069: // standards-compliant browsers such as Mozilla do send the "foo" parameter.
070: //
071: // Note that since actions are terminal widgets, there's no chance of conflict
072: // with a child "x" or "y" widget.
073: String value = request.getParameter(fullId + ".x");
074: if ((value != null) && value.length() > 0) {
075: form.setSubmitWidget(this );
076: }
077: }
078:
079: if (form.getSubmitWidget() == this ) {
080: handleActivate();
081: }
082: }
083:
084: /**
085: * Performs all actions and calls on-action listeners attached to this object. Note that this
086: * does not register this object as the submit widget and doesn't stop form processing.
087: */
088: public void performAction() {
089: getForm().addWidgetEvent(
090: new ActionEvent(this , definition.getActionCommand()));
091: }
092:
093: /**
094: * Handle the fact that this action was activated. The default here is to perform any
095: * action associated to this object, end the current form processing and redisplay the
096: * form.
097: *
098: * @see #performAction()
099: */
100: protected void handleActivate() {
101: performAction();
102: getForm().endProcessing(true);
103: }
104:
105: /**
106: * Always return <code>true</code> (an action has no validation)
107: *
108: * <br>TODO is there a use case for actions having validators?
109: */
110: public boolean validate() {
111: return true;
112: }
113:
114: /**
115: * @see org.apache.cocoon.forms.formmodel.Widget#isValid()
116: */
117: public boolean isValid() {
118: return true;
119: }
120:
121: private static final String ACTION_EL = "action";
122:
123: /**
124: * @return "action"
125: */
126: public String getXMLElementName() {
127: return ACTION_EL;
128: }
129:
130: /**
131: * Adds a ActionListener to this widget instance. Listeners defined
132: * on the widget instance will be executed in addtion to any listeners
133: * that might have been defined in the widget definition.
134: */
135: public void addActionListener(ActionListener listener) {
136: this .listener = WidgetEventMulticaster.add(this .listener,
137: listener);
138: }
139:
140: public void removeActionListener(ActionListener listener) {
141: this .listener = WidgetEventMulticaster.remove(this .listener,
142: listener);
143: }
144:
145: private void fireActionEvent(ActionEvent event) {
146: if (this .listener != null) {
147: this .listener.actionPerformed(event);
148: }
149: }
150:
151: public void broadcastEvent(WidgetEvent event) {
152: if (event instanceof ActionEvent) {
153: this .definition.fireActionEvent((ActionEvent) event);
154: fireActionEvent((ActionEvent) event);
155: } else {
156: // Other kinds of events
157: super.broadcastEvent(event);
158: }
159: }
160: }
|