1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: convdicxml.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_linguistic.hxx"
33 #include <tools/urlobj.hxx>
34 #include <tools/debug.hxx>
35 #include <tools/fsys.hxx>
36 #include <tools/string.hxx>
37 #include <i18npool/mslangid.hxx>
38 #include <tools/stream.hxx>
39 #include <sfx2/docfile.hxx>
40 #include <osl/mutex.hxx>
41 #include <unotools/processfactory.hxx>
42 #include <ucbhelper/content.hxx>
44 #include <cppuhelper/factory.hxx> // helper for factories
45 #include <com/sun/star/linguistic2/XConversionDictionary.hpp>
46 #include <com/sun/star/linguistic2/ConversionDictionaryType.hpp>
47 #include <com/sun/star/linguistic2/ConversionPropertyType.hpp>
48 #include <com/sun/star/util/XFlushable.hpp>
49 #include <com/sun/star/lang/Locale.hpp>
50 #include <com/sun/star/lang/EventObject.hpp>
51 #ifndef _COM_SUN_STAR_UNO_REFERENCE_HPP_
52 #include <com/sun/star/uno/Reference.h>
54 #include <com/sun/star/registry/XRegistryKey.hpp>
55 #include <com/sun/star/util/XFlushListener.hpp>
56 #include <com/sun/star/io/XActiveDataSource.hpp>
57 #include <com/sun/star/document/XFilter.hpp>
58 #include <com/sun/star/beans/PropertyValue.hpp>
59 #include <xmloff/nmspmap.hxx>
60 #include <xmloff/xmlnmspe.hxx>
61 #include <unotools/streamwrap.hxx>
63 #include "convdic.hxx"
64 #include "convdicxml.hxx"
72 using namespace com::sun::star
;
73 using namespace com::sun::star::lang
;
74 using namespace com::sun::star::uno
;
75 using namespace com::sun::star::linguistic2
;
76 using namespace linguistic
;
78 #define XML_NAMESPACE_TCD_STRING "http://openoffice.org/2003/text-conversion-dictionary"
79 #define CONV_TYPE_HANGUL_HANJA "Hangul / Hanja"
80 #define CONV_TYPE_SCHINESE_TCHINESE "Chinese simplified / Chinese traditional"
82 ///////////////////////////////////////////////////////////////////////////
84 static const OUString
ConversionTypeToText( sal_Int16 nConversionType
)
87 if (nConversionType
== ConversionDictionaryType::HANGUL_HANJA
)
88 aRes
= A2OU( CONV_TYPE_HANGUL_HANJA
);
89 else if (nConversionType
== ConversionDictionaryType::SCHINESE_TCHINESE
)
90 aRes
= A2OU( CONV_TYPE_SCHINESE_TCHINESE
);
94 static sal_Int16
GetConversionTypeFromText( const String
&rText
)
97 if (rText
.EqualsAscii( CONV_TYPE_HANGUL_HANJA
))
98 nRes
= ConversionDictionaryType::HANGUL_HANJA
;
99 else if (rText
.EqualsAscii( CONV_TYPE_SCHINESE_TCHINESE
))
100 nRes
= ConversionDictionaryType::SCHINESE_TCHINESE
;
104 ///////////////////////////////////////////////////////////////////////////
106 class ConvDicXMLImportContext
:
107 public SvXMLImportContext
110 ConvDicXMLImportContext(
111 ConvDicXMLImport
&rImport
,
112 sal_uInt16 nPrfx
, const OUString
& rLName
) :
113 SvXMLImportContext( rImport
, nPrfx
, rLName
)
117 const ConvDicXMLImport
& GetConvDicImport() const
119 return (const ConvDicXMLImport
&) GetImport();
122 ConvDicXMLImport
& GetConvDicImport()
124 return (ConvDicXMLImport
&) GetImport();
127 // SvXMLImportContext
128 virtual void Characters( const OUString
&rChars
);
129 virtual SvXMLImportContext
* CreateChildContext( sal_uInt16 nPrefix
, const OUString
& rLocalName
, const uno::Reference
< xml::sax::XAttributeList
> &rxAttrList
);
133 class ConvDicXMLDictionaryContext_Impl
:
134 public ConvDicXMLImportContext
137 sal_Int16 nConversionType
;
140 ConvDicXMLDictionaryContext_Impl( ConvDicXMLImport
&rImport
,
141 sal_uInt16 nPrefix
, const OUString
& rLName
) :
142 ConvDicXMLImportContext( rImport
, nPrefix
, rLName
)
144 nLanguage
= LANGUAGE_NONE
;
145 nConversionType
= -1;
148 // SvXMLImportContext
149 virtual void StartElement( const ::com::sun::star::uno::Reference
< ::com::sun::star::xml::sax::XAttributeList
>& xAttrList
);
150 virtual SvXMLImportContext
* CreateChildContext( sal_uInt16 nPrefix
, const OUString
& rLocalName
, const uno::Reference
< xml::sax::XAttributeList
> &rxAttrList
);
152 INT16
GetLanguage() const { return nLanguage
; }
153 sal_Int16
GetConversionType() const { return nConversionType
; }
157 class ConvDicXMLEntryTextContext_Impl
:
158 public ConvDicXMLImportContext
161 sal_Int16 nPropertyType
; // used for Chinese simplified/traditional conversion
162 ConvDicXMLDictionaryContext_Impl
&rDicContext
;
165 ConvDicXMLEntryTextContext_Impl(
166 ConvDicXMLImport
&rImport
,
167 sal_uInt16 nPrefix
, const OUString
& rLName
,
168 ConvDicXMLDictionaryContext_Impl
&rParentContext
) :
169 ConvDicXMLImportContext( rImport
, nPrefix
, rLName
),
170 nPropertyType( ConversionPropertyType::NOT_DEFINED
),
171 rDicContext( rParentContext
)
175 // SvXMLImportContext
176 virtual void StartElement( const ::com::sun::star::uno::Reference
< ::com::sun::star::xml::sax::XAttributeList
>& xAttrList
);
177 virtual SvXMLImportContext
* CreateChildContext( sal_uInt16 nPrefix
, const OUString
& rLocalName
, const uno::Reference
< xml::sax::XAttributeList
> &rxAttrList
);
179 const OUString
& GetLeftText() const { return aLeftText
; }
180 sal_Int16
GetPropertyType() const { return nPropertyType
; }
181 void SetPropertyType( sal_Int16 nVal
) { nPropertyType
= nVal
; }
185 class ConvDicXMLRightTextContext_Impl
:
186 public ConvDicXMLImportContext
189 ConvDicXMLEntryTextContext_Impl
&rEntryContext
;
192 ConvDicXMLRightTextContext_Impl(
193 ConvDicXMLImport
&rImport
,
194 sal_uInt16 nPrefix
, const OUString
& rLName
,
195 ConvDicXMLEntryTextContext_Impl
&rParentContext
) :
196 ConvDicXMLImportContext( rImport
, nPrefix
, rLName
),
197 rEntryContext( rParentContext
)
201 // SvXMLImportContext
202 virtual void EndElement();
203 virtual SvXMLImportContext
* CreateChildContext( sal_uInt16 nPrefix
, const OUString
& rLocalName
, const uno::Reference
< xml::sax::XAttributeList
> &rxAttrList
);
204 virtual void Characters( const OUString
&rChars
);
206 const OUString
& GetRightText() const { return aRightText
; }
207 const OUString
& GetLeftText() const { return rEntryContext
.GetLeftText(); }
208 ConvDic
* GetDic() { return GetConvDicImport().GetDic(); }
211 ///////////////////////////////////////////////////////////////////////////
213 void ConvDicXMLImportContext::Characters(const OUString
& /*rChars*/)
216 Whitespace occurring within the content of token elements is "trimmed"
217 from the ends (i.e. all whitespace at the beginning and end of the
218 content is removed), and "collapsed" internally (i.e. each sequence of
219 1 or more whitespace characters is replaced with one blank character).
221 //collapsing not done yet!
223 // warning-free code: since the result is not used there is no need for trimming...
224 //const OUString &rChars2 = rChars.trim();
227 SvXMLImportContext
* ConvDicXMLImportContext::CreateChildContext(
228 sal_uInt16 nPrefix
, const OUString
& rLocalName
,
229 const uno::Reference
< xml::sax::XAttributeList
> & /*rxAttrList*/ )
231 SvXMLImportContext
*pContext
= 0;
232 if (nPrefix
== XML_NAMESPACE_TCD
&& rLocalName
.equalsAscii( "text-conversion-dictionary" ))
233 pContext
= new ConvDicXMLDictionaryContext_Impl( GetConvDicImport(), nPrefix
, rLocalName
);
235 pContext
= new SvXMLImportContext( GetImport(), nPrefix
, rLocalName
);
239 ////////////////////////////////////////
241 void ConvDicXMLDictionaryContext_Impl::StartElement(
242 const uno::Reference
< xml::sax::XAttributeList
> &rxAttrList
)
244 sal_Int16 nAttrCount
= rxAttrList
.is() ? rxAttrList
->getLength() : 0;
245 for (sal_Int16 i
= 0; i
< nAttrCount
; ++i
)
247 OUString aAttrName
= rxAttrList
->getNameByIndex(i
);
249 sal_uInt16 nPrefix
= GetImport().GetNamespaceMap().
250 GetKeyByAttrName( aAttrName
, &aLocalName
);
251 OUString aValue
= rxAttrList
->getValueByIndex(i
);
253 if (nPrefix
== XML_NAMESPACE_TCD
&& aLocalName
.equalsAscii( "lang" ))
254 nLanguage
= MsLangId::convertIsoStringToLanguage( aValue
);
255 else if (nPrefix
== XML_NAMESPACE_TCD
&& aLocalName
.equalsAscii( "conversion-type" ))
256 nConversionType
= GetConversionTypeFromText( aValue
);
258 GetConvDicImport().SetLanguage( nLanguage
);
259 GetConvDicImport().SetConversionType( nConversionType
);
261 //!! hack to stop the parser from reading the rest of the file !!
262 //!! when only the header (language, conversion type) is needed !!
263 // if (GetConvDicImport().GetDic() == 0)
264 // throw uno::RuntimeException();
267 SvXMLImportContext
* ConvDicXMLDictionaryContext_Impl::CreateChildContext(
268 sal_uInt16 nPrefix
, const OUString
& rLocalName
,
269 const uno::Reference
< xml::sax::XAttributeList
> & /*rxAttrList*/ )
271 SvXMLImportContext
*pContext
= 0;
272 if (nPrefix
== XML_NAMESPACE_TCD
&& rLocalName
.equalsAscii( "entry" ))
273 pContext
= new ConvDicXMLEntryTextContext_Impl( GetConvDicImport(), nPrefix
, rLocalName
, *this );
275 pContext
= new SvXMLImportContext( GetImport(), nPrefix
, rLocalName
);
279 ////////////////////////////////////////
281 SvXMLImportContext
* ConvDicXMLEntryTextContext_Impl::CreateChildContext(
282 sal_uInt16 nPrefix
, const OUString
& rLocalName
,
283 const uno::Reference
< xml::sax::XAttributeList
> & /*rxAttrList*/ )
285 SvXMLImportContext
*pContext
= 0;
286 if (nPrefix
== XML_NAMESPACE_TCD
&& rLocalName
.equalsAscii( "right-text" ))
287 pContext
= new ConvDicXMLRightTextContext_Impl( GetConvDicImport(), nPrefix
, rLocalName
, *this );
289 pContext
= new SvXMLImportContext( GetImport(), nPrefix
, rLocalName
);
293 void ConvDicXMLEntryTextContext_Impl::StartElement(
294 const uno::Reference
< xml::sax::XAttributeList
>& rxAttrList
)
296 sal_Int16 nAttrCount
= rxAttrList
.is() ? rxAttrList
->getLength() : 0;
297 for (sal_Int16 i
= 0; i
< nAttrCount
; ++i
)
299 OUString aAttrName
= rxAttrList
->getNameByIndex(i
);
301 sal_uInt16 nPrefix
= GetImport().GetNamespaceMap().
302 GetKeyByAttrName( aAttrName
, &aLocalName
);
303 OUString aValue
= rxAttrList
->getValueByIndex(i
);
305 if (nPrefix
== XML_NAMESPACE_TCD
&& aLocalName
.equalsAscii( "left-text" ))
307 if (nPrefix
== XML_NAMESPACE_TCD
&& aLocalName
.equalsAscii( "property-type" ))
308 nPropertyType
= (sal_Int16
) aValue
.toInt32();
312 ////////////////////////////////////////
314 SvXMLImportContext
* ConvDicXMLRightTextContext_Impl::CreateChildContext(
315 sal_uInt16 nPrefix
, const OUString
& rLocalName
,
316 const uno::Reference
< xml::sax::XAttributeList
> & /*rxAttrList*/ )
318 // leaf: return default (empty) context
319 SvXMLImportContext
*pContext
= new SvXMLImportContext( GetImport(), nPrefix
, rLocalName
);
323 void ConvDicXMLRightTextContext_Impl::Characters( const OUString
&rChars
)
325 aRightText
+= rChars
;
328 void ConvDicXMLRightTextContext_Impl::EndElement()
330 ConvDic
*pDic
= GetDic();
332 pDic
->AddEntry( GetLeftText(), GetRightText() );
336 ///////////////////////////////////////////////////////////////////////////
338 sal_Bool
ConvDicXMLExport::Export( SfxMedium
& /*rMedium*/ )
340 sal_Bool bRet
= sal_False
;
342 uno::Reference
< document::XExporter
> xExporter( this );
343 uno::Reference
< document::XFilter
> xFilter( xExporter
, UNO_QUERY
);
344 uno::Sequence
< beans::PropertyValue
> aProps(0);
345 xFilter
->filter( aProps
); // calls exportDoc implicitly
347 return bRet
= bSuccess
;
351 sal_uInt32
ConvDicXMLExport::exportDoc( enum ::xmloff::token::XMLTokenEnum
/*eClass*/ )
353 _GetNamespaceMap().Add( A2OU( "tcd" ),
354 A2OU( XML_NAMESPACE_TCD_STRING
), XML_NAMESPACE_TCD
);
356 GetDocHandler()->startDocument();
358 // Add xmlns line and some other arguments
359 AddAttribute( _GetNamespaceMap().GetAttrNameByKey( XML_NAMESPACE_TCD
),
360 _GetNamespaceMap().GetNameByKey( XML_NAMESPACE_TCD
) );
361 AddAttributeASCII( XML_NAMESPACE_TCD
, "package", "org.openoffice.Office" );
363 OUString
aIsoLang( MsLangId::convertLanguageToIsoString( rDic
.nLanguage
) );
364 AddAttribute( XML_NAMESPACE_TCD
, "lang", aIsoLang
);
365 OUString
aConvType( ConversionTypeToText( rDic
.nConversionType
) );
366 AddAttribute( XML_NAMESPACE_TCD
, "conversion-type", aConvType
);
368 //!! block necessary in order to have SvXMLElementExport d-tor called
369 //!! before the call to endDocument
371 SvXMLElementExport
aRoot( *this, XML_NAMESPACE_TCD
, "text-conversion-dictionary", sal_True
, sal_True
);
375 GetDocHandler()->endDocument();
382 void ConvDicXMLExport::_ExportContent()
384 // aquire sorted list of all keys
385 ConvMapKeySet aKeySet
;
386 ConvMap::iterator aIt
;
387 for (aIt
= rDic
.aFromLeft
.begin(); aIt
!= rDic
.aFromLeft
.end(); ++aIt
)
388 aKeySet
.insert( (*aIt
).first
);
390 ConvMapKeySet::iterator aKeyIt
;
391 for (aKeyIt
= aKeySet
.begin(); aKeyIt
!= aKeySet
.end(); ++aKeyIt
)
393 OUString
aLeftText( *aKeyIt
);
394 AddAttribute( XML_NAMESPACE_TCD
, "left-text", aLeftText
);
395 if (rDic
.pConvPropType
.get()) // property-type list available?
397 sal_Int16 nPropertyType
= -1;
398 PropTypeMap::iterator aIt2
= rDic
.pConvPropType
->find( aLeftText
);
399 if (aIt2
!= rDic
.pConvPropType
->end())
400 nPropertyType
= (*aIt2
).second
;
401 DBG_ASSERT( nPropertyType
, "property-type not found" );
402 if (nPropertyType
== -1)
403 nPropertyType
= ConversionPropertyType::NOT_DEFINED
;
404 AddAttribute( XML_NAMESPACE_TCD
, "property-type", OUString::valueOf( (sal_Int32
) nPropertyType
) );
406 SvXMLElementExport
aEntryMain( *this, XML_NAMESPACE_TCD
,
407 "entry" , sal_True
, sal_True
);
409 pair
< ConvMap::iterator
, ConvMap::iterator
> aRange
=
410 rDic
.aFromLeft
.equal_range( *aKeyIt
);
411 for (aIt
= aRange
.first
; aIt
!= aRange
.second
; ++aIt
)
413 DBG_ASSERT( *aKeyIt
== (*aIt
).first
, "key <-> entry mismatch" );
414 OUString
aRightText( (*aIt
).second
);
415 SvXMLElementExport
aEntryRightText( *this, XML_NAMESPACE_TCD
,
416 "right-text" , sal_True
, sal_False
);
417 Characters( aRightText
);
422 ::rtl::OUString SAL_CALL
ConvDicXMLExport::getImplementationName()
423 throw( uno::RuntimeException
)
425 return A2OU( "com.sun.star.lingu2.ConvDicXMLExport" );
428 ///////////////////////////////////////////////////////////////////////////
430 void SAL_CALL
ConvDicXMLImport::startDocument(void)
431 throw( xml::sax::SAXException
, uno::RuntimeException
)
433 // register namespace at first possible opportunity
434 GetNamespaceMap().Add( A2OU( "tcd" ),
435 A2OU( XML_NAMESPACE_TCD_STRING
), XML_NAMESPACE_TCD
);
436 SvXMLImport::startDocument();
439 void SAL_CALL
ConvDicXMLImport::endDocument(void)
440 throw( xml::sax::SAXException
, uno::RuntimeException
)
442 SvXMLImport::endDocument();
445 SvXMLImportContext
* ConvDicXMLImport::CreateContext(
447 const rtl::OUString
&rLocalName
,
448 const uno::Reference
< xml::sax::XAttributeList
> & /*rxAttrList*/ )
450 SvXMLImportContext
*pContext
= 0;
451 if (nPrefix
== XML_NAMESPACE_TCD
&& rLocalName
.equalsAscii( "text-conversion-dictionary" ))
452 pContext
= new ConvDicXMLDictionaryContext_Impl( *this, nPrefix
, rLocalName
);
454 pContext
= new SvXMLImportContext( *this, nPrefix
, rLocalName
);
459 OUString SAL_CALL
ConvDicXMLImport::getImplementationName()
460 throw( uno::RuntimeException
)
462 return A2OU( "com.sun.star.lingu2.ConvDicXMLImport" );
465 ///////////////////////////////////////////////////////////////////////////