001 package org.andromda.core.metafacade;
002
003 import java.io.Serializable;
004 import java.util.ArrayList;
005 import java.util.Collection;
006 import java.util.LinkedHashMap;
007 import java.util.LinkedHashSet;
008 import java.util.List;
009 import java.util.Map;
010 import org.andromda.core.common.AndroMDALogger;
011 import org.andromda.core.common.ExceptionUtils;
012 import org.andromda.core.profile.Profile;
013 import org.apache.commons.collections.keyvalue.MultiKey;
014 import org.apache.commons.lang.StringUtils;
015 import org.apache.log4j.Logger;
016
017 /**
018 * The factory in charge of constructing Metafacade instances. In order for a
019 * metafacade (i.e. a facade around a meta model element) to be constructed, it
020 * must be constructed through this factory.
021 *
022 * @author <a href="http://www.mbohlen.de">Matthias Bohlen </a>
023 * @author Chad Brandon
024 * @author Peter Friese
025 * @author Bob Fields
026 */
027 public final class MetafacadeFactory
028 implements Serializable
029 {
030 private static final long serialVersionUID = 34L;
031
032 /**
033 * Caches the registered properties used within metafacades.
034 */
035 private final Map<String, Map<String, Map<String, Object>>> metafacadeNamespaces = new LinkedHashMap<String, Map<String, Map<String, Object>>>();
036
037 /**
038 * The shared instance of this factory.
039 */
040 private static MetafacadeFactory instance = null;
041
042 private MetafacadeFactory()
043 {
044 // make sure that nobody instantiates it
045 }
046
047 /**
048 * Returns the facade factory singleton.
049 *
050 * @return the only instance
051 */
052 public static MetafacadeFactory getInstance()
053 {
054 if (instance == null)
055 {
056 instance = new MetafacadeFactory();
057 }
058 return instance;
059 }
060
061 /**
062 * The metafacade cache for this factory.
063 */
064 private final MetafacadeCache cache = MetafacadeCache.newInstance();
065
066 /**
067 * The metafacade mappings instance for this factory.
068 */
069 private final MetafacadeMappings mappings = MetafacadeMappings.newInstance();
070
071 /**
072 * Performs any initialization required by the factory (i.e. discovering all
073 * <code>metafacade</code> mappings, etc).
074 */
075 public void initialize()
076 {
077 this.mappings.initialize();
078 }
079
080 /**
081 * The shared profile instance.
082 */
083 private final Profile profile = Profile.instance();
084
085 /**
086 * The namespace that is currently active (i.e. being used) within the factory
087 */
088 private String namespace;
089
090 /**
091 * Sets the active namespace. The AndroMDA core and each cartridge have their own namespace for metafacade
092 * registration.
093 *
094 * @param namespace the name of the active namespace.
095 */
096 public void setNamespace(final String namespace)
097 {
098 this.namespace = namespace;
099 this.profile.setNamespace(namespace);
100 this.cache.setNamespace(this.namespace);
101 }
102
103 /**
104 * Returns the name of the active namespace.
105 *
106 * @return String the namespace name
107 */
108 public String getNamespace()
109 {
110 if (this.namespace == null)
111 {
112 throw new MetafacadeFactoryException("This metafacade factory's namespace must be populated before " +
113 "metafacade construction can occur");
114 }
115 return this.namespace;
116 }
117
118 /**
119 * Returns a metafacade for a mappingObject, depending on its
120 * <code>mappingClass</code> and (optionally) its <code>stereotypes</code>
121 * and <code>context</code>.
122 *
123 * @param mappingObject the object used to map the metafacade (a meta model
124 * object or a metafacade itself).
125 * @param context the name of the context the meta model element is
126 * registered under.
127 * @return the new metafacade
128 */
129 public MetafacadeBase createMetafacade(
130 final Object mappingObject,
131 final String context)
132 {
133 return this.createMetafacade(
134 mappingObject,
135 context,
136 null);
137 }
138
139 /**
140 * Creates a metafacade given the <code>mappingObject</code>,
141 * <code>contextName</code> and <code>metafacadeClass</code>.
142 *
143 * @param mappingObject the object used to map the metafacade (a meta model
144 * object or a metafacade itself).
145 * @param context the name of the context the meta model element (if the
146 * mappObject is a meta model element) is registered under.
147 * @param metafacadeClass if not null, it contains the name of the
148 * metafacade class to be used. This is used ONLY when instantiating
149 * super metafacades in an inheritance chain. The final metafacade
150 * will NEVER have a metafacadeClass specified (it will ALWAYS be
151 * null).
152 * @return the new metafacade
153 */
154 private MetafacadeBase createMetafacade(
155 final Object mappingObject,
156 final String context,
157 Class metafacadeClass)
158 {
159 final String methodName = "MetafacadeFactory.createMetafacade";
160 ExceptionUtils.checkNull(
161 "mappingObject",
162 mappingObject);
163
164 // - register the namespace properties (if they haven't been)
165 this.registerNamespaceProperties();
166
167 // if the mappingObject is REALLY a metafacade, just return it
168 if (mappingObject instanceof MetafacadeBase)
169 {
170 return (MetafacadeBase)mappingObject;
171 }
172 try
173 {
174 final Collection<String> stereotypes = this.getModel().getStereotypeNames(mappingObject);
175 if (this.getLogger().isDebugEnabled())
176 {
177 this.getLogger().debug("mappingObject stereotypes --> '" + stereotypes + '\'');
178 }
179
180 MetafacadeMapping mapping = null;
181 if (metafacadeClass == null)
182 {
183 final MetafacadeMappings modelMetafacadeMappings = this.getModelMetafacadeMappings();
184 mapping = modelMetafacadeMappings.getMetafacadeMapping(
185 mappingObject,
186 this.getNamespace(),
187 context,
188 stereotypes);
189 if (this.getLogger().isDebugEnabled())
190 {
191 this.getLogger().debug("mappingObject getModelMetafacadeMappings for " + mappingObject + " namespace " + this.getNamespace() + " context " + context);
192 }
193 if (mapping != null)
194 {
195 metafacadeClass = mapping.getMetafacadeClass();
196 }
197 else
198 {
199 // get the default since no mapping was found.
200 metafacadeClass = modelMetafacadeMappings.getDefaultMetafacadeClass(this.getNamespace());
201 if (this.getLogger().isDebugEnabled())
202 {
203 this.getLogger().warn(
204 "Meta object model class '" + mappingObject.getClass() +
205 "' has no corresponding meta facade class, default is being used --> '" + metafacadeClass +
206 '\'');
207 }
208 }
209 }
210
211 if (metafacadeClass == null)
212 {
213 throw new MetafacadeMappingsException(methodName + " metafacadeClass was not retrieved from mappings" +
214 " or specified as an argument in this method for mappingObject --> '" + mappingObject + '\'');
215 }
216 final MetafacadeBase metafacade = this.getMetafacade(
217 metafacadeClass,
218 mappingObject,
219 context,
220 mapping);
221
222 // IMPORTANT: initialize each metafacade ONLY once (otherwise we
223 // get stack overflow errors)
224 if (metafacade != null && !metafacade.isInitialized())
225 {
226 metafacade.setInitialized();
227 metafacade.initialize();
228 }
229 return metafacade;
230 }
231 catch (final Throwable throwable)
232 {
233 final String message =
234 "Failed to construct a meta facade of type '" + metafacadeClass + "' with mappingObject of type --> '" +
235 mappingObject.getClass() + '\'';
236 this.getLogger().error(message);
237 throw new MetafacadeFactoryException(message, throwable);
238 }
239 }
240
241 /**
242 * Gets the model metafacade mappings (the mappings that correspond
243 * to the current metafacade model namespace).
244 *
245 * @return the model metafacade mappings.
246 */
247 private MetafacadeMappings getModelMetafacadeMappings()
248 {
249 return this.mappings.getModelMetafacadeMappings(this.metafacadeModelNamespace);
250 }
251
252 /**
253 * Validates all metafacades for the current namespace
254 * and collects the messages in the internal validation messages
255 * collection.
256 *
257 * @see #getValidationMessages()
258 */
259 public void validateAllMetafacades()
260 {
261 for (final MetafacadeBase metafacadeBase : this.getAllMetafacades())
262 {
263 metafacadeBase.validate(this.validationMessages);
264 }
265 }
266
267 /**
268 * Creates a metafacade from the passed in <code>mappingObject</code>, and
269 * <code>mapping</code> instance.
270 *
271 * @param mappingObject the mapping object for which to create the
272 * metafacade.
273 * @param mapping the mapping from which to create the metafacade
274 * @return the metafacade, or null if it can't be created.
275 */
276 protected MetafacadeBase createMetafacade(
277 final Object mappingObject,
278 final MetafacadeMapping mapping)
279 {
280 try
281 {
282 return this.getMetafacade(
283 mapping.getMetafacadeClass(),
284 mappingObject,
285 mapping.getContext(),
286 mapping);
287 }
288 catch (final Throwable throwable)
289 {
290 final String message =
291 "Failed to construct a meta facade of type '" + mapping.getMetafacadeClass() +
292 "' with mappingObject of type --> '" + mapping.getMappingClassNames() + '\'';
293 this.getLogger().error(message);
294 throw new MetafacadeFactoryException(message, throwable);
295 }
296 }
297
298 /**
299 * Retrieves (if one has already been constructed) or constructs a new
300 * <code>metafacade</code> from the given <code>metafacadeClass</code>
301 * and <code>mappingObject</code>.
302 *
303 * @param metafacadeClass the metafacade class.
304 * @param mappingObject the object to which the metafacade is mapped.
305 * @param context the context to which the metafacade applies
306 * @param mapping the optional MetafacadeMapping instance from which the
307 * metafacade is mapped.
308 * @return the new (or cached) metafacade.
309 * @throws Exception if any error occurs during metafacade creation
310 */
311 private MetafacadeBase getMetafacade(
312 final Class metafacadeClass,
313 final Object mappingObject,
314 final String context,
315 final MetafacadeMapping mapping)
316 throws Exception
317 {
318 MetafacadeBase metafacade = this.cache.get(
319 mappingObject,
320 metafacadeClass);
321 if (metafacade == null)
322 {
323 final MultiKey key = new MultiKey(mappingObject, metafacadeClass);
324 if (!this.metafacadesInCreation.contains(key))
325 {
326 this.metafacadesInCreation.add(
327 key);
328 if (mapping != null && mapping.isContextRoot())
329 {
330 metafacade = MetafacadeUtils.constructMetafacade(
331 metafacadeClass,
332 mappingObject,
333 null);
334 // set whether or not this metafacade is a context root
335 metafacade.setContextRoot(mapping.isContextRoot());
336 }
337 else
338 {
339 metafacade = MetafacadeUtils.constructMetafacade(
340 metafacadeClass,
341 mappingObject,
342 context);
343 }
344 this.metafacadesInCreation.remove(key);
345
346 this.cache.add(
347 mappingObject,
348 metafacade);
349 }
350 }
351
352 if (metafacade != null)
353 {
354 // if the requested metafacadeClass is different from the one in the mapping, contextRoot should be reset
355 if (mapping != null && !mapping.getMetafacadeClass().equals(metafacadeClass))
356 {
357 metafacade.setContextRoot(false);
358 metafacade.resetMetafacadeContext(context);
359 }
360 // we need to set some things each time
361 // we change a metafacade's namespace
362 final String metafacadeNamespace = metafacade.getMetafacadeNamespace();
363 if (metafacadeNamespace == null || !metafacadeNamespace.equals(this.getNamespace()))
364 {
365 // assign the logger and active namespace
366 metafacade.setNamespace(this.getNamespace());
367 metafacade.setLogger(this.getLogger());
368 }
369 }
370 return metafacade;
371 }
372
373 /**
374 * Stores the metafacades being created, so that we don't get stuck in
375 * endless recursion during creation.
376 */
377 private final Collection<MultiKey> metafacadesInCreation = new ArrayList<MultiKey>();
378
379 /**
380 * Returns a metafacade for a mappingObject, depending on its <code>mappingClass</code>.
381 *
382 * @param mappingObject the object which is used to map to the metafacade
383 * @return MetafacadeBase the facade object (not yet attached to mappingClass object)
384 */
385 public MetafacadeBase createMetafacade(final Object mappingObject)
386 {
387 return this.createMetafacade(
388 mappingObject,
389 null,
390 null);
391 }
392
393 /**
394 * Create a facade implementation object for a mappingObject. The facade
395 * implementation object must be found in a way that it implements the
396 * interface <code>interfaceName</code>.
397 *
398 * @param interfaceName the name of the interface that the implementation
399 * object has to implement
400 * @param mappingObject the mappingObject for which a facade shall be
401 * created
402 * @param context the context in which this metafacade will be created.
403 * @return MetafacadeBase the metafacade
404 */
405 public MetafacadeBase createFacadeImpl(
406 final String interfaceName,
407 final Object mappingObject,
408 final String context)
409 {
410 ExceptionUtils.checkEmpty(
411 "interfaceName",
412 interfaceName);
413 ExceptionUtils.checkNull(
414 "mappingObject",
415 mappingObject);
416
417 Class metafacadeClass = null;
418 try
419 {
420 metafacadeClass = this.metafacadeImpls.getMetafacadeImplClass(interfaceName);
421 return this.createMetafacade(
422 mappingObject,
423 context,
424 metafacadeClass);
425 }
426 catch (final Throwable throwable)
427 {
428 final String message =
429 "Failed to construct a meta facade of type '" + metafacadeClass + "' with mappingObject of type --> '" +
430 mappingObject.getClass().getName() + '\'';
431 this.getLogger().error(message);
432 throw new MetafacadeFactoryException(message, throwable);
433 }
434 }
435
436 /**
437 * Returns a metafacade for each mappingObject, contained within the
438 * <code>mappingObjects</code> collection depending on its
439 * <code>mappingClass</code> and (optionally) its <code>stereotypes</code>,
440 * and <code>contextName</code>.
441 *
442 * @param mappingObjects the meta model element.
443 * @param contextName the name of the context the meta model element is
444 * registered under.
445 * @return the Collection of newly created Metafacades.
446 */
447 protected Collection<MetafacadeBase> createMetafacades(
448 final Collection mappingObjects,
449 final String contextName)
450 {
451 final Collection<MetafacadeBase> metafacades = new ArrayList<MetafacadeBase>();
452 if (mappingObjects != null && !mappingObjects.isEmpty())
453 {
454 for (final Object mappingObject : mappingObjects)
455 {
456 if (this.getLogger().isDebugEnabled())
457 {
458 this.getLogger().debug("MetafacadeFactory createMetafacade for namespace " + this.getNamespace() + " model " + this.getModel() + " contextName " + contextName + " mappingObject " + mappingObject);
459 }
460 metafacades.add(this.createMetafacade(
461 mappingObject,
462 contextName,
463 null));
464 }
465 }
466 return metafacades;
467 }
468
469 /**
470 * Returns a metafacade for each mappingObject, contained within the
471 * <code>mappingObjects</code> collection depending on its
472 * <code>mappingClass</code>.
473 *
474 * @param mappingObjects the objects used to map the metafacades (can be a
475 * meta model element or an actual metafacade itself).
476 * @return Collection of metafacades
477 */
478 public Collection<MetafacadeBase> createMetafacades(final Collection mappingObjects)
479 {
480 return this.createMetafacades(
481 mappingObjects,
482 null);
483 }
484
485 /**
486 * The model facade which provides access to the underlying meta model.
487 */
488 private ModelAccessFacade model;
489
490 /**
491 * Gets the model which provides access to the underlying model and is used
492 * to construct metafacades.
493 *
494 * @return the model access facade.
495 */
496 public ModelAccessFacade getModel()
497 {
498 if (this.model == null)
499 {
500 throw new MetafacadeFactoryException("This metafacade factory's model must be populated before " +
501 "metafacade construction can occur");
502 }
503 return this.model;
504 }
505
506 /**
507 * The shared metafacade impls instance.
508 */
509 private MetafacadeImpls metafacadeImpls = MetafacadeImpls.instance();
510
511 /**
512 * Stores the namespace that contains the metafacade model implementation.
513 */
514 private String metafacadeModelNamespace;
515
516 /**
517 * The model access facade instance (provides access to the meta model).
518 *
519 * @param model the model
520 * @param metafacadeModelNamespace the namespace that contains the metafacade facade implementation.
521 */
522 public void setModel(
523 final ModelAccessFacade model,
524 final String metafacadeModelNamespace)
525 {
526 this.metafacadeModelNamespace = metafacadeModelNamespace;
527
528 // - set the model type as the namespace for the metafacade impls so we have
529 // access to the correct metafacade classes
530 this.metafacadeImpls.setMetafacadeModelNamespace(metafacadeModelNamespace);
531 this.model = model;
532 }
533
534 /**
535 * Gets the correct logger based on whether or not an namespace logger should be used
536 *
537 * @return the logger
538 */
539 final Logger getLogger()
540 {
541 return AndroMDALogger.getNamespaceLogger(this.getNamespace());
542 }
543
544 /**
545 * Registers a property with the specified <code>name</code> in the given
546 * <code>namespace</code>.
547 *
548 * @param namespace the namespace in which the property is stored.
549 * @param metafacadeName the name of the metafacade under which the property is registered
550 * @param name the name of the property
551 * @param value to give the property
552 */
553 final void registerProperty(
554 final String namespace,
555 final String metafacadeName,
556 final String name,
557 final Object value)
558 {
559 ExceptionUtils.checkEmpty(
560 "name",
561 name);
562 Map<String, Map<String, Object>> metafacadeNamespace = this.metafacadeNamespaces.get(namespace);
563 if (metafacadeNamespace == null)
564 {
565 metafacadeNamespace = new LinkedHashMap<String, Map<String, Object>>();
566 this.metafacadeNamespaces.put(
567 namespace,
568 metafacadeNamespace);
569 }
570 Map<String, Object> propertyNamespace = metafacadeNamespace.get(metafacadeName);
571 if (propertyNamespace == null)
572 {
573 propertyNamespace = new LinkedHashMap<String, Object>();
574 metafacadeNamespace.put(
575 metafacadeName,
576 propertyNamespace);
577 }
578 propertyNamespace.put(
579 name,
580 value);
581 }
582
583 /**
584 * Registers a property with the specified <code>name</code> in the namespace
585 * that is currently set within the factory.
586 *
587 * @param metafacadeName the name of the metafacade under which the property is registered
588 * @param name the name of the property
589 * @param value to give the property
590 */
591 final void registerProperty(
592 final String metafacadeName,
593 final String name,
594 final Object value)
595 {
596 this.registerProperty(
597 this.getNamespace(),
598 metafacadeName,
599 name,
600 value);
601 }
602
603 /**
604 * Gets the metafacade's property namespace (or returns null if hasn't be registered).
605 *
606 * @param metafacade the metafacade
607 * @return the metafacade's namespace
608 */
609 private Map<String, Object> getMetafacadePropertyNamespace(final MetafacadeBase metafacade)
610 {
611 Map<String, Object> metafacadeNamespace = null;
612 if (metafacade != null)
613 {
614 Map<String, Map<String, Object>> namespace = this.metafacadeNamespaces.get(this.getNamespace());
615 if (namespace != null)
616 {
617 metafacadeNamespace = namespace.get(metafacade.getMetafacadeName());
618 }
619 }
620 return metafacadeNamespace;
621 }
622
623 /**
624 * Returns true if this property is registered under the given
625 * <code>namespace</code>, false otherwise.
626 *
627 * @param metafacade the metafacade to search.
628 * @param name the name of the property.
629 * @return true if the property is registered, false otherwise.
630 */
631 final boolean isPropertyRegistered(
632 final MetafacadeBase metafacade,
633 final String name)
634 {
635 final Map<String, Object> propertyNamespace = this.getMetafacadePropertyNamespace(metafacade);
636 return propertyNamespace != null && propertyNamespace.containsKey(name);
637 }
638
639 /**
640 * Finds the first property having the given <code>namespaces</code>, or
641 * <code>null</code> if the property can <strong>NOT </strong> be found.
642 *
643 * @param metafacade the metafacade to search.
644 * @param name the name of the property to find.
645 * @return the property or null if it can't be found.
646 */
647 private Object findProperty(
648 final MetafacadeBase metafacade,
649 final String name)
650 {
651 final Map<String, Object> propertyNamespace = this.getMetafacadePropertyNamespace(metafacade); //final Map<String, Map>
652 return propertyNamespace != null ? propertyNamespace.get(name) : null;
653 }
654
655 /**
656 * Gets the registered property registered under the <code>namespace</code>
657 * with the <code>name</code>
658 *
659 * @param metafacade the metafacade to search
660 * @param name the name of the property to check.
661 * @return the registered property
662 */
663 final Object getRegisteredProperty(
664 final MetafacadeBase metafacade,
665 final String name)
666 {
667 final String methodName = "MetafacadeFactory.getRegisteredProperty";
668 final Object registeredProperty = this.findProperty(
669 metafacade,
670 name);
671 if (registeredProperty == null && !this.isPropertyRegistered(
672 metafacade,
673 name))
674 {
675 throw new MetafacadeFactoryException(methodName + " - no property '" + name +
676 "' registered under metafacade '" + metafacade.getMetafacadeName() + "' for namespace '" + this.getNamespace() +
677 '\'');
678 }
679 return registeredProperty;
680 }
681
682 /**
683 * The validation messages that have been collected during the
684 * execution of this factory.
685 */
686 private final Collection<ModelValidationMessage> validationMessages = new LinkedHashSet<ModelValidationMessage>();
687
688 /**
689 * Gets the list of all validation messages collection during model processing.
690 *
691 * @return Returns the validationMessages.
692 * @see #validateAllMetafacades()
693 */
694 public List<ModelValidationMessage> getValidationMessages()
695 {
696 return new ArrayList<ModelValidationMessage>(this.validationMessages);
697 }
698
699 /**
700 * Stores the collection of all metafacades for
701 * each namespace.
702 */
703 private final Map<String, Collection<MetafacadeBase>> allMetafacades = new LinkedHashMap<String, Collection<MetafacadeBase>>();
704
705 /**
706 * <p>
707 * Gets all metafacades for the entire model for the
708 * current namespace set within the factory.
709 * </p>
710 * <p>
711 * <strong>NOTE:</strong> The model package filter is applied
712 * before returning the results (if defined within the factory).
713 * </p>
714 *
715 * @return all metafacades
716 */
717 public Collection<MetafacadeBase> getAllMetafacades()
718 {
719 final String namespace = this.getNamespace();
720 Collection<MetafacadeBase> metafacades = null;
721 if (this.getModel() != null)
722 {
723 metafacades = allMetafacades.get(namespace);
724 if (metafacades == null)
725 {
726 metafacades = this.createMetafacades(this.getModel().getModelElements());
727 allMetafacades.put(
728 namespace,
729 metafacades);
730 }
731 if (metafacades != null)
732 {
733 metafacades = new ArrayList<MetafacadeBase>(metafacades);
734 }
735 }
736 return metafacades;
737 }
738
739 /**
740 * Caches the metafacades by stereotype.
741 */
742 private final Map<String, Map<String, Collection<MetafacadeBase>>> metafacadesByStereotype
743 = new LinkedHashMap<String, Map<String, Collection<MetafacadeBase>>>();
744
745 /**
746 * <p>
747 * Gets all metafacades for the entire model having the given
748 * stereotype.
749 * </p>
750 * <p>
751 * <strong>NOTE:</strong> The model package filter is applied
752 * before returning the results (if defined within the factory).
753 * </p>
754 *
755 * @param stereotype the stereotype by which to perform the search.
756 * @return the metafacades having the given <code>stereotype</code>.
757 */
758 public Collection<MetafacadeBase> getMetafacadesByStereotype(final String stereotype)
759 {
760 final String namespace = this.getNamespace();
761 Collection<MetafacadeBase> metafacades = null;
762 if (this.getModel() != null)
763 {
764 Map<String, Collection<MetafacadeBase>> stereotypeMetafacades = this.metafacadesByStereotype.get(namespace);
765 if (stereotypeMetafacades == null)
766 {
767 stereotypeMetafacades = new LinkedHashMap<String, Collection<MetafacadeBase>>();
768 }
769 metafacades = stereotypeMetafacades.get(stereotype);
770 if (metafacades == null)
771 {
772 metafacades = this.createMetafacades(this.getModel().findByStereotype(stereotype));
773 stereotypeMetafacades.put(
774 stereotype,
775 metafacades);
776 this.metafacadesByStereotype.put(
777 namespace,
778 stereotypeMetafacades);
779 }
780 if (metafacades != null)
781 {
782 metafacades = new ArrayList<MetafacadeBase>(metafacades);
783 }
784 }
785 return metafacades;
786 }
787
788 /**
789 * Performs shutdown procedures for the factory. This should be called <strong>ONLY</code> when model processing has
790 * completed.
791 */
792 public void shutdown()
793 {
794 this.clearCaches();
795 this.metafacadeNamespaces.clear();
796 this.mappings.shutdown();
797 this.model = null;
798 MetafacadeFactory.instance = null;
799
800 // - shutdown the profile instance
801 this.profile.shutdown();
802 }
803
804 /**
805 * Registers all namespace properties (if required).
806 */
807 private void registerNamespaceProperties()
808 {
809 // - only register them if they already aren't registered
810 if (this.metafacadeNamespaces.isEmpty())
811 {
812 if (StringUtils.isNotBlank(this.metafacadeModelNamespace))
813 {
814 final MetafacadeMappings modelMappings = this.getModelMetafacadeMappings();
815 if (modelMappings != null)
816 {
817 modelMappings.registerAllProperties();
818 }
819 }
820 }
821 }
822
823 /**
824 * Entirely resets all the internal resources within this factory instance (such
825 * as the caches, etc).
826 */
827 public void reset()
828 {
829 // - refresh the profile
830 this.profile.refresh();
831
832 // - clear out the namespace properties so we can re-register them next run
833 this.metafacadeNamespaces.clear();
834
835 // - re-register the namespace properties (if we're running again)
836 this.registerNamespaceProperties();
837
838 // - clear out the rest of the factory's caches
839 this.clearCaches();
840 }
841
842 /**
843 * Clears out the factory's internal caches (other
844 * than namespace properties, which can be cleared by
845 * calling {@link org.andromda.core.configuration.Namespaces#clear()}.
846 */
847 public void clearCaches()
848 {
849 this.validationMessages.clear();
850 this.allMetafacades.clear();
851 this.metafacadesByStereotype.clear();
852 this.cache.clear();
853 this.metafacadesInCreation.clear();
854 }
855 }