/* | |
* 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.axis2.corba.idl.parser; | |
import antlr.collections.AST; | |
import org.apache.axis2.corba.idl.types.ArrayType; | |
import org.apache.axis2.corba.idl.types.CompositeDataType; | |
import org.apache.axis2.corba.idl.types.DataType; | |
import org.apache.axis2.corba.idl.types.EnumType; | |
import org.apache.axis2.corba.idl.types.ExceptionType; | |
import org.apache.axis2.corba.idl.types.IDL; | |
import org.apache.axis2.corba.idl.types.Interface; | |
import org.apache.axis2.corba.idl.types.Member; | |
import org.apache.axis2.corba.idl.types.Operation; | |
import org.apache.axis2.corba.idl.types.PrimitiveDataType; | |
import org.apache.axis2.corba.idl.types.SequenceType; | |
import org.apache.axis2.corba.idl.types.Struct; | |
import org.apache.axis2.corba.idl.types.Typedef; | |
import org.apache.axis2.corba.idl.types.UnionMember; | |
import org.apache.axis2.corba.idl.types.UnionType; | |
import org.apache.axis2.corba.idl.types.ValueType; | |
import org.apache.axis2.corba.exceptions.InvalidIDLException; | |
import org.apache.commons.logging.Log; | |
import org.apache.commons.logging.LogFactory; | |
import java.util.Map; | |
/** | |
* Created by IntelliJ IDEA. | |
* User: Eranga | |
* Date: Feb 11, 2007 | |
* Time: 10:06:23 PM | |
*/ | |
public class IDLVisitor /*implements ASTVisitor*/ { | |
private static final Log log = LogFactory.getLog(IDLVisitor.class); | |
private IDL idl = new IDL(); | |
private String module = ""; | |
private String moduleForInnerTypes = null; | |
private static final String INNERTYPE_SUFFIX = "Package"; | |
public IDL getIDL() { | |
return idl; | |
} | |
public void setIDL(IDL idl) { | |
this.idl = idl; | |
} | |
public void visit(AST node) throws InvalidIDLException { | |
while (node != null) { | |
switch (node.getType()) { | |
case IDLTokenTypes.LITERAL_interface: { | |
idl.addInterface(visitInterface(node)); | |
break; | |
} | |
case IDLTokenTypes.LITERAL_module: { | |
AST moduleName = node.getFirstChild(); | |
IDLVisitor moduleVisitor = new IDLVisitor(); | |
moduleVisitor.setIDL(idl); | |
moduleVisitor.setModule(module + moduleName); | |
moduleVisitor.visit(moduleName.getNextSibling()); | |
idl.addIDL(moduleVisitor.getIDL()); | |
break; | |
} | |
case IDLTokenTypes.LITERAL_struct: { | |
idl.addType(visitStruct(node)); | |
break; | |
} | |
case IDLTokenTypes.LITERAL_valuetype: { | |
idl.addType(visitValueType(node)); | |
break; | |
} | |
case IDLTokenTypes.LITERAL_exception: { | |
idl.addType(visitException(node)); | |
break; | |
} | |
case IDLTokenTypes.LITERAL_enum: { | |
idl.addType(visitEnum(node)); | |
break; | |
} | |
case IDLTokenTypes.LITERAL_union: { | |
idl.addType(visitUnion(node)); | |
break; | |
} | |
case IDLTokenTypes.LITERAL_typedef: { | |
visitAndAddTypedefs(node, module); | |
break; | |
} | |
default: { | |
throw new InvalidIDLException("Unsupported IDL token " + node); | |
} | |
} | |
node = node.getNextSibling(); | |
} | |
} | |
private Struct visitStruct(AST node) throws InvalidIDLException { | |
AST structNode = node.getFirstChild(); | |
String structName = structNode.toString(); | |
Struct struct = new Struct(); | |
struct.setModule(module); | |
struct.setName(structName); | |
AST memberTypeNode = structNode.getNextSibling(); | |
while (memberTypeNode != null) { | |
Member member = new Member(); | |
DataType dataType = findDataType(memberTypeNode, structName); | |
AST memberNode = memberTypeNode.getNextSibling(); | |
String memberName = memberNode.getText(); | |
int dimensions = memberNode.getNumberOfChildren(); | |
if (dimensions > 0) { | |
AST dimensionNode = memberNode.getFirstChild(); | |
ArrayType arrayType = null; | |
ArrayType rootArrayType = null; | |
int i = 1; | |
while(dimensionNode!=null) { | |
ArrayType temp = new ArrayType(); | |
temp.setElementModule(module); | |
temp.setElementName(memberName); | |
temp.setDepth(i); | |
i++; | |
if (arrayType != null) { | |
arrayType.setDataType(temp); | |
} else { | |
rootArrayType = temp; | |
} | |
arrayType = temp; | |
arrayType.setElementCount(Integer.parseInt(dimensionNode.getText())); | |
dimensionNode = dimensionNode.getNextSibling(); | |
} | |
if (arrayType != null) { | |
arrayType.setDataType(dataType); | |
} | |
// dataType = rootArrayType; | |
Typedef typedef = new Typedef(); | |
typedef.setDataType(rootArrayType); | |
typedef.setModule(module); | |
typedef.setName(structName + '_' + memberName); | |
idl.addType(typedef); | |
dataType = typedef; | |
} | |
member.setDataType(dataType); | |
member.setName(memberName); | |
struct.addMember(member); | |
memberTypeNode = memberNode.getNextSibling(); | |
} | |
return struct; | |
} | |
private ValueType visitValueType(AST node) throws InvalidIDLException { | |
AST valueNode = node.getFirstChild(); | |
ValueType value = new ValueType(); | |
value.setModule(module); | |
String valueName = valueNode.toString(); | |
value.setName(valueName); | |
AST memberModifierNode = valueNode.getNextSibling(); | |
while (memberModifierNode != null) { | |
String memberModifierName = memberModifierNode.toString(); | |
if (!memberModifierName.equals("private") && !memberModifierName.equals("public")) { | |
if (IDLTokenTypes.PREPROC_DIRECTIVE==memberModifierNode.getType()) { | |
if (memberModifierName.startsWith("pragma ID ")) { | |
memberModifierName = memberModifierName.substring(10); | |
String[] pragma = memberModifierName.split(" "); | |
if (pragma.length==2 && pragma[0]!=null && pragma[1]!=null && pragma[0].equals(value.getName())) { | |
pragma[1] = pragma[1].replace('"', ' '); | |
value.setId(pragma[1].trim()); | |
} | |
} | |
} else { | |
// abstract operation | |
value.addOperation(visitOperation(memberModifierNode)); | |
} | |
memberModifierNode = memberModifierNode.getNextSibling(); | |
continue; | |
} | |
Member memberType = new Member(); | |
memberType.setModifier(memberModifierName); | |
AST memberTypeNode = memberModifierNode.getNextSibling(); | |
memberType.setDataType(findDataType(memberTypeNode, valueName)); | |
AST memberNode = memberTypeNode.getNextSibling(); | |
memberType.setName(memberNode.toString()); | |
value.addMember(memberType); | |
memberModifierNode = memberNode.getNextSibling(); | |
} | |
return value; | |
} | |
private Interface visitInterface(AST node) throws InvalidIDLException { | |
Interface intf = new Interface(); | |
intf.setModule(module); | |
AST interfaceNode = node.getFirstChild(); | |
String interfaceName = interfaceNode.toString(); | |
intf.setName(interfaceName); | |
moduleForInnerTypes = module + interfaceName + INNERTYPE_SUFFIX + CompositeDataType.MODULE_SEPERATOR; | |
AST node2 = interfaceNode.getNextSibling(); | |
while (node2 != null) { | |
switch (node2.getType()) { | |
case IDLTokenTypes.LITERAL_struct: | |
Struct innerStruct = visitStruct(node2); | |
innerStruct.setModule(moduleForInnerTypes); | |
idl.addType(innerStruct); | |
break; | |
case IDLTokenTypes.LITERAL_valuetype: | |
log.error("Unsupported IDL token " + node2); | |
// CORBA 3.O spec does not support this | |
break; | |
case IDLTokenTypes.LITERAL_exception: | |
Struct innerEx = visitException(node2); | |
innerEx.setModule(moduleForInnerTypes); | |
idl.addType(innerEx); | |
break; | |
case IDLTokenTypes.LITERAL_enum: | |
EnumType innerEnum = visitEnum(node2); | |
innerEnum.setModule(moduleForInnerTypes); | |
idl.addType(innerEnum); | |
break; | |
case IDLTokenTypes.LITERAL_union: | |
UnionType innerUnion = visitUnion(node2); | |
innerUnion.setModule(moduleForInnerTypes); | |
idl.addType(innerUnion); | |
break; | |
case IDLTokenTypes.LITERAL_typedef: | |
visitAndAddTypedefs(node2, moduleForInnerTypes); | |
break; | |
case IDLTokenTypes.LITERAL_const: | |
log.error("Unsupported IDL token " + node2); | |
break; | |
case IDLTokenTypes.LITERAL_attribute: | |
intf.addOperation(visitGetAttribute(node2)); | |
intf.addOperation(visitSetAttribute(node2)); | |
break; | |
default: | |
if (node2.toString().startsWith("pragma ID ")) { | |
String pragmaId = node2.toString().substring(10); | |
String[] pragma = pragmaId.split(" "); | |
if (pragma.length==2 && pragma[0]!=null && pragma[1]!=null && pragma[0].equals(intf.getName())) { | |
pragma[1] = pragma[1].replace('"', ' '); | |
intf.setId(pragma[1].trim()); | |
} | |
} else { | |
intf.addOperation(visitOperation(node2)); | |
} | |
break; | |
} | |
node2 = node2.getNextSibling(); | |
} | |
moduleForInnerTypes = null; | |
return intf; | |
} | |
private Operation visitGetAttribute(AST node) throws InvalidIDLException { | |
Operation operation = new Operation(); | |
AST type = node.getFirstChild(); | |
AST name = type.getNextSibling(); | |
String attrName = name.toString(); | |
operation.setReturnType(findDataType(type, attrName)); | |
operation.setName("_get_" + attrName); | |
return operation; | |
} | |
private Operation visitSetAttribute(AST node) throws InvalidIDLException { | |
Operation operation = new Operation(); | |
AST type = node.getFirstChild(); | |
operation.setReturnType(PrimitiveDataType.getPrimitiveDataType("void")); | |
AST name = type.getNextSibling(); | |
String attrName = name.toString(); | |
operation.setName("_set_" + attrName); | |
Member param = new Member(); | |
param.setName(attrName); | |
param.setDataType(findDataType(type, attrName)); | |
operation.addParam(param); | |
return operation; | |
} | |
private Operation visitOperation(AST node) throws InvalidIDLException { | |
Operation operation = new Operation(); | |
String opName = node.toString(); | |
operation.setName(opName); | |
AST type = node.getFirstChild(); | |
operation.setReturnType(findDataType(type, opName)); | |
AST mode = type.getNextSibling(); | |
while(mode != null) { | |
if (IDLTokenTypes.LITERAL_raises == mode.getType()) { | |
AST idlType = mode.getFirstChild(); | |
while(idlType != null) { | |
operation.addRaises((ExceptionType) findDataType(idlType, opName)); | |
idlType = idlType.getNextSibling(); | |
} | |
} else { | |
Member param = new Member(); | |
param.setMode(mode.toString()); | |
AST idlType = mode.getFirstChild(); | |
AST paramName = idlType.getNextSibling(); | |
String paramNameStr = paramName.toString(); | |
param.setDataType(findDataType(idlType, paramNameStr)); | |
param.setName(paramNameStr); | |
operation.addParam(param); | |
} | |
mode = mode.getNextSibling(); | |
} | |
return operation; | |
} | |
private ExceptionType visitException(AST node) throws InvalidIDLException { | |
ExceptionType raisesType = new ExceptionType(); | |
AST exNode = node.getFirstChild(); | |
String exName = exNode.toString(); | |
raisesType.setModule(module); | |
raisesType.setName(exName); | |
AST memberTypeNode = exNode.getNextSibling(); | |
while (memberTypeNode != null) { | |
Member member = new Member(); | |
member.setDataType(findDataType(memberTypeNode, exName)); | |
AST memberNode = memberTypeNode.getNextSibling(); | |
member.setName(memberNode.toString()); | |
raisesType.addMember(member); | |
memberTypeNode = memberNode.getNextSibling(); | |
} | |
return raisesType; | |
} | |
private DataType findDataType(AST typeNode, String parentName) throws InvalidIDLException { | |
return findDataType(typeNode, parentName, true, false); | |
} | |
private DataType findDataType(AST typeNode, String parentName, boolean root, boolean noTypeDefForSeqs) throws InvalidIDLException { | |
// Check for sequences | |
if (typeNode.getType()==IDLTokenTypes.LITERAL_sequence) { | |
SequenceType sequenceType = visitAnonymousSequence(typeNode, parentName, root); | |
if (noTypeDefForSeqs) { | |
return sequenceType; | |
} | |
Typedef typedef = new Typedef(); | |
typedef.setDataType(sequenceType); | |
typedef.setModule(module); | |
typedef.setName(parentName + '_' + sequenceType.getName()); | |
idl.addType(typedef); | |
return typedef; | |
} | |
DataType dataType = null; | |
Map compositeDataTypes = idl.getCompositeDataTypes(); | |
String typeName; | |
if (typeNode.getType() == IDLTokenTypes.LITERAL_unsigned) { | |
AST nextNode = typeNode.getNextSibling(); | |
if (nextNode == null) { | |
throw new InvalidIDLException("'unsigned' without a data type"); | |
} else if (nextNode.getType() == IDLTokenTypes.LITERAL_short) { | |
typeNode.setNextSibling(nextNode.getNextSibling()); | |
typeNode.setFirstChild(nextNode.getFirstChild()); | |
typeName = "ushort"; | |
} else if (nextNode.getType() == IDLTokenTypes.LITERAL_long) { | |
AST nextToLong = nextNode.getNextSibling(); | |
if (nextToLong == null) { | |
throw new InvalidIDLException("an identifier is required after the 'long' keyword"); | |
} else if (nextToLong.getType() == IDLTokenTypes.LITERAL_long) { | |
typeNode.setNextSibling(nextToLong.getNextSibling()); | |
typeNode.setFirstChild(nextToLong.getFirstChild()); | |
typeName = "ulonglong"; | |
} else { | |
typeNode.setNextSibling(nextNode.getNextSibling()); | |
typeNode.setFirstChild(nextNode.getFirstChild()); | |
typeName = "ulong"; | |
} | |
} else { | |
throw new InvalidIDLException("either 'long' or 'short' is expected after the 'unsigned' keyword"); | |
} | |
} else if (typeNode.getType() == IDLTokenTypes.LITERAL_long) { | |
AST nextToLong = typeNode.getNextSibling(); | |
if (nextToLong == null) { | |
throw new InvalidIDLException("an identifier is required after the 'long' keyword"); | |
} else if (nextToLong.getType() == IDLTokenTypes.LITERAL_long) { | |
typeNode.setNextSibling(nextToLong.getNextSibling()); | |
typeNode.setFirstChild(nextToLong.getFirstChild()); | |
typeName = "longlong"; | |
} else { | |
typeName = "long"; | |
} | |
} else { | |
typeName = getTypeName(typeNode); | |
} | |
if (compositeDataTypes!=null) { | |
if (!module.equals("")) { | |
if (!typeName.startsWith(module)) { | |
dataType = (DataType) idl.getCompositeDataTypes().get(module + typeName); | |
} | |
} | |
if (dataType==null && moduleForInnerTypes!=null) { | |
if (!typeName.startsWith(module)) { | |
dataType = (DataType) idl.getCompositeDataTypes().get(moduleForInnerTypes + typeName); | |
} | |
} | |
if (dataType==null) | |
dataType = (DataType) idl.getCompositeDataTypes().get(typeName); | |
} | |
if (dataType==null) | |
dataType = PrimitiveDataType.getPrimitiveDataType(typeName); | |
if (dataType == null) | |
throw new InvalidIDLException("Invalid data type: " + typeName); | |
return dataType; | |
} | |
public String getTypeName(AST node) { | |
String typeName = node.getText(); | |
AST memberTypeNodeChild = node.getFirstChild(); | |
while(memberTypeNodeChild!=null) { | |
typeName = typeName + CompositeDataType.MODULE_SEPERATOR + memberTypeNodeChild.toString(); | |
memberTypeNodeChild = memberTypeNodeChild.getNextSibling(); | |
} | |
return typeName; | |
} | |
public void setModule(String module) { | |
if (module==null || module.length()<1) | |
module = ""; | |
else if (!module.endsWith(CompositeDataType.MODULE_SEPERATOR)) | |
module += CompositeDataType.MODULE_SEPERATOR; | |
this.module = module; | |
} | |
private EnumType visitEnum(AST node) { | |
AST enumNode = node.getFirstChild(); | |
String enumName = enumNode.toString(); | |
EnumType enumType = new EnumType(); | |
enumType.setModule(module); | |
enumType.setName(enumName); | |
AST memberTypeNode = enumNode.getNextSibling(); | |
while (memberTypeNode != null) { | |
enumType.addEnumMember(memberTypeNode.toString()); | |
memberTypeNode = memberTypeNode.getNextSibling(); | |
} | |
return enumType; | |
} | |
private UnionType visitUnion(AST node) throws InvalidIDLException { | |
UnionType unionType = new UnionType(); | |
AST unNode = node.getFirstChild(); | |
String unName = unNode.toString(); | |
unionType.setModule(module); | |
unionType.setName(unName); | |
AST switchTypeNode = unNode.getNextSibling(); | |
unionType.setDiscriminatorType(findDataType(switchTypeNode, unName)); | |
AST caseOrDefaultNode = switchTypeNode.getNextSibling(); | |
while (caseOrDefaultNode != null) { | |
UnionMember unionMember = new UnionMember(); | |
AST typeNode; | |
if (IDLTokenTypes.LITERAL_default == caseOrDefaultNode.getType()) { | |
unionMember.setDefault(true); | |
typeNode = caseOrDefaultNode.getFirstChild(); | |
} else { | |
unionMember.setDefault(false); | |
AST caseValueNode = caseOrDefaultNode.getFirstChild(); | |
unionMember.setDiscriminatorValue(caseValueNode.getText()); | |
typeNode = caseValueNode.getNextSibling(); | |
} | |
unionMember.setDataType(findDataType(typeNode, unName)); | |
AST memberNode = typeNode.getNextSibling(); | |
unionMember.setName(memberNode.toString()); | |
unionType.addMember(unionMember); | |
caseOrDefaultNode = caseOrDefaultNode.getNextSibling(); | |
} | |
return unionType; | |
} | |
private void visitAndAddTypedefs(AST node, String moduleName) throws InvalidIDLException { | |
AST typedefNode = node.getFirstChild(); | |
DataType dataType; | |
//SequenceType sequence = null; | |
//if (typedefNode.getType()==IDLTokenTypes.LITERAL_sequence) { | |
// sequence = visitAnonymousSequence(typedefNode); | |
// dataType = sequence.getDataType(); | |
//} else { | |
dataType = findDataType(typedefNode, null, true, true); | |
//} | |
AST typedefNameNode = typedefNode.getNextSibling(); | |
AST dimensionNode; | |
String typedefName = typedefNameNode.toString(); | |
Typedef typedef; | |
while (typedefNameNode != null) { | |
int dimensions = typedefNameNode.getNumberOfChildren(); | |
if (dimensions > 0) { | |
dimensionNode = typedefNameNode.getFirstChild(); | |
ArrayType arrayType = null; | |
ArrayType rootArrayType = null; | |
int i = 1; | |
while(dimensionNode!=null) { | |
ArrayType temp = new ArrayType(); | |
temp.setElementModule(moduleName); | |
temp.setElementName(typedefName); | |
temp.setDepth(i); | |
i++; | |
if (arrayType != null) { | |
arrayType.setDataType(temp); | |
} else { | |
rootArrayType = temp; | |
} | |
arrayType = temp; | |
arrayType.setElementCount(Integer.parseInt(dimensionNode.getText())); | |
dimensionNode = dimensionNode.getNextSibling(); | |
} | |
if (arrayType != null) { | |
arrayType.setDataType(dataType); | |
} | |
dataType = rootArrayType; | |
} | |
typedef = new Typedef(); | |
typedef.setDataType(dataType); | |
typedef.setModule(moduleName); | |
typedef.setName(typedefName); | |
idl.addType(typedef); | |
typedefNameNode = typedefNameNode.getNextSibling(); | |
} | |
} | |
private SequenceType visitAnonymousSequence(AST node, String parentName, boolean root) throws InvalidIDLException { | |
AST typeNode = node.getFirstChild(); | |
SequenceType sequenceType = new SequenceType(); | |
DataType dataType = findDataType(typeNode, parentName, false, false); | |
sequenceType.setDataType(dataType); | |
sequenceType.setElementModule(module); | |
AST elementNode = node.getNextSibling(); | |
if (elementNode != null && root) { | |
String elementName = elementNode.getText(); | |
sequenceType.setName(elementName); | |
SequenceType tempSeqType = sequenceType; | |
int i = 1; | |
DataType tempDataType; | |
while(true) { | |
tempSeqType.setElementName(elementName); | |
tempSeqType.setDepth(i); | |
i++; | |
tempDataType = tempSeqType.getDataType(); | |
if (tempDataType instanceof SequenceType) { | |
tempSeqType = (SequenceType) tempDataType; | |
} else { | |
break; | |
} | |
} | |
} | |
AST countNode = typeNode.getNextSibling(); | |
if (countNode!=null) { | |
sequenceType.setElementCount(Integer.parseInt(countNode.getText())); | |
//sequenceType.setBounded(true); | |
} else { | |
sequenceType.setElementCount(0); | |
//sequenceType.setBounded(false); | |
} | |
return sequenceType; | |
} | |
} |