7474
7575import org .eclipse .microprofile .config .inject .ConfigProperties ;
7676import org .eclipse .microprofile .config .inject .ConfigProperty ;
77+ import org .eclipse .microprofile .config .spi .Converter ;
7778import org .objectweb .asm .AnnotationVisitor ;
7879import org .objectweb .asm .ClassVisitor ;
7980import org .objectweb .asm .ClassWriter ;
@@ -234,6 +235,7 @@ static byte[] generate(final ConfigMappingInterface mapping) {
234235 private static final String I_OPTIONAL_INT = getInternalName (OptionalInt .class );
235236 private static final String I_OPTIONAL_LONG = getInternalName (OptionalLong .class );
236237 private static final String I_OPTIONAL_DOUBLE = getInternalName (OptionalDouble .class );
238+ private static final String I_CONVERTER = getInternalName (Converter .class );
237239
238240 static byte [] generateBuilder (final ConfigMappingInterface mapping , final String builderClassName ) {
239241 ClassWriter writer = new ClassWriter (ClassWriter .COMPUTE_FRAMES | ClassWriter .COMPUTE_MAXS );
@@ -251,6 +253,7 @@ static byte[] generateBuilder(final ConfigMappingInterface mapping, final String
251253 continue ;
252254 }
253255
256+ // Set Default / Generate method to retrieve the default
254257 String fieldDesc = getDescriptor (property .getMethod ().getReturnType ());
255258 String memberName = property .getMethod ().getName ();
256259 String defaultMethodName = "default_" + memberName ;
@@ -261,18 +264,27 @@ static byte[] generateBuilder(final ConfigMappingInterface mapping, final String
261264 noArgsCtor .visitMethodInsn (INVOKESTATIC , builderClassName , defaultMethodName , "()" + fieldDesc , false );
262265 noArgsCtor .visitFieldInsn (PUTFIELD , builderClassName , memberName , fieldDesc );
263266 // Default Method
264- PrimitiveProperty primitive = property .asPrimitive ();
267+ PrimitiveProperty primitiveProperty = property .asPrimitive ();
265268 MethodVisitor mv = visitor .visitMethod (ACC_PUBLIC | ACC_STATIC , defaultMethodName , "()" + fieldDesc , null ,
266269 null );
267270 mv .visitLdcInsn (property .getDefaultValue ());
268- mv .visitLdcInsn (Type .getType (getDescriptor (primitive .getBoxType ())));
271+ if (primitiveProperty .hasConvertWith ()) {
272+ String convertWith = getInternalName (primitiveProperty .getConvertWith ());
273+ mv .visitTypeInsn (NEW , convertWith );
274+ mv .visitInsn (DUP );
275+ mv .visitMethodInsn (INVOKESPECIAL , convertWith , "<init>" , "()V" , false );
276+ } else {
277+ mv .visitLdcInsn (Type .getType (getDescriptor (primitiveProperty .getBoxType ())));
278+ mv .visitMethodInsn (INVOKESTATIC , I_CONFIG_INSTANCE_BUILDER_IMPL , "getConverter" ,
279+ "(L" + I_CLASS + ";)L" + I_CONVERTER + ";" , false );
280+ }
269281 mv .visitMethodInsn (INVOKESTATIC , I_CONFIG_INSTANCE_BUILDER_IMPL , "convertValue" ,
270- "(L" + I_STRING + ";L" + I_CLASS + ";)L" + I_OBJECT + ";" , false );
271- mv .visitTypeInsn (CHECKCAST , getInternalName (primitive .getBoxType ()));
282+ "(L" + I_STRING + ";L" + I_CONVERTER + ";)L" + I_OBJECT + ";" , false );
283+ mv .visitTypeInsn (CHECKCAST , getInternalName (primitiveProperty .getBoxType ()));
272284 mv .visitMethodInsn (INVOKEVIRTUAL ,
273- getInternalName (primitive .getBoxType ()),
274- primitive .getUnboxMethodName (),
275- primitive .getUnboxMethodDescriptor (), false );
285+ getInternalName (primitiveProperty .getBoxType ()),
286+ primitiveProperty .getUnboxMethodName (),
287+ primitiveProperty .getUnboxMethodDescriptor (), false );
276288 mv .visitInsn (getReturnInstruction (property ));
277289 mv .visitMaxs (0 , 0 );
278290 mv .visitEnd ();
@@ -284,9 +296,18 @@ static byte[] generateBuilder(final ConfigMappingInterface mapping, final String
284296 MethodVisitor mv = visitor .visitMethod (ACC_PUBLIC | ACC_STATIC , defaultMethodName , "()" + fieldDesc , null ,
285297 null );
286298 mv .visitLdcInsn (property .getDefaultValue ());
287- mv .visitLdcInsn (Type .getType (fieldDesc ));
299+ if (leafProperty .hasConvertWith ()) {
300+ String convertWith = getInternalName (leafProperty .getConvertWith ());
301+ mv .visitTypeInsn (NEW , convertWith );
302+ mv .visitInsn (DUP );
303+ mv .visitMethodInsn (INVOKESPECIAL , convertWith , "<init>" , "()V" , false );
304+ } else {
305+ mv .visitLdcInsn (Type .getType (fieldDesc ));
306+ mv .visitMethodInsn (INVOKESTATIC , I_CONFIG_INSTANCE_BUILDER_IMPL , "getConverter" ,
307+ "(L" + I_CLASS + ";)L" + I_CONVERTER + ";" , false );
308+ }
288309 mv .visitMethodInsn (INVOKESTATIC , I_CONFIG_INSTANCE_BUILDER_IMPL , "convertValue" ,
289- "(L" + I_STRING + ";L" + I_CLASS + ";)L" + I_OBJECT + ";" , false );
310+ "(L" + I_STRING + ";L" + I_CONVERTER + ";)L" + I_OBJECT + ";" , false );
290311 mv .visitTypeInsn (CHECKCAST , getInternalName (property .getMethod ().getReturnType ()));
291312 mv .visitInsn (getReturnInstruction (property ));
292313 mv .visitMaxs (0 , 0 );
@@ -317,9 +338,18 @@ static byte[] generateBuilder(final ConfigMappingInterface mapping, final String
317338 null );
318339 LeafProperty optionalProperty = property .asLeaf ();
319340 mv .visitLdcInsn (property .getDefaultValue ());
320- mv .visitLdcInsn (Type .getType (getDescriptor (optionalProperty .getValueRawType ())));
341+ if (optionalProperty .hasConvertWith ()) {
342+ String convertWith = getInternalName (optionalProperty .getConvertWith ());
343+ mv .visitTypeInsn (NEW , convertWith );
344+ mv .visitInsn (DUP );
345+ mv .visitMethodInsn (INVOKESPECIAL , convertWith , "<init>" , "()V" , false );
346+ } else {
347+ mv .visitLdcInsn (Type .getType (getDescriptor (optionalProperty .getValueRawType ())));
348+ mv .visitMethodInsn (INVOKESTATIC , I_CONFIG_INSTANCE_BUILDER_IMPL , "getConverter" ,
349+ "(L" + I_CLASS + ";)L" + I_CONVERTER + ";" , false );
350+ }
321351 mv .visitMethodInsn (INVOKESTATIC , I_CONFIG_INSTANCE_BUILDER_IMPL , "convertOptionalValue" ,
322- "(L" + I_STRING + ";L" + I_CLASS + ";)L" + I_OPTIONAL + ";" , false );
352+ "(L" + I_STRING + ";L" + I_CONVERTER + ";)L" + I_OPTIONAL + ";" , false );
323353 mv .visitTypeInsn (CHECKCAST , getInternalName (property .getMethod ().getReturnType ()));
324354 mv .visitInsn (getReturnInstruction (property ));
325355 mv .visitMaxs (0 , 0 );
@@ -343,7 +373,18 @@ static byte[] generateBuilder(final ConfigMappingInterface mapping, final String
343373 mv .visitTypeInsn (NEW , I_CONFIG_INSTANCE_BUILDER_IMPL + "$MapWithDefault" );
344374 mv .visitInsn (DUP );
345375 mv .visitLdcInsn (mapProperty .getDefaultValue ());
346- // TODO - Miss Converter
376+ if (valueProperty .hasConvertWith ()) {
377+ String convertWith = getInternalName (valueProperty .asLeaf ().getConvertWith ());
378+ mv .visitTypeInsn (NEW , convertWith );
379+ mv .visitInsn (DUP );
380+ mv .visitMethodInsn (INVOKESPECIAL , convertWith , "<init>" , "()V" , false );
381+ } else {
382+ mv .visitLdcInsn (getType (valueProperty .asLeaf ().getValueRawType ()));
383+ mv .visitMethodInsn (INVOKESTATIC , I_CONFIG_INSTANCE_BUILDER_IMPL , "getConverter" ,
384+ "(L" + I_CLASS + ";)L" + I_CONVERTER + ";" , false );
385+ }
386+ mv .visitMethodInsn (INVOKESTATIC , I_CONFIG_INSTANCE_BUILDER_IMPL , "convertValue" ,
387+ "(L" + I_STRING + ";L" + I_CONVERTER + ";)L" + I_OBJECT + ";" , false );
347388 mv .visitMethodInsn (INVOKESPECIAL , I_CONFIG_INSTANCE_BUILDER_IMPL + "$MapWithDefault" , "<init>" ,
348389 "(L" + I_OBJECT + ";)V" , false );
349390 mv .visitInsn (getReturnInstruction (property ));
@@ -367,10 +408,19 @@ static byte[] generateBuilder(final ConfigMappingInterface mapping, final String
367408 mv .visitTypeInsn (NEW , I_CONFIG_INSTANCE_BUILDER_IMPL + "$MapWithDefault" );
368409 mv .visitInsn (DUP );
369410 mv .visitLdcInsn (mapProperty .getDefaultValue ());
370- mv .visitLdcInsn (Type .getType (getDescriptor (elementProperty .getValueRawType ())));
411+ if (elementProperty .hasConvertWith ()) {
412+ String convertWith = getInternalName (elementProperty .getConvertWith ());
413+ mv .visitTypeInsn (NEW , convertWith );
414+ mv .visitInsn (DUP );
415+ mv .visitMethodInsn (INVOKESPECIAL , convertWith , "<init>" , "()V" , false );
416+ } else {
417+ mv .visitLdcInsn (getType (elementProperty .getValueRawType ()));
418+ mv .visitMethodInsn (INVOKESTATIC , I_CONFIG_INSTANCE_BUILDER_IMPL , "getConverter" ,
419+ "(L" + I_CLASS + ";)L" + I_CONVERTER + ";" , false );
420+ }
371421 mv .visitLdcInsn (Type .getType (getDescriptor (collectionProperty .getCollectionRawType ())));
372422 mv .visitMethodInsn (INVOKESTATIC , I_CONFIG_INSTANCE_BUILDER_IMPL , "convertValues" ,
373- "(L" + I_STRING + ";L" + I_CLASS + ";L" + I_CLASS + ";)L" + I_COLLECTION + ";" , false );
423+ "(L" + I_STRING + ";L" + I_CONVERTER + ";L" + I_CLASS + ";)L" + I_COLLECTION + ";" , false );
374424 mv .visitMethodInsn (INVOKESPECIAL , I_CONFIG_INSTANCE_BUILDER_IMPL + "$MapWithDefault" , "<init>" ,
375425 "(L" + I_OBJECT + ";)V" , false );
376426 mv .visitInsn (getReturnInstruction (property ));
@@ -418,10 +468,19 @@ static byte[] generateBuilder(final ConfigMappingInterface mapping, final String
418468 MethodVisitor mv = visitor .visitMethod (ACC_PUBLIC | ACC_STATIC , defaultMethodName , "()" + fieldDesc , null ,
419469 null );
420470 mv .visitLdcInsn (elementProperty .getDefaultValue ());
421- mv .visitLdcInsn (Type .getType (getDescriptor (elementProperty .getValueRawType ())));
471+ if (elementProperty .hasConvertWith ()) {
472+ String convertWith = getInternalName (elementProperty .getConvertWith ());
473+ mv .visitTypeInsn (NEW , convertWith );
474+ mv .visitInsn (DUP );
475+ mv .visitMethodInsn (INVOKESPECIAL , convertWith , "<init>" , "()V" , false );
476+ } else {
477+ mv .visitLdcInsn (Type .getType (getDescriptor (elementProperty .getValueRawType ())));
478+ mv .visitMethodInsn (INVOKESTATIC , I_CONFIG_INSTANCE_BUILDER_IMPL , "getConverter" ,
479+ "(L" + I_CLASS + ";)L" + I_CONVERTER + ";" , false );
480+ }
422481 mv .visitLdcInsn (Type .getType (getDescriptor (collectionProperty .getCollectionRawType ())));
423482 mv .visitMethodInsn (INVOKESTATIC , I_CONFIG_INSTANCE_BUILDER_IMPL , "convertValues" ,
424- "(L" + I_STRING + ";L" + I_CLASS + ";L" + I_CLASS + ";)L" + I_COLLECTION + ";" , false );
483+ "(L" + I_STRING + ";L" + I_CONVERTER + ";L" + I_CLASS + ";)L" + I_COLLECTION + ";" , false );
425484 mv .visitTypeInsn (CHECKCAST , getInternalName (property .getMethod ().getReturnType ()));
426485 mv .visitInsn (getReturnInstruction (property ));
427486 mv .visitMaxs (0 , 0 );
@@ -432,7 +491,28 @@ static byte[] generateBuilder(final ConfigMappingInterface mapping, final String
432491 CollectionProperty collectionProperty = property .asOptional ().getNestedProperty ().asCollection ();
433492 LeafProperty elementProperty = collectionProperty .getElement ().asLeaf ();
434493 if (elementProperty .hasDefaultValue () && elementProperty .getDefaultValue () != null ) {
435- throw new UnsupportedOperationException ();
494+ generateGetterWithDefaullt = true ;
495+ // Default Method
496+ MethodVisitor mv = visitor .visitMethod (ACC_PUBLIC | ACC_STATIC , defaultMethodName , "()" + fieldDesc , null ,
497+ null );
498+ mv .visitLdcInsn (elementProperty .getDefaultValue ());
499+ if (elementProperty .hasConvertWith ()) {
500+ String convertWith = getInternalName (elementProperty .getConvertWith ());
501+ mv .visitTypeInsn (NEW , convertWith );
502+ mv .visitInsn (DUP );
503+ mv .visitMethodInsn (INVOKESPECIAL , convertWith , "<init>" , "()V" , false );
504+ } else {
505+ mv .visitLdcInsn (Type .getType (getDescriptor (elementProperty .getValueRawType ())));
506+ mv .visitMethodInsn (INVOKESTATIC , I_CONFIG_INSTANCE_BUILDER_IMPL , "getConverter" ,
507+ "(L" + I_CLASS + ";)L" + I_CONVERTER + ";" , false );
508+ }
509+ mv .visitLdcInsn (Type .getType (getDescriptor (collectionProperty .getCollectionRawType ())));
510+ mv .visitMethodInsn (INVOKESTATIC , I_CONFIG_INSTANCE_BUILDER_IMPL , "convertOptionalValues" ,
511+ "(L" + I_STRING + ";L" + I_CONVERTER + ";L" + I_CLASS + ";)L" + I_OPTIONAL + ";" , false );
512+ mv .visitTypeInsn (CHECKCAST , getInternalName (property .getMethod ().getReturnType ()));
513+ mv .visitInsn (getReturnInstruction (property ));
514+ mv .visitMaxs (0 , 0 );
515+ mv .visitEnd ();
436516 } else {
437517 // There is no default, but we initialize an empty Optional inline in field
438518 noArgsCtor .visitVarInsn (ALOAD , V_THIS );
@@ -459,6 +539,7 @@ static byte[] generateBuilder(final ConfigMappingInterface mapping, final String
459539 noArgsCtor .visitFieldInsn (PUTFIELD , builderClassName , memberName , "L" + I_OPTIONAL + ";" );
460540 }
461541
542+ // Getter
462543 MethodVisitor mv = visitor .visitMethod (ACC_PUBLIC , memberName , "()" + fieldDesc , null , null );
463544 if (generateGetterWithDefaullt ) {
464545 mv .visitVarInsn (ALOAD , V_THIS );
@@ -493,7 +574,6 @@ static byte[] generateBuilder(final ConfigMappingInterface mapping, final String
493574
494575 // Field Declaration
495576 String fieldDesc = getDescriptor (method .getReturnType ());
496- // TODO - Should it be public? And use field access to copy from the builder to the config class?
497577 visitor .visitField (ACC_PUBLIC , memberName , fieldDesc , null , null );
498578
499579 // Setter
0 commit comments