Package org.cfeclipse.cfml.parser.docitems

Source Code of org.cfeclipse.cfml.parser.docitems.DocItem

/*
* Created on Mar 21, 2004
*
* The MIT License
* Copyright (c) 2004 Oliver Tupman
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the Software
* is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.cfeclipse.cfml.parser.docitems;

import java.util.ArrayList;

import org.cfeclipse.cfml.dictionary.SyntaxDictionary;
import org.cfeclipse.cfml.parser.CFNodeList;
import org.cfeclipse.cfml.parser.ParseError;
import org.cfeclipse.cfml.parser.ParseMessage;
import org.cfeclipse.cfml.parser.State;
import org.cfeclipse.cfml.parser.exception.InvalidChildItemException;
import org.cfeclipse.cfml.parser.exception.NodeNotFound;
import org.cfeclipse.cfml.parser.xpath.XPathSearch;
import org.cfeclipse.cfml.parser.xpath.expressions.ComparisonType;


/**
* The DocItem class is intended to be the abstract base class for parsing and representing
* internally the structure of a document.
* It has a name, a item specific name for the item. Examples might be 'cfset' in the
* case of CFML, or "DoAQuery" in the case of a UDF.
* DocItem is an abstract class, intended to be the base for representing an in-document item,
* be it a ScriptItem (like a scripted function) or a CFML tag such as <cfswitch>, <cfcase> or
* CFC stuff (which I'm most interested in!). DocItem stores the name, lineNumber and start &
* finish offsets within the document so that we can precisely locate it.
* DocItem also stores the children, therefore it can act as a branch for part of a tree.
* Hence the addChild() method. Haven't added anything else for retrieving children... because I'm lazy :)
*/
public abstract class DocItem implements Comparable {
  /** The name of the item (i.e. &lt;cfscript&gt;) */
  protected String itemName = "";
  /** The complete start-to-finish data for the item (i.e. &lt;cffunction name="asdf" ... &gt;)   */
  protected String itemData = "";
 
  /** The line number for the start of the match */
  protected int lineNumber;
  /** The start position in the document  */
  protected int startPosition;
  /** The end position in the document   */
  protected int endPosition;
  /** The list of variables for the document   */
  public ArrayList  docVariables;
  /** The children for this node.   */
  protected CFNodeList docNodes;
  /** The parent of this node. */
  protected DocItem parentNode;
  /** The previous sibling node. Null if there isn't one.*/
  protected DocItem prevSiblingNode = null;
  /** The next sibling node. Null if there isn't one.*/
  protected DocItem nextSiblingNode = null;
  /** Syntax dictionary for working out important things for the parser. */
  protected SyntaxDictionary syntax = null;
  /** */
  protected State parseMessages = null;
 
 
  /**
   * Initialises the dictionary
   * @param newDict the dictionary to init with
   */
  public void initDictionary(SyntaxDictionary newDict)
  {
    syntax = newDict;
  }
 
  /**
   * Returns itemData
   * @return the data for the item
   */
  public String getItemData()
  {
    return itemData;
  }
  /**
   * Sets the item's data. Shouldn't really be called.
   * @param data
   */
  public void setItemData(String data)
  {
    itemData = data;
  }
  /**
   * Constructor.
   * @param line - the line that the match was made
   * @param startDocPos - the start point in the doc
   * @param endDocPos - the end point in the doc
   * @param name - the name for the tag (i.e. <html> without the chevrons)
   */
  public DocItem(int line, int startDocPos, int endDocPos, String name)
  {
    lineNumber = line;
    startPosition = startDocPos;
    endPosition = endDocPos;
    itemName = name;
   
    docNodes = new CFNodeList();
    docVariables = new ArrayList();
    parseMessages = new State("");
  }
 
  /**
   * Constructor for a DocItem.
   * <strong>WARNING:</warning> This is only intended to be used by the CFScript parser.
   *
   */
  public DocItem() {
    docNodes = new CFNodeList();
    docVariables = new ArrayList();
    parseMessages = new State("");   
  }
 
  public State getParseState()
  {
    return parseMessages;
  }
 
  protected void addParseMessage(ParseMessage newMsg)
  {
  //System.out.println("DocItem::addParseMessage() - Adding message " + newMsg.getMessage());
    parseMessages.addMessage(newMsg);
  }
 
  public String getName()
  {
    return itemName;
  }
  public int getStartPosition() {
    return startPosition;
  }
  public int getEndPosition() {
    return endPosition;
  }
  public DocItem getMatchingItem() {
    return null;
  }
 
  public boolean hasChildren()
  {
    return docNodes.size() > 0;
  }
 
  public DocItem getFirstChild()
  {
    return (DocItem)docNodes.get(0);
  }
 
  public DocItem getLastChild()
  {
    return (DocItem) docNodes.get(docNodes.size() - 1);
  }
 
  /**
   * gets the parent of this docitem
   * @return
   */
  public DocItem getParent()
  {
    return parentNode;
  }
 
  public void setParent(DocItem newParent)
  {
    if(newParent != this)
    parentNode = newParent;
  }
 
  public void setPrevSibling(DocItem newPrevSibling)
  {
    prevSiblingNode = newPrevSibling;
  }
 
  public void setNextSibling(DocItem newNextSibling)
  {
    nextSiblingNode = newNextSibling;
  }
 
  public CFNodeList getChildNodes()
  {
    return docNodes;
  }
  /**
   *
   * @deprecated Please use getChildNodes() instead
   * @see org.cfeclipse.cfml.parser.docitems.DocItem::getChildNodes()
   */
  public ArrayList getChildren()
  {
    return docNodes;
  }
 
  public int getLineNumber() { return lineNumber; }
 
  /**
   * Adds a child to this item's child node list.
   * It first asks the new item whether it's allowed to belong to this
   * item, for example &lt;cfelse&gt; tags must only be a child of an &lt;cfif&gt; tag.
   * @param newItem The new document item to add.
   * @return true - child added, false - error with child.
   */
  public boolean addChild(DocItem newItem)
  {
    boolean addOkay = true;
   
    if(!newItem.validChildAddition(this))
    {
      parseMessages.addMessage(new ParseError(newItem.getLineNumber(), newItem.getStartPosition(), newItem.getEndPosition(), newItem.getItemData(),
                    "Invalid child " + newItem.getClass().getName() + ":\'" + newItem.getName() + "\' for parent \'" + getName() + "\'"));
      addOkay = false;
    }
    //
    // Set the item's parent & sibling
    newItem.setParent(this);
    if(docNodes.size() == 0)
      newItem.setPrevSibling(null);
    else
      newItem.setPrevSibling((DocItem)docNodes.get(docNodes.size()-1));
   
    docNodes.add(newItem);
   
    return addOkay;
  }
 
  /**
   * Inserts the node newChild before existing node refChild. If refChild is null, insert newChild at end of the list of children.
   * @param newChild The new child node to insert
   * @param refChild The reference node, i.e. the node before which the new node must be inserted.
   * @throws InvalidChildItemException Raised if <code>newChild</code> being added is not valid for this node type.
   * @throws NodeNotFound Raised if the <code>refChild</code> node is not found in the node's children.
   */
  public void insertBefore(DocItem newChild, DocItem refChild)
        throws InvalidChildItemException, NodeNotFound
  {
    if(!newChild.validChildAddition(this))
      throw new InvalidChildItemException("Child item of type \'" + newChild.getName() + "\' says it is not allowed to belong to this (\'" + itemName + "\') doc item");
   
    int insertPos = docNodes.size();
   
    //
    // Does the refChild exist and exists in this node's children?
    if(refChild != null && docNodes.contains(refChild))
      insertPos = docNodes.indexOf(refChild);
    else if(refChild != null// Isn't null & doesn't belong to this node. Argh!
      throw new NodeNotFound("Cannot find node \'" + refChild.getName() +"\'");
   
    docNodes.add(insertPos, newChild);
  }
 
  /**
   * Removes the specified child from the list of nodes.
   * @param oldChild The node to remove
   * @return The node removed.
   * @throws NodeNotFound Raised if the <code>refChild</code> node is not found in the node's children.
   */
  public DocItem removeChild(DocItem oldChild) throws NodeNotFound
  {
    if(!docNodes.remove(oldChild))
      throw new NodeNotFound("Cannot find node \'" + oldChild.getName() +"\'");
   
    return oldChild;
  }
 
  /**
   * Intended to be called from a DocItem's addChild() method. Asks the new child item to check whether
   * it is allowed to belong to the parent item.
   * <b>NB:</b> The default implementation <b>ALWAYS</b> returns false. Override in any derived classes.
   * @param parentItem
   * @return
   */
  public boolean validChildAddition(DocItem parentItem)
  {
    return false;
  }
 
  private CFNodeList selectNodes(XPathSearch search) {
    CFNodeList result = new CFNodeList();   
   
    if(docNodes == null) {
      docNodes = new CFNodeList();
    }

    for(int i = 0; i < docNodes.size(); i++)
    {
      DocItem currItem = (DocItem)docNodes.get(i);
      DocItem endItem = null;
      if (search.searchForEndTag
              && currItem.getMatchingItem() != null) {
          endItem = currItem.getMatchingItem();
      }

      int matches = 0;
      int endMatches = 0;
     
      if(search.doChildNodes)
        result.addAll(currItem.selectNodes(search));
     
      //r2 added simple * node selection
      if(search.searchForTag
        && (currItem.getName().compareToIgnoreCase(search.tagName) == 0
                || search.tagName.equals("*"))
      ) {
        matches++;
      }
      if (endItem != null
              && search.searchForTag
          && (endItem.getName().compareToIgnoreCase(search.tagName) == 0
                  || search.tagName.equals("*"))
        ) {
          endMatches++;
      }
     
  //System.out.print("DocItem::selectNodes() - Testing \'" + currItem.getName() + "\'");
      if(search.attrSearch.containsKey(XPathSearch.ATTR_STARTPOS)) {
        ComparisonType comp = (ComparisonType)search.attrSearch.get(XPathSearch.ATTR_STARTPOS);
    //System.out.println(XPathSearch.ATTR_STARTPOS + ": ");
        if(comp.performComparison(currItem.startPosition))
        {
          matches++;
          //System.out.print(" success ");
        }
        if (endItem != null
                && comp.performComparison(endItem.startPosition)) {
            endMatches++;
        }
         
      }
      if(search.attrSearch.containsKey(XPathSearch.ATTR_ENDPOS)) {
    //System.out.print(XPathSearch.ATTR_ENDPOS + ":");
        ComparisonType comp = (ComparisonType)search.attrSearch.get(XPathSearch.ATTR_ENDPOS);
        if(comp.performComparison(currItem.endPosition)) {
          matches++;
      //System.out.print(" success ");
        }
        if (endItem != null
                && comp.performComparison(endItem.endPosition)) {
            endMatches++;
      //System.out.println(" failed ");
        }
      }
     
      if(matches == search.getMatchesRequired())
      {
      //System.out.println("DocItem::selectNodes(XPathSearch) - Got match for " + currItem.itemName);
        result.add(currItem);
        //System.out.print(" name match success");
      }
      else if(endItem != null
              && endMatches == search.getMatchesRequired()){
          result.add(currItem);
          //System.out.println(" End matched " + endItem.getMatchingItem());
    //System.out.print(" name match failed with ");
      }
     
  //System.out.println("");
    }       
   
    return result;
  }
 
  public CFNodeList selectNodes(String searchString)// throws Exception
  {
   
    return selectNodes(searchString, false);
  }
 
 
  public CFNodeList selectNodes(String searchString, boolean includeEndTags)// throws Exception
  {
    //CFNodeList result = new CFNodeList();
    XPathSearch search = new XPathSearch();
    search.searchForEndTag = includeEndTags;
    if(!search.parseXPath(searchString)) {
      //throw new Exception("XPath string \'" + searchString + "\' was invalid");
    }
    return selectNodes(search);
  }
 
  /**
   * The final parse check. This is to be run just before the object's
   * parse messages are retrieved. Each document object will run a sanity
   * test to ensure that it is valid. For example a CfmlTagFunction will check
   * to make sure that it has the 'name' attribute.
   * @return true - item is sane, false - item is not sane.
   */
  public boolean IsSane()
  {
    return true;
  }
 
  /**
   * This is my sad attempt to make the content outline faster
   * it doesnt seem to do much. We can probably remove it but it's here
   * so - eh
   * @author Rob
   */
  public int compareTo(Object o)
  {
    if(o == null) throw new NullPointerException("DocItem compareTo got a null");
   
    if(o instanceof DocItem)
    {
      return o.toString().compareTo(this.toString());
    }
   
    return 0;
  }
 
  /**
   * This is my sad attempt to make the content outline faster
   * it doesnt seem to do much. We can probably remove it but it's here
   * so - eh
   * @author Rob
   */
  public boolean equals(Object obj)
  {
    if(obj instanceof DocItem)
    {
      //if it has the same name and number of parameters assume its
      //the same (this may need to be adjusted in the future)
      if( ((DocItem)obj).toString().equals(toString()) )
      {
        //System.err.println("we are equal: " + toString());
        return true;
      }
    }
    return false;
  }
 
  /**
   * override the toString so we can compare (might need to move this to a
   * less obvious method)
   * @author Rob
   */
  public String toString()
  {
    //weak, but should work, unique id
    return itemName + ":" + lineNumber + ":" + startPosition + ":" + endPosition;
  }
}
TOP

Related Classes of org.cfeclipse.cfml.parser.docitems.DocItem

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.