/** * The contents of this file are subject to the OpenMRS Public License * Version 1.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://license.openmrs.org * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * * Copyright (C) OpenMRS, LLC. All Rights Reserved. */ package org.eclipse.datatools.connectivity.oda.openmrs.impl; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.eclipse.datatools.connectivity.oda.OdaException; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; public class XMLParser { private static Logger log = Logger.getLogger(XMLParser.class.getName()); /** * Used to retrieve the List of token groups from the server. The List * returned contains objects of type String, which is the token group tag. * * @param path the path to the Logic Web Service * @param user the username * @param pass the password */ public static List getTokenTags(String path, String user, String pass) throws OdaException { List tags = new ArrayList(); InputStream stream; DocumentBuilder builder; Document doc; NodeList tagItems; // Create a stream that reads from the getEntities data. try { stream = getStream(path, user, pass, "getTokenTags"); } catch (Exception e) { throw new OdaException(e); } // Create a document builder and create a document try { builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); doc = builder.parse(stream); } catch (Exception e) { throw new OdaException(e); } // Access the document elements and add them to our List doc.getDocumentElement().normalize(); // normalize representation tagItems = doc.getDocumentElement().getElementsByTagName("tag"); for (int i = 0; i < tagItems.getLength(); i++) { Element tag = (Element) tagItems.item(i); String content = tag.getTextContent(); if (content != null && content.length() > 0) tags.add(tag.getTextContent()); else throw new OdaException( "Error Retrieving Token Tags (reading data)"); } return tags; } /** * Used to retrieve the List of filters from the server. The List returned * contains objects of type Filter, which is a wrapper for a String and an * Integer, representing the name and ID of a particular Filter. * * @param path the path to the Logic Web Service * @param user the username * @param pass the password */ public static List getFilters(String path, String user, String pass) throws OdaException { List filters = new ArrayList(); InputStream stream; DocumentBuilder builder; Document doc; NodeList filterItems; // Create a stream that reads from the getFilters data. try { stream = getStream(path, user, pass, "getFilters"); } catch (Exception e) { throw new OdaException(e); } // Create a document builder and create a document try { builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); doc = builder.parse(stream); } catch (Exception e) { throw new OdaException(e); } // Access the document elements and add them to our List doc.getDocumentElement().normalize(); // normalize representation filterItems = doc.getDocumentElement().getElementsByTagName("filter"); for (int i = 0; i < filterItems.getLength(); i++) { Element filter = (Element) filterItems.item(i); if (filter.hasAttribute("name") && filter.hasAttribute("id")) filters.add(new Filter(filter.getAttribute("name"), filter .getAttribute("id"))); else throw new OdaException( "Error Retrieving Filters (reading data)"); } log.info("Returning filters"); return filters; } /** * Used to retrieve a Map of filter ID to its Filter. The ID of a Filter as * a String is sent in, and the Filter is returned. * * @param path the path to the Logic Web Service * @param user the username * @param pass the password */ public static Map getFilterMap(String path, String user, String pass) throws OdaException { Map hm = new HashMap(); for (Filter f : getFilters(path, user, pass)) { hm.put(f.getId(), f); } return hm; } /** * Used to retrieve the List of tokens from the server. The List returned * contains objects of type Token, which is a wrapper for a String and an * integer, representing the name and type of a particular token. * * @param path the path to the Logic Web Service * @param user the username * @param pass the password * @param tag the token group */ public static List getTokens(String path, String user, String pass, String tag) throws OdaException { List tokens = new ArrayList(); InputStream stream; DocumentBuilder builder; Document doc; NodeList tokenItems; // Create a stream that reads from the getTokens data. try { if (tag.equals("")) stream = getStream(path, user, pass, "getTokens"); else stream = getStream(path, user, pass, "getTokens?tag=" + tag.replaceAll(" ", "%20")); } catch (Exception e) { throw new OdaException(e); } // Create a document builder and create a document try { builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); doc = builder.parse(stream); } catch (Exception e) { throw new OdaException(e); } // Access the document elements and add them to our List doc.getDocumentElement().normalize(); // normalize representation tokenItems = doc.getDocumentElement().getElementsByTagName("token"); for (int i = 0; i < tokenItems.getLength(); i++) { Element token = (Element) tokenItems.item(i); int precision = -1, scale = -1; if (token.hasAttribute("precision")) precision = Integer.parseInt(token.getAttribute("precision")); if (token.hasAttribute("scale")) scale = Integer.parseInt(token.getAttribute("scale")); if (token.hasAttribute("name") && token.hasAttribute("type")) { tokens.add(new Token(token.getAttribute("name"), token .getAttribute("type"), precision, scale)); } else { throw new OdaException("Error Retrieving Tokens (reading data)"); } } log.info("Returning tokens"); return tokens; } /** * Used to retrieve a Map of token names to token type. The name of a Token * as a String is sent in, and the type of that String is returned. * * @param path the path to the Logic Web Service * @param user the username * @param pass the password * @param tag the token group */ public static Map getTokenMap(String path, String user, String pass, String tag) throws OdaException { log.info("Getting token map"); Map hm = new HashMap(); for (Token t : getTokens(path, user, pass, tag)) { hm.put(t.getName(), t); } return hm; } /** * Used to retrieve a List of data from the server. The List returned * contains Maps of String to Object, where the Object is some type of data, * e.g. a String, or an Integer, or a Date. The idea is that each Map in the * List is a row of data, and takes a token name and returns the data * associated for that token for that patient. * * @param path the path to the Logic Web Service * @param user the username * @param pass the password * @param filter the filter (e.g., a filter definition) to be used to refine * the entity data * @param tokens the list of tokens being used for this query */ public static List> getData(String path, String user, String pass, Filter filter, List tokens, String dataStyle, ResultSetMetaData rsmd) throws OdaException { log.setLevel(Level.INFO); List> data = new ArrayList>(); List retTokens = new ArrayList(); InputStream stream; DocumentBuilder builder; Document doc; NodeList colItems, rowItems, curValItems; // Create a stream that reads from the data try { stream = getStream(path, user, pass, getCall(filter, tokens, dataStyle)); } catch (Exception e) { throw new OdaException(e); } // Create a document builder and create a document try { builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); doc = builder.parse(stream); } catch (Exception e) { throw new OdaException(e); } // Access the document columns and record them doc.getDocumentElement().normalize(); // normalize representation Element columns = (Element) doc.getDocumentElement() .getElementsByTagName("columns").item(0); colItems = columns.getElementsByTagName("column"); for (int i = 0; i < colItems.getLength(); i++) { Element col = (Element) colItems.item(i); if (col.hasAttribute("token")) retTokens.add(col.getAttribute("token")); else throw new OdaException("Malformed XML response from server."); } // Access the document rows and record the data in Maps Element rows = (Element) doc.getDocumentElement().getElementsByTagName( "rows").item(0); NodeList error = rows.getElementsByTagName("error"); if (error.getLength() > 0) throw new OdaException(((Element) error.item(0)).getTextContent()); rowItems = rows.getElementsByTagName("row"); for (int i = 0; i < rowItems.getLength(); i++) { // Row iteration Map rowMap = new HashMap(); curValItems = ((Element) rowItems.item(i)) .getElementsByTagName("value"); for (int j = 0; j < curValItems.getLength(); j++) { // Val iteration rowMap.put(retTokens.get(j), ((Element) curValItems.item(j)) .getTextContent()); } data.add(rowMap); } return data; } /* * Create a URL and set the stream that reads from that URL. */ private static InputStream getStream(String path, String user, String pass, String api) throws Exception { URL url = new URL(path + api); log.info(api); log.info("URL -> " + url.toString()); HttpURLConnection urlconn = (HttpURLConnection) url.openConnection(); urlconn.setRequestProperty("Authorization", "Basic " + Base64.encodeBytes((user + ":" + pass).getBytes())); urlconn.setRequestMethod("POST"); urlconn.connect(); InputStream stream = urlconn.getInputStream(); return stream; } /* * Formulate a string that is the api part of the call to the Logic Web * Service for getData. */ private static String getCall(Filter filter, List tokens, String dataStyle) { /* * * String filterStr = "filter=" + filter.getId(); * * String tokenStr = ""; for (Token t : tokens) { tokenStr += "&token=" + * t.getName().replaceAll(" ", "%20"); * * //if there are modifiers, we need to add these to the request as well * if(t.isModified()) { tokenStr += t.getModifiers().replaceAll(" ", * "%20"); } } */ String getData = "getData?query=" + QueryBuilder.getQuery(tokens, filter.getId(), dataStyle); getData = getData.replaceAll(" ", "%20"); log.info(getData); return getData; } }