import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.TransferHandler;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultStyledDocument;
import javax.swing.text.Document;
import javax.swing.text.Element;
import javax.swing.text.StyleConstants.ColorConstants;
import javax.swing.text.StyleConstants.FontConstants;

import sun.awt.datatransfer.ClipboardTransferable;


public class Analysis {
    public static void main(String[] args) throws Throwable {
        final JFrame f = new JFrame();
        final JEditorPane editor = new JEditorPane("text/rtf","");
        JScrollPane scroll = new JScrollPane(editor);
        JPanel panel = new JPanel(new BorderLayout());
        JButton but = new JButton("Export !!");
        panel.add(scroll, BorderLayout.CENTER);
        panel.add(but, BorderLayout.SOUTH);
        f.setContentPane(panel);
        but.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                Document document = editor.getDocument();
//                System.out.println(document);
                DefaultStyledDocument doc = (DefaultStyledDocument)document;
                Element[] rootElements = doc.getRootElements();
                StringBuilder buf = new StringBuilder();
                for (Element element : rootElements) {
                    exploreElement(element, 0, buf);
                }
                String data = buf.toString();
                while (data.startsWith("<BR>")) {
                    data = data.substring(4);
                }
                while (data.endsWith("<BR>")) {
                    data = data.substring(0, data.length()-4);
                }
                JTextArea area = new JTextArea("<BLOCKQUOTE><PRE>" + data + "</PRE><BLOCKQUOTE>");
                area.setWrapStyleWord(true);
                area.setLineWrap(true);
                JScrollPane scroll = new JScrollPane(area);
                Dimension preferredSize = new Dimension(400,300);
                scroll.setPreferredSize(preferredSize);
                scroll.setMinimumSize(preferredSize);
                JOptionPane.showMessageDialog(f, scroll);
            }
        });
        editor.setTransferHandler(new Delegate(editor.getTransferHandler()));
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setSize(800, 600);
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }
    
    
    private static void exploreElement(Element elt, int indent, StringBuilder buf) {
        String indentString = "";
        for (int index = 0; index < indent; index++) {
            indentString += "\t";
        }
//        System.out.print(indentString + "ELT:" + elt);
        AttributeSet attributes = elt.getAttributes();
//        Enumeration<?> attributeNames = attributes.getAttributeNames();
//        while (attributeNames.hasMoreElements()) {
//            Object name = (Object) attributeNames.nextElement();
//            Object attribute = attributes.getAttribute(name);
//            System.out.println(indentString + "  ATT:" + name + "=" + attribute);
//        }
//        System.out.println(indentString + " ELT NAME:" + elt.getName() + " " + elt.getClass());
        if (elt.getName().equals("content")) {
            try {
                int startOffset = elt.getStartOffset();
                String text = elt.getDocument().getText(startOffset,elt.getEndOffset() - startOffset);
//                System.out.println(indentString + "  ELT TEXT:");
//                System.out.println(text);
                Color color = getColor(attributes);
                boolean isBold = getBoolean(attributes, FontConstants.Bold);
                boolean isItalic = getBoolean(attributes, FontConstants.Italic);
                if (color != null) {
                    buf.append("<FONT COLOR=\"");
                    buf.append(format(color));
                    buf.append("\">");
                }
                if (isBold) {
                    buf.append("<B>");
                }
                if (isItalic) {
                    buf.append("<I>");
                }
                text = text.replaceAll("&", "&amp;");
                text = text.replaceAll("<", "&lt;");
                text = text.replaceAll(">", "&gt;");
                text = text.replaceAll("\n", "<BR>");
                buf.append(text);
                if (isItalic) {
                    buf.append("</I>");
                }
                if (isBold) {
                    buf.append("</B>");
                }
                if (color != null) {
                    buf.append("</FONT>");
                }
            } catch (BadLocationException e) {
                e.printStackTrace();
            }
        }
        for (int index = 0; index < elt.getElementCount(); index++) {
            Element child = elt.getElement(index);
            exploreElement(child, indent+1, buf);
        }
    }
    
    private static String format(Color col) {
        StringBuilder buf = new StringBuilder("#");
        buf.append(Integer.toHexString(col.getRed()+256).substring(1));
        buf.append(Integer.toHexString(col.getGreen()+256).substring(1));
        buf.append(Integer.toHexString(col.getBlue()+256).substring(1));
        return buf.toString();
    }
    
    private static Color getColor(AttributeSet attrs) {
        Object attribute = attrs.getAttribute(ColorConstants.Foreground);
        if (attribute != null) {
            if (attribute instanceof Color) {
                Color color = (Color) attribute;
                if (color.equals(Color.BLACK)) {
                    return null;
                }
                return color;
            }
        }
        return null;
    }
    
    private static boolean getBoolean(AttributeSet attrs, Object name) {
        Object attribute = attrs.getAttribute(name);
        if (attribute != null) {
            if (attribute instanceof Boolean) {
                Boolean bool = (Boolean) attribute;
                return bool;
            }
        }
        return false;
    }
    
    private static class Delegate extends TransferHandler {
        /**
         * 
         */
        private static final long serialVersionUID = 1L;
        private TransferHandler inner;

        public Delegate(TransferHandler inner) {
            super();
            this.inner = inner;
        }

        public boolean canImport(JComponent comp, DataFlavor[] transferFlavors) {
            return inner.canImport(comp, transferFlavors);
        }

        public boolean canImport(TransferSupport support) {
            return inner.canImport(support);
        }

        public boolean equals(Object obj) {
            return inner.equals(obj);
        }

        public void exportAsDrag(JComponent comp, InputEvent e, int action) {
            inner.exportAsDrag(comp, e, action);
        }

        public void exportToClipboard(JComponent comp, Clipboard clip, int action) throws IllegalStateException {
            inner.exportToClipboard(comp, clip, action);
        }

        public int getSourceActions(JComponent c) {
            return inner.getSourceActions(c);
        }

        public Icon getVisualRepresentation(Transferable t) {
            return inner.getVisualRepresentation(t);
        }

        public int hashCode() {
            return inner.hashCode();
        }

        public boolean importData(JComponent comp, Transferable t) {
            return inner.importData(comp, t);
        }

        public boolean importData(TransferSupport support) {
            DataFlavor[] dataFlavors = support.getDataFlavors();
            List<DataFlavor> out = new ArrayList<DataFlavor>();
            for (DataFlavor flavor : dataFlavors) {
                if (flavor.getMimeType().startsWith("text/rtf")) {
                    if (InputStream.class.isAssignableFrom(flavor.getDefaultRepresentationClass())) {
                        out.add(flavor);
                    }
                }
            }
            try {
                DataFlavor[] outArray = new DataFlavor[out.size()];
                outArray = out.toArray(outArray);
                Transferable transferable = support.getTransferable();
                if (transferable instanceof ClipboardTransferable) {
                    ClipboardTransferable ct = (ClipboardTransferable) transferable;
                    Field declaredField = ClipboardTransferable.class.getDeclaredField("flavors");
                    declaredField.setAccessible(true);
                    declaredField.set(ct, outArray);
                }
            } catch (Throwable e) {
                e.printStackTrace();
            }
            
            return inner.importData(support);
        }

        public String toString() {
            return inner.toString();
        }
        
        
        
    }
}
