// @(#)$Id: JMLSet.java-generic,v 1.83 2006/12/24 22:35:54 leavens Exp $ // Copyright (C) 2005 Iowa State University // // This file is part of the runtime library of the Java Modeling Language. // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public License // as published by the Free Software Foundation; either version 2.1, // of the License, or (at your option) any later version. // // This library 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 // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with JML; see the file LesserGPL.txt. If not, write to the Free // Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA // 02110-1301 USA. package org.jmlspecs.unfinished; import java.util.Enumeration; import org.jmlspecs.lang.*; import org.jmlspecs.annotation.*; /** Sets of objects. This type uses ".equals" to * compare elements, and does not clone elements that are passed into and * returned from the set's methods. * * <p> * For the purposes of informal specification in the methods below, we * assume there is a model field * <pre>public model mathematical_set theSet;</pre> * that you can think of as a mathematical set of objects. * * @version $Revision: 1.83 $ * @author Gary T. Leavens, with help from Albert Baker, Clyde Ruby, * and others. * @see JMLCollection * @see JMLType * @see JMLObjectSet * @see JMLValueSet * @see JMLEqualsSetEnumerator * * @see JMLObjectBag * @see JMLEqualsBag * @see JMLValueBag */ //-@ immutable // FIXME: adapt this file to non-null-by-default and remove the following modifier. /*@ nullable_by_default @*/ public /*@ pure @*/ class JMLEqualsSet<E> extends JMLAbstractSet<E> { public boolean elem_equals(E e, Object o) { return e == o || (e != null && e.equals(o)); } @Nullable public JMLListEqualsNode<E> the_list() { return the_list; } //*********************** equational theory *********************** /*@ public invariant (\forall JMLEqualsSet<E> s2; s2 != null; @ (\forall Object e1, e2; ; @ equational_theory(this, s2, e1, e2) )); @*/ /** An equational specification of the properties of sets. */ /*@ public normal_behavior @ {| @ // The following are defined by using has and induction. @ @ ensures \result <==> !(new JMLEqualsSet<E>()).has(e1); @ also @ ensures \result <==> @ s.insert(null).has(e2) == (e2 == null || s.has(e2)); @ also @ ensures \result <==> @ (e1 != null @ ==> s.insert(e1).has(e2) @ == (e1.equals(e2) || s.has(e2))); @ also @ ensures \result <==> @ (new JMLEqualsSet<E>()).int_size() == 0; @ also @ ensures \result <==> @ s.insert(e1).int_size() @ == (s.has(e1) ? s.int_size() : s.int_size() + 1); @ also @ ensures \result <==> @ s.isSubset(s2) @ == (\forall Object o; ; s.has(o) ==> s2.has(o)); @ also @ ensures \result <==> @ s.equals(s2) == (s.isSubset(s2) && s2.isSubset(s)); @ also @ ensures \result <==> @ (new JMLEqualsSet<E>()).remove(e1).equals(new JMLEqualsSet<E>()); @ also @ ensures \result <==> @ s.insert(null).remove(e2) @ .equals @ (e2 == null ? s : s.remove(e2).insert(null)); @ also @ ensures \result <==> @ e1 != null @ ==> s.insert(e1).remove(e2) @ .equals @ (e1.equals(e2) @ ? s : s.remove(e2).insert(e1)); @ also @ ensures \result <==> @ (s.union(s2)).has(e1) == (s.has(e1) || s2.has(e1)); @ also @ ensures \result <==> @ (s.intersection(s2)).has(e1) == (s.has(e1) && s2.has(e1)); @ also @ ensures \result <==> @ (s.difference(s2)).has(e1) == (s.has(e1) && !s2.has(e1)); @ @ @ // The following are all defined as abbreviations. @ @ also @ ensures \result <==> @ s.isEmpty() == (s.int_size() == 0); @ also @ ensures \result <==> @ (new JMLEqualsSet<E>(e1)).equals(new JMLEqualsSet<E>().insert(e1)); @ also @ ensures \result <==> @ s.isProperSubset(s2) @ == ( s.isSubset(s2) && !s.equals(s2)); @ also @ ensures \result <==> @ s.isSuperset(s2) == s2.isSubset(s); @ also @ ensures \result <==> @ s.isProperSuperset(s2) == s2.isProperSubset(s); @ |} @ @ implies_that // other ways to specify some operations @ @ ensures \result <==> (new JMLEqualsSet<E>()).isEmpty(); @ @ ensures \result <==> !s.insert(e1).isEmpty(); @ @ ensures \result <==> @ (new JMLEqualsSet<E>(null)).has(e2) == (e2 == null); @ @ ensures \result <==> @ (e1 != null @ ==> new JMLEqualsSet<E>(e1).has(e2) @ == (e1.equals(e2))); @ static public pure model boolean equational_theory(JMLEqualsSet<E> s, JMLEqualsSet<E> s2, E e1, E e2); @*/ //@ public invariant elementType <: \type(E); /*@ public invariant @ (\forall Object o; o != null && has(o); @ \typeof(o) <: elementType); @*/ //@ public invariant containsNull <==> has(null); //@ public invariant_redundantly isEmpty() ==> !containsNull; /** The list representing the elements of this set. */ protected final /*@ nullable @*/ JMLListEqualsNode<E> the_list; //@ in objectState; //@ maps the_list.elementState \into elementState; /** The number of elements in this set. */ /*@ spec_public @*/ protected final int size; //@ in objectState; //@ protected invariant the_list == null ==> size == 0; //@ protected invariant the_list != null ==> size == the_list.int_size(); //@ protected invariant (the_list == null) == (size == 0); //@ protected invariant size >= 0; /*@ protected invariant the_list != null && the_list.next != null ==> @ !the_list.next.has(the_list.val); @*/ //@ protected invariant_redundantly (* the_list has no duplicates *); //@ protected invariant size == 0 ==> !containsNull; //@ public invariant owner == null; //************************* Constructors ******************************** /** Initialize this to be an empty set. * @see #EMPTY */ /*@ public normal_behavior @ assignable objectState, elementType, containsNull, owner; @ ensures this.isEmpty(); @ ensures_redundantly (* this is an empty set *); @ implies_that @ ensures elementType <: \type(Object) && !containsNull; @*/ public JMLEqualsSet() { //@ set owner = null; the_list = null; size = 0; //@ set elementType = \type(E); //@ set containsNull = false; } /** Initialize this to be a singleton set containing the given element. * @see #singleton */ public JMLEqualsSet(E e) /*@ public normal_behavior @ assignable objectState, elementType, containsNull, owner; @ ensures this.has(e) && this.int_size() == 1; @ ensures_redundantly @ (* this is a singleton set containing e *); @*/ { //@ set owner = null; the_list = JMLListEqualsNode<E>.cons(e, null); // cons() clones if needed size = 1; //@ set elementType = (e == null ? \type(Object) : \typeof(e)); //@ set containsNull = (e == null); } /** Initialize this set with the given instance variables. */ //@ requires (ls == null) == (sz == 0); //@ requires sz >= 0; //@ assignable objectState, elementType, containsNull, owner; //@ ensures ls != null ==> elementType == ls.elementType; //@ ensures ls != null ==> containsNull == ls.containsNull; //@ ensures ls == null ==> elementType <: \type(Object); //@ ensures ls == null ==> !containsNull; protected JMLEqualsSet (@Nullable JMLListEqualsNode<E> ls, int sz) { //@ set owner = null; the_list = ls; size = sz; /*@ set elementType = ((ls == null) ? \type(Object) @ : ls.elementType); @*/ //@ set containsNull = ((ls == null) ? false : ls.containsNull); } /** Initialize this set with the given list. */ //@ assignable objectState, elementType, containsNull, owner; //@ ensures ls != null ==> elementType == ls.elementType; //@ ensures ls != null ==> containsNull == ls.containsNull; //@ ensures ls == null ==> elementType <: \type(Object); //@ ensures ls == null ==> !containsNull; protected JMLEqualsSet (@Nullable JMLListEqualsNode<E> ls) { this(ls, (ls == null) ? 0 : ls.int_size()); } //**************************** Static methods **************************** /** The empty JMLEqualsSet. * @see #JMLEqualsSet() */ public static final @NonNull <E> JMLEqualsSet<E> EMPTY() { return new JMLEqualsSet<E>(); } /** Return the singleton set containing the given element. * @see #JMLEqualsSet(Object) */ /*@ public normal_behavior @ ensures \result != null && \result.equals(new JMLEqualsSet(e)); @*/ public static @Pure @NonNull <E> JMLEqualsSet<E> singleton(E e) { return new JMLEqualsSet<E>(e); } /** Return the set containing all the elements in the given array. */ /*@ public normal_behavior @ requires a != null; @ ensures \result != null && \result.int_size() == a.length @ && (\forall int i; 0 <= i && i < a.length; \result.has(a[i])); @*/ public static /*@ pure @*/ /*@ non_null @*/ <E> JMLEqualsSet<E> convertFrom(/*@ non_null @*/ E[] a) { /*@ non_null @*/ JMLEqualsSet<E> ret = new JMLEqualsSet<E>(); for (int i = 0; i < a.length; i++) { ret = ret.insert(a[i]); } return ret; } //@ nowarn Exception; /** Return the set containing all the object in the * given collection. * @throws ClassCastException if some element in c is not an instance of * Object. * @see #containsAll(java.util.Collection) */ /*@ public normal_behavior @ requires c != null @ && (\forall Object o; c.contains(o); @ o == null || (o instanceof Object)); @ requires c.size() < Integer.MAX_VALUE; @ ensures \result != null && \result.int_size() == c.size() @ && (\forall Object x; c.contains(x) <==> \result.has(x)); @ also @ public exceptional_behavior @ requires c != null @ && (\exists Object o; c.contains(o); @ o != null && !(o instanceof Object)); @ signals_only ClassCastException; @*/ public static @Pure @NonNull <E> JMLEqualsSet<E> convertFrom(/*@ non_null @*/ java.util.Collection<E> c) throws ClassCastException { /*@ non_null @*/ JMLEqualsSet<E> ret = JMLEqualsSet.<E>EMPTY(); java.util.Iterator<E> celems = c.iterator(); while (celems.hasNext()) { E o = celems.next(); if (o == null) { ret = ret.insert(null); } else { ret = ret.insert(o); } } return ret; } //@ nowarn Exception; /** Return the set containing all the object in the * given JMLCollection. * @throws ClassCastException if some element in c is not an instance of * Object. */ /*@ public normal_behavior @ requires c != null @ && (c.elementType <: \type(Object)); @ ensures \result != null @ && (\forall Object x; c.has(x) <==> \result.has(x)); @ also @ public exceptional_behavior @ requires c != null && (\exists Object o; c.has(o); @ !(o instanceof Object)); @ signals_only ClassCastException; @*/ public static /*@ pure @*/ /*@ non_null @*/ <E> JMLEqualsSet<E> convertFrom(/*@ non_null @*/ JMLCollection<E> c) throws ClassCastException { /*@ non_null @*/ JMLEqualsSet<E> ret = JMLEqualsSet.<E>EMPTY(); JMLIterator<E> celems = c.iterator(); while (celems.hasNext()) { E o = celems.next(); if (o == null) { ret = ret.insert(null); } else { //@ assume o instanceof Object; ret = ret.insert(o); } } return ret; } //@ nowarn Exception; //**************************** Observers ********************************** /** Tell whether, for each element in the given collection, there is a * ".equals" element in this set. * @param c the collection whose elements are sought. * @see #isSuperset(JMLEqualsSet) * @see #convertFrom(java.util.Collection) */ /*@ public normal_behavior @ requires c != null; @ ensures \result <==> (\forall Object o; c.contains(o); this.has(o)); @*/ public boolean containsAll(/*@ non_null @*/ java.util.Collection<E> c) { java.util.Iterator<E> celems = c.iterator(); while (celems.hasNext()) { E o = celems.next(); if (!has(o)) { return false; } } return true; } /*@ also @ public normal_behavior @ ensures \result <==> @ s2 != null && s2 instanceof JMLEqualsSet @ && (\forall Object e; ; this.has(e) @ == ((JMLEqualsSet)s2).has(e)); @ ensures_redundantly \result ==> @ s2 != null && s2 instanceof JMLEqualsSet @ && containsNull == ((JMLEqualsSet)s2).containsNull; @*/ public boolean equals(/*@ nullable @*/ Object s2) { return (s2 != null && s2 instanceof JMLEqualsSet) && (size == ((JMLEqualsSet)s2).int_size()) && isSubset((JMLEqualsSet)s2); } /** Return a hash code for this object. */ public int hashCode() { if (size == 0) { return 0; } else { int hash = 0xffff; JMLListEqualsNode walker = the_list; while (walker != null) { Object wv = walker.val; if (wv != null) { hash ^= wv.hashCode(); } walker = walker.next; } return hash; } } /** Is the set empty. * @see #int_size() * @see #has(Object) */ /*@ public normal_behavior @ ensures \result == (\forall Object e; ; !this.has(e)); @ also @ protected normal_behavior @ ensures the_list == null <==> \result; @*/ public /*@ pure @*/ boolean isEmpty() { return the_list == null; } /** Tells the number of elements in the set. */ /*@ also @ public normal_behavior @ ensures @ (this.isEmpty() ==> \result == 0) @ && (!this.isEmpty() ==> @ (\exists Object e; this.has(e); @ \result == 1 + (this.remove(e).int_size())) ); @ implies_that @ ensures \result >= 0; @*/ public /*@ pure @*/ int int_size( ) { return size; } /** Tells whether this set is a subset of or equal to the argument. * @see #isProperSubset(JMLEqualsSet) * @see #isSuperset(JMLEqualsSet) */ /*@ public normal_behavior @ requires s2 != null; @ ensures \result <==> @ (\forall Object e; ; this.has(e) ==> s2.has(e)); @*/ public boolean isSubset(/*@ non_null @*/ JMLEqualsSet s2) { if (size > s2.int_size()) { return false; } else { for (JMLListEqualsNode walker = the_list; walker != null; walker = walker.next) { if (!s2.has(walker.val)) { return false; } } //@ assert (\forall Object e; ; this.has(e) ==> s2.has(e)); return true; } } /** Tells whether this set is a subset of but not equal to the * argument. * @see #isSubset(JMLEqualsSet) * @see #isProperSuperset(JMLEqualsSet) */ /*@ public normal_behavior @ requires s2 != null; @ ensures \result <==> @ this.isSubset(s2) && !this.equals(s2); @*/ public boolean isProperSubset(/*@ non_null @*/ JMLEqualsSet s2) { return size < s2.int_size() && isSubset(s2); } /** Tells whether this set is a superset of or equal to the argument. * @see #isProperSuperset(JMLEqualsSet) * @see #isSubset(JMLEqualsSet) * @see #containsAll(java.util.Collection) */ /*@ public normal_behavior @ requires s2 != null; @ ensures \result == s2.isSubset(this); @*/ public boolean isSuperset(/*@ non_null @*/ JMLEqualsSet s2) { return s2.isSubset(this); } /** Tells whether this set is a superset of but not equal to the * argument. * @see #isSuperset(JMLEqualsSet) * @see #isProperSubset(JMLEqualsSet) */ /*@ public normal_behavior @ requires s2 != null; @ ensures \result == s2.isProperSubset(this); @*/ public boolean isProperSuperset(/*@ non_null @*/ JMLEqualsSet s2) { return s2.isProperSubset(this); } /** Return an arbitrary element of this. * @exception JMLNoSuchElementException if this is empty. * @see #isEmpty() * @see #elements() */ /*@ public normal_behavior @ requires !isEmpty(); @ ensures (\exists Object e; this.has(e); @ (\result == null ==> e == null) @ && (\result != null ==> \result.equals(e))); @ also @ public exceptional_behavior @ requires isEmpty(); @ signals_only JMLNoSuchElementException; @ implies_that @ protected behavior @ ensures \result != null ==> \typeof(\result) <: elementType; @ ensures !containsNull ==> \result != null; @ signals_only JMLNoSuchElementException; @ signals (JMLNoSuchElementException) the_list == null; @*/ public Object choose() throws JMLNoSuchElementException { if (the_list != null) { Object entry = the_list.val; if (entry == null) { //@ assume containsNull; return null; } else { Object o = entry; //@ assume o instanceof Object; //@ assume \typeof(o) <: elementType; return (Object) o; } } else { throw new JMLNoSuchElementException("Tried to .choose() " + "with JMLEqualsSet empty"); } } // ****************** building new JMLEqualsSets ************************** /** Return a clone of this object. This method does not clone the * elements of the set. */ /*@ also @ public normal_behavior @ ensures \result != null @ && \result instanceof JMLEqualsSet @ && this.equals(\result); @*/ public /*@ non_null @*/ Object clone() { //@ assume owner == null; return this; } /** Returns a new set that contains all the elements of this and * also the given argument. * @see #has(Object) * @see #remove(Object) */ /*@ @ public normal_behavior @ requires int_size() < Integer.MAX_VALUE || has(elem); @ ensures \result != null @ && (\forall Object e; ; @ \result.has(e) <==> this.has(e) @ || (e == null && elem == null) @ || (e != null && e.equals(elem))); @ ensures_redundantly this.isSubset(\result) && \result.has(elem) @ && \result.int_size() == this.int_size() + (this.has(elem) ? 0 : 1); @ also public normal_behavior @ ensures elem == null ==> \result.containsNull; @ ensures elem != null ==> \result.containsNull == containsNull; @*/ public /*@ non_null @*/ JMLEqualsSet<E> insert(E elem) throws IllegalStateException { if (has(elem)) { return this; } else if (size < Integer.MAX_VALUE) { return fast_insert(elem); } else { throw new IllegalStateException("Cannot insert into a set " +"with Integer.MAX_VALUE elements"); } } /** Returns a new set that contains all the elements of this and * also the given argument, assuming the argument is not in the set. * @see #insert(Object) */ /*@ protected normal_behavior @ requires !has(elem); @ requires int_size() < Integer.MAX_VALUE; @ ensures \result != null @ && (\forall Object e; ; @ \result.has(e) <==> this.has(e) @ || (e == null && elem == null) @ || (e != null && e.equals(elem))); @ ensures_redundantly this.isSubset(\result) && \result.has(elem) @ && \result.int_size() == this.int_size() + 1; @*/ protected /*@ non_null @*/ JMLEqualsSet<E> fast_insert(E elem) { return new JMLEqualsSet<E>( // cons() clones if necessary JMLListEqualsNode<E>.cons(elem, the_list), size+1); } /** Returns a new set that contains all the elements of this except for * the given argument. * @see #has(Object) * @see #insert(Object) */ /*@ public normal_behavior @ ensures \result != null @ && (\forall Object e; ; @ \result.has(e) <==> @ this.has(e) && !((e == null && elem == null) @ || (e != null && e.equals(elem)))); @ ensures_redundantly \result.isSubset(this) && !\result.has(elem) @ && \result.int_size() == this.int_size() - (this.has(elem) ? 1 : 0); @ implies_that @ ensures \result != null @ && (!containsNull ==> !\result.containsNull); @*/ public /*@ non_null @*/ JMLEqualsSet remove(Object elem) { if (!has(elem)) { return this; } else { //@ assume the_list != null; JMLListEqualsNode new_list = the_list.remove(elem); //@ assume (new_list == null) == (size == 1); return new JMLEqualsSet(new_list, size - 1); } } //@ nowarn Post; /** Returns a new set that contains all the elements that are in * both this and the given argument. * @see #union(JMLEqualsSet) * @see #difference(JMLEqualsSet) */ /*@ public normal_behavior @ requires s2 != null; @ ensures \result != null @ && (\forall Object e; ; @ \result.has(e) <==> this.has(e) && s2.has(e)); @ implies_that @ ensures \result != null @ && (!containsNull || !s2.containsNull @ ==> !\result.containsNull); @*/ public /*@ non_null @*/ JMLEqualsSet intersection(/*@ non_null @*/ JMLEqualsSet s2) { JMLEqualsSet returnSet = new JMLEqualsSet(); JMLListEqualsNode thisWalker = the_list; while (thisWalker != null) { if (s2.has(thisWalker.val)) { returnSet = returnSet.fast_insert(thisWalker.val); } thisWalker = thisWalker.next; } return returnSet; } //@ nowarn Post; /** Returns a new set that contains all the elements that are in * either this or the given argument. * @see #intersection(JMLEqualsSet) * @see #difference(JMLEqualsSet) */ /*@ public normal_behavior @ requires s2 != null; @ requires int_size() < Integer.MAX_VALUE - s2.difference(this).int_size(); @ ensures \result != null @ && (\forall Object e; ; @ \result.has(e) <==> this.has(e) || s2.has(e)); @ implies_that @ ensures \result != null @ && (!containsNull && !s2.containsNull @ ==> !\result.containsNull); @*/ public /*@ non_null @*/ JMLEqualsSet<E> union(/*@ non_null @*/ JMLEqualsSet<E> s2) throws IllegalStateException { JMLEqualsSet<E> returnSet = s2; JMLListEqualsNode thisWalker = the_list; while (thisWalker != null) { returnSet = returnSet.insert(thisWalker.val); thisWalker = thisWalker.next; } return returnSet; } //@ nowarn Post; /** Returns a new set that contains all the elements that are in * this but not in the given argument. * @see #union(JMLEqualsSet<E>) * @see #difference(JMLEqualsSet<E>) */ /*@ public normal_behavior @ requires s2 != null; @ ensures \result != null @ && (\forall Object e; ; @ \result.has(e) <==> this.has(e) && !s2.has(e)); @ implies_that @ ensures \result != null @ && (!containsNull ==> !\result.containsNull); @*/ public /*@ non_null @*/ JMLEqualsSet<E> difference(/*@ non_null @*/ JMLEqualsSet<E> s2) { JMLEqualsSet<E> returnSet = new JMLEqualsSet<E>(); JMLListEqualsNode thisWalker = the_list; while (thisWalker != null) { if (!s2.has(thisWalker.val)) { returnSet = returnSet.fast_insert(thisWalker.val); } thisWalker = thisWalker.next; } return returnSet; } //@ nowarn Post; /** Returns a new set that is the set of all subsets of this. * * The implementation is by Tim Wahls. */ /*@ public normal_behavior @ requires int_size() < 32; @ ensures \result != null @ && (\forall JMLEqualsSet s; ; @ s.isSubset(this) <==> \result.has(s)); @ ensures_redundantly \result != null @ && (0 < size && size <= 31 @ ==> \result.int_size() == (2 << (int_size()-1))); @ implies_that @ ensures \result != null && !\result.containsNull; @ for_example @ public normal_example @ requires isEmpty(); @ ensures \result != null && \result.equals(new JMLEqualsSet(EMPTY)); @ ensures_redundantly \result.int_size() == 1; @ also @ public normal_example @ forall Object a, b, c; @ requires this.equals(new JMLEqualsSet<E>(a).insert(b).insert(c)) @ && int_size() == 3; @ ensures \result != null && \result.int_size() == 8 @ && \result.has(EMPTY) @ && \result.has(new JMLEqualsSet<E>(a)) @ && \result.has(new JMLEqualsSet<E>(b)) @ && \result.has(new JMLEqualsSet<E>(c)) @ && \result.has(new JMLEqualsSet<E>(a).insert(b)) @ && \result.has(new JMLEqualsSet<E>(a).insert(c)) @ && \result.has(new JMLEqualsSet<E>(b).insert(c)) @ && \result.has(new JMLEqualsSet<E>(a).insert(b).insert(c)); @*/ public /*@ non_null @*/ JMLEqualsSet<E> powerSet() throws IllegalStateException { if (size >= 32) { throw new IllegalStateException("Can't compute the powerSet " + "of such a large set"); } // This a dynamic programming algorithm. /*@ non_null @*/ JMLEqualsSet<E> ret = new JMLEqualsSet<E>(JMLEqualsSet<E>.EMPTY); // added is used to make the loop invariant easier to state. JMLEqualsSet<E> added = new JMLEqualsSet<E>(); Enumeration elems = elements(); //@ loop_invariant !ret.containsNull; /*@ maintaining added.isSubset(this) && ret.size >= 1 @ && (\forall JMLEqualsSet<E> s; s.isSubset(added); ret.has(s)); @ decreasing int_size()-added.int_size(); @*/ while (elems.hasMoreElements()) { Object cur = elems.nextElement(); Enumeration size_i_and_smaller_subsets = ret.elements(); while (size_i_and_smaller_subsets.hasMoreElements()) { JMLEqualsSet<E> subset = (JMLEqualsSet<E>) size_i_and_smaller_subsets.nextElement(); if (cur == null) { ret = ret.insert(subset.insert(null)); } else { ret = ret.insert(subset.insert((Object)cur)); } } added = added.insert((Object)cur); } return ret; } /** Return a new JMLEqualsBag containing all the elements of this. * @see #toSequence() */ /*@ public normal_behavior @ ensures \result != null @ && (\forall Object o;; @ \result.count(o) == 1 <==> this.has(o)); @ implies_that @ ensures \result != null && (containsNull <==> \result.containsNull); @*/ public /*@ non_null @*/ JMLEqualsBag toBag() { JMLEqualsBag ret = new JMLEqualsBag(); JMLEqualsSetEnumerator elems = elements(); while (elems.hasMoreElements()) { //@ assume elems.moreElements; Object o = elems.nextElement(); Object e = (o == null ? null : o); ret = ret.insert(e); } return ret; } //@ nowarn Exception, Post; /** Return a new JMLEqualsSequence containing all the elements of this. * @see #toBag() * @see #toArray() */ /*@ public normal_behavior @ ensures \result != null @ && (\forall Object o;; @ \result.count(o) == 1 <==> this.has(o)); @ implies_that @ ensures \result != null && (containsNull <==> \result.containsNull); @*/ public /*@ non_null @*/ JMLEqualsSequence toSequence() { JMLEqualsSequence ret = new JMLEqualsSequence(); JMLEqualsSetEnumerator elems = elements(); while (elems.hasMoreElements()) { //@ assume elems.moreElements; Object o = elems.nextElement(); Object e = (o == null ? null : o); ret = ret.insertFront(e); } return ret; } //@ nowarn Exception, Post; /** Return a new array containing all the elements of this. * @see #toSequence() */ /*@ public normal_behavior @ ensures \result != null && \result.length == int_size() @ && (\forall Object o;; @ JMLArrayOps.hasValueEquals(\result, o) <==> has(o)); @ ensures_redundantly \result != null && \result.length == int_size() @ && (\forall int i; 0 <= i && i < \result.length; @ JMLArrayOps.hasValueEquals(\result, \result[i]) @ == has(\result[i])); @ implies_that @ ensures \result != null @ && (containsNull <==> !\nonnullelements(\result)); @*/ public /*@ non_null @*/ Object[] toArray() { Object[] ret = new Object[int_size()]; JMLEqualsSetEnumerator elems = elements(); int i = 0; //@ loop_invariant 0 <= i && i <= ret.length; while (elems.hasMoreElements()) { //@ assume elems.moreElements && i < ret.length; Object o = elems.nextElement(); if (o == null) { ret[i] = null; } else { Object e = o; ret[i] = e; } i++; } return ret; } //@ nowarn Exception, Post; //********************** Tools Methods ********************************* // The elements and toString methods are of no value for writing // assertions in JML. They are included for the use of developers // of CASE tools based on JML, e.g., type checkers, assertion // evaluators, prototype generators, test tools, ... . They can // also be used in model programs in specifications. /** Returns an Enumeration over this set. * @see #iterator() */ /*@ public normal_behavior @ ensures \fresh(\result) && this.equals(\result.uniteratedElems); @ implies_that @ ensures \result != null @ && (containsNull == \result.returnsNull); @*/ public /*@ non_null @*/ JMLEqualsSetEnumerator<E> elements() { return new JMLEqualsSetEnumerator(this); } /** Returns an Iterator over this set. * @see #elements() */ /*@ also @ public normal_behavior @ ensures \fresh(\result) @ && \result.equals(new JMLEnumerationToIterator(elements())); @*/ public /*@ non_null @*/ JMLIterator<E> iterator() { return new JMLEnumerationToIterator<E>(elements()); } //@ nowarn Post; }