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 <stdio.h> 28 #include "propertyexport.hxx" 29 #include <xmloff/xmlexp.hxx> 30 #include "strings.hxx" 31 #include "xmloff/xmlnmspe.hxx" 32 #include <xmloff/xmluconv.hxx> 33 #include <xmloff/families.hxx> 34 #include <osl/diagnose.h> 35 #include <com/sun/star/beans/PropertyAttribute.hpp> 36 #include <com/sun/star/util/Date.hpp> 37 #include <com/sun/star/util/Time.hpp> 38 #include <com/sun/star/util/DateTime.hpp> 39 #include <osl/diagnose.h> 40 #include <comphelper/extract.hxx> 41 #include <comphelper/sequence.hxx> 42 #include <comphelper/types.hxx> 43 #include "callbacks.hxx" 44 #include <unotools/datetime.hxx> 45 #include <tools/date.hxx> 46 #include <tools/time.hxx> 47 #include <tools/datetime.hxx> 48 49 //......................................................................... 50 namespace xmloff 51 { 52 //......................................................................... 53 54 using namespace ::com::sun::star::uno; 55 using namespace ::com::sun::star::lang; 56 using namespace ::com::sun::star::beans; 57 58 // NO using namespace ...util !!! 59 // need a tools Date/Time/DateTime below, which would conflict with the uno types then 60 61 using namespace ::comphelper; 62 63 //===================================================================== 64 //= OPropertyExport 65 //===================================================================== 66 //--------------------------------------------------------------------- OPropertyExport(IFormsExportContext & _rContext,const Reference<XPropertySet> & _rxProps)67 OPropertyExport::OPropertyExport(IFormsExportContext& _rContext, const Reference< XPropertySet >& _rxProps) 68 :m_rContext(_rContext) 69 ,m_xProps(_rxProps) 70 ,m_xPropertyInfo( m_xProps->getPropertySetInfo() ) 71 ,m_xPropertyState( _rxProps, UNO_QUERY ) 72 { 73 // caching 74 ::rtl::OUStringBuffer aBuffer; 75 m_rContext.getGlobalContext().GetMM100UnitConverter().convertBool(aBuffer, sal_True); 76 m_sValueTrue = aBuffer.makeStringAndClear(); 77 m_rContext.getGlobalContext().GetMM100UnitConverter().convertBool(aBuffer, sal_False); 78 m_sValueFalse = aBuffer.makeStringAndClear(); 79 80 OSL_ENSURE(m_xPropertyInfo.is(), "OPropertyExport::OPropertyExport: need an XPropertySetInfo!"); 81 82 // collect the properties which need to be exported 83 examinePersistence(); 84 } 85 86 //--------------------------------------------------------------------- shouldExportProperty(const::rtl::OUString & i_propertyName) const87 bool OPropertyExport::shouldExportProperty( const ::rtl::OUString& i_propertyName ) const 88 { 89 // if the property state is DEFAULT, it does not need to be written - at least 90 // if it's a built-in property, and not a dynamically-added one. 91 bool bIsDefaultValue = m_xPropertyState.is() 92 && ( PropertyState_DEFAULT_VALUE == m_xPropertyState->getPropertyState( i_propertyName ) ); 93 bool bIsDynamicProperty = m_xPropertyInfo.is() 94 && ( ( m_xPropertyInfo->getPropertyByName( i_propertyName ).Attributes & PropertyAttribute::REMOVEABLE ) != 0 ); 95 return ( !bIsDefaultValue || bIsDynamicProperty ); 96 } 97 98 //--------------------------------------------------------------------- exportRemainingProperties()99 void OPropertyExport::exportRemainingProperties() 100 { 101 // the properties tag (will be created if we have at least one no-default property) 102 SvXMLElementExport* pPropertiesTag = NULL; 103 104 try 105 { 106 Any aValue; 107 ::rtl::OUString sValue; 108 109 // loop through all the properties which are yet to be exported 110 for ( ConstStringSetIterator aProperty = m_aRemainingProps.begin(); 111 aProperty != m_aRemainingProps.end(); 112 ++aProperty 113 ) 114 { 115 DBG_CHECK_PROPERTY_NO_TYPE(*aProperty); 116 117 #if OSL_DEBUG_LEVEL > 0 118 const ::rtl::OUString sPropertyName = *aProperty; (void)sPropertyName; 119 #endif 120 if ( !shouldExportProperty( *aProperty ) ) 121 continue; 122 123 // now that we have the first sub-tag we need the form:properties element 124 if (!pPropertiesTag) 125 pPropertiesTag = new SvXMLElementExport(m_rContext.getGlobalContext(), XML_NAMESPACE_FORM, token::XML_PROPERTIES, sal_True, sal_True); 126 127 // add the name attribute 128 AddAttribute(XML_NAMESPACE_FORM, token::XML_PROPERTY_NAME, *aProperty); 129 130 // get the value 131 aValue = m_xProps->getPropertyValue(*aProperty); 132 133 // the type to export 134 Type aExportType; 135 136 // is it a sequence 137 sal_Bool bIsSequence = TypeClass_SEQUENCE == aValue.getValueTypeClass(); 138 // the type of the property, maybe reduced to the element type of a sequence 139 if (bIsSequence) 140 aExportType = getSequenceElementType( aValue.getValueType() ); 141 else 142 aExportType = aValue.getValueType(); 143 144 // the type attribute 145 // modified by BerryJia for Bug102407 146 bool bIsEmptyValue = TypeClass_VOID == aValue.getValueType().getTypeClass(); 147 if ( bIsEmptyValue ) 148 { 149 com::sun::star::beans::Property aPropDesc; 150 aPropDesc = m_xPropertyInfo->getPropertyByName( *aProperty ); 151 aExportType = aPropDesc.Type; 152 } 153 token::XMLTokenEnum eValueType = implGetPropertyXMLType( aExportType ); 154 155 if ( bIsEmptyValue ) 156 AddAttribute( XML_NAMESPACE_OFFICE, token::XML_VALUE_TYPE, token::XML_VOID ); 157 else 158 AddAttribute( XML_NAMESPACE_OFFICE, token::XML_VALUE_TYPE, eValueType ); 159 160 token::XMLTokenEnum eValueAttName( token::XML_VALUE ); 161 switch ( eValueType ) 162 { 163 case token::XML_BOOLEAN: eValueAttName = token::XML_BOOLEAN_VALUE; break; 164 case token::XML_STRING: eValueAttName = token::XML_STRING_VALUE; break; 165 default: break; 166 } 167 168 if( !bIsSequence && !bIsEmptyValue ) 169 { // the simple case 170 //add by BerryJia for Bug102407 171 sValue = implConvertAny(aValue); 172 AddAttribute(XML_NAMESPACE_OFFICE, eValueAttName, sValue ); 173 } 174 175 176 // start the property tag 177 SvXMLElementExport aValueTag1(m_rContext.getGlobalContext(), 178 XML_NAMESPACE_FORM, 179 bIsSequence ? token::XML_LIST_PROPERTY 180 : token::XML_PROPERTY, sal_True, sal_True); 181 182 if (!bIsSequence) 183 continue; 184 185 // the not-that-simple case, we need to iterate through the sequence elements 186 IIterator* pSequenceIterator = NULL; 187 188 switch ( aExportType.getTypeClass() ) 189 { 190 case TypeClass_STRING: 191 pSequenceIterator = new OSequenceIterator< ::rtl::OUString >(aValue); 192 break; 193 case TypeClass_DOUBLE: 194 pSequenceIterator = new OSequenceIterator< double >(aValue); 195 break; 196 case TypeClass_BOOLEAN: 197 pSequenceIterator = new OSequenceIterator< sal_Bool >(aValue); 198 break; 199 case TypeClass_BYTE: 200 pSequenceIterator = new OSequenceIterator< sal_Int8 >(aValue); 201 break; 202 case TypeClass_SHORT: 203 pSequenceIterator = new OSequenceIterator< sal_Int16 >(aValue); 204 break; 205 case TypeClass_LONG: 206 pSequenceIterator = new OSequenceIterator< sal_Int32 >(aValue); 207 break; 208 case TypeClass_HYPER: 209 pSequenceIterator = new OSequenceIterator< sal_Int64 >(aValue); 210 break; 211 default: 212 OSL_ENSURE(sal_False, "OPropertyExport::exportRemainingProperties: unsupported sequence tyoe !"); 213 break; 214 } 215 if (pSequenceIterator) 216 { 217 while (pSequenceIterator->hasMoreElements()) 218 { 219 sValue = 220 implConvertAny(pSequenceIterator->nextElement()); 221 AddAttribute(XML_NAMESPACE_OFFICE, eValueAttName, sValue ); 222 SvXMLElementExport aValueTag( 223 m_rContext.getGlobalContext(), 224 XML_NAMESPACE_FORM, token::XML_LIST_VALUE, 225 sal_True, sal_False); 226 } 227 } 228 delete pSequenceIterator; 229 } 230 } 231 catch(...) 232 { 233 delete pPropertiesTag; 234 throw; 235 } 236 delete pPropertiesTag; 237 } 238 239 //--------------------------------------------------------------------- examinePersistence()240 void OPropertyExport::examinePersistence() 241 { 242 m_aRemainingProps.clear(); 243 Sequence< Property > aProperties = m_xPropertyInfo->getProperties(); 244 const Property* pProperties = aProperties.getConstArray(); 245 for (sal_Int32 i=0; i<aProperties.getLength(); ++i, ++pProperties) 246 { 247 // no transient props 248 if ( pProperties->Attributes & PropertyAttribute::TRANSIENT ) 249 continue; 250 // no read-only props 251 if ( ( pProperties->Attributes & PropertyAttribute::READONLY ) != 0 ) 252 // except they're dynamically added 253 if ( ( pProperties->Attributes & PropertyAttribute::REMOVEABLE ) == 0 ) 254 continue; 255 m_aRemainingProps.insert(pProperties->Name); 256 } 257 } 258 259 //--------------------------------------------------------------------- exportStringPropertyAttribute(const sal_uInt16 _nNamespaceKey,const sal_Char * _pAttributeName,const::rtl::OUString & _rPropertyName)260 void OPropertyExport::exportStringPropertyAttribute( const sal_uInt16 _nNamespaceKey, const sal_Char* _pAttributeName, 261 const ::rtl::OUString& _rPropertyName ) 262 { 263 DBG_CHECK_PROPERTY( _rPropertyName, ::rtl::OUString ); 264 265 // no try-catch here, this would be to expensive. The outer scope has to handle exceptions (which should not 266 // happen if we're used correctly :) 267 268 // this is way simple, as we don't need to convert anything (the property already is a string) 269 270 // get the string 271 ::rtl::OUString sPropValue; 272 m_xProps->getPropertyValue( _rPropertyName ) >>= sPropValue; 273 274 // add the attribute 275 if ( sPropValue.getLength() ) 276 AddAttribute( _nNamespaceKey, _pAttributeName, sPropValue ); 277 278 // the property does not need to be handled anymore 279 exportedProperty( _rPropertyName ); 280 } 281 282 //--------------------------------------------------------------------- exportBooleanPropertyAttribute(const sal_uInt16 _nNamespaceKey,const sal_Char * _pAttributeName,const::rtl::OUString & _rPropertyName,const sal_Int8 _nBooleanAttributeFlags)283 void OPropertyExport::exportBooleanPropertyAttribute(const sal_uInt16 _nNamespaceKey, const sal_Char* _pAttributeName, 284 const ::rtl::OUString& _rPropertyName, const sal_Int8 _nBooleanAttributeFlags) 285 { 286 DBG_CHECK_PROPERTY_NO_TYPE( _rPropertyName ); 287 // no check of the property value type: this method is allowed to be called with any integer properties 288 // (e.g. sal_Int32, sal_uInt16 etc) 289 290 sal_Bool bDefault = (BOOLATTR_DEFAULT_TRUE == (BOOLATTR_DEFAULT_MASK & _nBooleanAttributeFlags)); 291 sal_Bool bDefaultVoid = (BOOLATTR_DEFAULT_VOID == (BOOLATTR_DEFAULT_MASK & _nBooleanAttributeFlags)); 292 293 // get the value 294 sal_Bool bCurrentValue = bDefault; 295 Any aCurrentValue = m_xProps->getPropertyValue( _rPropertyName ); 296 if (aCurrentValue.hasValue()) 297 { 298 bCurrentValue = ::cppu::any2bool(aCurrentValue); 299 // this will extract a boolean value even if the Any contains a int or short or something like that ... 300 301 if (_nBooleanAttributeFlags & BOOLATTR_INVERSE_SEMANTICS) 302 bCurrentValue = !bCurrentValue; 303 304 // we have a non-void current value 305 if (bDefaultVoid || (bDefault != bCurrentValue)) 306 // and (the default is void, or the non-void default does not equal the current value) 307 // -> write the attribute 308 AddAttribute(_nNamespaceKey, _pAttributeName, bCurrentValue ? m_sValueTrue : m_sValueFalse); 309 } 310 else 311 // we have a void current value 312 if (!bDefaultVoid) 313 // and we have a non-void default 314 // -> write the attribute 315 AddAttribute(_nNamespaceKey, _pAttributeName, bCurrentValue ? m_sValueTrue : m_sValueFalse); 316 317 // the property does not need to be handled anymore 318 exportedProperty( _rPropertyName ); 319 } 320 321 //--------------------------------------------------------------------- exportInt16PropertyAttribute(const sal_uInt16 _nNamespaceKey,const sal_Char * _pAttributeName,const::rtl::OUString & _rPropertyName,const sal_Int16 _nDefault)322 void OPropertyExport::exportInt16PropertyAttribute(const sal_uInt16 _nNamespaceKey, const sal_Char* _pAttributeName, 323 const ::rtl::OUString& _rPropertyName, const sal_Int16 _nDefault) 324 { 325 DBG_CHECK_PROPERTY( _rPropertyName, sal_Int16 ); 326 327 // get the value 328 sal_Int16 nCurrentValue(_nDefault); 329 m_xProps->getPropertyValue( _rPropertyName ) >>= nCurrentValue; 330 331 // add the attribute 332 if (_nDefault != nCurrentValue) 333 { 334 // let the formatter of the export context build a string 335 ::rtl::OUStringBuffer sBuffer; 336 m_rContext.getGlobalContext().GetMM100UnitConverter().convertNumber(sBuffer, (sal_Int32)nCurrentValue); 337 338 AddAttribute(_nNamespaceKey, _pAttributeName, sBuffer.makeStringAndClear()); 339 } 340 341 // the property does not need to be handled anymore 342 exportedProperty( _rPropertyName ); 343 } 344 345 //--------------------------------------------------------------------- exportInt32PropertyAttribute(const sal_uInt16 _nNamespaceKey,const sal_Char * _pAttributeName,const::rtl::OUString & _rPropertyName,const sal_Int32 _nDefault)346 void OPropertyExport::exportInt32PropertyAttribute( const sal_uInt16 _nNamespaceKey, const sal_Char* _pAttributeName, 347 const ::rtl::OUString& _rPropertyName, const sal_Int32 _nDefault ) 348 { 349 DBG_CHECK_PROPERTY( _rPropertyName, sal_Int32 ); 350 351 // get the value 352 sal_Int32 nCurrentValue( _nDefault ); 353 m_xProps->getPropertyValue( _rPropertyName ) >>= nCurrentValue; 354 355 // add the attribute 356 if ( _nDefault != nCurrentValue ) 357 { 358 // let the formatter of the export context build a string 359 ::rtl::OUStringBuffer sBuffer; 360 m_rContext.getGlobalContext().GetMM100UnitConverter().convertNumber( sBuffer, nCurrentValue ); 361 362 AddAttribute( _nNamespaceKey, _pAttributeName, sBuffer.makeStringAndClear() ); 363 } 364 365 // the property does not need to be handled anymore 366 exportedProperty( _rPropertyName ); 367 } 368 369 //--------------------------------------------------------------------- exportEnumPropertyAttribute(const sal_uInt16 _nNamespaceKey,const sal_Char * _pAttributeName,const sal_Char * _pPropertyName,const SvXMLEnumMapEntry * _pValueMap,const sal_Int32 _nDefault,const sal_Bool _bVoidDefault)370 void OPropertyExport::exportEnumPropertyAttribute( 371 const sal_uInt16 _nNamespaceKey, const sal_Char* _pAttributeName, 372 const sal_Char* _pPropertyName, const SvXMLEnumMapEntry* _pValueMap, 373 const sal_Int32 _nDefault, const sal_Bool _bVoidDefault) 374 { 375 // get the value 376 sal_Int32 nCurrentValue(_nDefault); 377 ::rtl::OUString sPropertyName(::rtl::OUString::createFromAscii(_pPropertyName)); 378 Any aValue = m_xProps->getPropertyValue(sPropertyName); 379 380 if (aValue.hasValue()) 381 { // we have a non-void current value 382 ::cppu::enum2int(nCurrentValue, aValue); 383 384 // add the attribute 385 if ((_nDefault != nCurrentValue) || _bVoidDefault) 386 { // the default does not equal the value, or the default is void and the value isn't 387 388 // let the formatter of the export context build a string 389 ::rtl::OUStringBuffer sBuffer; 390 m_rContext.getGlobalContext().GetMM100UnitConverter().convertEnum(sBuffer, (sal_uInt16)nCurrentValue, _pValueMap); 391 392 AddAttribute(_nNamespaceKey, _pAttributeName, sBuffer.makeStringAndClear()); 393 } 394 } 395 else 396 { 397 if (!_bVoidDefault) 398 AddAttributeASCII(_nNamespaceKey, _pAttributeName, ""); 399 } 400 401 // the property does not need to be handled anymore 402 exportedProperty(sPropertyName); 403 } 404 405 //--------------------------------------------------------------------- exportTargetFrameAttribute()406 void OPropertyExport::exportTargetFrameAttribute() 407 { 408 DBG_CHECK_PROPERTY( PROPERTY_TARGETFRAME, ::rtl::OUString ); 409 410 ::rtl::OUString sTargetFrame = comphelper::getString(m_xProps->getPropertyValue(PROPERTY_TARGETFRAME)); 411 if (0 != sTargetFrame.compareToAscii("_blank")) 412 { // an empty string and "_blank" have the same meaning and don't have to be written 413 AddAttribute(OAttributeMetaData::getCommonControlAttributeNamespace(CCA_TARGET_FRAME) 414 ,OAttributeMetaData::getCommonControlAttributeName(CCA_TARGET_FRAME) 415 ,sTargetFrame); 416 } 417 418 exportedProperty(PROPERTY_TARGETFRAME); 419 } 420 421 //--------------------------------------------------------------------- exportRelativeTargetLocation(const ConstAsciiString & _sPropertyName,sal_Int32 _nProperty,bool _bAddType)422 void OPropertyExport::exportRelativeTargetLocation(const ConstAsciiString& _sPropertyName,sal_Int32 _nProperty,bool _bAddType) 423 { 424 DBG_CHECK_PROPERTY( _sPropertyName, ::rtl::OUString ); 425 426 ::rtl::OUString sTargetLocation = comphelper::getString(m_xProps->getPropertyValue(_sPropertyName)); 427 if ( sTargetLocation.getLength() ) 428 // If this isn't a GraphicObject then GetRelativeReference 429 // will be called anyway ( in AddEmbeddedGraphic ) 430 sTargetLocation = m_rContext.getGlobalContext().AddEmbeddedGraphicObject(sTargetLocation); 431 AddAttribute(OAttributeMetaData::getCommonControlAttributeNamespace(_nProperty) 432 ,OAttributeMetaData::getCommonControlAttributeName(_nProperty) 433 , sTargetLocation); 434 435 // #i110911# add xlink:type="simple" if required 436 if (_bAddType) 437 AddAttribute(XML_NAMESPACE_XLINK, token::XML_TYPE, token::XML_SIMPLE); 438 439 exportedProperty(_sPropertyName); 440 } 441 //--------------------------------------------------------------------- flagStyleProperties()442 void OPropertyExport::flagStyleProperties() 443 { 444 // flag all the properties which are part of the style as "handled" 445 UniReference< XMLPropertySetMapper > xStylePropertiesSupplier = m_rContext.getStylePropertyMapper()->getPropertySetMapper(); 446 for (sal_Int32 i=0; i<xStylePropertiesSupplier->GetEntryCount(); ++i) 447 exportedProperty(xStylePropertiesSupplier->GetEntryAPIName(i)); 448 449 // the font properties are exported as single properties, but there is a FontDescriptor property which 450 // collects them all-in-one, this has been exported implicitly 451 exportedProperty(PROPERTY_FONT); 452 453 // for the DateFormat and TimeFormat, there exist wrapper properties which has been exported as 454 // style, too 455 exportedProperty(PROPERTY_DATEFORMAT); 456 exportedProperty(PROPERTY_TIMEFORMAT); 457 458 // the following properties should have been exported at the shape already: 459 exportedProperty( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "VerticalAlign" ) ) ); 460 exportedProperty( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "WritingMode" ) ) ); 461 exportedProperty( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ScaleMode" ) ) ); 462 // ditto the TextWritingMode 463 exportedProperty( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "WritingMode" ) ) ); 464 } 465 466 //--------------------------------------------------------------------- exportGenericPropertyAttribute(const sal_uInt16 _nAttributeNamespaceKey,const sal_Char * _pAttributeName,const sal_Char * _pPropertyName)467 void OPropertyExport::exportGenericPropertyAttribute( 468 const sal_uInt16 _nAttributeNamespaceKey, const sal_Char* _pAttributeName, const sal_Char* _pPropertyName) 469 { 470 DBG_CHECK_PROPERTY_ASCII_NO_TYPE( _pPropertyName ); 471 472 ::rtl::OUString sPropertyName = ::rtl::OUString::createFromAscii(_pPropertyName); 473 exportedProperty(sPropertyName); 474 475 Any aCurrentValue = m_xProps->getPropertyValue(sPropertyName); 476 if (!aCurrentValue.hasValue()) 477 // nothing to do without a concrete value 478 return; 479 480 ::rtl::OUString sValue = implConvertAny(aCurrentValue); 481 if (!sValue.getLength() && (TypeClass_STRING == aCurrentValue.getValueTypeClass())) 482 { 483 // check whether or not the property is allowed to be VOID 484 Property aProperty = m_xPropertyInfo->getPropertyByName(sPropertyName); 485 if ((aProperty.Attributes & PropertyAttribute::MAYBEVOID) == 0) 486 // the string is empty, and the property is not allowed to be void 487 // -> don't need to write the attibute, 'cause missing it is unambiguous 488 return; 489 } 490 491 // finally add the attribute to the context 492 AddAttribute(_nAttributeNamespaceKey, _pAttributeName, sValue); 493 } 494 495 //--------------------------------------------------------------------- exportStringSequenceAttribute(const sal_uInt16 _nAttributeNamespaceKey,const sal_Char * _pAttributeName,const::rtl::OUString & _rPropertyName,const sal_Unicode _aQuoteCharacter,const sal_Unicode _aListSeparator)496 void OPropertyExport::exportStringSequenceAttribute(const sal_uInt16 _nAttributeNamespaceKey, const sal_Char* _pAttributeName, 497 const ::rtl::OUString& _rPropertyName, 498 const sal_Unicode _aQuoteCharacter, const sal_Unicode _aListSeparator) 499 { 500 DBG_CHECK_PROPERTY( _rPropertyName, Sequence< ::rtl::OUString > ); 501 OSL_ENSURE(_aListSeparator != 0, "OPropertyExport::exportStringSequenceAttribute: invalid separator character!"); 502 503 Sequence< ::rtl::OUString > aItems; 504 m_xProps->getPropertyValue( _rPropertyName ) >>= aItems; 505 506 ::rtl::OUString sFinalList; 507 508 // unfortunately the OUString can't append single sal_Unicode characters ... 509 const ::rtl::OUString sQuote(&_aQuoteCharacter, 1); 510 const ::rtl::OUString sSeparator(&_aListSeparator, 1); 511 const sal_Bool bQuote = 0 != sQuote.getLength(); 512 513 // concatenate the string items 514 const ::rtl::OUString* pItems = aItems.getConstArray(); 515 const ::rtl::OUString* pEnd = pItems + aItems.getLength(); 516 const ::rtl::OUString* pLastElement = pEnd - 1; 517 for ( ; 518 pItems != pEnd; 519 ++pItems 520 ) 521 { 522 OSL_ENSURE(!_aQuoteCharacter || (-1 == pItems->indexOf(_aQuoteCharacter)), 523 "OPropertyExport::exportStringSequenceAttribute: there is an item which contains the quote character!"); 524 OSL_ENSURE(_aQuoteCharacter || (-1 == pItems->indexOf(_aListSeparator)), 525 "OPropertyExport::exportStringSequenceAttribute: no quote character, but there is an item containing the separator character!"); 526 527 if (bQuote) 528 sFinalList += sQuote; 529 sFinalList += *pItems; 530 if (bQuote) 531 sFinalList += sQuote; 532 533 if (pItems != pLastElement) 534 sFinalList += sSeparator; 535 } 536 537 if (sFinalList.getLength()) 538 AddAttribute(_nAttributeNamespaceKey, _pAttributeName, sFinalList); 539 540 exportedProperty( _rPropertyName ); 541 } 542 543 //--------------------------------------------------------------------- implConvertAny(const Any & _rValue)544 ::rtl::OUString OPropertyExport::implConvertAny(const Any& _rValue) 545 { 546 ::rtl::OUStringBuffer aBuffer; 547 switch (_rValue.getValueTypeClass()) 548 { 549 case TypeClass_STRING: 550 { // extract the string 551 ::rtl::OUString sCurrentValue; 552 _rValue >>= sCurrentValue; 553 aBuffer.append(sCurrentValue); 554 } 555 break; 556 case TypeClass_DOUBLE: 557 // let the unit converter format is as string 558 m_rContext.getGlobalContext().GetMM100UnitConverter().convertDouble(aBuffer, getDouble(_rValue)); 559 break; 560 case TypeClass_BOOLEAN: 561 aBuffer = getBOOL(_rValue) ? m_sValueTrue : m_sValueFalse; 562 break; 563 case TypeClass_BYTE: 564 case TypeClass_SHORT: 565 case TypeClass_LONG: 566 // let the unit converter format is as string 567 m_rContext.getGlobalContext().GetMM100UnitConverter().convertNumber(aBuffer, getINT32(_rValue)); 568 break; 569 case TypeClass_HYPER: 570 // TODO 571 OSL_ENSURE(sal_False, "OPropertyExport::implConvertAny: missing implementation for sal_Int64!"); 572 break; 573 case TypeClass_ENUM: 574 { 575 // convert it into an int32 576 sal_Int32 nValue = 0; 577 ::cppu::enum2int(nValue, _rValue); 578 m_rContext.getGlobalContext().GetMM100UnitConverter().convertNumber(aBuffer, nValue); 579 } 580 break; 581 default: 582 { // hmmm .... what else do we know? 583 double fValue = 0; 584 ::com::sun::star::util::Date aDate; 585 ::com::sun::star::util::Time aTime; 586 ::com::sun::star::util::DateTime aDateTime; 587 if (_rValue >>= aDate) 588 { 589 Date aToolsDate; 590 ::utl::typeConvert(aDate, aToolsDate); 591 fValue = aToolsDate.GetDate(); 592 } 593 else if (_rValue >>= aTime) 594 { 595 fValue = ((aTime.Hours * 60 + aTime.Minutes) * 60 + aTime.Seconds) * 100 + aTime.HundredthSeconds; 596 fValue = fValue / 8640000.0; 597 } 598 else if (_rValue >>= aDateTime) 599 { 600 DateTime aToolsDateTime; 601 ::utl::typeConvert(aDateTime, aToolsDateTime); 602 // the time part (the digits behind the comma) 603 fValue = ((aDateTime.Hours * 60 + aDateTime.Minutes) * 60 + aDateTime.Seconds) * 100 + aDateTime.HundredthSeconds; 604 fValue = fValue / 8640000.0; 605 // plus the data part (the digits in front of the comma) 606 fValue += aToolsDateTime.GetDate(); 607 } 608 else 609 { 610 // if any other types are added here, please remember to adjust implGetPropertyXMLType accordingly 611 612 // no more options ... 613 OSL_ENSURE(sal_False, "OPropertyExport::implConvertAny: unsupported value type!"); 614 break; 615 } 616 // let the unit converter format is as string 617 m_rContext.getGlobalContext().GetMM100UnitConverter().convertDouble(aBuffer, fValue); 618 } 619 break; 620 } 621 622 return aBuffer.makeStringAndClear(); 623 } 624 625 626 //--------------------------------------------------------------------- implGetPropertyXMLType(const::com::sun::star::uno::Type & _rType)627 token::XMLTokenEnum OPropertyExport::implGetPropertyXMLType(const ::com::sun::star::uno::Type& _rType) 628 { 629 // handle the type description 630 switch (_rType.getTypeClass()) 631 { 632 case TypeClass_STRING: 633 return token::XML_STRING; 634 case TypeClass_DOUBLE: 635 case TypeClass_BYTE: 636 case TypeClass_SHORT: 637 case TypeClass_LONG: 638 case TypeClass_HYPER: 639 case TypeClass_ENUM: 640 return token::XML_FLOAT; 641 case TypeClass_BOOLEAN: 642 return token::XML_BOOLEAN; 643 644 default: 645 return token::XML_FLOAT; 646 } 647 } 648 649 #ifdef DBG_UTIL 650 //--------------------------------------------------------------------- AddAttribute(sal_uInt16 _nPrefix,const sal_Char * _pName,const::rtl::OUString & _rValue)651 void OPropertyExport::AddAttribute(sal_uInt16 _nPrefix, const sal_Char* _pName, const ::rtl::OUString& _rValue) 652 { 653 OSL_ENSURE(0 == m_rContext.getGlobalContext().GetXAttrList()->getValueByName(::rtl::OUString::createFromAscii(_pName)).getLength(), 654 "OPropertyExport::AddAttribute: already have such an attribute"); 655 656 m_rContext.getGlobalContext().AddAttribute(_nPrefix, _pName, _rValue); 657 } 658 659 //--------------------------------------------------------------------- AddAttribute(sal_uInt16 _nPrefix,const::rtl::OUString & _rName,const::rtl::OUString & _rValue)660 void OPropertyExport::AddAttribute( sal_uInt16 _nPrefix, const ::rtl::OUString& _rName, const ::rtl::OUString& _rValue ) 661 { 662 OSL_ENSURE(0 == m_rContext.getGlobalContext().GetXAttrList()->getValueByName( _rName ).getLength(), 663 "OPropertyExport::AddAttribute: already have such an attribute"); 664 665 m_rContext.getGlobalContext().AddAttribute( _nPrefix, _rName, _rValue ); 666 } 667 668 //--------------------------------------------------------------------- AddAttributeASCII(sal_uInt16 _nPrefix,const sal_Char * _pName,const sal_Char * pValue)669 void OPropertyExport::AddAttributeASCII(sal_uInt16 _nPrefix, const sal_Char* _pName, const sal_Char *pValue) 670 { 671 OSL_ENSURE(0 == m_rContext.getGlobalContext().GetXAttrList()->getValueByName(::rtl::OUString::createFromAscii(_pName)).getLength(), 672 "OPropertyExport::AddAttributeASCII: already have such an attribute"); 673 674 m_rContext.getGlobalContext().AddAttributeASCII(_nPrefix, _pName, pValue); 675 } 676 677 //--------------------------------------------------------------------- AddAttribute(sal_uInt16 _nPrefix,::xmloff::token::XMLTokenEnum _eName,const::rtl::OUString & _rValue)678 void OPropertyExport::AddAttribute(sal_uInt16 _nPrefix, ::xmloff::token::XMLTokenEnum _eName, const ::rtl::OUString& _rValue) 679 { 680 OSL_ENSURE(0 == m_rContext.getGlobalContext().GetXAttrList()->getValueByName(::xmloff::token::GetXMLToken(_eName)).getLength(), 681 "OPropertyExport::AddAttribute: already have such an attribute"); 682 683 m_rContext.getGlobalContext().AddAttribute(_nPrefix, _eName, _rValue); 684 } 685 686 //--------------------------------------------------------------------- AddAttribute(sal_uInt16 _nPrefix,::xmloff::token::XMLTokenEnum _eName,::xmloff::token::XMLTokenEnum _eValue)687 void OPropertyExport::AddAttribute(sal_uInt16 _nPrefix, ::xmloff::token::XMLTokenEnum _eName, ::xmloff::token::XMLTokenEnum _eValue ) 688 { 689 OSL_ENSURE(0 == m_rContext.getGlobalContext().GetXAttrList()->getValueByName(::xmloff::token::GetXMLToken(_eName)).getLength(), 690 "OPropertyExport::AddAttribute: already have such an attribute"); 691 692 m_rContext.getGlobalContext().AddAttribute(_nPrefix, _eName, _eValue); 693 } 694 695 //--------------------------------------------------------------------- dbg_implCheckProperty(const::rtl::OUString & _rPropertyName,const Type * _pType)696 void OPropertyExport::dbg_implCheckProperty(const ::rtl::OUString& _rPropertyName, const Type* _pType) 697 { 698 try 699 { 700 // the property must exist 701 if (!m_xPropertyInfo->hasPropertyByName(_rPropertyName)) 702 { 703 OSL_ENSURE(sal_False, 704 ::rtl::OString("OPropertyExport::dbg_implCheckProperty: no property with the name ") += 705 ::rtl::OString(_rPropertyName.getStr(), _rPropertyName.getLength(), RTL_TEXTENCODING_ASCII_US) += 706 ::rtl::OString("!")); 707 return; 708 } 709 710 if (_pType) 711 { 712 // and it must have the correct type 713 Property aPropertyDescription = m_xPropertyInfo->getPropertyByName(_rPropertyName); 714 OSL_ENSURE(aPropertyDescription.Type.equals(*_pType), "OPropertyExport::dbg_implCheckProperty: invalid property type!"); 715 } 716 } 717 catch(Exception&) 718 { 719 OSL_ENSURE(sal_False, "OPropertyExport::dbg_implCheckProperty: caught an exception, could not check the property!"); 720 } 721 } 722 #endif // DBG_UTIL - dbg_implCheckProperty 723 724 //......................................................................... 725 } // namespace xmloff 726 //......................................................................... 727 728 729