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.avalon.framework.CascadingRuntimeException;
020: import org.apache.cocoon.forms.FormsException;
021: import org.apache.cocoon.forms.binding.BindingException;
022: import org.apache.cocoon.forms.event.ActionEvent;
023: import org.apache.cocoon.forms.event.ActionListener;
024:
025: /**
026: * Abstract repeater action. Subclasses will typically just self-add an
027: * event handler that will act on the repeater.
028: *
029: * @see RepeaterActionDefinitionBuilder
030: * @version $Id: RepeaterActionDefinition.java 517733 2007-03-13 15:37:22Z vgritsenko $
031: */
032: public abstract class RepeaterActionDefinition extends ActionDefinition {
033:
034: private String name = null;
035:
036: /**
037: * Builds an action whose target repeater is the parent of this widget
038: */
039: public RepeaterActionDefinition() {
040: }
041:
042: /**
043: * Builds an action whose target is a sibling of this widget
044: * @param repeaterName the name of the repeater
045: */
046: public RepeaterActionDefinition(String repeaterName) {
047: this .name = repeaterName;
048: }
049:
050: /**
051: * initialize this definition with the other, sort of like a copy constructor
052: */
053: public void initializeFrom(WidgetDefinition definition)
054: throws Exception {
055: super .initializeFrom(definition);
056:
057: if (!(definition instanceof RepeaterActionDefinition)) {
058: throw new FormsException("Ancestor definition "
059: + definition.getClass().getName()
060: + " is not a RepeaterActionDefinition.",
061: getLocation());
062: }
063:
064: RepeaterActionDefinition other = (RepeaterActionDefinition) definition;
065:
066: this .name = other.name;
067: }
068:
069: public Widget createInstance() {
070: return new RepeaterAction(this );
071: }
072:
073: /**
074: * Get the name of the repeater on which to act. If <code>null</code>, the repeater
075: * is the parent of the current widget (i.e. actions are in repeater rows). Otherwise,
076: * the repeater is a sibling of the current widget.
077: *
078: * @return the repeater name (can be <code>null</code>).
079: */
080: public String getRepeaterName() {
081: return this .name;
082: }
083:
084: //---------------------------------------------------------------------------------------------
085:
086: /**
087: * The definition of a repeater action that deletes the selected rows of a sibling repeater.
088: * <p>
089: * The action listeners attached to this action, if any, are called <em>before</em> the rows
090: * are actually removed
091: */
092: public static class DeleteRowsActionDefinition extends
093: RepeaterActionDefinition {
094:
095: private String selectName;
096:
097: public DeleteRowsActionDefinition(String repeaterName,
098: String selectName) {
099: super (repeaterName);
100: this .selectName = selectName;
101: }
102:
103: /**
104: * initialize this definition with the other, sort of like a copy constructor
105: */
106: public void initializeFrom(WidgetDefinition definition)
107: throws Exception {
108: super .initializeFrom(definition);
109:
110: if (!(definition instanceof DeleteRowsActionDefinition)) {
111: throw new FormsException("Ancestor definition "
112: + definition.getClass().getName()
113: + " is not a DeleteRowsActionDefinition.",
114: getLocation());
115: }
116:
117: DeleteRowsActionDefinition other = (DeleteRowsActionDefinition) definition;
118:
119: this .selectName = other.selectName;
120: }
121:
122: public boolean hasActionListeners() {
123: // we always want to be notified
124: return true;
125: }
126:
127: public void fireActionEvent(ActionEvent event) {
128: // Call action listeners, if any
129: super .fireActionEvent(event);
130:
131: Repeater repeater = ((RepeaterAction) event.getSource())
132: .getRepeater();
133:
134: // and actually delete the rows
135: for (int i = repeater.getSize() - 1; i >= 0; i--) {
136: Repeater.RepeaterRow row = repeater.getRow(i);
137: if (Boolean.TRUE.equals(row.getChild(this .selectName)
138: .getValue())) {
139: repeater.removeRow(i);
140: }
141: }
142:
143: if (repeater instanceof EnhancedRepeater) {
144: try {
145: ((EnhancedRepeater) repeater).refreshPage();
146: } catch (BindingException e) {
147: throw new CascadingRuntimeException(
148: "Error refreshing repeater page", e);
149: }
150: }
151:
152: }
153: }
154:
155: //---------------------------------------------------------------------------------------------
156:
157: /**
158: * The definition of a repeater action that adds a row to a sibling repeater.
159: */
160: public static class AddRowActionDefinition extends
161: RepeaterActionDefinition {
162: private int insertRows;
163:
164: public AddRowActionDefinition(String repeaterName,
165: int insertRows) {
166: super (repeaterName);
167: this .insertRows = insertRows;
168:
169: addActionListener(new ActionListener() {
170: public void actionPerformed(ActionEvent event) {
171: Repeater repeater = ((RepeaterAction) event
172: .getSource()).getRepeater();
173: if (repeater instanceof EnhancedRepeater) {
174: try {
175: ((EnhancedRepeater) repeater)
176: .goToPage(((EnhancedRepeater) repeater)
177: .getMaxPage());
178: } catch (BindingException e) {
179: throw new CascadingRuntimeException(
180: "Error switching page", e);
181: }
182: }
183: for (int i = 0; i < AddRowActionDefinition.this .insertRows; i++) {
184: repeater.addRow();
185: }
186: }
187: });
188: }
189:
190: }
191:
192: //---------------------------------------------------------------------------------------------
193:
194: /**
195: * The definition of a repeater action that insert rows before the selected rows in a sibling repeater,
196: * or at the end of the repeater if no row is selected.
197: */
198: public static class InsertRowsActionDefinition extends
199: RepeaterActionDefinition {
200:
201: protected String selectName;
202:
203: /**
204: * initialize this definition with the other, sort of like a copy constructor
205: */
206: public void initializeFrom(WidgetDefinition definition)
207: throws Exception {
208: super .initializeFrom(definition);
209:
210: if (!(definition instanceof InsertRowsActionDefinition)) {
211: throw new FormsException("Ancestor definition "
212: + definition.getClass().getName()
213: + " is not an InsertRowsActionDefinition.",
214: getLocation());
215: }
216:
217: InsertRowsActionDefinition other = (InsertRowsActionDefinition) definition;
218:
219: this .selectName = other.selectName;
220: }
221:
222: public InsertRowsActionDefinition(String repeaterName,
223: String selectWidgetName) {
224: super (repeaterName);
225: this .selectName = selectWidgetName;
226:
227: this .addActionListener(new ActionListener() {
228: public void actionPerformed(ActionEvent event) {
229: Repeater repeater = ((RepeaterAction) event
230: .getSource()).getRepeater();
231: boolean foundSelection = false;
232: for (int i = repeater.getSize() - 1; i >= 0; i--) {
233: Repeater.RepeaterRow row = repeater.getRow(i);
234: Widget selectWidget = row.getChild(selectName);
235: if (Boolean.TRUE
236: .equals(selectWidget.getValue())) {
237: // Add a row
238: repeater.addRow(i);
239: foundSelection = true;
240: }
241: }
242:
243: if (!foundSelection) {
244: // Add a row at the end
245: repeater.addRow();
246: }
247: }
248: });
249: }
250: }
251:
252: public static class SortActionDefinition extends
253: RepeaterActionDefinition {
254: protected String field = null;
255:
256: public SortActionDefinition(String repeaterName, String field) {
257: super (repeaterName);
258: this .field = field;
259:
260: this .addActionListener(new ActionListener() {
261: public void actionPerformed(ActionEvent event) {
262: Repeater repeater = ((RepeaterAction) event
263: .getSource()).getRepeater();
264: if (repeater instanceof EnhancedRepeater) {
265: EnhancedRepeater erep = (EnhancedRepeater) repeater;
266: try {
267: if (repeater.validate()) {
268: erep
269: .sortBy(SortActionDefinition.this .field);
270: }
271: } catch (Exception e) {
272: throw new CascadingRuntimeException(
273: "Error switching page", e);
274: }
275: }
276: }
277: });
278:
279: }
280: }
281:
282: public static class ChangePageActionDefinition extends
283: RepeaterActionDefinition {
284:
285: protected int method;
286:
287: public static final int FIRST = 0;
288: public static final int PREV = 1;
289: public static final int NEXT = 2;
290: public static final int LAST = 3;
291: public static final int CUSTOM = 4;
292:
293: /**
294: * initialize this definition with the other, sort of like a copy constructor
295: */
296: public void initializeFrom(WidgetDefinition definition)
297: throws Exception {
298: super .initializeFrom(definition);
299: if (definition instanceof ChangePageActionDefinition) {
300: ChangePageActionDefinition other = (ChangePageActionDefinition) definition;
301: this .method = other.method;
302: } else {
303: throw new Exception(
304: "Definition to inherit from is not of the right type! (at "
305: + getLocation() + ")");
306: }
307: }
308:
309: public ChangePageActionDefinition(String repeaterName, int m) {
310: super (repeaterName);
311:
312: this .method = m;
313:
314: this .addActionListener(new ActionListener() {
315: public void actionPerformed(ActionEvent event) {
316: Repeater repeater = ((RepeaterAction) event
317: .getSource()).getRepeater();
318: if (repeater instanceof EnhancedRepeater) {
319: EnhancedRepeater erep = (EnhancedRepeater) repeater;
320: int page = erep.getCurrentPage();
321: if (method == FIRST) {
322: page = 0;
323: } else if (method == PREV && page > 0) {
324: page = erep.getCurrentPage() - 1;
325: } else if (method == NEXT
326: && page < erep.getMaxPage()) {
327: page = erep.getCurrentPage() + 1;
328: } else if (method == LAST) {
329: page = erep.getMaxPage();
330: } else if (method == CUSTOM) {
331: page = erep.getCustomPageWidgetValue();
332: } else {
333: return;
334: }
335: try {
336: if (repeater.validate()) {
337: erep.goToPage(page);
338: }
339: } catch (Exception e) {
340: throw new CascadingRuntimeException(
341: "Error switching page", e);
342: }
343: }
344: }
345: });
346: }
347: }
348:
349: }
|