1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
19 #include "conditionalexpression.hxx"
21 //........................................................................
24 // =============================================================================
25 // = ConditionalExpression
26 // =============================================================================
27 // -----------------------------------------------------------------------------
28 ConditionalExpression::ConditionalExpression( const sal_Char
* _pAsciiPattern
)
29 :m_sPattern( OUString::createFromAscii( _pAsciiPattern
) )
33 // -----------------------------------------------------------------------------
34 OUString
ConditionalExpression::assembleExpression( const OUString
& _rFieldDataSource
, const OUString
& _rLHS
, const OUString
& _rRHS
) const
36 OUString
sExpression( m_sPattern
);
38 sal_Int32 nPatternIndex
= sExpression
.indexOf( '$' );
39 while ( nPatternIndex
> -1 )
41 const OUString
* pReplace
= NULL
;
42 switch ( sExpression
.getStr()[ nPatternIndex
+ 1 ] )
44 case '$': pReplace
= &_rFieldDataSource
; break;
45 case '1': pReplace
= &_rLHS
; break;
46 case '2': pReplace
= &_rRHS
; break;
50 if ( pReplace
== NULL
)
52 OSL_FAIL( "ConditionalExpression::assembleExpression: illegal pattern!" );
56 sExpression
= sExpression
.replaceAt( nPatternIndex
, 2, *pReplace
);
57 nPatternIndex
= sExpression
.indexOf( '$', nPatternIndex
+ pReplace
->getLength() + 1 );
62 // -----------------------------------------------------------------------------
63 bool ConditionalExpression::matchExpression( const OUString
& _rExpression
, const OUString
& _rFieldDataSource
, OUString
& _out_rLHS
, OUString
& _out_rRHS
) const
66 (void)_rFieldDataSource
;
70 // if we had regular expression, the matching would be pretty easy ...
71 // just replace $1 and $2 in the pattern with (.*), and then get them with \1 resp. \2.
72 // Unfortunately, we don't have such a regexp engine ...
74 // Okay, let's start with replacing all $$ in our pattern with the actual field data source
75 OUString
sMatchExpression( m_sPattern
);
76 const OUString
sFieldDataPattern( "$$" );
77 sal_Int32
nIndex( sMatchExpression
.indexOf( sFieldDataPattern
) );
78 while ( nIndex
!= -1 )
80 sMatchExpression
= sMatchExpression
.replaceAt( nIndex
, sFieldDataPattern
.getLength(), _rFieldDataSource
);
81 nIndex
= sMatchExpression
.indexOf( sFieldDataPattern
, nIndex
+ _rFieldDataSource
.getLength() );
84 const OUString
sLHSPattern( "$1" );
85 const OUString
sRHSPattern( "$2" );
86 sal_Int32
nLHSIndex( sMatchExpression
.indexOf( sLHSPattern
) );
87 sal_Int32
nRHSIndex( sMatchExpression
.indexOf( sRHSPattern
) );
89 // now we should have at most one occurrence of $1 and $2, resp.
90 OSL_ENSURE( sMatchExpression
.indexOf( sLHSPattern
, nLHSIndex
+ 1 ) == -1,
91 "ConditionalExpression::matchExpression: unsupported pattern (more than one LHS occurrence)!" );
92 OSL_ENSURE( sMatchExpression
.indexOf( sRHSPattern
, nRHSIndex
+ 1 ) == -1,
93 "ConditionalExpression::matchExpression: unsupported pattern (more than one RHS occurrence)!" );
94 // Also, an LHS must be present, and precede the RHS (if present)
95 OSL_ENSURE( ( nLHSIndex
!= -1 ) && ( ( nLHSIndex
< nRHSIndex
) || ( nRHSIndex
== -1 ) ),
96 "ConditionalExpression::matchExpression: no LHS, or an RHS preceeding the LHS - this is not supported!" );
98 // up to the occurrence of the LHS (which must exist, see above), the two expressions
100 if ( _rExpression
.getLength() < nLHSIndex
)
102 const OUString
sExprPart1( _rExpression
.copy( 0, nLHSIndex
) );
103 const OUString
sMatchExprPart1( sMatchExpression
.copy( 0, nLHSIndex
) );
104 if ( sExprPart1
!= sMatchExprPart1
)
105 // the left-most expression parts do not match
108 // after the occurrence of the RHS (or the LHS, if there is no RHS), the two expressions
109 // must be identical, too
110 bool bHaveRHS( nRHSIndex
!= -1 );
111 sal_Int32
nRightMostIndex( bHaveRHS
? nRHSIndex
: nLHSIndex
);
112 const OUString
sMatchExprPart3( sMatchExpression
.copy( nRightMostIndex
+ 2 ) );
113 if ( _rExpression
.getLength() < sMatchExprPart3
.getLength() )
114 // the expression is not even long enough to hold the right-most part of the match expression
116 const OUString
sExprPart3( _rExpression
.copy( _rExpression
.getLength() - sMatchExprPart3
.getLength() ) );
117 if ( sExprPart3
!= sMatchExprPart3
)
118 // the right-most expression parts do not match
121 // if we don't have an RHS, we're done
124 _out_rLHS
= _rExpression
.copy( sExprPart1
.getLength(), _rExpression
.getLength() - sExprPart1
.getLength() - sExprPart3
.getLength() );
128 // strip the match expression by its right-most and left-most part, and by the placeholders $1 and $2
129 sal_Int32
nMatchExprPart2Start( nLHSIndex
+ sLHSPattern
.getLength() );
130 OUString sMatchExprPart2
= sMatchExpression
.copy(
131 nMatchExprPart2Start
,
132 sMatchExpression
.getLength() - nMatchExprPart2Start
- sMatchExprPart3
.getLength() - 2
134 // strip the expression by its left-most and right-most part
135 const OUString
sExpression( _rExpression
.copy(
136 sExprPart1
.getLength(),
137 _rExpression
.getLength() - sExprPart1
.getLength() - sExprPart3
.getLength()
140 sal_Int32 nPart2Index
= sExpression
.indexOf( sMatchExprPart2
);
141 if ( nPart2Index
== -1 )
142 // the "middle" part of the match expression does not exist in the expression at all
145 OSL_ENSURE( sExpression
.indexOf( sMatchExprPart2
, nPart2Index
+ 1 ) == -1,
146 "ConditionalExpression::matchExpression: ambiguous matching!" );
147 // if this fires, then we're lost: The middle part exists two times in the expression,
148 // so we cannot reliably determine what's the LHS and what's the RHS.
149 // Well, the whole mechanism is flawed, anyway:
150 // Encoding the field content in the conditional expression will break as soon
152 // - assigns a Data Field to a control
153 // - creates a conditional format expression for the control
154 // - assigns another Data Field to the control
155 // - opens the Conditional Format Dialog, again
156 // Here, at the latest, you can see that we need another mechanism, anyway, which does not
157 // rely on those strange expression building/matching
159 _out_rLHS
= sExpression
.copy( 0, nPart2Index
);
160 _out_rRHS
= sExpression
.copy( nPart2Index
+ sMatchExprPart2
.getLength() );
165 // =============================================================================
166 // = ConditionalExpressionFactory
167 // =============================================================================
168 // -----------------------------------------------------------------------------
169 size_t ConditionalExpressionFactory::getKnownConditionalExpressions( ConditionalExpressions
& _out_rCondExp
)
171 ConditionalExpressions aEmpty
;
172 _out_rCondExp
.swap( aEmpty
);
174 _out_rCondExp
[ eBetween
] = PConditionalExpression( new ConditionalExpression( "AND( ( $$ ) >= ( $1 ); ( $$ ) <= ( $2 ) )" ) );
175 _out_rCondExp
[ eNotBetween
] = PConditionalExpression( new ConditionalExpression( "NOT( AND( ( $$ ) >= ( $1 ); ( $$ ) <= ( $2 ) ) )" ) );
176 _out_rCondExp
[ eEqualTo
] = PConditionalExpression( new ConditionalExpression( "( $$ ) = ( $1 )" ) );
177 _out_rCondExp
[ eNotEqualTo
] = PConditionalExpression( new ConditionalExpression( "( $$ ) <> ( $1 )" ) );
178 _out_rCondExp
[ eGreaterThan
] = PConditionalExpression( new ConditionalExpression( "( $$ ) > ( $1 )" ) );
179 _out_rCondExp
[ eLessThan
] = PConditionalExpression( new ConditionalExpression( "( $$ ) < ( $1 )" ) );
180 _out_rCondExp
[ eGreaterOrEqual
] = PConditionalExpression( new ConditionalExpression( "( $$ ) >= ( $1 )" ) );
181 _out_rCondExp
[ eLessOrEqual
] = PConditionalExpression( new ConditionalExpression( "( $$ ) <= ( $1 )" ) );
183 return _out_rCondExp
.size();
185 //........................................................................
187 //........................................................................
189 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */