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 <i18nlangtag/languagetag.hxx>
23 #include <com/sun/star/linguistic2/ConversionDictionaryType.hpp>
24 #include <com/sun/star/linguistic2/ConversionPropertyType.hpp>
25 #include <com/sun/star/lang/Locale.hpp>
26 #include <com/sun/star/uno/Reference.h>
27 #include <com/sun/star/document/XFilter.hpp>
28 #include <com/sun/star/beans/PropertyValue.hpp>
29 #include <xmloff/namespacemap.hxx>
30 #include <xmloff/xmlnamespace.hxx>
31 #include <unotools/streamwrap.hxx>
33 #include "convdic.hxx"
34 #include "convdicxml.hxx"
35 #include <linguistic/misc.hxx>
37 using namespace com::sun::star
;
38 using namespace com::sun::star::uno
;
39 using namespace com::sun::star::linguistic2
;
42 constexpr OUStringLiteral XML_NAMESPACE_TCD_STRING
= u
"http://openoffice.org/2003/text-conversion-dictionary";
43 constexpr OUString CONV_TYPE_HANGUL_HANJA
= u
"Hangul / Hanja"_ustr
;
44 constexpr OUString CONV_TYPE_SCHINESE_TCHINESE
= u
"Chinese simplified / Chinese traditional"_ustr
;
47 static OUString
ConversionTypeToText( sal_Int16 nConversionType
)
50 if (nConversionType
== ConversionDictionaryType::HANGUL_HANJA
)
51 aRes
= CONV_TYPE_HANGUL_HANJA
;
52 else if (nConversionType
== ConversionDictionaryType::SCHINESE_TCHINESE
)
53 aRes
= CONV_TYPE_SCHINESE_TCHINESE
;
57 static sal_Int16
GetConversionTypeFromText( std::u16string_view rText
)
60 if (rText
== CONV_TYPE_HANGUL_HANJA
)
61 nRes
= ConversionDictionaryType::HANGUL_HANJA
;
62 else if (rText
== CONV_TYPE_SCHINESE_TCHINESE
)
63 nRes
= ConversionDictionaryType::SCHINESE_TCHINESE
;
69 class ConvDicXMLImportContext
:
70 public SvXMLImportContext
73 ConvDicXMLImportContext( ConvDicXMLImport
&rImport
) :
74 SvXMLImportContext( rImport
)
78 ConvDicXMLImport
& GetConvDicImport()
80 return static_cast<ConvDicXMLImport
&>(GetImport());
84 virtual css::uno::Reference
<XFastContextHandler
> SAL_CALL
createFastChildContext(
85 sal_Int32 Element
, const css::uno::Reference
< css::xml::sax::XFastAttributeList
> & xAttrList
) override
;
89 class ConvDicXMLDictionaryContext_Impl
:
90 public ConvDicXMLImportContext
92 LanguageType nLanguage
;
93 sal_Int16 nConversionType
;
96 ConvDicXMLDictionaryContext_Impl( ConvDicXMLImport
&rImport
) :
97 ConvDicXMLImportContext( rImport
),
98 nLanguage(LANGUAGE_NONE
), nConversionType(-1)
102 // SvXMLImportContext
103 virtual void SAL_CALL
startFastElement( sal_Int32 nElement
, const css::uno::Reference
< css::xml::sax::XFastAttributeList
>& Attribs
) override
;
104 virtual css::uno::Reference
<XFastContextHandler
> SAL_CALL
createFastChildContext(
105 sal_Int32 Element
, const css::uno::Reference
< css::xml::sax::XFastAttributeList
> & xAttrList
) override
;
109 class ConvDicXMLEntryTextContext_Impl
:
110 public ConvDicXMLImportContext
115 ConvDicXMLEntryTextContext_Impl( ConvDicXMLImport
&rImport
) :
116 ConvDicXMLImportContext( rImport
)
120 // SvXMLImportContext
121 virtual void SAL_CALL
startFastElement( sal_Int32 nElement
, const css::uno::Reference
< css::xml::sax::XFastAttributeList
>& Attribs
) override
;
122 virtual css::uno::Reference
<XFastContextHandler
> SAL_CALL
createFastChildContext(
123 sal_Int32 Element
, const css::uno::Reference
< css::xml::sax::XFastAttributeList
> & xAttrList
) override
;
125 const OUString
& GetLeftText() const { return aLeftText
; }
129 class ConvDicXMLRightTextContext_Impl
:
130 public ConvDicXMLImportContext
133 ConvDicXMLEntryTextContext_Impl
&rEntryContext
;
136 ConvDicXMLRightTextContext_Impl(
137 ConvDicXMLImport
&rImport
,
138 ConvDicXMLEntryTextContext_Impl
&rParentContext
) :
139 ConvDicXMLImportContext( rImport
),
140 rEntryContext( rParentContext
)
144 // SvXMLImportContext
145 virtual void SAL_CALL
endFastElement( sal_Int32 nElement
) override
;
146 virtual void SAL_CALL
characters( const OUString
&rChars
) override
;
151 //void ConvDicXMLImportContext::characters(const OUString & /*rChars*/)
154 Whitespace occurring within the content of token elements is "trimmed"
155 from the ends (i.e. all whitespace at the beginning and end of the
156 content is removed), and "collapsed" internally (i.e. each sequence of
157 1 or more whitespace characters is replaced with one blank character).
159 //collapsing not done yet!
163 css::uno::Reference
<XFastContextHandler
> ConvDicXMLImportContext::createFastChildContext(
165 const css::uno::Reference
< css::xml::sax::XFastAttributeList
> & /*xAttrList*/ )
167 if ( Element
== ConvDicXMLToken::TEXT_CONVERSION_DICTIONARY
)
168 return new ConvDicXMLDictionaryContext_Impl( GetConvDicImport() );
173 void ConvDicXMLDictionaryContext_Impl::startFastElement( sal_Int32
/*nElement*/,
174 const css::uno::Reference
< css::xml::sax::XFastAttributeList
>& rxAttrList
)
176 for (auto &aIter
: sax_fastparser::castToFastAttributeList( rxAttrList
))
178 switch (aIter
.getToken())
180 case XML_NAMESPACE_TCD
| XML_LANG
:
181 nLanguage
= LanguageTag::convertToLanguageType( aIter
.toString() );
183 case XML_NAMESPACE_TCD
| XML_CONVERSION_TYPE
:
184 nConversionType
= GetConversionTypeFromText( aIter
.toString() );
190 GetConvDicImport().SetLanguage( nLanguage
);
191 GetConvDicImport().SetConversionType( nConversionType
);
195 css::uno::Reference
<XFastContextHandler
> ConvDicXMLDictionaryContext_Impl::createFastChildContext(
197 const css::uno::Reference
< css::xml::sax::XFastAttributeList
> & /*xAttrList*/ )
199 if ( Element
== ConvDicXMLToken::ENTRY
)
200 return new ConvDicXMLEntryTextContext_Impl( GetConvDicImport() );
204 css::uno::Reference
<XFastContextHandler
> ConvDicXMLEntryTextContext_Impl::createFastChildContext(
206 const css::uno::Reference
< css::xml::sax::XFastAttributeList
> & /*xAttrList*/ )
208 if ( Element
== ConvDicXMLToken::RIGHT_TEXT
)
209 return new ConvDicXMLRightTextContext_Impl( GetConvDicImport(), *this );
213 void ConvDicXMLEntryTextContext_Impl::startFastElement(
214 sal_Int32
/*Element*/,
215 const css::uno::Reference
< css::xml::sax::XFastAttributeList
>& rxAttrList
)
217 for (auto &aIter
: sax_fastparser::castToFastAttributeList( rxAttrList
))
219 switch (aIter
.getToken())
221 case XML_NAMESPACE_TCD
| XML_LEFT_TEXT
:
222 aLeftText
= aIter
.toString();
231 void ConvDicXMLRightTextContext_Impl::characters( const OUString
&rChars
)
233 aRightText
+= rChars
;
236 void ConvDicXMLRightTextContext_Impl::endFastElement( sal_Int32
/*nElement*/ )
238 ConvDic
*pDic
= GetConvDicImport().GetDic();
240 pDic
->AddEntry( rEntryContext
.GetLeftText(), aRightText
);
244 bool ConvDicXMLExport::Export()
246 uno::Reference
< document::XExporter
> xExporter( this );
247 uno::Reference
< document::XFilter
> xFilter( xExporter
, UNO_QUERY
);
248 xFilter
->filter( {} ); // calls exportDoc implicitly
254 ErrCode
ConvDicXMLExport::exportDoc( enum ::xmloff::token::XMLTokenEnum
/*eClass*/ )
256 GetNamespaceMap_().Add( u
"tcd"_ustr
,
257 XML_NAMESPACE_TCD_STRING
, XML_NAMESPACE_TCD
);
259 GetDocHandler()->startDocument();
261 // Add xmlns line and some other arguments
262 AddAttribute( GetNamespaceMap_().GetAttrNameByKey( XML_NAMESPACE_TCD
),
263 GetNamespaceMap_().GetNameByKey( XML_NAMESPACE_TCD
) );
264 AddAttribute( XML_NAMESPACE_TCD
, u
"package"_ustr
, u
"org.openoffice.Office"_ustr
);
266 OUString
aIsoLang( LanguageTag::convertToBcp47( rDic
.nLanguage
) );
267 AddAttribute( XML_NAMESPACE_TCD
, u
"lang"_ustr
, aIsoLang
);
268 OUString
aConvType( ConversionTypeToText( rDic
.nConversionType
) );
269 AddAttribute( XML_NAMESPACE_TCD
, u
"conversion-type"_ustr
, aConvType
);
271 //!! block necessary in order to have SvXMLElementExport d-tor called
272 //!! before the call to endDocument
274 SvXMLElementExport
aRoot( *this, XML_NAMESPACE_TCD
, u
"text-conversion-dictionary"_ustr
, true, true );
278 GetDocHandler()->endDocument();
285 void ConvDicXMLExport::ExportContent_()
287 // acquire sorted list of all keys
288 std::set
<OUString
> aKeySet
;
289 for (auto const& elem
: rDic
.aFromLeft
)
290 aKeySet
.insert( elem
.first
);
292 for (const OUString
& aLeftText
: aKeySet
)
294 AddAttribute( XML_NAMESPACE_TCD
, u
"left-text"_ustr
, aLeftText
);
295 if (rDic
.pConvPropType
) // property-type list available?
297 sal_Int16 nPropertyType
= -1;
298 PropTypeMap::iterator aIt2
= rDic
.pConvPropType
->find( aLeftText
);
299 if (aIt2
!= rDic
.pConvPropType
->end())
300 nPropertyType
= (*aIt2
).second
;
301 DBG_ASSERT( nPropertyType
, "property-type not found" );
302 if (nPropertyType
== -1)
303 nPropertyType
= ConversionPropertyType::NOT_DEFINED
;
304 AddAttribute( XML_NAMESPACE_TCD
, u
"property-type"_ustr
, OUString::number( nPropertyType
) );
306 SvXMLElementExport
aEntryMain( *this, XML_NAMESPACE_TCD
,
307 u
"entry"_ustr
, true, true );
309 std::pair
< ConvMap::iterator
, ConvMap::iterator
> aRange
=
310 rDic
.aFromLeft
.equal_range(aLeftText
);
311 for (auto aIt
= aRange
.first
; aIt
!= aRange
.second
; ++aIt
)
313 DBG_ASSERT( aLeftText
== (*aIt
).first
, "key <-> entry mismatch" );
314 OUString
aRightText( (*aIt
).second
);
315 SvXMLElementExport
aEntryRightText( *this, XML_NAMESPACE_TCD
,
316 u
"right-text"_ustr
, true, false );
317 Characters( aRightText
);
322 //!! see comment for pDic member
323 ConvDicXMLImport::ConvDicXMLImport( ConvDic
*pConvDic
) :
324 SvXMLImport ( comphelper::getProcessComponentContext(), u
"com.sun.star.lingu2.ConvDicXMLImport"_ustr
, SvXMLImportFlags::ALL
),
325 pDic ( pConvDic
), nLanguage(LANGUAGE_NONE
), nConversionType(-1)
327 GetNamespaceMap().Add( GetXMLToken(XML_NP_TCD
), GetXMLToken(XML_N_TCD
), XML_NAMESPACE_TCD
);
330 SvXMLImportContext
* ConvDicXMLImport::CreateFastContext(
332 const css::uno::Reference
< css::xml::sax::XFastAttributeList
> & /*xAttrList*/ )
334 if( Element
== ConvDicXMLToken::TEXT_CONVERSION_DICTIONARY
)
335 return new ConvDicXMLDictionaryContext_Impl( *this );
339 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */