1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include "SchemaRestrictionContext.hxx"
22 #include "xformsapi.hxx"
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>
30 #include <sax/tools/converter.hxx>
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>
42 #include <tools/debug.hxx>
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
;
61 static SvXMLTokenMapEntry aAttributes
[] =
63 TOKEN_MAP_ENTRY( NONE
, BASE
),
67 static SvXMLTokenMapEntry aChildren
[] =
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
),
85 SchemaRestrictionContext::SchemaRestrictionContext(
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
),
96 DBG_ASSERT( mxRepository
.is(), "need repository" );
99 SchemaRestrictionContext::~SchemaRestrictionContext()
103 void SchemaRestrictionContext::CreateDataType()
105 // only do something if we don't have a data type already
106 if( mxDataType
.is() )
109 DBG_ASSERT( !msBaseName
.isEmpty(), "no base name?" );
110 DBG_ASSERT( mxRepository
.is(), "no repository?" );
115 Reference
<XPropertySet
>(
116 mxRepository
->cloneDataType(
117 xforms_getBasicTypeName( mxRepository
,
118 GetImport().GetNamespaceMap(),
123 catch( const Exception
& )
125 OSL_FAIL( "exception during type creation" );
127 DBG_ASSERT( mxDataType
.is(), "can't create type" );
130 void SchemaRestrictionContext::HandleAttribute(
132 const OUString
& rValue
)
134 if( nToken
== XML_BASE
)
140 typedef Any (*convert_t
)( const OUString
& );
142 Any
xforms_string( const OUString
& rValue
)
144 return makeAny( rValue
);
147 Any
xforms_int32( const OUString
& rValue
)
150 bool bSuccess
= ::sax::Converter::convertNumber( nValue
, rValue
);
151 return bSuccess
? makeAny( nValue
) : Any();
154 Any
xforms_int16( const OUString
& rValue
)
157 bool bSuccess
= ::sax::Converter::convertNumber( nValue
, rValue
);
158 return bSuccess
? makeAny( static_cast<sal_Int16
>( nValue
) ) : Any();
161 Any
xforms_whitespace( const OUString
& rValue
)
164 if( IsXMLToken( rValue
, XML_PRESERVE
) )
165 aValue
<<= com::sun::star::xsd::WhiteSpaceTreatment::Preserve
;
166 else if( IsXMLToken( rValue
, XML_REPLACE
) )
167 aValue
<<= com::sun::star::xsd::WhiteSpaceTreatment::Replace
;
168 else if( IsXMLToken( rValue
, XML_COLLAPSE
) )
169 aValue
<<= com::sun::star::xsd::WhiteSpaceTreatment::Collapse
;
173 Any
xforms_double( const OUString
& rValue
)
176 bool bSuccess
= ::sax::Converter::convertDouble( fValue
, rValue
);
177 return bSuccess
? makeAny( fValue
) : Any();
180 Any
xforms_date( const OUString
& rValue
)
185 sal_Int32 nPos1
= rValue
.indexOf( sal_Unicode('-') );
186 sal_Int32 nPos2
= rValue
.indexOf( sal_Unicode('-'), nPos1
+ 1 );
187 if( nPos1
> 0 && nPos2
> 0 )
190 aDate
.Year
= static_cast<sal_uInt16
>(
191 rValue
.copy( 0, nPos1
).toInt32() );
192 aDate
.Month
= static_cast<sal_uInt16
>(
193 rValue
.copy( nPos1
+ 1, nPos2
- nPos1
- 1 ).toInt32() );
194 aDate
.Day
= static_cast<sal_uInt16
>(
195 rValue
.copy( nPos2
+ 1 ).toInt32() );
201 Any
xforms_dateTime( const OUString
& rValue
)
203 util::DateTime aDateTime
;
204 bool const bSuccess
= ::sax::Converter::convertDateTime(aDateTime
, rValue
);
205 return bSuccess
? makeAny( aDateTime
) : Any();
208 Any
xforms_time( const OUString
& rValue
)
212 if (::sax::Converter::convertDuration( aDuration
, rValue
))
214 com::sun::star::util::Time aTime
;
215 aTime
.Hours
= aDuration
.Hours
;
216 aTime
.Minutes
= aDuration
.Minutes
;
217 aTime
.Seconds
= aDuration
.Seconds
;
218 aTime
.NanoSeconds
= aDuration
.NanoSeconds
;
225 SvXMLImportContext
* SchemaRestrictionContext::HandleChild(
228 const OUString
& rLocalName
,
229 const Reference
<XAttributeList
>& xAttrList
)
233 sal_Int16 nLength
= xAttrList
->getLength();
234 for( sal_Int16 n
= 0; n
< nLength
; n
++ )
236 if( IsXMLToken( xAttrList
->getNameByIndex( n
), XML_VALUE
) )
237 sValue
= xAttrList
->getValueByIndex( n
);
240 // determine property name + suitable converter
241 OUString sPropertyName
;
242 convert_t pConvert
= NULL
;
246 sPropertyName
= "Length";
247 pConvert
= &xforms_int32
;
250 sPropertyName
= "MinLength";
251 pConvert
= &xforms_int32
;
254 sPropertyName
= "MaxLength";
255 pConvert
= &xforms_int32
;
257 case XML_TOTALDIGITS
:
258 sPropertyName
= "TotalDigits";
259 pConvert
= &xforms_int32
;
261 case XML_FRACTIONDIGITS
:
262 sPropertyName
= "FractionDigits";
263 pConvert
= &xforms_int32
;
266 sPropertyName
= "Pattern";
267 pConvert
= &xforms_string
;
270 sPropertyName
= "WhiteSpace";
271 pConvert
= &xforms_whitespace
;
273 case XML_MININCLUSIVE
:
274 case XML_MINEXCLUSIVE
:
275 case XML_MAXINCLUSIVE
:
276 case XML_MAXEXCLUSIVE
:
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.
283 // first, attribute-dependent prefix
286 case XML_MININCLUSIVE
:
287 sPropertyName
= "MinInclusive";
289 case XML_MINEXCLUSIVE
:
290 sPropertyName
= "MinExclusive";
292 case XML_MAXINCLUSIVE
:
293 sPropertyName
= "MaxInclusive";
295 case XML_MAXEXCLUSIVE
:
296 sPropertyName
= "MaxExclusive";
300 // second, type-dependent suffix + converter
301 switch( xforms_getTypeClass( mxRepository
,
302 GetImport().GetNamespaceMap(),
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 sPropertyName
+= "Double";
309 pConvert
= &xforms_double
;
311 case com::sun::star::xsd::DataTypeClass::DATETIME
:
312 sPropertyName
+= "DateTime";
313 pConvert
= &xforms_dateTime
;
315 case com::sun::star::xsd::DataTypeClass::DATE
:
316 sPropertyName
+= "Date";
317 pConvert
= &xforms_date
;
319 case com::sun::star::xsd::DataTypeClass::TIME
:
320 sPropertyName
+= "Time";
321 pConvert
= &xforms_time
;
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 sPropertyName
+= "Int";
327 pConvert
= &xforms_int16
;
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
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:
350 OSL_FAIL( "unknown facet" );
353 // finally, set the property
356 && !sPropertyName
.isEmpty()
358 && mxDataType
->getPropertySetInfo()->hasPropertyByName(sPropertyName
) )
362 mxDataType
->setPropertyValue( sPropertyName
, pConvert( sValue
) );
364 catch( const Exception
& )
366 ; // can't set property? Then ignore.
370 return new SvXMLImportContext( GetImport(), nPrefix
, rLocalName
);
373 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */