package gov.nih.ncgc.bard.tools; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; import gov.nih.ncgc.bard.capextract.CAPAnnotation; import gov.nih.ncgc.bard.capextract.CAPDictionary; import gov.nih.ncgc.bard.capextract.CAPDictionaryElement; import java.io.IOException; import java.math.BigInteger; import java.sql.SQLException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; /** * Miscellaneous methods to handle CAP and non-CAP annotations. * * @author Rajarshi Guha */ public class AnnotationUtils { public static Map<String, String> getMinimumRequiredAssayAnnotations(Long aid, DBUtils db) throws SQLException, ClassNotFoundException, IOException { List<String> annoKeys = Arrays.asList(new String[]{ "species name", "assay format", "assay type", "cultured cell name", "detection method type", "detection instrument name", "assay footprint", "excitation wavelength", "emission wavelength", "absorbance wavelength", "measurement wavelength"}); List<CAPAnnotation> annos = db.getAssayAnnotations(aid); CAPDictionary dict = db.getCAPDictionary(); Map<String, String> ret = new HashMap<String, String>(); for (CAPAnnotation anno : annos) { String key = anno.key; String value = anno.value; if (key != null && Util.isNumber(key)) key = dict.getNode(new BigInteger(key)).getLabel(); if (value != null && Util.isNumber(value)) { CAPDictionaryElement node = dict.getNode(new BigInteger(value)); if (node != null) value = dict.getNode(new BigInteger(value)).getLabel(); else value = null; } if (annoKeys.contains(key) && value != null) { anno.key = key; anno.value = value; ret.put(key, value); } } return ret; } public static JsonNode getAnnotationJson(List<CAPAnnotation> a) throws ClassNotFoundException, IOException, SQLException { DBUtils db = new DBUtils(); CAPDictionary dict = db.getCAPDictionary(); // lets group these annotations and construct our JSON response CAPDictionaryElement node; Map<Integer, List<CAPAnnotation>> contexts = new HashMap<Integer, List<CAPAnnotation>>(); for (CAPAnnotation anno : a) { Integer id = anno.id; if (id == null) id = -1; // corresponds to dynamically generated annotations (from non-CAP sources) // go from dict key to label if (anno.key != null && Util.isNumber(anno.key)) { node = dict.getNode(new BigInteger(anno.key)); anno.key = node != null ? node.getLabel() : anno.key; } if (anno.value != null && Util.isNumber(anno.value)) { node = dict.getNode(new BigInteger(anno.value)); anno.value = node != null ? node.getLabel() : anno.value; } if (contexts.containsKey(id)) { List<CAPAnnotation> la = contexts.get(id); la.add(anno); contexts.put(id, la); } else { List<CAPAnnotation> la = new ArrayList<CAPAnnotation>(); la.add(anno); contexts.put(id, la); } } ObjectMapper mapper = new ObjectMapper(); ArrayNode docNode = mapper.createArrayNode(); ArrayNode contextNode = mapper.createArrayNode(); ArrayNode measureNode = mapper.createArrayNode(); ArrayNode miscNode = mapper.createArrayNode(); for (Integer contextId : contexts.keySet()) { List<CAPAnnotation> comps = contexts.get(contextId); Collections.sort(comps, new Comparator<CAPAnnotation>() { @Override public int compare(CAPAnnotation o1, CAPAnnotation o2) { if (o1.displayOrder == o2.displayOrder) return 0; return o1.displayOrder < o2.displayOrder ? -1 : 1; } }); JsonNode arrayNode = mapper.valueToTree(comps); ObjectNode n = mapper.createObjectNode(); n.put("id", comps.get(0).id); n.put("name", comps.get(0).contextRef); n.put("group", comps.get(0).contextGroup); n.put("comps", arrayNode); if (comps.get(0).source.equals("cap-doc")) docNode.add(n); else if (comps.get(0).source.equals("cap-context")) contextNode.add(n); else if (comps.get(0).source.equals("cap-measure")) measureNode.add(n); else { for (CAPAnnotation misca : comps) miscNode.add(mapper.valueToTree(misca)); } } ObjectNode topLevel = mapper.createObjectNode(); topLevel.put("contexts", contextNode); topLevel.put("measures", measureNode); topLevel.put("docs", docNode); topLevel.put("misc", miscNode); return topLevel; } }