View Javadoc
1   package de.fhdw.wtf.common.ast;
2   
3   import java.util.ArrayList;
4   import java.util.Collection;
5   import java.util.Collections;
6   import java.util.HashMap;
7   import java.util.Iterator;
8   import java.util.List;
9   import java.util.Map;
10  
11  import de.fhdw.wtf.common.ast.type.BaseType;
12  import de.fhdw.wtf.common.ast.type.ClassType;
13  import de.fhdw.wtf.common.ast.type.SumType;
14  import de.fhdw.wtf.common.ast.type.Type;
15  import de.fhdw.wtf.common.ast.visitor.GroupElementVisitor;
16  import de.fhdw.wtf.common.constants.referencer.BaseTypeConstants;
17  import de.fhdw.wtf.common.token.DummyToken;
18  import de.fhdw.wtf.common.token.IdentifierToken;
19  import de.fhdw.wtf.common.token.Token;
20  
21  /**
22   * This class represents the root node of the abstract syntax tree. This node only contains groups, but does not need to
23   * for generation.
24   */
25  public final class Model extends SyntaxObject {
26  	
27  	/**
28  	 * BaseType Integer.
29  	 */
30  	private final BaseType integer;
31  	
32  	/**
33  	 * BaseType String.
34  	 */
35  	private final BaseType string;
36  	
37  	/**
38  	 * "BaseType" Anything. The Referencer fill this Sum. Anything could contain itself, the prototype of Anything not.
39  	 */
40  	private final SumType anything;
41  	
42  	/**
43  	 * After analyzing the inheritance trees of this model. The responsible classes (regarding constructor calls) and
44  	 * the super types which shall be instantiated by those classes will be stored here. This result is stored here as
45  	 * it is needed by multiple task which's performances are based on it.
46  	 */
47  	private final Map<Type, List<Type>> constructorCallDependencies;
48  	
49  	/**
50  	 * generated.
51  	 */
52  	private static final long serialVersionUID = 5098229960027033738L;
53  	
54  	/**
55  	 * Constant for Line-Break.
56  	 */
57  	private static final String BREAK = " \n";
58  	
59  	/**
60  	 * The groups of this model.
61  	 */
62  	private final Collection<Group> groups;
63  	
64  	/**
65  	 * Private Constructor of {@link Model}.
66  	 * 
67  	 * @param group
68  	 *            The groups of the model
69  	 * @param firstToken
70  	 *            firstToken
71  	 * @param lastToken
72  	 *            lastToken
73  	 */
74  	private Model(final Collection<Group> group, final Token firstToken, final Token lastToken) {
75  		super(firstToken, lastToken);
76  		this.groups = group;
77  		this.anything = SumType.create(DummyToken.getInstance(), DummyToken.getInstance());
78  		this.integer =
79  				BaseType.create(
80  						UnqualifiedName.create(IdentifierToken.create(
81  								BaseTypeConstants.INTEGER_CONSTANT,
82  								DummyToken.getDummyPosition())),
83  						DummyToken.getInstance(),
84  						DummyToken.getInstance());
85  		this.string =
86  				BaseType.create(
87  						UnqualifiedName.create(IdentifierToken.create(
88  								BaseTypeConstants.STRING_CONSTANT,
89  								DummyToken.getDummyPosition())),
90  						DummyToken.getInstance(),
91  						DummyToken.getInstance());
92  		this.constructorCallDependencies = new HashMap<>();
93  	}
94  	
95  	/**
96  	 * Creates a {@link Model}-Object.
97  	 * 
98  	 * @param firstToken
99  	 *            firstToken
100 	 * @param lastToken
101 	 *            lastToken
102 	 * @return The Model-Object.
103 	 */
104 	public static Model create(final Token firstToken, final Token lastToken) {
105 		return new Model(new ArrayList<Group>(), firstToken, lastToken);
106 	}
107 	
108 	/**
109 	 * Creates a {@link Model}-Object.
110 	 * 
111 	 * @param firstToken
112 	 *            firstToken
113 	 * @return The Model-Object.
114 	 */
115 	public static Model create(final Token firstToken) {
116 		return new Model(new ArrayList<Group>(), firstToken, null);
117 	}
118 	
119 	/**
120 	 * Adds a Group to contained collection of groups.
121 	 * 
122 	 * @param group
123 	 *            : Group.
124 	 */
125 	public void addGroup(final Group group) {
126 		this.groups.add(group);
127 	}
128 	
129 	/**
130 	 * Returns the local list. The list can't be modified with the operations for Collections.
131 	 * 
132 	 * @return the stream
133 	 */
134 	public Collection<Group> getGroups() {
135 		return Collections.unmodifiableCollection(this.groups);
136 	}
137 	
138 	@Override
139 	public boolean equals(final Object o) {
140 		if (o instanceof Model) {
141 			boolean result = true;
142 			final Model other = (Model) o;
143 			result = result && this.getGroups().size() == other.getGroups().size();
144 			if (result) {
145 				final Group[] thisArray = this.getGroups().toArray(new Group[this.getGroups().size()]);
146 				final Group[] otherArray = other.getGroups().toArray(new Group[other.getGroups().size()]);
147 				for (int i = 0; i < this.getGroups().size(); i++) {
148 					result = result && thisArray[i].equals(otherArray[i]);
149 				}
150 				return result;
151 			}
152 		}
153 		return false;
154 	}
155 	
156 	@Override
157 	public int hashCode() {
158 		int result = 0;
159 		for (final Group group : this.getGroups()) {
160 			result ^= group.hashCode();
161 		}
162 		return result;
163 	}
164 	
165 	@Override
166 	public String toString() {
167 		final StringBuilder result = new StringBuilder();
168 		result.append(de.fhdw.wtf.common.constants.parser.AstDescriptionConstants.MODEL_TO_STRING).append(BREAK);
169 		final Iterator<Group> i = this.getGroups().iterator();
170 		while (i.hasNext()) {
171 			final Group current = i.next();
172 			result.append(current).append(BREAK);
173 		}
174 		return result.toString();
175 	}
176 	
177 	/**
178 	 * Calculates lists of all classes and groups.
179 	 * 
180 	 * @return list of classes, list of groups
181 	 */
182 	public Tuple<Collection<ClassType>, Collection<Group>> calcAllGroupsAndClasses() {
183 		final Collection<Group> allGroups = new ArrayList<>();
184 		final Collection<ClassType> classes = new ArrayList<>();
185 		for (final Group g : this.getGroups()) {
186 			allGroups.add(g);
187 			this.processGroupElementsForGroupsAndClasses(g, allGroups, classes);
188 		}
189 		return new Tuple<>(classes, allGroups);
190 		
191 	}
192 	
193 	/**
194 	 * Fill the list of classes and groups with all classes and groups of the Group g.
195 	 * 
196 	 * @param g
197 	 *            Group where the method searched
198 	 * @param allGroups
199 	 *            list, which fill this method with all groups of g
200 	 * @param classes
201 	 *            list, which fill this method with all classes of g
202 	 */
203 	void processGroupElementsForGroupsAndClasses(final Group g,
204 			final Collection<Group> allGroups,
205 			final Collection<ClassType> classes) {
206 		final GroupElementVisitor v = new GroupElementVisitor() {
207 			@Override
208 			public void handle(final Group g2) {
209 				allGroups.add(g2);
210 				Model.this.processGroupElementsForGroupsAndClasses(g2, allGroups, classes);
211 			}
212 			
213 			@Override
214 			public void handle(final ClassType clss) {
215 				classes.add(clss);
216 			}
217 		};
218 		for (final GroupElement element : g.getGroupElements()) {
219 			element.accept(v);
220 		}
221 	}
222 	
223 	/**
224 	 * Return the Basetype Integer.
225 	 * 
226 	 * @return Integer
227 	 */
228 	public BaseType getInteger() {
229 		return this.integer;
230 	}
231 	
232 	/**
233 	 * Return the Basetype String.
234 	 * 
235 	 * @return String
236 	 */
237 	public BaseType getString() {
238 		return this.string;
239 	}
240 	
241 	/**
242 	 * Return the "BaseType" Anything.
243 	 * 
244 	 * @return Anything
245 	 */
246 	public SumType getAnything() {
247 		return this.anything;
248 	}
249 	
250 	/**
251 	 * Adds the pair (responsibleType, supertypesToCall) to the constructorCallDependencies mapping.
252 	 * 
253 	 * @param responsibleType
254 	 *            the key.
255 	 * @param supertypesToCall
256 	 *            the value.
257 	 */
258 	public void putConstructorCallDependency(final Type responsibleType, final List<Type> supertypesToCall) {
259 		this.constructorCallDependencies.put(responsibleType, supertypesToCall);
260 	}
261 	
262 	/**
263 	 * Returns an unmodifiable version of the constructorCallDependencies map.
264 	 * 
265 	 * @return the constructorCallDependencies.
266 	 */
267 	public Map<Type, List<Type>> getConstructorCallDependencies() {
268 		return Collections.unmodifiableMap(this.constructorCallDependencies);
269 	}
270 	
271 }