blob: 4ff61f25dcfb3f9d0f1e92b0b01f4de6ecab7c85 [file] [log] [blame]
/*
* 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;
}
}