001: //--------------------------------------------------------------------------
002: // Copyright (c) 1998-2004, Drew Davidson and Luke Blanshard
003: // All rights reserved.
004: //
005: // Redistribution and use in source and binary forms, with or without
006: // modification, are permitted provided that the following conditions are
007: // met:
008: //
009: // Redistributions of source code must retain the above copyright notice,
010: // this list of conditions and the following disclaimer.
011: // Redistributions in binary form must reproduce the above copyright
012: // notice, this list of conditions and the following disclaimer in the
013: // documentation and/or other materials provided with the distribution.
014: // Neither the name of the Drew Davidson nor the names of its contributors
015: // may be used to endorse or promote products derived from this software
016: // without specific prior written permission.
017: //
018: // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
019: // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
020: // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
021: // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
022: // COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
023: // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
024: // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
025: // OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
026: // AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
027: // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
028: // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
029: // DAMAGE.
030: //--------------------------------------------------------------------------
031: package ognl;
032:
033: import java.lang.reflect.Array;
034:
035: /**
036: * @author Luke Blanshard (blanshlu@netscape.net)
037: * @author Drew Davidson (drew@ognl.org)
038: */
039: class ASTChain extends SimpleNode {
040: public ASTChain(int id) {
041: super (id);
042: }
043:
044: public ASTChain(OgnlParser p, int id) {
045: super (p, id);
046: }
047:
048: public void jjtClose() {
049: flattenTree();
050: }
051:
052: protected Object getValueBody(OgnlContext context, Object source)
053: throws OgnlException {
054: Object result = source;
055:
056: for (int i = 0, ilast = children.length - 1; i <= ilast; ++i) {
057: boolean handled = false;
058:
059: if (i < ilast) {
060: if (children[i] instanceof ASTProperty) {
061: ASTProperty propertyNode = (ASTProperty) children[i];
062: int indexType = propertyNode
063: .getIndexedPropertyType(context, result);
064:
065: if ((indexType != OgnlRuntime.INDEXED_PROPERTY_NONE)
066: && (children[i + 1] instanceof ASTProperty)) {
067: ASTProperty indexNode = (ASTProperty) children[i + 1];
068:
069: if (indexNode.isIndexedAccess()) {
070: Object index = indexNode.getProperty(
071: context, result);
072:
073: if (index instanceof DynamicSubscript) {
074: if (indexType == OgnlRuntime.INDEXED_PROPERTY_INT) {
075: Object array = propertyNode
076: .getValue(context, result);
077: int len = Array.getLength(array);
078:
079: switch (((DynamicSubscript) index)
080: .getFlag()) {
081: case DynamicSubscript.ALL:
082: result = Array
083: .newInstance(
084: array
085: .getClass()
086: .getComponentType(),
087: len);
088: System.arraycopy(array, 0,
089: result, 0, len);
090: handled = true;
091: i++;
092: break;
093: case DynamicSubscript.FIRST:
094: index = new Integer(
095: (len > 0) ? 0 : -1);
096: break;
097: case DynamicSubscript.MID:
098: index = new Integer(
099: (len > 0) ? (len / 2)
100: : -1);
101: break;
102: case DynamicSubscript.LAST:
103: index = new Integer(
104: (len > 0) ? (len - 1)
105: : -1);
106: break;
107: }
108: } else {
109: if (indexType == OgnlRuntime.INDEXED_PROPERTY_OBJECT) {
110: throw new OgnlException(
111: "DynamicSubscript '"
112: + indexNode
113: + "' not allowed for object indexed property '"
114: + propertyNode
115: + "'");
116: }
117: }
118: }
119: if (!handled) {
120: result = OgnlRuntime
121: .getIndexedProperty(
122: context,
123: result,
124: propertyNode
125: .getProperty(
126: context,
127: result)
128: .toString(),
129: index);
130: handled = true;
131: i++;
132: }
133: }
134: }
135: }
136: }
137: if (!handled) {
138: result = children[i].getValue(context, result);
139: }
140: }
141: return result;
142: }
143:
144: protected void setValueBody(OgnlContext context, Object target,
145: Object value) throws OgnlException {
146: boolean handled = false;
147:
148: for (int i = 0, ilast = children.length - 2; i <= ilast; ++i) {
149: if (i == ilast) {
150: if (children[i] instanceof ASTProperty) {
151: ASTProperty propertyNode = (ASTProperty) children[i];
152: int indexType = propertyNode
153: .getIndexedPropertyType(context, target);
154:
155: if ((indexType != OgnlRuntime.INDEXED_PROPERTY_NONE)
156: && (children[i + 1] instanceof ASTProperty)) {
157: ASTProperty indexNode = (ASTProperty) children[i + 1];
158:
159: if (indexNode.isIndexedAccess()) {
160: Object index = indexNode.getProperty(
161: context, target);
162:
163: if (index instanceof DynamicSubscript) {
164: if (indexType == OgnlRuntime.INDEXED_PROPERTY_INT) {
165: Object array = propertyNode
166: .getValue(context, target);
167: int len = Array.getLength(array);
168:
169: switch (((DynamicSubscript) index)
170: .getFlag()) {
171: case DynamicSubscript.ALL:
172: System.arraycopy(target, 0,
173: value, 0, len);
174: handled = true;
175: i++;
176: break;
177: case DynamicSubscript.FIRST:
178: index = new Integer(
179: (len > 0) ? 0 : -1);
180: break;
181: case DynamicSubscript.MID:
182: index = new Integer(
183: (len > 0) ? (len / 2)
184: : -1);
185: break;
186: case DynamicSubscript.LAST:
187: index = new Integer(
188: (len > 0) ? (len - 1)
189: : -1);
190: break;
191: }
192: } else {
193: if (indexType == OgnlRuntime.INDEXED_PROPERTY_OBJECT) {
194: throw new OgnlException(
195: "DynamicSubscript '"
196: + indexNode
197: + "' not allowed for object indexed property '"
198: + propertyNode
199: + "'");
200: }
201: }
202: }
203: if (!handled) {
204: OgnlRuntime.setIndexedProperty(context,
205: target, propertyNode
206: .getProperty(context,
207: target)
208: .toString(), index,
209: value);
210: handled = true;
211: i++;
212: }
213: }
214: }
215: }
216: }
217: if (!handled) {
218: target = children[i].getValue(context, target);
219: }
220: }
221: if (!handled) {
222: children[children.length - 1].setValue(context, target,
223: value);
224: }
225: }
226:
227: public boolean isSimpleNavigationChain(OgnlContext context)
228: throws OgnlException {
229: boolean result = false;
230:
231: if ((children != null) && (children.length > 0)) {
232: result = true;
233: for (int i = 0; result && (i < children.length); i++) {
234: if (children[i] instanceof SimpleNode) {
235: result = ((SimpleNode) children[i])
236: .isSimpleProperty(context);
237: } else {
238: result = false;
239: }
240: }
241: }
242: return result;
243: }
244:
245: public String toString() {
246: String result = "";
247:
248: if ((children != null) && (children.length > 0)) {
249: for (int i = 0; i < children.length; i++) {
250: if (i > 0) {
251: if (!(children[i] instanceof ASTProperty)
252: || !((ASTProperty) children[i])
253: .isIndexedAccess()) {
254: result = result + ".";
255: }
256: }
257: result += children[i].toString();
258: }
259: }
260: return result;
261: }
262: }
|