/**
* 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 crdt.tree.wordtree.policy;
import collect.HashTree;
import collect.Node;
import collect.Tree;
import collect.UnorderedNode;
import crdt.Factory;
import crdt.set.CRDTSet;
import crdt.set.SetOperation;
import crdt.tree.wordtree.WordPolicy;
import java.util.HashMap;
import java.util.List;
import java.util.Observable;
import java.util.Observer;
import java.util.Set;
/**
* une idée, si ça peut aider. C'est ce que j'ai essayé de t'expliquer avant de partir
* Il faut l'adapter à ta modélisation que j'ai lu un peut en diagonal.
* Je n'ai pas vraiment plus simple.
*
* @author Stephane
*/
public class MyWordIncremetanlTrapear<T> extends WordPolicy<T> implements Factory<WordPolicy<T>>, Observer {
HashMap<List<T>, NodeContainer> map; /* Fait la liaison entre une liste de mot et un containeur de noeud*/
HashTree tree; /* arbre du lookup */
@Override
public MyWordIncremetanlTrapear<T> create() {
MyWordIncremetanlTrapear<T> wp = new MyWordIncremetanlTrapear();
tree=new HashTree();
return (MyWordIncremetanlTrapear<T>) wp;
}
@Override
synchronized public void update(Observable o, Object o1) {
if (o instanceof CRDTSet
&& o1 instanceof SetOperation) {
SetOperation o2 = (SetOperation) o1;
List<T> mot = (List<T>) o2.getContent();
if (o2.getType() == SetOperation.OpType.add) {
/*
* Ajout d'un mot: - Si le noeud n'existe pas on le crée avec
* son chemin. - on le démarque si était ghost
*/
NodeContainer n;
n = getNode(mot);
/*
* le noeud n'est pas ghost
*/
n.setGhost(false);
} else {
/*
* Suppression d'un noeud :
* - on le marque ghost et on lance cleanPath avec ce noeud.
*
*/
NodeContainer n = map.get(mot);
/*
* Le mot doit être là par définition.
*/
n.setGhost(true);
cleanPath(n);
}
}
}
/* Va cherche un noeud
* S'il n'existe pas il va le créer en cherchant le père et récurcivement.
*/
NodeContainer getNode(List<T> mot) {
if (mot.isEmpty()) /*mot vite n'a pas de correspondance */
return null;
NodeContainer node = map.get(mot);/* On récupère le noeud s'il existe */
if (node==null){ /*Si n'existe pas */
/* on cherche sont père récurcivement */
NodeContainer father=getNode(mot.subList(1, mot.size() - 2));
/* On retourne nouveau noeud */
return new NodeContainer(father,mot);
}else{
/* Sinon on retourne celui qu'on a trouvé */
return node;
}
}
void cleanPath(NodeContainer n) {
/*
* On vérifie que le noeud est ghost et que ce n'est pas la racine sinon on ne fait rien.
*/
if (n!=null && n.isGhost()) {
/*
* On vérifie qu'il n'y a pas de fils. -S'il a des fils cela veut
* dire qu'il y a un autre chemin terminant par un non ghost.
*/
if (n.getNode().getChildrenNumber() == 0) {
/*
* On supprime le noeud
*/
n.del();
cleanPath(n.getFather());/* On remonte */
}
}
}
@Override
synchronized public Tree<T> lookup() {
return tree;
}
@Override
public Set<List<T>> addMapping(UnorderedNode<T> node) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public Set<List<T>> delMapping(UnorderedNode<T> node) {
throw new UnsupportedOperationException("Not supported yet.");
}
class NodeContainer {
private Node<T> node; /*
* Le noeud du lookup
*/
private boolean ghost; /*
* Savoir si le neoud est dans le CRDT
*/
private NodeContainer father;/*
* Pour le parcours
*/
private List<T> word; /*
* Histoire de pouvoir enlever la clef sans trop de prob
*/
NodeContainer(NodeContainer father, List<T> word) {
this.node = tree.add((father != null) ? father.getNode() : tree.getRoot(), word.get(word.size() - 1));
this.ghost = true; /* Par défaut c'est un ghost */
this.father = father;
this.word = word;
map.put(word,this);
}
/**
* Supprime le noeud de la map et du lookup
*/
void del(){
tree.remove(this.getNode());
map.remove(this.getWord());
}
/**
* @return the ghost
*/
boolean isGhost() {
return ghost;
}
/**
* @param ghost the ghost to set
*/
void setGhost(boolean ghost) {
this.ghost = ghost;
}
/**
* @return the father
*/
NodeContainer getFather() {
return father;
}
/**
* @return the word
*/
List<T> getWord() {
return word;
}
/**
* @return the node
*/
Node<T> getNode() {
return node;
}
}
}