LCOV - code coverage report
Current view: top level - libreoffice/reportdesign/source/core/misc - conditionalexpression.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 69 0.0 %
Date: 2012-12-27 Functions: 0 4 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : #include "conditionalexpression.hxx"
      20             : 
      21             : //........................................................................
      22             : namespace rptui
      23             : {
      24             : //........................................................................
      25             : 
      26             :     /** === begin UNO using === **/
      27             :     /** === end UNO using === **/
      28             : 
      29             :     // =============================================================================
      30             :     // = ConditionalExpression
      31             :     // =============================================================================
      32             :     // -----------------------------------------------------------------------------
      33           0 :     ConditionalExpression::ConditionalExpression( const sal_Char* _pAsciiPattern )
      34           0 :         :m_sPattern( ::rtl::OUString::createFromAscii( _pAsciiPattern ) )
      35             :     {
      36           0 :     }
      37             : 
      38             :     // -----------------------------------------------------------------------------
      39           0 :     ::rtl::OUString ConditionalExpression::assembleExpression( const ::rtl::OUString& _rFieldDataSource, const ::rtl::OUString& _rLHS, const ::rtl::OUString& _rRHS ) const
      40             :     {
      41           0 :         ::rtl::OUString sExpression( m_sPattern );
      42             : 
      43           0 :         sal_Int32 nPatternIndex = sExpression.indexOf( '$' );
      44           0 :         while ( nPatternIndex > -1 )
      45             :         {
      46           0 :             const ::rtl::OUString* pReplace = NULL;
      47           0 :             switch ( sExpression.getStr()[ nPatternIndex + 1 ] )
      48             :             {
      49           0 :             case '$': pReplace = &_rFieldDataSource; break;
      50           0 :             case '1': pReplace = &_rLHS; break;
      51           0 :             case '2': pReplace = &_rRHS; break;
      52           0 :             default: break;
      53             :             }
      54             : 
      55           0 :             if ( pReplace == NULL )
      56             :             {
      57             :                 OSL_FAIL( "ConditionalExpression::assembleExpression: illegal pattern!" );
      58           0 :                 break;
      59             :             }
      60             : 
      61           0 :             sExpression = sExpression.replaceAt( nPatternIndex, 2, *pReplace );
      62           0 :             nPatternIndex = sExpression.indexOf( '$', nPatternIndex + pReplace->getLength() + 1 );
      63             :         }
      64           0 :         return sExpression;
      65             :     }
      66             : 
      67             :     // -----------------------------------------------------------------------------
      68           0 :     bool ConditionalExpression::matchExpression( const ::rtl::OUString& _rExpression, const ::rtl::OUString& _rFieldDataSource, ::rtl::OUString& _out_rLHS, ::rtl::OUString& _out_rRHS ) const
      69             :     {
      70             :         (void)_rExpression;
      71             :         (void)_rFieldDataSource;
      72             :         (void)_out_rLHS;
      73             :         (void)_out_rRHS;
      74             : 
      75             :         // if we had regular expression, the matching would be pretty easy ...
      76             :         // just replace $1 and $2 in the pattern with (.*), and then get them with \1 resp. \2.
      77             :         // Unfortunately, we don't have such a regexp engine ...
      78             : 
      79             :         // Okay, let's start with replacing all $$ in our pattern with the actual field data source
      80           0 :         ::rtl::OUString sMatchExpression( m_sPattern );
      81           0 :         const ::rtl::OUString sFieldDataPattern( RTL_CONSTASCII_USTRINGPARAM( "$$" ) );
      82           0 :         sal_Int32 nIndex( sMatchExpression.indexOf( sFieldDataPattern ) );
      83           0 :         while ( nIndex != -1 )
      84             :         {
      85           0 :             sMatchExpression = sMatchExpression.replaceAt( nIndex, sFieldDataPattern.getLength(), _rFieldDataSource );
      86           0 :             nIndex = sMatchExpression.indexOf( sFieldDataPattern, nIndex + _rFieldDataSource.getLength() );
      87             :         }
      88             : 
      89           0 :         const ::rtl::OUString sLHSPattern( RTL_CONSTASCII_USTRINGPARAM( "$1" ) );
      90           0 :         const ::rtl::OUString sRHSPattern( RTL_CONSTASCII_USTRINGPARAM( "$2" ) );
      91           0 :         sal_Int32 nLHSIndex( sMatchExpression.indexOf( sLHSPattern ) );
      92           0 :         sal_Int32 nRHSIndex( sMatchExpression.indexOf( sRHSPattern ) );
      93             : 
      94             :         // now we should have at most one occurrence of $1 and $2, resp.
      95             :         OSL_ENSURE( sMatchExpression.indexOf( sLHSPattern, nLHSIndex + 1 ) == -1,
      96             :             "ConditionalExpression::matchExpression: unsupported pattern (more than one LHS occurrence)!" );
      97             :         OSL_ENSURE( sMatchExpression.indexOf( sRHSPattern, nRHSIndex + 1 ) == -1,
      98             :             "ConditionalExpression::matchExpression: unsupported pattern (more than one RHS occurrence)!" );
      99             :         // Also, an LHS must be present, and precede the RHS (if present)
     100             :         OSL_ENSURE( ( nLHSIndex != -1 ) && ( ( nLHSIndex < nRHSIndex ) || ( nRHSIndex == -1 ) ),
     101             :             "ConditionalExpression::matchExpression: no LHS, or an RHS preceeding the LHS - this is not supported!" );
     102             : 
     103             :         // up to the occurrence of the LHS (which must exist, see above), the two expressions
     104             :         // must be identical
     105           0 :         if ( _rExpression.getLength() < nLHSIndex )
     106           0 :             return false;
     107           0 :         const ::rtl::OUString sExprPart1( _rExpression.copy( 0, nLHSIndex ) );
     108           0 :         const ::rtl::OUString sMatchExprPart1( sMatchExpression.copy( 0, nLHSIndex ) );
     109           0 :         if ( sExprPart1 != sMatchExprPart1 )
     110             :             // the left-most expression parts do not match
     111           0 :             return false;
     112             : 
     113             :         // after the occurrence of the RHS (or the LHS, if there is no RHS), the two expressions
     114             :         // must be identical, too
     115           0 :         bool bHaveRHS( nRHSIndex != -1 );
     116           0 :         sal_Int32 nRightMostIndex( bHaveRHS ? nRHSIndex : nLHSIndex );
     117           0 :         const ::rtl::OUString sMatchExprPart3( sMatchExpression.copy( nRightMostIndex + 2 ) );
     118           0 :         if ( _rExpression.getLength() < sMatchExprPart3.getLength() )
     119             :             // the expression is not even long enough to hold the right-most part of the match expression
     120           0 :             return false;
     121           0 :         const ::rtl::OUString sExprPart3( _rExpression.copy( _rExpression.getLength() - sMatchExprPart3.getLength() ) );
     122           0 :         if ( sExprPart3 != sMatchExprPart3 )
     123             :             // the right-most expression parts do not match
     124           0 :             return false;
     125             : 
     126             :         // if we don't have an RHS, we're done
     127           0 :         if ( !bHaveRHS )
     128             :         {
     129           0 :             _out_rLHS = _rExpression.copy( sExprPart1.getLength(), _rExpression.getLength() - sExprPart1.getLength() - sExprPart3.getLength() );
     130           0 :             return true;
     131             :         }
     132             : 
     133             :         // strip the match expression by its right-most and left-most part, and by the placeholders $1 and $2
     134           0 :         sal_Int32 nMatchExprPart2Start( nLHSIndex + sLHSPattern.getLength() );
     135             :         ::rtl::OUString sMatchExprPart2 = sMatchExpression.copy(
     136             :             nMatchExprPart2Start,
     137           0 :             sMatchExpression.getLength() - nMatchExprPart2Start - sMatchExprPart3.getLength() - 2
     138           0 :         );
     139             :         // strip the expression by its left-most and right-most part
     140             :         const ::rtl::OUString sExpression( _rExpression.copy(
     141             :             sExprPart1.getLength(),
     142           0 :             _rExpression.getLength() - sExprPart1.getLength() - sExprPart3.getLength()
     143           0 :         ) );
     144             : 
     145           0 :         sal_Int32 nPart2Index = sExpression.indexOf( sMatchExprPart2 );
     146           0 :         if ( nPart2Index == -1 )
     147             :             // the "middle" part of the match expression does not exist in the expression at all
     148           0 :             return false;
     149             : 
     150             :         OSL_ENSURE( sExpression.indexOf( sMatchExprPart2, nPart2Index + 1 ) == -1,
     151             :             "ConditionalExpression::matchExpression: ambiguous matching!" );
     152             :             // if this fires, then we're lost: The middle part exists two times in the expression,
     153             :             // so we cannot reliably determine what's the LHS and what's the RHS.
     154             :             // Well, the whole mechanism is flawed, anyway:
     155             :             // Encoding the field content in the conditional expression will break as soon
     156             :             // as somebody
     157             :             // - assigns a Data Field to a control
     158             :             // - creates a conditional format expression for the control
     159             :             // - assigns another Data Field to the control
     160             :             // - opens the Conditional Format Dialog, again
     161             :             // Here, at the latest, you can see that we need another mechanism, anyway, which does not
     162             :             // rely on those strange expression building/matching
     163             : 
     164           0 :         _out_rLHS = sExpression.copy( 0, nPart2Index );
     165           0 :         _out_rRHS = sExpression.copy( nPart2Index + sMatchExprPart2.getLength() );
     166             : 
     167           0 :         return true;
     168             :     }
     169             : 
     170             :     // =============================================================================
     171             :     // = ConditionalExpressionFactory
     172             :     // =============================================================================
     173             :     // -----------------------------------------------------------------------------
     174           0 :     size_t ConditionalExpressionFactory::getKnownConditionalExpressions( ConditionalExpressions& _out_rCondExp )
     175             :     {
     176           0 :         ConditionalExpressions aEmpty;
     177           0 :         _out_rCondExp.swap( aEmpty );
     178             : 
     179           0 :         _out_rCondExp[ eBetween ]        = PConditionalExpression( new ConditionalExpression( "AND( ( $$ ) >= ( $1 ); ( $$ ) <= ( $2 ) )" ) );
     180           0 :         _out_rCondExp[ eNotBetween ]     = PConditionalExpression( new ConditionalExpression( "NOT( AND( ( $$ ) >= ( $1 ); ( $$ ) <= ( $2 ) ) )" ) );
     181           0 :         _out_rCondExp[ eEqualTo ]        = PConditionalExpression( new ConditionalExpression( "( $$ ) = ( $1 )" ) );
     182           0 :         _out_rCondExp[ eNotEqualTo ]     = PConditionalExpression( new ConditionalExpression( "( $$ ) <> ( $1 )" ) );
     183           0 :         _out_rCondExp[ eGreaterThan ]    = PConditionalExpression( new ConditionalExpression( "( $$ ) > ( $1 )" ) );
     184           0 :         _out_rCondExp[ eLessThan ]       = PConditionalExpression( new ConditionalExpression( "( $$ ) < ( $1 )" ) );
     185           0 :         _out_rCondExp[ eGreaterOrEqual ] = PConditionalExpression( new ConditionalExpression( "( $$ ) >= ( $1 )" ) );
     186           0 :         _out_rCondExp[ eLessOrEqual ]    = PConditionalExpression( new ConditionalExpression( "( $$ ) <= ( $1 )" ) );
     187             : 
     188           0 :         return _out_rCondExp.size();
     189             :     }
     190             : //........................................................................
     191             : } // namespace rptui
     192             : //........................................................................
     193             : 
     194             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10