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