Skip to content

Commit fd09c80

Browse files
committed
HHH-18060 - HbXmlTransformer work
* "special" basic type handling
1 parent e04304e commit fd09c80

File tree

7 files changed

+579
-6
lines changed

7 files changed

+579
-6
lines changed

hibernate-core/src/main/java/org/hibernate/boot/models/xml/internal/XmlAnnotationHelper.java

Lines changed: 346 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,30 @@
1010
import java.lang.reflect.Field;
1111
import java.math.BigDecimal;
1212
import java.math.BigInteger;
13+
import java.net.InetAddress;
14+
import java.net.URL;
15+
import java.sql.Blob;
16+
import java.sql.Clob;
17+
import java.sql.NClob;
18+
import java.sql.Timestamp;
19+
import java.time.Duration;
20+
import java.time.Instant;
21+
import java.time.LocalDate;
22+
import java.time.LocalDateTime;
23+
import java.time.LocalTime;
24+
import java.time.OffsetDateTime;
25+
import java.time.OffsetTime;
26+
import java.time.Year;
27+
import java.time.ZoneId;
28+
import java.time.ZoneOffset;
29+
import java.time.ZonedDateTime;
1330
import java.util.ArrayList;
31+
import java.util.Calendar;
32+
import java.util.Currency;
33+
import java.util.GregorianCalendar;
1434
import java.util.List;
35+
import java.util.Locale;
36+
import java.util.TimeZone;
1537
import java.util.UUID;
1638
import java.util.function.Consumer;
1739

@@ -136,6 +158,41 @@
136158
import org.hibernate.models.spi.MutableMemberDetails;
137159
import org.hibernate.models.spi.SourceModelBuildingContext;
138160
import org.hibernate.type.SqlTypes;
161+
import org.hibernate.type.descriptor.java.BasicJavaType;
162+
import org.hibernate.type.descriptor.java.BigDecimalJavaType;
163+
import org.hibernate.type.descriptor.java.BigIntegerJavaType;
164+
import org.hibernate.type.descriptor.java.BlobJavaType;
165+
import org.hibernate.type.descriptor.java.BooleanJavaType;
166+
import org.hibernate.type.descriptor.java.ByteJavaType;
167+
import org.hibernate.type.descriptor.java.CalendarJavaType;
168+
import org.hibernate.type.descriptor.java.CharacterJavaType;
169+
import org.hibernate.type.descriptor.java.ClassJavaType;
170+
import org.hibernate.type.descriptor.java.ClobJavaType;
171+
import org.hibernate.type.descriptor.java.CurrencyJavaType;
172+
import org.hibernate.type.descriptor.java.DateJavaType;
173+
import org.hibernate.type.descriptor.java.DoubleJavaType;
174+
import org.hibernate.type.descriptor.java.DurationJavaType;
175+
import org.hibernate.type.descriptor.java.InetAddressJavaType;
176+
import org.hibernate.type.descriptor.java.InstantJavaType;
177+
import org.hibernate.type.descriptor.java.IntegerJavaType;
178+
import org.hibernate.type.descriptor.java.LocalDateJavaType;
179+
import org.hibernate.type.descriptor.java.LocalDateTimeJavaType;
180+
import org.hibernate.type.descriptor.java.LocalTimeJavaType;
181+
import org.hibernate.type.descriptor.java.LocaleJavaType;
182+
import org.hibernate.type.descriptor.java.LongJavaType;
183+
import org.hibernate.type.descriptor.java.NClobJavaType;
184+
import org.hibernate.type.descriptor.java.OffsetDateTimeJavaType;
185+
import org.hibernate.type.descriptor.java.OffsetTimeJavaType;
186+
import org.hibernate.type.descriptor.java.ShortJavaType;
187+
import org.hibernate.type.descriptor.java.StringJavaType;
188+
import org.hibernate.type.descriptor.java.TimeZoneJavaType;
189+
import org.hibernate.type.descriptor.java.UUIDJavaType;
190+
import org.hibernate.type.descriptor.java.UrlJavaType;
191+
import org.hibernate.type.descriptor.java.YearJavaType;
192+
import org.hibernate.type.descriptor.java.ZoneIdJavaType;
193+
import org.hibernate.type.descriptor.java.ZoneOffsetJavaType;
194+
import org.hibernate.type.descriptor.java.ZonedDateTimeJavaType;
195+
import org.hibernate.usertype.UserType;
139196

140197
import jakarta.persistence.AssociationOverride;
141198
import jakarta.persistence.AttributeOverride;
@@ -146,6 +203,7 @@
146203
import jakarta.persistence.Index;
147204
import jakarta.persistence.PrimaryKeyJoinColumn;
148205
import jakarta.persistence.SecondaryTable;
206+
import jakarta.persistence.Temporal;
149207
import jakarta.persistence.TemporalType;
150208
import jakarta.persistence.UniqueConstraint;
151209
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -244,20 +302,305 @@ public static void applyUserType(
244302
JaxbUserTypeImpl jaxbType,
245303
MutableMemberDetails memberDetails,
246304
XmlDocumentContext xmlDocumentContext) {
247-
if ( jaxbType == null ) {
305+
if ( jaxbType == null || StringHelper.isEmpty( jaxbType.getValue() ) ) {
306+
return;
307+
}
308+
309+
final boolean wasSpecialCase = handleSpecialBasicTypeCases( jaxbType, memberDetails, xmlDocumentContext );
310+
if ( wasSpecialCase ) {
248311
return;
249312
}
250313

314+
final ClassDetails userTypeImpl = resolveJavaType( jaxbType.getValue(), xmlDocumentContext );
315+
assert userTypeImpl.isImplementor( UserType.class );
251316
final TypeAnnotation typeAnn = (TypeAnnotation) memberDetails.applyAnnotationUsage(
252317
HibernateAnnotations.TYPE,
253318
xmlDocumentContext.getModelBuildingContext()
254319
);
255-
256-
final ClassDetails userTypeImpl = resolveJavaType( jaxbType.getValue(), xmlDocumentContext );
257320
typeAnn.value( userTypeImpl.toJavaClass() );
258321
typeAnn.parameters( collectParameters( jaxbType.getParameters(), xmlDocumentContext ) );
259322
}
260323

324+
private static boolean handleSpecialBasicTypeCases(
325+
JaxbUserTypeImpl jaxbType,
326+
MutableMemberDetails memberDetails,
327+
XmlDocumentContext xmlDocumentContext) {
328+
if ( jaxbType.getValue().equalsIgnoreCase( "char" )
329+
|| jaxbType.getValue().equalsIgnoreCase( "character" )
330+
|| Character.class.getName().equalsIgnoreCase( jaxbType.getValue() ) ) {
331+
applyJavaTypeAnnotation( memberDetails, CharacterJavaType.class, xmlDocumentContext );
332+
return true;
333+
}
334+
335+
if ( jaxbType.getValue().equalsIgnoreCase( "string" )
336+
|| String.class.getName().equalsIgnoreCase( jaxbType.getValue() ) ) {
337+
applyJavaTypeAnnotation( memberDetails, StringJavaType.class, xmlDocumentContext );
338+
return true;
339+
}
340+
341+
if ( jaxbType.getValue().equalsIgnoreCase( "byte" )
342+
|| Byte.class.getName().equals( jaxbType.getValue() ) ) {
343+
applyJavaTypeAnnotation( memberDetails, ByteJavaType.class, xmlDocumentContext );
344+
return true;
345+
}
346+
347+
if ( jaxbType.getValue().equalsIgnoreCase( "boolean" )
348+
|| Boolean.class.getName().equals( jaxbType.getValue() ) ) {
349+
applyJavaTypeAnnotation( memberDetails, BooleanJavaType.class, xmlDocumentContext );
350+
return true;
351+
}
352+
353+
if ( jaxbType.getValue().equalsIgnoreCase( "short" )
354+
|| Short.class.getName().equals( jaxbType.getValue() ) ) {
355+
applyJavaTypeAnnotation( memberDetails, ShortJavaType.class, xmlDocumentContext );
356+
return true;
357+
}
358+
359+
if ( jaxbType.getValue().equalsIgnoreCase( "int" )
360+
|| jaxbType.getValue().equalsIgnoreCase( "integer" )
361+
|| Integer.class.getName().equals( jaxbType.getValue() ) ) {
362+
applyJavaTypeAnnotation( memberDetails, IntegerJavaType.class, xmlDocumentContext );
363+
return true;
364+
}
365+
366+
if ( jaxbType.getValue().equalsIgnoreCase( "long" )
367+
|| Long.class.getName().equals( jaxbType.getValue() ) ) {
368+
applyJavaTypeAnnotation( memberDetails, LongJavaType.class, xmlDocumentContext );
369+
return true;
370+
}
371+
372+
if ( jaxbType.getValue().equalsIgnoreCase( "double" )
373+
|| Double.class.getName().equals( jaxbType.getValue() ) ) {
374+
applyJavaTypeAnnotation( memberDetails, DoubleJavaType.class, xmlDocumentContext );
375+
return true;
376+
}
377+
378+
if ( jaxbType.getValue().equalsIgnoreCase( "float" )
379+
|| Float.class.getName().equals( jaxbType.getValue() ) ) {
380+
applyJavaTypeAnnotation( memberDetails, DoubleJavaType.class, xmlDocumentContext );
381+
return true;
382+
}
383+
384+
if ( jaxbType.getValue().equalsIgnoreCase( "biginteger" )
385+
|| jaxbType.getValue().equalsIgnoreCase( "big_integer" )
386+
|| BigInteger.class.getName().equals( jaxbType.getValue() ) ) {
387+
applyJavaTypeAnnotation( memberDetails, BigIntegerJavaType.class, xmlDocumentContext );
388+
return true;
389+
}
390+
391+
if ( jaxbType.getValue().equalsIgnoreCase( "bigdecimal" )
392+
|| jaxbType.getValue().equalsIgnoreCase( "big_decimal" )
393+
|| BigDecimal.class.getName().equals( jaxbType.getValue() ) ) {
394+
applyJavaTypeAnnotation( memberDetails, BigDecimalJavaType.class, xmlDocumentContext );
395+
return true;
396+
}
397+
398+
if ( jaxbType.getValue().equalsIgnoreCase( "uuid" )
399+
|| UUID.class.getName().equals( jaxbType.getValue() ) ) {
400+
applyJavaTypeAnnotation( memberDetails, UUIDJavaType.class, xmlDocumentContext );
401+
return true;
402+
}
403+
404+
if ( jaxbType.getValue().equalsIgnoreCase( "url" )
405+
|| URL.class.getName().equals( jaxbType.getValue() ) ) {
406+
applyJavaTypeAnnotation( memberDetails, UrlJavaType.class, xmlDocumentContext );
407+
return true;
408+
}
409+
410+
if ( jaxbType.getValue().equalsIgnoreCase( "inet" )
411+
|| jaxbType.getValue().equalsIgnoreCase( "inetaddress" )
412+
|| jaxbType.getValue().equalsIgnoreCase( "inet_address" )
413+
|| InetAddress.class.getName().equals( jaxbType.getValue() ) ) {
414+
applyJavaTypeAnnotation( memberDetails, InetAddressJavaType.class, xmlDocumentContext );
415+
return true;
416+
}
417+
418+
if ( jaxbType.getValue().equalsIgnoreCase( "currency" )
419+
|| Currency.class.getName().equals( jaxbType.getValue() ) ) {
420+
applyJavaTypeAnnotation( memberDetails, CurrencyJavaType.class, xmlDocumentContext );
421+
return true;
422+
}
423+
424+
if ( jaxbType.getValue().equalsIgnoreCase( "locale" )
425+
|| Locale.class.getName().equals( jaxbType.getValue() ) ) {
426+
applyJavaTypeAnnotation( memberDetails, LocaleJavaType.class, xmlDocumentContext );
427+
return true;
428+
}
429+
430+
if ( jaxbType.getValue().equalsIgnoreCase( "class" )
431+
|| Class.class.getName().equals( jaxbType.getValue() ) ) {
432+
applyJavaTypeAnnotation( memberDetails, ClassJavaType.class, xmlDocumentContext );
433+
return true;
434+
}
435+
436+
if ( jaxbType.getValue().equalsIgnoreCase( "blob" )
437+
|| Blob.class.getName().equals( jaxbType.getValue() ) ) {
438+
applyJavaTypeAnnotation( memberDetails, BlobJavaType.class, xmlDocumentContext );
439+
return true;
440+
}
441+
442+
if ( jaxbType.getValue().equalsIgnoreCase( "clob" )
443+
|| Clob.class.getName().equals( jaxbType.getValue() ) ) {
444+
applyJavaTypeAnnotation( memberDetails, ClobJavaType.class, xmlDocumentContext );
445+
return true;
446+
}
447+
448+
if ( jaxbType.getValue().equalsIgnoreCase( "nclob" )
449+
|| NClob.class.getName().equals( jaxbType.getValue() ) ) {
450+
applyJavaTypeAnnotation( memberDetails, NClobJavaType.class, xmlDocumentContext );
451+
return true;
452+
}
453+
454+
if ( jaxbType.getValue().equalsIgnoreCase( "instant" )
455+
|| Instant.class.getName().equals( jaxbType.getValue() ) ) {
456+
applyJavaTypeAnnotation( memberDetails, InstantJavaType.class, xmlDocumentContext );
457+
return true;
458+
}
459+
460+
if ( jaxbType.getValue().equalsIgnoreCase( "duration" )
461+
|| Duration.class.getName().equals( jaxbType.getValue() ) ) {
462+
applyJavaTypeAnnotation( memberDetails, DurationJavaType.class, xmlDocumentContext );
463+
return true;
464+
}
465+
466+
if ( jaxbType.getValue().equalsIgnoreCase( "year" )
467+
|| Year.class.getName().equals( jaxbType.getValue() ) ) {
468+
applyJavaTypeAnnotation( memberDetails, YearJavaType.class, xmlDocumentContext );
469+
return true;
470+
}
471+
472+
if ( jaxbType.getValue().equalsIgnoreCase( "localdatetime" )
473+
|| jaxbType.getValue().equalsIgnoreCase( "local_date_time" )
474+
|| LocalDateTime.class.getName().equals( jaxbType.getValue() ) ) {
475+
applyJavaTypeAnnotation( memberDetails, LocalDateTimeJavaType.class, xmlDocumentContext );
476+
return true;
477+
}
478+
479+
if ( jaxbType.getValue().equalsIgnoreCase( "localdate" )
480+
|| jaxbType.getValue().equalsIgnoreCase( "local_date" )
481+
|| LocalDate.class.getName().equals( jaxbType.getValue() ) ) {
482+
applyJavaTypeAnnotation( memberDetails, LocalDateJavaType.class, xmlDocumentContext );
483+
return true;
484+
}
485+
486+
if ( jaxbType.getValue().equalsIgnoreCase( "localtime" )
487+
|| jaxbType.getValue().equalsIgnoreCase( "local_time" )
488+
|| LocalTime.class.getName().equals( jaxbType.getValue() ) ) {
489+
applyJavaTypeAnnotation( memberDetails, LocalTimeJavaType.class, xmlDocumentContext );
490+
return true;
491+
}
492+
493+
if ( jaxbType.getValue().equalsIgnoreCase( "zoneddatetime" )
494+
|| jaxbType.getValue().equalsIgnoreCase( "zoned_date_time" )
495+
|| ZonedDateTime.class.getName().equals( jaxbType.getValue() ) ) {
496+
applyJavaTypeAnnotation( memberDetails, ZonedDateTimeJavaType.class, xmlDocumentContext );
497+
return true;
498+
}
499+
500+
if ( jaxbType.getValue().equalsIgnoreCase( "offsetdatetime" )
501+
|| jaxbType.getValue().equalsIgnoreCase( "offset_date_time" )
502+
|| OffsetDateTime.class.getName().equals( jaxbType.getValue() ) ) {
503+
applyJavaTypeAnnotation( memberDetails, OffsetDateTimeJavaType.class, xmlDocumentContext );
504+
return true;
505+
}
506+
507+
if ( jaxbType.getValue().equalsIgnoreCase( "offsettime" )
508+
|| jaxbType.getValue().equalsIgnoreCase( "offset_time" )
509+
|| OffsetTime.class.getName().equals( jaxbType.getValue() ) ) {
510+
applyJavaTypeAnnotation( memberDetails, OffsetTimeJavaType.class, xmlDocumentContext );
511+
return true;
512+
}
513+
514+
if ( jaxbType.getValue().equalsIgnoreCase( "zoneid" )
515+
|| jaxbType.getValue().equalsIgnoreCase( "zone_id" )
516+
|| ZoneId.class.getName().equals( jaxbType.getValue() ) ) {
517+
applyJavaTypeAnnotation( memberDetails, ZoneIdJavaType.class, xmlDocumentContext );
518+
return true;
519+
}
520+
521+
if ( jaxbType.getValue().equalsIgnoreCase( "zoneoffset" )
522+
|| jaxbType.getValue().equalsIgnoreCase( "zone_offset" )
523+
|| ZoneOffset.class.getName().equals( jaxbType.getValue() ) ) {
524+
applyJavaTypeAnnotation( memberDetails, ZoneOffsetJavaType.class, xmlDocumentContext );
525+
return true;
526+
}
527+
528+
if ( jaxbType.getValue().equalsIgnoreCase( "timestamp" )
529+
|| jaxbType.getValue().equalsIgnoreCase( "time_stamp" )
530+
|| java.util.Date.class.getName().equals( jaxbType.getValue() )
531+
|| Timestamp.class.getName().equals( jaxbType.getValue() ) ) {
532+
applyJavaTypeAnnotation( memberDetails, DateJavaType.class, xmlDocumentContext );
533+
applyTemporalPrecision( memberDetails, TemporalType.TIMESTAMP, xmlDocumentContext );
534+
return true;
535+
}
536+
537+
if ( jaxbType.getValue().equalsIgnoreCase( "date" )
538+
|| java.sql.Date.class.getName().equals( jaxbType.getValue() ) ) {
539+
applyJavaTypeAnnotation( memberDetails, DateJavaType.class, xmlDocumentContext );
540+
applyTemporalPrecision( memberDetails, TemporalType.DATE, xmlDocumentContext );
541+
return true;
542+
}
543+
544+
if ( jaxbType.getValue().equalsIgnoreCase( "time" )
545+
|| java.sql.Time.class.getName().equals( jaxbType.getValue() ) ) {
546+
applyJavaTypeAnnotation( memberDetails, DateJavaType.class, xmlDocumentContext );
547+
applyTemporalPrecision( memberDetails, TemporalType.TIME, xmlDocumentContext );
548+
return true;
549+
}
550+
551+
if ( jaxbType.getValue().equalsIgnoreCase( "calendar" )
552+
|| jaxbType.getValue().equalsIgnoreCase( "gregoriancalendar" )
553+
|| jaxbType.getValue().equalsIgnoreCase( "gregorian_calendar" )
554+
|| Calendar.class.getName().equals( jaxbType.getValue() )
555+
|| GregorianCalendar.class.getName().equals( jaxbType.getValue() ) ) {
556+
applyJavaTypeAnnotation( memberDetails, CalendarJavaType.class, xmlDocumentContext );
557+
return true;
558+
}
559+
560+
if ( jaxbType.getValue().equalsIgnoreCase( "timezone" )
561+
|| jaxbType.getValue().equalsIgnoreCase( "time_zone" )
562+
|| TimeZone.class.getName().equals( jaxbType.getValue() ) ) {
563+
applyJavaTypeAnnotation( memberDetails, TimeZoneJavaType.class, xmlDocumentContext );
564+
return true;
565+
}
566+
567+
return false;
568+
}
569+
570+
private static void applyJavaTypeAnnotation(
571+
MutableMemberDetails memberDetails,
572+
Class<? extends BasicJavaType<?>> descriptor,
573+
XmlDocumentContext xmlDocumentContext) {
574+
final JavaTypeAnnotation javaTypeAnnotation = (JavaTypeAnnotation) memberDetails.applyAnnotationUsage(
575+
HibernateAnnotations.JAVA_TYPE,
576+
xmlDocumentContext.getModelBuildingContext()
577+
);
578+
javaTypeAnnotation.value( descriptor );
579+
}
580+
581+
private static void applyTemporalPrecision(MutableMemberDetails memberDetails, TemporalType temporalType, XmlDocumentContext xmlDocumentContext) {
582+
final Temporal directUsage = memberDetails.getDirectAnnotationUsage( Temporal.class );
583+
if ( directUsage != null ) {
584+
// make sure they match
585+
if ( directUsage.value() != temporalType ) {
586+
throw new org.hibernate.MappingException( String.format(
587+
Locale.ROOT,
588+
"Mismatch in expected TemporalType on %s; found %s and %s",
589+
memberDetails,
590+
directUsage.value(),
591+
temporalType
592+
) );
593+
}
594+
return;
595+
}
596+
597+
final TemporalJpaAnnotation temporalAnnotation = (TemporalJpaAnnotation) memberDetails.applyAnnotationUsage(
598+
JpaAnnotations.TEMPORAL,
599+
xmlDocumentContext.getModelBuildingContext()
600+
);
601+
temporalAnnotation.value( temporalType );
602+
}
603+
261604
private static final Parameter[] NO_PARAMETERS = new Parameter[0];
262605

263606
public static Parameter[] collectParameters(

0 commit comments

Comments
 (0)