You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by sy...@apache.org on 2005/10/03 16:10:51 UTC
svn commit: r293356 - in
/cocoon/blocks/forms/trunk/java/org/apache/cocoon/forms:
formmodel/AbstractContainerWidget.java formmodel/WidgetList.java
util/ContainerWidgetAsMap.java util/RepeaterAsList.java
Author: sylvain
Date: Mon Oct 3 07:10:45 2005
New Revision: 293356
URL: http://svn.apache.org/viewcvs?rev=293356&view=rev
Log:
Add Map and List wrappers around widgets to ease binding with JDBI
Added:
cocoon/blocks/forms/trunk/java/org/apache/cocoon/forms/util/ContainerWidgetAsMap.java (with props)
cocoon/blocks/forms/trunk/java/org/apache/cocoon/forms/util/RepeaterAsList.java (with props)
Modified:
cocoon/blocks/forms/trunk/java/org/apache/cocoon/forms/formmodel/AbstractContainerWidget.java
cocoon/blocks/forms/trunk/java/org/apache/cocoon/forms/formmodel/WidgetList.java
Modified: cocoon/blocks/forms/trunk/java/org/apache/cocoon/forms/formmodel/AbstractContainerWidget.java
URL: http://svn.apache.org/viewcvs/cocoon/blocks/forms/trunk/java/org/apache/cocoon/forms/formmodel/AbstractContainerWidget.java?rev=293356&r1=293355&r2=293356&view=diff
==============================================================================
--- cocoon/blocks/forms/trunk/java/org/apache/cocoon/forms/formmodel/AbstractContainerWidget.java (original)
+++ cocoon/blocks/forms/trunk/java/org/apache/cocoon/forms/formmodel/AbstractContainerWidget.java Mon Oct 3 07:10:45 2005
@@ -79,7 +79,11 @@
public Iterator getChildren() {
return widgets.iterator();
}
-
+
+ public int getSize() {
+ return widgets.getWidgetList().size();
+ }
+
/**
* Delegates the readFromRequest() down to the contained child-widgets.
*
@@ -131,6 +135,5 @@
if (getCombinedState().isDisplayingValues()) {
widgets.generateSaxFragment(contentHandler, locale);
}
- }
-
+ }
}
Modified: cocoon/blocks/forms/trunk/java/org/apache/cocoon/forms/formmodel/WidgetList.java
URL: http://svn.apache.org/viewcvs/cocoon/blocks/forms/trunk/java/org/apache/cocoon/forms/formmodel/WidgetList.java?rev=293356&r1=293355&r2=293356&view=diff
==============================================================================
--- cocoon/blocks/forms/trunk/java/org/apache/cocoon/forms/formmodel/WidgetList.java (original)
+++ cocoon/blocks/forms/trunk/java/org/apache/cocoon/forms/formmodel/WidgetList.java Mon Oct 3 07:10:45 2005
@@ -16,6 +16,7 @@
package org.apache.cocoon.forms.formmodel;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@@ -59,6 +60,24 @@
public WidgetList() {
widgets = new ArrayList();
widgetsById = new HashMap();
+ }
+
+ /**
+ * Get the (unmodifiable) list of widgets
+ *
+ * @return the widget list
+ */
+ public List getWidgetList() {
+ return Collections.unmodifiableList(this.widgets);
+ }
+
+ /**
+ * Get the (unmodifiable) map of widgets
+ *
+ * @return the widget map
+ */
+ public Map getWidgetMap() {
+ return Collections.unmodifiableMap(this.widgetsById);
}
/**
Added: cocoon/blocks/forms/trunk/java/org/apache/cocoon/forms/util/ContainerWidgetAsMap.java
URL: http://svn.apache.org/viewcvs/cocoon/blocks/forms/trunk/java/org/apache/cocoon/forms/util/ContainerWidgetAsMap.java?rev=293356&view=auto
==============================================================================
--- cocoon/blocks/forms/trunk/java/org/apache/cocoon/forms/util/ContainerWidgetAsMap.java (added)
+++ cocoon/blocks/forms/trunk/java/org/apache/cocoon/forms/util/ContainerWidgetAsMap.java Mon Oct 3 07:10:45 2005
@@ -0,0 +1,172 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.forms.util;
+
+import java.util.AbstractMap;
+import java.util.AbstractSet;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.cocoon.forms.formmodel.AbstractContainerWidget;
+import org.apache.cocoon.forms.formmodel.Repeater;
+import org.apache.cocoon.forms.formmodel.Widget;
+import org.apache.commons.collections.iterators.AbstractIteratorDecorator;
+
+/**
+ * A <code>Map</code> view of a container widget, keys being children names and values either
+ * maps (for container children), objects (for terminal children) or lists (for repeaters).
+ * <p>
+ * The returned map is non-modifiable, except using the <code>put()</code> method, which much
+ * refer to an existing child widget, and <code>putAll(Map)</code> that will silently ignore keys
+ * that don't refer to existing child widgets.
+ *
+ * @since 2.1.8
+ * @version $Id$
+ */
+public class ContainerWidgetAsMap extends AbstractMap {
+ private AbstractContainerWidget container;
+ private boolean lowerCase;
+
+ /**
+ * Wraps a container widget in a <code>Map</code>.
+ * <p>
+ * The <code>keysToLowerCase</code> argument specifies if input keys given in <code>get()</code>,
+ * <code>put()</code> and <code>putAll()</code> should be converted to lower case before searching for
+ * the corresponding widget. This feature allows to directly feed widgets with <code>Map</code>s coming
+ * from JDBC resultset rows where keys are uppercase (see <a href="http://jdbi.codehaus.org">JDBI</a>).
+ *
+ * @param container the container to wrap
+ * @param keysToLowerCase should we convert keys to lower case?
+ */
+ public ContainerWidgetAsMap(AbstractContainerWidget container, boolean keysToLowerCase) {
+ this.container = container;
+ this.lowerCase = keysToLowerCase;
+ }
+
+ /**
+ * Same as <code>ContainerWidgetAsMap(container, true)</code>
+ */
+ public ContainerWidgetAsMap(AbstractContainerWidget container) {
+ this(container, true);
+ }
+
+ public Object put(Object key, Object value) {
+ String name = (String)key;
+ if (lowerCase) name = name.toLowerCase();
+
+ Widget w = container.getChild(name);
+ if (w != null) {
+ Object result = w.getValue();
+ setValue(w, value);
+ return result;
+ } else {
+ throw new UnsupportedOperationException(container + " has no child named '" + key + "'");
+ }
+ }
+
+ public void putAll(Map map) {
+ Iterator iter = map.entrySet().iterator();
+ while(iter.hasNext()) {
+ Map.Entry entry = (Map.Entry)iter.next();
+ String name = (String)entry.getKey();
+ if (lowerCase) name = name.toLowerCase();
+ Widget w = container.getChild(name);
+ if (w != null) {
+ setValue(w, entry.getValue());
+ }
+ }
+ }
+
+ public Object get(Object key) {
+ String name = (String)key;
+ if (lowerCase) name = name.toLowerCase();
+ Widget w = container.getChild(name);
+ return w == null ? null : asValueOrMap(w);
+ }
+
+ public Set entrySet() {
+ return new ContainerEntrySet();
+ }
+
+ private Object asValueOrMap(Widget w) {
+ if (w instanceof Repeater) {
+ return new RepeaterAsList((Repeater)w, lowerCase);
+ } else if (w instanceof AbstractContainerWidget) {
+ return new ContainerWidgetAsMap((AbstractContainerWidget)w, lowerCase);
+ } else {
+ return w.getValue();
+ }
+ }
+
+ private void setValue(Widget w, Object value) {
+ if (w instanceof Repeater) {
+ // Must be a collection
+ if (!(value instanceof Collection)) {
+ throw new IllegalArgumentException("A repeater cannot be filled with " + value);
+ }
+ new RepeaterAsList((Repeater)w, lowerCase).addAll((Collection)value);
+
+ } else if (w instanceof AbstractContainerWidget) {
+ // Must be a map
+ if (!(value instanceof Map)) {
+ throw new IllegalArgumentException("A container cannot be filled with " + value);
+ }
+ new ContainerWidgetAsMap((AbstractContainerWidget)w).putAll((Map)value);
+ } else {
+ w.setValue(value);
+ }
+ }
+
+ private class ContainerEntrySet extends AbstractSet {
+ public Iterator iterator() {
+ return new ContainerEntryIterator();
+ }
+
+ public int size() {
+ return container.getSize();
+ }
+ }
+
+ private class ContainerEntryIterator extends AbstractIteratorDecorator {
+ public ContainerEntryIterator() {
+ super(container.getChildren());
+ }
+
+ public Object next() {
+ return new ContainerEntry((Widget)super.next());
+ }
+ }
+
+ private class ContainerEntry implements Map.Entry {
+ Widget widget;
+ public ContainerEntry(Widget w) {
+ widget = w;
+ }
+ public Object getKey() {
+ return widget.getName();
+ }
+ public Object getValue() {
+ return asValueOrMap(widget);
+ }
+ public Object setValue(Object value) {
+ Object result = asValueOrMap(widget);
+ ContainerWidgetAsMap.this.setValue(widget, value);
+ return result;
+ }
+ }
+}
\ No newline at end of file
Propchange: cocoon/blocks/forms/trunk/java/org/apache/cocoon/forms/util/ContainerWidgetAsMap.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cocoon/blocks/forms/trunk/java/org/apache/cocoon/forms/util/ContainerWidgetAsMap.java
------------------------------------------------------------------------------
svn:keywords = Id
Added: cocoon/blocks/forms/trunk/java/org/apache/cocoon/forms/util/RepeaterAsList.java
URL: http://svn.apache.org/viewcvs/cocoon/blocks/forms/trunk/java/org/apache/cocoon/forms/util/RepeaterAsList.java?rev=293356&view=auto
==============================================================================
--- cocoon/blocks/forms/trunk/java/org/apache/cocoon/forms/util/RepeaterAsList.java (added)
+++ cocoon/blocks/forms/trunk/java/org/apache/cocoon/forms/util/RepeaterAsList.java Mon Oct 3 07:10:45 2005
@@ -0,0 +1,104 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.forms.util;
+
+import java.util.AbstractList;
+import java.util.Map;
+
+import org.apache.cocoon.forms.formmodel.Repeater;
+
+/**
+ * A <code>List</code> view of a {@link Repeater}, each element of the list being a <code>Map</code>
+ * wrapping a repeater row, as defined by {@link ContainerWidgetAsMap}.
+ * <p>
+ * This implementation of list supports all methods, with the following restrictions:
+ * <ul>
+ * <li>values stored in the list must be <code>Map</code>s, that will be used with {@link ContainerWidgetAsMap#putAll(Map)}
+ * on the <code>Map</code> representation of the repeater rows,</li>
+ * <li>operations that involve testing equality with the list contents (e.g. <code>contains(Object)</code>) will
+ * not function properly, the <code>Map</code> wrapping the rows being created on demand.</li>
+ * </ul>
+ *
+ * @since 2.1.8
+ * @version $Id$
+ */
+public class RepeaterAsList extends AbstractList {
+
+ private Repeater repeater;
+ private boolean lowerCase = true;
+
+ /**
+ * Create a <code>List<code> view around a repeater. The <code>keysToLowerCase</code> parameter
+ * specifies if <code>Map</code>s wrapping rows should convert input keys to lower case, as
+ * specified by {@link ContainerWidgetAsMap#ContainerWidgetAsMap(AbstractContainerWidget, boolean)}.
+ *
+ * @param repeater the repeater to wrap
+ * @param keysToLowerCase should we convert input keys to lower case?
+ */
+ public RepeaterAsList(Repeater repeater, boolean keysToLowerCase) {
+ this.repeater = repeater;
+ this.lowerCase = keysToLowerCase;
+ }
+
+ /**
+ * Same as <code>RepeaterAsList(repeater, true)</code>.
+ */
+ public RepeaterAsList(Repeater repeater) {
+ this(repeater, true);
+ }
+
+ public Object get(int index) {
+ return new ContainerWidgetAsMap(repeater.getRow(index), lowerCase);
+ }
+
+ public int size() {
+ return repeater.getSize();
+ }
+
+ public Object set(int index, Object o) {
+ if (o == null) {
+ throw new NullPointerException("Cannot set null to a repeater");
+ }
+ if (!(o instanceof Map)) {
+ throw new IllegalArgumentException("Cannot set a '" + o.getClass().toString() + "' to a repeater");
+ }
+ Map result = new ContainerWidgetAsMap(repeater.getRow(index));
+ result.putAll((Map)o);
+ return result;
+ }
+
+ public void add(int index, Object o) {
+ if (o == null) {
+ throw new NullPointerException("Cannot add null to a repeater");
+ }
+ if (!(o instanceof Map)) {
+ throw new IllegalArgumentException("Cannot add a '" + o.getClass().toString() + "' to a repeater");
+ }
+ Repeater.RepeaterRow row = repeater.addRow(index);
+ new ContainerWidgetAsMap(row).putAll((Map)o);
+ }
+
+ public Object remove(int index) {
+ Map result = new ContainerWidgetAsMap(repeater.getRow(index));
+ repeater.removeRow(index);
+ return result;
+ }
+
+ // Not mandated by the abstract class, but will speed up things
+ public void clear() {
+ repeater.clear();
+ }
+}
\ No newline at end of file
Propchange: cocoon/blocks/forms/trunk/java/org/apache/cocoon/forms/util/RepeaterAsList.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cocoon/blocks/forms/trunk/java/org/apache/cocoon/forms/util/RepeaterAsList.java
------------------------------------------------------------------------------
svn:keywords = Id