package net.obnoxint.util;
import java.io.Serializable;
import java.util.UUID;
/**
* <p>
* The DelayMeasure class is useful for recording the delay between the beginning and the finishing of many similar processes or when the execution environment must be stopped
* during the process.
* </p>
* <p>
* When beginning a process the {@link #begin()} method has to be called. After calling the {@link #end()} method the {@link #getDelay()} and {@link #getDelayNanos()} methods can
* be used to acquire the delay between the beginning and the finishing of the process.
* </p>
* <p>
* An instance of this class can not be used again.
* </p>
*/
public final class DelayMeasure implements Serializable {
private static final long serialVersionUID = 4180765053110711632L;
private boolean beganMeasuring = false;
private long beginDate;
private long beginNanos;
private boolean endedMeasuring = false;
private long endDate;
private long endNanos;
private final String id;
/**
* Creates a new instance and sets the Id to a random UUID.
*/
public DelayMeasure() {
this(UUID.randomUUID().toString());
}
/**
* Creates a clone of another instance.
*
* @param delayMeasure the instance to clone.
*/
public DelayMeasure(final DelayMeasure delayMeasure) {
this(delayMeasure, delayMeasure.id);
}
/**
* Creates a new instance based on an existing instance by copying its contents and assigning a new Id.
*
* @param delayMeasure the instance to copy.
* @param newId the new Id.
*/
public DelayMeasure(final DelayMeasure delayMeasure, final String newId) {
beganMeasuring = delayMeasure.beganMeasuring;
beginDate = delayMeasure.beginDate;
beginNanos = delayMeasure.beginNanos;
endDate = delayMeasure.endDate;
endedMeasuring = delayMeasure.endedMeasuring;
endNanos = delayMeasure.endNanos;
id = (newId == null || newId.isEmpty()) ? UUID.randomUUID().toString() : newId;
}
/**
* Creates a new instance with the given Id. An IllegalArgumentException will be thrown if <i>id</i> is null.
*
* @param id the Id.
*/
public DelayMeasure(final String id) {
if (id == null || id.isEmpty()) {
throw new IllegalArgumentException();
}
this.id = id;
}
/**
* @return true if the {@link #begin()} was called before.
*/
public boolean beganMeasuring() {
return beganMeasuring;
}
/**
* Begins measuring.
*/
public void begin() {
if (!beganMeasuring()) {
setBeginNanos();
setBeganMeasuring();
setBeginDate();
}
}
/**
* Ends measuring.
*/
public void end() {
if (beganMeasuring() && !endedMeasuring()) {
setEndDate();
setEndedMeasuring();
setEndNanos();
}
}
/**
* @return true if the {@link #end()} was called before.
*/
public boolean endedMeasuring() {
return endedMeasuring;
}
@Override
public boolean equals(final Object obj) {
if (obj != null) {
if (obj instanceof String) {
return ((String) obj).equals(id);
} else if (obj instanceof DelayMeasure) {
return ((DelayMeasure) obj).id.equals(id);
}
}
return false;
}
/**
* @return the date when the {@link #begin()} method was called.
*/
public long getBeginDate() {
return beginDate;
}
/**
* @return the nanos when the {@link #begin()} method was called.
*/
public long getBeginNanos() {
return beginNanos;
}
/**
* @return the delay between calling the {@link #begin()} and the {@link #end()} methods.
*/
public long getDelay() {
return getEndDate() - getBeginDate();
}
/**
* @return the delay in nano seconds between calling the {@link #begin()} and the {@link #end()} methods.
*/
public long getDelayNanos() {
return getEndNanos() - getBeginNanos();
}
/**
* @return the date when the {@link #end()} method was called.
*/
public long getEndDate() {
return endDate;
}
/**
* @return the nanos when the {@link #end()} method was called.
*/
public long getEndNanos() {
return endNanos;
}
/**
* @return the Id.
*/
public String getId() {
return id;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (beganMeasuring ? 1231 : 1237);
result = prime * result + (int) (beginDate ^ (beginDate >>> 32));
result = prime * result + (int) (beginNanos ^ (beginNanos >>> 32));
result = prime * result + (int) (endDate ^ (endDate >>> 32));
result = prime * result + (int) (endNanos ^ (endNanos >>> 32));
result = prime * result + (endedMeasuring ? 1231 : 1237);
result = prime * result + ((id == null) ? 0 : id.hashCode());
return result;
}
private void setBeganMeasuring() {
beganMeasuring = true;
}
private void setBeginDate() {
beginDate = System.currentTimeMillis();
}
private void setBeginNanos() {
beginNanos = System.nanoTime();
}
private void setEndDate() {
endDate = System.currentTimeMillis();
}
private void setEndedMeasuring() {
endedMeasuring = true;
}
private void setEndNanos() {
endNanos = System.nanoTime();
}
}