package fi.csc.emrex.smp;
/**
* Created by marko.hollanti on 20/08/15.
*/
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import java.util.ArrayList;
import java.util.List;
public class ElmoXmlImportHelper {
private final Logger logger = LoggerFactory.getLogger(ElmoXmlImportHelper.class);
public ElmoDocument getDocument(Node report) throws Exception {
ElmoDocument doc = new ElmoDocument();
String firstName = getValueForTag(report, "learner/givenNames");
String lastName = getValueForTag(report, "learner/familyName");
String birthday = getValueForTag(report, "learner/bday");
doc.setBirthday(birthday);
doc.setPersonName(firstName + " " + lastName);
doc.setInstitutionName(getValueForTag(report, "issuer/title"));
List<ElmoResult> results = new ArrayList<ElmoResult>();
XPath xpath = XPathFactory.newInstance().newXPath();
loopChildren(results, report, xpath, "learningOpportunitySpecification");
doc.setResults(results);
return doc;
}
private ElmoResult resultFromDegree(List<ElmoResult> results, Node los, XPath xpath) throws Exception {
ElmoResult res = new ElmoResult();
getLearningOpportunityValues(los, xpath, res);
loopChildren(results, los, xpath, "hasPart/learningOpportunitySpecification");
return res;
}
private ElmoResult resultFromModule(List<ElmoResult> results, Node los, XPath xpath) throws Exception {
ElmoResult res = new ElmoResult();
getLearningOpportunityValues(los, xpath, res);
res.setResult(getValueForTag(los, "specifies/learningOpportunityInstance/result"));
loopChildren(results, los, xpath, "hasPart/learningOpportunitySpecification");
return res;
}
private void getLearningOpportunityValues(Node los, XPath xpath, ElmoResult res) throws Exception {
res.setCode(getLocalContentValue(los, xpath, "identifier"));
res.setType(getValueForTag(los,"type"));
res.setLevel(getLevel(los, xpath));
res.setName(getEnglishContentValue(los, xpath, "title"));
res.setCredits(getValueForTag(los, "credit/value"));
res.setDate(getDate(los));
}
private String getDate(Node los) throws Exception {
String endDate;
endDate = getValueForTag(los, "specifies/learningOpportunityInstance/end");
if (endDate.isEmpty())
return getValueForTag(los, "specifies/learningOpportunityInstance/start");
else
return endDate;
}
private String getLevel(Node los, XPath xpath) throws Exception {
String simpleLevel = getValueForTag(los,"level");
if (!simpleLevel.isEmpty())
return simpleLevel;
else
return getPreferredContentValue(los, xpath, "qualification/educationLevel", "xml:lang", "en");
}
private void loopChildren(List<ElmoResult> results, Node los, XPath xpath, String path) throws Exception {
NodeList topLevelLOS = (NodeList) xpath.evaluate(path, los,
XPathConstants.NODESET);
for (int i = 0; i < topLevelLOS.getLength(); i++) {
Node node = topLevelLOS.item(i);
Node type = (Node) xpath.evaluate("type", node, XPathConstants.NODE);
if (type == null) {
continue;
}
if (type.getTextContent().equalsIgnoreCase("degree")) {
results.add(resultFromDegree(results, node, xpath));
} else if (type.getTextContent().equalsIgnoreCase("module")) {
results.add(resultFromModule(results, node, xpath));
} else if (type.getTextContent().equalsIgnoreCase("module group")) {
results.add(resultFromModule(results, node, xpath));
}
}
}
private String getValueForTag(Node node, String exp) {
XPath xpath = XPathFactory.newInstance().newXPath();
try {
return xpath.evaluate(exp, node);
} catch (Exception e) {
logger.info("XPATH error", e);
return null;
}
}
private String getLocalContentValue(Node node, XPath xpath, String expr) throws Exception {
return getPreferredContentValue(node, xpath, expr, "type", "local");
}
// returns english content, if not available any, if anything is not available we return default text
private String getEnglishContentValue(Node node, XPath xpath, String expr) throws Exception {
return getPreferredContentValue(node, xpath, expr, "xml:lang", "en");
}
private String getPreferredContentValue(Node node, XPath xpath, String expr, String itemName, String preferredValue) throws XPathExpressionException {
NodeList nList = (NodeList) xpath.evaluate(expr, node, XPathConstants.NODESET);
String content = " - ";
for (int i = 0; i < nList.getLength(); i++) {
Node n = (Node) nList.item(i);
String possibleContent = n.getTextContent();
if (possibleContent != null && !possibleContent.isEmpty())
content = possibleContent;
NamedNodeMap map = n.getAttributes();
Node item = map.getNamedItem(itemName);
if (preferredValue.equals(item.getTextContent())) {
return content;
}
}
return content;
}
}