package edu.northwestern.bioinformatics.studycalendar.xml.writers;

import edu.northwestern.bioinformatics.studycalendar.domain.PlanTreeInnerNode;
import edu.northwestern.bioinformatics.studycalendar.domain.PlanTreeNode;
import edu.northwestern.bioinformatics.studycalendar.domain.Study;
import edu.northwestern.bioinformatics.studycalendar.domain.delta.Changeable;
import edu.northwestern.bioinformatics.studycalendar.xml.AbstractStudyCalendarXmlSerializer;
import gov.nih.nci.cabig.ctms.domain.MutableDomainObject;
import org.dom4j.Document;
import org.dom4j.Element;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

public abstract class AbstractPlanTreeNodeXmlSerializer extends AbstractStudyCalendarXmlSerializer<PlanTreeNode<?>> implements StatefulTemplateXmlSerializer<PlanTreeNode<?>>{
    protected Study study;

    protected abstract PlanTreeNode<?> nodeInstance();

    protected abstract String elementName();

    protected abstract PlanTreeNode<?> getFromId(String id);

    protected abstract AbstractPlanTreeNodeXmlSerializer getChildSerializer();

//    protected void addAdditionalElementAttributes(final PlanTreeNode<?> node, Element element) {
//    }

    protected void addAdditionalElementAttributes(final Changeable node, Element element) {
    }

    protected void addAdditionalNodeAttributes(final Element element, PlanTreeNode<?> node) {
    }

//    protected void addChildrenElements(PlanTreeInnerNode<?, PlanTreeNode<?>, ?> node, Element eStudySegment) {
//    }

    protected void addChildrenElements(Changeable node, Element eStudySegment) {
    }

//    public Element createElement(PlanTreeNode<?> node) {
//        Element element = element(elementName());
//        element.addAttribute(ID, node.getGridId());
//        addAdditionalElementAttributes(node, element);
//
//        if (getChildSerializer() != null) {
//            addChildrenElements((PlanTreeInnerNode<?, PlanTreeNode<?>, ?>) node, element);
//        }
//
//        return element;
//    }

    public Element createElement(Changeable node) {
        Element element = element(elementName());
        element.addAttribute(ID, node.getGridId());
        addAdditionalElementAttributes(node, element);

        if (getChildSerializer() != null) {
            addChildrenElements((Changeable) node, element);
        }

        return element;
    }

    public PlanTreeNode<?> readElement(Element element) {
        if (!element.getName().equals(elementName())) {
            return null;
        }

        String key = element.attributeValue(ID);
        PlanTreeNode<?> node = key == null ? null : getFromId(key);
        if (node == null) {
            node = nodeInstance();
            node.setGridId(key);
            addAdditionalNodeAttributes(element, node);

            if (getChildSerializer() != null) {
                List<PlanTreeNode<?>> children = readChildElements(element);
                addChildren(children, node);
            }
        }
        return node;
    }

    protected List<PlanTreeNode<?>> readChildElements(Element element) {
        List<PlanTreeNode<?>> nodeList = new ArrayList<PlanTreeNode<?>>();
        for (Object oChild : element.elements()) {
            Element child = (Element) oChild;
            PlanTreeNode<?> childNode = getChildSerializer().readElement(child);
            nodeList.add(childNode);
        }
        return nodeList;
    }

    private void addChildren(List<PlanTreeNode<?>> children, PlanTreeNode<?> parent) {
        for (PlanTreeNode<?> child : children) {
            ((PlanTreeInnerNode) parent).addChild(child);
        }
    }

    public Document createDocument(PlanTreeNode<?> root) {
        throw new UnsupportedOperationException("PlanTreeNodes aren't root nodes");
    }

    public String createDocumentString(PlanTreeNode<?> root) {
        throw new UnsupportedOperationException("PlanTreeNodes aren't root nodes");
    }

    public PlanTreeNode<?> readDocument(Document document) {
        throw new UnsupportedOperationException("PlanTreeNodes aren't root nodes");
    }

    public PlanTreeNode<?> readDocument(InputStream in) {
        throw new UnsupportedOperationException("PlanTreeNodes aren't root nodes");
    }

    public void setStudy(Study study) {
        this.study = study;
    }

    public String validateElement(MutableDomainObject planTreeNode, Element ePlanTreeNode) {
        StringBuffer errorMessageStringBuffer = new StringBuffer("");


        if (!ePlanTreeNode.getName().equals(elementName())) {
            errorMessageStringBuffer.append(String.format("name  is different for " + planTreeNode.getClass().getSimpleName()
                    + ". expected:%s , found (in imported document) :%s. \n", ePlanTreeNode.getName(), elementName()));
        }

        String key = ePlanTreeNode.attributeValue(ID);
        if (!planTreeNode.getGridId().equals(key)) {
            errorMessageStringBuffer.append(String.format("id is different for " + planTreeNode.getClass().getSimpleName()
                    + ". expected:%s , found (in imported document) :%s. \n", planTreeNode.getGridId(), key));
        }

        return errorMessageStringBuffer.toString();
    }

}

@@ -285,86 +285,8 @@
 dy;%0A
-import edu.northwestern.bioinformatics.studycalendar.domain.delta.Changeable;%0A
 impo
@@ -681,16 +681,20 @@
 Node%3C?%3E%3E
+%0A   
  impleme
@@ -743,16 +743,17 @@
 Node%3C?%3E%3E
+%0A
 %7B%0A    pr
@@ -1018,18 +1018,16 @@
 zer();%0A%0A
-//
     prot
@@ -1119,109 +1119,8 @@
 ) %7B%0A
-//    %7D%0A%0A    protected void addAdditionalElementAttributes(final Changeable node, Element element) %7B%0A
     
@@ -1219,26 +1219,24 @@
 e) %7B%0A    %7D%0A%0A
-//
     protecte
@@ -1330,26 +1330,24 @@
 ySegment) %7B%0A
-//
     %7D%0A%0A    p
@@ -1350,548 +1350,51 @@
    p
-rotected void addChildrenElements(Changeable node, Element eStudySegment) %7B%0A    %7D%0A%0A//    public Element createElement(PlanTreeNode%3C?%3E node) %7B%0A//        Element element = element(elementName());%0A//        element.addAttribute(ID, node.getGridId());%0A//        addAdditionalElementAttributes(node, element);%0A//%0A//        if (getChildSerializer() != null) %7B%0A//            addChildrenElements((PlanTreeInnerNode%3C?, PlanTreeNode%3C?%3E, ?%3E) node, element);%0A//        %7D%0A//%0A//        return element;%0A//    %7D%0A%0A    public Element createElement(Changeable
+ublic Element createElement(PlanTreeNode%3C?%3E
  nod
@@ -1637,18 +1637,48 @@
 ts((
-Changeable
+PlanTreeInnerNode%3C?, PlanTreeNode%3C?%3E, ?%3E
 ) no

Revert changes from r3333 which caused application not to compile and which were apparently unnecessary (all tests pass)