package greenfoot;

import threadchecker.OnThread;
import threadchecker.Tag;

import java.util.*;


| A set which allows specifying iteration order according to class of contained | objects. | | <p>TreeActorSet is really an ordered "set of sets". Each set corresponds to |* a class; any actors of that class are put in the set, along with any actors * of subclasses as long as there isn't a more appropriate set for them. * * @author Davin McCall public class TreeActorSet extends AbstractSet<Actor>{ private List<ActorSet> subSets;
| ActorSet for objects of a class without a specific z-order | private ActorSet generalSet; private HashMap<Class<?>, ActorSet> classSets;
| Construct an empty TreeActorSet. | public TreeActorSet() { subSets = new LinkedList<ActorSet>(); generalSet = new ActorSet(); subSets.add(generalSet); classSets = new HashMap<Class<?>, ActorSet>(); }
| Set the iteration order of objects. The first given class will have | objects of its class last in the iteration order, the next will have | objects second last in iteration order, and so on. This hold if it is | reversed. If it is not reversed it will return the first one first and so | on. | | Objects not belonging to any of the specified classes will be first in | the iteration order if reversed, or last if not reversed | | @param reverse | Whether to reverse the order or not. | public void setClassOrder(boolean reverse, Class<?> ... classes) { HashMap<Class<?>, ActorSet> oldClassSets = classSets; classSets = new HashMap<Class<?>, ActorSet>(); LinkedList<Class<?>> sweepClasses = new LinkedList<Class<?>>(); for (int i = 0; i < classes.length; i++) { ActorSet oldSet = oldClassSets.remove(classes[i]); if (oldSet == null) { sweepClasses.add(classes[i]); oldSet = new ActorSet(); } classSets.put(classes[i], oldSet); } Set<Class<?>> sweptClasses = new HashSet<Class<?>>(); while (! sweepClasses.isEmpty()){ Class<?> sweepClass = sweepClasses.removeFirst().getSuperclass(); ActorSet sweepSet = classSets.get(sweepClass); while (sweepSet == null){ sweepClass = sweepClass.getSuperclass(); if (sweepClass == null) { sweepSet = generalSet; } else { sweepSet = classSets.get(sweepClass); } } if (! sweptClasses.contains(sweepClass)) { sweptClasses.add(sweepClass); Iterator<Actor> i = sweepSet.iterator(); while (i.hasNext()){ Actor actor = i.next(); ActorSet set = setForActor(actor); if (set != sweepSet) { set.add(actor); i.remove(); } } } } Iterator<Map.Entry<Class<?>,ActorSet>> ei = oldClassSets.entrySet().iterator(); for ( ; ei.hasNext(); ) { Map.Entry<Class<?>,ActorSet> entry = ei.next(); ActorSet destinationSet = setForClass(entry.getKey()); destinationSet.addAll(entry.getValue()); } subSets.clear(); if (reverse) { subSets.add(generalSet); for (int i = classes.length; i > 0; ) { subSets.add(classSets.get(classes[--i])); } } else { for (int i = 0; i < classes.length; i++) { subSets.add(classSets.get(classes[i])); } subSets.add(generalSet); } } @OnThread(value = Tag.Simulation, ignoreParent = true) public Iterator iterator() { return new TasIterator(); } @OnThread(value = Tag.Simulation, ignoreParent = true) @Override public int size() { int size = 0; for (Iterator<ActorSet> i = subSets.iterator(); i.hasNext(); ) { size += i.next().size(); } return size; } @OnThread(value = Tag.Simulation, ignoreParent = true) @Override public boolean add(Actor o) { if (o == null) { throw new UnsupportedOperationException("Cannot add null actor."); } return setForActor(o).add(o); } public boolean remove(Actor o) { return setForActor(o).remove(o); } @OnThread(value = Tag.Simulation, ignoreParent = true) public boolean contains(Actor o) { return setForActor(o).containsActor(o); }
| Get the actor set for a particular actor, depending on its class. | private ActorSet setForActor(Actor o) { Class<?> oClass = o.getClass(); return setForClass(oClass); } private ActorSet setForClass(Class<?> oClass) { ActorSet set = classSets.get(oClass); while (set == null && oClass != Object.class){ oClass = oClass.getSuperclass(); set = classSets.get(oClass); } if (set == null) { set = generalSet; } return set; }
| An iterator for a TreeActorSet | | @author Davin McCall | @OnThread(Tag.Simulation) class TasIterator implements Iterator<Actor> { private Iterator<ActorSet> setIterator; private ActorSet currentSet; private Iterator<Actor> actorIterator; public TasIterator() { setIterator = subSets.iterator(); currentSet = setIterator.next(); while (currentSet.isEmpty() && setIterator.hasNext()){ currentSet = setIterator.next(); } actorIterator = currentSet.iterator(); } @OnThread(value = Tag.Simulation, ignoreParent = true) public void remove() { actorIterator.remove(); } @OnThread(value = Tag.Simulation, ignoreParent = true) public Actor next() { hasNext(); return actorIterator.next(); } @OnThread(value = Tag.Simulation, ignoreParent = true) public boolean hasNext() { if (actorIterator.hasNext()) { return true; } if (! setIterator.hasNext()) { return false; } while (setIterator.hasNext()){ currentSet = setIterator.next(); if (! currentSet.isEmpty()) { break; } } actorIterator = currentSet.iterator(); return actorIterator.hasNext(); } } }

.   TreeActorSet
.   setClassOrder
.   iterator
.   size
.   add
.   remove
.   contains
.   setForActor
.   setForClass
.   TasIterator
.   remove
.   next
.   hasNext




297 neLoCode + 17 LoComm