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:Ali Erdem Ozcan
22   */
23  
24  package org.objectweb.fractal.cecilia.primitive.thinkMC.types;
25  
26  import static java.util.Arrays.asList;
27  import static org.objectweb.fractal.cecilia.adl.interfaces.InterfaceDecorationUtil.getBoundTo;
28  import static org.objectweb.fractal.cecilia.adl.interfaces.InterfaceDecorationUtil.getContainer;
29  import static org.objectweb.fractal.cecilia.adl.interfaces.InterfaceDecorationUtil.isNoStaticBinding;
30  import static org.objectweb.fractal.task.core.TaskFactory.EXPORT_ALL;
31  
32  import java.util.HashMap;
33  import java.util.HashSet;
34  import java.util.LinkedHashMap;
35  import java.util.List;
36  import java.util.Map;
37  import java.util.Set;
38  
39  import org.objectweb.fractal.adl.ADLException;
40  import org.objectweb.fractal.adl.components.ComponentContainer;
41  import org.objectweb.fractal.adl.interfaces.Interface;
42  import org.objectweb.fractal.adl.types.TypeInterface;
43  import org.objectweb.fractal.api.Component;
44  import org.objectweb.fractal.cecilia.adl.AbstractInstantiationTask;
45  import org.objectweb.fractal.cecilia.adl.InstanceNameProvider;
46  import org.objectweb.fractal.cecilia.adl.SourceCodeProvider;
47  import org.objectweb.fractal.cecilia.adl.TypeNameProvider;
48  import org.objectweb.fractal.cecilia.adl.file.CodeWriter;
49  import org.objectweb.fractal.cecilia.adl.interfaces.AbstractClientInterfaceVisitor;
50  import org.objectweb.fractal.task.core.TaskException;
51  import org.objectweb.fractal.task.core.primitive.annotations.ClientInterfaceForEach;
52  import org.objectweb.fractal.task.core.primitive.annotations.ServerInterface;
53  import org.objectweb.fractal.task.core.primitive.annotations.ServerInterfaces;
54  import org.objectweb.fractal.task.core.primitive.annotations.TaskParameters;
55  
56  /**
57   * Visitor component that builds the instantiation of the imported interfaces of
58   * the component for <code>ThinkMC</code> dialect.
59   */
60  public class ClientInterfaceInstantiationVisitor
61      extends
62        AbstractClientInterfaceVisitor {
63  
64    // ---------------------------------------------------------------------------
65    // Implementation of abstract methods of AbstractClientInterfaceVisitor
66    // ---------------------------------------------------------------------------
67  
68    /**
69     * Creates a task that writes the source code containing the instantiation of
70     * the client interfaces of the component.
71     */
72    @Override
73    protected Component createTask(final ComponentContainer container,
74        final List<TypeInterface> clientInterfaces) throws ADLException,
75        TaskException {
76      final LinkedHashMap<TypeInterface, Interface> clientInterfaceBindings = new LinkedHashMap<TypeInterface, Interface>();
77      final Set<Object> serverComponents = new HashSet<Object>();
78      for (final TypeInterface clientInterface : clientInterfaces) {
79        final Interface serverItf = isNoStaticBinding(clientInterface)
80            ? null
81            : getBoundTo(clientInterface);
82        clientInterfaceBindings.put(clientInterface, serverItf);
83        if (serverItf != null) {
84          serverComponents.add(getContainer(serverItf));
85        }
86      }
87      final Component includeTask = createIncludeClientInstanceTask(container,
88          clientInterfaceBindings, serverComponents);
89      final Component initializationTask = createInitializationClientInstanceTask(
90          container, clientInterfaceBindings, serverComponents);
91  
92      return taskFactoryItf.newCompositeTask(asList(includeTask,
93          initializationTask), EXPORT_ALL, null);
94    }
95  
96    // ---------------------------------------------------------------------------
97    // Utility methods
98    // ---------------------------------------------------------------------------
99  
100   protected Component createIncludeClientInstanceTask(
101       final ComponentContainer container,
102       final LinkedHashMap<TypeInterface, Interface> clientInterfaceBindings,
103       final Set<Object> serverComponents) throws TaskException {
104     return taskFactoryItf.newPrimitiveTask(new IncludeClientInstanceTask(
105         clientInterfaceBindings), container, serverComponents);
106   }
107 
108   protected Component createInitializationClientInstanceTask(
109       final ComponentContainer container,
110       final LinkedHashMap<TypeInterface, Interface> clientInterfaceBindings,
111       final Set<Object> serverComponents) throws TaskException {
112     return taskFactoryItf.newPrimitiveTask(
113         new InitializationClientInstanceTask(clientInterfaceBindings),
114         container, serverComponents);
115   }
116 
117   // ---------------------------------------------------------------------------
118   // Task classes
119   // ---------------------------------------------------------------------------
120 
121   /**
122    * Builds part of the source code for imported interface instantiation for the
123    * given component node. More precisely, this task builds the source codes
124    * that includes the ".adl.h" files of the server components to which the
125    * client interfaces are statically bound. This task provides the produced
126    * source code. <br>
127    * The <code>serverComponents</code> arguments must refer to the collection
128    * of the server components to which the given component is statically bound
129    * to.
130    */
131   @TaskParameters({"componentNode", "serverComponents"})
132   @ServerInterfaces(@ServerInterface(name = "source-code-provider", signature = SourceCodeProvider.class, record = "role:clientInterfaceInstantiation, id:%, codePiece:include", parameters = "componentNode"))
133   public static class IncludeClientInstanceTask
134       extends
135         AbstractInstantiationTask {
136 
137     protected final LinkedHashMap<TypeInterface, Interface> staticBindings;
138 
139     // -------------------------------------------------------------------------
140     // Task client interfaces
141     // -------------------------------------------------------------------------
142 
143     /**
144      * The client interface used to retrieve the type name of the server
145      * components to which client interfaces are bound to.
146      */
147     @ClientInterfaceForEach(iterable = "serverComponents", prefix = "server-type-name-provider", signature = TypeNameProvider.class, record = "role:staticBindingTypeNameProvider, id:%", parameters = "serverComponents.element")
148     public final Map<Object, TypeNameProvider>              serverTypeNameProviderItf       = new HashMap<Object, TypeNameProvider>();
149 
150     /**
151      * The client interfaces used to retrieve the code that defines the type of
152      * the server components to which client interfaces are bound to.
153      */
154     @ClientInterfaceForEach(iterable = "serverComponents", prefix = "server-type-definition-provider", signature = SourceCodeProvider.class, record = "role:staticBindingTypeDefinitionProvider, id:%", parameters = "serverComponents.element")
155     public final Map<Object, SourceCodeProvider>            serverTypeDefinitionProviderItf = new HashMap<Object, SourceCodeProvider>();
156 
157     /**
158      * The client interfaces used to retrieve the instance name of the server
159      * components to which client interfaces are bound to.
160      */
161     @ClientInterfaceForEach(iterable = "serverComponents", prefix = "server-instance-name-provider", signature = InstanceNameProvider.class, record = "role:staticBindingInstanceNameProvider, id:%", parameters = "serverComponents.element")
162     public final Map<Object, InstanceNameProvider>          serverInstanceNameProviderItf   = new HashMap<Object, InstanceNameProvider>();
163 
164     // -------------------------------------------------------------------------
165     // Task constructor
166     // -------------------------------------------------------------------------
167 
168     /**
169      * @param staticBindings Map associating client interface node to the server
170      *            interface to which they are bound to (or null if the client
171      *            interface is not statically bound). Use LinkedHashMap to
172      *            ensure iteration order.
173      */
174     public IncludeClientInstanceTask(
175         final LinkedHashMap<TypeInterface, Interface> staticBindings) {
176       this.staticBindings = staticBindings;
177     }
178 
179     @Override
180     protected String processSourceCode() throws Exception {
181       final CodeWriter cw = new CodeWriter(
182           "Client Interfaces Instantiation Builder (extern references to server components.)");
183       for (final Map.Entry<TypeInterface, Interface> staticBinding : staticBindings
184           .entrySet()) {
185         // if no static binding, pass it.
186         if (staticBinding.getValue() == null) continue;
187 
188         final Object serverComponent = getContainer(staticBinding.getValue());
189         final String serverTypeName = serverTypeNameProviderItf.get(
190             serverComponent).getCTypeName();
191         final String serverTypeDefinition = serverTypeDefinitionProviderItf
192             .get(serverComponent).getSourceCode();
193         final String serverInstanceName = serverInstanceNameProviderItf.get(
194             serverComponent).getCInstanceName();
195 
196         // Bug 307360: if the server component has the same type as this
197         // component do not (re)append type definition
198         cw.append("#ifndef ").append(serverInstanceName).append("_DECLARED")
199             .endl();
200         if (serverTypeName.equals(typeNameProviderItf.getCTypeName())) {
201           cw.append("extern struct ").append(
202               serverTypeName.toString().replace('.', '_')).append("_t ")
203               .append(serverInstanceName.replace('.', '_')).append(";").endl();
204         } else {
205           cw.append(serverTypeDefinition).endl();
206           cw.append("extern struct ").append(
207               serverTypeName.toString().replace('.', '_')).append("_exporteds ")
208               .append(serverInstanceName.replace('.', '_')).append(";").endl();
209         }
210         cw.append("#define ").append(serverInstanceName).append("_DECLARED")
211             .endl();
212         cw.appendln("#endif");
213 
214       }
215       return cw.toString();
216     }
217   }
218 
219   /**
220    * Builds part of the source code for imported interface instantiation for the
221    * given component node. More precisely, this task builds the source codes
222    * that initializes the client interfaces to point to the server interfaces
223    * they are statically bound to. This task provides the produced source code.
224    * <br>
225    * The <code>serverComponents</code> arguments must refer to the collection
226    * of the server components to which the given component is statically bound
227    * to.
228    */
229   @ServerInterfaces(@ServerInterface(name = "source-code-provider", signature = SourceCodeProvider.class, record = "role:clientInterfaceInstantiation, id:%, codePiece:initialization", parameters = "componentNode"))
230   public class InitializationClientInstanceTask
231       extends
232         IncludeClientInstanceTask {
233 
234     // -------------------------------------------------------------------------
235     // Task constructor
236     // -------------------------------------------------------------------------
237 
238     /**
239      * @see IncludeClientInstanceTask#IncludeClientInstanceTask(LinkedHashMap)
240      */
241     public InitializationClientInstanceTask(
242         final LinkedHashMap<TypeInterface, Interface> clientItfNodes) {
243       super(clientItfNodes);
244     }
245 
246     @Override
247     protected String processSourceCode() throws Exception {
248       final CodeWriter cw = new CodeWriter(
249           "Client Interfaces Instantiation Builder (initialization)");
250       cw.append("{").endl();
251       for (final Map.Entry<TypeInterface, Interface> clientBinding : staticBindings
252           .entrySet()) {
253 
254         final TypeInterface clientItf = clientBinding.getKey();
255         final Interface serverItf = clientBinding.getValue();
256         if (serverItf == null) {
257           cw.append("0");
258         } else {
259           final Object serverComponent = getContainer(serverItf);
260           final String serverTypeName = serverTypeNameProviderItf.get(
261               serverComponent).getCTypeName();
262           final String serverInstance = serverInstanceNameProviderItf.get(
263               serverComponent).getCInstanceName();
264 
265           if (serverTypeName.equals(typeNameProviderItf.getCTypeName())) {
266             // Bug 307360: if the server component has the same type as this
267             // component, server interfaces are accessed through
268             // ".type.exported"
269             cw.append(
270                 "(R" + clientItf.getSignature().replace('.', '_') + "*)&(")
271                 .append(serverInstance.replace('.', '_')).append(
272                     ".type.exported.").append(
273                     serverItf.getName().replace('-', '_')).append(')');
274           } else {
275             // otherwise, server interfaces are accessed through ".exported"
276             cw.append(
277                 "(R" + clientItf.getSignature().replace('.', '_') + "*)&(")
278                 .append(serverInstance.replace('.', '_')).append(".")
279                 .append(serverItf.getName().replace('-', '_')).append(')');
280           }
281         }
282         cw.append(", // ").append(clientItf.getName()).endl();
283 
284       }
285       cw.append("}").endl();
286 
287       return cw.toString();
288     }
289   }
290 }