/*
 * $Id: DocConverter.java,v 1.52 2007/10/30 12:21:34 marbobo Exp $
 *
 * Copyright (c) Siemens AG 2008 
 *           (c) Universität Paderborn 2008 
 * Licensed under EUPL 1.1. 
 *
 * $Log: DocConverter.java,v $
 * Revision 1.52  2007/10/30 12:21:34  marbobo
 * + removed unnecessary statements
 *
 * Revision 1.51  2007/08/21 08:03:32  marbobo
 * + Bugfix
 *
 * Revision 1.50  2007/08/09 14:38:51  marbobo
 * - 2 falsch zugeordnete LDAP- Parameter entfernt
 * + Löschen und Aktivieren von Lizenzen hinzugefügt
 *
 * Revision 1.49  2007/05/29 10:36:39  korowa
 * NullPointerException abgefangen
 */
package vkc.converter;

import vkc.analyse.Analyser;
import vkc.analyse.SummaryEntry;

import vkc.db.PersistenceManager;
import vkc.db.entities.VKCAdditionalDocumentFormat;
import vkc.db.entities.VKCDocumentType;
import vkc.db.helper.DBHelper;
import vkc.db.serializer.VKCDocumentTypeSerializer;
import vkc.exception.DBException;

import vkc.misc.VKCLogManager;

import vkc.util.FileUtils;
import vkc.util.StringUtils;
import vkc.util.VKCInputStream;
import vkc.util.ZipUtils;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;

import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;

/**
 * Klasse zum Konvertieren von Textdokumenten.
 * 
 * @author lawern
 */
public abstract class DocConverter implements Serializable {
    // Konstanten zum Erkennen des Dokumentenformats
    static final String MsWord_InputFormats = ".docx,.doc;.rtf;.asc;.ans;.wri;.mcw;.wpd;.ws;.txt;.sxw";

    static final String MsPowerpoint_InputFormats = ".pptx,.ppt;.pps";

    static final String MsExcel_InputFormats = ".xlsx,.xls";

    static final String Pdf_InputFormats = ".pdf";

    static final String Ps_InputFormats = ".ps";

    static final String Html_InputFormats = ".html;.htm;.shtml;.xml;.php;.jsp;.cgi;.do;.asp;.jhtml";

    static final String Tdf_InputFormats = ".tdf";

    static final String Eml_InputFormats = ".eml";

    static final String Msg_InputFormats = ".msg";

    static final String Tex_InputFormats = ".tex";

    // IDs aus der DB-Tabelle DOCUMENTTYPES
    public static final int txt = 1;

    public static final int pdf = 2;

    public static final int doc = 3;

    public static final int html = 4;

    public static final int ps = 5;

    public static final int ppt = 6;

    public static final int xls = 7;

    public static final int rtf = 8;

    public static final int wpd = 9;

    public static final int tdf = 10;

    public static final int note = 11;

    public static final int link = 12;

    public static final int eml = 20;

    public static final int msg = 21;

    public static final int htm = 22;

    public static final int tex = 23;

    public static final int sxw = 25;
    
    public static final int docx = 30;
    
    public static final int pptx = 31;
    
    public static final int xlsx = 32;

    /** Suffix für temporäre Dateien */
    public static String docSuffix = ".tmp";

    public static boolean openOffice = false;

    public static boolean windows = true;

    static String basePath = null;

    // Default Timeout auf 3 min setzen
    protected int timeout = 3;

    protected int openStreams = 0;

    protected Object openStreamsSemaphor = new Object();

    protected InputStream documentStream = null;

    protected URL documentUrl = null;

    private String rootFile = null;

    private boolean zipped;

    protected boolean enableHtml = false;

    protected boolean enableTdf = false;

    protected boolean enablePdf = false;

    private static HashMap documentTypes = new HashMap();

    public DocConverter() {
    }

    /**
     * Diese Methode konvertiert das aktuelle Dokument in die in der Collection
     * definierten Formate und liefert eine Collection der erzeugten
     * Konvertierungen zurück. Der Parameter conversions wird zur Zeit noch
     * nicht ausgewertet. Es wird immer HTML und TDF erzeugt. Diese Methode muss
     * aufgerufen werden, wenn ein neues Dokument publiziert wird.
     * 
     * @param conversions
     *            Collection von VKCDocumentTypes welche die zu erzeugenden
     *            Konvertierungen beschreibt.
     * 
     * @return Collection von VKCAdditionalDocumentFormat mit den erzeugten
     *         Konvertierungen.
     */
    public final Collection getAdditionalDocumentFormats(Collection conversions) {
        ArrayList finishedConversions = new ArrayList();

        if (conversions != null) {
            if (conversions.contains("EnableHTML")) {
                enableHtml = true;
            }

            if (conversions.contains("EnableTDF")) {
                enableTdf = true;
            }

            if (conversions.contains("EnablePDF")) {
                enablePdf = true;
            }
        }

        boolean converted = false;

        // Dokument konvertieren
        if (documentStream != null) {
            convert(documentStream, conversions);
            FileUtils.closeInputStream(documentStream);
            documentStream = null;
            converted = true;
        } else {
            if (documentUrl != null) {
                convert(documentUrl, conversions);
                documentUrl = null;
                converted = true;
            }
        }

        if (converted) {
            // Konverter-Streams holen
            VKCInputStream htmlStream = getHtmlStream();
            VKCInputStream tdfStream = getTdfStream();
            VKCInputStream pdfStream = getPdfStream();

            if (htmlStream != null && enableHtml) {
                // HTML-Stream vormerken
                finishedConversions.add(new VKCAdditionalDocumentFormat(htmlStream, new Integer(html), new Integer(1)));
            }

            if (tdfStream != null && enableTdf) {
                // TDF-Stream vormerken
                finishedConversions.add(new VKCAdditionalDocumentFormat(tdfStream, new Integer(tdf), new Integer(0)));
            }

            if (pdfStream != null && enablePdf) {
                // PDF-Stream vormerken
                finishedConversions.add(new VKCAdditionalDocumentFormat(pdfStream, new Integer(pdf), new Integer(0)));
            }
        }

        return finishedConversions;
    }

    /**
     * Erzeugt auf Basis des übergebenen VKCDocument einen Dokumentenkonverter
     * der das Dokument konvertieren kann, konvertiert aber das Dokument noch
     * nicht.
     * 
     * @param documentStream
     *            InputStream des zu konvertierendes Dokuments
     * @param docTypeId
     *            Dokumententyp des zu konvertierenden Streams
     * 
     * @return DocConverter der das Dokument konvertieren kann oder
     *         <code>null</code> falls kein Konverter verfügbar ist
     */
    public static final DocConverter createConverter(InputStream documentStream, int docTypeId) {
        return createConverter(documentStream, docTypeId, false, null);
    }

    /**
     * Erzeugt auf Basis des übergebenen VKCDocument einen Dokumentenkonverter
     * der das Dokument konvertieren kann, konvertiert aber das Dokument noch
     * nicht.
     * 
     * @param documentStream
     *            InputStream des zu konvertierendes Dokuments
     * @param docTypeId
     *            Dokumententyp des zu konvertierenden Streams
     * @param zipped
     *            muss auf <code>true</code> gesetzt werden, wenn der Stream
     *            komprimiert ist.
     * @param rootFile
     *            <code>null</code> falls <code>zipped==false</code>,
     *            ansonsten relativer Pfad zur Wurzeldatei.
     * 
     * @return DocConverter der das Dokument konvertieren kann oder
     *         <code>null</code> falls kein Konverter verfügbar ist
     */
    public static final DocConverter createConverter(InputStream documentStream, int docTypeId, boolean zipped, String rootFile) {
        DocConverter converter = null;

        switch (docTypeId) {
        // Adobe Portable Document Format
        case pdf:
            converter = new PdfDocConverter();

            break;

        // Generic ASCII Text
        case txt:

            // Microsoft Winword Document
        case doc:
            
            // Microsoft Winword Document
        case docx:
            
            // Rich Text Format Document
        case rtf:

            // Word Perfect Document
        case wpd:
            if (!openOffice) {
                converter = new MsWordDocConverter();
            } else {
                converter = new SoWordDocConverter();

            }

            break;

        case sxw:
            if (openOffice) {
                converter = new SoWordDocConverter();
            }

            break;
        // Hypertext Markup Language Document
        case html:
        case htm:
            converter = new HtmlDocConverter();

            break;

        // Postscript Document
        case ps:
            converter = new PsDocConverter();

            break;

         // Powerpoint Document
        case pptx:
        // Powerpoint Document
        case ppt:
            if (!openOffice) {
                converter = new MsPowerpointDocConverter();
            } else {
                converter = new SoPowerPointDocConverter();
            }

            break;

         // Excel Document
        case xlsx:
        // Excel Document
        case xls:
            if (!openOffice) {
                converter = new MsExcelDocConverter();
            } else {
                converter = new SoExcelDocConverter();
            }

            break;

        // TDF Document
        case tdf:
            converter = new TdfDocConverter();

            break;

        // EML Dokument
        case eml:
            converter = new EmlDocConverter();

            break;

        // Outlook Dokument
        case msg:
            converter = new MsOutlookDocConverter();

            break;

        // TeX Dokument
        case tex:
            converter = new TexDocConverter();

            break;
        }

        if (converter != null) {
            converter.setDocumentStream(documentStream);
            converter.setZipInfo(zipped, rootFile);
        }

        return converter;
    }

    /**
     * Interne Hilfsmethode um dem Konverter mitzuteilen ob ein Stream gezippt
     * ist oder nicht.
     * 
     * @param zipped
     *            muss auf <code>true</code> gesetzt werden, wenn der Stream
     *            komprimiert ist.
     * @param rootFile
     *            <code>null</code> falls <code>zipped==false</code>,
     *            ansonsten relativer Pfad zur Wurzeldatei.
     */
    private void setZipInfo(boolean zipped, String rootFile) {
        this.zipped = zipped;
        this.rootFile = rootFile;
    }

    /**
     * Interne Hilfsmethode um im Konverter den zu bearbeitende InputStream zu
     * setzen.
     * 
     * @param documentStream
     *            InputStream des zu konvertierenden Dokuments
     */
    private void setDocumentStream(InputStream documentStream) {
        this.documentStream = documentStream;
    }

    /**
     * Interne Hilfsmethode um im Konverter den zu bearbeitende Url zu setzen.
     * 
     * @param documentUrl
     *            Url des zu konvertierenden Dokuments
     */
    private void setDocumentUrl(URL documentUrl) {
        this.documentUrl = documentUrl;
    }

    public static final int calculateDocTypeID(URL docFile) {
        return calculateDocTypeID(docFile, 0);
    }

    public static final int calculateDocTypeID(URL docFile, int counter) {
        if (docFile == null) {
            return 0;
        }

        if (counter < 5) {
            // Eventuelle Redirects bis zum eigentlichen Dokument verfolgen
            try {
                URLConnection conn = docFile.openConnection();

                if (conn instanceof HttpURLConnection) {
                    HttpURLConnection hconn = (HttpURLConnection) conn;
                    hconn.setInstanceFollowRedirects(false);

                    int response = hconn.getResponseCode();
                    boolean redirect = ((response >= 300) && (response <= 399));

                    /*
                     * In the case of a redirect, we want to actually change the
                     * URL that was input to the new, redirected URL
                     */
                    if (redirect) {
                        String loc = conn.getHeaderField("Location");

                        if (loc.startsWith("http", 0)) {
                            docFile = new URL(loc);
                        } else {
                            docFile = new URL(docFile, loc);
                        }

                        return calculateDocTypeID(docFile, ++counter);
                    }
                }
            } catch (Throwable t) {
            }
        }

        // Dateityp aus Kopffeld auslesen
        try {
            String mimeType = docFile.openConnection().getHeaderField("Content-Type");
            int semikolon = -1;
            
            if (mimeType != null) {
                semikolon = mimeType.indexOf(';');

                // Kodierung abschneiden falls vorhanden
                if (semikolon > 0) {
                    mimeType = mimeType.substring(0, semikolon);
                }
                
                int docTypeId = getDocTypeIdByMimeType(mimeType);
                
                if (docTypeId != 0) {
                    return docTypeId;
                }
            }
        } catch (IOException e) {
        }
        
        // falls der Dateityp nicht aus dem Kopffeld ermittelt werden könnte,
        // versuchen anhand der Endung den Typ festzustellen
        // defaultmäßig wird html angenommen
        String extension = ".html";

        String docPath = docFile.getPath();
        int questionMarkId = docPath.indexOf('?');

        if (questionMarkId > 0) {
            docPath = docPath.substring(0, questionMarkId);
        }
        
        int colonMarkId = docPath.indexOf(';');
        
        if (colonMarkId > 0) {
            docPath = docPath.substring(0, colonMarkId);
        }

        int dotPosition = docPath.lastIndexOf(".");
        // falls nach dem "." "/" erscheint (z.B.
        // http://www.developer.com/ws/other/article.php/3604696),
        // dotPosition annulieren
        if (dotPosition < docPath.lastIndexOf("/")) {
            dotPosition = -1;
        }

        if (dotPosition > -1) {
            extension = docPath.substring(dotPosition).toLowerCase();
        }

        // HTML (muss vor MicrosoftWord getestet werden, da sonst .do und .doc
        // Unterscheidung falsch läuft
        
        if (Html_InputFormats.indexOf(extension) >= 0) {
            return html;
        }
        
        // MicrosoftWord
        if (MsWord_InputFormats.indexOf(extension) >= 0) {
            return doc;
        }

        // PDF
        if (Pdf_InputFormats.indexOf(extension) >= 0) {
            return pdf;
        }

        // PowerPoint
        if (MsPowerpoint_InputFormats.indexOf(extension) >= 0) {
            return ppt;
        }

        // Excel
        if (MsExcel_InputFormats.indexOf(extension) >= 0) {
            return xls;
        }

        // Postscript
        if (Ps_InputFormats.indexOf(extension) >= 0) {
            return ps;
        }

        // Tdf
        if (Tdf_InputFormats.indexOf(extension) >= 0) {
            return tdf;
        }

        // Eml
        if (Eml_InputFormats.indexOf(extension) >= 0) {
            return eml;
        }

        // Msg
        if (Msg_InputFormats.indexOf(extension) >= 0) {
            return msg;
        }

        // TeX
        if (Tex_InputFormats.indexOf(extension) >= 0) {
            return tex;
        }

        // unbekannt
        return 0;
    }

    /**
     * Erzeugt auf Basis der übergebenen URL einen Dokumentenkonverter der das
     * Dokument konvertieren kann.
     * 
     * @param docFile
     *            Url des zu konvertierenden Dokuments
     * 
     * @return DocConverter der das Dokument konvertieren kann oder null, wenn
     *         kein Konverter vorhanden
     */
    public static final DocConverter createConverter(URL docFile) {
        int docTypeId = calculateDocTypeID(docFile);
        DocConverter converter = null;
        System.out.println("DocTypeId :" + docTypeId);
        
        switch (docTypeId) {
        // MicrosoftWord-Konvertierung
        case doc:
            if (!openOffice) {
                converter = new MsWordDocConverter();
            } else {
                converter = new SoWordDocConverter();
            }

            break;

        // PDF-Konvertierung
        case pdf:
            converter = new PdfDocConverter();

            break;

        // PowerPoint-Konvertierung
        case ppt:
            if (!openOffice) {
                converter = new MsPowerpointDocConverter();
            } else {
                converter = new SoPowerPointDocConverter();
            }

            break;

        // Excel-Konvertierung
        case xls:
            if (!openOffice) {
                converter = new MsExcelDocConverter();
            } else {
                converter = new SoExcelDocConverter();
            }

            break;

        // HTML-Konvertierung
        case html:
        case htm:
            converter = new HtmlDocConverter();

            break;

        // Postscript-Konvertierung
        case ps:
            converter = new PsDocConverter();

            break;

        // Tdf-Konvertierung
        case tdf:
            converter = new TdfDocConverter();

            break;

        // Eml-Konvertierung
        case eml:
            converter = new EmlDocConverter();

            break;

        // Msg-Konvertierung
        case msg:
            converter = new MsOutlookDocConverter();

            break;

        // TeX-Konvertierung
        case tex:
            converter = new TexDocConverter();

            break;

        case sxw:
            if (openOffice) {
                converter = new SoWordDocConverter();
            }

            break;
        }

        if (converter != null) {
            converter.setDocumentUrl(docFile);
        }

        return converter;
    }

    /**
     * Setzt das Basisverzeichnis der aktuellen Installation.
     * 
     * @param path
     *            Basispfad der aktuellen Installation
     */
    public final static void setBasePath(String path) {
        basePath = path;
    }

    /**
     * Liefert das Basisverzeichnis der aktuellen Installation
     * 
     * @return basePath
     */
    public final static String getBasePath() {
        return basePath;
    }

    /**
     * Setzt das Office, welches verwendet werden soll.
     * 
     * @param _office
     *            "MsOffice" oder "OpenOffice"
     */
    public static void setOffice(String office) {
        if (office.toLowerCase().equals("openoffice")) {
            openOffice = true;
        }
    }

    /**
     * Liefert den Suffix für temporäre Dateien zurück.
     * 
     * @return docSuffix
     */
    public String getDocSuffix() {
        return docSuffix;
    }

    /**
     * Gibt eine Liste zurueck, der alle HREFs einer Seite enthält.
     * 
     * @return Link-Vektor
     */
    public ArrayList getLinks() {
        return null;
    }

    /**
     * Liefert eine Collection mit Objekten vom Typ TdfElement zurück, welche
     * das Dokument beschreiben.
     * 
     * @return Collection mit Objekten vom Typ TdfElement
     */
    public Collection getElements() {
        return null;
    }

    /**
     * Liefert den Titel des Dokuments zurück.
     * 
     * @return Titel des Dokuments oder <code>null</code>
     */
    public String getTitle() {
        return null;
    }

    /**
     * Liefert die Schlagwörter des Dokuments zurück.
     * 
     * @return Schlagwörter des Dokuments oder <code>null</code>
     */
    public String getKeyWords() {
        return null;
    }

    /**
     * Liefert die beschreibung des Dokuments zurück.
     * 
     * @return Beschreibung des Dokuments oder <code>null</code>
     */
    public String getDescription() {
        return null;
    }

    /**
     * Sichert die erzeugten Konvertierungen im DataStore und liefert eine
     * Collection der erzeugten Konvertierungen zurück.
     * 
     * @return Collection von VKCAdditionalDocumentFormat mit den gesicherten
     *         Konvertierungen.
     */
    Collection storeConversions() {
        return null;
    }

    /**
     * Setzen des Timeouts für die Konvertierung
     * 
     * <p>
     * </p>
     * 
     * @param minutes -
     *            Maximal erlaubte Dauer einer Konvertierung
     */
    public final void setTimeout(int minutes) {
        timeout = minutes;
    }

    /**
     * Diese Methode konvertiert das übergebene Dokument in die in der
     * Collection definierten Formate. Der Parameter conversions wird zur Zeit
     * noch nicht ausgewertet.
     * 
     * @param docStream
     *            InputStream mit dem zu konvertierenden Dokument
     * @param conversions
     *            Collection von VKCDocumentTypes welche die zu erzeugenden
     *            Konvertierungen beschreibt.
     */
    public void convert(InputStream docStream, Collection conversions) {
        File tmpFile = null;

        // prüfen ob der Stream ok ist
        try {
            if ((docStream == null) || (docStream.available() == 0)) {
                return;
            }
        } catch (IOException e) {
            return;
        }

        try {
            // Stream in temporäre Datei schreiben
            if (zipped == false) {
                // normalen Stream behandeln
                tmpFile = File.createTempFile("TmpDoc", getDocSuffix());
                tmpFile.deleteOnExit();
                FileUtils.saveInputStream(tmpFile, docStream, true);
                FileUtils.closeInputStream(docStream);

                // zweite Converter-Methode aufrufen
                convert(tmpFile.toURL(), conversions);
            } else {
                // gezippten Stream behandeln
                tmpFile = File.createTempFile("ZipFile", "");

                // tmpFile.delete();
                tmpFile.deleteOnExit();

                // tmpFile.mkdir();
                ZipUtils.unzip(docStream, tmpFile);

                // zweite Converter-Methode aufrufen
                convert(new File(tmpFile.getCanonicalPath() + File.separator + rootFile).toURL(), conversions);

                // Ausgepackte Dateien wieder löschen
                FileUtils.deleteDirectoryContent(tmpFile);
            }
        } catch (IOException ioe) {
            if (tmpFile != null) {
                VKCLogManager.errorLog(this, "7", "Can't create temp-file: " + tmpFile.getPath(), ioe);
            } else {
                VKCLogManager.errorLog(this, "7", "Can't create temp-file: ", ioe);
            }

            FileUtils.closeInputStream(docStream);
        } finally {
            // temporäre Dokumentendatei löschen
            if (tmpFile != null) {
                tmpFile.delete();
            }
        }
    }

    /**
     * Diese Methode konvertiert das übergebene Dokument in die in der
     * Collection definierten Formate. Der Parameter conversions wird zur Zeit
     * noch nicht ausgewertet.
     * 
     * @param document
     *            Zu konvertierendes Dokument
     * @param conversions
     *            Collection von VKCDocumentTypes welche die zu erzeugenden
     *            Konvertierungen beschreibt.
     * @throws DBException
     */
    public void convert(URL docFile, Collection conversions) {
    }

    /**
     * Initialisiert das Konverter-Objekt neu.
     */
    public void clear() {
    }

    /**
     * Liefert nach dem Aufruf der convert-Methode den Stream der
     * ASCII-Konvertierung.
     * 
     * @return Stream der ASCII-Konvertierung
     */
    public VKCInputStream getAsciiStream() {
        return null;
    }

    /**
     * Liefert nach dem Aufruf der convert-Methode den Stream der
     * Tdf-Konvertierung.
     * 
     * @return Stream der Tdf-Konvertierung
     */
    public VKCInputStream getTdfStream() {
        return null;
    }

    /**
     * Liefert nach dem Aufruf der convert-Methode den Stream der
     * Pdf-Konvertierung.
     * 
     * @return Stream der Pdf-Konvertierung
     */
    public VKCInputStream getPdfStream() {
        return null;
    }

    /**
     * Liefert nach dem Aufruf der convert-Methode den Stream der
     * HTML-Konvertierung.
     * 
     * @return Stream der HTML-Konvertierung
     */
    public VKCInputStream getHtmlStream() {
        return null;
    }

    /**
     * Sollte zum löschen der Ascii-Streams implementiert werden
     */
    void closeAsciiStream() {
    }

    /**
     * Sollte zum löschen der Ascii-Streams implementiert werden
     */
    void closeTdfStream() {
    }

    /**
     * Sollte zum löschen der Ascii-Streams implementiert werden
     */
    void closeHtmlStream() {
    }

    /**
     * erhöht die Anzahl der offenen Streams
     */
    protected void incOpenStreams() {
        synchronized (openStreamsSemaphor) {
            openStreams++;
        }
    }

    /**
     * vermindert die Anzahl der offenen Streams
     */
    protected void decOpenStreams() {
        synchronized (openStreamsSemaphor) {
            openStreams--;

            if (openStreams == 0) {
                closeConverter();
            }
        }
    }

    /**
     * Schließt das Konverter-Objekt und fügt es wieder in den Konverter-Pool
     * ein.
     */
    void closeConverter() {
    }

    /**
     * Main-Methode für Tests
     */
    public static void main(String[] args) {
        VKCLogManager.init("c:/temp/test_", ".log");
        VKCLogManager.setEnableLogging(true);
        VKCLogManager.setLogToConsole(true);

        URL url = null;

        try {
            url = new URL(args[0]);
        } catch (MalformedURLException mue) {
            System.out.println("Url ist ungültig!");
            System.exit(1);
        }

        setBasePath("./bin/win32");

        DocConverter.setOffice("OpenOffice");
        // DocConverter.setOffice("MsOffice");

        SOfficeDocConverter.startOpenOffice("C:/Program Files/OpenOffice.org 2.0/program/quickstart.exe", "localhost", "8100");
        DocConverter converter = createConverter(url);
        converter.convert(url, null);

        Collection elements = converter.getElements();

        if (elements != null) {
            // Elements ausgeben
            TdfElement actStyle = null;

            Iterator it = elements.iterator();

            while (it.hasNext()) {
                actStyle = (TdfElement) it.next();

                // neue Zeile?
                if (actStyle.newLine) {
                    System.out.println("");

                    // neuer Absatz?
                    if (actStyle.separated) {
                        System.out.println("<P>");
                    }
                }

                System.out.print("<S:" + actStyle.weight + ":" + actStyle.text + ">");
            }
        } else {
            System.out.println("Konvertierung war nicht erfolgreich!");
        }

        // TDF-Konverter testen
        try {
            InputStream tdfStream = converter.getTdfStream();
            File tmpFile = File.createTempFile("TmpDoc", ".tdf");
            tmpFile.deleteOnExit();
            FileUtils.saveInputStream(tmpFile, tdfStream, true);

            converter = createConverter(tmpFile.toURL());
            converter.convert(tmpFile.toURL().openStream(), null);
        } catch (Exception e) {
            VKCLogManager.errorLog(DocConverter.class, "", e.getMessage(), e);
        }

        // Ascii-Stream des TdfConverter ausgeben
        converter.getAsciiStream();

        // Analyser mit Elements-Collection aus dem Tdf-Stream testen
        Analyser analyser = Analyser.createAnalyser(converter.getElements());

        SummaryEntry[] keys = analyser.getKeyWords(10);

        for (int i = 0; i < 10; i++) {
            System.out.println(keys[i].getText() + ":" + keys[i].getWeight());
        }

        SummaryEntry[] summary = analyser.getSummary(5);

        for (int i = 0; i < 5; i++) {
            System.out.println(summary[i].getText() + ":" + summary[i].getWeight());
        }
    }

    /*
     * Holt die Dateierweiterung aus dem Datenbank für den mitgelieferten
     * Mimetype @param mimeType @return die Id der gesuchten Dateierweiterung
     */
    public final static int getDocTypeIdByMimeType(String mimeType) {
        if (StringUtils.isEmpty(mimeType)) {
            return 0;
        }
        
        Connection conn = null;
        
        try {
            if (documentTypes.isEmpty()) {
                conn = PersistenceManager.getInstance().getConnection();
                retrieveDocumentTypes(conn);
            }

            for (Iterator iter = documentTypes.values().iterator(); iter.hasNext();) {
                VKCDocumentType type = (VKCDocumentType) iter.next();

                if (mimeType.equalsIgnoreCase(type.getMimeType())) {
                    return type.getDocTypeId().intValue();
                }
            }

            return 0;
        } catch (DBException e) {
            return 0;
        } finally {
            DBHelper.close(conn);
        }
    }

    /*
     * Holt von VKC unterstützte Dateitypen aus dem Datenbank
     * 
     * @param conn Verbindung zum DB
     */
    private static final void retrieveDocumentTypes(Connection conn) throws DBException {
        PreparedStatement pStmt = null;
        ResultSet rs = null;

        try {
            pStmt = conn.prepareStatement("SELECT * FROM DOCUMENTTYPES");
            rs = pStmt.executeQuery();

            while (rs.next()) {
                VKCDocumentType type = new VKCDocumentType();

                type.setDocTypeId(new Integer(rs.getInt("DOCTYPEID")));
                type.setExtensionKey(rs.getString("EXTENSION_KEY"));
                type.setExtension(rs.getString("EXTENSION"));
                type.setDescription(rs.getString("DESCRIPTION"));
                type.setDescriptionKey(rs.getString("DESCR_KEY"));
                type.setShortDescription(rs.getString("DESCRIPTION_SHORT"));
                type.setInternal(new Integer(rs.getInt("INTERNAL")));
                type.setMimeType(rs.getString("MIMETYPE"));
                type.setImgPath(rs.getString("IMGPATH"));
                type.setIconExtension(rs.getString("ICON_EXTENSION"));
                type.setConvertible(new Integer(rs.getInt("CONVERTIBLE")));
                type.setEditable(new Integer(rs.getInt("EDITABLE")));
                documentTypes.put(type.getDocTypeId(), type);
            }
        } catch (Exception e) {
            VKCLogManager.errorLog(VKCDocumentTypeSerializer.class, "1", "Error while retrieving document types: ", e);
            throw new DBException(e);
        } finally {
            DBHelper.close(rs);
            DBHelper.close(pStmt);
        }
    }

    /**
     * Setzt das Betriebssystem.
     * 
     * @param _office
     *            "windows" oder "unix"
     */
    public static void setOs(String os) {
        if (os.toLowerCase().equals("unix")) {
            windows = false;
        }
    }
}