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