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 : :
29 : : #include "xsdvalidationhelper.hxx"
30 : : #include "xsddatatypes.hxx"
31 : : #include "formstrings.hxx"
32 : :
33 : : #include <com/sun/star/lang/XServiceInfo.hpp>
34 : : #include <com/sun/star/xsd/DataTypeClass.hpp>
35 : : #include <com/sun/star/util/NumberFormat.hpp>
36 : : #include <com/sun/star/util/XNumberFormatTypes.hpp>
37 : : #include <com/sun/star/util/XNumberFormatsSupplier.hpp>
38 : : #include <com/sun/star/xforms/XDataTypeRepository.hpp>
39 : : #include <unotools/syslocale.hxx>
40 : : #include <tools/diagnose_ex.h>
41 : :
42 : : //........................................................................
43 : : namespace pcr
44 : : {
45 : : //........................................................................
46 : :
47 : : using namespace ::com::sun::star;
48 : : using namespace ::com::sun::star::uno;
49 : : using namespace ::com::sun::star::beans;
50 : : using namespace ::com::sun::star::xsd;
51 : : using namespace ::com::sun::star::util;
52 : : using namespace ::com::sun::star::lang;
53 : : using namespace ::com::sun::star::xforms;
54 : :
55 : : namespace NumberFormat = ::com::sun::star::util::NumberFormat;
56 : :
57 : : //====================================================================
58 : : //= XSDValidationHelper
59 : : //====================================================================
60 : : //--------------------------------------------------------------------
61 : 0 : XSDValidationHelper::XSDValidationHelper( ::osl::Mutex& _rMutex, const Reference< XPropertySet >& _rxIntrospectee, const Reference< frame::XModel >& _rxContextDocument )
62 : : :EFormsHelper( _rMutex, _rxIntrospectee, _rxContextDocument )
63 : 0 : ,m_bInspectingFormattedField( false )
64 : : {
65 : : try
66 : : {
67 : 0 : Reference< XPropertySetInfo > xPSI;
68 : 0 : Reference< XServiceInfo > xSI( _rxIntrospectee, UNO_QUERY );
69 : 0 : if ( m_xControlModel.is() )
70 : 0 : xPSI = m_xControlModel->getPropertySetInfo();
71 : 0 : if ( xPSI.is()
72 : 0 : && xPSI->hasPropertyByName( PROPERTY_FORMATKEY )
73 : 0 : && xPSI->hasPropertyByName( PROPERTY_FORMATSSUPPLIER )
74 : 0 : && xSI.is()
75 : 0 : && xSI->supportsService( SERVICE_COMPONENT_FORMATTEDFIELD )
76 : : )
77 : 0 : m_bInspectingFormattedField = true;
78 : : }
79 : 0 : catch( const Exception& )
80 : : {
81 : : OSL_FAIL( "XSDValidationHelper::XSDValidationHelper: caught an exception while examining the introspectee!" );
82 : : }
83 : 0 : }
84 : :
85 : : //--------------------------------------------------------------------
86 : 0 : void XSDValidationHelper::getAvailableDataTypeNames( ::std::vector< ::rtl::OUString >& /* [out] */ _rNames ) const SAL_THROW(())
87 : : {
88 : 0 : _rNames.resize( 0 );
89 : :
90 : : try
91 : : {
92 : 0 : Reference< XDataTypeRepository > xRepository = getDataTypeRepository();
93 : 0 : Sequence< ::rtl::OUString > aElements;
94 : 0 : if ( xRepository.is() )
95 : 0 : aElements = xRepository->getElementNames();
96 : :
97 : 0 : _rNames.resize( aElements.getLength() );
98 : 0 : ::std::copy( aElements.getConstArray(), aElements.getConstArray() + aElements.getLength(), _rNames.begin() );
99 : : }
100 : 0 : catch( const Exception& )
101 : : {
102 : : OSL_FAIL( "XSDValidationHelper::getAvailableDataTypeNames: caught an exception!" );
103 : : }
104 : 0 : }
105 : :
106 : : //--------------------------------------------------------------------
107 : 0 : Reference< XDataTypeRepository > XSDValidationHelper::getDataTypeRepository() const SAL_THROW((Exception))
108 : : {
109 : 0 : Reference< XDataTypeRepository > xRepository;
110 : :
111 : 0 : Reference< xforms::XModel > xModel( getCurrentFormModel( ) );
112 : 0 : if ( xModel.is() )
113 : 0 : xRepository = xModel->getDataTypeRepository();
114 : :
115 : 0 : return xRepository;
116 : : }
117 : :
118 : : //--------------------------------------------------------------------
119 : 0 : Reference< XDataTypeRepository > XSDValidationHelper::getDataTypeRepository( const ::rtl::OUString& _rModelName ) const SAL_THROW((Exception))
120 : : {
121 : 0 : Reference< XDataTypeRepository > xRepository;
122 : :
123 : 0 : Reference< xforms::XModel > xModel( getFormModelByName( _rModelName ) );
124 : 0 : if ( xModel.is() )
125 : 0 : xRepository = xModel->getDataTypeRepository();
126 : :
127 : 0 : return xRepository;
128 : : }
129 : :
130 : : //--------------------------------------------------------------------
131 : 0 : Reference< XDataType > XSDValidationHelper::getDataType( const ::rtl::OUString& _rName ) const SAL_THROW((Exception))
132 : : {
133 : 0 : Reference< XDataType > xDataType;
134 : :
135 : 0 : if ( !_rName.isEmpty() )
136 : : {
137 : 0 : Reference< XDataTypeRepository > xRepository = getDataTypeRepository();
138 : 0 : if ( xRepository.is() )
139 : 0 : xDataType = xRepository->getDataType( _rName );
140 : : }
141 : 0 : return xDataType;
142 : : }
143 : :
144 : : //--------------------------------------------------------------------
145 : 0 : ::rtl::OUString XSDValidationHelper::getValidatingDataTypeName( ) const SAL_THROW(())
146 : : {
147 : 0 : ::rtl::OUString sDataTypeName;
148 : : try
149 : : {
150 : 0 : Reference< XPropertySet > xBinding( getCurrentBinding() );
151 : : // it's allowed here to not (yet) have a binding
152 : 0 : if ( xBinding.is() )
153 : : {
154 : 0 : OSL_VERIFY( xBinding->getPropertyValue( PROPERTY_XSD_DATA_TYPE ) >>= sDataTypeName );
155 : 0 : }
156 : : }
157 : 0 : catch( const Exception& )
158 : : {
159 : : OSL_FAIL( "XSDValidationHelper::getValidatingDataTypeName: caught an exception!" );
160 : : }
161 : 0 : return sDataTypeName;
162 : : }
163 : :
164 : : //--------------------------------------------------------------------
165 : 0 : ::rtl::Reference< XSDDataType > XSDValidationHelper::getDataTypeByName( const ::rtl::OUString& _rName ) const SAL_THROW(())
166 : : {
167 : 0 : ::rtl::Reference< XSDDataType > pReturn;
168 : :
169 : : try
170 : : {
171 : 0 : Reference< XDataType > xValidatedAgainst;
172 : :
173 : 0 : if ( !_rName.isEmpty() )
174 : 0 : xValidatedAgainst = getDataType( _rName );
175 : :
176 : 0 : if ( xValidatedAgainst.is() )
177 : 0 : pReturn = new XSDDataType( xValidatedAgainst );
178 : : }
179 : 0 : catch( const Exception& )
180 : : {
181 : : OSL_FAIL( "XSDValidationHelper::getDataTypeByName: caught an exception!" );
182 : : }
183 : :
184 : 0 : return pReturn;
185 : : }
186 : :
187 : : //--------------------------------------------------------------------
188 : 0 : ::rtl::Reference< XSDDataType > XSDValidationHelper::getValidatingDataType( ) const SAL_THROW(())
189 : : {
190 : 0 : return getDataTypeByName( getValidatingDataTypeName() );
191 : : }
192 : :
193 : : //--------------------------------------------------------------------
194 : 0 : bool XSDValidationHelper::cloneDataType( const ::rtl::Reference< XSDDataType >& _pDataType, const ::rtl::OUString& _rNewName ) const SAL_THROW(())
195 : : {
196 : : OSL_ENSURE( _pDataType.is(), "XSDValidationHelper::removeDataTypeFromRepository: invalid data type!" );
197 : 0 : if ( !_pDataType.is() )
198 : 0 : return false;
199 : :
200 : : try
201 : : {
202 : 0 : Reference< XDataTypeRepository > xRepository( getDataTypeRepository() );
203 : : OSL_ENSURE( xRepository.is(), "XSDValidationHelper::removeDataTypeFromRepository: invalid data type repository!" );
204 : 0 : if ( !xRepository.is() )
205 : 0 : return false;
206 : :
207 : 0 : Reference< XDataType > xDataType( _pDataType->getUnoDataType() );
208 : : OSL_ENSURE( xDataType.is(), "XSDValidationHelper::removeDataTypeFromRepository: invalid data type (II)!" );
209 : 0 : if ( !xDataType.is() )
210 : 0 : return false;
211 : :
212 : 0 : xRepository->cloneDataType( xDataType->getName(), _rNewName );
213 : : }
214 : 0 : catch( const Exception& )
215 : : {
216 : : OSL_FAIL( "XSDValidationHelper::cloneDataType: caught an exception!" );
217 : : }
218 : 0 : return true;
219 : : }
220 : :
221 : : //--------------------------------------------------------------------
222 : 0 : bool XSDValidationHelper::removeDataTypeFromRepository( const ::rtl::OUString& _rName ) const SAL_THROW(())
223 : : {
224 : : try
225 : : {
226 : 0 : Reference< XDataTypeRepository > xRepository( getDataTypeRepository() );
227 : : OSL_ENSURE( xRepository.is(), "XSDValidationHelper::removeDataTypeFromRepository: invalid data type repository!" );
228 : 0 : if ( !xRepository.is() )
229 : 0 : return false;
230 : :
231 : 0 : if ( !xRepository->hasByName( _rName ) )
232 : : {
233 : : OSL_FAIL( "XSDValidationHelper::removeDataTypeFromRepository: invalid repository and/or data type!" );
234 : 0 : return false;
235 : : }
236 : :
237 : 0 : xRepository->revokeDataType( _rName );
238 : : }
239 : 0 : catch( const Exception& )
240 : : {
241 : : OSL_FAIL( "XSDValidationHelper::removeDataTypeFromRepository: caught an exception!" );
242 : 0 : return false;
243 : : }
244 : 0 : return true;
245 : : }
246 : :
247 : : //--------------------------------------------------------------------
248 : 0 : void XSDValidationHelper::setValidatingDataTypeByName( const ::rtl::OUString& _rName ) const SAL_THROW(())
249 : : {
250 : : try
251 : : {
252 : 0 : Reference< XPropertySet > xBinding( getCurrentBinding() );
253 : : OSL_ENSURE( xBinding.is(), "XSDValidationHelper::setValidatingDataTypeByName: no active binding - how this?" );
254 : :
255 : 0 : if ( xBinding.is() )
256 : : {
257 : : // get the old data type - this is necessary for notifying property changes
258 : 0 : ::rtl::OUString sOldDataTypeName;
259 : 0 : OSL_VERIFY( xBinding->getPropertyValue( PROPERTY_XSD_DATA_TYPE ) >>= sOldDataTypeName );
260 : 0 : Reference< XPropertySet > xOldType;
261 : 0 : try { xOldType = xOldType.query( getDataType( sOldDataTypeName ) ); } catch( const Exception& ) { }
262 : :
263 : : // set the new data type name
264 : 0 : xBinding->setPropertyValue( PROPERTY_XSD_DATA_TYPE, makeAny( _rName ) );
265 : :
266 : : // retrieve the new data type object
267 : 0 : Reference< XPropertySet > xNewType( getDataType( _rName ), UNO_QUERY );
268 : :
269 : : // fire any changes in the properties which result from this new type
270 : 0 : std::set< ::rtl::OUString > aFilter; aFilter.insert( static_cast<const rtl::OUString&>(PROPERTY_NAME) );
271 : 0 : firePropertyChanges( xOldType, xNewType, aFilter );
272 : :
273 : : // fire the change in the Data Type property
274 : 0 : ::rtl::OUString sNewDataTypeName;
275 : 0 : OSL_VERIFY( xBinding->getPropertyValue( PROPERTY_XSD_DATA_TYPE ) >>= sNewDataTypeName );
276 : 0 : firePropertyChange( PROPERTY_XSD_DATA_TYPE, makeAny( sOldDataTypeName ), makeAny( sNewDataTypeName ) );
277 : 0 : }
278 : : }
279 : 0 : catch( const Exception& )
280 : : {
281 : : DBG_UNHANDLED_EXCEPTION();
282 : : }
283 : 0 : }
284 : :
285 : : //--------------------------------------------------------------------
286 : 0 : void XSDValidationHelper::copyDataType( const ::rtl::OUString& _rFromModel, const ::rtl::OUString& _rToModel,
287 : : const ::rtl::OUString& _rDataTypeName ) const SAL_THROW(())
288 : : {
289 : 0 : if ( _rFromModel == _rToModel )
290 : : // nothing to do (me thinks)
291 : 0 : return;
292 : :
293 : : try
294 : : {
295 : 0 : Reference< XDataTypeRepository > xFromRepository, xToRepository;
296 : 0 : if ( !_rFromModel.isEmpty() )
297 : 0 : xFromRepository = getDataTypeRepository( _rFromModel );
298 : 0 : if ( !_rToModel.isEmpty() )
299 : 0 : xToRepository = getDataTypeRepository( _rToModel );
300 : :
301 : 0 : if ( !xFromRepository.is() || !xToRepository.is() )
302 : : return;
303 : :
304 : 0 : if ( !xFromRepository->hasByName( _rDataTypeName ) || xToRepository->hasByName( _rDataTypeName ) )
305 : : // not existent in the source, or already existent (by name) in the destination
306 : : return;
307 : :
308 : : // determine the built-in type belonging to the source type
309 : 0 : ::rtl::Reference< XSDDataType > pSourceType = new XSDDataType( xFromRepository->getDataType( _rDataTypeName ) );
310 : 0 : ::rtl::OUString sTargetBaseType = getBasicTypeNameForClass( pSourceType->classify(), xToRepository );
311 : :
312 : : // create the target type
313 : 0 : Reference< XDataType > xTargetType = xToRepository->cloneDataType( sTargetBaseType, _rDataTypeName );
314 : 0 : ::rtl::Reference< XSDDataType > pTargetType = new XSDDataType( xTargetType );
315 : :
316 : : // copy the facets
317 : 0 : pTargetType->copyFacetsFrom( pSourceType );
318 : : }
319 : 0 : catch( const Exception& )
320 : : {
321 : : OSL_FAIL( "XSDValidationHelper::copyDataType: caught an exception!" );
322 : : }
323 : : }
324 : :
325 : : //--------------------------------------------------------------------
326 : 0 : void XSDValidationHelper::findDefaultFormatForIntrospectee() SAL_THROW(())
327 : : {
328 : : try
329 : : {
330 : 0 : ::rtl::Reference< XSDDataType > xDataType = getValidatingDataType();
331 : 0 : if ( xDataType.is() )
332 : : {
333 : : // find a NumberFormat type corresponding to the DataTypeClass
334 : 0 : sal_Int16 nNumberFormatType = NumberFormat::NUMBER;
335 : 0 : switch ( xDataType->classify() )
336 : : {
337 : : case DataTypeClass::DATETIME:
338 : 0 : nNumberFormatType = NumberFormat::DATETIME;
339 : 0 : break;
340 : : case DataTypeClass::DATE:
341 : 0 : nNumberFormatType = NumberFormat::DATE;
342 : 0 : break;
343 : : case DataTypeClass::TIME:
344 : 0 : nNumberFormatType = NumberFormat::TIME;
345 : 0 : break;
346 : : case DataTypeClass::STRING:
347 : : case DataTypeClass::anyURI:
348 : : case DataTypeClass::QName:
349 : : case DataTypeClass::NOTATION:
350 : 0 : nNumberFormatType = NumberFormat::TEXT;
351 : 0 : break;
352 : : }
353 : :
354 : : // get the number formatter from the introspectee
355 : 0 : Reference< XNumberFormatsSupplier > xSupplier;
356 : 0 : Reference< XNumberFormatTypes > xFormatTypes;
357 : 0 : OSL_VERIFY( m_xControlModel->getPropertyValue( PROPERTY_FORMATSSUPPLIER ) >>= xSupplier );
358 : 0 : if ( xSupplier.is() )
359 : 0 : xFormatTypes = xFormatTypes.query( xSupplier->getNumberFormats() );
360 : : OSL_ENSURE( xFormatTypes.is(), "XSDValidationHelper::findDefaultFormatForIntrospectee: no number formats for the introspectee!" );
361 : 0 : if ( !xFormatTypes.is() )
362 : 0 : return;
363 : :
364 : : // and the standard format for the given NumberFormat type
365 : 0 : sal_Int32 nDesiredFormat = xFormatTypes->getStandardFormat( nNumberFormatType, SvtSysLocale().GetLocaleData().getLocale() );
366 : :
367 : : // set this at the introspectee
368 : 0 : m_xControlModel->setPropertyValue( PROPERTY_FORMATKEY, makeAny( nDesiredFormat ) );
369 : 0 : }
370 : : }
371 : 0 : catch( const Exception& )
372 : : {
373 : : OSL_FAIL( "XSDValidationHelper::findDefaultFormatForIntrospectee: caught an exception!" );
374 : : }
375 : : }
376 : :
377 : : //--------------------------------------------------------------------
378 : 0 : ::rtl::OUString XSDValidationHelper::getBasicTypeNameForClass( sal_Int16 _nClass ) const SAL_THROW(())
379 : : {
380 : 0 : return getBasicTypeNameForClass( _nClass, getDataTypeRepository() );
381 : : }
382 : :
383 : : //--------------------------------------------------------------------
384 : 0 : ::rtl::OUString XSDValidationHelper::getBasicTypeNameForClass( sal_Int16 _nClass, Reference< XDataTypeRepository > _rxRepository ) const SAL_THROW(())
385 : : {
386 : 0 : ::rtl::OUString sReturn;
387 : : OSL_ENSURE( _rxRepository.is(), "XSDValidationHelper::getBasicTypeNameForClass: invalid repository!" );
388 : 0 : if ( !_rxRepository.is() )
389 : 0 : return sReturn;
390 : :
391 : : try
392 : : {
393 : 0 : Reference< XDataType > xDataType = _rxRepository->getBasicDataType( _nClass );
394 : : OSL_ENSURE( xDataType.is(), "XSDValidationHelper::getBasicTypeNameForClass: invalid data type returned!" );
395 : 0 : if ( xDataType.is() )
396 : 0 : sReturn = xDataType->getName();
397 : : }
398 : 0 : catch( const Exception& )
399 : : {
400 : : OSL_FAIL( "XSDValidationHelper::getBasicTypeNameForClass: caught an exception!" );
401 : : }
402 : :
403 : 0 : return sReturn;
404 : : }
405 : :
406 : : //........................................................................
407 : : } // namespace pcr
408 : : //........................................................................
409 : :
410 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|