/*=============================================================================*
* Copyright 2006 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.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://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*=============================================================================*/
package org.apache.muse.ws.notification.impl;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.xml.namespace.QName;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.apache.muse.core.serializer.Serializer;
import org.apache.muse.core.serializer.SerializerRegistry;
import org.apache.muse.util.messages.Messages;
import org.apache.muse.util.messages.MessagesFactory;
import org.apache.muse.util.xml.XPathUtils;
import org.apache.muse.util.xml.XmlSerializable;
import org.apache.muse.util.xml.XmlUtils;
import org.apache.muse.ws.addressing.EndpointReference;
import org.apache.muse.ws.notification.NotificationMessage;
import org.apache.muse.ws.notification.WsnConstants;
import org.apache.muse.ws.notification.faults.TopicExpressionDialectUnknownFault;
import org.apache.muse.ws.notification.topics.WstConstants;
import org.apache.muse.ws.addressing.soap.SoapFault;
/**
*
* SimpleNotificationMessage is Muse's default implementation of the WS-Notification
* NotificationMessageHolderType type. It provides serialization capabilities for
* these messages and validation of their contents.
*
* @author Dan Jemiolo (danj)
*
*/
public class SimpleNotificationMessage implements XmlSerializable, NotificationMessage
{
//
// Used to look up all exception messages
//
private static Messages _MESSAGES = MessagesFactory.get(SimpleNotificationMessage.class);
private Map _messageContent = new LinkedHashMap();
private EndpointReference _producer = null;
private EndpointReference _subscription = null;
private QName _topicPath = null;
/**
*
* The default constructor provides no initialization, allowing users
* to create messages in an 'aseembly line' system, where pieces of
* the messages are added by different components before being published.
*
*/
public SimpleNotificationMessage()
{
//
// no initialization tasks - this allows for assembly line-like
// creation of messages
//
}
/**
*
* @param root
* A DOM Element representing a WS-N SimpleNotificationMessage
*
*/
public SimpleNotificationMessage(Element root)
throws SoapFault
{
if (root == null)
throw new NullPointerException(_MESSAGES.get("NullMessageElement"));
_topicPath = XmlUtils.getQNameFromChild(root, WsnConstants.TOPIC_QNAME);
Element producerXML = XmlUtils.getElement(root, WsnConstants.PRODUCER_QNAME);
if (producerXML != null)
_producer = new EndpointReference(producerXML);
Element subXML = XmlUtils.getElement(root, WsnConstants.SUBSCRIPTION_EPR_QNAME);
if (subXML != null)
_subscription = new EndpointReference(subXML);
Element messageXML = XmlUtils.getElement(root, WsnConstants.MESSAGE_QNAME);
//
// we have to have a Message element, even if it's empty
//
if (messageXML == null)
throw new SoapFault(_MESSAGES.get("NoMessageContent"));
Element[] children = XmlUtils.getAllElements(messageXML);
for (int n = 0; n < children.length; ++n)
addMessageContent(children[n]);
}
public SimpleNotificationMessage(QName topicPath)
{
_topicPath = topicPath;
}
public void addMessageContent(Element content)
{
if (content == null)
throw new NullPointerException(_MESSAGES.get("NullMessageContent"));
QName name = XmlUtils.getElementQName(content);
_messageContent.put(name, content);
}
public void addMessageContent(QName qname, Object content)
throws SoapFault
{
if (qname == null)
throw new NullPointerException(_MESSAGES.get("NullContentName"));
if (content == null)
throw new NullPointerException(_MESSAGES.get("NullMessageContent"));
SerializerRegistry registry = SerializerRegistry.getInstance();
Serializer ser = registry.getSerializer(content.getClass());
Element xml = ser.toXML(content, qname);
_messageContent.put(qname, xml);
}
public Element getMessageContent(QName qname)
{
return (Element)_messageContent.get(qname);
}
public Object getMessageContent(QName qname, Class type)
throws SoapFault
{
Element content = getMessageContent(qname);
SerializerRegistry registry = SerializerRegistry.getInstance();
Serializer ser = registry.getSerializer(type);
return ser.fromXML(content);
}
public Collection getMessageContentNames()
{
return Collections.unmodifiableSet(_messageContent.keySet());
}
public EndpointReference getProducerReference()
{
return _producer;
}
public EndpointReference getSubscriptionReference()
{
return _subscription;
}
public QName getTopic()
{
return _topicPath;
}
/**
*
* @return The concrete expression dialect
*
* @see WstConstants#CONCRETE_TOPIC_URI
*
*/
public String getTopicDialect()
{
return WstConstants.CONCRETE_TOPIC_URI;
}
public void setProducerReference(EndpointReference producer)
{
if (producer == null)
_producer = null;
else
_producer = new EndpointReference(producer, WsnConstants.PRODUCER_QNAME);
}
public void setSubscriptionReference(EndpointReference subscription)
{
_subscription = subscription;
}
public void setTopic(QName topicPath)
{
_topicPath = topicPath;
}
public void setTopicDialect(String dialect)
throws TopicExpressionDialectUnknownFault
{
if (dialect == null || !dialect.equals(WstConstants.CONCRETE_TOPIC_URI))
{
Object[] filler = { dialect, XPathUtils.NAMESPACE_URI };
throw new TopicExpressionDialectUnknownFault(_MESSAGES.get("InvalidDialect", filler));
}
}
public String toString()
{
return XmlUtils.toString(toXML(), false);
}
public Element toXML()
{
return toXML(XmlUtils.EMPTY_DOC);
}
public Element toXML(Document doc)
{
if (doc == null)
throw new NullPointerException(_MESSAGES.get("NullDocument"));
Element root = XmlUtils.createElement(doc, WsnConstants.NOTIFICATION_MSG_QNAME);
EndpointReference sub = getSubscriptionReference();
if (sub != null)
{
Element eprXML = sub.toXML(doc);
XmlUtils.setElement(root, WsnConstants.SUBSCRIPTION_EPR_QNAME, eprXML);
}
QName topicPath = getTopic();
if (topicPath != null)
{
Element topic = XmlUtils.createElement(doc, WsnConstants.TOPIC_QNAME, topicPath);
topic.setAttribute(WsnConstants.DIALECT, getTopicDialect());
root.appendChild(topic);
}
EndpointReference producer = getProducerReference();
if (producer != null)
{
Element eprXML = producer.toXML(doc);
XmlUtils.setElement(root, WsnConstants.PRODUCER_QNAME, eprXML);
}
Element message = XmlUtils.createElement(doc, WsnConstants.MESSAGE_QNAME);
root.appendChild(message);
Iterator i = getMessageContentNames().iterator();
while (i.hasNext())
{
QName name = (QName)i.next();
Element next = getMessageContent(name);
next = (Element)doc.importNode(next, true);
message.appendChild(next);
}
//
// add the message's various namespaces to the root element
// so we can easily query them with XPath 1.0
//
Map namespacesByPrefix = XmlUtils.getAllNamespaces(root);
i = namespacesByPrefix.keySet().iterator();
while (i.hasNext())
{
String prefix = (String)i.next();
String namespace = (String)namespacesByPrefix.get(prefix);
XmlUtils.setNamespaceAttribute(root, prefix, namespace);
}
return root;
}
}