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 // uno
25 import com.sun.star.lib.uno.helper.ComponentBase;
26 import com.sun.star.uno.UnoRuntime;
27 
28 // factories
29 import com.sun.star.lang.XMultiServiceFactory;
30 import com.sun.star.lang.XSingleServiceFactory;
31 
32 // supported Interfaces
33 import com.sun.star.linguistic2.XHyphenator;
34 import com.sun.star.linguistic2.XLinguServiceEventBroadcaster;
35 import com.sun.star.lang.XInitialization;
36 import com.sun.star.lang.XComponent;
37 import com.sun.star.lang.XServiceInfo;
38 import com.sun.star.lang.XServiceDisplayName;
39 
40 // Exceptions
41 import com.sun.star.uno.Exception;
42 import com.sun.star.uno.RuntimeException;
43 import com.sun.star.lang.IllegalArgumentException;
44 
45 //used Interfaces
46 import com.sun.star.linguistic2.XLinguServiceEventListener;
47 import com.sun.star.linguistic2.XHyphenatedWord;
48 import com.sun.star.linguistic2.XPossibleHyphens;
49 import com.sun.star.lang.Locale;
50 import com.sun.star.lang.XEventListener;
51 import com.sun.star.lang.EventObject;
52 import com.sun.star.beans.XPropertySet;
53 import com.sun.star.beans.PropertyValue;
54 import com.sun.star.uno.AnyConverter;
55 import com.sun.star.lang.XTypeProvider;
56 import com.sun.star.uno.XInterface;
57 import com.sun.star.uno.Type;
58 
59 import java.util.ArrayList;
60 
61 public class SampleHyphenator extends ComponentBase implements
62         XHyphenator,
63         XLinguServiceEventBroadcaster,
64         XInitialization,
65         XServiceDisplayName,
66         XServiceInfo
67 {
68     PropChgHelper_Hyph          aPropChgHelper;
69     ArrayList                   aEvtListeners;
70     boolean                     bDisposing;
71 
72     public SampleHyphenator()
73     {
74         // names of relevant properties to be used
75         String[] aProps = new String[]
76             {
77                 "IsIgnoreControlCharacters",
78                 "IsUseDictionaryList",
79                 "IsGermanPreReform",
80                 "HyphMinLeading",
81                 "HyphMinTrailing",
82                 "HyphMinWordLength"
83             };
84         aPropChgHelper  = new PropChgHelper_Hyph( (XHyphenator) this, aProps );
85         aEvtListeners   = new ArrayList();;
86         bDisposing      = false;
87     }
88 
89     private boolean IsEqual( Locale aLoc1, Locale aLoc2 )
90     {
91         return aLoc1.Language.equals( aLoc2.Language ) &&
92                aLoc1.Country .equals( aLoc2.Country )  &&
93                aLoc1.Variant .equals( aLoc2.Variant );
94     }
95 
96     private boolean GetValueToUse(
97             String          aPropName,
98             boolean         bDefaultVal,
99             PropertyValue[] aProps )
100     {
101         boolean bRes = bDefaultVal;
102 
103         try
104         {
105             // use temporary value if supplied
106             for (int i = 0;  i < aProps.length;  ++i)
107             {
108                 if (aPropName.equals( aProps[i].Name ))
109                 {
110                     Object aObj = aProps[i].Value;
111                     if (AnyConverter.isBoolean( aObj ))
112                     {
113                         bRes = AnyConverter.toBoolean( aObj );
114                         return bRes;
115                     }
116                 }
117             }
118 
119             // otherwise use value from property set (if available)
120             XPropertySet xPropSet = aPropChgHelper.GetPropSet();
121             if (xPropSet != null)   // should always be the case
122             {
123                 Object aObj = xPropSet.getPropertyValue( aPropName );
124                 if (AnyConverter.isBoolean( aObj ))
125                     bRes = AnyConverter.toBoolean( aObj );
126             }
127         }
128         catch (Exception e) {
129             bRes = bDefaultVal;
130         }
131 
132         return bRes;
133     }
134 
135     private short GetValueToUse(
136             String          aPropName,
137             short           nDefaultVal,
138             PropertyValue[] aProps )
139     {
140         short nRes = nDefaultVal;
141 
142         try
143         {
144             // use temporary value if supplied
145             for (int i = 0;  i < aProps.length;  ++i)
146             {
147                 if (aPropName.equals( aProps[i].Name ))
148                 {
149                     Object aObj = aProps[i].Value;
150                     if (AnyConverter.isShort( aObj ))
151                     {
152                         nRes = AnyConverter.toShort( aObj );
153                         return nRes;
154                     }
155                 }
156             }
157 
158             // otherwise use value from property set (if available)
159             XPropertySet xPropSet = aPropChgHelper.GetPropSet();
160             if (xPropSet != null)   // should always be the case
161             {
162                     Object aObj = xPropSet.getPropertyValue( aPropName );
163                     if (AnyConverter.isShort( aObj ))
164                         nRes = AnyConverter.toShort( aObj );
165             }
166         }
167         catch (Exception e) {
168             nRes = nDefaultVal;
169         }
170 
171         return nRes;
172     }
173 
174     // __________ interface methods __________
175 
176 
177     //*****************
178     //XSupportedLocales
179     //*****************
180     public Locale[] getLocales()
181         throws com.sun.star.uno.RuntimeException
182     {
183         Locale aLocales[] =
184         {
185             new Locale( "de", "DE", "" ),
186             new Locale( "en", "US", "" )
187         };
188 
189         return aLocales;
190     }
191 
192     public boolean hasLocale( Locale aLocale )
193         throws com.sun.star.uno.RuntimeException
194     {
195         boolean bRes = false;
196         if ( IsEqual( aLocale, new Locale( "de", "DE", "" ) )  ||
197              IsEqual( aLocale, new Locale( "en", "US", "" ) ))
198             bRes = true;
199         return bRes;
200     }
201 
202     //***********
203     //XHyphenator
204     //***********
205     public XHyphenatedWord hyphenate(
206             String aWord, Locale aLocale,
207             short nMaxLeading, PropertyValue[] aProperties )
208         throws com.sun.star.uno.RuntimeException,
209                IllegalArgumentException
210     {
211         if (IsEqual( aLocale, new Locale() ) || aWord.length() == 0)
212             return null;
213 
214         // linguistic is currently not allowed to throw exceptions
215         // thus we return null fwhich means 'word cannot be hyphenated'
216         if (!hasLocale( aLocale ))
217             return null;
218 
219         // get values of relevant properties that may be used.
220         //! The values for 'IsIgnoreControlCharacters' and 'IsUseDictionaryList'
221         //! are handled by the dispatcher! Thus there is no need to access
222         //! them here.
223         boolean bIsIgnoreControlCharacters  = GetValueToUse( "IsIgnoreControlCharacters", true, aProperties );
224         boolean bIsUseDictionaryList        = GetValueToUse( "IsUseDictionaryList", true, aProperties );
225         boolean bIsGermanPreReform          = GetValueToUse( "IsGermanPreReform", false, aProperties );
226         short   nHyphMinLeading             = GetValueToUse( "HyphMinLeading", (short)2, aProperties );
227         short   nHyphMinTrailing            = GetValueToUse( "HyphMinTrailing", (short)2, aProperties );
228         short   nHyphMinWordLen             = GetValueToUse( "HyphMinWordLength", (short)5, aProperties );
229 
230         XHyphenatedWord xRes = null;
231 
232         if (aWord.length() >= nHyphMinWordLen)
233         {
234             String  aHyphenatedWord = aWord;
235             short   nHyphenationPos = -1;
236             short   nHyphenPos = -1;
237 
238             //!! This code needs to be replaced by code calling the actual
239             //!! implementation of your hyphenator
240             if (IsEqual( aLocale, new Locale( "de", "DE", "" ) ) )
241             {
242                 if (bIsGermanPreReform && aWord.equals( "Schiffahrt" ))
243                 {
244                     // Note: there is only one position where the word
245                     // can be hyphenated...
246 
247                     aHyphenatedWord = "Schifffahrt";
248                     nHyphenationPos = 4;
249                     nHyphenPos = 5;
250                 }
251                 else if (!bIsGermanPreReform && aWord.equals( "Schifffahrt" ))
252                 {
253                     nHyphenationPos = nHyphenPos = 5;
254                 }
255             }
256             else if (IsEqual( aLocale, new Locale( "en", "US", "" ) ) )
257             {
258                 int nLast = aWord.length() - 1 - nHyphMinTrailing;
259 
260                 if ( aWord.equals( "waterfall" ) )
261                 {
262                     if (4 <= nLast)
263                         nHyphenationPos = nHyphenPos = 4;
264                     else
265                         nHyphenationPos = nHyphenPos = 1;
266                 }
267                 else if ( aWord.equals( "driving" ) )
268                 {
269                     nHyphenationPos = nHyphenPos = 3;
270                 }
271             }
272 
273             // check if hyphenation pos is valid,
274             // a value of -1 indicates that hyphenation is not possible
275             if (  nHyphenationPos != -1 &&
276                 !(nHyphenationPos <  nHyphMinLeading) &&
277                 !(nHyphenationPos >= aWord.length() - nHyphMinTrailing))
278             {
279                 xRes = new XHyphenatedWord_impl(aWord, aLocale,
280                                 nHyphenationPos, aHyphenatedWord, nHyphenPos);
281             }
282         }
283         return xRes;
284     }
285 
286     public XHyphenatedWord queryAlternativeSpelling(
287             String aWord, Locale aLocale,
288             short nIndex, PropertyValue[] aProperties )
289         throws com.sun.star.uno.RuntimeException,
290                IllegalArgumentException
291     {
292         if (IsEqual( aLocale, new Locale() ) || aWord.length() == 0)
293             return null;
294 
295         // linguistic is currently not allowed to throw exceptions
296         // thus we return null which means 'word cannot be hyphenated'
297         if (!hasLocale( aLocale ))
298             return null;
299 
300         // get values of relevant properties that may be used.
301         //! The values for 'IsIgnoreControlCharacters' and 'IsUseDictionaryList'
302         //! are handled by the dispatcher! Thus there is no need to access
303         //! them here.
304         boolean bIsIgnoreControlCharacters  = GetValueToUse( "IsIgnoreControlCharacters", true, aProperties );
305         boolean bIsUseDictionaryList        = GetValueToUse( "IsUseDictionaryList", true, aProperties );
306         boolean bIsGermanPreReform          = GetValueToUse( "IsGermanPreReform", false, aProperties );
307         short   nHyphMinLeading             = GetValueToUse( "HyphMinLeading", (short)2, aProperties );
308         short   nHyphMinTrailing            = GetValueToUse( "HyphMinTrailing", (short)2, aProperties );
309         short   nHyphMinWordLen             = GetValueToUse( "HyphMinWordLength", (short)5, aProperties );
310 
311         XHyphenatedWord xRes = null;
312 
313         //!! This code needs to be replaced by code calling the actual
314         //!! implementation of your hyphenator
315         if ( IsEqual( aLocale, new Locale( "de", "DE", "" ) ) )
316         {
317             // there is an alternative spelling only when the
318             // word is hyphenated between the "ff" and old german spelling
319             // is set.
320             if (aWord.equals( "Schiffahrt" ) &&
321                 bIsGermanPreReform && nIndex == 4)
322             {
323                 xRes = new XHyphenatedWord_impl(aWord, aLocale,
324                               (short)4, "Schifffahrt", (short)5 );
325             }
326         }
327         else if ( IsEqual( aLocale, new Locale( "en", "US", "" ) ) )
328         {
329             // There are no alternative spellings in the English language
330         }
331 
332         return xRes;
333     }
334 
335     public XPossibleHyphens createPossibleHyphens(
336             String aWord, Locale aLocale,
337             PropertyValue[] aProperties )
338         throws com.sun.star.uno.RuntimeException,
339                IllegalArgumentException
340     {
341         if (IsEqual( aLocale, new Locale() ) || aWord.length() == 0)
342             return null;
343 
344         // linguistic is currently not allowed to throw exceptions
345         // thus we return null which means 'word cannot be hyphenated'
346         if (!hasLocale( aLocale ))
347             return null;
348 
349         // get values of relevant properties that may be used.
350         //! The values for 'IsIgnoreControlCharacters' and 'IsUseDictionaryList'
351         //! are handled by the dispatcher! Thus there is no need to access
352         //! them here.
353         boolean bIsIgnoreControlCharacters  = GetValueToUse( "IsIgnoreControlCharacters", true, aProperties );
354         boolean bIsUseDictionaryList        = GetValueToUse( "IsUseDictionaryList", true, aProperties );
355         boolean bIsGermanPreReform          = GetValueToUse( "IsGermanPreReform", false, aProperties );
356         short   nHyphMinLeading             = GetValueToUse( "HyphMinLeading", (short)2, aProperties );
357         short   nHyphMinTrailing            = GetValueToUse( "HyphMinTrailing", (short)2, aProperties );
358         short   nHyphMinWordLen             = GetValueToUse( "HyphMinWordLength", (short)5, aProperties );
359 
360         XPossibleHyphens xRes = null;
361 
362         //!! This code needs to be replaced by code calling the actual
363         //!! implementation of your hyphenator
364         if ( IsEqual( aLocale, new Locale( "de", "DE", "" ) ) )
365         {
366             if (bIsGermanPreReform && aWord.equals( "Schiffahrt" ))
367             {
368                 short aPos[] = new short[] { (short) 4 };
369                 xRes = new XPossibleHyphens_impl(aWord, aLocale,
370                             "Schiff=fahrt", aPos);
371             }
372             else if (!bIsGermanPreReform && aWord.equals( "Schifffahrt" ))
373             {
374                 short aPos[] = new short[] { (short) 5 };
375                 xRes = new XPossibleHyphens_impl(aWord, aLocale,
376                             "Schiff=fahrt", aPos);
377             }
378         }
379         else if ( IsEqual( aLocale, new Locale( "en", "US", "" ) ) )
380         {
381             if ( aWord.equals( "waterfall" ) )
382             {
383                 short aPos[] = new short[]
384                         { (short) 1, (short) 4 };
385                 xRes = new XPossibleHyphens_impl(aWord, aLocale,
386                             "wa=ter=fall", aPos);
387             }
388             else if ( aWord.equals( "driving" ) )
389             {
390                 short aPos[] = new short[]
391                         { (short) 3 };
392                 xRes = new XPossibleHyphens_impl(aWord, aLocale,
393                             "driv=ing", aPos);
394             }
395         }
396 
397         return xRes;
398     }
399 
400     //*****************************
401     //XLinguServiceEventBroadcaster
402     //*****************************
403     public boolean addLinguServiceEventListener (
404             XLinguServiceEventListener xLstnr )
405         throws com.sun.star.uno.RuntimeException
406     {
407         boolean bRes = false;
408         if (!bDisposing && xLstnr != null)
409             bRes = aPropChgHelper.addLinguServiceEventListener( xLstnr );
410         return bRes;
411     }
412 
413     public boolean removeLinguServiceEventListener(
414             XLinguServiceEventListener xLstnr )
415         throws com.sun.star.uno.RuntimeException
416     {
417         boolean bRes = false;
418         if (!bDisposing && xLstnr != null)
419             bRes = aPropChgHelper.removeLinguServiceEventListener( xLstnr );
420         return bRes;
421     }
422 
423     //********************
424     // XServiceDisplayName
425     //********************
426     public String getServiceDisplayName( Locale aLocale )
427         throws com.sun.star.uno.RuntimeException
428     {
429         return "Java Samples";
430     }
431 
432     //****************
433     // XInitialization
434     //****************
435     public void initialize( Object[] aArguments )
436         throws com.sun.star.uno.Exception,
437                com.sun.star.uno.RuntimeException
438     {
439         int nLen = aArguments.length;
440         if (2 == nLen)
441         {
442             XPropertySet xPropSet = (XPropertySet)UnoRuntime.queryInterface(
443                                          XPropertySet.class, aArguments[0]);
444             // start listening to property changes
445             aPropChgHelper.AddAsListenerTo( xPropSet );
446         }
447     }
448 
449 
450     //*************
451     // XServiceInfo
452     //*************
453     public boolean supportsService( String aServiceName )
454         throws com.sun.star.uno.RuntimeException
455     {
456         String[] aServices = getSupportedServiceNames_Static();
457         int i, nLength = aServices.length;
458         boolean bResult = false;
459 
460         for( i = 0; !bResult && i < nLength; ++i )
461             bResult = aServiceName.equals( aServices[ i ] );
462 
463         return bResult;
464     }
465 
466     public String getImplementationName()
467         throws com.sun.star.uno.RuntimeException
468     {
469         return _aSvcImplName;
470     }
471 
472     public String[] getSupportedServiceNames()
473         throws com.sun.star.uno.RuntimeException
474     {
475         return getSupportedServiceNames_Static();
476     }
477 
478     // __________ static things __________
479 
480     public static String _aSvcImplName = SampleHyphenator.class.getName();
481 
482     public static String[] getSupportedServiceNames_Static()
483     {
484         String[] aResult = { "com.sun.star.linguistic2.Hyphenator" };
485         return aResult;
486     }
487 
488 
489     /**
490      * Returns a factory for creating the service.
491      * This method is called by the <code>JavaLoader</code>
492      * <p>
493      * @return  returns a <code>XSingleServiceFactory</code> for creating the component
494      * @param   implName     the name of the implementation for which a service is desired
495      * @param   multiFactory the service manager to be used if needed
496      * @param   regKey       the registryKey
497      * @see                  com.sun.star.comp.loader.JavaLoader
498      */
499     public static XSingleServiceFactory __getServiceFactory(
500         String aImplName,
501         XMultiServiceFactory xMultiFactory,
502         com.sun.star.registry.XRegistryKey xRegKey )
503     {
504         XSingleServiceFactory xSingleServiceFactory = null;
505         if( aImplName.equals( _aSvcImplName ) )
506         {
507             xSingleServiceFactory = new OneInstanceFactory(
508                     SampleHyphenator.class, _aSvcImplName,
509                     getSupportedServiceNames_Static(),
510                     xMultiFactory );
511         }
512         return xSingleServiceFactory;
513     }
514 
515     /**
516      * Writes the service information into the given registry key.
517      * This method is called by the <code>JavaLoader</code>
518      * <p>
519      * @return  returns true if the operation succeeded
520      * @param   xRegKey       the registryKey
521      * @see                  com.sun.star.comp.loader.JavaLoader
522      */
523     // This method not longer necessary since OOo 3.4 where the component registration
524     // was changed to passive component registration. For more details see
525     // http://wiki.services.openoffice.org/wiki/Passive_Component_Registration
526 
527 //     public static boolean __writeRegistryServiceInfo(
528 //             com.sun.star.registry.XRegistryKey xRegKey )
529 //     {
530 //         boolean bResult = true;
531 //         String[] aServices = getSupportedServiceNames_Static();
532 //         int i, nLength = aServices.length;
533 //         for( i = 0; i < nLength; ++i )
534 //         {
535 //             bResult = bResult && com.sun.star.comp.loader.FactoryHelper.writeRegistryServiceInfo(
536 //                 _aSvcImplName, aServices[i], xRegKey );
537 //         }
538 //         return bResult;
539 //     }
540 }
541 
542