org.hippoecm.frontend.plugins.cms.browse.tree.FolderTreePlugin.java Source code

Java tutorial

Introduction

Here is the source code for org.hippoecm.frontend.plugins.cms.browse.tree.FolderTreePlugin.java

Source

/*
 *  Copyright 2008-2015 Hippo B.V. (http://www.onehippo.com)
 * 
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 * 
 *       http://www.apache.org/licenses/LICENSE-2.0
 * 
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package org.hippoecm.frontend.plugins.cms.browse.tree;

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;

import org.apache.commons.lang.StringUtils;
import org.apache.wicket.Component;
import org.apache.wicket.MarkupContainer;
import org.apache.wicket.Page;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.extensions.markup.html.tree.ITreeState;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.panel.EmptyPanel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.request.IRequestParameters;
import org.apache.wicket.request.cycle.RequestCycle;
import org.apache.wicket.util.string.StringValue;
import org.hippoecm.addon.workflow.ContextWorkflowManagerPlugin;
import org.hippoecm.frontend.PluginRequestTarget;
import org.hippoecm.frontend.behaviors.IContextMenuManager;
import org.hippoecm.frontend.model.JcrNodeModel;
import org.hippoecm.frontend.model.event.IObserver;
import org.hippoecm.frontend.model.tree.IJcrTreeNode;
import org.hippoecm.frontend.model.tree.JcrTreeModel;
import org.hippoecm.frontend.model.tree.JcrTreeNode;
import org.hippoecm.frontend.plugin.IPluginContext;
import org.hippoecm.frontend.plugin.config.IPluginConfig;
import org.hippoecm.frontend.plugins.cms.browse.tree.CmsJcrTree.ITreeNodeTranslator;
import org.hippoecm.frontend.plugins.cms.browse.tree.CmsJcrTree.TreeNodeTranslator;
import org.hippoecm.frontend.plugins.cms.browse.tree.yui.WicketTreeHelperBehavior;
import org.hippoecm.frontend.plugins.cms.browse.tree.yui.WicketTreeHelperSettings;
import org.hippoecm.frontend.plugins.standards.DocumentListFilter;
import org.hippoecm.frontend.plugins.standards.tree.FolderTreeNode;
import org.hippoecm.frontend.plugins.standards.tree.icon.DefaultTreeNodeIconProvider;
import org.hippoecm.frontend.plugins.standards.tree.icon.ITreeNodeIconProvider;
import org.hippoecm.frontend.plugins.yui.rightclick.RightClickBehavior;
import org.hippoecm.frontend.plugins.yui.scrollbehavior.ScrollBehavior;
import org.hippoecm.frontend.service.render.RenderPlugin;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class FolderTreePlugin extends RenderPlugin {
    static final Logger log = LoggerFactory.getLogger(FolderTreePlugin.class);

    protected final CmsJcrTree tree;
    protected JcrTreeModel treeModel;
    protected JcrTreeNode rootNode;
    private JcrNodeModel rootModel;

    private static final String DEFAULT_START_PATH = "/content";

    private WicketTreeHelperBehavior treeHelperBehavior;

    public FolderTreePlugin(final IPluginContext context, final IPluginConfig config) {
        super(context, config);

        String startingPath = config.getString("path", DEFAULT_START_PATH);
        boolean canAccessPath = true;
        try {
            final Session session = getSession().getJcrSession();
            if (!session.hasPermission(startingPath, Session.ACTION_READ)) {
                log.warn("User '{} is unauthorized to read at the configured path '{}'", session.getUserID(),
                        startingPath);
                canAccessPath = false;
            } else if (!session.itemExists(startingPath)) {
                log.warn("The configured path '{}' does not exist. Please check the configuration", startingPath);
                canAccessPath = false;
            }
        } catch (RepositoryException exception) {
            canAccessPath = false;
            log.debug("Path '{}' is invalid", startingPath);
        }

        if (!canAccessPath) {
            tree = null;
            add(new Label("tree", StringUtils.EMPTY));
            return;
        }

        add(tree = initializeTree(context, config, startingPath));
        onModelChanged();
        add(new ScrollBehavior());
    }

    private CmsJcrTree initializeTree(final IPluginContext context, final IPluginConfig config,
            final String startingPath) {
        rootModel = new JcrNodeModel(startingPath);

        DocumentListFilter folderTreeConfig = new DocumentListFilter(config);
        final boolean workflowEnabled = getPluginConfig().getAsBoolean("workflow.enabled", true);

        this.rootNode = new FolderTreeNode(rootModel, folderTreeConfig);
        treeModel = new JcrTreeModel(rootNode);
        context.registerService(treeModel, IObserver.class.getName());
        final CmsJcrTree cmsJcrTree = new CmsJcrTree("tree", treeModel, newTreeNodeTranslator(config),
                newTreeNodeIconProvider(context, config)) {
            private static final long serialVersionUID = 1L;

            @Override
            protected MarkupContainer newContextContent(MarkupContainer parent, String id, final TreeNode node) {
                IPluginConfig workflowConfig = config.getPluginConfig("module.workflow");
                if (workflowConfig != null && (node instanceof IJcrTreeNode)) {
                    ContextWorkflowManagerPlugin content = new ContextWorkflowManagerPlugin(context,
                            workflowConfig);
                    content.bind(FolderTreePlugin.this, id);
                    IModel<Node> nodeModel = ((IJcrTreeNode) node).getNodeModel();
                    content.setModel(nodeModel);
                    return content;
                }
                return new EmptyPanel(id);
            }

            @Override
            protected MarkupContainer newContextLink(final MarkupContainer parent, String id, final TreeNode node,
                    final MarkupContainer content) {

                if (getPluginConfig().getBoolean("contextmenu.rightclick.enabled")) {
                    parent.add(new RightClickBehavior(content, parent) {
                        private static final long serialVersionUID = 1L;

                        @Override
                        protected void respond(AjaxRequestTarget target) {
                            updateTree(target);
                            getContextmenu().setVisible(true);
                            target.add(getComponentToUpdate());
                            IContextMenuManager menuManager = findParent(IContextMenuManager.class);
                            if (menuManager != null) {
                                menuManager.showContextMenu(this);
                                final IRequestParameters requestParameters = RequestCycle.get().getRequest()
                                        .getRequestParameters();
                                StringValue x = requestParameters.getParameterValue(MOUSE_X_PARAM);
                                StringValue y = requestParameters.getParameterValue(MOUSE_Y_PARAM);
                                if (x != null && y != null) {
                                    target.appendJavaScript("Hippo.ContextMenu.renderAtPosition('"
                                            + content.getMarkupId() + "', " + x + ", " + y + ");");
                                } else {
                                    target.appendJavaScript(
                                            "Hippo.ContextMenu.renderInTree('" + content.getMarkupId() + "');");
                                }
                            }
                        }
                    });

                }
                MarkupContainer container = super.newContextLink(parent, id, node, content);
                if (!workflowEnabled) {
                    container.setEnabled(false);
                }
                return container;
            }

            @Override
            protected void onContextLinkClicked(MarkupContainer content, AjaxRequestTarget target) {
                target.appendJavaScript("Hippo.ContextMenu.renderInTree('" + content.getMarkupId() + "');");
            }

            @Override
            protected void onNodeLinkClicked(AjaxRequestTarget target, TreeNode clickedNode) {
                if (clickedNode instanceof IJcrTreeNode) {
                    IJcrTreeNode treeNodeModel = (IJcrTreeNode) clickedNode;
                    FolderTreePlugin.this.setDefaultModel(treeNodeModel.getNodeModel());
                    ITreeState state = getTreeState();
                    if (state.isNodeExpanded(clickedNode)) {
                        // super has already switched selection.
                        if (!state.isNodeSelected(clickedNode)) {
                            state.collapseNode(clickedNode);
                        }
                    } else {
                        state.expandNode(clickedNode);
                    }
                }
                updateTree(target);
            }

            @Override
            protected void onJunctionLinkClicked(AjaxRequestTarget target, TreeNode node) {
                updateTree(target);
            }

            @Override
            public void onTargetRespond(final AjaxRequestTarget target, boolean dirty) {
                if (dirty) {
                    target.appendJavaScript(treeHelperBehavior.getRenderString());
                }
            }

            @Override
            protected void addComponent(final AjaxRequestTarget target, final Component component) {
                if (component.findParent(Page.class) != null) {
                    super.addComponent(target, component);
                }
            }
        };

        cmsJcrTree.add(treeHelperBehavior = new WicketTreeHelperBehavior(new WicketTreeHelperSettings(config)) {
            private static final long serialVersionUID = 1L;

            @Override
            protected String getWicketId() {
                return tree.getMarkupId();
            }

        });

        cmsJcrTree.setRootLess(config.getBoolean("rootless"));
        return cmsJcrTree;
    }

    protected ITreeNodeTranslator newTreeNodeTranslator(IPluginConfig config) {
        return new TreeNodeTranslator();
    }

    public static ITreeNodeIconProvider newTreeNodeIconProvider(IPluginContext context, IPluginConfig config) {
        final List<ITreeNodeIconProvider> providers = new LinkedList<>();
        providers.add(new DefaultTreeNodeIconProvider());
        providers.addAll(context.getServices(ITreeNodeIconProvider.class.getName(), ITreeNodeIconProvider.class));
        if (config.containsKey("tree.icon.id")) {
            providers.addAll(context.getServices(config.getString("tree.icon.id"), ITreeNodeIconProvider.class));
        }
        Collections.reverse(providers);

        return new ITreeNodeIconProvider() {
            private static final long serialVersionUID = 1L;

            public Component getNodeIcon(final String id, final TreeNode treeNode, final ITreeState state) {
                for (ITreeNodeIconProvider provider : providers) {
                    final Component icon = provider.getNodeIcon(id, treeNode, state);
                    if (icon != null) {
                        return icon;
                    }
                }
                return null;
            }
        };
    }

    @Override
    public void render(PluginRequestTarget target) {
        super.render(target);
        if (tree != null) {
            if (target != null && isActive() && isVisible()) {
                tree.updateTree();
            }
        }
    }

    @Override
    public void onBeforeRender() {
        if (tree != null) {
            tree.detach();
        }
        super.onBeforeRender();
    }

    @Override
    public void onModelChanged() {
        super.onModelChanged();

        if (tree == null) {
            return;
        }
        JcrNodeModel model = (JcrNodeModel) getDefaultModel();
        ITreeState treeState = tree.getTreeState();
        TreePath treePath = treeModel.lookup(model);
        if (treePath != null) {
            for (Object component : treePath.getPath()) {
                TreeNode treeNode = (TreeNode) component;
                if (!treeState.isNodeExpanded(treeNode)) {
                    treeState.expandNode(treeNode);
                }
            }
            treeState.selectNode(treePath.getLastPathComponent(), true);
        }
    }

}