001/** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.camel.model.rest; 018 019import java.net.URISyntaxException; 020import java.util.ArrayList; 021import java.util.HashMap; 022import java.util.List; 023import java.util.Map; 024import javax.xml.bind.annotation.XmlAccessType; 025import javax.xml.bind.annotation.XmlAccessorType; 026import javax.xml.bind.annotation.XmlAttribute; 027import javax.xml.bind.annotation.XmlElementRef; 028import javax.xml.bind.annotation.XmlRootElement; 029 030import org.apache.camel.CamelContext; 031import org.apache.camel.model.OptionalIdentifiedDefinition; 032import org.apache.camel.model.ProcessorDefinition; 033import org.apache.camel.model.RouteDefinition; 034import org.apache.camel.model.ToDefinition; 035import org.apache.camel.model.ToDynamicDefinition; 036import org.apache.camel.spi.Metadata; 037import org.apache.camel.spi.RestConfiguration; 038import org.apache.camel.util.FileUtil; 039import org.apache.camel.util.ObjectHelper; 040import org.apache.camel.util.URISupport; 041 042/** 043 * Defines a rest service using the rest-dsl 044 */ 045@Metadata(label = "rest") 046@XmlRootElement(name = "rest") 047@XmlAccessorType(XmlAccessType.FIELD) 048public class RestDefinition extends OptionalIdentifiedDefinition<RestDefinition> { 049 050 @XmlAttribute 051 private String path; 052 053 @XmlAttribute 054 private String tag; 055 056 @XmlAttribute 057 private String consumes; 058 059 @XmlAttribute 060 private String produces; 061 062 @XmlAttribute @Metadata(defaultValue = "auto") 063 private RestBindingMode bindingMode; 064 065 @XmlAttribute 066 private Boolean skipBindingOnErrorCode; 067 068 @XmlAttribute 069 private Boolean enableCORS; 070 071 @XmlAttribute 072 private Boolean apiDocs; 073 074 @XmlElementRef 075 private List<VerbDefinition> verbs = new ArrayList<VerbDefinition>(); 076 077 @Override 078 public String getLabel() { 079 return "rest"; 080 } 081 082 public String getPath() { 083 return path; 084 } 085 086 /** 087 * Path of the rest service, such as "/foo" 088 */ 089 public void setPath(String path) { 090 this.path = path; 091 } 092 093 public String getTag() { 094 return tag; 095 } 096 097 /** 098 * To configure a special tag for the operations within this rest definition. 099 */ 100 public void setTag(String tag) { 101 this.tag = tag; 102 } 103 104 public String getConsumes() { 105 return consumes; 106 } 107 108 /** 109 * To define the content type what the REST service consumes (accept as input), such as application/xml or application/json. 110 * This option will override what may be configured on a parent level 111 */ 112 public void setConsumes(String consumes) { 113 this.consumes = consumes; 114 } 115 116 public String getProduces() { 117 return produces; 118 } 119 120 /** 121 * To define the content type what the REST service produces (uses for output), such as application/xml or application/json 122 * This option will override what may be configured on a parent level 123 */ 124 public void setProduces(String produces) { 125 this.produces = produces; 126 } 127 128 public RestBindingMode getBindingMode() { 129 return bindingMode; 130 } 131 132 /** 133 * Sets the binding mode to use. 134 * This option will override what may be configured on a parent level 135 * <p/> 136 * The default value is auto 137 */ 138 public void setBindingMode(RestBindingMode bindingMode) { 139 this.bindingMode = bindingMode; 140 } 141 142 public List<VerbDefinition> getVerbs() { 143 return verbs; 144 } 145 146 /** 147 * The HTTP verbs this REST service accepts and uses 148 */ 149 public void setVerbs(List<VerbDefinition> verbs) { 150 this.verbs = verbs; 151 } 152 153 public Boolean getSkipBindingOnErrorCode() { 154 return skipBindingOnErrorCode; 155 } 156 157 /** 158 * Whether to skip binding on output if there is a custom HTTP error code header. 159 * This allows to build custom error messages that do not bind to json / xml etc, as success messages otherwise will do. 160 * This option will override what may be configured on a parent level 161 */ 162 public void setSkipBindingOnErrorCode(Boolean skipBindingOnErrorCode) { 163 this.skipBindingOnErrorCode = skipBindingOnErrorCode; 164 } 165 166 public Boolean getEnableCORS() { 167 return enableCORS; 168 } 169 170 /** 171 * Whether to enable CORS headers in the HTTP response. 172 * This option will override what may be configured on a parent level 173 * <p/> 174 * The default value is false. 175 */ 176 public void setEnableCORS(Boolean enableCORS) { 177 this.enableCORS = enableCORS; 178 } 179 180 public Boolean getApiDocs() { 181 return apiDocs; 182 } 183 184 /** 185 * Whether to include or exclude the VerbDefinition in API documentation. 186 * This option will override what may be configured on a parent level 187 * <p/> 188 * The default value is true. 189 */ 190 public void setApiDocs(Boolean apiDocs) { 191 this.apiDocs = apiDocs; 192 } 193 194 // Fluent API 195 //------------------------------------------------------------------------- 196 197 /** 198 * To set the base path of this REST service 199 */ 200 public RestDefinition path(String path) { 201 setPath(path); 202 return this; 203 } 204 205 /** 206 * To set the tag to use of this REST service 207 */ 208 public RestDefinition tag(String tag) { 209 setTag(tag); 210 return this; 211 } 212 213 public RestDefinition get() { 214 return addVerb("get", null); 215 } 216 217 public RestDefinition get(String uri) { 218 return addVerb("get", uri); 219 } 220 221 public RestDefinition post() { 222 return addVerb("post", null); 223 } 224 225 public RestDefinition post(String uri) { 226 return addVerb("post", uri); 227 } 228 229 public RestDefinition put() { 230 return addVerb("put", null); 231 } 232 233 public RestDefinition put(String uri) { 234 return addVerb("put", uri); 235 } 236 237 public RestDefinition delete() { 238 return addVerb("delete", null); 239 } 240 241 public RestDefinition delete(String uri) { 242 return addVerb("delete", uri); 243 } 244 245 public RestDefinition head() { 246 return addVerb("head", null); 247 } 248 249 public RestDefinition head(String uri) { 250 return addVerb("head", uri); 251 } 252 253 public RestDefinition options() { 254 return addVerb("options", null); 255 } 256 257 public RestDefinition options(String uri) { 258 return addVerb("options", uri); 259 } 260 261 public RestDefinition verb(String verb) { 262 return addVerb(verb, null); 263 } 264 265 public RestDefinition verb(String verb, String uri) { 266 return addVerb(verb, uri); 267 } 268 269 @Override 270 public RestDefinition id(String id) { 271 if (getVerbs().isEmpty()) { 272 super.id(id); 273 } else { 274 // add on last verb as that is how the Java DSL works 275 VerbDefinition verb = getVerbs().get(getVerbs().size() - 1); 276 verb.id(id); 277 } 278 279 return this; 280 } 281 282 @Override 283 public RestDefinition description(String text) { 284 if (getVerbs().isEmpty()) { 285 super.description(text); 286 } else { 287 // add on last verb as that is how the Java DSL works 288 VerbDefinition verb = getVerbs().get(getVerbs().size() - 1); 289 verb.description(text); 290 } 291 292 return this; 293 } 294 295 @Override 296 public RestDefinition description(String id, String text, String lang) { 297 if (getVerbs().isEmpty()) { 298 super.description(id, text, lang); 299 } else { 300 // add on last verb as that is how the Java DSL works 301 VerbDefinition verb = getVerbs().get(getVerbs().size() - 1); 302 verb.description(id, text, lang); 303 } 304 305 return this; 306 } 307 308 public RestDefinition consumes(String mediaType) { 309 if (getVerbs().isEmpty()) { 310 this.consumes = mediaType; 311 } else { 312 // add on last verb as that is how the Java DSL works 313 VerbDefinition verb = getVerbs().get(getVerbs().size() - 1); 314 verb.setConsumes(mediaType); 315 } 316 317 return this; 318 } 319 320 public RestOperationParamDefinition param() { 321 if (getVerbs().isEmpty()) { 322 throw new IllegalArgumentException("Must add verb first, such as get/post/delete"); 323 } 324 VerbDefinition verb = getVerbs().get(getVerbs().size() - 1); 325 return param(verb); 326 } 327 328 public RestDefinition param(RestOperationParamDefinition param) { 329 if (getVerbs().isEmpty()) { 330 throw new IllegalArgumentException("Must add verb first, such as get/post/delete"); 331 } 332 VerbDefinition verb = getVerbs().get(getVerbs().size() - 1); 333 verb.getParams().add(param); 334 return this; 335 } 336 337 public RestDefinition params(List<RestOperationParamDefinition> params) { 338 if (getVerbs().isEmpty()) { 339 throw new IllegalArgumentException("Must add verb first, such as get/post/delete"); 340 } 341 VerbDefinition verb = getVerbs().get(getVerbs().size() - 1); 342 verb.getParams().addAll(params); 343 return this; 344 } 345 346 public RestOperationParamDefinition param(VerbDefinition verb) { 347 return new RestOperationParamDefinition(verb); 348 } 349 350 public RestDefinition responseMessage(RestOperationResponseMsgDefinition msg) { 351 if (getVerbs().isEmpty()) { 352 throw new IllegalArgumentException("Must add verb first, such as get/post/delete"); 353 } 354 VerbDefinition verb = getVerbs().get(getVerbs().size() - 1); 355 verb.getResponseMsgs().add(msg); 356 return this; 357 } 358 359 public RestOperationResponseMsgDefinition responseMessage() { 360 if (getVerbs().isEmpty()) { 361 throw new IllegalArgumentException("Must add verb first, such as get/post/delete"); 362 } 363 VerbDefinition verb = getVerbs().get(getVerbs().size() - 1); 364 return responseMessage(verb); 365 } 366 367 public RestOperationResponseMsgDefinition responseMessage(VerbDefinition verb) { 368 return new RestOperationResponseMsgDefinition(verb); 369 } 370 371 public RestDefinition responseMessages(List<RestOperationResponseMsgDefinition> msgs) { 372 if (getVerbs().isEmpty()) { 373 throw new IllegalArgumentException("Must add verb first, such as get/post/delete"); 374 } 375 VerbDefinition verb = getVerbs().get(getVerbs().size() - 1); 376 verb.getResponseMsgs().addAll(msgs); 377 return this; 378 } 379 380 public RestDefinition produces(String mediaType) { 381 if (getVerbs().isEmpty()) { 382 this.produces = mediaType; 383 } else { 384 // add on last verb as that is how the Java DSL works 385 VerbDefinition verb = getVerbs().get(getVerbs().size() - 1); 386 verb.setProduces(mediaType); 387 } 388 389 return this; 390 } 391 392 public RestDefinition type(Class<?> classType) { 393 // add to last verb 394 if (getVerbs().isEmpty()) { 395 throw new IllegalArgumentException("Must add verb first, such as get/post/delete"); 396 } 397 398 VerbDefinition verb = getVerbs().get(getVerbs().size() - 1); 399 verb.setType(classType.getCanonicalName()); 400 return this; 401 } 402 403 public RestDefinition typeList(Class<?> classType) { 404 // add to last verb 405 if (getVerbs().isEmpty()) { 406 throw new IllegalArgumentException("Must add verb first, such as get/post/delete"); 407 } 408 409 VerbDefinition verb = getVerbs().get(getVerbs().size() - 1); 410 // list should end with [] to indicate array 411 verb.setType(classType.getCanonicalName() + "[]"); 412 return this; 413 } 414 415 public RestDefinition outType(Class<?> classType) { 416 // add to last verb 417 if (getVerbs().isEmpty()) { 418 throw new IllegalArgumentException("Must add verb first, such as get/post/delete"); 419 } 420 421 VerbDefinition verb = getVerbs().get(getVerbs().size() - 1); 422 verb.setOutType(classType.getCanonicalName()); 423 return this; 424 } 425 426 public RestDefinition outTypeList(Class<?> classType) { 427 // add to last verb 428 if (getVerbs().isEmpty()) { 429 throw new IllegalArgumentException("Must add verb first, such as get/post/delete"); 430 } 431 432 VerbDefinition verb = getVerbs().get(getVerbs().size() - 1); 433 // list should end with [] to indicate array 434 verb.setOutType(classType.getCanonicalName() + "[]"); 435 return this; 436 } 437 438 public RestDefinition bindingMode(RestBindingMode mode) { 439 if (getVerbs().isEmpty()) { 440 this.bindingMode = mode; 441 } else { 442 // add on last verb as that is how the Java DSL works 443 VerbDefinition verb = getVerbs().get(getVerbs().size() - 1); 444 verb.setBindingMode(mode); 445 } 446 447 return this; 448 } 449 450 public RestDefinition skipBindingOnErrorCode(boolean skipBindingOnErrorCode) { 451 if (getVerbs().isEmpty()) { 452 this.skipBindingOnErrorCode = skipBindingOnErrorCode; 453 } else { 454 // add on last verb as that is how the Java DSL works 455 VerbDefinition verb = getVerbs().get(getVerbs().size() - 1); 456 verb.setSkipBindingOnErrorCode(skipBindingOnErrorCode); 457 } 458 459 return this; 460 } 461 462 public RestDefinition enableCORS(boolean enableCORS) { 463 if (getVerbs().isEmpty()) { 464 this.enableCORS = enableCORS; 465 } else { 466 // add on last verb as that is how the Java DSL works 467 VerbDefinition verb = getVerbs().get(getVerbs().size() - 1); 468 verb.setEnableCORS(enableCORS); 469 } 470 471 return this; 472 } 473 474 /** 475 * Include or exclude the current Rest Definition in API documentation. 476 * <p/> 477 * The default value is true. 478 */ 479 public RestDefinition apiDocs(Boolean apiDocs) { 480 if (getVerbs().isEmpty()) { 481 this.apiDocs = apiDocs; 482 } else { 483 // add on last verb as that is how the Java DSL works 484 VerbDefinition verb = getVerbs().get(getVerbs().size() - 1); 485 verb.setApiDocs(apiDocs); 486 } 487 488 return this; 489 } 490 491 /** 492 * Routes directly to the given static endpoint. 493 * <p/> 494 * If you need additional routing capabilities, then use {@link #route()} instead. 495 * 496 * @param uri the uri of the endpoint 497 * @return this builder 498 */ 499 public RestDefinition to(String uri) { 500 // add to last verb 501 if (getVerbs().isEmpty()) { 502 throw new IllegalArgumentException("Must add verb first, such as get/post/delete"); 503 } 504 505 ToDefinition to = new ToDefinition(uri); 506 507 VerbDefinition verb = getVerbs().get(getVerbs().size() - 1); 508 verb.setTo(to); 509 return this; 510 } 511 512 /** 513 * Routes directly to the given dynamic endpoint. 514 * <p/> 515 * If you need additional routing capabilities, then use {@link #route()} instead. 516 * 517 * @param uri the uri of the endpoint 518 * @return this builder 519 */ 520 public RestDefinition toD(String uri) { 521 // add to last verb 522 if (getVerbs().isEmpty()) { 523 throw new IllegalArgumentException("Must add verb first, such as get/post/delete"); 524 } 525 526 ToDynamicDefinition to = new ToDynamicDefinition(uri); 527 528 VerbDefinition verb = getVerbs().get(getVerbs().size() - 1); 529 verb.setToD(to); 530 return this; 531 } 532 533 public RouteDefinition route() { 534 // add to last verb 535 if (getVerbs().isEmpty()) { 536 throw new IllegalArgumentException("Must add verb first, such as get/post/delete"); 537 } 538 539 // link them together so we can navigate using Java DSL 540 RouteDefinition route = new RouteDefinition(); 541 route.setRestDefinition(this); 542 VerbDefinition verb = getVerbs().get(getVerbs().size() - 1); 543 verb.setRoute(route); 544 return route; 545 } 546 547 // Implementation 548 //------------------------------------------------------------------------- 549 550 private RestDefinition addVerb(String verb, String uri) { 551 VerbDefinition answer; 552 553 if ("get".equals(verb)) { 554 answer = new GetVerbDefinition(); 555 } else if ("post".equals(verb)) { 556 answer = new PostVerbDefinition(); 557 } else if ("delete".equals(verb)) { 558 answer = new DeleteVerbDefinition(); 559 } else if ("head".equals(verb)) { 560 answer = new HeadVerbDefinition(); 561 } else if ("put".equals(verb)) { 562 answer = new PutVerbDefinition(); 563 } else if ("options".equals(verb)) { 564 answer = new OptionsVerbDefinition(); 565 } else { 566 answer = new VerbDefinition(); 567 answer.setMethod(verb); 568 } 569 getVerbs().add(answer); 570 answer.setRest(this); 571 answer.setUri(uri); 572 return this; 573 } 574 575 /** 576 * Transforms this REST definition into a list of {@link org.apache.camel.model.RouteDefinition} which 577 * Camel routing engine can add and run. This allows us to define REST services using this 578 * REST DSL and turn those into regular Camel routes. 579 */ 580 public List<RouteDefinition> asRouteDefinition(CamelContext camelContext) { 581 List<RouteDefinition> answer = new ArrayList<RouteDefinition>(); 582 if (camelContext.getRestConfigurations().isEmpty()) { 583 camelContext.getRestConfiguration(); 584 } 585 for (RestConfiguration config : camelContext.getRestConfigurations()) { 586 addRouteDefinition(camelContext, answer, config.getComponent()); 587 } 588 return answer; 589 } 590 591 /** 592 * Transforms the rest api configuration into a {@link org.apache.camel.model.RouteDefinition} which 593 * Camel routing engine uses to service the rest api docs. 594 */ 595 public static RouteDefinition asRouteApiDefinition(CamelContext camelContext, RestConfiguration configuration) { 596 RouteDefinition answer = new RouteDefinition(); 597 598 // create the from endpoint uri which is using the rest-api component 599 String from = "rest-api:" + configuration.getApiContextPath(); 600 601 // append options 602 Map<String, Object> options = new HashMap<String, Object>(); 603 604 String routeId = configuration.getApiContextRouteId(); 605 if (routeId == null) { 606 routeId = answer.idOrCreate(camelContext.getNodeIdFactory()); 607 } 608 options.put("routeId", routeId); 609 if (configuration.getComponent() != null && !configuration.getComponent().isEmpty()) { 610 options.put("componentName", configuration.getComponent()); 611 } 612 if (configuration.getApiContextIdPattern() != null) { 613 options.put("contextIdPattern", configuration.getApiContextIdPattern()); 614 } 615 616 if (!options.isEmpty()) { 617 String query; 618 try { 619 query = URISupport.createQueryString(options); 620 } catch (URISyntaxException e) { 621 throw ObjectHelper.wrapRuntimeCamelException(e); 622 } 623 from = from + "?" + query; 624 } 625 626 // we use the same uri as the producer (so we have a little route for the rest api) 627 String to = from; 628 answer.fromRest(from); 629 answer.id(routeId); 630 answer.to(to); 631 632 return answer; 633 } 634 635 private void addRouteDefinition(CamelContext camelContext, List<RouteDefinition> answer, String component) { 636 for (VerbDefinition verb : getVerbs()) { 637 // either the verb has a singular to or a embedded route 638 RouteDefinition route = verb.getRoute(); 639 if (route == null) { 640 // it was a singular to, so add a new route and add the singular 641 // to as output to this route 642 route = new RouteDefinition(); 643 ProcessorDefinition def = verb.getTo() != null ? verb.getTo() : verb.getToD(); 644 route.getOutputs().add(def); 645 } 646 647 // add the binding 648 RestBindingDefinition binding = new RestBindingDefinition(); 649 binding.setComponent(component); 650 binding.setType(verb.getType()); 651 binding.setOutType(verb.getOutType()); 652 // verb takes precedence over configuration on rest 653 if (verb.getConsumes() != null) { 654 binding.setConsumes(verb.getConsumes()); 655 } else { 656 binding.setConsumes(getConsumes()); 657 } 658 if (verb.getProduces() != null) { 659 binding.setProduces(verb.getProduces()); 660 } else { 661 binding.setProduces(getProduces()); 662 } 663 if (verb.getBindingMode() != null) { 664 binding.setBindingMode(verb.getBindingMode()); 665 } else { 666 binding.setBindingMode(getBindingMode()); 667 } 668 if (verb.getSkipBindingOnErrorCode() != null) { 669 binding.setSkipBindingOnErrorCode(verb.getSkipBindingOnErrorCode()); 670 } else { 671 binding.setSkipBindingOnErrorCode(getSkipBindingOnErrorCode()); 672 } 673 if (verb.getEnableCORS() != null) { 674 binding.setEnableCORS(verb.getEnableCORS()); 675 } else { 676 binding.setEnableCORS(getEnableCORS()); 677 } 678 route.getOutputs().add(0, binding); 679 680 // create the from endpoint uri which is using the rest component 681 String from = "rest:" + verb.asVerb() + ":" + buildUri(verb); 682 683 // append options 684 Map<String, Object> options = new HashMap<String, Object>(); 685 // verb takes precedence over configuration on rest 686 if (verb.getConsumes() != null) { 687 options.put("consumes", verb.getConsumes()); 688 } else if (getConsumes() != null) { 689 options.put("consumes", getConsumes()); 690 } 691 if (verb.getProduces() != null) { 692 options.put("produces", verb.getProduces()); 693 } else if (getProduces() != null) { 694 options.put("produces", getProduces()); 695 } 696 697 // append optional type binding information 698 String inType = binding.getType(); 699 if (inType != null) { 700 options.put("inType", inType); 701 } 702 String outType = binding.getOutType(); 703 if (outType != null) { 704 options.put("outType", outType); 705 } 706 // if no route id has been set, then use the verb id as route id 707 if (!route.hasCustomIdAssigned()) { 708 // use id of verb as route id 709 String id = verb.getId(); 710 if (id != null) { 711 route.setId(id); 712 } 713 } 714 String routeId = route.idOrCreate(camelContext.getNodeIdFactory()); 715 verb.setRouteId(routeId); 716 options.put("routeId", routeId); 717 if (component != null && !component.isEmpty()) { 718 options.put("componentName", component); 719 } 720 721 // include optional description, which we favor from 1) to/route description 2) verb description 3) rest description 722 // this allows end users to define general descriptions and override then per to/route or verb 723 String description = verb.getTo() != null ? verb.getTo().getDescriptionText() : route.getDescriptionText(); 724 if (description == null) { 725 description = verb.getDescriptionText(); 726 } 727 if (description == null) { 728 description = getDescriptionText(); 729 } 730 if (description != null) { 731 options.put("description", description); 732 } 733 734 if (!options.isEmpty()) { 735 String query; 736 try { 737 query = URISupport.createQueryString(options); 738 } catch (URISyntaxException e) { 739 throw ObjectHelper.wrapRuntimeCamelException(e); 740 } 741 from = from + "?" + query; 742 } 743 744 String path = getPath(); 745 String s1 = FileUtil.stripTrailingSeparator(path); 746 String s2 = FileUtil.stripLeadingSeparator(verb.getUri()); 747 String allPath; 748 if (s1 != null && s2 != null) { 749 allPath = s1 + "/" + s2; 750 } else if (path != null) { 751 allPath = path; 752 } else { 753 allPath = verb.getUri(); 754 } 755 756 // each {} is a parameter (url templating) 757 String[] arr = allPath.split("\\/"); 758 for (String a : arr) { 759 // need to resolve property placeholders first 760 try { 761 a = camelContext.resolvePropertyPlaceholders(a); 762 } catch (Exception e) { 763 throw ObjectHelper.wrapRuntimeCamelException(e); 764 } 765 if (a.startsWith("{") && a.endsWith("}")) { 766 String key = a.substring(1, a.length() - 1); 767 // merge if exists 768 boolean found = false; 769 for (RestOperationParamDefinition param : verb.getParams()) { 770 // name is mandatory 771 String name = param.getName(); 772 ObjectHelper.notEmpty(name, "parameter name"); 773 // need to resolve property placeholders first 774 try { 775 name = camelContext.resolvePropertyPlaceholders(name); 776 } catch (Exception e) { 777 throw ObjectHelper.wrapRuntimeCamelException(e); 778 } 779 if (name.equalsIgnoreCase(key)) { 780 param.type(RestParamType.path); 781 found = true; 782 break; 783 } 784 } 785 if (!found) { 786 param(verb).name(key).type(RestParamType.path).endParam(); 787 } 788 } 789 } 790 791 if (verb.getType() != null) { 792 String bodyType = verb.getType(); 793 if (bodyType.endsWith("[]")) { 794 bodyType = "List[" + bodyType.substring(0, bodyType.length() - 2) + "]"; 795 } 796 RestOperationParamDefinition param = findParam(verb, RestParamType.body.name()); 797 if (param == null) { 798 // must be body type and set the model class as data type 799 param(verb).name(RestParamType.body.name()).type(RestParamType.body).dataType(bodyType).endParam(); 800 } else { 801 // must be body type and set the model class as data type 802 param.type(RestParamType.body).dataType(bodyType); 803 } 804 } 805 806 // the route should be from this rest endpoint 807 route.fromRest(from); 808 route.id(routeId); 809 route.setRestDefinition(this); 810 answer.add(route); 811 } 812 } 813 814 private String buildUri(VerbDefinition verb) { 815 if (path != null && verb.getUri() != null) { 816 return path + ":" + verb.getUri(); 817 } else if (path != null) { 818 return path; 819 } else if (verb.getUri() != null) { 820 return verb.getUri(); 821 } else { 822 return ""; 823 } 824 } 825 826 private RestOperationParamDefinition findParam(VerbDefinition verb, String name) { 827 for (RestOperationParamDefinition param : verb.getParams()) { 828 if (name.equals(param.getName())) { 829 return param; 830 } 831 } 832 return null; 833 } 834 835}