001package org.andromda.core.common; 002 003import java.net.URL; 004import java.util.ArrayList; 005import java.util.Collection; 006import java.util.HashMap; 007import java.util.Map; 008import org.andromda.core.configuration.Namespaces; 009import org.apache.commons.lang.StringUtils; 010import org.apache.commons.lang.builder.ToStringBuilder; 011import org.apache.log4j.Logger; 012 013/** 014 * Contains the configuration of a template object which are objects that are 015 * made available to the cartridge templates. 016 * 017 * @author Chad Brandon 018 * @author Bob Fields 019 */ 020public class TemplateObject 021{ 022 private static final Logger logger = Logger.getLogger(TemplateObject.class); 023 024 /** 025 * The name of this template object made available to the 026 * template. 027 */ 028 private String name; 029 030 /** 031 * Gets the current name of this TemplateObject. 032 * 033 * @return String 034 */ 035 public String getName() 036 { 037 final String methodName = "TemplateObject.getName"; 038 if (StringUtils.isEmpty(this.name)) 039 { 040 throw new TemplateObjectException(methodName + " - templateObject '" + this + "' has no name defined"); 041 } 042 return this.name; 043 } 044 045 /** 046 * Caches the template objects. 047 */ 048 private final Map<String, Object> objectCache = new HashMap<String, Object>(); 049 050 /** 051 * Defines the class should be used in a static way 052 */ 053 private static final String STATIC_SUFFIX = ".class"; 054 055 /** 056 * Returns the actuall object instance described by this 057 * template object. 058 * 059 * @return the actual object instance. 060 */ 061 public Object getObject() 062 { 063 final String methodName = "TemplateObject.getTemplateObject"; 064 if (StringUtils.isEmpty(this.className)) 065 { 066 throw new TemplateObjectException(methodName + " - templateObject '" + this + "' has no className defined"); 067 } 068 Object templateObject = this.objectCache.get(this.className); 069 try 070 { 071 if (templateObject == null) 072 { 073 final Class templateObjectClass; 074 if(this.className.endsWith(STATIC_SUFFIX)) 075 { 076 templateObjectClass = ClassUtils.loadClass(StringUtils.substringBefore(this.className, STATIC_SUFFIX)); 077 templateObject = templateObjectClass; 078 } 079 else 080 { 081 templateObjectClass = ClassUtils.loadClass(this.className); 082 templateObject = templateObjectClass.newInstance(); 083 } 084 this.objectCache.put(this.className, templateObject); 085 } 086 087 // - we want to set the properties each time we retrieve (in case they've changed) 088 this.setProperties(templateObject); 089 } 090 catch (final Throwable throwable) 091 { 092 throw new TemplateObjectException(throwable); 093 } 094 return templateObject; 095 } 096 097 /** 098 * Sets all the nested properties on the templateObject object. 099 * 100 * @param templateObject the template object on which to populate properties. 101 */ 102 protected void setProperties(final Object templateObject) 103 { 104 for (final String reference : propertyReferences) 105 { 106 String value = Namespaces.instance().getPropertyValue( 107 this.getNamespace(), 108 reference); 109 if (value != null) 110 { 111 if (this.getLogger().isDebugEnabled()) 112 { 113 this.getLogger().debug( 114 "populating template object '" + this.name + "' property '" + reference + "' with value '" + 115 value + "' for namespace '" + namespace + '\''); 116 } 117 try 118 { 119 Introspector.instance().setProperty(templateObject, reference, value); 120 } 121 catch (final Exception exception) 122 { 123 // - don't throw the exception 124 final String message = 125 "Error setting property '" + reference + "' with '" + value + "' on templateObject --> '" + 126 templateObject + '\''; 127 logger.warn(message); 128 } 129 } 130 } 131 } 132 133 /** 134 * Sets the name of the template object (this name will be what the template class is stored under in the template) 135 * 136 * @param name the name of the template object. 137 */ 138 public void setName(final String name) 139 { 140 this.name = StringUtils.trimToEmpty(name); 141 } 142 143 /** 144 * The name of the class for this template object. 145 */ 146 private String className; 147 148 /** 149 * Sets the class of the transformation object. 150 * 151 * @param className the name of the template object class. 152 */ 153 public void setClassName(final String className) 154 { 155 ExceptionUtils.checkEmpty("className", className); 156 this.className = className; 157 } 158 159 /** 160 * The property references that configure this template object. 161 */ 162 private final Collection<String> propertyReferences = new ArrayList<String>(); 163 164 /** 165 * Adds a templateObject property reference (used to customize templateObjects). Property references are used to 166 * populate bean like properties of template objects. 167 * 168 * @param reference the name of the property reference. 169 */ 170 public void addPropertyReference(final String reference) 171 { 172 this.propertyReferences.add(reference); 173 } 174 175 /** 176 * The resource in which the template object was found. 177 */ 178 private URL resource; 179 180 /** 181 * The resource in which the templateObject was found. 182 * 183 * @return the resource as a URL. 184 */ 185 public URL getResource() 186 { 187 return resource; 188 } 189 190 /** 191 * Sets the resource in which the templateObject was defined. 192 * 193 * @param resource the resource on which this template object was defined. 194 */ 195 public void setResource(final URL resource) 196 { 197 this.resource = resource; 198 } 199 200 /** 201 * The namespace to which this template object belongs. 202 */ 203 private String namespace; 204 205 /** 206 * Gets the namespace to which this template object belongs. 207 * 208 * @return Returns the namespace. 209 */ 210 public String getNamespace() 211 { 212 return namespace; 213 } 214 215 /** 216 * Sets the namespace to which this template object belongs. 217 * 218 * @param namespace The namespace to set. 219 */ 220 public void setNamespace(final String namespace) 221 { 222 this.namespace = StringUtils.trimToEmpty(namespace); 223 } 224 225 /** 226 * Gets the namespace logger (the logger under which output for this 227 * template object should be written). 228 * 229 * @return the logger instance. 230 */ 231 protected Logger getLogger() 232 { 233 return AndroMDALogger.getNamespaceLogger(this.namespace); 234 } 235 236 /** 237 * @see Object#toString() 238 */ 239 public String toString() 240 { 241 return ToStringBuilder.reflectionToString(this); 242 } 243}