private String buildDefaultColumnName(
      final PersistentClass referencedEntity, final String logicalReferencedColumn) {
    final Database database = getBuildingContext().getMetadataCollector().getDatabase();
    final ImplicitNamingStrategy implicitNamingStrategy =
        getBuildingContext().getBuildingOptions().getImplicitNamingStrategy();
    final PhysicalNamingStrategy physicalNamingStrategy =
        getBuildingContext().getBuildingOptions().getPhysicalNamingStrategy();

    Identifier columnIdentifier;
    boolean mappedBySide = mappedByTableName != null || mappedByPropertyName != null;
    boolean ownerSide = getPropertyName() != null;

    Boolean isRefColumnQuoted = StringHelper.isQuoted(logicalReferencedColumn);
    final String unquotedLogicalReferenceColumn =
        isRefColumnQuoted ? StringHelper.unquote(logicalReferencedColumn) : logicalReferencedColumn;

    if (mappedBySide) {
      // NOTE : While it is completely misleading here to allow for the combination
      //		of a "JPA ElementCollection" to be mappedBy, the code that uses this
      // 		class relies on this behavior for handling the inverse side of
      // 		many-to-many mappings

      final AttributePath attributePath = AttributePath.parse(mappedByPropertyName);
      final ImplicitJoinColumnNameSource.Nature implicitNamingNature;
      if (getPropertyHolder().isEntity()) {
        implicitNamingNature = ImplicitJoinColumnNameSource.Nature.ENTITY;
      } else if (JPA2ElementCollection) {
        implicitNamingNature = ImplicitJoinColumnNameSource.Nature.ELEMENT_COLLECTION;
      } else {
        implicitNamingNature = ImplicitJoinColumnNameSource.Nature.ENTITY_COLLECTION;
      }

      columnIdentifier =
          implicitNamingStrategy.determineJoinColumnName(
              new ImplicitJoinColumnNameSource() {
                private final EntityNaming entityNaming =
                    new EntityNaming() {
                      @Override
                      public String getClassName() {
                        return referencedEntity.getClassName();
                      }

                      @Override
                      public String getEntityName() {
                        return referencedEntity.getEntityName();
                      }

                      @Override
                      public String getJpaEntityName() {
                        return referencedEntity.getJpaEntityName();
                      }
                    };

                private final Identifier referencedTableName =
                    getBuildingContext()
                        .getMetadataCollector()
                        .getDatabase()
                        .toIdentifier(mappedByTableName);

                @Override
                public Nature getNature() {
                  return implicitNamingNature;
                }

                @Override
                public EntityNaming getEntityNaming() {
                  return entityNaming;
                }

                @Override
                public AttributePath getAttributePath() {
                  return attributePath;
                }

                @Override
                public Identifier getReferencedTableName() {
                  return referencedTableName;
                }

                @Override
                public Identifier getReferencedColumnName() {
                  if (logicalReferencedColumn != null) {
                    return getBuildingContext()
                        .getMetadataCollector()
                        .getDatabase()
                        .toIdentifier(logicalReferencedColumn);
                  }

                  if (mappedByEntityName == null || mappedByPropertyName == null) {
                    return null;
                  }

                  final PersistentClass mappedByEntityBinding =
                      getBuildingContext()
                          .getMetadataCollector()
                          .getEntityBinding(mappedByEntityName);
                  final Property mappedByProperty =
                      mappedByEntityBinding.getProperty(mappedByPropertyName);
                  final SimpleValue value = (SimpleValue) mappedByProperty.getValue();
                  final Iterator<Selectable> selectableValues = value.getColumnIterator();
                  if (!selectableValues.hasNext()) {
                    throw new AnnotationException(
                        String.format(
                            Locale.ENGLISH,
                            "mapped-by [%s] defined for attribute [%s] referenced an invalid property (no columns)",
                            mappedByPropertyName,
                            propertyHolder.getPath()));
                  }
                  final Selectable selectable = selectableValues.next();
                  if (!Column.class.isInstance(selectable)) {
                    throw new AnnotationException(
                        String.format(
                            Locale.ENGLISH,
                            "mapped-by [%s] defined for attribute [%s] referenced an invalid property (formula)",
                            mappedByPropertyName,
                            propertyHolder.getPath()));
                  }
                  if (selectableValues.hasNext()) {
                    throw new AnnotationException(
                        String.format(
                            Locale.ENGLISH,
                            "mapped-by [%s] defined for attribute [%s] referenced an invalid property (multiple columns)",
                            mappedByPropertyName,
                            propertyHolder.getPath()));
                  }
                  return getBuildingContext()
                      .getMetadataCollector()
                      .getDatabase()
                      .toIdentifier(((Column) selectable).getQuotedName());
                }

                @Override
                public MetadataBuildingContext getBuildingContext() {
                  return Ejb3JoinColumn.this.getBuildingContext();
                }
              });

      // one element was quoted so we quote
      if (isRefColumnQuoted || StringHelper.isQuoted(mappedByTableName)) {
        columnIdentifier = Identifier.quote(columnIdentifier);
      }
    } else if (ownerSide) {
      final String logicalTableName =
          getBuildingContext()
              .getMetadataCollector()
              .getLogicalTableName(referencedEntity.getTable());

      final ImplicitJoinColumnNameSource.Nature implicitNamingNature;
      if (JPA2ElementCollection) {
        implicitNamingNature = ImplicitJoinColumnNameSource.Nature.ELEMENT_COLLECTION;
      } else if (getPropertyHolder().isEntity()) {
        implicitNamingNature = ImplicitJoinColumnNameSource.Nature.ENTITY;
      } else {
        implicitNamingNature = ImplicitJoinColumnNameSource.Nature.ENTITY_COLLECTION;
      }

      columnIdentifier =
          getBuildingContext()
              .getBuildingOptions()
              .getImplicitNamingStrategy()
              .determineJoinColumnName(
                  new ImplicitJoinColumnNameSource() {
                    private final EntityNaming entityNaming =
                        new EntityNaming() {
                          @Override
                          public String getClassName() {
                            return referencedEntity.getClassName();
                          }

                          @Override
                          public String getEntityName() {
                            return referencedEntity.getEntityName();
                          }

                          @Override
                          public String getJpaEntityName() {
                            return referencedEntity.getJpaEntityName();
                          }
                        };

                    private final AttributePath attributePath =
                        AttributePath.parse(getPropertyName());
                    private final Identifier referencedTableName =
                        getBuildingContext()
                            .getMetadataCollector()
                            .getDatabase()
                            .toIdentifier(logicalTableName);
                    private final Identifier referencedColumnName =
                        getBuildingContext()
                            .getMetadataCollector()
                            .getDatabase()
                            .toIdentifier(logicalReferencedColumn);

                    @Override
                    public Nature getNature() {
                      return implicitNamingNature;
                    }

                    @Override
                    public EntityNaming getEntityNaming() {
                      return entityNaming;
                    }

                    @Override
                    public AttributePath getAttributePath() {
                      return attributePath;
                    }

                    @Override
                    public Identifier getReferencedTableName() {
                      return referencedTableName;
                    }

                    @Override
                    public Identifier getReferencedColumnName() {
                      return referencedColumnName;
                    }

                    @Override
                    public MetadataBuildingContext getBuildingContext() {
                      return Ejb3JoinColumn.this.getBuildingContext();
                    }
                  });

      // one element was quoted so we quote
      if (isRefColumnQuoted || StringHelper.isQuoted(logicalTableName)) {
        columnIdentifier = Identifier.quote(columnIdentifier);
      }
    } else {
      final Identifier logicalTableName =
          database.toIdentifier(
              getBuildingContext()
                  .getMetadataCollector()
                  .getLogicalTableName(referencedEntity.getTable()));

      // is an intra-entity hierarchy table join so copy the name by default
      columnIdentifier =
          implicitNamingStrategy.determinePrimaryKeyJoinColumnName(
              new ImplicitPrimaryKeyJoinColumnNameSource() {
                @Override
                public MetadataBuildingContext getBuildingContext() {
                  return Ejb3JoinColumn.this.getBuildingContext();
                }

                @Override
                public Identifier getReferencedTableName() {
                  return logicalTableName;
                }

                @Override
                public Identifier getReferencedPrimaryKeyColumnName() {
                  return database.toIdentifier(logicalReferencedColumn);
                }
              });

      if (!columnIdentifier.isQuoted() && (isRefColumnQuoted || logicalTableName.isQuoted())) {
        columnIdentifier = Identifier.quote(columnIdentifier);
      }
    }

    return physicalNamingStrategy
        .toPhysicalColumnName(columnIdentifier, database.getJdbcEnvironment())
        .render(database.getJdbcEnvironment().getDialect());
  }