com.cladonia.xngreditor.actions.ToolsStripTextAction.java Source code

Java tutorial

Introduction

Here is the source code for com.cladonia.xngreditor.actions.ToolsStripTextAction.java

Source

/*
 * $Id: ToolsStripTextAction.java,v 1.19 2005/03/10 10:54:04 tcurley Exp $ 
 *
 * Copyright (C) 2004, Cladonia Ltd. All rights reserved.
 *
 * This software is the proprietary information of Cladonia Ltd.  
 * Use is subject to license terms.
 */

package com.cladonia.xngreditor.actions;

import java.awt.event.ActionEvent;
import java.util.Vector;

import javax.swing.AbstractAction;
import javax.swing.SwingUtilities;
import org.dom4j.Attribute;
import org.dom4j.CDATA;
import org.dom4j.Element;
import org.dom4j.Entity;
import org.dom4j.Node;
import org.dom4j.Text;
import com.cladonia.xngreditor.ExchangerEditor;
import com.cladonia.xngreditor.ToolsStripTextDialog;
import com.cladonia.xml.ExchangerDocument;
import com.cladonia.xml.XElement;
import com.cladonia.xml.editor.Editor;
import com.cladonia.xngreditor.MessageHandler;
import com.cladonia.xngreditor.properties.ConfigurationProperties;

/**
 * An action that can be used to strip a document of its contents
 * 
 * @version $Revision: 1.19 $, $Date: 2005/03/10 10:54:04 $
 * @author Thomas Curley <tcurley@cladonia.com>
 */
public class ToolsStripTextAction extends AbstractAction {

    private static final boolean DEBUG = false;
    private ExchangerEditor parent = null;
    private ToolsStripTextDialog dialog = null;
    private Editor editor = null;
    public boolean mixed = false;
    private ConfigurationProperties props;

    public static boolean TRAVERSE_CHILDREN = true;
    public static boolean DONT_TRAVERSE_CHILDREN = false;

    /**
     * The constructor for the action which allows for striping a document of
     * its contents.
     * 
     * @param parent
     *            the parent frame.
     */
    public ToolsStripTextAction(ExchangerEditor parent, Editor editor, ConfigurationProperties props) {

        super("Strip Text ...");
        this.parent = parent;
        this.props = props;
        //this.properties = props;
        putValue(MNEMONIC_KEY, new Integer('T'));
        putValue(SHORT_DESCRIPTION, "Strip Text ...");
    }

    /**
     * Sets the current view.
     * 
     * @param view
     *            the current view.
     */
    public void setView(Object view) {

        if (view instanceof Editor) {
            editor = (Editor) view;
        } else {
            editor = null;
        }
        setDocument(parent.getDocument());
    }

    public void setDocument(ExchangerDocument doc) {

        if (doc != null && doc.isXML()) {
            setEnabled(editor != null);
        } else {
            setEnabled(false);
        }
    }

    /**
     * The implementation of the validate action, called after a user action.
     * 
     * @param event
     *            the action event.
     */
    public void actionPerformed(ActionEvent event) {

        if (dialog == null) {
            dialog = new ToolsStripTextDialog(parent, props);
        }
        //called to make sure that the model is up to date to
        //prevent any problems found when undo-ing etc.
        parent.getView().updateModel();
        //get the document
        final ExchangerDocument document = parent.getDocument();
        if (document.isError()) {
            MessageHandler.showError(parent, "Please make sure the document is well-formed.", "Parser Error");
            return;
        }
        //create temporary document
        String currentXPath = null;
        Node node = (Node) document.getLastNode(parent.getView().getEditor().getCursorPosition(), true);

        if (props.isUniqueXPath()) {
            currentXPath = node.getUniquePath();
        } else {
            currentXPath = node.getPath();
        }
        dialog.show(currentXPath);
        if (!dialog.isCancelled()) {
            parent.setWait(true);
            parent.setStatus("Stripping Document Text ...");
            // Run in Thread!!!
            Runnable runner = new Runnable() {

                public void run() {

                    try {

                        if ((dialog.elementsCheckBox.isSelected()) || (dialog.attributesCheckBox.isSelected())) {

                            ExchangerDocument tempDoc = new ExchangerDocument(document.getText());
                            String newDocument = null;

                            if (dialog.xpathPanel.xpathBox.isSelected()) {
                                String xpathPredicate = dialog.xpathPanel.getXpathPredicate();
                                newDocument = treeWalk(tempDoc, xpathPredicate,
                                        dialog.elementsCheckBox.isSelected(),
                                        dialog.attributesCheckBox.isSelected(),
                                        dialog.mixedContentCheckBox.isSelected(), TRAVERSE_CHILDREN);
                            } else {

                                newDocument = treeWalk(tempDoc, dialog.elementsCheckBox.isSelected(),
                                        dialog.attributesCheckBox.isSelected(),
                                        dialog.mixedContentCheckBox.isSelected());
                            }
                            if (newDocument != null) {
                                if (dialog.toNewDocumentRadio.isSelected()) {
                                    //user has selected to create the result as a
                                    // new document
                                    parent.open(new ExchangerDocument(newDocument), null);
                                } else {
                                    parent.getView().getEditor().setText(newDocument);
                                    SwingUtilities.invokeLater(new Runnable() {

                                        public void run() {

                                            parent.switchToEditor();
                                            parent.getView().updateModel();
                                        }
                                    });
                                }
                            }
                        }
                    } catch (Exception e) {
                        // This should never happen, just report and continue
                        MessageHandler.showError(parent, "Cannot Strip Document Text", "Tools Strip Text Error");
                    }

                    finally {
                        parent.setStatus("Done");
                        parent.setWait(false);
                    }
                }
            };
            // Create and start the thread ...
            Thread thread = new Thread(runner);
            thread.start();
            //          }
        }
    }

    public String treeWalk(ExchangerDocument document, boolean stripElements, boolean stripAttributes,
            boolean stripMixedContent) {

        try {
            XElement e = document.getRoot();
            //clear all attributes in the root
            if (stripAttributes) {
                if (e.attributeCount() > 0) {
                    int attCount = e.attributeCount();
                    for (int cnt = 0; cnt < attCount; ++cnt) {
                        Attribute att = e.attribute(cnt);
                        att.setText("");
                    }
                }
            }
            //check if it is mixed
            if ((stripMixedContent) && (isMixed(e))) {
                e.removeAllChildren();
            } else {
                treeWalk(e, stripElements, stripAttributes, stripMixedContent, true);
            }
            treeWalk(e, stripElements, stripAttributes, stripMixedContent, true);
            document.update();
        } catch (Exception e) {
            MessageHandler.showError(parent, "Cannot Strip The Text From This Document", "Tools Strip Text Error");
            return (null);
        }
        return (document.getText());
    }

    public String treeWalk(ExchangerDocument document, String xpathPredicate, boolean stripElements,
            boolean stripAttributes, boolean stripMixedContent, boolean traverseChildren) {

        try {
            Vector nodes = document.search(xpathPredicate);
            //System.out.println(nodes.size());
            if (nodes.size() < 1) {
                //throw new Exception("Cannot resolve xpath");
                MessageHandler.showError(parent, "Could Not Resolve XPath:\n" + xpathPredicate,
                        "Tools Strip Text Error");
                return (null);
            }
            for (int cnt = 0; cnt < nodes.size(); ++cnt) {
                Node node = (Node) nodes.get(cnt);
                if (node instanceof Element) {
                    XElement e = (XElement) nodes.get(cnt);
                    if (stripAttributes) {
                        if (e.attributeCount() > 0) {
                            int attCount = e.attributeCount();
                            for (int icnt = 0; icnt < attCount; ++icnt) {
                                Attribute att = e.attribute(icnt);
                                att.setText("");
                            }
                        }
                    }

                    //check if it is mixed
                    if ((stripMixedContent) && (traverseChildren) && (isMixed(e))) {
                        e.removeAllChildren();
                    } else {
                        treeWalk(e, stripElements, stripAttributes, stripMixedContent, traverseChildren);

                    }
                    treeWalk(e, stripElements, stripAttributes, stripMixedContent, traverseChildren);

                } else if (node instanceof Attribute) {
                    Attribute att = (Attribute) node;
                    att.setText("");
                }
            }
            document.update();
        } catch (Exception e) {
            MessageHandler.showError(parent, "Cannot Strip The Text From This Document", "Tools Strip Text Error");
            //e.printStackTrace();
            return (null);
        }
        return (document.getText());
    }

    private void treeWalk(XElement element, boolean stripElements, boolean stripAttributes,
            boolean stripMixedContent, boolean traverseChildren) throws Exception {

        for (int i = 0, size = element.nodeCount(); i < size; i++) {
            Node node = element.node(i);
            if ((node instanceof Element) && (traverseChildren)) {
                //remove the attributes first
                XElement e = (XElement) node;
                if (stripAttributes) {
                    if (e.attributeCount() > 0) {
                        int attCount = e.attributeCount();
                        for (int cnt = 0; cnt < attCount; ++cnt) {
                            Attribute att = e.attribute(cnt);
                            att.setText("");
                        }
                    }
                }
                //check if it is mixed
                if ((stripMixedContent) && (isMixed((XElement) node))) {
                    e.removeAllChildren();
                } else {
                    treeWalk(e, stripElements, stripAttributes, stripMixedContent, traverseChildren);
                }
            } else if ((stripElements) && (node instanceof Text)) {
                //these are all text nodes
                // blank but need to preserve formatting
                String value = node.getText();
                //if it does not contain a new line char then can blank
                // straight away
                if (value.indexOf("\n") == -1) {
                    node.setText("");
                } else {
                    //id does contain a newline
                    if (value.charAt(0) == '\n') {
                        //if the first char is new line
                        //the new value should have all the spaces, \n and \t
                        // but no letters or digits
                        String newValue = "";
                        for (int cnt = 0; cnt < value.length(); ++cnt) {
                            //look for the first occurence of a real character
                            if (Character.isLetterOrDigit(value.charAt(cnt))) {
                                //cnt = value.length();
                            } else if ((value.charAt(cnt) == '\n') || (value.charAt(cnt) == '\t')
                                    || (value.charAt(cnt) == ' ')) {
                                newValue += value.charAt(cnt);
                            }
                        }
                        node.setText(newValue);
                    } else {
                        String newValue = "";
                        for (int cnt = 0; cnt < value.length(); ++cnt) {
                            //look for the first occurence of a real character
                            if (Character.isLetterOrDigit(value.charAt(cnt))) {
                                //cnt = value.length();
                            } else if ((value.charAt(cnt) == '\n') || (value.charAt(cnt) == '\t')
                                    || (value.charAt(cnt) == ' ')) {
                                newValue += value.charAt(cnt);
                            }
                        }
                        node.setText(newValue);
                    }
                }
            }
        }
    }

    private static boolean isMixed(XElement element) throws Exception {

        if (element.hasMixedContent()) {
            boolean elementFound = false;
            boolean textFound = false;
            int count = element.nodeCount();
            for (int i = 0; i < count; i++) {
                Node node = element.node(i);
                if (node instanceof XElement) {
                    elementFound = true;
                } else if ((node instanceof Text) || (node instanceof CDATA) || (node instanceof Entity)) {
                    if (!isWhiteSpace(node)) {
                        textFound = true;
                    }
                }
                if (textFound && elementFound) {
                    return true;
                }
            }
        }
        return false;
    }

    private static boolean isWhiteSpace(Node node) throws Exception {

        return node.getText().trim().length() == 0;
    }
}