Package org.geoserver.web.translator.view

Source Code of org.geoserver.web.translator.view.ResourceKeyTreePanel$NodeBean

/* Copyright (c) 2001 - 2009 TOPP - www.openplans.org. All rights reserved.
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.web.translator.view;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.TreeSet;
import java.util.regex.Pattern;

import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreeNode;

import org.apache.wicket.Component;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.markup.html.tree.BaseTree;
import org.apache.wicket.markup.html.tree.ITreeState;
import org.apache.wicket.markup.html.tree.ITreeStateListener;
import org.apache.wicket.markup.html.tree.LinkTree;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.PropertyModel;
import org.geoserver.web.translator.model.TranslateBean;

/**
* A panel presenting the list of user interface string resource keys.
* <p>
* The contents of the tree view for this panel may be customized in order to show the resource keys
* as a tree or as a flat view, collapse or expand all nodes, or show only the resource keys that
* are not yet translated for the ongoing locale translation.
* </p>
*
* @author Gabriel Roldan
* @version $Id: ResourceKeyTreePanel.java 13241 2009-08-30 05:44:14Z groldan $
* @since 2.0
*/
public class ResourceKeyTreePanel extends Panel {
    private static final long serialVersionUID = 4308370741356525991L;

    private final BaseTree keyTree;

    private Set<String> keys;

    public ResourceKeyTreePanel(final String id, final IModel translateBeanModel) {
        super(id);
        setModel(translateBeanModel);
        setOutputMarkupId(true);

        keyTree = new LinkTree("keyTreePanel", new Model()) {
            private static final long serialVersionUID = 1L;

            @Override
            protected Component newNodeComponent(String id, IModel nodeModel) {

                Component nodeComponent = super.newNodeComponent(id, nodeModel);

                return nodeComponent;
            }
        };
        keyTree.setOutputMarkupId(true);
        keyTree.setRootLess(true);
        keyTree.getTreeState().addTreeStateListener(new SelectionKeyListener());

        refresh();

        add(keyTree);
    }

    /**
     * Parses the keywords and sets them as the or'ed filtered criteria, forces update of the
     * components that need to as a result of the different filtering
     */
    private Set<String> updateFilter(final String flatKeywords, final Collection<String> keys,
            final TranslateBean translationState) {

        final List<Pattern> patterns;
        {
            final String[] keywords = flatKeywords.split("\\s+");
            patterns = new ArrayList<Pattern>(keywords.length);
            String regex;
            for (String keyword : keywords) {
                regex = ".*" + escape(keyword) + ".*";
                Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE
                        | Pattern.UNICODE_CASE);
                patterns.add(pattern);
            }
        }
        Set<String> matches = new HashSet<String>();
        final Locale baseLanguage = translationState.getBaseLocale();
        final Locale targetLanguage = translationState.getTargetLanguage();

        for (String resourceKey : keys) {
            for (Pattern pattern : patterns) {
                if (pattern.matcher(resourceKey).matches()) {
                    matches.add(resourceKey);
                    break;
                }
                if (matchesContent(resourceKey, pattern, baseLanguage, translationState)) {
                    matches.add(resourceKey);
                    break;
                }
                if (matchesContent(resourceKey, pattern, targetLanguage, translationState)) {
                    matches.add(resourceKey);
                    break;
                }
            }
        }

        return matches;
    }

    private boolean matchesContent(final String resourceKey, final Pattern pattern,
            final Locale locale, final TranslateBean translationState) {
        String resource = translationState.getResource(locale, resourceKey);
        if (resource == null) {
            return false;
        }
        return pattern.matcher(resource).matches();
    }

    /**
     * Escape any character that's special for the regex api
     *
     * @param keyword
     * @return
     */
    private String escape(String keyword) {
        final String escapeSeq = "\\";
        final int len = keyword.length();
        StringBuilder sb = new StringBuilder();
        char c;
        for (int i = 0; i < len; i++) {
            c = keyword.charAt(i);
            if (isSpecial(c)) {
                sb.append(escapeSeq);
            }
            sb.append(keyword.charAt(i));
        }
        return sb.toString();
    }

    /**
     * Convenience method to determine if a character is special to the regex system.
     *
     * @param chr
     *            the character to test
     *
     * @return is the character a special character.
     */
    private boolean isSpecial(final char chr) {
        return ((chr == '.') || (chr == '?') || (chr == '*') || (chr == '^') || (chr == '$')
                || (chr == '+') || (chr == '[') || (chr == ']') || (chr == '(') || (chr == ')')
                || (chr == '|') || (chr == '\\') || (chr == '&'));
    }

    /**
     * Updates the state of the tree.
     * <p>
     * The following variables are considered to rebuild the tree:
     * <ul>
     * <li> {@link #flatView}
     * <li> {@link TranslateBean#isShowMissingOnly()}
     * </ul>
     * </p>
     */
    @SuppressWarnings("unchecked")
    public void refresh() {
        final IModel translateBeanModel = getModel();
        final Boolean missingOnly = (Boolean) new PropertyModel(translateBeanModel,
                "showMissingOnly").getObject();

        PropertyModel keysModel;
        if (missingOnly) {
            keysModel = new PropertyModel(translateBeanModel, "missingKeys");
        } else {
            keysModel = new PropertyModel(translateBeanModel, "resourceKeys");
        }

        Collection<String> keys = (Collection<String>) keysModel.getObject();

        final String flatKeywords = (String) new PropertyModel(translateBeanModel, "filter")
                .getObject();
        if (flatKeywords != null && flatKeywords.trim().length() > 0) {
            final TranslateBean translationState = (TranslateBean) translateBeanModel.getObject();
            this.keys = updateFilter(flatKeywords, keys, translationState);
        } else {
            this.keys = new TreeSet<String>(keys);
        }

        IModel flatViewModel = new PropertyModel(translateBeanModel, "flatView");
        boolean flatView = ((Boolean) flatViewModel.getObject()).booleanValue();
        if (flatView) {
            setFlatView();
        } else {
            setTreeView();
        }
    }

    public BaseTree getTree() {
        return keyTree;
    }

    public void expandAll(final AjaxRequestTarget target) {
        getTree().getTreeState().expandAll();
        if (target == null) {
            getTree().updateTree();
        } else {
            getTree().updateTree(target);
        }
    }

    public void collapseAll(final AjaxRequestTarget target) {
        getTree().getTreeState().collapseAll();
        if (target == null) {
            getTree().updateTree();
        } else {
            getTree().updateTree(target);
        }
    }

    private void setTreeView() {
        final TreeModel treeModel = createTreeModel();
        keyTree.setModelObject(treeModel);
    }

    private void setFlatView() {
        final TreeModel flatModel = creatFlatModel();
        keyTree.setModelObject(flatModel);
    }

    private TreeModel creatFlatModel() {
        DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode(new NodeBean("__ROOT", null));

        List<String> keySet = new ArrayList<String>(keys);
        Collections.sort(keySet, String.CASE_INSENSITIVE_ORDER);
        for (String key : keySet) {
            NodeBean node = new NodeBean(key, key);
            DefaultMutableTreeNode child = new DefaultMutableTreeNode(node);
            rootNode.add(child);
        }

        TreeModel treeModel = new DefaultTreeModel(rootNode);
        return treeModel;
    }

    private TreeModel createTreeModel() {
        DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode("__ROOT");

        List<String> keySet = new ArrayList<String>(keys);
        Collections.sort(keySet, String.CASE_INSENSITIVE_ORDER);
        HashMap<String, DefaultMutableTreeNode> hashMap = new HashMap<String, DefaultMutableTreeNode>();
        for (String key : keySet) {
            addNodes(rootNode, key, hashMap);
        }

        TreeModel treeModel = new DefaultTreeModel(rootNode);
        return treeModel;
    }

    private void addNodes(final DefaultMutableTreeNode parent, final String key,
            HashMap<String, DefaultMutableTreeNode> hashMap) {

        final int idx = key.indexOf('.');
        String name;
        if (idx == -1) {
            name = key;
        } else {
            name = key.substring(0, idx);
        }

        String path = getPath(parent, name);

        NodeBean node = new NodeBean(name, path);

        DefaultMutableTreeNode child = hashMap.get(path);
        if (child == null) {
            child = new DefaultMutableTreeNode(node);
            parent.add(child);
            hashMap.put(path, child);
        }

        if (idx > -1) {
            addNodes(child, key.substring(idx + 1), hashMap);
        }
    }

    private String getPath(DefaultMutableTreeNode node, String child) {
        String parentPath = getPath(node);
        StringBuilder sb = new StringBuilder(parentPath);
        if (sb.length() > 0) {
            sb.append('.');
        }
        sb.append(child);
        return sb.toString();
    }

    private String getPath(final DefaultMutableTreeNode node) {
        Object[] userObjectPath = node.getUserObjectPath();
        StringBuilder sb = new StringBuilder();
        // Ignore root
        for (int i = 1; i < userObjectPath.length; i++) {
            Object mb = userObjectPath[i];
            sb.append(mb.toString());
            if (i < userObjectPath.length - 1) {
                sb.append('.');
            }
        }

        return sb.toString();
    }

    private final class SelectionKeyListener implements ITreeStateListener, Serializable {
        private static final long serialVersionUID = -5354495649059977267L;

        private TreeNode previouslySelected;

        public void nodeUnselected(final TreeNode node) {
            // nothing to do
        }

        public void nodeSelected(final TreeNode node) {
            final ITreeState treeState = getTree().getTreeState();
            if (!node.isLeaf()) {
                if (node.equals(previouslySelected) && treeState.isNodeExpanded(node)) {
                    treeState.collapseNode(node);
                } else {
                    treeState.expandNode(node);
                }
            }
            previouslySelected = node;
        }

        public void nodeExpanded(final TreeNode node) {
            // nothing to do
        }

        public void nodeCollapsed(final TreeNode node) {
            // nothing to do
        }

        public void allNodesExpanded() {
            // nothing to do
        }

        public void allNodesCollapsed() {
            // nothing to do
        }
    }

    public static class NodeBean {

        private String name;

        private String resourceKey;

        /**
         *
         * @param name
         *            the node name as it is to be shown in the tree
         * @param resourceKey
         *            the resource key, or {@code null} if the node is not for an actual resource
         *            key but an intermediate node in the tree
         */
        public NodeBean(final String name, final String resourceKey) {
            this.name = name;
            this.resourceKey = resourceKey;
        }

        public String getName() {
            return name;
        }

        public String getResourceKey() {
            return resourceKey;
        }

        /**
         * @return the name as to be shown in the UI
         */
        @Override
        public String toString() {
            return getName();
        }
    }

    @SuppressWarnings("unchecked")
    public String getSelectedNodeKey() {
        ITreeState treeState = getTree().getTreeState();
        Collection<DefaultMutableTreeNode> selectedNodes = treeState.getSelectedNodes();
        String selectedKey = null;
        if (selectedNodes.size() > 0) {
            DefaultMutableTreeNode selectedNode = selectedNodes.iterator().next();
            ResourceKeyTreePanel.NodeBean userObject = (NodeBean) selectedNode.getUserObject();
            selectedKey = userObject.getResourceKey();
        }
        return selectedKey;
    }

}
TOP

Related Classes of org.geoserver.web.translator.view.ResourceKeyTreePanel$NodeBean

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.