NIHVIVO-3746 Permit DataGetter classes to have 4 different types of constructor - make reflection logic more rigorous to avoid NoSuchMethodException.

This commit is contained in:
j2blake 2012-05-02 17:04:24 +00:00
parent 18e171e1b9
commit a26f0c2809
6 changed files with 55 additions and 30 deletions

View file

@ -28,7 +28,7 @@ public class HomePageController extends FreemarkerHttpServlet {
Map<String, Object> body = new HashMap<String, Object>();
List<DataGetter> dgList = DataGetterUtils.getDataGettersForPage(vreq.getDisplayModel(), DisplayVocabulary.HOME_PAGE_URI);
List<DataGetter> dgList = DataGetterUtils.getDataGettersForPage(vreq, vreq.getDisplayModel(), DisplayVocabulary.HOME_PAGE_URI);
for( DataGetter dg : dgList){
Map<String,Object> moreData = dg.getData(getServletContext(),vreq,body);

View file

@ -282,7 +282,7 @@ public class MenuManagementController extends FreemarkerHttpServlet {
try{
String className = DataGetterUtils.getJClassForDataGetterURI(displayModel, dataGetterURI);
//TODO: Change so that instantiation here occurs correctly <-- how should data getter be instantiated
DataGetter pg = DataGetterUtils.dataGetterForURI(vreq.getDisplayModel(), dataGetterURI);
DataGetter pg = DataGetterUtils.dataGetterForURI(vreq, vreq.getDisplayModel(), dataGetterURI);
//TODO: Check template data variable and what that is?
Map<String, Object> pageData = pg.getData(getServletContext(), vreq, templateData);
//Map<String, Object> pageInfo = vreq.getWebappDaoFactory().getPageDao().getPage(pageURI);

View file

@ -23,7 +23,6 @@ import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.Tem
import edu.cornell.mannlib.vitro.webapp.dao.DisplayVocabulary;
import edu.cornell.mannlib.vitro.webapp.utils.dataGetter.DataGetter;
import edu.cornell.mannlib.vitro.webapp.utils.dataGetter.DataGetterUtils;
import edu.cornell.mannlib.vitro.webapp.utils.pageDataGetter.PageDataGetterUtils;
/**
* Controller for getting data for pages defined in the display model.
*
@ -78,7 +77,7 @@ public class PageController extends FreemarkerHttpServlet{
private void executeDataGetters(String pageUri, VitroRequest vreq, ServletContext context, Map<String, Object> mapForTemplate)
throws Exception {
List<DataGetter> dgList = DataGetterUtils.getDataGettersForPage(vreq.getDisplayModel(), pageUri);
List<DataGetter> dgList = DataGetterUtils.getDataGettersForPage(vreq, vreq.getDisplayModel(), pageUri);
for( DataGetter dg : dgList){
Map<String,Object> moreData = dg.getData(context,vreq,mapForTemplate);

View file

@ -59,14 +59,14 @@ public class DataGetterUtils {
* This should not return PageDataGetters and should not throw an
* exception if a page has PageDataGetters.
*/
public static List<DataGetter> getDataGettersForPage( Model displayModel, String pageURI)
public static List<DataGetter> getDataGettersForPage( VitroRequest vreq, Model displayModel, String pageURI)
throws InstantiationException, IllegalAccessException, ClassNotFoundException, IllegalArgumentException, SecurityException, InvocationTargetException, NoSuchMethodException{
//get data getter uris for pageURI
List<String> dgUris = getDataGetterURIsForPageURI( displayModel, pageURI);
List<DataGetter> dgList = new ArrayList<DataGetter>();
for( String dgURI: dgUris){
DataGetter dg =dataGetterForURI(displayModel, dgURI) ;
DataGetter dg =dataGetterForURI(vreq, displayModel, dgURI) ;
if( dg != null )
dgList.add(dg);
}
@ -83,7 +83,7 @@ public class DataGetterUtils {
* This should not throw an exception if the URI exists and has a type
* that does not implement the DataGetter interface.
*/
public static DataGetter dataGetterForURI(Model displayModel, String dataGetterURI)
public static DataGetter dataGetterForURI(VitroRequest vreq, Model displayModel, String dataGetterURI)
throws InstantiationException, IllegalAccessException, ClassNotFoundException, IllegalArgumentException, InvocationTargetException, SecurityException, NoSuchMethodException
{
//get java class for dataGetterURI
@ -95,26 +95,42 @@ public class DataGetterUtils {
log.debug("Class doesn't implement DataGetter: '" + dgClassName + "'");
return null;
}
@SuppressWarnings("unchecked")
Class<DataGetter> dgClass = (Class<DataGetter>) clz;
Constructor<DataGetter> ct = null;
// we want a constructor that will work for one of these argument lists (in this order)
Object[][] argLists = new Object[][] {
{ vreq, displayModel, dataGetterURI },
{ displayModel, dataGetterURI },
{ vreq },
{}
};
ct = dgClass.getConstructor(Model.class, String.class);
if (ct != null) {
log.debug("Using this constructor: " + ct);
return ct.newInstance(displayModel, dataGetterURI);
}
ct = dgClass.getConstructor();
if (ct != null) {
log.debug("Using this constructor: " + ct);
return ct.newInstance();
// look through the available constructors for the best fit
for (Object[] argList: argLists) {
for (Constructor<?> ct: clz.getConstructors()) {
if (isConstructorSuitableForArguments(ct, argList)) {
log.debug("Using this constructor: " + ct);
return (DataGetter) ct.newInstance(argList);
}
}
}
log.debug("Didn't find a suitable constructor for '" + dgClassName + "'");
return null;
}
private static boolean isConstructorSuitableForArguments(Constructor<?> ct, Object[] args) {
Class<?>[] parameterTypes = ct.getParameterTypes();
if (args.length != parameterTypes.length) {
return false;
}
for (int i = 0; i < args.length; i++) {
Class<? extends Object> argClass = args[i].getClass();
if (! parameterTypes[i].isAssignableFrom(argClass)) {
return false;
}
}
return true;
}
public static String getJClassForDataGetterURI(Model displayModel, String dataGetterURI) throws IllegalAccessException {
String query = prefixes +
@ -390,11 +406,11 @@ public class DataGetterUtils {
* @throws IllegalAccessException
* @throws InstantiationException
*/
public static JSONObject covertDataToJSONForPage(String pageUri, Model displayModel) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
public static JSONObject covertDataToJSONForPage(VitroRequest vreq, String pageUri, Model displayModel) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
//Get PageDataGetter types associated with pageUri
JSONObject rObj = null;
try{
List<DataGetter> dataGetters = getDataGettersForPage(displayModel, pageUri);
List<DataGetter> dataGetters = getDataGettersForPage(vreq, displayModel, pageUri);
for(DataGetter getter: dataGetters) {
JSONObject typeObj = null;
try{