Branch libreoffice-5-0-4
[LibreOffice.git] / reportdesign / source / core / misc / conditionalexpression.cxx
blobc83872fed3de216dbf0a5dbdbf3482a923305b92
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "conditionalexpression.hxx"
22 #include <osl/diagnose.h>
25 namespace rptui
28 // = ConditionalExpression
31 ConditionalExpression::ConditionalExpression( const sal_Char* _pAsciiPattern )
32 :m_sPattern( OUString::createFromAscii( _pAsciiPattern ) )
37 OUString ConditionalExpression::assembleExpression( const OUString& _rFieldDataSource, const OUString& _rLHS, const OUString& _rRHS ) const
39 OUString sExpression( m_sPattern );
41 sal_Int32 nPatternIndex = sExpression.indexOf( '$' );
42 while ( nPatternIndex > -1 )
44 const OUString* pReplace = NULL;
45 switch ( sExpression[ nPatternIndex + 1 ] )
47 case '$': pReplace = &_rFieldDataSource; break;
48 case '1': pReplace = &_rLHS; break;
49 case '2': pReplace = &_rRHS; break;
50 default: break;
53 if ( pReplace == NULL )
55 OSL_FAIL( "ConditionalExpression::assembleExpression: illegal pattern!" );
56 break;
59 sExpression = sExpression.replaceAt( nPatternIndex, 2, *pReplace );
60 nPatternIndex = sExpression.indexOf( '$', nPatternIndex + pReplace->getLength() + 1 );
62 return sExpression;
66 bool ConditionalExpression::matchExpression( const OUString& _rExpression, const OUString& _rFieldDataSource, OUString& _out_rLHS, OUString& _out_rRHS ) const
68 (void)_rExpression;
69 (void)_rFieldDataSource;
70 (void)_out_rLHS;
71 (void)_out_rRHS;
73 // if we had regular expression, the matching would be pretty easy ...
74 // just replace $1 and $2 in the pattern with (.*), and then get them with \1 resp. \2.
75 // Unfortunately, we don't have such a regexp engine ...
77 // Okay, let's start with replacing all $$ in our pattern with the actual field data source
78 OUString sMatchExpression( m_sPattern );
79 const OUString sFieldDataPattern( "$$" );
80 sal_Int32 nIndex( sMatchExpression.indexOf( sFieldDataPattern ) );
81 while ( nIndex != -1 )
83 sMatchExpression = sMatchExpression.replaceAt( nIndex, sFieldDataPattern.getLength(), _rFieldDataSource );
84 nIndex = sMatchExpression.indexOf( sFieldDataPattern, nIndex + _rFieldDataSource.getLength() );
87 const OUString sLHSPattern( "$1" );
88 const OUString sRHSPattern( "$2" );
89 sal_Int32 nLHSIndex( sMatchExpression.indexOf( sLHSPattern ) );
90 sal_Int32 nRHSIndex( sMatchExpression.indexOf( sRHSPattern ) );
92 // now we should have at most one occurrence of $1 and $2, resp.
93 OSL_ENSURE( sMatchExpression.indexOf( sLHSPattern, nLHSIndex + 1 ) == -1,
94 "ConditionalExpression::matchExpression: unsupported pattern (more than one LHS occurrence)!" );
95 OSL_ENSURE( sMatchExpression.indexOf( sRHSPattern, nRHSIndex + 1 ) == -1,
96 "ConditionalExpression::matchExpression: unsupported pattern (more than one RHS occurrence)!" );
97 // Also, an LHS must be present, and precede the RHS (if present)
98 OSL_ENSURE( ( nLHSIndex != -1 ) && ( ( nLHSIndex < nRHSIndex ) || ( nRHSIndex == -1 ) ),
99 "ConditionalExpression::matchExpression: no LHS, or an RHS preceding the LHS - this is not supported!" );
101 // up to the occurrence of the LHS (which must exist, see above), the two expressions
102 // must be identical
103 if ( _rExpression.getLength() < nLHSIndex )
104 return false;
105 const OUString sExprPart1( _rExpression.copy( 0, nLHSIndex ) );
106 const OUString sMatchExprPart1( sMatchExpression.copy( 0, nLHSIndex ) );
107 if ( sExprPart1 != sMatchExprPart1 )
108 // the left-most expression parts do not match
109 return false;
111 // after the occurrence of the RHS (or the LHS, if there is no RHS), the two expressions
112 // must be identical, too
113 bool bHaveRHS( nRHSIndex != -1 );
114 sal_Int32 nRightMostIndex( bHaveRHS ? nRHSIndex : nLHSIndex );
115 const OUString sMatchExprPart3( sMatchExpression.copy( nRightMostIndex + 2 ) );
116 if ( _rExpression.getLength() < sMatchExprPart3.getLength() )
117 // the expression is not even long enough to hold the right-most part of the match expression
118 return false;
119 const OUString sExprPart3( _rExpression.copy( _rExpression.getLength() - sMatchExprPart3.getLength() ) );
120 if ( sExprPart3 != sMatchExprPart3 )
121 // the right-most expression parts do not match
122 return false;
124 // if we don't have an RHS, we're done
125 if ( !bHaveRHS )
127 _out_rLHS = _rExpression.copy( sExprPart1.getLength(), _rExpression.getLength() - sExprPart1.getLength() - sExprPart3.getLength() );
128 return true;
131 // strip the match expression by its right-most and left-most part, and by the placeholders $1 and $2
132 sal_Int32 nMatchExprPart2Start( nLHSIndex + sLHSPattern.getLength() );
133 OUString sMatchExprPart2 = sMatchExpression.copy(
134 nMatchExprPart2Start,
135 sMatchExpression.getLength() - nMatchExprPart2Start - sMatchExprPart3.getLength() - 2
137 // strip the expression by its left-most and right-most part
138 const OUString sExpression( _rExpression.copy(
139 sExprPart1.getLength(),
140 _rExpression.getLength() - sExprPart1.getLength() - sExprPart3.getLength()
141 ) );
143 sal_Int32 nPart2Index = sExpression.indexOf( sMatchExprPart2 );
144 if ( nPart2Index == -1 )
145 // the "middle" part of the match expression does not exist in the expression at all
146 return false;
148 OSL_ENSURE( sExpression.indexOf( sMatchExprPart2, nPart2Index + 1 ) == -1,
149 "ConditionalExpression::matchExpression: ambiguous matching!" );
150 // if this fires, then we're lost: The middle part exists two times in the expression,
151 // so we cannot reliably determine what's the LHS and what's the RHS.
152 // Well, the whole mechanism is flawed, anyway:
153 // Encoding the field content in the conditional expression will break as soon
154 // as somebody
155 // - assigns a Data Field to a control
156 // - creates a conditional format expression for the control
157 // - assigns another Data Field to the control
158 // - opens the Conditional Format Dialog, again
159 // Here, at the latest, you can see that we need another mechanism, anyway, which does not
160 // rely on those strange expression building/matching
162 _out_rLHS = sExpression.copy( 0, nPart2Index );
163 _out_rRHS = sExpression.copy( nPart2Index + sMatchExprPart2.getLength() );
165 return true;
169 // = ConditionalExpressionFactory
172 size_t ConditionalExpressionFactory::getKnownConditionalExpressions( ConditionalExpressions& _out_rCondExp )
174 ConditionalExpressions aEmpty;
175 _out_rCondExp.swap( aEmpty );
177 _out_rCondExp[ eBetween ] = PConditionalExpression( new ConditionalExpression( "AND( ( $$ ) >= ( $1 ); ( $$ ) <= ( $2 ) )" ) );
178 _out_rCondExp[ eNotBetween ] = PConditionalExpression( new ConditionalExpression( "NOT( AND( ( $$ ) >= ( $1 ); ( $$ ) <= ( $2 ) ) )" ) );
179 _out_rCondExp[ eEqualTo ] = PConditionalExpression( new ConditionalExpression( "( $$ ) = ( $1 )" ) );
180 _out_rCondExp[ eNotEqualTo ] = PConditionalExpression( new ConditionalExpression( "( $$ ) <> ( $1 )" ) );
181 _out_rCondExp[ eGreaterThan ] = PConditionalExpression( new ConditionalExpression( "( $$ ) > ( $1 )" ) );
182 _out_rCondExp[ eLessThan ] = PConditionalExpression( new ConditionalExpression( "( $$ ) < ( $1 )" ) );
183 _out_rCondExp[ eGreaterOrEqual ] = PConditionalExpression( new ConditionalExpression( "( $$ ) >= ( $1 )" ) );
184 _out_rCondExp[ eLessOrEqual ] = PConditionalExpression( new ConditionalExpression( "( $$ ) <= ( $1 )" ) );
186 return _out_rCondExp.size();
189 } // namespace rptui
192 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */