001/* ======================================================================== 002 * JCommon : a free general purpose class library for the Java(tm) platform 003 * ======================================================================== 004 * 005 * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors. 006 * 007 * Project Info: http://www.jfree.org/jcommon/index.html 008 * 009 * This library is free software; you can redistribute it and/or modify it 010 * under the terms of the GNU Lesser General Public License as published by 011 * the Free Software Foundation; either version 2.1 of the License, or 012 * (at your option) any later version. 013 * 014 * This library is distributed in the hope that it will be useful, but 015 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 016 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 017 * License for more details. 018 * 019 * You should have received a copy of the GNU Lesser General Public 020 * License along with this library; if not, write to the Free Software 021 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 022 * USA. 023 * 024 * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 025 * in the United States and other countries.] 026 * 027 * ------------------------------ 028 * AbstractObjectDescription.java 029 * ------------------------------ 030 * (C)opyright 2003, 2004, by Thomas Morgner and Contributors. 031 * 032 * Original Author: Thomas Morgner; 033 * Contributor(s): David Gilbert (for Object Refinery Limited); 034 * 035 * $Id: AbstractObjectDescription.java,v 1.3 2005/11/14 10:58:37 mungady Exp $ 036 * 037 * Changes (from 19-Feb-2003) 038 * ------------------------- 039 * 19-Feb-2003 : Added standard header and Javadocs (DG); 040 * 29-Apr-2003 : Distilled from the JFreeReport project and moved into JCommon 041 * 042 */ 043 044package org.jfree.xml.factory.objects; 045 046import java.util.ArrayList; 047import java.util.Collections; 048import java.util.HashMap; 049import java.util.Iterator; 050 051import org.jfree.util.Configuration; 052import org.jfree.util.Log; 053import org.jfree.util.ReadOnlyIterator; 054 055/** 056 * An abstract base class for object descriptions. 057 * 058 * @author Thomas Morgner. 059 */ 060public abstract class AbstractObjectDescription implements ObjectDescription, Cloneable { 061 062 /** The class. */ 063 private Class className; 064 065 /** Storage for parameters. */ 066 private HashMap parameters; 067 068 /** Storage for parameter definitions. */ 069 private HashMap parameterDefs; 070 071 /** The configuration for the object description. */ 072 private Configuration config; 073 074 /** 075 * Creates a new object description. 076 * 077 * @param className the class. 078 */ 079 public AbstractObjectDescription(final Class className) { 080 this.className = className; 081 this.parameters = new HashMap(); 082 this.parameterDefs = new HashMap(); 083 } 084 085 /** 086 * Returns a parameter class. 087 * 088 * @param name the parameter definition. 089 * 090 * @return The class. 091 */ 092 public Class getParameterDefinition(final String name) { 093 return (Class) this.parameterDefs.get(name); 094 } 095 096 /** 097 * Sets the class for a parameter. 098 * 099 * @param name the parameter name. 100 * @param obj the parameter class. 101 */ 102 public void setParameterDefinition(final String name, final Class obj) { 103 if (obj == null) { 104 this.parameterDefs.remove(name); 105 } 106 else { 107 this.parameterDefs.put(name, obj); 108 } 109 } 110 111 /** 112 * Converts primitives to corresponding object class. 113 * 114 * @param obj the class. 115 * 116 * @return The class. 117 */ 118 public static Class convertPrimitiveClass(final Class obj) { 119 if (!obj.isPrimitive()) { 120 return obj; 121 } 122 if (obj == Boolean.TYPE) { 123 return Boolean.class; 124 } 125 if (obj == Byte.TYPE) { 126 return Byte.class; 127 } 128 if (obj == Character.TYPE) { 129 return Character.class; 130 } 131 if (obj == Short.TYPE) { 132 return Short.class; 133 } 134 if (obj == Integer.TYPE) { 135 return Integer.class; 136 } 137 if (obj == Long.TYPE) { 138 return Long.class; 139 } 140 if (obj == Float.TYPE) { 141 return Float.class; 142 } 143 if (obj == Double.TYPE) { 144 return Double.class; 145 } 146 throw new IllegalArgumentException("Class 'void' is not allowed here"); 147 } 148 149 /** 150 * Sets a parameter. 151 * 152 * @param name the name. 153 * @param value the value. 154 */ 155 public void setParameter(final String name, final Object value) { 156 if (getParameterDefinition(name) == null) { 157 throw new IllegalArgumentException("No such Parameter defined: " + name 158 + " in class " + getObjectClass()); 159 } 160 final Class parameterClass = convertPrimitiveClass(getParameterDefinition(name)); 161 if (!parameterClass.isAssignableFrom(value.getClass())) { 162 throw new ClassCastException("In Object " + getObjectClass() 163 + ": Value is not assignable: " + value.getClass() 164 + " is not assignable from " + parameterClass); 165 } 166 this.parameters.put(name, value); 167 } 168 169 /** 170 * Returns an iterator for the parameter names. 171 * 172 * @return The iterator. 173 */ 174 public synchronized Iterator getParameterNames() { 175 final ArrayList parameterNames = new ArrayList(this.parameterDefs.keySet()); 176 Collections.sort(parameterNames); 177 return new ReadOnlyIterator (parameterNames.iterator()); 178 } 179 180 /** 181 * Returns an iterator for the parameter names. 182 * 183 * @return The iterator. 184 */ 185 protected Iterator getDefinedParameterNames() { 186 return new ReadOnlyIterator (this.parameters.keySet().iterator()); 187 } 188 189 /** 190 * Returns a parameter value. 191 * 192 * @param name the parameter name. 193 * 194 * @return The parameter value. 195 */ 196 public Object getParameter(final String name) { 197 return this.parameters.get(name); 198 } 199 200 /** 201 * Returns the class for the object. 202 * 203 * @return The class. 204 */ 205 public Class getObjectClass() { 206 return this.className; 207 } 208 209 /** 210 * Returns a cloned instance of the object description. The contents 211 * of the parameter objects collection are cloned too, so that any 212 * already defined parameter value is copied to the new instance. 213 * <p> 214 * Parameter definitions are not cloned, as they are considered read-only. 215 * <p> 216 * The newly instantiated object description is not configured. If it 217 * need to be configured, then you have to call configure on it. 218 * 219 * @return A cloned instance. 220 */ 221 public ObjectDescription getInstance() { 222 try { 223 final AbstractObjectDescription c = (AbstractObjectDescription) super.clone(); 224 c.parameters = (HashMap) this.parameters.clone(); 225 return c; 226 } 227 catch (Exception e) { 228 Log.error("Should not happen: Clone Error: ", e); 229 return null; 230 } 231 } 232 233 234 /** 235 * Returns a cloned instance of the object description. The contents 236 * of the parameter objects collection are cloned too, so that any 237 * already defined parameter value is copied to the new instance. 238 * <p> 239 * Parameter definitions are not cloned, as they are considered read-only. 240 * <p> 241 * The newly instantiated object description is not configured. If it 242 * need to be configured, then you have to call configure on it. 243 * 244 * @return A cloned instance. 245 */ 246 public ObjectDescription getUnconfiguredInstance() { 247 try { 248 final AbstractObjectDescription c = (AbstractObjectDescription) super.clone(); 249 c.parameters = (HashMap) this.parameters.clone(); 250 c.config = null; 251 return c; 252 } 253 catch (Exception e) { 254 Log.error("Should not happen: Clone Error: ", e); 255 return null; 256 } 257 } 258 259 /** 260 * Configures this factory. The configuration contains several keys and 261 * their defined values. The given reference to the configuration object 262 * will remain valid until the report parsing or writing ends. 263 * <p> 264 * The configuration contents may change during the reporting. 265 * 266 * @param config the configuration, never null 267 */ 268 public void configure(final Configuration config) { 269 if (config == null) { 270 throw new NullPointerException("The given configuration is null"); 271 } 272 this.config = config; 273 } 274 275 /** 276 * Returns the configuration for that object description. 277 * 278 * @return the configuration or null, if not yet set. 279 */ 280 public Configuration getConfig() { 281 return this.config; 282 } 283 284 /** 285 * Tests for equality. 286 * 287 * @param o the object to test. 288 * 289 * @return A boolean. 290 */ 291 public boolean equals(final Object o) { 292 if (this == o) { 293 return true; 294 } 295 if (!(o instanceof AbstractObjectDescription)) { 296 return false; 297 } 298 299 final AbstractObjectDescription abstractObjectDescription = (AbstractObjectDescription) o; 300 301 if (!this.className.equals(abstractObjectDescription.className)) { 302 return false; 303 } 304 305 return true; 306 } 307 308 /** 309 * Returns a hash code for the object. 310 * 311 * @return The hash code. 312 */ 313 public int hashCode() { 314 return this.className.hashCode(); 315 } 316}