View Javadoc

1   /***
2    * Cecilia ADL Compiler
3    * Copyright (C) 2006-2008 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.adl.controllers;
26  
27  import static org.objectweb.fractal.adl.types.TypeInterfaceUtil.isClient;
28  import static org.objectweb.fractal.adl.types.TypeInterfaceUtil.isMandatory;
29  import static org.objectweb.fractal.adl.types.TypeInterfaceUtil.isServer;
30  import static org.objectweb.fractal.adl.types.TypeInterfaceUtil.isSingleton;
31  import static org.objectweb.fractal.cecilia.adl.implementations.ImplementationDecorationUtil.setCode;
32  
33  import java.util.ArrayList;
34  import java.util.List;
35  import java.util.Map;
36  
37  import org.objectweb.fractal.adl.ADLException;
38  import org.objectweb.fractal.adl.CompilerError;
39  import org.objectweb.fractal.adl.NodeUtil;
40  import org.objectweb.fractal.adl.components.ComponentContainer;
41  import org.objectweb.fractal.adl.error.GenericErrors;
42  import org.objectweb.fractal.adl.implementations.ImplementationCodeLoader;
43  import org.objectweb.fractal.adl.interfaces.Interface;
44  import org.objectweb.fractal.adl.interfaces.InterfaceContainer;
45  import org.objectweb.fractal.adl.types.TypeInterface;
46  import org.objectweb.fractal.adl.xml.XMLNodeFactory;
47  import org.objectweb.fractal.api.NoSuchInterfaceException;
48  import org.objectweb.fractal.api.control.BindingController;
49  import org.objectweb.fractal.api.control.IllegalBindingException;
50  import org.objectweb.fractal.api.control.IllegalLifeCycleException;
51  import org.objectweb.fractal.cecilia.adl.CeciliaADLConstants;
52  import org.objectweb.fractal.cecilia.adl.components.PrimitiveChecker;
53  import org.xml.sax.SAXException;
54  
55  /**
56   * Abstract implementation of a {@link PrimitiveChecker} component to check
57   * controller part.
58   */
59  public abstract class AbstractControllerChecker
60      implements
61        PrimitiveChecker,
62        BindingController {
63  
64    private static final String     INTERFACE_AST_NODE_NAME        = "interface";
65  
66    // ---------------------------------------------------------------------------
67    // Client interfaces
68    // ---------------------------------------------------------------------------
69  
70    /** The name of the {@link #nodeFactoryItf} client interface. */
71    public static final String      NODE_FACTORY_ITF               = "node-factory";
72  
73    /** The name of the {@link #implementationCodeLoaderItf} client interface. */
74    public static final String      IMPLEMENTATION_CODE_LOADER_ITF = "implementation-code-loader";
75  
76    /** The {@link XMLNodeFactory} client interface. */
77    public XMLNodeFactory           nodeFactoryItf;
78  
79    /** The {@link ImplementationCodeLoader} client interface. */
80    public ImplementationCodeLoader implementationCodeLoaderItf;
81  
82    // ---------------------------------------------------------------------------
83    // Implementation of the PrimitiveChecker interface
84    // ---------------------------------------------------------------------------
85  
86    public void beforeSubComponentCheck(final List<ComponentContainer> path,
87        final ComponentContainer container, final Map<Object, Object> context)
88        throws ADLException {
89      // do nothing.
90    }
91  
92    public void afterSubComponentCheck(final List<ComponentContainer> path,
93        final ComponentContainer container, final Map<Object, Object> context)
94        throws ADLException {
95      final InterfaceContainer itfContainer = NodeUtil.castNodeError(container,
96          InterfaceContainer.class);
97  
98      // check that the given component is valid
99      checkComponent(container);
100 
101     // retrieve the list of control interface.
102     final List<Interface> controllerInterfaces = getControllerInterfaces(
103         container, context);
104 
105     // remove all interfaces to add controllers at first
106     final Interface[] itfs = itfContainer.getInterfaces();
107     for (final Interface itf : itfs) {
108       itfContainer.removeInterface(itf);
109     }
110 
111     // add controller interfaces
112     for (final Interface controllerItf : controllerInterfaces) {
113       itfContainer.addInterface(controllerItf);
114     }
115     // re-add other interfaces
116     for (final Interface itf : itfs) {
117       itfContainer.addInterface(itf);
118     }
119   }
120 
121   // ---------------------------------------------------------------------------
122   // abstract methods
123   // ---------------------------------------------------------------------------
124 
125   protected abstract void checkComponent(final ComponentContainer container)
126       throws ADLException;
127 
128   protected abstract List<Interface> getControllerInterfaces(
129       final ComponentContainer container, final Map<Object, Object> context)
130       throws ADLException;
131 
132   // ---------------------------------------------------------------------------
133   // Utility methods
134   // ---------------------------------------------------------------------------
135 
136   protected TypeInterface getInterface(final String name,
137       final InterfaceContainer container) {
138     for (final Interface itf : container.getInterfaces()) {
139       if (itf.getName().equals(name)) return (TypeInterface) itf;
140     }
141     return null;
142   }
143 
144   /**
145    * @param signature
146    * @return the <em>server</em> <tt>TypeInterface</tt> with the given
147    *         <tt>signature</tt>, or <tt>null</tt> if none is found.
148    */
149   protected List<TypeInterface> getServerInterfacesBySignature(
150       final String signature, final InterfaceContainer container) {
151 
152     final List<TypeInterface> result = new ArrayList<TypeInterface>();
153 
154     for (final Interface itf : container.getInterfaces()) {
155       final TypeInterface typedInterface = (TypeInterface) itf;
156       if (typedInterface.getSignature().equals(signature)
157           && typedInterface.getRole().equals("server")) {
158         result.add(typedInterface);
159       }
160     }
161     return result;
162 
163   }
164 
165   protected void checkServerInterface(final TypeInterface itf)
166       throws ADLException {
167     if (!isServer(itf)) {
168       throw new ADLException(ControllerErrors.INVALID_CONTROLLER_ITF_ROLE, itf,
169           itf.getName(), TypeInterface.SERVER_ROLE);
170     }
171     if (!isMandatory(itf)) {
172       throw new ADLException(
173           ControllerErrors.INVALID_CONTROLLER_ITF_CONTINGENCY, itf, itf
174               .getName(), TypeInterface.MANDATORY_CONTINGENCY);
175     }
176     if (!isSingleton(itf)) {
177       throw new ADLException(
178           ControllerErrors.INVALID_CONTROLLER_ITF_CARDINALITY, itf, itf
179               .getName(), TypeInterface.SINGLETON_CARDINALITY);
180     }
181   }
182 
183   protected void checkClientInterface(final TypeInterface itf)
184       throws ADLException {
185     if (!isClient(itf)) {
186       throw new ADLException(ControllerErrors.INVALID_CONTROLLER_ITF_ROLE, itf,
187           itf.getName(), TypeInterface.CLIENT_ROLE);
188     }
189     if (!isMandatory(itf)) {
190       throw new ADLException(
191           ControllerErrors.INVALID_CONTROLLER_ITF_CONTINGENCY, itf, itf
192               .getName(), TypeInterface.MANDATORY_CONTINGENCY);
193     }
194     if (!isSingleton(itf)) {
195       throw new ADLException(
196           ControllerErrors.INVALID_CONTROLLER_ITF_CARDINALITY, itf, itf
197               .getName(), TypeInterface.SINGLETON_CARDINALITY);
198     }
199   }
200 
201   protected TypeInterface newServerInterfaceNode(final String name,
202       final String signature) {
203     TypeInterface itf;
204     try {
205       itf = (TypeInterface) nodeFactoryItf.newXMLNode(
206           CeciliaADLConstants.CECILIA_ADL_DTD,
207           AbstractControllerChecker.INTERFACE_AST_NODE_NAME);
208     } catch (final SAXException e) {
209       throw new CompilerError(GenericErrors.INTERNAL_ERROR, e,
210           "Unable to create interface node");
211     }
212     itf.setName(name);
213     itf.setSignature(signature);
214     itf.setCardinality(TypeInterface.SINGLETON_CARDINALITY);
215     itf.setRole(TypeInterface.SERVER_ROLE);
216     itf.setContingency(TypeInterface.MANDATORY_CONTINGENCY);
217     return itf;
218   }
219 
220   protected TypeInterface newClientInterfaceNode(final String name,
221       final String signature) {
222     TypeInterface itf;
223     try {
224       itf = (TypeInterface) nodeFactoryItf.newXMLNode(
225           CeciliaADLConstants.CECILIA_ADL_DTD,
226           AbstractControllerChecker.INTERFACE_AST_NODE_NAME);
227     } catch (final SAXException e) {
228       throw new CompilerError(GenericErrors.INTERNAL_ERROR, e,
229           "Unable to create interface node");
230     }
231     itf.setName(name);
232     itf.setSignature(signature);
233     itf.setCardinality(TypeInterface.SINGLETON_CARDINALITY);
234     itf.setRole(TypeInterface.CLIENT_ROLE);
235     itf.setContingency(TypeInterface.MANDATORY_CONTINGENCY);
236     return itf;
237   }
238 
239   /**
240    * Use {@link #setItfCode(Interface, Map, String...)} instead.
241    * 
242    * @param itf
243    * @param signature
244    * @param context
245    * @throws ADLException
246    */
247   @Deprecated
248   protected void setItfCode(final Interface itf, final String signature,
249       final Map<Object, Object> context) throws ADLException {
250     setItfCode(itf, context, signature);
251   }
252 
253   protected void setItfCode(final Interface itf,
254       final Map<Object, Object> context, final String... signatures)
255       throws ADLException {
256     final List<Object> codes = new ArrayList<Object>(signatures.length);
257     for (final String signature : signatures) {
258       codes.add(implementationCodeLoaderItf.loadImplementation(signature, null,
259           context));
260     }
261     setCode(itf, codes);
262   }
263 
264   // ---------------------------------------------------------------------------
265   // Implementation of the BindingController interface
266   // ---------------------------------------------------------------------------
267 
268   public void bindFc(final String s, final Object o)
269       throws NoSuchInterfaceException, IllegalBindingException,
270       IllegalLifeCycleException {
271 
272     if (s == null) {
273       throw new IllegalArgumentException("Interface name can't be null");
274     }
275 
276     if (s.equals(NODE_FACTORY_ITF)) {
277       this.nodeFactoryItf = (XMLNodeFactory) o;
278     } else if (s.equals(IMPLEMENTATION_CODE_LOADER_ITF)) {
279       this.implementationCodeLoaderItf = (ImplementationCodeLoader) o;
280     } else {
281       throw new NoSuchInterfaceException("There is no interface named '" + s
282           + "'");
283     }
284   }
285 
286   public String[] listFc() {
287     return new String[]{NODE_FACTORY_ITF, IMPLEMENTATION_CODE_LOADER_ITF};
288   }
289 
290   public Object lookupFc(final String s) throws NoSuchInterfaceException {
291     if (s == null) {
292       throw new IllegalArgumentException("Interface name can't be null");
293     }
294 
295     if (s.equals(NODE_FACTORY_ITF)) {
296       return this.nodeFactoryItf;
297     } else if (s.equals(IMPLEMENTATION_CODE_LOADER_ITF)) {
298       return this.implementationCodeLoaderItf;
299     } else {
300       throw new NoSuchInterfaceException("There is no interface named '" + s
301           + "'");
302     }
303   }
304 
305   public void unbindFc(final String s) throws NoSuchInterfaceException,
306       IllegalBindingException, IllegalLifeCycleException {
307 
308     if (s == null) {
309       throw new IllegalArgumentException("Interface name can't be null");
310     }
311 
312     if (s.equals(NODE_FACTORY_ITF)) {
313       this.nodeFactoryItf = null;
314     } else if (s.equals(IMPLEMENTATION_CODE_LOADER_ITF)) {
315       this.implementationCodeLoaderItf = null;
316     } else {
317       throw new NoSuchInterfaceException("There is no interface named '" + s
318           + "'");
319     }
320   }
321 
322 }