package org.apache.struts.config;

import java.io.Serializable;
import java.lang.reflect.Array;
import org.apache.commons.beanutils.ConvertUtils;

public class FormPropertyConfig implements Serializable {
  public FormPropertyConfig() {}
  
  public FormPropertyConfig(String name, String type, String initial) {
    this(name, type, initial, 0);
  }
  
  public FormPropertyConfig(String name, String type, String initial, int size) {
    setName(name);
    setType(type);
    setInitial(initial);
    setSize(size);
  }
  
  protected boolean configured = false;
  
  protected String initial = null;
  
  public String getInitial() {
    return this.initial;
  }
  
  public void setInitial(String initial) {
    if (this.configured)
      throw new IllegalStateException("Configuration is frozen"); 
    this.initial = initial;
  }
  
  protected String name = null;
  
  public String getName() {
    return this.name;
  }
  
  public void setName(String name) {
    if (this.configured)
      throw new IllegalStateException("Configuration is frozen"); 
    this.name = name;
  }
  
  protected int size = 0;
  
  public int getSize() {
    return this.size;
  }
  
  public void setSize(int size) {
    if (this.configured)
      throw new IllegalStateException("Configuration is frozen"); 
    if (size < 0)
      throw new IllegalArgumentException("size < 0"); 
    this.size = size;
  }
  
  protected String type = null;
  
  public String getType() {
    return this.type;
  }
  
  public void setType(String type) {
    if (this.configured)
      throw new IllegalStateException("Configuration is frozen"); 
    this.type = type;
  }
  
  public Class getTypeClass() {
    String baseType = getType();
    boolean indexed = false;
    if (baseType.endsWith("[]")) {
      baseType = baseType.substring(0, baseType.length() - 2);
      indexed = true;
    } 
    Class baseClass = null;
    if ("boolean".equals(baseType)) {
      baseClass = boolean.class;
    } else if ("byte".equals(baseType)) {
      Class clazz = byte.class;
    } else if ("char".equals(baseType)) {
      Class clazz = char.class;
    } else if ("double".equals(baseType)) {
      Class clazz = double.class;
    } else if ("float".equals(baseType)) {
      Class clazz = float.class;
    } else if ("int".equals(baseType)) {
      Class clazz = int.class;
    } else if ("long".equals(baseType)) {
      Class clazz = long.class;
    } else if ("short".equals(baseType)) {
      Class clazz = short.class;
    } else {
      ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
      if (classLoader == null)
        classLoader = getClass().getClassLoader(); 
      try {
        baseClass = (Class)classLoader.loadClass(baseType);
      } catch (Throwable t) {
        baseClass = null;
      } 
    } 
    if (indexed)
      return Array.newInstance(baseClass, 0).getClass(); 
    return baseClass;
  }
  
  public Object initial() {
    Object initialValue = null;
    try {
      Class clazz = getTypeClass();
      if (clazz.isArray()) {
        if (this.initial != null) {
          initialValue = ConvertUtils.convert(this.initial, clazz);
        } else {
          initialValue = Array.newInstance(clazz.getComponentType(), this.size);
          for (int i = 0; i < this.size; i++) {
            try {
              Array.set(initialValue, i, clazz.getComponentType().newInstance());
            } catch (Throwable t) {}
          } 
        } 
      } else if (this.initial != null) {
        initialValue = ConvertUtils.convert(this.initial, clazz);
      } else {
        initialValue = clazz.newInstance();
      } 
    } catch (Throwable t) {
      initialValue = null;
    } 
    return initialValue;
  }
  
  public void freeze() {
    this.configured = true;
  }
  
  public String toString() {
    StringBuffer sb = new StringBuffer("FormPropertyConfig[");
    sb.append("name=");
    sb.append(this.name);
    sb.append(",type=");
    sb.append(this.type);
    sb.append(",initial=");
    sb.append(this.initial);
    sb.append("]");
    return sb.toString();
  }
}
