package org.apache.commons.beanutils;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.io.StreamCorruptedException;
import java.util.List;
import java.util.Map;

public class DynaProperty implements Serializable {
  private static final int BOOLEAN_TYPE = 1;
  
  private static final int BYTE_TYPE = 2;
  
  private static final int CHAR_TYPE = 3;
  
  private static final int DOUBLE_TYPE = 4;
  
  private static final int FLOAT_TYPE = 5;
  
  private static final int INT_TYPE = 6;
  
  private static final int LONG_TYPE = 7;
  
  private static final int SHORT_TYPE = 8;
  
  protected String name;
  
  protected transient Class type;
  
  public DynaProperty(String name) {
    this(name, Object.class);
  }
  
  public DynaProperty(String name, Class type) {
    this.name = null;
    this.type = null;
    this.name = name;
    this.type = type;
  }
  
  public String getName() {
    return this.name;
  }
  
  public Class getType() {
    return this.type;
  }
  
  public boolean isIndexed() {
    if (this.type == null)
      return false; 
    if (this.type.isArray())
      return true; 
    if (List.class.isAssignableFrom(this.type))
      return true; 
    return false;
  }
  
  public boolean isMapped() {
    if (this.type == null)
      return false; 
    return Map.class.isAssignableFrom(this.type);
  }
  
  public String toString() {
    StringBuffer sb = new StringBuffer("DynaProperty[name=");
    sb.append(this.name);
    sb.append(",type=");
    sb.append(this.type);
    sb.append("]");
    return sb.toString();
  }
  
  private void writeObject(ObjectOutputStream out) throws IOException {
    int primitiveType = 0;
    if (boolean.class.equals(this.type)) {
      primitiveType = 1;
    } else if (byte.class.equals(this.type)) {
      primitiveType = 2;
    } else if (char.class.equals(this.type)) {
      primitiveType = 3;
    } else if (double.class.equals(this.type)) {
      primitiveType = 4;
    } else if (float.class.equals(this.type)) {
      primitiveType = 5;
    } else if (int.class.equals(this.type)) {
      primitiveType = 6;
    } else if (long.class.equals(this.type)) {
      primitiveType = 7;
    } else if (short.class.equals(this.type)) {
      primitiveType = 8;
    } 
    if (primitiveType == 0) {
      out.writeBoolean(false);
      out.writeObject(this.type);
    } else {
      out.writeBoolean(true);
      out.writeInt(primitiveType);
    } 
    out.defaultWriteObject();
  }
  
  private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
    if (in.readBoolean()) {
      switch (in.readInt()) {
        case 1:
          this.type = boolean.class;
          break;
        case 2:
          this.type = byte.class;
          break;
        case 3:
          this.type = char.class;
          break;
        case 4:
          this.type = double.class;
          break;
        case 5:
          this.type = float.class;
          break;
        case 6:
          this.type = int.class;
          break;
        case 7:
          this.type = long.class;
          break;
        case 8:
          this.type = short.class;
          break;
        default:
          throw new StreamCorruptedException("Invalid primitive type. Check version of beanutils used to serialize is compatible.");
      } 
    } else {
      this.type = (Class)in.readObject();
    } 
    in.defaultReadObject();
  }
}
