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



//  Example DataPilot source component

//  helper class to hold the settings

class ExampleSettings
{
    static public final int nDimensionCount = 6;
    static public final int nValueDimension = 4;
    static public final int nDataDimension = 5;
    static public final String [] aDimensionNames = {
        "ones", "tens", "hundreds", "thousands", "value", "" };

    static public final String getMemberName( int nMember )
    {
        return String.valueOf( nMember );
    }

    public int nMemberCount = 3;
    public java.util.List aColDimensions = new java.util.ArrayList();
    public java.util.List aRowDimensions = new java.util.ArrayList();
}

//  XPropertySetInfo implementation for getPropertySetInfo

class ExamplePropertySetInfo implements com.sun.star.beans.XPropertySetInfo
{
    private com.sun.star.beans.Property[] aProperties;

    public ExamplePropertySetInfo( com.sun.star.beans.Property[] aProps )
    {
        aProperties = aProps;
    }

    public com.sun.star.beans.Property[] getProperties()
    {
        return aProperties;
    }

    public com.sun.star.beans.Property getPropertyByName( String aName )
                    throws com.sun.star.beans.UnknownPropertyException
    {
        for ( int i=0; i<aProperties.length; i++ )
            if ( aProperties[i].Name.equals( aName ) )
                return aProperties[i];
        throw new com.sun.star.beans.UnknownPropertyException();
    }

    public boolean hasPropertyByName( String aName )
    {
        for ( int i=0; i<aProperties.length; i++ )
            if ( aProperties[i].Name.equals( aName ) )
                return true;
        return false;
    }
}

//  implementation of com.sun.star.sheet.DataPilotSourceMember

class ExampleMember implements com.sun.star.container.XNamed,
      com.sun.star.beans.XPropertySet
{
    private ExampleSettings aSettings;
    private int nDimension;
    private int nMember;

    public ExampleMember( ExampleSettings aSet, int nDim, int nMbr )
    {
        aSettings = aSet;
        nDimension = nDim;
        nMember = nMbr;
    }

    //  XNamed

    public String getName()
    {
        return ExampleSettings.getMemberName( nMember );
    }

    public void setName( String aName )
    {
        // ignored
    }

    //  XPropertySet

    public com.sun.star.beans.XPropertySetInfo getPropertySetInfo()
    {
        return new ExamplePropertySetInfo( new com.sun.star.beans.Property[] {
            new com.sun.star.beans.Property( "IsVisible",   -1,
                        new com.sun.star.uno.Type( Boolean.class ), (short) 0),
            new com.sun.star.beans.Property( "ShowDetails", -1,
                        new com.sun.star.uno.Type( Boolean.class ), (short) 0) });
    }

    public void setPropertyValue( String aPropertyName, Object aValue )
        throws com.sun.star.beans.UnknownPropertyException
    {
        if ( aPropertyName.equals( "IsVisible" ) ||
             aPropertyName.equals( "ShowDetails" ) )
        {
            // ignored
        }
        else
            throw new com.sun.star.beans.UnknownPropertyException();
    }

    public Object getPropertyValue( String aPropertyName )
        throws com.sun.star.beans.UnknownPropertyException
    {
        if ( aPropertyName.equals( "IsVisible" ) ||
             aPropertyName.equals( "ShowDetails" ) )
        {
            return new Boolean( true );     // always true
        }
        else
            throw new com.sun.star.beans.UnknownPropertyException();
    }

    public void addPropertyChangeListener(
        String aPropertyName, com.sun.star.beans.XPropertyChangeListener xListener)
    {
    }
    public void removePropertyChangeListener(
        String aPropertyName, com.sun.star.beans.XPropertyChangeListener aListener)
    {
    }
    public void addVetoableChangeListener(
        String PropertyName, com.sun.star.beans.XVetoableChangeListener aListener)
    {
    }
    public void removeVetoableChangeListener(
        String PropertyName, com.sun.star.beans.XVetoableChangeListener aListener)
    {
    }
}

//  implementation of com.sun.star.sheet.DataPilotSourceMembers

class ExampleMembers implements com.sun.star.container.XNameAccess
{
    private ExampleSettings aSettings;
    private int nDimension;
    private ExampleMember[] aMembers;

    public ExampleMembers( ExampleSettings aSet, int nDim )
    {
        aSettings = aSet;
        nDimension = nDim;
        aMembers = new ExampleMember[ aSettings.nMemberCount ];
    }

    //  XNameAccess

    public com.sun.star.uno.Type getElementType()
    {
        return new com.sun.star.uno.Type( com.sun.star.container.XNamed.class );
    }

    public boolean hasElements()
    {
        return true;    // always has elements
    }

    public Object getByName( String aName )
        throws com.sun.star.container.NoSuchElementException
    {
        int nCount = aSettings.nMemberCount;
        for ( int i=0; i<nCount; i++ )
            if ( aName.equals( ExampleSettings.getMemberName( i ) ) )
            {
                if ( aMembers[i] == null )
                    aMembers[i] = new ExampleMember( aSettings, nDimension, i );
                return aMembers[i];
            }
        throw new com.sun.star.container.NoSuchElementException();
    }

    public String[] getElementNames()
    {
        int nCount = aSettings.nMemberCount;
        String [] aNames = new String[ nCount ];
        for ( int i=0; i<nCount; i++ )
            aNames[i] = ExampleSettings.getMemberName( i );
        return aNames;
    }

    public boolean hasByName( String aName )
    {
        int nCount = aSettings.nMemberCount;
        for ( int i=0; i<nCount; i++ )
            if ( aName.equals( ExampleSettings.getMemberName( i ) ) )
                return true;
        return false;
    }
}

//  implementation of com.sun.star.sheet.DataPilotSourceLevel

class ExampleLevel implements
                    com.sun.star.container.XNamed,
                    com.sun.star.sheet.XMembersSupplier,
                    com.sun.star.sheet.XDataPilotMemberResults,
                    com.sun.star.beans.XPropertySet
{
    private ExampleSettings aSettings;
    private int nDimension;
    private ExampleMembers aMembers;

    public ExampleLevel( ExampleSettings aSet, int nDim )
    {
        aSettings = aSet;
        nDimension = nDim;
    }

    // XNamed

    public String getName()
    {
        return ExampleSettings.aDimensionNames[ nDimension ];
    }

    public void setName( String aName )
    {
        // ignored
    }

    // XMembersSupplier

    public com.sun.star.container.XNameAccess getMembers()
    {
        if ( aMembers == null )
            aMembers = new ExampleMembers( aSettings, nDimension );
        return aMembers;
    }

    // XDataPilotMemberResults

    public com.sun.star.sheet.MemberResult[] getResults()
    {
        int nDimensions = 0;
        int nPosition = aSettings.aColDimensions.indexOf( new Integer(nDimension));
        if ( nPosition >= 0 )
            nDimensions = aSettings.aColDimensions.size();
        else
        {
            nPosition = aSettings.aRowDimensions.indexOf( new Integer(nDimension));
            if ( nPosition >= 0 )
                nDimensions = aSettings.aRowDimensions.size();
        }

        if ( nPosition < 0 )
            return new com.sun.star.sheet.MemberResult[0];

        int nMembers = aSettings.nMemberCount;
        int nRepeat = 1;
        int nFill = 1;
        for ( int i=0; i<nDimensions; i++ )
        {
            if ( i < nPosition )
                nRepeat *= nMembers;
            else if ( i > nPosition )
                nFill *= nMembers;
        }
        int nSize = nRepeat * nMembers * nFill;

        com.sun.star.sheet.MemberResult[] aResults =
            new com.sun.star.sheet.MemberResult[nSize];
        int nResultPos = 0;
        for (int nOuter=0; nOuter<nRepeat; nOuter++)
        {
            for (int nMember=0; nMember<nMembers; nMember++)
            {
                aResults[nResultPos] = new com.sun.star.sheet.MemberResult();
                aResults[nResultPos].Name = ExampleSettings.getMemberName(nMember);
                aResults[nResultPos].Caption = aResults[nResultPos].Name;
                aResults[nResultPos].Flags =
                    com.sun.star.sheet.MemberResultFlags.HASMEMBER;                
                ++nResultPos;

                for (int nInner=1; nInner<nFill; nInner++)
                {
                    aResults[nResultPos] = new com.sun.star.sheet.MemberResult();
                    aResults[nResultPos].Flags =
                        com.sun.star.sheet.MemberResultFlags.CONTINUE;
                    ++nResultPos;
                }
            }
        }
        return aResults;
    }
    
    //  XPropertySet

    public com.sun.star.beans.XPropertySetInfo getPropertySetInfo()
    {
        return new ExamplePropertySetInfo( new com.sun.star.beans.Property[] {
            new com.sun.star.beans.Property( "SubTotals", -1,
                            new com.sun.star.uno.Type(
                                com.sun.star.sheet.GeneralFunction[].class ),
                                             (short) 0 ),
            new com.sun.star.beans.Property( "ShowEmpty", -1,
                             new com.sun.star.uno.Type( Boolean.class ),
                                             (short) 0 ) } );
    }

    public void setPropertyValue( String aPropertyName, Object aValue )
        throws com.sun.star.beans.UnknownPropertyException
    {
        if ( aPropertyName.equals( "SubTotals" ) ||
             aPropertyName.equals( "ShowEmpty" ) )
        {
            // ignored
        }
        else
            throw new com.sun.star.beans.UnknownPropertyException();
    }

    public Object getPropertyValue( String aPropertyName )
        throws com.sun.star.beans.UnknownPropertyException
    {
        if ( aPropertyName.equals( "SubTotals" ) )
            return new com.sun.star.sheet.GeneralFunction[0];
        else if ( aPropertyName.equals( "ShowEmpty" ) )
            return new Boolean( true );
        else
            throw new com.sun.star.beans.UnknownPropertyException();
    }

    public void addPropertyChangeListener(
        String aPropertyName, com.sun.star.beans.XPropertyChangeListener xListener)
    {
    }
    public void removePropertyChangeListener(
        String aPropertyName, com.sun.star.beans.XPropertyChangeListener aListener)
    {
    }
    public void addVetoableChangeListener(
        String PropertyName, com.sun.star.beans.XVetoableChangeListener aListener)
    {
    }
    public void removeVetoableChangeListener(
        String PropertyName, com.sun.star.beans.XVetoableChangeListener aListener)
    {
    }
}

//  implementation of com.sun.star.sheet.DataPilotSourceLevels

class ExampleLevels implements com.sun.star.container.XNameAccess
{
    private ExampleSettings aSettings;
    private int nDimension;
    private ExampleLevel aLevel;

    public ExampleLevels( ExampleSettings aSet, int nDim )
    {
        aSettings = aSet;
        nDimension = nDim;
    }

    // XNameAccess

    public com.sun.star.uno.Type getElementType()
    {
        return new com.sun.star.uno.Type( com.sun.star.container.XNamed.class );
    }

    public boolean hasElements()
    {
        return true;    // always has elements
    }

    public Object getByName( String aName )
        throws com.sun.star.container.NoSuchElementException
    {
        //  there's only one level with the same name as the dimension / hierarchy
        if ( aName.equals( ExampleSettings.aDimensionNames[nDimension] ) )
        {
            if ( aLevel == null )
                aLevel = new ExampleLevel( aSettings, nDimension );
            return aLevel;
        }
        throw new com.sun.star.container.NoSuchElementException();
    }

    public String[] getElementNames()
    {
        String [] aNames = new String[ 1 ];
        aNames[0] = ExampleSettings.aDimensionNames[nDimension];
        return aNames;
    }

    public boolean hasByName( String aName )
    {
        return aName.equals( ExampleSettings.aDimensionNames[nDimension] );
    }
}

//  implementation of com.sun.star.sheet.DataPilotSourceHierarchy

class ExampleHierarchy implements com.sun.star.container.XNamed,
      com.sun.star.sheet.XLevelsSupplier
{
    private ExampleSettings aSettings;
    private int nDimension;
    private ExampleLevels aLevels;

    public ExampleHierarchy( ExampleSettings aSet, int nDim )
    {
        aSettings = aSet;
        nDimension = nDim;
    }

    // XNamed

    public String getName()
    {
        return ExampleSettings.aDimensionNames[ nDimension ];
    }

    public void setName( String aName )
    {
        // ignored
    }

    // XLevelsSupplier

    public com.sun.star.container.XNameAccess getLevels()
    {
        if ( aLevels == null )
            aLevels = new ExampleLevels( aSettings, nDimension );
        return aLevels;
    }
}

//  implementation of com.sun.star.sheet.DataPilotSourceHierarchies

class ExampleHierarchies implements com.sun.star.container.XNameAccess
{
    private ExampleSettings aSettings;
    private int nDimension;
    private ExampleHierarchy aHierarchy;

    public ExampleHierarchies( ExampleSettings aSet, int nDim )
    {
        aSettings = aSet;
        nDimension = nDim;
    }

    //  XNameAccess

    public com.sun.star.uno.Type getElementType()
    {
        return new com.sun.star.uno.Type( com.sun.star.container.XNamed.class );
    }

    public boolean hasElements()
    {
        return true;    // always has elements
    }

    public Object getByName( String aName )
        throws com.sun.star.container.NoSuchElementException
    {
        //  there's only one hierarchy with the same name as the dimension
        if ( aName.equals( ExampleSettings.aDimensionNames[nDimension] ) )
        {
            if ( aHierarchy == null )
                aHierarchy = new ExampleHierarchy( aSettings, nDimension );
            return aHierarchy;
        }
        throw new com.sun.star.container.NoSuchElementException();
    }

    public String[] getElementNames()
    {
        String [] aNames = new String[ 1 ];
        aNames[0] = ExampleSettings.aDimensionNames[nDimension];
        return aNames;
    }

    public boolean hasByName( String aName )
    {
        return aName.equals( ExampleSettings.aDimensionNames[nDimension] );
    }
}

//  implementation of com.sun.star.sheet.DataPilotSourceDimension

class ExampleDimension implements
                    com.sun.star.container.XNamed,
                    com.sun.star.sheet.XHierarchiesSupplier,
                    com.sun.star.util.XCloneable,
                    com.sun.star.beans.XPropertySet
{
    private ExampleSettings aSettings;
    private int nDimension;
    private ExampleHierarchies aHierarchies;
    private com.sun.star.sheet.DataPilotFieldOrientation eOrientation;

    public ExampleDimension( ExampleSettings aSet, int nDim )
    {
        aSettings = aSet;
        nDimension = nDim;
        eOrientation = ( nDim == ExampleSettings.nValueDimension ) ?
            com.sun.star.sheet.DataPilotFieldOrientation.DATA :
            com.sun.star.sheet.DataPilotFieldOrientation.HIDDEN;
    }

    //  XNamed

    public String getName()
    {
        return ExampleSettings.aDimensionNames[ nDimension ];
    }

    public void setName( String aName )
    {
        // ignored
    }

    //  XHierarchiesSupplier

    public com.sun.star.container.XNameAccess getHierarchies()
    {
        if ( aHierarchies == null )
            aHierarchies = new ExampleHierarchies( aSettings, nDimension );
        return aHierarchies;
    }

    //  XCloneable

    public com.sun.star.util.XCloneable createClone()
    {
        return null;        // not supported
    }

    //  XPropertySet

    public com.sun.star.beans.XPropertySetInfo getPropertySetInfo()
    {
        return new ExamplePropertySetInfo( new com.sun.star.beans.Property[] {
            new com.sun.star.beans.Property( "Original", -1,
                new com.sun.star.uno.Type( com.sun.star.container.XNamed.class),
                (short) com.sun.star.beans.PropertyAttribute.READONLY ),
            new com.sun.star.beans.Property( "IsDataLayoutDimension", -1,
                new com.sun.star.uno.Type( Boolean.class),
                (short) com.sun.star.beans.PropertyAttribute.READONLY ),
            new com.sun.star.beans.Property( "Orientation", -1,
                new com.sun.star.uno.Type(
                  com.sun.star.sheet.DataPilotFieldOrientation.class), (short) 0),
            new com.sun.star.beans.Property( "Position", -1,
                new com.sun.star.uno.Type( Integer.class ), (short) 0),
            new com.sun.star.beans.Property( "Function", -1,
                new com.sun.star.uno.Type(com.sun.star.sheet.GeneralFunction.class),
                                             (short) 0 ),
            new com.sun.star.beans.Property( "UsedHierarchy", -1,
                new com.sun.star.uno.Type( Integer.class ), (short) 0 ),
            new com.sun.star.beans.Property( "Filter", -1,
                new com.sun.star.uno.Type(
                    com.sun.star.sheet.TableFilterField[].class), (short) 0) });
    }

    public void setPropertyValue( String aPropertyName, Object aValue )
                    throws com.sun.star.beans.UnknownPropertyException
    {
        if ( aPropertyName.equals( "Orientation" ) )
        {
            com.sun.star.sheet.DataPilotFieldOrientation eNewOrient =
                        (com.sun.star.sheet.DataPilotFieldOrientation) aValue;
            if ( nDimension != ExampleSettings.nValueDimension &&
                 nDimension != ExampleSettings.nDataDimension &&
                 eNewOrient != com.sun.star.sheet.DataPilotFieldOrientation.DATA )
            {
                // remove from list for old orientation and add for new one
                Integer aDimInt = new Integer(nDimension);
                if ( eOrientation == com.sun.star.sheet.DataPilotFieldOrientation.COLUMN )
                    aSettings.aColDimensions.remove( aDimInt );
                else if ( eOrientation == com.sun.star.sheet.DataPilotFieldOrientation.ROW )
                    aSettings.aRowDimensions.remove( aDimInt );
                if ( eNewOrient == com.sun.star.sheet.DataPilotFieldOrientation.COLUMN )
                    aSettings.aColDimensions.add( aDimInt );
                else if ( eNewOrient == com.sun.star.sheet.DataPilotFieldOrientation.ROW )
                    aSettings.aRowDimensions.add( aDimInt );

                // change orientation
                eOrientation = eNewOrient;
            }
        }
        else if ( aPropertyName.equals( "Position" ) )
        {
            int nNewPos = ((Integer) aValue).intValue();
            Integer aDimInt = new Integer(nDimension);
            if ( eOrientation == com.sun.star.sheet.DataPilotFieldOrientation.COLUMN )
            {
                aSettings.aColDimensions.remove( aDimInt );
                aSettings.aColDimensions.add( nNewPos, aDimInt );
            }
            else if ( eOrientation == com.sun.star.sheet.DataPilotFieldOrientation.ROW )
            {
                aSettings.aRowDimensions.remove( aDimInt );
                aSettings.aRowDimensions.add( nNewPos, aDimInt );
            }
        }
        else if ( aPropertyName.equals( "Function" ) || aPropertyName.equals( "UsedHierarchy" ) ||
                  aPropertyName.equals( "Filter" ) )
        {
            // ignored
        }
        else
            throw new com.sun.star.beans.UnknownPropertyException();
    }

    public Object getPropertyValue( String aPropertyName )
                    throws com.sun.star.beans.UnknownPropertyException
    {
        if ( aPropertyName.equals( "Original" ) )
            return null;
        else if ( aPropertyName.equals( "IsDataLayoutDimension" ) )
            return new Boolean( nDimension == ExampleSettings.nDataDimension );
        else if ( aPropertyName.equals( "Orientation" ) )
            return eOrientation;
        else if ( aPropertyName.equals( "Position" ) )
        {
            int nPosition;
            if ( eOrientation == com.sun.star.sheet.DataPilotFieldOrientation.COLUMN )
                nPosition = aSettings.aColDimensions.indexOf( new Integer(nDimension) );
            else if ( eOrientation == com.sun.star.sheet.DataPilotFieldOrientation.ROW )
                nPosition = aSettings.aRowDimensions.indexOf( new Integer(nDimension) );
            else
                nPosition = nDimension;
            return new Integer( nPosition );
        }
        else if ( aPropertyName.equals( "Function" ) )
            return com.sun.star.sheet.GeneralFunction.SUM;
        else if ( aPropertyName.equals( "UsedHierarchy" ) )
            return new Integer(0);
        else if ( aPropertyName.equals( "Filter" ) )
            return new com.sun.star.sheet.TableFilterField[0];
        else
            throw new com.sun.star.beans.UnknownPropertyException();
    }

    public void addPropertyChangeListener(
        String aPropertyName, com.sun.star.beans.XPropertyChangeListener xListener)
    {
    }
    public void removePropertyChangeListener(
        String aPropertyName, com.sun.star.beans.XPropertyChangeListener aListener)
    {
    }
    public void addVetoableChangeListener(
        String PropertyName, com.sun.star.beans.XVetoableChangeListener aListener)
    {
    }
    public void removeVetoableChangeListener(
        String PropertyName, com.sun.star.beans.XVetoableChangeListener aListener)
    {
    }
}

//  implementation of com.sun.star.sheet.DataPilotSourceDimensions

class ExampleDimensions implements com.sun.star.container.XNameAccess
{
    private ExampleSettings aSettings;
    private ExampleDimension[] aDimensions;

    public ExampleDimensions( ExampleSettings aSet )
    {
        aSettings = aSet;
    }

    //  XNameAccess

    public com.sun.star.uno.Type getElementType()
    {
        return new com.sun.star.uno.Type( com.sun.star.container.XNamed.class );
    }

    public boolean hasElements()
    {
        return true;    // always has elements
    }

    public Object getByName( String aName )
        throws com.sun.star.container.NoSuchElementException
    {
        for (int i=0; i<ExampleSettings.nDimensionCount; i++)
            if ( aName.equals( ExampleSettings.aDimensionNames[i] ) )
            {
                if ( aDimensions == null )
                    aDimensions = new ExampleDimension[ ExampleSettings.nDimensionCount ];
                if ( aDimensions[i] == null )
                    aDimensions[i] = new ExampleDimension( aSettings, i );
                return aDimensions[i];
            }
        throw new com.sun.star.container.NoSuchElementException();
    }

    public String[] getElementNames()
    {
        String [] aNames = new String[ ExampleSettings.nDimensionCount ];
        for (int i=0; i<ExampleSettings.nDimensionCount; i++)
            aNames[ i ] = ExampleSettings.aDimensionNames[i];
        return aNames;
    }

    public boolean hasByName( String aName )
    {
        for (int i=0; i<ExampleSettings.nDimensionCount; i++)
            if ( aName.equals( ExampleSettings.aDimensionNames[i] ) )
                return true;
        return false;
    }
}

//  outer class for service implementation

public class ExampleDataPilotSource
{
    //  implementation of com.sun.star.sheet.DataPilotSource

    static public class _ExampleDataPilotSource implements
                        com.sun.star.sheet.XDimensionsSupplier,
                        com.sun.star.sheet.XDataPilotResults,
                        com.sun.star.util.XRefreshable,
                        com.sun.star.beans.XPropertySet,
                        com.sun.star.lang.XInitialization,
                        com.sun.star.lang.XServiceInfo
    {
        static private final String aServiceName = "com.sun.star.sheet.DataPilotSource";
        static private final String aImplName =  _ExampleDataPilotSource.class.getName();

        private ExampleSettings aSettings = new ExampleSettings();
        private ExampleDimensions aDimensions;

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

        //  XInitialization

        public void initialize( Object[] aArguments )
        {
            //  If the first argument (Source) is a number between 2 and 10,
            //  use it as member count, otherwise keep the default value.
            try
            {
		if ( aArguments.length >= 1 )
		{
		    String aSource = com.sun.star.uno.AnyConverter.toString(aArguments[0]);
		    if ( aSource != null && aSource.length() > 0)
		    {
			int nValue = Integer.parseInt( aSource );
			if ( nValue >= 2 && nValue <= 10 )
			    aSettings.nMemberCount = nValue;
		    }
		}
	    }
	    catch ( NumberFormatException e )
	    {
		System.out.println( "Error: caught exception in " +
				    "ExampleDataPilotSource.initialize!\nException Message = "
				    + e.getMessage());
		e.printStackTrace();
	    }
	    catch ( com.sun.star.lang.IllegalArgumentException e )
	    {
		System.out.println( "Error: caught exception in " +
				    "ExampleDataPilotSource.initialize!\nException Message = "
				    + e.getMessage());
		e.printStackTrace();
	    }
        }

        //  XDataPilotResults
        
        public com.sun.star.sheet.DataResult[][] getResults()
        {
            int[] nDigits = new int[ExampleSettings.nDimensionCount];
            int nValue = 1;
            for (int i=0; i<ExampleSettings.nDimensionCount; i++)
            {
                nDigits[i] = nValue;
                nValue *= 10;
            }

            int nMemberCount = aSettings.nMemberCount;
            int nRowDimCount = aSettings.aRowDimensions.size();
            int nColDimCount = aSettings.aColDimensions.size();

            int nRows = 1;
            for (int i=0; i<nRowDimCount; i++)
                nRows *= nMemberCount;
            int nColumns = 1;
            for (int i=0; i<nColDimCount; i++)
                nColumns *= nMemberCount;

            com.sun.star.sheet.DataResult[][] aResults = new com.sun.star.sheet.DataResult[nRows][];
            for (int nRow=0; nRow<nRows; nRow++)
            {
                int nRowVal = nRow;
                int nRowResult = 0;
                for (int nRowDim=0; nRowDim<nRowDimCount; nRowDim++)
                {
                    int nDim = ((Integer)aSettings.aRowDimensions.get(nRowDimCount-nRowDim-1)).intValue();
                    nRowResult += ( nRowVal % nMemberCount ) * nDigits[nDim];
                    nRowVal /= nMemberCount;
                }

                aResults[nRow] = new com.sun.star.sheet.DataResult[nColumns];
                for (int nCol=0; nCol<nColumns; nCol++)
                {
                    int nColVal = nCol;
                    int nResult = nRowResult;
                    for (int nColDim=0; nColDim<nColDimCount; nColDim++)
                    {
                        int nDim = ((Integer)aSettings.aColDimensions.get(nColDimCount-nColDim-1)).intValue();
                        nResult += ( nColVal % nMemberCount ) * nDigits[nDim];
                        nColVal /= nMemberCount;
                    }

                    aResults[nRow][nCol] = new com.sun.star.sheet.DataResult();
                    aResults[nRow][nCol].Flags = com.sun.star.sheet.DataResultFlags.HASDATA;
                    aResults[nRow][nCol].Value = nResult;
                }
            }
            return aResults;
        }

        //  XDimensionsSupplier

        public com.sun.star.container.XNameAccess getDimensions()
        {
            if ( aDimensions == null )
                aDimensions = new ExampleDimensions( aSettings );
            return aDimensions;
        }

        //  XPropertySet

        public com.sun.star.beans.XPropertySetInfo getPropertySetInfo()
        {
            return new ExamplePropertySetInfo( new com.sun.star.beans.Property[] {
                new com.sun.star.beans.Property( "ColumnGrand", -1,
                       new com.sun.star.uno.Type( Boolean.class ), (short) 0),
                new com.sun.star.beans.Property( "RowGrand", -1,
                       new com.sun.star.uno.Type( Boolean.class ), (short) 0) });
        }

        public void setPropertyValue( String aPropertyName, Object aValue )
            throws com.sun.star.beans.UnknownPropertyException
        {
            if ( aPropertyName.equals( "ColumnGrand" ) ||
                 aPropertyName.equals( "RowGrand" ) )
            {
                // ignored
            }
            else
                throw new com.sun.star.beans.UnknownPropertyException();
        }

        public Object getPropertyValue( String aPropertyName )
            throws com.sun.star.beans.UnknownPropertyException
        {
            if ( aPropertyName.equals( "ColumnGrand" ) ||
                 aPropertyName.equals( "RowGrand" ) )
            {
                return new Boolean( false );        // always false
            }
            else
                throw new com.sun.star.beans.UnknownPropertyException();
        }

        public void addPropertyChangeListener(
            String aPropertyName,
            com.sun.star.beans.XPropertyChangeListener xListener )
        {
        }
        public void removePropertyChangeListener(
            String aPropertyName,
            com.sun.star.beans.XPropertyChangeListener aListener )
        {
        }
        public void addVetoableChangeListener(
            String PropertyName,
            com.sun.star.beans.XVetoableChangeListener aListener )
        {
        }
        public void removeVetoableChangeListener(
            String PropertyName,
            com.sun.star.beans.XVetoableChangeListener aListener )
        {
        }

        //  XRefreshable

        public void refresh()
        {
        }
        public void addRefreshListener( com.sun.star.util.XRefreshListener l )
        {
        }
        public void removeRefreshListener( com.sun.star.util.XRefreshListener l )
        {
        }

        //  XServiceInfo

        public String getImplementationName()
        {
            return aImplName;
        }

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

        public boolean supportsService( String aService )
        {
            return aService.equals( aServiceName );
        }
    }

    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(_ExampleDataPilotSource.aImplName) )
            xSingleServiceFactory =
                com.sun.star.comp.loader.FactoryHelper.getServiceFactory(
                    _ExampleDataPilotSource.class,
                    _ExampleDataPilotSource.aServiceName, 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)
//     {
//         return com.sun.star.comp.loader.FactoryHelper.writeRegistryServiceInfo(
//                     _ExampleDataPilotSource.aImplName,
//                     _ExampleDataPilotSource.aServiceName, regKey);
//     }
}

