/*
 * $Id: CheckGroup.java 5861 2006-05-25 20:55:07 +0000 (Thu, 25 May 2006)
 * eelco12 $ $Revision$ $Date: 2006-05-25 20:55:07 +0000 (Thu, 25 May
 * 2006) $
 * 
 * ==============================================================================
 * 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 wicket.markup.html.form;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import wicket.MarkupContainer;
import wicket.WicketRuntimeException;
import wicket.markup.html.WebMarkupContainer;
import wicket.model.IModel;
import wicket.model.Model;
import wicket.util.convert.ConversionException;

/**
 * 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="radio" wicket:id="checkbox1">choice 1</input>
 *   ...
 *   <input type="radio" wicket:id="checkbox2">choice 2</input>
 *   ...
 * </span>
 * </code>
 * 
 * @see wicket.markup.html.form.Check
 * @see wicket.markup.html.form.CheckGroupSelector
 * 
 * <p>
 * Note: This component does not support cookie persistence
 * @param <T>
 *            The type
 * 
 * @author Igor Vaynberg (ivaynberg@users.sf.net)
 * 
 */
public class CheckGroup<T> extends FormComponent<Collection<T>> implements IOnChangeListener
{
	private static final long serialVersionUID = 1L;

	/**
	 * Constructor that will create a default model collection
	 * 
	 * @param parent
	 *            The parent of this component
	 * 
	 * @param id
	 *            component id
	 */
	public CheckGroup(MarkupContainer parent, String id)
	{
		super(parent, id);
		setRenderBodyOnly(true);
	}

	/**
	 * Constructor that wraps the provided collection with the
	 * wicket.model.Model object
	 * 
	 * @param parent
	 *            The parent of this component
	 * 
	 * @param id
	 *            component id
	 * @param collection
	 *            collection to be used as the model
	 * 
	 */
	public CheckGroup(MarkupContainer parent, String id, Collection<T> collection)
	{
		this(parent, id, new Model<Collection<T>>(collection));
	}

	/**
	 * @see WebMarkupContainer#WebMarkupContainer(MarkupContainer,String,
	 *      IModel)
	 */
	public CheckGroup(MarkupContainer parent, String id, IModel<Collection<T>> model)
	{
		super(parent, id, model);
		setRenderBodyOnly(true);
	}

	/**
	 * @see wicket.markup.html.form.FormComponent#convertValue(String[])
	 */
	@SuppressWarnings("unchecked")
	@Override
	protected Collection<T> convertValue(String[] paths) throws ConversionException
	{
		List<T> collection = new ArrayList<T>();

		/*
		 * if the input is null we do not need to do anything since the model
		 * collection has already been cleared
		 */

		if (paths != null && paths.length > 0)
		{
			for (String element : paths)
			{
				String path = element;

				if (path != null)
				{
					
					// retrieve the selected checkbox component
					Check<T> checkbox = (Check<T>)get(path);

					if (checkbox == null)
					{
						throw new WicketRuntimeException(
								"submitted http post value ["
										+ paths.toString()
										+ "] for CheckGroup component ["
										+ getPath()
										+ "] contains an illegal relative path "
										+ "element ["
										+ path
										+ "] 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 componment hierarchy changed between rendering and form submission.");
					}

					// assign the value of the group's model
					collection.add(checkbox.getModelObject());
				}
			}
		}
		return collection;
	}

	/**
	 * @see FormComponent#updateModel()
	 */
	@Override
	public void updateModel()
	{
		Collection<T> collection = getModelObject();
		if (collection == null)
		{
			collection = getConvertedInput();
			setModelObject(collection);
		}
		else
		{
			modelChanging();
			collection.clear();
			collection.addAll(getConvertedInput());
			modelChanged();
		}
	}

	/**
	 * Check group does not support persistence through cookies
	 * 
	 * @see wicket.markup.html.form.FormComponent#supportsPersistence()
	 */
	@Override
	protected final boolean supportsPersistence()
	{
		return false;
	}

	/**
	 * Called when a selection changes.
	 */
	public final void onSelectionChanged()
	{
		convert();
		updateModel();
		onSelectionChanged(getModelObject());
	}

	/**
	 * Template method that can be overriden by clients that implement
	 * IOnChangeListener to be notified by onChange events of a select element.
	 * This method does nothing by default.
	 * <p>
	 * Called when a {@link Check} is clicked in a {@link CheckGroup} that wants
	 * to be notified of this event. This method is to be implemented by clients
	 * that want to be notified of selection events.
	 * 
	 * @param newSelection
	 *            The new selection of the {@link CheckGroup}. NOTE this is the
	 *            same as you would get by calling getModelObject() if the new
	 *            selection were current
	 */
	protected void onSelectionChanged(final Collection newSelection)
	{
	}

	/**
	 * This method should be overridden to return true if it is desirable to
	 * have on-selection-changed notifiaction.
	 * 
	 * @return true if component should receive on-selection-changed
	 *         notifications, false otherwise
	 */
	protected boolean wantOnSelectionChangedNotifications()
	{
		return false;
	}

	/**
	 * @see wicket.MarkupContainer#getStatelessHint()
	 */
	@Override
	protected boolean getStatelessHint()
	{
		if (wantOnSelectionChangedNotifications())
		{
			return false;
		}
		return super.getStatelessHint();
	}

}

@@ -3625,21 +3625,16 @@
 )%0A%09%09%09%09%7B%0A
-%09%09%09%09%09
 %0A%09%09%09%09%09//
@@ -4784,16 +4784,82 @@
 nged();%0A
+%09%09%09// call model.setObject()%0A%09%09%09getModel().setObject(collection);%0A
 %09%09%7D%0A%09%7D%0A%0A

fix where setobject() was not called on the model