package com.framsticks.util.dispatching; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Set; import com.framsticks.core.Entity; import com.framsticks.params.annotations.AutoAppendAnnotation; import com.framsticks.params.annotations.FramsClassAnnotation; import com.framsticks.util.FramsticksException; import com.framsticks.util.Misc; @FramsClassAnnotation public class JoinableCollection extends AbstractJoinable implements JoinableParent, Iterable { protected final Set joinables = new HashSet(); protected final Map namedJoinables = new HashMap<>(); protected boolean finishIfOne; protected String observableName; public JoinableCollection() { this(false); } public JoinableCollection(boolean finishIfOne) { this.finishIfOne = finishIfOne; } @AutoAppendAnnotation public void add(T joinable) { assert isInState(JoinableState.INITILIAZED); if (joinables.contains(joinable)) { throw new FramsticksException().msg("joinable is already observed").arg("joinable", joinable).arg("in", this); } // if (observables.containsKey(observable.getName())) { // throw new FramsticksException().msg("observable with given name already exists").arg("name", observable.getName()).arg("in", this); // } if (joinable instanceof Entity) { Entity e = (Entity) joinable; if (!namedJoinables.containsKey(e.getName())) { namedJoinables.put(e.getName(), joinable); } } joinables.add(joinable); } @Override protected void joinableStart() { for (T j : joinables) { Dispatching.use(j, this); } } @Override protected void joinableInterrupt() { if (joinables.isEmpty()) { finish(); return; } for (T j : joinables) { Dispatching.drop(j, this); } } @Override protected void joinableFinish() { } @Override protected void joinableJoin() throws InterruptedException { for (T j : joinables) { Dispatching.join(j); } } protected JoinableState getNextState() { if (joinables.isEmpty()) { return state; } JoinableState result = finishIfOne ? JoinableState.INITILIAZED : JoinableState.JOINED; for (Joinable j : joinables) { JoinableState s = j.getState(); if (finishIfOne) { if (s.ordinal() > result.ordinal()) { result = s; } } else { if (s.ordinal() < result.ordinal()) { result = s; } } } return result; } @Override public void childChangedState(Joinable joinable, JoinableState state) { proceedToState(getNextState()); } @Override public Iterator iterator() { return Collections.unmodifiableSet(joinables).iterator(); } @Override public String toString() { return Misc.returnNotNull(observableName, "collection"); } /** * @param observableName the observableName to set */ public JoinableCollection setObservableName(String observableName) { this.observableName = observableName; return this; } public T get(String name) { return namedJoinables.get(name); } public Map getObservables() { return Collections.unmodifiableMap(namedJoinables); } }