/*=============================================================================*
* 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.expression.impl;
import org.apache.ws.notification.topics.Topic;
import org.apache.ws.notification.topics.TopicNamespace;
import org.apache.ws.notification.topics.TopicNamespaceRegistry;
import org.apache.ws.notification.topics.TopicSiblingSet;
import org.apache.ws.notification.topics.expression.ConcreteTopicExpression;
import org.apache.ws.notification.topics.expression.InvalidTopicExpressionException;
import org.apache.ws.notification.topics.expression.TopicExpression;
import org.apache.ws.notification.topics.expression.TopicExpressionException;
import org.apache.ws.notification.topics.expression.TopicExpressionResolutionException;
import org.apache.ws.notification.topics.expression.TopicPathDialectUnknownException;
import org.apache.ws.notification.topics.v2004_06.TopicsConstants;
import javax.xml.namespace.QName;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
/**
* Topic expression evalutor for the WS-Topics "Concrete" topic expression dialect.
*
* @author Ian Springer (ian DOT springer AT hp DOT com)
* @see org.apache.ws.notification.topics.expression.TopicExpressionEvaluator
*/
public class ConcreteTopicExpressionEvaluator
extends AbstractTopicExpressionEvaluator
{
private static final String[] SUPPORTED_DIALECTS =
{
TopicsConstants.TOPIC_EXPR_DIALECT_CONCRETE
};
/**
* DOCUMENT_ME
*
* @return DOCUMENT_ME
*/
public String[] getDialects( )
{
return SUPPORTED_DIALECTS;
}
/**
* DOCUMENT_ME
*
* @param topicNsRegistry
* @param topicExpr a "Concrete" topic expression - MUST be an instance of {@link ConcreteTopicExpression}
*
* @return DOCUMENT_ME
*
* @throws TopicPathDialectUnknownException
* DOCUMENT_ME
* @throws TopicExpressionResolutionException
* DOCUMENT_ME
* @throws InvalidTopicExpressionException
* DOCUMENT_ME
* @throws TopicExpressionException DOCUMENT_ME
*/
public Topic[] evaluate( TopicNamespaceRegistry topicNsRegistry,
TopicExpression topicExpr )
throws TopicPathDialectUnknownException,
TopicExpressionResolutionException,
InvalidTopicExpressionException,
TopicExpressionException
{
Topic[] results;
if ( RESULTS_CACHE.containsKey( topicExpr ) )
{
results = (Topic[]) RESULTS_CACHE.get( topicExpr );
}
else
{
ConcreteTopicExpression concreteTopicExpr = (ConcreteTopicExpression) topicExpr;
results = evaluateTopicPath( topicNsRegistry,
concreteTopicExpr.getTopicPath( ) );
RESULTS_CACHE.put( topicExpr, results );
}
return results;
}
private Topic[] evaluateTopicPath( TopicNamespaceRegistry topicNsRegistry,
QName topicPath )
throws TopicExpressionResolutionException,
InvalidTopicExpressionException
{
validateTopicPath( topicPath );
List matchedTopics = new ArrayList( );
TopicNamespace topicNs = getTopicNamespace( topicNsRegistry, topicPath );
if ( ( topicPath.getLocalPart( ).indexOf( "//" ) != -1 )
|| ( topicPath.getLocalPart( ).indexOf( "*" ) != -1 )
|| ( topicPath.getLocalPart( ).indexOf( "|" ) != -1 )
|| ( topicPath.getLocalPart( ).indexOf( "." ) != -1 ) )
{
throw new InvalidTopicExpressionException( "Topic path '" + topicPath
+ "' contains one or more illegal characters ('//', '*', '|' or '.')." );
}
StringTokenizer pathTokenizer = new StringTokenizer( topicPath.getLocalPart( ),
"/" );
TopicSiblingSet topicSiblingSet = topicNs;
boolean resolvedPath = true;
while ( pathTokenizer.hasMoreTokens( ) )
{
String name = pathTokenizer.nextToken( );
if ( !topicSiblingSet.containsTopic( name ) )
{
resolvedPath = false;
break;
}
topicSiblingSet = topicSiblingSet.getTopic( name );
}
if ( resolvedPath )
{
matchedTopics.add( topicSiblingSet );
}
return (Topic[]) matchedTopics.toArray( new Topic[0] );
}
}