/*
 * Copyright (C) 2014 kgto.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301  USA
 */
/*
 * $Id: SearchDataRW.java 87 2014-10-08 07:50:03Z tuna_p $
 */

package Form;

import WebScraping.SearchData;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

/**
 *
 * @author kgto
 */
public class SearchDataRW {
    
    DocumentBuilder builder;
    public Document document;
    Element root;
    
    private final String splitchar = "\t";
    
    private String UrlAdress;
    private ArrayList slist;
    
    public SearchDataRW() {
        try {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            builder = factory.newDocumentBuilder();
            
        } catch (ParserConfigurationException ex) {
            Logger.getLogger(SearchDataRW.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    public void seturl(String UrlAdress) {
        this.UrlAdress = UrlAdress;
    }
    
    public void setslist(ArrayList slist) {
        this.slist = slist;
    }
    
    public String geturl() {
        return UrlAdress;
    }
    
    public ArrayList getslist() {
        return slist;
    }
    
    /**
     * 保存.
     * @param file 
     */
    public void save(File file) {
        //saveCsv(file);
        //saveXml(file);
        
        saveUrl(UrlAdress);
        saveSearchList(slist);
        write(file);
    }
    
    /**
     * 読込.
     * @param file 
     */
    public void load(File file) {
        //loadCsv(file);
        //loadXml(file);
        
        read(file);
        UrlAdress = loadUrl();
        slist     = loadSearchList();
    }
    
    /* ---------------------------------------------------------------------- */
    /**
     * 保存(CSV形式).
     * @param file 
     */
    public void saveCsv(File file) {
        
        try {
            //空のファイルを作成
            file.createNewFile();
            
            FileOutputStream fileoutputstream = new FileOutputStream(file);
            OutputStreamWriter outputstreamwriter = new OutputStreamWriter(fileoutputstream, "UTF-8");
            BufferedWriter bufferedwriter = new BufferedWriter(outputstreamwriter);
            
            // ＵＲＬ
            bufferedwriter.write(UrlAdress);
            bufferedwriter.write("\n");
            // 検索情報
            for (Object slist1 : slist) {
                SearchData sdat = (SearchData) slist1;
                StringBuilder str = new StringBuilder();
                str.append(sdat.getitem()).append(splitchar);
                str.append(sdat.getHtmltag()).append(splitchar);
                str.append(sdat.getHtmlid()).append(splitchar);
                str.append(sdat.getHtmlclass()).append(splitchar);
                str.append(sdat.getaround()).append(splitchar);
                str.append(sdat.getregexp()).append("\n");

                bufferedwriter.write(str.toString());
            }
            bufferedwriter.close();
            
        } catch(IOException ex) {
            Logger.getLogger(SearchDataRW.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    /**
     * 読込(CSV形式).
     * @param file 
     */
    public void loadCsv(File file) {
        slist = new ArrayList();
        
        try {
            FileInputStream fileinputstream = new FileInputStream(file);
            InputStreamReader inputstreamreader = new InputStreamReader(fileinputstream, "UTF-8");
            BufferedReader bufferedreader = new BufferedReader(inputstreamreader);
            
            String rec;
            
            // ＵＲＬ
            UrlAdress = bufferedreader.readLine();
            // 検索情報
            while((rec = bufferedreader.readLine()) != null) {
                String[] recary = rec.split(splitchar, -1);
                SearchData sdat = new SearchData();
                sdat.setitem(recary[0]);
                sdat.setHtmltag(recary[1]);                
                sdat.setHtmlid(recary[2]);
                sdat.setHtmlclass(recary[3]);
                sdat.setaround(recary[4]);
                sdat.setregexp(recary[5]);
                
                slist.add(sdat);
            }
            bufferedreader.close();
            
        } catch(IOException ex) {
            Logger.getLogger(SearchDataRW.class.getName()).log(Level.SEVERE, null, ex);
        }
        
    }
    
    /* ---------------------------------------------------------------------- */
    /**
     * 保存(XML形式).
     * @param file 
     */
    public void saveXml(File file) {
        try {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            DOMImplementation domImpl = builder.getDOMImplementation();
            
            Document document = domImpl.createDocument("","searchdata",null);
            Element root = document.getDocumentElement();
            
            // ＵＲＬ
            Element url = document.createElement("url");
            url.appendChild(document.createTextNode(UrlAdress));
            root.appendChild(url);
            
            // 検索情報
            for (Object slist1 : slist) {
                SearchData sdat = (SearchData) slist1;
                
                Element cslist    = document.createElement("searchlist");
                Element item      = document.createElement("item");
                Element htmltag   = document.createElement("htmltag");
                Element htmlid    = document.createElement("htmlid");
                Element htmlclass = document.createElement("htmlclass");
                Element around    = document.createElement("around");
                Element regexp    = document.createElement("regexp");
                
                item.appendChild(document.createTextNode(sdat.getitem()));
                htmltag.appendChild(document.createTextNode(sdat.getHtmltag()));
                htmlid.appendChild(document.createTextNode(sdat.getHtmlid()));
                htmlclass.appendChild(document.createTextNode(sdat.getHtmlclass()));
                around.appendChild(document.createTextNode(sdat.getaround()));
                regexp.appendChild(document.createTextNode(sdat.getregexp()));
                
                cslist.appendChild(item);
                cslist.appendChild(htmltag);
                cslist.appendChild(htmlid);
                cslist.appendChild(htmlclass);
                cslist.appendChild(around);
                cslist.appendChild(regexp);

                root.appendChild(cslist);
            }
            // 出力
            TransformerFactory transFactory = TransformerFactory.newInstance();
            Transformer transformer = transFactory.newTransformer();
            
            DOMSource source = new DOMSource(document);
            FileOutputStream os = new FileOutputStream(file);
            StreamResult result = new StreamResult(os);
            transformer.transform(source, result);
            
        } catch (ParserConfigurationException | FileNotFoundException ex) {
            Logger.getLogger(SearchDataRW.class.getName()).log(Level.SEVERE, null, ex);
        } catch (TransformerConfigurationException ex) {
            Logger.getLogger(SearchDataRW.class.getName()).log(Level.SEVERE, null, ex);
        } catch (TransformerException ex) {
            Logger.getLogger(SearchDataRW.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    /**
     * 読込(XML形式).
     * @param file 
     */
    public void loadXml(File file) {
        slist = new ArrayList();
        
        try {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document doc = builder.parse(file);
            
            // ルート要素の取得
            Element root = doc.getDocumentElement();
            
            // ＵＲＬ
            NodeList url = root.getElementsByTagName("url");
            Node urlnode = url.item(0);
            UrlAdress = urlnode.getFirstChild().getNodeValue();
            
            // 検索情報
            NodeList cslist = root.getElementsByTagName("searchlist");
            for(int i = 0; i < cslist.getLength(); i++) {
                SearchData sdat = new SearchData();
                
                Node slistnode = cslist.item(i);
                Node child;
                for (child = slistnode.getFirstChild(); child != null; child = child.getNextSibling()) {
                    if(child.getNodeType() == Node.ELEMENT_NODE) {
                        
                        String tag = child.getNodeName();
                        String rtn = "";
                        if(child.getFirstChild() != null) {
                            rtn = child.getFirstChild().getNodeValue();
                        }
                        
                        switch (tag) {
                            case "item" :
                                sdat.setitem(rtn);
                                break;
                            case "htmltag" :
                                sdat.setHtmltag(rtn);
                                break;
                            case "htmlid" :
                                sdat.setHtmlid(rtn);
                                break;
                            case "htmlclass" :
                                sdat.setHtmlclass(rtn);
                                break;
                            case "around" :
                                sdat.setaround(rtn);
                                break;
                            case "regexp" :
                                sdat.setregexp(rtn);
                                break;
                        }
                    }
                }
                slist.add(sdat);
            }
            
        } catch (ParserConfigurationException | SAXException | IOException ex) {
            Logger.getLogger(SearchDataRW.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    /* ---------------------------------------------------------------------- */
    
    public String loadUrl() {
        String urladdress;
        
        NodeList nodelist = root.getElementsByTagName("url");
        Node node = nodelist.item(0);
        urladdress = node.getFirstChild().getNodeValue();
        
        return urladdress;
    }
    
    public ArrayList<SearchData> loadSearchList() {
        ArrayList<SearchData> slist = new ArrayList<>();
        
        NodeList nodelist = root.getElementsByTagName("searchlist");
        for(int i = 0; i < nodelist.getLength(); i++) {
            Node childnode = nodelist.item(i);
            
            boolean sdatflg = false;
            SearchData sdat = new SearchData();
            
            //NodeList childnodelist = childnode.getChildNodes();
            //for(int j = 0; j < childnodelist.getLength(); j++) {
            //    Node child = childnodelist.item(j);
            
            for (Node child = childnode.getFirstChild(); 
                    child != null; child = child.getNextSibling()) {
                
                if(child.getNodeType() == Node.ELEMENT_NODE) {
                    
                    String tag = child.getNodeName();
                    String rtn = "";
                    if(child.getFirstChild() != null) {
                        rtn = child.getFirstChild().getNodeValue();
                    }

                    switch (tag) {
                        case "item" :
                            sdat.setitem(rtn);
                            sdatflg = true;
                            break;
                        case "htmltag" :
                            sdat.setHtmltag(rtn);
                            sdatflg = true;
                            break;
                        case "htmlid" :
                            sdat.setHtmlid(rtn);
                            sdatflg = true;
                            break;
                        case "htmlclass" :
                            sdat.setHtmlclass(rtn);
                            sdatflg = true;
                            break;
                        case "around" :
                            sdat.setaround(rtn);
                            sdatflg = true;
                            break;
                        case "regexp" :
                            sdat.setregexp(rtn);
                            sdatflg = true;
                            break;
                    }
                }
            }
            if(sdatflg) slist.add(sdat);
        }
        return slist;
    }
    
    public Element loadElement(String elementTagName) {
        NodeList nodelist = root.getElementsByTagName(elementTagName);
        Element element = (Element)nodelist.item(0);
        
        return element;
    }
    
    public void saveUrl(String urladdress) {
        checkdoc();
        removeElement("url");    // 既にElementが存在してた場合、一度削除
        
        Element url = document.createElement("url");
        url.appendChild(document.createTextNode(urladdress));
        root.appendChild(url);
    }
    
    public void saveSearchList(ArrayList slist) {
        checkdoc();
        removeElement("searchlist");    // 既にElementが存在してた場合、一度削除
        
        for (Object slist1 : slist) {
            SearchData sdat = (SearchData) slist1;
            
            Element cslist    = document.createElement("searchlist");

            addChild(cslist, "item", sdat.getitem());
            addChild(cslist, "htmltag", sdat.getHtmltag());
            addChild(cslist, "htmlid", sdat.getHtmlid());
            addChild(cslist, "htmlclass", sdat.getHtmlclass());
            addChild(cslist, "around", sdat.getaround());
            addChild(cslist, "regexp", sdat.getregexp());

            root.appendChild(cslist);
        }
    }
    
    public void saveElement(Element element) {
        checkdoc();
        removeElement(element.getTagName());    // 既にElementが存在してた場合、一度削除

        root.appendChild(element);
    }
    
    private void addChild(Element cslist, String keyword, String data) {
        if(!data.isEmpty()) {
            Element element = document.createElement(keyword);
            element.appendChild(document.createTextNode(data));
            cslist.appendChild(element);
        }
    }
    
    private void removeElement(String elementTagName) {
        NodeList nodelist = document.getElementsByTagName(elementTagName);
        for(int i = 0; i < nodelist.getLength(); i++) {
            Node node = nodelist.item(i);
            root.removeChild(node);
        }
    }
    
    /**
     * ドキュメントチェック.
     * 新規の場合やＸＭＬファイルの読込みが行われていない状態時、新たにルートエレメントを作成する。
     * 既読の場合、ルートエレメントの取得を行う。
     */
    public void checkdoc() {
        if(document == null) {
            DOMImplementation domImpl = builder.getDOMImplementation();
            document = domImpl.createDocument("","searchdata",null);
        }
        root = document.getDocumentElement();
    }
    
    /**
     * XML読込み.
     * @param file 
     */
    public void read(File file) {
        try {
            document = builder.parse(file);
            root = document.getDocumentElement();
            
        } catch (SAXException | IOException ex) {
            Logger.getLogger(SearchDataRW.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    /**
     * XML書込み.
     * @param file 
     */
    public void write(File file) {
        try {
            TransformerFactory transFactory = TransformerFactory.newInstance();
            Transformer transformer = transFactory.newTransformer();
            
            DOMSource source = new DOMSource(document);
            FileOutputStream os = new FileOutputStream(file);
            StreamResult result = new StreamResult(os);
            transformer.transform(source, result);
            
        } catch (TransformerConfigurationException ex) {
            Logger.getLogger(SearchDataRW.class.getName()).log(Level.SEVERE, null, ex);
        } catch (FileNotFoundException | TransformerException ex) {
            Logger.getLogger(SearchDataRW.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
}
