/***************************************************************************
* Copyright (C) 2006-2011 by Fabrizio Montesi <famontesi@gmail.com> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Library General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
* *
* For details about the authors of this software, see the AUTHORS file. *
***************************************************************************/
package jolie;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import jolie.lang.Constants;
import jolie.lang.Constants.ExecutionMode;
import jolie.lang.Constants.OperandType;
import jolie.lang.NativeType;
import jolie.lang.parse.CorrelationFunctionInfo;
import jolie.lang.parse.CorrelationFunctionInfo.CorrelationPairInfo;
import jolie.lang.parse.OLParser;
import jolie.lang.parse.OLVisitor;
import jolie.lang.parse.context.ParsingContext;
import jolie.lang.parse.Scanner;
import jolie.lang.parse.ast.AddAssignStatement;
import jolie.lang.parse.ast.expression.AndConditionNode;
import jolie.lang.parse.ast.AssignStatement;
import jolie.lang.parse.ast.CompareConditionNode;
import jolie.lang.parse.ast.CompensateStatement;
import jolie.lang.parse.ast.expression.ConstantIntegerExpression;
import jolie.lang.parse.ast.expression.ConstantDoubleExpression;
import jolie.lang.parse.ast.expression.ConstantStringExpression;
import jolie.lang.parse.ast.CorrelationSetInfo;
import jolie.lang.parse.ast.CorrelationSetInfo.CorrelationVariableInfo;
import jolie.lang.parse.ast.CurrentHandlerStatement;
import jolie.lang.parse.ast.DeepCopyStatement;
import jolie.lang.parse.ast.DefinitionCallStatement;
import jolie.lang.parse.ast.DefinitionNode;
import jolie.lang.parse.ast.DivideAssignStatement;
import jolie.lang.parse.ast.DocumentationComment;
import jolie.lang.parse.ast.EmbeddedServiceNode;
import jolie.lang.parse.ast.ExecutionInfo;
import jolie.lang.parse.ast.ExitStatement;
import jolie.lang.parse.ast.ForEachStatement;
import jolie.lang.parse.ast.ForStatement;
import jolie.lang.parse.ast.expression.FreshValueExpressionNode;
import jolie.lang.parse.ast.IfStatement;
import jolie.lang.parse.ast.InputPortInfo;
import jolie.lang.parse.ast.InstallFixedVariableExpressionNode;
import jolie.lang.parse.ast.InstallFunctionNode;
import jolie.lang.parse.ast.InstallStatement;
import jolie.lang.parse.ast.InterfaceDefinition;
import jolie.lang.parse.ast.InterfaceExtenderDefinition;
import jolie.lang.parse.ast.expression.IsTypeExpressionNode;
import jolie.lang.parse.ast.LinkInStatement;
import jolie.lang.parse.ast.LinkOutStatement;
import jolie.lang.parse.ast.SubtractAssignStatement;
import jolie.lang.parse.ast.MultiplyAssignStatement;
import jolie.lang.parse.ast.NDChoiceStatement;
import jolie.lang.parse.ast.expression.NotExpressionNode;
import jolie.lang.parse.ast.NotificationOperationStatement;
import jolie.lang.parse.ast.NullProcessStatement;
import jolie.lang.parse.ast.OLSyntaxNode;
import jolie.lang.parse.ast.OneWayOperationDeclaration;
import jolie.lang.parse.ast.OneWayOperationStatement;
import jolie.lang.parse.ast.OperationDeclaration;
import jolie.lang.parse.ast.expression.OrConditionNode;
import jolie.lang.parse.ast.OutputPortInfo;
import jolie.lang.parse.ast.ParallelStatement;
import jolie.lang.parse.ast.PointerStatement;
import jolie.lang.parse.ast.PostDecrementStatement;
import jolie.lang.parse.ast.PostIncrementStatement;
import jolie.lang.parse.ast.PreDecrementStatement;
import jolie.lang.parse.ast.PreIncrementStatement;
import jolie.lang.parse.ast.expression.ProductExpressionNode;
import jolie.lang.parse.ast.Program;
import jolie.lang.parse.ast.RequestResponseOperationDeclaration;
import jolie.lang.parse.ast.RequestResponseOperationStatement;
import jolie.lang.parse.ast.RunStatement;
import jolie.lang.parse.ast.Scope;
import jolie.lang.parse.ast.SequenceStatement;
import jolie.lang.parse.ast.SolicitResponseOperationStatement;
import jolie.lang.parse.ast.SpawnStatement;
import jolie.lang.parse.ast.expression.SumExpressionNode;
import jolie.lang.parse.ast.SynchronizedStatement;
import jolie.lang.parse.ast.ThrowStatement;
import jolie.lang.parse.ast.TypeCastExpressionNode;
import jolie.lang.parse.ast.UndefStatement;
import jolie.lang.parse.ast.ValueVectorSizeExpressionNode;
import jolie.lang.parse.ast.expression.VariableExpressionNode;
import jolie.lang.parse.ast.VariablePathNode;
import jolie.lang.parse.ast.WhileStatement;
import jolie.lang.parse.ast.courier.CourierChoiceStatement;
import jolie.lang.parse.ast.courier.CourierDefinitionNode;
import jolie.lang.parse.ast.courier.NotificationForwardStatement;
import jolie.lang.parse.ast.courier.SolicitResponseForwardStatement;
import jolie.lang.parse.ast.expression.ConstantBoolExpression;
import jolie.lang.parse.ast.expression.ConstantLongExpression;
import jolie.lang.parse.ast.expression.ConstantIntegerExpression;
import jolie.lang.parse.ast.expression.ConstantUInteger32Expression;
import jolie.lang.parse.ast.expression.ConstantInteger16Expression;
import jolie.lang.parse.ast.expression.ConstantUInteger16Expression;
import jolie.lang.parse.ast.expression.ConstantUInteger64Expression;
import jolie.lang.parse.ast.expression.ConstantByteExpression;
import jolie.lang.parse.ast.expression.InstanceOfExpressionNode;
import jolie.lang.parse.ast.types.TypeDefinition;
import jolie.lang.parse.ast.types.TypeDefinitionLink;
import jolie.lang.parse.ast.types.TypeInlineDefinition;
import jolie.net.ports.OutputPort;
import jolie.net.ext.CommProtocolFactory;
import jolie.net.ports.Interface;
import jolie.process.AddAssignmentProcess;
import jolie.process.AssignmentProcess;
import jolie.process.CallProcess;
import jolie.process.CompensateProcess;
import jolie.process.CurrentHandlerProcess;
import jolie.process.DeepCopyProcess;
import jolie.process.DefinitionProcess;
import jolie.process.DivideAssignmentProcess;
import jolie.process.ExitProcess;
import jolie.process.ForEachProcess;
import jolie.process.ForProcess;
import jolie.process.IfProcess;
import jolie.process.InputOperationProcess;
import jolie.process.InstallProcess;
import jolie.process.LinkInProcess;
import jolie.process.LinkOutProcess;
import jolie.process.InitDefinitionProcess;
import jolie.process.MakePointerProcess;
import jolie.process.SubtractAssignmentProcess;
import jolie.process.MultiplyAssignmentProcess;
import jolie.process.NDChoiceProcess;
import jolie.process.NotificationProcess;
import jolie.process.NullProcess;
import jolie.process.OneWayProcess;
import jolie.process.ParallelProcess;
import jolie.process.PostDecrementProcess;
import jolie.process.PostIncrementProcess;
import jolie.process.PreDecrementProcess;
import jolie.process.PreIncrementProcess;
import jolie.process.Process;
import jolie.process.RequestResponseProcess;
import jolie.process.RunProcess;
import jolie.process.ScopeProcess;
import jolie.process.SequentialProcess;
import jolie.process.SolicitResponseProcess;
import jolie.process.SpawnProcess;
import jolie.process.SynchronizedProcess;
import jolie.process.ThrowProcess;
import jolie.process.UndefProcess;
import jolie.process.WhileProcess;
import jolie.net.AggregatedOperation;
import jolie.net.ports.InputPort;
import jolie.net.ports.InterfaceExtender;
import jolie.process.courier.ForwardNotificationProcess;
import jolie.process.courier.ForwardSolicitResponseProcess;
import jolie.runtime.expression.AndCondition;
import jolie.runtime.expression.CastIntExpression;
import jolie.runtime.expression.CastDoubleExpression;
import jolie.runtime.expression.CastStringExpression;
import jolie.runtime.expression.CompareCondition;
import jolie.runtime.CompareOperator;
import jolie.runtime.embedding.EmbeddedServiceLoader;
import jolie.runtime.embedding.EmbeddedServiceLoaderCreationException;
import jolie.runtime.expression.Expression;
import jolie.runtime.expression.Expression.Operand;
import jolie.runtime.expression.FreshValueExpression;
import jolie.runtime.GlobalVariablePath;
import jolie.runtime.InstallFixedVariablePath;
import jolie.runtime.InvalidIdException;
import jolie.runtime.expression.IsDefinedExpression;
import jolie.runtime.expression.IsIntExpression;
import jolie.runtime.expression.IsDoubleExpression;
import jolie.runtime.expression.IsStringExpression;
import jolie.runtime.OneWayOperation;
import jolie.runtime.expression.OrCondition;
import jolie.runtime.expression.ProductExpression;
import jolie.runtime.RequestResponseOperation;
import jolie.runtime.expression.SumExpression;
import jolie.runtime.Value;
import jolie.runtime.ValueVectorSizeExpression;
import jolie.runtime.VariablePath;
import jolie.runtime.VariablePathBuilder;
import jolie.runtime.correlation.CorrelationSet;
import jolie.runtime.correlation.CorrelationSet.CorrelationPair;
import jolie.runtime.expression.*;
import jolie.runtime.typing.OneWayTypeDescription;
import jolie.runtime.typing.RequestResponseTypeDescription;
import jolie.runtime.typing.Type;
import jolie.util.ArrayListMultiMap;
import jolie.util.MultiMap;
import jolie.util.Pair;
/**
* Builds an interpretation tree by visiting a Jolie abstract syntax tree.
* @author Fabrizio Montesi
* @see OLVisitor
*/
public class OOITBuilder implements OLVisitor
{
private Program program;
private boolean valid = true;
private final Interpreter interpreter;
private String currentOutputPort = null;
private Interface currentPortInterface = null;
private final Map< String, Boolean > isConstantMap;
private final Map< String, InputPort > inputPorts = new HashMap< String, InputPort >();
private final List< Pair< Type.TypeLink, TypeDefinition > > typeLinks = new LinkedList< Pair< Type.TypeLink, TypeDefinition > >();
private final List< CorrelationSetInfo > correlationSetInfoList = new LinkedList< CorrelationSetInfo >();
private final CorrelationFunctionInfo correlationFunctionInfo;
private ExecutionMode executionMode = Constants.ExecutionMode.SINGLE;
private boolean registerSessionStarters = false;
private InputPort currCourierInputPort = null;
private String currCourierOperationName = null;
private final Map< String, Map< String, AggregationConfiguration > > aggregationConfigurations =
new HashMap< String, Map< String, AggregationConfiguration > >(); // Input port name -> (operation name -> aggregation configuration)
private final Map< String, InterfaceExtender > interfaceExtenders =
new HashMap< String, InterfaceExtender >();
private static class AggregationConfiguration {
private final OutputPort defaultOutputPort;
private final Interface aggregatedInterface;
private final InterfaceExtender interfaceExtender;
public AggregationConfiguration(
OutputPort defaultOutputPort,
Interface aggregatedInterface,
InterfaceExtender interfaceExtender
) {
this.defaultOutputPort = defaultOutputPort;
this.aggregatedInterface = aggregatedInterface;
this.interfaceExtender = interfaceExtender;
}
}
/**
* Constructor.
* @param interpreter the Interpreter requesting the interpretation tree building
* @param program the Program to generate the interpretation tree from
* @see Program
*/
public OOITBuilder(
Interpreter interpreter,
Program program,
Map< String, Boolean > isConstantMap,
CorrelationFunctionInfo correlationFunctionInfo
) {
this.interpreter = interpreter;
this.program = new Program( program.context() );
this.isConstantMap = isConstantMap;
this.correlationFunctionInfo = correlationFunctionInfo;
Map< String, TypeDefinition > builtInTypes = OLParser.createTypeDeclarationMap( program.context() );
this.program.children().addAll( builtInTypes.values() );
this.program.children().addAll( program.children() );
}
private void error( ParsingContext context, String message )
{
valid = false;
String s = context.sourceName() + ":" + context.line() + ": " + message;
interpreter.logSevere( s );
}
private void error( ParsingContext context, Exception e )
{
valid = false;
e.printStackTrace();
error( context, e.getMessage() );
}
/**
* Launches the build process.
*
* The Program passed to the constructor gets visited and the Interpreter
* passed to the constructor is set with the necessary references
* to the interpretation tree.
* @return true if the build process is successful, false otherwise
*/
public boolean build()
{
visit( program );
checkForInit();
resolveTypeLinks();
buildCorrelationSets();
return valid;
}
private void checkForInit()
{
try {
interpreter.getDefinition( "init" );
} catch( InvalidIdException e ) {
interpreter.register( "init",
new InitDefinitionProcess(
new ScopeProcess( "main", new InstallProcess( SessionThread.createDefaultFaultHandlers( interpreter ) ), false )
));
}
}
private void resolveTypeLinks()
{
Type type;
for( Pair< Type.TypeLink, TypeDefinition > pair : typeLinks ) {
type = types.get( pair.key().linkedTypeName() );
pair.key().setLinkedType( type );
if ( type == null ) {
error( pair.value().context(), "type link to " + pair.key().linkedTypeName() + " cannot be resolved" );
}
}
}
private void buildCorrelationSets()
{
Interpreter.SessionStarter starter;
Collection< String > operations;
VariablePath sessionVariablePath;
VariablePath messageVariablePath;
CorrelationSet currCorrelationSet;
Set< Interpreter.SessionStarter > starters = new HashSet< Interpreter.SessionStarter >();
List< VariablePath > correlationVariablePaths;
MultiMap< String, CorrelationPair > correlationMap;
for( CorrelationSetInfo csetInfo : correlationFunctionInfo.correlationSets() ) {
correlationVariablePaths = new ArrayList< VariablePath >();
correlationMap = new ArrayListMultiMap< String, CorrelationPair >();
for( CorrelationVariableInfo csetVariableInfo : csetInfo.variables() ) {
sessionVariablePath = buildCorrelationVariablePath( csetVariableInfo.correlationVariablePath() );
correlationVariablePaths.add( sessionVariablePath );
}
operations = correlationFunctionInfo.correlationSetOperations().get( csetInfo );
for( String operationName : operations ) {
for( CorrelationPairInfo pairInfo : correlationFunctionInfo.getOperationCorrelationPairs( operationName ) ) {
sessionVariablePath = buildCorrelationVariablePath( pairInfo.sessionPath() );
messageVariablePath = buildVariablePath( pairInfo.messagePath() );
correlationMap.put(
operationName,
new CorrelationPair( sessionVariablePath, messageVariablePath )
);
starter = interpreter.getSessionStarter( operationName );
if ( starter != null && starter.correlationInitializer() == null ) {
starters.add( starter );
}
}
}
currCorrelationSet = new CorrelationSet( correlationVariablePaths, correlationMap );
interpreter.addCorrelationSet( currCorrelationSet );
for( Interpreter.SessionStarter initStarter : starters ) {
initStarter.setCorrelationInitializer( currCorrelationSet );
}
starters.clear();
}
}
public void visit( ExecutionInfo n )
{
executionMode = n.mode();
interpreter.setExecutionMode( n.mode() );
}
public void visit( VariablePathNode n )
{}
public void visit( CorrelationSetInfo n )
{
correlationSetInfoList.add( n );
}
public void visit( OutputPortInfo n )
{
Process protocolConfigurationProcess = NullProcess.getInstance();
if ( n.protocolConfiguration() != null ) {
n.protocolConfiguration().accept( this );
protocolConfigurationProcess = currProcess;
}
Boolean isConstant;
if ( (isConstant = isConstantMap.get( n.id() )) == null ) {
isConstant = false;
}
currentOutputPort = n.id();
notificationTypes.put( currentOutputPort, new HashMap< String, OneWayTypeDescription >() );
solicitResponseTypes.put( currentOutputPort, new HashMap< String, RequestResponseTypeDescription >() );
for( OperationDeclaration decl : n.operations() ) {
decl.accept( this );
}
currentOutputPort = null;
interpreter.register( n.id(), new OutputPort(
interpreter,
n.id(),
n.protocolId(),
protocolConfigurationProcess,
n.location(),
getOutputPortInterface( n.id(), n.getInterfaceList() ),
isConstant,
n.messageBus()
)
);
}
private Interface getOutputPortInterface( String outputPortName, List<InterfaceDefinition> interfaceList )
{
Map< String, OneWayTypeDescription > oneWayMap = notificationTypes.get( outputPortName );
if ( oneWayMap == null ) {
oneWayMap = new HashMap< String, OneWayTypeDescription >();
}
Map< String, RequestResponseTypeDescription > rrMap = solicitResponseTypes.get( outputPortName );
if ( rrMap == null ) {
rrMap = new HashMap< String, RequestResponseTypeDescription >();
}
return new Interface( oneWayMap, rrMap, interfaceList );
}
public void visit( EmbeddedServiceNode n )
{
VariablePath path = null;
try {
path = interpreter.getOutputPort( n.portId() ).locationVariablePath();
} catch( InvalidIdException iie ) {}
try {
interpreter.addEmbeddedServiceLoader(
EmbeddedServiceLoader.create(
interpreter,
n.type(),
n.servicePath(),
path
) );
} catch( EmbeddedServiceLoaderCreationException e ) {
error( n.context(), e );
}
}
private AggregationConfiguration getAggregationConfiguration( String inputPortName, String operationName )
{
Map< String, AggregationConfiguration > map = aggregationConfigurations.get( inputPortName );
if ( map == null ) {
return null;
}
return map.get( operationName );
}
private void putAggregationConfiguration( String inputPortName, String operationName, AggregationConfiguration configuration )
{
Map< String, AggregationConfiguration > map = aggregationConfigurations.get( inputPortName );
if ( map == null ) {
map = new HashMap< String, AggregationConfiguration >();
aggregationConfigurations.put( inputPortName, map );
}
map.put( operationName, configuration );
}
public void visit( InputPortInfo n )
{
currentPortInterface = new Interface(
new HashMap< String, OneWayTypeDescription >(),
new HashMap< String, RequestResponseTypeDescription >(),
n.getInterfaceList()
);
for( OperationDeclaration op : n.operations() ) {
op.accept( this );
}
Map< String, OutputPort > redirectionMap =
new HashMap< String, OutputPort > ();
OutputPort oPort = null;
for( Entry< String, String > entry : n.redirectionMap().entrySet() ) {
try {
oPort = interpreter.getOutputPort( entry.getValue() );
} catch( InvalidIdException e ) {
error( n.context(), "Unknown output port (" + entry.getValue() + ") in redirection for input port " + n.id() );
}
redirectionMap.put( entry.getKey(), oPort );
}
OutputPort outputPort;
Map< String, OneWayTypeDescription > outputPortNotificationTypes;
Map< String, RequestResponseTypeDescription > outputPortSolicitResponseTypes;
Map< String, AggregatedOperation > aggregationMap = new HashMap< String, AggregatedOperation >();
InterfaceExtender extender;
for( InputPortInfo.AggregationItemInfo item : n.aggregationList() ) {
String outputPortName = item.outputPortList()[0];
if ( item.interfaceExtender() == null ) {
extender = null;
} else {
extender = interfaceExtenders.get( item.interfaceExtender().name() );
}
try {
outputPort = interpreter.getOutputPort( outputPortName );
outputPortNotificationTypes = notificationTypes.get( outputPortName );
outputPortSolicitResponseTypes = solicitResponseTypes.get( outputPortName );
for( String operationName : outputPortNotificationTypes.keySet() ) {
aggregationMap.put( operationName, AggregatedOperation.createDirect( operationName, Constants.OperationType.ONE_WAY, outputPort ) );
putAggregationConfiguration( n.id(), operationName,
new AggregationConfiguration( outputPort, outputPort.getInterface(), extender ) );
}
for( String operationName : outputPortSolicitResponseTypes.keySet() ) {
aggregationMap.put( operationName, AggregatedOperation.createDirect( operationName, Constants.OperationType.REQUEST_RESPONSE, outputPort ) );
putAggregationConfiguration( n.id(), operationName,
new AggregationConfiguration( outputPort, outputPort.getInterface(), extender ) );
}
} catch( InvalidIdException e ) {
error( n.context(), e );
}
}
String pId = n.protocolId();
CommProtocolFactory protocolFactory = null;
VariablePath protocolConfigurationPath =
new VariablePathBuilder( true )
.add( Constants.INPUT_PORTS_NODE_NAME, 0 )
.add( n.id(), 0 )
.add( Constants.PROTOCOL_NODE_NAME, 0 )
.toVariablePath();
try {
protocolFactory = interpreter.commCore().getCommProtocolFactory( pId );
} catch( IOException e ) {
error( n.context(), e );
}
VariablePath path =
new VariablePathBuilder( true )
.add( Constants.INPUT_PORTS_NODE_NAME, 0 )
.add( n.id(), 0 )
.add( Constants.LOCATION_NODE_NAME, 0 )
.toVariablePath();
Process assignLocation = new AssignmentProcess( path, Value.create( n.location().toString() ) );
path =
new VariablePathBuilder( true )
.add( Constants.INPUT_PORTS_NODE_NAME, 0 )
.add( n.id(), 0 )
.add( Constants.PROTOCOL_NODE_NAME, 0 )
.toVariablePath();
Process assignProtocol = new AssignmentProcess( path, Value.create( n.protocolId() ) );
Process[] confChildren = new Process[] { assignLocation, assignProtocol, buildProcess( n.protocolConfiguration() ) };
SequentialProcess protocolConfigurationSequence = new SequentialProcess( confChildren );
InputPort inputPort = new InputPort(
n.id(),
n.location(),
protocolConfigurationPath,
currentPortInterface,
aggregationMap,
redirectionMap,
n.messageBus()
);
if ( n.location().toString().equals( Constants.LOCAL_LOCATION_KEYWORD ) ) {
try {
interpreter.commCore().addLocalInputPort( inputPort );
inputPorts.put( inputPort.name(), inputPort );
} catch( IOException e ) {
error( n.context(), e );
}
} else if ( protocolFactory != null ) {
try {
interpreter.commCore().addInputPort(
inputPort,
protocolFactory,
protocolConfigurationSequence
);
inputPorts.put( inputPort.name(), inputPort );
} catch( IOException ioe ) {
error( n.context(), ioe );
}
} else {
error( n.context(), "Communication protocol extension for protocol " + pId + " not found." );
}
currentPortInterface = null;
}
private Process currProcess;
private Expression currExpression;
private Type currType;
boolean insideType = false;
private final Map< String, Type > types = new HashMap< String, Type >();
private final Map< String, Map< String, OneWayTypeDescription > > notificationTypes =
new HashMap< String, Map< String, OneWayTypeDescription > >(); // Maps output ports to their OW operation types
private final Map< String, Map< String, RequestResponseTypeDescription > > solicitResponseTypes =
new HashMap< String, Map< String, RequestResponseTypeDescription > >(); // Maps output ports to their RR operation types
public void visit( TypeInlineDefinition n )
{
boolean backupInsideType = insideType;
insideType = true;
if ( n.untypedSubTypes() ) {
currType = Type.create( n.nativeType(), n.cardinality(), true, null );
} else {
Map< String, Type > subTypes = new HashMap< String, Type >();
if ( n.subTypes() != null ) {
for( Entry< String, TypeDefinition > entry : n.subTypes() ) {
subTypes.put( entry.getKey(), buildType( entry.getValue() ) );
}
}
currType = Type.create( n.nativeType(), n.cardinality(), false, subTypes );
}
insideType = backupInsideType;
if ( insideType == false && insideOperationDeclaration == false ) {
types.put( n.id(), currType );
}
}
public void visit( TypeDefinitionLink n )
{
Type.TypeLink link = Type.createLink( n.linkedTypeName(), n.cardinality() );
currType = link;
typeLinks.add( new Pair< Type.TypeLink, TypeDefinition >( link, n ) );
if ( insideType == false && insideOperationDeclaration == false ) {
types.put( n.id(), currType );
}
}
public void visit( Program p )
{
for( OLSyntaxNode node : p.children() )
node.accept( this );
}
private boolean insideOperationDeclaration = false;
private OneWayTypeDescription buildOneWayTypeDescription( OneWayOperationDeclaration decl )
{
if ( decl == null ) {
return null;
}
if ( currentOutputPort == null ) { // We are in an input port (TODO: why does this matter? junk code?)
return new OneWayTypeDescription( types.get( decl.requestType().id() ) );
} else {
return new OneWayTypeDescription( buildType( decl.requestType() ) );
}
}
private RequestResponseTypeDescription buildRequestResponseTypeDescription( RequestResponseOperationDeclaration decl )
{
if ( decl == null ) {
return null;
}
RequestResponseTypeDescription typeDescription;
Map< String, Type > faults = new HashMap< String, Type >();
if ( currentOutputPort == null ) { // We are in an input port (TODO: why does this matter? junk code?)
for( Entry< String, TypeDefinition > entry : decl.faults().entrySet() ) {
faults.put( entry.getKey(), types.get( entry.getValue().id() ) );
}
typeDescription = new RequestResponseTypeDescription(
types.get( decl.requestType().id() ),
types.get( decl.responseType().id() ),
faults
);
} else {
for( Entry< String, TypeDefinition > entry : decl.faults().entrySet() ) {
faults.put( entry.getKey(), types.get( entry.getValue().id() ) );
}
typeDescription = new RequestResponseTypeDescription(
buildType( decl.requestType() ),
buildType( decl.responseType() ),
faults
);
}
return typeDescription;
}
public void visit( OneWayOperationDeclaration decl )
{
boolean backup = insideOperationDeclaration;
insideOperationDeclaration = true;
OneWayTypeDescription typeDescription = null;
if ( currentOutputPort == null ) { // We are in an input port
// Register if not already present
typeDescription = buildOneWayTypeDescription( decl );
try {
interpreter.getOneWayOperation( decl.id() );
} catch( InvalidIdException e ) {
interpreter.register( decl.id(), new OneWayOperation( decl.id(), types.get( decl.requestType().id() ) ) );
}
} else {
typeDescription = buildOneWayTypeDescription( decl );
notificationTypes.get( currentOutputPort ).put( decl.id(), typeDescription );
}
if ( currentPortInterface != null ) {
currentPortInterface.oneWayOperations().put( decl.id(), typeDescription );
}
insideOperationDeclaration = backup;
}
public void visit( RequestResponseOperationDeclaration decl )
{
RequestResponseTypeDescription typeDescription = null;
if ( currentOutputPort == null ) {
// Register if not already present
try {
RequestResponseOperation op = interpreter.getRequestResponseOperation( decl.id() );
typeDescription = op.typeDescription();
} catch( InvalidIdException e ) {
typeDescription = buildRequestResponseTypeDescription( decl );
interpreter.register(
decl.id(),
new RequestResponseOperation( decl.id(), typeDescription )
);
}
} else {
typeDescription = buildRequestResponseTypeDescription( decl );
solicitResponseTypes.get( currentOutputPort ).put( decl.id(), typeDescription );
}
if ( currentPortInterface != null ) {
currentPortInterface.requestResponseOperations().put( decl.id(), typeDescription );
}
}
public void visit( DefinitionNode n )
{
DefinitionProcess def;
if ( "main".equals( n.id() ) ) {
if ( executionMode == ExecutionMode.SINGLE ) {
// We are a single-session service, so we will not spawn sessions
registerSessionStarters = false;
buildProcess( n.body() );
} else {
registerSessionStarters = true;
buildProcess( n.body() );
registerSessionStarters = false;
}
def = new DefinitionProcess( currProcess );
} else if ( "init".equals( n.id() ) ) {
Process[] initChildren = {
new InstallProcess( SessionThread.createDefaultFaultHandlers( interpreter ) ),
buildProcess( n.body() )
};
def = new InitDefinitionProcess( new ScopeProcess( "main", new SequentialProcess( initChildren ), false ) );
} else {
def = new DefinitionProcess( buildProcess( n.body() ) );
}
interpreter.register( n.id(), def );
}
public void visit( ParallelStatement n )
{
Process[] children = new Process[ n.children().size() ];
int i = 0;
for( OLSyntaxNode node : n.children() ) {
node.accept( this );
children[ i++ ] = currProcess;
}
currProcess = new ParallelProcess( children );
}
public void visit( SynchronizedStatement n )
{
n.body().accept( this );
currProcess = new SynchronizedProcess( n.id(), currProcess );
}
public void visit( SequenceStatement n )
{
boolean origRegisterSessionStarters = registerSessionStarters;
registerSessionStarters = false;
List< Process > children = new LinkedList< Process >();
for( OLSyntaxNode child : n.children() ) {
children.add( buildProcess( child ) );
}
currProcess = new SequentialProcess( children.toArray( new Process[0] ) );
if ( origRegisterSessionStarters && children.get( 0 ) instanceof InputOperationProcess ) {
// We must register this sequence as a starter guarded by the first input process
InputOperationProcess first = (InputOperationProcess) children.remove( 0 );
registerSessionStarter(
first,
new SequentialProcess( children.toArray( new Process[0] ) )
);
}
registerSessionStarters = origRegisterSessionStarters;
}
private void registerSessionStarter( InputOperationProcess guard, Process body )
{
guard.setSessionStarter( true );
interpreter.registerSessionStarter( guard, body );
}
public void visit( NDChoiceStatement n )
{
boolean origRegisterSessionStarters = registerSessionStarters;
registerSessionStarters = false;
List< Pair< InputOperationProcess, Process > > branches =
new LinkedList< Pair< InputOperationProcess, Process > >();
InputOperationProcess guard;
for( Pair< OLSyntaxNode, OLSyntaxNode > pair : n.children() ) {
pair.key().accept( this );
try {
guard = (InputOperationProcess) currProcess;
pair.value().accept( this );
branches.add(
new Pair< InputOperationProcess, Process >( guard, currProcess )
);
if ( origRegisterSessionStarters ) {
registerSessionStarter( guard, currProcess );
}
} catch( Exception e ) {
e.printStackTrace();
}
}
currProcess = new NDChoiceProcess( branches.toArray( new Pair[0] ) );
registerSessionStarters = origRegisterSessionStarters;
}
public void visit( OneWayOperationStatement n )
{
boolean origRegisterSessionStarters = registerSessionStarters;
registerSessionStarters = false;
try {
InputOperationProcess inputProcess;
currProcess = inputProcess =
new OneWayProcess(
interpreter.getOneWayOperation( n.id() ),
buildVariablePath( n.inputVarPath() )
);
if ( origRegisterSessionStarters ) {
registerSessionStarter( inputProcess, NullProcess.getInstance() );
}
} catch( InvalidIdException e ) {
error( n.context(), e );
}
registerSessionStarters = origRegisterSessionStarters;
}
public void visit( RequestResponseOperationStatement n )
{
boolean origRegisterSessionStarters = registerSessionStarters;
registerSessionStarters = false;
Expression outputExpression = null;
if ( n.outputExpression() != null ) {
n.outputExpression().accept( this );
outputExpression = currExpression;
}
try {
InputOperationProcess inputProcess;
currProcess = inputProcess =
new RequestResponseProcess(
interpreter.getRequestResponseOperation( n.id() ),
buildVariablePath( n.inputVarPath() ),
outputExpression,
buildProcess( n.process() )
);
if ( origRegisterSessionStarters ) {
registerSessionStarter( inputProcess, NullProcess.getInstance() );
}
} catch( InvalidIdException e ) {
error( n.context(), e );
}
registerSessionStarters = origRegisterSessionStarters;
}
public void visit( NotificationOperationStatement n )
{
Expression outputExpression = null;
if ( n.outputExpression() != null ) {
n.outputExpression().accept( this );
outputExpression = currExpression;
}
try {
currProcess =
new NotificationProcess(
n.id(),
interpreter.getOutputPort( n.outputPortId() ),
outputExpression,
notificationTypes.get( n.outputPortId() ).get( n.id() )
);
} catch( InvalidIdException e ) {
error( n.context(), e );
}
}
public void visit( SolicitResponseOperationStatement n )
{
Expression outputExpression = null;
if ( n.outputExpression() != null ) {
n.outputExpression().accept( this );
outputExpression = currExpression;
}
try {
Process installProcess = NullProcess.getInstance();
if ( n.handlersFunction() != null )
installProcess = new InstallProcess( getHandlersFunction( n.handlersFunction() ) );
currProcess =
new SolicitResponseProcess(
n.id(),
interpreter.getOutputPort( n.outputPortId() ),
outputExpression,
buildVariablePath( n.inputVarPath() ),
installProcess,
solicitResponseTypes.get( n.outputPortId() ).get( n.id() )
);
} catch( InvalidIdException e ) {
error( n.context(), e );
}
}
public void visit( LinkInStatement n )
{
currProcess = new LinkInProcess( n.id() );
}
public void visit( LinkOutStatement n )
{
currProcess = new LinkOutProcess( n.id() );
}
public void visit( ThrowStatement n )
{
Expression expression = null;
if ( n.expression() != null ) {
n.expression().accept( this );
expression = currExpression;
}
currProcess = new ThrowProcess( n.id(), expression );
}
public void visit( CompensateStatement n )
{
currProcess = new CompensateProcess( n.id() );
}
public void visit( Scope n )
{
n.body().accept( this );
currProcess = new ScopeProcess( n.id(), currProcess );
}
public void visit( InstallStatement n )
{
currProcess = new InstallProcess( getHandlersFunction( n.handlersFunction() ) );
}
private List< Pair< String, Process > > getHandlersFunction( InstallFunctionNode n )
{
List< Pair< String, Process > > pairs = new LinkedList< Pair< String, Process > >();
for( Pair< String, OLSyntaxNode > pair : n.pairs() ) {
pair.value().accept( this );
pairs.add( new Pair< String, Process >( pair.key(), currProcess ) );
}
return pairs;
}
public void visit( AssignStatement n )
{
n.expression().accept( this );
AssignmentProcess p =
new AssignmentProcess(
buildVariablePath( n.variablePath() ),
currExpression
);
currProcess = p;
currExpression = p;
}
public void visit( AddAssignStatement n )
{
n.expression().accept( this );
AddAssignmentProcess p =
new AddAssignmentProcess(
buildVariablePath( n.variablePath() ),
currExpression );
currProcess = p;
currExpression = p;
}
public void visit( SubtractAssignStatement n )
{
n.expression().accept( this );
SubtractAssignmentProcess p =
new SubtractAssignmentProcess(
buildVariablePath( n.variablePath() ),
currExpression );
currProcess = p;
currExpression = p;
}
public void visit( MultiplyAssignStatement n )
{
n.expression().accept( this );
MultiplyAssignmentProcess p =
new MultiplyAssignmentProcess(
buildVariablePath( n.variablePath() ),
currExpression );
currProcess = p;
currExpression = p;
}
public void visit( DivideAssignStatement n )
{
n.expression().accept( this );
DivideAssignmentProcess p =
new DivideAssignmentProcess(
buildVariablePath( n.variablePath() ),
currExpression );
currProcess = p;
currExpression = p;
}
private VariablePath buildCorrelationVariablePath( VariablePathNode path )
{
VariablePathNode csetVarPathNode = new VariablePathNode( path.context(), VariablePathNode.Type.CSET );
csetVarPathNode.append( new Pair<OLSyntaxNode, OLSyntaxNode>(
new ConstantStringExpression( path.context(), Constants.CSETS ),
new ConstantIntegerExpression( path.context(), 0 )
));
csetVarPathNode.path().addAll( path.path() );
return buildVariablePath( csetVarPathNode );
}
private VariablePath buildVariablePath( VariablePathNode path )
{
if ( path == null )
return null;
Expression backupExpr = currExpression;
LinkedList< Pair< Expression, Expression > > list =
new LinkedList< Pair< Expression, Expression > >();
for( Pair< OLSyntaxNode, OLSyntaxNode > pair : path.path() ) {
pair.key().accept( this );
Expression keyExpr = currExpression;
if ( pair.value() != null ) {
pair.value().accept( this );
} else {
currExpression = null;
}
list.add( new Pair< Expression, Expression >( keyExpr, currExpression ) );
}
currExpression = backupExpr;
Pair< Expression, Expression >[] internalPath = new Pair[ list.size() ];
for( int i = 0; i < internalPath.length; i++ ) {
internalPath[i] = list.get( i );
}
if ( path.isGlobal() ) {
return new GlobalVariablePath( internalPath );
} else {
return new VariablePath( internalPath );
}
}
public void visit( PointerStatement n )
{
currProcess =
new MakePointerProcess(
buildVariablePath( n.leftPath() ),
buildVariablePath( n.rightPath() )
);
}
public void visit( DeepCopyStatement n )
{
currProcess =
new DeepCopyProcess(
buildVariablePath( n.leftPath() ),
buildVariablePath( n.rightPath() )
);
}
public void visit( IfStatement n )
{
IfProcess.CPPair[] pairs = new IfProcess.CPPair[ n.children().size() ];
Process elseProcess = null;
Expression condition;
int i = 0;
for( Pair< OLSyntaxNode, OLSyntaxNode > pair : n.children() ) {
pair.key().accept( this );
condition = currExpression;
pair.value().accept( this );
pairs[ i++ ] = new IfProcess.CPPair( condition, currProcess );
}
if ( n.elseProcess() != null ) {
n.elseProcess().accept( this );
elseProcess = currProcess;
}
currProcess = new IfProcess( pairs, elseProcess );
}
public void visit( CurrentHandlerStatement n )
{
currProcess = CurrentHandlerProcess.getInstance();
}
public void visit( DefinitionCallStatement n )
{
currProcess = new CallProcess( n.id() );
}
public void visit( RunStatement n )
{
n.expression().accept( this );
currProcess = new RunProcess( currExpression );
}
public void visit( WhileStatement n )
{
n.condition().accept( this );
Expression condition = currExpression;
n.body().accept( this );
currProcess = new WhileProcess( condition, currProcess );
}
public void visit( OrConditionNode n )
{
Expression[] children = new Expression[ n.children().size() ];
int i = 0;
for( OLSyntaxNode node : n.children() ) {
node.accept( this );
children[ i++ ] = currExpression;
}
currExpression = new OrCondition( children );
}
public void visit( AndConditionNode n )
{
Expression[] children = new Expression[ n.children().size() ];
int i = 0;
for( OLSyntaxNode node : n.children() ) {
node.accept( this );
children[ i++ ] = currExpression;
}
currExpression = new AndCondition( children );
}
public void visit( NotExpressionNode n )
{
n.expression().accept( this );
currExpression = new NotExpression( currExpression );
}
public void visit( CompareConditionNode n )
{
n.leftExpression().accept( this );
Expression left = currExpression;
n.rightExpression().accept( this );
CompareOperator operator = null;
Scanner.TokenType opType = n.opType();
if ( opType == Scanner.TokenType.EQUAL ) {
operator = CompareOperator.EQUAL;
} else if ( opType == Scanner.TokenType.NOT_EQUAL ) {
operator = CompareOperator.NOT_EQUAL;
} else if ( opType == Scanner.TokenType.LANGLE ) {
operator = CompareOperator.MINOR;
} else if ( opType == Scanner.TokenType.RANGLE ) {
operator = CompareOperator.MAJOR;
} else if ( opType == Scanner.TokenType.MINOR_OR_EQUAL ) {
operator = CompareOperator.MINOR_OR_EQUAL;
} else if ( opType == Scanner.TokenType.MAJOR_OR_EQUAL ) {
operator = CompareOperator.MAJOR_OR_EQUAL;
}
assert( operator != null );
currExpression = new CompareCondition( left, currExpression, operator );
}
public void visit( FreshValueExpressionNode n )
{
currExpression = FreshValueExpression.getInstance();
}
public void visit( ConstantByteExpression n )
{
currExpression = Value.create( n.value() );
}
public void visit( ConstantInteger16Expression n )
{
currExpression = Value.create( n.value() );
}
public void visit( ConstantUInteger16Expression n )
{
currExpression = Value.create( n.value() );
}
public void visit( ConstantIntegerExpression n )
{
currExpression = Value.create( n.value() );
}
public void visit( ConstantUInteger32Expression n )
{
currExpression = Value.create( n.value() );
}
public void visit( ConstantLongExpression n )
{
currExpression = Value.create( n.value() );
}
public void visit( ConstantUInteger64Expression n )
{
currExpression = Value.create( n.value() );
}
public void visit( ConstantBoolExpression n )
{
currExpression = Value.create( n.value() );
}
public void visit( ConstantDoubleExpression n )
{
currExpression = Value.create( n.value() );
}
public void visit( ConstantStringExpression n )
{
currExpression = Value.create( n.value() );
}
public void visit( ProductExpressionNode n )
{
Operand[] operands = new Operand[ n.operands().size() ];
int i = 0;
for( Pair< OperandType, OLSyntaxNode > pair : n.operands() ) {
pair.value().accept( this );
operands[i++] = new Operand( pair.key(), currExpression );
}
currExpression = new ProductExpression( operands );
}
public void visit( SumExpressionNode n )
{
Operand[] operands = new Operand[ n.operands().size() ];
int i = 0;
for( Pair< OperandType, OLSyntaxNode > pair : n.operands() ) {
pair.value().accept( this );
operands[i++] = new Operand( pair.key(), currExpression );
}
currExpression = new SumExpression( operands );
}
public void visit( VariableExpressionNode n )
{
currExpression = buildVariablePath( n.variablePath() );
}
public void visit( InstallFixedVariableExpressionNode n )
{
currExpression =
new InstallFixedVariablePath(
buildVariablePath( n.variablePath() )
);
}
public void visit( NullProcessStatement n )
{
currProcess = NullProcess.getInstance();
}
public void visit( ExitStatement n )
{
currProcess = ExitProcess.getInstance();
}
public void visit( ValueVectorSizeExpressionNode n )
{
currExpression = new ValueVectorSizeExpression( buildVariablePath( n.variablePath() ) );
}
public void visit( PreDecrementStatement n )
{
PreDecrementProcess p =
new PreDecrementProcess( buildVariablePath( n.variablePath() ) );
currProcess = p;
currExpression = p;
}
public void visit( PostDecrementStatement n )
{
PostDecrementProcess p =
new PostDecrementProcess( buildVariablePath( n.variablePath() ) );
currProcess = p;
currExpression = p;
}
public void visit( IsTypeExpressionNode n )
{
IsTypeExpressionNode.CheckType type = n.type();
if ( type == IsTypeExpressionNode.CheckType.DEFINED ) {
currExpression =
new IsDefinedExpression( buildVariablePath( n.variablePath() ) );
} else if ( type == IsTypeExpressionNode.CheckType.INT ) {
currExpression =
new IsIntExpression( buildVariablePath( n.variablePath() ) );
} else if ( type == IsTypeExpressionNode.CheckType.BYTE ) {
currExpression =
new IsByteExpression( buildVariablePath( n.variablePath() ) );
} else if ( type == IsTypeExpressionNode.CheckType.INT16 ) {
currExpression =
new IsInt16Expression( buildVariablePath( n.variablePath() ) );
} else if ( type == IsTypeExpressionNode.CheckType.UINT16 ) {
currExpression =
new IsUInt16Expression( buildVariablePath( n.variablePath() ) );
} else if ( type == IsTypeExpressionNode.CheckType.UINT32 ) {
currExpression =
new IsUInt32Expression( buildVariablePath( n.variablePath() ) );
} else if ( type == IsTypeExpressionNode.CheckType.UINT64 ) {
currExpression =
new IsUInt64Expression( buildVariablePath( n.variablePath() ) );
} else if ( type == IsTypeExpressionNode.CheckType.DOUBLE ) {
currExpression =
new IsDoubleExpression( buildVariablePath( n.variablePath() ) );
} else if ( type == IsTypeExpressionNode.CheckType.BOOL ) {
currExpression =
new IsBoolExpression( buildVariablePath( n.variablePath() ) );
} else if ( type == IsTypeExpressionNode.CheckType.LONG ) {
currExpression =
new IsLongExpression( buildVariablePath( n.variablePath() ) );
} else if ( type == IsTypeExpressionNode.CheckType.STRING ) {
currExpression =
new IsStringExpression( buildVariablePath( n.variablePath() ) );
}
}
public void visit( InstanceOfExpressionNode n )
{
currExpression = new InstanceOfExpression( buildExpression( n.expression() ), buildType( n.type() ) );
}
public void visit( TypeCastExpressionNode n )
{
n.expression().accept( this );
if ( n.type() == NativeType.INT ) {
currExpression = new CastIntExpression( currExpression );
} else if ( n.type() == NativeType.DOUBLE ) {
currExpression = new CastDoubleExpression( currExpression );
} else if ( n.type() == NativeType.STRING ) {
currExpression = new CastStringExpression( currExpression );
} else if ( n.type() == NativeType.BOOL ) {
currExpression = new CastBoolExpression( currExpression );
} else if ( n.type() == NativeType.LONG ) {
currExpression = new CastLongExpression( currExpression );
} else if ( n.type() == NativeType.BYTE ) {
currExpression = new CastByteExpression( currExpression);
} else if ( n.type() == NativeType.INT16 ) {
currExpression = new CastInt16Expression( currExpression);
} else if ( n.type() == NativeType.UINT16 ) {
currExpression = new CastUInt16Expression( currExpression);
} else if ( n.type() == NativeType.UINT32 ) {
currExpression = new CastUInt32Expression( currExpression);
} else if ( n.type() == NativeType.UINT64 ) {
currExpression = new CastUInt64Expression( currExpression);
}
}
public void visit( PreIncrementStatement n )
{
PreIncrementProcess p =
new PreIncrementProcess( buildVariablePath( n.variablePath() ) );
currProcess = p;
currExpression = p;
}
public void visit( PostIncrementStatement n )
{
PostIncrementProcess p =
new PostIncrementProcess( buildVariablePath( n.variablePath() ) );
currProcess = p;
currExpression = p;
}
public void visit( ForStatement n )
{
n.init().accept( this );
Process init = currProcess;
n.post().accept( this );
Process post = currProcess;
n.condition().accept( this );
Expression condition = currExpression;
n.body().accept( this );
currProcess = new ForProcess( init, condition, post, currProcess );
}
public void visit( ForEachStatement n )
{
n.body().accept( this );
currProcess =
new ForEachProcess(
buildVariablePath( n.keyPath() ),
buildVariablePath( n.targetPath() ),
currProcess
);
}
private Expression buildExpression( OLSyntaxNode n )
{
if ( n == null ) {
return null;
}
n.accept( this );
return currExpression;
}
private Process buildProcess( OLSyntaxNode n )
{
if ( n == null ) {
return null;
}
n.accept( this );
return currProcess;
}
private Type buildType( OLSyntaxNode n )
{
if ( n == null ) {
return null;
}
n.accept( this );
return currType;
}
public void visit( SpawnStatement n )
{
Process[] children = new Process[2];
children[ 0 ] = new InstallProcess( SessionThread.createDefaultFaultHandlers( interpreter ) );
children[ 1 ] = buildProcess( n.body() );
currProcess = new SpawnProcess(
buildVariablePath( n.indexVariablePath() ),
buildExpression( n.upperBoundExpression() ),
buildVariablePath( n.inVariablePath() ),
new SequentialProcess( children )
);
}
public void visit( UndefStatement n )
{
currProcess = new UndefProcess( buildVariablePath( n.variablePath() ) );
}
public void visit( InterfaceDefinition n ) {}
public void visit( DocumentationComment n ) {}
public void visit( InterfaceExtenderDefinition n )
{
Map< String, OneWayTypeDescription > oneWayDescs = new HashMap< String, OneWayTypeDescription >();
Map< String, RequestResponseTypeDescription > rrDescs = new HashMap< String, RequestResponseTypeDescription >();
for( Entry< String, OperationDeclaration > entry : n.operationsMap().entrySet() ) {
if ( entry.getValue() instanceof OneWayOperationDeclaration ) {
oneWayDescs.put( entry.getKey(), buildOneWayTypeDescription( (OneWayOperationDeclaration)entry.getValue() ) );
} else { // Request-Response
rrDescs.put( entry.getKey(), buildRequestResponseTypeDescription( (RequestResponseOperationDeclaration)entry.getValue() ) );
}
}
InterfaceExtender extender = new InterfaceExtender(
oneWayDescs,
rrDescs,
buildOneWayTypeDescription( n.defaultOneWayOperation() ),
buildRequestResponseTypeDescription( n.defaultRequestResponseOperation() )
);
interfaceExtenders.put( n.name(), extender );
}
public void visit( CourierDefinitionNode n )
{
currCourierInputPort = inputPorts.get( n.inputPortName() );
if ( currCourierInputPort == null ) {
error( n.context(), "cannot find input port: " + n.inputPortName() );
} else {
n.body().accept( this );
if ( currCourierInputPort.location().toString().equals( Constants.LOCAL_LOCATION_KEYWORD ) ) {
interpreter.commCore().localListener().inputPort().aggregationMap().putAll( currCourierInputPort.aggregationMap() );
}
}
currCourierInputPort = null;
}
private OneWayOperation getExtendedOneWayOperation( String inputPortName, String operationName )
{
AggregationConfiguration conf = getAggregationConfiguration( inputPortName, operationName );
OneWayTypeDescription desc = conf.aggregatedInterface.oneWayOperations().get( operationName );
Type extenderType = null;
if ( conf.interfaceExtender != null ) {
OneWayTypeDescription extenderDesc = conf.interfaceExtender.getOneWayTypeDescription( operationName );
if ( extenderDesc != null ) {
extenderType = extenderDesc.requestType();
}
}
return new OneWayOperation(
operationName,
Type.merge( desc.requestType(), extenderType )
);
}
private RequestResponseOperation getExtendedRequestResponseOperation( String inputPortName, String operationName )
{
AggregationConfiguration conf = getAggregationConfiguration( inputPortName, operationName );
RequestResponseTypeDescription desc = conf.aggregatedInterface.requestResponseOperations().get( operationName );
Map< String, Type > extendedFaultMap = new HashMap< String, Type >();
extendedFaultMap.putAll( desc.faults() );
Type requestExtenderType = null;
Type responseExtenderType = null;
if ( conf.interfaceExtender != null ) {
RequestResponseTypeDescription extenderDesc = conf.interfaceExtender.getRequestResponseTypeDescription( operationName );
if ( extenderDesc != null ) {
requestExtenderType = extenderDesc.requestType();
responseExtenderType = extenderDesc.responseType();
extendedFaultMap.putAll( extenderDesc.faults() );
}
}
return new RequestResponseOperation(
operationName,
new RequestResponseTypeDescription(
Type.merge( desc.requestType(), requestExtenderType ),
Type.merge( desc.responseType(), responseExtenderType ),
extendedFaultMap
)
);
}
public void visit( CourierChoiceStatement n )
{
for( CourierChoiceStatement.InterfaceOneWayBranch branch : n.interfaceOneWayBranches() ) {
for( Map.Entry< String, OperationDeclaration > entry : branch.interfaceDefinition.operationsMap().entrySet() ) {
if ( entry.getValue() instanceof OneWayOperationDeclaration ) {
currCourierOperationName = entry.getKey();
currCourierInputPort.aggregationMap().put(
entry.getKey(),
AggregatedOperation.createWithCourier(
getExtendedOneWayOperation( currCourierInputPort.name(), currCourierOperationName ),
buildVariablePath( branch.inputVariablePath ),
buildProcess( branch.body )
)
);
}
}
}
for( CourierChoiceStatement.InterfaceRequestResponseBranch branch : n.interfaceRequestResponseBranches() ) {
for( Map.Entry< String, OperationDeclaration > entry : branch.interfaceDefinition.operationsMap().entrySet() ) {
if ( entry.getValue() instanceof RequestResponseOperationDeclaration ) {
currCourierOperationName = entry.getKey();
currCourierInputPort.aggregationMap().put(
entry.getKey(),
AggregatedOperation.createWithCourier(
getExtendedRequestResponseOperation( currCourierInputPort.name(), currCourierOperationName ),
buildVariablePath( branch.inputVariablePath ), buildVariablePath( branch.outputVariablePath ),
buildProcess( branch.body )
)
);
}
}
}
for( CourierChoiceStatement.OperationOneWayBranch branch : n.operationOneWayBranches() ) {
currCourierOperationName = branch.operation;
currCourierInputPort.aggregationMap().put(
branch.operation,
AggregatedOperation.createWithCourier(
getExtendedOneWayOperation( currCourierInputPort.name(), currCourierOperationName ),
buildVariablePath( branch.inputVariablePath ),
buildProcess( branch.body )
)
);
}
for( CourierChoiceStatement.OperationRequestResponseBranch branch : n.operationRequestResponseBranches() ) {
currCourierOperationName = branch.operation;
currCourierInputPort.aggregationMap().put(
branch.operation,
AggregatedOperation.createWithCourier(
getExtendedRequestResponseOperation( currCourierInputPort.name(), currCourierOperationName ),
buildVariablePath( branch.inputVariablePath ), buildVariablePath( branch.outputVariablePath ),
buildProcess( branch.body )
)
);
}
currCourierOperationName = null;
}
public void visit( NotificationForwardStatement n )
{
AggregationConfiguration conf = getAggregationConfiguration( currCourierInputPort.name(), currCourierOperationName );
try {
OutputPort outputPort;
if ( n.outputPortName() != null ) {
outputPort = interpreter.getOutputPort( n.outputPortName() );
} else {
outputPort = conf.defaultOutputPort;
}
currProcess = new ForwardNotificationProcess(
currCourierOperationName,
outputPort,
buildVariablePath( n.outputVariablePath() ),
conf.aggregatedInterface.oneWayOperations().get( currCourierOperationName ),
(conf.interfaceExtender == null) ? null : conf.interfaceExtender.getOneWayTypeDescription( currCourierOperationName )
);
} catch( InvalidIdException e ) {
error( n.context(), e );
}
}
public void visit( SolicitResponseForwardStatement n )
{
AggregationConfiguration conf = getAggregationConfiguration( currCourierInputPort.name(), currCourierOperationName );
try {
OutputPort outputPort;
if ( n.outputPortName() != null ) {
outputPort = interpreter.getOutputPort( n.outputPortName() );
} else {
outputPort = conf.defaultOutputPort;
}
currProcess = new ForwardSolicitResponseProcess(
currCourierOperationName,
outputPort,
buildVariablePath( n.outputVariablePath() ),
buildVariablePath( n.inputVariablePath() ),
conf.aggregatedInterface.requestResponseOperations().get( currCourierOperationName ),
(conf.interfaceExtender == null) ? null : conf.interfaceExtender.getRequestResponseTypeDescription( currCourierOperationName )
);
} catch( InvalidIdException e ) {
error( n.context(), e );
}
}
}