1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: conditionalexpression.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 #include "conditionalexpression.hxx"
33 /** === begin UNO includes === **/
34 /** === end UNO includes === **/
36 //........................................................................
39 //........................................................................
41 /** === begin UNO using === **/
42 /** === end UNO using === **/
44 // =============================================================================
45 // = ConditionalExpression
46 // =============================================================================
47 // -----------------------------------------------------------------------------
48 ConditionalExpression::ConditionalExpression( const sal_Char
* _pAsciiPattern
)
49 :m_sPattern( ::rtl::OUString::createFromAscii( _pAsciiPattern
) )
53 // -----------------------------------------------------------------------------
54 ::rtl::OUString
ConditionalExpression::assembleExpression( const ::rtl::OUString
& _rFieldDataSource
, const ::rtl::OUString
& _rLHS
, const ::rtl::OUString
& _rRHS
) const
56 ::rtl::OUString
sExpression( m_sPattern
);
58 sal_Int32 nPatternIndex
= sExpression
.indexOf( '$' );
59 while ( nPatternIndex
> -1 )
61 const ::rtl::OUString
* pReplace
= NULL
;
62 switch ( sExpression
.getStr()[ nPatternIndex
+ 1 ] )
64 case '$': pReplace
= &_rFieldDataSource
; break;
65 case '1': pReplace
= &_rLHS
; break;
66 case '2': pReplace
= &_rRHS
; break;
70 if ( pReplace
== NULL
)
72 OSL_ENSURE( false, "ConditionalExpression::assembleExpression: illegal pattern!" );
76 sExpression
= sExpression
.replaceAt( nPatternIndex
, 2, *pReplace
);
77 nPatternIndex
= sExpression
.indexOf( '$', nPatternIndex
+ pReplace
->getLength() + 1 );
82 // -----------------------------------------------------------------------------
83 bool ConditionalExpression::matchExpression( const ::rtl::OUString
& _rExpression
, const ::rtl::OUString
& _rFieldDataSource
, ::rtl::OUString
& _out_rLHS
, ::rtl::OUString
& _out_rRHS
) const
86 (void)_rFieldDataSource
;
90 // if we had regular expression, the matching would be pretty easy ...
91 // just replace $1 and $2 in the pattern with (.*), and then get them with \1 resp. \2.
92 // Unfortunately, we don't have such a regexp engine ...
94 // Okay, let's start with replacing all $$ in our pattern with the actual field data source
95 ::rtl::OUString
sMatchExpression( m_sPattern
);
96 const ::rtl::OUString
sFieldDataPattern( RTL_CONSTASCII_USTRINGPARAM( "$$" ) );
97 sal_Int32
nIndex( sMatchExpression
.indexOf( sFieldDataPattern
) );
98 while ( nIndex
!= -1 )
100 sMatchExpression
= sMatchExpression
.replaceAt( nIndex
, sFieldDataPattern
.getLength(), _rFieldDataSource
);
101 nIndex
= sMatchExpression
.indexOf( sFieldDataPattern
, nIndex
+ _rFieldDataSource
.getLength() );
104 const ::rtl::OUString
sLHSPattern( RTL_CONSTASCII_USTRINGPARAM( "$1" ) );
105 const ::rtl::OUString
sRHSPattern( RTL_CONSTASCII_USTRINGPARAM( "$2" ) );
106 sal_Int32
nLHSIndex( sMatchExpression
.indexOf( sLHSPattern
) );
107 sal_Int32
nRHSIndex( sMatchExpression
.indexOf( sRHSPattern
) );
109 // now we should have at most one occurance of $1 and $2, resp.
110 OSL_ENSURE( sMatchExpression
.indexOf( sLHSPattern
, nLHSIndex
+ 1 ) == -1,
111 "ConditionalExpression::matchExpression: unsupported pattern (more than one LHS occurance)!" );
112 OSL_ENSURE( sMatchExpression
.indexOf( sRHSPattern
, nRHSIndex
+ 1 ) == -1,
113 "ConditionalExpression::matchExpression: unsupported pattern (more than one RHS occurance)!" );
114 // Also, an LHS must be present, and precede the RHS (if present)
115 OSL_ENSURE( ( nLHSIndex
!= -1 ) && ( ( nLHSIndex
< nRHSIndex
) || ( nRHSIndex
== -1 ) ),
116 "ConditionalExpression::matchExpression: no LHS, or an RHS preceeding the LHS - this is not supported!" );
118 // up to the occurance of the LHS (which must exist, see above), the two expressions
120 if ( _rExpression
.getLength() < nLHSIndex
)
122 const ::rtl::OUString
sExprPart1( _rExpression
.copy( 0, nLHSIndex
) );
123 const ::rtl::OUString
sMatchExprPart1( sMatchExpression
.copy( 0, nLHSIndex
) );
124 if ( sExprPart1
!= sMatchExprPart1
)
125 // the left-most expression parts do not match
128 // after the occurance of the RHS (or the LHS, if there is no RHS), the two expressions
129 // must be identical, too
130 bool bHaveRHS( nRHSIndex
!= -1 );
131 sal_Int32
nRightMostIndex( bHaveRHS
? nRHSIndex
: nLHSIndex
);
132 const ::rtl::OUString
sMatchExprPart3( sMatchExpression
.copy( nRightMostIndex
+ 2 ) );
133 if ( _rExpression
.getLength() < sMatchExprPart3
.getLength() )
134 // the expression is not even long enough to hold the right-most part of the match expression
136 const ::rtl::OUString
sExprPart3( _rExpression
.copy( _rExpression
.getLength() - sMatchExprPart3
.getLength() ) );
137 if ( sExprPart3
!= sMatchExprPart3
)
138 // the right-most expression parts do not match
141 // if we don't have an RHS, we're done
144 _out_rLHS
= _rExpression
.copy( sExprPart1
.getLength(), _rExpression
.getLength() - sExprPart1
.getLength() - sExprPart3
.getLength() );
148 // strip the match expression by its right-most and left-most part, and by the placeholders $1 and $2
149 sal_Int32
nMatchExprPart2Start( nLHSIndex
+ sLHSPattern
.getLength() );
150 ::rtl::OUString sMatchExprPart2
= sMatchExpression
.copy(
151 nMatchExprPart2Start
,
152 sMatchExpression
.getLength() - nMatchExprPart2Start
- sMatchExprPart3
.getLength() - 2
154 // strip the expression by its left-most and right-most part
155 const ::rtl::OUString
sExpression( _rExpression
.copy(
156 sExprPart1
.getLength(),
157 _rExpression
.getLength() - sExprPart1
.getLength() - sExprPart3
.getLength()
160 sal_Int32 nPart2Index
= sExpression
.indexOf( sMatchExprPart2
);
161 if ( nPart2Index
== -1 )
162 // the "middle" part of the match expression does not exist in the expression at all
165 OSL_ENSURE( sExpression
.indexOf( sMatchExprPart2
, nPart2Index
+ 1 ) == -1,
166 "ConditionalExpression::matchExpression: ambiguous matching!" );
167 // if this fires, then we're lost: The middle part exists two times in the expression,
168 // so we cannot reliably determine what's the LHS and what's the RHS.
169 // Well, the whole mechanism is flawed, anyway:
170 // Encoding the field content in the conditional expression will break as soon
172 // - assigns a Data Field to a control
173 // - creates a conditional format expression for the control
174 // - assigns another Data Field to the control
175 // - opens the Conditional Format Dialog, again
176 // Here, at the latest, you can see that we need another mechanism, anyway, which does not
177 // rely on those strange expression building/matching
179 _out_rLHS
= sExpression
.copy( 0, nPart2Index
);
180 _out_rRHS
= sExpression
.copy( nPart2Index
+ sMatchExprPart2
.getLength() );
185 // =============================================================================
186 // = ConditionalExpressionFactory
187 // =============================================================================
188 // -----------------------------------------------------------------------------
189 size_t ConditionalExpressionFactory::getKnownConditionalExpressions( ConditionalExpressions
& _out_rCondExp
)
191 ConditionalExpressions aEmpty
;
192 _out_rCondExp
.swap( aEmpty
);
194 _out_rCondExp
[ eBetween
] = PConditionalExpression( new ConditionalExpression( "AND( ( $$ ) >= ( $1 ); ( $$ ) <= ( $2 ) )" ) );
195 _out_rCondExp
[ eNotBetween
] = PConditionalExpression( new ConditionalExpression( "NOT( AND( ( $$ ) >= ( $1 ); ( $$ ) <= ( $2 ) ) )" ) );
196 _out_rCondExp
[ eEqualTo
] = PConditionalExpression( new ConditionalExpression( "( $$ ) = ( $1 )" ) );
197 _out_rCondExp
[ eNotEqualTo
] = PConditionalExpression( new ConditionalExpression( "( $$ ) <> ( $1 )" ) );
198 _out_rCondExp
[ eGreaterThan
] = PConditionalExpression( new ConditionalExpression( "( $$ ) > ( $1 )" ) );
199 _out_rCondExp
[ eLessThan
] = PConditionalExpression( new ConditionalExpression( "( $$ ) < ( $1 )" ) );
200 _out_rCondExp
[ eGreaterOrEqual
] = PConditionalExpression( new ConditionalExpression( "( $$ ) >= ( $1 )" ) );
201 _out_rCondExp
[ eLessOrEqual
] = PConditionalExpression( new ConditionalExpression( "( $$ ) <= ( $1 )" ) );
203 return _out_rCondExp
.size();
205 //........................................................................
207 //........................................................................