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.io.*;
036: import java.util.*;
037:
038: import org.apache.log4j.*;
039: import org.apache.oro.text.perl.*;
040:
041: public class TextPrinter extends Printer {
042: private static final Perl5Util perl = new Perl5Util();
043:
044: protected static Perl5Util perl() {
045: return perl;
046: }
047:
048: private boolean showInferred = true;
049: private Map<Node, Integer> dependencies = new TreeMap<Node, Integer>();
050:
051: public TextPrinter(PrintWriter out) {
052: super (out);
053: }
054:
055: public TextPrinter(TraversalStrategy strategy, PrintWriter out) {
056: super (strategy, out);
057: }
058:
059: public boolean isShowInferred() {
060: return showInferred;
061: }
062:
063: public void setShowInferred(boolean showInferred) {
064: this .showInferred = showInferred;
065: }
066:
067: protected void preprocessPackageNode(PackageNode node) {
068: Logger.getLogger(getClass()).debug(
069: "Printing package \"" + node + "\" and its "
070: + node.getInboundDependencies().size()
071: + " inbounds and "
072: + node.getOutboundDependencies().size()
073: + " outbounds");
074:
075: super .preprocessPackageNode(node);
076:
077: raiseIndent();
078:
079: dependencies.clear();
080: }
081:
082: protected void preprocessAfterDependenciesPackageNode(
083: PackageNode node) {
084: Logger.getLogger(getClass()).debug(
085: "Package \"" + node + "\" with "
086: + node.getInboundDependencies().size()
087: + " inbounds and "
088: + node.getOutboundDependencies().size()
089: + " outbounds had " + dependencies.size()
090: + " dependencies.");
091:
092: if (shouldShowPackageNode(node) || !dependencies.isEmpty()) {
093: lowerIndent();
094: indent().printScopeNodeName(node).eol();
095: raiseIndent();
096: }
097:
098: printDependencies(node, dependencies);
099: }
100:
101: protected void postprocessPackageNode(PackageNode node) {
102: lowerIndent();
103:
104: super .postprocessPackageNode(node);
105: }
106:
107: public void visitInboundPackageNode(PackageNode node) {
108: if (isShowInbounds()) {
109: Logger.getLogger(getClass()).debug(
110: "Printing \"" + getCurrentNode() + "\" <-- \""
111: + node + "\"");
112:
113: Integer i = dependencies.get(node);
114: if (i != null) {
115: dependencies.put(node, i - 1);
116: } else {
117: dependencies.put(node, -1);
118: }
119: } else {
120: Logger.getLogger(getClass()).debug(
121: "Ignoring \"" + getCurrentNode() + "\" <-- \""
122: + node + "\"");
123: }
124: }
125:
126: public void visitOutboundPackageNode(PackageNode node) {
127: if (isShowOutbounds()) {
128: Logger.getLogger(getClass()).debug(
129: "Printing \"" + getCurrentNode() + "\" --> \""
130: + node + "\"");
131:
132: Integer i = dependencies.get(node);
133: if (i != null) {
134: dependencies.put(node, i + 1);
135: } else {
136: dependencies.put(node, 1);
137: }
138: } else {
139: Logger.getLogger(getClass()).debug(
140: "Ignoring \"" + getCurrentNode() + "\" --> \""
141: + node + "\"");
142: }
143: }
144:
145: protected void preprocessClassNode(ClassNode node) {
146: Logger.getLogger(getClass()).debug(
147: "Printing class \"" + node + "\" and its "
148: + node.getInboundDependencies().size()
149: + " inbounds and "
150: + node.getOutboundDependencies().size()
151: + " outbounds");
152:
153: super .preprocessClassNode(node);
154:
155: raiseIndent();
156:
157: dependencies.clear();
158: }
159:
160: protected void preprocessAfterDependenciesClassNode(ClassNode node) {
161: Logger.getLogger(getClass()).debug(
162: "Class \"" + node + "\" with "
163: + node.getInboundDependencies().size()
164: + " inbounds and "
165: + node.getOutboundDependencies().size()
166: + " outbounds had " + dependencies.size()
167: + " dependencies.");
168:
169: if (shouldShowClassNode(node) || !dependencies.isEmpty()) {
170: lowerIndent();
171: indent().printScopeNodeName(node, node.getSimpleName())
172: .eol();
173: raiseIndent();
174: }
175:
176: printDependencies(node, dependencies);
177: }
178:
179: protected void postprocessClassNode(ClassNode node) {
180: lowerIndent();
181:
182: super .postprocessClassNode(node);
183: }
184:
185: public void visitInboundClassNode(ClassNode node) {
186: if (isShowInbounds()) {
187: Logger.getLogger(getClass()).debug(
188: "Printing \"" + getCurrentNode() + "\" <-- \""
189: + node + "\"");
190:
191: Integer i = dependencies.get(node);
192: if (i != null) {
193: dependencies.put(node, i - 1);
194: } else {
195: dependencies.put(node, -1);
196: }
197: } else {
198: Logger.getLogger(getClass()).debug(
199: "Ignoring \"" + getCurrentNode() + "\" <-- \""
200: + node + "\"");
201: }
202: }
203:
204: public void visitOutboundClassNode(ClassNode node) {
205: if (isShowOutbounds()) {
206: Logger.getLogger(getClass()).debug(
207: "Printing \"" + getCurrentNode() + "\" --> \""
208: + node + "\"");
209:
210: Integer i = dependencies.get(node);
211: if (i != null) {
212: dependencies.put(node, i + 1);
213: } else {
214: dependencies.put(node, 1);
215: }
216: } else {
217: Logger.getLogger(getClass()).debug(
218: "Ignoring \"" + getCurrentNode() + "\" --> \""
219: + node + "\"");
220: }
221: }
222:
223: protected void preprocessFeatureNode(FeatureNode node) {
224: Logger.getLogger(getClass()).debug(
225: "Printing feature \"" + node + "\" and its "
226: + node.getInboundDependencies().size()
227: + " inbounds and "
228: + node.getOutboundDependencies().size()
229: + " outbounds");
230:
231: super .preprocessFeatureNode(node);
232:
233: raiseIndent();
234:
235: dependencies.clear();
236: }
237:
238: protected void postprocessFeatureNode(FeatureNode node) {
239: Logger.getLogger(getClass()).debug(
240: "Feature \"" + node + "\" with "
241: + node.getInboundDependencies().size()
242: + " inbounds and "
243: + node.getOutboundDependencies().size()
244: + " outbounds had " + dependencies.size()
245: + " dependencies.");
246:
247: if (shouldShowFeatureNode(node) || !dependencies.isEmpty()) {
248: lowerIndent();
249: if (perl().match("/([^\\.]*\\(.*\\))$/", node.getName())) {
250: indent().printScopeNodeName(node, perl().group(1))
251: .eol();
252: } else if (perl().match("/([^\\.]*)$/", node.getName())) {
253: indent().printScopeNodeName(node, perl().group(1))
254: .eol();
255: } else {
256: indent().printScopeNodeName(
257: node,
258: node.getName().substring(
259: node.getName().lastIndexOf('.') + 1))
260: .eol();
261: }
262: raiseIndent();
263: }
264:
265: printDependencies(node, dependencies);
266:
267: lowerIndent();
268:
269: super .postprocessFeatureNode(node);
270: }
271:
272: public void visitInboundFeatureNode(FeatureNode node) {
273: if (isShowInbounds()) {
274: Logger.getLogger(getClass()).debug(
275: "Printing \"" + getCurrentNode() + "\" <-- \""
276: + node + "\"");
277:
278: Integer i = dependencies.get(node);
279: if (i != null) {
280: dependencies.put(node, i - 1);
281: } else {
282: dependencies.put(node, -1);
283: }
284: } else {
285: Logger.getLogger(getClass()).debug(
286: "Ignoring \"" + getCurrentNode() + "\" <-- \""
287: + node + "\"");
288: }
289: }
290:
291: public void visitOutboundFeatureNode(FeatureNode node) {
292: if (isShowOutbounds()) {
293: Logger.getLogger(getClass()).debug(
294: "Printing \"" + getCurrentNode() + "\" --> \""
295: + node + "\"");
296:
297: Integer i = dependencies.get(node);
298: if (i != null) {
299: dependencies.put(node, i + 1);
300: } else {
301: dependencies.put(node, 1);
302: }
303: } else {
304: Logger.getLogger(getClass()).debug(
305: "Ignoring \"" + getCurrentNode() + "\" --> \""
306: + node + "\"");
307: }
308: }
309:
310: protected Printer printNodeName(Node node, String name) {
311: super .printNodeName(node, name);
312:
313: if (isShowInferred() && !node.isConfirmed()) {
314: append(" *");
315: }
316:
317: return this ;
318: }
319:
320: protected void printDependencies(Node node,
321: Map<Node, Integer> dependencies) {
322: for (Map.Entry<Node, Integer> entry : dependencies.entrySet()) {
323: if (entry.getValue() < 0) {
324: indent().append("<-- ").printDependencyNodeName(
325: entry.getKey()).eol();
326: } else if (entry.getValue() > 0) {
327: indent().append("--> ").printDependencyNodeName(
328: entry.getKey()).eol();
329: } else {
330: indent().append("<-> ").printDependencyNodeName(
331: entry.getKey()).eol();
332: }
333: }
334: }
335: }
|