/*
 * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code 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
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.xml.internal.ws.spi.db;

import static com.sun.xml.internal.ws.model.RuntimeModeler.DocWrappeeNamespapceQualified;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Map.Entry;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import static com.sun.xml.internal.ws.wsdl.writer.WSDLGenerator.XsdNs;

import javax.xml.bind.JAXBException;
import javax.xml.bind.SchemaOutputResolver;
import javax.xml.namespace.QName;
import javax.xml.transform.Result;
import javax.xml.ws.WebServiceException;

import com.sun.xml.internal.bind.v2.schemagen.xmlschema.ComplexType;
import com.sun.xml.internal.bind.v2.schemagen.xmlschema.Element;
import com.sun.xml.internal.bind.v2.schemagen.xmlschema.ExplicitGroup;
import com.sun.xml.internal.bind.v2.schemagen.xmlschema.LocalElement;
import com.sun.xml.internal.bind.v2.schemagen.xmlschema.Occurs;
import com.sun.xml.internal.txw2.TXW;
import com.sun.xml.internal.txw2.output.ResultFactory;
import com.sun.xml.internal.ws.api.model.SEIModel;
import com.sun.xml.internal.ws.model.AbstractSEIModelImpl;
import com.sun.xml.internal.ws.model.JavaMethodImpl;
import com.sun.xml.internal.ws.model.ParameterImpl;
import com.sun.xml.internal.ws.model.WrapperParameter;
import com.sun.xml.internal.ws.wsdl.writer.document.xsd.Schema;

ServiceArtifactSchemaGenerator generates XML schema for service artifacts including the wrapper types of document-literal stype operation and exceptions.
Author:shih-chang.chen@oracle.com
/** * ServiceArtifactSchemaGenerator generates XML schema for service artifacts including the wrapper types of * document-literal stype operation and exceptions. * * @author shih-chang.chen@oracle.com */
public class ServiceArtifactSchemaGenerator { protected AbstractSEIModelImpl model; protected SchemaOutputResolver xsdResolver; public ServiceArtifactSchemaGenerator(SEIModel model) { this.model = (AbstractSEIModelImpl)model; } static final String FilePrefix = "jaxwsGen"; protected int fileIndex = 0; protected Schema create(String tns) { try { Result res = xsdResolver.createOutput(tns, FilePrefix + (fileIndex++) + ".xsd"); return TXW.create(Schema.class, ResultFactory.createSerializer(res)); } catch (IOException e) { // TODO Auto-generated catch block throw new WebServiceException(e); } } public void generate(SchemaOutputResolver resolver) { xsdResolver = resolver; List<WrapperParameter> wrappers = new ArrayList<WrapperParameter>(); for (JavaMethodImpl method : model.getJavaMethods()) { if(method.getBinding().isRpcLit()) continue; for (ParameterImpl p : method.getRequestParameters()) { if (p instanceof WrapperParameter) { if (WrapperComposite.class.equals((((WrapperParameter)p).getTypeInfo().type))) { wrappers.add((WrapperParameter)p); } } } for (ParameterImpl p : method.getResponseParameters()) { if (p instanceof WrapperParameter) { if (WrapperComposite.class.equals((((WrapperParameter)p).getTypeInfo().type))) { wrappers.add((WrapperParameter)p); } } } } if (wrappers.isEmpty()) return; HashMap<String, Schema> xsds = initWrappersSchemaWithImports(wrappers); postInit(xsds); for(WrapperParameter wp : wrappers) { String tns = wp.getName().getNamespaceURI(); Schema xsd = xsds.get(tns); Element e = xsd._element(Element.class); e._attribute("name", wp.getName().getLocalPart()); e.type(wp.getName()); ComplexType ct = xsd._element(ComplexType.class); ct._attribute("name", wp.getName().getLocalPart()); ExplicitGroup sq = ct.sequence(); for (ParameterImpl p : wp.getWrapperChildren() ) if (p.getBinding().isBody()) addChild(sq, p); } for(Schema xsd: xsds.values()) xsd.commit(); } protected void postInit(HashMap<String, Schema> xsds) { } protected void addChild(ExplicitGroup sq, ParameterImpl param) { TypeInfo typeInfo = param.getItemType(); boolean repeatedElement = false; if (typeInfo == null) { typeInfo = param.getTypeInfo(); } else { if (typeInfo.getWrapperType() != null) typeInfo = param.getTypeInfo(); else repeatedElement = true; } Occurs child = addChild(sq, param.getName(), typeInfo); if (repeatedElement && child != null) { child.maxOccurs("unbounded"); } } protected Occurs addChild(ExplicitGroup sq, QName name, TypeInfo typeInfo) { LocalElement le = null;; QName type = model.getBindingContext().getTypeName(typeInfo); if (type != null) { le = sq.element(); le._attribute("name", name.getLocalPart()); le.type(type); } else { if (typeInfo.type instanceof Class) { try { QName elemName = model.getBindingContext().getElementName((Class)typeInfo.type); if (elemName.getLocalPart().equals("any") && elemName.getNamespaceURI().equals(XsdNs)) { return sq.any(); } else { le = sq.element(); le.ref(elemName); } } catch (JAXBException je) { throw new WebServiceException(je.getMessage(), je); } } } return le; } //All the imports have to go first ... private HashMap<String, Schema> initWrappersSchemaWithImports(List<WrapperParameter> wrappers) { Object o = model.databindingInfo().properties().get(DocWrappeeNamespapceQualified); boolean wrappeeQualified = (o!= null && o instanceof Boolean) ? ((Boolean) o) : false; HashMap<String, Schema> xsds = new HashMap<String, Schema>(); HashMap<String, Set<String>> imports = new HashMap<String, Set<String>>(); for(WrapperParameter wp : wrappers) { String tns = wp.getName().getNamespaceURI(); Schema xsd = xsds.get(tns); if (xsd == null) { xsd = create(tns); xsd.targetNamespace(tns); if (wrappeeQualified) xsd._attribute("elementFormDefault", "qualified"); xsds.put(tns, xsd); } for (ParameterImpl p : wp.getWrapperChildren() ) { String nsToImport = (p.getBinding().isBody())? bodyParamNS(p): null; if (nsToImport != null && !nsToImport.equals(tns) && !nsToImport.equals("http://www.w3.org/2001/XMLSchema")) { Set<String> importSet = imports.get(tns); if (importSet == null) { importSet = new HashSet<String>(); imports.put(tns, importSet); } importSet.add(nsToImport); } } } for(Entry<String, Set<String>> entry: imports.entrySet()) { String tns = entry.getKey(); Set<String> importSet = entry.getValue(); Schema xsd = xsds.get(tns); for(String nsToImport : importSet) xsd._namespace(nsToImport, true); for(String nsToImport : importSet) { com.sun.xml.internal.ws.wsdl.writer.document.xsd.Import imp = xsd._import(); imp.namespace(nsToImport); } } return xsds; } protected String bodyParamNS(ParameterImpl p) { String nsToImport = null; TypeInfo typeInfo = p.getItemType(); if (typeInfo == null) typeInfo = p.getTypeInfo(); QName type = model.getBindingContext().getTypeName(typeInfo); if (type != null) { nsToImport = type.getNamespaceURI(); } else { if (typeInfo.type instanceof Class) { try { QName elemRef = model.getBindingContext().getElementName((Class)typeInfo.type); if (elemRef != null) nsToImport = elemRef.getNamespaceURI(); } catch (JAXBException je) { throw new WebServiceException(je.getMessage(), je); } } } return nsToImport; } }