/******************************************************************************* * Copyright 2011 The Regents of the University of California * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ package org.ohmage; import android.util.Xml; import org.ohmage.Utilities.KVLTriplet; import org.ohmage.prompt.Message; import org.ohmage.prompt.Prompt; import org.ohmage.prompt.PromptBuilder; import org.ohmage.prompt.PromptBuilderFactory; import org.ohmage.prompt.PromptFactory; import org.ohmage.prompt.RepeatableSetHeader; import org.ohmage.prompt.RepeatableSetTerminator; import org.ohmage.prompt.SurveyElement; import org.ohmage.logprobe.Log; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.List; public class PromptXmlParser { private static final String TAG = "PromptXmlParser"; //list of tags in our xml schema private static final String SURVEY = "survey"; private static final String SURVEY_ID = "id"; private static final String REPEATABLE_SET = "repeatableSet"; private static final String REPEATABLE_SET_ID = "id"; private static final String REPEATABLE_SET_TERMINATION_QUESTION = "terminationQuestion"; private static final String REPEATABLE_SET_TERMINATION_TRUE_LABEL = "terminationTrueLabel"; private static final String REPEATABLE_SET_TERMINATION_FALSE_LABEL = "terminationFalseLabel"; private static final String REPEATABLE_SET_TERMINATION_SKIP_ENABLED = "terminationSkipEnabled"; private static final String REPEATABLE_SET_TERMINATION_SKIP_LABEL = "terminationSkipLabel"; private static final String REPEATABLE_SET_CONDITION = "condition"; private static final String PROMPT = "prompt"; private static final String PROMPT_ID = "id"; private static final String PROMPT_DISPLAY_TYPE = "displayType"; private static final String PROMPT_DISPLAY_LABEL = "displayLabel"; private static final String PROMPT_UNIT = "unit"; private static final String PROMPT_TEXT = "promptText"; private static final String PROMPT_ABBREVIATED_TEXT = "abbreviatedText"; private static final String PROMPT_EXPLANATION_TEXT = "explanationText"; private static final String PROMPT_TYPE = "promptType"; private static final String PROMPT_DEFAULT = "default"; private static final String PROMPT_CONDITION = "condition"; private static final String PROMPT_SKIPPABLE = "skippable"; private static final String PROMPT_SKIP_LABEL = "skipLabel"; private static final String PROMPT_PROPERTIES = "properties"; private static final String PROMPT_PROPERTY = "property"; private static final String PROPERTY_KEY = "key"; private static final String PROPERTY_VALUE = "value"; private static final String PROPERTY_LABEL = "label"; private static final String MESSAGE = "message"; private static final String MESSAGE_TEXT = "messageText"; private static final String MESSAGE_CONDITION = "condition"; private static final String INSTRUCTIONS = "instructions"; public static List<SurveyElement> parseSurveyElements(InputStream promptXmlStream, String surveyId) throws XmlPullParserException, IOException { if(promptXmlStream == null) return null; XmlPullParser parser = Xml.newPullParser(); parser.setInput(new BufferedReader(new InputStreamReader(promptXmlStream, "UTF-8"))); List<SurveyElement> surveyElements = null; boolean promptInProgress = false; boolean repeatableSetInProgress = false; boolean messageInProgress = false; boolean surveyInProgress = false; boolean surveyFound = false; String id = null; String displayType = null; String displayLabel = null; String unit = null; String promptText = null; String abbreviatedText = null; String explanationText = null; String promptType = null; String defaultValue = null; String condition = null; String skippable = null; String skipLabel = null; //ArrayList<String[]> properties = null; ArrayList<KVLTriplet> properties = null; String key = null; String value = null; String label = null; String repeatableSetId = null; String terminationQuestion = null; String terminationTrueLabel = null; String terminationFalseLabel = null; String terminationSkipEnabled = null; String terminationSkipLabel = null; String repeatableSetCondition = null; List<Prompt> repeatableSetPrompts = null; String messageText = null; String messageCondition = null; // TODO deal with optional tags int eventType = parser.getEventType(); while (eventType != XmlPullParser.END_DOCUMENT) { String tagName = null; switch (eventType) { case XmlPullParser.START_DOCUMENT: break; case XmlPullParser.START_TAG: tagName = parser.getName(); if (tagName.equalsIgnoreCase(SURVEY)) { surveyInProgress = true; } else if (surveyInProgress) { if (tagName.equalsIgnoreCase(SURVEY_ID) && !promptInProgress && !repeatableSetInProgress && !messageInProgress) { if (parser.nextText().trim().equals(surveyId)) { surveyFound = true; surveyElements = new ArrayList<SurveyElement>(); } } else if (surveyFound) { if (tagName.equalsIgnoreCase(REPEATABLE_SET)) { repeatableSetInProgress = true; repeatableSetId = null; terminationQuestion = null; terminationFalseLabel = null; terminationTrueLabel = null; terminationSkipLabel = null; terminationSkipEnabled = null; repeatableSetCondition = null; repeatableSetPrompts = new ArrayList<Prompt>(); } else if (tagName.equalsIgnoreCase(PROMPT)) { promptInProgress = true; id = null; displayType = null; displayLabel = null; unit = null; promptText = null; abbreviatedText = null; explanationText = null; promptType = null; defaultValue = null; condition = null; skippable = null; skipLabel = null; properties = null; } else if (tagName.equalsIgnoreCase(MESSAGE)) { messageInProgress = true; messageText = null; messageCondition = null; } else if (promptInProgress) { if (tagName.equalsIgnoreCase(PROMPT_ID)) { id = parser.nextText().trim(); } else if (tagName.equalsIgnoreCase(PROMPT_DISPLAY_TYPE)) { displayType = parser.nextText().trim(); } else if (tagName.equalsIgnoreCase(PROMPT_DISPLAY_LABEL)) { displayLabel = parser.nextText().trim(); } else if (tagName.equalsIgnoreCase(PROMPT_UNIT)) { unit = parser.nextText().trim(); } else if (tagName.equalsIgnoreCase(PROMPT_TEXT)) { promptText = parser.nextText().trim(); } else if (tagName.equalsIgnoreCase(PROMPT_ABBREVIATED_TEXT)) { abbreviatedText = parser.nextText().trim(); } else if (tagName.equalsIgnoreCase(PROMPT_EXPLANATION_TEXT)) { explanationText = parser.nextText().trim(); } else if (tagName.equalsIgnoreCase(PROMPT_TYPE)) { promptType = parser.nextText().trim(); } else if (tagName.equalsIgnoreCase(PROMPT_DEFAULT)) { defaultValue = parser.nextText().trim(); } else if (tagName.equalsIgnoreCase(PROMPT_CONDITION)) { condition = parser.nextText().trim(); } else if (tagName.equalsIgnoreCase(PROMPT_SKIPPABLE)) { skippable = parser.nextText().trim(); } else if (tagName.equalsIgnoreCase(PROMPT_SKIP_LABEL)) { skipLabel = parser.nextText().trim(); } else if (tagName.equalsIgnoreCase(PROMPT_PROPERTIES)) { properties = new ArrayList<KVLTriplet>(); } else if (tagName.equalsIgnoreCase(PROMPT_PROPERTY)) { key = null; value = null; label = null; } else if (tagName.equalsIgnoreCase(PROPERTY_KEY)) { key = parser.nextText().trim(); } else if (tagName.equalsIgnoreCase(PROPERTY_VALUE)) { value = parser.nextText().trim(); } else if (tagName.equalsIgnoreCase(PROPERTY_LABEL)) { label = parser.nextText().trim(); } } else if (repeatableSetInProgress) { if (tagName.equalsIgnoreCase(REPEATABLE_SET_ID)) { repeatableSetId = parser.nextText().trim(); } else if (tagName.equalsIgnoreCase(REPEATABLE_SET_CONDITION)) { repeatableSetCondition = parser.nextText().trim(); } else if (tagName.equalsIgnoreCase(REPEATABLE_SET_TERMINATION_FALSE_LABEL)) { terminationFalseLabel = parser.nextText().trim(); } else if (tagName.equalsIgnoreCase(REPEATABLE_SET_TERMINATION_TRUE_LABEL)) { terminationTrueLabel = parser.nextText().trim(); } else if (tagName.equalsIgnoreCase(REPEATABLE_SET_TERMINATION_SKIP_LABEL)) { terminationSkipLabel = parser.nextText().trim(); } else if (tagName.equalsIgnoreCase(REPEATABLE_SET_TERMINATION_SKIP_ENABLED)) { terminationSkipEnabled = parser.nextText().trim(); } else if (tagName.equalsIgnoreCase(REPEATABLE_SET_TERMINATION_QUESTION)) { terminationQuestion = parser.nextText().trim(); } } else if (messageInProgress) { if (tagName.equalsIgnoreCase(MESSAGE_TEXT)) { messageText = parser.nextText().trim(); } else if (tagName.equalsIgnoreCase(MESSAGE_CONDITION)) { messageCondition = parser.nextText().trim(); } } } } break; case XmlPullParser.END_TAG: tagName = parser.getName(); if (tagName.equalsIgnoreCase(SURVEY)) { surveyInProgress = false; surveyFound = false; } else if (surveyFound) { if (tagName.equalsIgnoreCase(PROMPT)) { try { Prompt prompt = PromptFactory.createPrompt(promptType); PromptBuilder builder = PromptBuilderFactory.createPromptBuilder(promptType); builder.build(prompt, id, displayType, displayLabel, promptText, abbreviatedText, explanationText, defaultValue, condition, skippable, skipLabel, properties); if (repeatableSetInProgress) { repeatableSetPrompts.add(prompt); } else { surveyElements.add(prompt); } } catch (Exception e) { Log.e(TAG, "Error building prompt", e); } promptInProgress = false; } else if (tagName.equalsIgnoreCase(PROMPT_PROPERTY)) { if (promptInProgress) { properties.add(new KVLTriplet(key, value, label)); } } else if (tagName.equalsIgnoreCase(REPEATABLE_SET)) { surveyElements.add(new RepeatableSetHeader(repeatableSetId, repeatableSetCondition, repeatableSetPrompts.size())); surveyElements.addAll(repeatableSetPrompts); surveyElements.add(new RepeatableSetTerminator(repeatableSetId, repeatableSetCondition, terminationQuestion, terminationTrueLabel, terminationFalseLabel, terminationSkipLabel, terminationSkipEnabled, repeatableSetPrompts.size())); repeatableSetInProgress = false; } else if (tagName.equalsIgnoreCase(MESSAGE)) { surveyElements.add(new Message(messageText, messageCondition)); messageInProgress = false; } } break; } eventType = parser.next(); } return surveyElements; } /** * parse the instructions from a campaign * @param campaignXml * @return * @throws XmlPullParserException * @throws IOException */ public static String parseCampaignInstructions(InputStream campaignXml) throws XmlPullParserException, IOException { if (campaignXml == null) return null; XmlPullParser parser = Xml.newPullParser(); parser.setInput(new BufferedReader(new InputStreamReader(campaignXml, "UTF-8"))); int eventType = parser.getEventType(); while (eventType != XmlPullParser.END_DOCUMENT) { if (eventType == XmlPullParser.START_TAG && parser.getName().equalsIgnoreCase(INSTRUCTIONS)) { parser.next(); return parser.getText(); } eventType = parser.next(); } return null; } }