/*
* The Apache Software License, Version 1.1
*
*
* Copyright (c) 2003 The Apache Software Foundation.  All rights 
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer. 
*
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in
*    the documentation and/or other materials provided with the
*    distribution.
*
* 3. The end-user documentation included with the redistribution,
*    if any, must include the following acknowledgment:  
*       "This product includes software developed by the
*        Apache Software Foundation (http://www.apache.org/)."
*    Alternately, this acknowledgment may appear in the software itself,
*    if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" must 
*    not be used to endorse or promote products derived from this
*    software without prior written permission. For written 
*    permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache 
*    XMLBeans", nor may "Apache" appear in their name, without prior 
*    written permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation and was
* originally based on software copyright (c) 2000-2003 BEA Systems 
* Inc., <http://www.bea.com/>. For more information on the Apache Software
* Foundation, please see <http://www.apache.org/>.
*/

package org.apache.xmlbeans.impl.jaxb.compiler;

import org.apache.xmlbeans.SchemaType;
import java.lang.reflect.Constructor;

public abstract class ComponentInfo
{
    private String _fullJavaIntfName;
    private String _fullJavaImplName;
    private String _shortJavaIntfName;
    private String _shortJavaImplName;
    private String _baseIntfName;
    private String _baseImplName;
    private int _superCtrArgCount;

    // runtime support
    private volatile boolean     _implNotAvailable;
    private volatile Class       _javaImplClass;
    private volatile Constructor _javaImplConstructor;

    public String getFullJavaIntfName() {
        return _fullJavaIntfName;
    }

    public String getShortJavaIntfName() {
        return _shortJavaIntfName;
    }

    public void setFullJavaIntfName(String intfName) {
        _fullJavaIntfName = intfName;

        int index = Math.max(_fullJavaIntfName.lastIndexOf('$'),
                             _fullJavaIntfName.lastIndexOf('.')) + 1;

        _shortJavaIntfName = _fullJavaIntfName.substring(index);
    }

    public String getFullJavaImplName() {
        return _fullJavaImplName;
    }

    public String getShortJavaImplName() {
        return _shortJavaImplName;
    }

    public void setFullJavaImplName(String implName) {
        _fullJavaImplName = implName;

        int index = Math.max(_fullJavaImplName.lastIndexOf('$'),
                             _fullJavaImplName.lastIndexOf('.')) + 1;

        _shortJavaImplName = _fullJavaImplName.substring(index);
    }

    public void setBaseIntfName(String baseType)
    {
        _baseIntfName = baseType;
    }

    public String getBaseIntfName()
    {
        return _baseIntfName;
    }

    public void setBaseImplName(String basetype)
    {
        _baseImplName = basetype;
    }

    public String getBaseImplName()
    {
        return _baseImplName;
    }

    public int getSuperCtrArgCount() {
        return _superCtrArgCount;
    }

    public void setSuperCtrArgCount(int count) {
        _superCtrArgCount = count;
    }

    public Class getJavaImplClass(ClassLoader cl) {
        if (_implNotAvailable)
            return null;

        if (_javaImplClass == null)
        {
            try {
                if (getFullJavaImplName() != null)
                    _javaImplClass = Class.forName(getFullJavaImplName(), false, cl);
                else
                    _implNotAvailable = true;
            }
            catch (ClassNotFoundException e) {
                _implNotAvailable = true;
            }
        }

        return _javaImplClass;
    }

    public Constructor getJavaImplConstructor(ClassLoader cl)
    {
        if (_javaImplConstructor == null && !_implNotAvailable)
        {
            final Class impl = getJavaImplClass(cl);
            if (impl == null) return null;
            try
            {
                _javaImplConstructor = impl.getConstructor(null);
            }
            catch (NoSuchMethodException e)
            {
                e.printStackTrace();
            }
        }

        return _javaImplConstructor;

    }
}
