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;
019:
020: import java.util.Collection;
021: import java.util.LinkedList;
022: import java.util.List;
023:
024: import spoon.processing.ProcessingManager;
025: import spoon.processing.Processor;
026: import spoon.processing.Severity;
027: import spoon.reflect.Factory;
028: import spoon.reflect.declaration.CtElement;
029: import spoon.reflect.declaration.CtNamedElement;
030: import spoon.support.util.Timer;
031: import spoon.support.visitor.ProcessingVisitor;
032:
033: /**
034: * This processing manager implements a blocking processing policy that consists
035: * of applying the processors in a FIFO order until no processors remain to be
036: * applied.
037: */
038: public class RuntimeProcessingManager implements ProcessingManager {
039: Processor<?> current;
040:
041: Factory factory;
042:
043: List<Processor<?>> processors;
044:
045: ProcessingVisitor visitor;
046:
047: /**
048: * Creates a new processing manager that maintains a queue of processors to
049: * be applied to a given factory.
050: *
051: * @param factory
052: * the factory on which the processing applies (contains the
053: * meta-model)
054: */
055: public RuntimeProcessingManager(Factory factory) {
056: super ();
057: setFactory(factory);
058: }
059:
060: public void addProcessor(Class<? extends Processor<?>> type) {
061: try {
062: Processor<?> p = type.newInstance();
063: p.setFactory(factory);
064: p.init();
065: addProcessor(p);
066: } catch (Exception e) {
067: factory
068: .getEnvironment()
069: .report(
070: null,
071: Severity.ERROR,
072: "Unable to instantiate processor \""
073: + type.getName()
074: + "\" - Your processor should have a constructor with no arguments");
075: }
076: }
077:
078: public boolean addProcessor(Processor<?> p) {
079: p.setFactory(getFactory());
080: return getProcessors().add(p);
081: }
082:
083: @SuppressWarnings("unchecked")
084: public void addProcessor(String qualifiedName) {
085: try {
086: addProcessor((Class<? extends Processor<?>>) Class
087: .forName(qualifiedName));
088: } catch (ClassNotFoundException e) {
089: factory.getEnvironment().report(
090: null,
091: Severity.ERROR,
092: "Unable to load processor \"" + qualifiedName
093: + "\" - Check your classpath");
094: }
095: }
096:
097: public Processor<?> getCurrentProcessor() {
098: return current;
099: }
100:
101: public Factory getFactory() {
102: return factory;
103: }
104:
105: public List<Processor<?>> getProcessors() {
106: if (processors == null) {
107: processors = new LinkedList<Processor<?>>();
108: }
109: return processors;
110: }
111:
112: private ProcessingVisitor getVisitor() {
113: if (visitor == null)
114: visitor = new ProcessingVisitor(getFactory());
115: return visitor;
116: }
117:
118: public boolean isToBeApplied(Class<? extends Processor<?>> type) {
119: for (Processor<?> p : getProcessors()) {
120: if (p.getClass() == type) {
121: return true;
122: }
123: }
124: return false;
125: }
126:
127: public void process() {
128: Timer.start("process");
129: process(getFactory().Package().getAllRoots());
130: Timer.stop("process");
131: }
132:
133: public void process(Collection<? extends CtElement> elements) {
134: for (Processor<?> p : getProcessors()) {
135: current = p;
136: process(elements, p);
137: }
138: }
139:
140: /**
141: * Recursively processes elements and their children with a given processor.
142: */
143: public void process(Collection<? extends CtElement> elements,
144: Processor<?> processor) {
145: getFactory().getEnvironment().debugMessage(
146: "processing with '" + processor.getClass().getName()
147: + "'...");
148: current = processor;
149: Timer.start(processor.getClass().getName());
150: for (CtElement e : elements)
151: process(e, processor);
152: Timer.stop(processor.getClass().getName());
153: }
154:
155: public void process(CtElement element) {
156: for (Processor<?> p : getProcessors()) {
157: current = p;
158: process(element, p);
159: }
160: }
161:
162: /**
163: * Recursively processes an element and its children with a given processor.
164: */
165: public void process(CtElement element, Processor<?> processor) {
166: getFactory()
167: .getEnvironment()
168: .debugMessage(
169: "processing '"
170: + ((element instanceof CtNamedElement) ? ((CtNamedElement) element)
171: .getSimpleName()
172: : element.toString())
173: + "' with '"
174: + processor.getClass().getName()
175: + "'...");
176: processor.init();
177: getVisitor().setProcessor(processor);
178: getVisitor().scan(element);
179: processor.processingDone();
180: }
181:
182: public void setFactory(Factory factory) {
183: this.factory = factory;
184: factory.getEnvironment().setManager(this);
185: }
186:
187: }
|