package net.sf.jasperreports.engine.base;

import java.io.Serializable;
import net.sf.jasperreports.engine.JRExpression;
import net.sf.jasperreports.engine.JRParameter;
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 JRBaseParameter implements JRParameter, 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 boolean isSystemDefined = false;
  
  protected boolean isForPrompting = true;
  
  protected transient Class valueClass = null;
  
  protected JRExpression defaultValueExpression = null;
  
  protected JRPropertiesMap propertiesMap;
  
  private transient JRPropertyChangeSupport eventSupport;
  
  protected JRBaseParameter() {
    this.propertiesMap = new JRPropertiesMap();
  }
  
  protected JRBaseParameter(JRParameter parameter, JRBaseObjectFactory factory) {
    factory.put(parameter, this);
    this.name = parameter.getName();
    this.description = parameter.getDescription();
    this.valueClassName = parameter.getValueClassName();
    this.isSystemDefined = parameter.isSystemDefined();
    this.isForPrompting = parameter.isForPrompting();
    this.defaultValueExpression = factory.getExpression(parameter.getDefaultValueExpression());
    this.propertiesMap = parameter.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 isSystemDefined() {
    return this.isSystemDefined;
  }
  
  public boolean isForPrompting() {
    return this.isForPrompting;
  }
  
  public JRExpression getDefaultValueExpression() {
    return this.defaultValueExpression;
  }
  
  public boolean hasProperties() {
    return (this.propertiesMap != null && this.propertiesMap.hasProperties());
  }
  
  public JRPropertiesMap getPropertiesMap() {
    return this.propertiesMap;
  }
  
  public JRPropertiesHolder getParentProperties() {
    return null;
  }
  
  public Object clone() {
    JRBaseParameter clone = null;
    try {
      clone = (JRBaseParameter)super.clone();
    } catch (CloneNotSupportedException e) {
      throw new JRRuntimeException(e);
    } 
    if (this.defaultValueExpression != null)
      clone.defaultValueExpression = (JRExpression)this.defaultValueExpression.clone(); 
    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;
  }
}
