blob: d01c8ef255b1bd0a8f940f5589e55ce6cf6ca924 [file] [log] [blame]
/* $Id$
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.etch.compiler.ast;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.etch.compiler.Backend;
import org.apache.etch.compiler.EtchGrammarConstants;
import org.apache.etch.compiler.ParseException;
import org.apache.etch.compiler.opt.AsyncReceiver;
import org.apache.etch.compiler.opt.Authorize;
import org.apache.etch.compiler.opt.Direction;
import org.apache.etch.compiler.opt.Oneway;
import org.apache.etch.compiler.opt.Timeout;
/**
* Description of Message.
*/
public class Message extends ParamList<Service>
{
/**
* Constructs the Message.
* @param intf
* @param name
* @param nOpts
* @param type
*/
public Message( Service intf, Name name, Map<String, Opt> nOpts, TypeRef type )
{
super( intf, name, nOpts );
md = getMessageDirection();
this.type = type;
}
private MessageDirection md;
private final TypeRef type;
/**
* @return the suffix of this message's interface given the direction.
*/
public String suffix()
{
return MsgDirHelper.getSuffix( md );
}
/**
* @return the vname of this message (the fully qualified name with "_" instead of ".").
*/
public String mkVname()
{
Service intf = parent();
Name name = name();
return intf.parent().name().name.replace( '.', '_' )+'_'+intf.name()+'_'+name.name;
}
/**
* @return the fully qualified name of this message.
*/
public String mkFqName()
{
Service intf = parent();
Name name = name();
return intf.parent().name().name+'.'+intf.name().name+'.'+name.name;
}
/**
* @return the direction of this message.
*/
public MessageDirection msgDir()
{
return md;
}
/**
* Sets the message direction of this message.
* @param md
*/
public void setMsgDir( MessageDirection md )
{
this.md = md;
}
/**
* @param other
* @return true if this message's direction equals other.
*/
public boolean isMsgDir( MessageDirection other )
{
return md == other;
}
/**
*
* @return trus if this message's direction is both
*/
public boolean isMsgDirBoth()
{
return md == MessageDirection.BOTH;
}
/**
* @return the message direction per the Direction opt.
*/
public MessageDirection getMessageDirection()
{
Opt o = getOpt( "Direction" );
if (o == null)
return MessageDirection.SERVER;
Direction d = (Direction) o;
return d.getMessageDirection();
}
/**
* @return the message timeout per the Timeout opt.
*/
public int getTimeout()
{
Opt o = getOpt( "Timeout" );
if (o == null)
return 0;
Timeout t = (Timeout) o;
return t.timeout();
}
/**
* @return the type of this message.
*/
public TypeRef type()
{
return type;
}
@Override
public String vname( Backend helper )
{
return helper.mtvname( mkVname() );
}
/**
* @return the fully qualified name of this message.
*/
@Override
public String fqname()
{
return mkFqName();
}
// /**
// * @return the id of this message.
// */
// @Override
// public Integer id()
// {
// return mkId();
// }
@Override
public String toString()
{
return String.format( "message %s %s %s (%s) throws %s", md, type, name(), getParameters(), thrown );
}
/**
* @return the message description.
*/
public List<String> returnDescr()
{
return returnDescr;
}
/**
* @param returnDescr
*/
public void setReturnDescr( List<String> returnDescr )
{
this.returnDescr = returnDescr;
}
private List<String> returnDescr = new ArrayList<String>();
/**
* @return the message used to return a result from a call.
*/
public Message getResultMessage()
{
return resultMessage;
}
/**
* @param resultMessage
*/
public void setResultMessage( Message resultMessage )
{
this.resultMessage = resultMessage;
}
private Message resultMessage;
/**
* @return true if this is a message which contributes to the
* types and fields but should not appear in the interface
* (because it is a response message)
*/
public boolean isHidden()
{
return name().name.startsWith( RESULT_MESSAGE_NAME_PREFIX );
}
/**
* @return the expected name of a result message.
*/
public Name getResultMessageName()
{
return new Name( null, RESULT_MESSAGE_NAME_PREFIX+name().name );
}
/**
* The name of the parameter of a result message.
*/
public static final String RESULT_PARAM_NAME = "result";
/**
* The prefix to apply to the name of a result message.
*/
public static final String RESULT_MESSAGE_NAME_PREFIX = "_result_";
/**
* @return the name of the result parameter.
*/
public Name getResultParamName()
{
return new Name( null, RESULT_PARAM_NAME );
}
/**
* @return the result parameter.
*/
public Parameter getResultParam()
{
return getParameter( RESULT_PARAM_NAME );
}
/**
* @return true if this is a call (i.e., returns a value.
*/
public boolean hasReturn()
{
return type.type().kind != EtchGrammarConstants.VOID;
}
@Override
public void dump( String indent )
{
System.out.printf( "%smethod %s %s %s\n", indent, md, type, name().name );
String sIndent = indent+" ";
for (String s: descr())
System.out.printf( "%sdescr %s\n", sIndent, s );
for (Opt o: opts())
o.dump( sIndent );
for (Parameter p: this)
p.dump( sIndent );
if (hasReturn())
System.out.printf( "%sreturnDescr %s\n", sIndent, returnDescr );
for (Thrown n: thrown)
n.dump( sIndent );
}
/**
* Adds a name to the list of exceptions thrown by this message.
* @param n
* @return the representation object for a thrown exception.
* @throws ParseException
*/
public Thrown addThrown( Name n ) throws ParseException
{
if (isOneway())
throw new ParseException( String.format(
"Oneway message cannot throw exception at line %d", n.token.beginLine ) );
thrown.check( n );
Thrown t = new Thrown( this, n );
thrown.add( n, t );
return t;
}
/**
* @param n
* @return any thrown exception by the specified name.
*/
public Thrown getThrown( String n )
{
return thrown.get( n );
}
private final NameList<Thrown> thrown = new NameList<Thrown>();
/**
* @return true if this message has thrown exceptions.
*/
public boolean hasThrown()
{
return !thrown.list().isEmpty();
}
/**
* @return the async receiver mode.
*/
public AsyncReceiverMode getAsyncReceiver()
{
AsyncReceiver ar = (AsyncReceiver) getOpt( "AsyncReceiver" );
if (ar == null)
return AsyncReceiverMode.NONE;
return ar.getMode();
}
/**
* @return true if this method is marked to have an asynchronous
* receiver.
*/
public boolean isAsyncReceiver()
{
return getAsyncReceiver() != AsyncReceiverMode.NONE;
}
/**
* @return true if this method is marked to have a queued asynchronous
* receiver.
*/
public boolean isQueuedAsyncReceiver()
{
return getAsyncReceiver() == AsyncReceiverMode.QUEUED;
}
/**
* @return true if this method is marked to have a free asynchronous
* receiver.
*/
public boolean isFreeAsyncReceiver()
{
return getAsyncReceiver() == AsyncReceiverMode.FREE;
}
/**
* @return true if this is a oneway message which does not wait
* for any response from the other end.
*/
public boolean isOneway()
{
Oneway oneway = (Oneway) getOpt( "Oneway" );
return oneway != null && oneway.isOneway();
}
/**
* @return true if this message requires authorization.
*/
public Authorize getAuth()
{
return (Authorize) getOpt( "Authorize" );
}
/**
* @return true if this message requires authorization.
*/
public boolean hasAuth()
{
Authorize auth = getAuth();
return auth != null && auth.hasAuth();
}
@Override
public void check() throws ParseException
{
checkMessageName( name() );
type.check( parent() );
for (Parameter p: this)
p.check();
for (Thrown n: thrown)
n.check();
Authorize auth = getAuth();
if (auth != null)
auth.check( parent(), this );
}
@Override
public Service service()
{
return parent();
}
/**
* @return the list of thrown exceptions.
*/
public NameList<Thrown> thrown()
{
return thrown;
}
/**
* @return the request message of this result message.
*/
public Message getRequestMessage()
{
return reqMsg;
}
/**
* Sets the request message of this result message.
* @param reqMsg
*/
public void setRequestMessage( Message reqMsg )
{
this.reqMsg = reqMsg;
}
private Message reqMsg;
@Override
public void treewalk( TreeWalker walker ) throws ParseException
{
walker.preMessage( this );
walker.doTypeRef( type );
for (Parameter p: this)
p.treewalk( walker );
for (Thrown n: thrown)
n.treewalk( walker );
walker.postMessage( this );
}
}