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"
25 #include <xmloff/xmltoken.hxx>
26 #include <xmloff/namespacemap.hxx>
27 #include <xmloff/xmlnamespace.hxx>
28 #include <xmloff/xmltkmap.hxx>
29 #include <xmloff/xmlimp.hxx>
31 #include <sax/tools/converter.hxx>
33 #include <com/sun/star/beans/XPropertySet.hpp>
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 <o3tl/string_view.hxx>
43 #include <sal/log.hxx>
44 #include <comphelper/diagnose_ex.hxx>
47 using com::sun::star::uno::Reference
;
48 using com::sun::star::uno::Exception
;
49 using com::sun::star::uno::Any
;
50 using namespace com::sun::star
;
51 using com::sun::star::util::Duration
;
52 using com::sun::star::xml::sax::XFastAttributeList
;
53 using com::sun::star::xforms::XDataTypeRepository
;
54 using namespace xmloff::token
;
57 SchemaRestrictionContext::SchemaRestrictionContext(
59 Reference
<css::xforms::XDataTypeRepository
> const & rRepository
,
60 OUString sTypeName
) :
61 TokenContext( rImport
),
62 mxRepository( rRepository
),
63 msTypeName(std::move( sTypeName
))
65 SAL_WARN_IF( !mxRepository
.is(), "xmloff", "need repository" );
68 void SchemaRestrictionContext::CreateDataType()
70 // only do something if we don't have a data type already
74 SAL_WARN_IF( msBaseName
.isEmpty(), "xmloff", "no base name?" );
75 SAL_WARN_IF( !mxRepository
.is(), "xmloff", "no repository?" );
80 mxRepository
->cloneDataType(
81 xforms_getBasicTypeName( mxRepository
,
82 GetImport().GetNamespaceMap(),
86 catch( const Exception
& )
88 TOOLS_WARN_EXCEPTION("xmloff", "exception during type creation");
90 SAL_WARN_IF( !mxDataType
.is(), "xmloff", "can't create type" );
93 void SchemaRestrictionContext::HandleAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter
& aIter
)
95 switch (aIter
.getToken() & TOKEN_MASK
)
98 msBaseName
= aIter
.toString();
103 typedef Any (*convert_t
)( const OUString
& );
105 static Any
xforms_string( const OUString
& rValue
)
107 return Any( rValue
);
110 static Any
xforms_int32( const OUString
& rValue
)
113 bool bSuccess
= ::sax::Converter::convertNumber( nValue
, rValue
);
114 return bSuccess
? Any( nValue
) : Any();
117 static Any
xforms_int16( const OUString
& rValue
)
120 bool bSuccess
= ::sax::Converter::convertNumber( nValue
, rValue
);
121 return bSuccess
? Any( static_cast<sal_Int16
>( nValue
) ) : Any();
124 static Any
xforms_whitespace( const OUString
& rValue
)
127 if( IsXMLToken( rValue
, XML_PRESERVE
) )
128 aValue
<<= css::xsd::WhiteSpaceTreatment::Preserve
;
129 else if( IsXMLToken( rValue
, XML_REPLACE
) )
130 aValue
<<= css::xsd::WhiteSpaceTreatment::Replace
;
131 else if( IsXMLToken( rValue
, XML_COLLAPSE
) )
132 aValue
<<= css::xsd::WhiteSpaceTreatment::Collapse
;
136 static Any
xforms_double( const OUString
& rValue
)
139 bool bSuccess
= ::sax::Converter::convertDouble( fValue
, rValue
);
140 return bSuccess
? Any( fValue
) : Any();
143 static Any
xforms_date( const OUString
& rValue
)
148 sal_Int32 nPos1
= rValue
.indexOf( '-' );
149 sal_Int32 nPos2
= rValue
.indexOf( '-', nPos1
+ 1 );
150 if( nPos1
> 0 && nPos2
> 0 )
153 aDate
.Year
= static_cast<sal_uInt16
>(
154 o3tl::toInt32(rValue
.subView( 0, nPos1
)) );
155 aDate
.Month
= static_cast<sal_uInt16
>(
156 o3tl::toInt32(rValue
.subView( nPos1
+ 1, nPos2
- nPos1
- 1 )) );
157 aDate
.Day
= static_cast<sal_uInt16
>(
158 o3tl::toInt32(rValue
.subView( nPos2
+ 1 )) );
164 static Any
xforms_dateTime( const OUString
& rValue
)
166 util::DateTime aDateTime
;
167 bool const bSuccess
= ::sax::Converter::parseDateTime(aDateTime
, rValue
);
168 return bSuccess
? Any( aDateTime
) : Any();
171 static Any
xforms_time( const OUString
& rValue
)
175 if (::sax::Converter::convertDuration( aDuration
, rValue
))
177 css::util::Time aTime
;
178 aTime
.Hours
= aDuration
.Hours
;
179 aTime
.Minutes
= aDuration
.Minutes
;
180 aTime
.Seconds
= aDuration
.Seconds
;
181 aTime
.NanoSeconds
= aDuration
.NanoSeconds
;
188 SvXMLImportContext
* SchemaRestrictionContext::HandleChild(
189 sal_Int32 nElementToken
,
190 const Reference
<XFastAttributeList
>& xAttrList
)
194 for( auto& aIter
: sax_fastparser::castToFastAttributeList(xAttrList
) )
196 if( ( aIter
.getToken() & TOKEN_MASK
) == XML_VALUE
)
198 sValue
= aIter
.toString();
203 // determine property name + suitable converter
204 OUString sPropertyName
;
205 convert_t pConvert
= nullptr;
206 switch( nElementToken
& TOKEN_MASK
)
209 sPropertyName
= "Length";
210 pConvert
= &xforms_int32
;
213 sPropertyName
= "MinLength";
214 pConvert
= &xforms_int32
;
217 sPropertyName
= "MaxLength";
218 pConvert
= &xforms_int32
;
220 case XML_TOTALDIGITS
:
221 sPropertyName
= "TotalDigits";
222 pConvert
= &xforms_int32
;
224 case XML_FRACTIONDIGITS
:
225 sPropertyName
= "FractionDigits";
226 pConvert
= &xforms_int32
;
229 sPropertyName
= "Pattern";
230 pConvert
= &xforms_string
;
233 sPropertyName
= "WhiteSpace";
234 pConvert
= &xforms_whitespace
;
236 case XML_MININCLUSIVE
:
237 case XML_MINEXCLUSIVE
:
238 case XML_MAXINCLUSIVE
:
239 case XML_MAXEXCLUSIVE
:
241 // these attributes are mapped to different properties.
242 // To determine the property name, we use an attribute
243 // dependent prefix and a type dependent suffix. The
244 // converter is only type dependent.
246 // first, attribute-dependent prefix
247 switch( nElementToken
& TOKEN_MASK
)
249 case XML_MININCLUSIVE
:
250 sPropertyName
= "MinInclusive";
252 case XML_MINEXCLUSIVE
:
253 sPropertyName
= "MinExclusive";
255 case XML_MAXINCLUSIVE
:
256 sPropertyName
= "MaxInclusive";
258 case XML_MAXEXCLUSIVE
:
259 sPropertyName
= "MaxExclusive";
263 // second, type-dependent suffix + converter
264 switch( xforms_getTypeClass( mxRepository
,
265 GetImport().GetNamespaceMap(),
268 case css::xsd::DataTypeClass::DECIMAL
:
269 case css::xsd::DataTypeClass::DOUBLE
:
270 case css::xsd::DataTypeClass::FLOAT
:
271 sPropertyName
+= "Double";
272 pConvert
= &xforms_double
;
274 case css::xsd::DataTypeClass::DATETIME
:
275 sPropertyName
+= "DateTime";
276 pConvert
= &xforms_dateTime
;
278 case css::xsd::DataTypeClass::DATE
:
279 sPropertyName
+= "Date";
280 pConvert
= &xforms_date
;
282 case css::xsd::DataTypeClass::TIME
:
283 sPropertyName
+= "Time";
284 pConvert
= &xforms_time
;
286 case css::xsd::DataTypeClass::gYear
:
287 case css::xsd::DataTypeClass::gDay
:
288 case css::xsd::DataTypeClass::gMonth
:
289 sPropertyName
+= "Int";
290 pConvert
= &xforms_int16
;
293 case css::xsd::DataTypeClass::STRING
:
294 case css::xsd::DataTypeClass::anyURI
:
295 case css::xsd::DataTypeClass::BOOLEAN
:
296 // invalid: These shouldn't have min/max-inclusive
299 /* data types not yet supported:
300 case css::xsd::DataTypeClass::DURATION:
301 case css::xsd::DataTypeClass::gYearMonth:
302 case css::xsd::DataTypeClass::gMonthDay:
303 case css::xsd::DataTypeClass::hexBinary:
304 case css::xsd::DataTypeClass::base64Binary:
305 case css::xsd::DataTypeClass::QName:
306 case css::xsd::DataTypeClass::NOTATION:
313 OSL_FAIL( "unknown facet" );
316 // finally, set the property
319 && !sPropertyName
.isEmpty()
320 && pConvert
!= nullptr
321 && mxDataType
->getPropertySetInfo()->hasPropertyByName(sPropertyName
) )
325 mxDataType
->setPropertyValue( sPropertyName
, pConvert( sValue
) );
327 catch( const Exception
& )
329 ; // can't set property? Then ignore.
333 return new SvXMLImportContext( GetImport() );
336 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */