gt:     while (propsEn.hasMoreElements()) {
context: /*
   * $Source$
   * $Revision$
   *
   * Copyright (C) 2007 Tim Pizey
   *
   * Part of Melati (http://melati.org), a framework for the rapid
   * development of clean, maintainable web applications.
   *
   * Melati is free software; Permission is granted to copy, distribute
   * and/or modify this software under the terms either:
   *
   * a) the GNU General Public License as published by the Free Software
   *    Foundation; either version 2 of the License, or (at your option)
   *    any later version,
   *
   *    or
   *
   * b) any version of the Melati Software License, as published
   *    at http://melati.org
   *
   * You should have received a copy of the GNU General Public License and
   * the Melati Software License along with this program;
   * if not, write to the Free Software Foundation, Inc.,
   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA to obtain the
   * GNU General Public License and visit http://melati.org to obtain the
   * Melati Software License.
   *
   * Feel free to contact the Developers of Melati (http://melati.org),
   * if you would like to work out a different arrangement than the options
   * outlined here.  It is our intention to allow Melati to be used by as
   * wide an audience as possible.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * Contact details for copyright holder:
   *
   *     Tim Pizey <timp At paneris.org>
   *     http://paneris.org/~timp
   */
  package org.melati.poem;
  
  import java.lang.reflect.Method;
  import java.lang.reflect.Modifier;
  import java.util.Collection;
  import java.util.Enumeration;
  import java.util.Hashtable;
  import java.util.Map;
  
  import org.melati.poem.util.ClassUtils;
  import org.melati.poem.util.StringUtils;
  
  
  /**
   * Given an Object or class create a set of Tables to represent the graph 
   * it is the starting node of, and populate it for an Object.
   * 
   * The rules are a sub-set of the Hibernate rules: 
   * Only public types can be persisted.
   * Only members with a public setter and getter will be persisted.
   * If the object has a field called Id then the Persistent troid column will be called 
   * <tt>poemId</tt>.  
   *  
   * @author timp
   * @since 12 Jun 2007
   * 
   */
  public final class TableFactory {
  
    /**
     * Disable instantiation.
     */
    private TableFactory() {
    }
  
    /**
     * @param db
     *          the database to create table in and lookup existing tables
     * @param pojo
     *          class to introspect
     * @return A new or existing table
     */
    public static Table fromInstance(Database db, Object pojo) {
      return fromClass(db, pojo.getClass());
    }
  
    /**
     * @param db
     *          the database to create table in and lookup existing tables
     * @param clazz
     *          class to introspect
     * @return A new or existing table
     */
    public static Table fromClass(Database db, Class<?> clazz) {
      if (clazz.isPrimitive())
        throw new IllegalArgumentException(
        "Cannot create a Table for a primitive type: " + clazz.getName());
      if (clazz.isInterface())
        throw new IllegalArgumentException(
        "Cannot create a Table for an interface: " + clazz.getName());
      if(!Modifier.isPublic(clazz.getModifiers())) 
        throw new IllegalArgumentException(
          "Cannot create a Table for a non public type: "+ clazz.getName());
      if (clazz.isArray() && !(clazz == byte[].class))
        throw new IllegalArgumentException("Cannot create a Table for an array: " + clazz.getName());
      String name = clazz.getName();
      String simpleName = name.substring(name.lastIndexOf('.') + 1);
      try {
        return db.getTable(simpleName);
      } catch (NoSuchTablePoemException e) {
        System.err.println("Creating a table for : " + name);
      }
      // We will have to create one
      TableInfo tableInfo = (TableInfo)db.getTableInfoTable().newPersistent();
      tableInfo.setName(simpleName);
      tableInfo.setDisplayname(simpleName);
      tableInfo.setDescription(simpleName + " introspected table");
      tableInfo.setDisplayorder(13);
      tableInfo.setSeqcached(Boolean.FALSE);
      tableInfo.setCategory(TableCategoryTable.NORMAL);
      tableInfo.setCachelimit(555);
      tableInfo.makePersistent();
  
      Table table = new JdbcTable(db, simpleName, DefinitionSource.runtime);
      String troidName = "id";
      if (ClassUtils.getNoArgMethod(clazz, "getId") != null &&
          !(Persistent.class.isAssignableFrom(clazz)))
        troidName = "poemId";
      table.defineColumn(new ExtraColumn<Integer>(table, troidName, TroidPoemType.it,
              DefinitionSource.runtime, table.getNextExtrasIndex()));
      table.setTableInfo(tableInfo);
      table.unifyWithColumnInfo();
      table.unifyWithDB(null,troidName);
  
      PoemThread.commit();
      db.defineTable(table);
      Hashtable<String,Prop> props = new Hashtable<String,Prop>();
  
      Method[] methods = clazz.getMethods();
  
      for (int i = 0; i < methods.length; i++) {
        if (Modifier.isPublic(methods[i].getModifiers())) {
          if (methods[i].getName().startsWith("set") 
              && ! methods[i].getName().equals("set")
              && Character.isUpperCase(methods[i].getName().toCharArray()[3])
              && methods[i].getParameterTypes().length == 1
              && (methods[i].getParameterTypes()[0] == byte[].class || 
                  ! methods[i].getParameterTypes()[0].isArray())
              && !methods[i].getParameterTypes()[0].isInterface()
              && ! Collection.class.isAssignableFrom(methods[i].getParameterTypes()[0])
              && ! Map.class.isAssignableFrom(methods[i].getParameterTypes()[0])
              ) {
            String propName = methods[i].getName().substring(3);
            propName = StringUtils.uncapitalised(propName);
            Prop p = (Prop)props.get(propName);
            Class<?> setClass = methods[i].getParameterTypes()[0];
            if (p == null) {
              p = new Prop(propName);
              p.setSet(setClass);
            } else { 
              if (p.getGot() != null) { 
                if(p.getGot() == setClass)
                  p.setSet(setClass);
              } else { 
                p.setSet(setClass);                
              }
            }
            props.put(propName, p);
          }
          
          if (methods[i].getParameterTypes().length == 0
              && ! methods[i].getReturnType().isInterface()
              && (methods[i].getReturnType() == byte[].class || 
                  !methods[i].getReturnType().isArray())
              && !Collection.class.isAssignableFrom(methods[i].getReturnType())
              && !Map.class.isAssignableFrom(methods[i].getReturnType())
          ) {
            String propName = null;
            if ((methods[i].getName().startsWith("get")) && 
                 Character.isUpperCase(methods[i].getName().toCharArray()[3]))
              propName = methods[i].getName().substring(3);
            else if (methods[i].getName().startsWith("is") && 
                     Character.isUpperCase(methods[i].getName().toCharArray()[2])) 
              propName = methods[i].getName().substring(2);
            if (propName != null) { 
              propName = StringUtils.uncapitalised(propName);
              Prop p = (Prop)props.get(propName);
              Class<?> gotClass = methods[i].getReturnType();
              if (p == null) {
                p = new Prop(propName);
                p.setGot(gotClass);
              } else { 
                p.setGot(gotClass);
              }
              props.put(propName, p);
            }
          }
        }
      }
      Enumeration<Prop> propsEn = props.elements();
  