class PrintTree 
{
	public static void print(TreeNode tree)
	{
		if (tree instanceof BinaryNode) // a binary operator
		{
			BinaryNode bin = (BinaryNode) tree.getNode();
			
			// print the binary operator name
			System.out.print(bin.getOp()+ "( ");

			// print the left subtree of the node
			try
			{
				print(bin.getLeftTree());
			}
			catch (NullPointerException e)
			{
				// has no left node; pointing to null
			}
			System.out.print(",");
			// print the right subtree of the node
			try
			{
				print(bin.getRightTree());
			}
			catch (NullPointerException e)
			{
				// has no right node; pointing to null
			}
			System.out.print(" )");
		}

		else if(tree instanceof TableNode)
		{
			TableNode tab = (TableNode) tree.getNode(); // a table node
			
			// print table name
			System.out.print("GetTable(" + tab.getArg() +")");

			//print the subtree that follows node
			try
			{
				print(tab.getNext());
			}
			catch (NullPointerException e)
			{
				// has no next; pointing to null
			}
		}

		else if(tree instanceof ProjNode)
		{
			ProjNode proj = (ProjNode) tree.getNode(); // a project node

			System.out.print("ProjectFields( ");

			// print the field names to project
			System.out.print("<");
			for (int i=0; i<proj.getArgLen(); i++)
			{
				System.out.print(proj.getField(i) + " ");
			}
			System.out.print(">, ");

			//print the subtree that follows node
			try
			{
				print(proj.getNext());
			}
			catch (NullPointerException e)
			{
				// has no next; pointing to null
			}
			System.out.print(" )");
		}

		else if(tree instanceof CondNode)
		{
			CondNode cond = (CondNode) tree.getNode(); // a condition node

			System.out.print("Condition("+cond.getArg()+","+cond.getOp()+","+cond.getVal()+")");

			//print the subtree that follows node
			try
			{
				print(cond.getNext());
			}
			catch (NullPointerException e)
			{
				// has no next; pointing to null
			}
		}

		else if(tree instanceof CoalesceNode)
		{
			CoalesceNode coal = (CoalesceNode) tree.getNode(); // a coalesce node
			
			// print what is to be coalesced
			System.out.print("Coalesce( ");

			//print the subtree that follows node
			try
			{
				print(coal.getNext());
			}
			catch (NullPointerException e)
			{
				// has no next; pointing to null
			}
			System.out.print(" )");
		}

		else if(tree instanceof RenameNode)
		{
			RenameNode re = (RenameNode) tree.getNode(); // a rename node

			System.out.print("Rename( [ ");
			printArr(re.getOldCol());
			System.out.print("] to [ ");
			printArr(re.getNewCol());
			System.out.print("],  ");

			//print the subtree that follows node
			try
			{
				print(re.getNext());
			}
			catch (NullPointerException e)
			{
				// has no next; pointing to null
			}
			System.out.print(" )");
		}

		/////////////////////////////////////////////////////
		else if(tree instanceof OnWithNode)
		{
			OnWithNode ow = (OnWithNode) tree.getNode(); // a OnWith node

			System.out.print("On( < ");
			printArr( ow.getTabACol() );
			System.out.print("> with < ");
			printArr( ow.getTabBCol() );
			System.out.print(">,  ");

			//print the subtree that follows node
			try
			{
				print(ow.getNext());
			}
			catch (NullPointerException e)
			{
				// has no next; pointing to null
			}
			System.out.print(" )");
		}
		/////////////////////////////////////////////////////

		else if(tree instanceof ModalNode)
		{
			ModalNode mod = (ModalNode) tree.getNode(); // a modal node

			// print the modal operator name
			System.out.print(mod.getOp()+ "( ");

			//print the subtree that follows node
			try
			{
				print(mod.getNext());
			}
			catch (NullPointerException e)
			{
				// has no next; pointing to null
			}
			System.out.print(" )");
		}

		else if(tree instanceof AtTimeNode)
		{
			AtTimeNode at = (AtTimeNode) tree.getNode(); // a AtTime node
			
			// print table name
			System.out.print("At_Time( " + at.getArg() + ", ");

			//print the subtree that follows node
			try
			{
				print(at.getNext());
			}
			catch (NullPointerException e)
			{
				// has no next; pointing to null
			}
			System.out.print(" )");
		}

		else
		{
			// do nothing
			System.out.println("Unkown Node:" +tree.getClass().getName()+" that cannot be printed");
		}

	} // end of method

	private static void printArr(String[] list)
	{
		/* print contents of the array */
		for (int i=0; i<list.length; i++)
		{
			System.out.print(list[i]+" ");
		}
	}
}
