1 package org.andromda.core.metafacade;
2
3 import java.lang.reflect.Constructor;
4 import java.util.Arrays;
5 import java.util.Collection;
6 import java.util.HashMap;
7 import java.util.HashSet;
8 import java.util.Map;
9 import java.util.Set;
10 import org.andromda.core.common.ClassUtils;
11 import org.andromda.core.common.Introspector;
12 import org.andromda.core.configuration.Namespaces;
13 import org.apache.commons.collections.CollectionUtils;
14 import org.apache.commons.collections.Predicate;
15 import org.apache.log4j.Logger;
16
17
18
19
20
21
22
23 final class MetafacadeUtils
24 {
25
26
27
28
29
30
31
32
33 static boolean propertiesValid(
34 final MetafacadeBase metafacade,
35 final MetafacadeMapping mapping)
36 {
37 boolean valid = false;
38 final Collection<MetafacadeMapping.PropertyGroup> propertyGroups = mapping.getMappingPropertyGroups();
39 if (propertyGroups != null && !propertyGroups.isEmpty())
40 {
41 try
42 {
43 if (getLogger().isDebugEnabled())
44 {
45 getLogger().debug(
46 "evaluating " + propertyGroups.size() + " property groups(s) on metafacade '" + metafacade +
47 '\'');
48 }
49 final Introspector introspector = Introspector.instance();
50 for (final MetafacadeMapping.PropertyGroup propertyGroup : propertyGroups)
51 {
52 for (final MetafacadeMapping.Property property : propertyGroup.getProperties())
53 {
54 valid = introspector.containsValidProperty(
55 metafacade,
56 property.getName(),
57 property.getValue());
58 if (getLogger().isDebugEnabled())
59 {
60 getLogger().debug(
61 "property '" + property.getName() + "', with value '" + property.getValue() +
62 "' on metafacade '" + metafacade + "', evaluated to --> '" + valid + '\'');
63 }
64
65
66
67 if (!valid)
68 {
69 break;
70 }
71 }
72
73
74
75 if (valid)
76 {
77 break;
78 }
79 }
80 }
81 catch (final Throwable throwable)
82 {
83 if (getLogger().isDebugEnabled())
84 {
85 getLogger().debug(
86 "An error occurred while " + "evaluating properties on metafacade '" + metafacade +
87 "', setting valid to 'false'",
88 throwable);
89 }
90 valid = false;
91 }
92 if (getLogger().isDebugEnabled())
93 {
94 getLogger().debug(
95 "completed evaluating " + propertyGroups.size() + " properties on metafacade '" + metafacade +
96 "' with a result of --> '" + valid + '\'');
97 }
98 }
99 return valid;
100 }
101
102
103
104
105
106
107
108
109
110
111
112 static MetafacadeBase constructMetafacade(
113 final Class metafacadeClass,
114 final Object mappingObject,
115 final String context)
116 throws Exception
117 {
118 if (getLogger().isDebugEnabled())
119 {
120 getLogger().debug(
121 "constructing metafacade from class '" + metafacadeClass + "' mapping object '" + mappingObject +
122 "', and context '" + context + '\'');
123 }
124 final Constructor constructor = metafacadeClass.getDeclaredConstructors()[0];
125 return (MetafacadeBase)constructor.newInstance(mappingObject, context);
126 }
127
128
129
130
131
132
133
134
135
136 private static Set<String> intersection(Set<String> nameSet1, Set<String> nameSet2)
137 {
138 Set<String> results = new HashSet<String>();
139 if(nameSet1 == null || nameSet2 == null)
140 {
141 return results;
142 }
143
144 Map<Class<?>, String> classesToName = new HashMap<Class<?>, String>();
145 Set<Class<?>> classesSet1 = getClassesFromNames(nameSet1, classesToName);
146 Set<Class<?>> classesSet2 = getClassesFromNames(nameSet2, classesToName);
147
148 for(final Class<?> classToCheck : classesSet1)
149 {
150 Set<Class> classToCheckInterfaces = new HashSet<Class>(Arrays.asList(classToCheck.getInterfaces()));
151 for(final Class<?> expectedResult : classesSet2)
152 {
153 if(classToCheck.isAssignableFrom(expectedResult))
154 {
155 results.add(classesToName.get(expectedResult));
156 }
157 else if(expectedResult.isAssignableFrom(classToCheck))
158 {
159 results.add(classesToName.get(classToCheck));
160 }
161 else {
162
163 boolean expectedResultNotCompliant = CollectionUtils.exists(classToCheckInterfaces, new Predicate()
164 {
165 public boolean evaluate(Object object)
166 {
167 Class<?> classToCheckInterface = (Class<?>)object;
168 return !classToCheckInterface.isAssignableFrom(expectedResult);
169 }
170 });
171 if (!expectedResultNotCompliant) {
172 results.add(classesToName.get(expectedResult));
173 } else {
174 Set<Class> expectedResultInterfaces = new HashSet<Class>(Arrays.asList(expectedResult.getInterfaces()));
175 boolean classToCheckNotCompliant = CollectionUtils.exists(expectedResultInterfaces, new Predicate()
176 {
177 public boolean evaluate(Object object)
178 {
179 Class<?> expectedResultInterface = (Class<?>)object;
180 return !expectedResultInterface.isAssignableFrom(classToCheck);
181 }
182 });
183 if (!classToCheckNotCompliant) {
184 results.add(classesToName.get(classToCheck));
185 }
186 }
187 }
188 }
189 }
190 return results;
191 }
192
193
194
195
196
197
198
199
200
201
202 private static Set<Class<?>> getClassesFromNames(Set<String> nameSet, Map<Class<?>, String> classesToName)
203 {
204 final Set<Class<?>> classesSet = new HashSet<Class<?>>();
205 for(final String name : nameSet)
206 {
207 try
208 {
209 Class<?> cl = Class.forName(name);
210 classesToName.put(cl, name);
211 classesSet.add(cl);
212 }
213 catch (ClassNotFoundException e1)
214 {
215
216 try
217 {
218 String instanciatedName = name;
219 if(instanciatedName.endsWith("$Impl"))
220 {
221 instanciatedName = name.substring(0, name.lastIndexOf("$Impl"));
222 }
223 Class<?> cl = Class.forName(instanciatedName);
224 classesToName.put(cl, name);
225 classesSet.add(cl);
226 }
227 catch (ClassNotFoundException e2)
228 {
229 throw new RuntimeException(e2);
230 }
231 }
232 }
233 return classesSet;
234 }
235
236
237
238
239
240
241
242
243
244
245 private static Set<String> getInheritedMappingClassNames(final Class metafacadeClass, final MetafacadeImpls metafacadeImpls, final Map<Class, Set<String>> mappingInstances )
246 {
247 Set<String> result = null;
248 if(metafacadeClass != null)
249 {
250 if(metafacadeClass.isInterface())
251 {
252 result = mappingInstances.get(metafacadeImpls.getMetafacadeImplClass(metafacadeClass.getName()));
253 }
254 if(result == null)
255 {
256 for(Class currentInterface : metafacadeClass.getInterfaces())
257 {
258 Set<String> subInheritedMappingClassNames = getInheritedMappingClassNames(currentInterface, metafacadeImpls, mappingInstances);
259 if(subInheritedMappingClassNames != null)
260 {
261 if(result == null)
262 {
263 result = subInheritedMappingClassNames;
264 }
265 else
266 {
267 result = intersection(result, subInheritedMappingClassNames);
268 }
269 }
270 }
271 }
272 if(result == null)
273 {
274 result = getInheritedMappingClassNames(metafacadeClass.getSuperclass(), metafacadeImpls, mappingInstances);
275 }
276 }
277 return result;
278 }
279
280
281
282
283
284
285
286
287 public static Set<String> getInheritedMappingClassNames(final MetafacadeMapping mapping)
288 {
289 final Class metafacadeClass = mapping.getMetafacadeClass();
290 final MetafacadeImpls metafacadeImpls = MetafacadeImpls.instance();
291 final Map<Class, Set<String>> mappingInstances = MetafacadeMappings.getAllMetafacadeMappingInstances();
292 final Set<String> className = getInheritedMappingClassNames(metafacadeClass, metafacadeImpls, mappingInstances);
293 if (className == null || className.isEmpty())
294 {
295 throw new MetafacadeMappingsException("No mapping class could be found for '" + metafacadeClass.getName() +
296 '\'');
297 }
298 MetafacadeUtils.getLogger().debug("inheritedMappingClassName " + metafacadeClass.getName() + "=" + className);
299 return className;
300 }
301
302
303
304
305
306
307
308
309 public static boolean isMetafacadeModelPresent(final String namespace)
310 {
311 boolean present = false;
312 if (ClassUtils.isClassOfTypePresent(
313 Namespaces.instance().getResourceRoots(namespace),
314 ModelAccessFacade.class))
315 {
316 present = true;
317 }
318 return present;
319 }
320
321
322
323
324
325
326 private static Logger getLogger()
327 {
328 return MetafacadeFactory.getInstance().getLogger();
329 }
330 }