001: /*
002: * Spoon - http://spoon.gforge.inria.fr/
003: * Copyright (C) 2006 INRIA Futurs <renaud.pawlak@inria.fr>
004: *
005: * This software is governed by the CeCILL-C License under French law and
006: * abiding by the rules of distribution of free software. You can use, modify
007: * and/or redistribute the software under the terms of the CeCILL-C license as
008: * circulated by CEA, CNRS and INRIA at http://www.cecill.info.
009: *
010: * This program is distributed in the hope that it will be useful, but WITHOUT
011: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
012: * FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL-C License for more details.
013: *
014: * The fact that you are presently reading this means that you have had
015: * knowledge of the CeCILL-C license and that you accept its terms.
016: */
017:
018: package spoon.support.visitor;
019:
020: import java.util.ArrayList;
021: import java.util.Collection;
022: import java.util.ConcurrentModificationException;
023:
024: import spoon.processing.Processor;
025: import spoon.processing.TraversalStrategy;
026: import spoon.reflect.Factory;
027: import spoon.reflect.declaration.CtElement;
028: import spoon.reflect.visitor.CtScanner;
029:
030: /**
031: * This visitor implements the code processing engine.
032: *
033: */
034: public class ProcessingVisitor extends CtScanner {
035:
036: Factory factory;
037:
038: Processor<?> processor;
039:
040: /**
041: * The constructor.
042: */
043: public ProcessingVisitor(Factory factory) {
044: this .factory = factory;
045: }
046:
047: @SuppressWarnings("unchecked")
048: private boolean canBeProcessed(Processor p, CtElement e) {
049: if (!factory.getEnvironment().isProcessingStopped()
050: && p.getProcessedElementTypes() != null) {
051: for (Object o : p.getProcessedElementTypes()) {
052: if (((Class) o).isAssignableFrom(e.getClass())) {
053: return true;
054: }
055: }
056: }
057: return false;
058: }
059:
060: public Processor<?> getProcessor() {
061: return processor;
062: }
063:
064: @Override
065: public void scan(Collection<? extends CtElement> elements) {
066: if ((elements != null)) {
067: for (CtElement e : new ArrayList<CtElement>(elements)) {
068: scan(e);
069: }
070: }
071: }
072:
073: /**
074: * Applies the processing to the given element. To apply the processing,
075: * this method upcalls, for all the registered processor in
076: * {@link Factory#Processor }, the {@link Processor#process(CtElement)}
077: * method if {@link Processor#isToBeProcessed(CtElement)} returns true.
078: */
079: @SuppressWarnings("unchecked")
080: public void scan(CtElement e) {
081: if (e == null) {
082: return;
083: }
084: Processor<CtElement> p = (Processor<CtElement>) processor;
085: if (p.getTraversalStrategy() == TraversalStrategy.PRE_ORDER
086: && canBeProcessed(p, e)) {
087: if (p.isToBeProcessed(e)) {
088: p.process(e);
089: }
090: }
091: try {
092: super .scan(e);
093: } catch (ConcurrentModificationException e1) {
094: this .scan(e);
095: }
096: // try {
097: if (p.getTraversalStrategy() == TraversalStrategy.POST_ORDER
098: && canBeProcessed(p, e)) {
099: if (p.isToBeProcessed(e)) {
100: p.process(e);
101: }
102: }
103: }
104:
105: public void setProcessor(Processor<?> processor) {
106: this.processor = processor;
107: }
108: }
|