001: /*
002: * Copyright 2005 Joe Walker
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.directwebremoting.drapgen.ast;
017:
018: import java.io.File;
019: import java.io.IOException;
020: import java.util.Collection;
021: import java.util.Collections;
022: import java.util.HashMap;
023: import java.util.HashSet;
024: import java.util.Map;
025: import java.util.Set;
026: import java.util.SortedSet;
027: import java.util.TreeSet;
028:
029: import org.directwebremoting.drapgen.loader.gi.GiLoader;
030: import org.directwebremoting.util.Logger;
031:
032: /**
033: * A Project is a collection of {@link Type}s that we will convert to reverse
034: * ajax proxies.
035: * @author Joe Walker [joe at getahead dot ltd dot uk]
036: */
037: public class Project {
038: /**
039: * Save the types in the current project into XML files in the given
040: * directory.
041: * This helps us separate the process of creating the AST (from the
042: * Javascript) from the process of generating the Java from the AST
043: * @param directory The place to write to
044: * @throws IOException If the save process fails
045: */
046: public void save(File directory) throws IOException {
047: SortedSet<String> keys = new TreeSet<String>(types.keySet());
048: for (String className : keys) {
049: Type type = types.get(className);
050: type.save(directory);
051: }
052: }
053:
054: /**
055: * Load the types in the given directory into this Project.
056: * This method does *not* call clear before it loads Types
057: * @param directory The place to read from
058: * @throws IOException If the read fails.
059: */
060: public void load(File directory) throws IOException {
061: for (File file : directory.listFiles()) {
062: if (file.getName().endsWith(".xml")) {
063: Type type = new Type(this , file);
064: add(type);
065: }
066: }
067: }
068:
069: /**
070: * Allow users to dig into the code in a project
071: * @param visitor The object to pass around the code in a project
072: */
073: public void visit(Visitor visitor) {
074: boolean dig = visitor.visitEnter(this );
075: if (dig) {
076: for (Type type : types.values()) {
077: type.visit(visitor);
078: }
079: visitor.visitLeave(this );
080: }
081: }
082:
083: /**
084: * Useful if we have a classname that we know must be defined somewhere,
085: * but might not have been defined yet.
086: * @param className The potentially existing class name
087: * @return A newly created or existing Type
088: */
089: public Type getType(String className) {
090: Type type = types.get(className);
091:
092: if (className.indexOf(" ") != -1) {
093: log.warn("Creating class called: " + className);
094: }
095:
096: if (type == null) {
097: type = new Type(this , className);
098: add(type);
099: }
100:
101: return type;
102: }
103:
104: /**
105: * Is the given (full) class name one that another class claims as it's
106: * ancestor?
107: * @param name The class name to search for
108: * @return true iff the class has children
109: */
110: public boolean isSuperClass(String name) {
111: if (super Classes == null) {
112: super Classes = new HashSet<String>();
113: for (Type type : types.values()) {
114: Type super Class = type.getSuperClass();
115: if (super Class != null) {
116: super Classes.add(super Class.getFullName());
117: }
118:
119: for (Type iface : type.getInterfaces()) {
120: super Classes.add(iface.getFullName());
121: }
122: }
123: }
124:
125: return super Classes.contains(name);
126: }
127:
128: /**
129: * @return An class name with native types replaced by Object types
130: */
131: public String asObject(String maybeNative) {
132: if (maybeNative.equals("int")) {
133: return "Integer";
134: } else if (maybeNative.equals("char")) {
135: return "Character";
136: } else if (maybeNative.equals("boolean")) {
137: return "Boolean";
138: } else if (maybeNative.equals("long")) {
139: return "Long";
140: } else if (maybeNative.equals("float")) {
141: return "Float";
142: } else if (maybeNative.equals("double")) {
143: return "Double";
144: } else if (maybeNative.equals("short")) {
145: return "Short";
146: } else if (maybeNative.equals("byte")) {
147: return "Byte";
148: }
149: return maybeNative;
150: }
151:
152: /**
153: * @see java.util.Set#clear()
154: */
155: public void clear() {
156: types.clear();
157: }
158:
159: /**
160: * @see java.util.Set#contains(java.lang.Object)
161: */
162: public boolean contains(String className) {
163: return types.containsKey(className);
164: }
165:
166: /**
167: * @see java.util.Set#isEmpty()
168: */
169: public boolean isEmpty() {
170: return types.isEmpty();
171: }
172:
173: /**
174: * @return Read-only collection of all our types
175: */
176: public Collection<Type> getTypes() {
177: return Collections.unmodifiableCollection(types.values());
178: }
179:
180: /**
181: * @see java.util.Set#remove(java.lang.Object)
182: */
183: public void remove(Type type) {
184: types.remove(type.getFullName());
185: }
186:
187: /**
188: * @see java.util.Set#size()
189: */
190: public int size() {
191: return types.size();
192: }
193:
194: /**
195: * @see java.util.Set#add(java.lang.Object)
196: */
197: private void add(Type type) {
198: types.put(type.getFullName(), type);
199: }
200:
201: /* (non-Javadoc)
202: * @see java.lang.Object#equals(java.lang.Object)
203: */
204: @Override
205: public boolean equals(Object o) {
206: return types.equals(o);
207: }
208:
209: /* (non-Javadoc)
210: * @see java.lang.Object#hashCode()
211: */
212: @Override
213: public int hashCode() {
214: return types.hashCode();
215: }
216:
217: /**
218: * The store of the types we are about to generate from
219: */
220: private Map<String, Type> types = new HashMap<String, Type>();
221:
222: /**
223: * We cache the names of the super classes that we've found
224: */
225: private Set<String> super Classes;
226:
227: /**
228: * The log stream
229: */
230: private static final Logger log = Logger.getLogger(GiLoader.class);
231: }
|