001package org.andromda.core.metafacade; 002 003import java.io.Serializable; 004import java.util.ArrayList; 005import java.util.Collection; 006import java.util.LinkedHashMap; 007import java.util.LinkedHashSet; 008import java.util.List; 009import java.util.Map; 010import org.andromda.core.common.AndroMDALogger; 011import org.andromda.core.common.ExceptionUtils; 012import org.andromda.core.profile.Profile; 013import org.apache.commons.collections.keyvalue.MultiKey; 014import org.apache.commons.lang.StringUtils; 015import 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 */ 027public 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</strong> 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}