use of org.hibernate.property.access.internal.PropertyAccessStrategyCompositeUserTypeImpl in project hibernate-orm by hibernate.
the class AnnotationBinder method fillComponent.
public static Component fillComponent(PropertyHolder propertyHolder, PropertyData inferredData, // base inferred data correspond to the entity reproducing inferredData's properties (ie IdClass)
PropertyData baseInferredData, AccessType propertyAccessor, boolean isNullable, EntityBinder entityBinder, boolean isComponentEmbedded, boolean isIdentifierMapper, boolean inSecondPass, Class<? extends EmbeddableInstantiator> customInstantiatorImpl, Class<? extends CompositeUserType<?>> compositeUserTypeClass, MetadataBuildingContext buildingContext, Map<XClass, InheritanceState> inheritanceStatePerClass) {
/*
* inSecondPass can only be used to apply right away the second pass of a composite-element
* Because it's a value type, there is no bidirectional association, hence second pass
* ordering does not matter
*/
Component comp = createComponent(propertyHolder, inferredData, isComponentEmbedded, isIdentifierMapper, customInstantiatorImpl, buildingContext);
String subpath = BinderHelper.getPath(propertyHolder, inferredData);
LOG.tracev("Binding component with path: {0}", subpath);
PropertyHolder subHolder = buildPropertyHolder(comp, subpath, inferredData, propertyHolder, buildingContext);
// propertyHolder here is the owner of the component property. Tell it we are about to start the component...
propertyHolder.startingProperty(inferredData.getProperty());
final XClass xClassProcessed = inferredData.getPropertyClass();
List<PropertyData> classElements = new ArrayList<>();
final CompositeUserType<?> compositeUserType;
XClass returnedClassOrElement;
if (compositeUserTypeClass == null) {
compositeUserType = null;
returnedClassOrElement = inferredData.getClassOrElement();
} else {
compositeUserType = buildingContext.getBootstrapContext().getServiceRegistry().getService(ManagedBeanRegistry.class).getBean(compositeUserTypeClass).getBeanInstance();
comp.setTypeName(compositeUserTypeClass.getName());
returnedClassOrElement = buildingContext.getBootstrapContext().getReflectionManager().toXClass(compositeUserType.embeddable());
}
List<PropertyData> baseClassElements = null;
Map<String, PropertyData> orderedBaseClassElements = new HashMap<>();
XClass baseReturnedClassOrElement;
if (baseInferredData != null) {
baseClassElements = new ArrayList<>();
baseReturnedClassOrElement = baseInferredData.getClassOrElement();
// might be spread across the subclasses and super classes.
while (!Object.class.getName().equals(baseReturnedClassOrElement.getName())) {
addElementsOfClass(baseClassElements, new PropertyContainer(baseReturnedClassOrElement, xClassProcessed, propertyAccessor), buildingContext);
for (PropertyData element : baseClassElements) {
orderedBaseClassElements.put(element.getPropertyName(), element);
}
baseReturnedClassOrElement = baseReturnedClassOrElement.getSuperclass();
}
}
// embeddable elements can have type defs
PropertyContainer propContainer = new PropertyContainer(returnedClassOrElement, xClassProcessed, propertyAccessor);
addElementsOfClass(classElements, propContainer, buildingContext);
// add elements of the embeddable superclass
XClass superClass = xClassProcessed.getSuperclass();
while (superClass != null && superClass.isAnnotationPresent(MappedSuperclass.class)) {
// FIXME: proper support of type variables incl var resolved at upper levels
propContainer = new PropertyContainer(superClass, xClassProcessed, propertyAccessor);
addElementsOfClass(classElements, propContainer, buildingContext);
superClass = superClass.getSuperclass();
}
if (baseClassElements != null) {
// useful to avoid breaking pre JPA 2 mappings
if (!hasAnnotationsOnIdClass(xClassProcessed)) {
for (int i = 0; i < classElements.size(); i++) {
final PropertyData idClassPropertyData = classElements.get(i);
final PropertyData entityPropertyData = orderedBaseClassElements.get(idClassPropertyData.getPropertyName());
if (propertyHolder.isInIdClass()) {
if (entityPropertyData == null) {
throw new AnnotationException("Property of @IdClass not found in entity " + baseInferredData.getPropertyClass().getName() + ": " + idClassPropertyData.getPropertyName());
}
final boolean hasXToOneAnnotation = hasToOneAnnotation(entityPropertyData.getProperty());
final boolean isOfDifferentType = !entityPropertyData.getClassOrElement().equals(idClassPropertyData.getClassOrElement());
if (!hasXToOneAnnotation || !isOfDifferentType) {
// this works since they are in the same order
classElements.set(i, entityPropertyData);
}
// else {
// don't replace here as we need to use the actual original return type
// the annotation overriding will be dealt with by a mechanism similar to @MapsId
// }
} else {
// this works since they are in the same order
classElements.set(i, entityPropertyData);
}
}
}
}
for (PropertyData propertyAnnotatedElement : classElements) {
processElementAnnotations(subHolder, isNullable ? Nullability.NO_CONSTRAINT : Nullability.FORCED_NOT_NULL, propertyAnnotatedElement, new HashMap<>(), entityBinder, isIdentifierMapper, isComponentEmbedded, inSecondPass, buildingContext, inheritanceStatePerClass);
XProperty property = propertyAnnotatedElement.getProperty();
if (property.isAnnotationPresent(GeneratedValue.class) && property.isAnnotationPresent(Id.class)) {
GeneratedValue generatedValue = property.getAnnotation(GeneratedValue.class);
String generatorType = generatedValue != null ? generatorType(generatedValue, buildingContext, property.getType()) : DEFAULT_ID_GEN_STRATEGY;
String generator = generatedValue != null ? generatedValue.generator() : "";
if (isGlobalGeneratorNameGlobal(buildingContext)) {
buildGenerators(property, buildingContext);
SecondPass secondPass = new IdGeneratorResolverSecondPass((SimpleValue) comp.getProperty(property.getName()).getValue(), property, generatorType, generator, buildingContext);
buildingContext.getMetadataCollector().addSecondPass(secondPass);
handleTypeDescriptorRegistrations(property, buildingContext);
bindEmbeddableInstantiatorRegistrations(property, buildingContext);
bindCompositeUserTypeRegistrations(property, buildingContext);
} else {
Map<String, IdentifierGeneratorDefinition> localGenerators = new HashMap<>(buildGenerators(property, buildingContext));
makeIdGenerator((SimpleValue) comp.getProperty(property.getName()).getValue(), property, generatorType, generator, buildingContext, localGenerators);
}
}
}
if (compositeUserType != null) {
comp.sortProperties();
final List<String> sortedPropertyNames = new ArrayList<>(comp.getPropertySpan());
final List<Type> sortedPropertyTypes = new ArrayList<>(comp.getPropertySpan());
final PropertyAccessStrategy strategy = new PropertyAccessStrategyCompositeUserTypeImpl(compositeUserType, sortedPropertyNames, sortedPropertyTypes);
for (Property property : comp.getProperties()) {
sortedPropertyNames.add(property.getName());
sortedPropertyTypes.add(PropertyAccessStrategyMixedImpl.INSTANCE.buildPropertyAccess(compositeUserType.embeddable(), property.getName(), false).getGetter().getReturnType());
property.setPropertyAccessStrategy(strategy);
}
}
return comp;
}
Aggregations