1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 package org.objectweb.fractal.cecilia.primitive.thinkMC.source;
25
26 import static org.objectweb.fractal.adl.NodeUtil.castNodeError;
27 import static org.objectweb.fractal.api.type.TypeFactory.OPTIONAL;
28 import static org.objectweb.fractal.cecilia.adl.SourceCodeHelper.appendSortedSourceCodes;
29 import static org.objectweb.fractal.cecilia.adl.implementations.ImplementationDecorationUtil.getCode;
30
31 import java.io.File;
32 import java.io.IOException;
33 import java.util.ArrayList;
34 import java.util.Collection;
35 import java.util.HashMap;
36 import java.util.HashSet;
37 import java.util.List;
38 import java.util.Map;
39 import java.util.Set;
40
41 import org.objectweb.fractal.adl.ADLException;
42 import org.objectweb.fractal.adl.CompilerError;
43 import org.objectweb.fractal.adl.ComponentVisitor;
44 import org.objectweb.fractal.adl.Node;
45 import org.objectweb.fractal.adl.components.ComponentContainer;
46 import org.objectweb.fractal.adl.error.GenericErrors;
47 import org.objectweb.fractal.adl.implementations.Implementation;
48 import org.objectweb.fractal.adl.implementations.ImplementationContainer;
49 import org.objectweb.fractal.api.Component;
50 import org.objectweb.fractal.cecilia.adl.SourceCodeProvider;
51 import org.objectweb.fractal.cecilia.adl.TypeNameProvider;
52 import org.objectweb.fractal.cecilia.adl.directives.Include;
53 import org.objectweb.fractal.cecilia.adl.directives.IncludeContainer;
54 import org.objectweb.fractal.cecilia.adl.file.CodeWriter;
55 import org.objectweb.fractal.cecilia.adl.file.SourceFile;
56 import org.objectweb.fractal.cecilia.adl.file.SourceFileProvider;
57 import org.objectweb.fractal.cecilia.adl.file.SourceFileWriter;
58 import org.objectweb.fractal.task.core.AbstractTaskFactoryUser;
59 import org.objectweb.fractal.task.core.Executable;
60 import org.objectweb.fractal.task.core.TaskException;
61 import org.objectweb.fractal.task.core.TaskFactory;
62 import org.objectweb.fractal.task.core.primitive.annotations.ClientInterface;
63 import org.objectweb.fractal.task.core.primitive.annotations.ServerInterface;
64 import org.objectweb.fractal.task.core.primitive.annotations.ServerInterfaces;
65 import org.objectweb.fractal.task.core.primitive.annotations.TaskParameters;
66
67
68
69
70
71 public class SourceFileVisitor extends AbstractTaskFactoryUser
72 implements
73 ComponentVisitor {
74
75
76
77
78
79
80
81
82
83 public Component visit(final List<Node> path,
84 final ComponentContainer container, final Map<Object, Object> context)
85 throws ADLException, TaskException {
86 final Implementation impl = castNodeError(container,
87 ImplementationContainer.class).getImplementation();
88 if (impl == null) {
89 throw new CompilerError(GenericErrors.INTERNAL_ERROR,
90 "This visitor is only applicable for primitive component.");
91 }
92 final File adlBuildDirectory = (File) context.get("adlBuildDirectory");
93 final Component implTask = createSourceFileTask(container, impl,
94 adlBuildDirectory);
95 if (impl instanceof IncludeContainer
96 && ((IncludeContainer) impl).getIncludes().length != 0) {
97 final Include[] includes = ((IncludeContainer) impl).getIncludes();
98
99 final Collection<Component> tasks = new ArrayList<Component>(
100 includes.length + 1);
101 tasks.add(implTask);
102
103 final Set<String> moduleNames = new HashSet<String>();
104 for (final Include include : includes) {
105
106 if (!((SourceFile) getCode((Node) include)).isAssemblyFile()) {
107
108 String moduleName = include.getFile();
109
110
111 final int i = moduleName.lastIndexOf('.');
112 if (i != -1) {
113 moduleName = moduleName.substring(i);
114 }
115
116 if (!moduleNames.add(moduleName)) {
117
118
119 int suffix = 1;
120
121 while (!moduleNames.add(moduleName + suffix))
122 suffix++;
123
124 moduleName = moduleName + suffix;
125 }
126
127 tasks.add(createModuleSourceFileTask(container, include, moduleName,
128 adlBuildDirectory));
129 }
130 }
131 return taskFactoryItf.newCompositeTask(tasks, TaskFactory.EXPORT_ALL,
132 null);
133 } else {
134 return implTask;
135 }
136 }
137
138
139
140
141
142 protected Component createModuleSourceFileTask(
143 final ComponentContainer container, final Include include,
144 final String moduleName, final File adlBuildDirectory)
145 throws TaskException {
146 return taskFactoryItf.newPrimitiveTask(new ModuleSourceFileTask(
147 adlBuildDirectory, moduleName), container, include);
148 }
149
150 protected Component createSourceFileTask(final ComponentContainer container,
151 final Implementation impl, final File adlBuildDirectory)
152 throws TaskException {
153 return taskFactoryItf.newPrimitiveTask(
154 new SourceFileTask(adlBuildDirectory), container);
155 }
156
157
158
159
160
161 protected abstract static class AbstractSourceFileTask
162 implements
163 Executable,
164 SourceFileProvider {
165 protected final File adlBuildDirectory;
166
167
168 protected SourceFile sourceFile;
169
170
171
172
173
174
175 @ClientInterface(name = "type-name-provider", record = "role:typeNameProvider, id:%", parameters = "componentNode")
176 public TypeNameProvider typeNameProviderItf;
177
178
179 @ClientInterface(name = "component-definition-provider", record = "role:componentDefinition, id:%", parameters = "componentNode")
180 public SourceCodeProvider definitionProviderItf;
181
182
183 @ClientInterface(name = "implementation-provider", record = "role:implementation, id:%", parameters = "componentNode")
184 public SourceCodeProvider implementationProviderItf;
185
186
187
188
189
190
191
192
193
194 public AbstractSourceFileTask(final File adlBuildDirectory) {
195 this.adlBuildDirectory = adlBuildDirectory;
196 }
197
198
199
200
201
202 protected abstract void prepareSourceCode(CodeWriter cw);
203
204 protected abstract String getFileName();
205
206 protected abstract String getSignature();
207
208
209
210
211
212 public void execute() throws Exception {
213 final String fileName = getFileName();
214 final File outputFile = new File(adlBuildDirectory, fileName);
215
216 final CodeWriter cw = new CodeWriter();
217 cw.appendln("// THIS FILE HAS BEEN GENERATED BY THE CECILIA ADL "
218 + "COMPILER.");
219 cw.appendln("// DO NOT EDIT").endl();
220 prepareSourceCode(cw);
221
222 try {
223 SourceFileWriter.writeToFile(outputFile, cw.toString());
224 } catch (final IOException e) {
225 throw new ADLException(GenericErrors.INTERNAL_ERROR, e,
226 "An error occurs while writing to file '"
227 + outputFile.getAbsolutePath() + "'");
228 }
229
230 sourceFile = new SourceFile(getSignature(), outputFile);
231 }
232
233
234
235
236
237 public SourceFile getSourceFile() {
238 return sourceFile;
239 }
240 }
241
242
243
244
245
246
247 @TaskParameters("componentNode")
248 @ServerInterfaces(@ServerInterface(name = "component-definition-file-provider", signature = SourceFileProvider.class, record = "role:componentDefinitionFile, id:%", parameters = "componentNode"))
249 public static class SourceFileTask extends AbstractSourceFileTask {
250
251
252 public static final String FILE_NAME_SUFFIX = ".adl.c";
253
254
255
256
257
258
259 @ClientInterface(name = "vft-instantiation-provider", contingency = OPTIONAL, record = "role:interfaceVFTInstantiation, id:%", parameters = "componentNode")
260 public SourceCodeProvider vftInstantiationProviderItf;
261
262
263
264
265
266 @ClientInterface(name = "component-instantiation-aggregator", signature = SourceCodeProvider.class, record = "role:componentInstantiationAggregator, id:%", parameters = "componentNode")
267 public final Map<String, SourceCodeProvider> instantiationProviderItf = new HashMap<String, SourceCodeProvider>();
268
269
270
271
272
273
274 @ClientInterface(name = "additional-implementation-source-code", signature = SourceCodeProvider.class, record = "role:additionalImplementationSourceCode, id:%", parameters = "componentNode")
275 public final Map<String, SourceCodeProvider> additionalImplementationSourceCodeProviderItf = new HashMap<String, SourceCodeProvider>();
276
277
278
279
280
281
282
283
284
285 public SourceFileTask(final File adlBuildDirectory) {
286 super(adlBuildDirectory);
287 }
288
289
290
291
292
293 @Override
294 protected String getFileName() {
295 return typeNameProviderItf.getCTypeName() + FILE_NAME_SUFFIX;
296 }
297
298 @Override
299 protected String getSignature() {
300 return typeNameProviderItf.getTypeName();
301 }
302
303 @Override
304 protected void prepareSourceCode(final CodeWriter cw) {
305
306 cw.append(definitionProviderItf.getSourceCode()).endl();
307
308
309 cw.appendln(implementationProviderItf.getSourceCode()).endl();
310
311
312 for (final SourceCodeProvider codeProvider : additionalImplementationSourceCodeProviderItf
313 .values()) {
314 cw.appendln(codeProvider.getSourceCode());
315 }
316
317
318 if (vftInstantiationProviderItf != null)
319 cw.appendln(vftInstantiationProviderItf.getSourceCode());
320
321
322
323
324 appendSortedSourceCodes(cw, instantiationProviderItf.values());
325 }
326 }
327
328
329
330
331
332 @TaskParameters({"componentNode", "moduleNode"})
333 @ServerInterfaces(@ServerInterface(name = "component-module-file-provider", signature = SourceFileProvider.class, record = "role:componentModuleFile, id:%, module:%", parameters = {
334 "componentNode", "moduleNode"}))
335 public static class ModuleSourceFileTask extends AbstractSourceFileTask {
336
337
338 public static final String FILE_NAME_SUFFIX = ".adl.c";
339
340 protected final String moduleName;
341
342
343
344
345
346
347 @ClientInterface(name = "module-implementation-provider", record = "role:implementation, id:%, module:%", parameters = {
348 "componentNode", "moduleNode"})
349 public SourceCodeProvider moduleImplementationProviderItf;
350
351
352
353
354
355
356
357
358
359
360
361 public ModuleSourceFileTask(final File adlBuildDirectory,
362 final String moduleName) {
363 super(adlBuildDirectory);
364 this.moduleName = moduleName;
365 }
366
367
368
369
370
371 @Override
372 protected String getFileName() {
373 return typeNameProviderItf.getCTypeName() + '_' + moduleName
374 + FILE_NAME_SUFFIX;
375 }
376
377 @Override
378 protected String getSignature() {
379 return typeNameProviderItf.getTypeName() + '.' + moduleName;
380 }
381
382 @Override
383 protected void prepareSourceCode(final CodeWriter cw) {
384
385 cw.append(definitionProviderItf.getSourceCode()).endl();
386
387
388
389 cw.appendln(implementationProviderItf.getSourceCode()).endl();
390
391
392 cw.appendln(moduleImplementationProviderItf.getSourceCode());
393 }
394 }
395 }