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   * Initial Developper : J.-P. Fassino.
22   * Author: Matthieu Leclercq
23   * Contributor: Alessio Pace
24   */
25  
26  package org.objectweb.fractal.cecilia.adl.idl;
27  
28  import static org.objectweb.fractal.cecilia.adl.ReservedWordsChecker.isReservedCWord;
29  import static org.objectweb.fractal.cecilia.adl.idl.util.Util.getComplexType;
30  import static org.objectweb.fractal.cecilia.adl.idl.util.Util.getContainedType;
31  import static org.objectweb.fractal.cecilia.adl.idl.util.Util.isComplexType;
32  import static org.objectweb.fractal.cecilia.adl.idl.util.Util.setContainedDefinition;
33  import static org.objectweb.fractal.cecilia.adl.idl.util.Util.setImportedAST;
34  
35  import java.io.IOException;
36  import java.io.InputStream;
37  import java.net.URL;
38  import java.util.ArrayList;
39  import java.util.HashMap;
40  import java.util.HashSet;
41  import java.util.Iterator;
42  import java.util.List;
43  import java.util.Map;
44  import java.util.Set;
45  
46  import org.objectweb.fractal.adl.ADLException;
47  import org.objectweb.fractal.adl.CompilerError;
48  import org.objectweb.fractal.adl.ContextLocal;
49  import org.objectweb.fractal.adl.Node;
50  import org.objectweb.fractal.adl.error.ChainedErrorLocator;
51  import org.objectweb.fractal.adl.error.GenericErrors;
52  import org.objectweb.fractal.adl.error.NodeErrorLocator;
53  import org.objectweb.fractal.adl.interfaces.IDLLoader;
54  import org.objectweb.fractal.adl.timestamp.Timestamp;
55  import org.objectweb.fractal.adl.util.ClassLoaderHelper;
56  import org.objectweb.fractal.adl.xml.XMLNode;
57  import org.objectweb.fractal.adl.xml.XMLNodeFactory;
58  import org.objectweb.fractal.api.NoSuchInterfaceException;
59  import org.objectweb.fractal.api.control.BindingController;
60  import org.objectweb.fractal.api.control.IllegalBindingException;
61  import org.objectweb.fractal.api.control.IllegalLifeCycleException;
62  import org.objectweb.fractal.cecilia.adl.idl.ast.ComplexType;
63  import org.objectweb.fractal.cecilia.adl.idl.ast.EnumDefinition;
64  import org.objectweb.fractal.cecilia.adl.idl.ast.ExtendingDefinition;
65  import org.objectweb.fractal.cecilia.adl.idl.ast.Field;
66  import org.objectweb.fractal.cecilia.adl.idl.ast.FieldContainer;
67  import org.objectweb.fractal.cecilia.adl.idl.ast.IDLDefinition;
68  import org.objectweb.fractal.cecilia.adl.idl.ast.Import;
69  import org.objectweb.fractal.cecilia.adl.idl.ast.ImportContainer;
70  import org.objectweb.fractal.cecilia.adl.idl.ast.InterfaceDefinition;
71  import org.objectweb.fractal.cecilia.adl.idl.ast.Method;
72  import org.objectweb.fractal.cecilia.adl.idl.ast.MethodContainer;
73  import org.objectweb.fractal.cecilia.adl.idl.ast.Parameter;
74  import org.objectweb.fractal.cecilia.adl.idl.ast.ParameterContainer;
75  import org.objectweb.fractal.cecilia.adl.idl.ast.RecordDefinition;
76  import org.objectweb.fractal.cecilia.adl.idl.ast.Type;
77  import org.objectweb.fractal.cecilia.adl.idl.ast.TypeContainer;
78  import org.objectweb.fractal.cecilia.adl.idl.ast.UnionDefinition;
79  import org.objectweb.fractal.cecilia.adl.idl.parser.IDLParser;
80  import org.objectweb.fractal.cecilia.adl.idl.parser.ParseException;
81  import org.objectweb.fractal.cecilia.adl.interfaces.InterfaceDecorationUtil;
82  import org.xml.sax.SAXException;
83  
84  /**
85   * {@link IDLLoader} implementation for IDL source code. The
86   * {@link #loadInterface(String, Map) loadCode} method returns the AST of the
87   * IDL, (eventually) merging fields and methods in the above IDL inheritance
88   * tree, and decorating it with an ordered sequence of IDL types from the bottom
89   * to the top of inheritance tree.
90   */
91  public class BasicIDLLoader implements IDLLoader, BindingController {
92  
93    /** the client interface name for the node factory. */
94    public static final String                         NODE_FACTORY_ITF_NAME = "node-factory";
95  
96    /**
97     * Client interface bound to the {@link XMLNodeFactory node factory}
98     * component.
99     */
100   public XMLNodeFactory                              nodeFactoryItf;
101 
102   protected ContextLocal<Map<String, IDLDefinition>> loadedCode            = new ContextLocal<Map<String, IDLDefinition>>();
103 
104   // ---------------------------------------------------------------------------
105   // Implementation of the IDLLoader interface
106   // ---------------------------------------------------------------------------
107 
108   public Object loadInterface(final String signature,
109       final Map<Object, Object> context) throws ADLException {
110     // first, search in cache
111     Map<String, IDLDefinition> cache = loadedCode.get(context);
112     if (cache == null) {
113       cache = new HashMap<String, IDLDefinition>();
114       loadedCode.set(context, cache);
115     }
116     final Object c = cache.get(signature);
117     if (c != null) return c;
118 
119     final ClassLoader loader = ClassLoaderHelper.getClassLoader(this, context);
120     final Map<String, DependantNode> toBeLoaded = new HashMap<String, DependantNode>();
121     final IDLDefinition definition = loadIDL(signature, toBeLoaded,
122         new ArrayList<String>(), loader, cache);
123 
124     // load IDLs that have to be loaded.
125     // the while statement does not use an Iterator on toBeLoaded map since
126     // iterations may modify the Map, which invalidate the iterator.
127     while (!toBeLoaded.isEmpty()) {
128 
129       // remove the first element of the toBeLoaded map.
130       final Iterator<Map.Entry<String, DependantNode>> iter = toBeLoaded
131           .entrySet().iterator();
132       final Map.Entry<String, DependantNode> elem = iter.next();
133       iter.remove();
134 
135       final DependantNode dep = elem.getValue();
136       // Load the definition
137       try {
138         final IDLDefinition def = loadIDL(elem.getKey(), toBeLoaded,
139             new ArrayList<String>(), loader, cache);
140         // set the definition as the complex type of each ComplexTypeContainer
141         dep.setDefinition(def);
142       } catch (final ADLException e) {
143         if (dep.imports != null)
144           ChainedErrorLocator.chainLocator(e, dep.imports.get(0));
145         else if (dep.types != null)
146           ChainedErrorLocator.chainLocator(e, dep.types.get(0));
147 
148         throw e;
149       }
150     }
151     return definition;
152   }
153 
154   // --------------------------------------------------------------------------
155   // Utility methods
156   // --------------------------------------------------------------------------
157 
158   protected IDLDefinition loadIDL(final String signature,
159       final Map<String, DependantNode> toBeLoaded,
160       final List<String> inheritancePath, final ClassLoader loader,
161       final Map<String, IDLDefinition> cache) throws ADLException {
162 
163     // first, search in cache
164     IDLDefinition node = cache.get(signature);
165     if (node != null) return node;
166 
167     final URL srcFile = locate(signature, loader);
168 
169     InputStream inputStream;
170     try {
171       inputStream = srcFile.openStream();
172     } catch (final IOException e) {
173       throw new ADLException(IDLErrors.IO_ERROR, e, srcFile.getPath());
174     }
175     node = parseIDL(inputStream, signature, srcFile.getPath());
176 
177     // Set timestamp of the IDL file
178     Timestamp.setTimestamp(node, srcFile);
179 
180     check(signature, node, toBeLoaded, inheritancePath, loader, cache);
181     if (node instanceof ImportContainer) {
182       for (final Import i : ((ImportContainer) node).getImports()) {
183         DependantNode d = toBeLoaded.get(i.getName());
184         if (d == null) {
185           d = new DependantNode();
186           toBeLoaded.put(i.getName(), d);
187         }
188         d.addImport(i);
189       }
190     }
191 
192     cache.put(signature, node);
193     return node;
194   }
195 
196   /**
197    * Creates an {@link IDLParser} and uses it to parse the IDL.
198    * 
199    * @param inputStream
200    * @param srcFile
201    * @return
202    * @throws IDLSyntaxErrorException
203    */
204   protected IDLDefinition parseIDL(final InputStream inputStream,
205       final String signature, final String srcFile) throws ADLException {
206     IDLDefinition node;
207     final IDLParser parser = new IDLParser(inputStream);
208     parser.init(nodeFactoryItf, CeciliaIDLConstants.CECILIA_IDL_DTD, srcFile);
209     try {
210       node = parser.getIDLNode();
211     } catch (final ParseException e) {
212       throw new ADLException(IDLErrors.SYNTAX_ERROR, signature, e.getMessage());
213     }
214     return node;
215   }
216 
217   protected URL locate(final String signature, final ClassLoader loader)
218       throws ADLException {
219     final URL srcFile = loader
220         .getResource(signature.replace('.', '/') + ".idl");
221     if (srcFile == null) {
222       throw new ADLException(IDLErrors.IDL_NOT_FOUND, signature);
223     }
224     return srcFile;
225   }
226 
227   protected void resolv(final ComplexType typeNode,
228       final IDLDefinition idlNode, final Map<String, DependantNode> toBeLoaded,
229       final ClassLoader loader, final Map<String, IDLDefinition> cache)
230       throws ADLException {
231     final String signatureToResolv = typeNode.getName();
232     final String resolvedSignature = resolveSignature(idlNode,
233         signatureToResolv, typeNode, loader);
234     addImport(resolvedSignature, (ImportContainer) idlNode);
235     final IDLDefinition definition = cache.get(resolvedSignature);
236     if (definition == null) {
237       // the IDL is not loaded, add it to the toBeLoaded map
238       DependantNode l = toBeLoaded.get(resolvedSignature);
239       if (l == null) {
240         l = new DependantNode();
241         toBeLoaded.put(resolvedSignature, l);
242       }
243       l.addComplexType(typeNode);
244     } else {
245       setContainedDefinition(typeNode, definition);
246     }
247   }
248 
249   /**
250    * Resolve the full qualified name of a signature.
251    */
252   protected String resolveSignature(final IDLDefinition idlNode,
253       final String signatureToResolv, final Node referencingNode,
254       final ClassLoader loader) throws ADLException {
255     final String idlSignature = idlNode.getName();
256     String resolvedSignature = null;
257     if (signatureToResolv.equals(idlSignature)) {
258       return idlSignature;
259     } else if (signatureToResolv.indexOf('.') != -1) {
260       // the signature contains a '.', it is a fully qualified name.
261       resolvedSignature = signatureToResolv;
262     } else {
263       for (final Import imp : ((ImportContainer) idlNode).getImports()) {
264         final String importName = imp.getName();
265         final String interfaceName = importName.substring(importName
266             .lastIndexOf('.') + 1);
267         if (signatureToResolv.equals(interfaceName)) {
268           resolvedSignature = importName;
269           break;
270         }
271       }
272 
273       if (resolvedSignature == null) {
274         // If the signature to resolv is used without package name and it is in
275         // the same package with the userSignature
276         final int i = idlSignature.lastIndexOf('.');
277         if (i < 0) {
278           resolvedSignature = signatureToResolv;
279         } else {
280           resolvedSignature = idlSignature.substring(0, i) + "."
281               + signatureToResolv;
282         }
283       }
284     }
285     try {
286       locate(resolvedSignature, loader);
287     } catch (final ADLException e) {
288       ChainedErrorLocator.chainLocator(e, referencingNode);
289       throw e;
290     }
291     return resolvedSignature;
292   }
293 
294   protected void check(final String signature, IDLDefinition node,
295       final Map<String, DependantNode> toBeLoaded,
296       final List<String> inheritancePath, final ClassLoader loader,
297       final Map<String, IDLDefinition> cache) throws ADLException {
298 
299     checkPackageSrcCompatibility(signature, node);
300     checkInterfaceNameSrcCompatibility(signature, node);
301     normalizeIDL(node, loader);
302 
303     /*
304      * insert the node signature as first element in the inheritance path at
305      * this point
306      */
307     InterfaceDecorationUtil.updateInheritancePathDecoration(node, signature);
308 
309     if (node instanceof InterfaceDefinition) {
310       final InterfaceDefinition interfaceDefinition = (InterfaceDefinition) node;
311       inheritancePath.add(signature);
312       String ext = null;
313       if (interfaceDefinition instanceof ExtendingDefinition) {
314         ext = ((ExtendingDefinition) interfaceDefinition).getExtends();
315         ((ExtendingDefinition) interfaceDefinition).setExtends(null);
316       }
317       if (ext != null) {
318 
319         final String resolvedSuperSignature = resolveSignature(node, ext, node,
320             loader);
321         if (inheritancePath.contains(resolvedSuperSignature)) {
322           throw new ADLException(IDLErrors.INHERITANCE_CYCLE,
323               interfaceDefinition, signature, resolvedSuperSignature);
324         }
325         final IDLDefinition def;
326         try {
327           def = loadIDL(resolvedSuperSignature, toBeLoaded, inheritancePath,
328               loader, cache);
329         } catch (final ADLException e) {
330           ChainedErrorLocator.chainLocator(e, interfaceDefinition);
331           throw e;
332         }
333         if (!(def instanceof InterfaceDefinition)) {
334           throw new ADLException(IDLErrors.INVALID_SUPER_INTERFACE,
335               interfaceDefinition, resolvedSuperSignature);
336         }
337         addImport(resolvedSuperSignature, (ImportContainer) node);
338         node = merge(def, node);
339       }
340       inheritancePath.remove(inheritancePath.size() - 1);
341 
342       for (final Field field : ((FieldContainer) interfaceDefinition)
343           .getFields()) {
344         final Type type = getContainedType(field);
345         if (isComplexType(type))
346           resolv(getComplexType(type), node, toBeLoaded, loader, cache);
347       }
348       for (final Method method : ((MethodContainer) interfaceDefinition)
349           .getMethods()) {
350         final Type returnType = getContainedType(method);
351         if (isComplexType(returnType))
352           resolv(getComplexType(returnType), node, toBeLoaded, loader, cache);
353 
354         for (final Parameter parameter : ((ParameterContainer) method)
355             .getParameters()) {
356           final Type parameterType = getContainedType(parameter);
357           if (isComplexType(parameterType))
358             resolv(getComplexType(parameterType), node, toBeLoaded, loader,
359                 cache);
360         }
361       }
362     } else if (node instanceof RecordDefinition) {
363       final RecordDefinition recordDefinition = (RecordDefinition) node;
364 
365       for (final Field field : ((FieldContainer) recordDefinition).getFields()) {
366         final Type type = getContainedType(field);
367         if (isComplexType(type))
368           resolv(getComplexType(type), node, toBeLoaded, loader, cache);
369       }
370     } else if (node instanceof UnionDefinition) {
371       final UnionDefinition unionDefinition = (UnionDefinition) node;
372 
373       for (final Field field : ((FieldContainer) unionDefinition).getFields()) {
374         final Type type = getContainedType(field);
375         if (isComplexType(type))
376           resolv(getComplexType(type), node, toBeLoaded, loader, cache);
377       }
378     } else if (node instanceof EnumDefinition) {
379       // DO NOTHING HERE
380     } else {
381       throw new CompilerError(GenericErrors.INTERNAL_ERROR,
382           new NodeErrorLocator(node), "Unrecognized IDL construct in '"
383               + signature + "'");
384     }
385   }
386 
387   protected IDLDefinition merge(final IDLDefinition superNode,
388       final IDLDefinition node) throws ADLException {
389     // add imports from superNode to node
390     final Set<String> imports = new HashSet<String>();
391     for (final Import i : ((ImportContainer) node).getImports())
392       imports.add(i.getName());
393 
394     // add import of superNode only if it is not already present in Node
395     for (final Import i : ((ImportContainer) superNode).getImports())
396       if (imports.add(i.getName())) ((ImportContainer) node).addImport(i);
397 
398     /*
399      * Add fields from 'superNode' to 'node'. Sub nodes of 'superNode' must be
400      * placed before sub nodes of 'node' (see bug #24670). So we need to remove
401      * fields and methods of 'node', then add those of 'superNode' and finally
402      * re-add 'node' ones.
403      */
404     final FieldContainer nodeFieldCtn = (FieldContainer) node;
405     final Field[] nodeFields = nodeFieldCtn.getFields();
406     final MethodContainer nodeMethodCtn = (MethodContainer) node;
407     final Method[] nodeMethods = nodeMethodCtn.getMethods();
408 
409     /*
410      * create a map of the sub nodes of node. Keys will be used to detect name
411      * clashes and values will be used to create DuplicatedNameException
412      */
413     final Map<String, Node> nodes = new HashMap<String, Node>();
414     for (final Field f : nodeFieldCtn.getFields()) {
415       nodes.put(f.getName(), f);
416       nodeFieldCtn.removeField(f);
417     }
418     for (final Method m : (nodeMethodCtn).getMethods()) {
419       nodes.put(m.getName(), m);
420       nodeMethodCtn.removeMethod(m);
421     }
422 
423     // add fields from superNode to node
424     for (final Field f : ((FieldContainer) superNode).getFields()) {
425       final Node n = nodes.put(f.getName(), f);
426       if (n != null) {
427         throw new ADLException(IDLErrors.DUPLICATED_FIELD_NAME, f, f.getName(),
428             new NodeErrorLocator(n));
429       }
430       nodeFieldCtn.addField(f);
431     }
432 
433     // add methods from superNode to node
434     for (final Method m : ((MethodContainer) superNode).getMethods()) {
435       final Node n = nodes.put(m.getName(), m);
436       if (n != null) {
437         throw new ADLException(IDLErrors.DUPLICATED_METHOD_NAME, m,
438             m.getName(), new NodeErrorLocator(n));
439       }
440       nodeMethodCtn.addMethod(m);
441     }
442 
443     // re-add fields from node
444     for (final Field field : nodeFields)
445       nodeFieldCtn.addField(field);
446 
447     // re-add methods from node
448     for (final Method method : nodeMethods)
449       nodeMethodCtn.addMethod(method);
450 
451     /* append the parent node signature in the inheritance path for this node */
452     InterfaceDecorationUtil.updateInheritancePathDecoration(node,
453         InterfaceDecorationUtil.getInheritancePathDecoration(superNode));
454 
455     // merge timestamps
456     Timestamp.setTimestamp(node, Timestamp.getTimestamp(superNode));
457     return node;
458   }
459 
460   protected void normalizeIDL(final IDLDefinition idlNode,
461       final ClassLoader loader) throws ADLException {
462     if (idlNode instanceof ImportContainer) {
463       for (final Import i : ((ImportContainer) idlNode).getImports()) {
464         try {
465           locate(i.getName(), loader);
466         } catch (final ADLException e) {
467           ChainedErrorLocator.chainLocator(e, i);
468           throw e;
469         }
470       }
471     }
472     final Map<String, Node> nodes = new HashMap<String, Node>();
473     // Check for incorrectly named interfaces.
474     if (isReservedCWord(idlNode.getName())) {
475       throw new ADLException(IDLErrors.IDL_NAME_IS_RESERVED_WORD, idlNode,
476           idlNode.getName());
477     }
478 
479     // Check for duplicate fields
480     if (idlNode instanceof FieldContainer) {
481       for (final Field f : ((FieldContainer) idlNode).getFields()) {
482         if (isReservedCWord(f.getName())) {
483           throw new ADLException(IDLErrors.IDL_NAME_IS_RESERVED_WORD, f, f
484               .getName());
485         }
486         final Node n = nodes.put(f.getName(), f);
487         if (n != null)
488           throw new ADLException(IDLErrors.DUPLICATED_FIELD_NAME, f, f
489               .getName(), new NodeErrorLocator(n));
490       }
491     }
492     // Check for duplicate methods, or methods with duplicated parameter names.
493     if (idlNode instanceof MethodContainer) {
494       for (final Method m : ((MethodContainer) idlNode).getMethods()) {
495         if (isReservedCWord(m.getName())) {
496           throw new ADLException(IDLErrors.IDL_NAME_IS_RESERVED_WORD, m, m
497               .getName());
498         }
499         final Node previousDeclaration = nodes.put(m.getName(), m);
500         if (previousDeclaration != null)
501           throw new ADLException(IDLErrors.DUPLICATED_METHOD_NAME, m, m
502               .getName(), new NodeErrorLocator(previousDeclaration));
503         final Map<String, Node> params = new HashMap<String, Node>();
504         for (final Parameter p : m.getParameters()) {
505           if (isReservedCWord(p.getName())) {
506             throw new ADLException(IDLErrors.IDL_NAME_IS_RESERVED_WORD, p, p
507                 .getName());
508           }
509           final Node n1 = params.put(p.getName(), p);
510           if (n1 != null) {
511             throw new ADLException(IDLErrors.DUPLICATED_PARAMETER_NAME, p, p
512                 .getName(), new NodeErrorLocator(n1));
513           }
514         }
515       }
516     }
517   }
518 
519   protected XMLNode newNode(final String name) {
520     try {
521       return nodeFactoryItf.newXMLNode(CeciliaIDLConstants.CECILIA_IDL_DTD,
522           name);
523     } catch (final SAXException e) {
524       throw new CompilerError(GenericErrors.INTERNAL_ERROR, e,
525           "Unable to create node \"" + name + "\"");
526     }
527   }
528 
529   protected void addImport(final String signature,
530       final ImportContainer importContainer) {
531     for (final Import i : importContainer.getImports()) {
532       if (i.getName().equals(signature)) return;
533     }
534     final Import newImport = (Import) newNode("import");
535     newImport.setName(signature);
536     importContainer.addImport(newImport);
537   }
538 
539   protected void addComplexType(final IDLDefinition node,
540       final TypeContainer complexTypeContainer) {
541     // Test if there is already a sub-element
542     if (complexTypeContainer.getComplexType() == null) {
543       throw new IllegalStateException("There is already a sub element");
544     }
545     final ComplexType ct = (ComplexType) newNode("complexType");
546     ct.setIDLDefinition(node);
547     complexTypeContainer.setComplexType(ct);
548   }
549 
550   protected void checkPackageSrcCompatibility(final String signature,
551       final IDLDefinition node) throws ADLException {
552     final String nodeSignature = node.getName();
553     final String nodePkgName = (nodeSignature.lastIndexOf('.') < 0)
554         ? ""
555         : nodeSignature.substring(0, nodeSignature.lastIndexOf('.'));
556     final String expPkgName = (signature.lastIndexOf('.') < 0) ? "" : signature
557         .substring(0, signature.lastIndexOf('.'));
558     if (!expPkgName.equals(nodePkgName))
559       throw new ADLException(IDLErrors.INVALID_PACKAGE_NAME, node, nodePkgName,
560           expPkgName);
561   }
562 
563   protected void checkInterfaceNameSrcCompatibility(final String signature,
564       final IDLDefinition node) throws ADLException {
565     final String nodeSignature = node.getName();
566     final String nodeItfName = (nodeSignature.lastIndexOf('.') < 0)
567         ? nodeSignature
568         : nodeSignature.substring(nodeSignature.lastIndexOf('.') + 1);
569     final String expItfName = (signature.lastIndexOf('.') < 0)
570         ? signature
571         : signature.substring(signature.lastIndexOf('.') + 1);
572     if (!expItfName.equals(nodeItfName))
573       throw new ADLException(IDLErrors.INVALID_IDL_NAME, node, nodeItfName,
574           expItfName);
575   }
576 
577   protected static final class DependantNode {
578     private List<ComplexType> types;
579     private List<Import>      imports;
580 
581     protected void addComplexType(final ComplexType type) {
582       if (types == null) types = new ArrayList<ComplexType>();
583       types.add(type);
584     }
585 
586     protected void addImport(final Import i) {
587       if (imports == null) imports = new ArrayList<Import>();
588       imports.add(i);
589     }
590 
591     protected void setDefinition(final IDLDefinition def) {
592 
593       if (types != null) {
594         for (final ComplexType ct : types) {
595           ct.setIDLDefinition(def);
596         }
597       }
598 
599       if (imports != null) {
600         for (final Import i : imports)
601           setImportedAST(i, def);
602       }
603     }
604   }
605 
606   // ---------------------------------------------------------------------------
607   // Implementation of the BindingController interface
608   // ---------------------------------------------------------------------------
609 
610   public void bindFc(final String itfName, final Object value)
611       throws NoSuchInterfaceException, IllegalBindingException,
612       IllegalLifeCycleException {
613 
614     if (itfName == null) {
615       throw new IllegalArgumentException("Interface name can't be null");
616     }
617 
618     if (itfName.equals(NODE_FACTORY_ITF_NAME)) {
619       this.nodeFactoryItf = (XMLNodeFactory) value;
620     } else {
621       throw new NoSuchInterfaceException("There is no interface named '"
622           + itfName + "'");
623     }
624 
625   }
626 
627   public String[] listFc() {
628     return new String[]{NODE_FACTORY_ITF_NAME};
629   }
630 
631   public Object lookupFc(final String itfName) throws NoSuchInterfaceException {
632 
633     if (itfName == null) {
634       throw new IllegalArgumentException("Interface name can't be null");
635     }
636 
637     if (itfName.equals(NODE_FACTORY_ITF_NAME)) {
638       return this.nodeFactoryItf;
639     } else {
640       throw new NoSuchInterfaceException("There is no interface named '"
641           + itfName + "'");
642     }
643   }
644 
645   public void unbindFc(final String itfName) throws NoSuchInterfaceException,
646       IllegalBindingException, IllegalLifeCycleException {
647 
648     if (itfName == null) {
649       throw new IllegalArgumentException("Interface name can't be null");
650     }
651 
652     if (itfName.equals(NODE_FACTORY_ITF_NAME)) {
653       this.nodeFactoryItf = null;
654     } else {
655       throw new NoSuchInterfaceException("There is no interface named '"
656           + itfName + "'");
657     }
658   }
659 }