package surveyServerBase;
import java.io.File;
import java.util.Vector;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class LoadFromOsm {
Model model = null;
/*
* (non-Javadoc)
* @see org.smap.client.interfaces.SurveyService#getSurvey(java.lang.String)
* =================================================================================================================
*
* Load a survey in OSM format into the Smap Survey Meta Model
* @param surveyName The name of the survey to be created in the meta store
* @param fileName The name of the file to be loaded
*/
public void loadFile(String surveyName, String fileName) {
String fileBase = ""; // TODO redesign mapping to file that is to be loaded
String filePath = fileBase + "/completedSurveys/" + fileName + ".xml";
File surveyXML = new File(filePath);
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder b = dbf.newDocumentBuilder();
Document surveyDocument = b.parse(surveyXML);
Element rootElement = surveyDocument.getDocumentElement();
NodeList eList = rootElement.getChildNodes();
model = new Model();
model.createSurvey(surveyName);
if(model.existingSurvey()) {
System.out.println("Error: Survey already exists");
} else {
if (eList != null) {
for (int i = 0; i < eList.getLength(); i++) {
if(eList.item(i).getNodeType() == Node.ELEMENT_NODE) {
String eName = eList.item(i).getNodeName();
String sId = getId(eList.item(i)); // Get the id of the element
if(eName.equals("node")) { // Question or Option
if(isQuestion(eList.item(i))) {
updateQuestionList(sId, eList.item(i)); // Update the meta store with the question
} else {
updateOptionList(sId, eList.item(i)); // Update the meta store with the option
}
} else if (eName.equals("way")) { // Form
model.createForm(sId, getTag(eList.item(i), "name"));
addFormToQuestionList(sId, eList.item(i));
} else if (eName.equals("relation")) {
String relationType = getTag(eList.item(i), "type"); // Get the relation type
if(relationType.equals("repeat")) { // Add child form to a parent question
connectChildAndParent(eList.item(i));
} else if(relationType.equals("radio") || relationType.equals("checkbox")) { // Add options to a question
linkOptionsToQuestion(eList.item(i)); // Add the form name and link option to its question
} else if(relationType.equals("skipThis")) { // Add a skipThis to its question
createSkip(sId, eList.item(i));
} else if(relationType.equals("survey")) {
// Create the survey and add freeform tags to an HSTORE element
} else if(relationType.equals("group")) {
// Do something
} else {
System.out.println("Warning: Unknown relation type " + relationType + " in file: " + filePath);
}
} else {
System.out.println("Warning: Unknown element name in file: " + filePath);
}
}
}
// Write the accumulated data to the database
model.cleanseOSM();
model.writeToDb();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
/*
* Method replies the id of the passed in OSM element
* @param n The Node from the DOM containing the parsed XML
* @return the id of the osm element
*/
static private String getId(Node n) {
NamedNodeMap nm = n.getAttributes();
return nm.getNamedItem("id").getNodeValue();
}
/*
* Method gets the value of a specific tag from the DOM
* @param n The Node from the DOM containing the parsed XML
* @param targetKey The tag's key
* @return The value of the tag
*/
private String getTag(Node n, String targetKey) {
String tagValue = null;
NodeList eList = n.getChildNodes();
if (eList != null) {
for (int i = 0; i < eList.getLength(); i++) {
if(eList.item(i).getNodeType() == Node.ELEMENT_NODE) {
String eName = eList.item(i).getNodeName();
if(eName.equals("tag")) {
NamedNodeMap nm = eList.item(i).getAttributes();
String k = nm.getNamedItem("k").getNodeValue();
if(k.equals(targetKey)) {
tagValue = nm.getNamedItem("v").getNodeValue();
break;
}
}
}
}
}
return tagValue;
}
/*
* Method returns true if the passed in element is a question
* @param n The Node from the DOM containing the parsed XML
*/
private boolean isQuestion(Node n) {
boolean question = false;
NodeList eList = n.getChildNodes();
if (eList != null) {
for (int i = 0; i < eList.getLength(); i++) {
if(eList.item(i).getNodeType() == Node.ELEMENT_NODE) {
String eName = eList.item(i).getNodeName();
if(eName.equals("tag")) {
NamedNodeMap nm = eList.item(i).getAttributes();
String k = nm.getNamedItem("k").getNodeValue();
if(k.equals("q")) { // Its a question
question = true;
break;
}
}
}
}
}
return question;
}
/*
* Method updates the question list with the details of the question
* @param sId The unique identifier for this question
* @param n The Node from the DOM containing the parsed XML
*/
private void updateQuestionList(String questionRef, Node n){
Option o1 = null; // Objects used to store single choice options
Option o2 = null;
Option o3 = null;
NodeList eList = n.getChildNodes();
if (eList != null) {
model.createQuestion(questionRef, null);
Question q = model.getQuestion(questionRef);
for (int i = 0; i < eList.getLength(); i++) {
if(eList.item(i).getNodeType() == Node.ELEMENT_NODE) {
String eName = eList.item(i).getNodeName();
if(eName.equals("tag")) {
NamedNodeMap nm = eList.item(i).getAttributes();
String k = nm.getNamedItem("k").getNodeValue();
if(k.equals("q")) {
q.question = nm.getNamedItem("v").getNodeValue();
q.question = q.question.replaceAll("'", ""); // TODO handle apostrophes
} else if(k.equals("name")) {
q.qName = nm.getNamedItem("v").getNodeValue();
} else if (k.equals("type")) {
q.qType = nm.getNamedItem("v").getNodeValue();
} else if (k.equals("dateType") || k.equals("textType")) {
q.qSubType = nm.getNamedItem("v").getNodeValue();
} else if (k.equals("a")) {
q.defaultAnswer = nm.getNamedItem("v").getNodeValue();
} else if (k.equals("man")) {
String man = nm.getNamedItem("v").getNodeValue();
if(man.toLowerCase().startsWith("y")) {
q.mandatory = "TRUE";
}
} else if (k.equals("readOnly")) {
String ro = nm.getNamedItem("v").getNodeValue();
if(ro.toLowerCase().startsWith("y")) {
q.readOnly = "TRUE";
}
} else if (k.equals("i")) {
q.info = nm.getNamedItem("v").getNodeValue();
q.info = q.info.replaceAll("'", ""); // TODO handle apostrophes
} else if (k.equals("o1")) {
if(o1 == null) {
o1 = new Option();
}
o1.label = nm.getNamedItem("v").getNodeValue();
} else if (k.equals("o2")) {
if(o2 == null) {
o2 = new Option();
}
o2.label = nm.getNamedItem("v").getNodeValue();
} else if (k.equals("o3")) {
if(o3 == null) {
o3 = new Option();
}
o3.label = nm.getNamedItem("v").getNodeValue();
} else if (k.equals("o1val")) {
if(o1 == null) {
o1 = new Option();
}
o1.value = nm.getNamedItem("v").getNodeValue();
} else if (k.equals("o2val")) {
if(o2 == null) {
o2 = new Option();
}
o2.value = nm.getNamedItem("v").getNodeValue();
} else if (k.equals("o3val")) {
if(o3 == null) {
o3 = new Option();
}
o3.value = nm.getNamedItem("v").getNodeValue();
}
}
}
}
if(o1 != null) {
o1.seq = 0;
o1.questionRef = questionRef;
String nRef = questionRef + "sc1";
model.addOption(nRef, o1);
if(q.singleChoiceOptions == null) {
q.singleChoiceOptions = new Vector<String> ();
}
q.singleChoiceOptions.add(nRef);
}
if(o2 != null) {
o2.seq = 1;
o2.questionRef = questionRef;
String nRef = questionRef + "sc2";
model.addOption(nRef, o2);
if(q.singleChoiceOptions == null) {
q.singleChoiceOptions = new Vector<String> ();
}
q.singleChoiceOptions.add(nRef);
}
if(o3 != null) {
o3.seq = 2;
o3.questionRef = questionRef;
String nRef = questionRef + "sc3";
model.addOption(nRef, o3);
if(q.singleChoiceOptions == null) {
q.singleChoiceOptions = new Vector<String> ();
}
q.singleChoiceOptions.add(nRef);
}
}
}
/*
* Method adds the form name and sequence number to the question
* @param formRef The form that contains the questions
* @param n The Node from the DOM containing the parsed XML
*/
private void addFormToQuestionList(String formRef, Node n) {
NodeList eList = n.getChildNodes();
int sequence = 0;
if (eList != null) {
for (int i = 0; i < eList.getLength(); i++) {
if(eList.item(i).getNodeType() == Node.ELEMENT_NODE) {
String eName = eList.item(i).getNodeName();
if(eName.equals("nd")) {
NamedNodeMap nm = eList.item(i).getAttributes();
String ref = nm.getNamedItem("ref").getNodeValue();
// Update the
Question q = model.getQuestion(ref);
q.seq = sequence;
q.formRef = formRef;
sequence++;
}
}
}
}
}
/*
* Method adds the form name and sequence number to the question
* @param n The Node from the DOM containing the parsed XML
*/
private void connectChildAndParent(Node n) {
Form f = null;
String parentFormRef = null;
String parentQuestionRef = null;
NodeList eList = n.getChildNodes();
if (eList != null) {
for (int i = 0; i < eList.getLength(); i++) {
if(eList.item(i).getNodeType() == Node.ELEMENT_NODE) {
String eName = eList.item(i).getNodeName();
if(eName.equals("member")) {
NamedNodeMap nm = eList.item(i).getAttributes();
String role = nm.getNamedItem("role").getNodeValue();
if(role.equals("conditionNode")) { // The condition question
parentQuestionRef = nm.getNamedItem("ref").getNodeValue();
} else if(role.equals("parentWay")) {
parentFormRef = nm.getNamedItem("ref").getNodeValue();
} else if(role.equals("template")) {
String ref = nm.getNamedItem("ref").getNodeValue();
f = model.getForm(ref);
}
}
}
}
if (f != null) {
f.parentFormRef = parentFormRef;
f.parentQuestionRef = parentQuestionRef;
}
}
}
/*
* Method updates the options object with the details of the option
* @param oId The identifier of the option
* @param n The Node from the DOM containing the parsed XML
*/
private void updateOptionList(String oId, Node n) {
NodeList eList = n.getChildNodes();
if (eList != null) {
Option o = new Option();
for (int i = 0; i < eList.getLength(); i++) {
if(eList.item(i).getNodeType() == Node.ELEMENT_NODE) {
String eName = eList.item(i).getNodeName();
if(eName.equals("tag")) {
NamedNodeMap nm = eList.item(i).getAttributes();
String k = nm.getNamedItem("k").getNodeValue();
if(k.equals("label")) {
o.label = nm.getNamedItem("v").getNodeValue();
} else if(k.equals("value")) {
o.value = nm.getNamedItem("v").getNodeValue();
}
}
}
}
model.addOption(oId, o);
}
}
/*
* Method updates the options object with the question reference
* @param n The Node from the DOM containing the parsed XML
*/
private void linkOptionsToQuestion(Node n) {
String questionRef = null;
String choiceType = getTag(n, "type"); // Get the type of choice, either "radio" or "checkbox"
/*
* Get the question first, don't assume it is the first child in the XML although it probably is
*/
NodeList eList = n.getChildNodes();
if (eList != null) {
for (int i = 0; i < eList.getLength(); i++) {
if(eList.item(i).getNodeType() == Node.ELEMENT_NODE) {
String eName = eList.item(i).getNodeName();
if(eName.equals("member")) {
NamedNodeMap nm = eList.item(i).getAttributes();
String role = nm.getNamedItem("role").getNodeValue();
String ref = nm.getNamedItem("ref").getNodeValue();
if(role != null) {
if(role.equals("question")) {
questionRef = ref;
break;
}
}
}
}
}
if (questionRef != null) {
Question q = model.getQuestion(questionRef);
q.qSubType = choiceType; // Set the subtype of the question to the choice type (ie radio or checkbox)
/*
* Get the options to the question and link them to this question
*/
int sequence = 0;
for (int i = 0; i < eList.getLength(); i++) {
if(eList.item(i).getNodeType() == Node.ELEMENT_NODE) {
String eName = eList.item(i).getNodeName();
if(eName.equals("member")) {
NamedNodeMap nm = eList.item(i).getAttributes();
String role = nm.getNamedItem("role").getNodeValue();
String ref = nm.getNamedItem("ref").getNodeValue();
if(role != null && role.equals("option")) {
Option o = model.getOption(ref);
o.seq = sequence++; // set up the sequence for the options
o.questionRef = questionRef;
}
}
}
}
}
}
}
/*
* Method creates the rule objects for skips
* @param n The Node from the DOM containing the parsed XML
*/
private void createSkip(String skipRef, Node n) {
String targetRef = null;
String conditionRef = null;
/*
* Get the target and condition nodes
*/
NodeList eList = n.getChildNodes();
if (eList != null) {
for (int i = 0; i < eList.getLength(); i++) {
if(eList.item(i).getNodeType() == Node.ELEMENT_NODE) {
String eName = eList.item(i).getNodeName();
if(eName.equals("member")) {
NamedNodeMap nm = eList.item(i).getAttributes();
String role = nm.getNamedItem("role").getNodeValue();
String ref = nm.getNamedItem("ref").getNodeValue();
if(role != null) {
if(role.equals("conditionNode")) {
conditionRef = ref;
} else if(role.equals("targetNode")) {
targetRef = ref;
}
}
}
}
}
String expression = getTag(n, "rule");
String value = getTag(n, "value");
// Get the name of the condition node
Question q = model.getQuestion(conditionRef);
String conditionName = q.getName();
if (targetRef != null) {
Rule r = new Rule();
r.sequence = 0;
r.questionRef = targetRef;
r.action = "skip";
r.expression = "[" + conditionName + "] " + expression + " " + value;
model.addRule(skipRef, r);
}
}
}
}
|