001: /*
002: * Copyright (c) 2001-2007, Jean Tessier
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
007: * are met:
008: *
009: * * Redistributions of source code must retain the above copyright
010: * notice, this list of conditions and the following disclaimer.
011: *
012: * * Redistributions in binary form must reproduce the above copyright
013: * notice, this list of conditions and the following disclaimer in the
014: * documentation and/or other materials provided with the distribution.
015: *
016: * * Neither the name of Jean Tessier nor the names of his contributors
017: * may be used to endorse or promote products derived from this software
018: * without specific prior written permission.
019: *
020: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
021: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
022: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
023: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
024: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
025: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
026: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
027: * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
028: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
029: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
030: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
031: */
032:
033: package com.jeantessier.dependency;
034:
035: import java.util.*;
036:
037: import org.apache.log4j.*;
038:
039: /**
040: * This is a basic implementation of Visitor.
041: *
042: * @see Visitor
043: * @author Jean Tessier
044: */
045: public abstract class VisitorBase implements Visitor {
046: private TraversalStrategy strategy;
047:
048: private LinkedList<Node> currentNodes = new LinkedList<Node>();
049:
050: public VisitorBase() {
051: this (new SelectiveTraversalStrategy());
052: }
053:
054: public VisitorBase(TraversalStrategy strategy) {
055: this .strategy = strategy;
056: }
057:
058: protected TraversalStrategy getStrategy() {
059: return strategy;
060: }
061:
062: public void traverseNodes(Collection<? extends Node> nodes) {
063: if (Logger.getLogger(getClass()).isDebugEnabled()) {
064: Logger.getLogger(getClass()).debug("nodes = " + nodes);
065: }
066:
067: for (Node node : getStrategy().order(nodes)) {
068: node.accept(this );
069: }
070: }
071:
072: protected void traverseInbound(Collection<? extends Node> nodes) {
073: for (Node node : getStrategy().order(nodes)) {
074: node.acceptInbound(this );
075: }
076: }
077:
078: protected void traverseOutbound(Collection<? extends Node> nodes) {
079: for (Node node : getStrategy().order(nodes)) {
080: node.acceptOutbound(this );
081: }
082: }
083:
084: protected Node getCurrentNode() {
085: Node result = null;
086:
087: if (!currentNodes.isEmpty()) {
088: result = currentNodes.getLast();
089: }
090:
091: if (Logger.getLogger(getClass()).isDebugEnabled()) {
092: Logger.getLogger(getClass()).debug(
093: currentNodes + ": " + result);
094: }
095:
096: return result;
097: }
098:
099: protected void pushNode(Node currentNode) {
100: if (Logger.getLogger(getClass()).isDebugEnabled()) {
101: Logger.getLogger(getClass()).debug(
102: currentNodes + " + " + currentNode);
103: }
104:
105: currentNodes.addLast(currentNode);
106: }
107:
108: protected Node popNode() {
109: Node result = currentNodes.removeLast();
110:
111: if (Logger.getLogger(getClass()).isDebugEnabled()) {
112: Logger.getLogger(getClass()).debug(
113: currentNodes + " -> " + result);
114: }
115:
116: return result;
117: }
118:
119: public void visitPackageNode(PackageNode node) {
120: boolean inScope = isInScope(node);
121:
122: if (inScope) {
123: preprocessPackageNode(node);
124:
125: if (getStrategy().doPreOutboundTraversal()) {
126: traverseOutbound(node.getOutboundDependencies());
127: }
128:
129: if (getStrategy().doPreInboundTraversal()) {
130: traverseInbound(node.getInboundDependencies());
131: }
132:
133: preprocessAfterDependenciesPackageNode(node);
134: }
135:
136: traverseNodes(node.getClasses());
137:
138: if (inScope) {
139: postprocessBeforeDependenciesPackageNode(node);
140:
141: if (getStrategy().doPostOutboundTraversal()) {
142: traverseOutbound(node.getOutboundDependencies());
143: }
144:
145: if (getStrategy().doPostInboundTraversal()) {
146: traverseInbound(node.getInboundDependencies());
147: }
148:
149: postprocessPackageNode(node);
150: }
151: }
152:
153: protected boolean isInScope(PackageNode node) {
154: return getStrategy().isInScope(node);
155: }
156:
157: protected void preprocessPackageNode(PackageNode node) {
158: pushNode(node);
159: }
160:
161: protected void preprocessAfterDependenciesPackageNode(
162: PackageNode node) {
163: // Do nothing
164: }
165:
166: protected void postprocessBeforeDependenciesPackageNode(
167: PackageNode node) {
168: // Do nothing
169: }
170:
171: protected void postprocessPackageNode(PackageNode node) {
172: if (node.equals(getCurrentNode())) {
173: popNode();
174: }
175: }
176:
177: public void visitInboundPackageNode(PackageNode node) {
178: // Do nothing
179: }
180:
181: public void visitOutboundPackageNode(PackageNode node) {
182: // Do nothing
183: }
184:
185: public void visitClassNode(ClassNode node) {
186: boolean inScope = isInScope(node);
187:
188: if (inScope) {
189: preprocessClassNode(node);
190:
191: if (getStrategy().doPreOutboundTraversal()) {
192: traverseOutbound(node.getOutboundDependencies());
193: }
194:
195: if (getStrategy().doPreInboundTraversal()) {
196: traverseInbound(node.getInboundDependencies());
197: }
198:
199: preprocessAfterDependenciesClassNode(node);
200: }
201:
202: traverseNodes(node.getFeatures());
203:
204: if (inScope) {
205: postprocessBeforeDependenciesClassNode(node);
206:
207: if (getStrategy().doPostOutboundTraversal()) {
208: traverseOutbound(node.getOutboundDependencies());
209: }
210:
211: if (getStrategy().doPostInboundTraversal()) {
212: traverseInbound(node.getInboundDependencies());
213: }
214:
215: postprocessClassNode(node);
216: }
217: }
218:
219: protected boolean isInScope(ClassNode node) {
220: return getStrategy().isInScope(node);
221: }
222:
223: protected void preprocessClassNode(ClassNode node) {
224: pushNode(node);
225: }
226:
227: protected void preprocessAfterDependenciesClassNode(ClassNode node) {
228: // Do nothing
229: }
230:
231: protected void postprocessBeforeDependenciesClassNode(ClassNode node) {
232: // Do nothing
233: }
234:
235: protected void postprocessClassNode(ClassNode node) {
236: if (node.equals(getCurrentNode())) {
237: popNode();
238: }
239: }
240:
241: public void visitInboundClassNode(ClassNode node) {
242: // Do nothing
243: }
244:
245: public void visitOutboundClassNode(ClassNode node) {
246: // Do nothing
247: }
248:
249: public void visitFeatureNode(FeatureNode node) {
250: if (isInScope(node)) {
251: preprocessFeatureNode(node);
252:
253: if (getStrategy().doPreOutboundTraversal()) {
254: traverseOutbound(node.getOutboundDependencies());
255: }
256:
257: if (getStrategy().doPreInboundTraversal()) {
258: traverseInbound(node.getInboundDependencies());
259: }
260:
261: if (getStrategy().doPostOutboundTraversal()) {
262: traverseOutbound(node.getOutboundDependencies());
263: }
264:
265: if (getStrategy().doPostInboundTraversal()) {
266: traverseInbound(node.getInboundDependencies());
267: }
268:
269: postprocessFeatureNode(node);
270: }
271: }
272:
273: protected boolean isInScope(FeatureNode node) {
274: return getStrategy().isInScope(node);
275: }
276:
277: protected void preprocessFeatureNode(FeatureNode node) {
278: pushNode(node);
279: }
280:
281: protected void postprocessFeatureNode(FeatureNode node) {
282: if (node.equals(getCurrentNode())) {
283: popNode();
284: }
285: }
286:
287: public void visitInboundFeatureNode(FeatureNode node) {
288: // Do nothing
289: }
290:
291: public void visitOutboundFeatureNode(FeatureNode node) {
292: // Do nothing
293: }
294: }
|