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