/**************************************************************
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/



// Import everything we use

import com.sun.star.beans.XPropertySet;
import com.sun.star.beans.XMultiPropertySet;
import com.sun.star.beans.XHierarchicalPropertySet;
import com.sun.star.beans.XMultiHierarchicalPropertySet;
import com.sun.star.beans.XPropertyState;
import com.sun.star.beans.XMultiPropertyStates;

import com.sun.star.bridge.XUnoUrlResolver;

import com.sun.star.configuration.XTemplateInstance;

import com.sun.star.container.XNameAccess;
import com.sun.star.container.XNameReplace;
import com.sun.star.container.XNameContainer;
import com.sun.star.container.XNamed;
import com.sun.star.container.XChild;
import com.sun.star.container.XHierarchicalNameAccess;
import com.sun.star.container.XHierarchicalName;

import com.sun.star.lang.XComponent;
import com.sun.star.lang.XMultiComponentFactory;
import com.sun.star.lang.XSingleServiceFactory;
import com.sun.star.lang.XMultiServiceFactory;
import com.sun.star.lang.XMultiComponentFactory;
import com.sun.star.lang.XServiceInfo;
import com.sun.star.lang.EventObject;

import com.sun.star.uno.UnoRuntime;
import com.sun.star.uno.XComponentContext;
import com.sun.star.uno.XInterface;
import com.sun.star.uno.XNamingService;
import com.sun.star.uno.AnyConverter;

import com.sun.star.util.XChangesBatch;
import com.sun.star.util.XChangesNotifier;
import com.sun.star.util.XChangesListener;
import com.sun.star.util.ChangesEvent;
/** Config examples
	@author Joerg Barfurth
 */

/* These examples show how to use the following features of the Config API:

	o Accessing data
	o Updating data
	o Updating properties in groups
	o Adding and removing items in sets
	o Resetting data to their defaults

   Each example is in a separate method call.
*/ 
public class ConfigExamples  
{
	// The ComponentContext interface of the remote component context
	private XComponentContext mxContext = null;

    // The MultiComponentFactory interface of the ServiceManager
	private XMultiComponentFactory mxServiceManager = null;

	// The MultiServiceFactory interface of the ConfigurationProvider
	private XMultiServiceFactory mxProvider = null;

	public static void main( String args[] ) 
	{
        try {
            // get the remote office component context
            com.sun.star.uno.XComponentContext xContext =
                com.sun.star.comp.helper.Bootstrap.bootstrap();
            
            if( xContext != null )
                System.out.println("Connected to a running office ...");
            else
			    System.out.println( "ERROR: Cannot connect - no remote component context available." );
            
            // Create an instance of the class and call it's run method
            ConfigExamples aExample = new ConfigExamples(xContext);
            aExample.run( );
            
            // if you own the service manager dispose it here 
            // to ensure that the default provider is properly disposed and flushed            
            System.exit(0);
		} 
		catch( Exception e ) 
		{
			e.printStackTrace();
            System.exit(-1);
		}
	}

    /** Create a ConfigExamples instance supplying a service factory
    */
    public ConfigExamples(XComponentContext xContext)
    {
        mxContext = xContext;
        mxServiceManager = xContext.getServiceManager();
    }

    /** Run the examples with a default ConfigurationProvider
    */
	public void run() 
		throws com.sun.star.uno.Exception
	{
        mxProvider = createProvider(); 

        runExamples( );

        // we are using the default ConfigurationProvider, so we must not dispose it
        mxProvider = null;
    }

    /** Run the examples with a given ConfigurationProvider
    */
	public void runExamples( ) 
	{
        if (checkProvider(mxProvider))
        {
            System.out.println("\nStarting examples.");

            readDataExample();

            browseDataExample();

            updateGroupExample();

            resetGroupExample();

            updateSetExample();

            System.out.println("\nAll Examples completed.");
        }
        else
            System.out.println("ERROR: Cannot run examples without ConfigurationProvider.");

	} 

    /** Do some simple checks, if tehre is a valid ConfigurationProvider
    */
    public static boolean checkProvider(XMultiServiceFactory xProvider)
    {
        // check the provider we have
        if (xProvider == null)
        {
            System.out.println("No provider available. Cannot access configuration data.");
            return false;

        }

        try
        {
            // check the provider implementation
            XServiceInfo xProviderServices = 
                (XServiceInfo) UnoRuntime.queryInterface( XServiceInfo.class, xProvider );

            if (xProviderServices == null || 
                !xProviderServices.supportsService("com.sun.star.configuration.ConfigurationProvider"))
            {
                System.out.println("WARNING: The provider is not a com.sun.star.configuration.ConfigurationProvider");
            }

            if (xProviderServices != null)
            {
                System.out.println("Using provider implementation: " + xProviderServices.getImplementationName());
            }

            return true;
        }
        catch (com.sun.star.uno.RuntimeException e)
        {
            System.err.println("ERROR: Failure while checking the provider services.");
            e.printStackTrace();
            return false;
        }
    }
    
	/** Get the provider we have 
     */
	public XMultiServiceFactory getProvider( )
	{
        return mxProvider;
    }

	/** Create a default configuration provider 
     */
	public XMultiServiceFactory createProvider( )
		throws com.sun.star.uno.Exception
	{
        final String sProviderService = "com.sun.star.configuration.ConfigurationProvider";

        // create the provider and return it as a XMultiServiceFactory
        XMultiServiceFactory xProvider = (XMultiServiceFactory)
            UnoRuntime.queryInterface(XMultiServiceFactory.class, 
                mxServiceManager.createInstanceWithContext(sProviderService,
                                                           mxContext));	

        return xProvider;
    }

	/** Create a specified read-only configuration view
     */
    public Object createConfigurationView( String sPath )
		throws com.sun.star.uno.Exception
    {
        XMultiServiceFactory xProvider = getProvider();

        // The service name: Need only read access:
        final String sReadOnlyView = "com.sun.star.configuration.ConfigurationAccess";

        // creation arguments: nodepath   
        com.sun.star.beans.PropertyValue aPathArgument = new com.sun.star.beans.PropertyValue();
        aPathArgument.Name = "nodepath";
        aPathArgument.Value = sPath;

        Object[] aArguments = new Object[1];
        aArguments[0] = aPathArgument;

        // create the view
        Object xViewRoot = xProvider.createInstanceWithArguments(sReadOnlyView, aArguments);

        return xViewRoot;
    }

	/** Create a specified updatable configuration view
     */
    Object createUpdatableView( String sPath )
		throws com.sun.star.uno.Exception
    {
        XMultiServiceFactory xProvider = getProvider();

        // The service name: Need update access:
        final String cUpdatableView = "com.sun.star.configuration.ConfigurationUpdateAccess";

        // creation arguments: nodepath   
        com.sun.star.beans.PropertyValue aPathArgument = new com.sun.star.beans.PropertyValue();
        aPathArgument.Name = "nodepath";
        aPathArgument.Value = sPath;

        Object[] aArguments = new Object[1];
        aArguments[0] = aPathArgument;

        // create the view
        Object xViewRoot = xProvider.createInstanceWithArguments(cUpdatableView, aArguments);

        return xViewRoot;
    }

	/** This method demonstrates read access to data
	 */
	protected void readDataExample ()
	{
		try
		{
            System.out.println("\n--- starting example: read grid option settings --------------------");
            Object aData = readGridConfiguration( );
            System.out.println("Read grid options: " + aData);

		}
		catch ( Exception e )
		{
			e.printStackTrace();
		}
	}

	/** This method demonstrates browsing access to data
	 */
	protected void browseDataExample ()
	{
		try
		{
            System.out.println("\n--- starting example: browse filter configuration ------------------");
            printRegisteredFilters( );
		}
		catch ( Exception e )
		{
			e.printStackTrace();
		}
	}

	/** This method demonstrates update access to group data
	 */
	protected void updateGroupExample ()
	{
		try
		{
            System.out.println("\n--- starting example: update group data --------------");
            editGridOptions( );
		}   
		catch ( Exception e )
		{
			e.printStackTrace();
		}
	}

	/** This method demonstrates resetting data to its default state
	 */
	protected void resetGroupExample ()
	{
		try
		{
            System.out.println("\n--- starting example: reset group data -----------------------------");
            Object aOldData = readGridConfiguration( );
            resetGridConfiguration( );
            Object aNewData = readGridConfiguration( );
            System.out.println("Before reset:   user grid options: " + aOldData);
            System.out.println("After reset: default grid options: " + aNewData);
		}   
		catch ( Exception e )
		{
			e.printStackTrace();
		}
	}

	/** This method demonstrates update access to set data
	 */
	protected void updateSetExample ()
	{
		try
		{
            System.out.println("\n--- starting example: update set data ---------------");
            storeSampleDataSource( );
		}
		catch ( Exception e )
		{
			e.printStackTrace();
		}
	}

// READ example
    /// class to hold information about grid settings
    public static class GridOptions
    {
        public boolean visible;
        public int resolution_x;
        public int resolution_y;
        public int subdivision_x;
        public int subdivision_y;

        public String toString() {
            StringBuffer aBuffer = new StringBuffer();
            aBuffer.append("[ Grid is "); aBuffer.append(visible ? "VISIBLE" : "HIDDEN");
            aBuffer.append("; resolution  = (" + resolution_x  + "," + resolution_y  + ")");
            aBuffer.append("; subdivision = (" + subdivision_x + "," + subdivision_y + ")");
            aBuffer.append(" ]");
            return aBuffer.toString();
        }
    };

    /// This method reads information about grid settings
    protected GridOptions readGridConfiguration()
		throws com.sun.star.uno.Exception
    {
        // The path to the root element 
        final String cGridOptionsPath = "/org.openoffice.Office.Calc/Grid";

        // create the view
        Object xViewRoot = createConfigurationView(cGridOptionsPath);

        // the result structure
        GridOptions options = new GridOptions();
   
      // accessing a single nested value
        XHierarchicalPropertySet xProperties = 
            (XHierarchicalPropertySet)UnoRuntime.queryInterface(XHierarchicalPropertySet.class, xViewRoot);

        Object aVisible = xProperties.getHierarchicalPropertyValue("Option/VisibleGrid");
        options.visible = ((Boolean) aVisible).booleanValue();

      // accessing a nested object and its subproperties
        Object xSubdivision = xProperties.getHierarchicalPropertyValue("Subdivision");

        XMultiPropertySet xSubdivProperties =
            (XMultiPropertySet)UnoRuntime.queryInterface(XMultiPropertySet.class, xSubdivision);
    
        // variables for multi-element access 
        String[] aElementNames = new String[2];

        aElementNames[0] = "XAxis";
        aElementNames[1] = "YAxis";

        Object[] aElementValues = xSubdivProperties.getPropertyValues(aElementNames);

        options.subdivision_x = ((Integer) aElementValues[0]).intValue();
        options.subdivision_y = ((Integer) aElementValues[1]).intValue();

      // accessing deeply nested subproperties
        Object xResolution = xProperties.getHierarchicalPropertyValue("Resolution");

        XMultiHierarchicalPropertySet xResolutionProperties = 
            (XMultiHierarchicalPropertySet)
                UnoRuntime.queryInterface(XMultiHierarchicalPropertySet.class, xResolution);
    
        aElementNames[0] = "XAxis/Metric";
        aElementNames[1] = "YAxis/Metric";

        aElementValues = xResolutionProperties.getHierarchicalPropertyValues(aElementNames);

        options.resolution_x = ((Integer) aElementValues[0]).intValue();
        options.resolution_y = ((Integer) aElementValues[1]).intValue();

      // all options have been retrieved - clean up and return
        // we are done with the view - dispose it 

        ((XComponent)UnoRuntime.queryInterface(XComponent.class, xViewRoot)).dispose();

        return options;
    }

// BROWSE example
    /// Interface to procees information when browsing the configuration tree
    public static interface IConfigurationProcessor
    {
        /// process a value item
       public abstract void processValueElement( String sPath_, Object aValue_ );
        /// process a structural item
       public abstract void processStructuralElement( String sPath_, XInterface xElement_);
    };

    /// Internal method to recursively browse a structural element in preorder
    public void browseElementRecursively( XInterface xElement, IConfigurationProcessor aProcessor )
		throws com.sun.star.uno.Exception
    {
        // First process this as an element (preorder traversal)
        XHierarchicalName xElementPath = 
            (XHierarchicalName) UnoRuntime.queryInterface(XHierarchicalName.class, xElement);

        String sPath = xElementPath.getHierarchicalName();

        aProcessor.processStructuralElement( sPath, xElement);

        // now process this as a container
        XNameAccess xChildAccess =
            (XNameAccess) UnoRuntime.queryInterface(XNameAccess.class, xElement);
    
        // get a list of child elements
        String[] aElementNames = xChildAccess.getElementNames();

        // and process them one by one
        for(int i=0; i< aElementNames.length; ++i)
        {
            Object aChild = xChildAccess.getByName( aElementNames[i] );
            AnyConverter aAnyConv = new AnyConverter();
            // is it a structural element (object) ...
            if ( aAnyConv.isObject(aChild) && !aAnyConv.isArray(aChild) )
            {
                // then get an interface 
                XInterface xChildElement = (XInterface)UnoRuntime.queryInterface(XInterface.class, aChild);

                // and continue processing child elements recursively
                browseElementRecursively( xChildElement, aProcessor );
            }
            // ... or is it a simple value
            else
            {
                // Build the path to it from the path of 
                // the element and the name of the child
                String sChildPath;
                sChildPath = 
                    xElementPath.composeHierarchicalName(aElementNames[i]);

                // and process the value
                aProcessor.processValueElement( sChildPath, aChild );
            }
        }
    }

    /** Method to browse the part rooted at sRootPath 
        of the configuration that the Provider provides.

        All nodes will be processed by the IConfigurationProcessor passed.
    */
    public void browseConfiguration( String sRootPath, IConfigurationProcessor aProcessor )
		throws com.sun.star.uno.Exception
    {
        // create the root element
        XInterface xViewRoot = (XInterface)createConfigurationView( sRootPath );
   
        // now do the processing
        browseElementRecursively( xViewRoot, aProcessor );

        // we are done with the view - dispose it 
        //   This assumes that the processor 
        //   does not keep a reference to the elements in processStructuralElement

        ((XComponent) UnoRuntime.queryInterface(XComponent.class,xViewRoot)).dispose();
        xViewRoot = null;
    }

    /** Method to browse the filter configuration.

        Information about installed filters will be printed.
    */
    public void printRegisteredFilters()
		throws com.sun.star.uno.Exception
    {
        final String sProviderService = "com.sun.star.configuration.ConfigurationProvider";
        final String sFilterKey = "/org.openoffice.TypeDetection.Filter/Filters";

       // browse the configuration, dumping filter information
        browseConfiguration( sFilterKey, 
           new IConfigurationProcessor () {
               /// prints Path and Value of properties
               public void processValueElement( String sPath_, Object aValue_ ) {
                   if (new AnyConverter().isArray(aValue_))
				   {
					   final Object [] aArray = (Object [])aValue_;
					   
					   System.out.print("\tValue: " + sPath_ + " = { ");
					   for (int i=0; i<aArray.length; ++i)
					   {
						   if (i != 0) System.out.print(", ");
						   System.out.print(aArray[i]);
					   }
					   System.out.println(" }");
				   }
				   else
						System.out.println("\tValue: " + sPath_ + " = " + aValue_);
               }
               
               /// prints the Filter entries
               public void processStructuralElement( String sPath_, XInterface xElement_) {
                   // get template information, to detect instances of the 'Filter' template
                   XTemplateInstance xInstance = 
                       ( XTemplateInstance )UnoRuntime.queryInterface( XTemplateInstance .class,xElement_);

                   // only select the Filter entries 
                   if (xInstance != null && xInstance.getTemplateName().endsWith("Filter")) {
                        XNamed xNamed = (XNamed)UnoRuntime.queryInterface(XNamed.class,xElement_);
                        System.out.println("Filter " + xNamed.getName() + " (" + sPath_ + ")");
                   }
               }
           } );
    }

// GROUP UPDATE example

    /** This method simulates editing configuration data using a GridEditor dialog class  
    */
    public void editGridOptions( )
		throws com.sun.star.uno.Exception
    {
        // The path to the root element 
        final String cGridOptionsPath = "/org.openoffice.Office.Calc/Grid";

      // create the view
        Object xViewRoot = createUpdatableView( cGridOptionsPath );

        // the 'editor'
        GridOptionsEditor dialog = new GridOptionsEditor();

      // set up the initial values and register listeners
        // get a data access interface, to supply the view with a model 
        XMultiHierarchicalPropertySet xProperties =
            (XMultiHierarchicalPropertySet)
                UnoRuntime.queryInterface(XMultiHierarchicalPropertySet.class, xViewRoot);

        dialog.setModel( xProperties );

        // get a listener object (probably an adapter) that notifies
        // the dialog of external changes to its model 
        XChangesListener xListener = dialog.createChangesListener( );
    
        XChangesNotifier xNotifier = 
            (XChangesNotifier)UnoRuntime.queryInterface(XChangesNotifier.class, xViewRoot);

        xNotifier.addChangesListener( xListener );

        // trigger the listener
        changeSomeData( cGridOptionsPath + "/Subdivision" );

        if (dialog.execute() == GridOptionsEditor.SAVE_SETTINGS)
        {
            // changes have been applied to the view here
            XChangesBatch xUpdateControl = 
                (XChangesBatch) UnoRuntime.queryInterface(XChangesBatch.class,xViewRoot);
        
            try
            {
               xUpdateControl.commitChanges();
            }
            catch (Exception e)
            {
                dialog.informUserOfError( e );
            }
        }
   
      // all changes have been handled - clean up and return
        // listener is done now
        xNotifier.removeChangesListener( xListener );

        // we are done with the view - dispose it 
        ((XComponent)UnoRuntime.queryInterface(XComponent.class, xViewRoot)).dispose();
    }

    /** A class that changes some grid options settings

        The interface of this class is chose to resemble a possible UI dialog class
    */
    private class GridOptionsEditor {
        /// the data this editor edits
        XMultiHierarchicalPropertySet mxModel;

        public static final int CANCELED = 0;
        public static final int SAVE_SETTINGS = 1;

        // sets a model and updates the display
        public void setModel(XMultiHierarchicalPropertySet xModel) {
            mxModel = xModel;
            updateDisplay();
        }

        // this method 'runs' the 'dialog'
        public int execute() {
            try
            {
                System.out.println("-- GridEditor executing --");
                // simulate a user action changing some data
                toggleVisibility();
                System.out.println("-- GridEditor done      --");
                return SAVE_SETTINGS;
            }
            catch (Exception e)
            {
                informUserOfError(e);
                return CANCELED;
            }
        }

        /// this method is called to report an error during dialog execution to the zuser
        public void informUserOfError(Exception e) {
            System.err.println("ERROR in GridEditor:");
            e.printStackTrace();
        }

        /// this method is called to allow the dialog to get feedback about changes occurring elsewhere
        public XChangesListener createChangesListener() {
            if (mxModel == null) return null;

            return (new XChangesListener () {
                public void changesOccurred( ChangesEvent event ) {
                    System.out.println("GridEditor - Listener received changes event containing " +
                                        event.Changes.length + " change(s).");
                    updateDisplay();
                }

                public void disposing(EventObject event) {
                    System.out.println("GridEditor - Listener received disposed event: releasing model");
                    setModel(null);
                }
            });
        }
        /// this method is called when data has changed to display the updated data
        private void updateDisplay()  { 
            if (mxModel != null)
                System.out.println("Grid options editor: data=" + readModel());
            else
                System.out.println("Grid options editor: no model set");
        }

        // this method is used to read all relevant data from the model
        private GridOptions readModel() 
        {
            try
            {
                String [] aOptionNames = new String [5];
                aOptionNames[0] = "Option/VisibleGrid";
                aOptionNames[1] = "Subdivision/XAxis";
                aOptionNames[2] = "Subdivision/YAxis";
                aOptionNames[3] = "Resolution/XAxis/Metric";
                aOptionNames[4] = "Resolution/YAxis/Metric";

                Object [] aValues = mxModel.getHierarchicalPropertyValues(aOptionNames);

                GridOptions result = new GridOptions();
                result.visible = ((Boolean)aValues[0]).booleanValue();
                result.subdivision_x = ((Integer)aValues[1]).intValue();
                result.subdivision_y = ((Integer)aValues[2]).intValue();
                result.resolution_x  = ((Integer)aValues[3]).intValue();
                result.resolution_y  = ((Integer)aValues[4]).intValue();

                return result;
            }
            catch (Exception e)
            {
                informUserOfError(e);
                return null;
            }
        }

        // this method executes an edit
        private void toggleVisibility()
        {
            try
            {
                XHierarchicalPropertySet xHPS = 
                    (XHierarchicalPropertySet)UnoRuntime.queryInterface(XHierarchicalPropertySet.class, mxModel);

                final String sSetting = "Option/VisibleGrid";

                System.out.println("GridEditor: toggling Visibility");

                Boolean bOldValue = (Boolean)xHPS.getHierarchicalPropertyValue(sSetting);

                Boolean bNewValue = new Boolean( ! bOldValue.booleanValue() );
            
                xHPS.setHierarchicalPropertyValue(sSetting,bNewValue);
            }
            catch (Exception e)
            {
                informUserOfError(e);
            }
        }
    }

    /** This method creates an extra updatable view to change some data 
        and trigger the listener of the GridEditor  
    */
    void changeSomeData(String xKey) 
    {
        try
        {
            Object xOtherViewRoot = createUpdatableView(xKey);

            XNameReplace aReplace = (XNameReplace)UnoRuntime.queryInterface(XNameReplace.class, xOtherViewRoot);

            String aItemNames [] = aReplace.getElementNames();
            for (int i=0; i < aItemNames.length; ++i) {
                Object aItem = aReplace.getByName( aItemNames [i] );
                AnyConverter aAnyConv = new AnyConverter();
                // replace integers by a 'complement' value
                if ( aAnyConv.isInt(aItem) )
                {
                    int nOld = aAnyConv.toInt(aItem);
                    int nNew = 9999 - nOld;

                    System.out.println("Replacing integer value: " + aItemNames [i]);
                    aReplace.replaceByName( aItemNames [i], new Integer( nNew ) );
                }

                // and booleans by their negated value
                else if ( aAnyConv.isBoolean(aItem) )
                {
                    boolean bOld = aAnyConv.toBoolean(aItem);
                    boolean bNew = ! bOld;

                    System.out.println("Replacing boolean value: " + aItemNames [i]);
                    aReplace.replaceByName( aItemNames [i], new Boolean( bNew ) );
                }
            }

            // commit the changes
            XChangesBatch xUpdateControl = 
                (XChangesBatch) UnoRuntime.queryInterface(XChangesBatch.class,xOtherViewRoot);
        
            xUpdateControl.commitChanges();

            // we are done with the view - dispose it 
            ((XComponent)UnoRuntime.queryInterface(XComponent.class, xOtherViewRoot)).dispose();
        }
        catch (Exception e)
        {
            System.err.println("Could not change some data in a different view. An exception occurred:");
            e.printStackTrace();
        }
    }

// GROUP RESET EXAMPLE
    /// This method resets the grid settings to their default values
    protected void resetGridConfiguration()
		throws com.sun.star.uno.Exception
    {
        // The path to the root element 
        final String cGridOptionsPath = "/org.openoffice.Office.Calc/Grid";

        // create the view
        Object xViewRoot = createUpdatableView(cGridOptionsPath);

     // resetting a single nested value
        XHierarchicalNameAccess xHierarchicalAccess = 
            (XHierarchicalNameAccess)UnoRuntime.queryInterface(XHierarchicalNameAccess.class, xViewRoot);

        // get using absolute name
        Object xOptions = xHierarchicalAccess.getByHierarchicalName(cGridOptionsPath + "/Option");

        XPropertyState xOptionState = 
            (XPropertyState)UnoRuntime.queryInterface(XPropertyState.class, xOptions);

        xOptionState.setPropertyToDefault("VisibleGrid");

     // resetting more deeply nested values
        Object xResolutionX = xHierarchicalAccess.getByHierarchicalName("Resolution/XAxis");
        Object xResolutionY = xHierarchicalAccess.getByHierarchicalName("Resolution/YAxis");

        XPropertyState xResolutionStateX = 
            (XPropertyState)UnoRuntime.queryInterface(XPropertyState.class, xResolutionX);
        XPropertyState xResolutionStateY = 
            (XPropertyState)UnoRuntime.queryInterface(XPropertyState.class, xResolutionY);

        xResolutionStateX.setPropertyToDefault("Metric");
        xResolutionStateY.setPropertyToDefault("Metric");

     // resetting multiple sibling values
        Object xSubdivision = xHierarchicalAccess.getByHierarchicalName("Subdivision");

        XMultiPropertyStates xSubdivisionStates =
            (XMultiPropertyStates)UnoRuntime.queryInterface(XMultiPropertyStates.class, xSubdivision);
    
        xSubdivisionStates.setAllPropertiesToDefault();

        // commit the changes
        XChangesBatch xUpdateControl = 
            (XChangesBatch) UnoRuntime.queryInterface(XChangesBatch.class,xViewRoot);
    
        xUpdateControl.commitChanges();

       // we are done with the view - dispose it 
        ((XComponent)UnoRuntime.queryInterface(XComponent.class, xViewRoot)).dispose();
    }


// SET UPDATE EXAMPLE
    private static boolean SET_EXAMPLE_BROKEN_IN_THIS_RELEASE = true;

    /** This method stores a sample data source given some connection data.

        ATTENTION: This example requires an older version of the 
                   org.openoffice.Office.DataAccess schema.
                   It does not work with the current schema.
                   Because of this, the method currenty does nothing.
                   You can still use the techniques shown in the example code.
    */
    void storeSampleDataSource()
		throws com.sun.star.uno.Exception
    {
        if (SET_EXAMPLE_BROKEN_IN_THIS_RELEASE) 
        {
            System.out.println("-  DISABLED: (the existing example does not work with this version) -");
            return; // this function does not work
        }
        
        String sSampleDataSourceName = "SampleTextDatabase";

        String sSampleDataSourceURL = "sdbc:flat:$(userurl)/database/SampleTextDatabase";
        // String sSampleDataSourceURL = "sdbc:flat:file:///usr/local/database/SampleTextDatabase";
        // String sSampleDataSourceURL = "sdbc:flat:file:///C:/data/database/SampleTextDatabase";

        com.sun.star.beans.NamedValue [] aSettings = new com.sun.star.beans.NamedValue [2];
        aSettings[0] = new com.sun.star.beans.NamedValue("HeaderLine",new Boolean(true));
        aSettings[1] = new com.sun.star.beans.NamedValue("FieldDelimiter",";");

        String [] aTableFilter = new String[2];
        aTableFilter[0] = "table.txt";
        aTableFilter[1] = "othertable.txt";

        storeDataSource(sSampleDataSourceName,sSampleDataSourceURL,"",false,0,aSettings,aTableFilter);
    }

    /// This method stores a data source given some connection data
    void storeDataSource(
        String sDataSourceName,
        String sDataSourceURL,
        String sUser,
        boolean bNeedsPassword,
        int nTimeout,
        com.sun.star.beans.NamedValue [] aDriverSettings,
        String [] aTableFilter
    )
		throws com.sun.star.uno.Exception
    {
      // create the view and get the data source element 
        Object xDataSource = createDataSourceDescription(getProvider(),sDataSourceName);

      // set the values 
        XPropertySet xDataSourceProperties =
            (XPropertySet)UnoRuntime.queryInterface(XPropertySet.class, xDataSource);

        xDataSourceProperties.setPropertyValue("URL",  sDataSourceURL  );
        xDataSourceProperties.setPropertyValue("User", sUser  );
        xDataSourceProperties.setPropertyValue("IsPasswordRequired", new Boolean( bNeedsPassword ) );
        xDataSourceProperties.setPropertyValue("LoginTimeout", new Integer( nTimeout ) );

        if ( aTableFilter != null )
    	    xDataSourceProperties.setPropertyValue("TableFilter",  aTableFilter  );
    
      // store the driver-specific settings
        if (aDriverSettings != null)
        {
            Object xSettingsSet = xDataSourceProperties.getPropertyValue("DataSourceSettings");
            storeSettings( xSettingsSet, aDriverSettings);
        }

      // save the data and dispose the view
        // recover the view root
        Object xViewRoot = getViewRoot(xDataSource);

        // commit the changes
        XChangesBatch xUpdateControl = 
            (XChangesBatch) UnoRuntime.queryInterface(XChangesBatch.class,xViewRoot);
        
        xUpdateControl.commitChanges();

        // now clean up
        ((XComponent) UnoRuntime.queryInterface(XComponent.class, xViewRoot)).dispose();
    }

    /** This method gets the DataSourceDescription for a data source.
        It either gets the existing entry or creates a new instance.
    */
    Object createDataSourceDescription(XMultiServiceFactory xProvider, String sDataSourceName )
		throws com.sun.star.uno.Exception
    {
        // The service name: Need an update access:
        final String cUpdatableView = "com.sun.star.configuration.ConfigurationUpdateAccess";

         // The path to the DataSources set node 
        final String cDataSourcesPath = "/org.openoffice.Office.DataAccess/DataSources";

       // creation arguments: nodepath   
        com.sun.star.beans.PropertyValue aPathArgument = new com.sun.star.beans.PropertyValue();
        aPathArgument.Name = "nodepath";
        aPathArgument.Value = cDataSourcesPath ;

        Object[] aArguments = new Object[1];
        aArguments[0] = aPathArgument;

        // create the view
        Object xViewRoot = 
            xProvider.createInstanceWithArguments(cUpdatableView, aArguments);

        XNameAccess xSetOfDataSources =
            (XNameAccess) UnoRuntime.queryInterface(XNameAccess.class,xViewRoot);

        Object xDataSourceDescriptor = null; // the result
        if ( xSetOfDataSources .hasByName( sDataSourceName ))
        {
            // the element is there
            try 
            {
                // the view should point to the element directly, so we need to extend the path
                XHierarchicalName xComposePath = (XHierarchicalName)
                    UnoRuntime.queryInterface(XHierarchicalName.class, xSetOfDataSources );
            
                String sElementPath = xComposePath.composeHierarchicalName( sDataSourceName );

                // use the name of the element now
                aPathArgument.Value = sElementPath;

                // create another view now
                Object[] aDeepArguments = new Object[1];
                aDeepArguments[0] = aPathArgument;

                // create the view
                xDataSourceDescriptor  = 
                      xProvider.createInstanceWithArguments(cUpdatableView, aDeepArguments);

                if ( xDataSourceDescriptor != null) // all went fine 
                {
                    // dispose the other view
                    ((XComponent)UnoRuntime.queryInterface(XComponent.class, xViewRoot)).dispose();
                    xViewRoot = null;
                }
            }
            catch (Exception e) 
            {
              // something went wrong, we retry with a new element 
               System.err.println("WARNING: An exception occurred while creating a view for an existing data source: " + e);
               xDataSourceDescriptor  = null;
            }
        }

        // do we have a result element yet ?
        if ( xDataSourceDescriptor == null)
        {
            // get the container 
            XNameContainer xSetUpdate = 
                (XNameContainer)UnoRuntime.queryInterface(XNameContainer.class, xViewRoot);

            // create a new detached set element (instance of DataSourceDescription)
            XSingleServiceFactory xElementFactory =
                (XSingleServiceFactory)UnoRuntime.queryInterface(XSingleServiceFactory.class, xSetUpdate);

            // the new element is the result !
             xDataSourceDescriptor  = xElementFactory.createInstance();

            // insert it - this also names the element 
            xSetUpdate.insertByName( sDataSourceName ,  xDataSourceDescriptor  );
        }

        return xDataSourceDescriptor ;
    }

    /// this method stores a number of settings in a set node containing DataSourceSetting objects
    void storeSettings(Object xSettingsSet, com.sun.star.beans.NamedValue [] aSettings )
		throws com.sun.star.uno.Exception
    {
        if (aSettings == null) 
            return;

        // get the settings set as a container
        XNameContainer xSettingsContainer = 
            (XNameContainer) UnoRuntime.queryInterface( XNameContainer.class, xSettingsSet);

        // and get a factory interface for creating the entries
        XSingleServiceFactory xSettingsFactory = 
            (XSingleServiceFactory) UnoRuntime.queryInterface(XSingleServiceFactory.class, xSettingsSet);

        // now insert the individual settings
        for (int i = 0; i < aSettings.length; ++i) {
            // create a DataSourceSetting object
            XPropertySet xSetting = (XPropertySet) 
                UnoRuntime.queryInterface( XPropertySet.class, xSettingsFactory.createInstance() );

            // can set the value before inserting
            xSetting.setPropertyValue( "Value", aSettings[i].Value );

            // and now insert or replace as appropriate
            if (xSettingsContainer.hasByName( aSettings[i].Name ))
                xSettingsContainer.replaceByName( aSettings[i].Name, xSetting );
            else
                xSettingsContainer.insertByName( aSettings[i].Name, xSetting );
        }
    }

// HELPER FUNCTIONS

    /// This method get the view root node given an interface to any node in the view
    public static Object getViewRoot(Object xElement)
    {
        Object xResult = xElement; 
      
        // set the result to its parent until that would be null  
        Object xParent;
        do
        {
            XChild xParentAccess =
                (XChild) UnoRuntime.queryInterface(XChild.class,xResult);

            if (xParentAccess != null)
                xParent = xParentAccess.getParent();
            else
                xParent = null;

            if (xParent != null)
                xResult = xParent;
         }
         while (xParent != null);

         return xResult;
    }

// workaround methods for unimplemented functionality

    /// WORKAROUND: does the same as xNamedItem.setName(sNewName) should do
    void renameSetItem(XNamed xNamedItem, String sNewName) 
		throws com.sun.star.uno.Exception
    {
        XChild xChildItem = (XChild) 
            UnoRuntime.queryInterface(XChild.class, xNamedItem);

        XNameContainer xParentSet = (XNameContainer) 
            UnoRuntime.queryInterface( XNameContainer.class, xChildItem.getParent() );

        String sOldName = xNamedItem.getName();

        // now rename the item
        xParentSet.removeByName(sOldName);
        xParentSet.insertByName(sNewName,xNamedItem);
    }  

    /// WORKAROUND: does the same as xChildItem.setParent( xNewParent ) should do
    void moveSetItem(XChild xChildItem, XNameContainer xNewParent) 
		throws com.sun.star.uno.Exception
    {
        XNamed xNamedItem = (XNamed) 
            UnoRuntime.queryInterface(XNamed.class, xChildItem);

        XNameContainer xOldParent = (XNameContainer) 
            UnoRuntime.queryInterface( XNameContainer.class, xChildItem.getParent() );

        String sItemName = xNamedItem.getName();

        // now rename the item
        xOldParent.removeByName(sItemName);
        xNewParent.insertByName(sItemName,xChildItem);
    }


// ------- the end -----------
}
