package com.github.sriki77.apiproxy.instrument.model; import com.thoughtworks.xstream.annotations.XStreamImplicit; import com.thoughtworks.xstream.annotations.XStreamOmitField; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Optional; public abstract class FlowSteps implements NodeHolder, LocationProvider { @XStreamImplicit(itemFieldName = "Step") protected List<Step> steps; @XStreamOmitField protected LocationProvider parent; @Override public String toString() { return "FlowSteps{" + "steps=" + steps + '}'; } public List<Step> getSteps() { return steps == null ? Collections.emptyList() : Collections.unmodifiableList(steps); } public Step cloneStep(Step step) { final int i = steps.indexOf(step); if (i == -1) { throw new RuntimeException("Step not found: " + step); } Step copy = step.duplicate(); steps.add(i, copy); final List<Node> nodes = updateNode(i); return new DOMStep(copy, getNameNode(nodes), getCondNode(nodes)); } protected List<Node> updateNode(int index) { final Node domNode = getDOMNode(); NodeList childNodes = domNode.getChildNodes(); final Node origNode = getNthStep(childNodes, index); final Node cloneNode = origNode.cloneNode(true); final List<Node> nodes = usefulNodes(cloneNode); if (nodes.size() < 1 || nodes.size() > 2) { throw new RuntimeException("Step nodes with only Name and Condition elements are supported"); } domNode.insertBefore(cloneNode, origNode); return nodes; } private List<Node> usefulNodes(Node cloneNode) { List<Node> usefulNodes = new ArrayList<>(); final NodeList childNodes = cloneNode.getChildNodes(); for (int i = 0; i < childNodes.getLength(); i++) { final Node item = childNodes.item(i); if (item.getNodeName().equalsIgnoreCase("Name") || item.getNodeName().equalsIgnoreCase("Condition")) { usefulNodes.add(item); } } return usefulNodes; } private Optional<Node> getNameNode(List<Node> nodes) { return nodes.stream().filter(n -> n.getNodeName().equalsIgnoreCase("Name")).findFirst(); } private Optional<Node> getCondNode(List<Node> nodes) { return nodes.stream().filter(n -> n.getNodeName().equalsIgnoreCase("Condition")).findFirst(); } private Node getNthStep(NodeList childNodes, int index) { for (int i = 0, j = 0; i < childNodes.getLength(); i++) { final Node item = childNodes.item(i); if (item.getNodeName().equalsIgnoreCase("Step")) { if (index == j) { return item; } ++j; } } throw new RuntimeException(index + "th step node not found"); } @Override public void setParent(LocationProvider parent) { this.parent = parent; LocationProvider.setParent(steps, this); } protected abstract Node getDOMNode(); }