View Javadoc
1   package de.fhdw.wtf.generator.database.tasks;
2   
3   import java.util.Vector;
4   
5   import de.fhdw.wtf.common.ast.Attribute;
6   import de.fhdw.wtf.common.ast.AttributeModifier;
7   import de.fhdw.wtf.common.ast.ConstructorOrOperation;
8   import de.fhdw.wtf.common.ast.DatabaseIDSetState;
9   import de.fhdw.wtf.common.ast.Group;
10  import de.fhdw.wtf.common.ast.Model;
11  import de.fhdw.wtf.common.ast.UnqualifiedName;
12  import de.fhdw.wtf.common.ast.type.AtomicType;
13  import de.fhdw.wtf.common.ast.type.BaseType;
14  import de.fhdw.wtf.common.ast.type.ClassType;
15  import de.fhdw.wtf.common.ast.type.CompositeType;
16  import de.fhdw.wtf.common.ast.type.ListType;
17  import de.fhdw.wtf.common.ast.type.MapType;
18  import de.fhdw.wtf.common.ast.type.ProductType;
19  import de.fhdw.wtf.common.ast.type.SumType;
20  import de.fhdw.wtf.common.ast.type.ThrownType;
21  import de.fhdw.wtf.common.ast.type.TypeProxy;
22  import de.fhdw.wtf.common.ast.visitor.CompositeTypeVisitorException;
23  import de.fhdw.wtf.common.ast.visitor.TypeVisitorException;
24  import de.fhdw.wtf.common.exception.generation.NoTypeIdSetException;
25  import de.fhdw.wtf.common.exception.walker.TaskException;
26  import de.fhdw.wtf.common.task.TaskExecutor;
27  import de.fhdw.wtf.common.token.DummyToken;
28  import de.fhdw.wtf.common.token.IdentifierToken;
29  import de.fhdw.wtf.context.model.collections.MutableMap;
30  import de.fhdw.wtf.context.model.collections.PersistentList;
31  import de.fhdw.wtf.context.model.collections.PersistentMap;
32  import de.fhdw.wtf.generator.database.generation.InitialGenerator;
33  import de.fhdw.wtf.persistence.exception.PersistenceException;
34  import de.fhdw.wtf.persistence.facade.TypeManager;
35  import de.fhdw.wtf.persistence.meta.Type;
36  import de.fhdw.wtf.persistence.meta.UnidirectionalAssociation;
37  import de.fhdw.wtf.walker.walker.HelperUtils;
38  import de.fhdw.wtf.walker.walker.SimpleWalkerTask;
39  
40  /**
41   * The {@link AttributeGenerationTask} puts all classes of the Model (AST) into the database. It also adds Type-Ids to
42   * the AST.
43   * 
44   */
45  public class AttributeGenerationTask extends SimpleWalkerTask {
46  	
47  	/**
48  	 * The name of the default attribute 'This'.
49  	 */
50  	private static final String THIS_ATTRIBUTE_NAME = "This";
51  	/**
52  	 * The name of the default attribute '$generatedObjects'.
53  	 */
54  	private static final String GENERATED_OBJECTS_ATTRIBUTE_NAME = "$generatedObjects";
55  	
56  	/**
57  	 * Creates an {@link AttributeGenerationTask}.
58  	 * 
59  	 * @param m
60  	 *            The associated model.
61  	 * @param man
62  	 *            The task manager to use.
63  	 * @param generator
64  	 *            The generator to use.
65  	 */
66  	public AttributeGenerationTask(final Model m, final TaskExecutor man, final InitialGenerator generator) {
67  		super(m, man);
68  		this.generator = generator;
69  		this.persistentList = null;
70  		this.persistentMap = null;
71  	}
72  	
73  	/**
74  	 * The generator to use.
75  	 */
76  	private final InitialGenerator generator;
77  	/**
78  	 * The type used for persistent lists.
79  	 */
80  	private Type persistentList;
81  	/**
82  	 * The type used for persistent maps.
83  	 */
84  	private Type persistentMap;
85  	
86  	@Override
87  	public void handleAttribute(final Attribute a, final ClassType owner) throws TaskException {
88  		try {
89  			a.getAttrType().accept(new AttributeTypeVisitor(a, owner));
90  		} catch (final TaskException e) {
91  			throw e;
92  		} catch (final Exception e) {
93  			throw new TaskException(e);
94  		}
95  		
96  	}
97  	
98  	@Override
99  	public void finalizeTask() {
100 		// Not involved in this task
101 	}
102 	
103 	@Override
104 	public void handleConstructorOrOperation(final ConstructorOrOperation coo, final ClassType owner)
105 			throws TaskException {
106 		// Not involved in this task
107 	}
108 	
109 	@Override
110 	public void handleGroup(final Group g) throws TaskException {
111 		// Not involved in this task
112 	}
113 	
114 	/**
115 	 * Creates the fields 'This' and '$generatedObjects' as attributes of the class for classId in the persistence.
116 	 * 
117 	 * @param c
118 	 *            The class to create the fields for.
119 	 */
120 	@Override
121 	public void handleClass(final ClassType c) throws TaskException {
122 		long classId;
123 		try {
124 			classId = c.getTypeId().getId();
125 			final TypeManager typeManager = this.generator.getClassFacade().getTypeManager();
126 			if (!typeManager.existsType(MutableMap.class.getName())) {
127 				this.generator.createClass(MutableMap.class.getName(), false, false);
128 			}
129 			
130 			this.handleAttribute(
131 					Attribute.create(
132 							GENERATED_OBJECTS_ATTRIBUTE_NAME,
133 							MapType.create(
134 									de.fhdw.wtf.common.token.DummyToken.getInstance(),
135 									BaseType.create(
136 											UnqualifiedName.create(IdentifierToken.create(
137 													"String",
138 													DummyToken.getDummyPosition())),
139 											DummyToken.getInstance(),
140 											DummyToken.getInstance()),
141 									this.getModel().getAnything()),
142 							new Vector<AttributeModifier>(),
143 							DummyToken.getInstance()),
144 					c);
145 			this.handleAttribute(
146 					Attribute.create(THIS_ATTRIBUTE_NAME, c, new Vector<AttributeModifier>(), DummyToken.getInstance()),
147 					c);
148 		} catch (final NoTypeIdSetException | PersistenceException e) {
149 			throw new TaskException(e);
150 		}
151 	}
152 	
153 	@Override
154 	public void beginTask() throws TaskException {
155 		this.persistentList = this.generator.mapNameToType(PersistentList.class.getName());
156 		this.persistentMap = this.generator.mapNameToType(PersistentMap.class.getName());
157 	}
158 	
159 	/**
160 	 * Handles an attribute's type.
161 	 */
162 	private class AttributeTypeVisitor implements TypeVisitorException<Exception> {
163 		
164 		/**
165 		 * The attribute to operate on.
166 		 */
167 		private final Attribute a;
168 		/**
169 		 * The owner type of the attribute.
170 		 */
171 		private final ClassType owner;
172 		
173 		/**
174 		 * Creates an {@link AttributeTypeVisitor}.
175 		 * 
176 		 * @param a
177 		 *            The attribute to operate on.
178 		 * @param owner
179 		 *            The owner type of the attribute.
180 		 */
181 		AttributeTypeVisitor(final Attribute a, final ClassType owner) {
182 			this.a = a;
183 			this.owner = owner;
184 		}
185 		
186 		@Override
187 		public void handle(final AtomicType s) throws Exception {
188 			final UnidirectionalAssociation newAsso =
189 					AttributeGenerationTask.this.generator.createUnidirectionalAssociation(
190 							this.a.getName(),
191 							true,
192 							true,
193 							this.owner.getTypeId().getId(),
194 							s.getTypeId().getId());
195 			this.a.setAttributeId(new DatabaseIDSetState(newAsso.getId()));
196 		}
197 		
198 		@Override
199 		public void handle(final CompositeType c) throws Exception {
200 			c.accept(new CompositeAttributeTypeVisitor(this.a, this.owner));
201 		}
202 		
203 		@Override
204 		public void handle(final TypeProxy s) throws Exception {
205 			HelperUtils.getReferencedType(s).accept(this);
206 		}
207 	}
208 	
209 	/**
210 	 * Handles an attribute's composite type.
211 	 */
212 	private class CompositeAttributeTypeVisitor implements CompositeTypeVisitorException<Exception> {
213 		/**
214 		 * The attribute to operate on.
215 		 */
216 		private final Attribute a;
217 		/**
218 		 * The owner type of the attribute.
219 		 */
220 		private final ClassType owner;
221 		
222 		/**
223 		 * Creates an {@link AttributeTypeVisitor}.
224 		 * 
225 		 * @param a
226 		 *            The attribute to operate on.
227 		 * @param owner
228 		 *            The owner type of the attribute.
229 		 */
230 		CompositeAttributeTypeVisitor(final Attribute a, final ClassType owner) {
231 			this.a = a;
232 			this.owner = owner;
233 		}
234 		
235 		@Override
236 		public void handle(final ListType list) throws Exception {
237 			final UnidirectionalAssociation newAsso =
238 					AttributeGenerationTask.this.generator.createUnidirectionalAssociation(
239 							CompositeAttributeTypeVisitor.this.a.getName(),
240 							true,
241 							true,
242 							CompositeAttributeTypeVisitor.this.owner.getTypeId().getId(),
243 							AttributeGenerationTask.this.persistentList.getId());
244 			CompositeAttributeTypeVisitor.this.a.setAttributeId(new DatabaseIDSetState(newAsso.getId()));
245 		}
246 		
247 		@Override
248 		public void handle(final MapType map) throws Exception {
249 			final UnidirectionalAssociation newAsso =
250 					AttributeGenerationTask.this.generator.createUnidirectionalAssociation(
251 							CompositeAttributeTypeVisitor.this.a.getName(),
252 							true,
253 							true,
254 							CompositeAttributeTypeVisitor.this.owner.getTypeId().getId(),
255 							AttributeGenerationTask.this.persistentMap.getId());
256 			CompositeAttributeTypeVisitor.this.a.setAttributeId(new DatabaseIDSetState(newAsso.getId()));
257 		}
258 		
259 		@Override
260 		public void handle(final ProductType product) throws Exception {
261 			final UnidirectionalAssociation newAsso =
262 					AttributeGenerationTask.this.generator.createUnidirectionalAssociation(
263 							CompositeAttributeTypeVisitor.this.a.getName(),
264 							true,
265 							true,
266 							CompositeAttributeTypeVisitor.this.owner.getTypeId().getId(),
267 							product.getTypeId().getId());
268 			CompositeAttributeTypeVisitor.this.a.setAttributeId(new DatabaseIDSetState(newAsso.getId()));
269 		}
270 		
271 		@Override
272 		public void handle(final SumType sum) throws Exception {
273 			final UnidirectionalAssociation newAsso =
274 					AttributeGenerationTask.this.generator.createUnidirectionalAssociation(
275 							CompositeAttributeTypeVisitor.this.a.getName(),
276 							true,
277 							true,
278 							CompositeAttributeTypeVisitor.this.owner.getTypeId().getId(),
279 							sum.getTypeId().getId());
280 			CompositeAttributeTypeVisitor.this.a.setAttributeId(new DatabaseIDSetState(newAsso.getId()));
281 		}
282 		
283 		@Override
284 		public void handle(final ThrownType thrownType) throws Exception {
285 			throw new TaskException("A type that should be thrown is not possible in an attribute.");
286 		}
287 	}
288 }