Java tutorial
/** * 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.openmrs.module.drawing.obs.handler; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Date; import javax.imageio.ImageIO; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.openmrs.Obs; import org.openmrs.User; import org.openmrs.api.context.Context; import org.openmrs.module.drawing.AnnotatedImage; import org.openmrs.module.drawing.ImageAnnotation; import org.openmrs.module.drawing.ImageAnnotation.Status; import org.openmrs.module.drawing.Position; import org.openmrs.obs.ComplexData; import org.openmrs.obs.handler.ImageHandler; import org.openmrs.web.WebConstants; import org.w3c.dom.DOMImplementation; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; /** * */ public class DrawingHandler extends ImageHandler { private Log log = LogFactory.getLog(DrawingHandler.class); /** * @see org.openmrs.obs.handler.ImageHandler#saveObs(org.openmrs.Obs) */ @Override public Obs saveObs(Obs obs) { ComplexData c = obs.getComplexData(); AnnotatedImage ai = (AnnotatedImage) c.getData(); obs.setComplexData(new ComplexData(c.getTitle(), ai.getImage())); Obs o = super.saveObs(obs); for (ImageAnnotation annotation : ai.getAnnotations()) saveAnnotation(o, annotation, annotation.getStatus() == Status.DELETE); log.info("drawing:saving complexObs:" + o); return o; } public Obs getObs(Obs obs, String view) { File imageFile = getComplexDataFile(obs); BufferedImage img = null; try { img = ImageIO.read(imageFile); } catch (IOException e) { log.error("Trying to read file: " + imageFile.getAbsolutePath(), e); } AnnotatedImage aimage = loadMetadata(obs, new AnnotatedImage(img)); String url = "/" + WebConstants.WEBAPP_NAME + "/module/drawing/manage.form?obsId=" + obs.getId(); if (view == WebConstants.HYPERLINK_VIEW) { obs.setComplexData(new ComplexData(imageFile.getName(), url)); } else if (view == WebConstants.HTML_VIEW) { String html = "<a href=\"" + url + "\">" + imageFile.getName() + "</a>"; obs.setComplexData(new ComplexData(imageFile.getName(), html)); } else { obs.setComplexData(new ComplexData(imageFile.getName(), aimage)); } return obs; } /** * Parses the XML metadata file (if it exists) loads the metadata into the given AnnotatedImage * and returns it. * * @param obs */ public AnnotatedImage loadMetadata(Obs obs, AnnotatedImage image) { File metadataFile = getComplexMetadataFile(obs); image.setHandler(this); ArrayList<ImageAnnotation> annotations = new ArrayList<ImageAnnotation>(); if (metadataFile.exists() && metadataFile.canRead()) { try { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document xmldoc = builder.parse(metadataFile); NodeList annotationNodeList = xmldoc.getElementsByTagName("Annotation"); for (int i = 0; i < annotationNodeList.getLength(); i++) { try { Node node = annotationNodeList.item(i); NamedNodeMap attributes = node.getAttributes(); String text = node.getTextContent(); String idString = attributes.getNamedItem("id").getNodeValue(); String date = attributes.getNamedItem("date").getNodeValue(); String userid = attributes.getNamedItem("userid").getNodeValue(); String xcoordinate = attributes.getNamedItem("xcoordinate").getNodeValue(); String ycoordinate = attributes.getNamedItem("ycoordinate").getNodeValue(); Position position = new Position(Integer.parseInt(xcoordinate), Integer.parseInt(ycoordinate)); User user = Context.getUserService().getUser(Integer.parseInt(userid)); annotations.add(new ImageAnnotation(Integer.parseInt(idString), position, text, new Date(Long.parseLong(date)), user, Status.UNCHANGED)); } catch (NumberFormatException e) { // Skip that annotation } } } catch (Exception e) { //Likely ParserConfigurationException, SAXException or IOException. //Fail silently, log the error and return the image with no annotations. log.error("Error loading annotations", e); } } image.setAnnotations(annotations.toArray(new ImageAnnotation[0])); return image; } public void saveAnnotation(Obs obs, ImageAnnotation annotation, boolean delete) { try { log.info("drawing: Saving annotation for obs " + obs.getObsId()); File metadataFile = getComplexMetadataFile(obs); log.info("drawing: Using file " + metadataFile.getCanonicalPath()); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document xmldoc; Element annotationsParent; int newId = 0; if (metadataFile.exists()) { xmldoc = builder.parse(metadataFile); annotationsParent = (Element) xmldoc.getElementsByTagName("Annotations").item(0); NodeList annotationNodeList = xmldoc.getElementsByTagName("Annotation"); for (int i = 0; i < annotationNodeList.getLength(); i++) { NamedNodeMap attributes = annotationNodeList.item(i).getAttributes(); String idString = attributes.getNamedItem("id").getNodeValue(); int existingId = Integer.parseInt(idString); if (existingId == annotation.getId() && !(annotation.getStatus() == Status.UNCHANGED)) { annotationsParent.removeChild(annotationNodeList.item(i)); break; } if (existingId >= newId) newId = existingId + 1; } } else { metadataFile.createNewFile(); DOMImplementation domImpl = builder.getDOMImplementation(); xmldoc = domImpl.createDocument(null, "ImageMetadata", null); Element root = xmldoc.getDocumentElement(); annotationsParent = xmldoc.createElementNS(null, "Annotations"); root.appendChild(annotationsParent); } if (!delete && annotation.getStatus() != Status.UNCHANGED) { if (annotation.getId() >= 0) newId = annotation.getId(); Element e = xmldoc.createElementNS(null, "Annotation"); Node n = xmldoc.createTextNode(annotation.getText()); e.setAttributeNS(null, "id", newId + ""); e.setAttributeNS(null, "xcoordinate", annotation.getLocation().getX() + ""); e.setAttributeNS(null, "ycoordinate", annotation.getLocation().getY() + ""); e.setAttributeNS(null, "userid", annotation.getUser().getUserId() + ""); e.setAttributeNS(null, "date", annotation.getDate().getTime() + ""); e.appendChild(n); annotationsParent.appendChild(e); } Transformer transformer = TransformerFactory.newInstance().newTransformer(); transformer.setOutputProperty(OutputKeys.ENCODING, "UTF8"); transformer.setOutputProperty(OutputKeys.INDENT, "yes"); transformer.transform(new DOMSource(xmldoc), new StreamResult(metadataFile)); log.info("drawing: Saving annotation complete"); } catch (Exception e) { log.error("drawing: Error saving image metadata: " + e.getClass() + " " + e.getMessage()); } } /** * Convenience method to create and return a file for the stored metadata file * * @param obs * @return */ public static File getComplexMetadataFile(Obs obs) { File imageFile = ImageHandler.getComplexDataFile(obs); try { return new File(imageFile.getCanonicalPath() + ".xml"); } catch (IOException e) { return new File(imageFile.getAbsolutePath() + ".xml"); } } }