/*
// $Id: //open/dev/farrago/src/net/sf/farrago/runtime/FarragoUdrRuntime.java#15 $
// Farrago is an extensible data management system.
// Copyright (C) 2006-2009 The Eigenbase Project
// Copyright (C) 2006-2009 SQLstream, Inc.
// Copyright (C) 2006-2009 LucidEra, Inc.
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 of the License, or (at your option)
// any later version approved by The Eigenbase Project.
//
// This program 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 for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/
package net.sf.farrago.runtime;

import net.sf.farrago.catalog.*;
import net.sf.farrago.fennel.*;
import net.sf.farrago.session.*;

import org.eigenbase.util.*;


/**
 * FarragoUdrRuntime exposes a runtime support interface which can be used by
 * implementations of Farrago user-defined routines. For an example of how to
 * use this interface, see {@link
 * net.sf.farrago.test.FarragoTestUDR#generateRandomNumber}.
 *
 * <p>NOTE: By relying on this interface, your UDR becomes dependent on Farrago.
 *
 * @author John V. Sichi
 * @version $Id: //open/dev/farrago/src/net/sf/farrago/runtime/FarragoUdrRuntime.java#15 $
 */
public abstract class FarragoUdrRuntime
{
    //~ Methods ----------------------------------------------------------------

    /**
     * Accesses the context object for the calling UDR.
     *
     * @return context object, or null if none has been set yet
     */
    public static Object getContext()
    {
        FarragoUdrInvocationFrame frame =
            FarragoRuntimeContext.getUdrInvocationFrame();
        return frame.udrContext.getObject();
    }

    /**
     * Stores the context object for the calling UDR. If the given context
     * object implements the {@link ClosableAllocation} interface, its
     * closeAllocation method will be called automatically when statement
     * execution ends.
     *
     * @param context new context object to set
     */
    public static void setContext(Object context)
    {
        FarragoUdrInvocationFrame frame =
            FarragoRuntimeContext.getUdrInvocationFrame();
        frame.udrContext.setObject(context);
        if (context instanceof ClosableAllocation) {
            frame.context.addAllocation((ClosableAllocation) context);
        }
    }

    /**
     * If this UDR invocation was generated by a {@link
     * net.sf.farrago.namespace.FarragoMedDataServer}, invokes that server's
     * {@link net.sf.farrago.namespace.FarragoMedDataServer#getRuntimeSupport}
     * method. Otherwise, throws {@link IllegalStateException}.
     *
     * @param param server-specific runtime parameter
     *
     * @return server-specific runtime support object
     */
    public static Object getDataServerRuntimeSupport(Object param)
    {
        FarragoUdrInvocationFrame frame =
            FarragoRuntimeContext.getUdrInvocationFrame();
        String serverMofId = frame.udrContext.getServerMofId();
        if (serverMofId == null) {
            throw new IllegalStateException();
        }
        return frame.context.getDataServerRuntimeSupport(
            serverMofId,
            param);
    }

    /**
     * Tests to see whether the statement invoking this UDR has been cancelled;
     * if so, an exception is thrown. UDR's which take a lot of CPU time can
     * call this periodically in order to be responsive to cancel within calls.
     */
    public static void checkCancel()
    {
        FarragoUdrInvocationFrame frame =
            FarragoRuntimeContext.getUdrInvocationFrame();
        frame.context.checkCancel();
    }

    /**
     * Associates an execution handle with the context associated with the
     * executing UDR.
     *
     * @param execHandle the execution handle
     */
    public static void setExecutionHandle(FennelExecutionHandle execHandle)
    {
        FarragoUdrInvocationFrame frame =
            FarragoRuntimeContext.getUdrInvocationFrame();
        frame.context.setExecutionHandle(execHandle);
    }

    /**
     * Gets the session which called the UDR. Only system UDR's are allowed to
     * call this.
     *
     * @return a FarragoSession
     */
    public static FarragoSession getSession()
    {
        FarragoUdrInvocationFrame frame =
            FarragoRuntimeContext.getUdrInvocationFrame();
        return frame.udrContext.getSession();
    }

    /**
     * Gets the FarragoRepos for this context. Only system UDR's are allowed to
     * call this.
     *
     * @return a FarragoRepos
     */
    public static FarragoRepos getRepos()
    {
        FarragoUdrInvocationFrame frame =
            FarragoRuntimeContext.getUdrInvocationFrame();
        return frame.udrContext.getRepos();
    }

    /**
     * Forwards a row error to the runtime context. The runtime context then
     * decides how to process the error. For example, it might log the error,
     * send the error to a table, or cancel the statement.
     *
     * @param columnNames array of column names from the input stream
     * @param columnValues array of column values for the bad input row.
     * Primitive values such as long or int should be wrapped in Objects such as
     * Long or Int. Values should be printable via toString(). For example,
     * 2006-10-08 would be preferrable to Date@1ee80a.
     * @param ex the runtime exception to be handled
     * @param columnIndex the 1-based index of the column with the error. Since
     * the value 0 is reserved for filter conditions, the value -1 may be used
     * when a column index is not applicable.
     * @param tag a unique identifier for the source of the exception. It is
     * helpful for the tag to include information about the source. For example,
     * CleanseAddress[Id] may be more useful than [Id]. A timestamp suffix can
     * be informative and helps to satisfy the uniqueness requirement.
     * @param isWarning whether the exception is to be treated as a warning
     *
     * @return a server specific status value. A server may choose to return
     * null or to return a more detailed status such as {@link
     * org.eigenbase.runtime.TupleIter.NoDataReason} to indicate that the error
     * could not be processed.
     */
    public static Object handleRowError(
        String [] columnNames,
        Object [] columnValues,
        RuntimeException ex,
        int columnIndex,
        String tag,
        boolean isWarning)
    {
        return handleRowError(
            columnNames,
            columnValues,
            ex,
            columnIndex,
            tag,
            isWarning,
            null,
            null);
    }

    /**
     * Forwards error to runtime context, if error code is non-null, exceptions
     * will be defered until all errors have been processed/logged for a row
     */
    public static Object handleRowError(
        String [] columnNames,
        Object [] columnValues,
        RuntimeException ex,
        int columnIndex,
        String tag,
        boolean isWarning,
        String errorCode,
        String columnName)
    {
        FarragoUdrInvocationFrame frame =
            FarragoRuntimeContext.getUdrInvocationFrame();
        return frame.context.handleRowError(
            columnNames,
            columnValues,
            ex,
            columnIndex,
            tag,
            isWarning,
            errorCode,
            columnName);
    }

    public static void handleRowErrorCompletion(
        RuntimeException ex,
        String tag)
    {
        FarragoUdrInvocationFrame frame =
            FarragoRuntimeContext.getUdrInvocationFrame();
        frame.context.handleRowErrorCompletion(ex, tag);
    }

    /*
     * @return true if a UDR is currently executing
     */
    public static boolean inUdr()
    {
        return FarragoRuntimeContext.inUdr();
    }
}

// End FarragoUdrRuntime.java
