package org.commcare.cases.instance;

import org.commcare.cases.model.StorageIndexedTreeElementModel;
import org.javarosa.core.model.instance.TreeElement;
import org.javarosa.core.model.instance.TreeReference;

/**
 * Child TreeElement of an indexed fixture whose data is loaded from a DB.
 *
 * i.e. 'product' of "instance('product-list')/products/product"
 *
 * @author Phillip Mates (pmates@dimagi.com)
 */
public class IndexedFixtureChildElement extends StorageBackedChildElement<StorageIndexedTreeElementModel> {
    private TreeElement empty;

    protected IndexedFixtureChildElement(StorageInstanceTreeElement<StorageIndexedTreeElementModel, ?> parent,
                                         int mult, int recordId) {
        super(parent, mult, recordId, parent.getName(), parent.getChildHintName());
    }

    /**
     * Template constructor (For elements that need to create reference nodesets but never look up values)
     */
    private IndexedFixtureChildElement(StorageInstanceTreeElement<StorageIndexedTreeElementModel, ?> parent) {
        super(parent, TreeReference.INDEX_TEMPLATE,
                TreeReference.INDEX_TEMPLATE, parent.getName(),
                parent.getChildHintName());

        StorageIndexedTreeElementModel modelTemplate = parent.getModelTemplate();
        empty = modelTemplate.getRoot();
        empty.setMult(TreeReference.INDEX_TEMPLATE);
        // NOTE PLM: do we need to do more to convert a regular TreeElement into a template?
    }

    @Override
    protected TreeElement cache() {
        if (recordId == TreeReference.INDEX_TEMPLATE) {
            return empty;
        }

        synchronized (parent.treeCache) {
            TreeElement element = parent.treeCache.retrieve(recordId);
            if (element != null) {
                return element;
            }

            StorageIndexedTreeElementModel model = parent.getElement(recordId);
            TreeElement cacheBuilder = buildElementFromModel(model);

            parent.treeCache.register(recordId, cacheBuilder);

            return cacheBuilder;
        }
    }

    private TreeElement buildElementFromModel(StorageIndexedTreeElementModel model) {
        TreeElement cacheBuilder = model.getRoot();
        entityId = model.getEntityId();
        cacheBuilder.setMult(mult);
        cacheBuilder.setParent(this.parent);

        return cacheBuilder;
    }

    @Override
    public String getName() {
        return nameId;
    }

    public static IndexedFixtureChildElement buildFixtureChildTemplate(IndexedFixtureInstanceTreeElement parent) {
        return new IndexedFixtureChildElement(parent);
    }
}

@@ -816,679 +816,8 @@
  %7D%0A%0A
-    /**%0A     * Template constructor (For elements that need to create reference nodesets but never look up values)%0A     */%0A    private IndexedFixtureChildElement(StorageInstanceTreeElement%3CStorageIndexedTreeElementModel, ?%3E parent) %7B%0A        super(parent, TreeReference.INDEX_TEMPLATE,%0A                TreeReference.INDEX_TEMPLATE, parent.getName(),%0A                parent.getChildHintName());%0A%0A        StorageIndexedTreeElementModel modelTemplate = parent.getModelTemplate();%0A        empty = modelTemplate.getRoot();%0A        empty.setMult(TreeReference.INDEX_TEMPLATE);%0A        // NOTE PLM: do we need to do more to convert a regular TreeElement into a template?%0A    %7D%0A%0A
     
@@ -1911,53 +1911,473 @@
     
-return new IndexedFixtureChildElement(parent)
+IndexedFixtureChildElement template =%0A                new IndexedFixtureChildElement(parent, TreeReference.INDEX_TEMPLATE, TreeReference.INDEX_TEMPLATE);%0A%0A        StorageIndexedTreeElementModel modelTemplate = parent.getModelTemplate();%0A        // NOTE PLM: do we need to do more to convert a regular TreeElement into a template?%0A        template.empty = modelTemplate.getRoot();%0A        template.empty.setMult(TreeReference.INDEX_TEMPLATE);%0A        return template
 ;%0A  

remove redundant constructor