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