jira.codehaus.org

  • Log In Access more options
    • Online Help
    • Keyboard Shortcuts
    • About JIRA
    • JIRA Credits
    • What?s New
  • Dashboards Access more options (Alt+d)
  • Projects Access more options (Alt+p)
  • Issues Access more options (Alt+i)
  • QDox
  • QDOX-205

Expose Type.actualTypeArguments and add JavaClass.typeParameters

  • Log In
  • Views
    • XML
    • Word
    • Printable

Details

  • Type: Bug Bug
  • Status: Closed Closed
  • Priority: Major Major
  • Resolution: Fixed
  • Affects Version/s: 1.10.1
  • Fix Version/s: 1.11
  • Component/s: None
  • Labels:
    None

Description

I have two classes where first (GenericControllerImpl) is some generic purpose controller with common CRUD methods. Second class (GroupControllerImpl) extends parent to add some REST methods.
With QDox I can't resolve type variables from GenericControllerImpl. JavaClass returned after parsing GroupControllerImpl also has no parent class.

Code

Test code
JavaDocBuilder builder = new JavaDocBuilder();
        JavaSource source = builder.addSource(new File("GroupControllerImpl.java"));

        System.out.println(source.getClasses()[0].getParentClass());

        source = builder.addSource(new File("GenericControllerImpl.java"));
        System.out.println(source.getClasses()[0].getImplementedInterfaces()[0].asType());

Classes looks next:

GroupControllerImpl
package org.code_house.web;

import org.code_house.dataaccess.GroupDAO;
import org.code_house.domain.Group;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;

public class GroupControllerImpl extends
    GenericControllerImpl<Group, Long, GroupDAO> {

    @Autowired
    public void setUserDao(GroupDAO dao) {
        this.dao = dao;
    }

    @RequestMapping("/x")
    @ModelAttribute("test")
    public Boolean doSomething() {
        return null;
    }
}
GenericControllerImpl.java
package org.code_house.web;

import java.util.List;

import org.code_house.dataaccess.GenericDAO;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;


public abstract class GenericControllerImpl<T, K, D extends GenericDAO<T, K>>
    implements GenericController<T, K>, InitializingBean {

    protected D dao;

    @RequestMapping
    public T create(@RequestBody T object) {
        dao.create(object);
        return object;
    }

    @RequestMapping
    public Boolean update(@PathVariable K id, @RequestBody T object) {
        dao.update(object);
        return true;
    }

    @RequestMapping
    public T read(@PathVariable K id) {
        return dao.readById(id);
    }

    @RequestMapping
    public Boolean remove(@PathVariable K id) {
        return dao.deleteById(id);
    }

    @RequestMapping
    public List<T> getAllRecords() {
        return dao.getAll();
    }

    public void afterPropertiesSet() {
        Assert.notNull(dao);
    }
}

Activity

Ascending order - Click to sort in descending order
  • All
  • Comments
  • Work Log
  • History
  • Activity
Hide
Permalink
Robert Scholte added a comment - 05/Mar/10 9:53 AM

getParentClass() is used for innerClasses. You'll have to use getSuperClass() to get it's ... well, super class.
Hope this will solve your problem.

Show
Robert Scholte added a comment - 05/Mar/10 9:53 AM getParentClass() is used for innerClasses. You'll have to use getSuperClass() to get it's ... well, super class. Hope this will solve your problem.
Hide
Permalink
Lukasz Dywicki added a comment - 05/Mar/10 10:26 AM

Robert - yes you answer resolved first problem - the getSuperClass returns correct type with generic information.. After your response I also found resolution of no generic information about implemented interfaces in "GenericControllerImpl":

source = builder.addSource(new File("GenericControllerImpl.java"));
System.out.println(source.getClasses()[0].getImplements()[0].asType()); // Type contains actualArgumentTypes

The problem I still have is type level variables - to get this kind of information from Type I have to access actualArgumentTypes in Type class:

Field declaredField = tz.getClass().getDeclaredField("actualArgumentTypes");
declaredField.setAccessible(true);
return (Type[]) declaredField.get(tz);

Is there any other way of getting this stuff?

Second thing is - how to get generic class type variables? Code below don't contain any information about generic declaration and I can't find any method in JavaClass to check if class is generic.

source = builder.addSource(new File("GenericController.java"));
source.getClasses()[0].asType().getGenericValue();

Regards,
Lukasz

Show
Lukasz Dywicki added a comment - 05/Mar/10 10:26 AM Robert - yes you answer resolved first problem - the getSuperClass returns correct type with generic information.. After your response I also found resolution of no generic information about implemented interfaces in "GenericControllerImpl":
source = builder.addSource(new File("GenericControllerImpl.java"));
System.out.println(source.getClasses()[0].getImplements()[0].asType()); // Type contains actualArgumentTypes
The problem I still have is type level variables - to get this kind of information from Type I have to access actualArgumentTypes in Type class:
Field declaredField = tz.getClass().getDeclaredField("actualArgumentTypes");
declaredField.setAccessible(true);
return (Type[]) declaredField.get(tz);
Is there any other way of getting this stuff? Second thing is - how to get generic class type variables? Code below don't contain any information about generic declaration and I can't find any method in JavaClass to check if class is generic.
source = builder.addSource(new File("GenericController.java"));
source.getClasses()[0].asType().getGenericValue();
Regards, Lukasz
Hide
Permalink
Robert Scholte added a comment - 05/Mar/10 11:05 AM

The actualArgumentTypes are used to build the genericValue, as String representing of this Type. I haven't thought of a reason to expose these types, but if it's required I'm willing to do so.
I guess I should try to follow the java-api and just use the methodname used with ParameterizedType
I think after that you'll have all the access required, right?

Show
Robert Scholte added a comment - 05/Mar/10 11:05 AM The actualArgumentTypes are used to build the genericValue, as String representing of this Type. I haven't thought of a reason to expose these types, but if it's required I'm willing to do so. I guess I should try to follow the java-api and just use the methodname used with ParameterizedType I think after that you'll have all the access required, right?
Hide
Permalink
Robert Scholte added a comment - 09/Mar/10 5:03 AM

Lukasz,

I've just deployed a snapshot to http://snapshots.repository.codehaus.org/. Could you confirm that this is what you requested.

Show
Robert Scholte added a comment - 09/Mar/10 5:03 AM Lukasz, I've just deployed a snapshot to http://snapshots.repository.codehaus.org/. Could you confirm that this is what you requested.
Hide
Permalink
Lukasz Dywicki added a comment - 09/Mar/10 7:37 AM - edited

Robert thank you for helping me,
Snapshot version works well. I can get information about parameters.

Class are declared as below:

class GenericControllerImpl<T, K, D extends GenericDAO<T, K>>
    implements GenericController<T, K>
	
class GroupControllerImpl extends
    GenericControllerImpl<Group, Long, GroupDAO>
	
interface GenericController<T, K>

And following code prints

source = builder.addSource(new File(path + "GenericControllerImpl.java"));
Type type = source.getClasses()[0].asType();
// prints 'org.code_house.web.GenericControllerImpl' 
System.out.println(type.toGenericString());

type = source.getClasses()[0].getImplements()[0];
// prints 'GenericController<T,K>'
System.out.println(type.toGenericString());

I can't get declared parameters in class. The actual parameters are resolved correctly but we don't have access to type parameters - in that case I can't determine with parameters where should be bound.

I can get following information:
Class GenericControllerImpl implements interface GenericController with parameters T, K.
but I also need information:
Class GenericControllerImpl are declared with parameters T, K, D.
If I'll get this information I can do something more:
Class GroupControllerImpl provides following parameters: Group (T), Long (L), GroupDAO (D). The parameters Group (T), Long (K) are passed to GenericController mapped to T, K.

It is possible to obtain this information using current code base?

Show
Lukasz Dywicki added a comment - 09/Mar/10 7:37 AM - edited Robert thank you for helping me, Snapshot version works well. I can get information about parameters. Class are declared as below:
class GenericControllerImpl<T, K, D extends GenericDAO<T, K>>
    implements GenericController<T, K>
	
class GroupControllerImpl extends
    GenericControllerImpl<Group, Long, GroupDAO>
	
interface GenericController<T, K>
And following code prints
source = builder.addSource(new File(path + "GenericControllerImpl.java"));
Type type = source.getClasses()[0].asType();
// prints 'org.code_house.web.GenericControllerImpl' 
System.out.println(type.toGenericString());

type = source.getClasses()[0].getImplements()[0];
// prints 'GenericController<T,K>'
System.out.println(type.toGenericString());
I can't get declared parameters in class. The actual parameters are resolved correctly but we don't have access to type parameters - in that case I can't determine with parameters where should be bound. I can get following information: Class GenericControllerImpl implements interface GenericController with parameters T, K. but I also need information: Class GenericControllerImpl are declared with parameters T, K, D. If I'll get this information I can do something more: Class GroupControllerImpl provides following parameters: Group (T), Long (L), GroupDAO (D). The parameters Group (T), Long (K) are passed to GenericController mapped to T, K. It is possible to obtain this information using current code base?
Hide
Permalink
Robert Scholte added a comment - 09/Mar/10 11:23 AM

Lukasz,

I noticed we only provided typeParameters for methods, not for classes yet. I've added them, you should be able to access them by calling JavaClass.getTypeParameters().
Another snapshot deployed, ready to be reviewed.

btw, I changed the title of this issue: it didn't cover the real issue.

Show
Robert Scholte added a comment - 09/Mar/10 11:23 AM Lukasz, I noticed we only provided typeParameters for methods, not for classes yet. I've added them, you should be able to access them by calling JavaClass.getTypeParameters(). Another snapshot deployed, ready to be reviewed. btw, I changed the title of this issue: it didn't cover the real issue.
Hide
Permalink
Lukasz Dywicki added a comment - 10/Mar/10 5:17 AM

Robert,
I built code from sources - everything works.
I would notice that getValue method in TypeVariable can throw NullPointerException - the bounds field are not always initialized.

Thank you very much for working on this issue.
Best regards,
Lukasz Dywicki

Show
Lukasz Dywicki added a comment - 10/Mar/10 5:17 AM Robert, I built code from sources - everything works. I would notice that getValue method in TypeVariable can throw NullPointerException - the bounds field are not always initialized. Thank you very much for working on this issue. Best regards, Lukasz Dywicki

People

  • Assignee:
    Robert Scholte
    Reporter:
    Lukasz Dywicki
Vote (0)
Watch (0)

Dates

  • Created:
    05/Mar/10 3:54 AM
    Updated:
    10/Mar/10 5:23 AM
    Resolved:
    10/Mar/10 5:23 AM
  • Atlassian JIRA (v5.0.4#731-sha1:3aa7374)
  • Report a problem
  • Powered by a free Atlassian JIRA open source license for Codehaus. Try JIRA - bug tracking software for your team.