1 package org.andromda.cartridges.webservice.metafacades;
2
3 import java.util.Collection;
4 import java.util.HashMap;
5 import java.util.Iterator;
6 import java.util.Map;
7 import org.andromda.cartridges.webservice.WebServiceGlobals;
8 import org.andromda.cartridges.webservice.WebServiceUtils;
9 import org.andromda.core.metafacade.MetafacadeBase;
10 import org.andromda.core.metafacade.ModelValidationMessage;
11 import org.andromda.metafacades.uml.MetafacadeUtils;
12 import org.andromda.metafacades.uml.ModelElementFacade;
13 import org.andromda.metafacades.uml.ParameterFacade;
14 import org.andromda.metafacades.uml.Service;
15 import org.andromda.metafacades.uml.UMLProfile;
16 import org.andromda.translation.ocl.validation.OCLExpressions;
17 import org.andromda.translation.ocl.validation.OCLIntrospector;
18 import org.apache.commons.lang.StringUtils;
19 import org.apache.log4j.Logger;
20
21
22
23
24
25
26
27 public class WebServiceOperationLogicImpl
28 extends WebServiceOperationLogic
29 {
30 private static final long serialVersionUID = 34L;
31
32
33
34
35 public WebServiceOperationLogicImpl(
36 Object metaObject,
37 String context)
38 {
39 super(metaObject, context);
40 }
41
42
43
44
45 private static final Logger logger = Logger.getLogger(WebServiceOperationLogicImpl.class);
46
47
48
49
50
51 protected boolean handleIsExposed()
52 {
53
54 boolean visibility = this.getVisibility().equals("public") || this.getVisibility().equals("protected");
55 return visibility && (this.getOwner().hasStereotype(UMLProfile.STEREOTYPE_WEBSERVICE) ||
56 this.hasStereotype(UMLProfile.STEREOTYPE_WEBSERVICE_OPERATION));
57 }
58
59
60
61
62 private static final String TEST_IMPLEMENTATION_OPERATION_NAME_PREFIX =
63 "testImplementationOperationNamePrefix";
64
65
66
67
68 private String getTestImplementationOperationNamePrefix()
69 {
70 return String.valueOf(
71 this.getConfiguredProperty(TEST_IMPLEMENTATION_OPERATION_NAME_PREFIX));
72 }
73
74
75
76
77
78 protected String handleGetTestImplementationName()
79 {
80 return this.getTestImplementationOperationNamePrefix() +
81 StringUtils.capitalize(this.getTestName());
82 }
83
84
85
86
87
88 protected String handleGetTestImplementationCall()
89 {
90 return "this." + this.getTestImplementationSignature();
91 }
92
93
94
95
96
97 protected String handleGetTestImplementationSignature()
98 {
99 return this.getTestImplementationOperationNamePrefix() +
100 StringUtils.capitalize(this.getTestSignature());
101 }
102
103
104
105
106
107
108 protected String handleGetSignature(final boolean withArgumentNames)
109 {
110 Collection<ParameterFacade> arguments = this.getArguments();
111 String signature = MetafacadeUtils.getSignature(
112 this.getName(),
113 arguments,
114 withArgumentNames,
115 null);
116 Service service = this.getService();
117 if (this.hasStereotype("WSCustomHeader") || this.getService().hasStereotype("WSCustomHeader"))
118 {
119 String serviceElementName = (String) service.findTaggedValue("andromda_wsdl_header_element");
120 String serviceNamespace = (String) service.findTaggedValue("andromda_header_namespace");
121 String serviceClassName = WebServiceUtils.getPackageName(serviceNamespace) + '.' + serviceElementName;
122 String serviceParameterName = StringUtils.uncapitalize(serviceElementName);
123 signature = signature.substring(0, signature.length()-1);
124 if (!arguments.isEmpty())
125 {
126 signature += ", ";
127 }
128 signature += serviceClassName;
129 if (withArgumentNames)
130 {
131 signature += " " + serviceParameterName;
132 }
133 signature += ')';
134 }
135 if (this.hasStereotype("WSSecurity") || this.getService().hasStereotype("WSSecurity"))
136 {
137 String securityElementName = (String) service.findTaggedValue("andromda_wsdl_security_element");
138 String securityNamespace = (String) service.findTaggedValue("andromda_security_namespace");
139 String securityClassName = WebServiceUtils.getPackageName(securityNamespace) + '.' + securityElementName;
140 String securityParameterName = StringUtils.uncapitalize(securityElementName);
141 signature = signature.substring(0, signature.length()-1);
142 if (!arguments.isEmpty() || this.hasStereotype("WSCustomHeader") || this.getService().hasStereotype("WSCustomHeader"))
143 {
144 signature += ", ";
145 }
146 signature += securityClassName;
147 if (withArgumentNames)
148 {
149 signature += " " + securityParameterName;
150 }
151 signature += ')';
152 }
153 return signature;
154 }
155
156
157
158
159 private static final String TEST_NAME_PREFIX = "test";
160
161
162
163
164
165 protected String handleGetTestName()
166 {
167 return TEST_NAME_PREFIX + StringUtils.capitalize(this.getName());
168 }
169
170
171
172
173
174 protected String handleGetTestCall()
175 {
176 return "this." + this.getSignature();
177 }
178
179
180
181
182
183 protected String handleGetTestSignature()
184 {
185 return this.getTestName() + "()";
186 }
187
188
189
190
191 private static final String PROPERTY_DEFAULT_PARAMETER_STYLE = "defaultParameterStyle";
192 private static final String DEFAULT = "default";
193 private static final String EMPTY_STRING = "";
194 private static final String BOOLEAN_FALSE = "false";
195
196
197
198
199 @Override
200 protected String handleGetParameterStyle()
201 {
202 String style = (String)this.findTaggedValue(WebServiceGlobals.WEB_SERVICE_PARAMETER_STYLE);
203 if (StringUtils.isEmpty(style) || style.equals(DEFAULT))
204 {
205 style = String.valueOf(this.getConfiguredProperty(PROPERTY_DEFAULT_PARAMETER_STYLE));
206 }
207 if (StringUtils.isEmpty(style) || style.equals(DEFAULT))
208 {
209 style = "wrapped";
210 }
211 return style;
212 }
213
214
215
216 @Override
217 protected String handleGetRestCacheType()
218 {
219 String cacheType = (String)this.findTaggedValue(WebServiceGlobals.CACHE_TYPE);
220 if (!this.isRest() || StringUtils.isBlank(cacheType) || cacheType.equals(DEFAULT))
221 {
222 cacheType = EMPTY_STRING;
223 }
224 return cacheType;
225 }
226
227
228
229
230 @Override
231 protected String handleGetRestConsumes()
232 {
233 String consumes = (String)this.findTaggedValue(WebServiceGlobals.REST_CONSUMES);
234 if (!this.isRest() || StringUtils.isBlank(consumes) || consumes.equals(DEFAULT))
235 {
236 consumes = EMPTY_STRING;
237 }
238 else
239 {
240 consumes = translateMediaType(consumes);
241 }
242 return consumes;
243 }
244
245
246
247
248 @Override
249 protected String handleGetRestPartType()
250 {
251 String partType = (String)this.findTaggedValue(WebServiceGlobals.REST_PART_TYPE);
252 if (!this.isRest() || StringUtils.isBlank(partType) || partType.equals(DEFAULT))
253 {
254 partType = EMPTY_STRING;
255 }
256 return partType;
257 }
258
259 private static final String SLASH = "/";
260 private static final String QUOTE = "\"";
261 private static final String LBRACKET = "{";
262 private static final String RBRACKET = "}";
263
264
265
266
267 @Override
268 protected String handleGetRestPath()
269 {
270 String path = (String)this.findTaggedValue(WebServiceGlobals.REST_PATH);
271 StringBuilder pathBuffer = new StringBuilder();
272 if (!this.isRest() || StringUtils.isBlank(path) || path.equals(DEFAULT))
273 {
274 pathBuffer.append(QUOTE).append(SLASH).append(this.getName().toLowerCase()).append(SLASH);
275
276 Iterator<ParameterFacade> parameters = this.getArguments().iterator();
277 while (parameters.hasNext())
278 {
279 ParameterFacade param = parameters.next();
280
281
282 String paramName = param.getName();
283 pathBuffer.append(paramName).append(SLASH).append(LBRACKET).append(paramName).append(RBRACKET).append(SLASH);
284
285 }
286 pathBuffer.append(QUOTE);
287 }
288 else
289 {
290 if (StringUtils.isBlank(path))
291 {
292 path = EMPTY_STRING;
293 }
294 pathBuffer.append(path);
295 if (!path.startsWith(QUOTE))
296 {
297 pathBuffer.insert(0, QUOTE);
298 }
299 if (!path.endsWith(QUOTE) || path.length()<2)
300 {
301 pathBuffer.append(QUOTE);
302 }
303 }
304 return pathBuffer.toString();
305 }
306
307
308
309
310
311
312 @Override
313 protected String handleGetRestTestPath()
314 {
315 String path = (String)this.findTaggedValue(WebServiceGlobals.REST_PATH);
316 StringBuilder pathBuffer = new StringBuilder();
317 WebServiceLogic service = (WebServiceLogic)this.getService();
318 String servicePath = service.getRestPath();
319 WebServiceUtils wsutils = new WebServiceUtils();
320 if (!this.isRest() || StringUtils.isBlank(path) || path.equals(DEFAULT))
321 {
322 pathBuffer.append(SLASH).append(this.getName().toLowerCase()).append(SLASH);
323 Iterator<ParameterFacade> parameters = this.getArguments().iterator();
324 while (parameters.hasNext())
325 {
326 ParameterFacade param = parameters.next();
327
328 if (WebServiceUtils.isSimpleType(param))
329 {
330 String paramValue = wsutils.createConstructor(param);
331
332 if (paramValue.indexOf('(') > 0)
333 {
334 paramValue = paramValue.substring(paramValue.indexOf('(')+1, paramValue.indexOf(')'));
335 }
336 pathBuffer.append(param.getName()).append(SLASH).append(paramValue).append(SLASH);
337 }
338 }
339 path = pathBuffer.toString();
340 }
341 else
342 {
343 if (StringUtils.isBlank(path))
344 {
345 path = EMPTY_STRING;
346 }
347
348 path = pathBuffer.append(path).toString();
349 Iterator<ParameterFacade> parameters = this.getArguments().iterator();
350 while (parameters.hasNext())
351 {
352 ParameterFacade param = parameters.next();
353 if (WebServiceUtils.isSimpleType(param))
354 {
355 String paramValue = wsutils.createConstructor(param).replace("\"", "");
356 if (paramValue.indexOf('(') > 0)
357 {
358 paramValue = paramValue.substring(paramValue.indexOf('(')+1, paramValue.indexOf(')'));
359 }
360 path = StringUtils.replace(path, LBRACKET + param.getName() + RBRACKET, paramValue);
361 }
362
363 }
364 }
365 path = servicePath + path;
366 path = path.replaceAll("\"", "");
367 path = path.replaceAll("//", "/");
368 return path;
369 }
370
371
372
373
374 @Override
375 protected String handleGetRestProduces()
376 {
377 String produces = (String)this.findTaggedValue(WebServiceGlobals.REST_PRODUCES);
378
379 if (!this.isRest() || produces == DEFAULT)
380 {
381
382 produces = (String)this.getOwner().findTaggedValue(WebServiceGlobals.REST_PRODUCES);
383 if (produces == DEFAULT)
384 {
385
386 if (WebServiceUtils.isSimpleType(this.getReturnType()))
387 {
388 produces = "text/plain";
389 }
390 else
391 {
392 produces = "application/xml";
393 }
394 }
395 }
396 else
397 {
398 produces = translateMediaType(produces);
399 }
400 return produces;
401 }
402
403
404
405
406 private static Map<String, String> getMediaTranslation()
407 {
408 final Map<String, String> mediaMap = new HashMap<String, String>();
409 mediaMap.put("default", QUOTE + "application/xml" + QUOTE);
410 mediaMap.put("ApplicationAtom", QUOTE + "application/atom+xml" + QUOTE);
411 mediaMap.put("ApplicationAtomEntry", QUOTE + "application/atom+xml;type=entry" + QUOTE);
412 mediaMap.put("ApplicationAtomXML", QUOTE + "application/atom+xml" + QUOTE);
413 mediaMap.put("ApplicationFastinfoset", QUOTE + "application/fastinfoset" + QUOTE);
414 mediaMap.put("ApplicationFormURLEncoded", QUOTE + "application/x-www-form-urlencoded" + QUOTE);
415 mediaMap.put("ApplicationJSON", QUOTE + "application/json" + QUOTE);
416 mediaMap.put("ApplicationOctetStream", QUOTE + "application/octet-stream" + QUOTE);
417 mediaMap.put("ApplicationSvgXML", QUOTE + "application/svg+xml" + QUOTE);
418 mediaMap.put("ApplicationXhtmlXML", QUOTE + "application/xhtml+xml" + QUOTE);
419 mediaMap.put("ApplicationXML", QUOTE + "application/xml" + QUOTE);
420 mediaMap.put("ApplicationXMLAll", QUOTE + "application/*+xml" + QUOTE);
421 mediaMap.put("ApplicationYaml", QUOTE + "application/yaml" + QUOTE);
422 mediaMap.put("MultipartAlternative", QUOTE + "multipart/alternative" + QUOTE);
423 mediaMap.put("MultipartFixed", QUOTE + "multipart/fixed" + QUOTE);
424 mediaMap.put("MultipartFormData", QUOTE + "multipart/form-data" + QUOTE);
425 mediaMap.put("MultipartMixed", QUOTE + "multipart/mixed" + QUOTE);
426 mediaMap.put("MultipartRelated", QUOTE + "multipart/related" + QUOTE);
427 mediaMap.put("TextPlain", QUOTE + "text/plain" + QUOTE);
428 mediaMap.put("TextXML", QUOTE + "text/xml" + QUOTE);
429 mediaMap.put("TextXYaml", QUOTE + "text/xyaml" + QUOTE);
430 mediaMap.put("TextYaml", QUOTE + "text/xml" + QUOTE);
431 mediaMap.put("Wildcard", QUOTE + "*/*" + QUOTE);
432 return mediaMap;
433 }
434
435
436
437
438
439
440 public static String translateMediaType(String input)
441 {
442 String output = null;
443 if (StringUtils.isBlank(input) || input.equals(DEFAULT) || !getMediaTranslation().containsKey(input))
444 {
445 output = getMediaTranslation().get(DEFAULT);
446 }
447 else
448 {
449 output = getMediaTranslation().get(input);
450 }
451 return output;
452 }
453
454
455
456
457 @Override
458 protected String handleGetRestProvider()
459 {
460 String provider = (String)this.findTaggedValue(WebServiceGlobals.REST_PROVIDER);
461 if (!this.isRest() || StringUtils.isBlank(provider) || provider.equals(DEFAULT))
462 {
463 provider = EMPTY_STRING;
464 }
465 return provider;
466 }
467
468 private static final String GET = "@javax.ws.rs.GET";
469 private static final String AT = "@javax.ws.rs.";
470
471
472
473 @Override
474 protected String handleGetRestRequestType()
475 {
476 String requestType = (String)this.findTaggedValue(WebServiceGlobals.REST_REQUEST_TYPE);
477 if (!this.isRest() || StringUtils.isBlank(requestType) || requestType.equals(DEFAULT))
478 {
479 requestType = GET;
480 }
481 else if (!requestType.startsWith(AT))
482 {
483 requestType = AT + requestType;
484 }
485 return requestType;
486 }
487
488
489
490
491 @Override
492 protected int handleGetRestSuspend()
493 {
494 String suspend = (String)this.findTaggedValue(WebServiceGlobals.REST_SUSPEND);
495 if (!this.isRest() || StringUtils.isBlank(suspend) || suspend.equals(DEFAULT) || !StringUtils.isNumeric(suspend))
496 {
497 return 0;
498 }
499 return Integer.parseInt(suspend);
500 }
501
502
503
504
505 @Override
506 protected String handleGetRolesAllowed()
507 {
508 String rolesAllowed = (String)this.findTaggedValue(WebServiceGlobals.REST_ROLES_ALLOWED);
509 if (!this.isRest() || StringUtils.isBlank(rolesAllowed) || rolesAllowed.equals(DEFAULT))
510 {
511 rolesAllowed = EMPTY_STRING;
512 }
513 return rolesAllowed;
514 }
515
516
517
518
519 @Override
520 protected boolean handleIsRest()
521 {
522 String rest = (String)this.findTaggedValue(WebServiceGlobals.REST);
523 if (StringUtils.isBlank(rest) || rest.equals(DEFAULT))
524 {
525 rest = (String)this.getOwner().findTaggedValue(WebServiceGlobals.REST);
526 if (StringUtils.isBlank(rest) || rest.equals(DEFAULT))
527 {
528 rest = BOOLEAN_FALSE;
529 }
530 }
531 return Boolean.valueOf(rest);
532 }
533
534
535
536
537 @Override
538 protected boolean handleIsRestEncoded()
539 {
540 String restEncoded = (String)this.findTaggedValue(WebServiceGlobals.REST_ENCODED);
541 if (!this.isRest() || StringUtils.isBlank(restEncoded) || restEncoded.equals(DEFAULT))
542 {
543 restEncoded = BOOLEAN_FALSE;
544 }
545 return Boolean.valueOf(restEncoded);
546 }
547
548
549
550
551 @Override
552 protected boolean handleIsRestAtom()
553 {
554 WebServiceLogic service = (WebServiceLogic)this.getService();
555 boolean rest = this.isRest();
556 boolean restAtom = false;
557 if (rest)
558 {
559 restAtom = this.getRestProduces().contains("atom");
560 if (!restAtom)
561 {
562 restAtom = service.getRestProduces().indexOf("atom") > -1;
563 }
564 }
565 return restAtom;
566 }
567
568
569
570
571
572 @Override
573 protected String handleGetOperationName()
574 {
575 String serviceName = (String)this.findTaggedValue(WebServiceGlobals.WEB_SERVICE_NAME);
576 if (StringUtils.isBlank(serviceName))
577 {
578 serviceName = this.getName();
579 }
580 return serviceName;
581 }
582
583
584
585
586 @Override
587 protected boolean handleIsWebFaultOnAllExceptions()
588 {
589 boolean result = true;
590 String webserviceStack = String.valueOf(this.getConfiguredProperty("webserviceStack"));
591 if (webserviceStack.equals("cxf") || webserviceStack.equals("jaxws"))
592 {
593 Collection<ModelElementFacade> exceptions = this.getExceptions();
594 for (ModelElementFacade exception : exceptions)
595 {
596
597 if (!exception.hasStereotype(UMLProfile.STEREOTYPE_WEB_FAULT))
598 {
599 result = false;
600 logger.warn(exception.getFullyQualifiedName() + " WebFault stereotype missing from operation exception thrown by " + this.getFullyQualifiedName());
601 }
602 }
603 }
604 return result;
605 }
606
607
608
609
610 @Override
611 protected ModelElementFacade handleGetWebServicePackage()
612 {
613 return this.getOwner().getPackage();
614 }
615
616
617
618
619
620
621
622 @Override
623 public void validateInvariants(Collection<ModelValidationMessage> validationMessages)
624 {
625 super.validateInvariants(validationMessages);
626 try
627 {
628 final Object contextElement = this.THIS();
629 final String name = (String)OCLIntrospector.invoke(contextElement,"name");
630 boolean constraintValid = OCLExpressions.equal(
631 name.substring(0,1).toLowerCase(),
632 name.substring(0,1));
633 if (!constraintValid)
634 {
635 validationMessages.add(
636 new ModelValidationMessage(
637 (MetafacadeBase)contextElement ,
638 "org::andromda::cartridges::webservice::metafacades::WebServiceOperation::operation must start with a lowercase letter",
639 "Operation name must start with a lowercase letter."));
640 }
641 }
642 catch (Throwable th)
643 {
644 Throwable cause = th.getCause();
645 int depth = 0;
646 while (cause != null && depth < 7)
647 {
648 th = cause;
649 depth++;
650 }
651 logger.error("Error validating constraint 'org::andromda::cartridges::webservice::WebServicePackage::operation must start with a lowercase letter' ON "
652 + this.THIS().toString() + ": " + th.getMessage(), th);
653 }
654 }
655 }