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



class ExampleAddInResult implements com.sun.star.sheet.XVolatileResult
{
    private String aName;
    private int nValue;
    private java.util.Vector aListeners = new java.util.Vector();

    public ExampleAddInResult( String aNewName )
    {
        aName = aNewName;
    }

    private com.sun.star.sheet.ResultEvent getResult()
    {
        com.sun.star.sheet.ResultEvent aEvent =
            new com.sun.star.sheet.ResultEvent();
        aEvent.Value = aName + " " + String.valueOf( nValue );
        aEvent.Source = this;
        return aEvent;
    }

    public void addResultListener(com.sun.star.sheet.XResultListener aListener)
    {
        aListeners.addElement( aListener );

        // immediately notify of initial value
        aListener.modified( getResult() );
    }

    public void removeResultListener(com.sun.star.sheet.XResultListener aListener)
    {
        aListeners.removeElement( aListener );
    }

    public void incrementValue()
    {
        ++nValue;
        com.sun.star.sheet.ResultEvent aEvent = getResult();

        java.util.Enumeration aEnum = aListeners.elements();
        while (aEnum.hasMoreElements())
            ((com.sun.star.sheet.XResultListener)aEnum.nextElement()).modified(
                aEvent);
    }
}

class ExampleAddInThread extends Thread
{
    private java.util.Hashtable aCounters;

    public ExampleAddInThread( java.util.Hashtable aResults )
    {
        aCounters = aResults;
    }

    public void run()
    {
        while ( true )
        {
            try
            {
                sleep(1000);
            }
            catch( InterruptedException exception )
            {
            }

            // increment all counters
            java.util.Enumeration aEnum = aCounters.elements();
            while (aEnum.hasMoreElements())
                ((ExampleAddInResult)aEnum.nextElement()).incrementValue();
        }
    }
}

public class ExampleAddIn
{
    static public class _ExampleAddIn extends com.sun.star.lib.uno.helper.WeakBase
           implements org.openoffice.sheet.addin.XExampleAddIn,
                      com.sun.star.sheet.XAddIn,
                      com.sun.star.lang.XServiceName,
                      com.sun.star.lang.XServiceInfo
    {
        static private final String aExampleService = "org.openoffice.sheet.addin.ExampleAddIn";
        static private final String aAddInService = "com.sun.star.sheet.AddIn";
        static private final String aImplName = _ExampleAddIn.class.getName();

        private static final short FUNCTION_INVALID   = -1;
        private static final short FUNCTION_INCREMENT = 0;
        private static final short FUNCTION_COUNTER   = 1;

        private static final String[] aFunctionNames =
        {
            "getIncremented",
            "getCounter"
        };
        private static final String[] aDisplayFunctionNames =
        {
            "Increment",
            "Counter"
        };
        private static final String[] aDescriptions =
        {
            "Increments a value",
            "Returns a counter"
        };
        private static final String[] aFirstArgumentNames =
        {
            "Value",
            "Name"
        };
        private static final String[] aFirstArgumentDescriptions =
        {
            "The value that is incremented",
            "The name of the counter"
        };

        private com.sun.star.lang.Locale aFuncLocale;
        private java.util.Hashtable aResults;

        public _ExampleAddIn( com.sun.star.lang.XMultiServiceFactory xFactory )
        {
        }

        private int getFunctionID( String aProgrammaticFunctionName )
        {
            for ( int i = 0; i < aFunctionNames.length; i++ )
                if ( aProgrammaticFunctionName.equals(aFunctionNames[i]) )
                    return i;
            return FUNCTION_INVALID;
        }

        //  XExampleAddIn

        public int getIncremented( int nValue )
        {
            return nValue + 1;
        }

        public com.sun.star.sheet.XVolatileResult getCounter(String aName)
        {
            if ( aResults == null )
            {
                // create the table of results, and start a thread to increment
                // all counters
                aResults = new java.util.Hashtable();
                ExampleAddInThread aThread = new ExampleAddInThread( aResults );
                aThread.start();
            }

            ExampleAddInResult aResult = (ExampleAddInResult) aResults.get(aName);
            if ( aResult == null )
            {
                aResult = new ExampleAddInResult(aName);
                aResults.put( aName, aResult );
            }
            return aResult;
        }

        //  XAddIn

        public String getProgrammaticFuntionName(String aDisplayName)
        {
            for ( int i = 0; i < aFunctionNames.length; i++ )
                if ( aDisplayName.equals(aDisplayFunctionNames[i]) )
                    return aFunctionNames[i];
            return "";
        }

        public String getDisplayFunctionName(String aProgrammaticName)
        {
            int nFunction = getFunctionID( aProgrammaticName );
            return ( nFunction == FUNCTION_INVALID ) ? "" :
                aDisplayFunctionNames[nFunction];
        }

        public String getFunctionDescription(String aProgrammaticName)
        {
            int nFunction = getFunctionID( aProgrammaticName );
            return ( nFunction == FUNCTION_INVALID ) ? "" :
                aDescriptions[nFunction];
        }

        public String getDisplayArgumentName(String aProgrammaticFunctionName,
                                             int nArgument)
        {
            //  both functions in this example only have a first argument
            int nFunction = getFunctionID( aProgrammaticFunctionName );
            return ( nFunction == FUNCTION_INVALID || nArgument != 0) ? "" :
                aFirstArgumentNames[nFunction];
        }

        public String getArgumentDescription(String aProgrammaticFunctionName,
                                             int nArgument )
        {
            //  both functions in this example only have a first argument
            int nFunction = getFunctionID( aProgrammaticFunctionName );
            return ( nFunction == FUNCTION_INVALID || nArgument != 0) ? "" :
                aFirstArgumentDescriptions[nFunction];
        }

        public String getProgrammaticCategoryName(String aProgrammaticFunctionName)
        {
            return( "Add-In" );
        }

        public String getDisplayCategoryName(String aProgrammaticFunctionName)
        {
            return( "Add-In" );
        }

        //  XLocalizable

        public void setLocale( com.sun.star.lang.Locale aLocale )
        {
            // the locale is stored and used for getLocale, but otherwise
            // ignored in this example
            aFuncLocale = aLocale;
        }
        
        public com.sun.star.lang.Locale getLocale()
        {
            return aFuncLocale;
        }       

        //  XServiceName

        public String getServiceName()
        {
            return aExampleService;
        }

        //  XServiceInfo

        public String getImplementationName()
        {
            return aImplName;
        }

        public String[] getSupportedServiceNames()
        {
            String [] aSupportedServices = new String[ 2 ];
            aSupportedServices[ 0 ] = aExampleService;
            aSupportedServices[ 1 ] = aAddInService;
            return aSupportedServices;
        }

        public boolean supportsService( String aService )
        {
            return (aService.equals( aExampleService ) ||
                    aService.equals( aAddInService ) );
        }

    }


    public static com.sun.star.lang.XSingleServiceFactory __getServiceFactory(
        String implName,
        com.sun.star.lang.XMultiServiceFactory multiFactory,
        com.sun.star.registry.XRegistryKey regKey)
    {
        com.sun.star.lang.XSingleServiceFactory xSingleServiceFactory = null;
        if ( implName.equals(_ExampleAddIn.aImplName) )
            xSingleServiceFactory =
                com.sun.star.comp.loader.FactoryHelper.getServiceFactory(
                    _ExampleAddIn.class, _ExampleAddIn.aExampleService,
                    multiFactory, regKey);
        return xSingleServiceFactory;
    }
    
    // This method not longer necessary since OOo 3.4 where the component registration
    // was changed to passive component registration. For more details see
    // http://wiki.services.openoffice.org/wiki/Passive_Component_Registration

//     public static boolean __writeRegistryServiceInfo(
//         com.sun.star.registry.XRegistryKey regKey)
//     {
//         //  register for both the base AddIn and the own service
//         return com.sun.star.comp.loader.FactoryHelper.writeRegistryServiceInfo(
//                     _ExampleAddIn.aImplName, _ExampleAddIn.aExampleService, regKey)
//             && com.sun.star.comp.loader.FactoryHelper.writeRegistryServiceInfo(
//                     _ExampleAddIn.aImplName, _ExampleAddIn.aAddInService, regKey);
//     }
}

