View Javadoc

1   /*
2    * Copyright 2008 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.springframework.ws.wsdl.wsdl11.provider;
18  
19  import java.util.ArrayList;
20  import java.util.HashMap;
21  import java.util.Iterator;
22  import java.util.List;
23  import java.util.Map;
24  import javax.wsdl.Definition;
25  import javax.wsdl.Fault;
26  import javax.wsdl.Input;
27  import javax.wsdl.Message;
28  import javax.wsdl.Operation;
29  import javax.wsdl.OperationType;
30  import javax.wsdl.Output;
31  import javax.wsdl.PortType;
32  import javax.wsdl.WSDLException;
33  import javax.xml.namespace.QName;
34  
35  import org.apache.commons.logging.Log;
36  import org.apache.commons.logging.LogFactory;
37  
38  import org.springframework.util.Assert;
39  import org.springframework.util.StringUtils;
40  
41  /**
42   * Abstract base class for {@link PortTypesProvider} implementations.
43   *
44   * @author Arjen Poutsma
45   * @since 1.5.0
46   */
47  public abstract class AbstractPortTypesProvider implements PortTypesProvider {
48  
49      /** Logger available to subclasses. */
50      protected final Log logger = LogFactory.getLog(getClass());
51  
52      private String portTypeName;
53  
54      /** Returns the port type name used for this definition. */
55      public String getPortTypeName() {
56          return portTypeName;
57      }
58  
59      /** Sets the port type name used for this definition. Required. */
60      public void setPortTypeName(String portTypeName) {
61          this.portTypeName = portTypeName;
62      }
63  
64      /**
65       * Creates a single {@link PortType}, and calls {@link #populatePortType(Definition, PortType)} with it.
66       *
67       * @param definition the WSDL4J <code>Definition</code>
68       * @throws WSDLException in case of errors
69       */
70      public void addPortTypes(Definition definition) throws WSDLException {
71          Assert.notNull(getPortTypeName(), "'portTypeName' is required");
72          PortType portType = definition.createPortType();
73          populatePortType(definition, portType);
74          createOperations(definition, portType);
75          portType.setUndefined(false);
76          definition.addPortType(portType);
77      }
78  
79      /**
80       * Called after the {@link PortType} has been created.
81       * <p/>
82       * Default implementation sets the name of the port type to the defined value.
83       *
84       * @param portType the WSDL4J <code>PortType</code>
85       * @throws WSDLException in case of errors
86       * @see #setPortTypeName(String)
87       */
88      protected void populatePortType(Definition definition, PortType portType) throws WSDLException {
89          QName portTypeName = new QName(definition.getTargetNamespace(), getPortTypeName());
90          if (logger.isDebugEnabled()) {
91              logger.debug("Creating port type [" + portTypeName + "]");
92          }
93          portType.setQName(portTypeName);
94      }
95  
96      private void createOperations(Definition definition, PortType portType) throws WSDLException {
97          Map operations = new HashMap();
98          for (Iterator iterator = definition.getMessages().values().iterator(); iterator.hasNext();) {
99              Message message = (Message) iterator.next();
100             String operationName = getOperationName(message);
101             if (StringUtils.hasText(operationName)) {
102                 List messages = (List) operations.get(operationName);
103                 if (messages == null) {
104                     messages = new ArrayList();
105                     operations.put(operationName, messages);
106                 }
107                 messages.add(message);
108             }
109         }
110         if (operations.isEmpty() && logger.isWarnEnabled()) {
111             logger.warn("No operations were created, make sure the WSDL contains messages");
112         }
113         for (Iterator iterator = operations.keySet().iterator(); iterator.hasNext();) {
114             String operationName = (String) iterator.next();
115             Operation operation = definition.createOperation();
116             operation.setName(operationName);
117             List messages = (List) operations.get(operationName);
118             for (Iterator messagesIterator = messages.iterator(); messagesIterator.hasNext();) {
119                 Message message = (Message) messagesIterator.next();
120                 if (isInputMessage(message)) {
121                     Input input = definition.createInput();
122                     input.setMessage(message);
123                     populateInput(definition, input);
124                     operation.setInput(input);
125                 }
126                 else if (isOutputMessage(message)) {
127                     Output output = definition.createOutput();
128                     output.setMessage(message);
129                     populateOutput(definition, output);
130                     operation.setOutput(output);
131                 }
132                 else if (isFaultMessage(message)) {
133                     Fault fault = definition.createFault();
134                     fault.setMessage(message);
135                     populateFault(definition, fault);
136                     operation.addFault(fault);
137                 }
138             }
139             operation.setStyle(getOperationType(operation));
140             operation.setUndefined(false);
141             if (logger.isDebugEnabled()) {
142                 logger.debug(
143                         "Adding operation [" + operation.getName() + "] to port type [" + portType.getQName() + "]");
144             }
145             portType.addOperation(operation);
146         }
147     }
148 
149     /**
150      * Template method that returns the name of the operation coupled to the given {@link Message}. Subclasses can
151      * return <code>null</code> to indicate that a message should not be coupled to an operation.
152      *
153      * @param message the WSDL4J <code>Message</code>
154      * @return the operation name; or <code>null</code>
155      */
156     protected abstract String getOperationName(Message message);
157 
158     /**
159      * Indicates whether the given name name should be included as {@link Input} message in the definition.
160      *
161      * @param message the message
162      * @return <code>true</code> if to be included as input; <code>false</code> otherwise
163      */
164     protected abstract boolean isInputMessage(Message message);
165 
166     /**
167      * Called after the {@link javax.wsdl.Input} has been created, but it's added to the operation. Subclasses can
168      * override this method to define the input name.
169      * <p/>
170      * Default implementation sets the input name to the message name.
171      *
172      * @param definition the WSDL4J <code>Definition</code>
173      * @param input      the WSDL4J <code>Input</code>
174      */
175     protected void populateInput(Definition definition, Input input) {
176         input.setName(input.getMessage().getQName().getLocalPart());
177     }
178 
179     /**
180      * Indicates whether the given name name should be included as {@link Output} message in the definition.
181      *
182      * @param message the message
183      * @return <code>true</code> if to be included as output; <code>false</code> otherwise
184      */
185     protected abstract boolean isOutputMessage(Message message);
186 
187     /**
188      * Called after the {@link javax.wsdl.Output} has been created, but it's added to the operation. Subclasses can
189      * override this method to define the output name.
190      * <p/>
191      * Default implementation sets the output name to the message name.
192      *
193      * @param definition the WSDL4J <code>Definition</code>
194      * @param output     the WSDL4J <code>Output</code>
195      */
196     protected void populateOutput(Definition definition, Output output) {
197         output.setName(output.getMessage().getQName().getLocalPart());
198     }
199 
200     /**
201      * Indicates whether the given name name should be included as {@link Fault} message in the definition.
202      *
203      * @param message the message
204      * @return <code>true</code> if to be included as fault; <code>false</code> otherwise
205      */
206     protected abstract boolean isFaultMessage(Message message);
207 
208     /**
209      * Called after the {@link javax.wsdl.Fault} has been created, but it's added to the operation. Subclasses can
210      * override this method to define the fault name.
211      * <p/>
212      * Default implementation sets the fault name to the message name.
213      *
214      * @param definition the WSDL4J <code>Definition</code>
215      * @param fault      the WSDL4J <code>Fault</code>
216      */
217     protected void populateFault(Definition definition, Fault fault) {
218         fault.setName(fault.getMessage().getQName().getLocalPart());
219     }
220 
221     /**
222      * Returns the {@link OperationType} for the given operation.
223      * <p/>
224      * Default implementation returns {@link OperationType#REQUEST_RESPONSE} if both input and output are set; {@link
225      * OperationType#ONE_WAY} if only input is set, or {@link OperationType#NOTIFICATION} if only output is set.
226      *
227      * @param operation the WSDL4J <code>Operation</code>
228      * @return the operation type for the operation
229      */
230     protected OperationType getOperationType(Operation operation) {
231         if (operation.getInput() != null && operation.getOutput() != null) {
232             return OperationType.REQUEST_RESPONSE;
233         }
234         else if (operation.getInput() != null && operation.getOutput() == null) {
235             return OperationType.ONE_WAY;
236         }
237         else if (operation.getInput() == null && operation.getOutput() != null) {
238             return OperationType.NOTIFICATION;
239         }
240         else {
241             return null;
242         }
243     }
244 
245 
246 }
247 
248 
249