/**
* Replication Benchmarker
* https://github.com/score-team/replication-benchmarker/ Copyright (C) 2013
* LORIA / Inria / SCORE Team
*
* This program 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.
*
* This program 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
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package jbenchmarker.logoot;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* Treedoc identifiers for logoot algorithm. Identifier are a list of triple <<
* left/right, replica_id, clock_id >>.
*
* @author urso
*/
class LogootBinaryPosition implements ListIdentifier<LogootBinaryPosition> {
enum Direction {
left, right
};
List<Component> position;
LogootBinaryPosition(List<Component> position) {
this.position = new ArrayList<Component>(position);
}
LogootBinaryPosition(int size) {
this.position = new ArrayList<Component>(size);
}
LogootBinaryPosition(Direction d, int r, int c) {
this.position = new ArrayList<Component>(1);
this.position.add(new Component(d, r, c));
}
LogootBinaryPosition plus(LogootBinaryPosition rest) {
LogootBinaryPosition p = new LogootBinaryPosition(position);
p.position.addAll(rest.position);
return p;
}
LogootBinaryPosition plus(Direction direction, int replicaNumber, int nextClock) {
LogootBinaryPosition p = new LogootBinaryPosition(position);
p.position.add(new Component(direction, replicaNumber, nextClock));
return p;
}
@Override
public int length() {
return position.size();
}
@Override
public int replica() {
return position.get(position.size() - 1).replica;
}
@Override
public int clock() {
return position.get(position.size() - 1).clock;
}
@Override
public ListIdentifier clone() {
return new LogootBinaryPosition(this.position);
}
@Override
public int compareTo(LogootBinaryPosition other) {
Iterator<Component> it = this.position.iterator(), ot = other.position.iterator();
while (it.hasNext() && ot.hasNext()) {
Component t = it.next(), o = ot.next();
if (t.dir != o.dir) {
return t.dir == Direction.left ? -1 : 1;
}
int c = Integer.compare(t.replica, o.replica);
if (c != 0) {
return c;
}
c = Integer.compare(t.clock, o.clock);
if (c != 0) {
return c;
}
}
if (!it.hasNext() && !ot.hasNext()) {
return 0;
} else if (it.hasNext()) {
return it.next().dir == Direction.left ? -1 : 1;
} else {
return ot.next().dir == Direction.right ? -1 : 1;
}
}
public boolean isRightSonOf(LogootBinaryPosition father) {
Iterator<Component> it = this.position.iterator(), ot = father.position.iterator();
while (it.hasNext() && ot.hasNext()) {
if (!it.next().equals(ot.next())) {
return false;
}
}
return it.hasNext() && it.next().dir == Direction.right;
}
@Override
public int hashCode() {
int hash = 3;
hash = 23 * hash + (this.position != null ? this.position.hashCode() : 0);
return hash;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final LogootBinaryPosition other = (LogootBinaryPosition) obj;
if (this.position != other.position && (this.position == null || !this.position.equals(other.position))) {
return false;
}
return true;
}
@Override
public String toString() {
return position.toString();
}
static class Component {
final Direction dir;
final int replica, clock;
Component(Direction d, int r, int c) {
this.dir = d;
this.replica = r;
this.clock = c;
}
@Override
public int hashCode() {
int hash = 7;
hash = 67 * hash + (this.dir != null ? this.dir.hashCode() : 0);
hash = 67 * hash + this.replica;
hash = 67 * hash + this.clock;
return hash;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Component other = (Component) obj;
if (this.dir != other.dir) {
return false;
}
if (this.replica != other.replica) {
return false;
}
if (this.clock != other.clock) {
return false;
}
return true;
}
@Override
public String toString() {
return "<" + dir + ", " + replica + ", " + clock + '>';
}
}
}