1 /* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
3  *
4  *  The Contents of this file are made available subject to the terms of
5  *  the BSD license.
6  *
7  *  Copyright 2000, 2010 Oracle and/or its affiliates.
8  *  All rights reserved.
9  *
10  *  Redistribution and use in source and binary forms, with or without
11  *  modification, are permitted provided that the following conditions
12  *  are met:
13  *  1. Redistributions of source code must retain the above copyright
14  *     notice, this list of conditions and the following disclaimer.
15  *  2. Redistributions in binary form must reproduce the above copyright
16  *     notice, this list of conditions and the following disclaimer in the
17  *     documentation and/or other materials provided with the distribution.
18  *  3. Neither the name of Sun Microsystems, Inc. nor the names of its
19  *     contributors may be used to endorse or promote products derived
20  *     from this software without specific prior written permission.
21  *
22  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
29  *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30  *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
31  *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
32  *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  *
34  *************************************************************************/
35 
36 // Import everything we use
37 
38 import com.sun.star.beans.XPropertySet;
39 import com.sun.star.beans.XMultiPropertySet;
40 import com.sun.star.beans.XHierarchicalPropertySet;
41 import com.sun.star.beans.XMultiHierarchicalPropertySet;
42 import com.sun.star.beans.XPropertyState;
43 import com.sun.star.beans.XMultiPropertyStates;
44 
45 import com.sun.star.configuration.XTemplateInstance;
46 
47 import com.sun.star.container.XNameAccess;
48 import com.sun.star.container.XNameReplace;
49 import com.sun.star.container.XNameContainer;
50 import com.sun.star.container.XNamed;
51 import com.sun.star.container.XChild;
52 import com.sun.star.container.XHierarchicalNameAccess;
53 import com.sun.star.container.XHierarchicalName;
54 
55 import com.sun.star.lang.XComponent;
56 import com.sun.star.lang.XMultiComponentFactory;
57 import com.sun.star.lang.XSingleServiceFactory;
58 import com.sun.star.lang.XMultiServiceFactory;
59 import com.sun.star.lang.XServiceInfo;
60 import com.sun.star.lang.EventObject;
61 
62 import com.sun.star.uno.UnoRuntime;
63 import com.sun.star.uno.XComponentContext;
64 import com.sun.star.uno.XInterface;
65 import com.sun.star.uno.AnyConverter;
66 
67 import com.sun.star.util.XChangesBatch;
68 import com.sun.star.util.XChangesNotifier;
69 import com.sun.star.util.XChangesListener;
70 import com.sun.star.util.ChangesEvent;
71 // Config examples
72 
73 /* These examples show how to use the following features of the Config API:
74 
75     o Accessing data
76     o Updating data
77     o Updating properties in groups
78     o Adding and removing items in sets
79     o Resetting data to their defaults
80 
81    Each example is in a separate method call.
82 */
83 public class ConfigExamples
84 {
85     // The ComponentContext interface of the remote component context
86     private final XComponentContext mxContext;
87 
88     // The MultiComponentFactory interface of the ServiceManager
89     private final XMultiComponentFactory mxServiceManager;
90 
91     // The MultiServiceFactory interface of the ConfigurationProvider
92     private XMultiServiceFactory mxProvider = null;
93 
main( String args[] )94     public static void main( String args[] )
95     {
96         try {
97             // get the remote office component context
98             com.sun.star.uno.XComponentContext xContext =
99                 com.sun.star.comp.helper.Bootstrap.bootstrap();
100 
101             if( xContext != null )
102                 System.out.println("Connected to a running office ...");
103             else
104                 System.out.println( "ERROR: Cannot connect - no remote component context available." );
105 
106             // Create an instance of the class and call its run method
107             ConfigExamples aExample = new ConfigExamples(xContext);
108             aExample.run( );
109 
110             // if you own the service manager dispose it here
111             // to ensure that the default provider is properly disposed and flushed
112             System.exit(0);
113         }
114         catch( Exception e )
115         {
116             e.printStackTrace();
117             System.exit(-1);
118         }
119     }
120 
121     /** Create a ConfigExamples instance supplying a service factory
122     */
ConfigExamples(XComponentContext xContext)123     public ConfigExamples(XComponentContext xContext)
124     {
125         mxContext = xContext;
126         mxServiceManager = xContext.getServiceManager();
127     }
128 
129     /** Run the examples with a default ConfigurationProvider
130     */
run()131     public void run()
132         throws com.sun.star.uno.Exception
133     {
134         mxProvider = createProvider();
135 
136         runExamples( );
137 
138         // we are using the default ConfigurationProvider, so we must not dispose it
139         mxProvider = null;
140     }
141 
142     /** Run the examples with a given ConfigurationProvider
143     */
runExamples( )144     public void runExamples( )
145     {
146         if (checkProvider(mxProvider))
147         {
148             System.out.println("\nStarting examples.");
149 
150             readDataExample();
151 
152             browseDataExample();
153 
154             updateGroupExample();
155 
156             resetGroupExample();
157 
158             updateSetExample();
159 
160             System.out.println("\nAll Examples completed.");
161         }
162         else
163             System.out.println("ERROR: Cannot run examples without ConfigurationProvider.");
164 
165     }
166 
167     /** Do some simple checks, if there is a valid ConfigurationProvider
168     */
checkProvider(XMultiServiceFactory xProvider)169     public static boolean checkProvider(XMultiServiceFactory xProvider)
170     {
171         // check the provider we have
172         if (xProvider == null)
173         {
174             System.out.println("No provider available. Cannot access configuration data.");
175             return false;
176 
177         }
178 
179         try
180         {
181             // check the provider implementation
182             XServiceInfo xProviderServices =
183                 UnoRuntime.queryInterface( XServiceInfo.class, xProvider );
184 
185             if (xProviderServices == null ||
186                 !xProviderServices.supportsService("com.sun.star.configuration.ConfigurationProvider"))
187             {
188                 System.out.println("WARNING: The provider is not a com.sun.star.configuration.ConfigurationProvider");
189             }
190 
191             if (xProviderServices != null)
192             {
193                 System.out.println("Using provider implementation: " + xProviderServices.getImplementationName());
194             }
195 
196             return true;
197         }
198         catch (com.sun.star.uno.RuntimeException e)
199         {
200             System.err.println("ERROR: Failure while checking the provider services.");
201             e.printStackTrace();
202             return false;
203         }
204     }
205 
206     /** Get the provider we have
207      */
getProvider( )208     public XMultiServiceFactory getProvider( )
209     {
210         return mxProvider;
211     }
212 
213     /** Create a default configuration provider
214      */
createProvider( )215     public XMultiServiceFactory createProvider( )
216         throws com.sun.star.uno.Exception
217     {
218         final String sProviderService = "com.sun.star.configuration.ConfigurationProvider";
219 
220         // create the provider and return it as a XMultiServiceFactory
221         XMultiServiceFactory xProvider = UnoRuntime.queryInterface(XMultiServiceFactory.class,
222             mxServiceManager.createInstanceWithContext(sProviderService,
223                                                        mxContext));
224 
225         return xProvider;
226     }
227 
228     /** Create a specified read-only configuration view
229      */
createConfigurationView( String sPath )230     public Object createConfigurationView( String sPath )
231         throws com.sun.star.uno.Exception
232     {
233         XMultiServiceFactory xProvider = getProvider();
234 
235         // The service name: Need only read access:
236         final String sReadOnlyView = "com.sun.star.configuration.ConfigurationAccess";
237 
238         // creation arguments: nodepath
239         com.sun.star.beans.PropertyValue aPathArgument = new com.sun.star.beans.PropertyValue();
240         aPathArgument.Name = "nodepath";
241         aPathArgument.Value = sPath;
242 
243         Object[] aArguments = new Object[1];
244         aArguments[0] = aPathArgument;
245 
246         // create the view
247         Object xViewRoot = xProvider.createInstanceWithArguments(sReadOnlyView, aArguments);
248 
249         return xViewRoot;
250     }
251 
252     /** Create a specified updatable configuration view
253      */
createUpdatableView( String sPath )254     Object createUpdatableView( String sPath )
255         throws com.sun.star.uno.Exception
256     {
257         XMultiServiceFactory xProvider = getProvider();
258 
259         // The service name: Need update access:
260         final String cUpdatableView = "com.sun.star.configuration.ConfigurationUpdateAccess";
261 
262         // creation arguments: nodepath
263         com.sun.star.beans.PropertyValue aPathArgument = new com.sun.star.beans.PropertyValue();
264         aPathArgument.Name = "nodepath";
265         aPathArgument.Value = sPath;
266 
267         Object[] aArguments = new Object[1];
268         aArguments[0] = aPathArgument;
269 
270         // create the view
271         Object xViewRoot = xProvider.createInstanceWithArguments(cUpdatableView, aArguments);
272 
273         return xViewRoot;
274     }
275 
276     /** This method demonstrates read access to data
277      */
readDataExample()278     protected void readDataExample ()
279     {
280         try
281         {
282             System.out.println("\n--- starting example: read grid option settings --------------------");
283             Object aData = readGridConfiguration( );
284             System.out.println("Read grid options: " + aData);
285 
286         }
287         catch ( Exception e )
288         {
289             e.printStackTrace();
290         }
291     }
292 
293     /** This method demonstrates browsing access to data
294      */
browseDataExample()295     protected void browseDataExample ()
296     {
297         try
298         {
299             System.out.println("\n--- starting example: browse filter configuration ------------------");
300             printRegisteredFilters( );
301         }
302         catch ( Exception e )
303         {
304             e.printStackTrace();
305         }
306     }
307 
308     /** This method demonstrates update access to group data
309      */
updateGroupExample()310     protected void updateGroupExample ()
311     {
312         try
313         {
314             System.out.println("\n--- starting example: update group data --------------");
315             editGridOptions( );
316         }
317         catch ( Exception e )
318         {
319             e.printStackTrace();
320         }
321     }
322 
323     /** This method demonstrates resetting data to its default state
324      */
resetGroupExample()325     protected void resetGroupExample ()
326     {
327         try
328         {
329             System.out.println("\n--- starting example: reset group data -----------------------------");
330             Object aOldData = readGridConfiguration( );
331             resetGridConfiguration( );
332             Object aNewData = readGridConfiguration( );
333             System.out.println("Before reset:   user grid options: " + aOldData);
334             System.out.println("After reset: default grid options: " + aNewData);
335         }
336         catch ( Exception e )
337         {
338             e.printStackTrace();
339         }
340     }
341 
342     /** This method demonstrates update access to set data
343      */
updateSetExample()344     protected void updateSetExample ()
345     {
346         try
347         {
348             System.out.println("\n--- starting example: update set data ---------------");
349             storeSampleDataSource( );
350         }
351         catch ( Exception e )
352         {
353             e.printStackTrace();
354         }
355     }
356 
357 // READ example
358     /// class to hold information about grid settings
359     private static class GridOptions
360     {
361         private boolean visible;
362         private int resolution_x;
363         private int resolution_y;
364         private int subdivision_x;
365         private int subdivision_y;
366 
367         @Override
toString()368         public String toString() {
369             StringBuffer aBuffer = new StringBuffer();
370             aBuffer.append("[ Grid is "); aBuffer.append(visible ? "VISIBLE" : "HIDDEN");
371             aBuffer.append("; resolution  = (" + resolution_x  + "," + resolution_y  + ")");
372             aBuffer.append("; subdivision = (" + subdivision_x + "," + subdivision_y + ")");
373             aBuffer.append(" ]");
374             return aBuffer.toString();
375         }
376     }
377 
378     /// This method reads information about grid settings
readGridConfiguration()379     protected GridOptions readGridConfiguration()
380         throws com.sun.star.uno.Exception
381     {
382         // The path to the root element
383         final String cGridOptionsPath = "/org.openoffice.Office.Calc/Grid";
384 
385         // create the view
386         Object xViewRoot = createConfigurationView(cGridOptionsPath);
387 
388         // the result structure
389         GridOptions options = new GridOptions();
390 
391       // accessing a single nested value
392         XHierarchicalPropertySet xProperties =
393             UnoRuntime.queryInterface(XHierarchicalPropertySet.class, xViewRoot);
394 
395         Object aVisible = xProperties.getHierarchicalPropertyValue("Option/VisibleGrid");
396         options.visible = ((Boolean) aVisible).booleanValue();
397 
398       // accessing a nested object and its subproperties
399         Object xSubdivision = xProperties.getHierarchicalPropertyValue("Subdivision");
400 
401         XMultiPropertySet xSubdivProperties =
402             UnoRuntime.queryInterface(XMultiPropertySet.class, xSubdivision);
403 
404         // variables for multi-element access
405         String[] aElementNames = new String[] { "XAxis", "YAxis" };
406 
407         Object[] aElementValues = xSubdivProperties.getPropertyValues(aElementNames);
408 
409         options.subdivision_x = ((Integer) aElementValues[0]).intValue();
410         options.subdivision_y = ((Integer) aElementValues[1]).intValue();
411 
412       // accessing deeply nested subproperties
413         Object xResolution = xProperties.getHierarchicalPropertyValue("Resolution");
414 
415         XMultiHierarchicalPropertySet xResolutionProperties =
416             UnoRuntime.queryInterface(XMultiHierarchicalPropertySet.class, xResolution);
417 
418         aElementNames[0] = "XAxis/Metric";
419         aElementNames[1] = "YAxis/Metric";
420 
421         aElementValues = xResolutionProperties.getHierarchicalPropertyValues(aElementNames);
422 
423         options.resolution_x = ((Integer) aElementValues[0]).intValue();
424         options.resolution_y = ((Integer) aElementValues[1]).intValue();
425 
426       // all options have been retrieved - clean up and return
427         // we are done with the view - dispose it
428 
429         UnoRuntime.queryInterface(XComponent.class, xViewRoot).dispose();
430 
431         return options;
432     }
433 
434 // BROWSE example
435     /// Interface to process information when browsing the configuration tree
436     public interface IConfigurationProcessor
437     {
438         /// process a value item
processValueElement( String sPath_, Object aValue_ )439        void processValueElement( String sPath_, Object aValue_ );
440         /// process a structural item
processStructuralElement( String sPath_, XInterface xElement_)441        void processStructuralElement( String sPath_, XInterface xElement_);
442     }
443 
444     /// Internal method to recursively browse a structural element in preorder
browseElementRecursively( XInterface xElement, IConfigurationProcessor aProcessor )445     public void browseElementRecursively( XInterface xElement, IConfigurationProcessor aProcessor )
446         throws com.sun.star.uno.Exception
447     {
448         // First process this as an element (preorder traversal)
449         XHierarchicalName xElementPath =
450             UnoRuntime.queryInterface(XHierarchicalName.class, xElement);
451 
452         String sPath = xElementPath.getHierarchicalName();
453 
454         aProcessor.processStructuralElement( sPath, xElement);
455 
456         // now process this as a container
457         XNameAccess xChildAccess =
458             UnoRuntime.queryInterface(XNameAccess.class, xElement);
459 
460         // get a list of child elements
461         String[] aElementNames = xChildAccess.getElementNames();
462 
463         // and process them one by one
464         for(int i=0; i< aElementNames.length; ++i)
465         {
466             Object aChild = xChildAccess.getByName( aElementNames[i] );
467             // is it a structural element (object) ...
468             if ( AnyConverter.isObject(aChild) && !AnyConverter.isArray(aChild) )
469             {
470                 // then get an interface
471                 XInterface xChildElement = UnoRuntime.queryInterface(XInterface.class, aChild);
472 
473                 // and continue processing child elements recursively
474                 browseElementRecursively( xChildElement, aProcessor );
475             }
476             // ... or is it a simple value
477             else
478             {
479                 // Build the path to it from the path of
480                 // the element and the name of the child
481                 String sChildPath;
482                 sChildPath =
483                     xElementPath.composeHierarchicalName(aElementNames[i]);
484 
485                 // and process the value
486                 aProcessor.processValueElement( sChildPath, aChild );
487             }
488         }
489     }
490 
491     /** Method to browse the part rooted at sRootPath
492         of the configuration that the Provider provides.
493 
494         All nodes will be processed by the IConfigurationProcessor passed.
495     */
browseConfiguration( String sRootPath, IConfigurationProcessor aProcessor )496     public void browseConfiguration( String sRootPath, IConfigurationProcessor aProcessor )
497         throws com.sun.star.uno.Exception
498     {
499         // create the root element
500         XInterface xViewRoot = (XInterface)createConfigurationView( sRootPath );
501 
502         // now do the processing
503         browseElementRecursively( xViewRoot, aProcessor );
504 
505         // we are done with the view - dispose it
506         //   This assumes that the processor
507         //   does not keep a reference to the elements in processStructuralElement
508 
509         UnoRuntime.queryInterface(XComponent.class,xViewRoot).dispose();
510         xViewRoot = null;
511     }
512 
513     /** Method to browse the filter configuration.
514 
515         Information about installed filters will be printed.
516     */
printRegisteredFilters()517     public void printRegisteredFilters()
518         throws com.sun.star.uno.Exception
519     {
520         final String sFilterKey = "/org.openoffice.TypeDetection.Filter/Filters";
521 
522        // browse the configuration, dumping filter information
523         browseConfiguration( sFilterKey,
524            new IConfigurationProcessor () {
525                /// prints Path and Value of properties
526                public void processValueElement( String sPath_, Object aValue_ ) {
527                    if (AnyConverter.isArray(aValue_))
528                    {
529                        final Object [] aArray = (Object [])aValue_;
530 
531                        System.out.print("\tValue: " + sPath_ + " = { ");
532                        for (int i=0; i<aArray.length; ++i)
533                        {
534                            if (i != 0) System.out.print(", ");
535                            System.out.print(aArray[i]);
536                        }
537                        System.out.println(" }");
538                    }
539                    else
540                         System.out.println("\tValue: " + sPath_ + " = " + aValue_);
541                }
542 
543                /// prints the Filter entries
544                public void processStructuralElement( String sPath_, XInterface xElement_) {
545                    // get template information, to detect instances of the 'Filter' template
546                    XTemplateInstance xInstance =
547                        UnoRuntime.queryInterface( XTemplateInstance .class,xElement_);
548 
549                    // only select the Filter entries
550                    if (xInstance != null && xInstance.getTemplateName().endsWith("Filter")) {
551                         XNamed xNamed = UnoRuntime.queryInterface(XNamed.class,xElement_);
552                         System.out.println("Filter " + xNamed.getName() + " (" + sPath_ + ")");
553                    }
554                }
555            } );
556     }
557 
558 // GROUP UPDATE example
559 
560     /** This method simulates editing configuration data using a GridEditor dialog class
561     */
editGridOptions( )562     public void editGridOptions( )
563         throws com.sun.star.uno.Exception
564     {
565         // The path to the root element
566         final String cGridOptionsPath = "/org.openoffice.Office.Calc/Grid";
567 
568       // create the view
569         Object xViewRoot = createUpdatableView( cGridOptionsPath );
570 
571         // the 'editor'
572         GridOptionsEditor dialog = new GridOptionsEditor();
573 
574       // set up the initial values and register listeners
575         // get a data access interface, to supply the view with a model
576         XMultiHierarchicalPropertySet xProperties =
577             UnoRuntime.queryInterface(XMultiHierarchicalPropertySet.class, xViewRoot);
578 
579         dialog.setModel( xProperties );
580 
581         // get a listener object (probably an adapter) that notifies
582         // the dialog of external changes to its model
583         XChangesListener xListener = dialog.createChangesListener( );
584 
585         XChangesNotifier xNotifier =
586             UnoRuntime.queryInterface(XChangesNotifier.class, xViewRoot);
587 
588         xNotifier.addChangesListener( xListener );
589 
590         // trigger the listener
591         changeSomeData( cGridOptionsPath + "/Subdivision" );
592 
593         if (dialog.execute() == GridOptionsEditor.SAVE_SETTINGS)
594         {
595             // changes have been applied to the view here
596             XChangesBatch xUpdateControl =
597                 UnoRuntime.queryInterface(XChangesBatch.class,xViewRoot);
598 
599             try
600             {
601                xUpdateControl.commitChanges();
602             }
603             catch (Exception e)
604             {
605                 dialog.informUserOfError( e );
606             }
607         }
608 
609       // all changes have been handled - clean up and return
610         // listener is done now
611         xNotifier.removeChangesListener( xListener );
612 
613         // we are done with the view - dispose it
614         UnoRuntime.queryInterface(XComponent.class, xViewRoot).dispose();
615     }
616 
617     /** A class that changes some grid options settings
618 
619         The interface of this class is chose to resemble a possible UI dialog class
620     */
621     private class GridOptionsEditor {
622         /// the data this editor edits
623         XMultiHierarchicalPropertySet mxModel;
624 
625         public static final int CANCELED = 0;
626         public static final int SAVE_SETTINGS = 1;
627 
628         // sets a model and updates the display
setModel(XMultiHierarchicalPropertySet xModel)629         public void setModel(XMultiHierarchicalPropertySet xModel) {
630             mxModel = xModel;
631             updateDisplay();
632         }
633 
634         // this method 'runs' the 'dialog'
execute()635         public int execute() {
636             try
637             {
638                 System.out.println("-- GridEditor executing --");
639                 // simulate a user action changing some data
640                 toggleVisibility();
641                 System.out.println("-- GridEditor done      --");
642                 return SAVE_SETTINGS;
643             }
644             catch (Exception e)
645             {
646                 informUserOfError(e);
647                 return CANCELED;
648             }
649         }
650 
651         // this method is called to report an error during dialog execution to the user
informUserOfError(Exception e)652         public void informUserOfError(Exception e) {
653             System.err.println("ERROR in GridEditor:");
654             e.printStackTrace();
655         }
656 
657         /// this method is called to allow the dialog to get feedback about changes occurring elsewhere
createChangesListener()658         public XChangesListener createChangesListener() {
659             if (mxModel == null) return null;
660 
661             return (new XChangesListener () {
662                 public void changesOccurred( ChangesEvent event ) {
663                     System.out.println("GridEditor - Listener received changes event containing " +
664                                         event.Changes.length + " change(s).");
665                     updateDisplay();
666                 }
667 
668                 public void disposing(EventObject event) {
669                     System.out.println("GridEditor - Listener received disposed event: releasing model");
670                     setModel(null);
671                 }
672             });
673         }
674         /// this method is called when data has changed to display the updated data
updateDisplay()675         private void updateDisplay()  {
676             if (mxModel != null)
677                 System.out.println("Grid options editor: data=" + readModel());
678             else
679                 System.out.println("Grid options editor: no model set");
680         }
681 
682         // this method is used to read all relevant data from the model
readModel()683         private GridOptions readModel()
684         {
685             try
686             {
687                 String [] aOptionNames = new String [5];
688                 aOptionNames[0] = "Option/VisibleGrid";
689                 aOptionNames[1] = "Subdivision/XAxis";
690                 aOptionNames[2] = "Subdivision/YAxis";
691                 aOptionNames[3] = "Resolution/XAxis/Metric";
692                 aOptionNames[4] = "Resolution/YAxis/Metric";
693 
694                 Object [] aValues = mxModel.getHierarchicalPropertyValues(aOptionNames);
695 
696                 GridOptions result = new GridOptions();
697                 result.visible = ((Boolean)aValues[0]).booleanValue();
698                 result.subdivision_x = ((Integer)aValues[1]).intValue();
699                 result.subdivision_y = ((Integer)aValues[2]).intValue();
700                 result.resolution_x  = ((Integer)aValues[3]).intValue();
701                 result.resolution_y  = ((Integer)aValues[4]).intValue();
702 
703                 return result;
704             }
705             catch (Exception e)
706             {
707                 informUserOfError(e);
708                 return null;
709             }
710         }
711 
712         // this method executes an edit
toggleVisibility()713         private void toggleVisibility()
714         {
715             try
716             {
717                 XHierarchicalPropertySet xHPS =
718                     UnoRuntime.queryInterface(XHierarchicalPropertySet.class, mxModel);
719 
720                 final String sSetting = "Option/VisibleGrid";
721 
722                 System.out.println("GridEditor: toggling Visibility");
723 
724                 Boolean bOldValue = (Boolean)xHPS.getHierarchicalPropertyValue(sSetting);
725 
726                 Boolean bNewValue = Boolean.valueOf( ! bOldValue.booleanValue() );
727 
728                 xHPS.setHierarchicalPropertyValue(sSetting,bNewValue);
729             }
730             catch (Exception e)
731             {
732                 informUserOfError(e);
733             }
734         }
735     }
736 
737     /** This method creates an extra updatable view to change some data
738         and trigger the listener of the GridEditor
739     */
740     void changeSomeData(String xKey)
741     {
742         try
743         {
744             Object xOtherViewRoot = createUpdatableView(xKey);
745 
746             XNameReplace aReplace = UnoRuntime.queryInterface(XNameReplace.class, xOtherViewRoot);
747 
748             String aItemNames [] = aReplace.getElementNames();
749             for (int i=0; i < aItemNames.length; ++i) {
750                 Object aItem = aReplace.getByName( aItemNames [i] );
751                 // replace integers by a 'complement' value
752                 if ( AnyConverter.isInt(aItem) )
753                 {
754                     int nOld = AnyConverter.toInt(aItem);
755                     int nNew = 9999 - nOld;
756 
757                     System.out.println("Replacing integer value: " + aItemNames [i]);
758                     aReplace.replaceByName( aItemNames [i], Integer.valueOf( nNew ) );
759                 }
760 
761                 // and booleans by their negated value
762                 else if ( AnyConverter.isBoolean(aItem) )
763                 {
764                     boolean bOld = AnyConverter.toBoolean(aItem);
765                     boolean bNew = ! bOld;
766 
767                     System.out.println("Replacing boolean value: " + aItemNames [i]);
768                     aReplace.replaceByName( aItemNames [i], Boolean.valueOf( bNew ) );
769                 }
770             }
771 
772             // commit the changes
773             XChangesBatch xUpdateControl =
774                 UnoRuntime.queryInterface(XChangesBatch.class,xOtherViewRoot);
775 
776             xUpdateControl.commitChanges();
777 
778             // we are done with the view - dispose it
779             UnoRuntime.queryInterface(XComponent.class, xOtherViewRoot).dispose();
780         }
781         catch (Exception e)
782         {
783             System.err.println("Could not change some data in a different view. An exception occurred:");
784             e.printStackTrace();
785         }
786     }
787 
788 // GROUP RESET EXAMPLE
789     /// This method resets the grid settings to their default values
790     protected void resetGridConfiguration()
791         throws com.sun.star.uno.Exception
792     {
793         // The path to the root element
794         final String cGridOptionsPath = "/org.openoffice.Office.Calc/Grid";
795 
796         // create the view
797         Object xViewRoot = createUpdatableView(cGridOptionsPath);
798 
799      // resetting a single nested value
800         XHierarchicalNameAccess xHierarchicalAccess =
801             UnoRuntime.queryInterface(XHierarchicalNameAccess.class, xViewRoot);
802 
803         // get using absolute name
804         Object xOptions = xHierarchicalAccess.getByHierarchicalName(cGridOptionsPath + "/Option");
805 
806         XPropertyState xOptionState =
807             UnoRuntime.queryInterface(XPropertyState.class, xOptions);
808 
809         xOptionState.setPropertyToDefault("VisibleGrid");
810 
811      // resetting more deeply nested values
812         Object xResolutionX = xHierarchicalAccess.getByHierarchicalName("Resolution/XAxis");
813         Object xResolutionY = xHierarchicalAccess.getByHierarchicalName("Resolution/YAxis");
814 
815         XPropertyState xResolutionStateX =
816             UnoRuntime.queryInterface(XPropertyState.class, xResolutionX);
817         XPropertyState xResolutionStateY =
818             UnoRuntime.queryInterface(XPropertyState.class, xResolutionY);
819 
820         xResolutionStateX.setPropertyToDefault("Metric");
821         xResolutionStateY.setPropertyToDefault("Metric");
822 
823      // resetting multiple sibling values
824         Object xSubdivision = xHierarchicalAccess.getByHierarchicalName("Subdivision");
825 
826         XMultiPropertyStates xSubdivisionStates =
827             UnoRuntime.queryInterface(XMultiPropertyStates.class, xSubdivision);
828 
829         xSubdivisionStates.setAllPropertiesToDefault();
830 
831         // commit the changes
832         XChangesBatch xUpdateControl =
833             UnoRuntime.queryInterface(XChangesBatch.class,xViewRoot);
834 
835         xUpdateControl.commitChanges();
836 
837        // we are done with the view - dispose it
838         UnoRuntime.queryInterface(XComponent.class, xViewRoot).dispose();
839     }
840 
841 
842 // SET UPDATE EXAMPLE
843     private static boolean SET_EXAMPLE_BROKEN_IN_THIS_RELEASE = true;
844 
845     /** This method stores a sample data source given some connection data.
846 
847         ATTENTION: This example requires an older version of the
848                    org.openoffice.Office.DataAccess schema.
849                    It does not work with the current schema.
850                    Because of this, the method currently does nothing.
851                    You can still use the techniques shown in the example code.
852     */
853     void storeSampleDataSource()
854         throws com.sun.star.uno.Exception
855     {
856         if (SET_EXAMPLE_BROKEN_IN_THIS_RELEASE)
857         {
858             System.out.println("-  DISABLED: (the existing example does not work with this version) -");
859             return; // this function does not work
860         }
861 
862         String sSampleDataSourceName = "SampleTextDatabase";
863 
864         String sSampleDataSourceURL = "sdbc:flat:$(userurl)/database/SampleTextDatabase";
865 
866         com.sun.star.beans.NamedValue [] aSettings = new com.sun.star.beans.NamedValue [2];
867         aSettings[0] = new com.sun.star.beans.NamedValue("HeaderLine",Boolean.TRUE);
868         aSettings[1] = new com.sun.star.beans.NamedValue("FieldDelimiter",";");
869 
870         String [] aTableFilter = new String[] { "table.txt", "othertable.txt" };
871 
872         storeDataSource(sSampleDataSourceName,sSampleDataSourceURL,"",false,0,aSettings,aTableFilter);
873     }
874 
875     /// This method stores a data source given some connection data
876     void storeDataSource(
877         String sDataSourceName,
878         String sDataSourceURL,
879         String sUser,
880         boolean bNeedsPassword,
881         int nTimeout,
882         com.sun.star.beans.NamedValue [] aDriverSettings,
883         String [] aTableFilter
884     )
885         throws com.sun.star.uno.Exception
886     {
887       // create the view and get the data source element
888         Object xDataSource = createDataSourceDescription(getProvider(),sDataSourceName);
889 
890       // set the values
891         XPropertySet xDataSourceProperties =
892             UnoRuntime.queryInterface(XPropertySet.class, xDataSource);
893 
894         xDataSourceProperties.setPropertyValue("URL",  sDataSourceURL  );
895         xDataSourceProperties.setPropertyValue("User", sUser  );
896         xDataSourceProperties.setPropertyValue("IsPasswordRequired", Boolean.valueOf( bNeedsPassword ) );
897         xDataSourceProperties.setPropertyValue("LoginTimeout", Integer.valueOf( nTimeout ) );
898 
899         if ( aTableFilter != null )
900             xDataSourceProperties.setPropertyValue("TableFilter",  aTableFilter  );
901 
902       // store the driver-specific settings
903         if (aDriverSettings != null)
904         {
905             Object xSettingsSet = xDataSourceProperties.getPropertyValue("DataSourceSettings");
906             storeSettings( xSettingsSet, aDriverSettings);
907         }
908 
909       // save the data and dispose the view
910         // recover the view root
911         Object xViewRoot = getViewRoot(xDataSource);
912 
913         // commit the changes
914         XChangesBatch xUpdateControl =
915             UnoRuntime.queryInterface(XChangesBatch.class,xViewRoot);
916 
917         xUpdateControl.commitChanges();
918 
919         // now clean up
920         UnoRuntime.queryInterface(XComponent.class, xViewRoot).dispose();
921     }
922 
923     /** This method gets the DataSourceDescription for a data source.
924         It either gets the existing entry or creates a new instance.
925     */
926     Object createDataSourceDescription(XMultiServiceFactory xProvider, String sDataSourceName )
927         throws com.sun.star.uno.Exception
928     {
929         // The service name: Need an update access:
930         final String cUpdatableView = "com.sun.star.configuration.ConfigurationUpdateAccess";
931 
932          // The path to the DataSources set node
933         final String cDataSourcesPath = "/org.openoffice.Office.DataAccess/DataSources";
934 
935        // creation arguments: nodepath
936         com.sun.star.beans.PropertyValue aPathArgument = new com.sun.star.beans.PropertyValue();
937         aPathArgument.Name = "nodepath";
938         aPathArgument.Value = cDataSourcesPath ;
939 
940         Object[] aArguments = new Object[1];
941         aArguments[0] = aPathArgument;
942 
943         // create the view
944         Object xViewRoot =
945             xProvider.createInstanceWithArguments(cUpdatableView, aArguments);
946 
947         XNameAccess xSetOfDataSources =
948             UnoRuntime.queryInterface(XNameAccess.class,xViewRoot);
949 
950         Object xDataSourceDescriptor = null; // the result
951         if ( xSetOfDataSources .hasByName( sDataSourceName ))
952         {
953             // the element is there
954             try
955             {
956                 // the view should point to the element directly, so we need to extend the path
957                 XHierarchicalName xComposePath = UnoRuntime.queryInterface(XHierarchicalName.class, xSetOfDataSources );
958 
959                 String sElementPath = xComposePath.composeHierarchicalName( sDataSourceName );
960 
961                 // use the name of the element now
962                 aPathArgument.Value = sElementPath;
963 
964                 // create another view now
965                 Object[] aDeepArguments = new Object[1];
966                 aDeepArguments[0] = aPathArgument;
967 
968                 // create the view
969                 xDataSourceDescriptor  =
970                       xProvider.createInstanceWithArguments(cUpdatableView, aDeepArguments);
971 
972                 if ( xDataSourceDescriptor != null) // all went fine
973                 {
974                     // dispose the other view
975                     UnoRuntime.queryInterface(XComponent.class, xViewRoot).dispose();
976                     xViewRoot = null;
977                 }
978             }
979             catch (Exception e)
980             {
981               // something went wrong, we retry with a new element
982                System.err.println("WARNING: An exception occurred while creating a view for an existing data source: " + e);
983                xDataSourceDescriptor  = null;
984             }
985         }
986 
987         // do we have a result element yet ?
988         if ( xDataSourceDescriptor == null)
989         {
990             // get the container
991             XNameContainer xSetUpdate =
992                 UnoRuntime.queryInterface(XNameContainer.class, xViewRoot);
993 
994             // create a new detached set element (instance of DataSourceDescription)
995             XSingleServiceFactory xElementFactory =
996                 UnoRuntime.queryInterface(XSingleServiceFactory.class, xSetUpdate);
997 
998             // the new element is the result !
999              xDataSourceDescriptor  = xElementFactory.createInstance();
1000 
1001             // insert it - this also names the element
1002             xSetUpdate.insertByName( sDataSourceName ,  xDataSourceDescriptor  );
1003         }
1004 
1005         return xDataSourceDescriptor ;
1006     }
1007 
1008     /// this method stores a number of settings in a set node containing DataSourceSetting objects
1009     void storeSettings(Object xSettingsSet, com.sun.star.beans.NamedValue [] aSettings )
1010         throws com.sun.star.uno.Exception
1011     {
1012         if (aSettings == null)
1013             return;
1014 
1015         // get the settings set as a container
1016         XNameContainer xSettingsContainer =
1017             UnoRuntime.queryInterface( XNameContainer.class, xSettingsSet);
1018 
1019         // and get a factory interface for creating the entries
1020         XSingleServiceFactory xSettingsFactory =
1021             UnoRuntime.queryInterface(XSingleServiceFactory.class, xSettingsSet);
1022 
1023         // now insert the individual settings
1024         for (int i = 0; i < aSettings.length; ++i) {
1025             // create a DataSourceSetting object
1026             XPropertySet xSetting = UnoRuntime.queryInterface( XPropertySet.class, xSettingsFactory.createInstance() );
1027 
1028             // can set the value before inserting
1029             xSetting.setPropertyValue( "Value", aSettings[i].Value );
1030 
1031             // and now insert or replace as appropriate
1032             if (xSettingsContainer.hasByName( aSettings[i].Name ))
1033                 xSettingsContainer.replaceByName( aSettings[i].Name, xSetting );
1034             else
1035                 xSettingsContainer.insertByName( aSettings[i].Name, xSetting );
1036         }
1037     }
1038 
1039 // HELPER FUNCTIONS
1040 
1041     /// This method get the view root node given an interface to any node in the view
1042     public static Object getViewRoot(Object xElement)
1043     {
1044         Object xResult = xElement;
1045 
1046         // set the result to its parent until that would be null
1047         Object xParent;
1048         do
1049         {
1050             XChild xParentAccess =
1051                 UnoRuntime.queryInterface(XChild.class,xResult);
1052 
1053             if (xParentAccess != null)
1054                 xParent = xParentAccess.getParent();
1055             else
1056                 xParent = null;
1057 
1058             if (xParent != null)
1059                 xResult = xParent;
1060          }
1061          while (xParent != null);
1062 
1063          return xResult;
1064     }
1065 
1066 // workaround methods for unimplemented functionality
1067 
1068     /// WORKAROUND: does the same as xNamedItem.setName(sNewName) should do
1069     void renameSetItem(XNamed xNamedItem, String sNewName)
1070         throws com.sun.star.uno.Exception
1071     {
1072         XChild xChildItem = UnoRuntime.queryInterface(XChild.class, xNamedItem);
1073 
1074         XNameContainer xParentSet = UnoRuntime.queryInterface( XNameContainer.class, xChildItem.getParent() );
1075 
1076         String sOldName = xNamedItem.getName();
1077 
1078         // now rename the item
1079         xParentSet.removeByName(sOldName);
1080         xParentSet.insertByName(sNewName,xNamedItem);
1081     }
1082 
1083     /// WORKAROUND: does the same as xChildItem.setParent( xNewParent ) should do
1084     void moveSetItem(XChild xChildItem, XNameContainer xNewParent)
1085         throws com.sun.star.uno.Exception
1086     {
1087         XNamed xNamedItem = UnoRuntime.queryInterface(XNamed.class, xChildItem);
1088 
1089         XNameContainer xOldParent = UnoRuntime.queryInterface( XNameContainer.class, xChildItem.getParent() );
1090 
1091         String sItemName = xNamedItem.getName();
1092 
1093         // now rename the item
1094         xOldParent.removeByName(sItemName);
1095         xNewParent.insertByName(sItemName,xChildItem);
1096     }
1097 
1098 
1099 // ------- the end -----------
1100 }
1101 
1102 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1103