/*
 * Copyright (c) 1999, 2011, Oracle and/or its affiliates. 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.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.jndi.toolkit.ctx;

import javax.naming.*;
import javax.naming.spi.ResolveResult;
import java.util.Hashtable;

/**
  * This class contains information required to continue
  * the method (place where it left off, and remaining name to
  * continue).
  *
  * @author Rosanna Lee
  */

public class Continuation extends ResolveResult {
    /**
     * The name that we started out with. It is initialized by the constructor
     * and used to calculate to "resolved name" in NamingException in
     * fillInException().
     * %%% Note that this approach does not always do the calculation
     * correctly with respect to absence or presence of the trailing slash
     * for resolved name.
     */
    protected Name starter;

    /**
     * Whether links were encountered.
     */
    protected Object followingLink = null;

    /**
     * The environment used by the caller. Initialized by constructor and
     * used when filling out a CannotProceedException.
     */
    protected Hashtable environment = null;

    /**
     * Indicates whether the Continuation instance indicates that the operation
     * should be continued using the data in the Continuation.
     * Typically, this is only false if an error has been encountered or if
     * the operation has succeeded.
     */
    protected boolean continuing = false;

    /**
     * The last resolved context. Used to set the "AltNameCtx" in a
     * CannotProceedException.
     */
    protected Context resolvedContext = null;

    /**
     * The resolved name relative to resolvedContext. Used to set the
     * "AltName" in a CannotProceedException.
     */
    protected Name relativeResolvedName = null;

    /**
     * Constructs a new instance of Continuation.
     * Used as dummy for contexts that do not do federation (e.g. for schema ops)
     */
    public Continuation() {
    }

    /**
     * Constructs a new instance of Continuation.
     * @param top The name of the object that is to be resolved/operated upon.
     *          This becomes the Continuation's 'starter' and is used to
     *          calculate the "resolved name" when filling  in a NamingException.
     * @param environment The environment used by the caller. It is used
     * when setting the "environment" of a CannotProceedException.
     */
    public Continuation(Name top, Hashtable environment) {
        super();
        starter = top;
        this.environment = environment;
    }

    /**
     * Determines whether this Continuation contains data that should be
     * used to continue the operation.
     *
     * @return true if operation should continue; false if operation has
     * completed (successfully or unsuccessfully).
     */
    public boolean isContinue() {
        return continuing;
    }

    /**
     * Sets this Continuation to indicate successful completion.
     * Subsequent calls to isContinue() will return false.
     * This method is different from the setError() methods only from
     * the standpoint that this method does not set any of the other
     * fields such as resolved object or resolved context. This is because
     * this method is typically called when the context recognizes that
     * the operation has successfully completed and that the continuation
     * already contains the appropriately set fields.
     * @see setError
     * @see setErrorNNS
     */
    public void setSuccess() {
        continuing = false;
    }

    /**
     * Fills in an exception's fields using data from this Continuation.
     * The resolved name is set by subtracting remainingName from starter.
     * %%% This might not not always produce the correct answer wrt trailing "/".
     * If the exception is a CannotProceedException, its environment,
     * altName, and altNameCtx fields are set using this continuation's
     * environment, relativeResolvedName, and resolvedContext.
     *
     * @param e The non-null naming exception to fill.
     * @return The non-null naming exception with its fields set using
     * data from this Continuation.
     */
    public NamingException fillInException(NamingException e) {
        e.setRemainingName(remainingName);
        e.setResolvedObj(resolvedObj);

        if (starter == null || starter.isEmpty())
            e.setResolvedName(null);
        else if (remainingName == null)
            e.setResolvedName(starter);
        else
            e.setResolvedName(
                starter.getPrefix(starter.size() -
                                  remainingName.size()));

        if ((e instanceof CannotProceedException)) {
            CannotProceedException cpe = (CannotProceedException)e;
            Hashtable env = (environment == null ?
                new Hashtable(11) : (Hashtable)environment.clone());
            cpe.setEnvironment(env);
            cpe.setAltNameCtx(resolvedContext);
            cpe.setAltName(relativeResolvedName);
        }

        return e;
    }

    /**
     * Sets this Continuation to indicated that an error has occurred,
     * and that the remaining name is rename + "/".
     *
     * This method is typically called by _nns methods that have been
     * given a name to process. It might process part of that name but
     * encountered some error. Consequenetly, it would call setErrorNNS()
     * with the remaining name. Since the _nns method was expected to
     * operate upon the "nns" of the original name, the remaining name
     * must include the "nns". That's why this method adds a trailing "/".
     *<p>
     * After this method is called, isContinuing() returns false.
     *
     * @param resObj The possibly null object that was resolved to.
     * @param remain The non-null remaining name.
     */
    public void setErrorNNS(Object resObj, Name remain) {
        Name nm = (Name)(remain.clone());
        try {
            nm.add("");
        } catch (InvalidNameException e) {
            // ignore; can't happen for composite name
        }
        setErrorAux(resObj, nm);
    }

    /**
     * Form that accepts a String name instead of a Name name.

     * @param resObj The possibly null object that was resolved to.
     * @param remain The possibly String remaining name.
     *
     * @see #setErrorNNS(java.lang.Object, javax.naming.Name)
     */
    public void setErrorNNS(Object resObj, String remain) {
        CompositeName rname = new CompositeName();
        try {
            if (remain != null && !remain.equals(""))
                rname.add(remain);

            rname.add("");
        } catch (InvalidNameException e) {
            // ignore, can't happen for composite name
        }
        setErrorAux(resObj, rname);
    }

    /**
     * Sets this Continuation to indicated that an error has occurred
     * and supply resolved information.
     *
     * This method is typically called by methods that have been
     * given a name to process. It might process part of that name but
     * encountered some error. Consequenetly, it would call setError()
     * with the resolved object and the remaining name.
     *<p>
     * After this method is called, isContinuing() returns false.
     *
     * @param resObj The possibly null object that was resolved to.
     * @param remain The possibly null remaining name.
     */
    public void setError(Object resObj, Name remain) {
        if (remain != null)
            remainingName = (Name)(remain.clone());
        else
            remainingName = null;

        setErrorAux(resObj, remainingName);
    }


    /**
     * Form that accepts a String name instead of a Name name.

     * @param resObj The possibly null object that was resolved to.
     * @param remain The possibly String remaining name.
     *
     * @see #setError(java.lang.Object, javax.naming.Name)
     */
    public void setError(Object resObj, String remain) {
        CompositeName rname = new CompositeName();
        if (remain != null && !remain.equals("")) {
            try {
                rname.add(remain);
            } catch (InvalidNameException e) {
                // ignore; can't happen for composite name
            }
        }
        setErrorAux(resObj, rname);
    }

    private void setErrorAux(Object resObj, Name rname) {
        remainingName = rname;
        resolvedObj = resObj;
        continuing = false;
    }

    private void setContinueAux(Object resObj,
        Name relResName, Context currCtx,  Name remain) {
        if (resObj instanceof LinkRef) {
            setContinueLink(resObj, relResName, currCtx, remain);
        } else {
            remainingName = remain;
            resolvedObj = resObj;

            relativeResolvedName = relResName;
            resolvedContext = currCtx;

            continuing = true;
        }
    }

    /**
     * Sets this Continuation with the supplied data, and set remaining name
     * to be "/".
     * This method is typically called by _nns methods that have been
     * given a name to process. It might the name (without the nns) and
     * continue process of the nns elsewhere.
     * Consequently, it would call this form of the setContinueNNS().
     * This method supplies "/" as the remaining name.
     *<p>
     * After this method is called, isContinuing() returns true.
     *
     * @param resObj The possibly null resolved object.
     * @param relResName The non-null resolved name relative to currCtx.
     * @param currCtx The non-null context from which relResName is to be resolved.
     */
    public void setContinueNNS(Object resObj, Name relResName, Context currCtx) {
        CompositeName rname = new CompositeName();

        setContinue(resObj, relResName, currCtx, PartialCompositeContext._NNS_NAME);
    }

    /**
     * Overloaded form that accesses String names.
     *
     * @param resObj The possibly null resolved object.
     * @param relResName The non-null resolved name relative to currCtx.
     * @param currCtx The non-null context from which relResName is to be resolved.
     * @see #setContinueNNS(java.lang.Object, javax.naming.Name, javax.naming.Context)
     */
    public void setContinueNNS(Object resObj, String relResName, Context currCtx) {
        CompositeName relname = new CompositeName();
        try {
            relname.add(relResName);
        } catch (NamingException e) {}

        setContinue(resObj, relname, currCtx, PartialCompositeContext._NNS_NAME);
    }


    /**
     * Sets this Continuation with the supplied data, and set remaining name
     * to be the empty name.
     * This method is typically called by list-style methods
     * in which the target context implementing list() expects an
     * empty name. For example when c_list() is given a non-empty name to
     * process, it would resolve that name, and then call setContinue()
     * with the resolved object so that the target context to be listed
     * would be called with the empty name (i.e. list the target context itself).
     *<p>
     * After this method is called, isContinuing() returns true.
     *
     * @param resObj The possibly null resolved object.
     * @param relResName The non-null resolved name relative to currCtx.
     * @param currCtx The non-null context from which relResName is to be resolved.
     */
    public void setContinue(Object obj, Name relResName, Context currCtx) {
        setContinueAux(obj, relResName, currCtx,
            (Name)PartialCompositeContext._EMPTY_NAME.clone());
    }

    /**
     * Sets this Continuation with the supplied data.

     * This method is typically called by a method that has been asked
     * to operate on a name. The method resolves part of the name
     * (relResName) to obj and sets the unprocessed part to rename.
     * It calls setContinue() so that the operation can be continued
     * using this data.
     *<p>
     * After this method is called, isContinuing() returns true.
     *
     * @param resObj The possibly null resolved object.
     * @param relResName The non-null resolved name relative to currCtx.
     * @param currCtx The non-null context from which relResName is to be resolved.
     * @param remain The non-null remaining name.
     */
    public void setContinue(Object obj, Name relResName, Context currCtx, Name remain) {
        if (remain != null)
            this.remainingName = (Name)(remain.clone());
        else
            this.remainingName = new CompositeName();

        setContinueAux(obj, relResName, currCtx, remainingName);
    }

    /**
     * String overload.
     *
     * @param resObj The possibly null resolved object.
     * @param relResName The non-null resolved name relative to currCtx.
     * @param currCtx The non-null context from which relResName is to be resolved.
     * @param remain The non-null remaining name.
     * @see #setContinue(java.lang.Object, java.lang.String, javax.naming.Context, java.lang.String)
     */
    public void setContinue(Object obj, String relResName,
        Context currCtx, String remain) {
        CompositeName relname = new CompositeName();
        if (!relResName.equals("")) {
            try {
                relname.add(relResName);
            } catch (NamingException e){}
        }

        CompositeName rname = new CompositeName();
        if (!remain.equals("")) {
            try {
                rname.add(remain);
            } catch (NamingException e) {
            }
        }

        setContinueAux(obj, relname, currCtx, rname);
    }

    /**
     * %%% This method is kept only for backward compatibility. Delete when
     * old implementations updated.
     *
     * Replaced by setContinue(obj, relResName, (Context)currCtx);
     *
     * @deprecated
     */
    @Deprecated
    public void setContinue(Object obj, Object currCtx) {
        setContinue(obj, null, (Context)currCtx);
    }


    /**
     * Sets this Continuation to process a linkRef.
     * %%% Not working yet.
     */
    private void setContinueLink(Object linkRef, Name relResName,
        Context resolvedCtx, Name rname) {
        this.followingLink = linkRef;

        this.remainingName = rname;
        this.resolvedObj = resolvedCtx;

        this.relativeResolvedName = PartialCompositeContext._EMPTY_NAME;
        this.resolvedContext = resolvedCtx;

        this.continuing = true;
    }

    public String toString() {
        if (remainingName != null)
            return starter.toString() + "; remainingName: '" + remainingName + "'";
        else
            return starter.toString();
    }

    public String toString(boolean detail) {
        if (!detail || this.resolvedObj == null)
                return this.toString();
        return this.toString() + "; resolvedObj: " + this.resolvedObj +
            "; relativeResolvedName: " + relativeResolvedName +
            "; resolvedContext: " + resolvedContext;
    }

    private static final long serialVersionUID = 8162530656132624308L;
}
