blob: f3da71366d85c24fb6c1ea667409949cc2cbfdde [file] [log] [blame]
<!DOCTYPE html>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<html lang="en">
<head>
<title>Apache Velocity Tools - Creating Tools</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<meta property="og:image" content="http://www.apache.org/images/asf_logo.gif" />
<link rel="stylesheet" type="text/css" href="/css/site.css">
</head>
<body>
<div id="page">
<div id="header">
<div id="logo2"><img src="/tools/devel/images/velocitytools.png"/></div>
<a href="/">
<svg height="60" width="50%" viewBox="20 20 800 110" preserveAspectRatio="xMinYMin">
<linearGradient gradientTransform="matrix(0.07810935,0.01915457,0.02093045,-0.07148201,452.38809,497.7395)" y2="1395.619" x2="-4570.1162" y1="697.55487" x1="-5167.0962" gradientUnits="userSpaceOnUse" id="SVGID_1_">
<stop id="stop3521" style="stop-color:#F69923" offset="0" />
<stop id="stop3523" style="stop-color:#F79A23" offset="0.3123" />
<stop id="stop3525" style="stop-color:#E97826" offset="0.8383" />
</linearGradient>
<linearGradient gradientTransform="matrix(0.07810935,0.01915457,0.02093045,-0.07148201,452.38809,497.7395)" y2="620.50482" x2="-5326.209" y1="620.50482" x1="-9585.3418" gradientUnits="userSpaceOnUse" id="SVGID_2_">
<stop id="stop3546" style="stop-color:#9E2064" offset="0.3233" />
<stop id="stop3548" style="stop-color:#C92037" offset="0.6302" />
<stop id="stop3550" style="stop-color:#CD2335" offset="0.7514" />
<stop id="stop3552" style="stop-color:#E97826" offset="1" />
</linearGradient>
<linearGradient gradientTransform="matrix(0.07810935,0.01915457,0.02093045,-0.07148201,452.38809,497.7395)" y2="1047.6898" x2="-6533.1782" y1="1047.6898" x1="-9071.207" gradientUnits="userSpaceOnUse" id="SVGID_3_">
<stop id="stop3557" style="stop-color:#282662" offset="0" />
<stop id="stop3559" style="stop-color:#662E8D" offset="9.548390e-02" />
<stop id="stop3561" style="stop-color:#9F2064" 1 offset="0.7882" />
<stop id="stop3563" style="stop-color:#CD2032" offset="0.9487" />
</linearGradient>
<linearGradient gradientTransform="matrix(0.07810935,0.01915457,0.02093045,-0.07148201,452.38809,497.7395)" y2="580.81702" x2="-5086.9941" y1="580.81702" x1="-9346.126" gradientUnits="userSpaceOnUse" id="SVGID_4_">
<stop id="stop3568" style="stop-color:#9E2064" offset="0.3233" />
<stop id="stop3570" style="stop-color:#C92037" offset="0.6302" />
<stop id="stop3572" style="stop-color:#CD2335" offset="0.7514" />
<stop id="stop3574" style="stop-color:#E97826" offset="1" />
</linearGradient>
<linearGradient gradientTransform="matrix(0.07810935,0.01915457,0.02093045,-0.07148201,452.38809,497.7395)" y2="638.4408" x2="-6797.2012" y1="638.4408" x1="-9035.5029" gradientUnits="userSpaceOnUse" id="SVGID_5_">
<stop id="stop3579" style="stop-color:#282662" offset="0" />
<stop id="stop3581" style="stop-color:#662E8D" offset="9.548390e-02" />
<stop id="stop3583" style="stop-color:#9F2064" offset="0.7882" />
<stop id="stop3585" style="stop-color:#CD2032" offset="0.9487" />
</linearGradient>
<linearGradient gradientTransform="matrix(0.07810935,0.01915457,0.02093045,-0.07148201,452.38809,497.7395)" y2="1021.6218" x2="-5086.9941" y1="1021.6218" x1="-9346.126" gradientUnits="userSpaceOnUse" id="SVGID_6_">
<stop id="stop3590" style="stop-color:#9E2064" offset="0.3233" />
<stop id="stop3592" style="stop-color:#C92037" offset="0.6302" />
<stop id="stop3594" style="stop-color:#CD2335" offset="0.7514" />
<stop id="stop3596" style="stop-color:#E97826" offset="1" />
</linearGradient>
<linearGradient gradientTransform="matrix(0.07810935,0.01915457,0.02093045,-0.07148201,452.38809,497.7395)" y2="999.73297" x2="-5351.2017" y1="999.73297" x1="-9610.334" gradientUnits="userSpaceOnUse" id="SVGID_7_">
<stop id="stop3601" style="stop-color:#9E2064" offset="0.3233" />
<stop id="stop3603" style="stop-color:#C92037" offset="0.6302" />
<stop id="stop3605" style="stop-color:#CD2335" offset="0.7514" />
<stop id="stop3607" style="stop-color:#E97826" offset="1" />
</linearGradient>
<linearGradient gradientTransform="matrix(0.07810935,0.01915457,0.02093045,-0.07148201,452.38809,497.7395)" y2="1152.7261" x2="-5086.9941" y1="1152.7261" x1="-9346.126" gradientUnits="userSpaceOnUse" id="SVGID_8_">
<stop id="stop3616" style="stop-color:#9E2064" offset="0.3233" />
<stop id="stop3618" style="stop-color:#C92037" offset="0.6302" />
<stop id="stop3620" style="stop-color:#CD2335" offset="0.7514" />
<stop id="stop3622" style="stop-color:#E97826" offset="1" />
</linearGradient>
<linearGradient gradientTransform="matrix(0.07810935,0.01915457,0.02093045,-0.07148201,452.38809,497.7395)" y2="1137.7247" x2="-5086.9941" y1="1137.7247" x1="-9346.126" gradientUnits="userSpaceOnUse" id="SVGID_9_">
<stop id="stop3631" style="stop-color:#9E2064" offset="0.3233" />
<stop id="stop3633" style="stop-color:#C92037" offset="0.6302" />
<stop id="stop3635" style="stop-color:#CD2335" offset="0.7514" />
<stop id="stop3637" style="stop-color:#E97826" offset="1" />
</linearGradient>
<linearGradient gradientTransform="matrix(0.07810935,0.01915457,0.02093045,-0.07148201,452.38809,497.7395)" y2="1134.7161" x2="-6011.9995" y1="1134.7161" x1="-6953.4072" gradientUnits="userSpaceOnUse" id="SVGID_10_">
<stop id="stop3646" style="stop-color:#9E2064" offset="0.3233" />
<stop id="stop3648" style="stop-color:#C92037" offset="0.6302" />
<stop id="stop3650" style="stop-color:#CD2335" offset="0.7514" />
<stop id="stop3652" style="stop-color:#E97826" offset="1" />
</linearGradient>
<g transform="translate(275,-230)" id="g3735">
<path d="m 95.030525,353.34688 c -5.868388,1.89866 -18.455097,2.86966 -35.232972,2.68962 l -7.844759,-17.69411 c 11.922072,0.96277 23.155947,1.27149 33.446456,0.7785 0.806681,-0.0278 1.205437,-0.0597 1.205437,-0.0597 -0.39975,0.0215 -0.805689,0.0382 -1.205437,0.0597 -3.380984,0.11837 -13.97859,0.22097 -32.909158,-1.88263 6.824373,-6.72909 18.288583,-16.31958 28.008861,-23.85834 18.433387,9.69185 21.017957,20.51606 21.017957,20.51606 0,0 5.61321,15.54576 -6.486385,19.4509 z" id="path3527" style="fill:url(#SVGID_1_)" />
<path d="m 3.8322454,303.07135 c 0.059217,-0.0415 0.1120778,-0.0878 0.1712971,-0.12929 l -1.0221478,0.89604 c -0.088131,0.0386 -0.1658908,0.0658 -0.2478563,0.10915 0.3676459,-0.29732 0.7362578,-0.58424 1.098707,-0.8759 z" id="path3529" style="fill:none" />
<path d="m -27.876072,290.63399 c -0.650899,0.45658 -1.281214,0.94828 -1.904317,1.45519 0.623103,-0.50691 1.259608,-0.99386 1.904317,-1.45519 z" id="path3531" style="fill:none" />
<path d="m -128.18492,294.56272 c 0.27819,0.088 0.55639,0.17608 0.82938,0.26978 5.73136,1.8314 11.32321,3.58465 16.79937,5.26839 6.14427,1.88764 12.119072,3.68379 17.941982,5.39228 6.136306,1.80423 12.096924,3.5122 17.888098,5.1287 6.074555,1.69886 11.961044,3.29193 17.65531,4.79537 4.634037,1.22062 9.141965,2.38304 13.528979,3.48159 1.458542,0.36649 2.910894,0.72823 4.350865,1.08046 2.85092,0.70149 5.659501,1.38013 8.402938,2.03773 2.537553,0.60576 5.026574,1.18393 7.479394,1.74394 0.816212,0.19205 1.625242,0.36892 2.435266,0.55621 0.129295,0.0317 0.263817,0.0577 0.393113,0.0893 l -0.868431,0.76291 0.823816,1.77257 c -0.199639,-0.047 -0.398312,-0.0837 -0.603148,-0.12504 -3.709945,-0.80082 -7.434286,-1.63202 -11.17299,-2.49357 -2.160061,-0.49944 -4.326285,-1.00361 -6.493528,-1.51823 -6.008289,-1.42577 -12.02773,-2.90842 -18.046963,-4.44886 -6.083384,-1.55106 -12.155172,-3.16085 -18.201961,-4.8094 -5.94027,-1.61506 -11.850346,-3.27456 -17.722022,-4.95287 -5.860317,-1.67925 -11.671838,-3.38866 -17.421218,-5.10831 -6.00377,-1.79907 -11.9226,-3.61019 -17.74509,-5.43429 -1.31344,-0.40964 -2.62686,-0.81925 -3.9351,-1.23456 -4.69313,-1.47853 -9.30551,-2.95301 -13.84851,-4.42253 l -1.30665,-2.80027 0.97437,-0.85544 c 0.1365,0.0469 0.27298,0.0937 0.4033,0.1358 5.95137,1.97137 11.76945,3.86936 17.45943,5.68831 z" id="path3533" style="fill:none" />
<path d="m -30.254972,292.46861 0,0 c 0.0052,-0.006 0.01127,-0.001 0.01647,-0.007 0,0 -0.0052,0.006 -0.01647,0.007 z" id="path3535" style="fill:none" />
<path d="m -44.667842,285.26517 c -0.973928,0.73986 -1.967656,1.51281 -2.988395,2.30367 -0.0052,0.006 -0.01647,0.007 -0.02166,0.0123 0.500572,-0.40778 0.995948,-0.80989 1.498505,-1.19683 0.50256,-0.38694 1.00094,-0.75776 1.511673,-1.1191 z" id="path3537" style="fill:#be202e" />
<path d="m -44.667842,285.26517 c -0.973928,0.73986 -1.967656,1.51281 -2.988395,2.30367 -0.0052,0.006 -0.01647,0.007 -0.02166,0.0123 0.500572,-0.40778 0.995948,-0.80989 1.498505,-1.19683 0.50256,-0.38694 1.00094,-0.75776 1.511673,-1.1191 z" id="path3539" style="opacity:0.35;fill:#be202e" />
<path d="m -30.2218,292.45544 c 0,0 -0.0052,0.006 -0.01127,10e-4 -0.0052,0.006 -0.01127,9.9e-4 -0.01647,0.007 0.153662,-0.13318 0.314646,-0.25108 0.463195,-0.37852 0.628302,-0.51257 1.264807,-0.99953 1.904289,-1.45521 -0.763241,0.60216 -1.549259,1.20616 -2.339509,1.82623 l 0,0 0,0 z" id="path3541" style="fill:#be202e" />
<path d="m -30.2218,292.45544 c 0,0 -0.0052,0.006 -0.01127,10e-4 -0.0052,0.006 -0.01127,9.9e-4 -0.01647,0.007 0.153662,-0.13318 0.314646,-0.25108 0.463195,-0.37852 0.628302,-0.51257 1.264807,-0.99953 1.904289,-1.45521 -0.763241,0.60216 -1.549259,1.20616 -2.339509,1.82623 l 0,0 0,0 z" id="path3543" style="opacity:0.35;fill:#be202e" />
<path d="m -3.0502818,330.5069 c 6.1572269,1.1827 12.247534,2.26571 18.2471238,3.24041 6.227231,1.01426 12.356561,1.90504 18.357978,2.65895 0.348762,0.0456 0.708911,0.0903 1.063863,0.1407 5.913525,0.73472 11.699134,1.33257 17.339307,1.78976 l 7.844762,17.69411 c -1.160612,-0.0121 -2.333632,-0.0338 -3.529455,-0.0536 -4.497401,-0.0917 -9.271992,-0.26093 -14.266831,-0.51239 -5.629411,-0.28469 -11.556567,-0.6821 -17.699796,-1.1778 -5.67533,-0.46487 -11.549098,-1.02415 -17.5529729,-1.68334 -5.1106845,-0.5626 -10.3308648,-1.18997 -15.622198,-1.90096 -0.197654,-0.0262 -0.3953057,-0.0524 -0.5929873,-0.0786 L -20.52484,326.94198 c 5.866009,1.25856 11.69707,2.45163 17.4745582,3.56492 z" id="path3554" style="fill:url(#SVGID_2_)" />
<path d="m -148.64432,287.87492 c -4.62455,-1.5418 -9.31626,-3.12551 -14.09367,-4.76537 -0.0714,-0.0258 -0.13651,-0.0469 -0.20787,-0.0727 -0.67629,-0.2295 -1.34737,-0.46467 -2.02369,-0.69419 -3.21697,-1.10818 -6.09263,-2.12815 -12.63913,-4.44059 1.0996,-3.6285 -0.41103,-8.38228 -2.49019,-13.37944 3.85283,3.31605 6.24773,7.77315 6.52364,12.94094 11.22895,-13.43253 25.02773,-21.83891 40.65304,-19.66506 1.39603,0.1929 2.79384,0.46445 4.21819,0.83367 -6.03156,-0.16844 -10.5525,1.89547 -15.78323,8.30262 -0.0165,0.007 -0.0384,0.0188 -0.0549,0.0255 0.0165,-0.007 0.0384,-0.0188 0.0549,-0.0255 12.65883,-5.62036 21.02643,-6.89439 31.69203,-5.50534 2.52825,0.32813 5.18536,0.80351 8.06151,1.40845 -16.05366,1.09099 -26.93227,8.28126 -33.83488,19.35554 l -7.46769,6.54422 c -0.87076,-0.28223 -1.73631,-0.57012 -2.60806,-0.86277 z" id="path3565" style="fill:url(#SVGID_3_)" />
<path d="m -127.92557,298.05617 c 5.82769,1.81842 11.74652,3.62955 17.74512,5.43431 5.74415,1.7253 11.554681,3.42428 17.421188,5.10828 5.866507,1.68401 11.775562,3.33306 17.722022,4.95287 6.046789,1.64856 12.123776,3.25267 18.201961,4.8094 6.013043,1.53569 12.038702,3.02311 18.046963,4.44886 2.167243,0.51462 4.333467,1.0188 6.493528,1.51824 3.738705,0.86155 7.463045,1.69274 11.172991,2.49357 0.199636,0.047 0.398312,0.0837 0.603147,0.12503 l 11.0633797,23.68219 c -0.3953333,-0.0524 -0.7854697,-0.11047 -1.1807777,-0.16285 -5.606921,-0.76978 -11.295338,-1.6118 -17.027898,-2.55534 -5.790549,-0.94943 -11.619023,-1.99561 -17.461681,-3.12996 -4.930086,-0.95526 -9.854792,-1.97402 -14.768868,-3.06189 -0.99728,-0.22482 -1.97698,-0.44581 -2.962873,-0.67154 -6.150175,-1.40914 -11.974938,-2.89686 -17.487932,-4.42532 -6.244233,-1.73255 -12.086525,-3.52355 -17.517683,-5.33696 -3.574927,-1.18983 -6.978977,-2.39336 -10.215327,-3.58405 -2.73994,-1.04133 -5.46008,-2.11577 -8.13662,-3.21469 -6.31977,-2.58273 -12.45563,-5.34303 -18.38577,-8.29314 l -11.10848,-23.79411 c 4.54303,1.46954 9.15538,2.94401 13.84853,4.42255 1.30203,0.41054 2.62167,0.82493 3.93508,1.23455 z" id="path3576" style="fill:url(#SVGID_4_)" />
<path d="m -135.39748,315.78421 c -7.2115,-3.62494 -14.10198,-7.55402 -20.5914,-11.85137 -0.2272,-0.15514 -0.45863,-0.29422 -0.68582,-0.44936 2.3312,6.55285 0.24599,17.70369 0.21823,17.65338 -3.57467,-11.87432 -8.27251,-22.40852 -15.98628,-29.36565 -3.27442,2.37386 -5.94744,7.01608 -8.28358,12.96033 -0.41103,-8.38228 1.53485,-12.94527 2.45003,-14.5997 -4.28418,4.11989 -11.70198,6.14259 -19.64656,7.81875 9.09151,-4.3892 15.21177,-8.8767 17.7976,-13.46995 -24.55723,-8.42409 -51.09999,-18.3439 -78.93127,-29.25317 2.33282,-1.41596 4.74343,-1.47765 7.19121,-0.67033 5.0236,1.99314 38.05928,14.98608 83.16344,30.23283 1.28124,0.43321 2.57389,0.86552 3.8727,1.30257 0.36193,0.12335 0.72908,0.24106 1.08481,0.35966 4.73826,1.59047 9.59244,3.19267 14.55737,4.81229 1.13136,0.36642 2.26272,0.73284 3.40026,1.10401 0.0237,0.009 0.0476,0.0172 0.0652,0.021 l 11.11272,23.77804 c -0.25321,-0.12682 -0.52301,-0.24705 -0.7886,-0.38338 z" id="path3587" style="fill:url(#SVGID_5_)" />
<path d="m -20.879529,324.31241 c -0.803833,-0.18253 -1.613855,-0.36983 -2.435266,-0.5562 -2.447621,-0.56569 -4.936644,-1.14385 -7.479421,-1.74397 -2.748608,-0.6519 -5.5458,-1.33146 -8.402911,-2.03771 -1.439971,-0.35222 -2.880933,-0.71488 -4.350864,-1.08045 -4.387015,-1.09855 -8.894942,-2.26097 -13.528979,-3.48159 -5.694267,-1.50344 -11.580756,-3.09652 -17.65531,-4.79538 -5.791175,-1.61649 -11.75182,-3.32448 -17.888098,-5.1287 -5.82291,-1.70849 -11.803902,-3.50939 -17.941982,-5.39227 -5.47616,-1.68374 -11.06801,-3.43699 -16.79937,-5.26839 -0.27821,-0.088 -0.55639,-0.17608 -0.82938,-0.26978 -5.68998,-1.81895 -11.50806,-3.71694 -17.44804,-5.68923 -0.13651,-0.0469 -0.27299,-0.0937 -0.40331,-0.1358 l 7.4677,-6.54423 c -0.099,0.16552 -0.21555,0.32718 -0.31452,0.4927 9.07173,-7.71799 26.60886,-13.7657 42.082402,-14.50031 7.130974,-0.33982 14.689435,0.18964 22.840099,1.56994 6.067741,1.02703 12.461933,2.52695 19.257152,4.49905 5.938834,1.72022 12.180797,3.78914 18.773426,6.22395 -2.953943,1.10323 -5.869407,2.7287 -8.744022,4.78162 -0.499373,0.3604 -1.009112,0.73216 -1.511672,1.1191 -0.502585,0.38691 -1.004151,0.78427 -1.498505,1.19683 l 0,0 0,0 c 0.0052,-0.006 0.01647,-0.007 0.02166,-0.0123 10.741665,-5.44059 21.911677,-5.49972 33.275347,-3.05294 -3.512293,0.90633 -8.725108,2.75774 -13.490013,6.1124 -0.650869,0.45659 -1.281184,0.9483 -1.904287,1.4552 -0.160021,0.1283 -0.314677,0.25106 -0.463195,0.37852 l 0,0 0,0 c 0.0052,-0.006 0.01127,-9.9e-4 0.01647,-0.007 0,0 0.0052,-0.006 0.01127,-9.9e-4 l 0,0 c 3.833524,-1.80927 7.415482,-3.06785 10.971709,-3.81484 0.75953,-0.16062 1.521076,-0.30038 2.285595,-0.40887 1.160272,-0.17169 2.320337,-0.28559 3.490588,-0.35301 0.747698,-0.0441 1.497407,-0.0674 2.255322,-0.065 1.7736055,-1.9e-4 3.5809872,0.11249 5.4459147,0.34666 0.5691898,0.07 1.1394009,0.1504 1.7219926,0.24033 0.8080111,0.16642 1.5932437,0.33468 2.3670894,0.50385 3.4947139,0.7708 6.5151055,1.56378 9.1028098,2.33365 1.2938545,0.38493 2.4717831,0.75813 3.5461715,1.12911 0.427069,0.1444 0.842778,0.28973 1.24088,0.4312 1.189109,0.43009 2.22612,0.83033 3.11722,1.20547 1.333581,0.56035 2.345383,1.05716 3.054216,1.4469 l 0,0 0,0 c -0.484902,0.0914 -1.006187,0.22239 -1.55767,0.39787 -3.810562,1.20862 -9.0630554,4.26613 -12.8155016,7.10372 l 6.8589836,-6.00695 -6.8589836,6.00695 c -0.059219,0.0415 -0.1120802,0.0878 -0.1712972,0.1293 -0.3686395,0.2869 -0.73626,0.58424 -1.1100962,0.87681 0.088156,-0.0386 0.1659184,-0.0658 0.2478563,-0.10915 l -23.4688293,20.55321 c -0.123105,-0.0269 -0.246211,-0.0538 -0.380705,-0.0798 z" id="path3598" style="fill:url(#SVGID_6_)" />
<path d="m 52.489098,337.22784 c -5.221409,-0.58001 -11.072737,-1.32494 -17.582802,-2.29555 -0.337345,-0.0465 -0.687098,-0.10255 -1.030661,-0.15384 -5.631475,-0.8466 -11.74798,-1.84346 -18.359704,-3.03705 -5.7115598,-1.02402 -11.780866,-2.1875 -18.2388704,-3.51423 -5.6261705,-1.15166 -11.5511356,-2.4265 -17.7644676,-3.83584 L 2.9813947,303.8381 c 9.3594193,-4.04821 15.0606363,-4.69376 22.0219053,-4.22681 1.892116,0.15844 3.845172,0.35401 5.836389,0.58854 6.095793,0.72012 12.552647,1.79478 18.766426,3.08853 5.997499,1.25326 11.744739,2.71043 16.714058,4.25614 3.159483,0.98674 6.000949,2.00943 8.377522,3.03258 2.095388,0.90383 4.020884,1.83177 5.804442,2.7763 -9.724453,7.55488 -21.194854,17.14061 -28.013039,23.87446 z" id="path3609" style="fill:url(#SVGID_7_)" />
<path d="m -46.179514,286.38427 c -0.502558,0.38693 -1.004124,0.78429 -1.498506,1.19682 l 0,0 c 0.494382,-0.41253 0.995948,-0.80989 1.498506,-1.19682 z" id="path3611" style="fill:#be202e" />
<path d="m -46.179514,286.38427 c -0.502558,0.38693 -1.004124,0.78429 -1.498506,1.19682 l 0,0 c 0.494382,-0.41253 0.995948,-0.80989 1.498506,-1.19682 z" id="path3613" style="opacity:0.35;fill:#be202e" />
<path d="m -46.179514,286.38427 c -0.502558,0.38693 -1.004124,0.78429 -1.498506,1.19682 l 0,0 c 0.494382,-0.41253 0.995948,-0.80989 1.498506,-1.19682 z" id="path3624" style="fill:url(#SVGID_8_)" />
<path d="m -30.254972,292.46861 c 0.153663,-0.13318 0.314647,-0.25107 0.463193,-0.37852 -0.148463,0.12751 -0.303257,0.25016 -0.463193,0.37852 l 0,0 z" id="path3626" style="fill:#be202e" />
<path d="m -30.254972,292.46861 c 0.153663,-0.13318 0.314647,-0.25107 0.463193,-0.37852 -0.148463,0.12751 -0.303257,0.25016 -0.463193,0.37852 l 0,0 z" id="path3628" style="opacity:0.35;fill:#be202e" />
<path d="m -30.254972,292.46861 c 0.153663,-0.13318 0.314647,-0.25107 0.463193,-0.37852 -0.148463,0.12751 -0.303257,0.25016 -0.463193,0.37852 l 0,0 z" id="path3639" style="fill:url(#SVGID_9_)" />
<path d="m -30.233189,292.45636 c 0,0 0.0052,-0.006 0.01127,-0.001 l 0,0 0,0 0,0 c 0,0 -0.0052,0.006 -0.01127,0.001 z" id="path3641" style="fill:#be202e" />
<path d="m -30.233189,292.45636 c 0,0 0.0052,-0.006 0.01127,-0.001 l 0,0 0,0 0,0 c 0,0 -0.0052,0.006 -0.01127,0.001 z" id="path3643" style="opacity:0.35;fill:#be202e" />
<path d="m -30.233189,292.45636 c 0,0 0.0052,-0.006 0.01127,-0.001 l 0,0 0,0 0,0 c 0,0 -0.0052,0.006 -0.01127,0.001 z" id="path3654" style="fill:url(#SVGID_10_)" />
</g>
<text id="text3761" y="61.094482" x="290" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:40px;line-height:125%;font-family:Oswald;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" xml:space="preserve">
<tspan y="61.094482" x="290" id="tspan3763">The</tspan>
</text>
<text id="text3416" y="72.094482" x="356" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:57.5px;line-height:125%;font-family:Oswald;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" xml:space="preserve">
<tspan y="72.094482" x="356" id="tspan3418">Apache Velocity Project</tspan>
</text>
<path id="path3557" d="m 897.15,23.54449 0,1.58889 3.72099,0 0,10.51111 1.72469,0 0,-10.51111 3.74815,0 0,-1.58889 -9.19383,0 z m 21.49753,0 -4.15555,8.44691 -4.18272,-8.44691 -2.07778,0 0,12.1 1.58889,0 0,-9.60123 4.11482,8.32469 1.1,0 4.11481,-8.32469 0,9.60123 1.58889,0 0,-12.1 -2.09136,0 z" style="fill:#6d6e71" />
<text id="text3599" y="114.09448" x="400" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:35px;line-height:125%;font-family:Arial;text-align:start;letter-spacing:0.03em;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" xml:space="preserve">
<tspan y="114.09448" x="400" id="tspan3601">http://velocity.apache.org/</tspan>
</text>
</svg>
</a>
</div>
<div id="breadcrumb">
<ul><li><a href="http://www.apache.org">apache</a></li><li><a href="/">velocity</a></li><li><a href="/tools/">tools</a></li><li><a href="/tools/3.0/">3.0</a></li><li><a href="#">creating tools</a></li></ul>
</div>
<div id="middle">
<div id="leftnav">
<style type="text/css">
/* The following code is added by mdx_elementid.py
It was originally lifted from http://subversion.apache.org/style/site.css */
/*
* Hide class="elementid-permalink", except when an enclosing heading
* has the :hover property.
*/
.headerlink, .elementid-permalink {
visibility: hidden;
}
h2:hover > .headerlink, h3:hover > .headerlink, h1:hover > .headerlink, h6:hover > .headerlink, h4:hover > .headerlink, h5:hover > .headerlink, dt:hover > .elementid-permalink { visibility: visible }</style>
<h2 id="velocity-tools">Velocity Tools<a class="headerlink" href="#velocity-tools" title="Permanent link">&para;</a></h2>
<ul>
<li><a href="index.html">Overview</a></li>
<li><a href="/download.cgi#tools">Download</a></li>
</ul>
<h2 id="subprojects">Subprojects<a class="headerlink" href="#subprojects" title="Permanent link">&para;</a></h2>
<ul>
<li><a href="generic.html">GenericTools</a></li>
<li><a href="view.html">VelocityView</a></li>
</ul>
<h2 id="docs">Docs<a class="headerlink" href="#docs" title="Permanent link">&para;</a></h2>
<ul>
<li><a href="tools-summary.html">Standard Tools</a></li>
<li><a href="apidocs/index.html">Javadoc</a></li>
<li><a href="upgrading.html">Upgrading</a></li>
<li><a href="configuration.html">Configuration</a></li>
<li><a href="standalone.html">Standalone Use</a></li>
<li><a href="frameworks.html">Web Integration</a></li>
<li><a href="creating-tools.html">Creating Tools</a></li>
<li><a href="contributions.html">Contributions</a></li>
<li><a href="/engine/devel/glossary.html">Glossary</a></li>
<li><a href="http://wiki.apache.org/velocity/VelocityFAQ">FAQ</a></li>
<li><a href="http://wiki.apache.org/velocity/">Wiki</a></li>
</ul>
<h2 id="development">Development<a class="headerlink" href="#development" title="Permanent link">&para;</a></h2>
<ul>
<li><a href="changes.html">Changes</a></li>
<li><a href="dependencies.html">Dependencies</a></li>
<li><a href="index.html#helping-out">Participating</a></li>
<li><a href="http://velocity.apache.org/tools/releases/2.0/index.html#Subversion_Repository">Source Code</a></li>
<li><a href="http://issues.apache.org/jira/browse/VELTOOLS">Report Issue</a></li>
</ul>
<div id="bottom-nav">
<img src="/images/pbv90x30.png"/>
<div id="rss">
<a class="poweredBy" href="/rss/news.rss" title="Velocity News Feed"><img class="poweredBy" alt="Velocity News Feed" src="/images/feed-icon-24x24.jpg"></a>
</div>
<iframe src="http://www.apache.org/ads/buttonbar.html" style="border-width:0; float: left" frameborder="0" scrolling="no" width="135" height="265"></iframe>
</div>
</div>
<div id="content"><div class="section-content"><style type="text/css">
/* The following code is added by mdx_elementid.py
It was originally lifted from http://subversion.apache.org/style/site.css */
/*
* Hide class="elementid-permalink", except when an enclosing heading
* has the :hover property.
*/
.headerlink, .elementid-permalink {
visibility: hidden;
}
h2:hover > .headerlink, h3:hover > .headerlink, h1:hover > .headerlink, h6:hover > .headerlink, h4:hover > .headerlink, h5:hover > .headerlink, dt:hover > .elementid-permalink { visibility: visible }</style>
<h2 id="creating-tools">Creating Tools<a class="headerlink" href="#creating-tools" title="Permanent link">&para;</a></h2>
<p>This page contains advice and instructions for creating your own "tools". Of course, almost any POJO can be used as a tool, but there are ways to make your tools much more useful, maintainable and secure. The tips here should help you do that. If you have tips to add, email them to our <a href="http://velocity.apache.org/contact.html">development mailing list</a>.</p>
<div class="toc">
<ul>
<li><a href="#creating-tools">Creating Tools</a></li>
<li><a href="#basics">Basics</a></li>
<li><a href="#conventions">Conventions</a><ul>
<li><a href="#tool-keysnames">Tool Keys/Names</a></li>
<li><a href="#tool-properties">Tool Properties</a></li>
</ul>
</li>
<li><a href="#standard-tool-properties">Standard Tool Properties</a><ul>
<li><a href="#standard-properties-in-a-standalone-environment">Standard Properties in a Standalone Environment</a></li>
<li><a href="#standard-properties-in-a-web-environment">Standard Properties in a Web Environment</a></li>
</ul>
</li>
<li><a href="#annotations">Annotations</a></li>
<li><a href="#support-classes">Support Classes</a><ul>
<li><a href="#base-classes">Base Classes</a></li>
<li><a href="#utility-classes">Utility Classes</a></li>
</ul>
</li>
<li><a href="#designing-template-friendly-interfaces">Designing Template-Friendly Interfaces</a><ul>
<li><a href="#be-robust">Be Robust</a></li>
<li><a href="#be-flexible">Be Flexible</a></li>
<li><a href="#be-careful">Be Careful</a></li>
<li><a href="#be-fluent">Be Fluent</a></li>
</ul>
</li>
</ul>
</div>
<h2 id="basics">Basics<a class="headerlink" href="#basics" title="Permanent link">&para;</a></h2>
<p>Any class you wish to use as a tool must be declared public and have a public, no-argument constructor.</p>
<h2 id="conventions">Conventions<a class="headerlink" href="#conventions" title="Permanent link">&para;</a></h2>
<h3 id="tool-keysnames">Tool Keys/Names<a class="headerlink" href="#tool-keysnames" title="Permanent link">&para;</a></h3>
<p>As of VelocityTools 2, the toolbox support can now automatically determine the key name for a tool from its classname. So, a tool named org.com.FooTool would be assigned the key $foo in your templates, tool named org.com.FooBarTool would be $fooBar, and a tool named org.com.FooBar would be also be $fooBar.</p>
<p>If you would prefer to give your org.com.FooBar tool the key $foob, you can use the <code>org.apache.velocity.tools.config.DefaultKey</code> annotation like this:</p>
<div class="codehilite"><pre><span class="kn">package</span> <span class="nn">org.com</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">org.apache.velocity.tools.config.DefaultKey</span><span class="o">;</span>
<span class="nd">@DefaultKey</span><span class="o">(</span><span class="s">&quot;foob&quot;</span><span class="o">)</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">FooBar</span> <span class="o">{</span>
<span class="o">...</span>
<span class="o">}</span>
</pre></div>
<p>Of course, you or your tool users can always override your intended key by specifying a different one in the configuration. Configured key values take precedence over @DefaultKey annotations, and the annotations take precedence over the tool's class name.</p>
<h3 id="tool-properties">Tool Properties<a class="headerlink" href="#tool-properties" title="Permanent link">&para;</a></h3>
<p>If you want to allow your tool to be configured, you have two options: </p>
<ul>
<li>add a public setter for each property</li>
<li>add a <code>public void configure(Map props)</code> method</li>
</ul>
<p>You can, of course, do both, but if you do so keep in mind that the specific setters will be called before the configure() method. The application of configuration properties to specific setters is done using <code>org.apache.commons.beanutils.PropertyUtils</code> from the Commons-BeanUtils project, so the rules follow the typical bean property conventions.</p>
<p>One thing to consider here is the scope of your tool and whether or not you want the template authors to be able to alter tool settings from within the template. Remember, templates can call any public method on any public class, so your specific property setters will be accesible. This is almost always a bad thing for application or session scoped tools as it would make the tool non-threadsafe, and may or may not matter for a request scoped tool depending on how you use it. If you cannot rely on your template authors to avoid using those setters or just want to make sure nothing can be changed from within the template, you will probably want to use the configure() method and have your tool extend SafeConfig or one of its subclasses. (This is discussed more later.)</p>
<h2 id="standard-tool-properties">Standard Tool Properties<a class="headerlink" href="#standard-tool-properties" title="Permanent link">&para;</a></h2>
<p>Apart from custom properties you may define for your custom tool, the following properties are always defined and accessible to it, via the <code>configure(Map)</code> method or the appropriate setter.</p>
<h3 id="standard-properties-in-a-standalone-environment">Standard Properties in a Standalone Environment<a class="headerlink" href="#standard-properties-in-a-standalone-environment" title="Permanent link">&para;</a></h3>
<ul>
<li><code>key</code>: the context key this tool was mapped to.</li>
<li><code>velocityContext</code>: the current Velocity context (an <code>org.apache.velocity.tools.ToolContext</code> object)</li>
</ul>
<h3 id="standard-properties-in-a-web-environment">Standard Properties in a Web Environment<a class="headerlink" href="#standard-properties-in-a-web-environment" title="Permanent link">&para;</a></h3>
<ul>
<li><code>key</code>: the context key this tool was mapped to.</li>
<li><code>velocityEngine</code>: the Velocity engine (an <code>org.apache.velocity.app.VelocityEngine</code> object).</li>
<li><code>log</code>: the Velocity log (an <code>org.slf4j.Logger</code> object).</li>
<li><code>locale</code>: the tool's locale.</li>
<li><code>scope</code>: the tool's scope: <code>request</code>, <code>session</code> or <code>application</code>.</li>
<li><code>servletContext</code>: the current J2EE servlet context, used to store all application-scoped properties (a <code>javax.servlet.ServletContext</code> object).</li>
<li><code>session</code>: the current J2EE session, null if it hasn't been created (a <code>javax.servlet.http.HttpSession</code> object). Contains the current session at the time of the tool's initialization for application scoped tools, generally relevant only for session and request scoped tools.</li>
<li><code>request</code>: the current J2EE request (a <code>javax.servlet.http.HttpServletRequest</code> object). Contains the current request at the time of the tool's initialization for session and application scoped tools, so generally relevant only for request scoped tools.</li>
<li><code>response</code>: the current J2EE response (a <code>javax.servlet.http.HttpServletResponse</code> object). Contains the current response at the time of the tool's initialization for session and application scoped tools, so generally relevant only for request scoped tools.</li>
<li>requestPath`: the current request path portion of the URI. Generally relevant only for request scoped tools.</li>
<li><code>velocityContext</code>: the current Velocity context (an <code>org.apache.velocity.tools.view.context.ChainedContext</code> object). Generally relevant only for request scoped tools.</li>
</ul>
<h2 id="annotations">Annotations<a class="headerlink" href="#annotations" title="Permanent link">&para;</a></h2>
<p>There are three Annotations provided for tool authors: <a href="apidocs/org/apache/velocity/tools/config/DefaultKey.html">DefaultKey</a>, <a href="apidocs/org/apache/velocity/tools/config/InvalidScope.html">InvalidScope</a> and <a href="apidocs/org/apache/velocity/tools/config/ValidScope.html">ValidScope</a>.</p>
<p>As described above, the @DefaultKey annotation is used to specify a default key for your tool. The @InvalidScope and @ValidScope annotations allow you to restrict the <a href="apidocs/org/apache/velocity/tools/Scope.html">Scope</a>(s) in which the tool can be used in either negative or positive terms. When described positively using the @ValidScope annotation, the tool may <strong>only</strong> be used in a toolbox with the specified scope. If placed in any other toolbox, an <code>org.apache.velocity.tools.config.InvalidScopeException</code> will be thrown. Using @InvalidScope, on the other hand, allows you reject specific scope(s), whilst implicitly allowing any others.</p>
<p>Here's a scope annotation example:</p>
<div class="codehilite"><pre><span class="nd">@InvalidScope</span><span class="o">({</span><span class="n">Scope</span><span class="o">.</span><span class="na">APPLICATION</span><span class="o">,</span><span class="n">Scope</span><span class="o">.</span><span class="na">SESSION</span><span class="o">})</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">PagerTool</span>
<span class="o">{</span>
<span class="o">...</span>
<span class="o">}</span>
</pre></div>
<h2 id="support-classes">Support Classes<a class="headerlink" href="#support-classes" title="Permanent link">&para;</a></h2>
<h3 id="base-classes">Base Classes<a class="headerlink" href="#base-classes" title="Permanent link">&para;</a></h3>
<p><a href="apidocs/org/apache/velocity/tools/generic/SafeConfig.html">SafeConfig</a> - This serves as a base class for tools who need to have their configuration be read-only for thread-safety or other reasons. By default, tools which extend this can only be configured once.</p>
<p><a href="apidocs/org/apache/velocity/tools/generic/LocaleConfig.html">LocaleConfig</a> - Subclass of SafeConfig that has standardized support for configuring a Locale for the tool to use as its default.</p>
<p><a href="apidocs/org/apache/velocity/tools/generic/FormatConfig.html">FormatConfig</a> - Subclass of LocaleConfig that has standardized support for providing a format string value for the tool to use as its default.</p>
<h3 id="utility-classes">Utility Classes<a class="headerlink" href="#utility-classes" title="Permanent link">&para;</a></h3>
<p><a href="apidocs/org/apache/velocity/tools/ClassUtils.html">ClassUtils</a> - Provides utility methods for loading classes, finding methods, accessing static field values, and more.</p>
<p><a href="apidocs/org/apache/velocity/tools/ConversionUtils.html">ConversionUtils</a> - Provides utility methods for common type conversions/value parsing.</p>
<p><a href="apidocs/org/apache/velocity/tools/view/ServletUtils.html">ServletUtils</a> - Utility methods for the servlet environment, mostly centered on accessing the VelocityView or tool instances handled thereby.</p>
<p>[ValueParser] (apidocs/org/apache/velocity/tools/generic/ValueParser.html) - Used to retrieve and parse (aka convert) String values pulled from a map; this is mostly commonly used directly by other tools rather than within templates.</p>
<h2 id="designing-template-friendly-interfaces">Designing Template-Friendly Interfaces<a class="headerlink" href="#designing-template-friendly-interfaces" title="Permanent link">&para;</a></h2>
<p>Following a few best-practices can make your tools much more elegant and friendly to template authors.</p>
<ul>
<li><a href="#Be-Robust">Be robust</a>. Catch exceptions and return <code>null</code> on errors.</li>
<li><a href="#Be-Flexible">Be flexible</a>. Have methods accept <code>Object</code> when possible.</li>
<li><a href="#Be-Careful">Be cafeful</a>. Choose scope carefully and be aware of thread safety issues.</li>
<li><a href="#Be-Fluent">Be fluent</a>. Subtools or <code>get(key)</code> methods can make a clear and flexible API.</li>
</ul>
<h3 id="be-robust">Be Robust<a class="headerlink" href="#be-robust" title="Permanent link">&para;</a></h3>
<p>Always return null on errors! No Exceptions! Ok, maybe there are some exceptions if you are sure that's what you want your tool to do. Just be aware that this will likely surprise the user because uncaught exceptions halt template processing at the point the exception is thrown. If the output of the template is not buffered, this will result in an awkward, partial rendering. So, if you are going to let an exception through, make sure it is worth halting everything for. Often it is sufficient to return null, thus allowing the failed reference to appear in the output like this:</p>
<div class="codehilite"><pre><span class="p">$</span><span class="nv">mytool</span><span class="p">.</span><span class="nv">somemethod</span><span class="p">(</span><span class="s1">&#39;bad input&#39;</span><span class="p">)</span><span class="x"></span>
</pre></div>
<p>This, of course, assumes that quiet notation is not being used for that reference. For this reason, it may be prudent to give your tool access to a logging facility in order to log exceptions and make sure important errors are not silently swallowed. Standard tool management for VelocityTools (even just GenericTools) makes the result of <code>velocityEngine.getLog()</code> available to tools as a property under the key "log". So log access can be added as simply as adding a <code>public void setLog(org.slf4j.Logger log)</code> method and utilizing the provided Log instance. Or, simply call <code>LoggerFactory.getLogger(MyTool.class)</code> to get a static logger dedicated to your custom tool.</p>
<p>If you wish to toggle the exception catching or, more importantly, if you prefer to catch exceptions globally with a Velocity Event Handler, then have your tool watch for the "catchExceptions" property. This is <code>false</code> by default, but if the VelocityEngine has a MethodExceptionEventHandler configured, then it will be automatically set to <code>true</code>. Again, just add a <code>public void setCatchExceptions(boolean catch)</code> method to your tool or watch for the "catchExceptions" property in your <code>public void configure(Map props)</code> method. See <a href="apidocs/org/apache/velocity/tools/generic/RenderTool.html">RenderTool</a> for an example of this.</p>
<h3 id="be-flexible">Be Flexible<a class="headerlink" href="#be-flexible" title="Permanent link">&para;</a></h3>
<p>Variables in templates are strongly, but dynamically typed. As the current type (or whole subject of typing) is often not transparently obvious to the person working on the template, it is best to accept <code>Object</code> for most method parameters and handle any necessary conversions in your tool (either through overloading or actual conversion). This way template authors and maintainers don't have to worry about the variable being passed to tool methods.</p>
<p>Of course, there may be times when you wish to restrict what a method can accept or when a method is public for use by other classes, not templates. If the method is not meant to be used by the template, ignore this advice and pay careful attention to the <a href="#Be_Careful">advice below</a>. If you have other reasons for restricting the types accepted by a method that you do intend to be used, just be sure to document this plainly so it is easy to discover why the method isn't being called and what parameters it expects to receive.</p>
<h3 id="be-careful">Be Careful<a class="headerlink" href="#be-careful" title="Permanent link">&para;</a></h3>
<p>The first thing to remember is that all public methods declared in public classes may be called from templates. If it is imperative that a method not be called from a template, you must either change its permissions, its class's permissions or else put some sort of guard into the implementation of the method that renders it harmless when used by a template. See the implementation of <code>configure(Map)</code> in <a href="apidocs/org/apache/velocity/tools/generic/SafeConfig.html">SafeConfig</a> for an example of the latter option.</p>
<p>The second thing to think about is thread-safety. If your tool maintains internal state that is in any way changed by the calling of its public methods, then your tool is not thread safe. The only thread-safe tools are those that maintain no state or are otherwise immutable (e.g. return new, copied instances w/changed state and leave original unchanged). If your tool is not thread-safe, you should seriously consider <a href="#Annotations">using a scope-limiting annotation</a> to prevent such problems.</p>
<p>Thread-safety is, of course, most important if your tool is meant to be used in "application" or "session" scoped toolboxes for web applications or any other multi-threaded application. Allowing access to non-thread-safe tools in those scopes can lead to all sorts of unpleasant problems. Please note that sometimes request scope isn't safe either! if you #parse subtemplates or are otherwise composing your page of separate pieces (e.g. Tiles) that may not know what each other are doing at any one time.</p>
<p><a href="apidocs/org/apache/velocity/tools/generic/SafeConfig.html">SafeConfig</a> and its subclasses can help you have safely configurable tools in any scope. They do this by only allowing the public <code>configure(Map)</code> method to be called once. All other configuration methods should then be declared protected and the tool cannot be re-configured by a template. This technique may, in the future, be changed to allow you to replace the configure(Map) method with a constructor that takes a Map of configuration properties, but for various reasons, this is not currently the case.</p>
<p>As a final note here, if you really have good reason to use a mutable, non-thread-safe application or session scoped tool, tool path restrictions can help you limit possible damage here. Of course, this is something done purely at the <a href="configuration.html">configuration</a> level and cannot be currently defined by the tool itself.</p>
<h3 id="be-fluent">Be Fluent<a class="headerlink" href="#be-fluent" title="Permanent link">&para;</a></h3>
<p>When writing tools, you should take care in how you design its methods to make the resulting syntax in the templates clear, succinct and simple and thus decrease typos and "visual clutter". Readability is important for maintainability and things can get ugly and unreadable fast if you aren't careful. Typical Java method naming tends to be fairly verbose, which works fine in Java development environment with auto-complete and Java conventions to respect. It wouldn't be out of line for a BubbleGum class to have a method <code>getStickWithName(String name)</code>, but using that in a template (e.g. <code>$bubbleGum.getStickWithName('bigred')</code>) is not ideal. It would be much better to have a simple <code>get(String name)</code> method to simplify that down to just <code>$bubbleGum.bigred</code>.</p>
<p>One of your best assets when trying to simplify your tools' template-facing interface is the fact that Velocity includes <code>get('name')</code> in the method lookup for <code>$tool.name</code>. For some tools, this can greatly simplify the syntax, as shown above. Also, by encouraging the use of such short syntax, you give yourself greater flexibility in making changes to the tool later, which you would not have if the template references were all explicit method calls like <code>$tool.getName()</code>.</p>
<p>Another handy technique available to tool author's like yourself is the use of what we call subtools. These are examples of the <a href="http://www.martinfowler.com/bliki/FluentInterface.html">fluent interface pattern</a>. Essentially, the idea is that most methods return either the tool itself again, or else another object that has a similar or otherwise naturally subsequent interface. Such "fluent" interfaces tend to be very natural, clear and succinct, both saving keystrokes and keeping templates easy to read and maintain.</p>
<p>In VelocityTools' standard set of tools, this practice is put into place often and in a few different ways. Here's a few examples, out of the many tools which make good use of fluent interfaces and a <code>get(key)</code> method.</p>
<ul>
<li><a href="apidocs/org/apache/velocity/tools/generic/ResourceTool.html">ResourceTool</a> uses subtools to allow you to type <code>$text.org.com.Foo</code> instead of <code>$text.get('org.com.Foo')</code> or worse, something very java-ish like <code>$text.getResourceFromBundle('messages.properties', 'org.com.Foo')</code>. This is achieved by having the get() method return a new instance of its <code>Key</code> subclass that carries with it the value to be gotten. The Key, in turn, has a get() method that does the same (and more), returning a new Key instance that carries the concatenated values of both get() calls. And so on it goes, until the final resulting value is rendered by Velocity calling the last Key's toString() method.</li>
<li><a href="apidocs/org/apache/velocity/tools/view/LinkTool.html">LinkTool</a> takes a different approach. Rather than use a subclass as the subtool, it uses itself. Almost every method in LinkTool returns a copy of the original instance with the addition of the latest value. Both this approach and that of ResourceTool provide great flexibility to the template author. They can use the tools however they wish, with no concerns about thread collisions, shared state or lifecycle. And with modern JVMs, the performance cost of this flexibility is minimal--light object creation and reflection have become cheap and fast, and short-lived instances like those created in the process are quickly garbage collected.</li>
<li><a href="apidocs/org/apache/velocity/tools/generic/ClassTool.html">ClassTool</a> uses subtools to a somewhat different end. Rather than simply replicating the interface of the parent, the subtools provide a natural interface wrapping around the result of the previous call. This is done because the reflection API provided by JavaSE is not at all template-friendly. ClassTool wraps almost all returned methods, contructors and fields with subtools that continue to provide a natural, template-friendly interface.</li>
<li><a href="apidocs/org/apache/velocity/tools/generic/AlternatorTool.html">AlternatorTool</a> falls into a very simple class of "subtool" uses. In this case, the AlternatorTool class serves only as a factory for creating instances of the separate Alternator class. In this case, the so-called "subtool" is really the main thing and the tool exists solely to provide access to it.</li>
<li><a href="apidocs/org/apache/velocity/tools/generic/LoopTool.html">LoopTool</a> might be the strangest of them all. It is unlikely that you would find need to create such a tool, but if you are curious, read on. LoopTool exists to add value and convenience to using the #foreach directive. The methods on the main class are either used when starting a #foreach loop or else for use during said loop. The starting ones return a "subtool" of sorts called <a href="apidocs/org/apache/velocity/tools/generic/LoopTool.ManagedIterator.html">ManagedIterator</a>, which provides a few fluent methods for refinement of the loop control. The final result of those, however, is largely just used by #foreach internally. While the loop is going, however, the original LoopTool itself may be directly used to observe and/or influence the ManagedIterator being used internally by #foreach. This is because the main LoopTool keeps track of all its subtool instances in a Stack. This is very different from most subtool situations, where the tool and subtool are immediately disassociated.</li>
</ul></div></div>
<hr/>
<div id="copyright">
Copyright &#169; 2020 The Apache Software Foundation, Licensed under the <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache License, Version 2.0</a>.<br/>Apache and the Apache feather logo are trademarks of The Apache Software Foundation.
</div>
</div>
</div>
</body>
</html>