protected boolean isRequiredInConstructor(Property field) {
    if (hasMetaAttribute(field, "default-value")) {
      return false;
    }
    if (field.getValue() != null) {
      if (!field.isOptional()
          && (field.getValueGenerationStrategy() == null
              || field
                  .getValueGenerationStrategy()
                  .getGenerationTiming()
                  .equals(GenerationTiming.NEVER))) {
        return true;
      } else if (field.getValue() instanceof Component) {
        Component c = (Component) field.getValue();
        Iterator<?> it = c.getPropertyIterator();
        while (it.hasNext()) {
          Property prop = (Property) it.next();
          if (isRequiredInConstructor(prop)) {
            return true;
          }
        }
      }
    }

    return false;
  }
  @Deprecated
  public static StandardProperty buildStandardProperty(Property property, boolean lazyAvailable) {
    final Type type = property.getValue().getType();

    // we need to dirty check collections, since they can cause an owner
    // version number increment

    // we need to dirty check many-to-ones with not-found="ignore" in order
    // to update the cache (not the database), since in this case a null
    // entity reference can lose information

    boolean alwaysDirtyCheck =
        type.isAssociationType() && ((AssociationType) type).isAlwaysDirtyChecked();

    return new StandardProperty(
        property.getName(),
        type,
        lazyAvailable && property.isLazy(),
        property.isInsertable(),
        property.isUpdateable(),
        property.getValueGenerationStrategy(),
        property.isOptional(),
        alwaysDirtyCheck || property.isUpdateable(),
        property.isOptimisticLocked(),
        property.getCascadeStyle(),
        property.getValue().getFetchMode());
  }
  /**
   * Generates a VersionProperty representation for an entity mapping given its version mapping
   * Property.
   *
   * @param property The version mapping Property.
   * @param lazyAvailable Is property lazy loading currently available.
   * @return The appropriate VersionProperty definition.
   */
  public static VersionProperty buildVersionProperty(
      EntityPersister persister,
      SessionFactoryImplementor sessionFactory,
      int attributeNumber,
      Property property,
      boolean lazyAvailable) {
    String mappedUnsavedValue = ((KeyValue) property.getValue()).getNullValue();

    VersionValue unsavedValue =
        UnsavedValueFactory.getUnsavedVersionValue(
            mappedUnsavedValue,
            getGetter(property),
            (VersionType) property.getType(),
            getConstructor(property.getPersistentClass()));

    boolean lazy = lazyAvailable && property.isLazy();

    return new VersionProperty(
        persister,
        sessionFactory,
        attributeNumber,
        property.getName(),
        property.getValue().getType(),
        new BaselineAttributeInformation.Builder()
            .setLazy(lazy)
            .setInsertable(property.isInsertable())
            .setUpdateable(property.isUpdateable())
            .setValueGenerationStrategy(property.getValueGenerationStrategy())
            .setNullable(property.isOptional())
            .setDirtyCheckable(property.isUpdateable() && !lazy)
            .setVersionable(property.isOptimisticLocked())
            .setCascadeStyle(property.getCascadeStyle())
            .createInformation(),
        unsavedValue);
  }
 /**
  * Build a normal attribute.
  *
  * @param ownerType The descriptor of the attribute owner (aka declarer).
  * @param property The Hibernate property descriptor for the attribute
  * @param <X> The type of the owner
  * @param <Y> The attribute type
  * @return The built attribute descriptor or null if the attribute is not part of the JPA 2 model
  *     (eg backrefs)
  */
 @SuppressWarnings({"unchecked"})
 public <X, Y> AttributeImplementor<X, Y> buildAttribute(
     AbstractManagedType<X> ownerType, Property property) {
   if (property.isSynthetic()) {
     // hide synthetic/virtual properties (fabricated by Hibernate) from the JPA metamodel.
     LOG.tracef(
         "Skipping synthetic property %s(%s)",
         ownerType.getJavaType().getName(), property.getName());
     return null;
   }
   LOG.trace(
       "Building attribute ["
           + ownerType.getJavaType().getName()
           + "."
           + property.getName()
           + "]");
   final AttributeContext<X> attributeContext = wrap(ownerType, property);
   final AttributeMetadata<X, Y> attributeMetadata =
       determineAttributeMetadata(attributeContext, NORMAL_MEMBER_RESOLVER);
   if (attributeMetadata == null) {
     return null;
   }
   if (attributeMetadata.isPlural()) {
     return buildPluralAttribute((PluralAttributeMetadata) attributeMetadata);
   }
   final SingularAttributeMetadata<X, Y> singularAttributeMetadata =
       (SingularAttributeMetadata<X, Y>) attributeMetadata;
   final Type<Y> metaModelType = getMetaModelType(singularAttributeMetadata.getValueContext());
   return new SingularAttributeImpl<X, Y>(
       attributeMetadata.getName(),
       attributeMetadata.getJavaType(),
       ownerType,
       attributeMetadata.getMember(),
       false,
       false,
       property.isOptional(),
       metaModelType,
       attributeMetadata.getPersistentAttributeType());
 }
  /**
   * Generate a non-identifier (and non-version) attribute based on the given mapped property from
   * the given entity
   *
   * @param property The mapped property.
   * @param lazyAvailable Is property lazy loading currently available.
   * @return The appropriate NonIdentifierProperty definition.
   */
  public static NonIdentifierAttribute buildEntityBasedAttribute(
      EntityPersister persister,
      SessionFactoryImplementor sessionFactory,
      int attributeNumber,
      Property property,
      boolean lazyAvailable) {
    final Type type = property.getValue().getType();

    final NonIdentifierAttributeNature nature = decode(type);

    // we need to dirty check collections, since they can cause an owner
    // version number increment

    // we need to dirty check many-to-ones with not-found="ignore" in order
    // to update the cache (not the database), since in this case a null
    // entity reference can lose information

    boolean alwaysDirtyCheck =
        type.isAssociationType() && ((AssociationType) type).isAlwaysDirtyChecked();

    switch (nature) {
      case BASIC:
        {
          return new EntityBasedBasicAttribute(
              persister,
              sessionFactory,
              attributeNumber,
              property.getName(),
              type,
              new BaselineAttributeInformation.Builder()
                  .setLazy(lazyAvailable && property.isLazy())
                  .setInsertable(property.isInsertable())
                  .setUpdateable(property.isUpdateable())
                  .setValueGenerationStrategy(property.getValueGenerationStrategy())
                  .setNullable(property.isOptional())
                  .setDirtyCheckable(alwaysDirtyCheck || property.isUpdateable())
                  .setVersionable(property.isOptimisticLocked())
                  .setCascadeStyle(property.getCascadeStyle())
                  .setFetchMode(property.getValue().getFetchMode())
                  .createInformation());
        }
      case COMPOSITE:
        {
          return new EntityBasedCompositionAttribute(
              persister,
              sessionFactory,
              attributeNumber,
              property.getName(),
              (CompositeType) type,
              new BaselineAttributeInformation.Builder()
                  .setLazy(lazyAvailable && property.isLazy())
                  .setInsertable(property.isInsertable())
                  .setUpdateable(property.isUpdateable())
                  .setValueGenerationStrategy(property.getValueGenerationStrategy())
                  .setNullable(property.isOptional())
                  .setDirtyCheckable(alwaysDirtyCheck || property.isUpdateable())
                  .setVersionable(property.isOptimisticLocked())
                  .setCascadeStyle(property.getCascadeStyle())
                  .setFetchMode(property.getValue().getFetchMode())
                  .createInformation());
        }
      case ENTITY:
      case ANY:
      case COLLECTION:
        {
          return new EntityBasedAssociationAttribute(
              persister,
              sessionFactory,
              attributeNumber,
              property.getName(),
              (AssociationType) type,
              new BaselineAttributeInformation.Builder()
                  .setLazy(lazyAvailable && property.isLazy())
                  .setInsertable(property.isInsertable())
                  .setUpdateable(property.isUpdateable())
                  .setValueGenerationStrategy(property.getValueGenerationStrategy())
                  .setNullable(property.isOptional())
                  .setDirtyCheckable(alwaysDirtyCheck || property.isUpdateable())
                  .setVersionable(property.isOptimisticLocked())
                  .setCascadeStyle(property.getCascadeStyle())
                  .setFetchMode(property.getValue().getFetchMode())
                  .createInformation());
        }
      default:
        {
          throw new HibernateException("Internal error");
        }
    }
  }