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.idl;
25  
26  import static java.util.Arrays.asList;
27  import static org.objectweb.fractal.adl.NodeUtil.castNodeError;
28  import static org.objectweb.fractal.cecilia.adl.idl.util.Util.getImportedAST;
29  
30  import java.util.ArrayList;
31  import java.util.HashMap;
32  import java.util.HashSet;
33  import java.util.List;
34  import java.util.Map;
35  import java.util.Set;
36  
37  import org.objectweb.fractal.adl.ADLException;
38  import org.objectweb.fractal.adl.Definition;
39  import org.objectweb.fractal.adl.DefinitionVisitor;
40  import org.objectweb.fractal.adl.Node;
41  import org.objectweb.fractal.adl.attributes.Attributes;
42  import org.objectweb.fractal.adl.attributes.AttributesContainer;
43  import org.objectweb.fractal.adl.components.ComponentContainer;
44  import org.objectweb.fractal.adl.interfaces.Interface;
45  import org.objectweb.fractal.adl.interfaces.InterfaceContainer;
46  import org.objectweb.fractal.api.Component;
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.idl.ast.IDLDefinition;
52  import org.objectweb.fractal.cecilia.adl.idl.ast.IDLDefinitionContainer;
53  import org.objectweb.fractal.cecilia.adl.idl.ast.Import;
54  import org.objectweb.fractal.cecilia.adl.idl.ast.ImportContainer;
55  import org.objectweb.fractal.task.core.AbstractTaskFactoryUser;
56  import org.objectweb.fractal.task.core.TaskException;
57  
58  /**
59   * Travels the component's interfaces and attribute definitions and invokes
60   * recursively its client IDL visitor interfaces for all these definitions as
61   * well as all the definitions which are referenced.
62   */
63  public class RecursiveIDLDispatchVisitor extends AbstractTaskFactoryUser
64      implements
65        DefinitionVisitor,
66        BindingController {
67  
68    /** The composition schema used by this dispatcher. */
69    public static final String               TASK_FILE_NAME         = "org.objectweb.fractal.cecilia.adl.idl.IDLTask";
70  
71    // ---------------------------------------------------------------------------
72    // Client interfaces
73    // ---------------------------------------------------------------------------
74  
75    /** The name of the builder collection interface. */
76    public static final String               CLIENT_VISITORITF_NAME = "client-visitor";
77    /** The builders client interfaces. */
78    public Map<String, IDLDefinitionVisitor> visitorsItf            = new HashMap<String, IDLDefinitionVisitor>();
79  
80    // ---------------------------------------------------------------------------
81    // Implementation of the PrimitiveCompiler interface
82    // ---------------------------------------------------------------------------
83  
84    public Component visit(final List<Node> path, final Definition container,
85        final Map<Object, Object> context) throws ADLException, TaskException {
86  
87      final List<Component> taskComponents = new ArrayList<Component>();
88      final Set<String> visitedIDL = new HashSet<String>();
89  
90      visiteComponentContainer(path, (ComponentContainer) container,
91          taskComponents, visitedIDL, context);
92      return taskFactoryItf
93          .newCompositeTask(taskComponents, TASK_FILE_NAME, null);
94    }
95  
96    // ---------------------------------------------------------------------------
97    // Utility method
98    // ---------------------------------------------------------------------------
99  
100   private void visiteComponentContainer(final List<Node> path,
101       final ComponentContainer container, final List<Component> taskComponents,
102       final Set<String> visitedIDL, final Map<Object, Object> context)
103       throws ADLException, TaskException {
104 
105     path.add(container);
106     try {
107       for (final org.objectweb.fractal.adl.components.Component subComp : container
108           .getComponents()) {
109         visiteComponentContainer(path, subComp, taskComponents, visitedIDL,
110             context);
111       }
112 
113       if (container instanceof InterfaceContainer) {
114         for (final Interface itf : ((InterfaceContainer) container)
115             .getInterfaces()) {
116           invokeVisitors(path, castNodeError(itf, IDLDefinitionContainer.class)
117               .getIDLDefinition(), taskComponents, visitedIDL, context);
118         }
119       }
120       if (container instanceof AttributesContainer) {
121         final Attributes attributes = ((AttributesContainer) container)
122             .getAttributes();
123         if (attributes != null) {
124           invokeVisitors(path, castNodeError(attributes,
125               IDLDefinitionContainer.class).getIDLDefinition(), taskComponents,
126               visitedIDL, context);
127         }
128       }
129 
130     } finally {
131       path.remove(path.size() - 1);
132     }
133   }
134 
135   private void invokeVisitors(final List<Node> path,
136       final IDLDefinition idlDefinition, final List<Component> taskComponents,
137       final Set<String> visitedIDL, final Map<Object, Object> context)
138       throws ADLException, TaskException {
139 
140     // add the IDLDefinition's name in cache. If it is not added (i.e. it is
141     // already processed), that is the corresponding task component is already
142     // added. In this case, returns.
143     if (!visitedIDL.add(idlDefinition.getName())) return;
144 
145     // Invoke all the client idl-compiler interfaces for this IDL definition
146     for (final IDLDefinitionVisitor idlVisitor : visitorsItf.values()) {
147       final Component task = idlVisitor.visit(path, idlDefinition, context);
148       if (task != null) taskComponents.add(task);
149     }
150     if (idlDefinition instanceof ImportContainer) {
151       for (final Import imp : ((ImportContainer) idlDefinition).getImports()) {
152         final Node importedAST = getImportedAST(imp);
153         if (importedAST instanceof IDLDefinition) {
154           final IDLDefinition importedDef = (IDLDefinition) importedAST;
155           invokeVisitors(path, importedDef, taskComponents, visitedIDL, context);
156         }
157       }
158     }
159   }
160 
161   // ---------------------------------------------------------------------------
162   // Implementation of the BindignController interface
163   // ---------------------------------------------------------------------------
164 
165   @Override
166   public String[] listFc() {
167     final List<String> interfaceList = new ArrayList<String>(visitorsItf
168         .keySet());
169     interfaceList.addAll(asList(super.listFc()));
170     return interfaceList.toArray(new String[interfaceList.size()]);
171   }
172 
173   @Override
174   public Object lookupFc(final String clientItfName)
175       throws NoSuchInterfaceException {
176 
177     if (clientItfName == null) {
178       throw new IllegalArgumentException("Interface name can't be null");
179     }
180 
181     if (clientItfName.startsWith(CLIENT_VISITORITF_NAME)) {
182       return visitorsItf.get(clientItfName);
183     } else {
184       return super.lookupFc(clientItfName);
185     }
186   }
187 
188   @Override
189   public void bindFc(final String clientItfName, final Object serverItf)
190       throws NoSuchInterfaceException, IllegalBindingException,
191       IllegalLifeCycleException {
192 
193     if (clientItfName == null) {
194       throw new IllegalArgumentException("Interface name can't be null");
195     }
196 
197     if (clientItfName.startsWith(CLIENT_VISITORITF_NAME)) {
198       visitorsItf.put(clientItfName, (IDLDefinitionVisitor) serverItf);
199     } else {
200       super.bindFc(clientItfName, serverItf);
201     }
202   }
203 
204   @Override
205   public void unbindFc(final String clientItfName)
206       throws NoSuchInterfaceException, IllegalBindingException,
207       IllegalLifeCycleException {
208 
209     if (clientItfName == null) {
210       throw new IllegalArgumentException("Interface name can't be null");
211     }
212 
213     if (clientItfName.startsWith(CLIENT_VISITORITF_NAME)) {
214       visitorsItf.remove(clientItfName);
215     } else {
216       super.unbindFc(clientItfName);
217     }
218   }
219 }