/* * This file is part of ADDIS (Aggregate Data Drug Information System). * ADDIS is distributed from http://drugis.org/. * Copyright © 2009 Gert van Valkenhoef, Tommi Tervonen. * Copyright © 2010 Gert van Valkenhoef, Tommi Tervonen, Tijs Zwinkels, * Maarten Jacobs, Hanno Koeslag, Florin Schimbinschi, Ahmad Kamal, Daniel * Reid. * Copyright © 2011 Gert van Valkenhoef, Ahmad Kamal, Daniel Reid, Florin * Schimbinschi. * Copyright © 2012 Gert van Valkenhoef, Daniel Reid, Joël Kuiper, Wouter * Reckman. * Copyright © 2013 Gert van Valkenhoef, Joël Kuiper. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.drugis.addis.util.jaxb; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import javax.xml.bind.Unmarshaller; import javax.xml.bind.ValidationEvent; import javax.xml.bind.ValidationEventHandler; import javax.xml.bind.ValidationEventLocator; import org.drugis.addis.entities.Domain; import org.drugis.addis.entities.data.AddisData; public class JAXBHandler { public static class XmlFormatType { public static final int INVALID = -1; public static final int LEGACY_VERSION = 0; public static final int CURRENT_VERSION = currentSchemaVersion(); private final int d_version; XmlFormatType(int version) { d_version = version; } public int getVersion() { return d_version; } public boolean isLegacy() { return d_version == LEGACY_VERSION; } public boolean isPast() { return d_version < CURRENT_VERSION; } public boolean isFuture() { return d_version > CURRENT_VERSION; } public boolean isValid() { return d_version > INVALID; } } public static int currentSchemaVersion() { try { InputStream is = Domain.class.getResourceAsStream("current-schema-version"); BufferedReader br = new BufferedReader(new InputStreamReader(is)); return Integer.parseInt(br.readLine()); } catch (Exception e) { throw new RuntimeException(e); } } public static class JAXB { private volatile static JAXBContext singleton; public static JAXBContext getInstance() { if (singleton == null) { synchronized (JAXBContext.class) { if (singleton == null) try { singleton = JAXBContext.newInstance("org.drugis.addis.entities.data"); } catch (JAXBException e) { throw new RuntimeException("Failed to initialze JAXB", e); } } } return singleton; } } public static void marshallAddisData(AddisData data, OutputStream os) throws JAXBException { Marshaller marshaller = JAXB.getInstance().createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); marshaller.setProperty(Marshaller.JAXB_NO_NAMESPACE_SCHEMA_LOCATION, "http://drugis.org/files/addis-" + XmlFormatType.CURRENT_VERSION + ".xsd"); marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8"); marshaller.marshal(data, os); } public static AddisData unmarshallAddisData(InputStream is) throws JAXBException { Unmarshaller unmarshaller = JAXB.getInstance().createUnmarshaller(); unmarshaller.setEventHandler(new AddisDataValidationEventHandler()); return (AddisData) unmarshaller.unmarshal(is); } // should be moved somewhere else and changed public static class AddisDataValidationEventHandler implements ValidationEventHandler { public boolean handleEvent(ValidationEvent ve) { ValidationEventLocator locator = ve.getLocator(); //Print message from valdation event System.err.println("Invalid AddisData document: " + locator.getURL()); System.err.println("Error: " + ve.getMessage()); //Output line and column number System.err.println("Error at column " + locator.getColumnNumber() + ", line " + locator.getLineNumber()); if (ve.getSeverity() == ValidationEvent.ERROR) { return true; // keeps unmarshalling } else if (ve.getSeverity() == ValidationEvent.FATAL_ERROR) { System.err.println("Corrupt AddisData document ... stopped unmarshalling."); } return false; } } public static XmlFormatType determineXmlType(InputStream is) throws IOException { is.mark(1024); byte[] buffer = new byte[1024]; int bytesRead = is.read(buffer); if (bytesRead < 0) { return new XmlFormatType(XmlFormatType.INVALID); } String str = new String(buffer, 0, bytesRead); Pattern addisPattern = Pattern.compile("^(<\\?xml[^\\?]*\\?>[\\s]*)?<addis-data[^>]*>"); Matcher addisMatcher = addisPattern.matcher(str); if (!addisMatcher.find()) { return new XmlFormatType(XmlFormatType.INVALID); } Pattern versionPattern = Pattern.compile("http://drugis.org/files/addis-([0-9]*).xsd"); Matcher versionMatcher = versionPattern.matcher(str); XmlFormatType type = null; if (versionMatcher.find()) { type = new XmlFormatType(Integer.parseInt(versionMatcher.group(1))); } else { type = new XmlFormatType(XmlFormatType.LEGACY_VERSION); } is.reset(); return type; } }