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.util;
018:
019: import java.util.AbstractList;
020: import java.util.Map;
021:
022: import org.apache.cocoon.forms.formmodel.Repeater;
023: import org.apache.cocoon.forms.formmodel.Widget;
024:
025: /**
026: * A <code>List</code> view of a {@link Repeater}, each element of the list being a <code>Map</code>
027: * wrapping a repeater row, as defined by {@link ContainerWidgetAsMap}.
028: * <p>
029: * This implementation of list supports all methods, with the following restrictions:
030: * <ul>
031: * <li>values stored in the list must be <code>Map</code>s, that will be used with {@link ContainerWidgetAsMap#putAll(Map)}
032: * on the <code>Map</code> representation of the repeater rows,</li>
033: * <li>operations that involve testing equality with the list contents (e.g. <code>contains(Object)</code>) will
034: * not function properly, the <code>Map</code> wrapping the rows being created on demand.</li>
035: * </ul>
036: *
037: * @since 2.1.8
038: * @version $Id: RepeaterAsList.java 479296 2006-11-26 06:28:51Z antonio $
039: */
040: public class RepeaterAsList extends AbstractList {
041:
042: private Repeater repeater;
043: private boolean lowerCase;
044:
045: /**
046: * Create a <code>List<code> view around a repeater. The <code>keysToLowerCase</code> parameter
047: * specifies if <code>Map</code>s wrapping rows should convert input keys to lower case, as
048: * specified by {@link ContainerWidgetAsMap#ContainerWidgetAsMap(AbstractContainerWidget, boolean)}.
049: *
050: * @param repeater the repeater to wrap
051: * @param keysToLowerCase should we convert input keys to lower case?
052: */
053: public RepeaterAsList(Repeater repeater, boolean keysToLowerCase) {
054: this .repeater = repeater;
055: this .lowerCase = keysToLowerCase;
056: }
057:
058: /**
059: * Same as <code>RepeaterAsList(repeater, false)</code>.
060: */
061: public RepeaterAsList(Repeater repeater) {
062: this (repeater, false);
063: }
064:
065: /**
066: * Get the repeater widget that is wrapped by this <code>List</code>.
067: *
068: * @return the wrapped {@link Repeater}
069: */
070: public Repeater getWidget() {
071: return this .repeater;
072: }
073:
074: /**
075: * Get a widget relative to the repeater wrapped by this <code>List</code>
076: *
077: * @param path a widget lookup path
078: * @return the widget pointed to by <code>path</code> or <code>null</code> if it doesn't exist.
079: * @see Widget#lookupWidget(String)
080: */
081: public Widget getWidget(String path) {
082: return this .repeater.lookupWidget(path);
083: }
084:
085: public Object get(int index) {
086: return new ContainerWidgetAsMap(repeater.getRow(index),
087: lowerCase);
088: }
089:
090: public int size() {
091: return repeater.getSize();
092: }
093:
094: public Object set(int index, Object o) {
095: if (o == null) {
096: throw new NullPointerException(
097: "Cannot set null to a repeater");
098: }
099: if (!(o instanceof Map)) {
100: throw new IllegalArgumentException("Cannot set a '"
101: + o.getClass().toString() + "' to a repeater");
102: }
103: Map result = new ContainerWidgetAsMap(repeater.getRow(index));
104: result.putAll((Map) o);
105: return result;
106: }
107:
108: public void add(int index, Object o) {
109: if (o == null) {
110: throw new NullPointerException(
111: "Cannot add null to a repeater");
112: }
113: if (!(o instanceof Map)) {
114: throw new IllegalArgumentException("Cannot add a '"
115: + o.getClass().toString() + "' to a repeater");
116: }
117: Repeater.RepeaterRow row = repeater.addRow(index);
118: new ContainerWidgetAsMap(row).putAll((Map) o);
119: }
120:
121: public Object remove(int index) {
122: Map result = new ContainerWidgetAsMap(repeater.getRow(index));
123: repeater.removeRow(index);
124: return result;
125: }
126:
127: // Not mandated by the abstract class, but will speed up things
128: public void clear() {
129: repeater.clear();
130: }
131: }
|