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