// Due to @AnnotationOverride overriding rules, I don't want the constructor to be public
 // TODO get rid of it and use setters
 private Ejb3JoinColumn(
     String sqlType,
     String name,
     boolean nullable,
     boolean unique,
     boolean insertable,
     boolean updatable,
     String referencedColumn,
     String secondaryTable,
     Map<String, Join> joins,
     PropertyHolder propertyHolder,
     String propertyName,
     String mappedBy,
     boolean isImplicit,
     MetadataBuildingContext buildingContext) {
   super();
   setImplicit(isImplicit);
   setSqlType(sqlType);
   setLogicalColumnName(name);
   setNullable(nullable);
   setUnique(unique);
   setInsertable(insertable);
   setUpdatable(updatable);
   setExplicitTableName(secondaryTable);
   setPropertyHolder(propertyHolder);
   setJoins(joins);
   setBuildingContext(buildingContext);
   setPropertyName(BinderHelper.getRelativePath(propertyHolder, propertyName));
   bind();
   this.referencedColumn = referencedColumn;
   this.mappedBy = mappedBy;
 }
 /** build join column for SecondaryTables */
 private static Ejb3JoinColumn buildJoinColumn(
     JoinColumn ann,
     String mappedBy,
     Map<String, Join> joins,
     PropertyHolder propertyHolder,
     String propertyName,
     String suffixForDefaultColumnName,
     MetadataBuildingContext buildingContext) {
   if (ann != null) {
     if (BinderHelper.isEmptyAnnotationValue(mappedBy)) {
       throw new AnnotationException(
           "Illegal attempt to define a @JoinColumn with a mappedBy association: "
               + BinderHelper.getRelativePath(propertyHolder, propertyName));
     }
     Ejb3JoinColumn joinColumn = new Ejb3JoinColumn();
     joinColumn.setBuildingContext(buildingContext);
     joinColumn.setJoinAnnotation(ann, null);
     if (StringHelper.isEmpty(joinColumn.getLogicalColumnName())
         && !StringHelper.isEmpty(suffixForDefaultColumnName)) {
       joinColumn.setLogicalColumnName(propertyName + suffixForDefaultColumnName);
     }
     joinColumn.setJoins(joins);
     joinColumn.setPropertyHolder(propertyHolder);
     joinColumn.setPropertyName(BinderHelper.getRelativePath(propertyHolder, propertyName));
     joinColumn.setImplicit(false);
     joinColumn.bind();
     return joinColumn;
   } else {
     Ejb3JoinColumn joinColumn = new Ejb3JoinColumn();
     joinColumn.setMappedBy(mappedBy);
     joinColumn.setJoins(joins);
     joinColumn.setPropertyHolder(propertyHolder);
     joinColumn.setPropertyName(BinderHelper.getRelativePath(propertyHolder, propertyName));
     // property name + suffix is an "explicit" column name
     if (!StringHelper.isEmpty(suffixForDefaultColumnName)) {
       joinColumn.setLogicalColumnName(propertyName + suffixForDefaultColumnName);
       joinColumn.setImplicit(false);
     } else {
       joinColumn.setImplicit(true);
     }
     joinColumn.setBuildingContext(buildingContext);
     joinColumn.bind();
     return joinColumn;
   }
 }
  public static Ejb3JoinColumn[] buildJoinTableJoinColumns(
      JoinColumn[] annJoins,
      Map<String, Join> secondaryTables,
      PropertyHolder propertyHolder,
      String propertyName,
      String mappedBy,
      MetadataBuildingContext buildingContext) {
    Ejb3JoinColumn[] joinColumns;
    if (annJoins == null) {
      Ejb3JoinColumn currentJoinColumn = new Ejb3JoinColumn();
      currentJoinColumn.setImplicit(true);
      currentJoinColumn.setNullable(false); // I break the spec, but it's for good
      currentJoinColumn.setPropertyHolder(propertyHolder);
      currentJoinColumn.setJoins(secondaryTables);
      currentJoinColumn.setBuildingContext(buildingContext);
      currentJoinColumn.setPropertyName(BinderHelper.getRelativePath(propertyHolder, propertyName));
      currentJoinColumn.setMappedBy(mappedBy);
      currentJoinColumn.bind();

      joinColumns = new Ejb3JoinColumn[] {currentJoinColumn};

    } else {
      joinColumns = new Ejb3JoinColumn[annJoins.length];
      JoinColumn annJoin;
      int length = annJoins.length;
      for (int index = 0; index < length; index++) {
        annJoin = annJoins[index];
        Ejb3JoinColumn currentJoinColumn = new Ejb3JoinColumn();
        currentJoinColumn.setImplicit(true);
        currentJoinColumn.setPropertyHolder(propertyHolder);
        currentJoinColumn.setJoins(secondaryTables);
        currentJoinColumn.setBuildingContext(buildingContext);
        currentJoinColumn.setPropertyName(
            BinderHelper.getRelativePath(propertyHolder, propertyName));
        currentJoinColumn.setMappedBy(mappedBy);
        currentJoinColumn.setJoinAnnotation(annJoin, propertyName);
        currentJoinColumn.setNullable(false); // I break the spec, but it's for good
        // done afterQuery the annotation to override it
        currentJoinColumn.bind();
        joinColumns[index] = currentJoinColumn;
      }
    }
    return joinColumns;
  }
 /** build join formula */
 public static Ejb3JoinColumn buildJoinFormula(
     JoinFormula ann,
     String mappedBy,
     Map<String, Join> joins,
     PropertyHolder propertyHolder,
     String propertyName,
     MetadataBuildingContext buildingContext) {
   Ejb3JoinColumn formulaColumn = new Ejb3JoinColumn();
   formulaColumn.setFormula(ann.value());
   formulaColumn.setReferencedColumn(ann.referencedColumnName());
   formulaColumn.setBuildingContext(buildingContext);
   formulaColumn.setPropertyHolder(propertyHolder);
   formulaColumn.setJoins(joins);
   formulaColumn.setPropertyName(BinderHelper.getRelativePath(propertyHolder, propertyName));
   formulaColumn.bind();
   return formulaColumn;
 }