##### Coverage Report - org.apache.turbine.services.pull.tools.TemplateLink

Classes in this File | Line Coverage | Branch Coverage | Complexity
TemplateLink |
18% | 15/81
25% | 2/8
| 1.1176470588235294;1,118

1 |  |
     package org.apache.turbine.services.pull.tools;
2 |  |
3 |  |
4 |  |
     /*
5 |  |
      * Licensed to the Apache Software Foundation (ASF) under one
6 |  |
      * or more contributor license agreements.  See the NOTICE file
7 |  |
      * distributed with this work for additional information
8 |  |
      * regarding copyright ownership.  The ASF licenses this file
9 |  |
      * to you under the Apache License, Version 2.0 (the
10 |  |
      * "License"); you may not use this file except in compliance
11 |  |
      * with the License.  You may obtain a copy of the License at
12 |  |
      *
13 |  |
      *   http://www.apache.org/licenses/LICENSE-2.0
14 |  |
      *
15 |  |
      * Unless required by applicable law or agreed to in writing,
16 |  |
      * software distributed under the License is distributed on an
17 |  |
      * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18 |  |
      * KIND, either express or implied.  See the License for the
19 |  |
      * specific language governing permissions and limitations
20 |  |
      * under the License.
21 |  |
      */
22 |  |
23 |  |
24 |  |
     import org.apache.commons.configuration.Configuration;
25 |  |
     import org.apache.commons.logging.Log;
26 |  |
     import org.apache.commons.logging.LogFactory;
27 |  |
     import org.apache.fulcrum.parser.ParameterParser;
28 |  |
     import org.apache.turbine.Turbine;
29 |  |
     import org.apache.turbine.pipeline.PipelineData;
30 |  |
     import org.apache.turbine.services.pull.ApplicationTool;
31 |  |
     import org.apache.turbine.util.RunData;
32 |  |
     import org.apache.turbine.util.uri.TemplateURI;
33 |  |
34 |  |
     /**
35 |  |
      * This is a pull to to be used in Templates to convert links in
36 |  |
      * Templates into the correct references.
37 |  |
      *
38 |  |
      * The pull service might insert this tool into the Context.
39 |  |
      * in templates.  Here's an example of its Velocity use:
40 |  |
      *
41 |  |
      * <p><code>
42 |  |
      * $link.setPage("index.vm").addPathInfo("hello","world")
43 |  |
      * This would return: http://foo.com/Turbine/template/index.vm/hello/world
44 |  |
      * </code>
45 |  |
      *
46 |  |
      * <p>
47 |  |
      *
48 |  |
      * This is an application pull tool for the template system. You should <b>not</b>
49 |  |
      * use it in a normal application!
50 |  |
      *
51 |  |
      * @author <a href="mbryson@mont.mindspring.com">Dave Bryson</a>
52 |  |
      * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a>
53 |  |
      * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
54 |  |
      * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
55 |  |
      * @author <a href="mailto:peter@courcoux.biz">Peter Courcoux</a>
56 |  |
      * @version $Id: TemplateLink.java 1773378 2016-12-09 13:19:59Z tv $
57 |  |
      */
58 |  |
59 |  |
     public class TemplateLink
60 |  |
         implements ApplicationTool
61 |  |
     {
62 |  |
         /** Prefix for Parameters for this tool */
63 |  |
         public static final String TEMPLATE_LINK_PREFIX = "tool.link";
64 |  |
65 |  |
         /** Should this tool return relative URIs or absolute? Default: Absolute. */
66 |  |
         public static final String TEMPLATE_LINK_RELATIVE_KEY = "want.relative";
67 |  |
68 |  |
         /** Default Value for TEMPLATE_LINK_RELATIVE_KEY */
69 |  |
         public static final boolean TEMPLATE_LINK_RELATIVE_DEFAULT = false;
70 |  |
71 |  |
72 |  |
         /** Do we want a relative link? */
73 | 8 |
         protected boolean wantRelative = false;
74 |  |
75 |  |
         /** cache of the template name for getPage() */
76 | 8 |
         protected String template = null;
77 |  |
78 |  |
         /** TemplateURI used as backend for this object */
79 | 8 |
         protected TemplateURI templateURI = null;
80 |  |
81 |  |
         /** Logging */
82 | 17 |
         private static Log log = LogFactory.getLog(TemplateLink.class);
83 |  |
84 |  |
         /**
85 |  |
          * Default constructor
86 |  |
          * <p>
87 |  |
          * The init method must be called before use.
88 |  |
          */
89 |  |
         public TemplateLink()
90 | 8 |
         {
91 |  |
             // empty
92 | 8 |
         }
93 |  |
94 |  |
         /*
95 |  |
          * ========================================================================
96 |  |
          *
97 |  |
          * Application Tool Interface
98 |  |
          *
99 |  |
          * ========================================================================
100 |  |
          *
101 |  |
          */
102 |  |
103 |  |
         /**
104 |  |
          * This will initialize a TemplateLink object that was
105 |  |
          * constructed with the default constructor (ApplicationTool
106 |  |
          * method).
107 |  |
          *
108 |  |
          * @param data assumed to be a PipelineData object
109 |  |
          */
110 |  |
         @Override
111 |  |
         public void init(Object data)
112 |  |
         {
113 |  |
             // we just blithely cast to RunData as if another object
114 |  |
             // or null is passed in we'll throw an appropriate runtime
115 |  |
             // exception.
116 | 9 |
             if (data instanceof PipelineData)
117 |  |
             {
118 | 9 |
                 PipelineData pipelineData = (PipelineData) data;
119 | 9 |
                 RunData runData = (RunData)pipelineData;
120 | 9 |
                 templateURI = new TemplateURI(runData);
121 | 9 |
             }
122 |  |
             else
123 |  |
             {
124 | 0 |
                 templateURI = new TemplateURI((RunData) data);
125 |  |
             }
126 |  |
127 | 9 |
             Configuration conf =
128 |  |
                     Turbine.getConfiguration().subset(TEMPLATE_LINK_PREFIX);
129 |  |
130 | 9 |
             if (conf != null)
131 |  |
             {
132 | 9 |
                 wantRelative = conf.getBoolean(TEMPLATE_LINK_RELATIVE_KEY,
133 |  |
                         TEMPLATE_LINK_RELATIVE_DEFAULT);
134 |  |
             }
135 |  |
136 | 9 |
         }
137 |  |
138 |  |
         /**
139 |  |
          * Refresh method - does nothing
140 |  |
          */
141 |  |
         @Override
142 |  |
         public void refresh()
143 |  |
         {
144 |  |
             // empty
145 | 0 |
         }
146 |  |
147 |  |
         /*
148 |  |
          * ========================================================================
149 |  |
          *
150 |  |
          * getter/setter
151 |  |
          *
152 |  |
          * All setter return "this" so you can "chain" them together in the Context
153 |  |
          *
154 |  |
          * ========================================================================
155 |  |
          */
156 |  |
157 |  |
         /**
158 |  |
          * This will turn off the execution of res.encodeURL()
159 |  |
          * by making res == null. This is a hack for cases
160 |  |
          * where you don't want to see the session information
161 |  |
          *
162 |  |
          * @return A <code>TemplateLink</code> (self).
163 |  |
          */
164 |  |
         public TemplateLink setEncodeURLOff()
165 |  |
         {
166 | 0 |
             templateURI.clearResponse();
167 | 0 |
             return this;
168 |  |
         }
169 |  |
170 |  |
         /**
171 |  |
          * Sets the template variable used by the Template Service.
172 |  |
          *
173 |  |
          * @param template A String with the template name.
174 |  |
          * @return A TemplateLink.
175 |  |
          */
176 |  |
         public TemplateLink setPage(String template)
177 |  |
         {
178 | 0 |
             log.debug("setPage(" + template + ")");
179 | 0 |
             this.template = template;
180 | 0 |
             templateURI.setTemplate(template);
181 | 0 |
             return this;
182 |  |
         }
183 |  |
184 |  |
         /**
185 |  |
          * Gets the template variable used by the Template Service.
186 |  |
          * It is only available after setPage() has been called.
187 |  |
          *
188 |  |
          * @return The template name.
189 |  |
          */
190 |  |
         public String getPage()
191 |  |
         {
192 | 0 |
             return template;
193 |  |
         }
194 |  |
195 |  |
         /**
196 |  |
          * Sets the action= value for this URL.
197 |  |
          *
198 |  |
          * By default it adds the information to the path_info instead
199 |  |
          * of the query data.
200 |  |
          *
201 |  |
          * @param action A String with the action value.
202 |  |
          * @return A <code>TemplateLink</code> (self).
203 |  |
          */
204 |  |
         public TemplateLink setAction(String action)
205 |  |
         {
206 | 0 |
             log.debug("setAction(" + action + ")");
207 | 0 |
             templateURI.setAction(action);
208 | 0 |
             return this;
209 |  |
         }
210 |  |
211 |  |
         /**
212 |  |
          * Sets the action= and eventSubmit= values for this URL.
213 |  |
          *
214 |  |
          * By default it adds the information to the path_info instead
215 |  |
          * of the query data.
216 |  |
          *
217 |  |
          * @param action A String with the action value.
218 |  |
          * @param event A string with the event name.
219 |  |
          * @return A <code>TemplateLink</code> (self).
220 |  |
          */
221 |  |
         public TemplateLink setActionEvent(String action, String event)
222 |  |
         {
223 | 0 |
             log.debug("setActionEvent(" + action + ", "+ event +")");
224 | 0 |
             templateURI.setActionEvent(action, event);
225 | 0 |
             return this;
226 |  |
         }
227 |  |
228 |  |
         /**
229 |  |
          * Sets the screen= value for this URL.
230 |  |
          *
231 |  |
          * By default it adds the information to the path_info instead
232 |  |
          * of the query data.
233 |  |
          *
234 |  |
          * @param screen A String with the screen value.
235 |  |
          * @return A <code>TemplateLink</code> (self).
236 |  |
          */
237 |  |
         public TemplateLink setScreen(String screen)
238 |  |
         {
239 | 0 |
             log.debug("setScreen(" + screen + ")");
240 | 0 |
             templateURI.setScreen(screen);
241 | 0 |
             return this;
242 |  |
         }
243 |  |
244 |  |
         /**
245 |  |
          * Sets a reference anchor (#ref).
246 |  |
          *
247 |  |
          * @param reference A String containing the reference.
248 |  |
          * @return A <code>TemplateLink</code> (self).
249 |  |
          */
250 |  |
         public TemplateLink setReference(String reference)
251 |  |
         {
252 | 0 |
             templateURI.setReference(reference);
253 | 0 |
             return this;
254 |  |
         }
255 |  |
256 |  |
         /**
257 |  |
          * Returns the current reference anchor.
258 |  |
          *
259 |  |
          * @return A String containing the reference.
260 |  |
          */
261 |  |
         public String getReference()
262 |  |
         {
263 | 0 |
             return templateURI.getReference();
264 |  |
         }
265 |  |
266 |  |
         /*
267 |  |
          * ========================================================================
268 |  |
          *
269 |  |
          * Adding and removing Data from the Path Info and Query Data
270 |  |
          *
271 |  |
          * ========================================================================
272 |  |
          */
273 |  |
274 |  |
275 |  |
         /**
276 |  |
          * Adds a name=value pair for every entry in a ParameterParser
277 |  |
          * object to the path_info string.
278 |  |
          *
279 |  |
          * @param pp A ParameterParser.
280 |  |
          * @return A <code>TemplateLink</code> (self).
281 |  |
          */
282 |  |
         public TemplateLink addPathInfo(ParameterParser pp)
283 |  |
         {
284 | 0 |
             templateURI.addPathInfo(pp);
285 | 0 |
             return this;
286 |  |
         }
287 |  |
288 |  |
         /**
289 |  |
          * Adds a name=value pair to the path_info string.
290 |  |
          *
291 |  |
          * @param name A String with the name to add.
292 |  |
          * @param value An Object with the value to add.
293 |  |
          * @return A <code>TemplateLink</code> (self).
294 |  |
          */
295 |  |
         public TemplateLink addPathInfo(String name, Object value)
296 |  |
         {
297 | 0 |
             templateURI.addPathInfo(name, value);
298 | 0 |
             return this;
299 |  |
         }
300 |  |
301 |  |
         /**
302 |  |
          * Adds a name=value pair to the path_info string.
303 |  |
          *
304 |  |
          * @param name A String with the name to add.
305 |  |
          * @param value A String with the value to add.
306 |  |
          * @return A <code>TemplateLink</code> (self).
307 |  |
          */
308 |  |
         public TemplateLink addPathInfo(String name, String value)
309 |  |
         {
310 | 0 |
             templateURI.addPathInfo(name, value);
311 | 0 |
             return this;
312 |  |
         }
313 |  |
314 |  |
         /**
315 |  |
          * Adds a name=value pair to the path_info string.
316 |  |
          *
317 |  |
          * @param name A String with the name to add.
318 |  |
          * @param value A double with the value to add.
319 |  |
          * @return A <code>TemplateLink</code> (self).
320 |  |
          */
321 |  |
         public TemplateLink addPathInfo(String name, double value)
322 |  |
         {
323 | 0 |
             templateURI.addPathInfo(name, value);
324 | 0 |
             return this;
325 |  |
         }
326 |  |
327 |  |
         /**
328 |  |
          * Adds a name=value pair to the path_info string.
329 |  |
          *
330 |  |
          * @param name A String with the name to add.
331 |  |
          * @param value An int with the value to add.
332 |  |
          * @return A <code>TemplateLink</code> (self).
333 |  |
          */
334 |  |
         public TemplateLink addPathInfo(String name, int value)
335 |  |
         {
336 | 0 |
             templateURI.addPathInfo(name, value);
337 | 0 |
             return this;
338 |  |
         }
339 |  |
340 |  |
         /**
341 |  |
          * Adds a name=value pair to the path_info string.
342 |  |
          *
343 |  |
          * @param name A String with the name to add.
344 |  |
          * @param value A long with the value to add.
345 |  |
          * @return A <code>TemplateLink</code> (self).
346 |  |
          */
347 |  |
         public TemplateLink addPathInfo(String name, long value)
348 |  |
         {
349 | 0 |
             templateURI.addPathInfo(name, value);
350 | 0 |
             return this;
351 |  |
         }
352 |  |
353 |  |
         /**
354 |  |
          * Adds a name=value pair to the query string.
355 |  |
          *
356 |  |
          * @param name A String with the name to add.
357 |  |
          * @param value An Object with the value to add.
358 |  |
          * @return A <code>TemplateLink</code> (self).
359 |  |
          */
360 |  |
         public TemplateLink addQueryData(String name, Object value)
361 |  |
         {
362 | 0 |
             templateURI.addQueryData(name, value);
363 | 0 |
             return this;
364 |  |
         }
365 |  |
366 |  |
         /**
367 |  |
          * Adds a name=value pair to the query string.
368 |  |
          *
369 |  |
          * @param name A String with the name to add.
370 |  |
          * @param value A String with the value to add.
371 |  |
          * @return A <code>TemplateLink</code> (self).
372 |  |
          */
373 |  |
         public TemplateLink addQueryData(String name, String value)
374 |  |
         {
375 | 0 |
             templateURI.addQueryData(name, value);
376 | 0 |
             return this;
377 |  |
         }
378 |  |
379 |  |
         /**
380 |  |
          * Adds a name=value pair to the query string.
381 |  |
          *
382 |  |
          * @param name A String with the name to add.
383 |  |
          * @param value A double with the value to add.
384 |  |
          * @return A <code>TemplateLink</code> (self).
385 |  |
          */
386 |  |
         public TemplateLink addQueryData(String name, double value)
387 |  |
         {
388 | 0 |
             templateURI.addQueryData(name, value);
389 | 0 |
             return this;
390 |  |
         }
391 |  |
392 |  |
         /**
393 |  |
          * Adds a name=value pair to the query string.
394 |  |
          *
395 |  |
          * @param name A String with the name to add.
396 |  |
          * @param value An int with the value to add.
397 |  |
          * @return A <code>TemplateLink</code> (self).
398 |  |
          */
399 |  |
         public TemplateLink addQueryData(String name, int value)
400 |  |
         {
401 | 0 |
             templateURI.addQueryData(name, value);
402 | 0 |
             return this;
403 |  |
         }
404 |  |
405 |  |
         /**
406 |  |
          * Adds a name=value pair to the query string.
407 |  |
          *
408 |  |
          * @param name A String with the name to add.
409 |  |
          * @param value A long with the value to add.
410 |  |
          * @return A <code>TemplateLink</code> (self).
411 |  |
          */
412 |  |
         public TemplateLink addQueryData(String name, long value)
413 |  |
         {
414 | 0 |
             templateURI.addQueryData(name, value);
415 | 0 |
             return this;
416 |  |
         }
417 |  |
418 |  |
         /**
419 |  |
          * Adds a name=value pair for every entry in a ParameterParser
420 |  |
          * object to the query string.
421 |  |
          *
422 |  |
          * @param pp A ParameterParser.
423 |  |
          * @return A <code>TemplateLink</code> (self).
424 |  |
          */
425 |  |
         public TemplateLink addQueryData(ParameterParser pp)
426 |  |
         {
427 | 0 |
             templateURI.addQueryData(pp);
428 | 0 |
             return this;
429 |  |
         }
430 |  |
431 |  |
         /**
432 |  |
          * Removes all the path info elements.
433 |  |
          *
434 |  |
          * @return A <code>TemplateLink</code> (self).
435 |  |
          */
436 |  |
         public TemplateLink removePathInfo()
437 |  |
         {
438 | 0 |
             templateURI.removePathInfo();
439 | 0 |
             return this;
440 |  |
         }
441 |  |
442 |  |
         /**
443 |  |
          * Removes a name=value pair from the path info.
444 |  |
          *
445 |  |
          * @param name A String with the name to be removed.
446 |  |
          * @return A <code>TemplateLink</code> (self).
447 |  |
          */
448 |  |
         public TemplateLink removePathInfo(String name)
449 |  |
         {
450 | 0 |
             templateURI.removePathInfo(name);
451 | 0 |
             return this;
452 |  |
         }
453 |  |
454 |  |
         /**
455 |  |
          * Removes all the query string elements.
456 |  |
          *
457 |  |
          * @return A <code>TemplateLink</code> (self).
458 |  |
          */
459 |  |
         public TemplateLink removeQueryData()
460 |  |
         {
461 | 0 |
             templateURI.removeQueryData();
462 | 0 |
             return this;
463 |  |
         }
464 |  |
465 |  |
         /**
466 |  |
          * Removes a name=value pair from the query string.
467 |  |
          *
468 |  |
          * @param name A String with the name to be removed.
469 |  |
          * @return A <code>TemplateLink</code> (self).
470 |  |
          */
471 |  |
         public TemplateLink removeQueryData(String name)
472 |  |
         {
473 | 0 |
             templateURI.removeQueryData(name);
474 | 0 |
             return this;
475 |  |
         }
476 |  |
477 |  |
         /**
478 |  |
          * Builds the URL with all of the data URL-encoded as well as
479 |  |
          * encoded using HttpServletResponse.encodeUrl(). The resulting
480 |  |
          * URL is absolute; it starts with http/https...
481 |  |
          *
482 |  |
          * <pre>
483 |  |
          * TemplateURI tui = new TemplateURI (data, "UserScreen");
484 |  |
          * tui.addPathInfo("user","jon");
485 |  |
          * tui.getAbsoluteLink();
486 |  |
          * </pre>
487 |  |
          *
488 |  |
          * The above call to absoluteLink() would return the String:
489 |  |
          * <p>
490 |  |
          * http://www.server.com/servlets/Turbine/screen/UserScreen/user/jon
491 |  |
          * <p>
492 |  |
          * After rendering the URI, it clears the
493 |  |
          * pathInfo and QueryString portions of the TemplateURI. So you can
494 |  |
          * use the $link reference multiple times on a page and start over
495 |  |
          * with a fresh object every time.
496 |  |
          *
497 |  |
          * @return A String with the built URL.
498 |  |
          */
499 |  |
         public String getAbsoluteLink()
500 |  |
         {
501 | 0 |
             String output = templateURI.getAbsoluteLink();
502 |  |
503 |  |
             // This was added to use $link multiple times on a page and start
504 |  |
             // over with a fresh set of data every time.
505 | 0 |
             templateURI.removePathInfo();
506 | 0 |
             templateURI.removeQueryData();
507 |  |
508 | 0 |
             return output;
509 |  |
         }
510 |  |
511 |  |
512 |  |
         /**
513 |  |
          * Builds the URL with all of the data URL-encoded as well as
514 |  |
          * encoded using HttpServletResponse.encodeUrl(). The resulting
515 |  |
          * URL is relative to the webserver root.
516 |  |
          *
517 |  |
          * <pre>
518 |  |
          * TemplateURI tui = new TemplateURI (data, "UserScreen");
519 |  |
          * tui.addPathInfo("user","jon");
520 |  |
          * tui.getRelativeLink();
521 |  |
          * </pre>
522 |  |
          *
523 |  |
          * The above call to absoluteLink() would return the String:
524 |  |
          * <p>
525 |  |
          * /servlets/Turbine/screen/UserScreen/user/jon
526 |  |
          * <p>
527 |  |
          * After rendering the URI, it clears the
528 |  |
          * pathInfo and QueryString portions of the TemplateURI. So you can
529 |  |
          * use the $link reference multiple times on a page and start over
530 |  |
          * with a fresh object every time.
531 |  |
          *
532 |  |
          * @return A String with the built URL.
533 |  |
          */
534 |  |
         public String getRelativeLink()
535 |  |
         {
536 | 0 |
             String output = templateURI.getRelativeLink();
537 |  |
538 |  |
             // This was added to use $link multiple times on a page and start
539 |  |
             // over with a fresh set of data every time.
540 | 0 |
             templateURI.removePathInfo();
541 | 0 |
             templateURI.removeQueryData();
542 |  |
543 | 0 |
             return output;
544 |  |
         }
545 |  |
546 |  |
         /**
547 |  |
          * Returns the URI. After rendering the URI, it clears the
548 |  |
          * pathInfo and QueryString portions of the TemplateURI.
549 |  |
          *
550 |  |
          * @return A String with the URI in the form
551 |  |
          * http://foo.com/Turbine/template/index.wm/hello/world
552 |  |
          */
553 |  |
         public String getLink()
554 |  |
         {
555 | 0 |
             return wantRelative ?
556 |  |
                     getRelativeLink() : getAbsoluteLink();
557 |  |
         }
558 |  |
559 |  |
         /**
560 |  |
          * Returns the relative URI leaving the source intact. Use this
561 |  |
          * if you need the path_info and query data multiple times.
562 |  |
          * This is equivalent to $link.Link or just $link,
563 |  |
          * but does not reset the path_info and query data.
564 |  |
          *
565 |  |
          * @return A String with the URI in the form
566 |  |
          * http://foo.com/Turbine/template/index.wm/hello/world
567 |  |
          */
568 |  |
         public String getURI()
569 |  |
         {
570 | 0 |
             return wantRelative ?
571 |  |
                     templateURI.getRelativeLink() : templateURI.getAbsoluteLink();
572 |  |
         }
573 |  |
574 |  |
         /**
575 |  |
          * Returns the absolute URI leaving the source intact. Use this
576 |  |
          * if you need the path_info and query data multiple times.
577 |  |
          * This is equivalent to $link.AbsoluteLink but does not reset
578 |  |
          * the path_info and query data.
579 |  |
          *
580 |  |
          * @return A String with the URI in the form
581 |  |
          * http://foo.com/Turbine/template/index.wm/hello/world
582 |  |
          */
583 |  |
         public String getAbsoluteURI()
584 |  |
         {
585 | 0 |
             return templateURI.getAbsoluteLink();
586 |  |
         }
587 |  |
588 |  |
         /**
589 |  |
          * Returns the relative URI leaving the source intact. Use this
590 |  |
          * if you need the path_info and query data multiple times.
591 |  |
          * This is equivalent to $link.RelativeLink but does not reset
592 |  |
          * the path_info and query data.
593 |  |
          *
594 |  |
          * @return A String with the URI in the form
595 |  |
          * http://foo.com/Turbine/template/index.wm/hello/world
596 |  |
          */
597 |  |
         public String getRelativeURI()
598 |  |
         {
599 | 0 |
             return templateURI.getRelativeLink();
600 |  |
         }
601 |  |
602 |  |
         /**
603 |  |
          * Same as getLink().
604 |  |
          *
605 |  |
          * @return A String with the URI represented by this object.
606 |  |
          *
607 |  |
          */
608 |  |
         @Override
609 |  |
         public String toString()
610 |  |
         {
611 | 0 |
             return getLink();
612 |  |
         }
613 |  |
     }