// TODO refactor this code, there is a lot of duplication in this method
  public void doSecondPass(Map persistentClasses) throws MappingException {
    org.hibernate.mapping.OneToOne value =
        new org.hibernate.mapping.OneToOne(
            mappings, propertyHolder.getTable(), propertyHolder.getPersistentClass());
    final String propertyName = inferredData.getPropertyName();
    value.setPropertyName(propertyName);
    String referencedEntityName =
        ToOneBinder.getReferenceEntityName(inferredData, targetEntity, mappings);
    value.setReferencedEntityName(referencedEntityName);
    AnnotationBinder.defineFetchingStrategy(value, inferredData.getProperty());
    // value.setFetchMode( fetchMode );
    value.setCascadeDeleteEnabled(cascadeOnDelete);
    // value.setLazy( fetchMode != FetchMode.JOIN );

    if (!optional) value.setConstrained(true);
    value.setForeignKeyType(
        value.isConstrained()
            ? ForeignKeyDirection.FOREIGN_KEY_FROM_PARENT
            : ForeignKeyDirection.FOREIGN_KEY_TO_PARENT);
    PropertyBinder binder = new PropertyBinder();
    binder.setName(propertyName);
    binder.setValue(value);
    binder.setCascade(cascadeStrategy);
    binder.setAccessType(inferredData.getDefaultAccess());
    Property prop = binder.makeProperty();
    if (BinderHelper.isEmptyAnnotationValue(mappedBy)) {
      /*
       * we need to check if the columns are in the right order
       * if not, then we need to create a many to one and formula
       * but actually, since entities linked by a one to one need
       * to share the same composite id class, this cannot happen in hibernate
       */
      boolean rightOrder = true;

      if (rightOrder) {
        String path = StringHelper.qualify(propertyHolder.getPath(), propertyName);
        (new ToOneFkSecondPass(
                value,
                joinColumns,
                !optional, // cannot have nullabe and unique on certain DBs
                propertyHolder.getEntityOwnerClassName(),
                path,
                mappings))
            .doSecondPass(persistentClasses);
        // no column associated since its a one to one
        propertyHolder.addProperty(prop, inferredData.getDeclaringClass());
      } else {
        // this is a many to one with Formula

      }
    } else {
      PersistentClass otherSide =
          (PersistentClass) persistentClasses.get(value.getReferencedEntityName());
      Property otherSideProperty;
      try {
        if (otherSide == null) {
          throw new MappingException("Unable to find entity: " + value.getReferencedEntityName());
        }
        otherSideProperty = BinderHelper.findPropertyByName(otherSide, mappedBy);
      } catch (MappingException e) {
        throw new AnnotationException(
            "Unknown mappedBy in: "
                + StringHelper.qualify(ownerEntity, ownerProperty)
                + ", referenced property unknown: "
                + StringHelper.qualify(value.getReferencedEntityName(), mappedBy));
      }
      if (otherSideProperty == null) {
        throw new AnnotationException(
            "Unknown mappedBy in: "
                + StringHelper.qualify(ownerEntity, ownerProperty)
                + ", referenced property unknown: "
                + StringHelper.qualify(value.getReferencedEntityName(), mappedBy));
      }
      if (otherSideProperty.getValue() instanceof OneToOne) {
        propertyHolder.addProperty(prop, inferredData.getDeclaringClass());
      } else if (otherSideProperty.getValue() instanceof ManyToOne) {
        Iterator it = otherSide.getJoinIterator();
        Join otherSideJoin = null;
        while (it.hasNext()) {
          Join otherSideJoinValue = (Join) it.next();
          if (otherSideJoinValue.containsProperty(otherSideProperty)) {
            otherSideJoin = otherSideJoinValue;
            break;
          }
        }
        if (otherSideJoin != null) {
          // @OneToOne @JoinTable
          Join mappedByJoin =
              buildJoinFromMappedBySide(
                  (PersistentClass) persistentClasses.get(ownerEntity),
                  otherSideProperty,
                  otherSideJoin);
          ManyToOne manyToOne = new ManyToOne(mappings, mappedByJoin.getTable());
          // FIXME use ignore not found here
          manyToOne.setIgnoreNotFound(ignoreNotFound);
          manyToOne.setCascadeDeleteEnabled(value.isCascadeDeleteEnabled());
          manyToOne.setEmbedded(value.isEmbedded());
          manyToOne.setFetchMode(value.getFetchMode());
          manyToOne.setLazy(value.isLazy());
          manyToOne.setReferencedEntityName(value.getReferencedEntityName());
          manyToOne.setUnwrapProxy(value.isUnwrapProxy());
          prop.setValue(manyToOne);
          Iterator otherSideJoinKeyColumns = otherSideJoin.getKey().getColumnIterator();
          while (otherSideJoinKeyColumns.hasNext()) {
            Column column = (Column) otherSideJoinKeyColumns.next();
            Column copy = new Column();
            copy.setLength(column.getLength());
            copy.setScale(column.getScale());
            copy.setValue(manyToOne);
            copy.setName(column.getQuotedName());
            copy.setNullable(column.isNullable());
            copy.setPrecision(column.getPrecision());
            copy.setUnique(column.isUnique());
            copy.setSqlType(column.getSqlType());
            copy.setCheckConstraint(column.getCheckConstraint());
            copy.setComment(column.getComment());
            copy.setDefaultValue(column.getDefaultValue());
            manyToOne.addColumn(copy);
          }
          mappedByJoin.addProperty(prop);
        } else {
          propertyHolder.addProperty(prop, inferredData.getDeclaringClass());
        }

        value.setReferencedPropertyName(mappedBy);

        String propertyRef = value.getReferencedPropertyName();
        if (propertyRef != null) {
          mappings.addUniquePropertyReference(value.getReferencedEntityName(), propertyRef);
        }
      } else {
        throw new AnnotationException(
            "Referenced property not a (One|Many)ToOne: "
                + StringHelper.qualify(otherSide.getEntityName(), mappedBy)
                + " in mappedBy of "
                + StringHelper.qualify(ownerEntity, ownerProperty));
      }
    }
    ForeignKey fk = inferredData.getProperty().getAnnotation(ForeignKey.class);
    String fkName = fk != null ? fk.name() : "";
    if (!BinderHelper.isEmptyAnnotationValue(fkName)) value.setForeignKeyName(fkName);
  }