Created
May 14, 2021 18:53
-
-
Save MikeDombo/49b410f9561451a3a96f72322e4308f0 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | |
* SPDX-License-Identifier: Apache-2.0 | |
*/ | |
package com.fasterxml.jackson.jr.ob.impl; | |
import com.amazon.aws.iot.greengrass.JsonBuilder; | |
import com.fasterxml.jackson.core.JsonParser; | |
import com.fasterxml.jackson.jr.ob.JSONObjectException; | |
import java.io.IOException; | |
import java.lang.reflect.InvocationTargetException; | |
import java.lang.reflect.Method; | |
import java.util.Arrays; | |
import java.util.NoSuchElementException; | |
import java.util.Optional; | |
public class LombokBuilderBeanReader extends BeanReader { | |
private final Optional<Class<?>> builderClass; | |
private final Optional<Method> builderMethod; | |
private final Optional<Method> buildMethod; | |
public LombokBuilderBeanReader(Class<?> type, BeanReader defaultReader) { | |
super(type, defaultReader._propsByName, defaultReader._defaultCtor, defaultReader._stringCtor, | |
defaultReader._longCtor, defaultReader._ignorableNames, defaultReader._aliasMapping); | |
// To use Lombok builder for deserialization, the builder must be annotated with @JsonBuilder | |
builderClass = | |
Arrays.stream(_valueType.getDeclaredClasses()) | |
.filter(a -> a.getAnnotation(JsonBuilder.class) != null) | |
.findFirst(); | |
builderMethod = builderClass.flatMap(builderClass -> Arrays.stream(_valueType.getDeclaredMethods()) | |
.filter(m -> m.getName().equals("builder") && m.getParameterCount() == 0) | |
.findFirst()); | |
buildMethod = builderClass.flatMap(builderClass -> Arrays.stream(builderClass.getDeclaredMethods()) | |
.filter(n -> n.getName().equals("build") && n.getParameterCount() == 0) | |
.findFirst()); | |
} | |
@Override | |
public BeanPropertyReader findProperty(String name) { | |
return wrapReader(super.findProperty(name)); | |
} | |
private BeanPropertyReader wrapReader(BeanPropertyReader beanPropertyReader) { | |
if (beanPropertyReader == null) { | |
return beanPropertyReader; | |
} | |
if (builderClass.isPresent()) { | |
Method setter; | |
try { | |
// Find builder setter for the type or any super type | |
setter = Arrays.stream(builderClass.get().getDeclaredMethods()) | |
.filter(n -> n.getName().equals(beanPropertyReader.getName()) && n.getParameterCount() == 1 && n | |
.getParameterTypes()[0].isAssignableFrom(beanPropertyReader.rawSetterType())) | |
.findFirst().get(); | |
} catch (NoSuchElementException e) { | |
try { | |
setter = builderClass.get().getDeclaredMethod(beanPropertyReader.getName(), String.class); | |
} catch (NoSuchMethodException ex) { | |
return beanPropertyReader; | |
} | |
} | |
return new BeanPropertyReader(beanPropertyReader.getName(), null, setter) | |
.withReader(beanPropertyReader.getReader()); | |
} | |
return beanPropertyReader; | |
} | |
@Override | |
protected Object create() throws Exception { | |
if (builderClass.isPresent() && builderMethod.isPresent()) { | |
return builderMethod.get().invoke(null, (Object[]) null); | |
} | |
return super.create(); | |
} | |
@Override | |
public Object readNext(JSONReader r, JsonParser p) throws IOException { | |
Object b = super.readNext(r, p); | |
return runBuildOnBuilder(p, b); | |
} | |
@Override | |
public Object read(JSONReader reader, JsonParser p) throws IOException { | |
Object b = super.read(reader, p); | |
return runBuildOnBuilder(p, b); | |
} | |
private Object runBuildOnBuilder(JsonParser p, Object b) throws IOException { | |
if (b == null) { | |
return b; | |
} | |
if (buildMethod.isPresent()) { | |
try { | |
return buildMethod.get().invoke(b, (Object[]) null); | |
} catch (InvocationTargetException | IllegalAccessException e) { | |
throw JSONObjectException.from(p, e.getCause() == null ? e : e.getCause(), | |
e.getCause() == null ? e.getMessage() : e.getCause().getMessage()); | |
} | |
} | |
return b; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment