summaryrefslogtreecommitdiff
path: root/reportbuilder/java/com/sun/star/report/pentaho/SOFormulaParser.java
diff options
context:
space:
mode:
authorOliver Bolte <obo@openoffice.org>2009-03-04 15:27:10 +0000
committerOliver Bolte <obo@openoffice.org>2009-03-04 15:27:10 +0000
commit9544c14f4a931d8d8b2e66a6cb87fb53d4505cd4 (patch)
tree29b05df340e2c19c9e60947d63bf7b425cfb95c2 /reportbuilder/java/com/sun/star/report/pentaho/SOFormulaParser.java
parent4f4fe6aa7203aac35a774108f4880553df5b93a4 (diff)
CWS-TOOLING: integrate CWS rptfix04
2009-02-23 01:59:54 +0100 rene r268341 : #i10000# fix system-jfreereport build 2009-02-13 10:17:16 +0100 oj r267696 : #i98549# integrate zip form pentaho package 2009-02-03 14:48:34 +0100 oj r267330 : set formula locale to doc locale 2009-02-03 14:45:54 +0100 oj r267329 : set formula locale to doc locale 2009-02-03 11:50:03 +0100 oj r267311 : set formula locale to doc locale 2009-02-03 08:55:02 +0100 oj r267297 : unix line ends 2009-01-28 11:21:24 +0100 rene r267043 : #i98549# s/DESIGN/BUILDER/ also for Sun 2009-01-27 17:17:50 +0100 rene r267012 : merge builfix from trunk 2009-01-27 14:16:30 +0100 rene r266991 : #i10000# fix rebase which left out the whole changes in former config_office; sync variable names (s/LIB_//) and some other things 2009-01-27 10:01:09 +0100 oj r266959 : CWS-TOOLING: rebase CWS rptfix04 to trunk@266944 (milestone: DEV300:m40) 2009-01-27 08:00:16 +0100 oj r266951 : conflict in mergeinfo 2009-01-26 12:23:03 +0100 oj r266914 : #i98383# fix grouping 2009-01-23 22:03:03 +0100 rene r266852 : fix --enable-report-builder description 2009-01-23 10:37:27 +0100 oj r266778 : set escape processing when set at query 2009-01-23 09:17:16 +0100 fs r266770 : add CWS name to version 2009-01-21 13:57:35 +0100 oj r266669 : merge for build bots 2009-01-20 09:07:24 +0100 oj r266552 : CWS-TOOLING: rebase CWS rptfix04 to trunk@266428 (milestone: DEV300:m39) 2009-01-20 08:34:16 +0100 oj r266551 : rebase 2009-01-20 08:33:59 +0100 oj r266550 : rebase 2009-01-20 08:32:50 +0100 oj r266549 : rebase 2009-01-20 08:30:13 +0100 oj r266548 : rebase 2009-01-20 08:29:30 +0100 oj r266547 : rebase 2009-01-20 08:22:33 +0100 oj r266546 : merge short cuts from dba31g 2009-01-19 21:04:08 +0100 rene r266525 : #i10000# we need officecfg for component-update.dtd 2009-01-19 21:01:26 +0100 rene r266524 : #i10000# fix import 2009-01-19 20:26:20 +0100 rene r266523 : #i10000# remove svn conflicts markers; fix build 2009-01-19 14:23:56 +0100 rene r266496 : libbase depends on apache-commons.. 2009-01-19 14:00:42 +0100 oj r266495 : merge from m39 2009-01-19 12:39:00 +0100 oj r266489 : CWS-TOOLING: rebase CWS rptfix04 to trunk@266428 (milestone: DEV300:m39) 2009-01-16 11:47:04 +0100 oj r266410 : #i97560# add , between expressions 2009-01-09 17:11:38 +0100 rene r266103 : don't show "checking which Apache commons-* libs to use" when we neither build the wiki editor nor the SRB 2009-01-09 16:48:02 +0100 rene r266099 : #i10000# reportbuilder needs apache-commons 2009-01-09 15:43:35 +0100 oj r266093 : use of new nspaces 2009-01-09 15:41:34 +0100 oj r266092 : use of new nspaces 2009-01-09 14:44:15 +0100 rene r266088 : fix typo/description 2009-01-09 12:48:51 +0100 rene r266074 : #i10000# fix install 2009-01-09 11:52:53 +0100 rene r266070 : #i10000# more build fixes 2009-01-09 10:53:13 +0100 rene r266062 : #i10000# ENABLE_REPORTBUILDER also in set_soenv.in, fix typo 2009-01-09 10:40:24 +0100 rene r266060 : #i10000# configure fix for new reportbuilder module, typo fix at libfonts 2009-01-09 10:01:52 +0100 rene r266055 : #i10000# adapt to current configure.in 2009-01-09 09:59:32 +0100 oj r266054 : add new pentaho jars 2009-01-09 09:47:54 +0100 oj r266049 : merge changes from DEV300_m39 2009-01-09 09:14:08 +0100 oj r266048 : merge from DEV300_m39 2009-01-09 08:28:43 +0100 oj r266045 : merge changes from dba31g 2009-01-09 07:58:10 +0100 oj r266044 : replace JCOMMON with LIB 2009-01-08 13:42:24 +0100 oj r266005 : move ext to reportbuilder 2009-01-08 13:41:38 +0100 oj r266004 : add dep for license 2009-01-08 13:27:56 +0100 oj r266001 : new module for Sun report Builder extension 2009-01-07 12:58:13 +0100 oj r265960 : CWS-TOOLING: rebase CWS rptfix04 to trunk@265758 (milestone: DEV300:m38) 2008-12-15 13:47:18 +0100 oj r265481 : new pentaho resources 2008-12-15 10:04:01 +0100 oj r265462 : integrate new pentaho sources 2008-12-15 10:02:54 +0100 oj r265461 : #i96888# fix date time function 2008-12-12 09:23:29 +0100 oj r265389 : #97174# check of res < 0 removed 2008-12-12 09:15:54 +0100 oj r265388 : #i9716# fix for DayFunction 2008-12-11 12:24:24 +0100 oj r265281 : integrate new pentaho sources 2008-12-11 11:49:16 +0100 oj r265273 : integrate new pentaho sources 2008-12-11 09:34:07 +0100 oj r265248 : integrate new pentaho sources 2008-12-10 18:58:06 +0100 oj r265227 : introduce new pentaho sources 2008-12-10 18:56:43 +0100 oj r265226 : introduce new pentaho sources 2008-12-10 18:54:26 +0100 oj r265225 : introduce new pentaho sources 2008-12-10 18:42:59 +0100 oj r265221 : introduce new pentaho sources 2008-12-10 17:24:23 +0100 oj r265212 : introduce new pentaho sources 2008-12-10 17:24:07 +0100 oj r265211 : new pentaho sources 2008-12-10 17:23:00 +0100 oj r265210 : introduce new pentaho sources
Diffstat (limited to 'reportbuilder/java/com/sun/star/report/pentaho/SOFormulaParser.java')
-rw-r--r--reportbuilder/java/com/sun/star/report/pentaho/SOFormulaParser.java429
1 files changed, 429 insertions, 0 deletions
diff --git a/reportbuilder/java/com/sun/star/report/pentaho/SOFormulaParser.java b/reportbuilder/java/com/sun/star/report/pentaho/SOFormulaParser.java
new file mode 100644
index 000000000000..26a454cab9aa
--- /dev/null
+++ b/reportbuilder/java/com/sun/star/report/pentaho/SOFormulaParser.java
@@ -0,0 +1,429 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: SOFormulaParser.java,v $
+ *
+ * $Revision: 1.7 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+package com.sun.star.report.pentaho;
+
+import com.sun.star.lang.XServiceInfo;
+import com.sun.star.sheet.XFormulaOpCodeMapper;
+import com.sun.star.uno.Exception;
+import com.sun.star.uno.XComponentContext;
+import com.sun.star.lib.uno.helper.ComponentBase;
+import com.sun.star.uno.Type;
+import com.sun.star.lib.uno.helper.PropertySetMixin;
+import com.sun.star.sheet.FormulaLanguage;
+import com.sun.star.sheet.FormulaMapGroup;
+import com.sun.star.sheet.FormulaMapGroupSpecialOffset;
+import com.sun.star.sheet.FormulaOpCodeMapEntry;
+import com.sun.star.sheet.FormulaToken;
+import com.sun.star.uno.Any;
+import com.sun.star.uno.UnoRuntime;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Vector;
+import org.pentaho.reporting.libraries.formula.DefaultFormulaContext;
+import org.pentaho.reporting.libraries.formula.function.FunctionRegistry;
+import org.pentaho.reporting.libraries.formula.parser.FormulaParser;
+import org.pentaho.reporting.libraries.formula.parser.GeneratedFormulaParserConstants;
+import org.pentaho.reporting.libraries.formula.parser.GeneratedFormulaParserTokenManager;
+import org.pentaho.reporting.libraries.formula.parser.JavaCharStream;
+import org.pentaho.reporting.libraries.formula.parser.ParseException;
+import org.pentaho.reporting.libraries.formula.parser.Token;
+import org.pentaho.reporting.libraries.formula.parser.TokenMgrError;
+import org.pentaho.reporting.libraries.base.config.Configuration;
+
+public final class SOFormulaParser extends ComponentBase
+ implements com.sun.star.report.meta.XFormulaParser, XServiceInfo
+{
+
+ public static final int SEPARATORS = 0;
+ public static final int ARRAY_SEPARATORS = 1;
+ public static final int UNARY_OPERATORS = 2;
+ public static final int BINARY_OPERATORS = 3;
+ public static final int FUNCTIONS = 4;
+ private final XComponentContext m_xContext;
+ private final PropertySetMixin m_prophlp;
+ private static final String __serviceName = "com.sun.star.report.meta.FormulaParser";
+ private static final String OPERATORS = "org.pentaho.reporting.libraries.formula.operators.";
+
+ // attributes
+ final private List m_OpCodeMap = new ArrayList();
+ private XFormulaOpCodeMapper formulaOpCodeMapper = null;
+ private final Map parserAllOpCodes = new HashMap();
+ private final Map parserNames = new HashMap();
+ private final Map[] groupOpCodes = new HashMap[5];
+ private final Vector specialOpCodes = new Vector();
+
+ public Vector getSpecialOpCodes()
+ {
+ return specialOpCodes;
+ }
+ private int ownTokenCounter = 1000;
+ private final FormulaOpCodeMapEntry opCodePush;
+ private final FormulaParser parser;
+
+ public SOFormulaParser(XComponentContext context)
+ {
+
+ m_xContext = context;
+ final ClassLoader cl = java.lang.Thread.currentThread().getContextClassLoader();
+ Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
+
+ parser = new FormulaParser();
+ try
+ {
+ final XFormulaOpCodeMapper mapper = (XFormulaOpCodeMapper) UnoRuntime.queryInterface(XFormulaOpCodeMapper.class, m_xContext.getServiceManager().createInstanceWithContext("simple.formula.FormulaOpCodeMapperObj", m_xContext));
+ FormulaOpCodeMapEntry[] opCodes = mapper.getAvailableMappings(FormulaLanguage.ODFF, FormulaMapGroup.FUNCTIONS);
+ final DefaultFormulaContext defaultContext = new DefaultFormulaContext();
+ final FunctionRegistry functionRegistry = defaultContext.getFunctionRegistry();
+
+ String[] names = functionRegistry.getFunctionNames();
+ addOpCodes(names, opCodes, FUNCTIONS);
+ names = getOperators(defaultContext, OPERATORS);
+ opCodes = mapper.getAvailableMappings(FormulaLanguage.ODFF, FormulaMapGroup.UNARY_OPERATORS);
+ addOpCodes(names, opCodes, UNARY_OPERATORS);
+ opCodes = mapper.getAvailableMappings(FormulaLanguage.ODFF, FormulaMapGroup.BINARY_OPERATORS);
+ addOpCodes(names, opCodes, BINARY_OPERATORS);
+
+ names = GeneratedFormulaParserConstants.tokenImage.clone();
+ for (int i = 0; i < names.length; i++)
+ {
+ final String token = names[i];
+ if ( token != null && token.length() > 0 && token.charAt(0) == '"' )
+ {
+ names[i] = token.substring(1, token.length() - 1);
+ }
+ }
+ opCodes = mapper.getAvailableMappings(FormulaLanguage.ODFF, FormulaMapGroup.SEPARATORS);
+ addOpCodes(names, opCodes, SEPARATORS, false);
+
+ opCodes = mapper.getAvailableMappings(FormulaLanguage.ODFF, FormulaMapGroup.ARRAY_SEPARATORS);
+ addOpCodes(names, opCodes, ARRAY_SEPARATORS, false);
+
+ opCodes = mapper.getAvailableMappings(FormulaLanguage.ODFF, FormulaMapGroup.SPECIAL);
+ names = new String[opCodes.length];
+
+ for (int i = 0; i < opCodes.length; i++)
+ {
+ final FormulaOpCodeMapEntry opCode = opCodes[i];
+ parserAllOpCodes.put(opCode.Token.OpCode, opCode);
+ specialOpCodes.add(opCode);
+ }
+ // addOpCodes(names, opCodes,SPECIAL,false);
+ } catch ( Exception ex )
+ {
+ ex.printStackTrace();
+ }
+ opCodePush = (FormulaOpCodeMapEntry) specialOpCodes.get(FormulaMapGroupSpecialOffset.PUSH);
+ Thread.currentThread().setContextClassLoader(cl);
+ // use the last parameter of the PropertySetMixin constructor
+ // for your optional attributes if necessary. See the documentation
+ // of the PropertySetMixin helper for further information.
+ // Ensure that your attributes are initialized correctly!
+ m_prophlp = new PropertySetMixin(m_xContext, this,
+ new Type(com.sun.star.report.meta.XFormulaParser.class), null);
+ }
+ ;
+
+ // com.sun.star.sheet.XFormulaParser:
+ public com.sun.star.sheet.FormulaToken[] parseFormula(String aFormula)
+ {
+ final ArrayList tokens = new ArrayList();
+ if ( !"=".equals(aFormula) )
+ {
+ String formula;
+ if ( aFormula.charAt(0) == '=' )
+ formula = aFormula.substring(1);
+ else
+ formula = aFormula;
+ final ArrayList images = new ArrayList();
+ try
+ {
+ int brackets = 0;
+ final GeneratedFormulaParserTokenManager tokenParser = new GeneratedFormulaParserTokenManager(new JavaCharStream(new StringReader(formula), 1, 1));
+ Token token = tokenParser.getNextToken();
+ while (token.kind != GeneratedFormulaParserConstants.EOF)
+ {
+ final FormulaToken formulaToken;
+ images.add(token.image);
+ final String upper = token.image.toUpperCase();
+ if ( parserNames.containsKey(upper) )
+ {
+ if ( token.image.equals("("))
+ brackets++;
+ else if ( token.image.equals(")"))
+ --brackets;
+ final FormulaOpCodeMapEntry opCode = (FormulaOpCodeMapEntry) parserNames.get(upper);
+ formulaToken = opCode.Token;
+ }
+ else if ( token.kind == GeneratedFormulaParserConstants.WHITESPACE )
+ {
+ final FormulaOpCodeMapEntry opCode = (FormulaOpCodeMapEntry) specialOpCodes.get(FormulaMapGroupSpecialOffset.SPACES);
+ formulaToken = opCode.Token;
+ }
+ else
+ {
+ formulaToken = new FormulaToken();
+ formulaToken.OpCode = opCodePush.Token.OpCode;
+ formulaToken.Data = new Any(Type.STRING, token.image);
+ }
+
+ tokens.add(formulaToken);
+ token = tokenParser.getNextToken();
+ }
+ if ( brackets > 0 )
+ {
+ final FormulaOpCodeMapEntry opCode = (FormulaOpCodeMapEntry) parserNames.get(")");
+ while ( brackets-- != 0 )
+ {
+ formula = formula.concat(")");
+ images.add(")");
+ tokens.add(opCode.Token);
+ }
+
+ }
+
+ parser.parse(formula);
+ } catch ( ParseException ex )
+ {
+ boolean found = false;
+ // error occured so all token must be bad
+ for (int i = 0; i < tokens.size(); i++)
+ {
+ if ( !found && images.get(i).equals(ex.currentToken.image) )
+ found = true;
+ if ( found )
+ {
+ final FormulaToken dest = new FormulaToken();
+ dest.OpCode = ((FormulaOpCodeMapEntry) specialOpCodes.get(FormulaMapGroupSpecialOffset.BAD)).Token.OpCode;
+ dest.Data = new Any(Type.STRING, images.get(i));
+ tokens.remove(i);
+ tokens.add(i, dest);
+ }
+ }
+ } catch ( java.lang.Exception e )
+ {
+ } catch ( TokenMgrError e )
+ {
+ }
+ }
+ FormulaToken[] ret = (FormulaToken[]) tokens.toArray(new FormulaToken[tokens.size()]);
+ return ret;
+ }
+
+ public String printFormula(com.sun.star.sheet.FormulaToken[] aTokens)
+ {
+ final StringBuffer ret = new StringBuffer();
+ for (int i = 0; i < aTokens.length; i++)
+ {
+ final FormulaToken formulaToken = aTokens[i];
+ if ( formulaToken.OpCode == opCodePush.Token.OpCode && !formulaToken.Data.equals(Any.VOID) )
+ {
+ ret.append(formulaToken.Data);
+ }
+ else if ( parserAllOpCodes.containsKey(formulaToken.OpCode) )
+ {
+ final FormulaOpCodeMapEntry opCode = (FormulaOpCodeMapEntry) parserAllOpCodes.get(formulaToken.OpCode);
+ if ( opCode.Name.length() > 0 )
+ ret.append(opCode.Name);
+ else if ( !formulaToken.Data.equals(Any.VOID) )
+ ret.append(formulaToken.Data);
+ }
+ }
+ return ret.toString();
+ }
+
+ // com.sun.star.beans.XPropertySet:
+ public com.sun.star.beans.XPropertySetInfo getPropertySetInfo()
+ {
+ return m_prophlp.getPropertySetInfo();
+ }
+
+ public void setPropertyValue(String aPropertyName, Object aValue) throws com.sun.star.beans.UnknownPropertyException, com.sun.star.beans.PropertyVetoException, com.sun.star.lang.IllegalArgumentException, com.sun.star.lang.WrappedTargetException
+ {
+ m_prophlp.setPropertyValue(aPropertyName, aValue);
+ }
+
+ public Object getPropertyValue(String aPropertyName) throws com.sun.star.beans.UnknownPropertyException, com.sun.star.lang.WrappedTargetException
+ {
+ return m_prophlp.getPropertyValue(aPropertyName);
+ }
+
+ public void addPropertyChangeListener(String aPropertyName, com.sun.star.beans.XPropertyChangeListener xListener) throws com.sun.star.beans.UnknownPropertyException, com.sun.star.lang.WrappedTargetException
+ {
+ m_prophlp.addPropertyChangeListener(aPropertyName, xListener);
+ }
+
+ public void removePropertyChangeListener(String aPropertyName, com.sun.star.beans.XPropertyChangeListener xListener) throws com.sun.star.beans.UnknownPropertyException, com.sun.star.lang.WrappedTargetException
+ {
+ m_prophlp.removePropertyChangeListener(aPropertyName, xListener);
+ }
+
+ public void addVetoableChangeListener(String aPropertyName, com.sun.star.beans.XVetoableChangeListener xListener) throws com.sun.star.beans.UnknownPropertyException, com.sun.star.lang.WrappedTargetException
+ {
+ m_prophlp.addVetoableChangeListener(aPropertyName, xListener);
+ }
+
+ public void removeVetoableChangeListener(String aPropertyName, com.sun.star.beans.XVetoableChangeListener xListener) throws com.sun.star.beans.UnknownPropertyException, com.sun.star.lang.WrappedTargetException
+ {
+ m_prophlp.removeVetoableChangeListener(aPropertyName, xListener);
+ }
+
+ // com.sun.star.report.meta.XFormulaParser:
+ public com.sun.star.sheet.FormulaOpCodeMapEntry[] getOpCodeMap()
+ {
+ return (com.sun.star.sheet.FormulaOpCodeMapEntry[]) m_OpCodeMap.toArray(new FormulaOpCodeMapEntry[m_OpCodeMap.size()]);
+ }
+
+ public void setOpCodeMap(com.sun.star.sheet.FormulaOpCodeMapEntry[] the_value)
+ {
+// m_prophlp.prepareSet("OpCodeMap", null);
+// synchronized (this)
+// {
+// m_OpCodeMap.clear();
+// }
+ }
+
+ public String getImplementationName()
+ {
+ return SOFormulaParser.class.getName();
+ }
+
+ public boolean supportsService(String sServiceName)
+ {
+ return sServiceName.equals(__serviceName);
+ }
+
+ public String[] getSupportedServiceNames()
+ {
+ return getServiceNames();
+ }
+
+ /**
+ * This method is a simple helper function to used in the static component initialisation functions as well as
+ * in getSupportedServiceNames.
+ */
+ public static String[] getServiceNames()
+ {
+ return new String[]
+ {
+ __serviceName
+ };
+ }
+
+ public XFormulaOpCodeMapper getFormulaOpCodeMapper()
+ {
+ if ( formulaOpCodeMapper == null )
+ {
+ formulaOpCodeMapper = new SOFormulaOpCodeMapper(m_xContext, this);
+ }
+
+ return formulaOpCodeMapper;
+ }
+
+ private void addOpCodes(String[] names, FormulaOpCodeMapEntry[] opCodes, int group)
+ {
+ addOpCodes(names, opCodes, group, true);
+ }
+
+ private void addOpCodes(String[] names, FormulaOpCodeMapEntry[] opCodes, int group, boolean add)
+ {
+ groupOpCodes[group] = new HashMap();
+ for (int j = 0; j < names.length; j++)
+ {
+ FormulaOpCodeMapEntry opCode = null;
+ int i = 0;
+ for (; i < opCodes.length; i++)
+ {
+ opCode = opCodes[i];
+ if ( names[j].equals(opCode.Name) )
+ {
+ break;
+ }
+ }
+ if ( i >= opCodes.length )
+ {
+ if ( !add )
+ continue;
+ final FormulaToken token = new FormulaToken(ownTokenCounter++, Any.VOID);
+ opCode = new FormulaOpCodeMapEntry(names[j], token);
+ }
+ parserNames.put(names[j], opCode);
+ parserAllOpCodes.put(opCode.Token.OpCode, opCode);
+ groupOpCodes[group].put(opCode.Token.OpCode, opCode);
+ }
+ }
+
+ final public Map getNames()
+ {
+ return parserNames;
+ }
+
+ final public Map getGroup(int group)
+ {
+ return groupOpCodes[group];
+ }
+
+ private String[] getOperators(DefaultFormulaContext defaultContext, final String _kind)
+ {
+ final ArrayList ops = new ArrayList();
+ final Configuration configuration = defaultContext.getConfiguration();
+ final Iterator iter = configuration.findPropertyKeys(_kind);
+ while (iter.hasNext())
+ {
+ final String configKey = (String) iter.next();
+ if ( configKey.endsWith(".class") == false )
+ {
+ continue;
+ }
+ final String operatorClass = configuration.getConfigProperty(configKey);
+ if ( operatorClass == null )
+ {
+ continue;
+ }
+ if ( operatorClass.length() == 0 )
+ {
+ continue;
+ }
+ final String tokenKey = configKey.substring(0, configKey.length() - ".class".length()) + ".token";
+ final String token = configuration.getConfigProperty(tokenKey);
+ if ( token == null )
+ {
+ continue;
+ }
+ ops.add(token.trim());
+ }
+ return (String[]) ops.toArray(new String[ops.size()]);
+ }
+}
+