package w3c.wai.parser.html4.struct.table;

import java.util.Vector;
import java.util.Enumeration;
import java.util.StringTokenizer;
import java.io.*;

public class Table {
  static final int ORIENTATION_ROW=1;
  static final int ORIENTATION_COLUMN=2;
  static final int ORIENTATION_MARKUP=3;
  static final int REPEAT_ALL_HEADER_COLUMN_ROW=4;
  static final int REPEAT_DEEPEST_HEADER_COLUMN_ROW=2;
  static final int REPAEAT_ALL_HEADER_OR=3;
  static final int REPAEAT_DEEPEST_HEADER_OR=1;
  
  private Caption caption=null;
  private String summary=null;
  private int border=0;
  private Vector row=null;
  private BufferedWriter fw=null;

  
  protected static String headerSeparator;
  protected static String valueSeparator;
  protected static String cellSeparator;
  protected static String lineSeparator;
  private int repeat;
  private int orientation;
  private int recurs;
  private int interact;
  private int tableNumber;
  private String baseUrl=null;
  
    public Table(BufferedWriter fw,
		 int tableNumber,
		 int orientation,
		 int repeat,
		 int recurs,
		 int interact,
		 String headerSeparator,
		 String valueSeparator,
		 String cellSeparator,
		 String lineSeparator,
		 String baseUrl) {
      this.fw=fw;
      this.orientation=orientation;
      this.repeat=repeat;
      this.tableNumber=tableNumber;
      this.interact=interact;
      this.recurs=recurs;
      this.baseUrl=baseUrl;
      this.headerSeparator=headerSeparator;
      this.valueSeparator=valueSeparator;
      this.cellSeparator=cellSeparator;
      this.lineSeparator=lineSeparator;
      caption=new Caption();
      row=new Vector();
    }

  public void setCaption(boolean top) {
    caption.setCaption(top);
  }
  
  public void setCaption(String value) {
    caption.setCaption(value);
  }
  
  public void setSummary(String summary) {
    this.summary=summary;
  }
  
  public void setBorder(int border) {
    this.border=border;
  }
  
  public void addRow(Row row) {
    this.row.addElement(row);
  }
  
  private void printRow() throws IOException {
    for (int cpt=0;cpt<row.size();cpt++) {
      Row r=(Row)row.elementAt(cpt);
      int nbrPrintable=0;
      for (int cpt2=0;cpt2<r.numberOfCell();cpt2++) {
	Cell c=r.elementAt(cpt2);
	if (c.isPrintable() && c.isNotEmpty()) {
	  /*System.out.println(c.toString());*/
	    Vector vaux=findHeader(cpt-1,c.getColspan(),c.getRowspan(),
				   c.getHeader(),cpt2,false);
	    if (repeat==REPAEAT_ALL_HEADER_OR)
		vaux.setElementAt(new Vector(),1);
	    c.print(vaux,nbrPrintable,fw);
	    nbrPrintable++;
	}
      }
      fw.write(lineSeparator+"\n");
      fw.flush();
      /*System.out.println();*/
      
    }
  }
  
  private Vector findHeader(int lineNumber,
			    int colspan,
			    int rowspan,
			    String header,
			    int ind,boolean deepest) {
    Vector res=new Vector();
    if (header==null) {
      if (orientation==ORIENTATION_ROW) {
	res.addElement(findHeaderRow(lineNumber,ind,colspan,
				     rowspan,header));
	res.addElement(findHeaderColumn(lineNumber,ind,
					colspan,header,deepest));
      }
      else {
	res.addElement(findHeaderColumn(lineNumber,ind,colspan,
					header,deepest));
	res.addElement(findHeaderRow(lineNumber,ind,colspan,
				     rowspan,header));
      }
    }
    else {
      Vector vh=new Vector();
      StringTokenizer st=new StringTokenizer(header);
      while (st.hasMoreTokens()) {
	Cell c=findIdWithHeader((String)st.nextToken());
	if (c!=null)
	  vh.addElement(c);
      }
      res.addElement(vh);
      res.addElement(new Vector());
    }
    return res;
  }
  
  private Cell findIdWithHeader(String header) {
    for (int cpt=0;cpt<row.size();cpt++) {
      Cell c=elementAt(cpt).findIdWithHeader(header);
      if (c!=null)
	return c;
    }
    return null;
  }
  
  private boolean contains(Vector list,Vector value) {
    for (int ind=0;ind<list.size();ind++)
      if (((Cell)list.elementAt(ind)).getValue().equals(value))
	return true;
    return false;
  }
  
  private Vector findHeaderRow(int lineNumber,int ind,
			       int colspan,
			       int rowspan,
			       String header) {
    Vector line=new Vector();
    boolean flag=false;
    
    Row r=elementAt(lineNumber+1);
    
    int cpt=ind-1;
    while (cpt>=0) {
      if (r.elementAt(cpt).isAnHeader() && 
	  r.elementAt(cpt).isNotEmptyHeader()) {
	if (!contains(line,r.elementAt(cpt).getValue()))
	  line.insertElementAt(r.elementAt(cpt),0);	  
	
	/*int auxLine=lineNumber+2;
	for (int aux=rowspan;aux>1;aux--) {
	  if (auxLine==row.size())
	    break;
	  if (elementAt(auxLine).elementAt(cpt).isAnHeader()) {
	    if (!contains(line,elementAt(auxLine).elementAt(cpt).getValue()))
	      line.insertElementAt(elementAt(auxLine).elementAt(cpt),0);
	  }
	  auxLine++;
	}*/
	
	flag=true;			    
      }
      else 
	if (flag)
	  break;
      
      cpt--;
    }
    return line;
  }

  private Vector findHeaderColumn(int lineNumber,int ind,
				  int colspan,
				  String header,boolean deepest) {
    
    Vector column=new Vector();
    boolean flag=false; 
    
    while (lineNumber>=0) {
      if (elementAt(lineNumber).elementAt(ind).isAnHeader() &&
	   elementAt(lineNumber).elementAt(ind).isNotEmptyHeader()) {
	if (!contains(column,elementAt(lineNumber).elementAt(ind).getValue()))
	  column.insertElementAt(elementAt(lineNumber).elementAt(ind),
				 0);
	
	if (!deepest) {
	  int auxCol=ind+1;
	  for (int aux=colspan;aux>1;aux--) {
	    
	    if (auxCol==elementAt(lineNumber).numberOfCell())
	      break;
	    
	    if (elementAt(lineNumber).elementAt(auxCol).isAnHeader() &&
		 elementAt(lineNumber).elementAt(auxCol).isNotEmptyHeader())
	      if (!contains(column,elementAt(lineNumber).elementAt(auxCol).getValue()))
		column.insertElementAt(elementAt(lineNumber).elementAt(auxCol),
				       0);
	    
	    auxCol++;
	  }
	}
	flag=true;
      }
      else 
	if (flag)
	  break;
      lineNumber--;
    }
    
    while (lineNumber>=0) {
      if (elementAt(lineNumber).elementAt(ind).isTHeader() &&
	   elementAt(lineNumber).elementAt(ind).isNotEmptyHeader()) {
	if (!contains(column,elementAt(lineNumber).elementAt(ind).getValue()))
	  column.insertElementAt(elementAt(lineNumber).elementAt(ind),0);
	
	int auxCol=ind+1;
	for (int aux=colspan;aux>1;aux--) {
	  
	  if (auxCol==elementAt(lineNumber).numberOfCell())
	    break;
	  
	  if (elementAt(lineNumber).elementAt(auxCol).isTHeader() &&
	       elementAt(lineNumber).elementAt(auxCol).isNotEmptyHeader())
	    if (!contains(column,elementAt(lineNumber).elementAt(auxCol).getValue()))
	      column.insertElementAt(elementAt(lineNumber).elementAt(auxCol),
				     0);
	  
	  auxCol++;
	}
	
      }
      lineNumber--;
    }
    return column;
  }
  
  public void print() throws IOException {
    fw.write("<PRE>\n");
    fw.flush();
    
    /*
     * Prepare the table 
     */
    prepareTable();
    completeCellTable();
    //System.out.println(toString());
    

    /*
     * print the info for the summary
     */
    
    if (!caption.isNull()) 
      caption.print(fw);
    
    if (summary!=null && summary.length()>2 && summary.charAt(0)=='"' && summary.charAt(summary.length()-1)=='"')
      fw.write("Summary: "+summary.substring(1,summary.length()-1)+"\n");
    else
      if (summary!=null && !summary.equals(""))
	fw.write("Summary: "+summary+"\n");
    fw.flush();
    
    if (layoutTable()) 
      printLayout();
    else {
      if (orientation!=ORIENTATION_MARKUP)
	printRepeat();
      else 
	printMarkup();
    }
    
    fw.write("</PRE>\n");
    fw.flush();
  }
  
  private boolean layoutTable() {
    for (int cpt=0;cpt<row.size();cpt++) 
      if (!((Row)row.elementAt(cpt)).layoutTable())
	return false;
    return true;
  }
  
  private void printLayout() throws IOException  {
    for (int cpt=0;cpt<row.size();cpt++) 
      elementAt(cpt).printLayout(fw);
  }
    
  private void printMarkup() throws IOException  {
    for (int cpt=0;cpt<row.size();cpt++) 
    elementAt(cpt).printMarkup(fw);
  }
  
  private void printRepeat() throws IOException {


    
    switch (repeat) {
    case REPEAT_ALL_HEADER_COLUMN_ROW :
    case REPAEAT_ALL_HEADER_OR :
      if (interact==1) {
	fw.write("Orientation Option: <A HREF=\"http://localhost:8080/servlet/simple?url="+baseUrl+"&tableno="+tableNumber+"&cellSeparator="+cellSeparator+"&headerSeparator="+headerSeparator+"&valueSeparator="+valueSeparator+"&orient=row&repeat="+repeat+"&interact="+interact+"\">row</A>");
	fw.flush();
	fw.write(" <A HREF=\"http://localhost:8080/servlet/simple?url="+baseUrl+"&tableno="+tableNumber+"&cellSeparator="+cellSeparator+"&headerSeparator="+headerSeparator+"&valueSeparator="+valueSeparator+"&orient=col&repeat="+repeat+"&interact="+interact+"\">column</A>");
	fw.flush();
	fw.write(" <A HREF=\"http://localhost:8080/servlet/simple?url="+baseUrl+"&tableno="+tableNumber+"&cellSeparator="+cellSeparator+"&headerSeparator="+headerSeparator+"&valueSeparator="+valueSeparator+"&orient=mark&repeat="+repeat+"&interact="+interact+"\">markup</A>\n");
	fw.flush();
	
	
	fw.write("Repeat Option: <A HREF=\"http://localhost:8080/servlet/simple?url="+baseUrl+"&tableno="+tableNumber+"&cellSeparator="+cellSeparator+"&headerSeparator="+headerSeparator+"&valueSeparator="+valueSeparator+"&orient="+(orientation==1?"row":(orientation==2?"col":"mark"))+"&repeat=1&interact="+interact+"\">Deepest Header for each row or col</A>");
	fw.flush();
	fw.write(" <A HREF=\"http://localhost:8080/servlet/simple?url="+baseUrl+"&tableno="+tableNumber+"&cellSeparator="+cellSeparator+"&headerSeparator="+headerSeparator+"&valueSeparator="+valueSeparator+"&orient="+(orientation==1?"row":(orientation==2?"col":"mark"))+"&repeat=2&interact="+interact+"\">Deepest Header for each cell</A>");
	fw.flush();
	fw.write(" <A HREF=\"http://localhost:8080/servlet/simple?url="+baseUrl+"&tableno="+tableNumber+"&cellSeparator="+cellSeparator+"&headerSeparator="+headerSeparator+"&valueSeparator="+valueSeparator+"&orient="+(orientation==1?"row":(orientation==2?"col":"mark"))+"&repeat=3&interact="+interact+"\">All headers for each row or column</A>");
	fw.flush();
	fw.write(" <A HREF=\"http://localhost:8080/servlet/simple?url="+baseUrl+"&tableno="+tableNumber+"&cellSeparator="+cellSeparator+"&headerSeparator="+headerSeparator+"&valueSeparator="+valueSeparator+"&orient="+(orientation==1?"row":(orientation==2?"col":"mark"))+"&repeat=4&interact="+interact+"\">All headers for each cell</A>\n");
	fw.flush();
	
	
	fw.write("Interaction Option: <A HREF=\"http://localhost:8080/servlet/simple?url="+baseUrl+"&tableno="+tableNumber+"&cellSeparator="+cellSeparator+"&headerSeparator="+headerSeparator+"&valueSeparator="+valueSeparator+"&orient="+(orientation==1?"row":(orientation==2?"col":"mark"))+"&repeat="+repeat+"&interact=0\">None</A>");
	fw.flush();
	fw.write(" <A HREF=\"http://localhost:8080/servlet/simple?url="+baseUrl+"&tableno="+tableNumber+"&cellSeparator="+cellSeparator+"&headerSeparator="+headerSeparator+"&valueSeparator="+valueSeparator+"&orient="+(orientation==1?"row":(orientation==2?"col":"mark"))+"&repeat="+repeat+"&interact=1\">Table</A>\n");
	fw.flush();
	
      }
      printRow();
      break;
    case REPEAT_DEEPEST_HEADER_COLUMN_ROW :
    case REPAEAT_DEEPEST_HEADER_OR :
      printDeepestColumnRow();
      break;
    }
  }
  
  private void printDeepestColumnRow() throws IOException {
    Vector rh=new Vector();
    Vector ch=new Vector();
  
    for (int cpt=0;cpt<row.size();cpt++) {
      Row r=(Row)row.elementAt(cpt);
      
      for (int cpt2=0;cpt2<r.numberOfCell();cpt2++) {
	Cell c=r.elementAt(cpt2);
	if (c.isPrintableDeepest() && c.isNotEmpty()) {
	  Vector aux=findHeader(cpt-1,c.getColspan(),
				c.getRowspan(),c.getHeader(),cpt2,true);
	  if (orientation==ORIENTATION_ROW) {
	    rh.addElement((Vector)aux.elementAt(0));
	    ch.addElement((Vector)aux.elementAt(1));
	  }
	  else {
	    rh.addElement((Vector)aux.elementAt(1));
	    ch.addElement((Vector)aux.elementAt(0));
	  }
	}
      }
    }
    
    //System.out.println("RH="+rh.size()+"\tCH="+ch.size());

    switch (repeat) {
    case REPAEAT_DEEPEST_HEADER_OR :
      if (orientation==ORIENTATION_ROW) {
	fw.write("Repeat: deepest header for each row ");
	if (interact==1) {
	  fw.write("(option <A HREF=\"http://localhost:8080/servlet/simple?url="+baseUrl+"&tableno="+tableNumber+"&cellSeparator="+cellSeparator+"&headerSeparator="+headerSeparator+"&valueSeparator="+valueSeparator+"&orient="+(orientation==1?"row":(orientation==2?"col":"mark"))+"&repeat=1&interact="+interact+"\">Deepest Header for each row or col</A>");
	  fw.flush();
	  fw.write(" <A HREF=\"http://localhost:8080/servlet/simple?url="+baseUrl+"&tableno="+tableNumber+"&cellSeparator="+cellSeparator+"&headerSeparator="+headerSeparator+"&valueSeparator="+valueSeparator+"&orient="+(orientation==1?"row":(orientation==2?"col":"mark"))+"&repeat=2&interact="+interact+"\">Deepest Header for each cell</A>");
	  fw.flush();
	  fw.write(" <A HREF=\"http://localhost:8080/servlet/simple?url="+baseUrl+"&tableno="+tableNumber+"&cellSeparator="+cellSeparator+"&headerSeparator="+headerSeparator+"&valueSeparator="+valueSeparator+"&orient="+(orientation==1?"row":(orientation==2?"col":"mark"))+"&repeat=3&interact="+interact+"\">All headers for each row or column</A>");
	  fw.flush();
	  fw.write(" <A HREF=\"http://localhost:8080/servlet/simple?url="+baseUrl+"&tableno="+tableNumber+"&cellSeparator="+cellSeparator+"&headerSeparator="+headerSeparator+"&valueSeparator="+valueSeparator+"&orient="+(orientation==1?"row":(orientation==2?"col":"mark"))+"&repeat=4&interact="+interact+"\">All headers for each cell</A>)");
	  fw.flush();
	  
	}
	fw.write("\n");
	fw.flush();
	fw.write("Row header names: ");
	fw.flush();
	printDeepestHeader(rh);
	fw.write("\n");
	fw.flush();
      }
      else {
	fw.write("Repeat: deepest header for each col ");	
	if (interact==1) {
	  fw.write("(option <A HREF=\"http://localhost:8080/servlet/simple?url="+baseUrl+"&tableno="+tableNumber+"&cellSeparator="+cellSeparator+"&headerSeparator="+headerSeparator+"&valueSeparator="+valueSeparator+"&orient="+(orientation==1?"row":(orientation==2?"col":"mark"))+"&repeat=1&interact="+interact+"\">Deepest Header for each row or col</A>");
	  fw.flush();
	  fw.write(" <A HREF=\"http://localhost:8080/servlet/simple?url="+baseUrl+"&tableno="+tableNumber+"&cellSeparator="+cellSeparator+"&headerSeparator="+headerSeparator+"&valueSeparator="+valueSeparator+"&orient="+(orientation==1?"row":(orientation==2?"col":"mark"))+"&repeat=2&interact="+interact+"\">Deepest Header for each cell</A>");
	  fw.flush();
	  fw.write(" <A HREF=\"http://localhost:8080/servlet/simple?url="+baseUrl+"&tableno="+tableNumber+"&cellSeparator="+cellSeparator+"&headerSeparator="+headerSeparator+"&valueSeparator="+valueSeparator+"&orient="+(orientation==1?"row":(orientation==2?"col":"mark"))+"&repeat=3&interact="+interact+"\">All headers for each row or column</A>");
	  fw.flush();
	  fw.write(" <A HREF=\"http://localhost:8080/servlet/simple?url="+baseUrl+"&tableno="+tableNumber+"&cellSeparator="+cellSeparator+"&headerSeparator="+headerSeparator+"&valueSeparator="+valueSeparator+"&orient="+(orientation==1?"row":(orientation==2?"col":"mark"))+"&repeat=4&interact="+interact+"\">All headers for each cell</A>)");
	  fw.flush();
	  
	}
	fw.write("\n");
	fw.flush();
	
	fw.write("Column header names: ");
	fw.flush();
	printDeepestHeader(ch);
	fw.write("\n");
	fw.flush();
      }
      break;
    case REPEAT_DEEPEST_HEADER_COLUMN_ROW :
	fw.write("Repeat: deepest header for each cell ");
	if (interact==1) {
	  fw.write("(option <A HREF=\"http://localhost:8080/servlet/simple?url="+baseUrl+"&tableno="+tableNumber+"&cellSeparator="+cellSeparator+"&headerSeparator="+headerSeparator+"&valueSeparator="+valueSeparator+"&orient="+(orientation==1?"row":(orientation==2?"col":"mark"))+"&repeat=1&interact="+interact+"\">Deepest Header for each row or col</A>");
	  fw.flush();
	  fw.write(" <A HREF=\"http://localhost:8080/servlet/simple?url="+baseUrl+"&tableno="+tableNumber+"&cellSeparator="+cellSeparator+"&headerSeparator="+headerSeparator+"&valueSeparator="+valueSeparator+"&orient="+(orientation==1?"row":(orientation==2?"col":"mark"))+"&repeat=2&interact="+interact+"\">Deepest Header for each cell</A>");
	  fw.flush();
	  fw.write(" <A HREF=\"http://localhost:8080/servlet/simple?url="+baseUrl+"&tableno="+tableNumber+"&cellSeparator="+cellSeparator+"&headerSeparator="+headerSeparator+"&valueSeparator="+valueSeparator+"&orient="+(orientation==1?"row":(orientation==2?"col":"mark"))+"&repeat=3&interact="+interact+"\">All headers for each row or column</A>");
	  fw.flush();
	  fw.write(" <A HREF=\"http://localhost:8080/servlet/simple?url="+baseUrl+"&tableno="+tableNumber+"&cellSeparator="+cellSeparator+"&headerSeparator="+headerSeparator+"&valueSeparator="+valueSeparator+"&orient="+(orientation==1?"row":(orientation==2?"col":"mark"))+"&repeat=4&interact="+interact+"\">All headers for each cell</A>)");
	  fw.flush();
	  
	}
	fw.write("\n");
	fw.flush();	
	fw.write("Column header names: ");
	fw.flush();
	printDeepestHeader(ch);
	fw.write("Row header names: ");
	fw.flush();
	printDeepestHeader(rh);
	fw.write("\n");
	fw.flush();
	break;
    }


    if (interact==1) {
      fw.write("Orientation Option: <A HREF=\"http://localhost:8080/servlet/simple?url="+baseUrl+"&tableno="+tableNumber+"&cellSeparator="+cellSeparator+"&headerSeparator="+headerSeparator+"&valueSeparator="+valueSeparator+"&orient=row&repeat="+repeat+"&interact="+interact+"\">row</A>");
      fw.flush();
      fw.write(" <A HREF=\"http://localhost:8080/servlet/simple?url="+baseUrl+"&tableno="+tableNumber+"&cellSeparator="+cellSeparator+"&headerSeparator="+headerSeparator+"&valueSeparator="+valueSeparator+"&orient=col&repeat="+repeat+"&interact="+interact+"\">column</A>");
      fw.flush();
      fw.write(" <A HREF=\"http://localhost:8080/servlet/simple?url="+baseUrl+"&tableno="+tableNumber+"&cellSeparator="+cellSeparator+"&headerSeparator="+headerSeparator+"&valueSeparator="+valueSeparator+"&orient=mark&repeat="+repeat+"&interact="+interact+"\">markup</A>\n");
      fw.flush();
      
      fw.write("Interaction Option: <A HREF=\"http://localhost:8080/servlet/simple?url="+baseUrl+"&tableno="+tableNumber+"&cellSeparator="+cellSeparator+"&headerSeparator="+headerSeparator+"&valueSeparator="+valueSeparator+"&orient="+(orientation==1?"row":(orientation==2?"col":"mark"))+"&repeat="+repeat+"&interact=0\">None</A>");
      fw.flush();
      fw.write(" <A HREF=\"http://localhost:8080/servlet/simple?url="+baseUrl+"&tableno="+tableNumber+"&cellSeparator="+cellSeparator+"&headerSeparator="+headerSeparator+"&valueSeparator="+valueSeparator+"&orient="+(orientation==1?"row":(orientation==2?"col":"mark"))+"&repeat="+repeat+"&interact=1\">Table</A>\n");
      fw.flush();
      
    }
    
    int rowMin=deepestBaseHeader(rh);
    int colMin=deepestBaseHeader(ch);
    
    //System.out.println("ROWMIN: "+rowMin+"\tCOLMIN: "+colMin);
    //System.out.println(rh+"\n");
    
    for (int cpt=0;cpt<row.size();cpt++) {
      Row r=(Row)row.elementAt(cpt);
      int nbrPrintable=0;
      for (int cpt2=0;cpt2<r.numberOfCell();cpt2++) {
	Cell c=r.elementAt(cpt2);
	if (c.isPrintableDeepest() && c.isNotEmpty()) {
	  Vector aux=findHeader(cpt-1,c.getColspan(),
				c.getRowspan(),c.getHeader(),cpt2,true);
	  if (orientation==ORIENTATION_ROW) {
	    for (int i=0;i<rowMin;i++) 
	      ((Vector)aux.elementAt(0)).removeElementAt(0);
	    for (int i=0;i<colMin;i++) 
	      ((Vector)aux.elementAt(1)).removeElementAt(0);
	  }
	  else {
	    for (int i=0;i<rowMin;i++) 
	      ((Vector)aux.elementAt(1)).removeElementAt(0);
	    for (int i=0;i<colMin;i++) 
	      ((Vector)aux.elementAt(0)).removeElementAt(0);
	  }
	  if (repeat==REPAEAT_DEEPEST_HEADER_OR) 
	      aux.setElementAt(new Vector(),1);
	  c.print(aux,nbrPrintable,fw);	  
	  nbrPrintable++;
	}
      }
      fw.write(lineSeparator+"\n");
      fw.flush();
    }
  }
  
  private int deepestBaseHeader(Vector v) {
    int min=32000;
    for (int ind=0;ind<v.size();ind++)
      min=(((Vector)v.elementAt(ind)).size()<min?
	   ((Vector)v.elementAt(ind)).size():min);
    
    min--;
    return min;
  }
  
  private void printDeepestHeader(Vector v) throws IOException {
    //System.out.println("SIZE="+v.size());
    int min=deepestBaseHeader(v);
    //System.out.println("MIN: "+min);
    for (int ind=0;ind<min;ind++) {
      Vector aux=new Vector();
      for (int cpt=0;cpt<v.size();cpt++) {
	if (!contains(aux,
		      ((Cell)((Vector)v.elementAt(cpt)).elementAt(ind)).getValue())) {
	  aux.addElement((Cell)((Vector)v.elementAt(cpt)).elementAt(ind));
	  if (aux.size()==1 && ind!=0) {
	    fw.write(",");
	    fw.flush();
	  }
	  if (aux.size()>1) {
	    fw.write("/");
	    fw.flush();	
	  }    
	  ((Cell)((Vector)v.elementAt(cpt)).elementAt(ind)).print(fw);
	  
	}
      }
    }
    fw.write("\n");
    fw.flush();
    
    
  }
  
  /*
   * add a new cell on the row 
   * all the row of the table must have the same number of col
   */
  private void completeCellTable() {
    int max=0;
    for (int cpt=0;cpt<row.size();cpt++) {
      int aux=elementAt(cpt).numberOfCell();
      max=(max<aux?aux:max);
    }
    for (int cpt=0;cpt<row.size();cpt++) 
      elementAt(cpt).completeCellTable(max);
  }
  
  /*
   * clone cell for rowspan > 1
   * add new cell on the table
   */
  private void prepareTable() {
    for (int cpt=0;cpt<row.size();cpt++) {
      Row r=elementAt(cpt);
      for (int cpt2=0;cpt2<r.numberOfCell();cpt2++) {
	Cell c=r.elementAt(cpt2);
	if (c.getRowspan()>1 && !c.isSpecialRow()) {
	  try {
	    insertCellInRow(cpt2,c.getRowspan()-1,cpt+1,(Cell)c.myClone());
	  }
	  catch (ArrayIndexOutOfBoundsException e) {
	    // rowspan too big...
	  }
	}
      }
    }
  }
  
  private void insertCellInRow(int ind,
			       int numberOfRow,
			       int line,
			       Cell c) 
       throws ArrayIndexOutOfBoundsException {

	 for (int cpt=line;cpt<(line+numberOfRow);cpt++) 
	   elementAt(cpt).insertCellInRow(ind,c);
  }
  
    public String getSummary() {
	return summary;
    }

    public Caption getCaption() {
	return caption;
    }

  public Row elementAt(int line) {
    return (Row)row.elementAt(line);
  }

  public String toString() {
    return "Caption:"+caption.toString()+"\nSummary= "+summary+"\nBorder: "+border+"\nRow: "+row.toString();
  }

}






