blob: 9728f36b8d22d6dccdfb01e4e42cf06bf3c66cbc [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.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
// }
}