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.primitive.thinkMC.implementations;
25  
26  import static org.objectweb.fractal.adl.NodeUtil.castNodeError;
27  import static org.objectweb.fractal.cecilia.adl.SourceCodeHelper.appendSortedSourceCodes;
28  import static org.objectweb.fractal.cecilia.adl.implementations.ImplementationHelper.hasConstructor;
29  import static org.objectweb.fractal.cecilia.adl.implementations.ImplementationHelper.hasDestructor;
30  import static org.objectweb.fractal.cecilia.adl.SourceCodeHelper.appendReverseSortedSourceCodes;
31  
32  import java.util.HashMap;
33  import java.util.List;
34  import java.util.Map;
35  
36  import org.objectweb.fractal.adl.ADLException;
37  import org.objectweb.fractal.adl.CompilerError;
38  import org.objectweb.fractal.adl.ComponentVisitor;
39  import org.objectweb.fractal.adl.Node;
40  import org.objectweb.fractal.adl.components.ComponentContainer;
41  import org.objectweb.fractal.adl.error.GenericErrors;
42  import org.objectweb.fractal.adl.implementations.ImplementationContainer;
43  import org.objectweb.fractal.api.Component;
44  import org.objectweb.fractal.cecilia.adl.AbstractDefinitionTask;
45  import org.objectweb.fractal.cecilia.adl.SourceCodeProvider;
46  import org.objectweb.fractal.cecilia.adl.file.CodeWriter;
47  import org.objectweb.fractal.task.core.AbstractTaskFactoryUser;
48  import org.objectweb.fractal.task.core.TaskException;
49  import org.objectweb.fractal.task.core.primitive.annotations.ClientInterface;
50  import org.objectweb.fractal.task.core.primitive.annotations.ServerInterface;
51  import org.objectweb.fractal.task.core.primitive.annotations.ServerInterfaces;
52  import org.objectweb.fractal.task.core.primitive.annotations.TaskParameters;
53  
54  public class FactoryImplementationVisitor extends AbstractTaskFactoryUser
55      implements
56        ComponentVisitor {
57  
58    // ---------------------------------------------------------------------------
59    // Implementation of the ComponentVisitor interface
60    // ---------------------------------------------------------------------------
61  
62    /**
63     * Visits {@link ComponentContainer} nodes and creates a task that includes
64     * the implementation file, and that defines some macros that are used in the
65     * implementation file.
66     */
67    public Component visit(final List<Node> path,
68        final ComponentContainer container, final Map<Object, Object> context)
69        throws ADLException, TaskException {
70      if (castNodeError(container, ImplementationContainer.class)
71          .getImplementation() == null) {
72        throw new CompilerError(GenericErrors.INTERNAL_ERROR,
73            "This visitor is only applicable for primitive component.");
74      }
75      return taskFactoryItf.newPrimitiveTask(new FactoryImplementationTask(
76          hasConstructor(container), hasDestructor(container)), container);
77    }
78  
79    // ---------------------------------------------------------------------------
80    // Task classes
81    // ---------------------------------------------------------------------------
82  
83    /**
84     * Builds implementation source code of the factory interface for the given
85     * component node.
86     */
87    @TaskParameters("componentNode")
88    @ServerInterfaces(@ServerInterface(name = "factory-implementation", signature = SourceCodeProvider.class, record = "role:factoryImplementation, id:%", parameters = "componentNode"))
89    public static class FactoryImplementationTask extends AbstractDefinitionTask {
90  
91      protected final boolean hasConstructor;
92      protected final boolean hasDestructor;
93  
94      // -------------------------------------------------------------------------
95      // Task constructor
96      // -------------------------------------------------------------------------
97  
98      /**
99       * @param hasConstructor <code>true</code> if the component has a
100      *          constructor.
101      * @param hasDestructor <code>true</code> if the component has a destructor.
102      */
103     public FactoryImplementationTask(final boolean hasConstructor,
104         final boolean hasDestructor) {
105       this.hasConstructor = hasConstructor;
106       this.hasDestructor = hasDestructor;
107     }
108 
109     // -------------------------------------------------------------------------
110     // Task client interfaces
111     // -------------------------------------------------------------------------
112 
113     /**
114      * Client collection interface used to retrieve the implementation code
115      * pieces that contribute local-variable declarations to the 'newFcInstance'
116      * method.
117      */
118     @ClientInterface(name = "factory-instantiate-declaration", signature = SourceCodeProvider.class, record = "role:factoryInstantiateDeclaration, id:%", parameters = "componentNode")
119     public final Map<String, SourceCodeProvider> factoryInstantiateDeclarationProviderItfs = new HashMap<String, SourceCodeProvider>();
120 
121     /**
122      * Client collection interface used to retrieve the implementation code
123      * pieces that contribute 'sizeof' in local variable declarations to the
124      * 'newFcInstance' method.
125      */
126     @ClientInterface(name = "factory-instantiate-sizeof", signature = SourceCodeProvider.class, record = "role:factoryInstantiateSizeof, id:%", parameters = "componentNode")
127     public final Map<String, SourceCodeProvider> factoryInstantiateSizeofProviderItfs      = new HashMap<String, SourceCodeProvider>();
128 
129     /**
130      * Client collection interface used to retrieve the implementation code
131      * pieces that contribute to the 'newFcInstance' method.
132      */
133     @ClientInterface(name = "factory-instantiate-codes-pieces", signature = SourceCodeProvider.class, record = "role:factoryInstantiatePiece, id:%", parameters = "componentNode")
134     public final Map<String, SourceCodeProvider> factoryInstantiatePieceProviderItfs       = new HashMap<String, SourceCodeProvider>();
135 
136     // -------------------------------------------------------------------------
137     // Implementation of abstract methods of AbstractDefinitionTask
138     // -------------------------------------------------------------------------
139 
140     @Override
141     protected String processSourceCode() throws Exception {
142       final CodeWriter cw = new CodeWriter(
143           "Primitive Factory Implementation Builder");
144       final String componentCName = typeNameProviderItf.getCTypeName();
145 
146       cw.append("#include <string.h>").endl();
147 
148       // instantiate method implementation
149       // ---------------------------------------
150       cw.append("int ").append("METHOD(factory, newFcInstance)(void * _this, ")
151           .append("Rfractal_api_Component ** instance) {").endl();
152       cw.append("struct ").append(componentCName).append("_t *originalComp = ")
153           .append("(struct ").append(componentCName).append("_t *) _this;")
154           .endl();
155       cw.append("struct ").append(componentCName).append("_t *newComp = (")
156           .append("struct ").append(componentCName).append(
157               "_t *) CALL(REQUIRED.factory_allocator, alloc,").append(
158               "sizeof(struct ").append(componentCName).append("_t)");
159 
160       appendReverseSortedSourceCodes(cw, factoryInstantiateSizeofProviderItfs
161           .values());
162 
163       cw.appendln(");");
164       cw.appendln("unsigned char *_ptr = (unsigned char *)newComp;");
165 
166       appendReverseSortedSourceCodes(cw,
167           factoryInstantiateDeclarationProviderItfs.values());
168 
169       cw.append("memcpy(newComp, originalComp, sizeof(struct ").append(
170           componentCName).append("_t));").endl();
171       cw.append("_ptr += sizeof(struct ").append(componentCName).append("_t);")
172           .endl();
173 
174       appendReverseSortedSourceCodes(cw, factoryInstantiatePieceProviderItfs
175           .values());
176 
177       cw.append("*instance = & (newComp->type.exported.component);").endl();
178       if (hasConstructor) {
179         cw.append(componentCName).append("_constructor(newComp); ").endl();
180       }
181 
182       cw.append("return fractal_api_ErrorConst_OK;").endl();
183 
184       cw.append("}").endl().endl();
185 
186       // destroy method implementation
187       // -------------------------------------------
188       cw.append("int METHOD(factory, destroyFcInstance)").append(
189           "(void * _this, Rfractal_api_Component *comp) {").endl();
190       cw.append("struct ").append(componentCName)
191           .append("_t *originalComp = (").append("struct ").append(
192               componentCName).append("_t *) comp;").endl();
193 
194       if (hasDestructor) {
195         cw.append(componentCName).append("_destructor(comp); ").endl();
196       }
197 
198       cw.append(
199           "CALL(REQUIRED.factory_allocator, free, (jbyte *) originalComp);")
200           .endl();
201       cw.append("return fractal_api_ErrorConst_OK;").endl();
202 
203       cw.append("}").endl().endl();
204 
205       return cw.toString();
206     }
207   }
208 }