1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 #include "oox/xls/ooxformulaparser.hxx" 29 30 #include <com/sun/star/uno/XComponentContext.hpp> 31 #include "oox/xls/formulaparser.hxx" 32 33 namespace oox { 34 namespace xls { 35 36 // ============================================================================ 37 38 using namespace ::com::sun::star::lang; 39 using namespace ::com::sun::star::sheet; 40 using namespace ::com::sun::star::table; 41 using namespace ::com::sun::star::uno; 42 43 using ::rtl::OUString; 44 45 // ============================================================================ 46 47 class OOXMLFormulaParserImpl : private FormulaFinalizer 48 { 49 public: 50 explicit OOXMLFormulaParserImpl( const Reference< XMultiServiceFactory >& rxModelFactory ); 51 52 Sequence< FormulaToken > parseFormula( const OUString& rFormula, const CellAddress& rReferencePos ); 53 54 protected: 55 virtual const FunctionInfo* resolveBadFuncName( const OUString& rTokenData ) const; 56 57 private: 58 ApiParserWrapper maApiParser; 59 }; 60 61 // ---------------------------------------------------------------------------- 62 63 OOXMLFormulaParserImpl::OOXMLFormulaParserImpl( const Reference< XMultiServiceFactory >& rxModelFactory ) : 64 FormulaFinalizer( OpCodeProvider( rxModelFactory, FILTER_OOXML, BIFF_UNKNOWN, true ) ), 65 maApiParser( rxModelFactory, *this ) 66 { 67 } 68 69 Sequence< FormulaToken > OOXMLFormulaParserImpl::parseFormula( const OUString& rFormula, const CellAddress& rReferencePos ) 70 { 71 return finalizeTokenArray( maApiParser.parseFormula( rFormula, rReferencePos ) ); 72 } 73 74 const FunctionInfo* OOXMLFormulaParserImpl::resolveBadFuncName( const OUString& rTokenData ) const 75 { 76 /* Try to parse calls to library functions. The format of such a function 77 call is assumed to be 78 "'<path-to-office-install>\Library\<libname>'!<funcname>". */ 79 80 // the string has to start with an apostroph (followed by the library URL) 81 if( (rTokenData.getLength() >= 6) && (rTokenData[ 0 ] == '\'') ) 82 { 83 // library URL and function name are separated by an exclamation mark 84 sal_Int32 nExclamPos = rTokenData.lastIndexOf( '!' ); 85 if( (1 < nExclamPos) && (nExclamPos + 1 < rTokenData.getLength()) && (rTokenData[ nExclamPos - 1 ] == '\'') ) 86 { 87 // find the last backslash that separates library path and name 88 sal_Int32 nFileSep = rTokenData.lastIndexOf( '\\', nExclamPos - 2 ); 89 if( nFileSep > 1 ) 90 { 91 // find preceding backslash that separates the last directory name 92 sal_Int32 nDirSep = rTokenData.lastIndexOf( '\\', nFileSep - 1 ); 93 // function library is located in a directory called 'library' 94 if( (nDirSep > 0) && rTokenData.matchIgnoreAsciiCaseAsciiL( RTL_CONSTASCII_STRINGPARAM( "\\LIBRARY\\" ), nDirSep ) ) 95 { 96 // try to find a function info for the function name 97 OUString aFuncName = rTokenData.copy( nExclamPos + 1 ).toAsciiUpperCase(); 98 const FunctionInfo* pFuncInfo = getFuncInfoFromOoxFuncName( aFuncName ); 99 if( pFuncInfo && (pFuncInfo->meFuncLibType != FUNCLIB_UNKNOWN) ) 100 { 101 // check that the name of the library matches 102 OUString aLibName = rTokenData.copy( nFileSep + 1, nExclamPos - nFileSep - 2 ); 103 if( pFuncInfo->meFuncLibType == getFuncLibTypeFromLibraryName( aLibName ) ) 104 return pFuncInfo; 105 } 106 } 107 } 108 } 109 } 110 return 0; 111 } 112 113 // ============================================================================ 114 115 class OOXMLFormulaPrinterImpl : public OpCodeProvider 116 { 117 public: 118 explicit OOXMLFormulaPrinterImpl( const Reference< XMultiServiceFactory >& rxModelFactory ); 119 120 private: 121 ApiParserWrapper maApiParser; 122 }; 123 124 // ---------------------------------------------------------------------------- 125 126 OOXMLFormulaPrinterImpl::OOXMLFormulaPrinterImpl( const Reference< XMultiServiceFactory >& rxModelFactory ) : 127 OpCodeProvider( rxModelFactory, FILTER_OOXML, BIFF_UNKNOWN, false ), 128 maApiParser( rxModelFactory, *this ) 129 { 130 } 131 132 // ============================================================================ 133 134 Sequence< OUString > OOXMLFormulaParser_getSupportedServiceNames() 135 { 136 Sequence< OUString > aServiceNames( 1 ); 137 aServiceNames[ 0 ] = CREATE_OUSTRING( "com.sun.star.sheet.FilterFormulaParser" ); 138 return aServiceNames; 139 } 140 141 OUString OOXMLFormulaParser_getImplementationName() 142 { 143 return CREATE_OUSTRING( "com.sun.star.comp.oox.xls.FormulaParser" ); 144 } 145 146 Reference< XInterface > SAL_CALL OOXMLFormulaParser_createInstance( const Reference< XComponentContext >& ) throw( Exception ) 147 { 148 return static_cast< ::cppu::OWeakObject* >( new OOXMLFormulaParser ); 149 } 150 151 // ============================================================================ 152 153 OOXMLFormulaParser::OOXMLFormulaParser() 154 { 155 } 156 157 OOXMLFormulaParser::~OOXMLFormulaParser() 158 { 159 } 160 161 // com.sun.star.lang.XServiceInfo interface ----------------------------------- 162 163 OUString SAL_CALL OOXMLFormulaParser::getImplementationName() throw( RuntimeException ) 164 { 165 return OOXMLFormulaParser_getImplementationName(); 166 } 167 168 sal_Bool SAL_CALL OOXMLFormulaParser::supportsService( const OUString& rService ) throw( RuntimeException ) 169 { 170 const Sequence< OUString > aServices( OOXMLFormulaParser_getSupportedServiceNames() ); 171 const OUString* pArray = aServices.getConstArray(); 172 const OUString* pArrayEnd = pArray + aServices.getLength(); 173 return ::std::find( pArray, pArrayEnd, rService ) != pArrayEnd; 174 } 175 176 Sequence< OUString > SAL_CALL OOXMLFormulaParser::getSupportedServiceNames() throw( RuntimeException ) 177 { 178 return OOXMLFormulaParser_getSupportedServiceNames(); 179 } 180 181 // com.sun.star.lang.XInitialization interface -------------------------------- 182 183 void SAL_CALL OOXMLFormulaParser::initialize( const Sequence< Any >& rArgs ) throw( Exception, RuntimeException ) 184 { 185 OSL_ENSURE( rArgs.hasElements(), "OOXMLFormulaParser::initialize - missing arguments" ); 186 if( !rArgs.hasElements() ) 187 throw RuntimeException(); 188 mxComponent.set( rArgs[ 0 ], UNO_QUERY_THROW ); 189 } 190 191 // com.sun.star.sheet.XFilterFormulaParser interface -------------------------- 192 193 OUString SAL_CALL OOXMLFormulaParser::getSupportedNamespace() throw( RuntimeException ) 194 { 195 return CREATE_OUSTRING( "http://schemas.microsoft.com/office/excel/formula" ); 196 } 197 198 // com.sun.star.sheet.XFormulaParser interface -------------------------------- 199 200 Sequence< FormulaToken > SAL_CALL OOXMLFormulaParser::parseFormula( 201 const OUString& rFormula, const CellAddress& rReferencePos ) throw( RuntimeException ) 202 { 203 if( !mxParserImpl ) 204 { 205 Reference< XMultiServiceFactory > xModelFactory( mxComponent, UNO_QUERY_THROW ); 206 mxParserImpl.reset( new OOXMLFormulaParserImpl( xModelFactory ) ); 207 } 208 return mxParserImpl->parseFormula( rFormula, rReferencePos ); 209 } 210 211 OUString SAL_CALL OOXMLFormulaParser::printFormula( 212 const Sequence< FormulaToken >& /*rTokens*/, const CellAddress& /*rReferencePos*/ ) throw( RuntimeException ) 213 { 214 // not implemented 215 throw RuntimeException(); 216 } 217 218 // ============================================================================ 219 220 } // namespace xls 221 } // namespace oox 222