/*
 *  Ukázka ke článku Programujeme s XML (4.) - DOM v Jave
 *  
 *  Copyright (c) 2004 Ales Hakl
 *
 *  You are free to use this source code any way you like.
 *
 */

package cz.linuxsoft.xml.dom.phonebook;

import org.w3c.dom.*;
import javax.xml.parsers.*;

public class PhoneBookTableModel extends javax.swing.table.AbstractTableModel {
    
    protected Document doc;
    
    protected String[] tags  = {"first-name","surname","phone","email"};
    protected String[] names = {"First Name", "Surname", "Phone No.", "Email"};
    
    protected int rowCount;
    
    public PhoneBookTableModel() {
        rowCount = 0;
        try {
            DOMImplementation impl = DocumentBuilderFactory.newInstance().newDocumentBuilder().getDOMImplementation();
            doc = impl.createDocument(null,"phone-book",null);
        } catch (java.lang.Exception ex) { // Nelze vytvorit dokument, nema tedy smysl pokracovat v behu
            System.out.println("Cannot create Document: "+ex.toString());
            System.exit(1);
        }
    }
    
    public PhoneBookTableModel(java.lang.String uri) throws PhoneBookException {
        try {
            DocumentBuilder builder=DocumentBuilderFactory.newInstance().newDocumentBuilder();
            doc = builder.parse(uri);
        } catch (java.lang.Exception ex) { // Neco je spatne, vicemene nas nezajima co
            throw new PhoneBookException("Cannot load document: "+ex.toString());
        }
        checkDocumentStructure();
    }
    
    public PhoneBookTableModel(java.io.File file) throws PhoneBookException{
        try {
            DocumentBuilder builder=DocumentBuilderFactory.newInstance().newDocumentBuilder();
            doc = builder.parse(file);
        } catch (java.lang.Exception ex) { // Neco je spatne, vicemene nas nezajima co
            throw new PhoneBookException("Cannot load document: "+ex.toString());
        }
        checkDocumentStructure();
    }
    
    private void checkDocumentStructure() throws PhoneBookException{
        if (!doc.getDocumentElement().getNodeName().equals("phone-book"))
            throw new PhoneBookException("Wrong document: "+doc.getDocumentElement().getNodeName());
        rowCount=doc.getDocumentElement().getElementsByTagName("person").getLength();
        fireTableStructureChanged();
    }
    
    public String getColumnName(int col) {
        return names[col];
    }
    
    public void setValueAt(Object value, int row, int col) {
        Element it = ((Element)doc.getDocumentElement().getElementsByTagName("person").item(row));
        if (it==null) return;
        Element el = (Element)it.getElementsByTagName(tags[col]).item(0);
        if (el==null) return;
        Text newText = doc.createTextNode(value.toString());
        while (el.getFirstChild()!=null){
            el.removeChild(el.getFirstChild());
        }
        el.appendChild(newText);
    }
    
    public Class getColumnClass(int col) {
        return java.lang.String.class;
    }
    
    public int getColumnCount() {
        return 4;
    }
    
    public int getRowCount() {
        return rowCount;
    }
    
    public Object getValueAt(int row, int col) {
        Element it = ((Element)doc.getDocumentElement().getElementsByTagName("person").item(row));
        if (it==null) return null;
        Element el = (Element)it.getElementsByTagName(tags[col]).item(0);
        if (el==null) return null;
        Text text = (Text)el.getFirstChild();
        if (text==null) return null;
        return text.getData();
    }
    
    synchronized public void saveToFile(java.io.File file) throws PhoneBookException {
        try {
            javax.xml.transform.TransformerFactory.newInstance().newTransformer().
            transform(new javax.xml.transform.dom.DOMSource(doc), new javax.xml.
            transform.stream.StreamResult(file));
        } catch (Throwable ex) { // Neco je spatne, vicemene nas nezajima co
            throw new PhoneBookException("Cannot save document");
        }
    }
    
    public boolean isCellEditable(int param, int param1) {
        return true;
    }
    
    synchronized public void addItem(int row) {
        Element node = doc.createElement("person");
        for (int i=0; i<tags.length; i++)
            node.appendChild(doc.createElement(tags[i]));
        if (row+1>=rowCount){
            doc.getDocumentElement().appendChild(node);
        } else {
            doc.getDocumentElement().insertBefore(node,doc.getElementsByTagName("person").item(row+1));
        }
        this.fireTableRowsInserted(row,1);
        rowCount++;
    }
    
    synchronized public void deleteItem(int row) {
        if (row==-1) return;
        doc.getDocumentElement().removeChild(doc.getElementsByTagName("person").item(row));
        rowCount=doc.getDocumentElement().getElementsByTagName("person").getLength();
        this.fireTableRowsDeleted(row,1);
    }
    
    synchronized public void moveUp(int row) {
        if (row<1) return;