mercredi 2 janvier 2019

Accessing generic class members and get class type in java

I am trying to create a generic DAO class for my graph nodes in neo4j. I have multiple graph nodes class. One of which looks like this

import org.neo4j.ogm.annotation.GeneratedValue;
import org.neo4j.ogm.annotation.Id;
import org.neo4j.ogm.annotation.Relationship;

public class Skill {
    @Id @GeneratedValue
    private Long id;
    private String Name;
    private String CleanedText;
    public final static String GraphIdentifier = "skill-ontology";

    @Relationship(type = "BelongsTo", direction = Relationship.OUTGOING)
    private Set<SkillSubCluster> belongsTo = new HashSet<>();

    public Long getId() {
        return id;
    }

    public String getName() {
        return Name;
    }

    public String getCleanedText() {
        return CleanedText;
    }
}

and my GenericDAO class is -

public class NodeDAO<T> {
    private static final int DEPTH_LIST = 0;
    private static final int DEPTH_ENTITY = 1;
    final Class<T> typeParameterClass;
    private Session session;

    public NodeDAO(Session session, Class<T> typeParameterClass) {
        this.session = session;
        this.typeParameterClass = typeParameterClass;
    }

    public NodeDAO(Session session) {
        this.session = session;
        this.typeParameterClass = getEntityClass();
    }

    public Class<T> getEntityClass() {
        ParameterizedType parameterizedType = (ParameterizedType) getClass()
                .getGenericSuperclass();

        @SuppressWarnings("unchecked")
        Class<T> ret = (Class<T>) parameterizedType.getActualTypeArguments()[0];

        return ret;
    }


    protected Class<T> getEntityType() {
        return (Class<T>) this.typeParameterClass;

    }

    public Iterable<T> findAll() {
        return session.loadAll(getEntityType(), DEPTH_LIST);
    }

    // rest of the implementation
}

and then I have my manager class thats responsible for making connections to multiple graph instances whose one method is -

public <T> NodeDAO<T> getGraphNodeDAO(String graphDBIdentifier, Class<T> typeParameterClass){   

        // graphSessions is a hashmap<String, Session> storing multiple neo4j instances sessions. A session is identified by a graphDBIdentifier string
        Session session = graphSessions.get(graphDBIdentifier);
        // This works
        NodeDAO<T> nodeDAO = new NodeDAO<T>(session, typeParameterClass);
        //NodeDAO<T> nodeDAO = new NodeDAO<T>(session);
        return nodeDAO;
    }

This method is called for getting the DAO object for a given graph node

NodeDAO<Skill> skillNodeDAO = manager.getGraphNodeDAO(Skill.GraphIdentifier, Skill.class); 

The code works fine, but I want to the manager class getGraphNodeDAO method to automatically know which session to load based on the class passes (based on the class variable GraphIdentifier of Skill class) and NodeDAO class to automatically identify the class type on its own with the need of explicitly passing it.

Invoking NodeDAO<T> nodeDAO = new NodeDAO<T>(session); throws the following error

Exception in thread "main" java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType





Aucun commentaire:

Enregistrer un commentaire