/** * Fortika - Robust Group Communication * Copyright (C) 2002-2006 Sergio Mena de la Cruz (EPFL) (sergio.mena@epfl.ch) * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ package framework; import java.io.IOException; import java.util.LinkedList; import uka.transport.DeepClone; import uka.transport.MarshalStream; import uka.transport.Transportable; import uka.transport.UnmarshalStream; /** * Stores a set of compressable object * The set takes up only a small constant amount * of memory: if possible only lower and upper * limits are memorized. */ public class CompressedSet implements Transportable { // Limit is used to store a set of objects // that fullfilled the space between the inf limit // and the sup limit private static class Limit { public Compressable inf; public Compressable sup; public Limit(Compressable inf, Compressable sup) { this.inf = inf; this.sup = sup; } public String toString() { return new String("[ " + inf.toString() + " - " + sup.toString() + " ]"); } } // The limits describing all the objects contained // in the compressed Set private LinkedList allLimitsByClass; public CompressedSet() { allLimitsByClass = new LinkedList(); } /** * Add an element to the compressed Set. * * @param comp the element to add */ public void add(Compressable comp) { int sizeAllLimitsByClass = allLimitsByClass.size(); for (int i = 0; i < sizeAllLimitsByClass; i++) { LinkedList allLimits = (LinkedList) allLimitsByClass.get(i); if (((Limit) allLimits.getFirst()).inf.compareToCompressable(comp) != Compressable.NOT_COMPARABLE) { int sizeAllLimits = allLimits.size(); boolean lastLimitModified = false; // ASSERT: The Limits are sorted by type and from // the smallest to the biggest. for (int j = 0; j < sizeAllLimits; j++) { Limit limit = (Limit) allLimits.get(j); int resInf = comp.compareToCompressable(limit.inf); int resSup = comp.compareToCompressable(limit.sup); if (resInf == Compressable.SMALLER && !lastLimitModified) { allLimits.add(j, new Limit(comp, comp)); return; } if (resInf == Compressable.PREDECESSOR) { limit.inf = comp; if (lastLimitModified) { ((Limit) allLimits.get(j - 1)).sup = limit.sup; allLimits.remove(j); } return; } if (lastLimitModified || ((resInf >= Compressable.EQUAL) && (resSup <= Compressable.EQUAL))) return; if (resSup == Compressable.SUCCESSOR) { limit.sup = comp; lastLimitModified = true; } // If comp is bigger than superior limit of the last Limit // add a new Limit if ((resSup == Compressable.BIGGER) && (j+1 == sizeAllLimits)) allLimits.addLast(new Limit(comp, comp)); } return; } } // If the following instructions are executed, this means // that there is no list with Limits for the type of Comp // Below, we create such a list LinkedList allLimits = new LinkedList(); allLimits.addLast(new Limit(comp, comp)); allLimitsByClass.addLast(allLimits); } public boolean contains(Compressable comp) { int sizeAllLimitsByClass = allLimitsByClass.size(); for (int i = 0; i < sizeAllLimitsByClass; i++) { LinkedList allLimits = (LinkedList) allLimitsByClass.get(i); if (((Limit) allLimits.getFirst()).inf.compareToCompressable(comp) != Compressable.NOT_COMPARABLE) { int sizeAllLimits = allLimits.size(); for (int j = 0; j < sizeAllLimits; j++) { Limit limit = (Limit) allLimits.get(j); int resInf = limit.inf.compareToCompressable(comp); int resSup = limit.sup.compareToCompressable(comp); if ((resInf <= Compressable.EQUAL) && (resSup >= Compressable.EQUAL)) return true; } return false; } } return false; } public String toString(){ String result = new String(); int size = allLimitsByClass.size(); for (int i=0;i<size;i++) result = new String(result + allLimitsByClass.get(i)+"\n"); return result; } public void marshal(MarshalStream arg0) throws IOException { throw new RuntimeException("Not supported by CompressedSet"); } public void unmarshalReferences(UnmarshalStream arg0) throws IOException, ClassNotFoundException { throw new RuntimeException("Not supported by CompressedSet"); } public Object deepClone(DeepClone arg0) throws CloneNotSupportedException { throw new RuntimeException("Not supported by CompressedSet"); } }