/*
* 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) 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.binding.bts;

import java.util.Map;
import java.util.LinkedHashMap;
import java.util.Collection;

/**
 * Base class
 */ 
public abstract class BaseBindingLoader implements BindingLoader
{
    private final Map bindingTypes = new LinkedHashMap();    // name-pair -> BindingType
    private final Map xmlFromJava = new LinkedHashMap();     // javaName -> pair
    private final Map xmlFromJavaElement = new LinkedHashMap(); // javaName -> pair (xml element)
    private final Map javaFromXmlPojo = new LinkedHashMap(); // xmlName -> pair (pojo)
    private final Map javaFromXmlObj = new LinkedHashMap();  // xmlName -> pair (xmlobj)

    public BindingType getBindingType(BindingTypeName btName)
    {
        return (BindingType)bindingTypes.get(btName);
    }

    public BindingTypeName lookupPojoFor(XmlName xName)
    {
        return (BindingTypeName)javaFromXmlPojo.get(xName);
    }

    public BindingTypeName lookupXmlObjectFor(XmlName xName)
    {
        return (BindingTypeName)javaFromXmlObj.get(xName);
    }

    public BindingTypeName lookupTypeFor(JavaName jName)
    {
        return (BindingTypeName)xmlFromJava.get(jName);
    }

    public BindingTypeName lookupElementFor(JavaName jName)
    {
        return (BindingTypeName)xmlFromJavaElement.get(jName);
    }
    
    protected void addBindingType(BindingType bType)
    {
        bindingTypes.put(bType.getName(), bType);
    }
    
    protected void addPojoFor(XmlName xName, BindingTypeName btName)
    {
        assert(!btName.getJavaName().isXmlObject());
        javaFromXmlPojo.put(xName, btName);
    }

    protected void addXmlObjectFor(XmlName xName, BindingTypeName btName)
    {
        assert(btName.getJavaName().isXmlObject());
        javaFromXmlObj.put(xName, btName);
    }

    protected void addTypeFor(JavaName jName, BindingTypeName btName)
    {
        assert(btName.getXmlName().isSchemaType());
        xmlFromJava.put(jName, btName);
    }

    protected void addElementFor(JavaName jName, BindingTypeName btName)
    {
        assert(btName.getXmlName().getComponentType() == XmlName.ELEMENT);
        xmlFromJavaElement.put(jName, btName);
    }
    
    public Collection bindingTypes()
    {
        return bindingTypes.values();
    }
    
    public Collection typeMappedJavaTypes()
    {
        return xmlFromJava.keySet();
    }

    public Collection elementMappedJavaTypes()
    {
        return xmlFromJavaElement.keySet();
    }

    public Collection pojoMappedXmlTypes()
    {
        return javaFromXmlPojo.keySet();
    }

    public Collection xmlObjectMappedXmlTypes()
    {
        return javaFromXmlObj.keySet();
    }
}
