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