/*=============================================================================*
* Copyright 2004 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.ws.notification.topics.impl;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ws.notification.topics.Topic;
import org.apache.ws.notification.topics.TopicListener;
import org.apache.ws.notification.topics.TopicSpace;
import org.apache.ws.notification.topics.expression.TopicExpression;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Vector;
/**
* Simple in-memory implementation of the Topic interface
*/
public class TopicImpl
implements Topic,
TopicListener
{
private static final Log LOG = LogFactory.getLog( TopicImpl.class.getName( ) );
/** DOCUMENT_ME */
protected Map m_subTopics;
/** DOCUMENT_ME */
protected TopicExpression m_reference;
/** DOCUMENT_ME */
protected Collection m_listeners;
/** DOCUMENT_ME */
protected String m_name;
/** DOCUMENT_ME */
protected Object m_currentMsg;
/** DOCUMENT_ME */
protected List m_topicPath; // ordered set of QNames
/** DOCUMENT_ME */
protected TopicSpace m_topicSpace;
private Topic m_parent;
/** DOCUMENT_ME */
protected boolean m_isVisible = true;
/**
* Create a topic with the given name
*
* @param name The name of the created topic
*/
public TopicImpl( String name )
{
this( new HashMap( ), null, new Vector( ), name, null, null );
}
/**
* Create a topic with the given parameters
*
* @param subTopics A map of child topics
* @param reference A topic expression (only used if this is a topic alias)
* @param listeners A collection of topic listeners
* @param name The name of this topic
* @param current The current value of this topic
* @param topicPath The concrete topic path of this topic
*/
public TopicImpl( Map subTopics,
TopicExpression reference,
Collection listeners,
String name,
Object current,
List topicPath )
{
this.m_subTopics = subTopics;
this.m_reference = reference;
this.m_listeners = listeners;
this.m_name = name;
this.m_currentMsg = current;
if ( topicPath == null )
{
this.m_topicPath = new java.util.LinkedList( );
m_topicPath.add( name );
}
}
/**
* DOCUMENT_ME
*
* @return DOCUMENT_ME
*/
public Object getCurrentMessage( )
{
return m_currentMsg;
}
/**
* DOCUMENT_ME
*
* @param visible DOCUMENT_ME
*/
public void setIsVisible( boolean visible )
{
m_isVisible = visible;
}
/**
* DOCUMENT_ME
*
* @return DOCUMENT_ME
*/
public String getName( )
{
return m_name;
}
/**
* DOCUMENT_ME
*
* @return DOCUMENT_ME
*/
public Topic getParent( )
{
return m_parent;
}
/**
* DOCUMENT_ME
*
* @return DOCUMENT_ME
*/
public boolean isReference( )
{
return m_reference != null;
}
/**
* DOCUMENT_ME
*
* @param topicName DOCUMENT_ME
*
* @return DOCUMENT_ME
*/
public Topic getTopic( String topicName )
{
return (Topic) m_subTopics.get( topicName );
}
/**
* DOCUMENT_ME
*
* @param topicPath DOCUMENT_ME
*/
public void setTopicPath( List topicPath )
{
m_topicPath = topicPath;
}
/**
* DOCUMENT_ME
*
* @return DOCUMENT_ME
*/
public List getTopicPath( )
{
return m_topicPath;
}
/**
* DOCUMENT_ME
*
* @param topicPath DOCUMENT_ME
*/
public void setTopicReference( TopicExpression topicPath )
{
this.m_reference = topicPath;
}
/**
* Get the topic expression for the topic(s) that this topic references.
*
* @return The topic expression that this topic reference or null if this topic is not a reference.
*/
public TopicExpression getTopicReference( )
{
return m_reference;
}
/**
* DOCUMENT_ME
*
* @param topicSpace DOCUMENT_ME
*/
public void setTopicSpace( TopicSpace topicSpace )
{
m_topicSpace = topicSpace;
}
/**
* DOCUMENT_ME
*
* @return DOCUMENT_ME
*/
public TopicSpace getTopicSpace( )
{
return m_topicSpace;
}
/**
* DOCUMENT_ME
*
* @return DOCUMENT_ME
*/
public boolean isVisible( )
{
return m_isVisible;
}
/**
* DOCUMENT_ME
*
* @param topic DOCUMENT_ME
*
* @return DOCUMENT_ME
*/
public Topic addTopic( Topic topic )
{
if ( m_reference != null )
{
throw new IllegalStateException( "Cannot modify the TopicExpression reference by adding an additional Topic." );
}
m_subTopics.put( topic.getName( ),
topic );
List topicPath = new LinkedList( );
topicPath.addAll( m_topicPath );
topicPath.add( topic.getName( ) );
topic.setTopicPath( topicPath );
topic.addTopicListener( this );
topic.setTopicSpace( m_topicSpace );
( (TopicImpl) topic ).setParent( this );
return topic;
}
/**
* DOCUMENT_ME
*
* @param name DOCUMENT_ME
*
* @return DOCUMENT_ME
*/
public Topic addTopic( String name )
{
return addTopic( new TopicImpl( name ) );
}
/**
* DOCUMENT_ME
*
* @param listener DOCUMENT_ME
*/
public synchronized void addTopicListener( TopicListener listener )
{
m_listeners.add( listener );
}
/**
* DOCUMENT_ME
*
* @param name DOCUMENT_ME
*
* @return DOCUMENT_ME
*/
public boolean containsTopic( String name )
{
return m_subTopics.containsKey( name );
}
/**
* DOCUMENT_ME
*
* @param msg DOCUMENT_ME
*
* @throws Exception DOCUMENT_ME
*/
public void publish( Object msg )
throws Exception
{
m_currentMsg = msg;
if ( LOG.isDebugEnabled( ) )
{
LOG.debug( "Publish called on topic " + m_name + " with message " + msg );
}
this.topicChanged( this );
}
/**
* DOCUMENT_ME
*
* @param name DOCUMENT_ME
*/
public void removeTopic( String name )
{
m_subTopics.remove( name );
}
/**
* DOCUMENT_ME
*
* @param topic DOCUMENT_ME
*/
public void removeTopic( Topic topic )
{
m_subTopics.remove( topic.getName( ) );
topic.removeTopicListener( this );
}
/**
* DOCUMENT_ME
*
* @param listener DOCUMENT_ME
*/
public synchronized void removeTopicListener( TopicListener listener )
{
this.m_listeners.remove( listener );
}
/**
* DOCUMENT_ME
*
* @return DOCUMENT_ME
*/
public String toString( )
{
// TODO: *SJC* make this print the full concrete path of this Topic instead of just its name
return getName( );
}
/**
* DOCUMENT_ME
*
* @param topic DOCUMENT_ME
*/
public synchronized void topicChanged( Topic topic )
{
Iterator listenerIterator = this.m_listeners.iterator( );
TopicListener listener;
while ( listenerIterator.hasNext( ) )
{
listener = (TopicListener) listenerIterator.next( );
listener.topicChanged( topic );
}
}
/**
* DOCUMENT_ME
*
* @return DOCUMENT_ME
*/
public Iterator topicIterator( )
{
return m_subTopics.values( ).iterator( );
}
/**
* DOCUMENT_ME
*
* @return DOCUMENT_ME
*/
public synchronized Iterator topicListenerIterator( )
{
return this.m_listeners.iterator( );
}
/**
* DOCUMENT_ME
*
* @param parent DOCUMENT_ME
*/
void setParent( Topic parent )
{
m_parent = parent;
}
}