package io.gitlab.jfronny.gson.compile.processor.util.valueprocessor; import org.jetbrains.annotations.ApiStatus; import javax.lang.model.element.*; import javax.lang.model.type.TypeKind; import javax.lang.model.type.TypeMirror; import java.util.List; public abstract sealed class Property { protected final T element; private List annotations; public Property(T element) { this.element = element; this.annotations = element.getAnnotationMirrors(); } public T getElement() { return element; } /** * The name of the property. For fields and params this is the name in code. For getters, it may have the 'get' or * 'is' prefix stripped. * @see #getCallableName() */ public String getName() { return element.getSimpleName().toString(); } /** * The actual name of the property. This will not have any 'get' or 'is' prefix stripped. * @see #getName() */ public String getCallableName() { return getName(); } /** * The property's type. */ public TypeMirror getType() { return element.asType(); } /** * Annotations relevant to the property. These may be copied from another source. For example, if this is a getter * it may contain the annotations on the backing private field. */ public List getAnnotations() { return annotations; } public void setAnnotations(List annotations) { this.annotations = annotations; } @Override public String toString() { return getName() + ": " + getType(); } @Override public boolean equals(Object obj) { if (obj == null) return false; if (this == obj) return true; if (!(obj instanceof Property other)) return false; return element.equals(other.element); } @Override public int hashCode() { return element.hashCode(); } public static final class Field extends Property { public Field(VariableElement element) { super(element); } } public static final class Getter extends Property { private static final String BEAN_PREFIX = "get"; private static final String BEAN_PREFIX_BOOL = "is"; private boolean stripBean = false; public Getter(ExecutableElement element) { super(element); } public boolean isBean() { return getBeanPrefix() != null; } @Override public String getName() { String name = super.getName(); if (stripBean) { String prefix = getBeanPrefix(); if (prefix != null) { return Character.toLowerCase(name.charAt(prefix.length())) + name.substring(prefix.length() + 1); } } return name; } @Override public String getCallableName() { return super.getName(); } @Override public TypeMirror getType() { return element.getReturnType(); } @ApiStatus.Internal public void stripBean() { stripBean = true; } private String getBeanPrefix() { String name = super.getName(); if (element.getReturnType().getKind() == TypeKind.BOOLEAN) { if (name.length() > BEAN_PREFIX_BOOL.length() && name.startsWith(BEAN_PREFIX_BOOL)) { return BEAN_PREFIX_BOOL; } } return name.length() > BEAN_PREFIX.length() && name.startsWith(BEAN_PREFIX) ? BEAN_PREFIX : null; } } public static sealed abstract class Param extends Property { public Param(VariableElement element) { super(element); } } public static final class ConstructorParam extends Param { public ConstructorParam(VariableElement element) { super(element); } } public static final class BuilderParam extends Param { private final ExecutableElement method; public BuilderParam(ExecutableElement method) { super(method.getParameters().get(0)); this.method = method; } @Override public String getCallableName() { return method.getSimpleName().toString(); } } }