package net.sf.jasperreports.engine.design;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.ArrayList;
import java.util.List;
import net.sf.jasperreports.engine.JRQueryChunk;
import net.sf.jasperreports.engine.base.JRBaseQuery;
import net.sf.jasperreports.engine.design.events.JRChangeEventsSupport;
import net.sf.jasperreports.engine.design.events.JRPropertyChangeSupport;
import net.sf.jasperreports.engine.util.JRQueryChunkHandler;
import net.sf.jasperreports.engine.util.JRQueryParser;

public class JRDesignQuery extends JRBaseQuery implements JRChangeEventsSupport {
  private transient JRPropertyChangeSupport propSupport;
  
  private static final long serialVersionUID = 10200L;
  
  public static final String PROPERTY_LANGUAGE = "language";
  
  public static final String PROPERTY_TEXT = "text";
  
  protected List chunks = new ArrayList();
  
  private final transient JRQueryChunkHandler chunkAdder = new JRQueryChunkHandler() {
      private final JRDesignQuery this$0;
      
      public void handleParameterChunk(String text) {
        JRDesignQuery.this.addParameterChunk(text);
      }
      
      public void handleParameterClauseChunk(String text) {
        JRDesignQuery.this.addParameterClauseChunk(text);
      }
      
      public void handleTextChunk(String text) {
        JRDesignQuery.this.addTextChunk(text);
      }
      
      public void handleClauseChunk(String[] tokens) {
        JRDesignQuery.this.addClauseChunk(tokens);
      }
    };
  
  public JRQueryChunk[] getChunks() {
    JRQueryChunk[] chunkArray = null;
    if (this.chunks != null && this.chunks.size() > 0) {
      chunkArray = new JRQueryChunk[this.chunks.size()];
      this.chunks.toArray((Object[])chunkArray);
    } 
    return chunkArray;
  }
  
  public void setChunks(List chunks) {
    this.chunks = chunks;
  }
  
  public void addChunk(JRDesignQueryChunk chunk) {
    this.chunks.add(chunk);
  }
  
  public void addTextChunk(String text) {
    JRDesignQueryChunk chunk = new JRDesignQueryChunk();
    chunk.setType((byte)1);
    chunk.setText(text);
    this.chunks.add(chunk);
  }
  
  public void addParameterChunk(String text) {
    JRDesignQueryChunk chunk = new JRDesignQueryChunk();
    chunk.setType((byte)2);
    chunk.setText(text);
    this.chunks.add(chunk);
  }
  
  public void addParameterClauseChunk(String text) {
    JRDesignQueryChunk chunk = new JRDesignQueryChunk();
    chunk.setType((byte)3);
    chunk.setText(text);
    this.chunks.add(chunk);
  }
  
  public void addClauseChunk(String[] tokens) {
    JRDesignQueryChunk chunk = new JRDesignQueryChunk();
    chunk.setType((byte)4);
    chunk.setTokens(tokens);
    this.chunks.add(chunk);
  }
  
  public void setText(String text) {
    Object old = getText();
    this.chunks = new ArrayList();
    JRQueryParser.instance().parse(text, this.chunkAdder);
    getEventSupport().firePropertyChange("text", old, getText());
  }
  
  public void setLanguage(String language) {
    String oldValue = this.language;
    this.language = language;
    getPropertyChangeSupport().firePropertyChange("language", oldValue, this.language);
  }
  
  public JRPropertyChangeSupport getEventSupport() {
    synchronized (this) {
      if (this.propSupport == null)
        this.propSupport = new JRPropertyChangeSupport(this); 
    } 
    return this.propSupport;
  }
  
  protected PropertyChangeSupport getPropertyChangeSupport() {
    return (PropertyChangeSupport)getEventSupport();
  }
  
  public void addPropertyChangeListener(PropertyChangeListener l) {
    getPropertyChangeSupport().addPropertyChangeListener(l);
  }
  
  public void addPropertyChangeListener(String propName, PropertyChangeListener l) {
    getPropertyChangeSupport().addPropertyChangeListener(propName, l);
  }
  
  public void removePropertyChangeListener(PropertyChangeListener l) {
    getPropertyChangeSupport().removePropertyChangeListener(l);
  }
  
  public void removePropertyChangeListener(String propName, PropertyChangeListener l) {
    getPropertyChangeSupport().removePropertyChangeListener(propName, l);
  }
  
  public Object clone() {
    JRDesignQuery clone = (JRDesignQuery)super.clone();
    if (this.chunks != null) {
      clone.chunks = new ArrayList(this.chunks.size());
      for (int i = 0; i < this.chunks.size(); i++)
        clone.chunks.add(((JRQueryChunk)this.chunks.get(i)).clone()); 
    } 
    return clone;
  }
}
