tdf#42893: sw_autocorrect: Add unittest
[LibreOffice.git] / linguistic / source / convdicxml.cxx
blob5fca39078e8f8aa5fb7c47ae62a2096822160f56
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 )
49 OUString aRes;
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;
54 return aRes;
57 static sal_Int16 GetConversionTypeFromText( std::u16string_view rText )
59 sal_Int16 nRes = -1;
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;
64 return nRes;
67 namespace {
69 class ConvDicXMLImportContext :
70 public SvXMLImportContext
72 public:
73 ConvDicXMLImportContext( ConvDicXMLImport &rImport ) :
74 SvXMLImportContext( rImport )
78 ConvDicXMLImport & GetConvDicImport()
80 return static_cast<ConvDicXMLImport &>(GetImport());
83 // SvXMLImportContext
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;
95 public:
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
112 OUString aLeftText;
114 public:
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
132 OUString aRightText;
133 ConvDicXMLEntryTextContext_Impl &rEntryContext;
135 public:
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(
164 sal_Int32 Element,
165 const css::uno::Reference< css::xml::sax::XFastAttributeList > & /*xAttrList*/ )
167 if ( Element == ConvDicXMLToken::TEXT_CONVERSION_DICTIONARY )
168 return new ConvDicXMLDictionaryContext_Impl( GetConvDicImport() );
169 return nullptr;
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() );
182 break;
183 case XML_NAMESPACE_TCD | XML_CONVERSION_TYPE:
184 nConversionType = GetConversionTypeFromText( aIter.toString() );
185 break;
186 default:
190 GetConvDicImport().SetLanguage( nLanguage );
191 GetConvDicImport().SetConversionType( nConversionType );
195 css::uno::Reference<XFastContextHandler> ConvDicXMLDictionaryContext_Impl::createFastChildContext(
196 sal_Int32 Element,
197 const css::uno::Reference< css::xml::sax::XFastAttributeList > & /*xAttrList*/ )
199 if ( Element == ConvDicXMLToken::ENTRY )
200 return new ConvDicXMLEntryTextContext_Impl( GetConvDicImport() );
201 return nullptr;
204 css::uno::Reference<XFastContextHandler> ConvDicXMLEntryTextContext_Impl::createFastChildContext(
205 sal_Int32 Element,
206 const css::uno::Reference< css::xml::sax::XFastAttributeList > & /*xAttrList*/ )
208 if ( Element == ConvDicXMLToken::RIGHT_TEXT )
209 return new ConvDicXMLRightTextContext_Impl( GetConvDicImport(), *this );
210 return nullptr;
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();
223 break;
224 default:
231 void ConvDicXMLRightTextContext_Impl::characters( const OUString &rChars )
233 aRightText += rChars;
236 void ConvDicXMLRightTextContext_Impl::endFastElement( sal_Int32 /*nElement*/ )
238 ConvDic *pDic = GetConvDicImport().GetDic();
239 if (pDic)
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
250 return bSuccess;
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 );
275 ExportContent_();
278 GetDocHandler()->endDocument();
280 bSuccess = true;
281 return ERRCODE_NONE;
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(
331 sal_Int32 Element,
332 const css::uno::Reference< css::xml::sax::XFastAttributeList > & /*xAttrList*/ )
334 if( Element == ConvDicXMLToken::TEXT_CONVERSION_DICTIONARY )
335 return new ConvDicXMLDictionaryContext_Impl( *this );
336 return nullptr;
339 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */