/**
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 1999-2004 Bull S.A.
 * Contact: jonas-team@ow2.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
 *
 * --------------------------------------------------------------------------
 * $Id: VcCMRField.java 15428 2008-10-07 11:20:29Z sauthieg $
 * --------------------------------------------------------------------------
 */
package org.ow2.jonas.generators.genic;

import org.ow2.jonas.deployment.ejb.EjbRelationshipRoleDesc;
import org.ow2.jonas.deployment.ejb.EntityCmp2Desc;
import org.ow2.jonas.lib.util.BeanNaming;



/**
 * This class is used in the velocity context.
 * It represents a CMR field.
 *
 * @author S.Chassande-Barrioz : Initial developer
 * @author Helene Joanin
 */
public class VcCMRField {

    /**
     * Name of the cmr field
     */
    private String name;
    /**
     * Name of cmr field with the first letter capitalized
     */
    private String uFLName;
    /**
     * Type's name of the cmr field
     */
    private String typeName;
    /**
     * First relationship-role of the cmr field
     */
    private EjbRelationshipRoleDesc rsr;
    /**
     * Second relationship-role of the cmr field
     */
    private EjbRelationshipRoleDesc rsr2;
    /**
     * Relation's type of the cmr field
     */
    private byte relationType = -1;
    /**
     * Name of the JORM genclass.
     * This field has a non null value if the cmr field is a multivalued relation
     */
    private String genClassName = null;
    /**
     * Description of the cmr filed.
     */
    private EntityCmp2Desc element = null;

    /**
     * It builds a cmr field descriptor usable in velocity context.
     * @param rsr The EjbRelationshipRoleDesc where this CMR field is defined
     * @throws GenICException if the Deployment Decriptor is not conform
     */
    public VcCMRField(EjbRelationshipRoleDesc rsr) throws GenICException {
        this.rsr = rsr;
        name = rsr.getCmrFieldName();
        uFLName = upperFL(name);
        element = rsr.getTargetBean();
        typeName = rsr.getCmrFieldType().getName();
        if (rsr.isTargetMultiple()) {
            if (java.util.Collection.class.equals(rsr.getCmrFieldType())) {
                // TODO : Even if Collection has been defined as CMRField Type, we use a Set
                genClassName = "org.ow2.jonas.lib.ejb21.jorm.Set";
            } else if (java.util.Set.class.equals(rsr.getCmrFieldType())) {
                genClassName = "org.ow2.jonas.lib.ejb21.jorm.Set";
            } else {
                throw new GenICException("Unauthorized multivalued relation type:" + rsr.getCmrFieldType());
            }
        }
        rsr2 = rsr.getOppositeRelationshipRole();
        relationType = rsr.getRelationType();
    }

    /**
     * @return the name of the cmr field.
     */
    public String getName() {
        return name;
    }

    /**
     * @return the type name of the cmr field.
     * It is the referenced class if the relation is multiple,
     * otherwise the type of the multivalued relation (java.util.Collection or java.util.Set).
     */
    public String getTypeName() {
        return typeName;
    }

    /**
     * This is used to generate method names relative to the CMR Field
     * @return the name of cmr field with the first letter capitalized.
     */
    public String getUFLName() {
        return uFLName;
    }

    public String jormGetter() {
        return "paGet" + getUFLName();
    }

    public String jormSetter() {
        return "paSet" + getUFLName();
    }

    /**
     * @return the JOnAS meta object where the CMR field is defined
     */
    public EjbRelationshipRoleDesc getRsr() {
        return rsr;
    }

    /**
     * @return the name of opposite cmr field with the first letter capitalized.
     */
    public String getOppositeUFLCMRName() {
        return upperFL(rsr2.getCmrFieldName());
    }

    /**
     * CoherenceHelper class is used to manage coherence in relations.
     * @return The JOnAS CoherenceHelper class name
     */
    public String getHelperClassName() {
        return "JOnAS" + rsr.getSourceBeanName() + "CoherenceHelper";
    }

    /**
     * CoherenceHelper class is used to manage coherence in relations.
     * @return The Fully Qualified JOnAS CoherenceHelper class name
     */
    public String getHelperFQClassName() {
        String pn = BeanNaming.getPackageName(rsr2.getTargetBean().getFullDerivedBeanName());
        if (pn != null && pn.length() > 0) {
            return pn + "." + getHelperClassName();
        } else {
            return getHelperClassName();
        }
    }

    /**
     * CoherenceHelper class is used to manage coherence in relations.
     * @return The JOnAS CoherenceHelper class name for opposite bean
     */
    public String getOppositeHelperClassName() {
        return "JOnAS" + rsr2.getSourceBeanName() + "CoherenceHelper";
    }

    /**
     * CoherenceHelper class is used to manage coherence in relations.
     * @return The JOnAS CoherenceHelper fully qualified class name for opposite bean
     */
    public String getOppositeHelperFQClassName() {
        String pn = BeanNaming.getPackageName(rsr.getTargetBean().getFullDerivedBeanName());
        if (pn != null && pn.length() > 0) {
            return pn + "." + getOppositeHelperClassName();
        } else {
            return getOppositeHelperClassName();
        }
    }

    /**
     * @return the class name of the gen class which must be used if the cmr is multiple
     * and return null otherwise.
     * The class which the is returned implements the interface which the name is returned by the 'getTypeName' method.
     */
    public String getGenClassName() {
        return genClassName;
    }

    /**
     * @return the description of the field
     */
    public EntityCmp2Desc getElement() {
        return element;
    }

    /**
     * It capitalizes the first letter of a word.
     * @param word is the input string to capitalize the first letter
     * @return a String with first letter capitalized
     */
    public String upperFL(String word) {
        return Character.toUpperCase(word.charAt(0)) + word.substring(1);
    }

    /**
     * @return true if the relationship role is one-one unidirectional, false if not.
     */
    public boolean isOOu() {
        return relationType == EjbRelationshipRoleDesc.OOU;
    }

    /**
     * @return true if the relationship role is one-one bidirectional, false if not.
     */
    public boolean isOOb() {
        return relationType == EjbRelationshipRoleDesc.OOB;
    }

    /**
     * @return true if the relationship role is one-many unidirectional, false if not.
     */
    public boolean isOMu() {
        return relationType == EjbRelationshipRoleDesc.OMU;
    }

    /**
     * @return true if the relationship role is many-one unidirectional, false if not.
     */
    public boolean isMOu() {
        return relationType == EjbRelationshipRoleDesc.MOU;
    }

    /**
     * @return true if the relationship role is many-one bidirectional, false if not.
     */
    public boolean isMOb() {
        return relationType == EjbRelationshipRoleDesc.MOB;
    }

    /**
     * @return true if the relationship role is one-many bidirectional, false if not.
     */
    public boolean isOMb() {
        return relationType == EjbRelationshipRoleDesc.OMB;
    }

    /**
     * @return true if the relationship role is many-many unidirectional, false if not.
     */
    public boolean isMMu() {
        return relationType == EjbRelationshipRoleDesc.MMU;
    }

    /**
     * @return true if the relationship role is many-many bidirectional, false if not.
     */
    public boolean isMMb() {
        return relationType == EjbRelationshipRoleDesc.MMB;
    }

    /**
     * @return a string representation of the VcCMRField object for debug use
     */
    public String toString() {
        StringBuffer ret = new StringBuffer();
        ret.append("\n    Name                 = " + getName());
        ret.append("\n    TypeName             = " + getTypeName());
        ret.append("\n    UFLName              = " + getUFLName());
        ret.append("\n    OppositeUFLCMRName   = " + getOppositeUFLCMRName());
        ret.append("\n    HelperClassName      = " + getHelperClassName());
        ret.append("\n    HelperFQClassName    = " + getHelperFQClassName());
        ret.append("\n    OppositeHelperClassName   = " + getOppositeHelperClassName());
        ret.append("\n    OppositeHelperFQClassName = " + getOppositeHelperFQClassName());
        ret.append("\n    GenClassName         = " + getGenClassName());
        ret.append("\n    isOOu                = " + isOOu());
        ret.append("\n    isOOb                = " + isOOb());
        ret.append("\n    isOMu                = " + isOMu());
        ret.append("\n    isOMb                = " + isOMb());
        ret.append("\n    isMOb                = " + isMOb());
        ret.append("\n    isMNu                = " + isMMu());
        ret.append("\n    isMNb                = " + isMMb());
        return (ret.toString());
    }
}
