package org.scribble.model.global;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.scribble.model.MState;
import org.scribble.model.MPrettyState;
import org.scribble.model.endpoint.EState;
import org.scribble.model.endpoint.actions.EAction;
import org.scribble.model.endpoint.actions.EReceive;
import org.scribble.model.endpoint.actions.ESend;
import org.scribble.model.global.actions.SAction;
import org.scribble.sesstype.kind.Global;
import org.scribble.sesstype.name.Role;
// FIXME? make a WFModel front-end class? (cf. EGraph)
// Only uses MState.id cosmetically, cf. MState equals/hash -- overrides equals/hash based on this.config (maybe extending MState is a bit misleading)
public class SState extends MPrettyState<Void, SAction, SState, Global>
{
public final SConfig config;
// Unlike EState, SGraph is not just a "simple wrapper" for an existing graph of nodes -- it is a "semantic structure" that needs to be fully built properly (so no arbitrary "toGraph" method; cf., EState)
protected SState(SConfig config)
{
super(Collections.emptySet());
this.config = config;
}
// Based on config semantics, not "static" graph edges (cf., super.getAllActions) -- used to build global model graph
public Map<Role, List<EAction>> getFireable()
{
return this.config.getFireable();
}
public List<SConfig> fire(Role r, EAction a)
{
return this.config.fire(r, a);
}
// "Synchronous version" of fire
public List<SConfig> sync(Role r1, EAction a1, Role r2, EAction a2)
{
return this.config.sync(r1, a1, r2, a2);
}
public SStateErrors getErrors()
{
Map<Role, EReceive> stuck = this.config.getStuckMessages();
Set<Set<Role>> waitfor = this.config.getWaitForErrors();
//Set<Set<Role>> waitfor = Collections.emptySet();
Map<Role, Set<ESend>> orphs = this.config.getOrphanMessages();
Map<Role, EState> unfinished = this.config.getUnfinishedRoles();
return new SStateErrors(stuck, waitfor, orphs, unfinished);
}
@Override
protected String getNodeLabel()
{
String labs = this.config.toString();
return "label=\"" + this.id + ":" + labs.substring(1, labs.length() - 1) + "\"";
}
// FIXME? doesn't use super.hashCode (cf., equals)
@Override
public final int hashCode()
{
int hash = 79;
//int hash = super.hashCode();
hash = 31 * hash + this.config.hashCode();
return hash;
}
// FIXME? doesn't use this.id, cf. super.equals
// Not using id, cf. ModelState -- FIXME? use a factory pattern that associates unique states and ids? -- use id for hash, and make a separate "semantic equals"
// Care is needed if hashing, since mutable (OK to use immutable config -- cf., ModelState.id)
@Override
public boolean equals(Object o)
{
if (this == o)
{
return true;
}
if (!(o instanceof SState))
{
return false;
}
return ((SState) o).canEquals(this) && this.config.equals(((SState) o).config);
}
@Override
protected boolean canEquals(MState<?, ?, ?, ?> s)
{
return s instanceof SState;
}
@Override
public String toString()
{
return this.id + ":" + this.config.toString();
}
}