Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEATURE] Add a typed field info metadata #3297

Open
goncharovae opened this issue Nov 15, 2022 · 1 comment
Open

[FEATURE] Add a typed field info metadata #3297

goncharovae opened this issue Nov 15, 2022 · 1 comment

Comments

@goncharovae
Copy link

Background

I was pondering the idea of being able to imeplement a type-safe way to modify/query POJO classes.

The closest example is JPA Static Metamodel

Having such meta model allows not only to ensure that a given field exists, but also that the given value corresponds the field type.

The problem with that tool is that it's JPA specific. The need for such type-safe API is useful if we want to have a generic way to query/modify typed data, not necessarily in the context of the relational database (or any database).

Description

Let's say I have this class

@Data
public class Project {

    private Integer id;
    private String name;
    private Set<User> users;
    private Date createdAt;
}

By adding an annotation (let's say @Metamodel), it could produce this code:

@Data
class Project {

    private Integer id;
    private String name;
    private Set<User> users;
    private Date createdAt;

    public static class TypedFields<F> {

        private final String _name;

        private TypedFields(String name) {
            this._name = name;
        }

        public String toString() {
            return _name;
        }

        public final static TypedFields<Integer> id = new TypedFields<>("id");
        public final static TypedFields<String> name = new TypedFields<>("name");
        public final static TypedFields<Set<User>> users = new TypedFields<>("users");
        public final static TypedFields<Date> createdAt = new TypedFields<>("createdAt");
    }
}

Now let's say I want to implement a generic method to query data from whatever storage:

public <E, F> E findEntityByField(Class<E> type, EntityAttribute<E, F> attribute, F fieldValue) {}

Provided I have my EntityAttribute type declared like this:

interface EntityAttribute<E, F> {} // E - entity type, F - field type

and provided I changed my Project declaration to this:

@Data
@Metamodel
public class Project {

    private Integer id;
    private String name;
    private Set<User> users;
    private Date createdAt;
    
    public static class TypedFields<F> implements EntityAttribute<Project, F> {}
}

(assuming TypedFields get the same handling as Fields from @FieldNameContants),

I can now use my generic method in a fully type-safe way like this:

Project project = findByField(Project.class, Project.TypedFields.id, 5);

Target audience

Any back-end engineer who needs to implement a generic data querying/modifying/deserialization might find this useful.

Notes

Instead of requiring to declare TypedFields explicitly to make it implement a certain interface could be done via an annotation parameter (e.g. baseType = EntityAttribute.class)
Instead of making TypeFields implement toString() to return the field name, it could implement a method like getFieldName().
Also TypedFields could include the actual Class info and provide getFieldType() method since it might be useful for various generic implementations too.
More configuration options could be added to use accessor methods instead of fields, skip fields based on modifiers, etc.

Additional context

I stumbled upon this similar issue - #2496
It was closed as being covered by @FieldNameConstants. The case the author described there is indeed covered by @FieldNameConstants even though the original intent was probably more closer to this proposal.

@reggie-pierce-impilo
Copy link

I’ll second this. Having type info would be very helpful when handling patch requests to a server

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants