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 : :
30 : : #include "SchemaRestrictionContext.hxx"
31 : : #include "xformsapi.hxx"
32 : :
33 : : #include <xmloff/xmltoken.hxx>
34 : : #include <xmloff/nmspmap.hxx>
35 : : #include <xmloff/xmlnmspe.hxx>
36 : : #include <xmloff/xmltkmap.hxx>
37 : : #include <xmloff/xmlimp.hxx>
38 : :
39 : : #include <sax/tools/converter.hxx>
40 : :
41 : : #include <com/sun/star/beans/XPropertySet.hpp>
42 : : #include <com/sun/star/uno/Type.hxx>
43 : : #include <com/sun/star/util/Date.hpp>
44 : : #include <com/sun/star/util/Time.hpp>
45 : : #include <com/sun/star/util/DateTime.hpp>
46 : : #include <com/sun/star/util/Duration.hpp>
47 : : #include <com/sun/star/xforms/XDataTypeRepository.hpp>
48 : : #include <com/sun/star/xsd/DataTypeClass.hpp>
49 : : #include <com/sun/star/xsd/WhiteSpaceTreatment.hpp>
50 : :
51 : : #include <tools/debug.hxx>
52 : :
53 : :
54 : : using rtl::OUString;
55 : : using com::sun::star::uno::Reference;
56 : : using com::sun::star::uno::Exception;
57 : : using com::sun::star::uno::Any;
58 : : using com::sun::star::uno::makeAny;
59 : : using com::sun::star::uno::UNO_QUERY;
60 : : using com::sun::star::util::Date;
61 : : using com::sun::star::util::DateTime;
62 : : using com::sun::star::util::Duration;
63 : : using com::sun::star::xml::sax::XAttributeList;
64 : : using com::sun::star::beans::XPropertySet;
65 : : using com::sun::star::beans::XPropertySetInfo;
66 : : using com::sun::star::xforms::XDataTypeRepository;
67 : : using namespace xmloff::token;
68 : :
69 : :
70 : :
71 : :
72 : : static SvXMLTokenMapEntry aAttributes[] =
73 : : {
74 : : TOKEN_MAP_ENTRY( NONE, BASE ),
75 : : XML_TOKEN_MAP_END
76 : : };
77 : :
78 : : static SvXMLTokenMapEntry aChildren[] =
79 : : {
80 : : TOKEN_MAP_ENTRY( XSD, LENGTH ),
81 : : TOKEN_MAP_ENTRY( XSD, MINLENGTH ),
82 : : TOKEN_MAP_ENTRY( XSD, MAXLENGTH ),
83 : : TOKEN_MAP_ENTRY( XSD, MININCLUSIVE ),
84 : : TOKEN_MAP_ENTRY( XSD, MINEXCLUSIVE ),
85 : : TOKEN_MAP_ENTRY( XSD, MAXINCLUSIVE ),
86 : : TOKEN_MAP_ENTRY( XSD, MAXEXCLUSIVE ),
87 : : TOKEN_MAP_ENTRY( XSD, PATTERN ),
88 : : // ??? XML_ENUMERATION
89 : : TOKEN_MAP_ENTRY( XSD, WHITESPACE ),
90 : : TOKEN_MAP_ENTRY( XSD, TOTALDIGITS ),
91 : : TOKEN_MAP_ENTRY( XSD, FRACTIONDIGITS ),
92 : : XML_TOKEN_MAP_END
93 : : };
94 : :
95 : :
96 : 0 : SchemaRestrictionContext::SchemaRestrictionContext(
97 : : SvXMLImport& rImport,
98 : : sal_uInt16 nPrefix,
99 : : const OUString& rLocalName,
100 : : Reference<com::sun::star::xforms::XDataTypeRepository>& rRepository,
101 : : const OUString& sTypeName ) :
102 : : TokenContext( rImport, nPrefix, rLocalName, aAttributes, aChildren ),
103 : : mxRepository( rRepository ),
104 : : msTypeName( sTypeName ),
105 : 0 : msBaseName()
106 : : {
107 : : DBG_ASSERT( mxRepository.is(), "need repository" );
108 : 0 : }
109 : :
110 : 0 : SchemaRestrictionContext::~SchemaRestrictionContext()
111 : : {
112 [ # # ]: 0 : }
113 : :
114 : 0 : void SchemaRestrictionContext::CreateDataType()
115 : : {
116 : : // only do something if we don't have a data type already
117 [ # # ]: 0 : if( mxDataType.is() )
118 : 0 : return;
119 : :
120 : : DBG_ASSERT( !msBaseName.isEmpty(), "no base name?" );
121 : : DBG_ASSERT( mxRepository.is(), "no repository?" );
122 : :
123 : : try
124 : : {
125 : : mxDataType =
126 : : Reference<XPropertySet>(
127 [ # # ]: 0 : mxRepository->cloneDataType(
128 : : lcl_getBasicTypeName( mxRepository,
129 : 0 : GetImport().GetNamespaceMap(),
130 : : msBaseName ),
131 : 0 : msTypeName ),
132 [ # # ][ # # ]: 0 : UNO_QUERY );
[ # # ][ # # ]
[ # # ]
133 : : }
134 : 0 : catch( const Exception& )
135 : : {
136 : : OSL_FAIL( "exception during type creation" );
137 : : }
138 : : DBG_ASSERT( mxDataType.is(), "can't create type" );
139 : : }
140 : :
141 : 0 : void SchemaRestrictionContext::HandleAttribute(
142 : : sal_uInt16 nToken,
143 : : const OUString& rValue )
144 : : {
145 [ # # ]: 0 : if( nToken == XML_BASE )
146 : : {
147 : 0 : msBaseName = rValue;
148 : : }
149 : 0 : }
150 : :
151 : : typedef Any (*convert_t)( const OUString& );
152 : :
153 : 0 : Any lcl_string( const OUString& rValue )
154 : : {
155 : 0 : return makeAny( rValue );
156 : : }
157 : :
158 : 0 : Any lcl_int32( const OUString& rValue )
159 : : {
160 : : sal_Int32 nValue;
161 [ # # ]: 0 : bool bSuccess = ::sax::Converter::convertNumber( nValue, rValue );
162 [ # # ][ # # ]: 0 : return bSuccess ? makeAny( nValue ) : Any();
163 : : }
164 : :
165 : 0 : Any lcl_int16( const OUString& rValue )
166 : : {
167 : : sal_Int32 nValue;
168 [ # # ]: 0 : bool bSuccess = ::sax::Converter::convertNumber( nValue, rValue );
169 [ # # ][ # # ]: 0 : return bSuccess ? makeAny( static_cast<sal_Int16>( nValue ) ) : Any();
[ # # ][ # # ]
170 : : }
171 : :
172 : 0 : Any lcl_whitespace( const OUString& rValue )
173 : : {
174 : 0 : Any aValue;
175 [ # # ][ # # ]: 0 : if( IsXMLToken( rValue, XML_PRESERVE ) )
176 [ # # ]: 0 : aValue <<= com::sun::star::xsd::WhiteSpaceTreatment::Preserve;
177 [ # # ][ # # ]: 0 : else if( IsXMLToken( rValue, XML_REPLACE ) )
178 [ # # ]: 0 : aValue <<= com::sun::star::xsd::WhiteSpaceTreatment::Replace;
179 [ # # ][ # # ]: 0 : else if( IsXMLToken( rValue, XML_COLLAPSE ) )
180 [ # # ]: 0 : aValue <<= com::sun::star::xsd::WhiteSpaceTreatment::Collapse;
181 : 0 : return aValue;
182 : : }
183 : :
184 : 0 : Any lcl_double( const OUString& rValue )
185 : : {
186 : : double fValue;
187 [ # # ]: 0 : bool bSuccess = ::sax::Converter::convertDouble( fValue, rValue );
188 [ # # ][ # # ]: 0 : return bSuccess ? makeAny( fValue ) : Any();
189 : : }
190 : :
191 : 0 : Any lcl_date( const OUString& rValue )
192 : : {
193 : 0 : Any aAny;
194 : :
195 : : // parse ISO date
196 : 0 : sal_Int32 nPos1 = rValue.indexOf( sal_Unicode('-') );
197 : 0 : sal_Int32 nPos2 = rValue.indexOf( sal_Unicode('-'), nPos1 + 1 );
198 [ # # ][ # # ]: 0 : if( nPos1 > 0 && nPos2 > 0 )
199 : : {
200 : 0 : Date aDate;
201 : : aDate.Year = static_cast<sal_uInt16>(
202 : 0 : rValue.copy( 0, nPos1 ).toInt32() );
203 : : aDate.Month = static_cast<sal_uInt16>(
204 : 0 : rValue.copy( nPos1 + 1, nPos2 - nPos1 - 1 ).toInt32() );
205 : : aDate.Day = static_cast<sal_uInt16>(
206 : 0 : rValue.copy( nPos2 + 1 ).toInt32() );
207 [ # # ]: 0 : aAny <<= aDate;
208 : : }
209 : 0 : return aAny;
210 : : }
211 : :
212 : 0 : Any lcl_dateTime( const OUString& rValue )
213 : : {
214 : 0 : DateTime aDateTime;
215 [ # # ]: 0 : bool const bSuccess = ::sax::Converter::convertDateTime(aDateTime, rValue);
216 [ # # ][ # # ]: 0 : return bSuccess ? makeAny( aDateTime ) : Any();
217 : : }
218 : :
219 : 0 : Any lcl_time( const OUString& rValue )
220 : : {
221 : 0 : Any aAny;
222 : 0 : Duration aDuration;
223 [ # # ][ # # ]: 0 : if (::sax::Converter::convertDuration( aDuration, rValue ))
224 : : {
225 : 0 : com::sun::star::util::Time aTime;
226 : 0 : aTime.Hours = aDuration.Hours;
227 : 0 : aTime.Minutes = aDuration.Minutes;
228 : 0 : aTime.Seconds = aDuration.Seconds;
229 : 0 : aTime.HundredthSeconds = aDuration.MilliSeconds / 10;
230 [ # # ]: 0 : aAny <<= aTime;
231 : : }
232 : 0 : return aAny;
233 : : }
234 : :
235 : :
236 : 0 : SvXMLImportContext* SchemaRestrictionContext::HandleChild(
237 : : sal_uInt16 nToken,
238 : : sal_uInt16 nPrefix,
239 : : const OUString& rLocalName,
240 : : const Reference<XAttributeList>& xAttrList )
241 : : {
242 : : // find value
243 : 0 : OUString sValue;
244 [ # # ][ # # ]: 0 : sal_Int16 nLength = xAttrList->getLength();
245 [ # # ]: 0 : for( sal_Int16 n = 0; n < nLength; n++ )
246 : : {
247 [ # # ][ # # ]: 0 : if( IsXMLToken( xAttrList->getNameByIndex( n ), XML_VALUE ) )
[ # # ][ # # ]
248 [ # # ][ # # ]: 0 : sValue = xAttrList->getValueByIndex( n );
249 : : }
250 : :
251 : : // determine property name + suitable converter
252 : 0 : OUString sPropertyName;
253 : 0 : convert_t pConvert = NULL;
254 [ # # # # : 0 : switch( nToken )
# # # #
# ]
255 : : {
256 : : case XML_LENGTH:
257 [ # # ]: 0 : sPropertyName = OUString(RTL_CONSTASCII_USTRINGPARAM("Length"));
258 : 0 : pConvert = &lcl_int32;
259 : 0 : break;
260 : : case XML_MINLENGTH:
261 [ # # ]: 0 : sPropertyName = OUString(RTL_CONSTASCII_USTRINGPARAM("MinLength"));
262 : 0 : pConvert = &lcl_int32;
263 : 0 : break;
264 : : case XML_MAXLENGTH:
265 [ # # ]: 0 : sPropertyName = OUString(RTL_CONSTASCII_USTRINGPARAM("MaxLength"));
266 : 0 : pConvert = &lcl_int32;
267 : 0 : break;
268 : : case XML_TOTALDIGITS:
269 [ # # ]: 0 : sPropertyName = OUString(RTL_CONSTASCII_USTRINGPARAM("TotalDigits"));
270 : 0 : pConvert = &lcl_int32;
271 : 0 : break;
272 : : case XML_FRACTIONDIGITS:
273 [ # # ]: 0 : sPropertyName =OUString(RTL_CONSTASCII_USTRINGPARAM("FractionDigits"));
274 : 0 : pConvert = &lcl_int32;
275 : 0 : break;
276 : : case XML_PATTERN:
277 [ # # ]: 0 : sPropertyName = OUString(RTL_CONSTASCII_USTRINGPARAM("Pattern"));
278 : 0 : pConvert = &lcl_string;
279 : 0 : break;
280 : : case XML_WHITESPACE:
281 [ # # ]: 0 : sPropertyName = OUString(RTL_CONSTASCII_USTRINGPARAM("WhiteSpace"));
282 : 0 : pConvert = &lcl_whitespace;
283 : 0 : break;
284 : : case XML_MININCLUSIVE:
285 : : case XML_MINEXCLUSIVE:
286 : : case XML_MAXINCLUSIVE:
287 : : case XML_MAXEXCLUSIVE:
288 : : {
289 : : // these attributes are mapped to different properties.
290 : : // To determine the property name, we use an attribute
291 : : // dependent prefix and a type dependent suffix. The
292 : : // converter is only type dependent.
293 : :
294 : : // first, attribute-dependent prefix
295 [ # # # # : 0 : switch( nToken )
# ]
296 : : {
297 : : case XML_MININCLUSIVE:
298 [ # # ]: 0 : sPropertyName = OUString(RTL_CONSTASCII_USTRINGPARAM("MinInclusive"));
299 : 0 : break;
300 : : case XML_MINEXCLUSIVE:
301 [ # # ]: 0 : sPropertyName = OUString(RTL_CONSTASCII_USTRINGPARAM("MinExclusive"));
302 : 0 : break;
303 : : case XML_MAXINCLUSIVE:
304 [ # # ]: 0 : sPropertyName = OUString(RTL_CONSTASCII_USTRINGPARAM("MaxInclusive"));
305 : 0 : break;
306 : : case XML_MAXEXCLUSIVE:
307 [ # # ]: 0 : sPropertyName = OUString(RTL_CONSTASCII_USTRINGPARAM("MaxExclusive"));
308 : 0 : break;
309 : : }
310 : :
311 : : // second, type-dependent suffix + converter
312 [ # # # # : 0 : switch( lcl_getTypeClass( mxRepository,
# # # ]
313 : 0 : GetImport().GetNamespaceMap(),
314 [ # # ]: 0 : msBaseName ) )
315 : : {
316 : : case com::sun::star::xsd::DataTypeClass::DECIMAL:
317 : : case com::sun::star::xsd::DataTypeClass::DOUBLE:
318 : : case com::sun::star::xsd::DataTypeClass::FLOAT:
319 [ # # ]: 0 : sPropertyName += OUString(RTL_CONSTASCII_USTRINGPARAM("Double"));
320 : 0 : pConvert = &lcl_double;
321 : 0 : break;
322 : : case com::sun::star::xsd::DataTypeClass::DATETIME:
323 [ # # ]: 0 : sPropertyName += OUString(RTL_CONSTASCII_USTRINGPARAM("DateTime"));
324 : 0 : pConvert = &lcl_dateTime;
325 : 0 : break;
326 : : case com::sun::star::xsd::DataTypeClass::DATE:
327 [ # # ]: 0 : sPropertyName += OUString(RTL_CONSTASCII_USTRINGPARAM("Date"));
328 : 0 : pConvert = &lcl_date;
329 : 0 : break;
330 : : case com::sun::star::xsd::DataTypeClass::TIME:
331 [ # # ]: 0 : sPropertyName += OUString(RTL_CONSTASCII_USTRINGPARAM("Time"));
332 : 0 : pConvert = &lcl_time;
333 : 0 : break;
334 : : case com::sun::star::xsd::DataTypeClass::gYear:
335 : : case com::sun::star::xsd::DataTypeClass::gDay:
336 : : case com::sun::star::xsd::DataTypeClass::gMonth:
337 [ # # ]: 0 : sPropertyName += OUString(RTL_CONSTASCII_USTRINGPARAM("Int"));
338 : 0 : pConvert = &lcl_int16;
339 : 0 : break;
340 : :
341 : : case com::sun::star::xsd::DataTypeClass::STRING:
342 : : case com::sun::star::xsd::DataTypeClass::anyURI:
343 : : case com::sun::star::xsd::DataTypeClass::BOOLEAN:
344 : : // invalid: These shouldn't have min/max-inclusive
345 : 0 : break;
346 : :
347 : : /* data types not yet supported:
348 : : case com::sun::star::xsd::DataTypeClass::DURATION:
349 : : case com::sun::star::xsd::DataTypeClass::gYearMonth:
350 : : case com::sun::star::xsd::DataTypeClass::gMonthDay:
351 : : case com::sun::star::xsd::DataTypeClass::hexBinary:
352 : : case com::sun::star::xsd::DataTypeClass::base64Binary:
353 : : case com::sun::star::xsd::DataTypeClass::QName:
354 : : case com::sun::star::xsd::DataTypeClass::NOTATION:
355 : : */
356 : : }
357 : : }
358 : 0 : break;
359 : :
360 : : default:
361 : : OSL_FAIL( "unknown facet" );
362 : : }
363 : :
364 : : // finally, set the property
365 [ # # ]: 0 : CreateDataType();
366 [ # # # # ]: 0 : if( mxDataType.is()
[ # # ][ # # ]
[ # # ]
367 : 0 : && !sPropertyName.isEmpty()
368 : : && pConvert != NULL
369 [ # # ][ # # ]: 0 : && mxDataType->getPropertySetInfo()->hasPropertyByName(sPropertyName) )
[ # # ][ # # ]
[ # # ][ # # ]
370 : : {
371 : : try
372 : : {
373 [ # # ][ # # ]: 0 : mxDataType->setPropertyValue( sPropertyName, pConvert( sValue ) );
[ # # ][ # # ]
374 : : }
375 [ # # ]: 0 : catch( const Exception& )
376 : : {
377 : : ; // can't set property? Then ignore.
378 : : }
379 : : }
380 : :
381 [ # # ][ # # ]: 0 : return new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
382 : : }
383 : :
384 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|