package net.sf.jasperreports.engine.base;

import java.io.Serializable;
import net.sf.jasperreports.engine.JRField;
import net.sf.jasperreports.engine.JRPropertiesHolder;
import net.sf.jasperreports.engine.JRPropertiesMap;
import net.sf.jasperreports.engine.JRRuntimeException;
import net.sf.jasperreports.engine.design.events.JRChangeEventsSupport;
import net.sf.jasperreports.engine.design.events.JRPropertyChangeSupport;
import net.sf.jasperreports.engine.util.JRClassLoader;

public class JRBaseField implements JRField, Serializable, JRChangeEventsSupport {
  private static final long serialVersionUID = 10200L;
  
  public static final String PROPERTY_DESCRIPTION = "description";
  
  protected String name = null;
  
  protected String description = null;
  
  protected String valueClassName = String.class.getName();
  
  protected String valueClassRealName = null;
  
  protected transient Class valueClass = null;
  
  protected JRPropertiesMap propertiesMap;
  
  private transient JRPropertyChangeSupport eventSupport;
  
  protected JRBaseField() {
    this.propertiesMap = new JRPropertiesMap();
  }
  
  protected JRBaseField(JRField field, JRBaseObjectFactory factory) {
    factory.put(field, this);
    this.name = field.getName();
    this.description = field.getDescription();
    this.valueClassName = field.getValueClassName();
    this.propertiesMap = field.getPropertiesMap().cloneProperties();
  }
  
  public String getName() {
    return this.name;
  }
  
  public String getDescription() {
    return this.description;
  }
  
  public void setDescription(String description) {
    Object old = this.description;
    this.description = description;
    getEventSupport().firePropertyChange("description", old, this.description);
  }
  
  public Class getValueClass() {
    if (this.valueClass == null) {
      String className = getValueClassRealName();
      if (className != null)
        try {
          this.valueClass = JRClassLoader.loadClassForName(className);
        } catch (ClassNotFoundException e) {
          throw new JRRuntimeException(e);
        }  
    } 
    return this.valueClass;
  }
  
  public String getValueClassName() {
    return this.valueClassName;
  }
  
  private String getValueClassRealName() {
    if (this.valueClassRealName == null)
      this.valueClassRealName = JRClassLoader.getClassRealName(this.valueClassName); 
    return this.valueClassRealName;
  }
  
  public boolean hasProperties() {
    return (this.propertiesMap != null && this.propertiesMap.hasProperties());
  }
  
  public JRPropertiesMap getPropertiesMap() {
    return this.propertiesMap;
  }
  
  public JRPropertiesHolder getParentProperties() {
    return null;
  }
  
  public Object clone() {
    JRBaseField clone = null;
    try {
      clone = (JRBaseField)super.clone();
    } catch (CloneNotSupportedException e) {
      throw new JRRuntimeException(e);
    } 
    if (this.propertiesMap != null)
      clone.propertiesMap = (JRPropertiesMap)this.propertiesMap.clone(); 
    return clone;
  }
  
  public JRPropertyChangeSupport getEventSupport() {
    synchronized (this) {
      if (this.eventSupport == null)
        this.eventSupport = new JRPropertyChangeSupport(this); 
    } 
    return this.eventSupport;
  }
}
