/* * This file is part of JOP, the Java Optimized Processor * see <http://www.jopdesign.com/> * * Copyright (C) 2010, Benedikt Huber <benedikt.huber@gmail.com> * * 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 com.jopdesign.dfa.framework; import java.io.Serializable; import java.util.LinkedHashSet; import java.util.Set; /** * Factory for sets with a maximum size N. * For every bound N, there is one factory, and one top element. * * @author Benedikt Huber <benedikt.huber@gmail.com> */ public class BoundedSetFactory<V> { private int limit; private BoundedSet<V> top; public BoundedSetFactory(int limit) { this.limit = limit; BoundedSetImpl topset = new BoundedSetImpl(); topset.isSaturated = true; this.top = topset; } public BoundedSet<V> empty() { return new BoundedSetImpl(); } public BoundedSet<V> singleton(V el) { BoundedSetImpl bs = new BoundedSetImpl(); bs.add(el); return bs; } public BoundedSet<V> top() { return top; } public interface BoundedSet<V> { BoundedSet<V> newBoundedSet(); void add(V el); void addAll(BoundedSet<V> other); BoundedSet<V> join(BoundedSet<V> other); boolean isSaturated(); /** precondition: not (isTop()) */ Set<V> getSet(); int getSize(); boolean isSubset(BoundedSet<V> otherEntry); int getLimit(); } /** * Implementation for sets with a maximum size N. * * @author Benedikt Huber <benedikt.huber@gmail.com> */ public class BoundedSetImpl implements BoundedSet<V>, Serializable { private static final long serialVersionUID = 1L; private Set<V> setImpl; private boolean isSaturated; public BoundedSetImpl() { setImpl = new LinkedHashSet<V>(); } private BoundedSetImpl(LinkedHashSet<V> set) { if(set.size() > limit) { this.isSaturated = true; } else { setImpl = set; } } public void add(V el) { if(this.isSaturated()) return; setImpl.add(el); if(setImpl.size() > limit) { setTop(); } } public void addAll(BoundedSet<V> other) { if(this.isSaturated()) return; if(other.isSaturated()) { setTop(); return; } setImpl.addAll(other.getSet()); if(setImpl.size() > limit) { setTop(); } } public BoundedSet<V> join(BoundedSet<V> other) { if(this.isSaturated()) return this; else if(other != null && other.isSaturated()) return other; LinkedHashSet<V> joinedSet = new LinkedHashSet<V>(); joinedSet.addAll(this.getSet()); if(other!=null) joinedSet.addAll(other.getSet()); BoundedSetImpl r = new BoundedSetImpl(joinedSet); return r; } public Set<V> getSet() { return setImpl; } public boolean isSaturated() { return this.isSaturated; } private void setTop() { this.isSaturated = true; this.setImpl = null; } public int getSize() { if(setImpl.size() > limit) { throw new AssertionError("Bounded Set exceeded size: "+setImpl.size()); } if(isSaturated) return limit+1; else return setImpl.size(); } public int getLimit() { return limit; } @Override public int hashCode() { if(isSaturated) return 1; else return 2 + setImpl.hashCode(); } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; BoundedSetImpl other = (BoundedSetImpl) obj; if(this.isSaturated) return other.isSaturated; if(this.getSize() != other.getSize()) return false; else return setImpl.equals(other.setImpl); } public boolean isSubset(BoundedSet<V> otherEntry) { if(otherEntry.isSaturated()) return true; else if(this.isSaturated()) return false; return otherEntry.getSet().containsAll(this.getSet()); } @Override public String toString() { if(this.isSaturated) return "BoundedSet.TOP"; return this.setImpl.toString(); } public BoundedSet<V> newBoundedSet() { return new BoundedSetImpl(new LinkedHashSet<V>()); } } }