1/*
2 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package com.sun.xml.internal.ws.model.wsdl;
27
28import com.sun.istack.internal.NotNull;
29import com.sun.xml.internal.ws.api.model.ParameterBinding;
30import com.sun.xml.internal.ws.api.model.wsdl.WSDLMessage;
31import com.sun.xml.internal.ws.api.model.wsdl.WSDLModel;
32import com.sun.xml.internal.ws.api.model.wsdl.WSDLOperation;
33import com.sun.xml.internal.ws.api.model.wsdl.WSDLPortType;
34import com.sun.xml.internal.ws.api.model.wsdl.editable.EditableWSDLBoundOperation;
35import com.sun.xml.internal.ws.api.model.wsdl.editable.EditableWSDLBoundPortType;
36import com.sun.xml.internal.ws.api.model.wsdl.editable.EditableWSDLMessage;
37import com.sun.xml.internal.ws.api.model.wsdl.editable.EditableWSDLModel;
38import com.sun.xml.internal.ws.api.model.wsdl.editable.EditableWSDLPart;
39import com.sun.xml.internal.ws.api.model.wsdl.editable.EditableWSDLPort;
40import com.sun.xml.internal.ws.api.model.wsdl.editable.EditableWSDLPortType;
41import com.sun.xml.internal.ws.api.model.wsdl.editable.EditableWSDLService;
42import com.sun.xml.internal.ws.policy.PolicyMap;
43
44import javax.jws.WebParam.Mode;
45import javax.xml.namespace.QName;
46
47import java.util.Collections;
48import java.util.HashMap;
49import java.util.LinkedHashMap;
50import java.util.Map;
51
52/**
53 * Implementation of {@link WSDLModel}
54 *
55 * @author Vivek Pandey
56 */
57public final class WSDLModelImpl extends AbstractExtensibleImpl implements EditableWSDLModel {
58    private final Map<QName, EditableWSDLMessage> messages = new HashMap<QName, EditableWSDLMessage>();
59    private final Map<QName, EditableWSDLPortType> portTypes = new HashMap<QName, EditableWSDLPortType>();
60    private final Map<QName, EditableWSDLBoundPortType> bindings = new HashMap<QName, EditableWSDLBoundPortType>();
61    private final Map<QName, EditableWSDLService> services = new LinkedHashMap<QName, EditableWSDLService>();
62
63    private PolicyMap policyMap;
64    private final Map<QName, EditableWSDLBoundPortType> unmBindings
65        = Collections.<QName, EditableWSDLBoundPortType>unmodifiableMap(bindings);
66
67
68    public WSDLModelImpl(@NotNull String systemId) {
69        super(systemId,-1);
70    }
71
72    /**
73     * To create {@link WSDLModelImpl} from WSDL that doesn't have a system ID.
74     */
75    public WSDLModelImpl() {
76        super(null,-1);
77    }
78
79    public void addMessage(EditableWSDLMessage msg){
80        messages.put(msg.getName(), msg);
81    }
82
83    public EditableWSDLMessage getMessage(QName name){
84        return messages.get(name);
85    }
86
87    public void addPortType(EditableWSDLPortType pt){
88        portTypes.put(pt.getName(), pt);
89    }
90
91    public EditableWSDLPortType getPortType(QName name){
92        return portTypes.get(name);
93    }
94
95    public void addBinding(EditableWSDLBoundPortType boundPortType){
96        assert !bindings.containsValue(boundPortType);
97        bindings.put(boundPortType.getName(), boundPortType);
98    }
99
100    public EditableWSDLBoundPortType getBinding(QName name){
101        return bindings.get(name);
102    }
103
104    public void addService(EditableWSDLService svc){
105        services.put(svc.getName(), svc);
106    }
107
108    public EditableWSDLService getService(QName name){
109        return services.get(name);
110    }
111
112    public Map<QName, EditableWSDLMessage> getMessages() {
113        return messages;
114    }
115
116    public @NotNull Map<QName, EditableWSDLPortType> getPortTypes() {
117        return portTypes;
118    }
119
120    public @NotNull Map<QName, ? extends EditableWSDLBoundPortType> getBindings() {
121        return unmBindings;
122    }
123
124    public @NotNull Map<QName, EditableWSDLService> getServices(){
125        return services;
126    }
127
128    /**
129     * Returns the first service QName from insertion order
130     */
131    public QName getFirstServiceName(){
132        if(services.isEmpty())
133            return null;
134        return services.values().iterator().next().getName();
135    }
136
137    /**
138     *
139     * @param serviceName non-null service QName
140     * @param portName    non-null port QName
141     * @return
142     *          WSDLBoundOperation on success otherwise null. throws NPE if any of the parameters null
143     */
144    public EditableWSDLBoundPortType getBinding(QName serviceName, QName portName){
145        EditableWSDLService service = services.get(serviceName);
146        if(service != null){
147            EditableWSDLPort port = service.get(portName);
148            if(port != null)
149                return port.getBinding();
150        }
151        return null;
152    }
153
154    public void finalizeRpcLitBinding(EditableWSDLBoundPortType boundPortType){
155        assert(boundPortType != null);
156        QName portTypeName = boundPortType.getPortTypeName();
157        if(portTypeName == null)
158            return;
159        WSDLPortType pt = portTypes.get(portTypeName);
160        if(pt == null)
161            return;
162        for (EditableWSDLBoundOperation bop : boundPortType.getBindingOperations()) {
163            WSDLOperation pto = pt.get(bop.getName().getLocalPart());
164            WSDLMessage inMsgName = pto.getInput().getMessage();
165            if(inMsgName == null)
166                continue;
167            EditableWSDLMessage inMsg = messages.get(inMsgName.getName());
168            int bodyindex = 0;
169            if(inMsg != null){
170                for(EditableWSDLPart part:inMsg.parts()){
171                    String name = part.getName();
172                    ParameterBinding pb = bop.getInputBinding(name);
173                    if(pb.isBody()){
174                        part.setIndex(bodyindex++);
175                        part.setBinding(pb);
176                        bop.addPart(part, Mode.IN);
177                    }
178                }
179            }
180            bodyindex=0;
181            if(pto.isOneWay())
182                continue;
183            WSDLMessage outMsgName = pto.getOutput().getMessage();
184            if(outMsgName == null)
185                continue;
186            EditableWSDLMessage outMsg = messages.get(outMsgName.getName());
187            if(outMsg!= null){
188                for(EditableWSDLPart part:outMsg.parts()){
189                    String name = part.getName();
190                    ParameterBinding pb = bop.getOutputBinding(name);
191                    if(pb.isBody()){
192                        part.setIndex(bodyindex++);
193                        part.setBinding(pb);
194                        bop.addPart(part, Mode.OUT);
195                    }
196                }
197            }
198        }
199    }
200
201    /**
202     * Gives the PolicyMap associated with the WSDLModel
203     *
204     * @return PolicyMap
205     */
206    public PolicyMap getPolicyMap() {
207        return policyMap;
208    }
209
210    /**
211     * Set PolicyMap for the WSDLModel.
212     * @param policyMap
213     */
214    public void setPolicyMap(PolicyMap policyMap) {
215        this.policyMap = policyMap;
216    }
217
218    /**
219     * Invoked at the end of the model construction to fix up references, etc.
220     */
221    public void freeze() {
222        for (EditableWSDLService service : services.values()) {
223            service.freeze(this);
224        }
225        for (EditableWSDLBoundPortType bp : bindings.values()) {
226            bp.freeze();
227        }
228        // Enforce freeze all the portTypes referenced by this endpoints, see Bug8966673 for detail
229        for (EditableWSDLPortType pt : portTypes.values()) {
230            pt.freeze();
231        }
232    }
233}
234