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.ArrayList;
022: import java.util.Collection;
023: import java.util.List;
024: import java.util.Map;
025: import java.util.StringTokenizer;
026: import java.util.TreeMap;
027:
028: import spoon.reflect.Factory;
029: import spoon.reflect.declaration.CtPackage;
030: import spoon.reflect.declaration.CtType;
031: import spoon.reflect.reference.CtPackageReference;
032:
033: /**
034: * The {@link CtPackage} sub-factory.
035: */
036: public class PackageFactory extends SubFactory implements Serializable {
037: private static final long serialVersionUID = 1L;
038:
039: /**
040: * top-level package are indexed by name to improve search
041: */
042: private Map<String, CtPackage> packages = new TreeMap<String, CtPackage>();
043:
044: /**
045: * Creates a new package sub-factory.
046: *
047: * @param factory
048: * the parent factory
049: */
050: public PackageFactory(Factory factory) {
051: super (factory);
052: }
053:
054: /**
055: * Creates a reference to an existing package.
056: */
057: public CtPackageReference createReference(CtPackage pack) {
058: return createReference(pack.getQualifiedName());
059: }
060:
061: /**
062: * Creates a reference to a package by using its Java runtime
063: * representation.
064: *
065: * @param pack
066: * a runtime package
067: * @return reference to the package
068: */
069: public CtPackageReference createReference(Package pack) {
070: return createReference(pack.getName());
071: }
072:
073: CtPackageReference topLevel;
074:
075: /**
076: * Returns a reference on the top level package.
077: */
078: public CtPackageReference topLevel() {
079: if (topLevel == null) {
080: topLevel = createReference(CtPackage.TOP_LEVEL_PACKAGE_NAME);
081: }
082: return topLevel;
083: }
084:
085: /**
086: * Creates a reference to a package.
087: *
088: * @param name
089: * full name of the package to reference
090: */
091: public CtPackageReference createReference(String name) {
092: if (name.equals(CtPackage.TOP_LEVEL_PACKAGE_NAME))
093: return null;
094: CtPackageReference ref = factory.Core()
095: .createPackageReference();
096: ref.setSimpleName(name);
097: return ref;
098: }
099:
100: /**
101: * Creates a new package (see also {@link #getOrCreate(String)}).
102: *
103: * @param parent
104: * the parent package (can be null)
105: * @param simpleName
106: * the package's simple name (no dots)
107: * @return the newly created package
108: */
109: public CtPackage create(CtPackage parent, String simpleName) {
110: return getOrCreate(parent.toString()
111: + CtPackage.PACKAGE_SEPARATOR + simpleName);
112: }
113:
114: /**
115: * Gets or creates a package.
116: *
117: * @param qualifiedName
118: * the full name of the package
119: */
120: public CtPackage getOrCreate(String qualifiedName) {
121: StringTokenizer token = new StringTokenizer(qualifiedName,
122: CtPackage.PACKAGE_SEPARATOR);
123: CtPackage last = null;
124:
125: if (token.hasMoreElements()) {
126: String name = token.nextToken();
127: if (name.length() < 0)
128: name = CtPackage.TOP_LEVEL_PACKAGE_NAME;
129: if (packages.containsKey(name)) {
130: last = packages.get(name);
131: } else {
132: last = factory.Core().createPackage();
133: last.setSimpleName(name);
134: register(last);
135: }
136: }
137:
138: while (token.hasMoreElements()) {
139: String name = token.nextToken();
140: CtPackage next = last.getPackage(name);
141: if (next == null) {
142: next = factory.Core().createPackage();
143: next.setSimpleName(name);
144: last.getPackages().add(next);
145: next.setParent(last);
146: }
147: last = next;
148: }
149:
150: return last;
151: }
152:
153: /**
154: * Gets a created package.
155: *
156: * @param qualifiedName
157: * the package to search
158: * @return a found package or null
159: */
160: public CtPackage get(String qualifiedName) {
161: if (qualifiedName.contains(CtType.INNERTTYPE_SEPARATOR)) {
162: throw new RuntimeException("Invalid package name "
163: + qualifiedName);
164: }
165: StringTokenizer token = new StringTokenizer(qualifiedName,
166: CtPackage.PACKAGE_SEPARATOR);
167: CtPackage current = null;
168: if (token.hasMoreElements()) {
169: current = packages.get(token.nextElement());
170: while (token.hasMoreElements() && current != null)
171: current = current.getPackage(token.nextToken());
172: }
173: return current;
174: }
175:
176: /**
177: * Gets the list of all created packages. It includes all the top-level
178: * packages and their sub-packages.
179: */
180: public Collection<CtPackage> getAll() {
181: Collection<CtPackage> packs = new ArrayList<CtPackage>();
182: for (CtPackage pack : packages.values()) {
183: packs.addAll(getSubPackageList(pack));
184: }
185: return packs;
186: }
187:
188: /**
189: * Gets the list of all created root packages
190: */
191: public Collection<CtPackage> getAllRoots() {
192: return packages.values();
193: }
194:
195: private List<CtPackage> getSubPackageList(CtPackage pack) {
196: List<CtPackage> packs = new ArrayList<CtPackage>();
197: packs.add(pack);
198: for (CtPackage p : pack.getPackages()) {
199: packs.addAll(getSubPackageList(p));
200: }
201: return packs;
202: }
203:
204: /**
205: * Registers a top-level package.
206: */
207: public void register(CtPackage pck) {
208: if (packages.containsKey(pck.getQualifiedName())) {
209: throw new RuntimeException("package "
210: + pck.getQualifiedName() + " already created");
211: }
212: packages.put(pck.getQualifiedName(), pck);
213: }
214:
215: }
|