/*
 * e4nvisitor.cpp --
 *
 *	Implementation of the e4_NodeVisitor class defined in e4graph.h.
 *
 *	Authors: Jacob Levy and Jean-Claude Wippler.
 *		 jyl@best.com	jcw@equi4.com
 *
 * Copyright (c) 2000-2003, JYL Software Inc.
 * 
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE, EVEN IF
 * JYL SOFTWARE INC. IS MADE AWARE OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "e4graphimpl.h"

/*
 * Default constructor:
 */

e4_NodeVisitor::e4_NodeVisitor()
    : done(true),
      detachchoice(E4_DCATTACHED),
      n(invalidNode),
      s(invalidStorage)
{
}

/*
 * Copying constructor:
 */

e4_NodeVisitor::e4_NodeVisitor(const e4_NodeVisitor &referrer)
    : done(referrer.done),
      detachchoice(referrer.detachchoice),
      s(referrer.s),
      n(referrer.n)
{
}

/*
 * Assignment operator:
 */

e4_NodeVisitor &
e4_NodeVisitor::operator=(const e4_NodeVisitor &referrer)
{
    done = referrer.done;
    detachchoice = referrer.detachchoice;
    s = referrer.s;
    n = referrer.n;

    return * this;
}

/*
 * Comparison operators:
 */

bool
e4_NodeVisitor::operator==(const e4_NodeVisitor &compared) const
{
    if ((done == compared.done) &&
	(detachchoice == compared.detachchoice) &&
	(s == compared.s) &&
	(n == compared.n)) {
	return true;
    }
    return false;
}

bool
e4_NodeVisitor::operator!=(const e4_NodeVisitor &compared) const
{
    if ((done == compared.done) &&
	(detachchoice == compared.detachchoice) &&
	(s == compared.s) &&
	(n == compared.n)) {
	return false;
    }
    return true;
}

/*
 * Constructors that initialize the visitor from a storage, node or vertex.
 */

e4_NodeVisitor::e4_NodeVisitor(const e4_Storage &ss)
    : done(true)
{
    SetStorage(ss, E4_DCBOTH);
}

e4_NodeVisitor::e4_NodeVisitor(const e4_Storage &ss, e4_DetachChoice dc)
    : done(true)
{
    SetStorage(ss, dc);
}

e4_NodeVisitor::e4_NodeVisitor(const e4_Node &nn)
    : done(true)
{
    SetNode(nn);
}

e4_NodeVisitor::e4_NodeVisitor(const e4_Vertex &ff)
    : done(true)
{
    SetVertex(ff);
}

/*
 * Destructor:
 */

e4_NodeVisitor::~e4_NodeVisitor()
{
    s = invalidStorage;
    n = invalidNode;
}

/*
 * Reset the visitor from a storage.
 */

bool
e4_NodeVisitor::SetStorage(const e4_Storage &ss)
{
    return SetStorage(ss, E4_DCATTACHED);
}
			    
/*
 * Reset the visitor from a storage, node or vertex.
 */

bool
e4_NodeVisitor::SetStorage(const e4_Storage &ss, e4_DetachChoice dc)
{
    if (!ss.IsValid()) {
	return false;
    }
    s = ss;
    detachchoice = dc;
    done = (!s.FindNextNode(E4_NODENOTFOUND, detachchoice, n));
    return true;
}

bool
e4_NodeVisitor::SetNode(const e4_Node &nn)
{
    if (!nn.IsValid()) {
	return false;
    }
    done = (!nn.GetStorage(s));
    detachchoice = 
	((nn.IsDetached() && !nn.IsRoot()) 
	 ? E4_DCDETACHED
	 : E4_DCATTACHED);
    if (done) {
	n = invalidNode;
    } else {
	done = (!s.FindNextNode(E4_NODENOTFOUND, detachchoice, n));
    }
    return true;
}

bool
e4_NodeVisitor::SetVertex(const e4_Vertex &ff)
{
    if (!ff.IsValid()) {
	return false;
    }
    done = (!ff.GetStorage(s));
    detachchoice = E4_DCATTACHED;
    if (done) {
	n = invalidNode;
    } else {
	done = (!s.FindNextNode(E4_NODENOTFOUND, detachchoice, n));
    }
    return true;
}

/*
 * Get the current node.
 */

bool
e4_NodeVisitor::CurrentNode(e4_Node &nn)
{
    if (!n.IsValid() || !s.IsValid()) {
	done = true;
	return false;
    }
    nn = n;
    return true;
}

/*
 * Get the next node.
 */

bool
e4_NodeVisitor::NextNode(e4_Node &nn)
{
    if (done) {
	return false;
    }
    done = (!s.FindNextNode(n.GetRawUniqueID(), detachchoice, n));
    if (done) {
	return false;
    }
    nn = n;
    return true;
}

/*
 * Advance to the next node without returning it.
 */

bool
e4_NodeVisitor::Advance()
{
    if (done) {
	return false;
    }
    done = (!s.FindNextNode(n.GetRawUniqueID(), detachchoice, n));
    if (done) {
	return false;
    }
    return true;
}

/*
 * Get the current node and advance to the next one.
 */

bool
e4_NodeVisitor::CurrentNodeAndAdvance(e4_Node &nn)
{
    e4_Node dn = invalidNode;

    if (!CurrentNode(nn) || IsDone()) {
	return false;
    }
    (void) Advance();
    return true;
}

/*
 * Is this instance done?
 */

bool
e4_NodeVisitor::IsDone()
{
    if (done) {
	return true;
    }
    if (!s.IsValid() || !n.IsValid()) {
	done = true;
    }
    return done;
}

/*
 * Is this instance valid?
 */

bool
e4_NodeVisitor::IsValid()
{
    if (!s.IsValid()) {
	done = true;
	return false;
    }
    return true;
}

