View Javadoc
1   /*
2    * Copyright (c) 2002-2025 Gargoyle Software Inc.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * https://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software
10   * distributed under the License is distributed on an "AS IS" BASIS,
11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   * See the License for the specific language governing permissions and
13   * limitations under the License.
14   */
15  package org.htmlunit.javascript.host.html;
16  
17  import static org.htmlunit.BrowserVersionFeatures.JS_ANCHOR_HOSTNAME_IGNORE_BLANK;
18  import static org.htmlunit.BrowserVersionFeatures.JS_ANCHOR_PATHNAME_DETECT_WIN_DRIVES_URL_REPLACE;
19  import static org.htmlunit.BrowserVersionFeatures.JS_ANCHOR_PATHNAME_PREFIX_WIN_DRIVES_URL;
20  import static org.htmlunit.BrowserVersionFeatures.JS_ANCHOR_PROTOCOL_COLON_UPPER_CASE_DRIVE_LETTERS;
21  import static org.htmlunit.html.DomElement.ATTRIBUTE_NOT_DEFINED;
22  
23  import java.net.MalformedURLException;
24  import java.net.URL;
25  import java.util.Arrays;
26  import java.util.List;
27  import java.util.Locale;
28  
29  import org.htmlunit.BrowserVersion;
30  import org.htmlunit.HttpHeader;
31  import org.htmlunit.SgmlPage;
32  import org.htmlunit.html.DomElement;
33  import org.htmlunit.html.DomNode;
34  import org.htmlunit.html.HtmlAnchor;
35  import org.htmlunit.html.HtmlElement;
36  import org.htmlunit.html.HtmlPage;
37  import org.htmlunit.javascript.JavaScriptEngine;
38  import org.htmlunit.javascript.configuration.JsxClass;
39  import org.htmlunit.javascript.configuration.JsxConstructor;
40  import org.htmlunit.javascript.configuration.JsxGetter;
41  import org.htmlunit.javascript.configuration.JsxSetter;
42  import org.htmlunit.javascript.host.dom.DOMTokenList;
43  import org.htmlunit.util.StringUtils;
44  import org.htmlunit.util.UrlUtils;
45  
46  /**
47   * The JavaScript object that represents an anchor.
48   *
49   * @author Mike Bowler
50   * @author Alexei Goussev
51   * @author David D. Kilzer
52   * @author Marc Guillemot
53   * @author Chris Erskine
54   * @author Ahmed Ashour
55   * @author Sudhan Moghe
56   * @author Daniel Gredler
57   * @author Ronald Brill
58   */
59  @JsxClass(domClass = HtmlAnchor.class)
60  public class HTMLAnchorElement extends HTMLElement {
61      private static final List<String> REFERRER_POLICIES = Arrays.asList(
62                                          "no-referrer", HttpHeader.ORIGIN_LC, "unsafe-url");
63  
64      /**
65       * JavaScript constructor.
66       */
67      @Override
68      @JsxConstructor
69      public void jsConstructor() {
70          super.jsConstructor();
71      }
72  
73      /**
74       * Sets the {@code href} property.
75       * @param href the {@code href} property value
76       */
77      @JsxSetter
78      public void setHref(final String href) {
79          getDomNodeOrDie().setAttribute("href", href);
80      }
81  
82      /**
83       * Returns the value of this link's {@code href} property.
84       * @return the value of this link's {@code href} property
85       */
86      @JsxGetter
87      public String getHref() {
88          final HtmlAnchor anchor = (HtmlAnchor) getDomNodeOrDie();
89          final String hrefAttr = anchor.getHrefAttribute();
90  
91          if (ATTRIBUTE_NOT_DEFINED == hrefAttr) {
92              return "";
93          }
94  
95          try {
96              return getUrl().toString();
97          }
98          catch (final MalformedURLException e) {
99              return hrefAttr;
100         }
101     }
102 
103     /**
104      * Sets the focus to this element.
105      */
106     @Override
107     public void focus() {
108         final HtmlAnchor anchor = (HtmlAnchor) getDomNodeOrDie();
109         final String hrefAttr = anchor.getHrefAttribute();
110 
111         if (ATTRIBUTE_NOT_DEFINED != hrefAttr) {
112             anchor.focus();
113         }
114     }
115 
116     /**
117      * Sets the name property.
118      * @param name name attribute value
119      */
120     @JsxSetter
121     @Override
122     public void setName(final String name) {
123         getDomNodeOrDie().setAttribute(DomElement.NAME_ATTRIBUTE, name);
124     }
125 
126     /**
127      * Returns the value of the name property of this link.
128      * @return the name property
129      */
130     @JsxGetter
131     @Override
132     public String getName() {
133         return getDomNodeOrDie().getAttributeDirect(DomElement.NAME_ATTRIBUTE);
134     }
135 
136     /**
137      * Sets the target property of this link.
138      * @param target target attribute value
139      */
140     @JsxSetter
141     public void setTarget(final String target) {
142         getDomNodeOrDie().setAttribute("target", target);
143     }
144 
145     /**
146      * Returns the value of the target property of this link.
147      * @return the href property
148      */
149     @JsxGetter
150     public String getTarget() {
151         return getDomNodeOrDie().getAttributeDirect("target");
152     }
153 
154     /**
155      * Returns this link's current URL.
156      * @return this link's current URL
157      * @throws MalformedURLException if an error occurs
158      */
159     private URL getUrl() throws MalformedURLException {
160         final HtmlAnchor anchor = (HtmlAnchor) getDomNodeOrDie();
161         return ((HtmlPage) anchor.getPage()).getFullyQualifiedUrl(anchor.getHrefAttribute());
162     }
163 
164     /**
165      * Sets the {@code href} attribute of this link to the specified URL.
166      * @param url the new value of the {@code href} attribute
167      */
168     private void setUrl(final URL url) {
169         getDomNodeOrDie().setAttribute("href", url.toString());
170     }
171 
172     /**
173      * Sets the rel property.
174      * @param rel rel attribute value
175      */
176     @JsxSetter
177     public void setRel(final String rel) {
178         getDomNodeOrDie().setAttribute("rel", rel);
179     }
180 
181     /**
182      * Returns the value of the rel property.
183      * @return the rel property
184      */
185     @JsxGetter
186     public String getRel() {
187         return ((HtmlAnchor) getDomNodeOrDie()).getRelAttribute();
188     }
189 
190     /**
191      * Returns the value of the rev property.
192      * @return the rev property
193      */
194     @JsxGetter
195     public String getRev() {
196         return ((HtmlAnchor) getDomNodeOrDie()).getRevAttribute();
197     }
198 
199     /**
200      * Sets the rev property.
201      * @param rel rev attribute value
202      */
203     @JsxSetter
204     public void setRev(final String rel) {
205         getDomNodeOrDie().setAttribute("rev", rel);
206     }
207 
208     /**
209      * Returns the value of the rev property.
210      * @return the referrerPolicy property
211      */
212     @JsxGetter
213     public String getReferrerPolicy() {
214         String attrib = getDomNodeOrDie().getAttribute("referrerPolicy");
215         if (StringUtils.isEmptyOrNull(attrib)) {
216             return "";
217         }
218         attrib = attrib.toLowerCase(Locale.ROOT);
219         if (REFERRER_POLICIES.contains(attrib)) {
220             return attrib;
221         }
222         return "";
223     }
224 
225     /**
226      * Sets the rev property.
227      * @param referrerPolicy referrerPolicy attribute value
228      */
229     @JsxSetter
230     public void setReferrerPolicy(final String referrerPolicy) {
231         getDomNodeOrDie().setAttribute("referrerPolicy", referrerPolicy);
232     }
233 
234     /**
235      * Returns the search portion of the link's URL (the portion starting with
236      * '?' and up to but not including any '#').
237      * @return the search portion of the link's URL
238      * @see <a href="http://msdn.microsoft.com/en-us/library/ms534620.aspx">MSDN Documentation</a>
239      */
240     @JsxGetter
241     public String getSearch() {
242         try {
243             final String query = getUrl().getQuery();
244             if (query == null) {
245                 return "";
246             }
247             return "?" + query;
248         }
249         catch (final MalformedURLException e) {
250             return "";
251         }
252     }
253 
254     /**
255      * Sets the search portion of the link's URL (the portion starting with '?'
256      * and up to but not including any '#').
257      * @param search the new search portion of the link's URL
258      * @throws Exception if an error occurs
259      * @see <a href="http://msdn.microsoft.com/en-us/library/ms534620.aspx">MSDN Documentation</a>
260      */
261     @JsxSetter
262     public void setSearch(final String search) throws Exception {
263         final String query;
264         if (search == null
265                 || StringUtils.isEmptyString(search)
266                 || StringUtils.equalsChar('?', search)) {
267             query = null;
268         }
269         else if (search.charAt(0) == '?') {
270             query = search.substring(1);
271         }
272         else {
273             query = search;
274         }
275 
276         setUrl(UrlUtils.getUrlWithNewQuery(getUrl(), query));
277     }
278 
279     /**
280      * Returns the hash portion of the link's URL (the portion following the '#', including the '#').
281      * @return the hash portion of the link's URL
282      * @see <a href="http://msdn.microsoft.com/en-us/library/ms533775.aspx">MSDN Documentation</a>
283      */
284     @JsxGetter
285     public String getHash() {
286         try {
287             final String hash = getUrl().getRef();
288             if (hash == null) {
289                 return "";
290             }
291             return "#" + hash;
292         }
293         catch (final MalformedURLException e) {
294             return "";
295         }
296     }
297 
298     /**
299      * Sets the hash portion of the link's URL (the portion following the '#').
300      * @param hash the new hash portion of the link's URL
301      * @throws Exception if an error occurs
302      * @see <a href="http://msdn.microsoft.com/en-us/library/ms533775.aspx">MSDN Documentation</a>
303      */
304     @JsxSetter
305     public void setHash(final String hash) throws Exception {
306         setUrl(UrlUtils.getUrlWithNewRef(getUrl(), hash));
307     }
308 
309     /**
310      * Returns the host portion of the link's URL (the '[hostname]:[port]' portion).
311      * @return the host portion of the link's URL
312      * @see <a href="http://msdn.microsoft.com/en-us/library/ms533784.aspx">MSDN Documentation</a>
313      */
314     @JsxGetter
315     public String getHost() {
316         try {
317             final URL url = getUrl();
318             final int port = url.getPort();
319             final String host = url.getHost();
320 
321             if (port == -1) {
322                 return host;
323             }
324             return host + ":" + port;
325         }
326         catch (final MalformedURLException e) {
327             return "";
328         }
329     }
330 
331     /**
332      * Sets the host portion of the link's URL (the '[hostname]:[port]' portion).
333      * @param host the new host portion of the link's URL
334      * @throws Exception if an error occurs
335      * @see <a href="http://msdn.microsoft.com/en-us/library/ms533784.aspx">MSDN Documentation</a>
336      */
337     @JsxSetter
338     public void setHost(final String host) throws Exception {
339         final String hostname;
340         final int port;
341         final int index = host.indexOf(':');
342         if (index != -1) {
343             hostname = host.substring(0, index);
344             port = Integer.parseInt(host.substring(index + 1));
345         }
346         else {
347             hostname = host;
348             port = -1;
349         }
350         final URL url = UrlUtils.getUrlWithNewHostAndPort(getUrl(), hostname, port);
351         setUrl(url);
352     }
353 
354     /**
355      * Returns the hostname portion of the link's URL.
356      * @return the hostname portion of the link's URL
357      * @see <a href="http://msdn.microsoft.com/en-us/library/ms533785.aspx">MSDN Documentation</a>
358      */
359     @JsxGetter
360     public String getHostname() {
361         try {
362             return UrlUtils.encodeAnchor(getUrl().getHost());
363         }
364         catch (final MalformedURLException e) {
365             return "";
366         }
367     }
368 
369     /**
370      * Sets the hostname portion of the link's URL.
371      * @param hostname the new hostname portion of the link's URL
372      * @throws Exception if an error occurs
373      * @see <a href="http://msdn.microsoft.com/en-us/library/ms533785.aspx">MSDN Documentation</a>
374      */
375     @JsxSetter
376     public void setHostname(final String hostname) throws Exception {
377         if (getBrowserVersion().hasFeature(JS_ANCHOR_HOSTNAME_IGNORE_BLANK)) {
378             if (!StringUtils.isBlank(hostname)) {
379                 setUrl(UrlUtils.getUrlWithNewHost(getUrl(), hostname));
380             }
381         }
382         else if (!StringUtils.isEmptyOrNull(hostname)) {
383             setUrl(UrlUtils.getUrlWithNewHost(getUrl(), hostname));
384         }
385     }
386 
387     /**
388      * Returns the pathname portion of the link's URL.
389      * @return the pathname portion of the link's URL
390      * @see <a href="http://msdn.microsoft.com/en-us/library/ms534332.aspx">MSDN Documentation</a>
391      */
392     @JsxGetter
393     public String getPathname() {
394         final BrowserVersion browser = getBrowserVersion();
395         try {
396             if (browser.hasFeature(JS_ANCHOR_PATHNAME_DETECT_WIN_DRIVES_URL_REPLACE)) {
397                 final HtmlAnchor anchor = (HtmlAnchor) getDomNodeOrDie();
398                 String href = anchor.getHrefAttribute();
399                 if (href.length() > 1 && Character.isLetter(href.charAt(0)) && ':' == href.charAt(1)) {
400                     if (browser.hasFeature(JS_ANCHOR_PROTOCOL_COLON_UPPER_CASE_DRIVE_LETTERS)) {
401                         href = org.apache.commons.lang3.StringUtils.capitalize(href);
402                     }
403                     if (browser.hasFeature(JS_ANCHOR_PATHNAME_PREFIX_WIN_DRIVES_URL)) {
404                         href = "/" + href;
405                     }
406                     return href;
407                 }
408             }
409             return getUrl().getPath();
410         }
411         catch (final MalformedURLException e) {
412             final HtmlAnchor anchor = (HtmlAnchor) getDomNodeOrDie();
413             if (anchor.getHrefAttribute().startsWith("http")) {
414                 return "";
415             }
416             return "/";
417         }
418     }
419 
420     /**
421      * Sets the pathname portion of the link's URL.
422      * @param pathname the new pathname portion of the link's URL
423      * @throws Exception if an error occurs
424      * @see <a href="http://msdn.microsoft.com/en-us/library/ms534332.aspx">MSDN Documentation</a>
425      */
426     @JsxSetter
427     public void setPathname(final String pathname) throws Exception {
428         setUrl(UrlUtils.getUrlWithNewPath(getUrl(), pathname));
429     }
430 
431     /**
432      * Returns the port portion of the link's URL.
433      * @return the port portion of the link's URL
434      * @see <a href="http://msdn.microsoft.com/en-us/library/ms534342.aspx">MSDN Documentation</a>
435      */
436     @JsxGetter
437     public String getPort() {
438         try {
439             final int port = getUrl().getPort();
440             if (port == -1) {
441                 return "";
442             }
443             return Integer.toString(port);
444         }
445         catch (final MalformedURLException e) {
446             return "";
447         }
448     }
449 
450     /**
451      * Sets the port portion of the link's URL.
452      * @param port the new port portion of the link's URL
453      * @throws Exception if an error occurs
454      * @see <a href="http://msdn.microsoft.com/en-us/library/ms534342.aspx">MSDN Documentation</a>
455      */
456     @JsxSetter
457     public void setPort(final String port) throws Exception {
458         setUrl(UrlUtils.getUrlWithNewPort(getUrl(), Integer.parseInt(port)));
459     }
460 
461     /**
462      * Returns the protocol portion of the link's URL, including the trailing ':'.
463      * @return the protocol portion of the link's URL, including the trailing ':'
464      * @see <a href="http://msdn.microsoft.com/en-us/library/ms534353.aspx">MSDN Documentation</a>
465      */
466     @JsxGetter
467     public String getProtocol() {
468         final BrowserVersion browser = getBrowserVersion();
469         try {
470             if (browser.hasFeature(JS_ANCHOR_PATHNAME_DETECT_WIN_DRIVES_URL_REPLACE)) {
471                 final HtmlAnchor anchor = (HtmlAnchor) getDomNodeOrDie();
472                 final String href = anchor.getHrefAttribute().toLowerCase(Locale.ROOT);
473                 if (href.length() > 1 && Character.isLetter(href.charAt(0)) && ':' == href.charAt(1)) {
474                     return "file:";
475                 }
476             }
477 
478             return getUrl().getProtocol() + ":";
479         }
480         catch (final MalformedURLException e) {
481             final HtmlAnchor anchor = (HtmlAnchor) getDomNodeOrDie();
482             if (anchor.getHrefAttribute().startsWith("http")) {
483                 return ":";
484             }
485             return StringUtils.substringBefore(anchor.getHrefAttribute(), "/");
486         }
487     }
488 
489     /**
490      * Sets the protocol portion of the link's URL.
491      * @param protocol the new protocol portion of the link's URL
492      * @throws Exception if an error occurs
493      * @see <a href="http://msdn.microsoft.com/en-us/library/ms534353.aspx">MSDN Documentation</a>
494      */
495     @JsxSetter
496     public void setProtocol(final String protocol) throws Exception {
497         if (protocol.isEmpty()) {
498             return;
499         }
500 
501         final String bareProtocol = StringUtils.substringBefore(protocol, ":").trim();
502         if (!UrlUtils.isValidScheme(bareProtocol)) {
503             return;
504         }
505         if (!UrlUtils.isSpecialScheme(bareProtocol)) {
506             return;
507         }
508 
509         try {
510             URL url = UrlUtils.getUrlWithNewProtocol(getUrl(), bareProtocol);
511             url = UrlUtils.removeRedundantPort(url);
512             setUrl(url);
513         }
514         catch (final MalformedURLException ignored) {
515             // ignore
516         }
517     }
518 
519     /**
520      * Calls for instance for implicit conversion to string.
521      * @see org.htmlunit.javascript.HtmlUnitScriptable#getDefaultValue(java.lang.Class)
522      * @param hint the type hint
523      * @return the default value
524      */
525     @Override
526     public Object getDefaultValue(final Class<?> hint) {
527         final HtmlElement element = getDomNodeOrNull();
528         if (element == null) {
529             return super.getDefaultValue(null);
530         }
531         return getDefaultValue(element);
532     }
533 
534     static String getDefaultValue(final HtmlElement element) {
535         String href = element.getAttributeDirect("href");
536 
537         if (ATTRIBUTE_NOT_DEFINED == href) {
538             return ""; // for example for named anchors
539         }
540 
541         href = href.trim();
542 
543         final SgmlPage page = element.getPage();
544         if (page == null || !page.isHtmlPage()) {
545             return href;
546         }
547 
548         try {
549             return HtmlAnchor.getTargetUrl(href, (HtmlPage) page).toExternalForm();
550         }
551         catch (final MalformedURLException e) {
552             return href;
553         }
554     }
555 
556     /**
557      * Returns the {@code text} attribute.
558      * @return the {@code text} attribute
559      */
560     @JsxGetter
561     public String getText() {
562         final DomNode htmlElement = getDomNodeOrDie();
563         return htmlElement.asNormalizedText();
564     }
565 
566     /**
567      * Sets the {@code text} attribute.
568      * @param text the {@code text} attribute
569      */
570     @JsxSetter
571     public void setText(final String text) {
572         final DomNode htmlElement = getDomNodeOrDie();
573         htmlElement.setTextContent(text);
574     }
575 
576     /**
577      * Returns the {@code charset} attribute.
578      * @return the {@code charset} attribute
579      */
580     @JsxGetter
581     public String getCharset() {
582         return getDomNodeOrDie().getAttributeDirect("charset");
583     }
584 
585     /**
586      * Sets the {@code charset} attribute.
587      * @param charset the {@code charset} attribute
588      */
589     @JsxSetter
590     public void setCharset(final String charset) {
591         getDomNodeOrDie().setAttribute("charset", charset);
592     }
593 
594     /**
595      * Returns the {@code coords} attribute.
596      * @return the {@code coords} attribute
597      */
598     @JsxGetter
599     public String getCoords() {
600         return getDomNodeOrDie().getAttributeDirect("coords");
601     }
602 
603     /**
604      * Sets the {@code coords} attribute.
605      * @param coords {@code coords} attribute
606      */
607     @JsxSetter
608     public void setCoords(final String coords) {
609         getDomNodeOrDie().setAttribute("coords", coords);
610     }
611 
612     /**
613      * Returns the {@code hreflang} attribute.
614      * @return the {@code hreflang} attribute
615      */
616     @JsxGetter
617     public String getHreflang() {
618         return getDomNodeOrDie().getAttributeDirect("hreflang");
619     }
620 
621     /**
622      * Sets the {@code hreflang} attribute.
623      * @param hreflang {@code hreflang} attribute
624      */
625     @JsxSetter
626     public void setHreflang(final String hreflang) {
627         getDomNodeOrDie().setAttribute("hreflang", hreflang);
628     }
629 
630     /**
631      * Returns the {@code origin} attribute.
632      * @return the {@code origin} attribute
633      */
634     @JsxGetter
635     public String getOrigin() {
636         if (!getDomNodeOrDie().hasAttribute("href")) {
637             return "";
638         }
639 
640         try {
641             return getUrl().getProtocol() + "://" + getHost();
642         }
643         catch (final Exception e) {
644             return "";
645         }
646     }
647 
648     /**
649      * Returns the {@code username} attribute.
650      * @return the {@code username} attribute
651      */
652     @JsxGetter
653     public String getUsername() {
654         try {
655             final String userInfo = getUrl().getUserInfo();
656             if (userInfo == null) {
657                 return "";
658             }
659             return org.apache.commons.lang3.StringUtils.substringBefore(userInfo, ':');
660         }
661         catch (final MalformedURLException e) {
662             return "";
663         }
664     }
665 
666     /**
667      * Sets the {@code username} attribute.
668      * @param username {@code username} attribute
669      */
670     @JsxSetter
671     public void setUsername(final String username) {
672         try {
673             final HtmlAnchor anchor = (HtmlAnchor) getDomNodeOrDie();
674             final String href = anchor.getHrefAttribute();
675             if (ATTRIBUTE_NOT_DEFINED == href) {
676                 return;
677             }
678 
679             final URL url = ((HtmlPage) anchor.getPage()).getFullyQualifiedUrl(href);
680             setUrl(UrlUtils.getUrlWithNewUserName(url, username));
681         }
682         catch (final MalformedURLException ignored) {
683             // ignore
684         }
685     }
686 
687     /**
688      * Returns the {@code password} attribute.
689      * @return the {@code password} attribute
690      */
691     @JsxGetter
692     public String getPassword() {
693         try {
694             final String userName = getUrl().getUserInfo();
695             if (userName == null) {
696                 return "";
697             }
698             return StringUtils.substringAfter(userName, ":");
699         }
700         catch (final MalformedURLException e) {
701             return "";
702         }
703     }
704 
705     /**
706      * Sets the {@code password} attribute.
707      * @param password {@code password} attribute
708      */
709     @JsxSetter
710     public void setPassword(final String password) {
711         try {
712             final HtmlAnchor anchor = (HtmlAnchor) getDomNodeOrDie();
713             final String href = anchor.getHrefAttribute();
714             if (ATTRIBUTE_NOT_DEFINED == href) {
715                 return;
716             }
717 
718             final URL url = ((HtmlPage) anchor.getPage()).getFullyQualifiedUrl(href);
719             setUrl(UrlUtils.getUrlWithNewUserPassword(url, password));
720         }
721         catch (final MalformedURLException ignored) {
722             // ignore
723         }
724     }
725 
726     /**
727      * Returns the {@code download} attribute.
728      * @return the {@code download} attribute
729      */
730     @JsxGetter
731     public String getDownload() {
732         return ((HtmlAnchor) getDomNodeOrDie()).getDownloadAttribute();
733     }
734 
735     /**
736      * Sets the {@code download} attribute.
737      * @param download {@code download} attribute
738      */
739     @JsxSetter
740     public void setDownload(final String download) {
741         getDomNodeOrDie().setAttribute("download", download);
742     }
743 
744     /**
745      * Returns the {@code ping} attribute.
746      * @return the {@code ping} attribute
747      */
748     @JsxGetter
749     public String getPing() {
750         return ((HtmlAnchor) getDomNodeOrDie()).getPingAttribute();
751     }
752 
753     /**
754      * Sets the {@code ping} attribute.
755      * @param ping {@code ping} attribute
756      */
757     @JsxSetter
758     public void setPing(final String ping) {
759         getDomNodeOrDie().setAttribute("ping", ping);
760     }
761 
762     /**
763      * Returns the {@code shape} attribute.
764      * @return the {@code shape} attribute
765      */
766     @JsxGetter
767     public String getShape() {
768         return getDomNodeOrDie().getAttribute("shape");
769     }
770 
771     /**
772      * Sets the {@code shape} attribute.
773      * @param shape {@code shape} attribute
774      */
775     @JsxSetter
776     public void setShape(final String shape) {
777         getDomNodeOrDie().setAttribute("shape", shape);
778     }
779 
780     /**
781      * Returns the {@code type} attribute.
782      * @return the {@code type} attribute
783      */
784     @JsxGetter
785     public String getType() {
786         return getDomNodeOrDie().getAttributeDirect(DomElement.TYPE_ATTRIBUTE);
787     }
788 
789     /**
790      * Sets the {@code type} attribute.
791      * @param type {@code type} attribute
792      */
793     @JsxSetter
794     public void setType(final String type) {
795         getDomNodeOrDie().setAttribute(DomElement.TYPE_ATTRIBUTE, type);
796     }
797 
798     /**
799      * Returns the {@code relList} attribute.
800      * @return the {@code relList} attribute
801      */
802     @JsxGetter
803     public DOMTokenList getRelList() {
804         return new DOMTokenList(this, "rel");
805     }
806 
807     /**
808      * Sets the relList property.
809      * @param rel attribute value
810      */
811     @JsxSetter
812     public void setRelList(final Object rel) {
813         setRel(JavaScriptEngine.toString(rel));
814     }
815 }