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   * Contributors: Matthieu Leclercq
23   */
24  
25  package org.objectweb.fractal.cecilia.primitive.thinkMC.controllers;
26  
27  import static org.objectweb.fractal.adl.types.TypeInterfaceUtil.isClient;
28  import static org.objectweb.fractal.cecilia.adl.controllers.ControllerDecorationUtil.setCustomBindingController;
29  import static org.objectweb.fractal.cecilia.adl.controllers.ControllerDecorationUtil.setDataSuffix;
30  import static org.objectweb.fractal.cecilia.adl.controllers.ControllerDecorationUtil.setVTable;
31  import static org.objectweb.fractal.cecilia.adl.controllers.ControllerInterface.AC;
32  import static org.objectweb.fractal.cecilia.adl.controllers.ControllerInterface.BC;
33  import static org.objectweb.fractal.cecilia.adl.controllers.ControllerInterface.BINDING_CONTROLLER_SIGNATURE;
34  import static org.objectweb.fractal.cecilia.adl.controllers.ControllerInterface.CI;
35  import static org.objectweb.fractal.cecilia.adl.controllers.ControllerInterface.COMPONENT_IDENTITY_SIGNATURE;
36  import static org.objectweb.fractal.cecilia.adl.interfaces.InterfaceDecorationUtil.setNoStaticBinding;
37  
38  import java.util.ArrayList;
39  import java.util.List;
40  import java.util.Map;
41  
42  import org.objectweb.fractal.adl.ADLException;
43  import org.objectweb.fractal.adl.attributes.Attributes;
44  import org.objectweb.fractal.adl.attributes.AttributesContainer;
45  import org.objectweb.fractal.adl.components.ComponentContainer;
46  import org.objectweb.fractal.adl.error.GenericErrors;
47  import org.objectweb.fractal.adl.implementations.ImplementationContainer;
48  import org.objectweb.fractal.adl.interfaces.Interface;
49  import org.objectweb.fractal.adl.interfaces.InterfaceContainer;
50  import org.objectweb.fractal.adl.types.TypeInterface;
51  import org.objectweb.fractal.cecilia.adl.controllers.AbstractControllerChecker;
52  import org.objectweb.fractal.cecilia.adl.controllers.ControllerInterface;
53  import org.objectweb.fractal.cecilia.adl.idl.ast.Field;
54  import org.objectweb.fractal.cecilia.adl.idl.ast.FieldContainer;
55  import org.objectweb.fractal.cecilia.adl.idl.ast.IDLDefinitionContainer;
56  import org.objectweb.fractal.cecilia.adl.idl.ast.RecordDefinition;
57  
58  /**
59   * Adds controllers interface for <code>"primitive"</code> components.
60   */
61  public class PrimitiveControllerLoader extends AbstractControllerChecker {
62  
63    // --------------------------------------------------------------------------
64    // Implementation of abstract methods
65    // --------------------------------------------------------------------------
66  
67    @Override
68    protected void checkComponent(final ComponentContainer container)
69        throws ADLException {
70      if (container instanceof ImplementationContainer
71          && (((ImplementationContainer) container).getImplementation() == null))
72        throw new ADLException(GenericErrors.GENERIC_ERROR,
73            "'primitive' controller can only be used for primitive components",
74            container);
75    }
76  
77    @Override
78    protected List<Interface> getControllerInterfaces(
79        final ComponentContainer container, final Map<Object, Object> context)
80        throws ADLException {
81      final List<Interface> controllerItfs = new ArrayList<Interface>();
82      final Interface ciItf = getComponentIdentityInterface(container, context);
83      if (ciItf != null) controllerItfs.add(ciItf);
84  
85      final Interface bcItf = getBindingControllerInterface(container, context);
86      if (bcItf != null) controllerItfs.add(bcItf);
87  
88      final Interface acItf = getAttributeControllerInterface(container, context);
89      if (acItf != null) controllerItfs.add(acItf);
90  
91      checkCustomLifeCycleControllerInterface(container, context);
92  
93      return controllerItfs;
94    }
95  
96    // --------------------------------------------------------------------------
97    // Utility methods
98    // --------------------------------------------------------------------------
99  
100   protected void checkCustomLifeCycleControllerInterface(
101       final ComponentContainer container, final Map<Object, Object> context)
102       throws ADLException {
103 
104     final List<TypeInterface> lcc = this.getServerInterfacesBySignature(
105         ControllerInterface.LIFECYCLE_CONTROLLER_SIGNATURE,
106         (InterfaceContainer) container);
107 
108     if (lcc.size() > 1) {
109       throw new ADLException(GenericErrors.GENERIC_ERROR,
110           "It is not allowed to specify TWO " + ControllerInterface.LCC
111               + " interfaces");
112     }
113 
114     /* if there is a user provided LCC... */
115     if (lcc.size() == 1) {
116 
117       final TypeInterface lifeCycleControllerItf = lcc.get(0);
118 
119       // .. check that the name matches the canonical name
120       if (!lifeCycleControllerItf.getName().equals(ControllerInterface.LCC)) {
121         throw new ADLException(GenericErrors.GENERIC_ERROR,
122             "Custom server interface of type "
123                 + ControllerInterface.LIFECYCLE_CONTROLLER_SIGNATURE
124                 + " must be called '" + ControllerInterface.LCC + "'",
125             lifeCycleControllerItf);
126       }
127     }
128 
129   }
130 
131   protected Interface getComponentIdentityInterface(
132       final ComponentContainer container, final Map<Object, Object> context)
133       throws ADLException {
134     final InterfaceContainer itfContainer = (InterfaceContainer) container;
135     TypeInterface ciItf = getInterface(CI, itfContainer);
136     if (ciItf == null) {
137       ciItf = newServerInterfaceNode(CI, COMPONENT_IDENTITY_SIGNATURE);
138       setVTable(ciItf, "__cecilia_default_ComponentMeths");
139       setDataSuffix(ciItf, "CI_data");
140       setItfCode(ciItf, context, "fractal.lib.CIdelegate");
141     } else {
142       checkServerInterface(ciItf);
143       // remove the interface form the interface container, since it is re-added
144       itfContainer.removeInterface(ciItf);
145     }
146     return ciItf;
147   }
148 
149   protected Interface getBindingControllerInterface(
150       final ComponentContainer container, final Map<Object, Object> context)
151       throws ADLException {
152     final InterfaceContainer itfContainer = (InterfaceContainer) container;
153     TypeInterface bcItf = getInterface(BC, itfContainer);
154     if (isComponentNeedBindingControllerInterfaces(itfContainer)
155         && bcItf == null) {
156       bcItf = newServerInterfaceNode(BC, BINDING_CONTROLLER_SIGNATURE);
157       setVTable(bcItf, "__cecilia_default_BindingControllerMeths");
158       setDataSuffix(bcItf, "BC_data");
159       setItfCode(bcItf, context, "fractal.lib.BCdelegate");
160     } else if (bcItf != null) {
161       checkServerInterface(bcItf);
162       // remove the interface form the interface container, since it is re-added
163       itfContainer.removeInterface(bcItf);
164 
165       // if the component has a custom binding controller, do not use statically
166       // initialized binding.
167       for (final Interface i : itfContainer.getInterfaces()) {
168         if (isClient(i)) setNoStaticBinding(i, true);
169       }
170       // set the "custom-binding-controller" decoration on bcItf
171       setCustomBindingController(bcItf, true);
172     }
173     return bcItf;
174   }
175 
176   protected Interface getAttributeControllerInterface(
177       final ComponentContainer container, final Map<Object, Object> context)
178       throws ADLException {
179     final InterfaceContainer itfContainer = (InterfaceContainer) container;
180     TypeInterface acItf = getInterface(AC, itfContainer);
181 
182     if (container instanceof AttributesContainer
183         && ((AttributesContainer) container).getAttributes() != null
184         && acItf == null) {
185 
186       final Attributes attributes = ((AttributesContainer) container)
187           .getAttributes();
188 
189       final RecordDefinition recordDefinition = (RecordDefinition) ((IDLDefinitionContainer) attributes)
190           .getIDLDefinition();
191 
192       final boolean hasConstFields = isComponentNeedAttributeControllerConstAwareDelegate(recordDefinition);
193 
194       acItf = newServerInterfaceNode(AC,
195           ControllerInterface.ATTRIBUTE_CONTROLLER_SIGNATURE);
196       setDataSuffix(acItf, "AC_data");
197 
198       if (hasConstFields) {
199         setItfCode(acItf, context, "fractal.lib.ACdelegate_constattributes");
200         setVTable(acItf, "__cecilia_AttributeControllerConstAttributesMeths");
201       } else {
202         setItfCode(acItf, context, "fractal.lib.ACdelegate");
203         setVTable(acItf, "__cecilia_default_AttributeControllerMeths");
204       }
205     } else if (acItf != null) {
206       checkServerInterface(acItf);
207       // remove the interface form the interface container, since it is re-added
208       itfContainer.removeInterface(acItf);
209     }
210     return acItf;
211   }
212 
213   /**
214    * @param container the <tt>Interface</tt> container.
215    * @return <tt>true</tt> if the component has at least one client interface,
216    *         <tt>false</tt> otherwise.
217    */
218   protected boolean isComponentNeedBindingControllerInterfaces(
219       final InterfaceContainer container) {
220     for (final Interface itf : container.getInterfaces()) {
221       if (isClient(itf)) return true;
222     }
223     return false;
224   }
225 
226   /**
227    * @param fields
228    * @return <code>true</code> if at least one of the {@link Field}s has a
229    *         {@link Field#CONST} qualifier, <code>false</code> otherwise.
230    */
231   protected boolean isComponentNeedAttributeControllerConstAwareDelegate(
232       final RecordDefinition recordDefinition) {
233 
234     final Field[] fields = ((FieldContainer) recordDefinition).getFields();
235 
236     for (final Field f : fields) {
237       if (f.getQualifier().equals(Field.CONST)) {
238         return true;
239       }
240     }
241     return false;
242   }
243 
244 }