package przyklady.software;
/**Przykład do artykułu "Alternatywne źródła SAX".
 * "Sztuczny" parser SAX czytający wynik zapytania bazodanowego.
 * 
 * Kwiecień 2004.
 * @author Patryk Czarnik
 */

import java.io.IOException;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;

import org.xml.sax.ContentHandler;
import org.xml.sax.DTDHandler;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.SAXNotSupportedException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.AttributesImpl;

/**"Sztuczny" parser SAX, tworzący zdarzenia SAX
 * reprezentujące dokument zgodny z db_res.dtd
 * na podstawie obiektu ResultSet (wyniku zapytania bazodanowego).
 * 
 * @author Patryk Czarnik
 */
public class DBReader implements XMLReader {
  public DBReader() {
  }
  public DBReader(ResultSet aData) {
    setResultSet(aData);
  }

  /** Ustawia źródło danych. */
  public void setResultSet(ResultSet aData) {
    fData = aData;
  }

  /**Tworzy zdarzenia SAX reprezentujące dokument wynikowy
   * i wysyła je do obiektu ustawionego w setContentHandler.
   */
  public void parse(String aSystemId) throws IOException, SAXException {
    if(fData != null && fHandler != null) {
      try {
        ResultSetMetaData meta = fData.getMetaData();
        int cols_count = meta.getColumnCount();
        AttributesImpl attrs = new AttributesImpl();
        
        fHandler.startDocument();
        attrs.addAttribute("", "column-count", "column-count", "CDATA", String.valueOf(cols_count));
        fHandler.startElement("", "result", "result", attrs);
        attrs.clear();
        
        // nagłówki kolumn
        fHandler.startElement("", "header", "header", attrs);
        for(int i=1; i<=cols_count; i++) {
          String name = meta.getColumnName(i);
          fHandler.startElement("", "col", "col", attrs);
          fHandler.characters(name.toCharArray(), 0, name.length());
          fHandler.endElement("", "col", "col");
        }
        fHandler.endElement("", "header", "header");

        // dane
        while(fData.next()) {
          fHandler.startElement("", "row", "row", attrs);
          for(int i=1; i<=cols_count; i++) {
            String val = fData.getString(i);
            fHandler.startElement("", "col", "col", attrs);
            fHandler.characters(val.toCharArray(), 0, val.length());
            fHandler.endElement("", "col", "col");
          }
          fHandler.endElement("", "row", "row");
        }
        
        fHandler.endElement("", "result", "result");
        fHandler.endDocument();
      } catch (SQLException e) {
        throw new SAXException(e);
      }
    }
  }

  public void parse(InputSource aInput) throws IOException, SAXException {
    this.parse("");
  }

  public ContentHandler getContentHandler() {
    return fHandler;
  }

  /**Ustawia obiekt, do którego będą wysyłane zdarzenia SAX
   * podczas parsowania.
   */
  public void setContentHandler(ContentHandler aHandler) {
    fHandler = aHandler;
  }

  // Nie implementowane:
  public DTDHandler getDTDHandler() {
    return null;
  }
  public void setDTDHandler(DTDHandler handler) {
  }
  public EntityResolver getEntityResolver() {
    return null;
  }
  public void setEntityResolver(EntityResolver resolver) {
  }
  public ErrorHandler getErrorHandler() {
    return null;
  }
  public void setErrorHandler(ErrorHandler handler) {
  }
  public boolean getFeature(String name) throws SAXNotRecognizedException,
  SAXNotSupportedException {
    return false;
  }
  public void setFeature(String name, boolean value)
  	throws SAXNotRecognizedException, SAXNotSupportedException {
  }
  public Object getProperty(String name) throws SAXNotRecognizedException,
      SAXNotSupportedException {
    return null;
  }
  public void setProperty(String name, Object value)
      throws SAXNotRecognizedException, SAXNotSupportedException {
  }
  
  private ResultSet fData;
  private ContentHandler fHandler;
}
