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