001// Copyright (c) 2001 Hursh Jain (http://www.mollypages.org) 
002// The Molly framework is freely distributable under the terms of an
003// MIT-style license. For details, see the molly pages web site at:
004// http://www.mollypages.org/. Use, modify, have fun !
005
006package fc.util;
007
008import java.util.*;
009
010/** 
011Implements a simple table data structure. Like a 2D array
012but uses nested hash tables to get (row, col) based on a 
013(name, name) pair. The table grows automatically as needed.
014<p>
015Differs from a 2D Object[][] in that names can be used 
016instead of indices.
017<p>
018All indexes are internally strings. When adding or retrieving
019values, either numerical and string indices can be specified
020for either row or col when retrieving a (row,col) value. <i>A
021numerical index is converted into a string value</i> so if one puts
022a value at (3, 5), that can later be retrieved as ("3", "5")
023if desired.
024<p>
025Thread safety: This data structure is fully thread safe.
026
027@author hursh jain
028**/
029public final class Table
030{
031private static final boolean dbg = false;
032
033int row_default_size;
034int col_default_size;
035
036/*    
037         A     B    C
038rows  1:   x     y    z
039      2:   a     e    n
040      3:   c     d    m
041
042rows(1) => hashtable (A->x, B->y, C->z)
043rows(2) => hashtable (A->a, B->e, C->n)
044..
045*/
046Map table;
047
048/** 
049Constructs a new table.
050**/
051public Table() {
052  this(32, 32);
053  }
054
055/** 
056Constructs a new table of the specified initial size.
057**/
058public Table(int rows, int cols) {
059  this.row_default_size = rows;
060  this.col_default_size = cols;
061  this.table = new Hashtable(rows);
062  }
063
064/** 
065Returns the object at row, col or <tt>null</tt> if the
066specified row or col do not exist.
067*/
068public Object get(String row, String col) 
069  {
070  Object val = null;
071  
072  Map cols = (Map) table.get(row);
073  
074  if (cols != null) 
075    val = cols.get(col);
076    
077  return val;
078  }
079
080
081/**
082Returns the object at row, col or <tt>null</tt> if the
083specified row or col do not exist.
084*/
085public Object get(int row, String col) 
086  {
087  return get(String.valueOf(row), col);
088  }
089
090/**
091Returns the object at row, col or <tt>null</tt> if the
092specified row or col do not exist.
093*/
094public Object get(String row, int col) 
095  {
096  return get(row, String.valueOf(col));
097  }
098
099/**
100Returns the object at row, col or <tt>null</tt> if the
101specified row or col do not exist.
102*/
103public Object get(int row, int col) 
104  {
105  return get(String.valueOf(row), String.valueOf(col));
106  }
107
108/**
109Returns the object at row, col or <tt>null</tt> if the
110specified row or col do not exist.
111
112@return the old object at that (row, col) if it exists
113*/
114public Object put(String row, String col, Object obj) 
115  {
116  Object val = null;
117  
118  Map c = (Map) table.get(row);
119  if (c == null) {
120    c = new Hashtable(col_default_size);
121    table.put(row, c);
122    }
123  
124  val = c.put(col, obj);  
125  return val;
126  }
127
128
129public Object put(int row, String col, Object obj) 
130  {
131  return put(String.valueOf(row), col, obj);
132  }
133
134public Object put(String row, int col, Object obj) 
135  {
136  return put(row, String.valueOf(col), obj);
137  }
138
139public Object put(int row, int col, Object obj) 
140  {
141  return put(String.valueOf(row), String.valueOf(col), obj);
142  }
143
144
145public String toString() {
146  return "Table: [" + table.size() + " rows]";
147  }
148  
149public static void main (String args[])
150  {
151  Table t = new Table();
152  System.out.println("t.get(1,1)="+t.get(1,1));
153  System.out.println("t.put(1,1,\"hello\")="+t.put(1,1, "hello"));
154  System.out.println("t.get(\"1\",\"1\")="+t.get("1","1"));
155  System.out.println("t.get(1,\"1\")="+t.get(1,"1"));
156  System.out.println("t.get(1,0)="+t.get(1,0));
157  System.out.println("t.put(1,1,\"hello\")="+t.put(1,1, "world"));
158  System.out.println("t.get(\"1\",1)="+t.get("1",1));
159
160  for (int n = 0; n < 10; n++) {
161    t.put(n, n, n);
162    }
163
164  for (int n = 0; n < 10; n++) {
165    System.out.println("table["+n+","+n+"]:"+t.get(n, n));
166    }
167  
168  Watch w = new Watch().start();
169  t.get(5,5);
170  w.stop();
171  System.out.println("time for one t.get() op: " + w.time() + " ms");
172  }
173}   //~class Table