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   */
23  
24  package org.objectweb.fractal.cecilia.adl.interfaces;
25  
26  import static org.objectweb.fractal.cecilia.adl.ReservedWordsChecker.isReservedCWord;
27  
28  import java.util.HashMap;
29  import java.util.Map;
30  
31  import org.objectweb.fractal.adl.ADLException;
32  import org.objectweb.fractal.adl.AbstractLoader;
33  import org.objectweb.fractal.adl.CompilerError;
34  import org.objectweb.fractal.adl.Definition;
35  import org.objectweb.fractal.adl.Loader;
36  import org.objectweb.fractal.adl.Node;
37  import org.objectweb.fractal.adl.components.Component;
38  import org.objectweb.fractal.adl.components.ComponentContainer;
39  import org.objectweb.fractal.adl.error.ChainedErrorLocator;
40  import org.objectweb.fractal.adl.error.GenericErrors;
41  import org.objectweb.fractal.adl.error.NodeErrorLocator;
42  import org.objectweb.fractal.adl.interfaces.IDLLoader;
43  import org.objectweb.fractal.adl.interfaces.Interface;
44  import org.objectweb.fractal.adl.interfaces.InterfaceContainer;
45  import org.objectweb.fractal.adl.merger.MergeException;
46  import org.objectweb.fractal.adl.merger.NodeMerger;
47  import org.objectweb.fractal.adl.types.TypeInterface;
48  import org.objectweb.fractal.adl.xml.XMLNodeFactory;
49  import org.objectweb.fractal.api.NoSuchInterfaceException;
50  import org.objectweb.fractal.api.control.IllegalBindingException;
51  import org.objectweb.fractal.cecilia.adl.idl.ast.IDLDefinitionContainer;
52  import org.objectweb.fractal.cecilia.adl.idl.ast.InterfaceDefinition;
53  import org.xml.sax.SAXException;
54  
55  /**
56   * A {@link Loader} to check {@link Interface} nodes in definitions. This loader
57   * checks:
58   * <ul>
59   * <li>that interface names are locally unique</li>
60   * <li>loads the AST of the interface definition</li>
61   * <li>merges the AST definition of the interface with the one of the ADL.</li>
62   * </ul>
63   */
64  public class InterfaceLoader extends AbstractLoader {
65  
66    /**
67     * The URL of the DTD that defines AST node interfaces for bridging ADL and
68     * IDL trees.
69     */
70    public static final String ADL_IDL_BRIGDE_DTD   = "classpath://org/objectweb/fractal/cecilia/adl/idl/adl-idl-bridge.dtd";
71  
72    // ---------------------------------------------------------------------------
73    // Client interfaces
74    // ---------------------------------------------------------------------------
75  
76    /** The name of the {@link #idlLoaderItf} client interface. */
77    public static final String INTERFACE_LOADER_ITF = "interface-loader";
78  
79    /** The {@link IDLLoader} client interface used by this component. */
80    public IDLLoader           idlLoaderItf;
81  
82    /** The {@link NodeMerger} client interface used by this component. */
83    public NodeMerger          nodeMergerItf;
84  
85    /** The {@link XMLNodeFactory} client interface used by this component. */
86    public XMLNodeFactory      nodeFactoryItf;
87  
88    // ---------------------------------------------------------------------------
89    // Implementation of the Loader interface
90    // ---------------------------------------------------------------------------
91  
92    public Definition load(final String name, final Map<Object, Object> context)
93        throws ADLException {
94      final Definition d = clientLoader.load(name, context);
95      checkNode(d, context);
96      return d;
97    }
98  
99    // ---------------------------------------------------------------------------
100   // Checking methods
101   // ---------------------------------------------------------------------------
102 
103   protected void checkNode(final Object node, final Map<Object, Object> context)
104       throws ADLException {
105     if (node instanceof InterfaceContainer) {
106       checkInterfaceContainer((InterfaceContainer) node, context);
107     }
108     if (node instanceof ComponentContainer) {
109       for (final Component comp : ((ComponentContainer) node).getComponents()) {
110         checkNode(comp, context);
111       }
112     }
113   }
114 
115   protected void checkInterfaceContainer(final InterfaceContainer container,
116       final Map<Object, Object> context) throws ADLException {
117     final Map<String, Interface> names = new HashMap<String, Interface>();
118     for (Interface itf : container.getInterfaces()) {
119       final String name = itf.getName();
120       if (name == null) {
121         throw new ADLException(
122             org.objectweb.fractal.adl.interfaces.InterfaceErrors.INTERFACE_NAME_MISSING,
123             itf);
124       }
125       if (isReservedCWord(name)) {
126         throw new ADLException(InterfaceErrors.IDL_NAME_IS_RESERVED_WORD, name);
127       }
128       final Interface previousDefinition = names.put(name, itf);
129       if (previousDefinition != null) {
130         throw new ADLException(
131             org.objectweb.fractal.adl.interfaces.InterfaceErrors.DUPLICATED_INTERFACE_NAME,
132             itf, name, new NodeErrorLocator(previousDefinition));
133       }
134       if (!(itf instanceof IDLDefinitionContainer)) {
135         // the interface node is not an IDLDefinitionContainer
136         // - create a bridge node;
137         // - merge it with the interface node.
138         try {
139           Node bridge = nodeFactoryItf.newXMLNode(ADL_IDL_BRIGDE_DTD,
140               ((Node) itf).astGetType());
141           bridge = nodeMergerItf.merge(itf, bridge,
142               new HashMap<String, String>());
143           if (bridge != itf) {
144             // replace itf node
145             container.removeInterface(itf);
146             itf = (Interface) bridge;
147             container.addInterface(itf);
148           }
149         } catch (final SAXException e) {
150           throw new CompilerError(GenericErrors.INTERNAL_ERROR, e,
151               "Unable to create AST node.");
152         } catch (final MergeException e) {
153           throw new CompilerError(GenericErrors.INTERNAL_ERROR, e,
154               "Unable to merge interface node.");
155         }
156       }
157       // Load the interface definition node
158       Node interfaceDefinition = null;
159       final String signature = ((TypeInterface) itf).getSignature();
160       try {
161         interfaceDefinition = (Node) idlLoaderItf.loadInterface(signature,
162             context);
163       } catch (final ADLException e) {
164         ChainedErrorLocator.chainLocator(e, itf);
165         throw e;
166       }
167       // Test if the node is an instance of InterfaceDefinition
168       if (!(interfaceDefinition instanceof InterfaceDefinition)) {
169         throw new ADLException(InterfaceErrors.INVALID_SIGNATURE, itf,
170             signature);
171       }
172       // Add the interface definition node into the interface node
173       ((IDLDefinitionContainer) itf)
174           .setIDLDefinition((InterfaceDefinition) interfaceDefinition);
175     }
176   }
177 
178   // ---------------------------------------------------------------------------
179   // Overridden BindingController methods
180   // ---------------------------------------------------------------------------
181 
182   @Override
183   public void bindFc(final String s, final Object o)
184       throws NoSuchInterfaceException, IllegalBindingException {
185 
186     if (s == null) {
187       throw new IllegalArgumentException("Interface name can't be null");
188     }
189 
190     if (s.equals(INTERFACE_LOADER_ITF)) {
191       idlLoaderItf = (IDLLoader) o;
192     } else if (s.equals(NodeMerger.ITF_NAME)) {
193       nodeMergerItf = (NodeMerger) o;
194     } else if (s.equals(XMLNodeFactory.ITF_NAME)) {
195       nodeFactoryItf = (XMLNodeFactory) o;
196     } else {
197       super.bindFc(s, o);
198     }
199   }
200 
201   @Override
202   public String[] listFc() {
203     final String[] superList = super.listFc();
204     final String[] list = new String[superList.length + 3];
205     list[0] = INTERFACE_LOADER_ITF;
206     list[1] = NodeMerger.ITF_NAME;
207     list[2] = XMLNodeFactory.ITF_NAME;
208     System.arraycopy(superList, 0, list, 3, superList.length);
209     return list;
210   }
211 
212   @Override
213   public Object lookupFc(final String s) throws NoSuchInterfaceException {
214 
215     if (s == null) {
216       throw new IllegalArgumentException("Interface name can't be null");
217     }
218 
219     if (s.equals(INTERFACE_LOADER_ITF)) {
220       return idlLoaderItf;
221     } else if (s.equals(NodeMerger.ITF_NAME)) {
222       return nodeMergerItf;
223     } else if (s.equals(XMLNodeFactory.ITF_NAME)) {
224       return nodeFactoryItf;
225     } else {
226       return super.lookupFc(s);
227     }
228   }
229 
230   @Override
231   public void unbindFc(final String s) throws IllegalBindingException,
232       NoSuchInterfaceException {
233 
234     if (s == null) {
235       throw new IllegalArgumentException("Interface name can't be null");
236     }
237 
238     if (s.equals(INTERFACE_LOADER_ITF)) {
239       idlLoaderItf = null;
240     } else if (s.equals(NodeMerger.ITF_NAME)) {
241       nodeMergerItf = null;
242     } else if (s.equals(XMLNodeFactory.ITF_NAME)) {
243       nodeFactoryItf = null;
244     } else {
245       super.unbindFc(s);
246     }
247   }
248 }