/** * 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.cxf.tools.corba.processors.idl; import java.util.ArrayList; import java.util.List; import javax.wsdl.Definition; import javax.xml.namespace.QName; import antlr.collections.AST; import org.apache.cxf.binding.corba.wsdl.Alias; import org.apache.cxf.binding.corba.wsdl.Anonarray; import org.apache.cxf.binding.corba.wsdl.Anonsequence; import org.apache.cxf.binding.corba.wsdl.Array; import org.apache.cxf.binding.corba.wsdl.CorbaConstants; import org.apache.cxf.binding.corba.wsdl.CorbaType; import org.apache.cxf.binding.corba.wsdl.Sequence; import org.apache.cxf.binding.corba.wsdl.TypeMappingType; import org.apache.cxf.tools.corba.common.XmlSchemaPrimitiveMap; import org.apache.ws.commons.schema.XmlSchema; import org.apache.ws.commons.schema.XmlSchemaCollection; import org.apache.ws.commons.schema.XmlSchemaType; import org.apache.ws.commons.schema.constants.Constants; public class ScopedNameVisitor extends VisitorBase { private static boolean exceptionMode; private static XmlSchemaPrimitiveMap xmlSchemaPrimitiveMap = new XmlSchemaPrimitiveMap(); public ScopedNameVisitor(Scope scope, Definition defn, XmlSchema schemaRef, WSDLASTVisitor wsdlVisitor) { super(scope, defn, schemaRef, wsdlVisitor); } public void setExceptionMode(boolean value) { exceptionMode = value; } public static boolean accept(Scope scope, Definition defn, XmlSchema schemaRef, AST node, WSDLASTVisitor wsdlVisitor) { return accept(scope, defn, schemaRef, node, wsdlVisitor, false); } // when accepting a "name" (for example, name of a field in a struct), we may need // to relax the strict checking for forward decls and schema types to not count for // exact parent scope names public static boolean accept(Scope scope, Definition defn, XmlSchema schemaRef, AST node, WSDLASTVisitor wsdlVisitor, boolean asName) { boolean result = false; if (PrimitiveTypesVisitor.accept(node)) { result = true; } else if (isforwardDeclared(scope, node, wsdlVisitor, asName)) { result = true; } else if (ObjectReferenceVisitor.accept(scope, schemaRef, defn, node, wsdlVisitor)) { result = true; } else if (findSchemaType(scope, defn, schemaRef, node, wsdlVisitor, null, asName)) { result = true; } return result; } public void visit(AST node) { // <scoped_name> ::= <identifier> // | :: <identifier> // | <scoped_name> "::" <identifier> XmlSchemaType stype = null; CorbaType ctype = null; if (PrimitiveTypesVisitor.accept(node)) { // primitive type PrimitiveTypesVisitor primitiveVisitor = new PrimitiveTypesVisitor(null, definition, schema, schemas); primitiveVisitor.visit(node); stype = primitiveVisitor.getSchemaType(); ctype = primitiveVisitor.getCorbaType(); } else if (isforwardDeclared(getScope(), node, wsdlVisitor)) { // forward declaration Scope scope = forwardDeclared(getScope(), definition, schema, node, wsdlVisitor); setFullyQualifiedName(scope); // how will we create the corbatype ???? } else if (ObjectReferenceVisitor.accept(getScope(), schema, definition, node, wsdlVisitor)) { ObjectReferenceVisitor objRefVisitor = new ObjectReferenceVisitor(getScope(), definition, schema, wsdlVisitor); objRefVisitor.visit(node); stype = objRefVisitor.getSchemaType(); ctype = objRefVisitor.getCorbaType(); } else { VisitorTypeHolder holder = new VisitorTypeHolder(); boolean found = findSchemaType(getScope(), definition, schema, node, wsdlVisitor, holder); if (found) { ctype = holder.getCorbaType(); stype = holder.getSchemaType(); } else { Scope scopedName = new Scope(getScope(), node); QName qname = new QName(schema.getTargetNamespace(), scopedName.toString()); throw new RuntimeException("[ScopedNameVisitor: Corba type " + qname + " not found in typeMap]"); } } setSchemaType(stype); setCorbaType(ctype); } private static CorbaType getCorbaSchemaType(XmlSchema xmlSchema, TypeMappingType typeMap, XmlSchemaType stype, Scope scopedName) { CorbaType ctype = null; if (stype.getQName().equals(Constants.XSD_STRING)) { ctype = new CorbaType(); ctype.setName(CorbaConstants.NT_CORBA_STRING.getLocalPart()); ctype.setQName(CorbaConstants.NT_CORBA_STRING); ctype.setType(Constants.XSD_STRING); } else { QName qname = stype.getQName(); ctype = findCorbaTypeForSchemaType(typeMap, qname, scopedName); } return ctype; } protected static boolean isforwardDeclared(Scope scope, AST node, WSDLASTVisitor wsdlVisitor) { return isforwardDeclared(scope, node, wsdlVisitor, false); } protected static boolean isforwardDeclared(Scope scope, AST node, WSDLASTVisitor wsdlVisitor, boolean b) { boolean isForward = false; Scope currentScope = scope; ScopeNameCollection scopedNames = wsdlVisitor.getScopedNames(); // Check for forward declaration from local scope outwards if ((node.getFirstChild() == null) || (node.getFirstChild() != null && node.getFirstChild().getType() != IDLTokenTypes.SCOPEOP)) { while (!isForward && currentScope != currentScope.getParent()) { Scope scopedName = null; if (isFullyScopedName(node)) { scopedName = getFullyScopedName(currentScope, node); } else { scopedName = new Scope(currentScope, node); } if (scopedNames.getScope(scopedName) != null) { isForward = true; } if (b && currentScope.equals(new Scope(currentScope.getParent(), node))) { break; } currentScope = currentScope.getParent(); } } // Check for forward declaration in global scope if (!isForward) { Scope scopedName = null; if (isFullyScopedName(node)) { scopedName = getFullyScopedName(new Scope(), node); } else { scopedName = new Scope(new Scope(), node); } if (scopedNames.getScope(scopedName) != null) { isForward = true; } } return isForward; } protected static Scope forwardDeclared(Scope scope, Definition defn, XmlSchema schemaRef, AST node, WSDLASTVisitor wsdlVisitor) { //XmlSchemaType result = null; Scope result = null; Scope currentScope = scope; ScopeNameCollection scopedNames = wsdlVisitor.getScopedNames(); // Check for forward declaration from local scope outwards if ((node.getFirstChild() == null) || (node.getFirstChild() != null && node.getFirstChild().getType() != IDLTokenTypes.SCOPEOP)) { while (result == null && currentScope != currentScope.getParent()) { Scope scopedName = null; if (isFullyScopedName(node)) { scopedName = getFullyScopedName(currentScope, node); } else { scopedName = new Scope(currentScope, node); } if (scopedNames.getScope(scopedName) != null) { XmlSchema xmlSchema = schemaRef; String tns = wsdlVisitor.getModuleToNSMapper().map(scopedName.getParent()); if (tns != null) { xmlSchema = wsdlVisitor.getManager().getXmlSchema(tns); } if (ObjectReferenceVisitor.accept(scope, xmlSchema, defn, node, wsdlVisitor)) { // checks if its a forward Visitor visitor = new ObjectReferenceVisitor(scope, defn, xmlSchema, wsdlVisitor); visitor.visit(node); } result = scopedName; } currentScope = currentScope.getParent(); } } // Check for forward declaration in global scope if (result == null) { Scope scopedName = null; if (isFullyScopedName(node)) { scopedName = getFullyScopedName(new Scope(), node); } else { scopedName = new Scope(new Scope(), node); } if (scopedNames.getScope(scopedName) != null) { XmlSchema xmlSchema = schemaRef; String tns = wsdlVisitor.getModuleToNSMapper().map(scopedName.getParent()); if (tns != null) { xmlSchema = wsdlVisitor.getManager().getXmlSchema(tns); } if (ObjectReferenceVisitor.accept(scope, xmlSchema, defn, node, wsdlVisitor)) { // checks if an object ref Visitor visitor = new ObjectReferenceVisitor(scope, defn, xmlSchema, wsdlVisitor); visitor.visit(node); } result = scopedName; } } return result; } protected static boolean findSchemaType(Scope scope, Definition defn, XmlSchema schemaRef, AST node, WSDLASTVisitor wsdlVisitor, VisitorTypeHolder holder) { return findSchemaType(scope, defn, schemaRef, node, wsdlVisitor, holder, false); } protected static boolean findSchemaType(Scope scope, Definition defn, XmlSchema schemaRef, AST node, WSDLASTVisitor wsdlVisitor, VisitorTypeHolder holder, boolean checkExact) { boolean result = false; Scope currentScope = scope; // checks from innermost local scope outwards if ((node.getFirstChild() == null) || (node.getFirstChild() != null && node.getFirstChild().getType() != IDLTokenTypes.SCOPEOP)) { while (!result && currentScope != currentScope.getParent()) { // A name can be used in an unqualified form within a particular // scope; // it will be resolved by successvely n searching farther out in // enclosing scopes, while taking into consideration // inheritance relationships among interfaces. Scope scopedName = null; if (isFullyScopedName(node)) { scopedName = getFullyScopedName(currentScope, node); } else { scopedName = new Scope(currentScope, node); } result = findScopeSchemaType(scopedName, schemaRef, wsdlVisitor, holder); // Search inherited scopes for the type if (!result) { result = findSchemaTypeInInheritedScope(scope, defn, schemaRef, node, wsdlVisitor, holder); } if (checkExact && currentScope.equals(new Scope(currentScope.getParent(), node))) { return false; } currentScope = currentScope.getParent(); } } if (!result) { // Global scope is our last chance to resolve the node result = findSchemaTypeInGlobalScope(scope, defn, schemaRef, node, wsdlVisitor, holder); } return result; } private static boolean findSchemaTypeInGlobalScope(Scope scope, Definition defn, XmlSchema currentSchema, AST node, WSDLASTVisitor wsdlVisitor, VisitorTypeHolder holder) { XmlSchemaCollection schemas = wsdlVisitor.getSchemas(); TypeMappingType typeMap = wsdlVisitor.getTypeMap(); ModuleToNSMapper mapper = wsdlVisitor.getModuleToNSMapper(); WSDLSchemaManager manager = wsdlVisitor.getManager(); Scope scopedName = new Scope(scope, node); String name = node.toString(); if (isFullyScopedName(node)) { scopedName = getFullyScopedName(new Scope(), node); name = scopedName.toString(); } boolean result = findNonSchemaType(name, wsdlVisitor, holder); if (!result) { XmlSchema xmlSchema = currentSchema; QName qname = null; String tns = mapper.map(scopedName.getParent()); if (tns != null) { xmlSchema = manager.getXmlSchema(tns); if (xmlSchema != null) { qname = new QName(xmlSchema.getTargetNamespace(), scopedName.tail()); } } else { qname = new QName(xmlSchema.getTargetNamespace(), name); } XmlSchemaType stype = null; if (qname != null) { // Exceptions are treated as a special case as above if (exceptionMode) { qname = new QName(xmlSchema.getTargetNamespace(), qname.getLocalPart() + "Type"); } stype = xmlSchema.getTypeByName(qname); if (stype == null) { stype = schemas.getTypeByQName(qname); } } if (stype != null) { result = true; if (holder != null) { holder.setSchemaType(stype); holder.setCorbaType(getCorbaSchemaType(xmlSchema, typeMap, stype, scopedName)); //add a xmlschema import if (!currentSchema.getTargetNamespace().equals(xmlSchema.getTargetNamespace())) { String importFile = wsdlVisitor.getOutputDir() + System.getProperty("file.separator") + scopedName.getParent().toString("_"); manager.addXmlSchemaImport(currentSchema, xmlSchema, importFile); } } } } return result; } // Searches all the inherited interfaces for the type. private static boolean findSchemaTypeInInheritedScope(Scope scope, Definition defn, XmlSchema schemaRef, AST node, WSDLASTVisitor wsdlVisitor, VisitorTypeHolder holder) { boolean result = false; List<Scope> baseScopes = wsdlVisitor.getInheritedScopeMap().get(scope); if (baseScopes != null) { List<Scope> scopeList = new ArrayList<>(); for (Scope scopeName : baseScopes) { scopeList.add(scopeName); } result = findSchemaTypeInBaseScope(scopeList, scope, defn, schemaRef, node, wsdlVisitor, holder); } return result; } // Does a breath depth search first. public static boolean findSchemaTypeInBaseScope(List<Scope> scopeList, Scope scope, Definition defn, XmlSchema schemaRef, AST node, WSDLASTVisitor wsdlVisitor, VisitorTypeHolder holder) { List<Scope> inheritedList = new ArrayList<>(); boolean result = false; if (scopeList != null) { for (Scope scopeName : scopeList) { inheritedList.add(scopeName); } for (Scope inheritScope : scopeList) { Scope scopedName = new Scope(inheritScope, node); result = findScopeSchemaType(scopedName, schemaRef, wsdlVisitor, holder); if (!result) { inheritedList.remove(inheritScope); List<Scope> scopes = wsdlVisitor.getInheritedScopeMap().get(inheritScope); if (scopes != null) { for (Scope scopeName : scopes) { inheritedList.add(scopeName); } } } else { return result; } } if (!inheritedList.isEmpty()) { List<Scope> baseList = new ArrayList<>(); for (Scope scopeName : inheritedList) { baseList.add(scopeName); } result = findSchemaTypeInBaseScope(baseList, scope, defn, schemaRef, node, wsdlVisitor, holder); } } return result; } // Searches this scope for the schema type. private static boolean findScopeSchemaType(Scope scopedName, XmlSchema schemaRef, WSDLASTVisitor wsdlVisitor, VisitorTypeHolder holder) { XmlSchemaCollection schemas = wsdlVisitor.getSchemas(); TypeMappingType typeMap = wsdlVisitor.getTypeMap(); ModuleToNSMapper mapper = wsdlVisitor.getModuleToNSMapper(); WSDLSchemaManager manager = wsdlVisitor.getManager(); boolean result = findNonSchemaType(scopedName.toString(), wsdlVisitor, holder); if (!result) { QName qname = null; XmlSchema xmlSchema = schemaRef; String tns = wsdlVisitor.getModuleToNSMapper().map(scopedName.getParent()); if (tns != null) { xmlSchema = wsdlVisitor.getManager().getXmlSchema(tns); } XmlSchemaType stype = null; if (xmlSchema != null) { // Exceptions are treated as a special case as for the // doc/literal style // in the schema we will have an element and a complextype // so the name // and the typename will be different. String scopedNameString = null; if (mapper.isDefaultMapping()) { scopedNameString = scopedName.toString(); } else { scopedNameString = scopedName.tail(); } if (exceptionMode) { qname = new QName(xmlSchema.getTargetNamespace(), scopedNameString + "Type"); } else { qname = new QName(xmlSchema.getTargetNamespace(), scopedNameString); } stype = xmlSchema.getTypeByName(qname); if (stype == null) { stype = schemas.getTypeByQName(qname); } } if (stype != null) { result = true; } if (result && holder != null) { holder.setSchemaType(stype); holder.setCorbaType(getCorbaSchemaType(xmlSchema, typeMap, stype, scopedName)); // add a xmlschema import if (!schemaRef.getTargetNamespace().equals(xmlSchema.getTargetNamespace())) { String importFile = wsdlVisitor.getOutputDir() + System.getProperty("file.separator") + scopedName.getParent().toString("_"); manager.addXmlSchemaImport(schemaRef, xmlSchema, importFile); } } } return result; } public static CorbaType findCorbaTypeForSchemaType(TypeMappingType typeMap, QName schemaTypeName, Scope scopedName) { CorbaType result = null; for (CorbaType type : typeMap.getStructOrExceptionOrUnion()) { if ((type instanceof Sequence) || (type instanceof Array) || (type.getType() == null) || (type instanceof Anonsequence) || (type instanceof Anonarray)) { //REVISIT, cannot compare the type because they are incorrect if (type.getQName().getLocalPart().equals(schemaTypeName.getLocalPart())) { result = type; break; } // If we are using the module to ns mapping, then the name of the type in schema // and in the typemap are actually different. We should then compare with the scoped // name that we are given. if (type.getQName().getLocalPart().equals(scopedName.toString())) { result = type; break; } } else if (schemaTypeName.equals(type.getType())) { result = type; break; } } return result; } public static CorbaType findCorbaType(TypeMappingType typeMap, QName typeName) { CorbaType result = null; for (CorbaType type : typeMap.getStructOrExceptionOrUnion()) { if (type.getQName().equals(typeName)) { result = type; break; } } return result; } protected static boolean isFullyScopedName(AST node) { return node.getType() == IDLTokenTypes.IDENT && node.getFirstChild() != null && ((node.getFirstChild().getType() == IDLTokenTypes.SCOPEOP) || (node.getFirstChild().getType() == IDLTokenTypes.IDENT)); } protected static Scope getFullyScopedName(Scope currentScope, AST node) { Scope scopedName = new Scope(); if (!currentScope.toString().equals(node.getText())) { scopedName = new Scope(currentScope); } scopedName = new Scope(scopedName, node); AST scopeNode = node.getFirstChild(); if (node.getFirstChild().getType() == IDLTokenTypes.IDENT) { scopedName = new Scope(scopedName, scopeNode); } while (scopeNode.getNextSibling() != null) { scopeNode = scopeNode.getNextSibling(); scopedName = new Scope(scopedName, scopeNode); } return scopedName; } protected static boolean findNonSchemaType(String name, WSDLASTVisitor wsdlVisitor, VisitorTypeHolder holder) { boolean result = false; TypeMappingType typeMap = wsdlVisitor.getTypeMap(); XmlSchemaCollection schemas = wsdlVisitor.getSchemas(); QName qname = new QName(typeMap.getTargetNamespace(), name); CorbaType corbaType = findCorbaType(typeMap, qname); if (corbaType != null) { if (corbaType instanceof Alias) { result = true; if (holder != null) { populateAliasSchemaType(corbaType, wsdlVisitor, holder); } } else if (((corbaType instanceof Sequence) || (corbaType instanceof Anonsequence)) && ((corbaType.getType().equals(Constants.XSD_BASE64)))) { //special case of sequence of octets result = true; if (holder != null) { holder.setCorbaType(corbaType); holder.setSchemaType(schemas.getTypeByQName(corbaType.getType())); } } } return result; } protected static void populateAliasSchemaType(CorbaType corbaType, WSDLASTVisitor wsdlVisitor, VisitorTypeHolder holder) { XmlSchemaCollection schemas = wsdlVisitor.getSchemas(); TypeMappingType typeMap = wsdlVisitor.getTypeMap(); holder.setCorbaType(corbaType); Alias alias = (Alias) corbaType; //loop through alias base types, till you get a non-alias corba type CorbaType type = findCorbaType(typeMap, alias.getBasetype()); while ((type != null) && (type instanceof Alias)) { alias = (Alias) type; type = findCorbaType(typeMap, alias.getBasetype()); } QName tname; if (type == null) { //it must be a primitive type tname = xmlSchemaPrimitiveMap.get(alias.getBasetype()); } else { tname = type.getType(); } XmlSchemaType stype = schemas.getTypeByQName(tname); if (stype == null) { XmlSchema xmlSchema = wsdlVisitor.getManager().getXmlSchema(tname.getNamespaceURI()); if (xmlSchema != null) { stype = xmlSchema.getTypeByName(tname); } else { stype = wsdlVisitor.getSchema().getTypeByName(tname); } } holder.setSchemaType(stype); } }