package com.vmware.vcloud.nclient;
import java.io.StringReader;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.ObjectWriter;
public class NotificationMessage implements Comparable<NotificationMessage>{
final static String NS_URI = "http://www.vmware.com/vcloud/extension/v1.5";
public static final String JSON_KEY_TYPE = "type";
public static final String JSON_KEY_STATUS = "operationSuccess";
public static final String JSON_KEY_TIMESTAMP = "timestamp";
public static final String JSON_KEY_ENTITY = "entity";
public static final String JSON_CONTENT_TYPE = "application/json";
public static final String XML_CONTENT_TYPE = "application/xml";
final String payload;
final Map<String, Object> headers;
final String contentType;
String type;
String entityType;
String entityName;
String entityHref;
String orgName;
String userName;
Date timestamp;
boolean success;
private NotificationMessage(String payload, Map<String, Object> headers, String contentType) {
this.payload = payload;
this.headers = headers;
this.contentType = contentType;
}
public static NotificationMessage createFromPayloadAndHeaders(String payload, Map<String, Object> headers) throws Exception {
boolean isXml = payload.startsWith("<?xml");
return isXml ? createFromXml(payload, headers) : createFromJson(payload, headers);
}
public String getContentType() {
return contentType;
}
static NotificationMessage createFromXml(String payload, Map<String, Object> headers) throws Exception {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setValidating(false);
factory.setNamespaceAware(true);
DocumentBuilder docBuilder = factory.newDocumentBuilder();
Document doc = docBuilder.parse(new InputSource(new StringReader(payload)));
NotificationMessage result = new NotificationMessage(payload, headers, XML_CONTENT_TYPE);
Node root = doc.getFirstChild();
result.type = root.getAttributes().getNamedItem("type").getNodeValue();
Node resolver = doc.getElementsByTagNameNS(NS_URI, "Link").item(0);
String resolverHref = resolver.getAttributes().getNamedItem("href").getNodeValue();
NodeList links = doc.getElementsByTagNameNS(NS_URI, "EntityLink");
Node org = getLinkByRel(links, "up");
result.orgName = org.getAttributes().getNamedItem("name").getNodeValue();
Node user = getLinkByRel(links, "down");
if (user != null) {
result.userName = user.getAttributes().getNamedItem("name").getNodeValue();
}
Node entity = getLinkByRel(links, "entity");
if (entity != null) {
result.entityType = entity.getAttributes().getNamedItem("type").getNodeValue();
int ind = result.entityType.indexOf(':');
if (ind >= 0) {
result.entityType = result.entityType.substring(ind + 1);
}
Node namedItem = entity.getAttributes().getNamedItem("name");
if (namedItem != null) {
result.entityName = namedItem.getNodeValue();
}
result.entityHref = resolverHref + entity.getAttributes().getNamedItem("id").getNodeValue();
}
Node ts = doc.getElementsByTagNameNS(NS_URI, "Timestamp").item(0);
XMLGregorianCalendar xmlDate = DatatypeFactory.newInstance().newXMLGregorianCalendar(ts.getTextContent());
result.timestamp = xmlDate.toGregorianCalendar().getTime();
Node success = doc.getElementsByTagNameNS(NS_URI, "OperationSuccess").item(0);
result.success = Boolean.parseBoolean(success.getTextContent());
return result;
}
static NotificationMessage createFromJson(String payload, Map<String, Object> headers) throws Exception {
ObjectMapper mapper = new ObjectMapper();
@SuppressWarnings("unchecked")
Map<String, Object> data = mapper.readValue(payload, Map.class);
ObjectWriter writer = mapper.defaultPrettyPrintingWriter();
payload = writer.writeValueAsString(data);
NotificationMessage result = new NotificationMessage(payload, headers, JSON_CONTENT_TYPE);
if (data.containsKey(JSON_KEY_TYPE)) {
result.type = (String) data.get(JSON_KEY_TYPE);
}
if (data.containsKey(JSON_KEY_ENTITY)) {
String entity = (String) data.get(JSON_KEY_ENTITY);
Pattern p = Pattern.compile("urn:vcloud:([^:]+):.*");
Matcher m = p.matcher(entity);
if (m.find()) {
result.entityType = m.group(1);
}
}
if (data.containsKey(JSON_KEY_STATUS)) {
result.success = (Boolean) data.get(JSON_KEY_STATUS);
}
if (data.containsKey(JSON_KEY_TIMESTAMP)) {
try {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
result.timestamp = sdf.parse((String) data.get(JSON_KEY_TIMESTAMP));
} catch (java.text.ParseException ex) {
String date = (String) data.get(JSON_KEY_TIMESTAMP);
XMLGregorianCalendar xmlDate = DatatypeFactory.newInstance().newXMLGregorianCalendar(date);
result.timestamp = xmlDate.toGregorianCalendar().getTime();
}
}
return result;
}
static Node getLinkByRel(NodeList links, String rel) {
for (int i = 0; i < links.getLength(); i++) {
Node link = links.item(i);
if (link.getAttributes().getNamedItem("rel").getNodeValue().equals(rel)) {
return link;
}
}
return null;
}
public String getType() {
return type;
}
public String getEntityType() {
return entityType == null ? "" : entityType;
}
public String getEntityName() {
return entityName == null ? "" : entityName;
}
public String getEntityHref() {
return entityHref == null ? "" : entityHref;
}
public String getOrgName() {
return orgName == null ? "" : orgName;
}
public String getUserName() {
return userName == null ? "" : userName;
}
public Date getTimestamp() {
return timestamp;
}
public boolean isOperationSuccess() {
return success;
}
public String getPayload() {
return payload;
}
public Map<String, Object> getHeaders() {
return headers;
}
@Override
public int compareTo(NotificationMessage o) {
return getType().compareTo(o.getType());
}
}