From a26f0c28097f969d54d041526a9e3374dfbce305 Mon Sep 17 00:00:00 2001 From: j2blake Date: Wed, 2 May 2012 17:04:24 +0000 Subject: [PATCH] NIHVIVO-3746 Permit DataGetter classes to have 4 different types of constructor - make reflection logic more rigorous to avoid NoSuchMethodException. --- .../freemarker/HomePageController.java | 2 +- .../freemarker/MenuManagementController.java | 2 +- .../controller/freemarker/PageController.java | 3 +- .../utils/dataGetter/DataGetterUtils.java | 52 ++++++++++++------- .../utils/dataGetter/DataGetterUtilsTest.java | 16 +++--- .../dataGetter/SparqlQueryDataGetterTest.java | 10 +++- 6 files changed, 55 insertions(+), 30 deletions(-) diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/HomePageController.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/HomePageController.java index ea05b1418..0372725fd 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/HomePageController.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/HomePageController.java @@ -28,7 +28,7 @@ public class HomePageController extends FreemarkerHttpServlet { Map body = new HashMap(); - List dgList = DataGetterUtils.getDataGettersForPage(vreq.getDisplayModel(), DisplayVocabulary.HOME_PAGE_URI); + List dgList = DataGetterUtils.getDataGettersForPage(vreq, vreq.getDisplayModel(), DisplayVocabulary.HOME_PAGE_URI); for( DataGetter dg : dgList){ Map moreData = dg.getData(getServletContext(),vreq,body); diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/MenuManagementController.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/MenuManagementController.java index 369cbb66f..d62f2e91f 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/MenuManagementController.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/MenuManagementController.java @@ -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 pageData = pg.getData(getServletContext(), vreq, templateData); //Map pageInfo = vreq.getWebappDaoFactory().getPageDao().getPage(pageURI); diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/PageController.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/PageController.java index 6c72b3d75..5db8c7b1a 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/PageController.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/PageController.java @@ -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 mapForTemplate) throws Exception { - List dgList = DataGetterUtils.getDataGettersForPage(vreq.getDisplayModel(), pageUri); + List dgList = DataGetterUtils.getDataGettersForPage(vreq, vreq.getDisplayModel(), pageUri); for( DataGetter dg : dgList){ Map moreData = dg.getData(context,vreq,mapForTemplate); diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/DataGetterUtils.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/DataGetterUtils.java index 6e2013d4f..8edb7bd0f 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/DataGetterUtils.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/DataGetterUtils.java @@ -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 getDataGettersForPage( Model displayModel, String pageURI) + public static List getDataGettersForPage( VitroRequest vreq, Model displayModel, String pageURI) throws InstantiationException, IllegalAccessException, ClassNotFoundException, IllegalArgumentException, SecurityException, InvocationTargetException, NoSuchMethodException{ //get data getter uris for pageURI List dgUris = getDataGetterURIsForPageURI( displayModel, pageURI); List dgList = new ArrayList(); 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 dgClass = (Class) clz; - Constructor 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 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 dataGetters = getDataGettersForPage(displayModel, pageUri); + List dataGetters = getDataGettersForPage(vreq, displayModel, pageUri); for(DataGetter getter: dataGetters) { JSONObject typeObj = null; try{ diff --git a/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/DataGetterUtilsTest.java b/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/DataGetterUtilsTest.java index 0f4749f7c..3c03fd856 100644 --- a/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/DataGetterUtilsTest.java +++ b/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/DataGetterUtilsTest.java @@ -1,8 +1,6 @@ /* $This file is distributed under the terms of the license in /doc/license.txt$ */ package edu.cornell.mannlib.vitro.webapp.utils.dataGetter; -import static org.junit.Assert.fail; - import java.io.InputStream; import java.lang.reflect.InvocationTargetException; import java.util.List; @@ -13,6 +11,8 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import stubs.javax.servlet.http.HttpServletRequestStub; + import com.hp.hpl.jena.ontology.OntModel; import com.hp.hpl.jena.ontology.OntModelSpec; import com.hp.hpl.jena.rdf.model.Model; @@ -20,10 +20,12 @@ import com.hp.hpl.jena.rdf.model.ModelFactory; import com.hp.hpl.jena.rdf.model.impl.RDFDefaultErrorHandler; import edu.cornell.mannlib.vitro.testing.AbstractTestClass; +import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; public class DataGetterUtilsTest extends AbstractTestClass{ OntModel displayModel; + VitroRequest vreq; String testDataGetterURI_1 = "http://vitro.mannlib.cornell.edu/ontologies/display/1.1#query1data"; String pageURI_1 = "http://vitro.mannlib.cornell.edu/ontologies/display/1.1#SPARQLPage"; String pageX = "http://vitro.mannlib.cornell.edu/ontologies/display/1.1#pageX"; @@ -38,6 +40,8 @@ public class DataGetterUtilsTest extends AbstractTestClass{ InputStream in = DataGetterUtilsTest.class.getResourceAsStream("resources/dataGetterTest.n3"); model.read(in,"","N3"); displayModel = ModelFactory.createOntologyModel(OntModelSpec.OWL_DL_MEM,model); + + vreq = new VitroRequest(new HttpServletRequestStub()); } @Test @@ -50,14 +54,14 @@ public class DataGetterUtilsTest extends AbstractTestClass{ @Test public void testDataGetterForURI() throws IllegalArgumentException, SecurityException, InstantiationException, IllegalAccessException, ClassNotFoundException, InvocationTargetException, NoSuchMethodException { - DataGetter dg = DataGetterUtils.dataGetterForURI(displayModel, testDataGetterURI_1); + DataGetter dg = DataGetterUtils.dataGetterForURI(vreq, displayModel, testDataGetterURI_1); Assert.assertNotNull(dg); } @Test public void testGetDataGettersForPage() throws IllegalArgumentException, SecurityException, InstantiationException, IllegalAccessException, ClassNotFoundException, InvocationTargetException, NoSuchMethodException { List dgList = - DataGetterUtils.getDataGettersForPage(displayModel, pageURI_1); + DataGetterUtils.getDataGettersForPage(vreq, displayModel, pageURI_1); Assert.assertNotNull(dgList); Assert.assertTrue("List of DataGetters was empty, it should not be.", dgList.size() > 0); } @@ -65,11 +69,11 @@ public class DataGetterUtilsTest extends AbstractTestClass{ @Test public void testNonPageDataGetter() throws IllegalArgumentException, SecurityException, InstantiationException, IllegalAccessException, ClassNotFoundException, InvocationTargetException, NoSuchMethodException{ - DataGetter dg = DataGetterUtils.dataGetterForURI(displayModel,dataGetterX); + DataGetter dg = DataGetterUtils.dataGetterForURI(vreq, displayModel,dataGetterX); Assert.assertNull(dg); List dgList = - DataGetterUtils.getDataGettersForPage(displayModel, pageX); + DataGetterUtils.getDataGettersForPage(vreq, displayModel, pageX); Assert.assertNotNull(dgList); Assert.assertTrue("List should be, it was not", dgList.size() == 0); } diff --git a/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/SparqlQueryDataGetterTest.java b/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/SparqlQueryDataGetterTest.java index b0801f78d..6dd1dc7e4 100644 --- a/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/SparqlQueryDataGetterTest.java +++ b/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/SparqlQueryDataGetterTest.java @@ -12,6 +12,8 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import stubs.javax.servlet.http.HttpServletRequestStub; + import com.hp.hpl.jena.ontology.OntModel; import com.hp.hpl.jena.ontology.OntModelSpec; import com.hp.hpl.jena.rdf.model.Model; @@ -21,6 +23,7 @@ import com.hp.hpl.jena.rdf.model.impl.RDFDefaultErrorHandler; import com.hp.hpl.jena.vocabulary.RDF; import edu.cornell.mannlib.vitro.testing.AbstractTestClass; +import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory; import edu.cornell.mannlib.vitro.webapp.dao.jena.SimpleOntModelSelector; import edu.cornell.mannlib.vitro.webapp.dao.jena.WebappDaoFactoryJena; @@ -30,6 +33,7 @@ public class SparqlQueryDataGetterTest extends AbstractTestClass{ OntModel displayModel; String testDataGetterURI_1 = "http://vitro.mannlib.cornell.edu/ontologies/display/1.1#query1data"; WebappDaoFactory wdf; + VitroRequest vreq; @Before public void setUp() throws Exception { @@ -43,12 +47,14 @@ public class SparqlQueryDataGetterTest extends AbstractTestClass{ SimpleOntModelSelector sos = new SimpleOntModelSelector( ModelFactory.createOntologyModel(OntModelSpec.OWL_DL_MEM)); sos.setDisplayModel(displayModel); - wdf = new WebappDaoFactoryJena(sos); + wdf = new WebappDaoFactoryJena(sos); + + vreq = new VitroRequest(new HttpServletRequestStub()); } @Test public void testBasicGetData() throws IllegalArgumentException, SecurityException, InstantiationException, IllegalAccessException, ClassNotFoundException, InvocationTargetException, NoSuchMethodException { - DataGetter dg = DataGetterUtils.dataGetterForURI(displayModel, testDataGetterURI_1); + DataGetter dg = DataGetterUtils.dataGetterForURI(vreq, displayModel, testDataGetterURI_1); Assert.assertNotNull(dg); Assert.assertTrue( "DataGetter should be of type " + SparqlQueryDataGetter.class.getName(),