001package org.andromda.core.metafacade; 002 003import java.io.Serializable; 004import java.util.HashMap; 005import java.util.Map; 006 007/** 008 * A global cache for metafacades. Used by the {@link MetafacadeFactory}when constructing or retrieving metafacade 009 * instances. If the cache constains the metafacade it should not be constructed again. 010 * 011 * @author Chad Brandon 012 */ 013public final class MetafacadeCache 014 implements Serializable 015{ 016 private static final long serialVersionUID = 34L; 017 018 /** 019 * Constructs a new instance of this class. 020 * 021 * @return the new instance 022 */ 023 public static MetafacadeCache newInstance() 024 { 025 return new MetafacadeCache(); 026 } 027 028 private MetafacadeCache() 029 { 030 // don't allow instantiation 031 } 032 033 /** 034 * The namespace to which the cache currently applies 035 */ 036 private String namespace; 037 038 /** 039 * Sets the namespace to which the cache currently applies. 040 * 041 * @param namespace the current namespace. 042 */ 043 public final void setNamespace(final String namespace) 044 { 045 this.namespace = namespace; 046 } 047 048 /** 049 * The cache for already created metafacades. 050 */ 051 private final Map<Object, Map<Class, Map<String, MetafacadeBase>>> metafacadeCache = new HashMap<Object, Map<Class, Map<String, MetafacadeBase>>>(); 052 053 /** 054 * <p> 055 * Returns the metafacade from the metafacade cache. The Metafacades are cached first by according to its 056 * <code>mappingObject</code>, next the <code>metafacadeClass</code>, and finally by the current namespace. </p> 057 * <p> 058 * Metafacades must be cached in order to keep track of the state of its validation. If we keep creating a new one 059 * each time, we can never tell whether or not a metafacade has been previously validated. Not to mention tremendous 060 * performance gains. </p> 061 * 062 * @param mappingObject the object to which the mapping applies 063 * @param metafacadeClass the class of the metafacade. 064 * @return MetafacadeBase stored in the cache. 065 */ 066 public final MetafacadeBase get( 067 final Object mappingObject, 068 final Class metafacadeClass) 069 { 070 MetafacadeBase metafacade = null; 071 final Map<Class, Map<String, MetafacadeBase>> namespaceMetafacadeCache = this.metafacadeCache.get(mappingObject); 072 if (namespaceMetafacadeCache != null) 073 { 074 final Map<String, MetafacadeBase> metafacadeCache = namespaceMetafacadeCache.get(metafacadeClass); 075 if (metafacadeCache != null) 076 { 077 metafacade = metafacadeCache.get(this.namespace); 078 } 079 } 080 return metafacade; 081 } 082 083 /** 084 * Adds the <code>metafacade</code> to the cache according to first <code>mappingObject</code>, second the 085 * <code>metafacade</code>, and finally by the current <code>namespace</code>. 086 * 087 * @param mappingObject the mappingObject for which to cache the metafacade. 088 * @param metafacade the metafacade to cache. 089 */ 090 public final void add( 091 final Object mappingObject, 092 final MetafacadeBase metafacade) 093 { 094 Map<Class, Map<String, MetafacadeBase>> namespaceMetafacadeCache = this.metafacadeCache.get(mappingObject); 095 if (namespaceMetafacadeCache == null) 096 { 097 namespaceMetafacadeCache = new HashMap<Class, Map<String, MetafacadeBase>>(); 098 this.metafacadeCache.put(mappingObject, namespaceMetafacadeCache); 099 } 100 Map<String, MetafacadeBase> metafacadeCache = namespaceMetafacadeCache.get(metafacade.getClass()); 101 if (metafacadeCache == null) 102 { 103 metafacadeCache = new HashMap<String, MetafacadeBase>(); 104 namespaceMetafacadeCache.put( 105 metafacade.getClass(), 106 metafacadeCache); 107 } 108 metafacadeCache.put(this.namespace, metafacade); 109 } 110 111 /** 112 * Clears the cache of any metafacades 113 */ 114 public final void clear() 115 { 116 this.metafacadeCache.clear(); 117 } 118 119 /** 120 * @see Object#toString() 121 */ 122 public String toString() 123 { 124 return this.metafacadeCache.toString(); 125 } 126}