/**************************************************************
 * 
 * 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.
 * 
 *************************************************************/

package helper;

import com.sun.star.uno.*;
import com.sun.star.lang.*;
import com.sun.star.container.*;
import com.sun.star.beans.*;
import com.sun.star.util.*;

/**
 * This <CODE>ConfigHelper</CODE> makes it possible to access the 
 * configuration and change their content.<P>
 * <P>
 * Example: <P>
 * Listing of the <CODE>Configuration</CODE> Views.xcu:<P>
 * &lt;oor:component-data xmlns:oor=&quot;http://openoffice.org/2001/registry&quot; xmlns:xs=&quot;http://www.w3.org/2001/XMLSchema&quot; oor:name=&quot;Views&quot; oor:package=&quot;org.openoffice.Office&quot;&gt;<p>
 *   &lt;node oor:name=&quot;Windows&quot;&gt;<P>
 *       <&lt;node oor:name=&quot;SplitWindow0&quot; oor:op=&quot;replace&quot;&gt;<P>
 *           &lt;prop oor:name=&quot;Visible&quot; oor:type=&quot;xs:boolean&quot;&gt;<P>
 *                &lt;value&gt;false&lt;/value&gt;<P>
 *           &lt;/prop&gt;<P>
 *           &lt;prop oor:name=&quot;WindowState&quot; oor:type=&quot;xs:string&quot;&gt;<P>
 *               &lt;value/&gt;<P>
 *           &lt;/prop&gt;<P>
 *            &lt;node oor:name=&quot;UserData&quot;&gt;<P>
 *               &lt;prop oor:name=&quot;UserItem&quot; oor:op=&quot;replace&quot;
 *                oor:type=&quot;xs:string&quot;&gt;<P>
 *                   &lt;value&gt;V1,2,0&lt;/value&gt;<P>
 *               &lt;/prop&gt;<P>
 *           &lt;/node&gt;<P>
 *        &lt;/node&gt;<P>
 *  &lt;/node&gt;<P>
 * <P>
 * <CODE>Definition</CODE><P>
 * <ul>
 *    <li><CODE>&lt;node oor:name=&quot;Windows&quot;&gt;</CODE> 
 *        represents a <CODE>Set</CODE> and is a <CODE>XNameContainer</CODE></LI>
 *    <li><CODE>&lt;node oor:name=&quot;SplitWindow0&quot;&gt;</CODE> 
 *        represents a <CODE>Group</CODE> and is a <CODE>XNameReplace</CODE></LI>
 *    <li><CODE>&lt;prop oor:name=&quot;Visible&quot;&gt;</CODE> 
 *        represents a pr<CODE></CODE>operty of the group</li>
 *    <li><CODE>&lt;node oor:name=&quot;UserData&quot;&gt;</CODE> 
 *        represents a <CODE>extensible group</CODE> and is a <CODE>XNameContainer</CODE></LI>
 *    <li><CODE>&lt;prop oor:name=&quot;UserItem&quot;&gt;</CODE> 
 *        represents a <CODE>property</CODE> of the extensible group</LI>
 * </UL>
 * We assume in the following examples the existence of:<P>
 * <CODE>ConfigHelper aConfig = new ConfigHelper(xMSF, "org.openoffice.Office.Views", false);</CODE>
 * <ul>
 *    <li>If you like to insert a new <CODE>Group</CODE> into the <CODE>Set</CODE> "Windows":<p>
 *        <CODE>XNameReplace xMyGroup = aConfig.getOrInsertGroup("Windows", "myGroup");</CODE><P>
 *        The method <CODE>getOrInsertGroup()</CODE> uses the 
 *        <CODE>XSingleServiceFactory</CODE> to create the skeleton of a new group.
 *        
 *    </li>
 *    <li>If you like to change the property "WindowState" of "myGroup"
 *        of the Set "Windows"<p>
 *        <CODE>aConfig.updateGroupProperty(
 *          "Windows","myGroup", "WindowState", "952,180,244,349;1;0,0,0,0;");</CODE>
 *    </li>
 *    <li>If you like to change the property "myProp" of the extensible group
 *        "myExtGroup" which is an extensible group of "my2ndGroup" of the 
 *        Set "Windows":<p>
 *        <CODE>aConfig.insertOrUpdateExtensibleGroupProperty(
 *              "Windows", "my2ndGroup", "myExtGroup", "myProp","TheValue");</CODE>
 *    </li>
 * </ul>
 */
public class ConfigHelper
{
    private XMultiServiceFactory m_xSMGR = null;
    private XHierarchicalNameAccess m_xConfig = null;

    //-----------------------------------------------
    public ConfigHelper(XMultiServiceFactory xSMGR       ,
                        String               sConfigPath ,
                        boolean              bReadOnly   )
        throws com.sun.star.uno.Exception
    {
        m_xSMGR = xSMGR;

        XMultiServiceFactory xConfigRoot = (XMultiServiceFactory)
                        UnoRuntime.queryInterface(
                        XMultiServiceFactory.class,
                        m_xSMGR.createInstance(
                        "com.sun.star.configuration.ConfigurationProvider"));

        PropertyValue[] lParams = new PropertyValue[1];
        lParams[0] = new PropertyValue();
        lParams[0].Name  = "nodepath";
        lParams[0].Value = sConfigPath;

        Object aConfig;
        if (bReadOnly)
            aConfig = xConfigRoot.createInstanceWithArguments(
                            "com.sun.star.configuration.ConfigurationAccess",
                            lParams);
        else
            aConfig = xConfigRoot.createInstanceWithArguments(
                            "com.sun.star.configuration.ConfigurationUpdateAccess",
                            lParams);

        m_xConfig = (XHierarchicalNameAccess)UnoRuntime.queryInterface(
                            XHierarchicalNameAccess.class,
                            aConfig);

        if (m_xConfig == null)
            throw new com.sun.star.uno.Exception("Could not open configuration \""+sConfigPath+"\"");
    }

    //-----------------------------------------------
    public Object readRelativeKey(String sRelPath,
                                  String sKey    )
        throws com.sun.star.container.NoSuchElementException
    {
        try
        {
            XPropertySet xPath = (XPropertySet)UnoRuntime.queryInterface(
                                    XPropertySet.class,
                                    m_xConfig.getByHierarchicalName(sRelPath));
            return xPath.getPropertyValue(sKey);
        }
        catch(com.sun.star.uno.Exception ex)
        {
            throw new com.sun.star.container.NoSuchElementException(ex.getMessage());
        }
    }

    //-----------------------------------------------
    public void writeRelativeKey(String sRelPath,
                                 String sKey    ,
                                 Object aValue  )
        throws com.sun.star.container.NoSuchElementException
    {
        try
        {
            XPropertySet xPath = (XPropertySet)UnoRuntime.queryInterface(
                                    XPropertySet.class,
                                    m_xConfig.getByHierarchicalName(sRelPath));
            xPath.setPropertyValue(sKey, aValue);
        }
        catch(com.sun.star.uno.Exception ex)
        {
            throw new com.sun.star.container.NoSuchElementException(ex.getMessage());
        }
    }

    //-----------------------------------------------
    /**
     * Updates the configuration.<p>
     * This must be called after you have changed the configuration 
     * else you changes will be lost.
     */
    public void flush()
    {
        try
        {
            XChangesBatch xBatch = (XChangesBatch)UnoRuntime.queryInterface(
                                        XChangesBatch.class,
                                        m_xConfig);
            xBatch.commitChanges();
        }
        catch(com.sun.star.uno.Exception ex)
        {}
    }

    //-----------------------------------------------
    public static Object readDirectKey(XMultiServiceFactory xSMGR      ,
                                       String               sConfigFile,
                                       String               sRelPath   ,
                                       String               sKey       )
        throws com.sun.star.uno.Exception
    {
        ConfigHelper aConfig = new ConfigHelper(xSMGR, sConfigFile, true);
        return aConfig.readRelativeKey(sRelPath, sKey);
    }

    //-----------------------------------------------
    public static void writeDirectKey(XMultiServiceFactory xSMGR      ,
                                      String               sConfigFile,
                                      String               sRelPath   ,
                                      String               sKey       ,
                                      Object               aValue     )
        throws com.sun.star.uno.Exception
    {
        ConfigHelper aConfig = new ConfigHelper(xSMGR, sConfigFile, false);
        aConfig.writeRelativeKey(sRelPath, sKey, aValue);
        aConfig.flush();
    }
    
    
    /**
     * Insert a structured node (group) in a name container (set) 
     * or else update it and retrun the <CODE>XNameReplace</CODE> of it.<P>
     * The <CODE>XSingleServiceFacttory</CODE> of the <CODE>set</CODE> will be used
     * to create a new group. This group is specific to its set and
     * creates defined entries.
     * @return The [inserted] group of the set
     * @param groupName The name of the goup which should be returned
     * @param setName The name of the set
     * @throws com.sun.star.uno.Exception throws 
     *         <CODE>com.sun.star.uno.Exeception</CODE> on any error.
     */
    public XNameReplace getOrInsertGroup(String setName, String groupName) 
        throws  com.sun.star.uno.Exception
                
    {
        XNameContainer xSetCont = this.getSet(setName);
        
        XNameReplace xChildAccess = null;

        try {
            Object xChild=xSetCont.getByName(groupName);
            xChildAccess = (XNameReplace) UnoRuntime.queryInterface(
                            XNameReplace.class,xSetCont);
        } catch(com.sun.star.container.NoSuchElementException e) {
             // proceed with inserting
        }
        
        if (xChildAccess == null)  {
            XSingleServiceFactory xChildfactory = (XSingleServiceFactory) 
                UnoRuntime.queryInterface(XSingleServiceFactory.class,xSetCont);

            Object xNewChild = xChildfactory.createInstance();

            xSetCont.insertByName(groupName, xNewChild);

            xChildAccess = (XNameReplace) 
                UnoRuntime.queryInterface(XNameContainer.class,xNewChild);   
       }
        
        return xChildAccess;
    }

     /**
     * Update a property of a group container of a set container
     * @param setName the name of the <CODE>set</CODE> which contains the <CODE>group</CODE>
     * @param groupName the name of the <CODE>group</CODE> which property should be changed
     * @param propName the name of the property which should be changed
     * @param propValue the value the property should get
     * @throws com.sun.star.uno.Exception throws <CODE>com.sun.star.uno.Exeception</CODE> on any error.
     */
    public void updateGroupProperty(String setName,
                                    String groupName, 
                                    String propName, 
                                    Object propValue)
        throws  com.sun.star.uno.Exception
    {
        XNameContainer xSetCont = this.getSet(setName);
        
        XPropertySet xProp = null;
        try {
        xProp = (XPropertySet)UnoRuntime.queryInterface(
                                    XPropertySet.class,
                                    xSetCont.getByName(groupName));
        } catch (com.sun.star.container.NoSuchElementException e){
            throw new com.sun.star.uno.Exception(
                "could not get group '" + groupName + 
               "' from set '"+ setName +"':\n" + e.toString());
        }
        try{
            xProp.setPropertyValue(propName, propValue);
        } catch (com.sun.star.uno.Exception e) {
             throw new com.sun.star.uno.Exception(
                "could not set property '" + propName +
                "' from group '"+ groupName +
                "' from set '"+ setName +"':\n" + e.toString());
        }
    }   

   
    /**
     * Insert a property in an extensible group container or else update it
     * @param setName the name of the <CODE>set</CODE> which contains the <CODE>group</CODE>
     * @param group The name of the <CODE>group</CODE> which conatins the <CODE>extensible group</CODE>.
     * @param extGroup The name of the <CODE>extensible group</CODE> which 
     *                  [should] contain the property
     * @param propName The name of the property.
     * @param propValue The value of the property.
     * @throws com.sun.star.uno.Exception throws <CODE>com.sun.star.uno.Exeception</CODE> on any error.
     */
    public void insertOrUpdateExtensibleGroupProperty(
                    String setName,
                    String group,
                    String extGroup, 
                    String propName, 
                    Object propValue) 
        throws  com.sun.star.uno.Exception
    {
        XNameContainer xSetCont = this.getSet(setName);
        
        XNameReplace xGroupAccess = null;
        XNameContainer xExtGroupCont = null;

        try {
            Object xGroup=xSetCont.getByName(group);
            xGroupAccess = (XNameReplace) UnoRuntime.queryInterface(
                            XNameReplace.class,xGroup);
        } catch(com.sun.star.container.NoSuchElementException e) {
             throw new com.sun.star.uno.Exception(
                "could not get group '" + group + 
                "' from set '"+ setName +"':\n" + e.toString());
        }
        
        try {
            Object xGroup=xGroupAccess.getByName(extGroup);
            xExtGroupCont = (XNameContainer) UnoRuntime.queryInterface(
                            XNameContainer.class,xGroup);
        } catch(com.sun.star.container.NoSuchElementException e) {
             throw new com.sun.star.uno.Exception(
                "could not get extensilbe group '"+extGroup+
                "' from group '"+ group +
                "' from set '"+ setName +"':\n" + e.toString());
        }
        
        try {
            xExtGroupCont.insertByName(propName, propValue);
        }
        catch(com.sun.star.container.ElementExistException e) {
            xExtGroupCont .replaceByName(propName, propValue);
        }
        
    }
    
    
    /**
     * Returns a <CODE>XNameContainer</CODE> of the <CODE>Set</CODE>
     * of the <CODE>Configuration</CODE>
     * @param setName the name of the Set which sould be returned
     * @throws com.sun.star.uno.Exception on any error
     * @return A XNameContainer of the Set
     */
    public XNameContainer getSet(String setName)
        throws com.sun.star.uno.Exception
    {
        XNameReplace xCont = (XNameReplace) 
                    UnoRuntime.queryInterface(XNameReplace.class, m_xConfig);

        Object oSet = xCont.getByName(setName);
        
        if (oSet == null)
             throw new com.sun.star.uno.Exception(
                "could not get set '" + setName + ": null");
            
        return (XNameContainer) UnoRuntime.queryInterface(
                                                XNameContainer.class, oSet);
        
    }
}
