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 .
20 #include <tools/debug.hxx>
21 #include <tools/fsys.hxx>
22 #include <tools/string.hxx>
23 #include <i18npool/languagetag.hxx>
24 #include <tools/stream.hxx>
25 #include <osl/mutex.hxx>
26 #include <ucbhelper/content.hxx>
28 #include <cppuhelper/factory.hxx> // helper for factories
29 #include <com/sun/star/linguistic2/XConversionDictionary.hpp>
30 #include <com/sun/star/linguistic2/ConversionDictionaryType.hpp>
31 #include <com/sun/star/linguistic2/ConversionPropertyType.hpp>
32 #include <com/sun/star/util/XFlushable.hpp>
33 #include <com/sun/star/lang/Locale.hpp>
34 #include <com/sun/star/lang/EventObject.hpp>
35 #include <com/sun/star/uno/Reference.h>
36 #include <com/sun/star/registry/XRegistryKey.hpp>
37 #include <com/sun/star/util/XFlushListener.hpp>
38 #include <com/sun/star/io/XActiveDataSource.hpp>
39 #include <com/sun/star/document/XFilter.hpp>
40 #include <com/sun/star/beans/PropertyValue.hpp>
41 #include <xmloff/nmspmap.hxx>
42 #include <xmloff/xmlnmspe.hxx>
43 #include <unotools/streamwrap.hxx>
45 #include "convdic.hxx"
46 #include "convdicxml.hxx"
47 #include "linguistic/misc.hxx"
53 using namespace com::sun::star
;
54 using namespace com::sun::star::lang
;
55 using namespace com::sun::star::uno
;
56 using namespace com::sun::star::linguistic2
;
57 using namespace linguistic
;
59 using ::rtl::OUString
;
61 #define XML_NAMESPACE_TCD_STRING "http://openoffice.org/2003/text-conversion-dictionary"
62 #define CONV_TYPE_HANGUL_HANJA "Hangul / Hanja"
63 #define CONV_TYPE_SCHINESE_TCHINESE "Chinese simplified / Chinese traditional"
66 static const OUString
ConversionTypeToText( sal_Int16 nConversionType
)
69 if (nConversionType
== ConversionDictionaryType::HANGUL_HANJA
)
70 aRes
= A2OU( CONV_TYPE_HANGUL_HANJA
);
71 else if (nConversionType
== ConversionDictionaryType::SCHINESE_TCHINESE
)
72 aRes
= A2OU( CONV_TYPE_SCHINESE_TCHINESE
);
76 static sal_Int16
GetConversionTypeFromText( const String
&rText
)
79 if (rText
.EqualsAscii( CONV_TYPE_HANGUL_HANJA
))
80 nRes
= ConversionDictionaryType::HANGUL_HANJA
;
81 else if (rText
.EqualsAscii( CONV_TYPE_SCHINESE_TCHINESE
))
82 nRes
= ConversionDictionaryType::SCHINESE_TCHINESE
;
87 class ConvDicXMLImportContext
:
88 public SvXMLImportContext
91 ConvDicXMLImportContext(
92 ConvDicXMLImport
&rImport
,
93 sal_uInt16 nPrfx
, const OUString
& rLName
) :
94 SvXMLImportContext( rImport
, nPrfx
, rLName
)
98 const ConvDicXMLImport
& GetConvDicImport() const
100 return (const ConvDicXMLImport
&) GetImport();
103 ConvDicXMLImport
& GetConvDicImport()
105 return (ConvDicXMLImport
&) GetImport();
108 // SvXMLImportContext
109 virtual void Characters( const OUString
&rChars
);
110 virtual SvXMLImportContext
* CreateChildContext( sal_uInt16 nPrefix
, const OUString
& rLocalName
, const uno::Reference
< xml::sax::XAttributeList
> &rxAttrList
);
114 class ConvDicXMLDictionaryContext_Impl
:
115 public ConvDicXMLImportContext
118 sal_Int16 nConversionType
;
121 ConvDicXMLDictionaryContext_Impl( ConvDicXMLImport
&rImport
,
122 sal_uInt16 nPrefix
, const OUString
& rLName
) :
123 ConvDicXMLImportContext( rImport
, nPrefix
, rLName
)
125 nLanguage
= LANGUAGE_NONE
;
126 nConversionType
= -1;
129 // SvXMLImportContext
130 virtual void StartElement( const ::com::sun::star::uno::Reference
< ::com::sun::star::xml::sax::XAttributeList
>& xAttrList
);
131 virtual SvXMLImportContext
* CreateChildContext( sal_uInt16 nPrefix
, const OUString
& rLocalName
, const uno::Reference
< xml::sax::XAttributeList
> &rxAttrList
);
133 sal_Int16
GetLanguage() const { return nLanguage
; }
134 sal_Int16
GetConversionType() const { return nConversionType
; }
138 class ConvDicXMLEntryTextContext_Impl
:
139 public ConvDicXMLImportContext
142 sal_Int16 nPropertyType
; // used for Chinese simplified/traditional conversion
145 ConvDicXMLEntryTextContext_Impl(
146 ConvDicXMLImport
&rImport
,
147 sal_uInt16 nPrefix
, const OUString
& rLName
) :
148 ConvDicXMLImportContext( rImport
, nPrefix
, rLName
),
149 nPropertyType( ConversionPropertyType::NOT_DEFINED
)
153 // SvXMLImportContext
154 virtual void StartElement( const ::com::sun::star::uno::Reference
< ::com::sun::star::xml::sax::XAttributeList
>& xAttrList
);
155 virtual SvXMLImportContext
* CreateChildContext( sal_uInt16 nPrefix
, const OUString
& rLocalName
, const uno::Reference
< xml::sax::XAttributeList
> &rxAttrList
);
157 const OUString
& GetLeftText() const { return aLeftText
; }
158 sal_Int16
GetPropertyType() const { return nPropertyType
; }
159 void SetPropertyType( sal_Int16 nVal
) { nPropertyType
= nVal
; }
163 class ConvDicXMLRightTextContext_Impl
:
164 public ConvDicXMLImportContext
167 ConvDicXMLEntryTextContext_Impl
&rEntryContext
;
170 ConvDicXMLRightTextContext_Impl(
171 ConvDicXMLImport
&rImport
,
172 sal_uInt16 nPrefix
, const OUString
& rLName
,
173 ConvDicXMLEntryTextContext_Impl
&rParentContext
) :
174 ConvDicXMLImportContext( rImport
, nPrefix
, rLName
),
175 rEntryContext( rParentContext
)
179 // SvXMLImportContext
180 virtual void EndElement();
181 virtual SvXMLImportContext
* CreateChildContext( sal_uInt16 nPrefix
, const OUString
& rLocalName
, const uno::Reference
< xml::sax::XAttributeList
> &rxAttrList
);
182 virtual void Characters( const OUString
&rChars
);
184 const OUString
& GetRightText() const { return aRightText
; }
185 const OUString
& GetLeftText() const { return rEntryContext
.GetLeftText(); }
186 ConvDic
* GetDic() { return GetConvDicImport().GetDic(); }
190 void ConvDicXMLImportContext::Characters(const OUString
& /*rChars*/)
193 Whitespace occurring within the content of token elements is "trimmed"
194 from the ends (i.e. all whitespace at the beginning and end of the
195 content is removed), and "collapsed" internally (i.e. each sequence of
196 1 or more whitespace characters is replaced with one blank character).
198 //collapsing not done yet!
202 SvXMLImportContext
* ConvDicXMLImportContext::CreateChildContext(
203 sal_uInt16 nPrefix
, const OUString
& rLocalName
,
204 const uno::Reference
< xml::sax::XAttributeList
> & /*rxAttrList*/ )
206 SvXMLImportContext
*pContext
= 0;
207 if ( nPrefix
== XML_NAMESPACE_TCD
&& rLocalName
== "text-conversion-dictionary" )
208 pContext
= new ConvDicXMLDictionaryContext_Impl( GetConvDicImport(), nPrefix
, rLocalName
);
210 pContext
= new SvXMLImportContext( GetImport(), nPrefix
, rLocalName
);
215 void ConvDicXMLDictionaryContext_Impl::StartElement(
216 const uno::Reference
< xml::sax::XAttributeList
> &rxAttrList
)
218 sal_Int16 nAttrCount
= rxAttrList
.is() ? rxAttrList
->getLength() : 0;
219 for (sal_Int16 i
= 0; i
< nAttrCount
; ++i
)
221 OUString aAttrName
= rxAttrList
->getNameByIndex(i
);
223 sal_uInt16 nPrefix
= GetImport().GetNamespaceMap().
224 GetKeyByAttrName( aAttrName
, &aLocalName
);
225 OUString aValue
= rxAttrList
->getValueByIndex(i
);
227 if ( nPrefix
== XML_NAMESPACE_TCD
&& aLocalName
== "lang" )
228 nLanguage
= LanguageTag( aValue
).getLanguageType();
229 else if ( nPrefix
== XML_NAMESPACE_TCD
&& aLocalName
== "conversion-type" )
230 nConversionType
= GetConversionTypeFromText( aValue
);
232 GetConvDicImport().SetLanguage( nLanguage
);
233 GetConvDicImport().SetConversionType( nConversionType
);
237 SvXMLImportContext
* ConvDicXMLDictionaryContext_Impl::CreateChildContext(
238 sal_uInt16 nPrefix
, const OUString
& rLocalName
,
239 const uno::Reference
< xml::sax::XAttributeList
> & /*rxAttrList*/ )
241 SvXMLImportContext
*pContext
= 0;
242 if ( nPrefix
== XML_NAMESPACE_TCD
&& rLocalName
== "entry" )
243 pContext
= new ConvDicXMLEntryTextContext_Impl( GetConvDicImport(), nPrefix
, rLocalName
);
245 pContext
= new SvXMLImportContext( GetImport(), nPrefix
, rLocalName
);
250 SvXMLImportContext
* ConvDicXMLEntryTextContext_Impl::CreateChildContext(
251 sal_uInt16 nPrefix
, const OUString
& rLocalName
,
252 const uno::Reference
< xml::sax::XAttributeList
> & /*rxAttrList*/ )
254 SvXMLImportContext
*pContext
= 0;
255 if ( nPrefix
== XML_NAMESPACE_TCD
&& rLocalName
== "right-text" )
256 pContext
= new ConvDicXMLRightTextContext_Impl( GetConvDicImport(), nPrefix
, rLocalName
, *this );
258 pContext
= new SvXMLImportContext( GetImport(), nPrefix
, rLocalName
);
262 void ConvDicXMLEntryTextContext_Impl::StartElement(
263 const uno::Reference
< xml::sax::XAttributeList
>& rxAttrList
)
265 sal_Int16 nAttrCount
= rxAttrList
.is() ? rxAttrList
->getLength() : 0;
266 for (sal_Int16 i
= 0; i
< nAttrCount
; ++i
)
268 OUString aAttrName
= rxAttrList
->getNameByIndex(i
);
270 sal_uInt16 nPrefix
= GetImport().GetNamespaceMap().
271 GetKeyByAttrName( aAttrName
, &aLocalName
);
272 OUString aValue
= rxAttrList
->getValueByIndex(i
);
274 if ( nPrefix
== XML_NAMESPACE_TCD
&& aLocalName
== "left-text" )
276 if ( nPrefix
== XML_NAMESPACE_TCD
&& aLocalName
== "property-type" )
277 nPropertyType
= (sal_Int16
) aValue
.toInt32();
282 SvXMLImportContext
* ConvDicXMLRightTextContext_Impl::CreateChildContext(
283 sal_uInt16 nPrefix
, const OUString
& rLocalName
,
284 const uno::Reference
< xml::sax::XAttributeList
> & /*rxAttrList*/ )
286 // leaf: return default (empty) context
287 SvXMLImportContext
*pContext
= new SvXMLImportContext( GetImport(), nPrefix
, rLocalName
);
291 void ConvDicXMLRightTextContext_Impl::Characters( const OUString
&rChars
)
293 aRightText
+= rChars
;
296 void ConvDicXMLRightTextContext_Impl::EndElement()
298 ConvDic
*pDic
= GetDic();
300 pDic
->AddEntry( GetLeftText(), GetRightText() );
305 sal_Bool
ConvDicXMLExport::Export()
307 sal_Bool bRet
= sal_False
;
309 uno::Reference
< document::XExporter
> xExporter( this );
310 uno::Reference
< document::XFilter
> xFilter( xExporter
, UNO_QUERY
);
311 uno::Sequence
< beans::PropertyValue
> aProps(0);
312 xFilter
->filter( aProps
); // calls exportDoc implicitly
314 return bRet
= bSuccess
;
318 sal_uInt32
ConvDicXMLExport::exportDoc( enum ::xmloff::token::XMLTokenEnum
/*eClass*/ )
320 _GetNamespaceMap().Add( A2OU( "tcd" ),
321 A2OU( XML_NAMESPACE_TCD_STRING
), XML_NAMESPACE_TCD
);
323 GetDocHandler()->startDocument();
325 // Add xmlns line and some other arguments
326 AddAttribute( _GetNamespaceMap().GetAttrNameByKey( XML_NAMESPACE_TCD
),
327 _GetNamespaceMap().GetNameByKey( XML_NAMESPACE_TCD
) );
328 AddAttributeASCII( XML_NAMESPACE_TCD
, "package", "org.openoffice.Office" );
330 OUString
aIsoLang( LanguageTag( rDic
.nLanguage
).getBcp47() );
331 AddAttribute( XML_NAMESPACE_TCD
, "lang", aIsoLang
);
332 OUString
aConvType( ConversionTypeToText( rDic
.nConversionType
) );
333 AddAttribute( XML_NAMESPACE_TCD
, "conversion-type", aConvType
);
335 //!! block necessary in order to have SvXMLElementExport d-tor called
336 //!! before the call to endDocument
338 SvXMLElementExport
aRoot( *this, XML_NAMESPACE_TCD
, "text-conversion-dictionary", sal_True
, sal_True
);
342 GetDocHandler()->endDocument();
349 void ConvDicXMLExport::_ExportContent()
351 // aquire sorted list of all keys
352 ConvMapKeySet aKeySet
;
353 ConvMap::iterator aIt
;
354 for (aIt
= rDic
.aFromLeft
.begin(); aIt
!= rDic
.aFromLeft
.end(); ++aIt
)
355 aKeySet
.insert( (*aIt
).first
);
357 ConvMapKeySet::iterator aKeyIt
;
358 for (aKeyIt
= aKeySet
.begin(); aKeyIt
!= aKeySet
.end(); ++aKeyIt
)
360 OUString
aLeftText( *aKeyIt
);
361 AddAttribute( XML_NAMESPACE_TCD
, "left-text", aLeftText
);
362 if (rDic
.pConvPropType
.get()) // property-type list available?
364 sal_Int16 nPropertyType
= -1;
365 PropTypeMap::iterator aIt2
= rDic
.pConvPropType
->find( aLeftText
);
366 if (aIt2
!= rDic
.pConvPropType
->end())
367 nPropertyType
= (*aIt2
).second
;
368 DBG_ASSERT( nPropertyType
, "property-type not found" );
369 if (nPropertyType
== -1)
370 nPropertyType
= ConversionPropertyType::NOT_DEFINED
;
371 AddAttribute( XML_NAMESPACE_TCD
, "property-type", OUString::valueOf( (sal_Int32
) nPropertyType
) );
373 SvXMLElementExport
aEntryMain( *this, XML_NAMESPACE_TCD
,
374 "entry" , sal_True
, sal_True
);
376 pair
< ConvMap::iterator
, ConvMap::iterator
> aRange
=
377 rDic
.aFromLeft
.equal_range( *aKeyIt
);
378 for (aIt
= aRange
.first
; aIt
!= aRange
.second
; ++aIt
)
380 DBG_ASSERT( *aKeyIt
== (*aIt
).first
, "key <-> entry mismatch" );
381 OUString
aRightText( (*aIt
).second
);
382 SvXMLElementExport
aEntryRightText( *this, XML_NAMESPACE_TCD
,
383 "right-text" , sal_True
, sal_False
);
384 Characters( aRightText
);
389 ::rtl::OUString SAL_CALL
ConvDicXMLExport::getImplementationName()
390 throw( uno::RuntimeException
)
392 return A2OU( "com.sun.star.lingu2.ConvDicXMLExport" );
396 void SAL_CALL
ConvDicXMLImport::startDocument(void)
397 throw( xml::sax::SAXException
, uno::RuntimeException
)
399 // register namespace at first possible opportunity
400 GetNamespaceMap().Add( A2OU( "tcd" ),
401 A2OU( XML_NAMESPACE_TCD_STRING
), XML_NAMESPACE_TCD
);
402 SvXMLImport::startDocument();
405 void SAL_CALL
ConvDicXMLImport::endDocument(void)
406 throw( xml::sax::SAXException
, uno::RuntimeException
)
408 SvXMLImport::endDocument();
411 SvXMLImportContext
* ConvDicXMLImport::CreateContext(
413 const rtl::OUString
&rLocalName
,
414 const uno::Reference
< xml::sax::XAttributeList
> & /*rxAttrList*/ )
416 SvXMLImportContext
*pContext
= 0;
417 if ( nPrefix
== XML_NAMESPACE_TCD
&& rLocalName
== "text-conversion-dictionary" )
418 pContext
= new ConvDicXMLDictionaryContext_Impl( *this, nPrefix
, rLocalName
);
420 pContext
= new SvXMLImportContext( *this, nPrefix
, rLocalName
);
425 OUString SAL_CALL
ConvDicXMLImport::getImplementationName()
426 throw( uno::RuntimeException
)
428 return A2OU( "com.sun.star.lingu2.ConvDicXMLImport" );
432 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */