org.sakaiproject.delegatedaccess.tool.pages.BaseTreePage.java Source code

Java tutorial

Introduction

Here is the source code for org.sakaiproject.delegatedaccess.tool.pages.BaseTreePage.java

Source

/*
* The Trustees of Columbia University in the City of New York
* licenses this file to you under the Educational Community 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://opensource.org/licenses/ecl2.txt
*
* 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.sakaiproject.delegatedaccess.tool.pages;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

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

import org.apache.log4j.Logger;
import org.apache.wicket.AttributeModifier;
import org.apache.wicket.Component;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.AjaxLink;
import org.apache.wicket.behavior.AttributeAppender;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.markup.html.tree.AbstractTree;
import org.apache.wicket.model.AbstractReadOnlyModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.StringResourceModel;
import org.sakaiproject.delegatedaccess.model.ListOptionSerialized;
import org.sakaiproject.delegatedaccess.model.NodeModel;
import org.sakaiproject.delegatedaccess.util.DelegatedAccessMutableTreeNode;

/**
 * BaseTreePage is a base page for all pages that want to use AbstractTree.  It extends BasePage as well.
 * 
 * @author Bryan Holladay (holladay@longsight.com)
 */

public abstract class BaseTreePage extends BasePage {
    private static final Logger log = Logger.getLogger(BaseTreePage.class);

    /**
     * Returns the tree on this pages. This is used to collapse, expand, ect
     * 
     * @return Tree instance on this page
     */
    protected abstract AbstractTree getTree();

    /**
     * This saves the state of the tree.  It goes through the entire structure and saves the access and role information
     * for each node.  It will remove and add all information.
     * 
     * @param userId
     * @param defaultRole  pass this in if there is a default Role, if null, it will be ignored
     */
    protected void updateNodeAccess(String userId, String[] defaultRole) {
        if (getTree() != null) {
            DefaultMutableTreeNode rootNode = (DefaultMutableTreeNode) getTree().getModelObject().getRoot();
            if (rootNode != null) {
                updateNodeAccessHelper(rootNode, userId, defaultRole);
            }
            projectLogic.syncMyworkspaceToolForUser(userId);
        }
    }

    /**
     * This is a helper function for updateNodeAccess
     * 
     * @param node
     * @param userId
     * @param defaultRole
     */
    private void updateNodeAccessHelper(DefaultMutableTreeNode node, String userId, String[] defaultRole) {
        if (node.getUserObject() != null) {
            NodeModel nodeModel = (NodeModel) node.getUserObject();
            if (defaultRole != null && defaultRole.length == 2) {
                nodeModel.setRealm(defaultRole[0]);
                nodeModel.setRole(defaultRole[1]);
            }
            if (nodeModel.isModified()) {
                //since this is the DA UI, we need to set instructorEdit to false
                ((NodeModel) node.getUserObject()).setInstructorEdited(false);
                projectLogic.updateNodePermissionsForUser(node, userId);
                //now reset the node's "original" values to ensure the next save will check against
                //the newly saved settings
                nodeModel.setOriginals();
            }

            //check the rest of the children:
            for (int i = 0; i < node.getChildCount(); i++) {
                updateNodeAccessHelper((DefaultMutableTreeNode) node.getChildAt(i), userId, defaultRole);
            }
        }
    }

    public boolean anyNodesModified(DefaultMutableTreeNode node) {
        boolean modified = false;
        if (((NodeModel) node.getUserObject()).isModified()) {
            return true;
        } else {
            for (int i = 0; i < node.getChildCount(); i++) {
                modified = modified || anyNodesModified((DefaultMutableTreeNode) node.getChildAt(i));
                if (modified) {
                    break;
                }
            }
            return modified;
        }
    }

    /**
     * This collapses all empty folders in the tree.  This helps the user know that they need to click on the folder
     * in order to populate the children nodes.  (used when the structure is being populated on the fly w/ajax and the
     * folders haven't been populated yet)
     */
    protected void collapseEmptyFolders() {
        collapseEmptyFoldersHelper((DefaultMutableTreeNode) getTree().getModelObject().getRoot());
    }

    /**
     * Helper function for collapseEmptyFoldersHelper
     * @param node
     */
    protected void collapseEmptyFoldersHelper(DefaultMutableTreeNode node) {
        if (node != null) {
            if (!node.isLeaf() && node.getChildCount() == 0) {
                //this is a node that isn't a leaf but hasn't had the children updated, make it collapse
                getTree().getTreeState().collapseNode(node);
            }
            for (int i = 0; i < node.getChildCount(); i++) {
                collapseEmptyFoldersHelper((DefaultMutableTreeNode) node.getChildAt(i));
            }
        }
    }

    protected AjaxLink getExpandCollapseLink() {
        //Expand Collapse Link:
        final Label expandCollapse = new Label("expandCollapse", new StringResourceModel("exapndNodes", null));
        expandCollapse.setOutputMarkupId(true);
        AjaxLink expandLink = new AjaxLink("expandAll") {
            boolean expand = true;

            @Override
            public void onClick(AjaxRequestTarget target) {
                if (expand) {
                    getTree().getTreeState().expandAll();
                    expandCollapse.setDefaultModel(new StringResourceModel("collapseNodes", null));
                    collapseEmptyFolders();
                } else {
                    getTree().getTreeState().collapseAll();
                    expandCollapse.setDefaultModel(new StringResourceModel("exapndNodes", null));
                }
                target.addComponent(expandCollapse);
                getTree().updateTree(target);
                expand = !expand;

            }

            @Override
            public boolean isVisible() {
                return getTree().getDefaultModelObject() != null;
            }
        };
        expandLink.add(expandCollapse);
        return expandLink;
    }

    private void createInheritedSpan() {
        WebMarkupContainer inheritedSpan = new WebMarkupContainer("inheritedSpan");
        inheritedSpan.setOutputMarkupId(true);
        final String inheritedSpanId = inheritedSpan.getMarkupId();
        add(inheritedSpan);

        AbstractReadOnlyModel<List<? extends ListOptionSerialized>> inheritedRestrictedToolsModel = new AbstractReadOnlyModel<List<? extends ListOptionSerialized>>() {
            private static final long serialVersionUID = 1L;

            @Override
            public List<? extends ListOptionSerialized> getObject() {
                return new ArrayList<ListOptionSerialized>();
            }

        };

        final ListView<ListOptionSerialized> inheritedListView = new ListView<ListOptionSerialized>(
                "inheritedRestrictedTools", inheritedRestrictedToolsModel) {
            private static final long serialVersionUID = 1L;

            @Override
            protected void populateItem(ListItem<ListOptionSerialized> item) {
                ListOptionSerialized tool = (ListOptionSerialized) item.getModelObject();
                Label name = new Label("name", tool.getName());
                item.add(name);
            }
        };
        inheritedListView.setOutputMarkupId(true);
        inheritedSpan.add(inheritedListView);

        AjaxLink<Void> closeInheritedSpanLink = new AjaxLink("closeInheritedSpanLink") {
            @Override
            public void onClick(AjaxRequestTarget arg0) {
            }
        };
        inheritedSpan.add(closeInheritedSpanLink);

        Label inheritedNodeTitle = new Label("inheritedNodeTitle", "");
        inheritedSpan.add(inheritedNodeTitle);

        Label noInheritedToolsLabel = new Label("noToolsInherited",
                new StringResourceModel("inheritedNothing", null));
        inheritedSpan.add(noInheritedToolsLabel);

    }

    public void expandTreeToDepth(DefaultMutableTreeNode node, int depth, String userId,
            List<ListOptionSerialized> blankRestrictedTools, List<String> accessAdminNodeIds,
            boolean onlyAccessNodes, boolean shopping, boolean shoppingPeriodTool, String filterSearch) {
        projectLogic.addChildrenNodes(node, userId, blankRestrictedTools, onlyAccessNodes, accessAdminNodeIds,
                shopping, shoppingPeriodTool);
        //set expand flag to true so to not look for children again:
        ((NodeModel) node.getUserObject()).setAddedDirectChildrenFlag(true);
        getTree().getTreeState().expandNode(node);
        if (depth > 0) {
            //recursive function stopper:
            int newDepth = depth - 1;
            //count down backwards since we could be deleting these children nodes
            for (int i = node.getChildCount() - 1; i >= 0; i--) {
                expandTreeToDepth((DefaultMutableTreeNode) node.getChildAt(i), newDepth, userId,
                        blankRestrictedTools, accessAdminNodeIds, onlyAccessNodes, shopping, shoppingPeriodTool,
                        filterSearch);
            }
        } else {
            //make sure all children are collapsed and filter out the ones that need to be filtered
            //count down backwards since we could be deleting these children nodes
            for (int i = node.getChildCount() - 1; i >= 0; i--) {
                getTree().getTreeState().collapseNode(node.getChildAt(i));
                String nodeTitle = ((NodeModel) ((DefaultMutableTreeNode) node.getChildAt(i)).getUserObject())
                        .getNode().description.toLowerCase();
                if (filterSearch != null && !"".equals(filterSearch.trim())
                        && !nodeTitle.contains(filterSearch.toLowerCase())) {
                    //delete this child:
                    node.remove(i);
                }
            }
        }
        //check if all of the children have been removed (but don't delete root node)
        if (node.getParent() != null && node.getChildCount() == 0) {
            ((DefaultMutableTreeNode) node.getParent()).remove(node);
        }
    }
}