package com.quantum.view.subset;

import com.quantum.Messages;
import com.quantum.model.Entity;
import com.quantum.model.EntityHolder;
import com.quantum.sql.metadata.MetaDataXMLInterface;
import com.quantum.sql.metadata.ObjectMetaData;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

/**
 * Defines a node for the Subset. It contains an editable ObjectMetaData 
 * where you can erase columns you are not interested in. 
 * @author jparrai
 *
 */
public class ObjectNode implements Comparable, EntityHolder {
	private SubsetNode parent = null;
	private ObjectMetaData metadata = null;
	private int order = 0;
    private Entity entity;
	
	public ObjectNode(SubsetNode parent, ObjectMetaData metadata, String bookmark, String name, String schema) {
		this.parent = parent;
		this.metadata = metadata;
        this.entity = new EntitySubset(name, schema, bookmark);
	}
	
	public ObjectNode(){
	}
	public String getType(){
		return Entity.VIEW_TYPE;
	}

	/* (non-Javadoc)
	 * @see com.quantum.view.bookmark.TreeNode#getChildren()
	 * We consider the columns of the metadata to be the children.
	 */
	public Object[] getChildren() {
//		if (metadata != null && ColumnMetaData.getColumnsMetaDataNode(metadata, this) != null) {
//			return ColumnMetaData.getColumnsMetaDataNode(metadata, this).toArray();
//		} else {
			return SubsetRoot.EMPTY_ARRAY;
//		}
	}

	public Object getParent() {
		return parent;
	}

	public boolean hasChildren() {
//		if (metadata == null) return false;
//		return (ColumnMetaData.getColumnsMetaDataNode(metadata, this) != null && 
//				ColumnMetaData.getColumnsMetaDataNode(metadata, this).size() > 0);
        return false;
	}
	
	public String getName() {
		return this.entity.getName();
	}
	
	public String toString() {
		return getName();
	}

	public int compareTo(Object o) {
		if (o instanceof ObjectNode) {
			ObjectNode node = (ObjectNode) o;
			if (node.getOrder() > getOrder()) return -1;
			if (node.getOrder() < getOrder()) return 1;
			// If the order is the same, we use alphabetical order 
			return getEntity().getQualifiedName().compareTo(
                node.getEntity().getQualifiedName());
		} else throw new ClassCastException();
	}
	
	public void setObjectMetadata(ObjectMetaData metadata) {
		this.metadata = metadata;
	}
	/**
	 * @return
	 */
	public ObjectMetaData getMetaData() {
		return metadata;
	}

	/**
	 * @return The order of this ObjectNode inside the SubsetNode
	 */
	public int getOrder() {
		return order;
	}
	/**
	 * Sets an ordering (inside the SubsetNode) to the ObjectNode
	 * @param i
	 */
	public void setOrder(int i) {
		order = i;
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	public boolean equals(Object obj) {
		if (!(obj instanceof ObjectNode)) return false;
		return (getEntity().getQualifiedName().equals(
            ((ObjectNode) obj).getEntity().getQualifiedName()));
	}
	
	/**
	 * Imports one ObjectNode from an XMLDocument. There must be a tag for the Table Name, another for the Bookmark
	 * name and other for the metadata. The complement function is exportXML()
	 * @param root Document to get the data from
	 * @param parent The SubsetNode to which to add the new ObjectNode
	 * @return The newly created ObjectNode, or null if some error.
	 */
	public static ObjectNode importXML(Element root, SubsetNode parent){
		// Get the name tag value into objName
		String objName = MetaDataXMLInterface.getElementText(root, Messages.getString("ExportXMLAction.TableName")); //$NON-NLS-1$
		String objSchema = MetaDataXMLInterface.getElementText(root, Messages.getString("ExportXMLAction.SchemaName")); //$NON-NLS-1$
		if (objName == "") return null;	 //$NON-NLS-1$
		// Get the bookmark tag value into objName
		String bookmarkName = MetaDataXMLInterface.getElementText(root, Messages.getString("ExportXMLAction.BookmarkName")); //$NON-NLS-1$
		if (bookmarkName == "") return null; //$NON-NLS-1$
		ObjectMetaData metadata = new ObjectMetaData();
		// The rest of the tags go to be the metadata
		MetaDataXMLInterface.xmlToMetaData(metadata, root);
		// We can finally create the new ObjectNode with the collected data
		ObjectNode objectNode = new ObjectNode(parent, metadata, bookmarkName, objName, objSchema);
		return objectNode;					
	}
	
	/**
	 * Exports an ObjectNode to an XMLDocument. The complement function is importXML()
	 * @param root	Document to write the XML tags to
	 */
	public void exportXML(Element root){
		Document doc = root.getOwnerDocument();
		Element sub = (Element) root.appendChild(doc.createElement(Messages.getString("ExportXMLAction.Table"))); //$NON-NLS-1$
		MetaDataXMLInterface.createElementText(sub,Messages.getString("ExportXMLAction.TableName"), getEntity().getName()); //$NON-NLS-1$
		MetaDataXMLInterface.createElementText(sub,Messages.getString("ExportXMLAction.SchemaName"), getEntity().getSchema()); //$NON-NLS-1$
		MetaDataXMLInterface.createElementText(sub,Messages.getString("ExportXMLAction.BookmarkName"), getEntity().getBookmark().getName()); //$NON-NLS-1$
		if (this.metadata != null)
			MetaDataXMLInterface.metaDataToXML(this.metadata, doc, sub);
	}

	/**
	 * Generates a query with all the columns in the metadata of the ObjectNode.
	 * "SELECT *" would not be valid because you can have less columns in the ObjectNode than in the table or view.
	 * @return	String with the Query
	 */
	public String getQuery() {
		String result = new String(""); //$NON-NLS-1$
		result = "SELECT " + metadata.getColumnsString() + " FROM " + getEntity().getQualifiedName(); //$NON-NLS-1$ //$NON-NLS-2$
		return result;
	}

    /**
     * @see com.quantum.model.EntityHolder#getEntity()
     */
    public Entity getEntity() {
        return this.entity;
    }

}