View Javadoc

1   /***
2    * Cecilia ADL Compiler
3    * Copyright (C) 2006-2007 STMicroelectronics
4    *
5    * This library is free software; you can redistribute it and/or
6    * modify it under the terms of the GNU Lesser General Public
7    * License as published by the Free Software Foundation; either
8    * version 2 of the License, or (at your option) any later version.
9    *
10   * This library is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13   * Lesser General Public License for more details.
14   *
15   * You should have received a copy of the GNU Lesser General Public
16   * License along with this library; if not, write to the Free Software
17   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18   *
19   * Contact: fractal@objectweb.org
20   *
21   * Author:Matthieu Leclercq
22   */
23  
24  package org.objectweb.fractal.cecilia.adl.controllers;
25  
26  import static org.objectweb.fractal.adl.NodeUtil.castNodeError;
27  
28  import java.io.File;
29  import java.util.ArrayList;
30  import java.util.Collection;
31  import java.util.HashMap;
32  import java.util.HashSet;
33  import java.util.List;
34  import java.util.Map;
35  import java.util.Set;
36  import java.util.concurrent.ExecutorService;
37  import java.util.concurrent.Future;
38  
39  import org.objectweb.fractal.adl.ADLException;
40  import org.objectweb.fractal.adl.Definition;
41  import org.objectweb.fractal.adl.DefinitionVisitor;
42  import org.objectweb.fractal.adl.Node;
43  import org.objectweb.fractal.adl.components.ComponentContainer;
44  import org.objectweb.fractal.adl.interfaces.Interface;
45  import org.objectweb.fractal.adl.interfaces.InterfaceContainer;
46  import org.objectweb.fractal.adl.types.TypeInterface;
47  import org.objectweb.fractal.api.Component;
48  import org.objectweb.fractal.api.NoSuchInterfaceException;
49  import org.objectweb.fractal.api.control.IllegalBindingException;
50  import org.objectweb.fractal.api.control.IllegalLifeCycleException;
51  import org.objectweb.fractal.cecilia.adl.SourceCodeProvider;
52  import org.objectweb.fractal.cecilia.adl.compiler.CompilationTaskFactory;
53  import org.objectweb.fractal.cecilia.adl.file.FutureFileCollectionProvider;
54  import org.objectweb.fractal.cecilia.adl.file.FutureFileProvider;
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.idl.ast.IDLDefinition;
58  import org.objectweb.fractal.cecilia.adl.idl.ast.IDLDefinitionContainer;
59  import org.objectweb.fractal.cecilia.adl.implementations.ImplementationDecorationUtil;
60  import org.objectweb.fractal.task.core.AbstractTaskFactoryUser;
61  import org.objectweb.fractal.task.core.Executable;
62  import org.objectweb.fractal.task.core.TaskException;
63  import org.objectweb.fractal.task.core.primitive.annotations.ClientInterface;
64  import org.objectweb.fractal.task.core.primitive.annotations.ClientInterfaceForEach;
65  import org.objectweb.fractal.task.core.primitive.annotations.ServerInterface;
66  import org.objectweb.fractal.task.core.primitive.annotations.ServerInterfaces;
67  import org.objectweb.fractal.task.core.primitive.annotations.TaskParameters;
68  
69  public class ControllerImplementationVisitor extends AbstractTaskFactoryUser
70      implements
71        DefinitionVisitor {
72  
73    public static final String    COMPOSTION                        = "org.objectweb.fractal.cecilia.adl.controllers.ControllerCompilation";
74  
75    // ---------------------------------------------------------------------------
76    // Client interface
77    // ---------------------------------------------------------------------------
78  
79    /** The name of the {@link #compilationTaskFactoryItf} client interface. */
80    public static final String    COMPILATION_TASK_FACTORY_ITF_NAME = "compilation-task-factory";
81  
82    /** The client interface used to create compilation tasks. */
83    public CompilationTaskFactory compilationTaskFactoryItf;
84  
85    // ---------------------------------------------------------------------------
86    // Implementation of the DefinitionVisitor interface
87    // ---------------------------------------------------------------------------
88  
89    /**
90     * Visits a {@link ComponentContainer} node and creates a task that creates
91     * the source file containing the components' definition and instance code.
92     */
93    public Component visit(final List<Node> path, final Definition container,
94        final Map<Object, Object> context) throws ADLException, TaskException {
95      final HashMap<SourceFile, Set<IDLDefinition>> controllerImplementation = new HashMap<SourceFile, Set<IDLDefinition>>();
96      findControllers(container, controllerImplementation, context);
97  
98      final Collection<Component> tasks = new ArrayList<Component>();
99      for (final Map.Entry<SourceFile, Set<IDLDefinition>> entry : controllerImplementation
100         .entrySet()) {
101       final SourceFile code = entry.getKey();
102       final String signature = code.getSignature();
103 
104       tasks.add(createControllerImplementationFileProviderTask(entry, code,
105           signature));
106       tasks.add(createControllerImplementationCompilationTask(context,
107           signature));
108     }
109     tasks.add(taskFactoryItf.newPrimitiveTask(
110         new CompiledControllerFileAggregator(), container));
111     return taskFactoryItf.newCompositeTask(tasks, COMPOSTION, null, container);
112   }
113 
114   // ---------------------------------------------------------------------------
115   // Utility methods
116   // ---------------------------------------------------------------------------
117 
118   protected Component createControllerImplementationCompilationTask(
119       final Map<Object, Object> context, final String signature)
120       throws TaskException {
121     return compilationTaskFactoryItf.newCompileTask(signature, null, context);
122   }
123 
124   protected Component createControllerImplementationFileProviderTask(
125       final Map.Entry<SourceFile, Set<IDLDefinition>> entry,
126       final SourceFile code, final String signature) throws TaskException {
127     return taskFactoryItf.newPrimitiveTask(
128         new ControllerImplementationFileProvider(code), signature, entry
129             .getValue());
130   }
131 
132   protected void findControllers(final Object container,
133       final Map<SourceFile, Set<IDLDefinition>> controllerImplementation,
134       final Map<Object, Object> context) throws TaskException {
135     if (container instanceof InterfaceContainer) {
136       for (final Interface itf : ((InterfaceContainer) container)
137           .getInterfaces()) {
138         final Collection<?> codes = (Collection<?>) ImplementationDecorationUtil
139             .getCode(itf);
140         if (codes == null) continue;
141         for (final Object c : codes) {
142           final SourceFile code = (SourceFile) c;
143 
144           Set<IDLDefinition> controllerItf = controllerImplementation.get(code);
145           if (controllerItf == null) {
146             controllerItf = new HashSet<IDLDefinition>();
147             controllerItf.add(castNodeError(itf, IDLDefinitionContainer.class)
148                 .getIDLDefinition());
149             controllerImplementation.put(code, controllerItf);
150           }
151           controllerItf.add(((IDLDefinitionContainer) itf).getIDLDefinition());
152         }
153       }
154     }
155 
156     if (container instanceof ComponentContainer) {
157       for (final org.objectweb.fractal.adl.components.Component component : ((ComponentContainer) container)
158           .getComponents()) {
159         findControllers(component, controllerImplementation, context);
160       }
161     }
162   }
163 
164   // ---------------------------------------------------------------------------
165   // Task classes
166   // ---------------------------------------------------------------------------
167 
168   /**
169    * A {@link SourceFileProvider} task that provides controller implementation
170    * source file.
171    */
172   @TaskParameters({"signature", "implementedInterfaces"})
173   @ServerInterfaces(@ServerInterface(name = "controller-implementation-file-provider", signature = SourceFileProvider.class, record = "role:controllerImplementationFile, id:%", parameters = "signature"))
174   public static class ControllerImplementationFileProvider
175       implements
176         Executable,
177         SourceFileProvider {
178 
179     protected final SourceFile                          providedFile;
180 
181     // -------------------------------------------------------------------------
182     // Client interfaces
183     // -------------------------------------------------------------------------
184 
185     @ClientInterfaceForEach(iterable = "implementedInterfaces", prefix = "idl-header", signature = SourceCodeProvider.class, record = "role:cInterfaceDefinition, id:%", parameters = "implementedInterfaces.element")
186     public final Map<TypeInterface, SourceCodeProvider> cInterfaceDefinitionItfs = new HashMap<TypeInterface, SourceCodeProvider>();
187 
188     // -------------------------------------------------------------------------
189     // Task constructor
190     // -------------------------------------------------------------------------
191 
192     /**
193      * @param providedFile the file provided by this task.
194      */
195     public ControllerImplementationFileProvider(final SourceFile providedFile) {
196       this.providedFile = providedFile;
197     }
198 
199     // -------------------------------------------------------------------------
200     // Implementation of the Executable interface
201     // -------------------------------------------------------------------------
202 
203     public void execute() throws Exception {
204       // simply get the interface definitions to ensure that they are
205       // generated before the controller implementation is compiled.
206       for (final SourceCodeProvider itfDef : cInterfaceDefinitionItfs.values()) {
207         itfDef.getSourceCode();
208       }
209     }
210 
211     // -------------------------------------------------------------------------
212     // Implementation of the SourceFileProvider interface
213     // -------------------------------------------------------------------------
214 
215     public SourceFile getSourceFile() {
216       return providedFile;
217     }
218   }
219 
220   @TaskParameters("definitionNode")
221   @ServerInterfaces(@ServerInterface(name = "controller-implementation-files", signature = FutureFileCollectionProvider.class, record = "role:controllerImplementations, id:%", parameters = "definitionNode"))
222   public static class CompiledControllerFileAggregator
223       implements
224         FutureFileCollectionProvider {
225 
226     protected Collection<Future<File>>           providedFiles;
227 
228     // -------------------------------------------------------------------------
229     // Task client interfaces
230     // -------------------------------------------------------------------------
231 
232     /**
233      * Client collection interface used to retrieve files provided by this task.
234      */
235     @ClientInterface(name = "file-providers", signature = FutureFileProvider.class, record = "role:compiledFile, id:%", parameters = "definitionNode")
236     public final Map<String, FutureFileProvider> clientProviderItfs = new HashMap<String, FutureFileProvider>();
237 
238     // -------------------------------------------------------------------------
239     // Implementation of the FutureFileCollectionProvider interface
240     // -------------------------------------------------------------------------
241 
242     public synchronized Collection<Future<File>> getFiles(
243         final ExecutorService executorService) {
244       if (providedFiles == null) {
245         providedFiles = new HashSet<Future<File>>();
246         for (final FutureFileProvider fileProvider : clientProviderItfs
247             .values()) {
248           providedFiles.add(fileProvider.getFile(executorService));
249         }
250       }
251       return providedFiles;
252     }
253   }
254 
255   // ---------------------------------------------------------------------------
256   // Implementation of the BindingController interface
257   // ---------------------------------------------------------------------------
258 
259   @Override
260   public String[] listFc() {
261     final String[] superItfs = super.listFc();
262     final String[] itfs = new String[superItfs.length + 1];
263     System.arraycopy(superItfs, 0, itfs, 0, superItfs.length);
264     itfs[superItfs.length] = COMPILATION_TASK_FACTORY_ITF_NAME;
265     return itfs;
266   }
267 
268   @Override
269   public void bindFc(final String clientItfName, final Object serverItf)
270       throws NoSuchInterfaceException, IllegalBindingException,
271       IllegalLifeCycleException {
272 
273     if (clientItfName == null) {
274       throw new IllegalArgumentException("Interface name can't be null");
275     }
276 
277     if (clientItfName.equals(COMPILATION_TASK_FACTORY_ITF_NAME))
278       compilationTaskFactoryItf = (CompilationTaskFactory) serverItf;
279     else
280       super.bindFc(clientItfName, serverItf);
281   }
282 
283   @Override
284   public Object lookupFc(final String clientItfName)
285       throws NoSuchInterfaceException {
286 
287     if (clientItfName == null) {
288       throw new IllegalArgumentException("Interface name can't be null");
289     }
290 
291     if (clientItfName.equals(COMPILATION_TASK_FACTORY_ITF_NAME))
292       return compilationTaskFactoryItf;
293     else
294       return super.lookupFc(clientItfName);
295   }
296 
297   @Override
298   public void unbindFc(final String clientItfName)
299       throws NoSuchInterfaceException, IllegalBindingException,
300       IllegalLifeCycleException {
301 
302     if (clientItfName == null) {
303       throw new IllegalArgumentException("Interface name can't be null");
304     }
305 
306     if (clientItfName.equals(COMPILATION_TASK_FACTORY_ITF_NAME))
307       compilationTaskFactoryItf = null;
308     else
309       super.unbindFc(clientItfName);
310   }
311 }