/*
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 1999 Bull S.A.
 * Contact: jonas-team@objectweb.org
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or any later version.
 * 
 * This library 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
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 * USA
 *
 * Initial developer(s): ____________________________________.
 * Contributor(s): Lutris Technologies Inc http://www.lutris.com
 *
 * --------------------------------------------------------------------------
 * $Id$
 * --------------------------------------------------------------------------
 * cney 13.3.00
*/


package org.objectweb.jonas_ejb.deployment.api;

import java.lang.String;
import java.util.Enumeration;
import java.util.Iterator;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

import org.objectweb.jonas_ejb.deployment.xml.AssemblyDescriptor;
import org.objectweb.jonas_ejb.deployment.xml.Entity;
import org.objectweb.jonas_ejb.deployment.xml.JonasEntity;
import org.objectweb.jonas_ejb.deployment.xml.JdbcMapping;
import org.objectweb.jonas_ejb.deployment.xml.CmpFieldJdbcMapping;
import org.objectweb.jonas_ejb.deployment.xml.FinderMethodJdbcMapping;
import org.objectweb.jonas_ejb.deployment.xml.JonasMethod;

/**
 * Base class for descriptor of an entity bean with jdbc based container managed persistence 
 * @author Christophe Ney
 */
public class EntityJdbcCmpDesc extends EntityCmpDesc {


    String jdbcTableName;
    String datasourceJndiName;
    
    /**
     * Package protected constructor used by API
     */
    EntityJdbcCmpDesc(ClassLoader classLoader, Entity ent, AssemblyDescriptor asd, JonasEntity jEnt)
                throws DeploymentDescException {
        super(classLoader,ent,asd,jEnt);
        
        // check for jdbcMapping
        JdbcMapping jm = jEnt.getJdbcMapping();
        if (jm==null)
            throw new DeploymentDescException("jdbc-mapping missing for bean "+ent.getEjbName());

        // populate field descriptor hashtable with jdbc information
        for (Iterator i= jm.getCmpFieldJdbcMappingList().iterator(); i.hasNext(); ) {
            CmpFieldJdbcMapping cmpFieldJdbcMapping = (CmpFieldJdbcMapping)i.next();
            String fn = cmpFieldJdbcMapping.getFieldName().getValue();
            FieldDesc f = (FieldDesc)fieldDesc.get(fn);
            if (f==null)
                throw new DeploymentDescException("field-name "+fn+" listed in cmp-field-jdbc-mapping is not of cmp-field of bean "+ent.getEjbName());
            fieldDesc.put(fn,new FieldJdbcDesc(cmpFieldJdbcMapping.getJdbcFieldName().getValue(),f.isPrimaryKey()));
        }
        // check that all cmp fields are jdbc
        Enumeration e = fieldDesc.keys();
        while (e.hasMoreElements()) {
            String fn = (String)e.nextElement();
            if (!(fieldDesc.get(fn) instanceof FieldJdbcDesc)) 
                throw new DeploymentDescException("field-name "+fn+" is missing in cmp-field-jdbc-mapping for bean "+ent.getEjbName());
        }

        // change all methodDesc to jdbcMethodDesc
        e = methodDesc.keys();
        while (e.hasMoreElements()) {
            Method key = (Method)e.nextElement();
            methodDesc.put(key,new MethodJdbcDesc((MethodDesc)methodDesc.get(key)));
        }
        
        // populate method descriptor hashtable with jdbc information
        for (Iterator i= jm.getFinderMethodJdbcMappingList().iterator(); i.hasNext(); ) {
            FinderMethodJdbcMapping fmj = ((FinderMethodJdbcMapping)i.next());
            JonasMethod m = fmj.getJonasMethod();
            // loop on methods in the hashtable
            e = methodDesc.keys();
            while (e.hasMoreElements()) {
                java.lang.reflect.Method meth = (java.lang.reflect.Method)e.nextElement();
                // create new descriptor if pattern matches with method                    
                int matchStatus = MethodDesc.matchPattern(meth,null,m.getMethodName().getValue(),m.getMethodParams());
                MethodJdbcDesc md = (MethodJdbcDesc)methodDesc.get(meth);
                // set if proper level of assignation
                md.overwriteJdbcWhereClause(fmj.getJdbcWhereClause().getValue(),matchStatus);
            }
        }

        // modify non jdbc method descriptors
        e = this.methodDesc.keys();
        while (e.hasMoreElements()) {
             java.lang.reflect.Method meth = (java.lang.reflect.Method)e.nextElement();
             MethodDesc md = (MethodDesc)methodDesc.get(meth);
             if (!(md instanceof MethodJdbcDesc)) {
                 this.methodDesc.put(meth,new MethodJdbcDesc(md));
             }
        }
        
        // jndi name of the datasource
        datasourceJndiName = jm.getJndiName().getValue();
            
        //table name
        jdbcTableName=jm.getJdbcTableName().getValue();
    }

    
    /**
     * Get the datasource jndi name
     * @return String representation of the jndi name
     */
    public String getDatasourceJndiName(){
        return datasourceJndiName;
    }

    /**
     * Assessor for existence of a jdbc descriptor for a given field
     * @param field public field of the bean class
     * @return true if jdbc descriptor is available for given field
     */
    public boolean hasFieldJdbcDesc(Field field) {
        return super.hasCmpFieldDesc(field);        
    }
    
    
    /**
     * Get jdbc specific descriptor for a given field.
     * Used by GenIC
     * @param field of the bean class
     * @return Descriptor for the given field
     */
    public FieldJdbcDesc getFieldJdbcDesc(Field field) {
        return (FieldJdbcDesc)super.getCmpFieldDesc(field);
    }
    

    /**
     * Get the associated DataBase table name in case of container persistence type.
     * Used by GenIC (This information is JOnAS specific).
     * @return Name of the database table where entity bean is stored
     */
    public String getJdbcTableName(){
        return jdbcTableName;
    }

    /**
     * String representation of the object for test purpose
     * @return String representation of this object
     */
    public String toString() {
        StringBuffer ret = new StringBuffer();
        ret.append(super.toString());
        ret.append("\ngetDatasourceJndiName()="+getDatasourceJndiName());
        ret.append("\ngetJdbcTableName()="+getJdbcTableName());
        return ret.toString();
    }

}

