/* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (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.mozilla.org/MPL/ * * 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. * * The Original Code is OpenEMRConnect. * * The Initial Developer of the Original Code is International Training & * Education Center for Health (I-TECH) <http://www.go2itech.org/> * * Portions created by the Initial Developer are Copyright (C) 2011 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * ***** END LICENSE BLOCK ***** */ package ke.go.moh.oec.adt.controller; import java.io.File; import java.io.IOException; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.util.*; import java.util.logging.Level; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import ke.go.moh.oec.adt.data.Column; import ke.go.moh.oec.adt.data.RecordSource; import ke.go.moh.oec.adt.exceptions.BadRecordSourceException; import ke.go.moh.oec.lib.Mediator; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; /** * @date Apr 29, 2012 * * @author Gitahi Ng'ang'a */ public class ResourceManager { private static Map<String, Connection> connectionMap = new HashMap<String, Connection>(); private final String DEFAULT_FILE_NAME = "record_sources.xml"; public static Connection getDatabaseConnection(String name) throws SQLException { if (!connectionMap.containsKey(name)) { connectionMap.put(name, createDatabaseConnection(name)); } return connectionMap.get(name); } public static String getSetting(String name) { return Mediator.getProperty(name); } public List<RecordSource> loadRecordSources() throws ParserConfigurationException, SAXException, IOException, BadRecordSourceException { return loadRecordSources(DEFAULT_FILE_NAME); } public List<RecordSource> loadRecordSources(String fileName) throws ParserConfigurationException, SAXException, IOException, BadRecordSourceException { List<RecordSource> recordSourceList = new ArrayList<RecordSource>(); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document document = builder.parse(new File(fileName)); document.getDocumentElement().normalize(); NodeList recordSourceNodeList = document.getElementsByTagName("record_source"); int recordSourceCount = recordSourceNodeList.getLength(); List<Integer> orderList = new ArrayList<Integer>(); for (int i = 0; i < recordSourceCount; i++) { Node recordSourceNode = recordSourceNodeList.item(i); if (recordSourceNode.getNodeType() == Node.ELEMENT_NODE) { RecordSource recordSource = createRecordSource(recordSourceNode); if (orderList.contains(recordSource.getOrder())) { throw new BadRecordSourceException("The order " + recordSource.getOrder() + " has been allocated to more than one record sources. Unique order expected."); } if (recordSourceList.contains(recordSource)) { throw new BadRecordSourceException("Record source for " + recordSource.getTableName() + " configured more than once in the xml " + "configuration file. Only one instance is expected."); } recordSourceList.add(recordSource); orderList.add(recordSource.getOrder()); } } Collections.sort(recordSourceList); return recordSourceList; } private static Connection createDatabaseConnection(String name) throws SQLException { Connection connection = null; try { if (name.equals("source")) { Class.forName(Mediator.getProperty("source.driver")); connection = DriverManager.getConnection(Mediator.getProperty("source.url"), Mediator.getProperty("source.username"), Mediator.getProperty("source.password")); } else if (name.equals("shadow")) { Class.forName(Mediator.getProperty("shadow.driver")); connection = DriverManager.getConnection(Mediator.getProperty("shadow.url"), Mediator.getProperty("shadow.username"), Mediator.getProperty("shadow.password")); } } catch (ClassNotFoundException cnfe) { Mediator.getLogger(ResourceManager.class.getName()).log(Level.SEVERE, null, cnfe); } return connection; } private RecordSource createRecordSource(Node recordSourceNode) throws BadRecordSourceException { Element recordSourceElement = (Element) recordSourceNode; RecordSource recordSource = new RecordSource(Integer.parseInt(readTagValue(recordSourceElement, "order"))); recordSource.setRelationship(RecordSource.Relationship.valueOf(readTagValue(recordSourceElement, "relationship").toUpperCase().trim())); recordSource.setTableName(readTagValue(recordSourceElement, "table_name")); recordSource.setPrimaryKeyColumnMap(readKeyColumns(recordSourceElement, "primary_key_column")); recordSource.setForeignKeyColumnMap(readKeyColumns(recordSourceElement, "foreign_key_column")); recordSource.setCumulate(Boolean.parseBoolean(readTagValue(recordSourceElement, "cumulate"))); String limitString = readTagValue(recordSourceElement, "limit"); if (limitString != null) { recordSource.setLimit(Integer.parseInt(limitString)); } List<Column> columnList = readOrdinaryColumns(recordSourceElement, "columns"); if (!columnList.isEmpty()) { recordSource.setColumnList(columnList); } validateRecordSource(recordSource); return recordSource; } private Map<String, Column> readKeyColumns(Element pkListElement, String keyName) { Map<String, Column> primaryKeyColumnSet = new LinkedHashMap<String, Column>(); NodeList nodeList = pkListElement.getElementsByTagName(keyName); int length = nodeList.getLength(); for (int i = 0; i < length; i++) { Element element = (Element) nodeList.item(0); String name = readTagValue(element, "name"); boolean quote = Boolean.parseBoolean(readTagValue(element, "quote")); primaryKeyColumnSet.put(name, new Column(name, quote)); } return primaryKeyColumnSet; } private String readTagValue(Element parentElement, String tagName) { String tagValue = null; NodeList nodeList = parentElement.getElementsByTagName(tagName); Element element = (Element) nodeList.item(0); NodeList childNodeList = element.getChildNodes(); Node childNode = (Node) childNodeList.item(0); if (childNode != null) { tagValue = childNode.getNodeValue(); } return tagValue; } private List<Column> readOrdinaryColumns(Element parentElement, String tagName) { List<Column> columnList = new ArrayList<Column>(); NodeList nodeList = parentElement.getElementsByTagName(tagName); Element element = (Element) nodeList.item(0); NodeList childNodeList = element.getChildNodes(); if (childNodeList != null) { int length = childNodeList.getLength(); for (int i = 0; i < length; i++) { Node childNode = (Node) childNodeList.item(i); if (childNode != null && childNode.getNodeType() == Node.ELEMENT_NODE) { Element childElement = (Element) childNode; NodeList grandChildNodeList = childElement.getChildNodes(); Node grandChildNode = (Node) grandChildNodeList.item(0); if (grandChildNode != null) { columnList.add(new Column(grandChildNode.getNodeValue(), true)); } } } } return columnList; } private void validateRecordSource(RecordSource recordSource) throws BadRecordSourceException { if (recordSource.getOrder() == null) { throw new BadRecordSourceException("Null 'order' not allowed."); } if (recordSource.getTableName() == null) { throw new BadRecordSourceException("Null 'table name' not allowed."); } if (recordSource.getPrimaryKeyColumnMap() == null || recordSource.getPrimaryKeyColumnMap().isEmpty()) { throw new BadRecordSourceException("Null 'pk columns' not allowed."); } if (recordSource.getRelationship() == RecordSource.Relationship.SLAVE) { if (recordSource.getForeignKeyColumnMap() == null) { throw new BadRecordSourceException("Null 'fk columns' not allowed for record sources related to master."); } } if (recordSource.getColumnList() == null || recordSource.getColumnList().isEmpty()) { throw new BadRecordSourceException("Null 'columns' not allowed."); } } }