package org.commcare.android.javarosa;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import org.commcare.CommCareApplication;
import org.commcare.utils.GeoUtils;
import org.javarosa.core.model.FormDef;
import org.javarosa.core.model.actions.Action;
import org.javarosa.core.model.condition.EvaluationContext;
import org.javarosa.core.model.condition.Recalculate;
import org.javarosa.core.model.data.AnswerDataFactory;
import org.javarosa.core.model.data.IAnswerData;
import org.javarosa.core.model.instance.AbstractTreeElement;
import org.javarosa.core.model.instance.TreeReference;
import org.javarosa.core.util.externalizable.DeserializationException;
import org.javarosa.core.util.externalizable.ExtUtil;
import org.javarosa.core.util.externalizable.ExtWrapNullable;
import org.javarosa.core.util.externalizable.PrototypeFactory;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
/**
* XForms Action extension to periodically poll a sensor and optionally save
* its value.
*
* @author jschweers
*/
public class PollSensorAction extends Action {
public static final String ELEMENT_NAME = "pollsensor";
public static final String KEY_UNRESOLVED_XPATH = "unresolved_xpath";
public static final String XPATH_ERROR_ACTION = "poll_sensor_xpath_error_action";
private FormDef formDef = null;
private TreeReference contextRef;
private TreeReference target;
public PollSensorAction() {
super(ELEMENT_NAME);
}
public PollSensorAction(TreeReference target) {
super(ELEMENT_NAME);
this.target = target;
}
/**
* Deal with a pollsensor action: start getting a GPS fix, and prepare to
* cancel after maximum amount of time.
*
* @param model The FormDef that triggered the action
*/
@Override
public TreeReference processAction(FormDef model, TreeReference contextRef) {
formDef = model;
this.contextRef = contextRef;
PollSensorController.INSTANCE.startLocationPolling(this);
return null;
}
void updateReference(Location location) {
if (target != null) {
String result = GeoUtils.locationToString(location);
TreeReference qualifiedReference = contextRef == null ? target : target.contextualize(contextRef);
EvaluationContext context = new EvaluationContext(formDef.getEvaluationContext(), qualifiedReference);
AbstractTreeElement node = context.resolveReference(qualifiedReference);
if (node == null) {
Context applicationContext = CommCareApplication.instance();
Intent xpathErrorIntent = new Intent(XPATH_ERROR_ACTION);
xpathErrorIntent.putExtra(KEY_UNRESOLVED_XPATH, qualifiedReference.toString(true));
applicationContext.sendStickyBroadcast(xpathErrorIntent);
} else {
int dataType = node.getDataType();
IAnswerData val = Recalculate.wrapData(result, dataType);
if (val == null) {
formDef.setValue(null, qualifiedReference);
} else {
IAnswerData answer =
AnswerDataFactory.templateByDataType(dataType).cast(val.uncast());
formDef.setValue(answer, qualifiedReference);
}
}
}
}
@Override
public void readExternal(DataInputStream in, PrototypeFactory pf)
throws IOException, DeserializationException {
super.readExternal(in, pf);
target = (TreeReference)ExtUtil.read(in, new ExtWrapNullable(TreeReference.class), pf);
}
@Override
public void writeExternal(DataOutputStream out) throws IOException {
super.writeExternal(out);
ExtUtil.write(out, new ExtWrapNullable(target));
}
}