
// Copyright (C) 1998-1999
// Object Oriented Concepts, Inc.

// **********************************************************************
//
// Copyright (c) 1997
// Mark Spruiell (mark@intellisoft.com)
//
// See the COPYING file for more information
//
// **********************************************************************

package jacorb.trading.db.pse.offers;


import org.omg.CORBA.*;
import jtport.ORBLayer;


/**
 * TypeCodeValue represents a persistent CORBA TypeCode object
 */
public class TypeCodeValue
{
    // not the most space-efficient representation, but the alternative
    // is a bunch of subclasses
  private int m_kind;
  private String m_id;
  private String m_name;
  private int m_length;
  private TypeCodeValue m_content;
  private java.lang.Object m_arg;
  private transient TypeCode m_typeCode;


  private TypeCodeValue()
  {
  }


  public TypeCodeValue(TypeCode tc)
  {
    setValue(tc);
  }


  public TypeCode getValue()
  {
    TypeCode result = m_typeCode;

    if (result == null) {
      ORB orb = ORBLayer.instance().getORB();

      switch (m_kind) {
          // the primitive types
        case TCKind._tk_null:
        case TCKind._tk_void:
        case TCKind._tk_short:
        case TCKind._tk_ushort:
        case TCKind._tk_long:
        case TCKind._tk_ulong:
        case TCKind._tk_float:
        case TCKind._tk_double:
        case TCKind._tk_boolean:
        case TCKind._tk_char:
        case TCKind._tk_octet:
        case TCKind._tk_any:
        case TCKind._tk_TypeCode:
        case TCKind._tk_Principal:
          result = orb.get_primitive_tc(TCKind.from_int(m_kind));
          break;

        case TCKind._tk_string:
          result = orb.create_string_tc(m_length);
          break;

        case TCKind._tk_sequence:
          result = orb.create_sequence_tc(m_length, m_content.getValue());
          break;

        case TCKind._tk_array:
          result = orb.create_array_tc(m_length, m_content.getValue());
          break;

        case TCKind._tk_alias:
          result = orb.create_alias_tc(m_id, m_name, m_content.getValue());
          break;

        case TCKind._tk_objref:
          result = orb.create_interface_tc(m_id, m_name);
          break;

        case TCKind._tk_longlong:
        case TCKind._tk_ulonglong:
        case TCKind._tk_longdouble:
        case TCKind._tk_wstring:
        case TCKind._tk_wchar:
        case TCKind._tk_fixed:
        case TCKind._tk_except:
        case TCKind._tk_struct:
        case TCKind._tk_union:
          throw new RuntimeException("Unsupported type");

        default:
          throw new RuntimeException("Unexpected type");
      }

        // keep it for next time
      m_typeCode = result;
    }

    return result;
  }


  protected void setValue(TypeCode tc)
  {
    TCKind kind = tc.kind();

      // initialize members
    m_kind = kind.value();
    m_id = null;
    m_name = null;
    m_length = 0;
    m_content = null;
    m_arg = null;
    m_typeCode = tc;


    try {
      switch (kind.value()) {
          // the primitive types
        case TCKind._tk_null:
        case TCKind._tk_void:
        case TCKind._tk_short:
        case TCKind._tk_ushort:
        case TCKind._tk_long:
        case TCKind._tk_ulong:
        case TCKind._tk_float:
        case TCKind._tk_double:
        case TCKind._tk_boolean:
        case TCKind._tk_char:
        case TCKind._tk_octet:
        case TCKind._tk_any:
        case TCKind._tk_TypeCode:
        case TCKind._tk_Principal:
            // nothing to do
          break;

        case TCKind._tk_string:
          m_length = tc.length();
          break;

        case TCKind._tk_sequence:
          m_length = tc.length();
          m_content = new TypeCodeValue(tc.content_type());
          break;

        case TCKind._tk_array:
          m_length = tc.length();
          m_content = new TypeCodeValue(tc.content_type());
          break;

        case TCKind._tk_alias:
          m_id = tc.id();
          m_name = tc.name();
          m_content = new TypeCodeValue(tc.content_type());
          break;

        case TCKind._tk_objref:
          m_id = tc.id();
          m_name = tc.name();
          break;

        case TCKind._tk_longlong:
        case TCKind._tk_ulonglong:
        case TCKind._tk_longdouble:
        case TCKind._tk_wstring:
        case TCKind._tk_wchar:
        case TCKind._tk_fixed:
        case TCKind._tk_except:
        case TCKind._tk_struct:
        case TCKind._tk_union:
          throw new RuntimeException("Unsupported type");

        default:
          throw new RuntimeException("Unexpected type");
      }
    }
    catch (org.omg.CORBA.TypeCodePackage.BadKind e) {
      throw new RuntimeException(e.getMessage());
    }
  }


  /** ObjectStore PSE hook method to initialize transient fields */
  public void postInitializeContents()
  {
    m_typeCode = null;
  }


  /** ObjectStore PSE hook method to clear transient fields */
  public void preClearContents()
  {
    m_typeCode = null;
  }


  /*********************** comment out to enable main()

  public static void main(String[] args)
  {
    ORB orb = ORBLayer.instance().init(args);

      // test the primitives

    testType("null", orb.get_primitive_tc(TCKind.tk_null));
    testType("void", orb.get_primitive_tc(TCKind.tk_void));
    testType("short", orb.get_primitive_tc(TCKind.tk_short));
    testType("ushort", orb.get_primitive_tc(TCKind.tk_ushort));
    testType("long", orb.get_primitive_tc(TCKind.tk_long));
    testType("ulong", orb.get_primitive_tc(TCKind.tk_ulong));
    testType("float", orb.get_primitive_tc(TCKind.tk_float));
    testType("double", orb.get_primitive_tc(TCKind.tk_double));
    testType("boolean", orb.get_primitive_tc(TCKind.tk_boolean));
    testType("char", orb.get_primitive_tc(TCKind.tk_char));
    testType("octet", orb.get_primitive_tc(TCKind.tk_octet));
    //testType("longlong", orb.get_primitive_tc(TCKind.tk_longlong));
    //testType("ulonglong", orb.get_primitive_tc(TCKind.tk_ulonglong));
    //testType("longdouble", orb.get_primitive_tc(TCKind.tk_longdouble));
    //testType("wchar", orb.get_primitive_tc(TCKind.tk_wchar));
    //testType("fixed", orb.get_primitive_tc(TCKind.tk_fixed));
    testType("any", orb.get_primitive_tc(TCKind.tk_any));
    testType("TypeCode", orb.get_primitive_tc(TCKind.tk_TypeCode));
    testType("Principal", orb.get_primitive_tc(TCKind.tk_Principal));

    TypeCode tc;

      // test alias

    tc = orb.create_alias_tc("ID", "Name",
      orb.get_primitive_tc(TCKind.tk_double));
    testType("alias", tc);

      // test interface

    tc = orb.create_interface_tc("ID", "Name");
    testType("objref", tc);

      // test string

    tc = orb.create_string_tc(10);
    testType("string", tc);

      // test sequence

    tc = orb.create_sequence_tc(20, orb.get_primitive_tc(TCKind.tk_long));
    testType("sequence", tc);

      // test array

    tc = orb.create_array_tc(20, orb.get_primitive_tc(TCKind.tk_ulong));
    testType("array", tc);
  }


  protected static void testType(String name, TypeCode tc)
  {
      // test a TypeCodeValue by writing it out, reading it back in,
      // and comparing its TypeCode to the one we've been given

    System.out.println("Testing " + name + "...");

    try {
      TypeCodeValue val = new TypeCodeValue(tc);
      File f = new File("tctest.dat");

      FileOutputStream fileOut = new FileOutputStream(f);
      ObjectOutputStream objOut = new ObjectOutputStream(fileOut);
      objOut.writeObject(val);
      fileOut.close();

      FileInputStream fileIn = new FileInputStream(f);
      ObjectInputStream objIn = new ObjectInputStream(fileIn);
      val = (TypeCodeValue)objIn.readObject();
      fileIn.close();

      f.delete();

      TypeCode newTC = val.getValue();
      if (! newTC.equal(tc)) {
        System.out.println("Read/write mismatch");
        System.exit(1);
      }
    }
    catch (IOException e) {
      System.err.println("I/O error: " + e.getMessage());
      System.exit(1);
    }
    catch (ClassNotFoundException e) {
      System.err.println("Class not found: " + e.getMessage());
      System.exit(1);
    }
  }

  /*********************** comment out to enable main() */
}




