org.brixcms.plugin.hierarchical.HierarchicalNodePlugin.java Source code

Java tutorial

Introduction

Here is the source code for org.brixcms.plugin.hierarchical.HierarchicalNodePlugin.java

Source

/**
 * 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.brixcms.plugin.hierarchical;

import java.util.Collection;
import java.util.Collections;
import java.util.List;

import org.apache.wicket.Component;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.IModel;
import org.brixcms.Brix;
import org.brixcms.BrixNodeModel;
import org.brixcms.Plugin;
import org.brixcms.auth.Action;
import org.brixcms.auth.Action.Context;
import org.brixcms.jcr.JcrNodeWrapperFactory;
import org.brixcms.jcr.RepositoryInitializer;
import org.brixcms.jcr.api.JcrNode;
import org.brixcms.jcr.api.JcrSession;
import org.brixcms.jcr.wrapper.BrixNode;
import org.brixcms.plugin.hierarchical.admin.HierarchicalNodeManagerPanel;
import org.brixcms.plugin.hierarchical.admin.NodeEditorPlugin;
import org.brixcms.plugin.hierarchical.admin.NodeTreeParentComponent;
import org.brixcms.plugin.hierarchical.auth.AccessHierarchicalNodePluginAction;
import org.brixcms.plugin.hierarchical.folder.ManageFolderNodeTabFactory;
import org.brixcms.plugin.hierarchical.nodes.SimpleFolderNode;
import org.brixcms.plugin.hierarchical.nodes.TitledNode;
import org.brixcms.plugin.site.ManageNodeTabFactory;
import org.brixcms.plugin.site.SitePlugin;
import org.brixcms.plugin.site.auth.SiteNodeAction;
import org.brixcms.plugin.site.auth.SiteNodeAction.Type;
import org.brixcms.registry.ExtensionPoint;
import org.brixcms.registry.ExtensionPointRegistry;
import org.brixcms.web.tab.AbstractWorkspaceTab;
import org.brixcms.web.tab.IBrixTab;
import org.brixcms.workspace.Workspace;

/**
 * The HierarchicalNodePlugin was created as an abstract parent plugin to make
 * it easy to create new plugins that focus on editing hierarchical nodes. It is
 * largely based off of the work of the {@link SitePlugin}. The
 * {@link SitePlugin} had many great features that were desired in other
 * plugins, but it was not built for reuse in other plugins. Therefore, this was
 * created, and hopefully at some point the {@link SitePlugin} can be refactored
 * to use this as a parent.
 * 
 * You will notice that use of this plugin requires certain dependencies on
 * classes belonging to the {@link SitePlugin}. I tried reusing whatever classes
 * could easily be reused. Unfortunately, many of them had to be rewritten
 * because of hard-coded dependencies on the {@link SitePlugin} class itself.
 * So, there is some reuse of interfaces, mainly.
 * 
 * @author Jeremy Thomerson
 */
@SuppressWarnings("deprecation")
public abstract class HierarchicalNodePlugin implements Plugin {
    public static final String NAMESPACE = "brixhierarchicalnode";
    public static final String NS_PREFIX = NAMESPACE + ":";

    private final Brix brix;

    public HierarchicalNodePlugin(Brix brix) {
        this.brix = brix;
    }

    protected void initializeExtensionPoints(Brix brix) {
        ExtensionPointRegistry registry = brix.getConfig().getRegistry();
        registry.register(RepositoryInitializer.POINT, new HierarchicalRepoInitializer());
        registry.register(JcrNodeWrapperFactory.POINT, TitledNode.FACTORY);
        registry.register(getManageNodeTabFactoryExtensionPoint(),
                new ManageFolderNodeTabFactory(getPluginLocator()));
    }

    protected abstract IModel<String> getTabName();

    protected abstract String getRootNodeName();

    protected abstract HierarchicalPluginLocator getPluginLocator();

    protected abstract ExtensionPoint<? extends NodeEditorPlugin> getNodeEditorPluginExtensionPoint();

    protected abstract ExtensionPoint<ManageNodeTabFactory> getManageNodeTabFactoryExtensionPoint();

    protected int getTabPriority() {
        return 0;
    }

    public BrixNode getRootNode(String workspaceID) {
        JcrSession workspaceSession = getBrix().getCurrentSession(workspaceID);
        return (BrixNode) workspaceSession.getItem(getRootNodePath());
    }

    public NodeEditorPlugin getNodeEditorPluginForType(String nodeType) {
        for (NodeEditorPlugin plugin : getNodeEditorPlugins()) {
            if (plugin.getNodeType().equals(nodeType)) {
                return plugin;
            }
        }
        return null;
    }

    public Collection<? extends NodeEditorPlugin> getNodeEditorPlugins() {
        return brix.getConfig().getRegistry().lookupCollection(getNodeEditorPluginExtensionPoint());
    }

    public Collection<? extends ManageNodeTabFactory> getManageNodeTabFactories() {
        return brix.getConfig().getRegistry().lookupCollection(getManageNodeTabFactoryExtensionPoint());
    }

    public String getRootNodePath() {
        return brix.getRootPath() + "/" + getRootNodeName();
    }

    public Brix getBrix() {
        return brix;
    }

    public void refreshNavigationTree(Component component) {
        NodeTreeParentComponent panel = findContainer(component);
        if (panel != null) {
            panel.updateTree();
        } else {
            throw new IllegalStateException(
                    "Can't call refreshNaviagtionTree with component outside of the hierarchy.");
        }
    }

    public void selectNode(Component component, BrixNode node, boolean refreshTree) {
        NodeTreeParentComponent panel = findContainer(component);
        if (panel != null) {
            panel.selectNode(node);
            panel.updateTree();
        } else {
            throw new IllegalStateException("Can't call selectNode with component outside of the hierarchy.");
        }
    }

    private NodeTreeParentComponent findContainer(Component component) {
        if (component instanceof NodeTreeParentComponent) {
            return (NodeTreeParentComponent) component;
        } else {
            return component.findParent(NodeTreeParentComponent.class);
        }
    }

    public boolean canViewNode(BrixNode node, Context context) {
        Action action = new SiteNodeAction(context, Type.NODE_VIEW, node);
        return brix.getAuthorizationStrategy().isActionAuthorized(action);
    }

    public boolean canViewNodeChildren(BrixNode node, Context context) {
        Action action = new SiteNodeAction(context, Type.NODE_VIEW_CHILDREN, node);
        return brix.getAuthorizationStrategy().isActionAuthorized(action);
    }

    public boolean canEditNode(BrixNode node, Context context) {
        if (!isNodeEditable(node)) {
            return false;
        }
        Action action = new SiteNodeAction(context, Type.NODE_EDIT, node);
        return brix.getAuthorizationStrategy().isActionAuthorized(action);
    }

    public boolean canDeleteNode(BrixNode node, Context context) {
        if (!isNodeEditable(node)) {
            return false;
        }
        Action action = new SiteNodeAction(context, Type.NODE_DELETE, node);
        return brix.getAuthorizationStrategy().isActionAuthorized(action);
    }

    public boolean canRenameNode(BrixNode node, Context context) {
        if (!isNodeEditable(node)) {
            return false;
        }
        Action action = new SiteNodeAction(context, Type.NODE_DELETE, node);
        return brix.getAuthorizationStrategy().isActionAuthorized(action);
    }

    public boolean canAddNodeChild(BrixNode node, Context context) {
        if (!isNodeEditable(node)) {
            return false;
        }
        Action action = new SiteNodeAction(context, Type.NODE_ADD_CHILD, node);
        return brix.getAuthorizationStrategy().isActionAuthorized(action);
    }

    private boolean isNodeEditable(BrixNode node) {
        if (node.isNodeType("mix:versionable") && !node.isCheckedOut()) {
            return false;
        }
        if (node.isLocked() && node.getLock().getLockToken() == null) {
            return false;
        }
        return true;
    }

    /* Implemented (Plugin) interface methods */
    public List<Workspace> getWorkspaces(Workspace currentWorkspace, boolean isFrontend) {
        return null;
    }

    public void initWorkspace(Workspace workspace, JcrSession workspaceSession) {
        JcrNode root = (JcrNode) workspaceSession.getItem(brix.getRootPath());
        JcrNode pluginRoot = null;
        if (root.hasNode(getRootNodeName())) {
            pluginRoot = root.getNode(getRootNodeName());
        } else {
            pluginRoot = root.addNode(getRootNodeName(), SimpleFolderNode.JCR_PRIMARY_TYPE);
        }

        if (pluginRoot != null) {
            if (!pluginRoot.isNodeType(BrixNode.JCR_TYPE_BRIX_NODE)) {
                pluginRoot.addMixin(BrixNode.JCR_TYPE_BRIX_NODE);
            }
        }
    }

    public boolean isPluginWorkspace(Workspace workspace) {
        return false;
    }

    public List<IBrixTab> newTabs(IModel<Workspace> workspaceModel) {
        IBrixTab tab = new NodeTreeEditorTab(getTabName(), workspaceModel, getPluginLocator(), getTabPriority());
        return Collections.singletonList(tab);
    }

    /* end of implemented (Plugin) interface methods */

    static class NodeTreeEditorTab extends AbstractWorkspaceTab {
        private final HierarchicalPluginLocator pluginLocator;

        public NodeTreeEditorTab(IModel<String> title, IModel<Workspace> workspaceModel,
                HierarchicalPluginLocator pluginLocator, int priority) {
            super(title, workspaceModel, priority);
            this.pluginLocator = pluginLocator;
        }

        @Override
        public Panel newPanel(String panelId, IModel<Workspace> workspaceModel) {
            BrixNode rootNode = pluginLocator.getPlugin().getRootNode(workspaceModel.getObject().getId());
            return new HierarchicalNodeManagerPanel(panelId, workspaceModel, new BrixNodeModel(rootNode),
                    pluginLocator);
        }

        @Override
        public boolean isVisible() {
            final Action action = new AccessHierarchicalNodePluginAction(pluginLocator,
                    getWorkspaceModel().getObject());
            return Brix.get().getAuthorizationStrategy().isActionAuthorized(action);
        }

    }

}