/** * */ package fr.cedrik.inotes; import java.io.IOException; import java.io.InputStream; import java.nio.charset.Charset; import java.text.ParseException; import javax.xml.namespace.QName; import javax.xml.stream.FactoryConfigurationError; import javax.xml.stream.Location; import javax.xml.stream.XMLEventReader; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLReporter; import javax.xml.stream.XMLStreamException; import javax.xml.stream.events.Attribute; import javax.xml.stream.events.StartElement; import javax.xml.stream.events.XMLEvent; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import fr.cedrik.email.MessagesMetaData; import fr.cedrik.util.DateUtils; /** * @author Cédrik LIME */ // StAX event API class MeetingNoticesXMLConverter { protected static final Logger logger = LoggerFactory.getLogger(MeetingNoticesXMLConverter.class); public MeetingNoticesXMLConverter() { } protected XMLEventReader getXMLEventReader(InputStream input, Charset charset) throws FactoryConfigurationError, XMLStreamException { XMLInputFactory factory = XMLInputFactory.newInstance(); if (factory.isPropertySupported(XMLInputFactory.IS_VALIDATING)) { factory.setProperty(XMLInputFactory.IS_VALIDATING, Boolean.FALSE); } if (factory.isPropertySupported(XMLInputFactory.IS_COALESCING)) { factory.setProperty(XMLInputFactory.IS_COALESCING, Boolean.TRUE); } factory.setXMLReporter(new XMLReporter() { @Override public void report(String message, String errorType, Object relatedInformation, Location location) throws XMLStreamException { logger.warn("XML error of type: " + errorType + " at ligne: " + location.getLineNumber() + " column: " + location.getColumnNumber() + ", message: " + message); } }); XMLEventReader reader; if (charset != null) { reader = factory.createXMLEventReader(input, charset.name()); } else { reader = factory.createXMLEventReader(input); } return reader; } public MessagesMetaData<MeetingNoticeMetaData> convertXML(InputStream input, Charset charset) throws IOException, XMLStreamException { XMLEventReader reader = getXMLEventReader(input, charset); MessagesMetaData<MeetingNoticeMetaData> notices = new MessagesMetaData<MeetingNoticeMetaData>(); while (reader.hasNext()) { XMLEvent next = reader.nextEvent(); if (next.isStartElement()) { StartElement start = next.asStartElement(); String startName = start.getName().getLocalPart(); if ("viewentry".equals(startName)) { try { MeetingNoticeMetaData notice = new MeetingNoticeMetaData(); loadViewEntry(notice, start, reader); if (StringUtils.isBlank(notice.getId())) { logger.error("Error while parsing XML viewentry: empty unid!"); return null; } notices.entries.add(notice); } catch (ParseException e) { logger.error("", e); return null; } } else if ("dbquotasize".equals(startName)) { loadDbQuotaSize(notices, reader); } else { logger.debug("Unknown root element: {}", startName); } } } reader.close(); return notices; } protected void loadDbQuotaSize(MessagesMetaData<?> notices, XMLEventReader reader) throws XMLStreamException { while (reader.hasNext()) { XMLEvent next = reader.nextEvent(); if (next.isStartElement()) { StartElement start = next.asStartElement(); String startName = start.getName().getLocalPart(); if ("dbsize".equals(startName)) { notices.dbsize = Integer.parseInt(readElementValue(reader, start)); } else if ("sizelimit".equals(startName)) { notices.sizelimit = Integer.parseInt(readElementValue(reader, start)); } else if ("warning".equals(startName)) { notices.warning = Integer.parseInt(readElementValue(reader, start)); } else if ("ignorequota".equals(startName)) { notices.ignorequota = Integer.parseInt(readElementValue(reader, start)); } else if ("currentusage".equals(startName)) { notices.currentusage = Integer.parseInt(readElementValue(reader, start)); } else { logger.debug("Unknown DbQuotaSize element: {}", startName); } } else if (next.isEndElement()) { if ("dbquotasize".equals(next.asEndElement().getName().getLocalPart())) { return; } } } } protected void loadViewEntry(MeetingNoticeMetaData notice, StartElement viewEntry, XMLEventReader reader) throws XMLStreamException, ParseException { Attribute unid = viewEntry.getAttributeByName(QName.valueOf("unid")); notice.unid = unid.getValue(); Attribute noteid = viewEntry.getAttributeByName(QName.valueOf("noteid")); notice.noteid = noteid.getValue(); while (reader.hasNext()) { XMLEvent next = reader.nextEvent(); if (next.isStartElement()) { StartElement start = next.asStartElement(); String startName = start.getName().getLocalPart(); if ("entrydata".equals(startName)) { // read data value String value = readSingleSubElementValue(reader, start); // determine which attribute this is String name = start.getAttributeByName(QName.valueOf("name")).getValue(); // if ("$149".equals(name)) { // message.xxx = value; if ("$144".equals(name)) { // meeting date if (StringUtils.isNotBlank(value)) { notice.meetingDate = DateUtils.parseLotusXMLDate(value); } // } else if ("SametimeInfo".equals(name)) { // availability // message.availability = value; } else if ("$2".equals(name)) { // from notice.from = value; } else if ("$3".equals(name)) { // date if (StringUtils.isNotBlank(value)) { notice.date = DateUtils.parseLotusXMLDate(value); } } else if ("$147".equals(name)) { // subject notice.subject = value; // } else if ("$146".equals(name)) { // message.xxx = value; // } else if ("$154".equals(name)) { // message.xxx = value; } else { logger.debug("Unknown EntryData attribute value: {}", name); } } else { logger.debug("Unknown ViewEntry element: {}", startName); } } else if (next.isEndElement()) { if ("viewentry".equals(next.asEndElement().getName().getLocalPart())) { return; } } } } protected String readSingleSubElementValue(XMLEventReader reader, StartElement start) throws XMLStreamException { String value = null; boolean inValueElement = false; while (reader.hasNext()) { XMLEvent next = reader.nextEvent(); if (next.isStartElement()) { inValueElement = true; StartElement startData = next.asStartElement(); logger.trace("{} element: {}", start.getName().getLocalPart(), startData.getName().getLocalPart()); } else if (next.isCharacters() && inValueElement) { value = next.asCharacters().getData(); } else if (next.isEndElement()) { inValueElement = false; if (start.getName().getLocalPart().equals(next.asEndElement().getName().getLocalPart())) { return value; } } } return value; } protected String readElementValue(XMLEventReader reader, StartElement start) throws XMLStreamException { String value = null; while (reader.hasNext()) { XMLEvent next = reader.nextEvent(); if (next.isCharacters()) { value = next.asCharacters().getData(); } else if (next.isEndElement()) { if (start.getName().getLocalPart().equals(next.asEndElement().getName().getLocalPart())) { return value; } } } return value; } }