19e0e4191SAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 39e0e4191SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 49e0e4191SAndrew Rist * or more contributor license agreements. See the NOTICE file 59e0e4191SAndrew Rist * distributed with this work for additional information 69e0e4191SAndrew Rist * regarding copyright ownership. The ASF licenses this file 79e0e4191SAndrew Rist * to you under the Apache License, Version 2.0 (the 89e0e4191SAndrew Rist * "License"); you may not use this file except in compliance 99e0e4191SAndrew Rist * with the License. You may obtain a copy of the License at 109e0e4191SAndrew Rist * 119e0e4191SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 129e0e4191SAndrew Rist * 139e0e4191SAndrew Rist * Unless required by applicable law or agreed to in writing, 149e0e4191SAndrew Rist * software distributed under the License is distributed on an 159e0e4191SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 169e0e4191SAndrew Rist * KIND, either express or implied. See the License for the 179e0e4191SAndrew Rist * specific language governing permissions and limitations 189e0e4191SAndrew Rist * under the License. 199e0e4191SAndrew Rist * 209e0e4191SAndrew Rist *************************************************************/ 219e0e4191SAndrew Rist 229e0e4191SAndrew Rist 23*b63233d8Sdamjan #include "precompiled_reportdesign.hxx" 24cdf0e10cSrcweir #include "conditionalexpression.hxx" 25cdf0e10cSrcweir 26cdf0e10cSrcweir /** === begin UNO includes === **/ 27cdf0e10cSrcweir /** === end UNO includes === **/ 28cdf0e10cSrcweir 29cdf0e10cSrcweir //........................................................................ 30cdf0e10cSrcweir namespace rptui 31cdf0e10cSrcweir { 32cdf0e10cSrcweir //........................................................................ 33cdf0e10cSrcweir 34cdf0e10cSrcweir /** === begin UNO using === **/ 35cdf0e10cSrcweir /** === end UNO using === **/ 36cdf0e10cSrcweir 37cdf0e10cSrcweir // ============================================================================= 38cdf0e10cSrcweir // = ConditionalExpression 39cdf0e10cSrcweir // ============================================================================= 40cdf0e10cSrcweir // ----------------------------------------------------------------------------- ConditionalExpression(const sal_Char * _pAsciiPattern)41cdf0e10cSrcweir ConditionalExpression::ConditionalExpression( const sal_Char* _pAsciiPattern ) 42cdf0e10cSrcweir :m_sPattern( ::rtl::OUString::createFromAscii( _pAsciiPattern ) ) 43cdf0e10cSrcweir { 44cdf0e10cSrcweir } 45cdf0e10cSrcweir 46cdf0e10cSrcweir // ----------------------------------------------------------------------------- assembleExpression(const::rtl::OUString & _rFieldDataSource,const::rtl::OUString & _rLHS,const::rtl::OUString & _rRHS) const47cdf0e10cSrcweir ::rtl::OUString ConditionalExpression::assembleExpression( const ::rtl::OUString& _rFieldDataSource, const ::rtl::OUString& _rLHS, const ::rtl::OUString& _rRHS ) const 48cdf0e10cSrcweir { 49cdf0e10cSrcweir ::rtl::OUString sExpression( m_sPattern ); 50cdf0e10cSrcweir 51cdf0e10cSrcweir sal_Int32 nPatternIndex = sExpression.indexOf( '$' ); 52cdf0e10cSrcweir while ( nPatternIndex > -1 ) 53cdf0e10cSrcweir { 54cdf0e10cSrcweir const ::rtl::OUString* pReplace = NULL; 55cdf0e10cSrcweir switch ( sExpression.getStr()[ nPatternIndex + 1 ] ) 56cdf0e10cSrcweir { 57cdf0e10cSrcweir case '$': pReplace = &_rFieldDataSource; break; 58cdf0e10cSrcweir case '1': pReplace = &_rLHS; break; 59cdf0e10cSrcweir case '2': pReplace = &_rRHS; break; 60cdf0e10cSrcweir default: break; 61cdf0e10cSrcweir } 62cdf0e10cSrcweir 63cdf0e10cSrcweir if ( pReplace == NULL ) 64cdf0e10cSrcweir { 65cdf0e10cSrcweir OSL_ENSURE( false, "ConditionalExpression::assembleExpression: illegal pattern!" ); 66cdf0e10cSrcweir break; 67cdf0e10cSrcweir } 68cdf0e10cSrcweir 69cdf0e10cSrcweir sExpression = sExpression.replaceAt( nPatternIndex, 2, *pReplace ); 70cdf0e10cSrcweir nPatternIndex = sExpression.indexOf( '$', nPatternIndex + pReplace->getLength() + 1 ); 71cdf0e10cSrcweir } 72cdf0e10cSrcweir return sExpression; 73cdf0e10cSrcweir } 74cdf0e10cSrcweir 75cdf0e10cSrcweir // ----------------------------------------------------------------------------- matchExpression(const::rtl::OUString & _rExpression,const::rtl::OUString & _rFieldDataSource,::rtl::OUString & _out_rLHS,::rtl::OUString & _out_rRHS) const76cdf0e10cSrcweir bool ConditionalExpression::matchExpression( const ::rtl::OUString& _rExpression, const ::rtl::OUString& _rFieldDataSource, ::rtl::OUString& _out_rLHS, ::rtl::OUString& _out_rRHS ) const 77cdf0e10cSrcweir { 78cdf0e10cSrcweir (void)_rExpression; 79cdf0e10cSrcweir (void)_rFieldDataSource; 80cdf0e10cSrcweir (void)_out_rLHS; 81cdf0e10cSrcweir (void)_out_rRHS; 82cdf0e10cSrcweir 83cdf0e10cSrcweir // if we had regular expression, the matching would be pretty easy ... 84cdf0e10cSrcweir // just replace $1 and $2 in the pattern with (.*), and then get them with \1 resp. \2. 85cdf0e10cSrcweir // Unfortunately, we don't have such a regexp engine ... 86cdf0e10cSrcweir 87cdf0e10cSrcweir // Okay, let's start with replacing all $$ in our pattern with the actual field data source 88cdf0e10cSrcweir ::rtl::OUString sMatchExpression( m_sPattern ); 89cdf0e10cSrcweir const ::rtl::OUString sFieldDataPattern( RTL_CONSTASCII_USTRINGPARAM( "$$" ) ); 90cdf0e10cSrcweir sal_Int32 nIndex( sMatchExpression.indexOf( sFieldDataPattern ) ); 91cdf0e10cSrcweir while ( nIndex != -1 ) 92cdf0e10cSrcweir { 93cdf0e10cSrcweir sMatchExpression = sMatchExpression.replaceAt( nIndex, sFieldDataPattern.getLength(), _rFieldDataSource ); 94cdf0e10cSrcweir nIndex = sMatchExpression.indexOf( sFieldDataPattern, nIndex + _rFieldDataSource.getLength() ); 95cdf0e10cSrcweir } 96cdf0e10cSrcweir 97cdf0e10cSrcweir const ::rtl::OUString sLHSPattern( RTL_CONSTASCII_USTRINGPARAM( "$1" ) ); 98cdf0e10cSrcweir const ::rtl::OUString sRHSPattern( RTL_CONSTASCII_USTRINGPARAM( "$2" ) ); 99cdf0e10cSrcweir sal_Int32 nLHSIndex( sMatchExpression.indexOf( sLHSPattern ) ); 100cdf0e10cSrcweir sal_Int32 nRHSIndex( sMatchExpression.indexOf( sRHSPattern ) ); 101cdf0e10cSrcweir 10230acf5e8Spfg // now we should have at most one occurrence of $1 and $2, resp. 103cdf0e10cSrcweir OSL_ENSURE( sMatchExpression.indexOf( sLHSPattern, nLHSIndex + 1 ) == -1, 10430acf5e8Spfg "ConditionalExpression::matchExpression: unsupported pattern (more than one LHS occurrence)!" ); 105cdf0e10cSrcweir OSL_ENSURE( sMatchExpression.indexOf( sRHSPattern, nRHSIndex + 1 ) == -1, 10630acf5e8Spfg "ConditionalExpression::matchExpression: unsupported pattern (more than one RHS occurrence)!" ); 107cdf0e10cSrcweir // Also, an LHS must be present, and precede the RHS (if present) 108cdf0e10cSrcweir OSL_ENSURE( ( nLHSIndex != -1 ) && ( ( nLHSIndex < nRHSIndex ) || ( nRHSIndex == -1 ) ), 10930acf5e8Spfg "ConditionalExpression::matchExpression: no LHS, or an RHS preceding the LHS - this is not supported!" ); 110cdf0e10cSrcweir 11130acf5e8Spfg // up to the occurrence of the LHS (which must exist, see above), the two expressions 112cdf0e10cSrcweir // must be identical 113cdf0e10cSrcweir if ( _rExpression.getLength() < nLHSIndex ) 114cdf0e10cSrcweir return false; 115cdf0e10cSrcweir const ::rtl::OUString sExprPart1( _rExpression.copy( 0, nLHSIndex ) ); 116cdf0e10cSrcweir const ::rtl::OUString sMatchExprPart1( sMatchExpression.copy( 0, nLHSIndex ) ); 117cdf0e10cSrcweir if ( sExprPart1 != sMatchExprPart1 ) 118cdf0e10cSrcweir // the left-most expression parts do not match 119cdf0e10cSrcweir return false; 120cdf0e10cSrcweir 12130acf5e8Spfg // after the occurrence of the RHS (or the LHS, if there is no RHS), the two expressions 122cdf0e10cSrcweir // must be identical, too 123cdf0e10cSrcweir bool bHaveRHS( nRHSIndex != -1 ); 124cdf0e10cSrcweir sal_Int32 nRightMostIndex( bHaveRHS ? nRHSIndex : nLHSIndex ); 125cdf0e10cSrcweir const ::rtl::OUString sMatchExprPart3( sMatchExpression.copy( nRightMostIndex + 2 ) ); 126cdf0e10cSrcweir if ( _rExpression.getLength() < sMatchExprPart3.getLength() ) 127cdf0e10cSrcweir // the expression is not even long enough to hold the right-most part of the match expression 128cdf0e10cSrcweir return false; 129cdf0e10cSrcweir const ::rtl::OUString sExprPart3( _rExpression.copy( _rExpression.getLength() - sMatchExprPart3.getLength() ) ); 130cdf0e10cSrcweir if ( sExprPart3 != sMatchExprPart3 ) 131cdf0e10cSrcweir // the right-most expression parts do not match 132cdf0e10cSrcweir return false; 133cdf0e10cSrcweir 134cdf0e10cSrcweir // if we don't have an RHS, we're done 135cdf0e10cSrcweir if ( !bHaveRHS ) 136cdf0e10cSrcweir { 137cdf0e10cSrcweir _out_rLHS = _rExpression.copy( sExprPart1.getLength(), _rExpression.getLength() - sExprPart1.getLength() - sExprPart3.getLength() ); 138cdf0e10cSrcweir return true; 139cdf0e10cSrcweir } 140cdf0e10cSrcweir 141cdf0e10cSrcweir // strip the match expression by its right-most and left-most part, and by the placeholders $1 and $2 142cdf0e10cSrcweir sal_Int32 nMatchExprPart2Start( nLHSIndex + sLHSPattern.getLength() ); 143cdf0e10cSrcweir ::rtl::OUString sMatchExprPart2 = sMatchExpression.copy( 144cdf0e10cSrcweir nMatchExprPart2Start, 145cdf0e10cSrcweir sMatchExpression.getLength() - nMatchExprPart2Start - sMatchExprPart3.getLength() - 2 146cdf0e10cSrcweir ); 147cdf0e10cSrcweir // strip the expression by its left-most and right-most part 148cdf0e10cSrcweir const ::rtl::OUString sExpression( _rExpression.copy( 149cdf0e10cSrcweir sExprPart1.getLength(), 150cdf0e10cSrcweir _rExpression.getLength() - sExprPart1.getLength() - sExprPart3.getLength() 151cdf0e10cSrcweir ) ); 152cdf0e10cSrcweir 153cdf0e10cSrcweir sal_Int32 nPart2Index = sExpression.indexOf( sMatchExprPart2 ); 154cdf0e10cSrcweir if ( nPart2Index == -1 ) 155cdf0e10cSrcweir // the "middle" part of the match expression does not exist in the expression at all 156cdf0e10cSrcweir return false; 157cdf0e10cSrcweir 158cdf0e10cSrcweir OSL_ENSURE( sExpression.indexOf( sMatchExprPart2, nPart2Index + 1 ) == -1, 159cdf0e10cSrcweir "ConditionalExpression::matchExpression: ambiguous matching!" ); 160cdf0e10cSrcweir // if this fires, then we're lost: The middle part exists two times in the expression, 161cdf0e10cSrcweir // so we cannot reliably determine what's the LHS and what's the RHS. 162cdf0e10cSrcweir // Well, the whole mechanism is flawed, anyway: 163cdf0e10cSrcweir // Encoding the field content in the conditional expression will break as soon 164cdf0e10cSrcweir // as somebody 165cdf0e10cSrcweir // - assigns a Data Field to a control 166cdf0e10cSrcweir // - creates a conditional format expression for the control 167cdf0e10cSrcweir // - assigns another Data Field to the control 168cdf0e10cSrcweir // - opens the Conditional Format Dialog, again 169cdf0e10cSrcweir // Here, at the latest, you can see that we need another mechanism, anyway, which does not 170cdf0e10cSrcweir // rely on those strange expression building/matching 171cdf0e10cSrcweir 172cdf0e10cSrcweir _out_rLHS = sExpression.copy( 0, nPart2Index ); 173cdf0e10cSrcweir _out_rRHS = sExpression.copy( nPart2Index + sMatchExprPart2.getLength() ); 174cdf0e10cSrcweir 175cdf0e10cSrcweir return true; 176cdf0e10cSrcweir } 177cdf0e10cSrcweir 178cdf0e10cSrcweir // ============================================================================= 179cdf0e10cSrcweir // = ConditionalExpressionFactory 180cdf0e10cSrcweir // ============================================================================= 181cdf0e10cSrcweir // ----------------------------------------------------------------------------- getKnownConditionalExpressions(ConditionalExpressions & _out_rCondExp)182cdf0e10cSrcweir size_t ConditionalExpressionFactory::getKnownConditionalExpressions( ConditionalExpressions& _out_rCondExp ) 183cdf0e10cSrcweir { 184cdf0e10cSrcweir ConditionalExpressions aEmpty; 185cdf0e10cSrcweir _out_rCondExp.swap( aEmpty ); 186cdf0e10cSrcweir 187cdf0e10cSrcweir _out_rCondExp[ eBetween ] = PConditionalExpression( new ConditionalExpression( "AND( ( $$ ) >= ( $1 ); ( $$ ) <= ( $2 ) )" ) ); 188cdf0e10cSrcweir _out_rCondExp[ eNotBetween ] = PConditionalExpression( new ConditionalExpression( "NOT( AND( ( $$ ) >= ( $1 ); ( $$ ) <= ( $2 ) ) )" ) ); 189cdf0e10cSrcweir _out_rCondExp[ eEqualTo ] = PConditionalExpression( new ConditionalExpression( "( $$ ) = ( $1 )" ) ); 190cdf0e10cSrcweir _out_rCondExp[ eNotEqualTo ] = PConditionalExpression( new ConditionalExpression( "( $$ ) <> ( $1 )" ) ); 191cdf0e10cSrcweir _out_rCondExp[ eGreaterThan ] = PConditionalExpression( new ConditionalExpression( "( $$ ) > ( $1 )" ) ); 192cdf0e10cSrcweir _out_rCondExp[ eLessThan ] = PConditionalExpression( new ConditionalExpression( "( $$ ) < ( $1 )" ) ); 193cdf0e10cSrcweir _out_rCondExp[ eGreaterOrEqual ] = PConditionalExpression( new ConditionalExpression( "( $$ ) >= ( $1 )" ) ); 194cdf0e10cSrcweir _out_rCondExp[ eLessOrEqual ] = PConditionalExpression( new ConditionalExpression( "( $$ ) <= ( $1 )" ) ); 195cdf0e10cSrcweir 196cdf0e10cSrcweir return _out_rCondExp.size(); 197cdf0e10cSrcweir } 198cdf0e10cSrcweir //........................................................................ 199cdf0e10cSrcweir } // namespace rptui 200cdf0e10cSrcweir //........................................................................ 201