Package org.formulacompiler.spreadsheet.internal.excel.xlsx.saver

Source Code of org.formulacompiler.spreadsheet.internal.excel.xlsx.saver.ExpressionFormatter

/*
* Copyright (c) 2006-2009 by Abacus Research AG, Switzerland.
* All rights reserved.
*
* This file is part of the Abacus Formula Compiler (AFC).
*
* For commercial licensing, please contact sales(at)formulacompiler.com.
*
* AFC is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AFC 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AFC.  If not, see <http://www.gnu.org/licenses/>.
*/

package org.formulacompiler.spreadsheet.internal.excel.xlsx.saver;

import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.formulacompiler.compiler.Function;
import org.formulacompiler.compiler.Operator;
import org.formulacompiler.compiler.internal.Duration;
import org.formulacompiler.compiler.internal.LocalDate;
import org.formulacompiler.compiler.internal.expressions.ExpressionNode;
import org.formulacompiler.compiler.internal.expressions.ExpressionNodeForConstantValue;
import org.formulacompiler.compiler.internal.expressions.ExpressionNodeForFunction;
import org.formulacompiler.compiler.internal.expressions.ExpressionNodeForOperator;
import org.formulacompiler.runtime.New;
import org.formulacompiler.spreadsheet.Spreadsheet.Range;
import org.formulacompiler.spreadsheet.internal.CellIndex;
import org.formulacompiler.spreadsheet.internal.ExpressionNodeForCell;
import org.formulacompiler.spreadsheet.internal.ExpressionNodeForRange;
import org.formulacompiler.spreadsheet.internal.ExpressionNodeForRangeIntersection;
import org.formulacompiler.spreadsheet.internal.ExpressionNodeForRangeUnion;


/**
* @author Igor Didyuk
*/
class ExpressionFormatter
{
  private static final Set<Operator> COMMUTATIVE_OPERATORS = New.set();
  private static final char QUOTE = '\'';
  private static final char SHEET_NAME_SEPARATOR = '!';
  private static final char RANGE_SEPARATOR = ':';

  static {
    COMMUTATIVE_OPERATORS.add( Operator.CONCAT );
    COMMUTATIVE_OPERATORS.add( Operator.PLUS );
    COMMUTATIVE_OPERATORS.add( Operator.TIMES );
  }

  public static String format( ExpressionNode _expr, CellIndex _baseCell )
  {
    final StringBuilder stringBuilder = new StringBuilder();
    append( stringBuilder, _expr, _baseCell, null );
    return stringBuilder.toString();
  }

  public static String format( Range _range, int _sheetIndex )
  {
    final StringBuilder sb = new StringBuilder();
    appendRangeRef( sb, _range, _sheetIndex );
    return sb.toString();
  }

  private static void appendRangeRef( final StringBuilder _sb, final Range _range, final int _sheetIndex )
  {
    final CellIndex cellFrom = (CellIndex) _range.getTopLeft();
    final CellIndex cellTo = (CellIndex) _range.getBottomRight();
    if (_sheetIndex != cellFrom.getSheetIndex() || _sheetIndex != cellTo.getSheetIndex()) {
      if (cellFrom.getSheetIndex() != cellTo.getSheetIndex()) {
        final String fromSheetName = cellFrom.getSheet().getName();
        final String toSheetName = cellTo.getSheet().getName();
        final boolean quoted = needsQuotes( fromSheetName ) || needsQuotes( toSheetName );
        if (quoted) _sb.append( QUOTE );
        _sb.append( escapeSheetName( fromSheetName ) );
        _sb.append( RANGE_SEPARATOR );
        _sb.append( escapeSheetName( toSheetName ) );
        if (quoted) _sb.append( QUOTE );
      }
      else {
        final String sheetName = cellFrom.getSheet().getName();
        final boolean quoted = needsQuotes( sheetName );
        if (quoted) _sb.append( QUOTE );
        _sb.append( escapeSheetName( sheetName ) );
        if (quoted) _sb.append( QUOTE );
      }
      _sb.append( SHEET_NAME_SEPARATOR );
    }
    CellIndex.appendNameA1ForCellIndex( _sb, cellFrom );
    if (cellFrom.getColumnIndex() != cellTo.getColumnIndex() ||
        cellFrom.getRowIndex() != cellTo.getRowIndex()) {
      _sb.append( RANGE_SEPARATOR );
      CellIndex.appendNameA1ForCellIndex( _sb, cellTo );
    }
  }

  private static String escapeSheetName( String _sheetName )
  {
    return _sheetName.replaceAll( "'", "''" );
  }

  private static boolean needsQuotes( String _sheetName )
  {
    for (int i = 0; i < _sheetName.length(); i++) {
      final char ch = _sheetName.charAt( i );
      if (!Character.isLetterOrDigit( _sheetName.charAt( i ) ) && ch != '_') return true;
    }
    return false;
  }

  private static void append( StringBuilder _stringBuilder, ExpressionNode _expr, CellIndex _baseCell, Operator _context )
  {
    if (_expr instanceof ExpressionNodeForConstantValue) {
      final Object constantValue = _expr.getConstantValue();
      if (constantValue instanceof Boolean) {
        _stringBuilder.append( ((Boolean) constantValue).booleanValue() ? "TRUE" : "FALSE" );
      }
      else if (constantValue instanceof Date) {
        throw new IllegalArgumentException( "Saving dates is not supported." );
      }
      else if (constantValue instanceof LocalDate) {
        final LocalDate localDate = (LocalDate) constantValue;
        _stringBuilder.append( localDate.doubleValue() );
      }
      else if (constantValue instanceof Duration) {
        final Duration duration = (Duration) constantValue;
        _stringBuilder.append( duration.doubleValue() );
      }
      else if (constantValue instanceof Number) {
        _stringBuilder.append( constantValue.toString() );
      }
      else if (constantValue instanceof String) {
        _stringBuilder.append( '"' );
        final String str = (String) constantValue;
        _stringBuilder.append( str.replaceAll( "\"", "\"\"" ) );
        _stringBuilder.append( '"' );
      }

    }
    else if (_expr instanceof ExpressionNodeForOperator) {
      final Operator operator = ((ExpressionNodeForOperator) _expr).getOperator();
      final List<ExpressionNode> arguments = _expr.arguments();
      final int argCount = arguments.size();
      final boolean parenthesesNeeded = _context != null &&
          !(operator.equals( _context ) && COMMUTATIVE_OPERATORS.contains( operator ));
      switch (argCount) {
        case 0:
          _stringBuilder.append( operator.getSymbol() );
          break;
        case 1:
          if (parenthesesNeeded) _stringBuilder.append( '(' );
          final boolean isPrefix = operator.isPrefix();
          if (isPrefix) _stringBuilder.append( operator.getSymbol() );
          append( _stringBuilder, arguments.get( 0 ), _baseCell, operator );
          if (!isPrefix) _stringBuilder.append( operator.getSymbol() );
          if (parenthesesNeeded) _stringBuilder.append( ')' );
          break;
        default:
          if (parenthesesNeeded) _stringBuilder.append( '(' );
          appendArguments( _stringBuilder, arguments, operator.getSymbol(), _baseCell, operator );
          if (parenthesesNeeded) _stringBuilder.append( ')' );
          break;
      }
    }
    else if (_expr instanceof ExpressionNodeForFunction) {
      final Function function = ((ExpressionNodeForFunction) _expr).getFunction();
      _stringBuilder.append( function );
      _stringBuilder.append( '(' );
      final List<ExpressionNode> argList = _expr.arguments();
      appendArguments( _stringBuilder, argList, ",", _baseCell, null );
      _stringBuilder.append( ')' );
    }
    else if (_expr instanceof ExpressionNodeForCell) {
      final ExpressionNodeForCell expressionNodeForCell = (ExpressionNodeForCell) _expr;
      final String name = expressionNodeForCell.getName();
      if (name != null) {
        _stringBuilder.append( name );
      }
      else {
        _stringBuilder.append( expressionNodeForCell.toString() );
      }
    }
    else if (_expr instanceof ExpressionNodeForRange) {
      final ExpressionNodeForRange expressionNodeForRange = (ExpressionNodeForRange) _expr;
      final String name = expressionNodeForRange.getName();
      if (name != null) {
        _stringBuilder.append( name );
      }
      else {
        appendRangeRef( _stringBuilder, expressionNodeForRange.getRange(), _baseCell.getSheetIndex() );
      }
    }
    else if (_expr instanceof ExpressionNodeForRangeIntersection) {
      final List<ExpressionNode> arguments = _expr.arguments();
      appendArguments( _stringBuilder, arguments, " ", _baseCell, null );
    }
    else if (_expr instanceof ExpressionNodeForRangeUnion) {
      final List<ExpressionNode> arguments = _expr.arguments();
      appendArguments( _stringBuilder, arguments, ";", _baseCell, null );
    }
    else {
      throw new IllegalArgumentException( "Cannot format " + _expr );
    }
  }

  private static void appendArguments( final StringBuilder _stringBuilder, final List<ExpressionNode> _argList, final String _separator, final CellIndex _baseCell, Operator _context )
  {
    final Iterator<ExpressionNode> argIterator = _argList.iterator();
    if (argIterator.hasNext()) {
      append( _stringBuilder, argIterator.next(), _baseCell, _context );
    }
    while (argIterator.hasNext()) {
      _stringBuilder.append( _separator );
      append( _stringBuilder, argIterator.next(), _baseCell, _context );
    }
  }
}
TOP

Related Classes of org.formulacompiler.spreadsheet.internal.excel.xlsx.saver.ExpressionFormatter

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.