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 java.util.HashSet;
27  import java.util.Set;
28  
29  import org.objectweb.fractal.adl.attributes.Attributes;
30  import org.objectweb.fractal.adl.attributes.AttributesContainer;
31  import org.objectweb.fractal.adl.components.ComponentContainer;
32  import org.objectweb.fractal.adl.implementations.Controller;
33  import org.objectweb.fractal.adl.implementations.ControllerContainer;
34  import org.objectweb.fractal.adl.implementations.Implementation;
35  import org.objectweb.fractal.adl.implementations.ImplementationContainer;
36  import org.objectweb.fractal.adl.interfaces.Interface;
37  import org.objectweb.fractal.adl.interfaces.InterfaceContainer;
38  import org.objectweb.fractal.adl.types.TypeInterface;
39  import org.objectweb.fractal.cecilia.adl.directives.Cflag;
40  import org.objectweb.fractal.cecilia.adl.directives.CflagContainer;
41  import org.objectweb.fractal.cecilia.adl.directives.Include;
42  import org.objectweb.fractal.cecilia.adl.directives.IncludeContainer;
43  import org.objectweb.fractal.cecilia.adl.directives.Ldflag;
44  import org.objectweb.fractal.cecilia.adl.directives.LdflagContainer;
45  import org.objectweb.fractal.cecilia.adl.implementations.ExtendedImplementation;
46  
47  /**
48   * Descriptor of component definition. It is used by
49   * {@link PrimitiveDefinitionCompiler} to find if a component of the same type
50   * has already been compiled. Two components have the same type if and only if
51   * they have the same implementation, the same interfaces, the same attribute
52   * signature and the same compilation flags.
53   */
54  public class ComponentTypeDesc {
55  
56    private int                        hashCode = 0;
57  
58    protected final ComponentContainer container;
59  
60    // --------------------------------------------------------------------------
61    // Constructor
62    // --------------------------------------------------------------------------
63  
64    protected ComponentTypeDesc(final ComponentContainer container) {
65      this.container = container;
66      computeHashCode();
67    }
68  
69    // --------------------------------------------------------------------------
70    // Overridden Object methods
71    // --------------------------------------------------------------------------
72  
73    @Override
74    public boolean equals(final Object o) {
75      final ComponentContainer container1 = ((ComponentTypeDesc) o).container;
76  
77      // compare implementations
78      if (container instanceof ImplementationContainer) {
79        final Implementation impl = ((ImplementationContainer) container)
80            .getImplementation();
81        if (container1 instanceof ImplementationContainer) {
82          final Implementation impl1 = ((ImplementationContainer) container1)
83              .getImplementation();
84          if (impl != null || impl1 != null) {
85            if (impl == null || impl1 == null) return false;
86            if (!equalsIgnoreNull(impl.getClassName(), impl1.getClassName()))
87              return false;
88          }
89  
90          final Set<String> contentElementSet = new HashSet<String>();
91          final Set<String> contentElementSet1 = new HashSet<String>();
92          contentElementsSet(impl, contentElementSet);
93          contentElementsSet(impl1, contentElementSet1);
94          if (contentElementSet.size() != contentElementSet1.size()
95              || !contentElementSet.containsAll(contentElementSet1))
96            return false;
97  
98        } else { // container1 NOT instanceof ImplementationContainer
99          if (impl != null) return false;
100       }
101     } else if (container1 instanceof ImplementationContainer) {
102       if (((ImplementationContainer) container1).getImplementation() != null)
103         return false;
104     }
105 
106     // compare interfaces
107     if (container instanceof InterfaceContainer) {
108       final Interface[] itfs = ((InterfaceContainer) container).getInterfaces();
109       if (container1 instanceof InterfaceContainer) {
110         final Interface[] itfs1 = ((InterfaceContainer) container1)
111             .getInterfaces();
112         for (final Interface itf : itfs) {
113           if (itf.getName().endsWith("-controller")) continue;
114           boolean found = false;
115           for (final Interface itf1 : itfs1) {
116             if (!equalsIgnoreNull(itf.getName(), itf1.getName())) continue;
117             if (itf instanceof TypeInterface) {
118               if (!(itf1 instanceof TypeInterface)) continue;
119               final TypeInterface itfType = (TypeInterface) itf;
120               final TypeInterface itfType1 = (TypeInterface) itf1;
121               if (!equalsIgnoreNull(itfType.getSignature(), itfType1
122                   .getSignature())) continue;
123               if (!equalsIgnoreNull(itfType.getRole(), itfType1.getRole()))
124                 continue;
125               if (!equalsIgnoreNull(itfType.getContingency(), itfType1
126                   .getContingency())) continue;
127             }
128             found = true;
129             break;
130           }
131           if (!found) return false;
132         }
133       } else { // container1 NOT instanceof InterfaceContainer
134         if (itfs != null && itfs.length != 0) return false;
135       }
136     } else if (container1 instanceof InterfaceContainer) {
137       final Interface[] itfs1 = ((InterfaceContainer) container1)
138           .getInterfaces();
139       if (itfs1 != null && itfs1.length != 0) return false;
140     }
141 
142     // compare attributes
143     if (container instanceof AttributesContainer) {
144       final Attributes attrs = ((AttributesContainer) container)
145           .getAttributes();
146       if (container1 instanceof AttributesContainer) {
147         final Attributes attrs1 = ((AttributesContainer) container1)
148             .getAttributes();
149         if (attrs != null || attrs1 != null) {
150           if (attrs == null || attrs1 == null) return false;
151           if (!equalsIgnoreNull(attrs.getSignature(), attrs1.getSignature()))
152             return false;
153         }
154       } else { // container1 NOT instanceof AttributesContainer
155         if (attrs != null) return false;
156       }
157     } else if (container1 instanceof AttributesContainer) {
158       if (((AttributesContainer) container1).getAttributes() != null)
159         return false;
160     }
161 
162     // compare controller
163     if (container instanceof ControllerContainer) {
164       final Controller controller = ((ControllerContainer) container)
165           .getController();
166       if (container1 instanceof ControllerContainer) {
167         final Controller controller1 = ((ControllerContainer) container1)
168             .getController();
169         if (controller != null || controller1 != null) {
170           if (controller == null || controller1 == null) return false;
171           if (!equalsIgnoreNull(controller.getDescriptor(), controller1
172               .getDescriptor())) return false;
173         }
174       } else { // container1 NOT instanceof ControllerContainer
175         if (controller != null) return false;
176       }
177     } else if (container1 instanceof ControllerContainer) {
178       if (((ControllerContainer) container1).getController() != null)
179         return false;
180     }
181 
182     return true;
183   }
184 
185   @Override
186   public int hashCode() {
187     return hashCode;
188   }
189 
190   // --------------------------------------------------------------------------
191   // Utility methods
192   // --------------------------------------------------------------------------
193 
194   private void computeHashCode() {
195     hashCode = 23;
196     if (container instanceof ImplementationContainer) {
197       final Implementation impl = ((ImplementationContainer) container)
198           .getImplementation();
199       if (impl != null && impl.getClassName() != null)
200         hashCode += impl.getClassName().hashCode() * 37;
201     }
202 
203     if (container instanceof InterfaceContainer) {
204       final Interface[] itfs = ((InterfaceContainer) container).getInterfaces();
205       for (final Interface element : itfs) {
206         if (element.getName() != null)
207           hashCode += element.getName().hashCode() * 127;
208       }
209     }
210 
211     if (container instanceof AttributesContainer) {
212       final Attributes attrs = ((AttributesContainer) container)
213           .getAttributes();
214       if (attrs != null) hashCode += attrs.getSignature().hashCode() * 73;
215     }
216   }
217 
218   protected static boolean equalsIgnoreNull(final Object o1, final Object o2) {
219     if (o1 == null) return o2 == null;
220     return o2 != null && o1.equals(o2);
221   }
222 
223   protected static void contentElementsSet(final Implementation impl,
224       final Set<String> elementSet) {
225     if (impl == null) return;
226 
227     String language = "";
228     if (impl instanceof ExtendedImplementation)
229       language = ((ExtendedImplementation) impl).getLanguage();
230     if (impl instanceof CflagContainer) {
231       final String header = language + "_CFLAG_";
232       for (final Cflag cflag : ((CflagContainer) impl).getCflags())
233         elementSet.add(header + cflag.getValue());
234     }
235     if (impl instanceof LdflagContainer) {
236       final String header = language + "_LDFLAG_";
237       for (final Ldflag ldflag : ((LdflagContainer) impl).getLdflags())
238         elementSet.add(header + ldflag.getValue());
239     }
240     if (impl instanceof IncludeContainer) {
241       final String header = language + "_INCLUDE_";
242       for (final Include include : ((IncludeContainer) impl).getIncludes())
243         elementSet.add(header + include.getFile());
244     }
245   }
246 
247 }