1 package org.andromda.core.mapping;
2
3 import java.io.File;
4 import java.io.FileReader;
5 import java.net.MalformedURLException;
6 import java.net.URL;
7 import java.util.Collection;
8 import java.util.HashMap;
9 import java.util.Iterator;
10 import java.util.LinkedHashMap;
11 import java.util.Map;
12 import org.andromda.core.common.ExceptionUtils;
13 import org.andromda.core.common.ResourceUtils;
14 import org.andromda.core.common.XmlObjectFactory;
15 import org.apache.commons.lang.StringUtils;
16 import org.apache.commons.lang.builder.ToStringBuilder;
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 public class Mappings
33 {
34
35
36
37
38 private final Map<String, Mapping> mappings = new LinkedHashMap<String, Mapping>();
39
40
41
42
43 private static final Map<String, Mappings> logicalMappings = new LinkedHashMap<String, Mappings>();
44
45
46
47
48 private URL resource;
49
50
51
52
53
54
55
56
57 public static Mappings getInstance(String mappingsUri)
58 {
59 mappingsUri = StringUtils.trimToEmpty(mappingsUri);
60 ExceptionUtils.checkEmpty(
61 "mappingsUri",
62 mappingsUri);
63 try
64 {
65 Mappings mappings = logicalMappings.get(mappingsUri);
66 if (mappings == null)
67 {
68 try
69 {
70 mappings = getInstance(new URL(mappingsUri));
71 }
72 catch (final MalformedURLException exception)
73 {
74 throw new MappingsException("The given URI --> '" + mappingsUri + "' is invalid", exception);
75 }
76 }
77 return getInheritedMappings(mappings);
78 }
79 catch (final Throwable throwable)
80 {
81 throw new MappingsException(throwable);
82 }
83 }
84
85
86
87
88
89
90
91
92
93
94
95
96 private static Mappings getInheritedMappings(final Mappings mappings)
97 throws Exception
98 {
99 return getInheritedMappings(
100 mappings,
101 false);
102 }
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119 private static Mappings getInheritedMappings(
120 final Mappings mappings,
121 final boolean ignoreInheritanceFailure)
122 throws Exception
123 {
124
125
126
127 if (mappings != null && StringUtils.isNotBlank(mappings.extendsUri))
128 {
129 Mappings parentMappings = logicalMappings.get(mappings.extendsUri);
130 if (parentMappings == null)
131 {
132 try
133 {
134
135
136 parentMappings = getInstance(new File(mappings.getCompletePath(mappings.extendsUri)));
137 }
138 catch (final Exception exception)
139 {
140 if (!ignoreInheritanceFailure)
141 {
142 throw exception;
143 }
144 }
145 }
146 if (parentMappings != null)
147 {
148 mergeWithoutOverriding(parentMappings, mappings);
149 }
150 }
151 return mappings;
152 }
153
154
155
156
157
158
159
160
161 public static Mappings getInstance(final URL mappingsUri)
162 {
163 return getInstance(
164 mappingsUri,
165 false);
166 }
167
168
169
170
171
172
173
174
175
176
177 private static Mappings getInstance(
178 final URL mappingsUri,
179 final boolean ignoreInheritanceFailure)
180 {
181 ExceptionUtils.checkNull(
182 "mappingsUri",
183 mappingsUri);
184 try
185 {
186 final Mappings mappings = (Mappings)XmlObjectFactory.getInstance(Mappings.class).getObject(mappingsUri);
187 mappings.resource = mappingsUri;
188 return getInheritedMappings(
189 mappings,
190 ignoreInheritanceFailure);
191 }
192 catch (final Throwable throwable)
193 {
194 throw new MappingsException(throwable);
195 }
196 }
197
198
199
200
201
202
203
204
205 private static Mappings getInstance(final File mappingsFile)
206 throws Exception
207 {
208 final FileReader reader = new FileReader(mappingsFile);
209 final Mappings mappings =
210 (Mappings)XmlObjectFactory.getInstance(Mappings.class).getObject(reader);
211 mappings.resource = mappingsFile.toURI().toURL();
212 reader.close();
213 return mappings;
214 }
215
216
217
218
219
220
221
222
223 public static void initializeLogicalMappings()
224 {
225
226
227
228
229
230 final Map<String, Mappings> unprocessedMappings = new HashMap<String, Mappings>(logicalMappings);
231 final Map<String, Mappings> processedMappings = new LinkedHashMap<String, Mappings>();
232
233
234
235
236 boolean processed = true;
237 while (processed)
238 {
239
240 processed = false;
241
242
243 for (final Iterator<Map.Entry<String, Mappings>> iterator = unprocessedMappings.entrySet().iterator(); iterator.hasNext();)
244 {
245 final Map.Entry<String, Mappings> logicalMapping = iterator.next();
246 final String name = logicalMapping.getKey();
247 final Mappings mappings = logicalMapping.getValue();
248
249 if (mappings.extendsUri == null)
250 {
251
252
253
254 processedMappings.put(name, mappings);
255
256 iterator.remove();
257
258 processed = true;
259 }
260 else if (processedMappings.containsKey(mappings.extendsUri))
261 {
262 final Mappings parentMappings = processedMappings.get(mappings.extendsUri);
263 if (parentMappings != null)
264 {
265 mergeWithoutOverriding(parentMappings, mappings);
266 }
267
268
269 processedMappings.put(name, mappings);
270
271 iterator.remove();
272
273 processed = true;
274 }
275 }
276
277 }
278
279 if (!unprocessedMappings.isEmpty())
280 {
281 throw new MappingsException(
282 "Logical mappings cannot be initialized due to invalid inheritance: " +
283 unprocessedMappings.keySet());
284 }
285
286 logicalMappings.putAll(processedMappings);
287 }
288
289
290
291
292 public static void clearLogicalMappings()
293 {
294 logicalMappings.clear();
295 }
296
297
298
299
300
301 private String name = null;
302
303
304
305
306
307
308
309 public String getName()
310 {
311 final String methodName = "Mappings.getName";
312 if (StringUtils.isEmpty(this.name))
313 {
314 throw new MappingsException(methodName + " - name can not be null or empty");
315 }
316 return name;
317 }
318
319
320
321
322
323
324 public void setName(final String name)
325 {
326 this.name = name;
327 }
328
329
330
331
332 private String extendsUri;
333
334
335
336
337
338
339
340
341 public void setExtendsUri(final String extendsUri)
342 {
343 this.extendsUri = extendsUri;
344 }
345
346
347
348
349
350
351 public void addMapping(final Mapping mapping)
352 {
353 ExceptionUtils.checkNull(
354 "mapping",
355 mapping);
356 final Collection<String> fromTypes = mapping.getFroms();
357 ExceptionUtils.checkNull(
358 "mapping.fromTypes",
359 fromTypes);
360 for (final String fromType : fromTypes)
361 {
362 mapping.setMappings(this);
363 this.mappings.put(
364 fromType,
365 mapping);
366 }
367 }
368
369
370
371
372
373
374
375 public void addMappings(final Mappings mappings)
376 {
377 if (mappings != null && mappings.mappings != null)
378 {
379 this.mappings.putAll(mappings.mappings);
380 }
381 }
382
383
384
385
386
387
388
389
390 private static void mergeWithoutOverriding(Mappings sourceMappings, Mappings targetMappings)
391 {
392 final Map<String, Mapping> allMappings = new LinkedHashMap<String, Mapping>(targetMappings.mappings.size() + sourceMappings.mappings.size());
393 allMappings.putAll(sourceMappings.mappings);
394 allMappings.putAll(targetMappings.mappings);
395 targetMappings.mappings.clear();
396 targetMappings.mappings.putAll(allMappings);
397 }
398
399
400
401
402
403
404
405
406
407
408 public String getTo(String from)
409 {
410 from = StringUtils.trimToEmpty(from);
411 final String initialFrom = from;
412 String to = null;
413
414
415
416 final Mapping mapping = this.getMapping(from);
417 if (mapping != null)
418 {
419 to = mapping.getTo();
420 }
421 if (to == null)
422 {
423 to = initialFrom;
424 }
425 return StringUtils.trimToEmpty(to);
426 }
427
428
429
430
431
432
433
434
435
436 public static void addLogicalMappings(final URL mappingsUri)
437 {
438 final Mappings mappings = Mappings.getInstance(
439 mappingsUri,
440 true);
441 logicalMappings.put(
442 mappings.getName(),
443 mappings);
444 }
445
446
447
448
449
450
451
452 public boolean containsFrom(final String from)
453 {
454 return this.getMapping(from) != null;
455 }
456
457
458
459
460
461
462
463 public boolean containsTo(final String to)
464 {
465 for (Mapping mapping : this.getMappings())
466 {
467 if (mapping.getTo().trim().equals(to))
468 {
469 return true;
470 }
471 }
472 return false;
473 }
474
475
476
477
478
479
480 public URL getResource()
481 {
482 return this.resource;
483 }
484
485
486
487
488
489
490 public Collection<Mapping> getMappings()
491 {
492 return this.mappings.values();
493 }
494
495
496
497
498
499
500
501 public Mapping getMapping(final String from)
502 {
503 return this.mappings.get(StringUtils.trimToEmpty(from));
504 }
505
506
507
508
509 private final Map<String, String> completePaths = new LinkedHashMap<String, String>();
510
511
512
513
514
515
516
517
518 final String getCompletePath(final String relativePath)
519 {
520 String completePath = this.completePaths.get(relativePath);
521 if (completePath == null)
522 {
523 final StringBuilder path = new StringBuilder();
524 if (this.mappings != null)
525 {
526 final URL resource = this.getResource();
527 if (resource != null)
528 {
529 String rootPath = resource.getFile().replace(
530 '\\',
531 '/');
532 rootPath = rootPath.substring(
533 0,
534 rootPath.lastIndexOf('/') + 1);
535 path.append(rootPath);
536 }
537 }
538 if (relativePath != null)
539 {
540 path.append(StringUtils.trimToEmpty(relativePath));
541 }
542 completePath = path.toString();
543 this.completePaths.put(
544 relativePath,
545 completePath);
546 }
547 return ResourceUtils.unescapeFilePath(completePath);
548 }
549
550
551
552
553 public String toString()
554 {
555 return ToStringBuilder.reflectionToString(this);
556 }
557 }