package org.scribble.del.global;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.scribble.ast.Module;
import org.scribble.ast.ScribNode;
import org.scribble.ast.context.DependencyMap;
import org.scribble.ast.context.global.GProtocolDeclContext;
import org.scribble.ast.global.GProtocolDecl;
import org.scribble.ast.local.LProtocolDecl;
import org.scribble.ast.local.LProtocolDef;
import org.scribble.del.ModuleDel;
import org.scribble.del.ProtocolDeclDel;
import org.scribble.main.Job;
import org.scribble.main.JobContext;
import org.scribble.main.ScribbleException;
import org.scribble.model.global.SGraph;
import org.scribble.sesstype.kind.Global;
import org.scribble.sesstype.name.GProtocolName;
import org.scribble.sesstype.name.ProtocolName;
import org.scribble.sesstype.name.Role;
import org.scribble.visit.context.Projector;
import org.scribble.visit.context.ProtocolDeclContextBuilder;
import org.scribble.visit.context.env.ProjectionEnv;
import org.scribble.visit.util.RoleCollector;
import org.scribble.visit.validation.GProtocolValidator;
public class GProtocolDeclDel extends ProtocolDeclDel<Global>
{
public GProtocolDeclDel()
{
}
@Override
public GProtocolDeclContext getProtocolDeclContext()
{
return (GProtocolDeclContext) super.getProtocolDeclContext();
}
@Override
protected GProtocolDeclDel copy()
{
return new GProtocolDeclDel();
}
@Override
protected void addSelfDependency(ProtocolDeclContextBuilder builder, ProtocolName<?> proto, Role role)
{
builder.addGlobalProtocolDependency(role, (GProtocolName) proto, role);
}
@Override
public GProtocolDecl
leaveProtocolDeclContextBuilding(ScribNode parent, ScribNode child, ProtocolDeclContextBuilder builder, ScribNode visited) throws ScribbleException
{
GProtocolDecl gpd = (GProtocolDecl) visited;
GProtocolDeclContext gcontext = new GProtocolDeclContext(builder.getGlobalProtocolDependencyMap());
GProtocolDeclDel del = (GProtocolDeclDel) setProtocolDeclContext(gcontext);
return (GProtocolDecl) gpd.del(del);
}
@Override
public ScribNode leaveRoleCollection(ScribNode parent, ScribNode child, RoleCollector coll, ScribNode visited) throws ScribbleException
{
GProtocolDecl gpd = (GProtocolDecl) visited;
// Need to do here (e.g. RoleDeclList too early, def not visited yet)
// Currently only done for global, local does roledecl fixing after role collection -- should separate this check to a later pass after context building
// Maybe relax to check only occs.size() > 1
List<Role> decls = gpd.header.roledecls.getRoles();
Set<Role> occs = coll.getNames();
if (occs.size() != decls.size())
{
decls.removeAll(occs);
throw new ScribbleException(gpd.header.roledecls.getSource(), "Unused role decl(s) in " + gpd.header.name + ": " + decls);
}
return super.leaveRoleCollection(parent, child, coll, gpd);
}
@Override
public GProtocolDecl
leaveProjection(ScribNode parent, ScribNode child, Projector proj, ScribNode visited) throws ScribbleException
{
Module root = proj.job.getContext().getModule(proj.getModuleContext().root);
GProtocolDecl gpd = (GProtocolDecl) visited;
Role self = proj.peekSelf();
LProtocolDef def = (LProtocolDef) ((ProjectionEnv) gpd.def.del().env()).getProjection();
LProtocolDecl lpd = gpd.project(root, self, def); // FIXME: is root (always) the correct module? (wrt. LProjectionDeclDel?)
Map<GProtocolName, Set<Role>> deps = ((GProtocolDeclDel) gpd.del()).getGlobalProtocolDependencies(self);
Module projected = ((ModuleDel) root.del()).createModuleForProjection(proj, root, gpd, lpd, deps);
proj.addProjection(gpd.getFullMemberName(root), self, projected);
return gpd;
}
private Map<GProtocolName, Set<Role>> getGlobalProtocolDependencies(Role self)
{
DependencyMap<GProtocolName> deps = getProtocolDeclContext().getDependencyMap();
return deps.getDependencies().get(self);
}
@Override
public void enterValidation(ScribNode parent, ScribNode child, GProtocolValidator checker) throws ScribbleException
{
GProtocolDecl gpd = (GProtocolDecl) child;
if (gpd.isAuxModifier())
{
return;
}
GProtocolName fullname = gpd.getFullMemberName((Module) parent);
validate(checker.job, fullname, true);
if (!checker.job.fair)
{
checker.job.debugPrintln("(" + fullname + ") Validating with \"unfair\" output choices.. ");
validate(checker.job, fullname, false); // FIXME: only need to check progress, not full validation
}
}
private static void validate(Job job, GProtocolName fullname, boolean fair) throws ScribbleException
{
JobContext jc = job.getContext();
SGraph graph = (fair) ? jc.getSGraph(fullname) : jc.getUnfairSGraph(fullname);
graph.toModel().validate(job);
}
}