package jetbrains.mps.make.script;
/*Generated by MPS */
import org.apache.log4j.Logger;
import org.apache.log4j.LogManager;
import java.util.Set;
import jetbrains.mps.make.facet.IFacet;
import jetbrains.mps.internal.collections.runtime.SetSequence;
import java.util.HashSet;
import jetbrains.mps.make.facet.ITarget;
import java.util.List;
import jetbrains.mps.internal.make.runtime.script.ValidationError;
import jetbrains.mps.internal.collections.runtime.ListSequence;
import java.util.ArrayList;
import jetbrains.mps.internal.collections.runtime.Sequence;
import java.util.Map;
import jetbrains.mps.internal.make.runtime.script.InvalidScript;
import jetbrains.mps.internal.collections.runtime.MapSequence;
import java.util.HashMap;
import jetbrains.mps.internal.make.runtime.script.TargetRange;
import jetbrains.mps.internal.make.runtime.script.Script;
import jetbrains.mps.make.facet.FacetRegistry;
import jetbrains.mps.internal.collections.runtime.ITranslator2;
import jetbrains.mps.internal.collections.runtime.IMapping;
import jetbrains.mps.internal.make.runtime.util.GraphAnalyzer;
import jetbrains.mps.internal.collections.runtime.ISelector;
public class ScriptBuilder {
private static Logger LOG = LogManager.getLogger(ScriptBuilder.class);
private Set<IFacet.Name> facets = SetSequence.fromSet(new HashSet<IFacet.Name>());
private Set<ITarget.Name> requestedTargets = SetSequence.fromSet(new HashSet<ITarget.Name>());
private ITarget.Name finalTarget;
private ITarget.Name startingTarget;
private List<ValidationError> errors = ListSequence.fromList(new ArrayList<ValidationError>());
public ScriptBuilder() {
}
public ScriptBuilder withFacetName(IFacet.Name facetName) {
SetSequence.fromSet(facets).addElement(facetName);
return this;
}
public ScriptBuilder withFacetNames(IFacet.Name... facetNames) {
return withFacetNames(Sequence.fromArray(facetNames));
}
public ScriptBuilder withFacetNames(Iterable<IFacet.Name> facetNames) {
SetSequence.fromSet(facets).addSequence(Sequence.fromIterable(facetNames));
return this;
}
public ScriptBuilder withAuxTarget(ITarget.Name targetName) {
if (targetName == null) {
throw new NullPointerException();
}
SetSequence.fromSet(requestedTargets).addElement(targetName);
return this;
}
public ScriptBuilder withStartingTarget(ITarget.Name targetName) {
if (targetName == null) {
throw new NullPointerException();
}
SetSequence.fromSet(requestedTargets).addElement(targetName);
this.startingTarget = targetName;
return this;
}
public ScriptBuilder withFinalTarget(ITarget.Name targetName) {
if (targetName == null) {
throw new NullPointerException();
}
SetSequence.fromSet(requestedTargets).addElement(targetName);
this.finalTarget = targetName;
return this;
}
public IScript toScript() {
Map<IFacet.Name, IFacet> facetsView = collectFacets();
if (ListSequence.fromList(errors).isNotEmpty()) {
return new InvalidScript(errors);
}
final Map<IFacet.Name, ScriptBuilder.FacetRefs> refs = MapSequence.fromMap(new HashMap<IFacet.Name, ScriptBuilder.FacetRefs>());
this.collectRefs(refs, facetsView);
if (ListSequence.fromList(errors).isNotEmpty()) {
return new InvalidScript(errors);
}
Iterable<IFacet.Name> sortedFacets = this.toposortByExtended(refs, facetsView);
if (ListSequence.fromList(errors).isNotEmpty()) {
return new InvalidScript(errors);
}
TargetRange tr = new TargetRange();
this.collectTargets(sortedFacets, tr, facetsView);
if (ListSequence.fromList(errors).isNotEmpty()) {
return new InvalidScript(errors);
}
Script sc = new Script(tr, finalTarget, startingTarget);
sc.validate();
return sc;
}
private Map<IFacet.Name, IFacet> collectFacets() {
Map<IFacet.Name, IFacet> facetsView = MapSequence.fromMap(new HashMap<IFacet.Name, IFacet>());
for (IFacet.Name fn : SetSequence.fromSet(facets)) {
IFacet fct = FacetRegistry.getInstance().lookup(fn);
if (fct != null) {
MapSequence.fromMap(facetsView).put(fn, fct);
} else {
String msg = "facet not found: " + fn;
error(fn, msg);
}
}
if (SetSequence.fromSet(facets).isEmpty()) {
error(null, "No make facets found, nothing to make. This may have been caused by a language module failed to load.");
}
return facetsView;
}
private void collectTargets(Iterable<IFacet.Name> sortedFacets, TargetRange tr, final Map<IFacet.Name, IFacet> facetsView) {
List<ITarget> allTargets = ListSequence.fromList(Sequence.fromIterable(sortedFacets).translate(new ITranslator2<IFacet.Name, ITarget>() {
public Iterable<ITarget> translate(IFacet.Name fname) {
return MapSequence.fromMap(facetsView).get(fname).targets();
}
}).toListSequence()).reversedList();
for (ITarget trg : ListSequence.fromList(allTargets)) {
if (SetSequence.fromSet(requestedTargets).contains(trg.getName())) {
tr.addTarget(trg);
}
}
for (ITarget.Name tn : SetSequence.fromSet(requestedTargets)) {
if (!(tr.hasTarget(tn))) {
error(tn, "target not found: " + tn);
}
}
if (ListSequence.fromList(errors).isNotEmpty()) {
return;
}
tr.addRelatedPrecursors(Sequence.fromIterable(MapSequence.fromMap(facetsView).values()).translate(new ITranslator2<IFacet, ITarget>() {
public Iterable<ITarget> translate(IFacet fct) {
return fct.targets();
}
}));
}
private void collectRefs(final Map<IFacet.Name, ScriptBuilder.FacetRefs> refs, Map<IFacet.Name, IFacet> facetsView) {
for (IFacet fct : Sequence.fromIterable(MapSequence.fromMap(facetsView).values())) {
ScriptBuilder.FacetRefs facetRefs = new ScriptBuilder.FacetRefs(facetsView);
facetRefs.collect(fct);
MapSequence.fromMap(refs).put(fct.getName(), facetRefs);
}
}
private Iterable<IFacet.Name> toposortByExtended(final Map<IFacet.Name, ScriptBuilder.FacetRefs> refs, Map<IFacet.Name, IFacet> facetsView) {
for (IMapping<IFacet.Name, ScriptBuilder.FacetRefs> m : SetSequence.fromSet(MapSequence.fromMap(refs).mappingsSet())) {
IFacet fct = MapSequence.fromMap(facetsView).get(m.key());
for (IFacet ex : ListSequence.fromList(m.value().extended)) {
ListSequence.fromList(MapSequence.fromMap(refs).get(ex.getName()).extendedBy).addElement(fct);
}
}
GraphAnalyzer<IFacet.Name> ga = new GraphAnalyzer<IFacet.Name>() {
@Override
public Iterable<IFacet.Name> forwardEdges(IFacet.Name v) {
return ListSequence.fromList(MapSequence.fromMap(refs).get(v).extendedBy).select(new ISelector<IFacet, IFacet.Name>() {
public IFacet.Name select(IFacet f) {
return f.getName();
}
});
}
@Override
public Iterable<IFacet.Name> backwardEdges(IFacet.Name v) {
return ListSequence.fromList(MapSequence.fromMap(refs).get(v).extended).select(new ISelector<IFacet, IFacet.Name>() {
public IFacet.Name select(IFacet f) {
return f.getName();
}
});
}
@Override
public Iterable<IFacet.Name> vertices() {
return MapSequence.fromMap(refs).keySet();
}
};
for (List<IFacet.Name> cyc : ListSequence.fromList(ga.findCycles())) {
error(null, "found cycle: " + cyc);
}
return ga.topologicalSort();
}
private void error(Object o, String message) {
LOG.debug(message);
ListSequence.fromList(this.errors).addElement(new ValidationError(o, message));
}
private class FacetRefs {
/*package*/ List<IFacet> extended = ListSequence.fromList(new ArrayList<IFacet>());
/*package*/ List<IFacet> extendedBy = ListSequence.fromList(new ArrayList<IFacet>());
/*package*/ List<IFacet> required = ListSequence.fromList(new ArrayList<IFacet>());
/*package*/ List<IFacet> optional = ListSequence.fromList(new ArrayList<IFacet>());
private Map<IFacet.Name, IFacet> facetsView;
public FacetRefs(Map<IFacet.Name, IFacet> facetsView) {
this.facetsView = facetsView;
}
public void collect(IFacet fct) {
for (IFacet.Name req : Sequence.fromIterable(fct.extended())) {
addIfExists(fct, req, extended, true);
}
for (IFacet.Name req : Sequence.fromIterable(fct.required())) {
addIfExists(fct, req, required, true);
}
for (IFacet.Name opt : Sequence.fromIterable(fct.optional())) {
addIfExists(fct, opt, optional, false);
}
}
private void addIfExists(IFacet requestor, IFacet.Name requestee, List<IFacet> destination, boolean required) {
IFacet f = MapSequence.fromMap(facetsView).get(requestee);
if (f != null) {
ListSequence.fromList(destination).addElement(f);
} else {
if (required) {
String msg = "not found required facet: " + requestee;
error(requestor.getName(), msg);
} else {
LOG.debug("not found optional facet: " + requestee + " for facet " + requestor.getName());
}
}
}
}
}