/*******************************************************************************
* Copyright (c) 2013-2014 MEDEVIT.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* MEDEVIT <office@medevit.at> - initial API and implementation
******************************************************************************/
package at.medevit.atc_codes.internal;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;
import at.medevit.atc_codes.ATCCode;
import at.medevit.atc_codes.ATCCodeService;
import at.medevit.atc_codes.parser.ATCDDDParser.ATCDDDDefinition;
import at.medevit.atc_codes.parser.ATCParser.ATCDefinition;
public class ATCCodes {
public static final String ATC_CODES_SERIALIZED_FILE = "/lib/ATCCodesMap.ser";
private static ATCCodes instance = null;
private HashMap<String, ATCCode> atcCodesMap = null;
private ATCHierarchyComparator ahc = new ATCHierarchyComparator();
private ATCCodes(){
initHashMapFromSerializedObject();
}
public static ATCCodes getInstance(){
if (instance == null) {
instance = new ATCCodes();
}
return instance;
}
private void initHashMapFromSerializedObject(){
try {
// use buffering
InputStream is = ATCCodes.class.getResourceAsStream(ATC_CODES_SERIALIZED_FILE);
if (is == null) {
// patch to load library from within non-osgi environment
is = ATCCodes.class.getResourceAsStream("/ATCCodesMap.ser");
}
ObjectInput input = new ObjectInputStream(is);
try {
// deserialize the List
atcCodesMap =
(HashMap<java.lang.String, at.medevit.atc_codes.ATCCode>) input.readObject();
} finally {
input.close();
}
} catch (ClassNotFoundException | IOException ex) {
ex.printStackTrace();
}
}
protected HashMap<String, ATCCode> getAtcCodesMap(){
return atcCodesMap;
}
protected void initHashMap(List<ATCDefinition> atcDefinitions,
HashMap<String, ATCDDDDefinition> atcDDDDefinitions, HashMap<String, String> atcCodeToGerman){
atcCodesMap = new HashMap<String, at.medevit.atc_codes.ATCCode>();
for (ATCDefinition def : atcDefinitions) {
ATCDDDDefinition dddDef = atcDDDDefinitions.get(def.atcCode);
int level = determineLevel(def.atcCode);
float ddd = 0.0f;
ATCCode.DDD_UNIT_TYPE dddUt = null;
String dddAc = null;
String dddComment = null;
if (dddDef != null) {
ddd =
(dddDef.ddd != null && dddDef.ddd.length() > 0) ? Float.parseFloat(dddDef.ddd)
: 0.0f;
if (dddDef.unitType != null)
dddUt = ATCCode.DDD_UNIT_TYPE.valueOf(dddDef.unitType.toUpperCase());
if (dddDef.admCode != null)
dddAc = dddDef.admCode;
if (dddDef.dddComment != null)
dddComment = dddDef.dddComment;
}
String germanName = atcCodeToGerman.get(def.atcCode);
ATCCode c =
new ATCCode(def.atcCode, def.name, germanName, level, ddd, dddUt, dddAc, dddComment);
atcCodesMap.put(def.atcCode, c);
}
}
private int determineLevel(String atcCode){
switch (atcCode.length()) {
case 7:
return 5;
case 5:
return 4;
case 4:
return 3;
case 3:
return 2;
case 1:
return 1;
default:
return 0;
}
}
/**
* Used in test code only
*
* @param inFile
* @param parser
* @throws IOException
*/
protected void readXMLFile(File inFile, DefaultHandler parser) throws IOException{
try {
XMLReader xr = XMLReaderFactory.createXMLReader();
xr.setContentHandler(parser);
xr.setErrorHandler(parser);
FileReader fr = new FileReader(inFile);
xr.parse(new InputSource(fr));
} catch (SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
*
* @param atcCode
* @return {@link ATCCode} if valid ATC code, else <code>null</code>
*/
public ATCCode getATCCode(String atcCode){
return atcCodesMap.get(atcCode.trim());
}
/**
* @see ATCCodeService#getATCCodesMatchingName(String, int)
*/
public List<ATCCode> getATCCodesMatchingName(String name, int language, int matchType){
List<ATCCode> ret = new ArrayList<>();
Collection<ATCCode> values = atcCodesMap.values();
if (matchType == ATCCodeService.MATCH_NAME_BY_NAME_ONLY) {
matchByNameOnly(ret, values, language, name);
} else {
matchByNameOrATC(ret, values, language, name);
}
orderByATCHierarchy(ret);
return ret;
}
/**
* Orders the elements in the list according to the ATC hierarchy
*
* @param ret
*/
private void orderByATCHierarchy(List<ATCCode> ret){
Collections.sort(ret, ahc);
}
private void matchByNameOrATC(List<ATCCode> ret, Collection<ATCCode> values, int language,
String name){
if (language == ATCCodeService.ATC_NAME_LANGUAGE_GERMAN) {
for (ATCCode atcCode : values) {
if ((atcCode.name_german != null && atcCode.name_german.toLowerCase().contains(
name.toLowerCase()))
|| atcCode.atcCode.contains(name)) {
ret.add(atcCode);
} else if (atcCode.name != null
&& atcCode.name.toLowerCase().contains(name.toLowerCase())) {
ret.add(atcCode);
}
}
} else {
for (ATCCode atcCode : values) {
if (atcCode.name != null && atcCode.name.toLowerCase().contains(name.toLowerCase())) {
ret.add(atcCode);
}
}
}
}
private void matchByNameOnly(List<ATCCode> ret, Collection<ATCCode> values, int language,
String name){
if (language == ATCCodeService.ATC_NAME_LANGUAGE_GERMAN) {
for (ATCCode atcCode : values) {
if (atcCode.name_german != null
&& atcCode.name_german.toLowerCase().contains(name.toLowerCase())) {
ret.add(atcCode);
} else if (atcCode.name != null
&& atcCode.name.toLowerCase().contains(name.toLowerCase())) {
ret.add(atcCode);
}
}
} else {
for (ATCCode atcCode : values) {
if (atcCode.name != null && atcCode.name.toLowerCase().contains(name.toLowerCase())) {
ret.add(atcCode);
}
}
}
}
public List<ATCCode> getAllATCCodes(){
ArrayList<ATCCode> list = new ArrayList<ATCCode>(atcCodesMap.values());
orderByATCHierarchy(list);
return Collections.unmodifiableList(list);
}
}