public Definition generate()

in modules/binding-ws-wsdlgen/src/main/java/org/apache/tuscany/sca/binding/ws/wsdlgen/Interface2WSDLGenerator.java [298:600]


    public Definition generate(Interface interfaze, WSDLDefinition wsdlDefinition) throws WSDLException {
        if (interfaze == null) {
            return null;
        }
        if (interfaze instanceof WSDLInterface) {
            return ((WSDLInterface)interfaze).getWsdlDefinition().getDefinition();
        }
        JavaInterface iface = (JavaInterface)interfaze;
        if (!interfaze.isRemotable()) {
            fatal("InterfaceNotRemotable", interfaze, iface.getName());
        }
        QName name = getQName(iface);
        Definition definition = factory.newDefinition();
        if (requiresSOAP12) {
            definition.addNamespace("SOAP12", "http://schemas.xmlsoap.org/wsdl/soap12/");
        } else {
            definition.addNamespace("SOAP", "http://schemas.xmlsoap.org/wsdl/soap/");
        }
        definition.addNamespace("wsdl", "http://schemas.xmlsoap.org/wsdl/");
        definition.addNamespace("xs", SCHEMA_NS);

        String namespaceURI = name.getNamespaceURI();
        definition.setTargetNamespace(namespaceURI);
        definition.setQName(new QName(namespaceURI, name.getLocalPart() + "Service", name.getPrefix()));
        definition.addNamespace(name.getPrefix(), namespaceURI);

        PortType portType = definition.createPortType();
        portType.setQName(name);
        Binding binding = definitionGenerator.createBinding(definition, portType);
        Map<String, XMLTypeHelper> helpers = new HashMap<String, XMLTypeHelper>();
        Map<QName, List<ElementInfo>> wrappers = new HashMap<QName, List<ElementInfo>>();
        for (Operation op : interfaze.getOperations()) {
            javax.wsdl.Operation operation = generateOperation(definition, op, helpers, wrappers);
            portType.addOperation(operation);
            String action = ((JavaOperation)op).getAction();
            if ((action == null || "".equals(action)) && !op.isInputWrapperStyle() && op.getInputWrapper() == null) {
                // Bare style
                action = "urn:" + op.getName();
            }
            BindingOperation bindingOp = definitionGenerator.createBindingOperation(definition, operation, action);
            binding.addBindingOperation(bindingOp);
        }
        portType.setUndefined(false);
        definition.addPortType(portType);
        binding.setUndefined(false);
        definition.addBinding(binding);
        wsdlDefinition.setBinding(binding);
        
        // call each helper in turn to populate the wsdl.types element
        XmlSchemaCollection schemaCollection = new XmlSchemaCollection(); 

        // TUSCANY-3298: enable JAXB wrapper generation
        for (Map.Entry<XMLTypeHelper, List<DataType>> en: getDataTypes(interfaze, true, helpers).entrySet()) {
            XMLTypeHelper helper = en.getKey();
            if (helper == null) {
                continue;
            }
            List<XSDefinition> xsDefinitions = helper.getSchemaDefinitions(xsdFactory, resolver, en.getValue());
            
            for (XSDefinition xsDef: xsDefinitions) {

                Document doc = xsDef.getDocument();
                if (doc != null) {                    
                    // TUSCANY-2757 and TUSCANY-3267 - flip global wrapper elements with nillable 
                    // set true to be set to false.  The JAXB RI seems to be generating this setting
                    // incorrectly according to the JAXB spec.                    
                    NodeList nodes = doc.getFirstChild().getChildNodes();
                    for (int i = 0; i < nodes.getLength(); i++) {
                        Node aNode = nodes.item(i);
                        if (aNode.getLocalName() != null && aNode.getLocalName().equals("element")) {
                            NamedNodeMap attributes = aNode.getAttributes();
                            Node nameAttr = attributes.getNamedItem("name");
                            if (nameAttr != null) { 
                                QName elementName = new QName(xsDef.getNamespace(), nameAttr.getNodeValue());
                                if (wrappers.containsKey(elementName)) {
                                    Node nillable = attributes.getNamedItem("nillable");
                                    if (nillable != null) {
                                        nillable.setNodeValue("false");
                                    }
                                }
                            }
                        }
                    }
                }
                
                loadXSD(schemaCollection, xsDef);
                wsdlDefinition.getXmlSchemas().add(xsDef);
            }
        }

        // remove global wrapper elements with schema definitions from generation list
        for (QName wrapperName: new HashSet<QName>(wrappers.keySet())) {
            if (wsdlDefinition.getXmlSchemaElement(wrapperName) != null) {
                wrappers.remove(wrapperName);
            }
        }
        
        schemaCollection = new XmlSchemaCollection(); 

        // generate schema elements for wrappers that aren't defined in the schemas
        if (wrappers.size() > 0) {
            int i = 0;
            int index = 0;
            Map<String, XSDefinition> wrapperXSDs = new HashMap<String, XSDefinition>();
            Map<Element, Map<String, String>> prefixMaps = new HashMap<Element, Map<String, String>>();
            for (Map.Entry<QName, List<ElementInfo>> entry: wrappers.entrySet()) {
                String targetNS = entry.getKey().getNamespaceURI();
                Document schemaDoc = null;
                Element schema = null;
                XSDefinition xsDef = wrapperXSDs.get(targetNS);
                if (xsDef != null) {
                    schemaDoc = xsDef.getDocument();
                    schema = schemaDoc.getDocumentElement();
                } else {
                    xsDef = wsdlDefinition.getSchema(targetNS);
                    if (xsDef != null) {
                        schemaDoc = xsDef.getDocument();
                        schema = schemaDoc.getDocumentElement();
                        wrapperXSDs.put(targetNS, xsDef);
                        Map<String, String> prefixMap = prefixMaps.get(schema);
                        if (prefixMap == null){
                            prefixMap = new HashMap<String, String>();
                            prefixMaps.put(schema, prefixMap);
                            String [] prefixes = xsDef.getSchema().getNamespaceContext().getDeclaredPrefixes();
                            for (int j = 0; j < prefixes.length; j++){
                                prefixMap.put(xsDef.getSchema().getNamespaceContext().getNamespaceURI(prefixes[j]),
                                              prefixes[j]);
                            }
                        }                        
                    } else {
                        schemaDoc = createDocument();
                        schema = schemaDoc.createElementNS(SCHEMA_NS, "xs:schema");
                        // The elementFormDefault should be set to unqualified, see TUSCANY-2388
                        schema.setAttribute("elementFormDefault", "unqualified");
                        schema.setAttribute("attributeFormDefault", "qualified");
                        schema.setAttribute("targetNamespace", targetNS);
                        schema.setAttributeNS(XMLNS_NS, "xmlns:xs", SCHEMA_NS);
                        schema.setAttributeNS(XMLNS_NS, "xmlns:tns", targetNS);
                        schemaDoc.appendChild(schema);
                        prefixMaps.put(schema, new HashMap<String, String>());
                        xsDef = xsdFactory.createXSDefinition();
                        xsDef.setUnresolved(true);
                        xsDef.setNamespace(targetNS);
                        xsDef.setDocument(schemaDoc);
                        // TUSCANY-2465: Set the system id to avoid schema conflict
                        xsDef.setLocation(URI.create("xsd_" + index + ".xsd"));
                        index++;
                        wrapperXSDs.put(targetNS, xsDef);
                    }  
                }
                Element wrapper = schemaDoc.createElementNS(SCHEMA_NS, "xs:element");
                schema.appendChild(wrapper);
                wrapper.setAttribute("name", entry.getKey().getLocalPart());
                if (entry.getValue().size() == 1 && entry.getValue().get(0).getQName() == null) {
                    // special case for global fault element
                    QName typeName = entry.getValue().get(0).getType().getQName();
                    String nsURI = typeName.getNamespaceURI();
                    if ("".equals(nsURI)) {
                        wrapper.setAttribute("type", typeName.getLocalPart());
                        addSchemaImport(schema, "", schemaDoc);
                    } else if (targetNS.equals(nsURI)) {
                        wrapper.setAttribute("type", typeName.getLocalPart());
                    } else if (SCHEMA_NS.equals(nsURI)) {
                        wrapper.setAttribute("type", "xs:" + typeName.getLocalPart());
                    } else {
                        Map<String, String> prefixMap = prefixMaps.get(schema);
                        String prefix = prefixMap.get(nsURI);
                        if (prefix == null) {
                            prefix = "ns" + i++;
                            while(prefixMap.containsValue(prefix)){
                                prefix = "ns" + i++;
                            }
                            prefixMap.put(nsURI, prefix);
                            schema.setAttributeNS(XMLNS_NS, "xmlns:" + prefix, nsURI);
                            addSchemaImport(schema, nsURI, schemaDoc);
                        }
                        wrapper.setAttribute("type", prefix + ":" + typeName.getLocalPart());
                    }                    
                } else {
                    // normal wrapper containing type definition inline
                    Element complexType = schemaDoc.createElementNS(SCHEMA_NS, "xs:complexType");
                    wrapper.appendChild(complexType);
                    if (entry.getValue().size() > 0) {
                        Element sequence = schemaDoc.createElementNS(SCHEMA_NS, "xs:sequence");
                        complexType.appendChild(sequence);
                        for (ElementInfo element: entry.getValue()) {
                            Element xsElement = schemaDoc.createElementNS(SCHEMA_NS, "xs:element"); 
                            if (element.isMany()) {
                                xsElement.setAttribute("maxOccurs", "unbounded");
                            }
                            xsElement.setAttribute("minOccurs", "0");
                            xsElement.setAttribute("name", element.getQName().getLocalPart());
                            if (element.isNillable()) {
                                xsElement.setAttribute("nillable", "true");
                            }
                            QName typeName = element.getType().getQName();
                            String nsURI = typeName.getNamespaceURI();
                            if ("".equals(nsURI)) {
                                xsElement.setAttribute("type", typeName.getLocalPart());
                                addSchemaImport(schema, "", schemaDoc);
                            } else if (SCHEMA_NS.equals(nsURI)) {
                                xsElement.setAttribute("type", "xs:" + typeName.getLocalPart());
                            } else {
                                Map<String, String> prefixMap = prefixMaps.get(schema);
                                String prefix = prefixMap.get(nsURI);
                                if (prefix == null) {
                                    if (targetNS.equals(nsURI)) {
									    prefix = "tns";
									} else {
                                        prefix = "ns" + i++;
                                        while(prefixMap.containsValue(prefix)){
                                            prefix = "ns" + i++;
                                        }
                                        addSchemaImport(schema, nsURI, schemaDoc);
									}
                                    prefixMap.put(nsURI, prefix);
                                    schema.setAttributeNS(XMLNS_NS, "xmlns:" + prefix, nsURI);
                                }
                                xsElement.setAttribute("type", prefix + ":" + typeName.getLocalPart());
                            }
                            sequence.appendChild(xsElement);
                        }
                    }
                }
            }
 
            // resolve XSDefinitions containing generated wrappers
            for (XSDefinition xsDef: wrapperXSDs.values()) {
                if (wsdlDefinition.getSchema(xsDef.getNamespace()) == null) {
                     wsdlDefinition.getXmlSchemas().add(xsDef);
                }
                
                xsDef.setSchema(null);
                xsDef.setSchemaCollection(null);
                loadXSD(schemaCollection, xsDef);
            }
        }
        
        XSDefinition noNamespaceSchema = null;
        XSDefinition defaultNamespaceSchema = null;     

        for (XSDefinition xsDef: wsdlDefinition.getXmlSchemas()) {
            // only apply these changes if we have a DOM to work with
            // this will generally come from the JAXB generation. SDO
            // just goes straight to generating XmlSchema structures
            Document doc = xsDef.getDocument();
            if (doc != null) {
                // TUSCANY-3283 find any schema that has been generated without a namespace
                //              and any schema using the default WSDL schema so that we can
                //              merge the two together              
                if (xsDef.getNamespace().equals("")){
                    noNamespaceSchema = xsDef;
                }
                if (xsDef.getNamespace().equals(namespaceURI)){
                    defaultNamespaceSchema = xsDef;
                } 
            }
        }    
        
        // useful for debugging DOM issues
        //System.out.println("======================= Schema DOM Pre Merge=======================" );
        //for (XSDefinition xsDef : wsdlDefinition.getXmlSchemas()) {
        //    if (xsDef.getDocument() != null) {
        //        printDOM(xsDef.getDocument());
        //    }
        //}          
        
        // TUSCANY-3283 merge the no namespace schema into the default namespace schema
        if (noNamespaceSchema != null && defaultNamespaceSchema != null){
            // remove the no namespace schema from our list of schema
            wsdlDefinition.getXmlSchemas().remove(noNamespaceSchema);
            // merge the schema with no namespace into the schema with the default namspace for this WSDL
            mergeSchema(noNamespaceSchema, defaultNamespaceSchema, wsdlDefinition.getXmlSchemas());
            
            // useful for debugging DOM issues
            //System.out.println("======================= Schema DOM Post Merge=======================" );
            //for (XSDefinition xsDef : wsdlDefinition.getXmlSchemas()) {
            //    if (xsDef.getDocument() != null) {
            //        printDOM(xsDef.getDocument());
            //    }
            //}            
            
            schemaCollection = new XmlSchemaCollection();
            defaultNamespaceSchema.setSchema(null);
            defaultNamespaceSchema.setSchemaCollection(null);
            loadXSD(schemaCollection, defaultNamespaceSchema);
        }         
        
        // push the schema into the WSDL 
        for (XSDefinition xsDef: wsdlDefinition.getXmlSchemas()){
            addSchemaExtension(xsDef, schemaCollection, wsdlDefinition, definition);
        }
        
        // useful for debugging DOM issues
        //System.out.println("======================= Schema DOM Process End =======================" );
        //for (XSDefinition xsDef : wsdlDefinition.getXmlSchemas()) {
        //    if (xsDef.getDocument() != null) {
        //        printDOM(xsDef.getDocument());
        //    }
        //}        
        
        return definition;
    }