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