1
2
3
4
5
6
7
8
9
10
11
12
13 package com.eviware.soapui.impl.rest;
14
15 import java.util.ArrayList;
16 import java.util.Collections;
17 import java.util.HashMap;
18 import java.util.List;
19 import java.util.Map;
20
21 import org.apache.xmlbeans.XmlException;
22 import org.apache.xmlbeans.XmlObject;
23 import org.apache.xmlbeans.XmlOptions;
24 import org.w3c.dom.Element;
25 import org.w3c.dom.NamedNodeMap;
26 import org.w3c.dom.NodeList;
27
28 import com.eviware.soapui.impl.rest.panels.request.inspectors.schema.InferredSchemaManager;
29 import com.eviware.soapui.impl.rest.support.RestParamProperty;
30 import com.eviware.soapui.impl.rest.support.RestParamsPropertyHolder;
31 import com.eviware.soapui.impl.wsdl.support.Constants;
32 import com.eviware.soapui.model.ModelItem;
33 import com.eviware.soapui.support.StringUtils;
34 import com.eviware.soapui.support.types.StringToStringMap;
35
36 import net.java.dev.wadl.x2009.x02.ApplicationDocument;
37 import net.java.dev.wadl.x2009.x02.ParamStyle;
38 import net.java.dev.wadl.x2009.x02.ApplicationDocument.Application;
39 import net.java.dev.wadl.x2009.x02.DocDocument.Doc;
40 import net.java.dev.wadl.x2009.x02.GrammarsDocument.Grammars;
41 import net.java.dev.wadl.x2009.x02.MethodDocument.Method;
42 import net.java.dev.wadl.x2009.x02.ParamDocument.Param;
43 import net.java.dev.wadl.x2009.x02.RepresentationDocument.Representation;
44 import net.java.dev.wadl.x2009.x02.RequestDocument.Request;
45 import net.java.dev.wadl.x2009.x02.ResourceDocument.Resource;
46 import net.java.dev.wadl.x2009.x02.ResourcesDocument.Resources;
47 import net.java.dev.wadl.x2009.x02.ResponseDocument.Response;
48
49 public class WadlGenerator
50 {
51 private RestService restService;
52
53 private boolean isWADL11 = true;
54
55 public WadlGenerator( RestService restService )
56 {
57 this.restService = restService;
58 }
59
60 public XmlObject generateWadl()
61 {
62 ApplicationDocument applicationDocument = ApplicationDocument.Factory.newInstance();
63 Application application = applicationDocument.addNewApplication();
64
65 createDoc( application.addNewDoc(), restService );
66
67 Resources resources = application.addNewResources();
68
69
70 String basePath = restService.getBasePath();
71 String[] endpoints = restService.getEndpoints();
72 if( endpoints.length > 0 )
73 basePath = endpoints[0] + basePath;
74
75 resources.setBase( basePath );
76
77 for( int c = 0; c < restService.getOperationCount(); c++ )
78 {
79 resources.addNewResource().set( generateWadlResource( restService.getOperationAt( c ) ) );
80 }
81
82 String[] namespaces = InferredSchemaManager.getInferredSchema( restService ).getNamespaces();
83 if( namespaces.length > 0 )
84 {
85 Grammars grammars = application.addNewGrammars();
86 for( String namespace : namespaces )
87 {
88 grammars.addNewInclude().setHref( InferredSchemaManager.filenameForNamespace( namespace ) );
89 }
90 }
91
92 if(!isWADL11)
93 {
94 XmlOptions options = new XmlOptions();
95 StringToStringMap subst = new StringToStringMap();
96 subst.put( Constants.WADL11_NS, Constants.WADL10_NS );
97 options.setLoadSubstituteNamespaces( subst );
98 try
99 {
100 return XmlObject.Factory.parse( applicationDocument.xmlText(), options );
101 }
102 catch( XmlException e )
103 {
104 e.printStackTrace();
105 }
106 }
107
108 return applicationDocument;
109 }
110
111 private XmlObject generateWadlResource( RestResource resource )
112 {
113 Resource resourceConfig = Resource.Factory.newInstance();
114 createDoc( resourceConfig.addNewDoc(), resource );
115 String path = resource.getPath();
116 if( path.startsWith( "/" ) )
117 path = path.length() > 1 ? path.substring( 1 ) : "";
118
119 resourceConfig.setPath( path );
120 resourceConfig.setId( resource.getName() );
121
122 RestParamsPropertyHolder params = resource.getParams();
123 for( int c = 0; c < params.size(); c++ )
124 {
125 generateParam( resourceConfig.addNewParam(), params.getPropertyAt( c ) );
126 }
127
128 for( int c = 0; c < resource.getChildResourceCount(); c++ )
129 {
130 resourceConfig.addNewResource().set( generateWadlResource( resource.getChildResourceAt( c ) ) );
131 }
132
133 for( int c = 0; c < resource.getRestMethodCount(); c++ )
134 {
135 RestMethod restMethod = resource.getRestMethodAt( c );
136 generateWadlMethod( resourceConfig, restMethod );
137 }
138
139 return resourceConfig;
140 }
141
142 private void generateParam( Param paramConfig, RestParamProperty param )
143 {
144 paramConfig.setName( param.getName() );
145
146 if( StringUtils.hasContent( param.getDefaultValue() ) )
147 paramConfig.setDefault( param.getDefaultValue() );
148
149 paramConfig.setType( param.getType() );
150 paramConfig.setRequired( param.getRequired() );
151 paramConfig.setDefault( param.getDefaultValue() );
152
153 if( StringUtils.hasContent( param.getDescription() ) )
154 createDoc( paramConfig.addNewDoc(), param.getName() + " Parameter", param.getDescription() );
155
156 String[] options = param.getOptions();
157 for( String option : options )
158 paramConfig.addNewOption().setValue( option );
159
160 ParamStyle.Enum style = ParamStyle.QUERY;
161 switch( param.getStyle() )
162 {
163 case HEADER :
164 style = ParamStyle.HEADER;
165 break;
166 case MATRIX :
167 style = ParamStyle.MATRIX;
168 break;
169 case PLAIN :
170 style = ParamStyle.PLAIN;
171 break;
172 case TEMPLATE :
173 style = ParamStyle.TEMPLATE;
174 break;
175 }
176
177 paramConfig.setStyle( style );
178 }
179
180 private void createDoc( Doc docConfig, ModelItem modelItem )
181 {
182 createDoc( docConfig, modelItem.getName(), modelItem.getDescription() );
183 }
184
185 private void createDoc( Doc docConfig, String name, String description )
186 {
187 docConfig.setLang( "en" );
188 docConfig.setTitle( name );
189 docConfig.getDomNode().appendChild( docConfig.getDomNode().getOwnerDocument().createTextNode( description ) );
190 }
191
192 private void generateWadlMethod( Resource resourceConfig, RestMethod restMethod )
193 {
194 Method methodConfig = resourceConfig.addNewMethod();
195 createDoc( methodConfig.addNewDoc(), restMethod );
196 methodConfig.setName( restMethod.getMethod().toString() );
197 methodConfig.setId( restMethod.getName() );
198 Request requestConfig = methodConfig.addNewRequest();
199
200 Map<String, RestParamProperty> defaultParams = new HashMap<String, RestParamProperty>();
201 for( RestParamProperty defaultParam : restMethod.getResource().getDefaultParams() )
202 defaultParams.put( defaultParam.getName(), defaultParam );
203
204 RestParamsPropertyHolder params = restMethod.getParams();
205 for( int c = 0; c < params.size(); c++ )
206 {
207 RestParamProperty param = params.getPropertyAt( c );
208 if( !defaultParams.containsKey( param.getName() ) || !param.equals( defaultParams.get( param.getName() ) ) )
209 generateParam( requestConfig.addNewParam(), param );
210 }
211
212 if( restMethod.hasRequestBody() )
213 {
214 for( RestRepresentation representation : restMethod.getRepresentations( RestRepresentation.Type.REQUEST, null ) )
215 {
216 generateRepresentation( requestConfig.addNewRepresentation(), representation );
217 }
218 }
219
220 Map<String,Response> responses = new HashMap<String, Response>();
221 if( !isWADL11 )
222 responses.put( null, methodConfig.addNewResponse() );
223 for( RestRepresentation representation : restMethod.getRepresentations() )
224 {
225 Response response;
226 if( isWADL11 )
227 {
228 List<Comparable> status = new ArrayList<Comparable>((List<Comparable>)representation.getStatus());
229 Collections.sort( status );
230 StringBuilder statusStrBuilder = new StringBuilder();
231 for(Object o : status)
232 statusStrBuilder.append( o ).append( " " );
233 String statusStr = statusStrBuilder.toString();
234
235 if(!responses.containsKey( statusStr ))
236 {
237 response = methodConfig.addNewResponse();
238 response.setStatus( status );
239 responses.put( statusStr, response );
240 }
241 else
242 {
243 response = responses.get( statusStr );
244 }
245 }
246 else
247 {
248 response = responses.get( null );
249 }
250
251 Representation representationConfig = response.addNewRepresentation();
252 generateRepresentation( representationConfig, representation );
253
254 if( !isWADL11 && representation.getType() == RestRepresentation.Type.FAULT )
255 {
256 Element resp = ( Element )response.getDomNode();
257 Element rep = ( Element )representationConfig.getDomNode();
258 Element fault = resp.getOwnerDocument().createElementNS( Constants.WADL11_NS, "fault" );
259
260 NamedNodeMap attributes = rep.getAttributes();
261 for( int i=0; i<attributes.getLength(); i++)
262 {
263 fault.setAttribute( attributes.item( i ).getNodeName(), attributes.item( i ).getNodeValue() );
264 }
265 NodeList children = rep.getChildNodes();
266 for( int i=0; i<children.getLength(); i++ )
267 {
268 fault.appendChild( children.item( i ) );
269 }
270
271 resp.appendChild( fault );
272 rep.getParentNode().removeChild( rep );
273 }
274 }
275 }
276
277 private void generateRepresentation( Representation representationConfig, RestRepresentation representation )
278 {
279 representationConfig.setMediaType( representation.getMediaType() );
280
281 if( StringUtils.hasContent( representation.getId() ) )
282 representationConfig.setId( representation.getId() );
283
284 if(!isWADL11)
285 {
286 List<?> status = representation.getStatus();
287 if( status != null && status.size() > 0 )
288 {
289 StringBuilder statusStr = new StringBuilder();
290 for( Object s : status )
291 statusStr.append( s ).append( " " );
292 ( ( Element )representationConfig.getDomNode() ).setAttribute( "status", statusStr.toString().trim() );
293 }
294 }
295
296 if( representation.getElement() != null )
297 representationConfig.setElement( representation.getElement() );
298 }
299
300 }