001: /*
002: * Copyright 2002-2006 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.springframework.beans.factory.parsing;
018:
019: import java.util.Stack;
020:
021: /**
022: * Simple {@link Stack}-based structure for tracking the logical position during
023: * a parsing process. {@link Entry entries} are added to the stack at
024: * each point during the parse phase in a reader-specific manner.
025: *
026: * <p>Calling {@link #toString()} will render a tree-style view of the current logical
027: * position in the parse phase. This representation is intended for use in
028: * error messages.
029: *
030: * @author Rob Harrop
031: * @since 2.0
032: */
033: public final class ParseState {
034:
035: /**
036: * Tab character used when rendering the tree-style representation.
037: */
038: private static final char TAB = '\t';
039:
040: /**
041: * Internal {@link Stack} storage.
042: */
043: private final Stack state;
044:
045: /**
046: * Create a new <code>ParseState</code> with an empty {@link Stack}.
047: */
048: public ParseState() {
049: this .state = new Stack();
050: }
051:
052: /**
053: * Create a new <code>ParseState</code> whose {@link Stack} is a {@link Object#clone clone}
054: * of that of the passed in <code>ParseState</code>.
055: */
056: private ParseState(ParseState other) {
057: this .state = (Stack) other.state.clone();
058: }
059:
060: /**
061: * Add a new {@link Entry} to the {@link Stack}.
062: */
063: public void push(Entry entry) {
064: this .state.push(entry);
065: }
066:
067: /**
068: * Remove an {@link Entry} from the {@link Stack}.
069: */
070: public void pop() {
071: this .state.pop();
072: }
073:
074: /**
075: * Return the {@link Entry} currently at the top of the {@link Stack} or
076: * <code>null</code> if the {@link Stack} is empty.
077: */
078: public Entry peek() {
079: return (Entry) (this .state.empty() ? null : this .state.peek());
080: }
081:
082: /**
083: * Create a new instance of {@link ParseState} which is an independent snapshot
084: * of this instance.
085: */
086: public ParseState snapshot() {
087: return new ParseState(this );
088: }
089:
090: /**
091: * Returns a tree-style representation of the current <code>ParseState</code>.
092: */
093: public String toString() {
094: StringBuffer sb = new StringBuffer();
095: for (int x = 0; x < this .state.size(); x++) {
096: if (x > 0) {
097: sb.append('\n');
098: for (int y = 0; y < x; y++) {
099: sb.append(TAB);
100: }
101: sb.append("-> ");
102: }
103: sb.append(this .state.get(x));
104: }
105: return sb.toString();
106: }
107:
108: /**
109: * Marker interface for entries into the {@link ParseState}.
110: */
111: public interface Entry {
112:
113: }
114:
115: }
|