Package org.eclipse.wst.xml.core.internal.provisional.format

Source Code of org.eclipse.wst.xml.core.internal.provisional.format.NodeFormatter

/*******************************************************************************
* Copyright (c) 2001, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*     IBM Corporation - initial API and implementation
*     Jens Lukowski/Innoopract - initial renaming/restructuring
*     Jesper Steen M�ller - xml:space='preserve' support
*    
*******************************************************************************/
package org.eclipse.wst.xml.core.internal.provisional.format;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Preferences;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.wst.sse.core.internal.format.IStructuredFormatContraints;
import org.eclipse.wst.sse.core.internal.format.IStructuredFormatPreferences;
import org.eclipse.wst.sse.core.internal.format.IStructuredFormatter;
import org.eclipse.wst.sse.core.internal.format.StructuredFormatContraints;
import org.eclipse.wst.sse.core.internal.parser.ContextRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList;
import org.eclipse.wst.sse.core.utils.StringUtils;
import org.eclipse.wst.xml.core.internal.Logger;
import org.eclipse.wst.xml.core.internal.XMLCorePlugin;
import org.eclipse.wst.xml.core.internal.document.CDATASectionImpl;
import org.eclipse.wst.xml.core.internal.document.CharacterDataImpl;
import org.eclipse.wst.xml.core.internal.document.CommentImpl;
import org.eclipse.wst.xml.core.internal.parser.regions.TagNameRegion;
import org.eclipse.wst.xml.core.internal.preferences.XMLCorePreferenceNames;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
import org.w3c.dom.Node;

public class NodeFormatter implements IStructuredFormatter {
  static protected final String EMPTY_STRING = ""; //$NON-NLS-1$
  static private final char SPACE_CHAR = ' '; //$NON-NLS-1$
  static private final char TAB_CHAR = '\t'; //$NON-NLS-1$
  static private final String TAB = "\t"; //$NON-NLS-1$
  protected IStructuredFormatContraints fFormatContraints = null;
  protected IStructuredFormatPreferences fFormatPreferences = null;
  protected IProgressMonitor fProgressMonitor = null;

  protected boolean firstStructuredDocumentRegionContainsLineDelimiters(IDOMNode node) {
    boolean result = false;

    if (node != null) {
      IStructuredDocumentRegion firstStructuredDocumentRegion = node.getFirstStructuredDocumentRegion();
      if (firstStructuredDocumentRegion != null) {
        String firstStructuredDocumentRegionText = firstStructuredDocumentRegion.getText();
        result = StringUtils.containsLineDelimiter(firstStructuredDocumentRegionText);
      }
    }

    return result;
  }

  public void format(Node node) {
    IStructuredFormatContraints formatContraints = getFormatContraints();

    format(node, formatContraints);
  }

  public void format(Node node, IStructuredFormatContraints formatContraints) {
    if (formatContraints.getFormatWithSiblingIndent())
      formatContraints.setCurrentIndent(getSiblingIndent(node));

    if (node instanceof IDOMNode)
      formatNode((IDOMNode) node, formatContraints);
  }

  protected void formatIndentationAfterNode(IDOMNode node, IStructuredFormatContraints formatContraints) {
    // [111674] If inside xml:space="preserve" element, we bail
    if (formatContraints.getInPreserveSpaceElement())
      return;
    if (node != null) {
      IDOMNode nextSibling = (IDOMNode) node.getNextSibling();
      IStructuredDocument doc = node.getModel().getStructuredDocument();
      String lineDelimiter = getLineDelimiter(node, doc);

      if (node.getParentNode() != null) {
        if (node.getParentNode().getNodeType() == Node.DOCUMENT_NODE)
          if (nextSibling != null)
            if (nextSibling.getNodeType() == Node.TEXT_NODE)
              getFormatter(nextSibling).format(nextSibling, formatContraints);
            else if (nextSibling.getNodeType() == Node.COMMENT_NODE) {
              // do nothing
            }
            else {
              String lineIndent = formatContraints.getCurrentIndent();
              insertAfterNode(node, lineDelimiter + lineIndent);
            }
          else {
          }

        else if (nextSibling != null)
          if (nextSibling.getNodeType() == Node.TEXT_NODE)
            getFormatter(nextSibling).format(nextSibling, formatContraints);
          else if (nextSibling.getNodeType() == Node.COMMENT_NODE) {
            // do nothing
          }
          else {
            String lineIndent = formatContraints.getCurrentIndent();
            insertAfterNode(node, lineDelimiter + lineIndent);
          }
        else {
          IDOMNode indentNode = getParentIndentNode(node);
          String lineIndent = getNodeIndent(indentNode);
          IDOMNode lastChild = getDeepestChildNode(node);
          boolean clearAllBlankLines = formatContraints.getClearAllBlankLines();

          if (lastChild != null) {
            if ((lastChild.getNodeType() == Node.TEXT_NODE) && (lastChild.getNodeValue().endsWith(lineDelimiter + lineIndent))) {
              // this text node already ends with the requested
              // indentation
            }

            else if ((lastChild.getNodeType() == Node.TEXT_NODE) && (lastChild.getNodeValue() != null && lastChild.getNodeValue().endsWith(lineDelimiter)))
              if (clearAllBlankLines) {
                replaceNodeValue(lastChild, lineDelimiter + lineIndent);
              }
              else {
                // append indentation
                insertAfterNode(lastChild, lineIndent);
              }
            else if (lastChild.getNodeType() == Node.TEXT_NODE)
              if (lastChild.getNodeValue().length() == 0) {
                // replace
                replaceNodeValue(lastChild, lineDelimiter + lineIndent);
              }
              else {
                // append indentation
                insertAfterNode(lastChild, lineDelimiter + lineIndent);
              }
            else {
              // as long as not at the end of the document
              IStructuredDocumentRegion endRegion = node.getLastStructuredDocumentRegion();
              if (endRegion != null && endRegion.getNext() != null)
                // append indentation
                insertAfterNode(lastChild, lineDelimiter + lineIndent);
            }
          }
        }
      }
    }
  }

  protected void formatIndentationBeforeNode(IDOMNode node, IStructuredFormatContraints formatContraints) {
    // [111674] If inside xml:space="preserve" element, we bail
    if (formatContraints.getInPreserveSpaceElement())
      return;
    if (node != null) {
      IDOMNode previousSibling = (IDOMNode) node.getPreviousSibling();
      IStructuredDocument doc = node.getModel().getStructuredDocument();
      String lineDelimiter = getLineDelimiter(node, doc);

      String lineIndent = formatContraints.getCurrentIndent();

      if (node.getParentNode() != null) {
        if (node.getParentNode().getNodeType() == Node.DOCUMENT_NODE) {
          if (previousSibling != null)
            if (previousSibling.getNodeType() == Node.TEXT_NODE)
              getFormatter(previousSibling).format(previousSibling, formatContraints);
            else {
              insertBeforeNode(node, lineDelimiter + lineIndent);
            }
        }
        else {
          if (previousSibling == null || previousSibling.getNodeType() != Node.TEXT_NODE) {
            // 261968 - formatting tag without closing bracket:
            // <t1><t1
            // 265673 - Null ptr in formatIndentationBeforeNode
            int prevEndNodeOffset = -1;
            int prevEndRegionOffset = -1;
            if (previousSibling != null) {
              prevEndNodeOffset = previousSibling.getEndOffset();
              IStructuredDocumentRegion endRegion = previousSibling.getEndStructuredDocumentRegion();
              if (endRegion != null) {
                prevEndRegionOffset = endRegion.getTextEndOffset();
              }
            }
            if ((previousSibling == null) || (prevEndNodeOffset != -1 && prevEndNodeOffset == prevEndRegionOffset)) {
              insertBeforeNode(node, lineDelimiter + lineIndent);
            }

          }
          else {
            if (previousSibling.getNodeValue().length() == 0) {
              // replace
              replaceNodeValue(previousSibling, lineDelimiter + lineIndent);
            }
            else {
              // append indentation
              if (!previousSibling.getNodeValue().endsWith(lineDelimiter + lineIndent)) {
                if (previousSibling.getNodeValue().endsWith(lineDelimiter)) {
                  insertAfterNode(previousSibling, lineIndent);
                }
                else
                  getFormatter(previousSibling).format(previousSibling, formatContraints);
              }
            }
          }
        }
      }
    }
  }

  private String getLineDelimiter(IDOMNode node, IStructuredDocument doc) {
    int line = doc.getLineOfOffset(node.getStartOffset());
    String lineDelimiter = doc.getLineDelimiter();
    try {
      if (line > 0) {
        lineDelimiter = doc.getLineDelimiter(line - 1);
      }
    }
    catch (BadLocationException e) {
      // log for now, unless we find reason not to
      Logger.log(Logger.INFO, e.getMessage());
    }
    // BUG115716: if cannot get line delimiter from current line, just
    // use default line delimiter
    if (lineDelimiter == null)
      lineDelimiter = doc.getLineDelimiter();
    return lineDelimiter;
  }

  protected void formatNode(IDOMNode node, IStructuredFormatContraints formatContraints) {
    if (node != null && (fProgressMonitor == null || !fProgressMonitor.isCanceled())) {
      // format indentation before node
      formatIndentationBeforeNode(node, formatContraints);

      // format indentation after node
      formatIndentationAfterNode(node, formatContraints);
    }
  }

  /**
   * This method will compute the correct indentation after this node
   * depending on the indentations of its sibling nodes and parent node. Not
   * needed anymore?
   */
  protected void formatTrailingText(IDOMNode node, IStructuredFormatContraints formatContraints) {
    // [111674] If inside xml:space="preserve" element, we bail
    if (formatContraints.getInPreserveSpaceElement())
      return;

    String lineDelimiter = node.getModel().getStructuredDocument().getLineDelimiter();
    String lineIndent = formatContraints.getCurrentIndent();
    String parentLineIndent = getNodeIndent(node.getParentNode());
    boolean clearAllBlankLines = formatContraints.getClearAllBlankLines();

    if ((node != null) && (node.getNodeType() != Node.DOCUMENT_NODE)) {
      IDOMNode nextSibling = (IDOMNode) node.getNextSibling();
      if ((nextSibling != null) && (nextSibling.getNodeType() == Node.TEXT_NODE)) {
        String nextSiblingText = nextSibling.getNodeValue();
        if (nextSibling.getNextSibling() == null)
          if ((nextSibling.getParentNode().getNodeType() == Node.DOCUMENT_NODE) && (nextSiblingText.trim().length() == 0))
            // delete spaces at the end of the document
            replaceNodeValue(nextSibling, EMPTY_STRING);
          else
            // replace the text node with parent indentation
            replaceNodeValue(nextSibling, lineDelimiter + parentLineIndent);
        else
          // replace the text node with indentation
          replaceNodeValue(nextSibling, lineDelimiter + lineIndent);
      }
      else {
        if (nextSibling == null) {
          lineIndent = parentLineIndent;

          if (node.getParentNode().getNodeType() != Node.DOCUMENT_NODE)
            if ((node.getNodeType() == Node.TEXT_NODE) && (node.getNodeValue().endsWith(lineDelimiter + lineIndent))) {
              // this text node already ends with the requested
              // indentation
            }

            else if ((node.getNodeType() == Node.TEXT_NODE) && (node.getNodeValue().endsWith(lineDelimiter)))
              if (clearAllBlankLines)
                replaceNodeValue(node, lineDelimiter + lineIndent);
              else
                // append indentation
                insertAfterNode(node, lineIndent);
            else if (node.getNodeType() == Node.TEXT_NODE)
              if (node.getNodeValue().length() == 0)
                // replace
                replaceNodeValue(node, lineDelimiter + lineIndent);
              else
              // append indentation
              if (!node.getNodeValue().endsWith(lineDelimiter + lineIndent))
                if (node.getNodeValue().endsWith(lineDelimiter))
                  insertAfterNode(node, lineIndent);
                else
                  insertAfterNode(node, lineDelimiter + lineIndent);
              else
                replaceNodeValue(node, lineDelimiter + lineIndent);
        }
        else {
          if ((node.getNodeType() == Node.TEXT_NODE) && (node.getNodeValue().endsWith(lineDelimiter + lineIndent))) {
            // this text node already ends with the requested
            // indentation
          }

          else if ((node.getNodeType() == Node.TEXT_NODE) && (node.getNodeValue().endsWith(lineDelimiter)))
            if (clearAllBlankLines)
              replaceNodeValue(node, lineDelimiter + lineIndent);
            else
              // append indentation
              insertAfterNode(node, lineIndent);
          else if (node.getNodeType() == Node.TEXT_NODE)
            if (node.getNodeValue().length() == 0)
              // replace
              replaceNodeValue(node, lineDelimiter + lineIndent);
            else
              // append indentation
              insertAfterNode(node, lineDelimiter + lineIndent);
          else
            // append indentation
            insertAfterNode(node, lineDelimiter + lineIndent);
        }
      }
    }
  }

  protected IDOMNode getDeepestChildNode(IDOMNode node) {
    IDOMNode result = null;
    IDOMNode lastChild = (IDOMNode) node.getLastChild();

    if (lastChild == null)
      result = node;
    else {
      result = getDeepestChildNode(lastChild);

      if ((result.getNodeType() == Node.TEXT_NODE || result.getNodeType() == Node.COMMENT_NODE) && !isEndTagMissing(node))
        result = node;
    }

    return result;
  }

  public IStructuredFormatContraints getFormatContraints() {
    if (fFormatContraints == null) {
      fFormatContraints = new StructuredFormatContraints();

      fFormatContraints.setClearAllBlankLines(getFormatPreferences().getClearAllBlankLines());
    }

    return fFormatContraints;
  }

  public IStructuredFormatPreferences getFormatPreferences() {
    if (fFormatPreferences == null) {
      fFormatPreferences = new StructuredFormatPreferencesXML();

      Preferences preferences = getModelPreferences();
      if (preferences != null) {
        fFormatPreferences.setLineWidth(preferences.getInt(XMLCorePreferenceNames.LINE_WIDTH));
        ((StructuredFormatPreferencesXML) fFormatPreferences).setSplitMultiAttrs(preferences.getBoolean(XMLCorePreferenceNames.SPLIT_MULTI_ATTRS));
        ((StructuredFormatPreferencesXML) fFormatPreferences).setAlignEndBracket(preferences.getBoolean(XMLCorePreferenceNames.ALIGN_END_BRACKET));
        ((StructuredFormatPreferencesXML) fFormatPreferences).setPreservePCDATAContent(preferences.getBoolean(XMLCorePreferenceNames.PRESERVE_CDATACONTENT));
        fFormatPreferences.setClearAllBlankLines(preferences.getBoolean(XMLCorePreferenceNames.CLEAR_ALL_BLANK_LINES));

        char indentChar = ' ';
        String indentCharPref = preferences.getString(XMLCorePreferenceNames.INDENTATION_CHAR);
        if (XMLCorePreferenceNames.TAB.equals(indentCharPref)) {
          indentChar = '\t';
        }
        int indentationWidth = preferences.getInt(XMLCorePreferenceNames.INDENTATION_SIZE);

        StringBuffer indent = new StringBuffer();
        for (int i = 0; i < indentationWidth; i++) {
          indent.append(indentChar);
        }
        fFormatPreferences.setIndent(indent.toString());
      }
    }

    return fFormatPreferences;
  }

  protected IStructuredFormatter getFormatter(IDOMNode node) {
    // 262135 - NPE during format of empty document
    if (node == null)
      return null;

    short nodeType = ((Node) node).getNodeType();
    IStructuredFormatter formatter = null;
    switch (nodeType) {
      case Node.ELEMENT_NODE : {
        formatter = new ElementNodeFormatter();
        break;
      }
      case Node.TEXT_NODE : {
        formatter = new TextNodeFormatter();
        break;
      }
      case Node.CDATA_SECTION_NODE : {
        formatter = new NoMoveFormatter();
        break;
      }
      case Node.COMMENT_NODE : {
        formatter = new CommentNodeFormatter();
        break;
      }
      case Node.PROCESSING_INSTRUCTION_NODE : {
        formatter = new NodeFormatter();
        break;
      }
      case Node.DOCUMENT_NODE : {
        formatter = new DocumentNodeFormatter();
        break;
      }
      case Node.ENTITY_REFERENCE_NODE : {
        formatter = new NoMoveFormatter();
        break;
      }
      default : {
        formatter = new NodeFormatter();
      }
    }

    // init fomatter
    formatter.setFormatPreferences(getFormatPreferences());
    formatter.setProgressMonitor(fProgressMonitor);

    return formatter;
  }

  protected int getIndentationLength(String indent) {
    // TODO Kit : The calculation of IndentationLength is not correct
    // here.
    // nodeIndentation may contain tabs. Multiply by 4 temporarily to get
    // approx. width.
    // Need to re-work.

    int indentationLength = 0;

    for (int i = 0; i < indent.length(); i++) {
      if (indent.substring(i, i + 1).compareTo(TAB) == 0)
        indentationLength += 4;
      else
        indentationLength++;
    }

    return indentationLength;
  }

  protected Preferences getModelPreferences() {
    return XMLCorePlugin.getDefault().getPluginPreferences();
  }

  /**
   * This method will find the indentation for this node. It will search
   * backwards starting from the beginning of the node until a character
   * other than a space or a tab is found. If this node is null or it's a
   * document node or it's a first level node (node's parent is a document
   * node) the default empty string will be returned as the indentation.
   */
  protected String getNodeIndent(Node node) {
    String result = EMPTY_STRING;

    if ((node != null) && (node.getNodeType() != Node.DOCUMENT_NODE) && (node.getParentNode() != null) && (node.getParentNode().getNodeType() != Node.DOCUMENT_NODE)) {
      IDOMNode siblingTextNode = (IDOMNode) node.getPreviousSibling();
      if ((siblingTextNode != null) && (siblingTextNode.getNodeType() == Node.TEXT_NODE)) {
        // find the indentation
        String siblingText = siblingTextNode.getNodeValue();
        int siblingTextLength = siblingText.length();
        if ((siblingText != null) && (siblingTextLength > 0) && ((siblingText.charAt(siblingTextLength - 1) == SPACE_CHAR) || (siblingText.charAt(siblingTextLength - 1) == TAB_CHAR))) {
          int searchIndex = siblingTextLength - 1;
          while ((searchIndex >= 0) && ((siblingText.charAt(searchIndex) == SPACE_CHAR) || (siblingText.charAt(searchIndex) == TAB_CHAR)))
            searchIndex--;

          if (searchIndex < siblingTextLength)
            result = siblingText.substring(searchIndex + 1, siblingTextLength);
        }
      }
    }

    return result;
  }

  protected String getNodeName(IDOMNode node) {
    return node.getNodeName();
  }

  protected String getNodeText(IDOMNode node) {
    String text = null;

    if ((node instanceof CharacterDataImpl) && !(node instanceof CommentImpl) && !(node instanceof CDATASectionImpl) && !isJSPTag(node))
      text = ((CharacterDataImpl) node).getSource();
    else
      text = node.getFirstStructuredDocumentRegion().getText();

    return text;
  }

  protected IDOMNode getParentIndentNode(IDOMNode node) {
    IDOMNode result = null;
    IDOMNode parentNode = (IDOMNode) node.getParentNode();

    if (parentNode.getNodeType() == Node.DOCUMENT_NODE)
      result = parentNode;
    else {
      ITextRegion region = parentNode.getLastStructuredDocumentRegion().getFirstRegion();
      if (region.getType() == DOMRegionContext.XML_END_TAG_OPEN)
        result = parentNode;
      else
        result = getParentIndentNode(parentNode);
    }

    return result;
  }

  /**
   * This method will find the indentation for a node sibling to this node.
   * It will try to find a sibling node before this node first. If there is
   * no sibling node before this node, it will try to find a sibling node
   * after this node. If still not found, we will check if this node is
   * already indented from its parent. If yes, this node's indentation will
   * be used. Otherwise, the parent node's indentation plus one indentation
   * will be used. If this node is null or it's a document node or it's a
   * first level node (node's parent is a document node) the default empty
   * string will be returned as the indentation.
   */
  protected String getSiblingIndent(Node node) {
    String result = EMPTY_STRING;

    if ((node != null) && (node.getNodeType() != Node.DOCUMENT_NODE) && (node.getParentNode() != null) && (node.getParentNode().getNodeType() != Node.DOCUMENT_NODE)) {
      // find the text node before the previous non-text sibling
      // if that's not found, we will try the text node before the next
      // non-text sibling
      IDOMNode sibling = (IDOMNode) node.getPreviousSibling();
      while ((sibling != null) && (sibling.getNodeType() == Node.TEXT_NODE || sibling.getNodeType() == Node.COMMENT_NODE)) {
        if (sibling.getNodeType() == Node.COMMENT_NODE && sibling.getPreviousSibling() != null && sibling.getPreviousSibling().getNodeType() == Node.TEXT_NODE && StringUtils.containsLineDelimiter(sibling.getPreviousSibling().getNodeValue()))
          break;
        sibling = (IDOMNode) sibling.getPreviousSibling();
      }
      if (sibling == null) {
        sibling = (IDOMNode) node.getNextSibling();
        while ((sibling != null) && (sibling.getNodeType() == Node.TEXT_NODE))
          sibling = (IDOMNode) sibling.getNextSibling();
      }
      String singleIndent = getFormatPreferences().getIndent();
      String parentLineIndent = getNodeIndent(node.getParentNode());

      if (sibling != null) {
        String siblingIndent = getNodeIndent(sibling);
        if (siblingIndent.length() > 0)
          result = siblingIndent;
        else {
          String nodeIndent = getNodeIndent(node);
          if (nodeIndent.length() > parentLineIndent.length())
            // this node is indented from its parent, its
            // indentation will be used
            result = nodeIndent;
          else
            result = parentLineIndent + singleIndent;
        }
      }
      else {
        String nodeIndent = getNodeIndent(node);
        if (nodeIndent.length() > parentLineIndent.length())
          // this node is indented from its parent, its indentation
          // will be used
          result = nodeIndent;
        else
          result = parentLineIndent + singleIndent;
      }
    }

    return result;
  }

  protected void insertAfterNode(IDOMNode node, String string) {
    IDOMModel structuredModel = node.getModel();
    IStructuredDocument structuredDocument = structuredModel.getStructuredDocument();

    int offset = node.getEndOffset();
    int length = 0;

    // 261968 - formatting tag without closing bracket: <t1><t1
    if (node.getEndStructuredDocumentRegion() != null) {
      offset = node.getEndStructuredDocumentRegion().getTextEndOffset();
      length = node.getEndOffset() - offset;
    }
    replace(structuredDocument, offset, length, string);
  }

  protected void insertBeforeNode(IDOMNode node, String string) {
    IDOMModel structuredModel = node.getModel();
    IStructuredDocument structuredDocument = structuredModel.getStructuredDocument();

    replace(structuredDocument, node.getStartOffset(), 0, string);
  }

  /**
   * Allowing the INodeAdapter to compare itself against the type allows it
   * to return true in more than one case.
   */
  public boolean isAdapterForType(Object type) {
    return type.equals(IStructuredFormatter.class);
  }

  protected boolean isEndTagMissing(IDOMNode node) {
    boolean result = false;

    if ((node != null) && (node.getNodeType() != Node.DOCUMENT_NODE) && !isJSPTag(node)) {
      IStructuredDocumentRegion startTagStructuredDocumentRegion = node.getFirstStructuredDocumentRegion();
      IStructuredDocumentRegion endTagStructuredDocumentRegion = node.getLastStructuredDocumentRegion();

      ITextRegion startTagNameRegion = null;
      if (startTagStructuredDocumentRegion.getRegions().size() > 1)
        startTagNameRegion = startTagStructuredDocumentRegion.getRegions().get(1);
      ITextRegion endTagNameRegion = null;
      if (endTagStructuredDocumentRegion.getRegions().size() > 1)
        endTagNameRegion = endTagStructuredDocumentRegion.getRegions().get(1);

      ITextRegionList startTagRegions = startTagStructuredDocumentRegion.getRegions();
      if (startTagNameRegion == endTagNameRegion && startTagNameRegion != null && (startTagRegions.get(0)).getType() != DOMRegionContext.XML_END_TAG_OPEN && (startTagRegions.get(startTagRegions.size() - 1).getType()) != DOMRegionContext.XML_EMPTY_TAG_CLOSE)
        // end tag missing
        result = true;
    }

    return result;
  }

  protected boolean nodeHasSiblings(IDOMNode node) {
    return (node.getPreviousSibling() != null) || (node.getNextSibling() != null);
  }

  /**
   * Node changed. No format should be performed automatically.
   */
  public void notifyChanged(org.eclipse.wst.sse.core.internal.provisional.INodeNotifier notifier, int eventType, Object changedFeature, Object oldValue, Object newValue, int pos) {
  }

  protected void removeRegionSpaces(IDOMNode node, IStructuredDocumentRegion flatNode, ITextRegion region) {
    if ((region != null) && (region instanceof ContextRegion || region instanceof TagNameRegion) && (flatNode.getEndOffset(region) > flatNode.getTextEndOffset(region))) {
      IDOMModel structuredModel = node.getModel();
      IStructuredDocument structuredDocument = structuredModel.getStructuredDocument();

      replace(structuredDocument, flatNode.getTextEndOffset(region), flatNode.getEndOffset(region) - flatNode.getTextEndOffset(region), EMPTY_STRING);
    }
  }

  /**
   * This method will replace the string at offset and length with a new
   * string. If the string to be replaced is the same as the new string, the
   * string will not be replaced.
   */
  protected void replace(IStructuredDocument structuredDocument, int offset, int length, String string) {
    try {
      String structuredDocumentString = structuredDocument.get(offset, length);
      if (structuredDocumentString.compareTo(string) != 0)
        structuredDocument.replaceText(structuredDocument, offset, length, string);
    }
    catch (BadLocationException e) {
      // log for now, unless we find reason not to
      Logger.log(Logger.INFO, e.getMessage());
    }
  }

  /**
   * This method will replace the node value with a new string. If the node
   * value to be replaced is the same as the new string, the node value will
   * not be replaced.
   */
  protected void replaceNodeValue(IDOMNode node, String string) {
    IDOMModel structuredModel = node.getModel();
    IStructuredDocument structuredDocument = structuredModel.getStructuredDocument();
    int offset = node.getStartOffset();
    int length = node.getEndOffset() - node.getStartOffset();

    try {
      String structuredDocumentString = structuredDocument.get(offset, length);
      if (structuredDocumentString.compareTo(string) != 0)
        replace(structuredDocument, offset, length, string);
    }
    catch (BadLocationException e) {
      // log for now, unless we find reason not to
      Logger.log(Logger.INFO, e.getMessage());
    }
  }

  public void setFormatPreferences(IStructuredFormatPreferences formatPreferences) {
    fFormatPreferences = formatPreferences;
  }

  /*
   * (non-Javadoc)
   *
   * @see org.eclipse.wst.sse.core.format.IStructuredFormatter#setProgressMonitor(org.eclipse.core.runtime.IProgressMonitor)
   */
  public void setProgressMonitor(IProgressMonitor monitor) {
    fProgressMonitor = monitor;
  }

  /**
   * ISSUE: this is a bit of hidden JSP knowledge that was implemented this
   * way for expedency. Should be evolved in future to depend on
   * "nestedContext".
   */
  private boolean isJSPTag(Node node) {

    final String JSP_CLOSE = "JSP_CLOSE"; //$NON-NLS-1$
    // final String JSP_COMMENT_CLOSE = "JSP_COMMENT_CLOSE"; //$NON-NLS-1$

    // final String JSP_COMMENT_OPEN = "JSP_COMMENT_OPEN"; //$NON-NLS-1$
    // final String JSP_COMMENT_TEXT = "JSP_COMMENT_TEXT"; //$NON-NLS-1$

    final String JSP_CONTENT = "JSP_CONTENT"; //$NON-NLS-1$
    final String JSP_DECLARATION_OPEN = "JSP_DECLARATION_OPEN"; //$NON-NLS-1$
    final String JSP_DIRECTIVE_CLOSE = "JSP_DIRECTIVE_CLOSE"; //$NON-NLS-1$
    final String JSP_DIRECTIVE_NAME = "JSP_DIRECTIVE_NAME"; //$NON-NLS-1$

    final String JSP_DIRECTIVE_OPEN = "JSP_DIRECTIVE_OPEN"; //$NON-NLS-1$
    final String JSP_EXPRESSION_OPEN = "JSP_EXPRESSION_OPEN"; //$NON-NLS-1$

    // final String JSP_ROOT_TAG_NAME = "JSP_ROOT_TAG_NAME"; //$NON-NLS-1$

    final String JSP_SCRIPTLET_OPEN = "JSP_SCRIPTLET_OPEN"; //$NON-NLS-1$

    boolean result = false;

    if (node instanceof IDOMNode) {
      IStructuredDocumentRegion flatNode = ((IDOMNode) node).getFirstStructuredDocumentRegion();
      // in some cases, the nodes exists, but hasn't been associated
      // with
      // a flatnode yet (the screen updates can be initiated on a
      // different thread,
      // so the request for a flatnode can come in before the node is
      // fully formed.
      // if the flatnode is null, we'll just allow the defaults to
      // apply.
      if (flatNode != null) {
        String flatNodeType = flatNode.getType();
        // should not be null, but just to be sure
        if (flatNodeType != null) {
          if ((flatNodeType.equals(JSP_CONTENT)) || (flatNodeType.equals(JSP_EXPRESSION_OPEN)) || (flatNodeType.equals(JSP_SCRIPTLET_OPEN)) || (flatNodeType.equals(JSP_DECLARATION_OPEN)) || (flatNodeType.equals(JSP_DIRECTIVE_CLOSE)) || (flatNodeType.equals(JSP_DIRECTIVE_NAME)) || (flatNodeType.equals(JSP_DIRECTIVE_OPEN)) || (flatNodeType.equals(JSP_CLOSE))) {
            result = true;
          }
        }
      }
    }

    return result;
  }
}
TOP

Related Classes of org.eclipse.wst.xml.core.internal.provisional.format.NodeFormatter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.