package eu.leads.processor.plan; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.common.base.Strings; import eu.leads.processor.execute.operators.OutputOperator; import eu.leads.processor.sql.Plan; import eu.leads.processor.sql.PlanNode; import java.util.*; /** * Created with IntelliJ IDEA. * User: vagvaz * Date: 9/16/13 * Time: 3:57 PM * To change this template use File | Settings | File Templates. */ @JsonAutoDetect //@JsonDeserialize(converter = ExecutionPlanConverter.class) public class ExecutionPlan implements Plan { private OutputOperator output; private Map<String, ExecutionPlanNode> graph; private List<String> sources; @JsonIgnore private PlanNode current; @JsonCreator public ExecutionPlan(@JsonProperty("output") OutputOperator output, @JsonProperty("graph") Map<String, ExecutionPlanNode> graph, @JsonProperty("sources") List<String> sources) { this.output = output; this.graph = graph; this.sources = sources; } public ExecutionPlan() { graph = new HashMap<String, ExecutionPlanNode>(); sources = new ArrayList<String>(); } public Map<String, ExecutionPlanNode> getGraph() { return graph; } public void setGraph(Map<String, ExecutionPlanNode> graph) { this.graph = graph; } public void setSources(List<String> sources) { this.sources = sources; } void setOutput(OutputOperator node) { output = (node); graph.put(node.getName(), output); current = output; } @Override public void setOutput(PlanNode node) { this.setOutput((OutputOperator) node); } public OutputOperator getOutput() { return output; } @Override public void addSource(PlanNode node) { if( node instanceof ExecutionPlanNode){ sources.add(node.getName()); graph.put(node.getName(), (ExecutionPlanNode) node); } } @JsonIgnore @Override public void addTo(String nodeId, Plan subPlan) throws Exception { PlanNode entryPoint = getNode(nodeId); if (entryPoint == null) throw new Exception("sub plan has invalid connection point to this plan " + nodeId); if (entryPoint.getSources().size() == 0) { PlanNode subOutput = subPlan.getOutput(); entryPoint.setSources(subOutput.getSources()); for (String source : subOutput.getSources()) { PlanNode node = subPlan.getNode(source); node.setOutput(entryPoint.getName()); } } for (PlanNode node : subPlan.getNodes()) { if (!node.equals(subPlan.getOutput())) { graph.put(node.getName(), (ExecutionPlanNode) node); } } sources.addAll(subPlan.getSources()); } @JsonIgnore public PlanNode getNode(String nodeId) { return graph.get(nodeId); } @JsonIgnore @Override public PlanNode createNode() { return null; //TODO } @JsonIgnore @Override public void addTo(String nodeId, PlanNode newNode) throws Exception { PlanNode node = getNode(nodeId); if (node == null) throw new Exception("sub plan has invalid connection point to this plan " + nodeId); node.getSources().add(newNode.getName()); newNode.setOutput(node.getName()); graph.put(newNode.getName(), (ExecutionPlanNode) newNode); } @JsonIgnore public void addAfter() { //TODO } @JsonIgnore @Override public void addAfterCurrent(PlanNode node) throws Exception { this.addAfter(); setCurrent(node); } @JsonIgnore @Override public void addAfterCurrent() { //TODO } @JsonIgnore @Override public void addToCurrent(PlanNode node) throws Exception { try { this.addTo(getCurrent().getName(), node); } catch (Exception e) { e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. } setCurrent(node); } @JsonIgnore @Override public void addToCurrent() { //TODO } @Override public Collection<String> getSources() { return sources; } @JsonIgnore @Override public void computeSources() { sources.clear(); for (Map.Entry<String, ExecutionPlanNode> entry : graph.entrySet()) { if (entry.getValue().getSources().size() == 0) sources.add(entry.getValue().getName()); } } @JsonIgnore @Override public void merge(Plan extracted) throws Exception { addTo(extracted.getOutput().getName(), extracted); } @JsonIgnore @Override public Collection<PlanNode> getNodes() { ArrayList<PlanNode> result = new ArrayList<PlanNode>(); result.addAll(graph.values()); return result; } @JsonIgnore @Override public PlanNode getCurrent() { return current; } @JsonIgnore @Override public void setCurrent(String nodeId) throws Exception { PlanNode tmp = graph.get(nodeId); if (tmp != null) current = tmp; else throw new Exception("Setting Current to invalid node " + nodeId); } @JsonIgnore @Override public void setCurrent(PlanNode node) throws Exception { PlanNode tmp = graph.get(node.getName()); if (tmp != null) current = tmp; else throw new Exception("Setting Current to invalid node " + node.getName()); } @Override public String toString() { Set<PlanNode> current = new HashSet<PlanNode>(); for (String source : sources) current.add(graph.get(source)); Set<PlanNode> next = new HashSet<PlanNode>(); StringBuilder builder = new StringBuilder(); while (current.size() > 0) { for (PlanNode node : current) { builder.append(node.toString() + "\t"); if (node.getName().equals(output.getName())) break; if (!Strings.isNullOrEmpty(node.getOutput())) next.add(graph.get(node.getOutput())); } builder.append("\n"); current.clear(); current = next; next = new HashSet<PlanNode>(); } return builder.toString(); } }