public class AddReverseNode {

    private ValidateReverseContext validateReverseContext;

    public AddReverseNode(ValidateReverseContext validateReverseContext) {
        this.validateReverseContext = validateReverseContext;
    }

    public final void addReverseNode(Node node) {
        addValidNode(node);
        addUnreachableParents(node);
        addNodeChildren(node);
    }

    private void addUnreachableParents(Node node) {
        for (Nodechild nc : getReverseChildList(node)) {
            Node parent = nc.getParent();
            if (!isReachable(parent)) {
                parent.getNodechildList().remove(nc);
                nc.setParent(node);
                nc.setChild(parent);
                node.getNodechildList().addFirst(nc);
                addReachable(parent);
                if (!getValidNodeList().contains(parent)) {
                    addReverseNode(parent);
                }
            }
        }
    }

    private void addNodeChildren(Node node) {
        for (Nodechild nc : node.getNodechildList()) {
            Node child = nc.getChild();
            if (nc.collapsed()) {
            } else {
                if (!getValidNodeList().contains(child)) {
                    addReachable(child);
                    addReverseNode(child);
                }
            }
        }
    }

    private ValidateReverseContext getValidateReverseContext() {
        return validateReverseContext;
    }

    private FlowchartContext getFlowchartContext() {
        return getValidateReverseContext().getFlowchartContext();
    }

    private SourceAppData getSourceAppData() {
        return getFlowchartContext().getSourceAppData();
    }

    private boolean addValidNode(Node item) {
        return getSourceAppData().addValidNode(item);
    }

    private NodechildIList getReverseChildList(Node mapkey) {
        return getValidateReverseContext().getReverseChildList(mapkey);
    }

    private boolean addReachable(Node item) {
        return getValidateReverseContext().addReachable(item);
    }

    private NodeHList getValidNodeList() {
        return getSourceAppData().getValidNodeList();
    }

    private boolean isReachable(Node item) {
        return getValidateReverseContext().isReachable(item);
    }
}