Gtk-WARNING gtktreestore.c:1047: Invalid column number 1 added to iter
[LibreOffice.git] / xmloff / source / xforms / SchemaRestrictionContext.cxx
blobc7c4cd390a74be7b78e7e3794997a461c06beb18
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 <utility>
25 #include <xmloff/xmltoken.hxx>
26 #include <xmloff/xmlimp.hxx>
28 #include <sax/tools/converter.hxx>
30 #include <com/sun/star/beans/XPropertySet.hpp>
31 #include <com/sun/star/util/Date.hpp>
32 #include <com/sun/star/util/Time.hpp>
33 #include <com/sun/star/util/DateTime.hpp>
34 #include <com/sun/star/util/Duration.hpp>
35 #include <com/sun/star/xforms/XDataTypeRepository.hpp>
36 #include <com/sun/star/xsd/DataTypeClass.hpp>
37 #include <com/sun/star/xsd/WhiteSpaceTreatment.hpp>
39 #include <o3tl/string_view.hxx>
40 #include <sal/log.hxx>
41 #include <comphelper/diagnose_ex.hxx>
44 using com::sun::star::uno::Reference;
45 using com::sun::star::uno::Exception;
46 using com::sun::star::uno::Any;
47 using namespace com::sun::star;
48 using com::sun::star::util::Duration;
49 using com::sun::star::xml::sax::XFastAttributeList;
50 using com::sun::star::xforms::XDataTypeRepository;
51 using namespace xmloff::token;
54 SchemaRestrictionContext::SchemaRestrictionContext(
55 SvXMLImport& rImport,
56 Reference<css::xforms::XDataTypeRepository> const & rRepository,
57 OUString sTypeName ) :
58 TokenContext( rImport ),
59 mxRepository( rRepository ),
60 msTypeName(std::move( sTypeName ))
62 SAL_WARN_IF( !mxRepository.is(), "xmloff", "need repository" );
65 void SchemaRestrictionContext::CreateDataType()
67 // only do something if we don't have a data type already
68 if( mxDataType.is() )
69 return;
71 SAL_WARN_IF( msBaseName.isEmpty(), "xmloff", "no base name?" );
72 SAL_WARN_IF( !mxRepository.is(), "xmloff", "no repository?" );
74 try
76 mxDataType =
77 mxRepository->cloneDataType(
78 xforms_getBasicTypeName( mxRepository,
79 GetImport().GetNamespaceMap(),
80 msBaseName ),
81 msTypeName );
83 catch( const Exception& )
85 TOOLS_WARN_EXCEPTION("xmloff", "exception during type creation");
87 SAL_WARN_IF( !mxDataType.is(), "xmloff", "can't create type" );
90 void SchemaRestrictionContext::HandleAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter & aIter )
92 switch (aIter.getToken() & TOKEN_MASK)
94 case XML_BASE:
95 msBaseName = aIter.toString();
96 break;
100 typedef Any (*convert_t)( const OUString& );
102 static Any xforms_string( const OUString& rValue )
104 return Any( rValue );
107 static Any xforms_int32( const OUString& rValue )
109 sal_Int32 nValue;
110 bool bSuccess = ::sax::Converter::convertNumber( nValue, rValue );
111 return bSuccess ? Any( nValue ) : Any();
114 static Any xforms_int16( const OUString& rValue )
116 sal_Int32 nValue;
117 bool bSuccess = ::sax::Converter::convertNumber( nValue, rValue );
118 return bSuccess ? Any( static_cast<sal_Int16>( nValue ) ) : Any();
121 static Any xforms_whitespace( const OUString& rValue )
123 Any aValue;
124 if( IsXMLToken( rValue, XML_PRESERVE ) )
125 aValue <<= css::xsd::WhiteSpaceTreatment::Preserve;
126 else if( IsXMLToken( rValue, XML_REPLACE ) )
127 aValue <<= css::xsd::WhiteSpaceTreatment::Replace;
128 else if( IsXMLToken( rValue, XML_COLLAPSE ) )
129 aValue <<= css::xsd::WhiteSpaceTreatment::Collapse;
130 return aValue;
133 static Any xforms_double( const OUString& rValue )
135 double fValue;
136 bool bSuccess = ::sax::Converter::convertDouble( fValue, rValue );
137 return bSuccess ? Any( fValue ) : Any();
140 static Any xforms_date( const OUString& rValue )
142 Any aAny;
144 // parse ISO date
145 sal_Int32 nPos1 = rValue.indexOf( '-' );
146 sal_Int32 nPos2 = rValue.indexOf( '-', nPos1 + 1 );
147 if( nPos1 > 0 && nPos2 > 0 )
149 util::Date aDate;
150 aDate.Year = static_cast<sal_uInt16>(
151 o3tl::toInt32(rValue.subView( 0, nPos1 )) );
152 aDate.Month = static_cast<sal_uInt16>(
153 o3tl::toInt32(rValue.subView( nPos1 + 1, nPos2 - nPos1 - 1 )) );
154 aDate.Day = static_cast<sal_uInt16>(
155 o3tl::toInt32(rValue.subView( nPos2 + 1 )) );
156 aAny <<= aDate;
158 return aAny;
161 static Any xforms_dateTime( const OUString& rValue )
163 util::DateTime aDateTime;
164 bool const bSuccess = ::sax::Converter::parseDateTime(aDateTime, rValue);
165 return bSuccess ? Any( aDateTime ) : Any();
168 static Any xforms_time( const OUString& rValue )
170 Any aAny;
171 Duration aDuration;
172 if (::sax::Converter::convertDuration( aDuration, rValue ))
174 css::util::Time aTime;
175 aTime.Hours = aDuration.Hours;
176 aTime.Minutes = aDuration.Minutes;
177 aTime.Seconds = aDuration.Seconds;
178 aTime.NanoSeconds = aDuration.NanoSeconds;
179 aAny <<= aTime;
181 return aAny;
185 SvXMLImportContext* SchemaRestrictionContext::HandleChild(
186 sal_Int32 nElementToken,
187 const Reference<XFastAttributeList>& xAttrList )
189 // find value
190 OUString sValue;
191 for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
193 if( ( aIter.getToken() & TOKEN_MASK) == XML_VALUE )
195 sValue = aIter.toString();
196 break;
200 // determine property name + suitable converter
201 OUString sPropertyName;
202 convert_t pConvert = nullptr;
203 switch( nElementToken & TOKEN_MASK )
205 case XML_LENGTH:
206 sPropertyName = "Length";
207 pConvert = &xforms_int32;
208 break;
209 case XML_MINLENGTH:
210 sPropertyName = "MinLength";
211 pConvert = &xforms_int32;
212 break;
213 case XML_MAXLENGTH:
214 sPropertyName = "MaxLength";
215 pConvert = &xforms_int32;
216 break;
217 case XML_TOTALDIGITS:
218 sPropertyName = "TotalDigits";
219 pConvert = &xforms_int32;
220 break;
221 case XML_FRACTIONDIGITS:
222 sPropertyName = "FractionDigits";
223 pConvert = &xforms_int32;
224 break;
225 case XML_PATTERN:
226 sPropertyName = "Pattern";
227 pConvert = &xforms_string;
228 break;
229 case XML_WHITESPACE:
230 sPropertyName = "WhiteSpace";
231 pConvert = &xforms_whitespace;
232 break;
233 case XML_MININCLUSIVE:
234 case XML_MINEXCLUSIVE:
235 case XML_MAXINCLUSIVE:
236 case XML_MAXEXCLUSIVE:
238 // these attributes are mapped to different properties.
239 // To determine the property name, we use an attribute
240 // dependent prefix and a type dependent suffix. The
241 // converter is only type dependent.
243 // first, attribute-dependent prefix
244 switch( nElementToken & TOKEN_MASK )
246 case XML_MININCLUSIVE:
247 sPropertyName = "MinInclusive";
248 break;
249 case XML_MINEXCLUSIVE:
250 sPropertyName = "MinExclusive";
251 break;
252 case XML_MAXINCLUSIVE:
253 sPropertyName = "MaxInclusive";
254 break;
255 case XML_MAXEXCLUSIVE:
256 sPropertyName = "MaxExclusive";
257 break;
260 // second, type-dependent suffix + converter
261 switch( xforms_getTypeClass( mxRepository,
262 GetImport().GetNamespaceMap(),
263 msBaseName ) )
265 case css::xsd::DataTypeClass::DECIMAL:
266 case css::xsd::DataTypeClass::DOUBLE:
267 case css::xsd::DataTypeClass::FLOAT:
268 sPropertyName += "Double";
269 pConvert = &xforms_double;
270 break;
271 case css::xsd::DataTypeClass::DATETIME:
272 sPropertyName += "DateTime";
273 pConvert = &xforms_dateTime;
274 break;
275 case css::xsd::DataTypeClass::DATE:
276 sPropertyName += "Date";
277 pConvert = &xforms_date;
278 break;
279 case css::xsd::DataTypeClass::TIME:
280 sPropertyName += "Time";
281 pConvert = &xforms_time;
282 break;
283 case css::xsd::DataTypeClass::gYear:
284 case css::xsd::DataTypeClass::gDay:
285 case css::xsd::DataTypeClass::gMonth:
286 sPropertyName += "Int";
287 pConvert = &xforms_int16;
288 break;
290 case css::xsd::DataTypeClass::STRING:
291 case css::xsd::DataTypeClass::anyURI:
292 case css::xsd::DataTypeClass::BOOLEAN:
293 // invalid: These shouldn't have min/max-inclusive
294 break;
296 /* data types not yet supported:
297 case css::xsd::DataTypeClass::DURATION:
298 case css::xsd::DataTypeClass::gYearMonth:
299 case css::xsd::DataTypeClass::gMonthDay:
300 case css::xsd::DataTypeClass::hexBinary:
301 case css::xsd::DataTypeClass::base64Binary:
302 case css::xsd::DataTypeClass::QName:
303 case css::xsd::DataTypeClass::NOTATION:
307 break;
309 default:
310 OSL_FAIL( "unknown facet" );
313 // finally, set the property
314 CreateDataType();
315 if( mxDataType.is()
316 && !sPropertyName.isEmpty()
317 && pConvert != nullptr
318 && mxDataType->getPropertySetInfo()->hasPropertyByName(sPropertyName) )
322 mxDataType->setPropertyValue( sPropertyName, pConvert( sValue ) );
324 catch( const Exception& )
326 ; // can't set property? Then ignore.
330 return new SvXMLImportContext( GetImport() );
333 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */