Package org.zkoss.zss.model.impl

Source Code of org.zkoss.zss.model.impl.XSSFBookImpl

/* XSSFBook.java

  Purpose:
   
  Description:
   
  History:
    Mar 22, 2010 7:17:28 PM, Created by henrichen

Copyright (C) 2010 Potix Corporation. All Rights Reserved.

*/

package org.zkoss.zss.model.impl;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.openxmlformats.schemas.officeDocument.x2006.docPropsVTypes.CTVariant;
import org.openxmlformats.schemas.officeDocument.x2006.docPropsVTypes.CTVector;
import org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.CTProperties;
import org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.CTVectorLpstr;
import org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.CTVectorVariant;
import org.zkoss.lang.Classes;
import org.zkoss.lang.Library;
import org.zkoss.poi.POIXMLProperties;
import org.zkoss.poi.ss.SpreadsheetVersion;
import org.zkoss.poi.ss.formula.FormulaParser;
import org.zkoss.poi.ss.formula.FormulaType;
import org.zkoss.poi.ss.formula.SheetNameFormatter;
import org.zkoss.poi.ss.formula.WorkbookEvaluator;
import org.zkoss.poi.ss.formula.ptg.Ptg;
import org.zkoss.poi.ss.usermodel.Color;
import org.zkoss.poi.ss.usermodel.Font;
import org.zkoss.poi.ss.usermodel.FormulaEvaluator;
import org.zkoss.poi.ss.usermodel.PictureData;
import org.zkoss.poi.ss.usermodel.PivotCache;
import org.zkoss.poi.ss.util.AreaReference;
import org.zkoss.poi.ss.util.CellRangeAddress;
import org.zkoss.poi.xssf.usermodel.XSSFColor;
import org.zkoss.poi.xssf.usermodel.XSSFEvaluationWorkbook;
import org.zkoss.poi.xssf.usermodel.XSSFFont;
import org.zkoss.poi.xssf.usermodel.XSSFFormulaEvaluator;
import org.zkoss.poi.xssf.usermodel.XSSFName;
import org.zkoss.poi.xssf.usermodel.XSSFRelation;
import org.zkoss.poi.xssf.usermodel.XSSFSheet;
import org.zkoss.poi.xssf.usermodel.XSSFWorkbook;
import org.zkoss.xel.FunctionMapper;
import org.zkoss.xel.VariableResolver;
import org.zkoss.zk.ui.UiException;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zss.engine.Ref;
import org.zkoss.zss.engine.RefBook;
import org.zkoss.zss.formula.DefaultFunctionResolver;
import org.zkoss.zss.formula.FunctionResolver;
import org.zkoss.zss.formula.NoCacheClassifier;
import org.zkoss.zss.model.Book;
import org.zkoss.zss.model.BookSeries;
import org.zkoss.zss.model.Worksheet;

/**
* Implementation of {@link Book} based on XSSFWorkbook.
* @author henrichen
*
*/
public class XSSFBookImpl extends XSSFWorkbook implements Book, BookCtrl {
  private final String _bookname;
  private final FormulaEvaluator _evaluator;
  private final WorkbookEvaluator _bookEvaluator;
  private final FunctionMapper _functionMapper;
  private final VariableResolver _variableResolver;
  private RefBook _refBook;
  private BookSeries _bookSeries;
  private int _defaultCharWidth = 7; //TODO: don't know how to calculate this yet per the default font.
 
  //override the XSSFSheet Relation
  static {
    Field fd = null;
    try {
      fd = Classes.getAnyField(XSSFRelation.class, "_cls");
    } catch (NoSuchFieldException e) {
      throw new RuntimeException(e);
    }
    final boolean old = fd.isAccessible();
    try {
      fd.setAccessible(true);
      fd.set(XSSFRelation.WORKSHEET, XSSFSheetImpl.class); //Use the new XSSFSheet implementation
    } catch (IllegalAccessException e) {
      throw new RuntimeException(e);
    } finally {
      fd.setAccessible(old);
    }
  }

  public XSSFBookImpl(String bookname, InputStream is) throws IOException {
    super(is);
    for(XSSFSheet sheet : this) {
      ((SheetCtrl)sheet).initMerged();
    }
    _bookname = bookname;
    FunctionResolver resolver = (FunctionResolver) BookHelper.getLibraryInstance(FunctionResolver.CLASS);
    if (resolver == null) resolver = new DefaultFunctionResolver();
    _evaluator = XSSFFormulaEvaluator.create(this, NoCacheClassifier.instance, resolver.getUDFFinder());
    _bookEvaluator = _evaluator.getWorkbookEvaluator();
    _bookEvaluator.setDependencyTracker(resolver.getDependencyTracker(this));
    _functionMapper = new JoinFunctionMapper(resolver.getFunctionMapper());
    _variableResolver = new JoinVariableResolver();
  }
 
  /*package*/ WorkbookEvaluator getWorkbookEvaluator() {
    return _bookEvaluator;
  }
 
  /*package*/ RefBook getOrCreateRefBook() {
    if (_refBook == null) {
      _refBook = newRefBook(this);
    }
    return _refBook;
  }
 
  /*package*/ BookSeries getBookSeries() {
    return _bookSeries;
  }
 
  /*package*/ void setBookSeries(BookSeries books) {
    _bookSeries = books;
  }
 
  /*package*/ VariableResolver getVariableResolver() {
    return _variableResolver;
  }
 
  /*package*/ FunctionMapper getFunctionMapper() {
    return _functionMapper;
  }
 
  //--Book--//
  @Override
  public SpreadsheetVersion getSpreadsheetVersion() {
    return SpreadsheetVersion.EXCEL2007;
  }
 
  @Override
  public String getBookName() {
    return _bookname;
  }
 
  @Override
  public FormulaEvaluator getFormulaEvaluator() {
    return _evaluator;
  }

  @Override
  public void addFunctionMapper(FunctionMapper mapper) {
    ((JoinFunctionMapper)getFunctionMapper()).addFunctionMapper(mapper);
  }

  @Override
  public void addVariableResolver(VariableResolver resolver) {
    ((JoinVariableResolver)getVariableResolver()).addVariableResolver(resolver);
  }

  @Override
  public void removeFunctionMapper(FunctionMapper mapper) {
    ((JoinFunctionMapper)getFunctionMapper()).removeFunctionMapper(mapper);
  }

  @Override
  public void removeVariableResolver(VariableResolver resolver) {
    ((JoinVariableResolver)getVariableResolver()).removeVariableResolver(resolver);
  }

  @Override
  public void subscribe(EventListener listener) {
    getOrCreateRefBook().subscribe(listener);
  }

  @Override
  public void unsubscribe(EventListener listener) {
    getOrCreateRefBook().unsubscribe(listener);
  }
 
  @Override
  public Font getDefaultFont() {
    return getFontAt((short)0);
  }
 
  @Override
  public void setDefaultFont(Font font) {
    final Font defFont = getDefaultFont();
    defFont.setBoldweight(font.getBoldweight());
    defFont.setCharSet(font.getCharSet());
    defFont.setColor(font.getColor());
    defFont.setFontHeight(font.getFontHeight());
    defFont.setFontName(font.getFontName());
    defFont.setItalic(font.getItalic());
    defFont.setStrikeout(font.getStrikeout());
    defFont.setTypeOffset(font.getTypeOffset());
    defFont.setUnderline(font.getUnderline());
   
    //TODO: recalic _defaultCharWidth
  }
 
  @Override
  public int getDefaultCharWidth() {
    return _defaultCharWidth;
  }
 
  @Override
  public void notifyChange(String[] variables) {
    final RefBook refBook = getOrCreateRefBook();
    final Set<Ref> all = new HashSet<Ref>();
    final Set<Ref> last = new HashSet<Ref>();
    for(String name : variables) {
      final Set<Ref>[] refs = refBook.getBothDependents(name);
      if (refs != null) {
        last.addAll(refs[0]);
        all.addAll(refs[1]);
      }
    }
    BookHelper.reevaluateAndNotify(this, last, all);
  }
 
  @Override
  public void deletePictureData(PictureData img) {
    getAllPictures().remove(img);
  }
 
  //--Workbook--//
  @Override
  public void removeSheetAt(int index) {
    if (_refBook != null) {
      final String sheetname = getSheetName(index);
      _refBook.removeRefSheet(sheetname);
    }
    super.removeSheetAt(index);
  }

  @Override
  public void setSheetName(int index, String name) {
    final String oldsheetname = getSheetName(index);
    super.setSheetName(index, name);
    if (_refBook != null) {
      _refBook.setSheetName(oldsheetname, name);
    }
    for (XSSFSheet sheet : this) { //scan all sheets to change the possible reference
      ((SheetCtrl)sheet).whenRenameSheet(oldsheetname, name);
    }
    ranameSheetInAppXml(oldsheetname, name);
  }

  //rename sheet in app.xml(extended properties)
  private void ranameSheetInAppXml(String oldsheetname, String name) {
      POIXMLProperties properties = getProperties(); //app.xml and custom.xml

    CTProperties ext = properties.getExtendedProperties().getUnderlyingProperties();
    CTVectorVariant vectorv = ext.getHeadingPairs();
    CTVector vector = vectorv.getVector();
    CTVariant[] variants = vector.getVariantArray();
    int sheetCount = -1;
    int nameCount = -1;
    for(int j = 0; j < variants.length; ++j) {
      final CTVariant variant = variants[j];
      if ((j & 1) == 0) { //string
        String key = variant.getLpstr();
        if ("Worksheets".equalsIgnoreCase(key)) {
          final CTVariant variant2 = variants[++j];
          sheetCount = variant2.getI4();
        } else if ("Named Ranges".equalsIgnoreCase(key)) {
          final CTVariant variant2 = variants[++j];
          nameCount = variant2.getI4();
        }
      }
    }
    if (sheetCount >= 0 && nameCount >= 0) {
      nameCount += sheetCount;
    }
    CTVectorLpstr vectorv2 = ext.getTitlesOfParts();
    CTVector vector2 = vectorv2.getVector();
    String[] lpstrs = vector2.getLpstrArray();
    int j = 0;
    for(; j < sheetCount; ++j) {
      final String sname = lpstrs[j];
      if (oldsheetname.equals(sname)) {
        vector2.setLpstrArray(j, name);
        j = sheetCount;
        break;
      }
    }
    final String o = SheetNameFormatter.format(oldsheetname);
    final String n = SheetNameFormatter.format(name);
    for(; j < nameCount; ++j) {
      final String refname = lpstrs[j];
      final String newrefname = refname.replace(o+"!", n+"!");
      if (!newrefname.equals(refname)) {
        vector2.setLpstrArray(j, newrefname);
      }
    }
  }

  @Override
  public CellRangeAddress getRepeatingRowsAndColumns(int sheetNumber) {
    final XSSFName name = getBuiltInName(XSSFName.BUILTIN_PRINT_TITLE, sheetNumber);
    if (name == null) {
      return new CellRangeAddress(-1, -1, -1, -1);
    } else {
      final String formula = name.getRefersToFormula();
      final Ptg[] ptgs = FormulaParser.parse(formula, XSSFEvaluationWorkbook.create(this), FormulaType.NAMEDRANGE, name.getSheetIndex());
      return BookHelper.getRepeatRowsAndColumns(ptgs);
    }
  }
    public XSSFName getBuiltInName(String builtInCode, int sheetNumber) {
      final int sz  = getNumberOfNames();
      for (int j = 0; j < sz; ++j) {
        XSSFName name = getNameAt(j);
            if (name.getNameName().equalsIgnoreCase(builtInCode) && name.getSheetIndex() == sheetNumber) {
                return name;
            }
        }
        return null;
    }

  /**
   * Finds a font that matches the one with the supplied attributes
   */
  public XSSFFont findFont(short boldWeight, Color color, short fontHeight, String name, boolean italic, boolean strikeout, short typeOffset, byte underline) {
    for (XSSFFont font : getStylesSource().getFonts()) {
      final XSSFColor fontColor = font.getXSSFColor();
      if (  (font.getBoldweight() == boldWeight)
          && (color == fontColor || color != null && color.equals(fontColor))
          && font.getFontHeight() == fontHeight
          && font.getFontName().equals(name)
          && font.getItalic() == italic
          && font.getStrikeout() == strikeout
          && font.getTypeOffset() == typeOffset
          && font.getUnderline() == underline)
      {
        return font;
      }
    }
    return null;
  }
 
  private volatile BookCtrl _bookCtrl; //double-checking locking
  private BookCtrl getBookCtrl() {
    BookCtrl ctrl = _bookCtrl;
    if (ctrl == null)
      synchronized (this) {
        ctrl = _bookCtrl;
        if (ctrl == null) {
          String clsnm = Library.getProperty(BookCtrl.CLASS);
          if (clsnm != null)
            try {
              final Object o = Classes.newInstanceByThread(clsnm);
              if (!(o instanceof BookCtrl))
                throw new UiException(o.getClass().getName()+" must implement "+BookCtrl.class.getName());
              ctrl = (BookCtrl)o;
            } catch (UiException ex) {
              throw ex;
            } catch (Throwable ex) {
              throw UiException.Aide.wrap(ex, "Unable to load "+clsnm);
            }
          if (ctrl == null)
            ctrl = new BookCtrlImpl();
          _bookCtrl = ctrl;
        }
      }
    return ctrl;
  }

  @Override
  public String getShareScope() {
    return getOrCreateRefBook().getShareScope();
  }

  @Override
  public void setShareScope(String scope) {
    getOrCreateRefBook().setShareScope(scope);
  }
 
  @Override
  public Worksheet getWorksheet(String name) {
    return (Worksheet) getSheet(name);
  }
 
  @Override
  public boolean isDate1904() {
    return super.isDate1904();
  }

  @Override
  public Worksheet getWorksheetAt(int index) {
    return (Worksheet) getSheetAt(index);
  }

   
  //--BookCtrl--//
  @Override
  public RefBook newRefBook(Book book) {
    return getBookCtrl().newRefBook(book);
  }

  @Override
  public Object nextSheetId() {
    return getBookCtrl().nextSheetId();
  }
 
  @Override
  public String nextFocusId() {
    return (String) getBookCtrl().nextFocusId();
  }

  @Override
  public void addFocus(Object focus) {
    getBookCtrl().addFocus(focus);
  }

  @Override
  public void removeFocus(Object focus) {
    getBookCtrl().removeFocus(focus)}

  @Override
  public boolean containsFocus(Object focus) {
    return getBookCtrl().containsFocus(focus);
  }
}
TOP

Related Classes of org.zkoss.zss.model.impl.XSSFBookImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.