Package org.hibernate.metamodel.source.annotations

Source Code of org.hibernate.metamodel.source.annotations.EntityBinder

/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors.  All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA  02110-1301  USA
*/
package org.hibernate.metamodel.source.annotations;

import java.util.List;

import org.jboss.jandex.AnnotationInstance;
import org.jboss.jandex.AnnotationValue;

import org.hibernate.AssertionFailure;
import org.hibernate.MappingException;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.metamodel.binding.EntityBinding;
import org.hibernate.metamodel.binding.SimpleAttributeBinding;
import org.hibernate.metamodel.domain.Entity;
import org.hibernate.metamodel.domain.Hierarchical;
import org.hibernate.metamodel.relational.Identifier;
import org.hibernate.metamodel.relational.Schema;
import org.hibernate.metamodel.source.annotations.state.domain.AttributeDomainState;
import org.hibernate.metamodel.source.annotations.state.relational.AttributeColumnRelationalState;
import org.hibernate.metamodel.source.annotations.state.relational.AttributeTupleRelationalState;
import org.hibernate.metamodel.source.annotations.util.JandexHelper;
import org.hibernate.metamodel.source.internal.MetadataImpl;

/**
* Creates the domain and relational metamodel for a configured class and binds them together.
*
* @author Hardy Ferentschik
*/
public class EntityBinder {
  private final ConfiguredClass configuredClass;
  private final MetadataImpl meta;
  private final Schema.Name schemaName;

  public EntityBinder(MetadataImpl metadata, ConfiguredClass configuredClass) {
    this.configuredClass = configuredClass;
    this.meta = metadata;
    EntityBinding entityBinding = new EntityBinding();
    bindJpaEntityAnnotation( entityBinding );
    bindHibernateEntityAnnotation( entityBinding ); // optional hibernate specific @org.hibernate.annotations.Entity
    bindWhereFilter( entityBinding );
    schemaName = createSchemaName();
    bindTable( entityBinding );

    if ( configuredClass.isRoot() ) {
      bindId( entityBinding );
    }
    bindAttributes( entityBinding );

    meta.addEntity( entityBinding );
  }

  private void bindWhereFilter(EntityBinding entityBinding) {
    AnnotationInstance whereAnnotation = JandexHelper.getSingleAnnotation(
        configuredClass.getClassInfo(), HibernateDotNames.WHERE
    );
    if ( whereAnnotation != null ) {
      // no null check needed, it is a required attribute
      String clause = whereAnnotation.value( "clause" ).asString();
      entityBinding.setWhereFilter( clause );
    }
  }

  private Schema.Name createSchemaName() {
    String schema = null;
    String catalog = null;

    AnnotationInstance tableAnnotation = JandexHelper.getSingleAnnotation(
        configuredClass.getClassInfo(), JPADotNames.TABLE
    );
    if ( tableAnnotation != null ) {
      AnnotationValue schemaValue = tableAnnotation.value( "schema" );
      AnnotationValue catalogValue = tableAnnotation.value( "catalog" );

      schema = schemaValue != null ? schemaValue.asString() : null;
      catalog = catalogValue != null ? catalogValue.asString() : null;
    }

    return new Schema.Name( schema, catalog );
  }

  private void bindTable(EntityBinding entityBinding) {
    final Schema schema = meta.getDatabase().getSchema( schemaName );
    final Identifier tableName = Identifier.toIdentifier( configuredClass.getPrimaryTableName() );
    org.hibernate.metamodel.relational.Table table = schema.getTable( tableName );
    if ( table == null ) {
      table = schema.createTable( tableName );
    }
    entityBinding.setBaseTable( table );

    AnnotationInstance hibernateTableAnnotation = JandexHelper.getSingleAnnotation(
        configuredClass.getClassInfo(), HibernateDotNames.TABLE
    );

    if ( hibernateTableAnnotation != null && hibernateTableAnnotation.value( "comment" ) != null ) {
      table.addComment( hibernateTableAnnotation.value( "comment" ).asString().trim() );
    }
    // todo map rest of Hibernate @Table attributes

    AnnotationInstance checkAnnotation = JandexHelper.getSingleAnnotation(
        configuredClass.getClassInfo(), HibernateDotNames.CHECK
    );
    if ( checkAnnotation != null ) {
      table.addCheckConstraint( checkAnnotation.value( "constraints" ).asString() );
    }
  }

  private void bindId(EntityBinding entityBinding) {
    switch ( determineIdType() ) {
      case SIMPLE: {
        bindSingleIdAnnotation( entityBinding );
        break;
      }
      case COMPOSED: {
        // todo
        break;
      }
      case EMBEDDED: {
        // todo
        break;
      }
      default: {
      }
    }
  }

  private void bindJpaEntityAnnotation(EntityBinding entityBinding) {
    AnnotationInstance jpaEntityAnnotation = JandexHelper.getSingleAnnotation(
        configuredClass.getClassInfo(), JPADotNames.ENTITY
    );
    String name;
    if ( jpaEntityAnnotation.value( "name" ) == null ) {
      name = StringHelper.unqualify( configuredClass.getName() );
    }
    else {
      name = jpaEntityAnnotation.value( "name" ).asString();
    }
    entityBinding.setEntity( new Entity( name, getSuperType() ) );
  }

  private void bindSingleIdAnnotation(EntityBinding entityBinding) {
    AnnotationInstance idAnnotation = JandexHelper.getSingleAnnotation(
        configuredClass.getClassInfo(), JPADotNames.ID
    );

    String idName = JandexHelper.getPropertyName( idAnnotation.target() );
    entityBinding.getEntity().getOrCreateSingularAttribute( idName );
    SimpleAttributeBinding idBinding = entityBinding.makeSimplePrimaryKeyAttributeBinding( idName );

    MappedAttribute idAttribute = configuredClass.getMappedProperty( idName );

    AttributeDomainState domainState = new AttributeDomainState( entityBinding, idAttribute );
    idBinding.initialize( domainState );

    AttributeColumnRelationalState columnRelationsState = new AttributeColumnRelationalState( idAttribute, meta );
    AttributeTupleRelationalState relationalState = new AttributeTupleRelationalState();
    relationalState.addValueState( columnRelationsState );
    idBinding.initializeSimpleTupleValue( relationalState );
  }

  private void bindAttributes(EntityBinding entityBinding) {
    for ( MappedAttribute mappedAttribute : configuredClass.getMappedAttributes() ) {
      if ( mappedAttribute.isId() ) {
        continue;
      }

      String attributeName = mappedAttribute.getName();
      entityBinding.getEntity().getOrCreateSingularAttribute( attributeName );
      SimpleAttributeBinding attributeBinding;

      if ( mappedAttribute.isVersioned() ) {
        attributeBinding = entityBinding.makeVersionBinding( attributeName );
      }
      else {
        attributeBinding = entityBinding.makeSimpleAttributeBinding( attributeName );
      }

      AttributeDomainState domainState = new AttributeDomainState( entityBinding, mappedAttribute );
      attributeBinding.initialize( domainState );

      AttributeColumnRelationalState columnRelationsState = new AttributeColumnRelationalState(
          mappedAttribute, meta
      );
      AttributeTupleRelationalState relationalState = new AttributeTupleRelationalState();
      relationalState.addValueState( columnRelationsState );
      attributeBinding.initializeSimpleTupleValue( relationalState );
    }
  }

  private void bindHibernateEntityAnnotation(EntityBinding entityBinding) {
    AnnotationInstance hibernateEntityAnnotation = JandexHelper.getSingleAnnotation(
        configuredClass.getClassInfo(), HibernateDotNames.ENTITY
    );
//    if ( hibAnn != null ) {
//      dynamicInsert = hibAnn.dynamicInsert();
//      dynamicUpdate = hibAnn.dynamicUpdate();
//      optimisticLockType = hibAnn.optimisticLock();
//      selectBeforeUpdate = hibAnn.selectBeforeUpdate();
//      polymorphismType = hibAnn.polymorphism();
//      explicitHibernateEntityAnnotation = true;
//      //persister handled in bind
//    }
//    else {
//      //default values when the annotation is not there
//      dynamicInsert = false;
//      dynamicUpdate = false;
//      optimisticLockType = OptimisticLockType.VERSION;
//      polymorphismType = PolymorphismType.IMPLICIT;
//      selectBeforeUpdate = false;
//    }
  }

  private Hierarchical getSuperType() {
    ConfiguredClass parent = configuredClass.getParent();
    if ( parent == null ) {
      return null;
    }

    EntityBinding parentBinding = meta.getEntityBinding( parent.getName() );
    if ( parentBinding == null ) {
      throw new AssertionFailure(
          "Parent entity " + parent.getName() + " of entity " + configuredClass.getName() + "not yet created!"
      );
    }

    return parentBinding.getEntity();
  }

  private IdType determineIdType() {
    List<AnnotationInstance> idAnnotations = configuredClass.getClassInfo().annotations().get( JPADotNames.ENTITY );
    List<AnnotationInstance> embeddedIdAnnotations = configuredClass.getClassInfo()
        .annotations()
        .get( JPADotNames.EMBEDDED_ID );

    if ( idAnnotations != null && embeddedIdAnnotations != null ) {
      throw new MappingException(
          "@EmbeddedId and @Id cannot be used together. Check the configuration for " + configuredClass.getName() + "."
      );
    }

    if ( embeddedIdAnnotations != null ) {
      if ( embeddedIdAnnotations.size() == 1 ) {
        return IdType.EMBEDDED;
      }
      else {
        throw new MappingException( "Multiple @EmbeddedId annotations are not allowed" );
      }
    }

    if ( idAnnotations != null ) {
      if ( idAnnotations.size() == 1 ) {
        return IdType.SIMPLE;
      }
      else {
        return IdType.COMPOSED;
      }
    }

    return IdType.NONE;
  }

  enum IdType {
    // single @Id annotation
    SIMPLE,
    // multiple @Id annotations
    COMPOSED,
    // @EmbeddedId annotation
    EMBEDDED,
    // does not contain any identifier mappings
    NONE
  }
}


TOP

Related Classes of org.hibernate.metamodel.source.annotations.EntityBinder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.