001/* 002 * Copyright 2002-2012 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 * https://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 017package org.springframework.beans.factory.parsing; 018 019import 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 each point 024 * 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 error messages. 028 * 029 * @author Rob Harrop 030 * @since 2.0 031 */ 032public final class ParseState { 033 034 /** 035 * Internal {@link Stack} storage. 036 */ 037 private final Stack<Entry> state; 038 039 040 /** 041 * Create a new {@code ParseState} with an empty {@link Stack}. 042 */ 043 public ParseState() { 044 this.state = new Stack<Entry>(); 045 } 046 047 /** 048 * Create a new {@code ParseState} whose {@link Stack} is a clone 049 * of that of the passed in {@code ParseState}. 050 */ 051 @SuppressWarnings("unchecked") 052 private ParseState(ParseState other) { 053 this.state = (Stack<Entry>) other.state.clone(); 054 } 055 056 057 /** 058 * Add a new {@link Entry} to the {@link Stack}. 059 */ 060 public void push(Entry entry) { 061 this.state.push(entry); 062 } 063 064 /** 065 * Remove an {@link Entry} from the {@link Stack}. 066 */ 067 public void pop() { 068 this.state.pop(); 069 } 070 071 /** 072 * Return the {@link Entry} currently at the top of the {@link Stack} or 073 * {@code null} if the {@link Stack} is empty. 074 */ 075 public Entry peek() { 076 return (this.state.empty() ? null : this.state.peek()); 077 } 078 079 /** 080 * Create a new instance of {@link ParseState} which is an independent snapshot 081 * of this instance. 082 */ 083 public ParseState snapshot() { 084 return new ParseState(this); 085 } 086 087 088 /** 089 * Returns a tree-style representation of the current {@code ParseState}. 090 */ 091 @Override 092 public String toString() { 093 StringBuilder sb = new StringBuilder(64); 094 int i = 0; 095 for (ParseState.Entry entry : this.state) { 096 if (i > 0) { 097 sb.append('\n'); 098 for (int j = 0; j < i; j++) { 099 sb.append('\t'); 100 } 101 sb.append("-> "); 102 } 103 sb.append(entry); 104 i++; 105 } 106 return sb.toString(); 107 } 108 109 110 /** 111 * Marker interface for entries into the {@link ParseState}. 112 */ 113 public interface Entry { 114 115 } 116 117}