org.hibernate.boot.model.TypeDefinition Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of hibernate-core Show documentation
Show all versions of hibernate-core Show documentation
Hibernate's core ORM functionality
/*
* 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.boot.model;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Objects;
import java.util.Properties;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Supplier;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.boot.model.process.internal.UserTypeResolution;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.mapping.BasicValue;
import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
import org.hibernate.resource.beans.spi.ManagedBean;
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
import org.hibernate.type.BasicType;
import org.hibernate.type.CustomType;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
import org.hibernate.type.descriptor.java.MutabilityPlan;
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
import org.hibernate.type.spi.TypeConfiguration;
import org.hibernate.usertype.ParameterizedType;
import org.hibernate.usertype.UserType;
/**
* Models the information pertaining to a custom type definition supplied by the user. Used
* to delay instantiation of the actual {@link org.hibernate.type.Type} instance.
*
* Generally speaking this information would come from annotations
* ({@link org.hibernate.annotations.TypeDef}) or XML mappings. An alternative form of
* supplying custom types is programmatically via one of:
* - {@link org.hibernate.boot.MetadataBuilder#applyBasicType(org.hibernate.type.BasicType)}
* - {@link org.hibernate.boot.MetadataBuilder#applyBasicType(org.hibernate.usertype.UserType, String[])}
* - {@link org.hibernate.boot.MetadataBuilder#applyTypes(TypeContributor)}
*
*
* @author Steve Ebersole
* @author John Verhaeg
*/
public class TypeDefinition implements Serializable {
private static final AtomicInteger nameCounter = new AtomicInteger();
private final String name;
private final Class typeImplementorClass;
private final String[] registrationKeys;
private final Properties parameters;
private final TypeConfiguration typeConfiguration;
private BasicValue.Resolution reusableResolution;
public TypeDefinition(
String name,
Class typeImplementorClass,
String[] registrationKeys,
Properties parameters,
TypeConfiguration typeConfiguration) {
this.name = name;
this.typeImplementorClass = typeImplementorClass;
this.registrationKeys= registrationKeys;
this.parameters = parameters;
this.typeConfiguration = typeConfiguration;
}
public String getName() {
return name;
}
public Class getTypeImplementorClass() {
return typeImplementorClass;
}
public String[] getRegistrationKeys() {
return registrationKeys;
}
public Properties getParameters() {
return parameters;
}
public Properties getParametersAsProperties() {
Properties properties = new Properties();
properties.putAll( parameters );
return properties;
}
public BasicValue.Resolution resolve(
JavaTypeDescriptor explicitJtd,
SqlTypeDescriptor explicitStd,
Properties localConfigParameters,
MutabilityPlan explicitMutabilityPlan,
MetadataBuildingContext context) {
if ( CollectionHelper.isEmpty( localConfigParameters ) ) {
// we can use the re-usable resolution...
if ( reusableResolution == null ) {
final ManagedBean typeBean = context.getBootstrapContext()
.getServiceRegistry()
.getService( ManagedBeanRegistry.class )
.getBean( typeImplementorClass );
final Object typeInstance = typeBean.getBeanInstance();
injectParameters( typeInstance, () -> parameters );
reusableResolution = createReusableResolution( typeInstance, name, context );
}
return reusableResolution;
}
else {
final String name = this.name + ":" + nameCounter.getAndIncrement();
final ManagedBean typeBean = context.getBootstrapContext()
.getServiceRegistry()
.getService( ManagedBeanRegistry.class )
.getBean( name, typeImplementorClass );
final Object typeInstance = typeBean.getBeanInstance();
injectParameters(
typeInstance,
() -> mergeParameters( parameters, localConfigParameters )
);
return createResolution(
name,
typeInstance,
explicitJtd,
explicitStd,
explicitMutabilityPlan,
context
);
}
}
private static Properties mergeParameters(Properties parameters, Properties localConfigParameters) {
final Properties mergedParameters = new Properties();
if ( parameters != null ) {
mergedParameters.putAll( parameters );
}
if ( localConfigParameters != null && ! localConfigParameters.isEmpty() ) {
mergedParameters.putAll( localConfigParameters );
}
return mergedParameters;
}
private static void injectParameters(Object customType, Supplier parameterSupplier) {
if ( customType instanceof ParameterizedType ) {
final Properties parameterValues = parameterSupplier.get();
if ( parameterValues != null ) {
( (ParameterizedType) customType ).setParameterValues( parameterValues );
}
}
}
public static BasicValue.Resolution createReusableResolution(
Object namedTypeInstance,
String name,
MetadataBuildingContext buildingContext) {
if ( namedTypeInstance instanceof UserType ) {
final UserType userType = (UserType) namedTypeInstance;
final CustomType customType = new CustomType( userType, buildingContext.getBootstrapContext().getTypeConfiguration() );
return new UserTypeResolution( customType, null );
}
else if ( namedTypeInstance instanceof BasicType ) {
final BasicType resolvedBasicType = (BasicType) namedTypeInstance;
return new BasicValue.Resolution