Package org.hibernate.metamodel.source.annotations.attribute

Source Code of org.hibernate.metamodel.source.annotations.attribute.BasicAttribute

/*
* 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.attribute;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import javax.persistence.FetchType;
import javax.persistence.GenerationType;

import org.hibernate.AnnotationException;
import org.hibernate.annotations.GenerationTime;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.mapping.PropertyGeneration;
import org.hibernate.metamodel.binding.IdGenerator;
import org.hibernate.metamodel.source.MappingException;
import org.hibernate.metamodel.source.annotations.EnumConversionHelper;
import org.hibernate.metamodel.source.annotations.HibernateDotNames;
import org.hibernate.metamodel.source.annotations.JPADotNames;
import org.hibernate.metamodel.source.annotations.JandexHelper;
import org.hibernate.metamodel.source.annotations.attribute.type.AttributeTypeResolver;
import org.hibernate.metamodel.source.annotations.attribute.type.AttributeTypeResolverImpl;
import org.hibernate.metamodel.source.annotations.attribute.type.CompositeAttributeTypeResolver;
import org.hibernate.metamodel.source.annotations.attribute.type.EnumeratedTypeResolver;
import org.hibernate.metamodel.source.annotations.attribute.type.LobTypeResolver;
import org.hibernate.metamodel.source.annotations.attribute.type.TemporalTypeResolver;
import org.hibernate.metamodel.source.annotations.entity.EntityBindingContext;

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

/**
* Represent a basic attribute (explicitly or implicitly mapped).
*
* @author Hardy Ferentschik
*/
public class BasicAttribute extends MappedAttribute {

  /**
   * The id generator in case this basic attribute represents an simple id. Will be {@code null} in case there
   * is no explicit id generator or the containing entity does not have a simple id
   */
  private final IdGenerator idGenerator;

  /**
   * Is this a versioned property (annotated w/ {@code @Version}.
   */
  private final boolean isVersioned;

  /**
   * Is this property lazy loaded (see {@link javax.persistence.Basic}).
   */
  private boolean isLazy = false;

  /**
   * Is this property optional  (see {@link javax.persistence.Basic}).
   */
  private boolean isOptional = true;

  /**
   * Are this properties generated and when
   */
  private PropertyGeneration propertyGeneration;
  private boolean isInsertable = true;
  private boolean isUpdatable = true;

  private final String customWriteFragment;
  private final String customReadFragment;
  private final String checkCondition;
  private AttributeTypeResolver resolver;

  public static BasicAttribute createSimpleAttribute(String name,
                             Class<?> attributeType,
                             Map<DotName, List<AnnotationInstance>> annotations,
                             String accessType,
                             EntityBindingContext context) {
    return new BasicAttribute( name, attributeType, accessType, annotations, context );
  }

  BasicAttribute(String name,
           Class<?> attributeType,
           String accessType,
           Map<DotName, List<AnnotationInstance>> annotations,
           EntityBindingContext context) {
    super( name, attributeType, accessType, annotations, context );

    AnnotationInstance versionAnnotation = JandexHelper.getSingleAnnotation( annotations, JPADotNames.VERSION );
    isVersioned = versionAnnotation != null;

    if ( isId() ) {
      // an id must be unique and cannot be nullable
      getColumnValues().setUnique( true );
      getColumnValues().setNullable( false );
      idGenerator = checkGeneratedValueAnnotation();
    }
    else {
      idGenerator = null;
    }

    checkBasicAnnotation();
    checkGeneratedAnnotation();

    List<AnnotationInstance> columnTransformerAnnotations = getAllColumnTransformerAnnotations();
    String[] readWrite = createCustomReadWrite( columnTransformerAnnotations );
    this.customReadFragment = readWrite[0];
    this.customWriteFragment = readWrite[1];
    this.checkCondition = parseCheckAnnotation();
  }

  public boolean isVersioned() {
    return isVersioned;
  }

  public boolean isLazy() {
    return isLazy;
  }

  public boolean isOptional() {
    return isOptional;
  }

  public boolean isInsertable() {
    return isInsertable;
  }

  public boolean isUpdatable() {
    return isUpdatable;
  }

  public PropertyGeneration getPropertyGeneration() {
    return propertyGeneration;
  }

  public String getCustomWriteFragment() {
    return customWriteFragment;
  }

  public String getCustomReadFragment() {
    return customReadFragment;
  }

  public String getCheckCondition() {
    return checkCondition;
  }

  public IdGenerator getIdGenerator() {
    return idGenerator;
  }

  @Override
  public String toString() {
    final StringBuilder sb = new StringBuilder();
    sb.append( "SimpleAttribute" );
    sb.append( "{name=" ).append( getName() );
    return sb.toString();
  }

  private void checkBasicAnnotation() {
    AnnotationInstance basicAnnotation = JandexHelper.getSingleAnnotation( annotations(), JPADotNames.BASIC );
    if ( basicAnnotation != null ) {
      FetchType fetchType = FetchType.LAZY;
      AnnotationValue fetchValue = basicAnnotation.value( "fetch" );
      if ( fetchValue != null ) {
        fetchType = Enum.valueOf( FetchType.class, fetchValue.asEnum() );
      }
      this.isLazy = fetchType == FetchType.LAZY;

      AnnotationValue optionalValue = basicAnnotation.value( "optional" );
      if ( optionalValue != null ) {
        this.isOptional = optionalValue.asBoolean();
      }
    }
  }

  // TODO - there is more todo for updatable and insertable. Checking the @Generated annotation is only one part (HF)
  private void checkGeneratedAnnotation() {
    AnnotationInstance generatedAnnotation = JandexHelper.getSingleAnnotation(
        annotations(),
        HibernateDotNames.GENERATED
    );
    if ( generatedAnnotation != null ) {
      this.isInsertable = false;

      AnnotationValue generationTimeValue = generatedAnnotation.value();
      if ( generationTimeValue != null ) {
        GenerationTime genTime = Enum.valueOf( GenerationTime.class, generationTimeValue.asEnum() );
        if ( GenerationTime.ALWAYS.equals( genTime ) ) {
          this.isUpdatable = false;
          this.propertyGeneration = PropertyGeneration.parse( genTime.toString().toLowerCase() );
        }
      }
    }
  }

  private List<AnnotationInstance> getAllColumnTransformerAnnotations() {
    List<AnnotationInstance> allColumnTransformerAnnotations = new ArrayList<AnnotationInstance>();

    // not quite sure about the usefulness of @ColumnTransformers (HF)
    AnnotationInstance columnTransformersAnnotations = JandexHelper.getSingleAnnotation(
        annotations(),
        HibernateDotNames.COLUMN_TRANSFORMERS
    );
    if ( columnTransformersAnnotations != null ) {
      AnnotationInstance[] annotationInstances = allColumnTransformerAnnotations.get( 0 ).value().asNestedArray();
      allColumnTransformerAnnotations.addAll( Arrays.asList( annotationInstances ) );
    }

    AnnotationInstance columnTransformerAnnotation = JandexHelper.getSingleAnnotation(
        annotations(),
        HibernateDotNames.COLUMN_TRANSFORMER
    );
    if ( columnTransformerAnnotation != null ) {
      allColumnTransformerAnnotations.add( columnTransformerAnnotation );
    }
    return allColumnTransformerAnnotations;
  }

  private String[] createCustomReadWrite(List<AnnotationInstance> columnTransformerAnnotations) {
    String[] readWrite = new String[2];

    boolean alreadyProcessedForColumn = false;
    for ( AnnotationInstance annotationInstance : columnTransformerAnnotations ) {
      String forColumn = annotationInstance.value( "forColumn" ) == null ?
          null : annotationInstance.value( "forColumn" ).asString();

      if ( forColumn != null && !forColumn.equals( getName() ) ) {
        continue;
      }

      if ( alreadyProcessedForColumn ) {
        throw new AnnotationException( "Multiple definition of read/write conditions for column " + getName() );
      }

      readWrite[0] = annotationInstance.value( "read" ) == null ?
          null : annotationInstance.value( "read" ).asString();
      readWrite[1] = annotationInstance.value( "write" ) == null ?
          null : annotationInstance.value( "write" ).asString();

      alreadyProcessedForColumn = true;
    }
    return readWrite;
  }

  private String parseCheckAnnotation() {
    String checkCondition = null;
    AnnotationInstance checkAnnotation = JandexHelper.getSingleAnnotation( annotations(), HibernateDotNames.CHECK );
    if ( checkAnnotation != null ) {
      checkCondition = checkAnnotation.value( "constraints" ).toString();
    }
    return checkCondition;
  }

  private IdGenerator checkGeneratedValueAnnotation() {
    IdGenerator generator = null;
    AnnotationInstance generatedValueAnnotation = JandexHelper.getSingleAnnotation(
        annotations(),
        JPADotNames.GENERATED_VALUE
    );
    if ( generatedValueAnnotation != null ) {
      String name = JandexHelper.getValue( generatedValueAnnotation, "generator", String.class );
      if ( StringHelper.isNotEmpty( name ) ) {
        generator = getContext().getMetadataImplementor().getIdGenerator( name );
        if ( generator == null ) {
          throw new MappingException( String.format( "Unable to find named generator %s", name ), null );
        }
      }
      else {
        GenerationType genType = JandexHelper.getEnumValue(
            generatedValueAnnotation,
            "strategy",
            GenerationType.class
        );
        String strategy = EnumConversionHelper.generationTypeToGeneratorStrategyName(
            genType,
            getContext().getMetadataImplementor().getOptions().useNewIdentifierGenerators()
        );
        generator = new IdGenerator( null, strategy, null );
      }
    }
    return generator;
  }

  @Override
  public AttributeTypeResolver getHibernateTypeResolver() {
    if ( resolver == null ) {
      resolver = getDefaultHibernateTypeResolver();
    }
    return resolver;
  }

  private AttributeTypeResolver getDefaultHibernateTypeResolver() {
    CompositeAttributeTypeResolver resolver = new CompositeAttributeTypeResolver(
        new AttributeTypeResolverImpl(
            this
        )
    );
    resolver.addHibernateTypeResolver( new TemporalTypeResolver( this ) );
    resolver.addHibernateTypeResolver( new LobTypeResolver( this ) );
    resolver.addHibernateTypeResolver( new EnumeratedTypeResolver( this ) );
    return resolver;
  }
}

TOP

Related Classes of org.hibernate.metamodel.source.annotations.attribute.BasicAttribute

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.