| /* |
| * 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.cocoon.forms.formmodel; |
| |
| import org.apache.cocoon.forms.FormContext; |
| import org.apache.cocoon.forms.FormsRuntimeException; |
| import org.apache.cocoon.forms.event.ValueChangedEvent; |
| import org.apache.cocoon.forms.event.ValueChangedListener; |
| import org.apache.cocoon.forms.event.ValueChangedListenerEnabled; |
| |
| import org.apache.commons.lang.ObjectUtils; |
| |
| /** |
| * A discriminated union that references a discriminant value in another |
| * widget and contains one of several cases (widgets). To have a case |
| * hold more than one widget or to use a different id for the case than |
| * for the widget id, just wrap the widget(s) in a container widget named |
| * with the desired case id. |
| * |
| * @version $Id$ |
| */ |
| public class Union extends AbstractContainerWidget { |
| |
| //Note: union instances behave like simple "field" instance with respect to |
| // XSLT post-processing, the choice of element-name reflects this. |
| private static final String UNION_EL = "field"; |
| |
| private Widget caseWidget; |
| protected String caseValue; |
| |
| private final UnionDefinition definition; |
| |
| |
| public Union(UnionDefinition definition) { |
| super(definition); |
| this.definition = definition; |
| // TODO: Remove after moving logic to Field. |
| //item.enteredValue = (String)definition.getDefaultValue(); |
| } |
| |
| public WidgetDefinition getDefinition() { |
| return definition; |
| } |
| |
| /** |
| * Called after widget's environment has been setup, |
| * to allow for any contextual initalization such as |
| * looking up case widgets for union widgets. |
| */ |
| public void initialize() { |
| String caseWidgetId = definition.getCaseWidgetId(); |
| this.caseWidget = getParent().lookupWidget(caseWidgetId); |
| if (this.caseWidget == null) { |
| throw new FormsRuntimeException("Could not find case widget '" + caseWidgetId + "' for union '" + getId() + "'.", |
| getLocation()); |
| } |
| |
| ((ValueChangedListenerEnabled) caseWidget).addValueChangedListener( |
| new ValueChangedListener() { |
| public void valueChanged(ValueChangedEvent event) { |
| String newValue = (String)event.getNewValue(); |
| if (!ObjectUtils.equals(Union.this.caseValue, newValue)) { |
| Union.this.caseValue = newValue; |
| getForm().addWidgetUpdate(Union.this); |
| } |
| } |
| } |
| ); |
| } |
| |
| /** |
| * @return "field" |
| */ |
| public String getXMLElementName() { |
| return UNION_EL; |
| } |
| |
| public Object getValue() { |
| return this.caseWidget.getValue(); |
| } |
| |
| public void readFromRequest(FormContext formContext) { |
| // Ensure the case widget has read its value |
| this.caseWidget.readFromRequest(formContext); |
| |
| Widget widget; |
| // Read current case from request |
| String newValue = (String)getValue(); |
| if (newValue != null && !newValue.equals("")) { |
| // We need to know if the case widget is the submit widget, |
| // and since the submit widget is only determined after the readFromRequest, |
| // we need to do it here prematurely (as happens in Action & Upload) |
| String fullId = caseWidget.getRequestParameterName(); |
| if (fullId.equals(formContext.getRequest().getParameter(Form.SUBMIT_ID_PARAMETER))) { |
| getForm().setSubmitWidget(this.caseWidget); |
| } |
| |
| if (getForm().getSubmitWidget() == this.caseWidget && !newValue.equals(this.caseValue)) { |
| // If submitted by the case widget and its value has changed, read the values |
| // for the previous case value. This allows to keep any already entered values |
| // despite the case change. |
| widget = getChild(this.caseValue); |
| } else { |
| // Get the corresponding widget (will create it if needed) |
| widget = getChild(newValue); |
| } |
| |
| if (widget != null && getCombinedState().isAcceptingInputs()) { |
| widget.readFromRequest(formContext); |
| } |
| } |
| |
| if (!ObjectUtils.equals(this.caseValue, newValue)) { |
| this.caseValue = newValue; |
| getForm().addWidgetUpdate(this); |
| } |
| } |
| |
| // TODO: Simplify this logic. |
| public boolean validate() { |
| if (!getCombinedState().isValidatingValues()) { |
| this.wasValid = true; |
| return true; |
| } |
| |
| Widget widget; |
| boolean valid = true; |
| // Read current case from request |
| String value = (String)getValue(); |
| if (value != null && !value.equals("")) { |
| if ((widget = getChild(value)) != null) { |
| valid = valid & widget.validate(); |
| } |
| } |
| this.wasValid = valid; |
| return valid; |
| } |
| |
| public Widget getChild(String id) { |
| if (!widgets.hasWidget(id) && definition.hasWidget(id)) { |
| definition.createWidget(this, id); |
| Widget child = super.getChild(id); |
| child.initialize(); |
| return child; |
| } |
| return super.getChild(id); |
| } |
| |
| //TODO: check further: cause the claim in the accompanied comment doesn't seem |
| // to be completely correct |
| |
| // This method is overridden to suppress output of sub-widget sax fragments. |
| // public void generateItemsSaxFragment(ContentHandler contentHandler, Locale locale) throws SAXException { |
| // // Do nothing |
| // } |
| |
| } |