/**
* This file Copyright (c) 2005-2008 Aptana, Inc. This program is
* dual-licensed under both the Aptana Public License and the GNU General
* Public license. You may elect to use one or the other of these licenses.
*
* This program is distributed in the hope that it will be useful, but
* AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
* NONINFRINGEMENT. Redistribution, except as permitted by whichever of
* the GPL or APL you select, is prohibited.
*
* 1. For the GPL license (GPL), you can redistribute and/or modify this
* program under the terms of the GNU General Public License,
* Version 3, as published by the Free Software Foundation. You should
* have received a copy of the GNU General Public License, Version 3 along
* with this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Aptana provides a special exception to allow redistribution of this file
* with certain other free and open source software ("FOSS") code and certain additional terms
* pursuant to Section 7 of the GPL. You may view the exception and these
* terms on the web at http://www.aptana.com/legal/gpl/.
*
* 2. For the Aptana Public License (APL), this program and the
* accompanying materials are made available under the terms of the APL
* v1.0 which accompanies this distribution, and is available at
* http://www.aptana.com/legal/apl/.
*
* You may view the GPL, Aptana's exception and additional terms, and the
* APL in the file titled license.html at the root of the corresponding
* plugin containing this source file.
*
* Any modifications to this file must keep this entire header intact.
*/
package com.aptana.xml;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
/**
* @author Kevin Lindsey
*/
public class NodeBase implements INode, Comparable<NodeBase>
{
/**
* empty string
*/
protected static final String EMPTY_STRING = ""; //$NON-NLS-1$
private List<Class<?>> childTypes;
private INode _parent;
private List<INode> _children;
private int _childCount;
private StringBuffer _text;
private int _columnNumber;
private int _lineNumber;
/**
* NodeBase
*/
public NodeBase()
{
}
/**
* addAllowableChildType
*
* @param type
*/
public void addChildType(Class<?> type)
{
if (childTypes == null)
{
childTypes = new ArrayList<Class<?>>();
}
if (childTypes.contains(type) == false)
{
childTypes.add(type);
}
}
/**
* @see com.aptana.xml.INode#appendChild(INode)
*/
public void appendChild(INode child)
{
boolean allowed = false;
if (childTypes != null)
{
for (int i = 0; i < childTypes.size(); i++)
{
Class<?> type = childTypes.get(i);
if (type.isInstance(child))
{
allowed = true;
break;
}
}
}
if (allowed)
{
if (this._children == null)
{
this._children = new ArrayList<INode>();
}
this._children.add(child);
this._childCount++;
if (child instanceof NodeBase)
{
((NodeBase) child).setParent(this);
}
}
else
{
String thisName = this.getClass().getName();
String childName = child.getClass().getName();
String message = MessageFormat.format(
Messages.NodeBase_Invalid_Child_Type,
new Object[] { thisName, childName }
);
throw new IllegalArgumentException(message);
}
}
/**
* @see com.aptana.xml.INode#appendText(java.lang.String)
*/
public void appendText(String text)
{
if (text != null && text.length() > 0)
{
if (this._text == null)
{
this._text = new StringBuffer();
}
this._text.append(text);
}
}
/**
* @see com.aptana.xml.INode#getChild(int)
*/
public INode getChild(int index)
{
INode result = null;
if (this._children != null)
{
if (0 <= index && index < this._childCount)
{
result = this._children.get(index);
}
}
return result;
}
/**
* @see com.aptana.xml.INode#getChildCount()
*/
public int getChildCount()
{
return this._childCount;
}
/**
* @see com.aptana.xml.INode#getDocument()
*/
public DocumentNode getDocument()
{
INode result = this.getParent();
while (result != null && (result instanceof DocumentNode) == false)
{
result = result.getParent();
}
// TODO: [KEL] DocumentNode should create all nodes so it can auto-associated itself.
// We will not this hack once that is in place.
if (result == null)
{
result = new DocumentNode();
}
return (DocumentNode) result;
}
/**
* @see com.aptana.xml.INode#getParent()
*/
public INode getParent()
{
return this._parent;
}
/**
* @see com.aptana.xml.INode#getText()
*/
public String getText()
{
String result = EMPTY_STRING;
if (this._text != null)
{
result = this._text.toString();
}
return result;
}
/**
* removeChild
*
* @param child
*/
public void removeChild(INode child)
{
if (this._children != null)
{
if (this._children.remove(child))
{
this._childCount--;
}
if (child instanceof NodeBase)
{
((NodeBase) child)._parent = null;
}
}
}
/**
* removeChildType
*
* @param type
*/
public void removeChildType(Class<?> type)
{
if (childTypes != null)
{
childTypes.remove(type);
}
}
/**
* removeText
*/
public void removeText()
{
this._text = null;
}
/**
* setParent
*
* @param parent
*/
protected void setParent(INode parent)
{
if (this._parent != null)
{
// remove from old parent
this._parent.removeChild(this);
}
this._parent = parent;
}
/**
* getColumnNumber
*
* @return int
*/
public int getColumnNumber()
{
return this._columnNumber;
}
/**
* setColumnNumber
*
* @param columnNumber
*/
public void setColumnNumber(int columnNumber)
{
this._columnNumber = columnNumber;
}
/**
* getLineNumber
*
* @return int
*/
public int getLineNumber()
{
return this._lineNumber;
}
/**
* setLineNumber
*
* @param lineNumber
*/
public void setLineNumber(int lineNumber)
{
this._lineNumber = lineNumber;
}
/**
* @see java.lang.Comparable#compareTo(java.lang.Object)
*/
public int compareTo(NodeBase that)
{
int result = this.getLineNumber() - that.getLineNumber();
if (result == 0)
{
result = this.getColumnNumber() - that.getColumnNumber();
}
return result;
}
}