You are viewing a plain text version of this content. The canonical link for it is here.
Posted to muse-commits@ws.apache.org by da...@apache.org on 2006/06/16 00:20:09 UTC

svn commit: r414696 [7/7] - in /webservices/muse/trunk/modules: muse-wsdm-muws-adv/ muse-wsdm-muws-adv/src-api/ muse-wsdm-muws-adv/src-api/org/ muse-wsdm-muws-adv/src-api/org/apache/ muse-wsdm-muws-adv/src-api/org/apache/muse/ muse-wsdm-muws-adv/src-ap...

Added: webservices/muse/trunk/modules/muse-wsn/src-impl/org/apache/muse/ws/notification/properties/ChangeNotificationListenerFactory.java
URL: http://svn.apache.org/viewvc/webservices/muse/trunk/modules/muse-wsn/src-impl/org/apache/muse/ws/notification/properties/ChangeNotificationListenerFactory.java?rev=414696&view=auto
==============================================================================
--- webservices/muse/trunk/modules/muse-wsn/src-impl/org/apache/muse/ws/notification/properties/ChangeNotificationListenerFactory.java (added)
+++ webservices/muse/trunk/modules/muse-wsn/src-impl/org/apache/muse/ws/notification/properties/ChangeNotificationListenerFactory.java Thu Jun 15 15:19:57 2006
@@ -0,0 +1,53 @@
+/*=============================================================================*
+ *  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.properties;
+
+import javax.xml.namespace.QName;
+
+import org.apache.muse.ws.resource.WsResource;
+import org.apache.muse.ws.resource.properties.listeners.PropertyChangeListener;
+import org.apache.muse.ws.resource.properties.listeners.ResourcePropertyListeners;
+
+/**
+ *
+ * ChangeNotificationListenerFactory is a device for creating 
+ * {@linkplain PropertyChangeListener PropertyChangeListeners} that publish 
+ * WS-N notifications about property changes. The factory allows users of 
+ * {@linkplain ResourcePropertyListeners ResourcePropertyListeners} containers to 
+ * control how the property change notifications are formatted before sending 
+ * them out to subscribers.
+ *
+ * @author Dan Jemiolo (danj)
+ *
+ */
+
+public interface ChangeNotificationListenerFactory
+{
+    /**
+     * 
+     * @param propertyQName
+     *        The name of the property being monitored.
+     * 
+     * @param resource
+     *        The WS-resource that is publishing the given property.
+     * 
+     * @return A PropertyChangeListener that will send out notifications 
+     *         in response to property changes.
+     *
+     */
+    PropertyChangeListener newInstance(QName propertyQName, WsResource resource);
+}

Added: webservices/muse/trunk/modules/muse-wsn/src-impl/org/apache/muse/ws/notification/properties/Messages.properties
URL: http://svn.apache.org/viewvc/webservices/muse/trunk/modules/muse-wsn/src-impl/org/apache/muse/ws/notification/properties/Messages.properties?rev=414696&view=auto
==============================================================================
    (empty)

Added: webservices/muse/trunk/modules/muse-wsn/src-impl/org/apache/muse/ws/notification/properties/WsrpNotificationListenerFactory.java
URL: http://svn.apache.org/viewvc/webservices/muse/trunk/modules/muse-wsn/src-impl/org/apache/muse/ws/notification/properties/WsrpNotificationListenerFactory.java?rev=414696&view=auto
==============================================================================
--- webservices/muse/trunk/modules/muse-wsn/src-impl/org/apache/muse/ws/notification/properties/WsrpNotificationListenerFactory.java (added)
+++ webservices/muse/trunk/modules/muse-wsn/src-impl/org/apache/muse/ws/notification/properties/WsrpNotificationListenerFactory.java Thu Jun 15 15:19:57 2006
@@ -0,0 +1,50 @@
+/*=============================================================================*
+ *  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.properties;
+
+
+import javax.xml.namespace.QName;
+
+import org.apache.muse.ws.notification.NotificationProducer;
+import org.apache.muse.ws.notification.WsnConstants;
+import org.apache.muse.ws.resource.WsResource;
+import org.apache.muse.ws.resource.properties.listeners.PropertyChangeListener;
+
+/**
+ *
+ * WsrpNotificationListenerFactory creates instances of the 
+ * {@linkplain ChangeNotificationListener ChangeNotificationListener} class. This is 
+ * the default factory for WS-RP users who want to send out valid WS-RP 
+ * change notifications and aren't using any other event format.
+ *
+ * @author Dan Jemiolo (danj)
+ *
+ */
+
+public class WsrpNotificationListenerFactory implements ChangeNotificationListenerFactory
+{
+    /**
+     * 
+     * This implementation returns an instance of ChangeNotificationListener.
+     * 
+     */
+    public PropertyChangeListener newInstance(QName property, WsResource resource)
+    {
+        NotificationProducer wsn = (NotificationProducer)resource.getCapability(WsnConstants.PRODUCER_URI);
+        return new ChangeNotificationListener(property, wsn);
+    }
+}

Added: webservices/muse/trunk/modules/muse-wsn/src-impl/org/apache/muse/ws/notification/remote/NotificationConsumerClient.java
URL: http://svn.apache.org/viewvc/webservices/muse/trunk/modules/muse-wsn/src-impl/org/apache/muse/ws/notification/remote/NotificationConsumerClient.java?rev=414696&view=auto
==============================================================================
--- webservices/muse/trunk/modules/muse-wsn/src-impl/org/apache/muse/ws/notification/remote/NotificationConsumerClient.java (added)
+++ webservices/muse/trunk/modules/muse-wsn/src-impl/org/apache/muse/ws/notification/remote/NotificationConsumerClient.java Thu Jun 15 15:19:57 2006
@@ -0,0 +1,100 @@
+/*=============================================================================*
+ *  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.remote;
+
+import java.net.URI;
+
+import org.apache.muse.core.Environment;
+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.resource.remote.WsResourceClient;
+import org.apache.muse.ws.addressing.soap.SoapClient;
+import org.apache.muse.ws.addressing.soap.SoapFault;
+import org.w3c.dom.Element;
+
+/**
+ *
+ * NotificationConsumerClient is a proxy class for resources that implement 
+ * the WS-N NotificationConsumer port type. It adds the notify() method to 
+ * the base WS-RF interfaces.
+ *
+ * @author Dan Jemiolo (danj)
+ *
+ */
+
+public class NotificationConsumerClient extends WsResourceClient
+{
+    public NotificationConsumerClient(EndpointReference destination)
+    {
+        super(destination);
+    }
+    
+    public NotificationConsumerClient(EndpointReference destination, 
+                                      EndpointReference source)
+    {
+        super(destination, source);
+    }
+    
+    public NotificationConsumerClient(EndpointReference destination, 
+                                      EndpointReference source, 
+                                      Environment environment)
+    {
+        super(destination, source, environment);
+    }
+    
+    public NotificationConsumerClient(EndpointReference destination, 
+                                      EndpointReference source, 
+                                      SoapClient soapClient)
+    {
+        super(destination, source, soapClient);
+    }
+        
+    public EndpointReference getProducerReference()
+    {
+        return getSource();
+    }
+    
+    public EndpointReference getConsumerReference()
+    {
+        return getDestination();
+    }
+    
+    public void notify(NotificationMessage message)
+        throws SoapFault
+    {
+        notify(new NotificationMessage[]{ message });
+    }
+
+    public void notify(NotificationMessage[] messages)
+        throws SoapFault
+    {
+        EndpointReference epr = getProducerReference();
+        
+        for (int n = 0; n < messages.length; ++n)
+            messages[n].setProducerReference(epr);
+        
+        URI action = URI.create(WsnConstants.NOTIFY_URI);
+        Element notify = XmlUtils.createElement(WsnConstants.NOTIFY_QNAME);
+        
+        for (int n = 0; n < messages.length; ++n)
+            notify.appendChild(messages[n].toXML());
+        
+        invoke(action, notify);
+    }
+}

Added: webservices/muse/trunk/modules/muse-wsn/src-impl/org/apache/muse/ws/notification/remote/NotificationProducerClient.java
URL: http://svn.apache.org/viewvc/webservices/muse/trunk/modules/muse-wsn/src-impl/org/apache/muse/ws/notification/remote/NotificationProducerClient.java?rev=414696&view=auto
==============================================================================
--- webservices/muse/trunk/modules/muse-wsn/src-impl/org/apache/muse/ws/notification/remote/NotificationProducerClient.java (added)
+++ webservices/muse/trunk/modules/muse-wsn/src-impl/org/apache/muse/ws/notification/remote/NotificationProducerClient.java Thu Jun 15 15:19:57 2006
@@ -0,0 +1,106 @@
+/*=============================================================================*
+ *  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.remote;
+
+import java.net.URI;
+import java.util.Date;
+
+import javax.xml.namespace.QName;
+
+import org.w3c.dom.Element;
+
+import org.apache.muse.core.Environment;
+import org.apache.muse.util.xml.XmlUtils;
+import org.apache.muse.ws.addressing.EndpointReference;
+import org.apache.muse.ws.notification.Filter;
+import org.apache.muse.ws.notification.NotificationMessage;
+import org.apache.muse.ws.notification.WsnConstants;
+import org.apache.muse.ws.notification.impl.SimpleNotificationMessage;
+import org.apache.muse.ws.notification.impl.Subscribe;
+import org.apache.muse.ws.notification.impl.SubscribeResponse;
+import org.apache.muse.ws.resource.remote.WsResourceClient;
+import org.apache.muse.ws.addressing.soap.SoapClient;
+import org.apache.muse.ws.addressing.soap.SoapFault;
+
+/**
+ *
+ * NotificationConsumerClient is a proxy class for resources that implement 
+ * the WS-N NotificationProducer port type. It adds the subscribe() and 
+ * getCurrentMessage() methods to the base WS-RF interfaces.
+ *
+ * @author Dan Jemiolo (danj)
+ *
+ */
+
+public class NotificationProducerClient extends WsResourceClient
+{
+    public NotificationProducerClient(EndpointReference destination)
+    {
+        super(destination);
+    }
+    
+    public NotificationProducerClient(EndpointReference destination,
+                                      EndpointReference source)
+    {
+        super(destination, source);
+    }
+    
+    public NotificationProducerClient(EndpointReference destination,
+                                      EndpointReference source, 
+                                      Environment environment)
+    { 
+        super(destination, source, environment);
+    }
+      
+    public NotificationProducerClient(EndpointReference destination,
+                                      EndpointReference source, 
+                                      SoapClient soapClient)
+    {
+        super(destination, source, soapClient);
+    }
+    
+    public NotificationMessage getCurrentMessage(QName topicPath)
+        throws SoapFault
+    {
+        URI action = URI.create(WsnConstants.GET_CURRENT_URI);
+        Element getXML = XmlUtils.createElement(WsnConstants.GET_CURRENT_QNAME, topicPath);
+        
+        Element responseXML = invoke(action, getXML);
+        Element messageXML = XmlUtils.getFirstElement(responseXML);
+        
+        if (messageXML == null)
+            return null;
+        
+        return new SimpleNotificationMessage(messageXML);
+    }
+    
+    public SubscriptionClient subscribe(EndpointReference consumer, 
+                                        Filter filter, 
+                                        Date termination)
+        throws SoapFault
+    {
+        Subscribe sub = new Subscribe(consumer, filter, termination);
+        URI action = URI.create(WsnConstants.SUBSCRIBE_URI);
+        
+        Element responseXML = invoke(action, sub.toXML());
+        
+        SubscribeResponse response = new SubscribeResponse(responseXML);
+        EndpointReference epr = response.getSubscriptionReference();
+        
+        return new SubscriptionClient(epr, getSource());
+    }
+}

Added: webservices/muse/trunk/modules/muse-wsn/src-impl/org/apache/muse/ws/notification/remote/SubscriptionClient.java
URL: http://svn.apache.org/viewvc/webservices/muse/trunk/modules/muse-wsn/src-impl/org/apache/muse/ws/notification/remote/SubscriptionClient.java?rev=414696&view=auto
==============================================================================
--- webservices/muse/trunk/modules/muse-wsn/src-impl/org/apache/muse/ws/notification/remote/SubscriptionClient.java (added)
+++ webservices/muse/trunk/modules/muse-wsn/src-impl/org/apache/muse/ws/notification/remote/SubscriptionClient.java Thu Jun 15 15:19:57 2006
@@ -0,0 +1,83 @@
+/*=============================================================================*
+ *  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.remote;
+
+import java.net.URI;
+
+import org.w3c.dom.Element;
+
+import org.apache.muse.core.Environment;
+import org.apache.muse.ws.addressing.EndpointReference;
+import org.apache.muse.ws.notification.WsnConstants;
+import org.apache.muse.ws.resource.remote.WsResourceClient;
+import org.apache.muse.ws.addressing.soap.SoapClient;
+import org.apache.muse.ws.addressing.soap.SoapFault;
+import org.apache.muse.util.xml.XmlUtils;
+
+/**
+ *
+ * SubscriptionClient is a proxy class for resources that implement the 
+ * WS-N SubscriptionManager port type. It adds the pause() and resume() 
+ * methods to the base WS-RF interfaces.
+ *
+ * @author Dan Jemiolo (danj)
+ *
+ */
+
+public class SubscriptionClient extends WsResourceClient
+{
+    public SubscriptionClient(EndpointReference destination)
+    {
+        super(destination);
+    }
+    
+    public SubscriptionClient(EndpointReference destination,
+                              EndpointReference source)
+    {
+        super(destination, source);
+    }
+    
+    public SubscriptionClient(EndpointReference destination,
+                              EndpointReference source, 
+                              Environment environment)
+    {
+        super(destination, source, environment);
+    }
+    
+    public SubscriptionClient(EndpointReference destination,
+                              EndpointReference source, 
+                              SoapClient soapClient)
+    {
+        super(destination, source, soapClient);
+    }
+    
+    public void pauseSubscription()
+        throws SoapFault
+    {
+        Element body = XmlUtils.createElement(WsnConstants.PAUSE_QNAME);
+        URI action = URI.create(WsnConstants.PAUSE_URI);
+        invoke(action, body);
+    }
+    
+    public void resumeSubscription()
+        throws SoapFault
+    {
+        Element body = XmlUtils.createElement(WsnConstants.RESUME_QNAME);
+        URI action = URI.create(WsnConstants.RESUME_URI);
+        invoke(action, body);
+    }
+}

Added: webservices/muse/trunk/modules/muse-wsn/src-impl/org/apache/muse/ws/notification/topics/impl/ConcretePathExpression.java
URL: http://svn.apache.org/viewvc/webservices/muse/trunk/modules/muse-wsn/src-impl/org/apache/muse/ws/notification/topics/impl/ConcretePathExpression.java?rev=414696&view=auto
==============================================================================
--- webservices/muse/trunk/modules/muse-wsn/src-impl/org/apache/muse/ws/notification/topics/impl/ConcretePathExpression.java (added)
+++ webservices/muse/trunk/modules/muse-wsn/src-impl/org/apache/muse/ws/notification/topics/impl/ConcretePathExpression.java Thu Jun 15 15:19:57 2006
@@ -0,0 +1,292 @@
+/*=============================================================================*
+ *  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.topics.impl;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.ListIterator;
+
+import javax.xml.namespace.QName;
+
+import org.apache.muse.util.messages.Messages;
+import org.apache.muse.util.messages.MessagesFactory;
+import org.apache.muse.util.xml.XmlUtils;
+import org.apache.muse.ws.notification.faults.InvalidTopicExpressionFault;
+import org.apache.muse.ws.notification.topics.Topic;
+import org.apache.muse.ws.notification.topics.TopicPathExpression;
+import org.apache.muse.ws.notification.topics.TopicNamespace;
+import org.apache.muse.ws.notification.topics.TopicSet;
+
+/**
+ *
+ * ConcretePathExpression allows users to evaluate simple and concrete 
+ * topic expressions, as defined by WS-Topics 1.2 draft 03. This class 
+ * cannot evaluate paths with wildcards ('full' expressions).
+ *
+ * @author Dan Jemiolo (danj)
+ *
+ */
+
+public class ConcretePathExpression implements TopicPathExpression
+{
+    private static Messages _MESSAGES = MessagesFactory.get(ConcretePathExpression.class);
+    
+    private TopicNamespace _topicSpace = null;
+    
+    private QName _topicPath = null;
+    
+    public ConcretePathExpression(TopicNamespace topicSpace, QName topicPath)
+        throws InvalidTopicExpressionFault
+    {
+        if (topicSpace == null)
+            throw new NullPointerException(_MESSAGES.get("NullTopicSpace"));
+
+        if (topicPath == null)
+            throw new NullPointerException(_MESSAGES.get("NullTopicPath"));
+        
+        _topicSpace = topicSpace;
+        _topicPath = topicPath;
+
+        String topicNS = topicPath.getNamespaceURI();
+        String targetNS = _topicSpace.getTargetNamespace();
+        
+        if (!targetNS.equals(topicNS))
+        {
+            Object[] filler = { topicNS, targetNS };
+            throw new InvalidTopicExpressionFault(_MESSAGES.get("InvalidTopicNS", filler));
+        }
+        
+        validateTopicPath(_topicPath);
+    }
+    
+    public ConcretePathExpression(TopicSet topics, QName topicPath)
+        throws InvalidTopicExpressionFault
+    {
+        if (topics == null)
+            throw new NullPointerException(_MESSAGES.get("NullTopicSpaceForest"));
+        
+        if (topicPath == null)
+            throw new NullPointerException(_MESSAGES.get("NullTopicPath"));
+        
+        _topicPath = topicPath;
+        
+        String uri = _topicPath.getNamespaceURI();
+        _topicSpace = topics.getTopicNamespace(uri);
+        
+        if (_topicSpace == null)
+        {
+            Object[] filler = { uri };
+            throw new InvalidTopicExpressionFault(_MESSAGES.get("InvalidTopicSpaceNS", filler));
+        }
+
+        String topicNS = topicPath.getNamespaceURI();
+        String targetNS = _topicSpace.getTargetNamespace();
+        
+        if (!targetNS.equals(topicNS))
+        {
+            Object[] filler = { topicNS, targetNS };
+            throw new InvalidTopicExpressionFault(_MESSAGES.get("InvalidTopicNS", filler));
+        }
+        
+        validateTopicPath(_topicPath);
+    }
+    
+    public ConcretePathExpression(Topic topic)
+    {
+        if (topic == null)
+            throw new NullPointerException(_MESSAGES.get("NullTopic"));
+        
+        _topicSpace = topic.getTopicNamespace();
+        _topicPath = createTopicPath(_topicSpace, topic);
+    }
+    
+    private QName createTopicPath(TopicNamespace topicSpace, Topic topic)
+    {
+        String namespace = topicSpace.getTargetNamespace();
+        
+        LinkedList nodes = new LinkedList();
+        
+        String name = topic.getName();
+        int totalSize = name.length();
+        nodes.add(name);
+        
+        Topic parent = topic.getParentTopic();
+        
+        while (parent != null)
+        {
+            name = parent.getName();
+            totalSize += name.length();
+            
+            nodes.addFirst(name);
+            parent = parent.getParentTopic();
+        }
+        
+        StringBuffer buffer = new StringBuffer(totalSize);
+        Iterator i = nodes.iterator();
+        
+        while (i.hasNext())
+        {
+            buffer.append(i.next());
+            
+            if (i.hasNext())
+                buffer.append('/');
+        }
+        
+        return new QName(namespace, buffer.toString(), "topic");
+    }
+    
+    public static void validateTopicPath(QName topicPath) 
+        throws InvalidTopicExpressionFault
+    {        
+        String unqualifiedPath = topicPath.getLocalPart();
+        
+        if (unqualifiedPath.indexOf('*') >= 0 || 
+            unqualifiedPath.indexOf("//") >= 0)
+        {
+            Object[] filler = { XmlUtils.toString(topicPath) };
+            throw new InvalidTopicExpressionFault(_MESSAGES.get("InvalidConcretePath", filler));
+        }
+    }
+    
+    public QName getTopicPath()
+    {
+        return _topicPath;
+    }
+        
+    public TopicNamespace getTopicSpace()
+    {
+        return _topicSpace;
+    }
+    
+    public ListIterator iterator()
+    {
+        String[] nodes = _topicPath.getLocalPart().split("/");
+        return new ConcretePathIterator(_topicSpace, nodes);
+    }
+    
+    public Topic resolve()
+    {
+        //
+        // all we have to do is use a ConcretePathIterator to move 
+        // through the path; if we can get through each node with 
+        // the iterator without hitting a dead end (no topic), then 
+        // we have found a match
+        //
+        
+        ListIterator i = iterator();
+        Topic topic = null;
+        
+        while (i.hasNext())
+        {
+            topic = (Topic)i.next();
+            
+            if (topic == null)
+                return null;
+        }
+        
+        return topic;
+    }
+
+    /**
+     *
+     * ConcretePathIterator is an internal class that allows us to 
+     * move back and forth between nodes in a topic path. Each 
+     * node is one of the strings between the '/' characters in 
+     * the path.
+     *
+     * @author Dan Jemiolo (danj)
+     *
+     */
+    class ConcretePathIterator implements ListIterator
+    {
+        private TopicNamespace _root = null;
+        private Topic _currentTopic = null;
+        
+        private String[] _nodes = null;
+        private int _currentNode = 0;
+        
+        public ConcretePathIterator(TopicNamespace root, String[] nodes)
+        {
+            _root = root;
+            _nodes = nodes;
+        }
+        
+        public void add(Object item)
+        {
+            throw new UnsupportedOperationException();
+        }
+
+        public boolean hasNext()
+        {
+            return _currentNode < _nodes.length;
+        }
+        
+        public boolean hasPrevious()
+        {
+            return _currentNode > 0;
+        }
+
+        public Object next()
+        {
+            if (!hasNext())
+                throw new IllegalStateException();
+            
+            String name = _nodes[_currentNode++];
+            
+            //
+            // special case - if we're at the beginning, we have 
+            // to get the first topic from the SimpleTopicNamespace
+            //
+            if (_currentTopic == null)
+                _currentTopic = _root.getTopic(name);
+            
+            else
+                _currentTopic = _currentTopic.getTopic(name);
+            
+            return _currentTopic;
+        }
+        
+        public int nextIndex()
+        {
+            return _currentNode;
+        }
+        
+        public Object previous()
+        {
+            if (!hasPrevious())
+                throw new IllegalStateException();
+            
+            --_currentNode;
+            return _currentTopic.getParentTopic();
+        }
+        
+        public int previousIndex()
+        {
+            return _currentNode - 1;
+        }
+
+        public void remove()
+        {
+            throw new UnsupportedOperationException();
+        }
+
+        public void set(Object item)
+        {
+            throw new UnsupportedOperationException();
+        }
+    }
+}

Added: webservices/muse/trunk/modules/muse-wsn/src-impl/org/apache/muse/ws/notification/topics/impl/Messages.properties
URL: http://svn.apache.org/viewvc/webservices/muse/trunk/modules/muse-wsn/src-impl/org/apache/muse/ws/notification/topics/impl/Messages.properties?rev=414696&view=auto
==============================================================================
--- webservices/muse/trunk/modules/muse-wsn/src-impl/org/apache/muse/ws/notification/topics/impl/Messages.properties (added)
+++ webservices/muse/trunk/modules/muse-wsn/src-impl/org/apache/muse/ws/notification/topics/impl/Messages.properties Thu Jun 15 15:19:57 2006
@@ -0,0 +1,21 @@
+NoTopicName = There topic XML has no name attribute. Every topic must have a name.
+InvalidTopicNS = The topic's namespace - XXX - does not match that of its topic space - XXX. A topic must have the same namespace as its parent topic space.
+InvalidConcretePath = The value 'XXX' is not a concrete topic path as defined by WS-Topics. Only simple and concrete topic paths are supported.
+InvalidTopicSpaceNS = There is no topic space that has the namespace 'XXX'. 
+NoTopicSpaceNS = The topic space XML has no targetNamespace attribute. Every topic space must have a unique target namespace.
+NoNewTopics = The topic 'XXX' is final - it cannot have any more sub-topics.
+SubTopicExists = There is already a sub-topic named 'XXX' in the topic 'XXX'.
+TopicExists = There is already a topic named 'XXX' in the topic space for 'XXX'.
+TopicSpaceNSExists = There is already a topic space with the namespace 'XXX'. Each topic space in a resource must have a unique namespace.
+NullTopicSpace = The TopicSpace is null.
+NullTopicPath = The QName with the topic path is null.
+NullTopicSpaceForest = The TopicSpaceForest is null.
+NullTopic = The Topic is null.
+NullTopicElement = The DOM Element representing the Topic is null.
+NullTopicName = The topic name is null.
+NullTargetNS = The target namespace is null.
+NullMessageType = The QName with the messageType value is null.
+NullSubscription = The Subscription is null.
+MustBeRootTopic = A Topic must be a root topic (have no parent topic) to set the topic space. Setting the topic space will affect all child topics, and child topics cannot have different topic spaces than their parents.
+NullDocument = The DOM Document is null.
+NullTopicSpaceElement = The DOM Element representing the TopicSpace is null.

Added: webservices/muse/trunk/modules/muse-wsn/src-impl/org/apache/muse/ws/notification/topics/impl/SimpleTopic.java
URL: http://svn.apache.org/viewvc/webservices/muse/trunk/modules/muse-wsn/src-impl/org/apache/muse/ws/notification/topics/impl/SimpleTopic.java?rev=414696&view=auto
==============================================================================
--- webservices/muse/trunk/modules/muse-wsn/src-impl/org/apache/muse/ws/notification/topics/impl/SimpleTopic.java (added)
+++ webservices/muse/trunk/modules/muse-wsn/src-impl/org/apache/muse/ws/notification/topics/impl/SimpleTopic.java Thu Jun 15 15:19:57 2006
@@ -0,0 +1,430 @@
+/*=============================================================================*
+ *  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.topics.impl;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+
+import javax.xml.namespace.QName;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+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.XmlUtils;
+import org.apache.muse.util.xml.XsdUtils;
+import org.apache.muse.ws.resource.basefaults.BaseFault;
+import org.apache.muse.ws.notification.NotificationMessage;
+import org.apache.muse.ws.notification.faults.InvalidTopicExpressionFault;
+import org.apache.muse.ws.notification.topics.Topic;
+import org.apache.muse.ws.notification.topics.TopicPathExpression;
+import org.apache.muse.ws.notification.topics.TopicNamespace;
+import org.apache.muse.ws.notification.topics.WstConstants;
+
+/**
+ *
+ * SimpleTopic is a representation of the WS-Topics SimpleTopic type. It is responsible 
+ * for managing all sub-topics (its topic tree) as well as the subscriptions 
+ * that have been made against the topic. Whenever a resource publishes a 
+ * message to a SimpleTopic, it must record the message and then send it out to 
+ * all of the subscribers. This class is used by all resources that implement 
+ * {@linkplain org.apache.muse.ws.notification.NotificationProducer NotificationProducer} 
+ * to actually send messages to subscribers.
+ *
+ * @author Dan Jemiolo (danj)
+ *
+ */
+
+public class SimpleTopic implements Topic
+{
+    private static Messages _MESSAGES = MessagesFactory.get(SimpleTopic.class);
+    
+    private Map _childTopics = new LinkedHashMap();
+    
+    private NotificationMessage _currentMessage = null;
+    
+    private boolean _isFinal = false;
+    
+    private String _messagePattern = null;
+
+    private Set _messageTypes = new HashSet();
+
+    private String _name = null;
+    
+    private Topic _parentTopic = null;
+    
+    private TopicNamespace _topicSpace = null;
+    
+    public SimpleTopic(Element root, TopicNamespace topicSpace)
+        throws InvalidTopicExpressionFault, BaseFault
+    {
+        if (root == null)
+            throw new NullPointerException(_MESSAGES.get("NullTopicElement"));
+        
+        if (topicSpace == null)
+            throw new NullPointerException(_MESSAGES.get("NullTopicSpace"));
+
+        _topicSpace = topicSpace;
+        
+        _name = root.getAttribute(XsdUtils.NAME);
+        
+        if (_name == null || _name.length() == 0)
+            throw new InvalidTopicExpressionFault(_MESSAGES.get("NoTopicName"));
+        
+        String finalValue = root.getAttribute(WstConstants.FINAL);
+        
+        if (finalValue != null && finalValue.length() > 0)
+            _isFinal = Boolean.valueOf(finalValue).booleanValue();
+        
+        String messageTypesValue = root.getAttribute(WstConstants.MESSAGE_TYPES);
+        
+        if (messageTypesValue != null && messageTypesValue.length() > 0)
+        {
+            String[] values = messageTypesValue.split(" ");
+            
+            for (int n = 0; n < values.length; ++n)
+            {
+                QName qname = XmlUtils.parseQName(values[n], root);
+                _messageTypes.add(qname);
+            }
+        }
+        
+        _messagePattern = XmlUtils.getElementText(root, WstConstants.PATTERN_QNAME);
+        
+        Element[] children = XmlUtils.getElements(root, WstConstants.TOPIC_QNAME);
+        
+        for (int n = 0; n < children.length; ++n)
+        {
+            SimpleTopic topic = new SimpleTopic(children[n], topicSpace);
+            addTopicEvenIfFinal(topic);
+        }
+    }
+    
+    public SimpleTopic(String name, TopicNamespace topicSpace)
+        throws BaseFault
+    {
+        if (name == null)
+            throw new NullPointerException(_MESSAGES.get("NullTopicName"));
+        
+        if (topicSpace == null)
+            throw new NullPointerException(_MESSAGES.get("NullTopicSpace"));
+        
+        _topicSpace = topicSpace;
+        
+        int slash = name.indexOf('/');
+        int end = slash >= 0 ? slash : name.length();
+        _name = name.substring(0, end);
+                
+        if (end < name.length())
+        {
+            String childName = name.substring(end + 1);
+            addTopic(new SimpleTopic(childName, topicSpace));
+        }
+    }
+    
+    public synchronized final void addMessageType(QName messageType)
+    {
+        if (messageType == null)
+            throw new NullPointerException(_MESSAGES.get("NullMessageType"));
+        
+        _messageTypes.add(messageType);
+    }
+    
+    public synchronized final void addTopic(Topic childTopic) 
+        throws InvalidTopicExpressionFault, BaseFault
+    {
+        if (childTopic == null)
+            throw new NullPointerException(_MESSAGES.get("NullTopic"));
+        
+        if (isFinal())
+        {
+            Object[] filler = { getConcretePath() };
+            throw new InvalidTopicExpressionFault(_MESSAGES.get("NoNewTopics", filler));
+        }
+        
+        addTopicEvenIfFinal(childTopic);
+    }
+    
+    private void addTopicEvenIfFinal(Topic childTopic) 
+        throws InvalidTopicExpressionFault, BaseFault
+    {
+        String name = childTopic.getName();
+        
+        if (_childTopics.containsKey(name))
+        {
+            Object[] filler = { name, getConcretePath() };
+            throw new InvalidTopicExpressionFault(_MESSAGES.get("SubTopicExists", filler));
+        }
+        
+        String topicNS = childTopic.getTopicNamespace().getTargetNamespace();
+        String targetNS = getTopicNamespace().getTargetNamespace();
+        
+        if (!targetNS.equals(topicNS))
+        {
+            Object[] filler = { topicNS, targetNS };
+            throw new InvalidTopicExpressionFault(_MESSAGES.get("InvalidTopicNS", filler));
+        }
+        
+        childTopic.setParentTopic(this);
+        
+        _childTopics.put(name, childTopic);
+    }
+    
+    public synchronized boolean equals(Object obj)
+    {
+        if (obj == null)
+            return false;
+        
+        Topic that = (Topic)obj;
+        
+        if (!getName().equals(that.getName()))
+            return false;
+        
+        String thisNS = getTopicNamespace().getTargetNamespace();
+        String thatNS = that.getTopicNamespace().getTargetNamespace();
+        
+        if (!thisNS.equals(thatNS))
+            return false;
+        
+        if (!getConcretePath().equals(that.getConcretePath()))
+            return false;
+
+        if (isFinal() != that.isFinal())
+            return false;
+        
+        String thisPattern = getMessagePattern();
+        String thatPattern = that.getMessagePattern();
+        
+        if (thisPattern != null)
+            return thisPattern.equals(thatPattern);
+        
+        return thatPattern == null;
+    }
+    
+    /**
+     *
+     * @return A fully-qualified name for the SimpleTopic, which can be used 
+     *         in WS-N requests.
+     *
+     */
+    public synchronized QName getConcretePath()
+    {
+        TopicPathExpression path = new ConcretePathExpression(this);
+        return path.getTopicPath();
+    }
+    
+    /**
+     *
+     * @return The last message published to this SimpleTopic (via publish()).
+     *
+     */
+    public synchronized NotificationMessage getCurrentMessage()
+    {
+        return _currentMessage;
+    }
+    
+    /**
+     *
+     * @return An XPath that further expresses the types of messages 
+     *         this topic publishes.
+     *
+     */
+    public synchronized String getMessagePattern()
+    {
+        return _messagePattern;
+    }
+    
+    /**
+     *
+     * @return The XPath 1.0 namespace.
+     *
+     */
+    public String getMessagePatternDialect()
+    {
+        return XPathUtils.NAMESPACE_URI;
+    }
+    
+    public Set getMessageTypes()
+    {
+        return Collections.unmodifiableSet(_messageTypes);
+    }
+    
+    public final String getName()
+    {
+        return _name;
+    }
+    
+    /**
+     *
+     * @return The SimpleTopic's parent SimpleTopic, or null if it is a root SimpleTopic.
+     *
+     */
+    public synchronized Topic getParentTopic()
+    {
+        return _parentTopic;
+    }
+    
+    public synchronized Topic getTopic(String topicName)
+    {
+        return (Topic)_childTopics.get(topicName);
+    }
+    
+    public synchronized Collection getTopics()
+    {
+        return Collections.unmodifiableCollection(_childTopics.values());
+    }
+    
+    public synchronized TopicNamespace getTopicNamespace()
+    {
+        return _topicSpace;
+    }
+    
+    public synchronized int hashCode()
+    {
+        String pattern = getMessagePattern();
+        String ns = getTopicNamespace().getTargetNamespace();
+        
+        return getName().hashCode() + 
+               ns.hashCode() + 
+               getConcretePath().hashCode() + 
+               ( isFinal() ? 1 : 0 ) + 
+               ( pattern == null ? 0 : pattern.hashCode());
+    }
+    
+    public synchronized boolean hasTopic(String topicName)
+    {
+        return getTopic(topicName) != null;
+    }
+    
+    public synchronized boolean isFinal()
+    {
+        return _isFinal;
+    }
+    
+    public synchronized boolean isRootTopic()
+    {
+        return getParentTopic() == null;
+    }
+    
+    public synchronized final void removeAllTopics()
+    {
+        _childTopics.clear();
+    }
+    
+    public synchronized final void removeMessageType(QName messageType)
+    {
+        if (messageType == null)
+            throw new NullPointerException(_MESSAGES.get("NullMessageType"));
+        
+        _messageTypes.remove(messageType);
+    }
+    
+    public synchronized final void removeTopic(String topicName)
+    {
+        if (topicName == null)
+            throw new NullPointerException(_MESSAGES.get("NullTopicName"));
+        
+        _childTopics.remove(topicName);
+    }
+    
+    public synchronized void setFinal(boolean isFinal)
+    {
+        _isFinal = isFinal;
+    }
+    
+    public synchronized void setMessagePattern(String messagePattern)
+    {
+        _messagePattern = messagePattern;
+    }
+    
+    public synchronized void setParentTopic(Topic parentTopic)
+    {
+        _parentTopic = parentTopic;
+    }
+    
+    public synchronized String toString()
+    {
+        return XmlUtils.toString(toXML(), false);
+    }
+    
+    public synchronized Element toXML()
+    {
+        return toXML(XmlUtils.EMPTY_DOC);
+    }
+    
+    public synchronized Element toXML(Document doc)
+    {
+        if (doc == null)
+            throw new NullPointerException(_MESSAGES.get("NullDocument"));
+        
+        Element root = XmlUtils.createElement(doc, WstConstants.TOPIC_QNAME);
+        
+        root.setAttribute(XsdUtils.NAME, getName());
+        root.setAttribute(XmlUtils.TARGET_NS, getTopicNamespace().getTargetNamespace());
+        root.setAttribute(WstConstants.FINAL, Boolean.toString(isFinal()));
+        
+        String pattern = getMessagePattern();
+        
+        if (pattern != null)
+        {
+            Element patternXML = 
+                XmlUtils.createElement(doc, WstConstants.PATTERN_QNAME, pattern);
+            root.appendChild(patternXML);
+            
+            patternXML.setAttribute(WstConstants.DIALECT, XPathUtils.NAMESPACE_URI);
+        }
+        
+        Set messageTypes = getMessageTypes();
+        
+        if (!messageTypes.isEmpty())
+        {
+            Iterator i = messageTypes.iterator();
+            
+            int size = messageTypes.size();
+            StringBuffer buffer = new StringBuffer(size * 128);
+            
+            for (int n = 1; i.hasNext(); ++n)
+            {
+                QName messageName = (QName)i.next();
+                buffer.append(XmlUtils.toString(messageName));
+                
+                if (n != size)
+                    buffer.append(' ');
+            }
+            
+            root.setAttribute(WstConstants.MESSAGE_TYPES, buffer.toString());
+        }
+        
+        Iterator i = getTopics().iterator();
+        
+        while (i.hasNext())
+        {
+            Topic topic = (Topic)i.next();
+            Element topicXML = topic.toXML(doc);
+            root.appendChild(topicXML);
+        }
+        
+        return root;
+    }
+}

Added: webservices/muse/trunk/modules/muse-wsn/src-impl/org/apache/muse/ws/notification/topics/impl/SimpleTopicNamespace.java
URL: http://svn.apache.org/viewvc/webservices/muse/trunk/modules/muse-wsn/src-impl/org/apache/muse/ws/notification/topics/impl/SimpleTopicNamespace.java?rev=414696&view=auto
==============================================================================
--- webservices/muse/trunk/modules/muse-wsn/src-impl/org/apache/muse/ws/notification/topics/impl/SimpleTopicNamespace.java (added)
+++ webservices/muse/trunk/modules/muse-wsn/src-impl/org/apache/muse/ws/notification/topics/impl/SimpleTopicNamespace.java Thu Jun 15 15:19:57 2006
@@ -0,0 +1,205 @@
+/*=============================================================================*
+ *  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.topics.impl;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import org.apache.muse.util.messages.Messages;
+import org.apache.muse.util.messages.MessagesFactory;
+import org.apache.muse.util.xml.XmlUtils;
+import org.apache.muse.util.xml.XsdUtils;
+import org.apache.muse.ws.notification.faults.InvalidTopicExpressionFault;
+import org.apache.muse.ws.notification.topics.Topic;
+import org.apache.muse.ws.notification.topics.TopicNamespace;
+import org.apache.muse.ws.notification.topics.WstConstants;
+import org.apache.muse.ws.resource.basefaults.BaseFault;
+
+/**
+ *
+ * SimpleTopicNamespace is a representation of the WS-Topics SimpleTopicNamespace type. It 
+ * contains a set of topic trees that all have the same namespace. Users 
+ * can evaluate topic path expressions against TopicSpaces to find out if 
+ * a SimpleTopic is published by a resource.
+ *
+ * @author Dan Jemiolo (danjemiolo)
+ *
+ */
+
+public class SimpleTopicNamespace implements TopicNamespace
+{
+    private static Messages _MESSAGES = MessagesFactory.get(SimpleTopicNamespace.class);
+    
+    private String _name = null;
+
+    private Map _rootTopics = new LinkedHashMap();
+    
+    private String _targetNamespace = null;
+    
+    public SimpleTopicNamespace(Element root)
+        throws BaseFault
+    {
+        if (root == null)
+            throw new NullPointerException(_MESSAGES.get("NullTopicSpaceElement"));
+        
+        _targetNamespace = root.getAttribute(XmlUtils.TARGET_NS);
+        
+        if (_targetNamespace == null)
+            throw new InvalidTopicExpressionFault(_MESSAGES.get("NoTopicSpaceNS"));
+        
+        _name = root.getAttribute(XsdUtils.NAME);
+        
+        Element[] children = XmlUtils.getElements(root, WstConstants.TOPIC_QNAME);
+        
+        for (int n = 0; n < children.length; ++n)
+        {
+            Topic topic = new SimpleTopic(children[n], this);
+            addTopic(topic);
+        }
+    }
+    
+    public SimpleTopicNamespace(String targetNamespace)
+    {
+        if (targetNamespace == null)
+            throw new NullPointerException(_MESSAGES.get("NullTargetNS"));
+        
+        _targetNamespace = targetNamespace;
+    }
+    
+    public synchronized final void addTopic(Topic topic)
+        throws BaseFault
+    {
+        if (topic == null)
+            throw new NullPointerException(_MESSAGES.get("NullTopic"));
+        
+        String name = topic.getName();
+        
+        if (_rootTopics.containsKey(name))
+        {
+            Object[] filler = { name, getTargetNamespace() };
+            throw new InvalidTopicExpressionFault(_MESSAGES.get("TopicExists", filler));
+        }
+        
+        TopicNamespace topicSpace = topic.getTopicNamespace();
+        
+        if (topicSpace != this)
+        {
+            Object[] filler = { topicSpace.getTargetNamespace(), getTargetNamespace() };
+            throw new InvalidTopicExpressionFault(_MESSAGES.get("InvalidTopicNS", filler));
+        }
+        
+        _rootTopics.put(name, topic);
+    }
+    
+    public boolean equals(Object obj)
+    {
+        if (obj == null)
+            return false;
+        
+        TopicNamespace that = (TopicNamespace)obj;
+        return getTargetNamespace().equals(that.getTargetNamespace());
+    }
+    
+    public synchronized final String getName()
+    {
+        return _name;
+    }
+
+    public synchronized final Collection getRootTopics()
+    {
+        return Collections.unmodifiableCollection(_rootTopics.values());
+    }
+    
+    public synchronized final Iterator iterator()
+    {
+        return getRootTopics().iterator();
+    }
+    
+    public synchronized final String getTargetNamespace()
+    {
+        return _targetNamespace;
+    }
+
+    public synchronized final Topic getTopic(String topicName)
+    {
+        return (Topic)_rootTopics.get(topicName);
+    }
+    
+    public int hashCode()
+    {
+        return getTargetNamespace().hashCode();
+    }
+    
+    public synchronized final boolean hasTopic(String topicName)
+    {
+        return getTopic(topicName) != null;
+    }
+    
+    public synchronized final void removeTopic(String topicName)
+    {
+        if (topicName == null)
+            throw new NullPointerException(_MESSAGES.get("NullTopicName"));
+        
+        _rootTopics.remove(topicName);
+    }
+    
+    public synchronized final void setName(String name)
+    {
+        _name = name;
+    }
+    
+    public synchronized String toString()
+    {
+        return XmlUtils.toString(toXML(), false);
+    }
+    
+    public synchronized Element toXML()
+    {
+        return toXML(XmlUtils.EMPTY_DOC);
+    }
+    
+    public synchronized Element toXML(Document doc)
+    {
+        if (doc == null)
+            throw new NullPointerException(_MESSAGES.get("NullDocument"));
+        
+        Element topicSpace = XmlUtils.createElement(doc, WstConstants.TOPIC_NAMESPACE_QNAME);
+        topicSpace.setAttribute(XmlUtils.TARGET_NS, getTargetNamespace());
+        
+        String name = getName();
+        
+        if (name != null)
+            topicSpace.setAttribute(XsdUtils.NAME, name);
+        
+        Iterator i = getRootTopics().iterator();
+        
+        while (i.hasNext())
+        {
+            SimpleTopic topic = (SimpleTopic)i.next();
+            Element topicXML = topic.toXML(doc);
+            topicSpace.appendChild(topicXML);
+        }
+        
+        return topicSpace;
+    }
+}

Added: webservices/muse/trunk/modules/muse-wsn/src-impl/org/apache/muse/ws/notification/topics/impl/SimpleTopicSet.java
URL: http://svn.apache.org/viewvc/webservices/muse/trunk/modules/muse-wsn/src-impl/org/apache/muse/ws/notification/topics/impl/SimpleTopicSet.java?rev=414696&view=auto
==============================================================================
--- webservices/muse/trunk/modules/muse-wsn/src-impl/org/apache/muse/ws/notification/topics/impl/SimpleTopicSet.java (added)
+++ webservices/muse/trunk/modules/muse-wsn/src-impl/org/apache/muse/ws/notification/topics/impl/SimpleTopicSet.java Thu Jun 15 15:19:57 2006
@@ -0,0 +1,103 @@
+/*=============================================================================*
+ *  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.topics.impl;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.muse.util.messages.Messages;
+import org.apache.muse.util.messages.MessagesFactory;
+import org.apache.muse.util.xml.XmlUtils;
+import org.apache.muse.ws.notification.faults.InvalidTopicExpressionFault;
+import org.apache.muse.ws.notification.topics.TopicNamespace;
+import org.apache.muse.ws.notification.topics.TopicSet;
+import org.apache.muse.ws.notification.topics.WstConstants;
+import org.apache.muse.ws.resource.basefaults.BaseFault;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/**
+ *
+ * SimpleTopicSet is a top-level container that keeps all of a 
+ * resource's topic spaces sorted by their namespaces.
+ *
+ * @author Dan Jemiolo (danj)
+ *
+ */
+
+public class SimpleTopicSet implements TopicSet
+{
+    //
+    // Used to lookup all exception messages
+    //
+    private static Messages _MESSAGES = 
+        MessagesFactory.get(SimpleTopicSet.class);
+    
+    private Map _topicSpacesByNS = new HashMap();
+    
+    public synchronized final void addTopicNamespace(TopicNamespace topicSpace)
+        throws BaseFault
+    {
+        if (topicSpace == null)
+            throw new NullPointerException(_MESSAGES.get("NullTopicSpace"));
+
+        String namespace = topicSpace.getTargetNamespace();
+        
+        if (_topicSpacesByNS.keySet().contains(namespace))
+        {
+            Object[] filler = { namespace };
+            throw new InvalidTopicExpressionFault(_MESSAGES.get("TopicSpaceNSExists", filler));
+        }
+        
+        _topicSpacesByNS.put(namespace, topicSpace);
+    }
+    
+    public synchronized final Collection getTopicNamespaceURIs()
+    {
+        return Collections.unmodifiableCollection(_topicSpacesByNS.keySet());
+    }
+    
+    public synchronized final TopicNamespace getTopicNamespace(String namespace)
+    {
+        return (TopicNamespace)_topicSpacesByNS.get(namespace);
+    }
+    
+    public synchronized final void removeTopicNamespace(String namespace)
+    {
+        if (namespace == null)
+            throw new NullPointerException(_MESSAGES.get("NullTargetNS"));
+        
+        _topicSpacesByNS.remove(namespace);
+    }
+
+    public Element toXML()
+    {
+        return toXML(XmlUtils.EMPTY_DOC);
+    }
+
+    public Element toXML(Document factory)
+    {
+        Element root = XmlUtils.createElement(WstConstants.TOPIC_SET_QNAME);
+
+        // FIXME: placeholder - not implemented yet
+        XmlUtils.setElement(root, WstConstants.TOPIC_QNAME, "Placeholder");
+        
+        return root;
+    }
+}



---------------------------------------------------------------------
To unsubscribe, e-mail: muse-commits-unsubscribe@ws.apache.org
For additional commands, e-mail: muse-commits-help@ws.apache.org