package com.renaghan.notes2cloud; import org.apache.log4j.Logger; import javax.xml.namespace.QName; import javax.xml.stream.*; import javax.xml.stream.events.Attribute; import javax.xml.stream.events.StartElement; import javax.xml.stream.events.XMLEvent; import java.io.IOException; import java.io.Reader; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Collection; import java.util.Date; /** * parse notes mail export list response * * @author prenagha */ public class NotesListResponseParser { private static final Logger LOG = Logger.getLogger(NotesListResponseParser.class); public NotesListResponseParser() { } private XMLEventReader getXMLEventReader(Reader input) 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 { LOG.warn("XML error of type: " + errorType + " at line: " + location.getLineNumber() + " column: " + location.getColumnNumber() + ", message: " + message); } }); return factory.createXMLEventReader(input); } public Collection<NotesMailMeta> convertXML(Reader input) throws IOException, XMLStreamException { XMLEventReader reader = getXMLEventReader(input); Collection<NotesMailMeta> messages = new ArrayList<NotesMailMeta>(700); while (reader.hasNext()) { XMLEvent next = reader.nextEvent(); if (next.isStartElement()) { StartElement start = next.asStartElement(); String startName = start.getName().getLocalPart(); if ("viewentry".equals(startName)) { try { NotesMailMeta msg = loadViewEntry(start, reader); if (msg != null) { messages.add(msg); LOG.trace(msg); //if (messages.size() > 4) break; } } catch (ParseException e) { throw new RuntimeException("parse Error converting xml " + start, e); } } } } reader.close(); return messages; } protected NotesMailMeta loadViewEntry(StartElement viewEntry, XMLEventReader reader) throws XMLStreamException, ParseException { Attribute unid = viewEntry.getAttributeByName(QName.valueOf("unid")); String id = unid.getValue(); if (id == null) throw new RuntimeException("Item missing unid"); id = id.trim(); if (id == null) throw new RuntimeException("Item has empty unid"); String type = null; Calendar date = null; String subject = null; String name = null; try { while (reader.hasNext()) { XMLEvent next = reader.nextEvent(); if (next.isStartElement()) { StartElement start = next.asStartElement(); String startName = start.getName().getLocalPart(); if ("entrydata".equals(startName)) { name = start.getAttributeByName(QName.valueOf("name")).getValue(); if (type == null && ("$86".equals(name) || "$149".equals(name))) { // type type = readSingleSubElementValue(reader, start); if (type == null) throw new RuntimeException("Type is empty"); } else if (date == null && ("$68".equals(name) || "$134".equals(name) || "$144".equals(name))) { // date String dateStr = readSingleSubElementValue(reader, start); if (dateStr == null) throw new RuntimeException("Date is null"); date = convertTimeFormat(dateStr); } else if (subject == null && ("$74".equals(name) || "$147".equals(name))) { // subject subject = readSingleSubElementValue(reader, start); } } } else if (next.isEndElement()) { if ("viewentry".equals(next.asEndElement().getName().getLocalPart())) { return new NotesMailMeta(id, type, date, subject); } } } } catch (Exception e) { throw new RuntimeException("Error parsing " + id + " " + name, e); } throw new RuntimeException("Can't load view entry " + id); } protected String readSingleSubElementValue(XMLEventReader reader, StartElement start) throws XMLStreamException { String value = null; while (reader.hasNext()) { XMLEvent next = reader.nextEvent(); if (value == null && next.isCharacters()) { value = next.asCharacters().getData(); value = value == null ? value : value.trim(); value = value == null || value.isEmpty() ? null : value; } else if (next.isEndElement() && start.getName().getLocalPart().equals(next.asEndElement().getName().getLocalPart())) { break; } } return value; } private Calendar convertTimeFormat(String dateStr) throws ParseException { String year, month, day, hour, minute, second, timezone1, timezone; if (dateStr == null) return null; if (dateStr.length() == 8) { year = dateStr.substring(0, 4); month = dateStr.substring(4, 6); day = dateStr.substring(6, 8); hour = "00"; minute = "00"; second = "00"; String str = year + "-" + month + "-" + day + " " + hour + ":" + minute + ":" + second; SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date sd = sdf.parse(str); Calendar c = Calendar.getInstance(); c.setTime(sd); return c; } if (dateStr.length() < 18) throw new IllegalArgumentException("Notes time too short " + dateStr); // 20100405T170000,00-04 // 20100412T115157,95-04 year = dateStr.substring(0, 4); month = dateStr.substring(4, 6); day = dateStr.substring(6, 8); hour = dateStr.substring(9, 11); minute = dateStr.substring(11, 13); second = dateStr.substring(13, 15); timezone1 = dateStr.substring(18, 21); //timezone2 = lotusnotesDateTimeFormat.substring(16, 18); timezone = timezone1 + "00"; String str = year + "-" + month + "-" + day + " " + hour + ":" + minute + ":" + second + timezone; SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ssZ"); Date sd = sdf.parse(str); Calendar c = Calendar.getInstance(); c.setTime(sd); return c; } }