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: Matthieu Leclercq
22   */
23  
24  package org.objectweb.fractal.cecilia.adl.types;
25  
26  import static org.objectweb.fractal.cecilia.adl.types.TypeDecorationUtil.setTypeDecoration;
27  
28  import java.util.HashMap;
29  import java.util.List;
30  import java.util.Map;
31  
32  import org.objectweb.fractal.adl.ADLException;
33  import org.objectweb.fractal.adl.ComponentVisitor;
34  import org.objectweb.fractal.adl.ContextLocal;
35  import org.objectweb.fractal.adl.Node;
36  import org.objectweb.fractal.adl.components.ComponentContainer;
37  import org.objectweb.fractal.adl.interfaces.Interface;
38  import org.objectweb.fractal.adl.interfaces.InterfaceContainer;
39  import org.objectweb.fractal.api.Component;
40  import org.objectweb.fractal.api.NoSuchInterfaceException;
41  import org.objectweb.fractal.api.control.BindingController;
42  import org.objectweb.fractal.api.control.IllegalBindingException;
43  import org.objectweb.fractal.api.control.IllegalLifeCycleException;
44  import org.objectweb.fractal.task.core.TaskException;
45  
46  /**
47   * This visitor determines the type of a given primitive component and if this
48   * type is already defined. If the type is not yet defined, this visitor calls
49   * its {@link #definitionVisitorItf} client interface, otherwise it returns
50   * <code>null</code>.
51   * 
52   * @see ComponentTypeDesc
53   */
54  public class PrimitiveTypeDefinitionFilter
55      implements
56        ComponentVisitor,
57        BindingController {
58  
59    /**
60     * A context local map associating {@link ComponentTypeDesc} to themselves.
61     * Note that : thanks to the implementation of the
62     * {@link ComponentTypeDesc#equals(Object) equals} method of this class, if
63     * two components A and B share the same type, then ComponentTypeDesc(A) is
64     * equals to ComponentTypeDesc(B).
65     */
66    protected final ContextLocal<Map<ComponentTypeDesc, ComponentTypeDesc>> componentTypes              = new ContextLocal<Map<ComponentTypeDesc, ComponentTypeDesc>>();
67  
68    // ---------------------------------------------------------------------------
69    // Client interfaces
70    // ---------------------------------------------------------------------------
71  
72    /** The name of the {@link #definitionVisitorItf} client interface. */
73    public static final String                                              DEFINITION_VISITOR_ITF_NAME = "definition-visitor";
74  
75    /**
76     * The {@link ComponentVisitor} client interface use to create the task that
77     * defines the component type.
78     */
79    public ComponentVisitor                                                 definitionVisitorItf;
80  
81    // ---------------------------------------------------------------------------
82    // Implementation of the ComponentVisitor interface
83    // ---------------------------------------------------------------------------
84  
85    public Component visit(final List<Node> path,
86        final ComponentContainer container, final Map<Object, Object> context)
87        throws ADLException, TaskException {
88      if (needTypeDefinition(path, container, context)) {
89        return definitionVisitorItf.visit(path, container, context);
90      } else {
91        return null;
92      }
93    }
94  
95    // --------------------------------------------------------------------------
96    // Utility methods
97    // --------------------------------------------------------------------------
98  
99    protected boolean needTypeDefinition(final List<Node> path,
100       final ComponentContainer container, final Map<Object, Object> context)
101       throws ADLException, TaskException {
102 
103     // retrieve the component type map for the current context
104     Map<ComponentTypeDesc, ComponentTypeDesc> types = componentTypes
105         .get(context);
106     if (types == null) {
107       types = new HashMap<ComponentTypeDesc, ComponentTypeDesc>();
108       componentTypes.set(context, types);
109     }
110 
111     // compute component definition descriptor
112     final ComponentTypeDesc componentDefDesc = new ComponentTypeDesc(container);
113 
114     // look for a component previously compiled with the same definition
115     // descriptor.
116     final ComponentTypeDesc typeComp = types.get(componentDefDesc);
117     if (typeComp == null) {
118       // the component has an unknown type.
119       // add it in the component type map
120       types.put(componentDefDesc, componentDefDesc);
121 
122       // set the type decoration
123       setTypeDecoration(container, container);
124 
125       // this component defines a new type, so return true.
126       return true;
127     } else {
128       // the component has a known type
129 
130       // set the type decoration
131       setTypeDecoration(container, typeComp.container);
132 
133       /*
134        * 'container' has the same set of interface as 'typeComp', but they may
135        * not be in the same order. We must ensure that the 'container' component
136        * and the 'typeComp' component have their interfaces in the same order.
137        */
138       if (container instanceof InterfaceContainer) {
139         final Map<String, Interface> itfs = new HashMap<String, Interface>();
140         // We first remove all the interfaces of 'container' and store
141         // them in a map.
142         final InterfaceContainer interfaceContainer = (InterfaceContainer) container;
143         for (final Interface itf : interfaceContainer.getInterfaces()) {
144           itfs.put(itf.getName(), itf);
145           interfaceContainer.removeInterface(itf);
146         }
147         // Then re-add the stored interfaces respecting the order of 'typeComp'.
148         for (final Interface itf : ((InterfaceContainer) typeComp.container)
149             .getInterfaces()) {
150           interfaceContainer.addInterface(itfs.get(itf.getName()));
151         }
152       }
153 
154       // this component does not define a new type, return false.
155       return false;
156     }
157   }
158 
159   // ---------------------------------------------------------------------------
160   // Implementation of the BindingController interface
161   // ---------------------------------------------------------------------------
162 
163   public String[] listFc() {
164     return new String[]{DEFINITION_VISITOR_ITF_NAME};
165   }
166 
167   public void bindFc(final String clientItfName, final Object serverItf)
168       throws NoSuchInterfaceException, IllegalBindingException,
169       IllegalLifeCycleException {
170 
171     if (clientItfName == null) {
172       throw new IllegalArgumentException("Interface name can't be null");
173     }
174 
175     if (DEFINITION_VISITOR_ITF_NAME.equals(clientItfName))
176       definitionVisitorItf = (ComponentVisitor) serverItf;
177     else
178       throw new NoSuchInterfaceException("There is no interface named '"
179           + clientItfName + "'");
180   }
181 
182   public Object lookupFc(final String clientItfName)
183       throws NoSuchInterfaceException {
184 
185     if (clientItfName == null) {
186       throw new IllegalArgumentException("Interface name can't be null");
187     }
188 
189     if (DEFINITION_VISITOR_ITF_NAME.equals(clientItfName))
190       return definitionVisitorItf;
191     else
192       throw new NoSuchInterfaceException("There is no interface named '"
193           + clientItfName + "'");
194   }
195 
196   public void unbindFc(final String clientItfName)
197       throws NoSuchInterfaceException, IllegalBindingException,
198       IllegalLifeCycleException {
199 
200     if (clientItfName == null) {
201       throw new IllegalArgumentException("Interface name can't be null");
202     }
203 
204     if (DEFINITION_VISITOR_ITF_NAME.equals(clientItfName))
205       definitionVisitorItf = null;
206     else
207       throw new NoSuchInterfaceException("There is no interface named '"
208           + clientItfName + "'");
209   }
210 }