1717
1818import java .nio .ByteBuffer ;
1919import java .util .List ;
20+ import java .util .Map ;
2021
2122import com .google .common .collect .Lists ;
2223
2627/**
2728 * Serializes a class annotated with {@code @UDT} to the corresponding CQL user-defined type.
2829 */
29- class MappedUDTCodec <T > extends TypeCodec <T > {
30+ class MappedUDTCodec <T > extends TypeCodec . AbstractUDTCodec <T > {
3031 private final UserType cqlUserType ;
3132 private final Class <T > udtClass ;
32- private final List < ColumnMapper <T >> columnMappers ;
33+ private final Map < String , ColumnMapper <T >> columnMappers ;
3334 private final CodecRegistry codecRegistry ;
3435
35- public MappedUDTCodec (UserType cqlUserType , Class <T > udtClass , List < ColumnMapper <T >> columnMappers , MappingManager mappingManager ) {
36+ public MappedUDTCodec (UserType cqlUserType , Class <T > udtClass , Map < String , ColumnMapper <T >> columnMappers , MappingManager mappingManager ) {
3637 super (cqlUserType , udtClass );
3738 this .cqlUserType = cqlUserType ;
3839 this .udtClass = udtClass ;
@@ -41,70 +42,58 @@ public MappedUDTCodec(UserType cqlUserType, Class<T> udtClass, List<ColumnMapper
4142 }
4243
4344 @ Override
44- public ByteBuffer serialize (T sourceObject , ProtocolVersion protocolVersion ) throws InvalidTypeException {
45- if (sourceObject == null )
46- return null ;
47-
48- int size = 0 ;
49-
50- List <ByteBuffer > serializedFields = Lists .newArrayList ();
51- for (ColumnMapper <T > cm : columnMappers ) {
52- Object value = cm .getValue (sourceObject );
53- TypeCodec <Object > codec = cm .getCustomCodec ();
54- if (codec == null )
55- codec = codecRegistry .codecFor (cqlUserType .getFieldType (cm .getColumnName ()), cm .getJavaType ());
56- ByteBuffer serializedField = codec .serialize (value , protocolVersion );
57- size += 4 + (serializedField == null ? 0 : serializedField .remaining ());
58- serializedFields .add (serializedField );
59- }
60-
61- ByteBuffer result = ByteBuffer .allocate (size );
62- for (ByteBuffer bb : serializedFields ) {
63- if (bb == null ) {
64- result .putInt (-1 );
65- } else {
66- result .putInt (bb .remaining ());
67- result .put (bb .duplicate ());
68- }
45+ protected T newInstance () {
46+ try {
47+ return udtClass .newInstance ();
48+ } catch (Exception e ) {
49+ throw new IllegalArgumentException ("Error creating instance of @UDT-annotated class " + udtClass , e );
6950 }
70- return (ByteBuffer )result .flip ();
7151 }
7252
7353 @ Override
74- public T deserialize (ByteBuffer bytes , ProtocolVersion protocolVersion ) throws InvalidTypeException {
75- if (bytes == null || bytes .remaining () == 0 )
54+ protected ByteBuffer serializeField (T source , String fieldName , ProtocolVersion protocolVersion ) {
55+ // The parent class passes lowercase names unquoted, but in our internal map of mappers they are always quoted
56+ if (!fieldName .startsWith ("\" " ))
57+ fieldName = Metadata .quote (fieldName );
58+
59+ ColumnMapper <T > columnMapper = columnMappers .get (fieldName );
60+
61+ if (columnMapper == null )
7662 return null ;
77- ByteBuffer input = bytes .duplicate ();
7863
79- T targetObject = newInstance ( );
64+ Object value = columnMapper . getValue ( source );
8065
81- for (ColumnMapper <T > cm : columnMappers ) {
82- int size = input .getInt ();
83- ByteBuffer serialized = (size < 0 ) ? null : CodecUtils .readBytes (input , size );
84- TypeCodec <Object > codec = cm .getCustomCodec ();
85- if (codec == null )
86- codec = codecRegistry .codecFor (cqlUserType .getFieldType (cm .getColumnName ()), cm .getJavaType ());
87- cm .setValue (targetObject , codec .deserialize (serialized , protocolVersion ));
88- }
66+ TypeCodec <Object > codec = columnMapper .getCustomCodec ();
67+ if (codec == null )
68+ codec = codecRegistry .codecFor (cqlUserType .getFieldType (columnMapper .getColumnName ()), columnMapper .getJavaType ());
8969
90- return targetObject ;
70+ return codec . serialize ( value , protocolVersion ) ;
9171 }
9272
93- private T newInstance () {
94- try {
95- return udtClass .newInstance ();
96- } catch (Exception e ) {
97- throw new IllegalArgumentException ("Error creating instance of @UDT-annotated class " + udtClass , e );
73+ @ Override
74+ protected T deserializeAndSetField (ByteBuffer input , T target , String fieldName , ProtocolVersion protocolVersion ) {
75+ if (!fieldName .startsWith ("\" " ))
76+ fieldName = Metadata .quote (fieldName );
77+
78+ ColumnMapper <T > columnMapper = columnMappers .get (fieldName );
79+ if (columnMapper != null ) {
80+ TypeCodec <Object > codec = columnMapper .getCustomCodec ();
81+ if (codec == null )
82+ codec = codecRegistry .codecFor (cqlUserType .getFieldType (columnMapper .getColumnName ()), columnMapper .getJavaType ());
83+ columnMapper .setValue (target , codec .deserialize (input , protocolVersion ));
9884 }
85+ return target ;
9986 }
10087
10188 @ Override
102- public T parse (String value ) throws InvalidTypeException {
89+ protected String formatField (T source , String fieldName ) {
90+ // This codec implementation is internal-use only, and its format method is never used
10391 throw new UnsupportedOperationException ();
10492 }
10593
10694 @ Override
107- public String format (T value ) throws InvalidTypeException {
95+ protected T parseAndSetField (String input , T target , String fieldName ) {
96+ // This codec implementation is internal-use only, and its parse method is never used
10897 throw new UnsupportedOperationException ();
10998 }
11099}
0 commit comments