Repository: wicket Updated Branches: refs/heads/master a8c6daec3 -> c2e12216f
WICKET-5518 support unmodifiable collections as well as models without setter Project: http://git-wip-us.apache.org/repos/asf/wicket/repo Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/c2e12216 Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/c2e12216 Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/c2e12216 Branch: refs/heads/master Commit: c2e12216f38b4bd0517aff239f67e9925ac5a106 Parents: a8c6dae Author: svenmeier <[email protected]> Authored: Tue Feb 25 23:20:02 2014 +0100 Committer: svenmeier <[email protected]> Committed: Tue Feb 25 23:20:02 2014 +0100 ---------------------------------------------------------------------- .../wicket/markup/html/form/FormComponent.java | 43 ++-- .../html/form/CollectionFormComponentTest.java | 195 +++++++++++++++++++ 2 files changed, 226 insertions(+), 12 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/wicket/blob/c2e12216/wicket-core/src/main/java/org/apache/wicket/markup/html/form/FormComponent.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/main/java/org/apache/wicket/markup/html/form/FormComponent.java b/wicket-core/src/main/java/org/apache/wicket/markup/html/form/FormComponent.java index fdeb8c6..cb4ad05 100644 --- a/wicket-core/src/main/java/org/apache/wicket/markup/html/form/FormComponent.java +++ b/wicket-core/src/main/java/org/apache/wicket/markup/html/form/FormComponent.java @@ -1610,8 +1610,8 @@ public abstract class FormComponent<T> extends LabeledWebMarkupContainer impleme * @param formComponent * the form component to update * @see FormComponent#updateModel() - * @throws UnsupportedOperationException - * if the existing model object Collection cannot be modified + * @throws WicketRuntimeException + * if the existing model object collection is unmodifiable and no setter exists */ public static <S> void updateCollectionModel(FormComponent<Collection<S>> formComponent) { @@ -1625,23 +1625,42 @@ public abstract class FormComponent<T> extends LabeledWebMarkupContainer impleme } else { + Exception failure; + formComponent.modelChanging(); - collection.clear(); - if (convertedInput != null) - { - collection.addAll(convertedInput); - } - formComponent.modelChanged(); + + try { + collection.clear(); + if (convertedInput != null) + { + collection.addAll(convertedInput); + } + failure = null; + } catch (UnsupportedOperationException unmodifiable) { + logger.debug("An error occurred while trying to change the collection attached to " + formComponent, unmodifiable); + failure = unmodifiable; + collection = new ArrayList<>(convertedInput); + } + try { formComponent.getModel().setObject(collection); + failure = null; } - catch (Exception e) + catch (Exception noSetter) { - // ignore this exception because it could be that there - // is not setter for this collection. - logger.info("An error occurred while trying to set the new value for the property attached to " + formComponent, e); + logger.debug("An error occurred while trying to set the collection attached to " + formComponent, noSetter); + + if (failure != null) { + failure = noSetter; + } + } + + if (failure == null) { + formComponent.modelChanged(); + } else { + throw new WicketRuntimeException("Unable to update the collection attached to " + formComponent); } } } http://git-wip-us.apache.org/repos/asf/wicket/blob/c2e12216/wicket-core/src/test/java/org/apache/wicket/markup/html/form/CollectionFormComponentTest.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/test/java/org/apache/wicket/markup/html/form/CollectionFormComponentTest.java b/wicket-core/src/test/java/org/apache/wicket/markup/html/form/CollectionFormComponentTest.java new file mode 100644 index 0000000..81f4e80 --- /dev/null +++ b/wicket-core/src/test/java/org/apache/wicket/markup/html/form/CollectionFormComponentTest.java @@ -0,0 +1,195 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.wicket.markup.html.form; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.apache.wicket.WicketRuntimeException; +import org.apache.wicket.WicketTestCase; +import org.apache.wicket.model.PropertyModel; +import org.junit.Test; + +/** + * Testing updating model collections through + * {@link FormComponent#updateCollectionModel(FormComponent)}. + * + * @author svenmeier + */ +public class CollectionFormComponentTest extends WicketTestCase +{ + @Test + public void getSetNullCollection() + { + final AtomicBoolean setCalled = new AtomicBoolean(); + + Object object = new Object() + { + private Collection<String> internal = null; + + public Collection<String> getStrings() + { + return internal; + } + + public void setStrings(Collection<String> strings) + { + this.internal = strings; + + setCalled.set(true); + } + }; + + Choice choice = new Choice(object); + choice.setConvertedInput(Arrays.asList("A", "B")); + FormComponent.updateCollectionModel(choice); + + assertEquals(true, setCalled.get()); + assertEquals("[A, B]", choice.getDefaultModelObjectAsString()); + } + + @Test(expected = WicketRuntimeException.class) + public void getNullCollectionFails() + { + Object object = new Object() + { + private Collection<String> internal = null; + + public Collection<String> getStrings() + { + return internal; + } + }; + + Choice choice = new Choice(object); + choice.setConvertedInput(Arrays.asList("A", "B")); + FormComponent.updateCollectionModel(choice); + } + + @Test + public void getSetModifiableCollection() + { + final AtomicBoolean setCalled = new AtomicBoolean(); + + Object object = new Object() + { + private Collection<String> internal = new ArrayList<>(); + + public Collection<String> getStrings() + { + return internal; + } + + public void setStrings(Collection<String> strings) + { + this.internal = strings; + + setCalled.set(true); + } + }; + + Choice choice = new Choice(object); + choice.setConvertedInput(Arrays.asList("A", "B")); + FormComponent.updateCollectionModel(choice); + + assertEquals(true, setCalled.get()); + assertEquals("[A, B]", choice.getDefaultModelObjectAsString()); + } + + @Test + public void getModifiableCollection() + { + Object object = new Object() + { + private Collection<String> internal = new ArrayList<>(); + + public Collection<String> getStrings() + { + return internal; + } + }; + + Choice choice = new Choice(object); + choice.setConvertedInput(Arrays.asList("A", "B")); + FormComponent.updateCollectionModel(choice); + + assertEquals("[A, B]", choice.getDefaultModelObjectAsString()); + } + + /** + * WICKET-5518 + */ + @Test + public void getSetUnmodifiableCollection() + { + final AtomicBoolean setCalled = new AtomicBoolean(); + + Object object = new Object() + { + private Collection<String> internal = new ArrayList<>(); + + public Collection<String> getStrings() + { + return Collections.unmodifiableCollection(internal); + } + + public void setStrings(Collection<String> strings) + { + this.internal = strings; + + setCalled.set(true); + } + }; + + Choice choice = new Choice(object); + choice.setConvertedInput(Arrays.asList("A", "B")); + FormComponent.updateCollectionModel(choice); + + assertEquals(true, setCalled.get()); + assertEquals("[A, B]", choice.getDefaultModelObjectAsString()); + } + + @Test(expected = WicketRuntimeException.class) + public void getUnmodifiableFails() + { + Object object = new Object() + { + private Collection<String> internal = new ArrayList<>(); + + public Collection<String> getStrings() + { + return Collections.unmodifiableCollection(internal); + } + }; + + Choice choice = new Choice(object); + choice.setConvertedInput(Arrays.asList("A", "B")); + FormComponent.updateCollectionModel(choice); + } + + private class Choice extends FormComponent<Collection<String>> + { + + public Choice(Object object) + { + super("choice", new PropertyModel(object, "strings")); + } + } +}
