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.reflect.factory;
019:
020: import java.io.Serializable;
021: import java.util.Map;
022: import java.util.TreeMap;
023:
024: import spoon.reflect.Factory;
025: import spoon.reflect.declaration.CtClass;
026: import spoon.reflect.declaration.CtElement;
027: import spoon.reflect.declaration.CtSimpleType;
028: import spoon.reflect.declaration.CtType;
029: import spoon.reflect.reference.CtReference;
030: import spoon.reflect.reference.CtTypeReference;
031: import spoon.reflect.visitor.CtScanner;
032: import spoon.template.Template;
033: import spoon.template.TemplateException;
034:
035: /**
036: * A factory for storing, accessing and creating templates and associated types.
037: */
038: public class TemplateFactory extends SubFactory implements Serializable {
039:
040: private static final long serialVersionUID = 1L;
041:
042: /**
043: * Creates a new template factory.
044: *
045: * @param factory
046: * the parent factory
047: */
048: public TemplateFactory(Factory factory) {
049: super (factory);
050: }
051:
052: private Map<String, CtClass<?>> templates = new TreeMap<String, CtClass<?>>();
053:
054: /**
055: * Adds a template to this factory.
056: *
057: * @param template
058: * the template class
059: */
060: public void add(CtClass<?> template) {
061: if (templates.containsKey(template.getQualifiedName()))
062: templates.remove(template.getQualifiedName());
063: templates.put(template.getQualifiedName(), template);
064: new CtScanner() {
065: public void enter(CtElement e) {
066: e.setFactory(factory);
067: super .enter(e);
068: }
069:
070: @Override
071: protected void enterReference(CtReference e) {
072: e.setFactory(factory);
073: super .enterReference(e);
074: }
075: }.scan(template);
076: }
077:
078: /**
079: * Gets all the templates in this factory.
080: *
081: * @return the stored templates as a map
082: */
083: public Map<String, CtClass<?>> getAll() {
084: return templates;
085: }
086:
087: /**
088: * Gets a template CT class from its actual class.
089: *
090: * @param templateClass
091: * the runtime class
092: * @return the compile-time class
093: */
094: public <T> CtClass<T> get(Class<?> templateClass) {
095: return get(templateClass.getName());
096: }
097:
098: /**
099: * Gets a template class from its qualified name.
100: *
101: * @param templateName
102: * the template's fully qualified name
103: * @return the template class
104: */
105: @SuppressWarnings("unchecked")
106: public <T> CtClass<T> get(String templateName) {
107: if (!templates.containsKey(templateName))
108: throw new TemplateException("Unable to load template \""
109: + templateName
110: + "\". Check your template source path.");
111: return (CtClass<T>) templates.get(templateName);
112: }
113:
114: /**
115: * Look for template classes in the parent factory and add them to this
116: * factory.
117: */
118: @SuppressWarnings("unchecked")
119: public void parseTypes() {
120: for (CtSimpleType<?> t : factory.Type().getAll()) {
121: if (t instanceof CtClass) {
122: for (CtSimpleType nested : ((CtType<?>) t)
123: .getNestedTypes()) {
124: if (nested instanceof CtClass)
125: scanType((CtClass<? extends Template>) nested);
126: }
127: scanType((CtClass<? extends Template>) t);
128: }
129: }
130: }
131:
132: private void scanType(CtClass<? extends Template> t) {
133: if (factory.Type().createReference(Template.class)
134: .isAssignableFrom(t.getReference())) {
135: add(t);
136: }
137: }
138:
139: /**
140: * Helper method to know if a given type reference points to a Template or
141: * not
142: *
143: * @param candidate
144: * the reference to check
145: *
146: * @return <code> true </code> if the reference points to a template type
147: */
148: public boolean isTemplate(CtTypeReference<?> candidate) {
149: return templates.containsKey(candidate.getQualifiedName());
150: }
151: }
|