Package org.hibernate.metamodel.source.annotations

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

/*
* 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.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import org.jboss.jandex.Index;
import org.jboss.jandex.Indexer;
import org.jboss.logging.Logger;

import org.hibernate.HibernateException;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.metamodel.MetadataSources;
import org.hibernate.metamodel.binding.EntityBinding;
import org.hibernate.metamodel.domain.Hierarchical;
import org.hibernate.metamodel.domain.NonEntity;
import org.hibernate.metamodel.domain.Superclass;
import org.hibernate.metamodel.source.annotation.xml.XMLEntityMappings;
import org.hibernate.metamodel.source.annotations.entity.ConfiguredClassHierarchy;
import org.hibernate.metamodel.source.annotations.entity.ConfiguredClassType;
import org.hibernate.metamodel.source.annotations.entity.EntityBinder;
import org.hibernate.metamodel.source.annotations.entity.EntityClass;
import org.hibernate.metamodel.source.annotations.global.FetchProfileBinder;
import org.hibernate.metamodel.source.annotations.global.FilterDefBinder;
import org.hibernate.metamodel.source.annotations.global.IdGeneratorBinder;
import org.hibernate.metamodel.source.annotations.global.QueryBinder;
import org.hibernate.metamodel.source.annotations.global.TableBinder;
import org.hibernate.metamodel.source.annotations.global.TypeDefBinder;
import org.hibernate.metamodel.source.annotations.util.ConfiguredClassHierarchyBuilder;
import org.hibernate.metamodel.source.annotations.xml.OrmXmlParser;
import org.hibernate.metamodel.source.annotations.xml.PseudoJpaDotNames;
import org.hibernate.metamodel.source.internal.JaxbRoot;
import org.hibernate.metamodel.source.internal.MetadataImpl;
import org.hibernate.metamodel.source.spi.Binder;
import org.hibernate.metamodel.source.spi.MetadataImplementor;
import org.hibernate.service.classloading.spi.ClassLoaderService;

/**
* Main class responsible to creating and binding the Hibernate meta-model from annotations.
* This binder only has to deal with the (jandex) annotation index/repository. XML configuration is already processed
* and pseudo annotations are created.
*
* @author Hardy Ferentschik
* @see org.hibernate.metamodel.source.annotations.xml.OrmXmlParser
*/
public class AnnotationBinder implements Binder {
  private static final CoreMessageLogger LOG = Logger.getMessageLogger(
      CoreMessageLogger.class,
      AnnotationBinder.class.getName()
  );

  private final MetadataImpl metadata;

  private Index index;
  private ClassLoaderService classLoaderService;

  public AnnotationBinder(MetadataImpl metadata) {
    this.metadata = metadata;
  }

  @Override
  @SuppressWarnings( { "unchecked" })
  public void prepare(MetadataSources sources) {
    // create a jandex index from the annotated classes
    Indexer indexer = new Indexer();
    for ( Class<?> clazz : sources.getAnnotatedClasses() ) {
      indexClass( indexer, clazz.getName().replace( '.', '/' ) + ".class" );
    }

    // add package-info from the configured packages
    for ( String packageName : sources.getAnnotatedPackages() ) {
      indexClass( indexer, packageName.replace( '.', '/' ) + "/package-info.class" );
    }

    index = indexer.complete();

    List<JaxbRoot<XMLEntityMappings>> mappings = new ArrayList<JaxbRoot<XMLEntityMappings>>();
    for ( JaxbRoot<?> root : sources.getJaxbRootList() ) {
      if ( root.getRoot() instanceof XMLEntityMappings ) {
        mappings.add( (JaxbRoot<XMLEntityMappings>) root );
      }
    }
    if ( !mappings.isEmpty() ) {
      // process the xml configuration
      final OrmXmlParser ormParser = new OrmXmlParser( metadata );
      index = ormParser.parseAndUpdateIndex( mappings, index );
    }

        if( index.getAnnotations( PseudoJpaDotNames.DEFAULT_DELIMITED_IDENTIFIERS ) != null ) {
            metadata.setGloballyQuotedIdentifiers( true );
        }
  }

  /**
   * Adds the class w/ the specified name to the jandex index.
   *
   * @param indexer The jandex indexer
   * @param className the fully qualified class name to be indexed
   */
  private void indexClass(Indexer indexer, String className) {
    InputStream stream = classLoaderService().locateResourceStream( className );
    try {
      indexer.index( stream );
    }
    catch ( IOException e ) {
      throw new HibernateException( "Unable to open input stream for class " + className, e );
    }
  }

  private ClassLoaderService classLoaderService() {
    if ( classLoaderService == null ) {
      classLoaderService = metadata.getServiceRegistry().getService( ClassLoaderService.class );
    }
    return classLoaderService;
  }

  @Override
  public void bindIndependentMetadata(MetadataSources sources) {
    TypeDefBinder.bind( metadata, index );
  }

  @Override
  public void bindTypeDependentMetadata(MetadataSources sources) {
    IdGeneratorBinder.bind( metadata, index );
  }

  @Override
  public void bindMappingMetadata(MetadataSources sources, List<String> processedEntityNames) {
    AnnotationBindingContext context = new AnnotationBindingContext( index, metadata.getServiceRegistry() );
    // need to order our annotated entities into an order we can process
    Set<ConfiguredClassHierarchy<EntityClass>> hierarchies = ConfiguredClassHierarchyBuilder.createEntityHierarchies(
        context
    );

    // now we process each hierarchy one at the time
    Hierarchical parent = null;
    for ( ConfiguredClassHierarchy<EntityClass> hierarchy : hierarchies ) {
      for ( EntityClass entityClass : hierarchy ) {
        // for classes annotated w/ @Entity we create a EntityBinding
        if ( ConfiguredClassType.ENTITY.equals( entityClass.getConfiguredClassType() ) ) {
          LOG.bindingEntityFromAnnotatedClass( entityClass.getName() );
          EntityBinder entityBinder = new EntityBinder( metadata, entityClass, parent );
          EntityBinding binding = entityBinder.bind();
          parent = binding.getEntity();
        }
        // for classes annotated w/ @MappedSuperclass we just create the domain instance
        // the attribute bindings will be part of the first entity subclass
        else if ( ConfiguredClassType.MAPPED_SUPERCLASS.equals( entityClass.getConfiguredClassType() ) ) {
          parent = new Superclass( entityClass.getName(), parent );
        }
        // for classes which are not annotated at all we create the NonEntity domain class
        // todo - not sure whether this is needed. It might be that we don't need this information (HF)
        else {
          parent = new NonEntity( entityClass.getName(), parent );
        }
      }
    }
  }

  @Override
  public void bindMappingDependentMetadata(MetadataSources sources) {
    TableBinder.bind( metadata, index );
    FetchProfileBinder.bind( metadata, index );
    QueryBinder.bind( metadata, index );
    FilterDefBinder.bind( metadata, index );
  }
}

TOP

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

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.