1 /**
2 * Copyright 2006 woelfle
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License
6 *
7 * at http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 package org.tratoo.mdd.kernel.transformation.impl;
16
17 import java.io.File;
18 import java.net.URI;
19 import java.util.ArrayList;
20 import java.util.Collection;
21 import java.util.HashSet;
22 import java.util.List;
23 import java.util.Set;
24
25 import org.tratoo.mdd.kernel.AmbiguousConfigurationException;
26 import org.tratoo.mdd.kernel.Domain;
27 import org.tratoo.mdd.kernel.Repository;
28 import org.tratoo.mdd.kernel.RepositoryFactory;
29 import org.tratoo.mdd.kernel.TransformationChain;
30 import org.tratoo.mdd.kernel.TratooRuntimeException;
31 import org.tratoo.mdd.kernel.emitter.Emitter;
32 import org.tratoo.mdd.kernel.emitter.EmitterEngine;
33 import org.tratoo.mdd.kernel.emitter.EmitterException;
34 import org.tratoo.mdd.kernel.transformation.RunConfiguration;
35 import org.tratoo.mdd.kernel.transformation.Transformation;
36 import org.tratoo.mdd.kernel.transformation.TransformationEngine;
37
38 /**
39 * Default implementation of the {@link TransformationEngine} interface.
40 * @see TransformationEngine
41 * @author woelfle
42 *
43 */
44 public final class TransformationEngineImpl implements TransformationEngine
45 {
46 private final TransformationRepository trafoRepository = new TransformationRepository();
47
48 /**
49 * @see TransformationEngine#run(RunConfiguration)
50 * @param runConfig @see {@link TransformationEngine#run(RunConfiguration)}
51 * @return @see {@link TransformationEngine#run(RunConfiguration)}
52 */
53 public Collection<Object> run(final RunConfiguration runConfig)
54 {
55 final Collection<Object> results = new ArrayList<Object>();
56
57
58 final ExecutionContext executionContext = new ExecutionContext(runConfig.getSourceRepository(), runConfig.getTargetRepository(), runConfig.getTransformation());
59 final TransformationRun executor = new TransformationRun(trafoRepository, executionContext);
60
61 for(Object element : runConfig.getSourceElements())
62 {
63
64 results.addAll(executor.run(element));
65 }
66
67 return results;
68 }
69
70 public boolean execute(TransformationChain chain)
71 {
72 boolean bResult = false;
73
74 if(canExecute(chain))
75 {
76
77 Repository sourceRepository = chain.getSourceRepository();
78 Repository targetRepository = null;
79 if(chain.getTargetDomain() == null)
80 {
81 targetRepository = sourceRepository;
82 }
83 else
84 {
85 TransformationPath path = findPath(chain.getSourceRepository().getDomain(), chain.getTargetDomain()).iterator().next();
86 for(Transformation trafo : path.transformations)
87 {
88 if(trafo.getTargetDomainID().equals(chain.getTargetDomain()) && chain.getTargetRepository() != null)
89 {
90 targetRepository = chain.getTargetRepository();
91 }
92 else
93 {
94 URI id = trafo.getTargetDomainID();
95 targetRepository = createRepository(id);
96 }
97 final ExecutionContext executionContext = new ExecutionContext(sourceRepository, targetRepository, trafo);
98 final TransformationRun executor = new TransformationRun(trafoRepository, executionContext);
99 for(Object element : chain.getSourceElements())
100 {
101 executor.run(element);
102 }
103 }
104 }
105
106
107
108 Class emitterClass = chain.getEmitter();
109 if(emitterClass != null)
110 {
111 for(Emitter emitter : trafoRepository.getEmitters())
112 {
113 if(emitterClass.isAssignableFrom(emitter.getClass()))
114 {
115 Class emitterEngineClass = emitter.getEmitterEngine();
116 try
117 {
118 EmitterEngine engine = (EmitterEngine) emitterEngineClass.newInstance();
119 File rootDir = chain.getRootDir();
120 Collection sourceElements = targetRepository.getAllElements();
121 org.tratoo.mdd.kernel.emitter.RunConfiguration config = new org.tratoo.mdd.kernel.emitter.RunConfiguration(sourceElements, emitterClass, rootDir);
122 engine.registerEmitter(emitter);
123 engine.emit(config);
124 }
125 catch (InstantiationException e)
126 {
127 throw new TratooRuntimeException("Unable to create emitter engine <" + emitterEngineClass + "> for emitter <" + emitter + ">", e);
128 }
129 catch (IllegalAccessException e)
130 {
131 throw new TratooRuntimeException("Unable to create emitter engine <" + emitterEngineClass + "> for emitter <" + emitter + ">", e);
132 }
133 catch (EmitterException e)
134 {
135 throw new TratooRuntimeException("Unable to emit using emitter <"+emitter+">, rootDir <"+chain.getRootDir()+">", e);
136 }
137 catch (AmbiguousConfigurationException e)
138 {
139 throw new TratooRuntimeException("Unable to register emitter.", e);
140 }
141 }
142 }
143 }
144 }
145 else
146 {
147 bResult = false;
148 }
149
150 chain.setStatus(TransformationChain.Status.success);
151
152 return bResult;
153 }
154
155 protected Repository createRepository(URI domainId)
156 {
157 Repository repository = null;
158 return repository;
159 }
160
161 /**
162 * Checks whether the given {@link TransformationChain}
163 * can be executed. Returns <code>true</code> if it can
164 * be executed. Otherwise <code>false</code> is returned.
165 * If the chain cannot be executed then descriptions on
166 * what happened can be found in the
167 * {@link TransformationChain#getWarnings()} collection.
168 * @param chain The {@link TransformationChain} to check.
169 * @return
170 */
171 public boolean canExecute(TransformationChain chain)
172 {
173 boolean canExecute = false;
174
175
176
177
178
179 Domain sourceDomain = chain.getSourceRepository().getDomain();
180 Domain targetDomain = chain.getTargetDomain();
181 if(targetDomain != null && !sourceDomain.equals(targetDomain))
182 {
183 List<TransformationPath> paths = findPath(sourceDomain, targetDomain);
184 if(paths.size() == 0)
185 {
186 String message = "No transformation path found from source domain <" +
187 sourceDomain.getID() + "> to target domain <" +
188 targetDomain.getID() + ">";
189 chain.getWarnings().add(message);
190 }
191 else if(paths.size() > 1)
192 {
193 String message = "Found more than one path from source domain <" +
194 sourceDomain.getID() + "> to target domain <" +
195 targetDomain.getID() + ">.\nFound paths: \n";
196
197 for(TransformationPath path : paths)
198 {
199 message += "(sourceDomain->";
200 for(Transformation trafo : path.transformations)
201 {
202 message += trafo + "->";
203 }
204 message += "targetDomain)\n";
205 }
206 chain.getWarnings().add(message);
207 }
208 }
209 else
210 {
211 canExecute = true;
212 }
213
214 return canExecute;
215 }
216
217 protected List<TransformationPath> findPath(Domain source, Domain target)
218 {
219 return findPath(source.getID(), target.getID(), new HashSet<URI>());
220 }
221
222 private List<TransformationPath> findPath(URI source, URI target, Set<URI> alreadyVisited)
223 {
224 List<TransformationPath> paths = new ArrayList<TransformationPath>();
225 for(Transformation trafo : getTransformations())
226 {
227 if(trafo.getSourceDomainID().equals(source))
228 {
229
230 URI tmpURI = trafo.getTargetDomainID();
231
232
233
234 if(tmpURI.equals(target))
235 {
236
237
238
239 TransformationPath path = new TransformationPath();
240 path.transformations.add(trafo);
241 paths.add(path);
242 }
243
244
245
246 if(!alreadyVisited.contains(tmpURI))
247 {
248
249
250 Set<URI> newVisited = new HashSet<URI>(alreadyVisited);
251 newVisited.add(source);
252 paths = findPath(tmpURI, target, newVisited);
253
254
255
256 for(TransformationPath path : paths)
257 {
258 path.transformations.add(trafo);
259 }
260 }
261 }
262 }
263 return paths;
264 }
265
266 /**
267 * @param transformation @see {@link TransformationEngine#registerTransformation(Transformation)}
268 */
269 public void registerTransformation(final Transformation transformation)
270 {
271 trafoRepository.registerTransformation(transformation);
272 }
273
274 /**
275 * @param transformation @see {@link TransformationEngine#unregisterTransformation(Transformation)}
276 */
277 public void unregisterTransformation(final Transformation transformation)
278 {
279 trafoRepository.unregisterTransformation(transformation);
280 }
281
282 /**
283 * @param domain @see {@link TransformationEngine#registerDomain(Domain)}
284 */
285 public void registerDomain(final Domain domain)
286 {
287 trafoRepository.registerDomain(domain);
288 }
289
290 /**
291 * @param domain @see {@link TransformationEngine#unregisterDomain(Domain)}
292 */
293 public void unregisterDomain(final Domain domain)
294 {
295 trafoRepository.unregisterDomain(domain);
296 }
297
298 /**
299 * @return @see {@link TransformationEngine#getDomains()}
300 */
301 public Set<Domain> getDomains()
302 {
303 return trafoRepository.getDomains();
304 }
305
306 /**
307 * @return @see {@link TransformationEngine#getTransformations()}
308 */
309 public Set<Transformation> getTransformations()
310 {
311 return trafoRepository.getTransformations();
312 }
313
314 public Set<Emitter> getEmitters()
315 {
316 return trafoRepository.getEmitters();
317 }
318
319 public void registerEmitter(Emitter emitter)
320 {
321 trafoRepository.registerEmitter(emitter);
322 }
323
324 public void unregisterEmitter(Emitter emitter)
325 {
326 trafoRepository.unregisterEmitter(emitter);
327 }
328
329 public void registerRepositoryFactory(RepositoryFactory factory)
330 {
331 trafoRepository.registerRepositoryFactory(factory);
332 }
333
334 public void unregisterRepositoryFactory(RepositoryFactory factory)
335 {
336 trafoRepository.unregisterRepositoryFactory(factory);
337 }
338
339 public Set<RepositoryFactory> getRepositoryFactories()
340 {
341 return trafoRepository.getRepositoryFactories();
342 }
343
344 private class TransformationPath
345 {
346 public final List<Transformation> transformations = new ArrayList<Transformation>();
347 }
348 }