/*
 * Copyright 1997-2007 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */


package com.sun.jmx.snmp.agent;



// java imports
//
import java.io.Serializable;
import java.util.Vector;
import java.util.Hashtable;
import java.util.Enumeration;

// jmx imports
//
import com.sun.jmx.snmp.SnmpOid;
import com.sun.jmx.snmp.SnmpValue;
import com.sun.jmx.snmp.SnmpVarBind;
import com.sun.jmx.snmp.SnmpDefinitions;
import com.sun.jmx.snmp.SnmpStatusException;

/**
 * The <CODE>SnmpMibNode</CODE> class represents a node in an SNMP MIB.
 * <P>
 * This class is used internally and by the class generated by
 * <CODE>mibgen</CODE>.
 * You should not need to use this class directly.
 *
 * <p><b>This API is a Sun Microsystems internal API  and is subject
 * to change without notice.</b></p>
 */

public abstract class SnmpMibNode implements Serializable {

    // ---------------------------------------------------------------------
    // PUBLIC METHODS
    //----------------------------------------------------------------------

    /**
     * Get the next OID arc corresponding to a readable scalar variable,
     * a branch leading to a subgroub, or a table.
     *
     * @param id Id we start from looking for the next.
     * @param userData A contextual object containing user-data.
     *        This object is allocated through the <code>
     *        {@link com.sun.jmx.snmp.agent.SnmpUserDataFactory}</code>
     *        for each incoming SNMP request.
     *
     * @return The next id in this group.
     *
     * @exception SnmpStatusException If no id is found after the given id.
     */
    public long getNextVarId(long id, Object userData)
        throws SnmpStatusException {
        return getNextIdentifier(varList,id);
    }

    /**
     * Get the next OID arc corresponding to a readable scalar variable,
     * a branch leading to a subgroub, or a table, possibly skipping over
     * those arcs that must not or cannot be returned.
     *
     * Calls {@link #getNextVarId(long,java.lang.Object)} until
     * {@link #skipVariable(long,java.lang.Object,int)} returns false.
     *
     * @param id Id we start from looking for the next.
     * @param userData A contextual object containing user-data.
     *        This object is allocated through the <code>
     *        {@link com.sun.jmx.snmp.agent.SnmpUserDataFactory}</code>
     *        for each incoming SNMP request.
     * @param pduVersion Protocol version of the original request PDU.
     *
     * @return The next id in this group which can be returned using
     *         the given PDU's protocol version.
     *
     * @exception SnmpStatusException If no id is found after the given id.
     */
    public long getNextVarId(long id, Object userData, int pduVersion)
        throws SnmpStatusException {
        long varid=id;
        do {
            varid = getNextVarId(varid,userData);
        } while (skipVariable(varid,userData,pduVersion));

        return varid;
    }

    /**
     * Hook for subclasses.
     * The default implementation of this method is to always return
     * false. Subclasses should redefine this method so that it returns
     * true when:
     * <ul><li>the variable is a leaf that is not instantiated,</li>
     * <li>or the variable is a leaf whose type cannot be returned by that
     *     version of the protocol (e.g. an Counter64 with SNMPv1).</li>
     * </ul>
     *
     * @param id Id we start from looking for the next.
     * @param userData A contextual object containing user-data.
     *        This object is allocated through the <code>
     *        {@link com.sun.jmx.snmp.agent.SnmpUserDataFactory}</code>
     *        for each incoming SNMP request.
     * @param pduVersion Protocol version of the original request PDU.
     *
     * @return true if the variable must be skipped by the get-next
     *         algorithm.
     */
    protected boolean skipVariable(long id, Object userData, int pduVersion) {
        return false;
    }

    /**
     * Find the node which handles a varbind, and register it in the
     * SnmpRequestTree. This method is a pure internal method. You should
     * never try to call it directly.
     *
     * @param varbind  The varbind to be handled
     *
     * @param oid      The OID array extracted from the varbind
     *
     * @param depth    The depth reached in the OID at this step of the
     *                 processing.
     *
     * @param handlers The Hashtable in which the varbind will be registered
     *                 with its handling node. This hashtable contains
     *                 <CODE>SnmpRequestTree.Handler</CODE> items.
     *
     * @exception SnmpStatusException No handling node was found.
     **/
    void findHandlingNode(SnmpVarBind varbind,
                          long[] oid, int depth,
                          SnmpRequestTree handlers)
        throws SnmpStatusException {
        throw noSuchObjectException;
    }

    /**
     * Find the node which handles the leaf that immediately follows the
     * given varbind OID, and register the it in the SnmpRequestTree.
     * This method is a pure internal method. You should never try to call
     * it directly.
     *
     * @param varbind  The varbind to be handled
     *
     * @param oid      The OID array extracted from the varbind
     *
     * @param depth    The depth reached in the OID at this step of the
     *                 processing.
     *
     * @param handlers The Hashtable in which the varbind will be registered
     *                 with its handling node. This hashtable contains
     *                 SnmpRequestTree.Handler items.
     *
     * @return The SnmpOid of the next leaf.
     *
     * @exception SnmpStatusException No handling node was found.
     **/
    long[] findNextHandlingNode(SnmpVarBind varbind,
                                 long[] oid, int pos, int depth,
                                 SnmpRequestTree handlers, AcmChecker checker)
        throws SnmpStatusException {
        throw noSuchObjectException;
    }

    /**
     * Generic handling of the <CODE>get</CODE> operation.
     *
     * <p> You can override this method if you need to implement some
     * specific policies for minimizing the accesses made to some remote
     * underlying resources.
     * <p>
     *
     * @param req   The sub-request that must be handled by this node.
     *
     * @param depth The depth reached in the OID tree.
     *
     * @exception SnmpStatusException An error occurred while accessing
     *  the MIB node.
     */
    public abstract void get(SnmpMibSubRequest req, int depth)
        throws SnmpStatusException;

    /**
     * Generic handling of the <CODE>set</CODE> operation.
     * <p> You can override this method if you need to implement some
     * specific policies for minimizing the accesses made to some remote
     * underlying resources.
     * <p>
     *
     * @param req   The sub-request that must be handled by this node.
     *
     * @param depth The depth reached in the OID tree.
     *
     * @exception SnmpStatusException An error occurred while accessing
     *  the MIB node.
     */
    public abstract void set(SnmpMibSubRequest req, int depth)
        throws SnmpStatusException;

    /**
     * Generic handling of the <CODE>check</CODE> operation.
     * <p> You can override this method if you need to implement some
     * specific policies for minimizing the accesses made to some remote
     * underlying resources, or if you need to implement some consistency
     * checks between the different values provided in the varbind list.
     * <p>
     *
     * @param req   The sub-request that must be handled by this node.
     *
     * @param depth The depth reached in the OID tree.
     *
     * @exception SnmpStatusException An error occurred while accessing
     *  the MIB node.
     */
    public abstract void check(SnmpMibSubRequest req, int depth)
        throws SnmpStatusException;

    /**
     * Sorts the specified integer array.
     *
     * @param array An integer array.
     */
    static public void sort(int array[]) {
        QuickSort(array, 0, array.length - 1);
    }

    /**
     * Computes the root OID of the MIB.
     */
    public void getRootOid(Vector<Integer> result) {
        return;
    }

    //----------------------------------------------------------------------
    // PACKAGE METHODS
    //----------------------------------------------------------------------

    /**
     * This is a generic version of C.A.R Hoare's Quick Sort
     * algorithm.  This will handle arrays that are already
     * sorted, and arrays with duplicate keys.
     *
     * If you think of a one dimensional array as going from
     * the lowest index on the left to the highest index on the right
     * then the parameters to this function are lowest index or
     * left and highest index or right.  The first time you call
     * this function it will be with the parameters 0, a.length - 1.
     *
     * @param a An integer array.
     * @param lo0 Left boundary of array partition.
     * @param hi0 Right boundary of array partition.
     */
    static void QuickSort(int a[], int lo0, int hi0) {
        int lo = lo0;
        int hi = hi0;
        int mid;

        if ( hi0 > lo0) {

            /* Arbitrarily establishing partition element as the midpoint of
             * the array.
             */
            mid = a[ ( lo0 + hi0 ) / 2 ];

            // loop through the array until indices cross
            while( lo <= hi ) {
                /* find the first element that is greater than or equal to
                 * the partition element starting from the left Index.
                 */
                while( ( lo < hi0 )  && ( a[lo] < mid ))
                    ++lo;

                /* find an element that is smaller than or equal to
                 * the partition element starting from the right Index.
                 */
                while( ( hi > lo0 ) && ( a[hi] > mid ))
                    --hi;

                // if the indexes have not crossed, swap
                if( lo <= hi ) {
                    swap(a, lo, hi);
                    ++lo;
                    --hi;
                }
            }

            /* If the right index has not reached the left side of array
             * must now sort the left partition.
             */
            if( lo0 < hi )
                QuickSort( a, lo0, hi );

            /* If the left index has not reached the right side of array
             * must now sort the right partition.
             */
            if( lo < hi0 )
                QuickSort( a, lo, hi0 );

        }
    }

    //----------------------------------------------------------------------
    // PROTECTED METHODS
    //----------------------------------------------------------------------

    /**
     * This will give the first element greater than <CODE>value</CODE>
     * in a sorted array.
     * If there is no element of the array greater than <CODE>value</CODE>,
     * the method will throw a <CODE>SnmpStatusException</CODE>.
     *
     * @param table A sorted integer array.
     *
     * @param value The greatest value.
     *
     * @exception SnmpStatusException If there is no element greater than
     *     <CODE>value</CODE>.
     */
    final static protected int getNextIdentifier(int table[], long value)
        throws SnmpStatusException {

        final int[] a = table;
        final int val= (int) value;

        if (a == null)
            throw noSuchObjectException;

        int low= 0;
        int max= a.length;
        int curr= low + (max-low)/2;
        int elmt= 0;

        // Basic check
        //
        if (max < 1)
            throw noSuchObjectException;

        if (a[max-1] <= val)
            throw noSuchObjectException;

        while (low <= max) {
            elmt= a[curr];
            if (val == elmt) {
                // We ned to get the next index ...
                //
                curr++;
                return a[curr];
            }
            if (elmt < val) {
                low= curr +1;
            } else {
                max= curr -1;
            }
            curr= low + (max-low)/2;
        }
        return a[curr];
    }


    //----------------------------------------------------------------------
    // PRIVATE METHODS
    //----------------------------------------------------------------------

    final static private void swap(int a[], int i, int j) {
        int T;
        T = a[i];
        a[i] = a[j];
        a[j] = T;
    }

    //----------------------------------------------------------------------
    // PROTECTED VARIABLES
    //----------------------------------------------------------------------

    /**
     * Contains the list of variable identifiers.
     */
    protected int[] varList;

    /**
     * Contains a predefined exception that is often fired when an
     * object is not found in the MIB.
     */
    static final protected SnmpStatusException noSuchInstanceException =
        new SnmpStatusException(SnmpStatusException.noSuchInstance);
    static final protected SnmpStatusException noSuchObjectException =
        new SnmpStatusException(SnmpStatusException.noSuchObject);
    static final protected SnmpStatusException noSuchNameException =
        new SnmpStatusException(SnmpDefinitions.snmpRspNoSuchName);
}
