/**
  * {@inheritDoc}
  *
  * @see AbstractSelectionExecutable#execute(String)
  */
 public boolean execute(String param) {
   // Get the selected anchor
   AnchorElement selectedAnchor = LinkExecutableUtils.getSelectedAnchor(rta);
   if (selectedAnchor == null) {
     return false;
   }
   Range range = rta.getDocument().getSelection().getRangeAt(0);
   // unlink
   // but first check where is the selection. If the selection is a caret and is at one side of the
   // anchor, just
   // move the caret out instead of removing the link
   boolean moveSelection = range.isCollapsed();
   boolean isBeginning = false;
   boolean isEnd = false;
   if (moveSelection) {
     // check if it's at the beginning or at the end
     isBeginning =
         (domUtils.getFirstAncestor(
                     domUtils.getPreviousLeaf(range), LinkExecutableUtils.ANCHOR_TAG_NAME)
                 != selectedAnchor)
             && range.getStartOffset() == 0;
     isEnd =
         (domUtils.getFirstAncestor(
                     domUtils.getNextLeaf(range), LinkExecutableUtils.ANCHOR_TAG_NAME)
                 != selectedAnchor)
             && range.getEndOffset() == domUtils.getLength(range.getEndContainer());
   }
   if (moveSelection && (isEnd || isBeginning) && selectedAnchor.getOffsetWidth() > 0) {
     // cursor it's at the beginning or at the end, move it out of the anchor
     moveCaretOuside(rta, Element.as(selectedAnchor), isEnd);
   } else {
     Element.as(selectedAnchor).unwrap();
   }
   return true;
 }
 /**
  * Updates the meta data of the given anchor.
  *
  * @param anchor the anchor whose meta data will be updated
  * @param reference the new link reference
  * @param linkType the new link type
  */
 private void updateMetaData(AnchorElement anchor, String reference, LinkType linkType) {
   Document document = (Document) anchor.getOwnerDocument();
   DocumentFragment metaData = document.createDocumentFragment();
   metaData.appendChild(
       document.createComment("startwikilink:" + EscapeUtils.escapeComment(reference)));
   metaData.appendChild(document.createSpanElement());
   if (CLASS_NAME_MAPPING.containsKey(linkType)) {
     Element.as(metaData.getChild(1)).setClassName(CLASS_NAME_MAPPING.get(linkType));
   }
   metaData.getChild(1).appendChild(document.createTextNode(Element.INNER_HTML_PLACEHOLDER));
   metaData.appendChild(document.createComment("stopwikilink"));
   Element.as(anchor).setMetaData(metaData);
 }
 /**
  * {@inheritDoc}
  *
  * @see ConfigDOMWriter#write(Object, com.google.gwt.dom.client.Element)
  */
 public void write(LinkConfig config, AnchorElement anchor) {
   // Required attributes.
   updateMetaData(anchor, config.getReference(), config.getType());
   anchor.setHref(config.getUrl());
   // Optional attributes.
   updateAttribute(anchor, "title", config.getTooltip());
   if (config.isOpenInNewWindow()) {
     anchor.setRel(TARGET_BLANK);
   } else if (TARGET_BLANK.equalsIgnoreCase(anchor.getRel())) {
     anchor.removeAttribute("rel");
   }
   // Update the content.
   if (!anchor.getInnerHTML().equals(config.getLabel())) {
     // Inner HTML listeners have to be notified in order to extract the meta data.
     Element.as(anchor).xSetInnerHTML(config.getLabel());
   }
 }