org.netxilia.server.rest.HomeResource.java Source code

Java tutorial

Introduction

Here is the source code for org.netxilia.server.rest.HomeResource.java

Source

/*******************************************************************************
 * 
 * Copyright 2010 Alexandru Craciun, and individual contributors as indicated
 * by the @authors tag. 
 * 
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 3 of
 * the License, or (at your option) any later version.
 * 
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 ******************************************************************************/
package org.netxilia.server.rest;

import java.security.AccessControlException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Stack;
import java.util.TreeSet;

import javax.swing.tree.DefaultMutableTreeNode;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import org.netxilia.api.exception.NetxiliaBusinessException;
import org.netxilia.api.exception.NetxiliaResourceException;
import org.netxilia.api.exception.NotFoundException;
import org.netxilia.api.exception.StorageException;
import org.netxilia.api.model.CellData;
import org.netxilia.api.model.ISheet;
import org.netxilia.api.model.IWorkbook;
import org.netxilia.api.model.SheetFullName;
import org.netxilia.api.model.SheetType;
import org.netxilia.api.model.WorkbookId;
import org.netxilia.api.reference.AreaReference;
import org.netxilia.api.storage.DataSourceConfiguration;
import org.netxilia.api.storage.DataSourceConfigurationId;
import org.netxilia.api.storage.IDataSourceConfigurationService;
import org.netxilia.api.user.IAclService;
import org.netxilia.api.user.IUserService;
import org.netxilia.api.user.Permission;
import org.netxilia.api.user.User;
import org.netxilia.api.utils.Matrix;
import org.netxilia.api.utils.Pair;
import org.netxilia.jaxrs.html.ModelAndView;
import org.netxilia.server.rest.html.HomeModel;
import org.netxilia.server.util.StringHolder;
import org.springframework.beans.factory.annotation.Autowired;

@Path("/home")
public class HomeResource extends AbstractResource {
    private static org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(HomeResource.class);

    private static final String FOLDERS_SHEET = "folders";

    @Autowired
    private IDataSourceConfigurationService dataSourceConfigurationService;

    @Autowired
    private IAclService aclService;

    @Autowired
    private IUserService userService;

    public IDataSourceConfigurationService getDataSourceConfigurationService() {
        return dataSourceConfigurationService;
    }

    public void setDataSourceConfigurationService(IDataSourceConfigurationService dataSourceConfigurationService) {
        this.dataSourceConfigurationService = dataSourceConfigurationService;
    }

    public IAclService getAclService() {
        return aclService;
    }

    public void setAclService(IAclService aclService) {
        this.aclService = aclService;
    }

    public IUserService getUserService() {
        return userService;
    }

    public void setUserService(IUserService userService) {
        this.userService = userService;
    }

    private DataSourceConfigurationId getMostUsedDataSource() throws StorageException {
        Map<DataSourceConfigurationId, Integer> dataSourceWorkbookCount = new HashMap<DataSourceConfigurationId, Integer>();

        List<Pair<WorkbookId, DataSourceConfigurationId>> workbooksAndConfigs = dataSourceConfigurationService
                .findAllWorkbooksConfigurations();
        for (Pair<WorkbookId, DataSourceConfigurationId> wkCfg : workbooksAndConfigs) {
            Integer count = dataSourceWorkbookCount.get(wkCfg.getSecond());
            dataSourceWorkbookCount.put(wkCfg.getSecond(), count != null ? count + 1 : 0);
        }

        DataSourceConfigurationId maxEntry = null;
        int max = Integer.MIN_VALUE;
        for (Map.Entry<DataSourceConfigurationId, Integer> entry : dataSourceWorkbookCount.entrySet()) {
            if (entry.getValue() > max) {
                maxEntry = entry.getKey();
                max = entry.getValue();
            }
        }
        return maxEntry;
    }

    @GET
    @Produces(MediaType.TEXT_HTML)
    public ModelAndView<HomeModel> get() throws NetxiliaResourceException, NetxiliaBusinessException {
        HomeModel homeModel = new HomeModel(treeview().getValue(), getMostUsedDataSource());
        return new ModelAndView<HomeModel>(homeModel, "/WEB-INF/jsp/home.jsp");
    }

    @GET
    @Path("/treeview")
    @Produces(MediaType.APPLICATION_JSON)
    public StringHolder treeview() throws NetxiliaResourceException, NetxiliaBusinessException {
        // TODO - here a light version if IWorkbook should be return to not be able to get around security exceptions

        // add workbooks
        List<Pair<WorkbookId, DataSourceConfigurationId>> workbooksAndConfigs = dataSourceConfigurationService
                .findAllWorkbooksConfigurations();

        DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode(null);

        for (Pair<WorkbookId, DataSourceConfigurationId> wkCfg : workbooksAndConfigs) {
            WorkbookId wkId = wkCfg.getFirst();
            IWorkbook workbook = null;
            Set<SheetFullName> sheetNames = new TreeSet<SheetFullName>();
            try {
                workbook = getWorkbookProcessor().getWorkbook(wkId);

                for (ISheet sheet : workbook.getSheets()) {
                    if (sheet.getType() == SheetType.normal) {
                        try {
                            aclService.checkPermission(sheet.getFullName(), Permission.read);
                        } catch (AccessControlException e) {
                            continue;
                        }
                        sheetNames.add(sheet.getFullName());
                    }
                }
            } catch (AccessControlException ex) {
                // user has not write to see the workbook
                continue;
            } catch (Exception ex) {
                log.error("Could not load workbook " + wkId + ":" + ex, ex);
                // add the workbook with error
                DefaultMutableTreeNode workbookNode = new DefaultMutableTreeNode(
                        new TreeViewData(wkId.getKey(), wkId.getKey(), "workbook error"));
                rootNode.add(workbookNode);
                continue;
            }

            ISheet foldersSheet = null;
            SheetFullName folderSheetName = new SheetFullName(workbook.getName(), FOLDERS_SHEET);
            try {
                foldersSheet = getWorkbookProcessor().getWorkbook(wkId).getSheet(FOLDERS_SHEET);
            } catch (NotFoundException ex) {
                // no folder sheet
            } catch (Exception ex) {
                log.error("Could not load folder sheet" + folderSheetName + ":" + ex, ex);
            }
            DefaultMutableTreeNode workbookNode = buildWorkbookTree(workbook, foldersSheet, sheetNames);
            rootNode.add(workbookNode);

        }

        // only for admins
        User currentUser = userService.getCurrentUser();
        if (currentUser != null && currentUser.isAdmin()) {
            // add admin
            DefaultMutableTreeNode adminNode = new DefaultMutableTreeNode(
                    new TreeViewData("admin", "Administration", "admin", true));
            rootNode.add(adminNode);

            // add datasources nodes
            DefaultMutableTreeNode dsNode = new DefaultMutableTreeNode(
                    new TreeViewData("ds", "Datasources", "datasources", true));
            adminNode.add(dsNode);
            for (DataSourceConfiguration dsConfig : dataSourceConfigurationService.findAll()) {
                dsNode.add(new DefaultMutableTreeNode(
                        new TreeViewData(dsConfig.getId().toString(), dsConfig.getName(), "datasource")));
            }

            // add modules nodes
            DefaultMutableTreeNode moduleNode = new DefaultMutableTreeNode(
                    new TreeViewData("modules", "Modules", "modules", true));
            adminNode.add(moduleNode);

            // add build nodes
            DefaultMutableTreeNode buildNode = new DefaultMutableTreeNode(
                    new TreeViewData("build", "Custom Modules", "build", true));
            adminNode.add(buildNode);
        }

        StringBuilder treeview = new StringBuilder();
        buildTreeView(rootNode, treeview);
        return new StringHolder(treeview.toString());
    }

    /**
     * walk the tree and dump the node to the tree
     * 
     * @param node
     * @param treeview
     */
    @SuppressWarnings("unchecked")
    private void buildTreeView(DefaultMutableTreeNode node, StringBuilder treeview) {
        // <ul id="example" class="filetree">
        // <li><span class="folder">Folder 1</span>
        // <ul>
        // <li><span class="file">Item 1.1</span></li>
        // </ul>
        // </li>
        // <li><span class="folder">Folder 2</span>

        TreeViewData viewData = (TreeViewData) node.getUserObject();
        if (node.isLeaf()) {
            if (viewData != null) {
                treeview.append("<li><span id='").append(viewData.getId()).append("' class='")
                        .append(viewData.getCssClass()).append("'>").append(viewData.getName())
                        .append("</span></li>");
            }
        } else {
            if (viewData != null) {
                if (viewData.isCollapsed()) {
                    treeview.append("<li class='closed'>");
                } else {
                    treeview.append("<li>");
                }
                treeview.append("<span class='folder ").append(viewData.getCssClass()).append("'>")
                        .append(viewData.getName()).append("</span><ul>");
            }
            Enumeration<DefaultMutableTreeNode> childrenEnum = node.children();
            while (childrenEnum.hasMoreElements()) {
                buildTreeView(childrenEnum.nextElement(), treeview);
            }
            if (viewData != null) {
                treeview.append("</ul></li>");
            }
        }
    }

    /**
     * build the HTML tags for a tree like view
     * 
     * @param foldersSheet
     * @param treeview
     * @throws NetxiliaBusinessException
     * @throws NetxiliaResourceException
     */
    private DefaultMutableTreeNode buildWorkbookTree(IWorkbook workbook, ISheet foldersSheet,
            Set<SheetFullName> sheetNames) throws NetxiliaResourceException, NetxiliaBusinessException {
        DefaultMutableTreeNode workbookNode = new DefaultMutableTreeNode(
                new TreeViewData(workbook.getId().getKey(), workbook.getName(), "workbook"));

        Stack<DefaultMutableTreeNode> stockNodes = new Stack<DefaultMutableTreeNode>();
        stockNodes.push(workbookNode);

        Set<SheetFullName> alreadyInsertedSheets = new HashSet<SheetFullName>();
        if (foldersSheet != null) {
            Matrix<CellData> folderCells = foldersSheet.receiveCells(AreaReference.ALL).getNonBlocking();
            for (List<CellData> row : folderCells.getRows()) {
                int level = 0;
                String nodeName = null;
                for (CellData cell : row) {
                    if (cell.getValue() != null) {
                        nodeName = cell.getValue().getStringValue();
                        if (nodeName != null && nodeName.length() > 0) {
                            level = cell.getReference().getColumnIndex();
                            break;
                        }
                    }
                }

                if (nodeName == null) {
                    // empty line - ignored
                    continue;
                }

                // first level for folders is 1 (under the root node)
                level = level + 1;
                SheetFullName sheetName = new SheetFullName(workbook.getName(), nodeName);
                boolean isSheet = sheetNames.contains(sheetName);
                if (isSheet) {
                    alreadyInsertedSheets.add(sheetName);
                }
                DefaultMutableTreeNode crt = new DefaultMutableTreeNode(new TreeViewData(sheetName.toString(),
                        sheetName.getSheetName(), isSheet ? "sheet" : "folder"));
                while (!stockNodes.empty()) {
                    DefaultMutableTreeNode node = stockNodes.peek();
                    if (level > node.getLevel()) {
                        // make sure is the direct child
                        node.add(crt);
                        break;
                    }
                    stockNodes.pop();
                }
                stockNodes.push(crt);
            }
        }
        // add the sheets not already added
        for (SheetFullName sheetName : sheetNames) {
            if (alreadyInsertedSheets.contains(sheetName)) {
                continue;
            }
            DefaultMutableTreeNode sheetNode = new DefaultMutableTreeNode(
                    new TreeViewData(sheetName.toString(), sheetName.getSheetName(), "sheet"));
            workbookNode.add(sheetNode);
        }

        return workbookNode;
    }

    private static class TreeViewData {
        private final String id;
        private final String name;
        private final String cssClass;
        private final boolean collapsed;

        public TreeViewData(String id, String name, String cssClass) {
            this(id, name, cssClass, false);
        }

        public TreeViewData(String id, String name, String cssClass, boolean collapsed) {
            this.id = id;
            this.name = name;
            this.cssClass = cssClass;
            this.collapsed = collapsed;
        }

        public String getId() {
            return id;
        }

        public String getName() {
            return name;
        }

        public String getCssClass() {
            return cssClass;
        }

        public boolean isCollapsed() {
            return collapsed;
        }

    }
}