001: /**
002: * MVEL (The MVFLEX Expression Language)
003: *
004: * Copyright (C) 2007 Christopher Brock, MVFLEX/Valhalla Project and the Codehaus
005: *
006: * Licensed under the Apache License, Version 2.0 (the "License");
007: * you may not use this file except in compliance with the License.
008: * You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing, software
013: * distributed under the License is distributed on an "AS IS" BASIS,
014: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: * See the License for the specific language governing permissions and
016: * limitations under the License.
017: *
018: */package org.mvel.util;
019:
020: import org.mvel.ast.ASTNode;
021:
022: import java.io.Serializable;
023: import java.util.ArrayList;
024: import java.util.NoSuchElementException;
025:
026: /**
027: * A fast, array-based implementation of the ASTIterator. Primarily used in compiled statements for fast execution.
028: */
029: @SuppressWarnings({"ManualArrayCopy"})
030: public class ASTArrayList implements ASTIterator, Serializable {
031: private ASTNode[] astNodes;
032: private int length = 0;
033: private int cursor = 0;
034:
035: public ASTArrayList() {
036: astNodes = new ASTNode[7];
037: }
038:
039: public ASTArrayList(int ensureCapacity) {
040: astNodes = new ASTNode[ensureCapacity];
041: }
042:
043: public ASTArrayList(final ASTArrayList fi) {
044: astNodes = fi.astNodes;
045: length = fi.length;
046: }
047:
048: public ASTArrayList(ASTIterator map) {
049: map.finish();
050:
051: if (map instanceof ASTArrayList) {
052: this .length = (this .astNodes = ((ASTArrayList) map).astNodes).length;
053: } else {
054: ArrayList<ASTNode> astNodes = new ArrayList<ASTNode>();
055: map.reset();
056: while (map.hasMoreNodes()) {
057: astNodes.add(map.nextNode());
058: }
059:
060: this .astNodes = astNodes
061: .toArray(new ASTNode[length = astNodes.size()]);
062: }
063: }
064:
065: public void reset() {
066: cursor = 0;
067: }
068:
069: public void addTokenNode(ASTNode node) {
070: growIfFull(1);
071: astNodes[length++] = node;
072: }
073:
074: public void addTokenNode(ASTNode node1, ASTNode node2) {
075: growIfFull(2);
076: astNodes[length++] = node1;
077: astNodes[length++] = node2;
078: }
079:
080: public ASTNode remove(int index) {
081: if (index >= length) {
082: throw new NoSuchElementException("" + index);
083: }
084:
085: ASTNode n = astNodes[index];
086:
087: for (int i = index; i < (length - 1); i++) {
088: astNodes[i] = astNodes[i + 1];
089: }
090:
091: length--;
092:
093: return n;
094: }
095:
096: public ASTNode remove(ASTNode node) {
097: return remove(indexOf(node));
098: }
099:
100: public int indexOf(ASTNode n) {
101: for (int i = 0; i < length; i++) {
102: if (astNodes[i].equals(n))
103: return i;
104: }
105: return -1;
106: }
107:
108: public ASTNode set(int index, ASTNode n) {
109: if (index >= length) {
110: throw new IndexOutOfBoundsException("" + index);
111: }
112:
113: ASTNode old = astNodes[index];
114: astNodes[index] = n;
115: return old;
116: }
117:
118: public ASTNode firstNode() {
119: return astNodes[0];
120: }
121:
122: public ASTNode nextNode() {
123: if (cursor < length)
124: return astNodes[cursor++];
125: else
126: return null;
127: }
128:
129: public void skipNode() {
130: cursor++;
131: }
132:
133: public ASTNode peekNext() {
134: if (cursor < length)
135: return astNodes[cursor + 1];
136: else
137: return null;
138: }
139:
140: public ASTNode peekNode() {
141: if (cursor < length)
142: return astNodes[cursor];
143: else
144: return null;
145: }
146:
147: public ASTNode peekLast() {
148: if (length > 0) {
149: return astNodes[length - 1];
150: } else {
151: return null;
152: }
153: }
154:
155: public ASTNode nodesBack(int offset) {
156: if (cursor - offset >= 0) {
157: return astNodes[cursor - offset];
158: } else {
159: return null;
160: }
161: }
162:
163: public void back() {
164: cursor--;
165: }
166:
167: public boolean hasMoreNodes() {
168: return cursor < length;
169: }
170:
171: public String showNodeChain() {
172: StringAppender sb = new StringAppender();
173: for (int i = 0; i < length; i++) {
174: sb
175: .append(
176: "("
177: + i
178: + "): <<"
179: + astNodes[i].getName()
180: + ">> = <<"
181: + astNodes[i].getLiteralValue()
182: + ">> ["
183: + (astNodes[i].getLiteralValue() != null ? astNodes[i]
184: .getLiteralValue()
185: .getClass()
186: : "null") + "]").append(
187: "\n");
188: }
189:
190: return sb.toString();
191: }
192:
193: public int size() {
194: return length;
195: }
196:
197: public int index() {
198: return cursor;
199: }
200:
201: private void growIfFull(int plannedIncrease) {
202: if ((length + plannedIncrease) >= astNodes.length) {
203: ASTNode[] newNodes = new ASTNode[astNodes.length * 2];
204:
205: for (int i = 0; i < length; i++) {
206: newNodes[i] = astNodes[i];
207: }
208:
209: astNodes = newNodes;
210: }
211: }
212:
213: public void finish() {
214: ASTArrayList newList = new ASTArrayList(length);
215:
216: int len = length;
217: for (int i = 0; i < len; i++) {
218: if (!astNodes[i].isDiscard()) {
219: newList.addTokenNode(astNodes[i]);
220: } else {
221: length--;
222: }
223: }
224:
225: astNodes = newList.astNodes;
226:
227: reset();
228: }
229:
230: public ASTLinkedList toASTLinkedList() {
231: ASTLinkedList list = new ASTLinkedList();
232: for (int i = 0; i < length; i++) {
233: if (astNodes[i] == null) {
234: System.out.println("NULL");
235: }
236: if (!astNodes[i].isDiscard())
237: list.addTokenNode(astNodes[i]);
238: }
239: list.reset();
240: return list;
241: }
242: }
|