/***************************************************************************
* Copyright (C) 2009 by Fabrizio Montesi *
* *
* 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 joliex.plasma;
import java.io.IOException;
import java.io.Writer;
import java.util.Map.Entry;
import java.util.logging.Logger;
import jolie.lang.NativeType;
import jolie.lang.parse.ast.InterfaceDefinition;
import jolie.lang.parse.ast.OneWayOperationDeclaration;
import jolie.lang.parse.ast.OperationDeclaration;
import jolie.lang.parse.ast.Program;
import jolie.lang.parse.ast.RequestResponseOperationDeclaration;
import jolie.lang.parse.ast.types.TypeDefinition;
import jolie.lang.parse.ast.types.TypeDefinitionUndefined;
import joliex.plasma.impl.InterfaceVisitor;
import joliex.plasma.impl.InterfaceVisitor.InterfaceNotFound;
/**
*
* @author Fabrizio Montesi
*/
public class InterfaceConverter
{
private final Program program;
private final String[] interfaceNames;
private final Logger logger;
public InterfaceConverter( Program program, String[] interfaceNames, Logger logger )
{
this.program = program;
this.interfaceNames = interfaceNames;
this.logger = logger;
}
public void convert( Writer writer )
throws InterfaceNotFound, IOException
{
InterfaceDefinition[] interfaceDefinitions =
new InterfaceVisitor( program, interfaceNames ).getInterfaceDefinitions();
writer.write( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" );
writer.write( "<!DOCTYPE kcfg SYSTEM\n\t\"http://www.kde.org/standards/kcfg/1.0/kcfg.xsd\">\n" );
writer.write( "<kcfg>\n" );
for( InterfaceDefinition i : interfaceDefinitions ) {
convertInterfaceDefinition( i, writer );
}
writer.write( "</kcfg>\n" );
writer.flush();
}
private void unsupported( InterfaceDefinition iface, String operationName, String message )
{
logger.severe( iface.name() + "." + operationName + " uses a feature unsupported by plasma service specifications: " + message );
}
private void convertInterfaceDefinition( InterfaceDefinition iface, Writer writer )
throws IOException
{
TypeDefinition type;
for( Entry< String, OperationDeclaration > entry : iface.operationsMap().entrySet() ) {
if ( entry.getValue() instanceof OneWayOperationDeclaration ) { // It's a One-Way
type = ((OneWayOperationDeclaration)entry.getValue()).requestType();
} else { // It's a Request-Response
type = ((RequestResponseOperationDeclaration)entry.getValue()).requestType();
}
writer.write( "\t<group name=\"" + entry.getKey() + "\"" );
if ( type == null || type.equals( TypeDefinitionUndefined.getInstance() ) ) {
writer.write( " />\n" );
unsupported( iface, entry.getKey(), "undefined request type" );
} else {
writeType( iface, entry.getKey(), type, writer );
}
}
}
private void writeEntry( String entryName, String entryType, Writer writer )
throws IOException
{
writer.write( "\t\t<entry name=\"" + entryName + "\" type=\"" + entryType + "\" />\n" );
}
private void writeType( InterfaceDefinition iface, String operationName, TypeDefinition type, Writer writer )
throws IOException
{
boolean empty = true;
if ( type.nativeType() != NativeType.VOID ) {
empty = false;
writer.write( ">\n" );
writeEntry( "/", getPlasmaParameterType( iface, operationName, "/", type ), writer );
}
if ( type.hasSubTypes() ) {
if ( empty ) { writer.write( ">\n" ); }
writeParameters( iface, operationName, type, writer );
writer.write( "\t</group>\n" );
} else {
if ( empty ) {
writer.write( " />\n" );
} else {
writer.write( "\t</group>\n" );
}
}
}
private void writeParameters( InterfaceDefinition iface, String operationName, TypeDefinition type, Writer writer )
throws IOException
{
String plasmaType;
for( Entry< String, TypeDefinition > entry : type.subTypes() ) {
plasmaType = getPlasmaParameterType( iface, operationName, entry.getKey(), entry.getValue() );
writeEntry( entry.getKey(), plasmaType, writer );
}
}
private String getPlasmaParameterType(
InterfaceDefinition iface,
String operationName,
String parameterName,
TypeDefinition type
) {
String ret = "unsupported";
if ( type.hasSubTypes() ) {
// TODO check for sub types that can be represented by a Qt class, like QRect or QPoint
unsupported( iface, operationName, "nested sub-elements under parameter " + parameterName );
}
NativeType nativeType = type.nativeType();
if ( nativeType == NativeType.VOID ) {
unsupported( iface, operationName, "void native type for parameter " + parameterName );
} else if ( nativeType == NativeType.INT ) {
ret = "Int";
} else if ( nativeType == NativeType.DOUBLE ) {
ret = "Double";
} else if ( nativeType == NativeType.STRING ) {
ret = "String";
} else if ( nativeType == NativeType.ANY ) {
unsupported( iface, operationName, "any native type for parameter " + parameterName );
}
return ret;
}
}