/*
 * Copyright (c) 1999, 2000, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code 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
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package com.sun.org.omg.CORBA;


/**
* com/sun/org/omg/CORBA/_IDLTypeStub.java
* Generated by the IDL-to-Java compiler (portable), version "3.0"
* from ir.idl
* Thursday, May 6, 1999 1:51:45 AM PDT
*/

// This file has been manually _CHANGED_

// _CHANGED_
//public class _IDLTypeStub extends org.omg.CORBA.portable.ObjectImpl implements com.sun.org.omg.CORBA.IDLType
public class _IDLTypeStub extends org.omg.CORBA.portable.ObjectImpl implements org.omg.CORBA.IDLType
{
    // Constructors
    // NOTE:  If the default constructor is used, the
    //        object is useless until _set_delegate (...)
    //        is called.
    public _IDLTypeStub ()
    {
        super ();
    }

    public _IDLTypeStub (org.omg.CORBA.portable.Delegate delegate)
    {
        super ();
        _set_delegate (delegate);
    }

    public org.omg.CORBA.TypeCode type ()
    {
        org.omg.CORBA.portable.InputStream _in = null;
        try {
            org.omg.CORBA.portable.OutputStream _out = _request ("_get_type", true);
            _in = _invoke (_out);
            org.omg.CORBA.TypeCode __result = _in.read_TypeCode ();
            return __result;
        } catch (org.omg.CORBA.portable.ApplicationException _ex) {
            _in = _ex.getInputStream ();
            String _id = _ex.getId ();
            throw new org.omg.CORBA.MARSHAL (_id);
        } catch (org.omg.CORBA.portable.RemarshalException _rm) {
            return type ();
        } finally {
            _releaseReply (_in);
        }
    } // type


    // read interface
    // _CHANGED_
    //public com.sun.org.omg.CORBA.DefinitionKind def_kind ()
    public org.omg.CORBA.DefinitionKind def_kind ()
    {
        org.omg.CORBA.portable.InputStream _in = null;
        try {
            org.omg.CORBA.portable.OutputStream _out = _request ("_get_def_kind", true);
            _in = _invoke (_out);
            // _CHANGED_
            //com.sun.org.omg.CORBA.DefinitionKind __result = com.sun.org.omg.CORBA.DefinitionKindHelper.read (_in);
            org.omg.CORBA.DefinitionKind __result = com.sun.org.omg.CORBA.DefinitionKindHelper.read (_in);
            return __result;
        } catch (org.omg.CORBA.portable.ApplicationException _ex) {
            _in = _ex.getInputStream ();
            String _id = _ex.getId ();
            throw new org.omg.CORBA.MARSHAL (_id);
        } catch (org.omg.CORBA.portable.RemarshalException _rm) {
            return def_kind ();
        } finally {
            _releaseReply (_in);
        }
    } // def_kind


    // write interface
    public void destroy ()
    {
        org.omg.CORBA.portable.InputStream _in = null;
        try {
            org.omg.CORBA.portable.OutputStream _out = _request ("destroy", true);
            _in = _invoke (_out);
        } catch (org.omg.CORBA.portable.ApplicationException _ex) {
            _in = _ex.getInputStream ();
            String _id = _ex.getId ();
            throw new org.omg.CORBA.MARSHAL (_id);
        } catch (org.omg.CORBA.portable.RemarshalException _rm) {
            destroy ();
        } finally {
            _releaseReply (_in);
        }
    } // destroy

    // Type-specific CORBA::Object operations
    private static String[] __ids = {
        "IDL:omg.org/CORBA/IDLType:1.0",
        "IDL:omg.org/CORBA/IRObject:1.0"};

    public String[] _ids ()
    {
        return (String[])__ids.clone ();
    }

    private void readObject (java.io.ObjectInputStream s)
    {
        try
            {
                String str = s.readUTF ();
                org.omg.CORBA.Object obj = org.omg.CORBA.ORB.init ().string_to_object (str);
                org.omg.CORBA.portable.Delegate delegate = ((org.omg.CORBA.portable.ObjectImpl) obj)._get_delegate ();
                _set_delegate (delegate);
            } catch (java.io.IOException e) {}
    }

    private void writeObject (java.io.ObjectOutputStream s)
    {
        try
            {
                String str = org.omg.CORBA.ORB.init ().object_to_string (this);
                s.writeUTF (str);
            } catch (java.io.IOException e) {}
    }
} // class _IDLTypeStub
