org.netxilia.api.impl.model.Workbook.java Source code

Java tutorial

Introduction

Here is the source code for org.netxilia.api.impl.model.Workbook.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.api.impl.model;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
import org.netxilia.api.display.IStyleService;
import org.netxilia.api.event.IWorkbookEventListener;
import org.netxilia.api.event.SheetEvent;
import org.netxilia.api.event.SheetEventType;
import org.netxilia.api.exception.AlreadyExistsException;
import org.netxilia.api.exception.NotFoundException;
import org.netxilia.api.exception.StorageException;
import org.netxilia.api.impl.NetxiliaSystemImpl;
import org.netxilia.api.impl.dependencies.WorkbookAliasDependencyManager;
import org.netxilia.api.impl.dependencies.WorkbookDependencyManager;
import org.netxilia.api.model.ISheet;
import org.netxilia.api.model.IWorkbook;
import org.netxilia.api.model.SheetData;
import org.netxilia.api.model.SheetFullName;
import org.netxilia.api.model.SheetType;
import org.netxilia.api.model.WorkbookId;
import org.netxilia.api.user.IAclService;
import org.netxilia.api.user.IUserService;
import org.netxilia.api.user.Permission;
import org.netxilia.api.value.IGenericValueParseService;
import org.netxilia.spi.formula.IFormulaParser;
import org.springframework.util.Assert;

/**
 * A workbook represents a collection of Sheets. It should be seen in a larger wy than a Excel workbook as is meant to
 * contain many sheets.
 * 
 * The access to sheets is synchronized.
 * 
 * @author <a href='mailto:ax.craciun@gmail.com'>Alexandru Craciun</a>
 * 
 */
public class Workbook implements Serializable, IWorkbook {
    private static final long serialVersionUID = -2496417506141917109L;

    private final WorkbookId id;
    private final Map<String, ISheet> sheetsByName;
    private String name;
    private final NetxiliaSystemImpl workbookProcessor;

    private WorkbookDependencyManager dependencyManager;
    private WorkbookAliasDependencyManager aliasDependencyManager;

    private final WorkbookEventSupport eventSupport;

    public static Workbook newInstance(NetxiliaSystemImpl workbookProcessor, WorkbookId workbookId)
            throws StorageException, NotFoundException {
        return newInstance(workbookProcessor, workbookId, new ArrayList<SheetData>());
    }

    public static Workbook newInstance(NetxiliaSystemImpl workbookProcessor, WorkbookId workbookId,
            List<SheetData> sheets) throws StorageException, NotFoundException {
        Workbook workbook = new Workbook(workbookProcessor, workbookId, sheets);
        workbook.dependencyManager = WorkbookDependencyManager.newInstance(workbook,
                workbookProcessor.getMoreCellCommands(), workbookProcessor.getFormulaParser());
        workbook.aliasDependencyManager = WorkbookAliasDependencyManager.newInstance(workbook,
                workbookProcessor.getFormulaParser(), workbookProcessor.getMoreCellCommands());

        return workbook;
    }

    private Workbook(NetxiliaSystemImpl workbookProcessor, WorkbookId workbookId, List<SheetData> sheets)
            throws StorageException, NotFoundException {
        Assert.notNull(workbookProcessor);
        Assert.notNull(workbookId);
        Assert.notNull(sheets);

        this.id = workbookId;
        // by default take the key as name
        this.name = id.getKey();

        eventSupport = new WorkbookEventSupport();
        this.workbookProcessor = workbookProcessor;

        this.sheetsByName = new HashMap<String, ISheet>();
        for (SheetData sheetData : sheets) {
            sheetsByName.put(sheetData.getFullName().getSheetName(), createSheetActorRef(sheetData));
        }

    }

    public WorkbookId getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
        // changing the name of a workbook is not supported!
        // ModificationsTracker.updated(this, "name");
    }

    /**
     * 
     * @return if the sheet must be initialized on open - used for tests only
     */
    public boolean isInitializationEnabled() {
        return workbookProcessor.isSheetInitializationEnabled();
    }

    public synchronized ISheet getSheet(String sheetName) throws NotFoundException {
        getAclService().checkPermission(id, Permission.read);
        ISheet sheet = sheetsByName.get(sheetName);
        if (sheet == null) {
            throw new NotFoundException("Sheet named " + sheetName + " was not found in workbook:" + name);
        }
        return sheet;
    }

    public synchronized boolean hasSheet(String sheetName) {
        getAclService().checkPermission(id, Permission.read);
        return sheetsByName.containsKey(sheetName);
    }

    private IAclService getAclService() {
        return workbookProcessor.getAclService();
    }

    public void addListener(IWorkbookEventListener listener) {
        eventSupport.removeListener(listener);
        eventSupport.addListener(listener);
    }

    public void removeListener(IWorkbookEventListener listener) {
        eventSupport.removeListener(listener);
    }

    /**
     * 
     * @param mainSheetName
     * @return all the "user" sheets linked to the given sheet name
     */
    public synchronized Collection<ISheet> getUserSheets(String mainSheetName) {
        List<ISheet> userSheets = new ArrayList<ISheet>();
        SheetFullName summarySheetName = SheetFullName.summarySheetName(new SheetFullName(name, mainSheetName),
                null);
        for (ISheet sheet : sheetsByName.values()) {
            if (!sheet.getName().equals(summarySheetName.getSheetName())
                    && sheet.getName().startsWith(mainSheetName + ".") && sheet.getType() == SheetType.user) {
                userSheets.add(sheet);
            }
        }
        return userSheets;
    }

    @Override
    public synchronized Collection<ISheet> getSheets() {
        getAclService().checkPermission(id, Permission.read);
        return new ArrayList<ISheet>(sheetsByName.values());
    }

    public synchronized ISheet addNewSheet(String sheetName, SheetType type)
            throws AlreadyExistsException, StorageException, NotFoundException {
        getAclService().checkPermission(id, Permission.write);
        if ((sheetName == null) || sheetName.isEmpty()) {
            throw new IllegalArgumentException("The sheet has to have a non-empty name");
        }

        if (sheetsByName.containsKey(sheetName)) {
            throw new AlreadyExistsException(
                    "A sheet with the name [" + sheetName + "] already exists in this workbook");
        }
        SheetData sheetData = new SheetData(new SheetFullName(id, sheetName), type);
        ISheet sheet = createSheetActorRef(sheetData);
        sheetsByName.put(sheetName, sheet);
        getAclService().setPermissions(sheetData.getFullName(), getUserService().getCurrentUser(), Permission.read,
                Permission.write);
        eventSupport.fireEvent(
                new SheetEvent(SheetEventType.inserted, sheetData, Collections.<SheetData.Property>emptyList()));
        return sheet;
    }

    /**
     * deletes the sheet with the given name
     * 
     * @param sheetName
     * @throws NotFoundException
     *             if the given sheet does not exist in this workbook
     */
    public synchronized void deleteSheet(ISheet sheet) throws NotFoundException {
        if (sheetsByName.remove(sheet.getName()) != null) {
            workbookProcessor.getStorageService().deleteSheet(sheet.getFullName(), sheet.getType());
            eventSupport.fireEvent(new SheetEvent(SheetEventType.deleted,
                    new SheetData(new SheetFullName(id, sheet.getName()), sheet.getType()),
                    Collections.<SheetData.Property>emptyList()));
        }
    }

    @Override
    public synchronized void deleteSheet(String sheetFullName) throws NotFoundException, StorageException {

        ISheet sheetDesc = getSheet(sheetFullName);

        // check the rights on the main sheet only
        getAclService().checkPermission(SheetFullName.mainSheetName(new SheetFullName(id, sheetDesc.getName()),
                getUserService().getCurrentUser()), Permission.write);

        if (sheetDesc.getType() == SheetType.normal) {
            // delete also summary
            ISheet summarySheet = sheetsByName.get(SheetFullName.summarySheetName(sheetDesc, null).getSheetName());
            if (summarySheet != null) {
                deleteSheet(summarySheet);
            }
            // delete also user sheets
            Collection<ISheet> userSheets = getUserSheets(sheetFullName);
            for (ISheet userSheet : userSheets) {
                deleteSheet(userSheet);
            }
        }

        deleteSheet(sheetDesc);
    }

    public WorkbookDependencyManager getDependencyManager() {
        return dependencyManager;
    }

    public synchronized void removeAllSheets() {
        sheetsByName.clear();
    }

    private IUserService getUserService() {
        return workbookProcessor.getUserService();
    }

    public IFormulaParser getFormulaParser() {
        return workbookProcessor.getFormulaParser();
    }

    IStyleService getStyleService() {
        return workbookProcessor.getStyleService();
    }

    IGenericValueParseService getParseService() {
        return workbookProcessor.getParseService();
    }

    NetxiliaSystemImpl getWorkbookProcessor() {
        return workbookProcessor;
    }

    public WorkbookAliasDependencyManager getAliasDependencyManager() {
        return aliasDependencyManager;
    }

    protected ISheet createSheetActorRef(SheetData sheetData) throws StorageException, NotFoundException {
        SheetActor actor = new SheetActor(this, sheetData, workbookProcessor.getFormulaCalculatorFactory(),
                getFormulaParser(),
                workbookProcessor.getStorageService().getSheetStorage(sheetData.getFullName(), sheetData.getType()),
                workbookProcessor.getExecutorServiceFactory(), workbookProcessor.getSpringUserService(),
                workbookProcessor.getMoreCellCommands(), workbookProcessor.getPreloadContextFactory());
        SheetProxy proxy = new SheetProxy(
                workbookProcessor.getExecutorServiceFactory()
                        .newExecutorService(sheetData.getFullName().toString()),
                workbookProcessor.getSpringUserService(), workbookProcessor.getAclService(), actor);
        actor.setActorRef(proxy);
        return proxy;
    }

    @Override
    public String toString() {
        return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) //
                .append("workbook", id) //
                .append("name", name) //
                .append("sheetsSize", sheetsByName.size()) //
                .toString();
    }

}