Package org.pentaho.reporting.libraries.formula.util

Source Code of org.pentaho.reporting.libraries.formula.util.FormulaUtil

/*!
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software
* Foundation.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
* or from the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This program 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.
*
* Copyright (c) 2002-2013 Pentaho Corporation..  All rights reserved.
*/

package org.pentaho.reporting.libraries.formula.util;

import java.math.BigDecimal;
import java.util.LinkedHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.pentaho.reporting.libraries.base.util.ArgumentNullException;
import org.pentaho.reporting.libraries.base.util.DebugLog;
import org.pentaho.reporting.libraries.formula.DefaultFormulaContext;
import org.pentaho.reporting.libraries.formula.Formula;
import org.pentaho.reporting.libraries.formula.FormulaContext;
import org.pentaho.reporting.libraries.formula.lvalues.ContextLookup;
import org.pentaho.reporting.libraries.formula.lvalues.LValue;
import org.pentaho.reporting.libraries.formula.lvalues.StaticValue;
import org.pentaho.reporting.libraries.formula.lvalues.Term;
import org.pentaho.reporting.libraries.formula.parser.FormulaParser;
import org.pentaho.reporting.libraries.formula.parser.ParseException;

public class FormulaUtil
{
  private static final char QUOTE_CHAR = '"';

  private FormulaUtil()
  {
  }

  public static String quoteReference(final String reference)
  {
    if (reference == null)
    {
      throw new NullPointerException();
    }
    final char[] referenceChars = reference.toCharArray();
    if (isQuotingNeeded(referenceChars) == false)
    {
      return '[' + reference + ']';
    }

    return '[' + quoteString(reference) + ']';
  }

  private static boolean isQuotingNeeded(final char[] referenceChars)
  {
    if (referenceChars == null)
    {
      throw new NullPointerException();
    }
    for (int i = 0; i < referenceChars.length; i++)
    {
      final char c = referenceChars[i];
      if (Character.isJavaIdentifierPart(c) == false)
      {
        return true;
      }
    }
    return false;
  }

  public static String quoteString(final String text)
  {
    if (text == null)
    {
      return null;
    }
    final StringBuilder b = new StringBuilder(text.length());
    final char[] chars = text.toCharArray();
    b.append(QUOTE_CHAR);
    for (int i = 0; i < chars.length; i++)
    {
      final char c = chars[i];
      if (c == QUOTE_CHAR)
      {
        b.append(QUOTE_CHAR);
      }
      b.append(c);
    }
    b.append(QUOTE_CHAR);
    return b.toString();
  }

  public static String[] getReferences(final String formula) throws ParseException
  {
    if (formula == null)
    {
      throw new NullPointerException();
    }
    final String formulaExpression = extractFormula(formula);
    if (formulaExpression == null)
    {
      throw new ParseException("Formula is invalid");
    }
    return getReferences(new Formula(formulaExpression));
  }

  public static String[] getReferences(final Formula formula)
  {
    if (formula == null)
    {
      throw new NullPointerException();
    }
    final LinkedHashMap<String,Boolean> map = new LinkedHashMap<String, Boolean>();
    final LValue lValue = formula.getRootReference();
    collectReferences(lValue, map);
    return map.keySet().toArray(new String[map.size()]);
  }

  private static void collectReferences(final LValue lval, final LinkedHashMap<String,Boolean> map)
  {
    if (lval instanceof Term)
    {
      final Term t = (Term) lval;
      final LValue[] childValues = t.getChildValues();
      for (int i = 0; i < childValues.length; i++)
      {
        final LValue childValue = childValues[i];
        collectReferences(childValue, map);
      }
    }
    else if (lval instanceof ContextLookup)
    {
      final ContextLookup cl = (ContextLookup) lval;
      map.put(cl.getName(), Boolean.TRUE);
    }
  }

  public static String extractFormula(final String formula)
  {
    String[] strings = extractFormulaContext(formula);
    return strings[1];
  }

  public static String extractStaticTextFromFormula(final String formula)
  {
    if (formula == null)
    {
      return null;
    }
    final String formulaFragment = extractFormula(formula);
    return extractStaticTextFromFormulaFragment(formulaFragment);
  }

  public static String extractStaticTextFromFormulaFragment(final String formula)
  {
    if (formula == null)
    {
      return null;
    }
    try
    {
      final FormulaParser parser = new FormulaParser();
      final LValue lValue = parser.parse(formula);
      if (lValue.isConstant())
      {
        if (lValue instanceof StaticValue)
        {
          final StaticValue staticValue = (StaticValue) lValue;
          final Object o = staticValue.getValue();
          if (o == null)
          {
            return null; // NON-NLS
          }
          return String.valueOf(o);
        }
      }
      return null; // NON-NLS
    }
    catch (Exception e)
    {
      return null; // NON-NLS
    }
  }

  public static boolean isValidFormulaFragment(final String formula)
  {
    try
    {
      final FormulaParser parser = new FormulaParser();
      final LValue lValue = parser.parse(formula);
      return true;
    }
    catch (Exception e)
    {
      return false;
    }
  }

  public static String createCellUITextFromFormula(final String formula)
  {
    return createCellUITextFromFormula(formula, new DefaultFormulaContext());
  }

  public static String createCellUITextFromFormula(final String formula, final FormulaContext context)
  {
    try
    {
      final FormulaParser parser = new FormulaParser();
      final LValue lValue = parser.parse(formula);
      lValue.initialize(context);

      if (lValue.isConstant())
      {
        if (lValue instanceof StaticValue)
        {
          final StaticValue staticValue = (StaticValue) lValue;
          final Object o = staticValue.getValue();
          if (o == null)
          {
            return "=NA()"; // NON-NLS
          }
          return String.valueOf(o);
        }
      }
      else if (lValue instanceof ContextLookup)
      {
        ContextLookup l = (ContextLookup) lValue;
        return l.toString();
      }

      final String cellText = formula;
      return cellText.startsWith("=") ? cellText : "=" + cellText;
    }
    catch (Exception e)
    {
      e.printStackTrace();
      return formula;
    }
  }

  public static String createEditorTextFromFormula(final String formula,
                                                   final FormulaContext formulaContext)
  {
    ArgumentNullException.validate("fomulaContext", formulaContext);

    try
    {
      final FormulaParser parser = new FormulaParser();
      final LValue lValue = parser.parse(formula);
      lValue.initialize(formulaContext);
      if (lValue.isConstant())
      {
        if (lValue instanceof StaticValue)
        {
          final StaticValue staticValue = (StaticValue) lValue;
          final Object o = staticValue.getValue();
          if (o == null)
          {
            return "=NA()";
          }
          if (o instanceof Number)
          {
            return String.valueOf(o);
          }
          return '\'' + String.valueOf(o);
        }
      }

      final String cellText = formula;
      return cellText.startsWith("=") ? cellText : "=" + cellText;
    }
    catch (Exception e)
    {
      return "'" + formula;
    }
  }

  /**
   * Creates a formula fragment from the given UI text. Within the reporting engine, the fragment
   * must be prefixed with a formula-context selector.
   * <p/>
   * The input follows the Excel/OpenOffice Calc rules: A leading equals indicates a formula, a
   * leading apostrophe indicates a text. Otherwise, if the input is parsable as number it will
   * be formed into a formula that returns that static number, and everything else will be treated
   * as text.
   * <p/>
   * Note that there is no syntax check for formula input - if the user writes garbage after the
   * formula selector, this garbage will still be treated as formula.
   *
   * @param formula the input from the user.
   * @return the normalized formula.
   */
  public static String createFormulaFromUIText(final String formula)
  {
    if (formula.startsWith("="))
    {
      // it is a formula ...
      return formula.substring(1);
    }
    try
    {
      final BigDecimal bd = new BigDecimal(formula.trim());
      return formula.trim();
    }
    catch (NumberFormatException nfe)
    {
      // ignore ..
    }

    if (formula.startsWith("\'"))
    {
      // is a explicit text ..
      return FormulaUtil.quoteString(formula.substring(1));
    }

    return FormulaUtil.quoteString(formula);
  }

  public static String[] extractFormulaContext(String formula)
  {
    String formulaNamespace;
    String formulaExpression;
    if (formula == null)
    {
      formulaNamespace = null;
      formulaExpression = null;
    }
    else
    {
      if (formula.endsWith(";"))
      {
        DebugLog.log("A formula with a trailing semicolon is not valid. Auto-correcting the formula.");
        formula = formula.substring(0, formula.length() - 1);
      }

      Pattern pattern = Pattern.compile("^((\\w+):|=)(.*)");
      Matcher matcher = pattern.matcher(formula);
      if (matcher.matches())
      {
        formulaNamespace = matcher.group(2);
        if (formulaNamespace == null)
        {
          formulaNamespace = "report";
        }
        formulaExpression = matcher.group(3);
      }
      else
      {
        formulaNamespace = null;
        formulaExpression = null;
      }
    }
    return new String[] { formulaNamespace, formulaExpression};
  }
}
TOP

Related Classes of org.pentaho.reporting.libraries.formula.util.FormulaUtil

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.