All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.hibernate.metamodel.internal.AbstractIdentifiableType Maven / Gradle / Ivy

There is a newer version: 7.0.0.Alpha1
Show newest version
/*
 * Hibernate, Relational Persistence for Idiomatic Java
 *
 * License: GNU Lesser General Public License (LGPL), version 2.1 or later.
 * See the lgpl.txt file in the root directory or .
 */
package org.hibernate.metamodel.internal;

import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.metamodel.Attribute;
import javax.persistence.metamodel.IdentifiableType;
import javax.persistence.metamodel.SingularAttribute;
import javax.persistence.metamodel.Type;

/**
 * Defines commonality for the JPA {@link IdentifiableType} types.  JPA defines
 * identifiable types as entities or mapped-superclasses.  Basically things to which an
 * identifier can be attached.
 * 

* NOTE : Currently we only really have support for direct entities in the Hibernate metamodel * as the information for them is consumed into the closest actual entity subclass(es) in the * internal Hibernate mapping-metamodel. * * @author Steve Ebersole */ public abstract class AbstractIdentifiableType extends AbstractManagedType implements IdentifiableType, Serializable { private final boolean hasIdentifierProperty; private final boolean hasIdClass; private SingularAttributeImpl id; private Set> idClassAttributes; private final boolean isVersioned; private SingularAttributeImpl version; public AbstractIdentifiableType( Class javaType, String typeName, AbstractIdentifiableType superType, boolean hasIdClass, boolean hasIdentifierProperty, boolean versioned) { super( javaType, typeName, superType ); this.hasIdClass = hasIdClass; this.hasIdentifierProperty = hasIdentifierProperty; this.isVersioned = versioned; } public boolean hasIdClass() { return hasIdClass; } @Override public boolean hasSingleIdAttribute() { return !hasIdClass() && hasIdentifierProperty; } @Override @SuppressWarnings("unchecked") public AbstractIdentifiableType getSupertype() { // overridden simply to perform the cast return (AbstractIdentifiableType) super.getSupertype(); } @Override @SuppressWarnings({ "unchecked" }) public SingularAttribute getId(Class javaType) { ensureNoIdClass(); SingularAttributeImpl id = locateIdAttribute(); if ( id != null ) { checkType( id, javaType ); } return ( SingularAttribute ) id; } private void ensureNoIdClass() { if ( hasIdClass() ) { throw new IllegalArgumentException( "Illegal call to IdentifiableType#getId for class [" + getTypeName() + "] defined with @IdClass" ); } } private SingularAttributeImpl locateIdAttribute() { if ( id != null ) { return id; } else { if ( getSupertype() != null ) { SingularAttributeImpl id = getSupertype().internalGetId(); if ( id != null ) { return id; } } } return null; } protected SingularAttributeImpl internalGetId() { if ( id != null ) { return id; } else { if ( getSupertype() != null ) { return getSupertype().internalGetId(); } } return null; } @SuppressWarnings("unchecked") private void checkType(SingularAttributeImpl attribute, Class javaType) { if ( ! javaType.isAssignableFrom( attribute.getType().getJavaType() ) ) { throw new IllegalArgumentException( String.format( "Attribute [%s#%s : %s] not castable to requested type [%s]", getTypeName(), attribute.getName(), attribute.getType().getJavaType().getName(), javaType.getName() ) ); } } @Override @SuppressWarnings({ "unchecked" }) public SingularAttribute getDeclaredId(Class javaType) { ensureNoIdClass(); if ( id == null ) { throw new IllegalArgumentException( "The id attribute is not declared on this type [" + getTypeName() + "]" ); } checkType( id, javaType ); return (SingularAttribute) id; } @Override @SuppressWarnings("unchecked") public Type getIdType() { final SingularAttributeImpl id = locateIdAttribute(); if ( id != null ) { return id.getType(); } Set> idClassAttributes = getIdClassAttributesSafely(); if ( idClassAttributes != null ) { if ( idClassAttributes.size() == 1 ) { return idClassAttributes.iterator().next().getType(); } } return null; } /** * A form of {@link #getIdClassAttributes} which prefers to return {@code null} rather than throw exceptions * * @return IdClass attributes or {@code null} */ public Set> getIdClassAttributesSafely() { if ( !hasIdClass() ) { return null; } final Set> attributes = new HashSet>(); internalCollectIdClassAttributes( attributes ); if ( attributes.isEmpty() ) { return null; } return attributes; } @Override public Set> getIdClassAttributes() { if ( !hasIdClass() ) { throw new IllegalArgumentException( "This class [" + getJavaType() + "] does not define an IdClass" ); } final Set> attributes = new HashSet>(); internalCollectIdClassAttributes( attributes ); if ( attributes.isEmpty() ) { throw new IllegalArgumentException( "Unable to locate IdClass attributes [" + getJavaType() + "]" ); } return attributes; } @SuppressWarnings("unchecked") private void internalCollectIdClassAttributes(Set attributes) { if ( idClassAttributes != null ) { attributes.addAll( idClassAttributes ); } else if ( getSupertype() != null ) { getSupertype().internalCollectIdClassAttributes( attributes ); } } @Override public boolean hasVersionAttribute() { return isVersioned; } public boolean hasDeclaredVersionAttribute() { return isVersioned && version != null; } @Override @SuppressWarnings({ "unchecked" }) public SingularAttribute getVersion(Class javaType) { // todo : is return null allowed? if ( ! hasVersionAttribute() ) { return null; } SingularAttributeImpl version = locateVersionAttribute(); if ( version != null ) { checkType( version, javaType ); } return ( SingularAttribute ) version; } private SingularAttributeImpl locateVersionAttribute() { if ( version != null ) { return version; } else { if ( getSupertype() != null ) { SingularAttributeImpl version = getSupertype().internalGetVersion(); if ( version != null ) { return version; } } } return null; } protected SingularAttributeImpl internalGetVersion() { if ( version != null ) { return version; } else { if ( getSupertype() != null ) { return getSupertype().internalGetVersion(); } } return null; } @Override @SuppressWarnings({ "unchecked" }) public SingularAttribute getDeclaredVersion(Class javaType) { checkDeclaredVersion(); checkType( version, javaType ); return ( SingularAttribute ) version; } private void checkDeclaredVersion() { if ( version == null || ( getSupertype() != null && getSupertype().hasVersionAttribute() )) { throw new IllegalArgumentException( "The version attribute is not declared by this type [" + getJavaType() + "]" ); } } /** * For used to retrieve the declared version when populating the static metamodel. * * @return The declared */ public SingularAttribute getDeclaredVersion() { checkDeclaredVersion(); return version; } public Builder getBuilder() { final AbstractManagedType.Builder managedBuilder = super.getBuilder(); return new Builder() { public void applyIdAttribute(SingularAttributeImpl idAttribute) { AbstractIdentifiableType.this.id = idAttribute; managedBuilder.addAttribute( idAttribute ); } public void applyIdClassAttributes(Set> idClassAttributes) { for ( SingularAttribute idClassAttribute : idClassAttributes ) { if ( AbstractIdentifiableType.this == idClassAttribute.getDeclaringType() ) { @SuppressWarnings({ "unchecked" }) SingularAttribute declaredAttribute = ( SingularAttribute ) idClassAttribute; addAttribute( declaredAttribute ); } } AbstractIdentifiableType.this.idClassAttributes = idClassAttributes; } public void applyVersionAttribute(SingularAttributeImpl versionAttribute) { AbstractIdentifiableType.this.version = versionAttribute; managedBuilder.addAttribute( versionAttribute ); } public void addAttribute(Attribute attribute) { managedBuilder.addAttribute( attribute ); } }; } public static interface Builder extends AbstractManagedType.Builder { public void applyIdAttribute(SingularAttributeImpl idAttribute); public void applyIdClassAttributes(Set> idClassAttributes); public void applyVersionAttribute(SingularAttributeImpl versionAttribute); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy