Package org.zkoss.poi.ss.formula

Source Code of org.zkoss.poi.ss.formula.DefaultDependencyTracker

/* RefBookDepencyTracker.java

  Purpose:
   
  Description:
   
  History:
    Mar 23, 2010 4:49:57 PM, Created by henrichen

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

*/

package org.zkoss.poi.ss.formula;

import java.util.HashSet;
import java.util.Set;

import org.zkoss.poi.ss.formula.eval.ErrorEval;
import org.zkoss.poi.ss.formula.eval.NameEval;
import org.zkoss.poi.ss.formula.eval.StringEval;
import org.zkoss.poi.ss.formula.eval.ValueEval;
import org.zkoss.poi.ss.formula.eval.NotImplementedException;
import org.zkoss.poi.ss.formula.function.FunctionMetadataRegistry;
import org.zkoss.poi.ss.formula.ptg.AreaPtgBase;
import org.zkoss.poi.ss.formula.ptg.FuncPtg;
import org.zkoss.poi.ss.formula.ptg.Ptg;
import org.zkoss.poi.ss.formula.ptg.RefPtgBase;
import org.zkoss.poi.ss.util.CellReference;
import org.zkoss.xel.XelContext;
import org.zkoss.zk.ui.UiException;
import org.zkoss.zss.engine.RefBook;
import org.zkoss.zss.engine.RefSheet;
import org.zkoss.zss.engine.impl.CellRefImpl;
import org.zkoss.zss.engine.impl.DependencyTrackerHelper;
import org.zkoss.zss.model.Book;
import org.zkoss.zss.model.impl.BookHelper;
import org.zkoss.zss.model.impl.XelContextHolder;

/**
* Implementation of formula dependency tracking.
* @author henrichen
*
*/
public class DefaultDependencyTracker implements DependencyTracker {
  private final Book _book;
  public DefaultDependencyTracker(Book book) {
    _book = book;
  }
 
  @Override
  public ValueEval postProcessValueEval(OperationEvaluationContext ec, ValueEval opResult, boolean eval) {
    if (eval && opResult instanceof NameEval) {
      return ErrorEval.NAME_INVALID;
    }
    return opResult;
  }
 
  protected CellRefImpl prepareSrcRef(OperationEvaluationContext ec) {
    final XelContext ctx = XelContextHolder.getXelContext();
    CellRefImpl srcRef = null;
    boolean isOld = false;
    final String srcSheetName = ec.getSheetName();
    final int srcRow = ec.getRowIndex();
    final int srcCol = ec.getColumnIndex();
    final RefBook srcRefBook = BookHelper.getOrCreateRefBook(_book);
    final RefSheet srcRefSheet = srcRefBook.getOrCreateRefSheet(srcSheetName);
    if (ctx != null) {
      final String srcRefKey = srcRefBook.getBookName()+"]"+srcSheetName+"!"+new CellReference(srcRow, srcCol).formatAsString();
      final Object[] refs = (Object[]) ctx.getAttribute(srcRefKey);
      if (refs != null) {
        srcRef = (CellRefImpl) refs[0];
        isOld = ((Boolean)refs[1]).booleanValue();
      } else {
        srcRef = (CellRefImpl) srcRefSheet.getRef(srcRow, srcCol, srcRow, srcCol);
        if (srcRef == null) { // a new evaluated one
          srcRef = (CellRefImpl) srcRefSheet.getOrCreateRef(srcRow, srcCol, srcRow, srcCol);
        } else {
          isOld = !srcRef.getPrecedents().isEmpty();
        }
        ctx.setAttribute(srcRefKey, new Object[] {srcRef, Boolean.valueOf(isOld)});
      }
      if (isOld) { //an old src ref, no need to add dependency
        return null;
      }
    } else {
      srcRef = (CellRefImpl) srcRefSheet.getOrCreateRef(srcRow, srcCol, srcRow, srcCol);
    }
    return srcRef;
  }
   
  private void myAddDependency(CellRefImpl srcRef, String refBookname,
    String refSheetname, String refLastSheetName, int tRow, int lCol, int bRow, int rCol) {
    if ("#REF".equals(refSheetname) || "#REF".equals(refLastSheetName)) { //handle refer to deleted sheet
      return;
    }
    final Book targetBook = BookHelper.getBook(_book, refBookname);
    if (targetBook == null) {
      throw new UiException("cannot find the named book, have you add it in the Books:"+ refBookname);
    }
    final RefBook targetRefBook = BookHelper.getOrCreateRefBook(targetBook);
   
    final int s1 = targetBook.getSheetIndex(refSheetname);
    final int s2 = targetBook.getSheetIndex(refLastSheetName);
    final int sheetIndex1 = Math.min(s1, s2);
    final int sheetIndex2 = Math.max(s1, s2);
    for(int j = sheetIndex1; j <= sheetIndex2; ++j) {
      final String sheetname = targetBook.getSheetName(j);
      final RefSheet targetRefSheet = targetRefBook.getOrCreateRefSheet(sheetname);
      DependencyTrackerHelper.addDependency(srcRef, targetRefSheet, tRow, lCol, bRow, rCol);
    }
  }

  @Override
  public void addDependency(OperationEvaluationContext ec, Ptg[] ptgs) {
    boolean withIndirect = false;
    final Set<Ptg> precedents = new HashSet<Ptg>(ptgs.length);
    for(int j = 0; j < ptgs.length; ++j) {
      final Ptg ptg = ptgs[j];
      if (ptg instanceof FuncPtg) {
        if (((FuncPtg)ptg).getFunctionIndex() == FunctionMetadataRegistry.FUNCTION_INDEX_INDIRECT) {
          withIndirect = true;
          break;
        }
      } else if (ptg instanceof AreaPtgBase || ptg instanceof RefPtgBase) {
        precedents.add(ptg);
      }
    }
    final CellRefImpl srcRef = prepareSrcRef(ec);
    if (srcRef != null) {
      if (withIndirect) {
        srcRef.setWithIndirectPrecedent(true); //src ref with indirect precedent will always be evaluated, no need to handle other reference
        return;
      }
      for(Ptg ptg : precedents) {
        final WorkbookEvaluator evaluator = ec.getWorkbookEvaluator();
        final ValueEval opResult = evaluator.getEvalForPtg(ptg, ec);
        if (opResult instanceof LazyAreaEval) {
          final LazyAreaEval ae = (LazyAreaEval) opResult;
          final String refBookName = ae.getBookName();
          final String refSheetName = ae.getSheetName();
          final String refLastSheetName = ae.getLastSheetName();
          final int tRow = ae.getFirstRow();
          final int lCol = ae.getFirstColumn();
          final int bRow = ae.getLastRow();
          final int rCol = ae.getLastColumn();
         
          myAddDependency(srcRef, refBookName, refSheetName, refLastSheetName, tRow, lCol, bRow, rCol);
        } else if (opResult instanceof LazyRefEval) {
          final LazyRefEval ae = (LazyRefEval) opResult;
          final String refBookName = ae.getBookName();
          final String refSheetName = ae.getSheetName();
          final String refLastSheetName = ae.getLastSheetName();
          final int tRow = ae.getRow();
          final int lCol = ae.getColumn();
   
          myAddDependency(srcRef, refBookName, refSheetName, refLastSheetName, tRow, lCol, tRow, lCol);
        }
      }
    }
  }
}
TOP

Related Classes of org.zkoss.poi.ss.formula.DefaultDependencyTracker

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.