blob: e05b0d51b4ddd912e9b1dd17a31e00de80405641 [file] [log] [blame]
/*
* 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.Collection;
import java.util.List;
import org.apache.wicket.WicketRuntimeException;
import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.util.CollectionModel;
import org.apache.wicket.util.convert.ConversionException;
import org.apache.wicket.util.lang.Generics;
import org.apache.wicket.util.string.Strings;
import org.apache.wicket.util.visit.IVisit;
import org.apache.wicket.util.visit.IVisitor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Component used to connect instances of Check components into a group. Instances of Check have to
* be in the component hierarchy somewhere below the group component. The model of the CheckGroup
* component has to be an instance of java.util.Collection. The model collection of the group is
* filled with model objects of all selected Check components.
*
* ie <code>
* <span wicket:id="checkboxgroup">
* ...
* <input type="checkbox" wicket:id="checkbox1">choice 1</input>
* ...
* <input type="checkbox" wicket:id="checkbox2">choice 2</input>
* ...
* </span>
* </code>
*
* @see org.apache.wicket.markup.html.form.Check
* @see org.apache.wicket.markup.html.form.CheckGroupSelector <p>
* Note: This component does not support cookie persistence
*
* @author Igor Vaynberg
*
* @param <T>
* The model object type
*/
public class CheckGroup<T> extends FormComponent<Collection<T>>
{
private static final long serialVersionUID = 1L;
private static final Logger log = LoggerFactory.getLogger(CheckGroup.class);
/**
* Constructor that will create a default model collection
*
* @param id
* component id
*/
public CheckGroup(String id)
{
super(id);
setRenderBodyOnly(true);
}
/**
* Constructor that wraps the provided collection with the org.apache.wicket.model.Model object
*
* @param id
* component id
* @param collection
* collection to be used as the model
*
*/
public CheckGroup(String id, Collection<T> collection)
{
this(id, new CollectionModel<T>(collection));
}
/**
* @param id
* @param model
* @see WebMarkupContainer#WebMarkupContainer(String, IModel)
*/
@SuppressWarnings("unchecked")
public CheckGroup(String id, IModel<? extends Collection<T>> model)
{
super(id, (IModel<Collection<T>>)model);
setRenderBodyOnly(true);
}
/**
* @see FormComponent#getModelValue()
*/
@Override
protected String getModelValue()
{
final StringBuilder builder = new StringBuilder();
final Collection<T> ts = getModelObject();
visitChildren(Check.class, new IVisitor<Check<T>, Void>()
{
@Override
public void component(Check<T> check, IVisit<Void> visit)
{
if (ts.contains(check.getModelObject()))
{
if (builder.length() > 0)
{
builder.append(VALUE_SEPARATOR);
}
builder.append(check.getValue());
}
}
});
return builder.toString();
}
@Override
protected Collection<T> convertValue(String[] values) throws ConversionException
{
List<T> collection = Generics.newArrayList();
/*
* if the input is null we do not need to do anything since the model collection has already
* been cleared
*/
if (values != null && values.length > 0)
{
for (final String value : values)
{
if (value != null)
{
Check<T> checkbox = visitChildren(Check.class,
new org.apache.wicket.util.visit.IVisitor<Check<T>, Check<T>>()
{
@Override
public void component(final Check<T> check, final IVisit<Check<T>> visit)
{
if (String.valueOf(check.getValue()).equals(value))
{
visit.stop(check);
}
}
});
if (checkbox == null)
{
throw new WicketRuntimeException(
"submitted http post value [" +
Strings.join(",", values) +
"] for CheckGroup component [" +
getPath() +
"] contains an illegal value [" +
value +
"] which does not point to a Check component. Due to this the CheckGroup component cannot resolve the selected Check component pointed to by the illegal value. A possible reason is that component hierarchy changed between rendering and form submission.");
}
// assign the value of the group's model
collection.add(checkbox.getModelObject());
}
}
}
return collection;
}
/**
* See {@link FormComponent#updateCollectionModel(FormComponent)} for details on how the model
* is updated.
*/
@Override
public void updateModel()
{
FormComponent.updateCollectionModel(this);
}
@Override
protected void onComponentTag(ComponentTag tag)
{
super.onComponentTag(tag);
// No longer applicable, breaks XHTML validation.
tag.remove("disabled");
tag.remove("name");
}
}