/** This method return the fieldName of relation role on the other end. */
  public String getInverseFieldName(String ejbName, String fieldName) {
    EjbRelationshipRole oppRole = getOppositeRoleDescriptor(ejbName, fieldName);
    CmrField inverse = ((oppRole == null) ? null : oppRole.getCmrField());
    String inverseName = ((inverse == null) ? null : inverse.getCmrFieldName());

    // if we are generating relationships, check for a generated inverse
    if (generateFields() && (inverseName == null)) {
      inverseName = getNameMapper().getGeneratedFieldForEjbField(ejbName, fieldName)[1];
    }

    return inverseName;
  }
  // TODO: can this be implemented in a simpler way?  is there
  // any real value to using the map here as opposed to iterating
  // the relationships live?
  private EjbRelationshipRole getRoleDescriptor(
      String ejbName, String cmrFieldName, boolean opposite) {
    Map rels = (HashMap) relationshipRoleMap.get(ejbName);
    Iterator iterator = rels.keySet().iterator();

    while (iterator.hasNext()) {
      EjbRelation rel = (EjbRelation) iterator.next();
      EjbRelationshipRole role = (EjbRelationshipRole) rels.get(rel);
      EjbRelationshipRole role1 = rel.getEjbRelationshipRole();
      EjbRelationshipRole role2 = rel.getEjbRelationshipRole2();
      CmrField candidateCmr = role.getCmrField();

      if (ejbName.equals(role.getRelationshipRoleSource().getEjbName())
          && (candidateCmr != null)
          && cmrFieldName.equals(candidateCmr.getCmrFieldName())) {
        return ((opposite) ? ((role == role1) ? role2 : role1) : role);
      } else { // check for self ref relationship
        String ejb1 = role1.getRelationshipRoleSource().getEjbName();

        if (ejb1.equals(role2.getRelationshipRoleSource().getEjbName()) && ejbName.equals(ejb1)) {
          role = ((role == role1) ? role2 : role1);
          candidateCmr = role.getCmrField();

          if ((candidateCmr != null) && cmrFieldName.equals(candidateCmr.getCmrFieldName())) {
            return ((opposite) ? ((role == role1) ? role2 : role1) : role);
          }
        }
      }
    }
    throw new IllegalArgumentException();
  }
  // TODO: is caching okay?  is synchronization needed?
  private void addRole(EjbRelation relationship, EjbRelationshipRole testRole) {
    String ejbName = testRole.getRelationshipRoleSource().getEjbName();
    Map rels = (HashMap) relationshipRoleMap.get(ejbName);

    if (rels == null) {
      rels = new HashMap();
      relationshipRoleMap.put(ejbName, rels);
    }

    rels.put(relationship, testRole);
  }
  /** This API will only be called from MappingFile when multiplicity is Many on the other role. */
  public String getRelationshipFieldType(String ejbName, String fieldName) {
    if (isGeneratedRelationship(ejbName, fieldName)) return COLLECTION;
    else {
      // TODO: protect against NPE? test for one way rels
      EjbRelationshipRole thisRole = getRoleDescriptor(ejbName, fieldName, false);
      String returnType = thisRole.getCmrField().getCmrFieldType();

      // CmrField's info on type says it is only populated for
      // collection fields, so get the related field content for null
      if ((returnType == null) || !returnType.equals(COLLECTION)) {
        // TODO: DOL impl returns the local interface name, but not
        // sure why it isn't just the related bean (may not matter due
        // to comment about Many multiplicity above)
        returnType =
            getNameMapper()
                .getLocalInterfaceForEjbName(getRelationshipFieldContent(ejbName, fieldName));
      }

      return returnType;
    }
  }
  public boolean relatedObjectsAreDeleted(String beanName, String fieldName) {
    EjbRelationshipRole oppRole = getOppositeRoleDescriptor(beanName, fieldName);

    return oppRole.isCascadeDelete();
  }
  public String getRelationshipFieldContent(String ejbName, String fieldName) {
    EjbRelationshipRole oppRole = getOppositeRoleDescriptor(ejbName, fieldName);

    return oppRole.getRelationshipRoleSource().getEjbName();
  }
  /**
   * getMultiplicity of the other role on the relationship Please note that multiplicity is JDO
   * style
   */
  public String getMultiplicity(String ejbName, String fieldName) {
    EjbRelationshipRole oppRole = getOppositeRoleDescriptor(ejbName, fieldName);

    return oppRole.getMultiplicity();
  }