View Javadoc
1   package de.fhdw.wtf.facade;
2   
3   import java.io.IOException;
4   import java.util.Collection;
5   import java.util.concurrent.ExecutionException;
6   
7   import de.fhdw.wtf.common.ast.Model;
8   import de.fhdw.wtf.common.exception.editor.GeneralCheckException;
9   import de.fhdw.wtf.common.exception.editor.MultipleCheckExceptions;
10  import de.fhdw.wtf.common.exception.walker.CyclicDependencyException;
11  import de.fhdw.wtf.common.exception.walker.CyclicPartDefinitionException;
12  import de.fhdw.wtf.common.task.DependencyTask;
13  import de.fhdw.wtf.common.task.GroupDependencyTask;
14  import de.fhdw.wtf.common.task.TaskExecutorFixed;
15  import de.fhdw.wtf.common.task.result.ExceptionalTaskResult;
16  import de.fhdw.wtf.common.task.result.OKTaskResult;
17  import de.fhdw.wtf.common.task.result.TaskResult;
18  import de.fhdw.wtf.common.task.result.visitor.TaskResultVisitor;
19  import de.fhdw.wtf.generator.database.generation.InitialGenerator;
20  import de.fhdw.wtf.generator.database.tasks.AttributeGenerationTask;
21  import de.fhdw.wtf.generator.database.tasks.SpecializationGenerationTask;
22  import de.fhdw.wtf.generator.database.tasks.TypeGenerationTask;
23  import de.fhdw.wtf.generator.java.generatorModel.GeneratorModel;
24  import de.fhdw.wtf.generator.transformer.clipper.ClipToFileTask;
25  import de.fhdw.wtf.generator.transformer.clipper.ClipperConfiguration;
26  import de.fhdw.wtf.generator.transformer.clipper.LinkToGenClassTask;
27  import de.fhdw.wtf.generator.transformer.transformers.classTransformer.AppStarterTransformer;
28  import de.fhdw.wtf.generator.transformer.transformers.classTransformer.ConstructorSymmetricAttribute;
29  import de.fhdw.wtf.generator.transformer.transformers.classTransformer.DelegationTransformer;
30  import de.fhdw.wtf.generator.transformer.transformers.classTransformer.FactoryTransformer;
31  import de.fhdw.wtf.generator.transformer.transformers.classTransformer.InheritanceTransformer;
32  import de.fhdw.wtf.generator.transformer.transformers.classTransformer.OperationAttributeTransformer;
33  import de.fhdw.wtf.generator.transformer.transformers.classTransformer.SuperGenerationTransformer;
34  import de.fhdw.wtf.generator.transformer.transformers.classTransformer.TypeTransformer;
35  import de.fhdw.wtf.generator.transformer.visitorTransformation.VisitorTypeTransformer;
36  import de.fhdw.wtf.generator.writer.tasks.FileWriterTask;
37  import de.fhdw.wtf.persistence.exception.PersistenceException;
38  import de.fhdw.wtf.persistence.facade.OracleDataBasePreparator;
39  import de.fhdw.wtf.persistence.facade.OracleDatabaseManager;
40  import de.fhdw.wtf.persistence.facade.OracleObjectFacadeImplementation;
41  import de.fhdw.wtf.persistence.utils.PropertiesReaderFile;
42  import de.fhdw.wtf.tooling.SyntaxCheckAbstract;
43  
44  /**
45   * This class provides operations for generating Java-sources and generating the needed database for an AST-Model.
46   */
47  public final class ModelManager extends SyntaxCheckAbstract {
48  	
49  	/**
50  	 * The one existing instance of ModelManager.
51  	 */
52  	private static ModelManager instance;
53  	
54  	/**
55  	 * Provides the one Instance for ModelManager.
56  	 *
57  	 * @return ModelManager
58  	 */
59  	public static synchronized ModelManager getInstance() {
60  		if (instance == null) {
61  			instance = new ModelManager();
62  		}
63  		return instance;
64  	}
65  	
66  	/**
67  	 * Constructs a ModelManager.
68  	 */
69  	private ModelManager() {
70  		
71  	}
72  	
73  	/**
74  	 * Generates Java and aspectJ files to the given directory.
75  	 *
76  	 * @param referencedModel
77  	 *            model must be referenced successfully before
78  	 * @param modelRootDirectory
79  	 *            Root directory to generate Java sources in.
80  	 * @throws MultipleCheckExceptions
81  	 *             An exception that represents many exceptions that occured while generating.
82  	 * @return The produced GeneratorModel.
83  	 */
84  	public GeneratorModel generateJava(final Model referencedModel, final String modelRootDirectory)
85  			throws MultipleCheckExceptions {
86  		final ClipperConfiguration configurationClip =
87  				new ClipperConfiguration(modelRootDirectory + "clipper/generated/model", modelRootDirectory
88  						+ "/generated/model");
89  		final ClipperConfiguration configurationLink =
90  				new ClipperConfiguration(modelRootDirectory + "clipper/", modelRootDirectory);
91  		return this.generateJava(referencedModel, modelRootDirectory, configurationClip, configurationLink, true);
92  	}
93  	
94  	/**
95  	 * Generates Java and aspectJ files to the given directory.
96  	 *
97  	 * @param referencedModel
98  	 *            model must be referenced successfully before
99  	 * @param modelRootDirectory
100 	 *            Root directory to generate Java sources in. If null, the file writer task is not started.
101 	 * @param configurationClip
102 	 *            The configuration for the ClipToFileTask.
103 	 * @param configurationLink
104 	 *            The configuration for the LinkToGenClassTask.
105 	 * @param runVisitorAndFactoryGenerators
106 	 *            If true, the visitor and factory generators are run.
107 	 * @throws MultipleCheckExceptions
108 	 *             An exception that represents many exceptions that occured while generating.
109 	 * @return The produced GeneratorModel.
110 	 */
111 	public GeneratorModel generateJava(final Model referencedModel,
112 			final String modelRootDirectory,
113 			final ClipperConfiguration configurationClip,
114 			final ClipperConfiguration configurationLink,
115 			final boolean runVisitorAndFactoryGenerators) throws MultipleCheckExceptions {
116 		final MultipleCheckExceptions results = new MultipleCheckExceptions();
117 		final TaskExecutorFixed exec = TaskExecutorFixed.create();
118 		final GeneratorModel javaGeneratorModel = GeneratorModel.create();
119 		
120 		final GroupDependencyTask transformers = new GroupDependencyTask(exec);
121 		/* WalkerTasks and WalkerTasks for types */
122 		try {
123 			final TypeTransformer typeTransformer = new TypeTransformer(referencedModel, exec, javaGeneratorModel);
124 			
125 			final OperationAttributeTransformer operationAttributeTransformer =
126 					OperationAttributeTransformer.create(referencedModel, exec, javaGeneratorModel, typeTransformer);
127 			
128 			final DelegationTransformer delegationTransformer =
129 					new DelegationTransformer(referencedModel, exec, javaGeneratorModel);
130 			delegationTransformer.addDependency(operationAttributeTransformer);
131 			
132 			final SuperGenerationTransformer constructorCallGenerationTask =
133 					new SuperGenerationTransformer(referencedModel, exec, javaGeneratorModel);
134 			
135 			constructorCallGenerationTask.addDependency(delegationTransformer);
136 			
137 			final InheritanceTransformer inheritanceTransformer =
138 					new InheritanceTransformer(referencedModel, exec, javaGeneratorModel, operationAttributeTransformer);
139 			
140 			final ConstructorSymmetricAttribute constructorSymmetricAttribute =
141 					new ConstructorSymmetricAttribute(referencedModel, exec, javaGeneratorModel);
142 			
143 			constructorSymmetricAttribute.addDependency(constructorCallGenerationTask);
144 			constructorSymmetricAttribute.addDependency(operationAttributeTransformer);
145 			
146 			transformers.addMembers(
147 					typeTransformer,
148 					operationAttributeTransformer,
149 					constructorCallGenerationTask,
150 					inheritanceTransformer,
151 					delegationTransformer,
152 					constructorSymmetricAttribute);
153 			
154 			if (runVisitorAndFactoryGenerators) {
155 				final VisitorTypeTransformer typeVisitor =
156 						VisitorTypeTransformer
157 								.create(referencedModel, exec, javaGeneratorModel, inheritanceTransformer);
158 				delegationTransformer.addDependency(typeVisitor);
159 				final DependencyTask appStarterTransformer =
160 						new AppStarterTransformer(exec, javaGeneratorModel, inheritanceTransformer);
161 				appStarterTransformer.addDependency(typeVisitor);
162 				final DependencyTask factoryTransformer =
163 						new FactoryTransformer(exec, javaGeneratorModel, inheritanceTransformer);
164 				factoryTransformer.addDependency(appStarterTransformer);
165 				
166 				// TODO der FinderTransformer muss eventuell eingebunden werden (und
167 				// Dependencies hinzugefügt werden)
168 				transformers.addMembers(typeVisitor, appStarterTransformer, factoryTransformer);
169 				
170 			}
171 		} catch (final CyclicPartDefinitionException | CyclicDependencyException e) {
172 			throw new SystemException(e);
173 		}
174 		
175 		/* Clipper */
176 		final GroupDependencyTask clipper = new GroupDependencyTask(exec);
177 		final ClipToFileTask clipperImport = new ClipToFileTask(exec, configurationClip);
178 		final LinkToGenClassTask methodInsertion =
179 				new LinkToGenClassTask(exec, javaGeneratorModel, configurationLink, clipperImport);
180 		try {
181 			clipper.addMembers(clipperImport, methodInsertion);
182 			clipper.addDependency(transformers);
183 		} catch (final CyclicPartDefinitionException | CyclicDependencyException e) {
184 			throw new SystemException(e);
185 		}
186 		
187 		if (modelRootDirectory != null) {
188 			new FileWriterTask(exec, javaGeneratorModel, modelRootDirectory, clipper);
189 		}
190 		
191 		try {
192 			exec.startAllKnownTasks();
193 			final Collection<TaskResult> resultTasks = exec.getResultsAndShutdown();
194 			this.addsExceptionalTasksToMultipleExceptions(results, resultTasks);
195 			
196 		} catch (final InterruptedException | ExecutionException e) {
197 			throw new SystemException(e);
198 		}
199 		
200 		if (!results.isEmpty()) {
201 			throw results;
202 		}
203 		
204 		return javaGeneratorModel;
205 	}
206 	
207 	/**
208 	 * Generates initial persistence and deletes all existing data!
209 	 *
210 	 * @param model
211 	 *            The AST-Model to generate persistence for.
212 	 * @param genModel
213 	 *            The Generator model.
214 	 * @param dbPropertiesPath
215 	 *            The path to connection-constants for accessing the database.
216 	 * @throws MultipleCheckExceptions
217 	 *             An exception that represents many exceptions that occured while generating.
218 	 */
219 	public void generatePersistence(final Model model, final GeneratorModel genModel, final String dbPropertiesPath)
220 			throws MultipleCheckExceptions {
221 		final MultipleCheckExceptions results = new MultipleCheckExceptions();
222 		try {
223 			this.prepareDatabase(dbPropertiesPath);
224 			
225 			final InitialGenerator generator = new InitialGenerator();
226 			final TaskExecutorFixed taskManager = TaskExecutorFixed.create();
227 			
228 			final TypeGenerationTask typeGenerationTask =
229 					new TypeGenerationTask(model, genModel, taskManager, generator);
230 			final AttributeGenerationTask attributeGenerationTask =
231 					new AttributeGenerationTask(model, taskManager, generator);
232 			final SpecializationGenerationTask specializationGenerationTask =
233 					new SpecializationGenerationTask(model, taskManager, generator);
234 			
235 			attributeGenerationTask.addDependency(typeGenerationTask);
236 			specializationGenerationTask.addDependency(typeGenerationTask);
237 			
238 			taskManager.startAllKnownTasks();
239 			
240 			final Collection<TaskResult> resultTasks = taskManager.getResultsAndShutdown();
241 			this.addsExceptionalTasksToMultipleExceptions(results, resultTasks);
242 		} catch (final PersistenceException e) {
243 			results.add(new GeneralCheckException(e));
244 		} catch (final InterruptedException | ExecutionException | CyclicDependencyException | IOException e) {
245 			throw new SystemException(e);
246 		}
247 		if (!results.isEmpty()) {
248 			throw results;
249 		}
250 		
251 	}
252 	
253 	/**
254 	 * Inspects TaskResults and adds corresponding CheckExceptions to list.
255 	 *
256 	 * @param list
257 	 *            A list of exceptions encapsulated as MultipleCheckException.
258 	 * @param taskresults
259 	 *            A collection of the results of executed tasks.
260 	 */
261 	private void addsExceptionalTasksToMultipleExceptions(final MultipleCheckExceptions list,
262 			final Collection<TaskResult> taskresults) {
263 		for (final TaskResult taskResult : taskresults) {
264 			taskResult.accept(new TaskResultVisitor() {
265 				
266 				@Override
267 				public void handleOkTaskResult(final OKTaskResult result) {
268 					// nothing to do
269 				}
270 				
271 				@Override
272 				public void handleExceptionalTaskResult(final ExceptionalTaskResult result) {
273 					// TODO get Markable Exceptions
274 					list.add(new GeneralCheckException(result.getError()));
275 				}
276 			});
277 		}
278 	}
279 	
280 	/**
281 	 * Trys to prepare the database by generating the meta-structure and procedures.
282 	 *
283 	 * @param propertiesPath
284 	 *            Path for a file with connection-constants.
285 	 * @throws IOException
286 	 *             Thrown when the file with connection-constants could not be accessed.
287 	 * @throws PersistenceException
288 	 *             Thrown when some error in the persistence layer occured.
289 	 */
290 	private void prepareDatabase(final String propertiesPath) throws IOException, PersistenceException {
291 		
292 		final OracleDatabaseManager oracleDatabaseManager = OracleDatabaseManager.getInstance();
293 		final PropertiesReaderFile prop = new PropertiesReaderFile();
294 		prop.initialize(propertiesPath);
295 		oracleDatabaseManager.setConnectionConstantsFromFile(prop);
296 		oracleDatabaseManager.connect();
297 		
298 		final OracleDataBasePreparator preparator = new OracleDataBasePreparator();
299 		if (!preparator.isTableStructureValid()) {
300 			preparator.dropWholeSchema();
301 			preparator.createWholeSchema();
302 		}
303 		if (!preparator.areProceduresCreated()) {
304 			preparator.createProcedures();
305 		}
306 		new OracleObjectFacadeImplementation(oracleDatabaseManager, null).clear();
307 		oracleDatabaseManager.getClassFacade().clear();
308 	}
309 }