/**
* Copyright (C) 2010-2017 Structr GmbH
*
* This file is part of Structr <http://structr.org>.
*
* Structr 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 3 of the
* License, or (at your option) any later version.
*
* Structr 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 Structr. If not, see <http://www.gnu.org/licenses/>.
*/
package org.structr.net.data.time;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.UUID;
import org.structr.net.protocol.AbstractMessage;
import org.structr.net.protocol.ProtocolEntity;
/**
*
*/
public class PseudoTime implements Comparable<PseudoTime>, ProtocolEntity {
private long instant = 0L;
private String uuid = null;
private long timeDerived = 0L;
private long tick = 0L;
public PseudoTime() {
}
public PseudoTime(final long instant, final String uuid, final long timeDerived) {
this(instant, uuid, timeDerived, 0L);
}
public PseudoTime(final long instant, final String uuid, final long timeDerived, final long tick) {
this.uuid = uuid;
this.instant = instant;
this.timeDerived = timeDerived;
this.tick = tick;
}
@Override
public String toString() {
return instant + "." + uuid + "." + pad(timeDerived) + "." + pad(tick);
}
public long getTimestamp() {
return instant;
}
public boolean after(final PseudoTime other) {
return compareTo(other) == 1;
}
public boolean before(final PseudoTime other) {
return compareTo(other) == -1;
}
public PseudoTime next() {
return new PseudoTime(instant, uuid, timeDerived, tick+1);
}
@Override
public int compareTo(final PseudoTime other) {
// instants are equal
if (this.instant == other.instant) {
// IDs are equal
if (this.uuid.equals(other.uuid)) {
if (this.timeDerived == other.timeDerived) {
// times are equal!
if (this.tick == other.tick) {
return 0;
}
return compare(this.tick, other.tick);
}
return compare(this.timeDerived, other.timeDerived);
}
return this.uuid.compareTo(other.uuid);
}
return compare(this.instant, other.instant);
}
// ----- private methods -----
private int compare(final long t1, final long t2) {
if (t1 < t2) {
return -1;
}
if (t1 > t2) {
return 1;
}
return 0;
}
private String pad(final long value) {
if (value < 100) {
if (value < 10) {
return "00" + value;
}
return "0" + value;
}
return String.valueOf(value);
}
@Override
public void serialize(final DataOutputStream dos) throws IOException {
dos.writeLong(instant);
AbstractMessage.serializeUUID(dos, uuid); // dos.writeUTF(uuid);
dos.writeLong(timeDerived);
dos.writeLong(tick);
}
@Override
public void deserialize(final DataInputStream dis) throws IOException {
this.instant = dis.readLong();
this.uuid = AbstractMessage.deserializeUUID(dis); // dis.readUTF();
this.timeDerived = dis.readLong();
this.tick = dis.readLong();
}
public static PseudoTime fromStream(final DataInputStream dis) throws IOException {
final PseudoTime time = new PseudoTime();
time.deserialize(dis);
return time;
}
public static PseudoTime fromString(final String src) {
final PseudoTime time = new PseudoTime();
if (src != null) {
final String[] parts = src.split("[\\.]+");
switch (parts.length) {
case 4: time.tick = Long.valueOf(parts[3]);
case 3: time.timeDerived = Long.valueOf(parts[2]);
case 2: time.uuid = parts[1];
case 1: time.instant = Long.valueOf(parts[0]);
}
} else {
time.instant = System.currentTimeMillis();
time.uuid = UUID.randomUUID().toString().replaceAll("\\-", "");
}
return time;
}
public static PseudoTime now(final Clock clock) {
final PseudoTime time = new PseudoTime();
time.instant = clock.getTime();
time.uuid = UUID.randomUUID().toString().replaceAll("\\-", "");
return time;
}
public static PseudoTime fromTimestamp(final long timestamp, final String pteId) {
final PseudoTime time = new PseudoTime();
time.instant = timestamp;
time.uuid = pteId;
return time;
}
public static PseudoTime epoch() {
final PseudoTime time = new PseudoTime();
time.instant = 0L;
time.uuid = UUID.randomUUID().toString().replaceAll("\\-", "");
return time;
}
}