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_linguistic.hxx"
26 #include <tools/urlobj.hxx>
27 #include <tools/debug.hxx>
28 #include <tools/fsys.hxx>
29 #include <tools/string.hxx>
30 #include <i18npool/mslangid.hxx>
31 #include <tools/stream.hxx>
32 #include <osl/mutex.hxx>
33 #include <unotools/processfactory.hxx>
34 #include <ucbhelper/content.hxx>
35
36 #include <cppuhelper/factory.hxx> // helper for factories
37 #include <com/sun/star/linguistic2/XConversionDictionary.hpp>
38 #include <com/sun/star/linguistic2/ConversionDictionaryType.hpp>
39 #include <com/sun/star/linguistic2/ConversionPropertyType.hpp>
40 #include <com/sun/star/util/XFlushable.hpp>
41 #include <com/sun/star/lang/Locale.hpp>
42 #include <com/sun/star/lang/EventObject.hpp>
43 #ifndef _COM_SUN_STAR_UNO_REFERENCE_HPP_
44 #include <com/sun/star/uno/Reference.h>
45 #endif
46 #include <com/sun/star/registry/XRegistryKey.hpp>
47 #include <com/sun/star/util/XFlushListener.hpp>
48 #include <com/sun/star/io/XActiveDataSource.hpp>
49 #include <com/sun/star/document/XFilter.hpp>
50 #include <com/sun/star/beans/PropertyValue.hpp>
51 #include <xmloff/nmspmap.hxx>
52 #include <xmloff/xmlnmspe.hxx>
53 #include <unotools/streamwrap.hxx>
54
55 #include "convdic.hxx"
56 #include "convdicxml.hxx"
57 #include "linguistic/misc.hxx"
58 #include "defs.hxx"
59
60 using namespace std;
61 using namespace utl;
62 using namespace osl;
63 using namespace rtl;
64 using namespace com::sun::star;
65 using namespace com::sun::star::lang;
66 using namespace com::sun::star::uno;
67 using namespace com::sun::star::linguistic2;
68 using namespace linguistic;
69
70 #define XML_NAMESPACE_TCD_STRING "http://openoffice.org/2003/text-conversion-dictionary"
71 #define CONV_TYPE_HANGUL_HANJA "Hangul / Hanja"
72 #define CONV_TYPE_SCHINESE_TCHINESE "Chinese simplified / Chinese traditional"
73
74 ///////////////////////////////////////////////////////////////////////////
75
ConversionTypeToText(sal_Int16 nConversionType)76 static const OUString ConversionTypeToText( sal_Int16 nConversionType )
77 {
78 OUString aRes;
79 if (nConversionType == ConversionDictionaryType::HANGUL_HANJA)
80 aRes = A2OU( CONV_TYPE_HANGUL_HANJA );
81 else if (nConversionType == ConversionDictionaryType::SCHINESE_TCHINESE)
82 aRes = A2OU( CONV_TYPE_SCHINESE_TCHINESE );
83 return aRes;
84 }
85
GetConversionTypeFromText(const String & rText)86 static sal_Int16 GetConversionTypeFromText( const String &rText )
87 {
88 sal_Int16 nRes = -1;
89 if (rText.EqualsAscii( CONV_TYPE_HANGUL_HANJA ))
90 nRes = ConversionDictionaryType::HANGUL_HANJA;
91 else if (rText.EqualsAscii( CONV_TYPE_SCHINESE_TCHINESE ))
92 nRes = ConversionDictionaryType::SCHINESE_TCHINESE;
93 return nRes;
94 }
95
96 ///////////////////////////////////////////////////////////////////////////
97
98 class ConvDicXMLImportContext :
99 public SvXMLImportContext
100 {
101 public:
ConvDicXMLImportContext(ConvDicXMLImport & rImport,sal_uInt16 nPrfx,const OUString & rLName)102 ConvDicXMLImportContext(
103 ConvDicXMLImport &rImport,
104 sal_uInt16 nPrfx, const OUString& rLName ) :
105 SvXMLImportContext( rImport, nPrfx, rLName )
106 {
107 }
108
GetConvDicImport() const109 const ConvDicXMLImport & GetConvDicImport() const
110 {
111 return (const ConvDicXMLImport &) GetImport();
112 }
113
GetConvDicImport()114 ConvDicXMLImport & GetConvDicImport()
115 {
116 return (ConvDicXMLImport &) GetImport();
117 }
118
119 // SvXMLImportContext
120 virtual void Characters( const OUString &rChars );
121 virtual SvXMLImportContext * CreateChildContext( sal_uInt16 nPrefix, const OUString& rLocalName, const uno::Reference< xml::sax::XAttributeList > &rxAttrList);
122 };
123
124
125 class ConvDicXMLDictionaryContext_Impl :
126 public ConvDicXMLImportContext
127 {
128 sal_Int16 nLanguage;
129 sal_Int16 nConversionType;
130
131 public:
ConvDicXMLDictionaryContext_Impl(ConvDicXMLImport & rImport,sal_uInt16 nPrefix,const OUString & rLName)132 ConvDicXMLDictionaryContext_Impl( ConvDicXMLImport &rImport,
133 sal_uInt16 nPrefix, const OUString& rLName) :
134 ConvDicXMLImportContext( rImport, nPrefix, rLName )
135 {
136 nLanguage = LANGUAGE_NONE;
137 nConversionType = -1;
138 }
139
140 // SvXMLImportContext
141 virtual void StartElement( const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& xAttrList );
142 virtual SvXMLImportContext * CreateChildContext( sal_uInt16 nPrefix, const OUString& rLocalName, const uno::Reference< xml::sax::XAttributeList > &rxAttrList );
143
GetLanguage() const144 sal_Int16 GetLanguage() const { return nLanguage; }
GetConversionType() const145 sal_Int16 GetConversionType() const { return nConversionType; }
146 };
147
148
149 class ConvDicXMLEntryTextContext_Impl :
150 public ConvDicXMLImportContext
151 {
152 OUString aLeftText;
153 sal_Int16 nPropertyType; // used for Chinese simplified/traditional conversion
154 ConvDicXMLDictionaryContext_Impl &rDicContext;
155
156 public:
ConvDicXMLEntryTextContext_Impl(ConvDicXMLImport & rImport,sal_uInt16 nPrefix,const OUString & rLName,ConvDicXMLDictionaryContext_Impl & rParentContext)157 ConvDicXMLEntryTextContext_Impl(
158 ConvDicXMLImport &rImport,
159 sal_uInt16 nPrefix, const OUString& rLName,
160 ConvDicXMLDictionaryContext_Impl &rParentContext ) :
161 ConvDicXMLImportContext( rImport, nPrefix, rLName ),
162 nPropertyType( ConversionPropertyType::NOT_DEFINED ),
163 rDicContext( rParentContext )
164 {
165 }
166
167 // SvXMLImportContext
168 virtual void StartElement( const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& xAttrList );
169 virtual SvXMLImportContext * CreateChildContext( sal_uInt16 nPrefix, const OUString& rLocalName, const uno::Reference< xml::sax::XAttributeList > &rxAttrList );
170
GetLeftText() const171 const OUString & GetLeftText() const { return aLeftText; }
GetPropertyType() const172 sal_Int16 GetPropertyType() const { return nPropertyType; }
SetPropertyType(sal_Int16 nVal)173 void SetPropertyType( sal_Int16 nVal ) { nPropertyType = nVal; }
174 };
175
176
177 class ConvDicXMLRightTextContext_Impl :
178 public ConvDicXMLImportContext
179 {
180 OUString aRightText;
181 ConvDicXMLEntryTextContext_Impl &rEntryContext;
182
183 public:
ConvDicXMLRightTextContext_Impl(ConvDicXMLImport & rImport,sal_uInt16 nPrefix,const OUString & rLName,ConvDicXMLEntryTextContext_Impl & rParentContext)184 ConvDicXMLRightTextContext_Impl(
185 ConvDicXMLImport &rImport,
186 sal_uInt16 nPrefix, const OUString& rLName,
187 ConvDicXMLEntryTextContext_Impl &rParentContext ) :
188 ConvDicXMLImportContext( rImport, nPrefix, rLName ),
189 rEntryContext( rParentContext )
190 {
191 }
192
193 // SvXMLImportContext
194 virtual void EndElement();
195 virtual SvXMLImportContext * CreateChildContext( sal_uInt16 nPrefix, const OUString& rLocalName, const uno::Reference< xml::sax::XAttributeList > &rxAttrList );
196 virtual void Characters( const OUString &rChars );
197
GetRightText() const198 const OUString & GetRightText() const { return aRightText; }
GetLeftText() const199 const OUString & GetLeftText() const { return rEntryContext.GetLeftText(); }
GetDic()200 ConvDic * GetDic() { return GetConvDicImport().GetDic(); }
201 };
202
203 ///////////////////////////////////////////////////////////////////////////
204
Characters(const OUString &)205 void ConvDicXMLImportContext::Characters(const OUString & /*rChars*/)
206 {
207 /*
208 Whitespace occurring within the content of token elements is "trimmed"
209 from the ends (i.e. all whitespace at the beginning and end of the
210 content is removed), and "collapsed" internally (i.e. each sequence of
211 1 or more whitespace characters is replaced with one blank character).
212 */
213 //collapsing not done yet!
214
215 // warning-free code: since the result is not used there is no need for trimming...
216 //const OUString &rChars2 = rChars.trim();
217 }
218
CreateChildContext(sal_uInt16 nPrefix,const OUString & rLocalName,const uno::Reference<xml::sax::XAttributeList> &)219 SvXMLImportContext * ConvDicXMLImportContext::CreateChildContext(
220 sal_uInt16 nPrefix, const OUString& rLocalName,
221 const uno::Reference< xml::sax::XAttributeList > & /*rxAttrList*/ )
222 {
223 SvXMLImportContext *pContext = 0;
224 if (nPrefix == XML_NAMESPACE_TCD && rLocalName.equalsAscii( "text-conversion-dictionary" ))
225 pContext = new ConvDicXMLDictionaryContext_Impl( GetConvDicImport(), nPrefix, rLocalName );
226 else
227 pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
228 return pContext;
229 }
230
231 ////////////////////////////////////////
232
StartElement(const uno::Reference<xml::sax::XAttributeList> & rxAttrList)233 void ConvDicXMLDictionaryContext_Impl::StartElement(
234 const uno::Reference< xml::sax::XAttributeList > &rxAttrList )
235 {
236 sal_Int16 nAttrCount = rxAttrList.is() ? rxAttrList->getLength() : 0;
237 for (sal_Int16 i = 0; i < nAttrCount; ++i)
238 {
239 OUString aAttrName = rxAttrList->getNameByIndex(i);
240 OUString aLocalName;
241 sal_uInt16 nPrefix = GetImport().GetNamespaceMap().
242 GetKeyByAttrName( aAttrName, &aLocalName );
243 OUString aValue = rxAttrList->getValueByIndex(i);
244
245 if (nPrefix == XML_NAMESPACE_TCD && aLocalName.equalsAscii( "lang" ))
246 nLanguage = MsLangId::convertIsoStringToLanguage( aValue );
247 else if (nPrefix == XML_NAMESPACE_TCD && aLocalName.equalsAscii( "conversion-type" ))
248 nConversionType = GetConversionTypeFromText( aValue );
249 }
250 GetConvDicImport().SetLanguage( nLanguage );
251 GetConvDicImport().SetConversionType( nConversionType );
252
253 //!! hack to stop the parser from reading the rest of the file !!
254 //!! when only the header (language, conversion type) is needed !!
255 // if (GetConvDicImport().GetDic() == 0)
256 // throw uno::RuntimeException();
257 }
258
CreateChildContext(sal_uInt16 nPrefix,const OUString & rLocalName,const uno::Reference<xml::sax::XAttributeList> &)259 SvXMLImportContext * ConvDicXMLDictionaryContext_Impl::CreateChildContext(
260 sal_uInt16 nPrefix, const OUString& rLocalName,
261 const uno::Reference< xml::sax::XAttributeList > & /*rxAttrList*/ )
262 {
263 SvXMLImportContext *pContext = 0;
264 if (nPrefix == XML_NAMESPACE_TCD && rLocalName.equalsAscii( "entry" ))
265 pContext = new ConvDicXMLEntryTextContext_Impl( GetConvDicImport(), nPrefix, rLocalName, *this );
266 else
267 pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
268 return pContext;
269 }
270
271 ////////////////////////////////////////
272
CreateChildContext(sal_uInt16 nPrefix,const OUString & rLocalName,const uno::Reference<xml::sax::XAttributeList> &)273 SvXMLImportContext * ConvDicXMLEntryTextContext_Impl::CreateChildContext(
274 sal_uInt16 nPrefix, const OUString& rLocalName,
275 const uno::Reference< xml::sax::XAttributeList > & /*rxAttrList*/ )
276 {
277 SvXMLImportContext *pContext = 0;
278 if (nPrefix == XML_NAMESPACE_TCD && rLocalName.equalsAscii( "right-text" ))
279 pContext = new ConvDicXMLRightTextContext_Impl( GetConvDicImport(), nPrefix, rLocalName, *this );
280 else
281 pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
282 return pContext;
283 }
284
StartElement(const uno::Reference<xml::sax::XAttributeList> & rxAttrList)285 void ConvDicXMLEntryTextContext_Impl::StartElement(
286 const uno::Reference< xml::sax::XAttributeList >& rxAttrList )
287 {
288 sal_Int16 nAttrCount = rxAttrList.is() ? rxAttrList->getLength() : 0;
289 for (sal_Int16 i = 0; i < nAttrCount; ++i)
290 {
291 OUString aAttrName = rxAttrList->getNameByIndex(i);
292 OUString aLocalName;
293 sal_uInt16 nPrefix = GetImport().GetNamespaceMap().
294 GetKeyByAttrName( aAttrName, &aLocalName );
295 OUString aValue = rxAttrList->getValueByIndex(i);
296
297 if (nPrefix == XML_NAMESPACE_TCD && aLocalName.equalsAscii( "left-text" ))
298 aLeftText = aValue;
299 if (nPrefix == XML_NAMESPACE_TCD && aLocalName.equalsAscii( "property-type" ))
300 nPropertyType = (sal_Int16) aValue.toInt32();
301 }
302 }
303
304 ////////////////////////////////////////
305
CreateChildContext(sal_uInt16 nPrefix,const OUString & rLocalName,const uno::Reference<xml::sax::XAttributeList> &)306 SvXMLImportContext * ConvDicXMLRightTextContext_Impl::CreateChildContext(
307 sal_uInt16 nPrefix, const OUString& rLocalName,
308 const uno::Reference< xml::sax::XAttributeList > & /*rxAttrList*/ )
309 {
310 // leaf: return default (empty) context
311 SvXMLImportContext *pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
312 return pContext;
313 }
314
Characters(const OUString & rChars)315 void ConvDicXMLRightTextContext_Impl::Characters( const OUString &rChars )
316 {
317 aRightText += rChars;
318 }
319
EndElement()320 void ConvDicXMLRightTextContext_Impl::EndElement()
321 {
322 ConvDic *pDic = GetDic();
323 if (pDic)
324 pDic->AddEntry( GetLeftText(), GetRightText() );
325 }
326
327
328 ///////////////////////////////////////////////////////////////////////////
329
Export()330 sal_Bool ConvDicXMLExport::Export()
331 {
332 sal_Bool bRet = sal_False;
333
334 uno::Reference< document::XExporter > xExporter( this );
335 uno::Reference< document::XFilter > xFilter( xExporter, UNO_QUERY );
336 uno::Sequence< beans::PropertyValue > aProps(0);
337 xFilter->filter( aProps ); // calls exportDoc implicitly
338
339 return bRet = bSuccess;
340 }
341
342
exportDoc(enum::xmloff::token::XMLTokenEnum)343 sal_uInt32 ConvDicXMLExport::exportDoc( enum ::xmloff::token::XMLTokenEnum /*eClass*/ )
344 {
345 _GetNamespaceMap().Add( A2OU( "tcd" ),
346 A2OU( XML_NAMESPACE_TCD_STRING ), XML_NAMESPACE_TCD );
347
348 GetDocHandler()->startDocument();
349
350 // Add xmlns line and some other arguments
351 AddAttribute( _GetNamespaceMap().GetAttrNameByKey( XML_NAMESPACE_TCD ),
352 _GetNamespaceMap().GetNameByKey( XML_NAMESPACE_TCD ) );
353 AddAttributeASCII( XML_NAMESPACE_TCD, "package", "org.openoffice.Office" );
354
355 OUString aIsoLang( MsLangId::convertLanguageToIsoString( rDic.nLanguage ) );
356 AddAttribute( XML_NAMESPACE_TCD, "lang", aIsoLang );
357 OUString aConvType( ConversionTypeToText( rDic.nConversionType ) );
358 AddAttribute( XML_NAMESPACE_TCD, "conversion-type", aConvType );
359
360 //!! block necessary in order to have SvXMLElementExport d-tor called
361 //!! before the call to endDocument
362 {
363 SvXMLElementExport aRoot( *this, XML_NAMESPACE_TCD, "text-conversion-dictionary", sal_True, sal_True );
364 _ExportContent();
365 }
366
367 GetDocHandler()->endDocument();
368
369 bSuccess = sal_True;
370 return 0;
371 }
372
373
_ExportContent()374 void ConvDicXMLExport::_ExportContent()
375 {
376 // acquire sorted list of all keys
377 ConvMapKeySet aKeySet;
378 ConvMap::iterator aIt;
379 for (aIt = rDic.aFromLeft.begin(); aIt != rDic.aFromLeft.end(); ++aIt)
380 aKeySet.insert( (*aIt).first );
381
382 ConvMapKeySet::iterator aKeyIt;
383 for (aKeyIt = aKeySet.begin(); aKeyIt != aKeySet.end(); ++aKeyIt)
384 {
385 OUString aLeftText( *aKeyIt );
386 AddAttribute( XML_NAMESPACE_TCD, "left-text", aLeftText );
387 if (rDic.pConvPropType.get()) // property-type list available?
388 {
389 sal_Int16 nPropertyType = -1;
390 PropTypeMap::iterator aIt2 = rDic.pConvPropType->find( aLeftText );
391 if (aIt2 != rDic.pConvPropType->end())
392 nPropertyType = (*aIt2).second;
393 DBG_ASSERT( nPropertyType, "property-type not found" );
394 if (nPropertyType == -1)
395 nPropertyType = ConversionPropertyType::NOT_DEFINED;
396 AddAttribute( XML_NAMESPACE_TCD, "property-type", OUString::valueOf( (sal_Int32) nPropertyType ) );
397 }
398 SvXMLElementExport aEntryMain( *this, XML_NAMESPACE_TCD,
399 "entry" , sal_True, sal_True );
400
401 pair< ConvMap::iterator, ConvMap::iterator > aRange =
402 rDic.aFromLeft.equal_range( *aKeyIt );
403 for (aIt = aRange.first; aIt != aRange.second; ++aIt)
404 {
405 DBG_ASSERT( *aKeyIt == (*aIt).first, "key <-> entry mismatch" );
406 OUString aRightText( (*aIt).second );
407 SvXMLElementExport aEntryRightText( *this, XML_NAMESPACE_TCD,
408 "right-text" , sal_True, sal_False );
409 Characters( aRightText );
410 }
411 }
412 }
413
getImplementationName()414 ::rtl::OUString SAL_CALL ConvDicXMLExport::getImplementationName()
415 throw( uno::RuntimeException )
416 {
417 return A2OU( "com.sun.star.lingu2.ConvDicXMLExport" );
418 }
419
420 ///////////////////////////////////////////////////////////////////////////
421
startDocument(void)422 void SAL_CALL ConvDicXMLImport::startDocument(void)
423 throw( xml::sax::SAXException, uno::RuntimeException )
424 {
425 // register namespace at first possible opportunity
426 GetNamespaceMap().Add( A2OU( "tcd" ),
427 A2OU( XML_NAMESPACE_TCD_STRING ), XML_NAMESPACE_TCD );
428 SvXMLImport::startDocument();
429 }
430
endDocument(void)431 void SAL_CALL ConvDicXMLImport::endDocument(void)
432 throw( xml::sax::SAXException, uno::RuntimeException )
433 {
434 SvXMLImport::endDocument();
435 }
436
CreateContext(sal_uInt16 nPrefix,const rtl::OUString & rLocalName,const uno::Reference<xml::sax::XAttributeList> &)437 SvXMLImportContext * ConvDicXMLImport::CreateContext(
438 sal_uInt16 nPrefix,
439 const rtl::OUString &rLocalName,
440 const uno::Reference < xml::sax::XAttributeList > & /*rxAttrList*/ )
441 {
442 SvXMLImportContext *pContext = 0;
443 if (nPrefix == XML_NAMESPACE_TCD && rLocalName.equalsAscii( "text-conversion-dictionary" ))
444 pContext = new ConvDicXMLDictionaryContext_Impl( *this, nPrefix, rLocalName );
445 else
446 pContext = new SvXMLImportContext( *this, nPrefix, rLocalName );
447 return pContext;
448 }
449
450
getImplementationName()451 OUString SAL_CALL ConvDicXMLImport::getImplementationName()
452 throw( uno::RuntimeException )
453 {
454 return A2OU( "com.sun.star.lingu2.ConvDicXMLImport" );
455 }
456
457 ///////////////////////////////////////////////////////////////////////////
458
459