Package org.hibernate.cfg.beanvalidation

Source Code of org.hibernate.cfg.beanvalidation.HibernateTraversableResolver

/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2010, 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.cfg.beanvalidation;

import java.lang.annotation.ElementType;
import java.util.Set;
import java.util.HashSet;
import java.util.concurrent.ConcurrentHashMap;
import javax.validation.TraversableResolver;
import javax.validation.Path;

import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.Hibernate;
import org.hibernate.annotations.common.AssertionFailure;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.type.CompositeType;
import org.hibernate.type.Type;
import org.hibernate.type.CollectionType;

/**
* Use Hibernate metadata to ignore cascade on entities.
* cascade on embeddable objects or collection of embeddable objects are accepted
*
* Also use Hibernate's native isInitialized method call.
*
* @author Emmanuel Bernard
*/
public class HibernateTraversableResolver implements TraversableResolver {
  private Set<String> associations;

  public HibernateTraversableResolver(
      EntityPersister persister,
      ConcurrentHashMap<EntityPersister, Set<String>> associationsPerEntityPersister,
      SessionFactoryImplementor factory) {
    this.associations = associationsPerEntityPersister.get( persister );
    if (this.associations == null) {
      this.associations = new HashSet<String>();
      addAssociationsToTheSetForAllProperties( persister.getPropertyNames(), persister.getPropertyTypes(), "", factory );
      associationsPerEntityPersister.put( persister, associations );
    }
  }

  private void addAssociationsToTheSetForAllProperties(String[] names, Type[] types, String prefix, SessionFactoryImplementor factory) {
    final int length = names.length;
    for( int index = 0 ; index < length; index++ ) {
      addAssociationsToTheSetForOneProperty( names[index], types[index], prefix, factory );
    }
  }

  private void addAssociationsToTheSetForOneProperty(String name, Type type, String prefix, SessionFactoryImplementor factory) {

    if ( type.isCollectionType() ) {
      CollectionType collType = (CollectionType) type;
      Type assocType = collType.getElementType( factory );
      addAssociationsToTheSetForOneProperty(name, assocType, prefix, factory);
    }
    //ToOne association
    else if ( type.isEntityType() || type.isAnyType() ) {
      associations.add( prefix + name );
    } else if ( type.isComponentType() ) {
      CompositeType componentType = (CompositeType) type;
      addAssociationsToTheSetForAllProperties(
          componentType.getPropertyNames(),
          componentType.getSubtypes(),
          (prefix.equals( "" ) ? name : prefix + name) + ".",
          factory);
    }
  }

  private String getStringBasedPath(Path.Node traversableProperty, Path pathToTraversableObject) {
    StringBuilder path = new StringBuilder( );
    for ( Path.Node node : pathToTraversableObject ) {
      if (node.getName() != null) {
        path.append( node.getName() ).append( "." );
      }
    }
    if ( traversableProperty.getName() == null ) {
      throw new AssertionFailure(
          "TraversableResolver being passed a traversableProperty with null name. pathToTraversableObject: "
              + path.toString() );
    }
    path.append( traversableProperty.getName() );

    return path.toString();
  }

  public boolean isReachable(Object traversableObject,
                 Path.Node traversableProperty,
                 Class<?> rootBeanType,
                 Path pathToTraversableObject,
                 ElementType elementType) {
    //lazy, don't load
    return Hibernate.isInitialized( traversableObject )
        && Hibernate.isPropertyInitialized( traversableObject, traversableProperty.getName() );
  }

  public boolean isCascadable(Object traversableObject,
              Path.Node traversableProperty,
              Class<?> rootBeanType,
              Path pathToTraversableObject,
              ElementType elementType) {
    String path = getStringBasedPath( traversableProperty, pathToTraversableObject );
    return ! associations.contains(path);
  }
}
TOP

Related Classes of org.hibernate.cfg.beanvalidation.HibernateTraversableResolver

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.