package vroom.common.modeling.dataModel;
import java.util.LinkedList;
import java.util.List;
import vroom.common.modeling.dataModel.attributes.Duration;
import vroom.common.modeling.dataModel.attributes.ITimeWindow;
import vroom.common.modeling.dataModel.attributes.NodeAttributeKey;
import vroom.common.modeling.dataModel.attributes.RequestAttributeKey;
import vroom.common.utilities.Utilities;
/**
* <code>NodeVisit</code> is a wrapper class used to add information on the
* {@link Node} when it is visited by a route.
*
* @author Victor Pillac, <a href="http://uniandes.edu.co">Universidad de Los
* Andes</a> - <a href="http://copa.uniandes.edu.co">Copa</a>, <a
* href="http://www.emn.fr">Ecole des Mines de Nantes</a>-<a
* href="http://www.irccyn.ec-nantes.fr/irccyn/d/en/equipes/Slp">SLP</a>
* @version 1.0 #updated 16-Feb-2010 10:07:26 a.m.
*/
public class NodeVisit implements INodeVisit {
/** The node visited. */
private final Node mNode;
/**
* The request corresponding to the wrapped node, <code>null</code> if the
* node is a depot.
*
* @see #mNode
*/
private final IVRPRequest mParentRequest;
/** a list of predecessors **/
private final List<INodeVisit> mPredecesors;
/*
* (non-Javadoc)
*
* @see vroom.common.modeling.dataModel.INodeVisit#getPredecesors()
*/
@Override
public List<INodeVisit> getPredecesors() {
return mPredecesors;
}
/** a list of successors **/
private final List<INodeVisit> mSuccessors;
/*
* (non-Javadoc)
*
* @see vroom.common.modeling.dataModel.INodeVisit#getSuccessors()
*/
@Override
public List<INodeVisit> getSuccessors() {
return mSuccessors;
}
/**
* a flag defining whether this visit is a pickup or delivery for PD
* problems
**/
private final boolean mPickup;
/*
* (non-Javadoc)
*
* @see vroom.common.modeling.dataModel.INodeVisit#isPickup()
*/
@Override
public boolean isPickup() {
return mPickup;
}
/** The fixed flag */
private boolean mFixed;
/*
* (non-Javadoc)
*
* @see vroom.common.modeling.dataModel.INodeVisit#isFixed()
*/
@Override
public boolean isFixed() {
return mFixed;
}
/*
* (non-Javadoc)
*
* @see vroom.common.modeling.dataModel.INodeVisit#fix()
*/
@Override
public void fix() {
mFixed = true;
}
/*
* (non-Javadoc)
*
* @see vroom.common.modeling.dataModel.INodeVisit#free()
*/
@Override
public void free() {
mFixed = false;
}
/**
* Creates a new <code>NodeVisit</code> associated with a depot.
*
* @param depot
* the depot that is associated with this visit
*/
public NodeVisit(Depot depot) {
mParentRequest = null;
mNode = depot;
mPredecesors = new LinkedList<INodeVisit>();
mSuccessors = new LinkedList<INodeVisit>();
mPickup = true;
fix();
}
/**
* Creates a new <code>NodeVisit</code>
*
* @param node
* @param parentRequest
* @param predecesors
* @param successors
*/
protected NodeVisit(Node node, IVRPRequest parentRequest, boolean pickup) {
mNode = node;
mParentRequest = parentRequest;
mPredecesors = new LinkedList<INodeVisit>();
mSuccessors = new LinkedList<INodeVisit>();
mPickup = pickup;
free();
}
/*
* (non-Javadoc)
*
* @see vroom.common.modeling.dataModel.INodeVisit#getNode()
*/
@Override
public Node getNode() {
return mNode;
}
/*
* (non-Javadoc)
*
* @see vroom.common.modeling.dataModel.INodeVisit#getParentRequest()
*/
@Override
public IVRPRequest getParentRequest() {
return mParentRequest;
}
/*
* (non-Javadoc)
*
* @see vroom.common.modeling.dataModel.INodeVisit#isDepot()
*/
@Override
public boolean isDepot() {
return mNode instanceof Depot;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
if (mParentRequest != null) {
return String.format("%s[r:%s]", mParentRequest
.isOriginDestination() ? isPickup() ? "P" : "D" : "",
mParentRequest);
} else {
return mNode.toString();
}
}
/*
* (non-Javadoc)
*
* @see java.lang.Comparable#compareTo(java.lang.Object)
*/
@Override
public int compareTo(INodeVisit o) {
return getNode() != null && o.getNode() != null ? getNode().getID()
- o.getNode().getID() : 0;
}
@Override
public NodeVisit clone() {
NodeVisit clone;
if (isDepot()) {
clone = new NodeVisit((Depot) getNode());
} else {
clone = new NodeVisit(getNode(), getParentRequest(), isPickup());
}
return clone;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
return getID();
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof INodeVisit)) {
return false;
}
if (obj == this) {
return true;
}
INodeVisit v = (INodeVisit) obj;
return Utilities.equal(mParentRequest, v.getParentRequest())
&& Utilities.equal(mNode, v.getNode());
}
/**
* Factory method to create the node visits associated with a request.
*
* @param request
* @return an array containing the corresponding node visit, or the node
* visit of the pickup and the node visit of teh delivery
*/
public static NodeVisit[] createNodeVisits(IVRPRequest request) {
NodeVisit o = new NodeVisit(request.getNode(), request, true);
if (request.isOriginDestination()) {
NodeVisit d = new NodeVisit(request.getDestinationNode(), request,
false);
o.getSuccessors().add(d);
d.getPredecesors().add(o);
return new NodeVisit[] { o, d };
} else {
return new NodeVisit[] { o };
}
}
/**
* Factory method to create the node visit associated with a request.
*
* @param request
* @return the corresponding node visit
*/
public static NodeVisit createNodeVisit(IVRPRequest request) {
return new NodeVisit(request.getNode(), request, true);
}
/*
* (non-Javadoc)
*
* @see vroom.common.utilities.dataModel.IObjectWithID#getID()
*/
@Override
public int getID() {
if (isDepot()) {
return getNode().getID();
} else {
int id = getParentRequest().getID();
return isPickup() ? id : -id;
}
}
/*
* (non-Javadoc)
*
* @see vroom.common.modeling.dataModel.INodeVisit#getDemand(int)
*/
@Override
public double getDemand(int product) {
return getParentRequest() != null ? getParentRequest().getDemand(
product) : 0;
}
/*
* (non-Javadoc)
*
* @see vroom.common.modeling.dataModel.INodeVisit#getDemand()
*/
@Override
public double getDemand() {
return getParentRequest() != null ? getParentRequest().getDemand() : 0;
}
@Override
public double getServiceTime() {
if (getParentRequest() == null)
return 0;
Duration st = getParentRequest().getAttribute(
RequestAttributeKey.SERVICE_TIME);
return st != null ? st.getDuration() : 0;
}
@Override
public ITimeWindow getTimeWindow() {
ITimeWindow tw;
if (getParentRequest().isOriginDestination()) {
tw = getNode().getAttribute(NodeAttributeKey.TIME_WINDOW);
if (tw == null)
tw = getParentRequest().getAttribute(
NodeAttributeKey.TIME_WINDOW);
} else
tw = getParentRequest().getAttribute(NodeAttributeKey.TIME_WINDOW);
return tw;
}
}// end NodeVisit