package org.javarosa.core.model.util.restorable;

import org.javarosa.core.model.Constants;
import org.javarosa.core.model.condition.EvaluationContext;
import org.javarosa.core.model.data.IAnswerData;
import org.javarosa.core.model.instance.FormInstance;
import org.javarosa.core.model.instance.TreeElement;
import org.javarosa.core.model.instance.TreeReference;
import org.javarosa.core.services.storage.Persistable;

import java.util.Date;
import java.util.Vector;

public class RestoreUtils {
    public static final String RECORD_ID_TAG = "rec-id";

    public static IXFormyFactory xfFact;

    private static TreeReference ref(String refStr) {
        return xfFact.ref(refStr);
    }

    private static TreeReference topRef(FormInstance dm) {
        return ref("/" + dm.getRoot().getName());
    }

    private static TreeReference childRef(String childPath, TreeReference parentRef) {
        return ref(childPath).parent(parentRef);
    }

<<<<<<< HEAD
=======
    private static FormInstance newDataModel(String topTag) {
        FormInstance dm = new FormInstance();
        dm.addNode(ref("/" + topTag));
        return dm;
    }

    public static FormInstance createDataModel(Restorable r) {
        FormInstance dm = newDataModel(r.getRestorableType());

        if (r instanceof Persistable) {
            addData(dm, RECORD_ID_TAG, new Integer(((Persistable)r).getID()));
        }

        return dm;
    }

    public static void addData(FormInstance dm, String xpath, Object data) {
        addData(dm, xpath, data, getDataType(data));
    }

    public static void addData(FormInstance dm, String xpath, Object data, int dataType) {
        if (data == null) {
            dataType = -1;
        }

        IAnswerData val;
        switch (dataType) {
            case -1:
                val = null;
                break;
            case Constants.DATATYPE_TEXT:
                val = new StringData((String)data);
                break;
            case Constants.DATATYPE_INTEGER:
                val = new IntegerData((Integer)data);
                break;
            case Constants.DATATYPE_LONG:
                val = new LongData((Long)data);
                break;
            case Constants.DATATYPE_DECIMAL:
                val = new DecimalData((Double)data);
                break;
            case Constants.DATATYPE_BOOLEAN:
                val = new StringData(((Boolean)data).booleanValue() ? "t" : "f");
                break;
            case Constants.DATATYPE_DATE:
                val = new DateData((Date)data);
                break;
            case Constants.DATATYPE_DATE_TIME:
                val = new DateTimeData((Date)data);
                break;
            case Constants.DATATYPE_TIME:
                val = new TimeData((Date)data);
                break;
            case Constants.DATATYPE_CHOICE_LIST:
                val = (SelectMultiData)data;
                break;
            default:
                throw new IllegalArgumentException("Don't know how to handle data type [" + dataType + "]");
        }

        TreeReference ref = absRef(xpath, dm);
        if (dm.addNode(ref, val, dataType) == null) {
            throw new RuntimeException("error setting value during object backup [" + xpath + "]");
        }
    }

    //used for outgoing data
    public static int getDataType(Object o) {
        int dataType = -1;
        if (o instanceof String) {
            dataType = Constants.DATATYPE_TEXT;
        } else if (o instanceof Integer) {
            dataType = Constants.DATATYPE_INTEGER;
        } else if (o instanceof Long) {
            dataType = Constants.DATATYPE_LONG;
        } else if (o instanceof Float || o instanceof Double) {
            dataType = Constants.DATATYPE_DECIMAL;
        } else if (o instanceof Date) {
            dataType = Constants.DATATYPE_DATE;
        } else if (o instanceof Boolean) {
            dataType = Constants.DATATYPE_BOOLEAN; //booleans are serialized as a literal 't'/'f'
        } else if (o instanceof SelectMultiData) {
            dataType = Constants.DATATYPE_CHOICE_LIST;
        }
        return dataType;
    }

>>>>>>> master
    //used for incoming data
    private static int getDataType(Class c) {
        int dataType;
        if (c == String.class) {
            dataType = Constants.DATATYPE_TEXT;
        } else if (c == Integer.class) {
            dataType = Constants.DATATYPE_INTEGER;
        } else if (c == Long.class) {
            dataType = Constants.DATATYPE_LONG;
        } else if (c == Float.class || c == Double.class) {
            dataType = Constants.DATATYPE_DECIMAL;
        } else if (c == Date.class) {
            dataType = Constants.DATATYPE_DATE;
            //Clayton Sims - Jun 16, 2009 - How are we handling Date v. Time v. DateTime?
        } else if (c == Boolean.class) {
            dataType = Constants.DATATYPE_TEXT; //booleans are serialized as a literal 't'/'f'
        } else {
            throw new RuntimeException("Can't handle data type " + c.getName());
        }

        return dataType;
    }

    public static Object getValue(String xpath, FormInstance tree) {
        TreeReference context = topRef(tree);
        TreeElement node = tree.resolveReference(ref(xpath).contextualize(context));
        if (node == null) {
            throw new RuntimeException("Could not find node [" + xpath + "] when parsing saved instance!");
        }

        if (node.isRelevant()) {
            IAnswerData val = node.getValue();
            return (val == null ? null : val.getValue());
        } else {
            return null;
        }
    }

    public static void applyDataType(FormInstance dm, String path, TreeReference parent, Class type) {
        applyDataType(dm, path, parent, getDataType(type));
    }

    public static void applyDataType(FormInstance dm, String path, TreeReference parent, int dataType) {
        TreeReference ref = childRef(path, parent);

        Vector v = new EvaluationContext(dm).expandReference(ref);
        for (int i = 0; i < v.size(); i++) {
            TreeElement e = dm.resolveReference((TreeReference)v.elementAt(i));
            e.setDataType(dataType);
        }
    }

    public static void templateData(Restorable r, FormInstance dm, TreeReference parent) {
        if (parent == null) {
            parent = topRef(dm);
            applyDataType(dm, "timestamp", parent, Date.class);
        }

        if (r instanceof Persistable) {
            applyDataType(dm, RECORD_ID_TAG, parent, Integer.class);
        }

        r.templateData(dm, parent);
    }
}

@@ -948,3225 +948,8 @@
  %7D%0A%0A
-%3C%3C%3C%3C%3C%3C%3C HEAD%0A=======%0A    private static FormInstance newDataModel(String topTag) %7B%0A        FormInstance dm = new FormInstance();%0A        dm.addNode(ref(%22/%22 + topTag));%0A        return dm;%0A    %7D%0A%0A    public static FormInstance createDataModel(Restorable r) %7B%0A        FormInstance dm = newDataModel(r.getRestorableType());%0A%0A        if (r instanceof Persistable) %7B%0A            addData(dm, RECORD_ID_TAG, new Integer(((Persistable)r).getID()));%0A        %7D%0A%0A        return dm;%0A    %7D%0A%0A    public static void addData(FormInstance dm, String xpath, Object data) %7B%0A        addData(dm, xpath, data, getDataType(data));%0A    %7D%0A%0A    public static void addData(FormInstance dm, String xpath, Object data, int dataType) %7B%0A        if (data == null) %7B%0A            dataType = -1;%0A        %7D%0A%0A        IAnswerData val;%0A        switch (dataType) %7B%0A            case -1:%0A                val = null;%0A                break;%0A            case Constants.DATATYPE_TEXT:%0A                val = new StringData((String)data);%0A                break;%0A            case Constants.DATATYPE_INTEGER:%0A                val = new IntegerData((Integer)data);%0A                break;%0A            case Constants.DATATYPE_LONG:%0A                val = new LongData((Long)data);%0A                break;%0A            case Constants.DATATYPE_DECIMAL:%0A                val = new DecimalData((Double)data);%0A                break;%0A            case Constants.DATATYPE_BOOLEAN:%0A                val = new StringData(((Boolean)data).booleanValue() ? %22t%22 : %22f%22);%0A                break;%0A            case Constants.DATATYPE_DATE:%0A                val = new DateData((Date)data);%0A                break;%0A            case Constants.DATATYPE_DATE_TIME:%0A                val = new DateTimeData((Date)data);%0A                break;%0A            case Constants.DATATYPE_TIME:%0A                val = new TimeData((Date)data);%0A                break;%0A            case Constants.DATATYPE_CHOICE_LIST:%0A                val = (SelectMultiData)data;%0A                break;%0A            default:%0A                throw new IllegalArgumentException(%22Don't know how to handle data type %5B%22 + dataType + %22%5D%22);%0A        %7D%0A%0A        TreeReference ref = absRef(xpath, dm);%0A        if (dm.addNode(ref, val, dataType) == null) %7B%0A            throw new RuntimeException(%22error setting value during object backup %5B%22 + xpath + %22%5D%22);%0A        %7D%0A    %7D%0A%0A    //used for outgoing data%0A    public static int getDataType(Object o) %7B%0A        int dataType = -1;%0A        if (o instanceof String) %7B%0A            dataType = Constants.DATATYPE_TEXT;%0A        %7D else if (o instanceof Integer) %7B%0A            dataType = Constants.DATATYPE_INTEGER;%0A        %7D else if (o instanceof Long) %7B%0A            dataType = Constants.DATATYPE_LONG;%0A        %7D else if (o instanceof Float %7C%7C o instanceof Double) %7B%0A            dataType = Constants.DATATYPE_DECIMAL;%0A        %7D else if (o instanceof Date) %7B%0A            dataType = Constants.DATATYPE_DATE;%0A        %7D else if (o instanceof Boolean) %7B%0A            dataType = Constants.DATATYPE_BOOLEAN; //booleans are serialized as a literal 't'/'f'%0A        %7D else if (o instanceof SelectMultiData) %7B%0A            dataType = Constants.DATATYPE_CHOICE_LIST;%0A        %7D%0A        return dataType;%0A    %7D%0A%0A%3E%3E%3E%3E%3E%3E%3E master%0A
     

Resolve conflict from merge