001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.cocoon.forms.formmodel;
018:
019: import java.math.BigDecimal;
020: import java.util.ArrayList;
021: import java.util.Collection;
022: import java.util.Iterator;
023: import java.util.List;
024:
025: import org.apache.cocoon.forms.util.WidgetFinder;
026: import org.outerj.expression.ExpressionContext;
027:
028: /**
029: * Implementation of the ExpressionContext required for the evaluation of
030: * expressions by xReporter expression interpreter.
031: *
032: * @version $Id: ExpressionContextImpl.java 449149 2006-09-23 03:58:05Z crossley $
033: */
034: public class ExpressionContextImpl implements ExpressionContext {
035: private Widget widget;
036: private boolean referenceChildren;
037:
038: public ExpressionContextImpl(Widget widget) {
039: this .widget = widget;
040: this .referenceChildren = false;
041: }
042:
043: /**
044: * @param referenceChildren if true, variables will be resolved among the children of the given
045: * container widget, rather than among the siblings of the widget.
046: */
047: public ExpressionContextImpl(Widget widget,
048: boolean referenceChildren) {
049: this .widget = widget;
050: this .referenceChildren = referenceChildren;
051: }
052:
053: /**
054: * Variables refer to other widgets.
055: *
056: * <p>You can access parent and root widgets (with ../widget and /widget paths
057: * respectively), but mind that in xreporter expressions these variables names
058: * must be placed in brakets to be correctly parsed. For example
059: * "{../widget} + otherWidget".
060: *
061: * <p>In case the value of a widget is null but the widget is required or calculated, then
062: * a special exception will be thrown, the {@link CannotYetResolveWarning}. This is
063: * because in that case, you'll probably want to re-evaluate the expression at a later time
064: * (since the widget is required, it will eventually get a value).
065: *
066: * <p>In case the value of the widget is null but the field is not required, then simply
067: * null is returned. (TODO: a function IsNull() will provided in the expression library
068: * so that expression writers can check for the likely condition where a non-required field
069: * is null).
070: *
071: * <p>If the variable name does not refer to an existing widget, null is returned (TODO: this
072: * behaviour will probably change in the future)
073: *
074: * <p>If the variable name contains the "/./" notation, it will return a Collection of values,
075: * using the {@link org.apache.cocoon.forms.util.WidgetFinder} utility.
076: */
077: public Object resolveVariable(String name) {
078: if (name.indexOf("/./") != -1) {
079: WidgetFinder finder = new WidgetFinder(widget, name, false);
080: Collection widgets = finder.getWidgets();
081: List result = new ArrayList();
082: for (Iterator iter = widgets.iterator(); iter.hasNext();) {
083: Widget widget = (Widget) iter.next();
084: if (widget.getValue() != null) {
085: result.add(widget.getValue());
086: } else if (widget.isRequired()
087: || widget instanceof CalculatedField) {
088: // the widget currently has not yet a value, but since it is required or calculated, it will get a value sooner
089: // or later. Therefore, we throw an exception here indicating that this expression can currenlty
090: // not yet be evaluated, but will be at a later time.
091: throw new CannotYetResolveWarning();
092: }
093: }
094: return result;
095: } else {
096: Widget widget;
097: if (!referenceChildren)
098: widget = ((ContainerWidget) this .widget.getParent())
099: .lookupWidget(name);
100: else
101: widget = ((ContainerWidget) this .widget)
102: .lookupWidget(name);
103: if (widget != null) {
104: Object value = widget.getValue();
105:
106: if (value == null
107: && (widget.isRequired() || widget instanceof CalculatedField)) {
108: // the widget currently has not yet a value, but since it is required or calculated, it will get a value sooner
109: // or later. Therefore, we throw an exception here indicating that this expression can currenlty
110: // not yet be evaluated, but will be at a later time.
111: throw new CannotYetResolveWarning();
112: }
113:
114: // do some type conversions:
115: // * the expression library only knows about BigDecimals as being numbers, so convert Longs first to BigDecimals
116: // * same for Integer
117: // * all other Number instances will get converted to String first.
118: if (value instanceof Long)
119: return new BigDecimal(((Long) value).longValue());
120: else if (value instanceof Integer)
121: return new BigDecimal(((Integer) value).intValue());
122: else if (value instanceof Number)
123: return new BigDecimal(value.toString());
124: else
125: return value;
126: }
127: return null;
128: }
129: }
130:
131: public Object get(String s) {
132: return null;
133: }
134:
135: }
|