From cead502f89e7665b85d1a3151ded7d216b5b8519 Mon Sep 17 00:00:00 2001 From: brianjlowe Date: Mon, 4 Jun 2012 21:09:36 +0000 Subject: [PATCH] SDB implementation of RDF API (and merge from trunk) --- webapp/build.xml | 14 +- webapp/config/default.log4j.properties | 5 + webapp/lib/commons-beanutils.jar | Bin 0 -> 188671 bytes webapp/lib/ezmorph-1.0.4.jar | Bin 0 -> 86381 bytes webapp/lib/json-lib-2.2.2-jdk15.jar | Bin 0 -> 143977 bytes .../vitro/webapp/beans/Individual.java | 7 +- .../vitro/webapp/beans/IndividualImpl.java | 5 - .../ConfigurationPropertiesSmokeTests.java} | 9 +- .../vitro/webapp/controller/JsonServlet.java | 587 ----------------- .../controller/ajax/VitroAjaxController.java | 56 +- .../freemarker/BaseSiteAdminController.java | 2 + .../freemarker/ContactMailController.java | 14 +- .../FreemarkerComponentGenerator.java | 24 +- .../freemarker/FreemarkerConfiguration.java | 16 +- .../FreemarkerConfigurationLoader.java | 11 +- .../freemarker/FreemarkerHttpServlet.java | 46 +- .../freemarker/HomePageController.java | 4 +- .../freemarker/IndividualListController.java | 123 +--- .../IndividualListQueryResults.java | 98 +++ .../freemarker/ListClassGroupsController.java | 117 ++++ .../ListVClassWebappsController.java | 141 ++++ .../freemarker/MenuManagementController.java | 4 +- .../controller/freemarker/PageController.java | 9 +- .../ShowClassHierarchyController.java | 247 +++++++ .../freemarker/TemplateProcessingHelper.java | 25 +- .../individual/IndividualRdfAssembler.java | 30 +- .../controller/jena/JenaIngestController.java | 4 +- .../controller/json/GetDataForPage.java | 39 ++ .../controller/json/GetEntitiesByVClass.java | 125 ++++ .../json/GetEntitiesByVClassContinuation.java | 96 +++ .../GetRenderedSolrIndividualsByVClass.java | 79 +++ .../json/GetSolrIndividualsByVClass.java | 42 ++ .../json/GetSolrIndividualsByVClasses.java | 51 ++ .../json/GetVClassesForVClassGroup.java | 56 ++ .../controller/json/JsonArrayProducer.java | 60 ++ .../controller/json/JsonObjectProducer.java | 76 +++ .../webapp/controller/json/JsonProducer.java | 89 +++ .../webapp/controller/json/JsonServlet.java | 141 ++++ .../controller/login/LoginTemplateHelper.java | 5 +- .../dao/filtering/IndividualFiltering.java | 5 - .../vitro/webapp/dao/jena/IndividualJena.java | 26 - .../vitro/webapp/dao/jena/IndividualSDB.java | 17 - .../vitro/webapp/dao/jena/ModelContext.java | 8 + .../edit/elements/DateTimeWithPrecision.java | 600 ------------------ .../n3editing/VTwo/BaseEditElementVTwo.java | 1 + .../n3editing/VTwo/BasicValidationVTwo.java | 1 + .../VTwo/DateTimeIntervalValidationVTwo.java | 9 +- .../VTwo/DateTimeWithPrecisionVTwo.java | 5 +- .../VTwo/EditConfigurationUtils.java | 3 +- .../n3editing/VTwo/EditConfigurationVTwo.java | 76 ++- .../webapp/edit/n3editing/VTwo/FieldVTwo.java | 229 ------- .../VTwo/MultiValueEditSubmission.java | 2 +- .../VTwo/SelectListGeneratorVTwo.java | 504 --------------- .../VTwo/fields/ChildVClassesOptions.java | 83 +++ .../VTwo/fields/ChildVClassesWithParent.java | 66 ++ .../VTwo/fields/ConstantFieldOptions.java | 76 +++ .../n3editing/VTwo/fields/FieldOptions.java | 53 ++ .../edit/n3editing/VTwo/fields/FieldVTwo.java | 141 ++++ .../IndividualsViaClassGroupOptions.java | 38 ++ .../IndividualsViaObjectPropetyOptions.java | 125 ++++ .../fields/IndividualsViaVClassOptions.java | 131 ++++ .../n3editing/VTwo/fields/RdfTypeOptions.java | 60 ++ .../VTwo/fields/SelectListGeneratorVTwo.java | 542 ++++++++++++++++ .../DateTimeIntervalFormGenerator.java | 2 +- .../DateTimeValueFormGenerator.java | 2 +- ...aultAddMissingIndividualFormGenerator.java | 51 +- .../DefaultDataPropertyFormGenerator.java | 3 +- .../generators/DefaultDeleteGenerator.java | 4 +- .../DefaultObjectPropertyFormGenerator.java | 135 +--- .../EditConfigurationGenerator.java | 2 +- .../generators/ManagePageGenerator.java | 313 +++++++++ .../generators/MenuEditingFormGenerator.java | 8 +- .../NewIndividualFormGenerator.java | 22 +- .../generators/RDFSLabelGenerator.java | 24 +- .../generators/RdfTypeGenerator.java | 49 ++ .../preprocessors/ManagePagePreprocessor.java | 274 ++++++++ .../utils/ProcessDataGetterN3.java | 26 + .../utils/ProcessDataGetterN3Utils.java | 53 ++ .../utils/ProcessSparqlDataGetterN3.java | 127 ++++ .../DateTimeIntervalValidation.java | 154 ----- .../EditRequestDispatchController.java | 4 +- .../webapp/email/FreemarkerEmailFactory.java | 6 +- .../webapp/email/FreemarkerEmailMessage.java | 18 +- .../vitro/webapp/rdfservice/RDFService.java | 6 + .../webapp/rdfservice/RDFServiceFactory.java | 11 + .../rdfservice/impl/RDFServiceImpl.java | 508 +++------------ .../rdfservice/impl/RDFServiceUtils.java | 22 + .../impl/sdb/RDFServiceFactorySDB.java | 23 + .../rdfservice/impl/sdb/RDFServiceSDB.java | 267 ++++++++ .../impl/sparql/RDFServiceSparql.java | 460 ++++++++++++++ .../webapp/search/VitroSearchTermNames.java | 2 - .../beans/IndividualProhibitedFromSearch.java | 8 - .../IndividualProhibitedFromSearchImpl.java | 84 --- .../controller/PagedSearchController.java | 4 +- .../search/solr/ExcludeBasedOnNamespace.java | 34 + .../search/solr/ExcludeBasedOnType.java | 60 ++ .../solr/ExcludeBasedOnTypeNamespace.java | 58 ++ .../search/solr/ExcludeNonFlagVitro.java | 44 ++ .../search/solr/IndividualToSolrDocument.java | 167 ++--- .../vitro/webapp/search/solr/NameBoost.java | 20 +- .../search/solr/SearchIndexExcluder.java | 19 + .../vitro/webapp/search/solr/SolrSetup.java | 70 +- .../solr/SyncingExcludeBasedOnType.java | 199 ++++++ .../webapp/search/solr/ThumbnailImageURL.java | 16 +- .../FreemarkerProcessingService.java | 86 +++ .../FreemarkerProcessingServiceImpl.java | 99 +++ .../FreemarkerProcessingServiceSetup.java | 15 + .../FakeApplicationOntologyService.java | 179 ++++++ .../services/shortview/ShortViewService.java | 97 +++ .../shortview/ShortViewServiceImpl.java | 146 +++++ .../shortview/ShortViewServiceSetup.java | 39 ++ .../servlet/setup/ApplicationModelSetup.java | 252 ++++++++ .../servlet/setup/JenaDataSourceSetup.java | 6 +- .../setup/JenaDataSourceSetupBase.java | 84 ++- .../setup/JenaDataSourceSetupSparql.java | 7 +- .../setup/JenaDataSourceSetupSparql2.java | 7 +- .../setup/JenaPersistentDataSourceSetup.java | 226 +------ .../webapp/servlet/setup/ModelSetup.java | 239 +++++++ .../vitro/webapp/servlet/setup/SDBSetup.java | 231 +++++++ .../webapp/servlet/setup/UserModelSetup.java | 69 ++ .../servlet/setup/WebappDaoSDBSetup.java | 275 ++++++++ .../utils/dataGetter/BrowseDataGetter.java | 18 +- .../utils/dataGetter/ClassGroupPageData.java | 59 +- .../webapp/utils/dataGetter/DataGetter.java | 41 +- .../utils/dataGetter/DataGetterUtils.java | 93 ++- .../IndividualsForClassesDataGetter.java | 24 +- .../dataGetter/SparqlQueryDataGetter.java | 15 +- .../vitro/webapp/utils/log/LogUtils.java | 159 +++++ .../MenuManagementDataUtils.java | 34 - .../menuManagement/ProcessClassGroup.java | 27 +- .../ProcessIndividualsForClasses.java | 20 - .../menuManagement/SelectDataGetterUtils.java | 26 - .../pageDataGetter/BrowseDataGetter.java | 2 +- .../pageDataGetter/PageDataGetterUtils.java | 13 +- .../vitro/webapp/web/TemplateUtils.java | 53 ++ .../mannlib/vitro/webapp/web/ViewFinder.java | 2 +- .../BaseTemplateDirectiveModel.java | 41 +- .../webapp/web/directives/EmailDirective.java | 16 - .../IndividualShortViewDirective.java | 152 +++++ .../jsptags/InputElementFormattingTag.java | 2 +- .../customlistview/PropertyListConfig.java | 9 +- .../edit/EditConfigurationTemplateModel.java | 15 +- .../ObjectPropertyTemplateModel.java | 16 +- .../BaseIndividualSearchResult.java | 8 +- .../webapp/web/widgets/BrowseWidget.java | 3 +- .../auth/policy/PolicyHelper_ModelsTest.java | 2 +- .../controller/json/JsonServletTest.java | 250 ++++++++ .../elements/DateTimeWithPrecisionTest.java | 423 ------------ .../n3editing/VTwo/ProcessRdfFormTest.java | 7 +- .../validators/AntiXssValidationTest.java | 2 +- .../utils/dataGetter/DataGetterUtilsTest.java | 16 +- .../dataGetter/SparqlQueryDataGetterTest.java | 10 +- ...yTemplateModel_PropertyListConfigTest.java | 179 +----- .../individual/testConfig-notValidXml.xml | 30 - .../testConfig-selectQueryNoSubNodes.xml | 13 - .../testConfig-selectQueryNodeBlank.xml | 22 - .../testConfig-selectQueryNodeNotFound.xml | 19 - .../testConfig-selectQuerySubNodes.xml | 14 - .../testConfig-templateNodeIsEmpty.xml | 30 - .../testConfig-templateNodeNotFound.xml | 29 - .../vitro/webapp/beans/IndividualStub.java | 7 - .../vitro/webapp/dao/VClassDaoStub.java | 264 ++++++++ .../servlet/http/HttpServletResponseStub.java | 35 +- .../solr/client/solrj/SolrServerStub.java | 46 ++ .../app/ApplicationConfiguration.n3 | 278 ++++++++ .../app/ApplicationConfiguration.owl | 595 ----------------- webapp/web/WEB-INF/ontologies/app/menu.n3 | 20 +- .../ontologies/app/menuload/displayDisplay.n3 | 103 +-- .../ontologies/app/menuload/displayTBOX.n3 | 13 + .../WEB-INF/resources/startup_listeners.txt | 16 +- webapp/web/WEB-INF/web.xml | 20 +- webapp/web/css/classHierarchy.css | 85 +++ webapp/web/css/individual/individual.css | 7 +- webapp/web/css/menupage/pageList.css | 5 + webapp/web/css/menupage/pageManagement.css | 19 + webapp/web/images/checkMark.png | Bin 0 -> 283 bytes webapp/web/images/individual/arrow-up.gif | Bin 0 -> 179 bytes webapp/web/images/vitro_minus_sign.gif | Bin 0 -> 200 bytes webapp/web/images/vitro_plus_sign.gif | Bin 0 -> 324 bytes webapp/web/js/json2.js | 487 ++++++++++++++ webapp/web/js/menupage/browseByVClass.js | 76 +-- webapp/web/js/menupage/pageManagementUtils.js | 516 +++++++++++++++ .../web/js/siteAdmin/classHierarchyUtils.js | 269 ++++++++ .../freemarker/body/individualList.ftl | 2 +- .../body/pagemanagement/page-pageList.ftl | 32 + .../body/pagemanagement/pageList.ftl | 63 ++ .../individual/individual-properties.ftl | 20 +- .../shortview/view-browse-default.ftl | 33 + .../view-search-default.ftl | 0 .../body/search/search-pagedResults.ftl | 2 +- .../siteAdmin/siteAdmin-classHierarchy.ftl | 43 ++ .../siteAdmin/siteAdmin-siteConfiguration.ftl | 6 +- .../freemarker/edit/forms/pageManagement.ftl | 171 +++++ .../freemarker/edit/forms/rdfTypeForm.ftl | 45 ++ 194 files changed, 10522 insertions(+), 5324 deletions(-) create mode 100644 webapp/lib/commons-beanutils.jar create mode 100644 webapp/lib/ezmorph-1.0.4.jar create mode 100644 webapp/lib/json-lib-2.2.2-jdk15.jar rename webapp/src/edu/cornell/mannlib/vitro/webapp/{servlet/setup/BasicSmokeTests.java => config/ConfigurationPropertiesSmokeTests.java} (94%) delete mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/controller/JsonServlet.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/IndividualListQueryResults.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/ListClassGroupsController.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/ListVClassWebappsController.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/ShowClassHierarchyController.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/controller/json/GetDataForPage.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/controller/json/GetEntitiesByVClass.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/controller/json/GetEntitiesByVClassContinuation.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/controller/json/GetRenderedSolrIndividualsByVClass.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/controller/json/GetSolrIndividualsByVClass.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/controller/json/GetSolrIndividualsByVClasses.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/controller/json/GetVClassesForVClassGroup.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/controller/json/JsonArrayProducer.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/controller/json/JsonObjectProducer.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/controller/json/JsonProducer.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/controller/json/JsonServlet.java delete mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/edit/elements/DateTimeWithPrecision.java delete mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/FieldVTwo.java delete mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/SelectListGeneratorVTwo.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/ChildVClassesOptions.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/ChildVClassesWithParent.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/ConstantFieldOptions.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/FieldOptions.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/FieldVTwo.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/IndividualsViaClassGroupOptions.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/IndividualsViaObjectPropetyOptions.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/IndividualsViaVClassOptions.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/RdfTypeOptions.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/SelectListGeneratorVTwo.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/ManagePageGenerator.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/RdfTypeGenerator.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/ManagePagePreprocessor.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/utils/ProcessDataGetterN3.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/utils/ProcessDataGetterN3Utils.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/utils/ProcessSparqlDataGetterN3.java delete mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/validators/DateTimeIntervalValidation.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/rdfservice/RDFServiceFactory.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/RDFServiceUtils.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/sdb/RDFServiceFactorySDB.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/sdb/RDFServiceSDB.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/sparql/RDFServiceSparql.java delete mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/search/beans/IndividualProhibitedFromSearch.java delete mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/search/beans/IndividualProhibitedFromSearchImpl.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/search/solr/ExcludeBasedOnNamespace.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/search/solr/ExcludeBasedOnType.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/search/solr/ExcludeBasedOnTypeNamespace.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/search/solr/ExcludeNonFlagVitro.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/search/solr/SearchIndexExcluder.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/search/solr/SyncingExcludeBasedOnType.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/services/freemarker/FreemarkerProcessingService.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/services/freemarker/FreemarkerProcessingServiceImpl.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/services/freemarker/FreemarkerProcessingServiceSetup.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/services/shortview/FakeApplicationOntologyService.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/services/shortview/ShortViewService.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/services/shortview/ShortViewServiceImpl.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/services/shortview/ShortViewServiceSetup.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/ApplicationModelSetup.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/ModelSetup.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/SDBSetup.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/UserModelSetup.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/WebappDaoSDBSetup.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/utils/log/LogUtils.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/web/TemplateUtils.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/web/directives/IndividualShortViewDirective.java create mode 100644 webapp/test/edu/cornell/mannlib/vitro/webapp/controller/json/JsonServletTest.java delete mode 100644 webapp/test/edu/cornell/mannlib/vitro/webapp/edit/elements/DateTimeWithPrecisionTest.java delete mode 100644 webapp/test/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/testConfig-notValidXml.xml delete mode 100644 webapp/test/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/testConfig-selectQueryNoSubNodes.xml delete mode 100644 webapp/test/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/testConfig-selectQueryNodeBlank.xml delete mode 100644 webapp/test/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/testConfig-selectQueryNodeNotFound.xml delete mode 100644 webapp/test/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/testConfig-selectQuerySubNodes.xml delete mode 100644 webapp/test/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/testConfig-templateNodeIsEmpty.xml delete mode 100644 webapp/test/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/testConfig-templateNodeNotFound.xml create mode 100644 webapp/test/stubs/edu/cornell/mannlib/vitro/webapp/dao/VClassDaoStub.java create mode 100644 webapp/test/stubs/org/apache/solr/client/solrj/SolrServerStub.java create mode 100644 webapp/web/WEB-INF/ontologies/app/ApplicationConfiguration.n3 delete mode 100644 webapp/web/WEB-INF/ontologies/app/ApplicationConfiguration.owl create mode 100644 webapp/web/css/classHierarchy.css create mode 100644 webapp/web/css/menupage/pageList.css create mode 100644 webapp/web/css/menupage/pageManagement.css create mode 100644 webapp/web/images/checkMark.png create mode 100644 webapp/web/images/individual/arrow-up.gif create mode 100644 webapp/web/images/vitro_minus_sign.gif create mode 100644 webapp/web/images/vitro_plus_sign.gif create mode 100644 webapp/web/js/json2.js create mode 100644 webapp/web/js/menupage/pageManagementUtils.js create mode 100644 webapp/web/js/siteAdmin/classHierarchyUtils.js create mode 100644 webapp/web/templates/freemarker/body/pagemanagement/page-pageList.ftl create mode 100644 webapp/web/templates/freemarker/body/pagemanagement/pageList.ftl create mode 100644 webapp/web/templates/freemarker/body/partials/shortview/view-browse-default.ftl rename webapp/web/templates/freemarker/body/partials/{class/view/search => shortview}/view-search-default.ftl (100%) create mode 100644 webapp/web/templates/freemarker/body/siteAdmin/siteAdmin-classHierarchy.ftl create mode 100644 webapp/web/templates/freemarker/edit/forms/pageManagement.ftl create mode 100644 webapp/web/templates/freemarker/edit/forms/rdfTypeForm.ftl diff --git a/webapp/build.xml b/webapp/build.xml index 0a009efa7..429c87998 100644 --- a/webapp/build.xml +++ b/webapp/build.xml @@ -3,7 +3,7 @@ @@ -12,7 +12,7 @@ + - - - - - - - - - - - - - - - - --> @@ -137,15 +137,15 @@ deploy - Deploy the application directly into the Tomcat webapps directory. - - + + - + Get field for this base label, with counter value - that you get from configuration +/* + while(jsonObject.keys().hasNext()) + { + //Other than class, all other variables considered a submission value corresponding to field + String key = (String) jsonObject.keys().next(); + if(key != "dataGetterClass") { + //not expecting multiple values, so will need to either make this array or + //think about this some more + //TODO: Consider multiple values here + Map submissionValues = new HashMap(); + submissionValues.put(key, new String[]{jsonObject.getString(key)} ); + + if(literalLabels.contains(key)) { + submission.addLiteralToForm(editConfiguration.getField(key), field, var, valuesArray) + } + } + + } + List uris = pn.retrieveUrissOnForm(counter); + for(String l:literals) { + //json object should have + submissionValues.put(l, new String[]{jsonObject.getString(l)} ); + }*/ + + } + + + + + private void addFields(ProcessDataGetterN3 pn, int counter) { + List fields = pn.retrieveFields(counter); + editConfiguration.addFields(fields); + } + + + + //original literals on form: label, uris on form: conceptNode and conceptSource + //This will overwrite the original values in the edit configuration + private void addLiteralsAndUrisOnForm(ProcessDataGetterN3 pn, int counter) { + List literalsOnForm = pn.retrieveLiteralsOnForm(counter); + editConfiguration.addLiteralsOnForm(literalsOnForm); + List urisOnForm = pn.retrieveUrisOnForm(counter); + editConfiguration.addUrisOnForm(urisOnForm); + } + + // N3 being reproduced + /* + * ?subject ?predicate ?conceptNode . + */ + //This will overwrite the original with the set of new n3 required + private void addN3Required(ProcessDataGetterN3 pn, int counter) { + //Use the process utils to figure out what class required to retrieve the N3 required + List requiredList = pn.retrieveN3Required(counter); + //Add connection between data getter and page + requiredList.addAll(getPageToDataGetterN3(pn, counter)); + if(requiredList != null) { + editConfiguration.addN3Required(requiredList); + } + } + private List getPageToDataGetterN3( + ProcessDataGetterN3 pn, int counter) { + String dataGetterVar = pn.getDataGetterVar(counter); + //Put this method in the generator but can be put elsewhere + String pageToDataGetterN3 = ManagePageGenerator.getDataGetterN3(dataGetterVar); + return Arrays.asList(pageToDataGetterN3); + + } + + //Add n3 optional + + private void addN3Optional(ProcessDataGetterN3 pn, int counter) { + List optionalList = pn.retrieveN3Optional(counter); + if(optionalList != null) { + editConfiguration.addN3Optional(optionalList); + } + } + + private String[] convertDelimitedStringToArray(String inputString) { + String[] inputArray = new String[1]; + if (inputString.indexOf(",") != -1) { + inputArray = inputString.split(","); + } else { + inputArray[0] = inputString; + } + return inputArray; + + } + + + + + private Object getFirstElement(List inputList) { + if(inputList == null || inputList.size() == 0) + return null; + return inputList.get(0); + } + + //Each JSON Object will indicate the type of the data getter within it + private String getDataGetterClass(JSONObject jsonObject) { + String javaURI = jsonObject.getString("dataGetterClass"); + return getQualifiedDataGetterName(javaURI); + + + } + + //Get rid of java: in front of class name + private String getQualifiedDataGetterName(String dataGetterTypeURI) { + String javaURI = "java:"; + + if(dataGetterTypeURI.startsWith(javaURI)) { + int beginIndex = javaURI.length(); + return dataGetterTypeURI.substring(beginIndex); + } + return dataGetterTypeURI; + } + +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/utils/ProcessDataGetterN3.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/utils/ProcessDataGetterN3.java new file mode 100644 index 000000000..a69417d4c --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/utils/ProcessDataGetterN3.java @@ -0,0 +1,26 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.preprocessors.utils; + +import java.util.ArrayList; +import java.util.List; + +import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.fields.FieldVTwo; + +//Returns the appropriate n3 based on data getter + +public interface ProcessDataGetterN3 { + public List retrieveN3Required(int counter); + public List retrieveN3Optional(int counter); + public ListretrieveLiteralsOnForm(int counter); + + + public List retrieveUrisOnForm(int counter); + public List retrieveFields(int counter); + public List getLiteralVarNamesBase(); + public List getUriVarNamesBase(); + public String getVarName(String base, int counter); + public String getDataGetterVar(int counter); + public List getNewResources(int counter); + +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/utils/ProcessDataGetterN3Utils.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/utils/ProcessDataGetterN3Utils.java new file mode 100644 index 000000000..ff4a96daf --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/utils/ProcessDataGetterN3Utils.java @@ -0,0 +1,53 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.preprocessors.utils; + +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.ServletContext; + +import net.sf.json.JSONObject; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import com.hp.hpl.jena.ontology.OntModel; +import com.hp.hpl.jena.rdf.model.RDFNode; +import com.hp.hpl.jena.rdf.model.ResourceFactory; +import com.hp.hpl.jena.rdf.model.StmtIterator; + +import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary; +import edu.cornell.mannlib.vitro.webapp.dao.jena.ModelContext; +import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.preprocessors.utils.ProcessDataGetterN3; + +/* + * This class determines what n3 should be returned for a particular data getter and can be overwritten or extended in VIVO. + */ +public class ProcessDataGetterN3Utils { + private static final Log log = LogFactory.getLog(ProcessDataGetterN3Utils.class); + public static HashMap getDataGetterTypeToProcessorMap() { + HashMap map = new HashMap(); + map.put("edu.cornell.mannlib.vitro.webapp.utils.dataGetter.SparqlQueryDataGetter", "edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.preprocessors.utils.ProcessSparqlDataGetterN3"); + return map; + } + + public static ProcessDataGetterN3 getDataGetterProcessorN3(String dataGetterClass) { + HashMap map = getDataGetterTypeToProcessorMap(); + // + if(map.containsKey(dataGetterClass)) { + String processorClass = map.get(dataGetterClass); + try { + Class clz = Class.forName(processorClass); + //Don't actually need to pass in json object since that includes the actual submission values + ProcessDataGetterN3 pn = (ProcessDataGetterN3) clz.getConstructor().newInstance(); + return pn; + } catch(Exception ex) { + log.error("Exception occurred in trying to get processor class for n3 for " + dataGetterClass, ex); + return null; + } + } + return null; + } + +} \ No newline at end of file diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/utils/ProcessSparqlDataGetterN3.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/utils/ProcessSparqlDataGetterN3.java new file mode 100644 index 000000000..37b1d6c43 --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/utils/ProcessSparqlDataGetterN3.java @@ -0,0 +1,127 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.preprocessors.utils; + +import java.util.List; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import com.hp.hpl.jena.rdf.model.Literal; + +import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.fields.FieldVTwo; + +import net.sf.json.JSONObject; +import net.sf.json.JSONSerializer; +//Returns the appropriate n3 based on data getter +public class ProcessSparqlDataGetterN3 implements ProcessDataGetterN3 { + private static String classType = "java:edu.cornell.mannlib.vitro.webapp.utils.dataGetter.SparqlQueryDataGetter"; + + public ProcessSparqlDataGetterN3(){ + + } + //Pass in variable that represents the counter + + //TODO: ensure correct model returned + //We shouldn't use the ACTUAL values here but generate the n3 required + public List retrieveN3Required(int counter) { + String dataGetterVar = getDataGetterVar(counter); + String n3 = dataGetterVar + " a <" + classType + ">; \n" + + "display:queryModel " + getN3VarName("queryModel", counter) + "; \n" + + "display:saveToVar " + getN3VarName("saveToVar", counter) + "; \n" + + "display:query " + getN3VarName("query", counter) + " ."; + List requiredList = new ArrayList(); + requiredList.add(getPrefixes() + n3); + return requiredList; + + } + public List retrieveN3Optional(int counter) { + return null; + } + //placeholder so need "?" in front of the variable + public String getDataGetterVar(int counter) { + return "?dataGetter" + counter; + } + + private String getPrefixes() { + return "@prefix display: . \n" + + "@prefix rdfs: . \n"; + } + + + //Need to add method sfor returning the fields, literals on form, and all that + /* + * addLiteralsAndUrisOnForm(pn, counter); + // Add fields + addFields(pn, counter); + //Add input values to submission + addInputsToSubmission(pn, counter); + */ + public List retrieveLiteralsOnForm(int counter) { + List literalsOnForm = new ArrayList(); + literalsOnForm.add(getVarName("saveToVar",counter)); + literalsOnForm.add(getVarName("query", counter)); + return literalsOnForm; + + } + + + public List retrieveUrisOnForm(int counter) { + List urisOnForm = new ArrayList(); + //We have no uris as far as I know.. well query Model is a uri + urisOnForm.add(getVarName("queryModel", counter)); + return urisOnForm; + + } + + public List retrieveFields(int counter) { + List fields = new ArrayList(); + + //An alternative way of doing this + /* + List allFieldsBase = new ArrayList(); + allFieldsBase.addAll(getLiteralVarNamesBase()); + allFieldsBase.addAll(getUriVarNamesBase()); + + for(String varName: allFieldsBase) { + fields.add(new FieldVTwo().setName(getVarName(varName, counter))); + } */ + //For existing data getters + //fields.add(new FieldVTwo().setName(getVarName("dataGetter", counter))); + fields.add(new FieldVTwo().setName(getVarName("queryModel", counter))); + fields.add(new FieldVTwo().setName(getVarName("saveToVar", counter))); + fields.add(new FieldVTwo().setName(getVarName("query", counter))); + + return fields; + } + + public List getLiteralVarNamesBase() { + return Arrays.asList("saveToVar", "query"); + } + + //these are for the fields ON the form + public List getUriVarNamesBase() { + return Arrays.asList("queryModel"); + } + + public String getVarName(String base, int counter) { + return base + counter; + } + + //For use within n3 strings, need a "?" + public String getN3VarName(String base, int counter) { + return "?" + getVarName(base, counter); + } + + //Return name of new resources + public List getNewResources(int counter) { + //Each data getter requires a new resource + List newResources = new ArrayList(); + newResources.add("dataGetter" + counter); + return newResources; + } + +} + + diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/validators/DateTimeIntervalValidation.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/validators/DateTimeIntervalValidation.java deleted file mode 100644 index 3954a6356..000000000 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/validators/DateTimeIntervalValidation.java +++ /dev/null @@ -1,154 +0,0 @@ -/* $This file is distributed under the terms of the license in /doc/license.txt$ */ - -package edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.validators; - -import java.util.Calendar; -import java.util.HashMap; -import java.util.Map; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import com.hp.hpl.jena.datatypes.xsd.XSDDateTime; -import com.hp.hpl.jena.rdf.model.Literal; - -import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary; -import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary.Precision; -import edu.cornell.mannlib.vitro.webapp.edit.elements.DateTimeWithPrecision; -import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.EditConfiguration; -import edu.cornell.mannlib.vitro.webapp.edit.n3editing.processEdit.EditSubmission; - -public class DateTimeIntervalValidation implements N3Validator { - private static Log log = LogFactory.getLog(DateTimeIntervalValidation.class); - - private String startFieldName; - private String endFieldName; - - private String startValueName; - private String endValueName; - - private String startPrecisionName; - private String endPrecisionName; - - public DateTimeIntervalValidation(String startFieldName, String endFieldName){ - this.startFieldName = startFieldName; - this.endFieldName = endFieldName; - startValueName = startFieldName + "-value"; - endValueName = endFieldName + "-value"; - startPrecisionName = startFieldName + "-precision"; - endPrecisionName = endFieldName + "-precision"; - } - - public Map validate(EditConfiguration editConfig, - EditSubmission editSub) { - Map existingLiterals = editConfig.getLiteralsInScope(); - Literal existingStartYear = existingLiterals.get(startValueName); - Literal existingEndYear = existingLiterals.get(endValueName); - - Map literalsFromForm = editSub.getLiteralsFromForm(); - Literal formStartYear = literalsFromForm.get(startValueName); - Literal formEndYear = literalsFromForm.get(endValueName); - - VitroVocabulary.Precision startPrecision = getPrecision(startPrecisionName, editConfig, editSub); - VitroVocabulary.Precision endPrecision = getPrecision(endPrecisionName, editConfig, editSub); - - Map errors = new HashMap(); - - // NIHVIVO-2541 Commented out to allow end date with no start date -// if( formStartYear == null && formEndYear != null ){ -// errors.put(startFieldName, "If there is an end date, there should be a start date"); -// return errors; -// } - - if (formStartYear != null && formEndYear != null) { - errors.putAll(checkDateLiterals(formStartYear, formEndYear, startPrecision, endPrecision)); - } else if (formStartYear != null && existingEndYear != null) { - errors.putAll(checkDateLiterals(formStartYear, existingEndYear, startPrecision, endPrecision)); - } else if (existingStartYear != null && formEndYear != null) { - errors.putAll(checkDateLiterals(existingStartYear, formEndYear, startPrecision, endPrecision)); - } else if (existingStartYear != null && existingEndYear != null) { - errors.putAll(checkDateLiterals(existingStartYear, existingEndYear, startPrecision, endPrecision)); - } - - if (errors.size() != 0) - return errors; - else - return null; - } - - private Precision getPrecision(String precisionVarName, - EditConfiguration editConfig, EditSubmission editSub) { - if( editSub != null - && editSub.getUrisFromForm() != null - && editSub.getUrisFromForm().containsKey(precisionVarName)){ - String precisionStr = editSub.getUrisFromForm().get(precisionVarName); - VitroVocabulary.Precision precision = DateTimeWithPrecision.toPrecision( precisionStr ); - if( precision == null ) - log.warn("cannot convert " + precisionStr + " to a precision"); - else - return precision; - }else if( editConfig != null - && editConfig.getUrisInScope() != null - && editConfig.getUrisInScope().containsKey(precisionVarName)){ - String precisionStr = editConfig.getUrisInScope().get(precisionVarName); - VitroVocabulary.Precision precision = DateTimeWithPrecision.toPrecision( precisionStr ); - if( precision == null ) - log.warn("cannot convert " + precisionStr + " to a precision"); - else - return precision; - } - //this is what is returned if a precision was not found in the config or submission - return null; - } - - private Map checkDateLiterals( - Literal startLit, Literal endLit, - VitroVocabulary.Precision startPrecision, VitroVocabulary.Precision endPrecision) { - Map errors = new HashMap(); - - if( endPrecision == null ){ - //there is no end date, nothing to check - return errors; - } - - try{ - XSDDateTime startDate = (XSDDateTime)startLit.getValue(); - XSDDateTime endDate = (XSDDateTime)endLit.getValue(); - if( startDate != null && endDate!= null ){ - Calendar startCal = startDate.asCalendar(); - Calendar endCal = endDate.asCalendar(); - - if( endCal != null ){ - if( !startCal.before( endCal ) ){ - if( startPrecision == VitroVocabulary.Precision.YEAR - && endPrecision == VitroVocabulary.Precision.YEAR ){ - errors.putAll( checkYears(startCal,endCal)); - }else{ - errors.put(startFieldName, "Start must be before end"); - errors.put(endFieldName, "End must be after start"); - } - } - } - } - }catch(ClassCastException cce){ - errors.put(startFieldName, "could not format start or end date"); - errors.put(endFieldName, "could not format start or end date"); - log.debug("could not format dates " + cce); - } - - return errors; - } - - private Map checkYears( - Calendar startCal, Calendar endCal) { - - Map errors = new HashMap(); - - if( ! (endCal.get(Calendar.YEAR) >= startCal.get(Calendar.YEAR) )){ - errors.put(startFieldName, "Start must be before end"); - errors.put(endFieldName, "End must be after start"); - } - - return errors; - } -} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/controller/EditRequestDispatchController.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/controller/EditRequestDispatchController.java index c4f29741d..07308865b 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/controller/EditRequestDispatchController.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/controller/EditRequestDispatchController.java @@ -153,7 +153,7 @@ public class EditRequestDispatchController extends FreemarkerHttpServlet { //TODO: should more of what happens in this method //happen in the generators? private EditConfigurationVTwo setupEditConfiguration(String editConfGeneratorName, - VitroRequest vreq) { + VitroRequest vreq) throws Exception { HttpSession session = vreq.getSession(); EditConfigurationVTwo editConfig = makeEditConfigurationVTwo( editConfGeneratorName, vreq, session); @@ -362,7 +362,7 @@ public class EditRequestDispatchController extends FreemarkerHttpServlet { private EditConfigurationVTwo makeEditConfigurationVTwo( - String editConfGeneratorName, VitroRequest vreq, HttpSession session) { + String editConfGeneratorName, VitroRequest vreq, HttpSession session) throws Exception { EditConfigurationGenerator EditConfigurationVTwoGenerator = null; diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/email/FreemarkerEmailFactory.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/email/FreemarkerEmailFactory.java index 7284f738a..bedeab160 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/email/FreemarkerEmailFactory.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/email/FreemarkerEmailFactory.java @@ -25,6 +25,8 @@ import org.apache.commons.logging.LogFactory; import edu.cornell.mannlib.vitro.webapp.config.ConfigurationProperties; import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; +import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerConfiguration; +import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerConfigurationLoader; import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus; /** @@ -57,7 +59,9 @@ public class FreemarkerEmailFactory { } FreemarkerEmailFactory factory = getFactory(vreq); - return new FreemarkerEmailMessage(vreq, factory.getEmailSession(), + FreemarkerConfiguration fConfig = FreemarkerConfigurationLoader + .getConfig(vreq); + return new FreemarkerEmailMessage(fConfig, factory.getEmailSession(), factory.getReplyToAddress()); } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/email/FreemarkerEmailMessage.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/email/FreemarkerEmailMessage.java index b0353dd35..db7356ed4 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/email/FreemarkerEmailMessage.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/email/FreemarkerEmailMessage.java @@ -23,7 +23,6 @@ import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeBodyPart; import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMultipart; -import javax.servlet.http.HttpServletRequest; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -48,9 +47,6 @@ public class FreemarkerEmailMessage { private static final Log log = LogFactory .getLog(FreemarkerEmailMessage.class); - private static final String CONFIG_ATTRIBUTE = "freemarkerConfig"; - - private final HttpServletRequest req; private final Session session; private final FreemarkerConfiguration config; @@ -67,21 +63,11 @@ public class FreemarkerEmailMessage { /** * Package access - should only be created by the factory. */ - FreemarkerEmailMessage(HttpServletRequest req, Session session, + FreemarkerEmailMessage(FreemarkerConfiguration fConfig, Session session, InternetAddress replyToAddress) { - this.req = req; this.session = session; this.replyToAddress = replyToAddress; - - Object o = req.getAttribute(CONFIG_ATTRIBUTE); - if (!(o instanceof FreemarkerConfiguration)) { - String oClass = (o == null) ? "null" : o.getClass().getName(); - - throw new IllegalStateException( - "Request does not contain a Configuration at '" - + CONFIG_ATTRIBUTE + "': " + oClass); - } - this.config = (FreemarkerConfiguration) o; + this.config = fConfig; } public void addRecipient(RecipientType type, String emailAddress) { diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/rdfservice/RDFService.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/rdfservice/RDFService.java index 8fb11b491..cb78f6b52 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/rdfservice/RDFService.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/rdfservice/RDFService.java @@ -146,4 +146,10 @@ public interface RDFService { * @return ChangeSet an empty ChangeSet object */ public ChangeSet manufactureChangeSet(); + + /** + * Free any resources held by this RDFService object + */ + public void close(); + } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/rdfservice/RDFServiceFactory.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/rdfservice/RDFServiceFactory.java new file mode 100644 index 000000000..a2d062ffe --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/rdfservice/RDFServiceFactory.java @@ -0,0 +1,11 @@ +package edu.cornell.mannlib.vitro.webapp.rdfservice; + +import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; + +public interface RDFServiceFactory { + + public RDFService getRDFService(); + + public RDFService getRDFService(VitroRequest vreq); + +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/RDFServiceImpl.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/RDFServiceImpl.java index 055200ef2..38abf61ac 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/RDFServiceImpl.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/RDFServiceImpl.java @@ -3,24 +3,11 @@ package edu.cornell.mannlib.vitro.webapp.rdfservice.impl; import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.InputStream; import java.util.ArrayList; import java.util.Iterator; -import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.openrdf.model.Resource; -import org.openrdf.query.MalformedQueryException; -import org.openrdf.query.QueryLanguage; -import org.openrdf.query.Update; -import org.openrdf.query.UpdateExecutionException; -import org.openrdf.repository.Repository; -import org.openrdf.repository.RepositoryConnection; -import org.openrdf.repository.RepositoryException; -import org.openrdf.repository.RepositoryResult; -import org.openrdf.repository.http.HTTPRepository; import com.hp.hpl.jena.graph.Node; import com.hp.hpl.jena.graph.Triple; @@ -29,11 +16,9 @@ import com.hp.hpl.jena.query.QueryExecution; import com.hp.hpl.jena.query.QueryExecutionFactory; import com.hp.hpl.jena.query.QueryFactory; import com.hp.hpl.jena.query.ResultSet; -import com.hp.hpl.jena.query.ResultSetFormatter; import com.hp.hpl.jena.rdf.model.Model; import com.hp.hpl.jena.rdf.model.ModelFactory; -import com.hp.hpl.jena.rdf.model.Statement; -import com.hp.hpl.jena.rdf.model.StmtIterator; +import com.hp.hpl.jena.sparql.resultset.XMLInput; import com.hp.hpl.jena.vocabulary.RDF; import edu.cornell.mannlib.vitro.webapp.rdfservice.ChangeListener; @@ -47,67 +32,12 @@ import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFServiceException; * to allow listening, logging and auditing. */ -public class RDFServiceImpl implements RDFService { +public abstract class RDFServiceImpl implements RDFService { private static final Log log = LogFactory.getLog(RDFServiceImpl.class); - private String endpointURI; - private String defaultWriteGraphURI; - private Repository repository; - private ArrayList registeredListeners; - - /** - * Returns an RDFService for a remote repository - * @param String - URI of the SPARQL endpoint for the knowledge base - * @param String - URI of the default write graph within the knowledge base. - * this is the graph that will be written to when a graph - * is not explicitly specified. - * - * The default read graph is the union of all graphs in the - * knowledge base - */ - public RDFServiceImpl(String endpointURI, String defaultWriteGraphURI) { - this.endpointURI = endpointURI; - this.defaultWriteGraphURI = defaultWriteGraphURI; - this.repository = new HTTPRepository(endpointURI); - this.registeredListeners = new ArrayList(); - } + protected String defaultWriteGraphURI; + protected ArrayList registeredListeners = new ArrayList(); - /** - * Perform a series of additions to and or removals from specified graphs - * in the RDF store. preConditionSparql will be executed against the - * union of all the graphs in the knowledge base before any updates are made. - * If the precondition query returns a non-empty result no updates - * will be made. - * - * @param ChangeSet - a set of changes to be performed on the RDF store. - * - * @return boolean - indicates whether the precondition was satisfied - */ - @Override - public boolean changeSetUpdate(ChangeSet changeSet) throws RDFServiceException { - - if (!isPreconditionSatisfied(changeSet.getPreconditionQuery(), changeSet.getPreconditionQueryType())) { - return false; - } - - Iterator csIt = changeSet.getModelChanges().iterator(); - - while (csIt.hasNext()) { - - ModelChange modelChange = csIt.next(); - - if (modelChange.getOperation() == ModelChange.Operation.ADD) { - performAdd(modelChange); - } else if (modelChange.getOperation() == ModelChange.Operation.REMOVE) { - performRemove(modelChange); - } else { - log.error("unrecognized operation type"); - } - } - - return true; - } - /** * If the given individual already exists in the default graph, throws an * RDFServiceException, otherwise adds one type assertion to the default @@ -122,206 +52,46 @@ public class RDFServiceImpl implements RDFService { newIndividual(individualURI, individualTypeURI, defaultWriteGraphURI); } - + /** - * If the given individual already exists in the given graph, throws an - * RDFServiceException, otherwise adds one type assertion to the given - * graph. - * - * @param String individualURI - URI of the individual to be added - * @param String individualTypeURI - URI of the type for the individual - * @param String graphURI - URI of the graph to which to add the individual - */ - @Override - public void newIndividual(String individualURI, - String individualTypeURI, - String graphURI) throws RDFServiceException { - - StringBuffer containsQuery = new StringBuffer("ASK { \n"); + * If the given individual already exists in the given graph, throws an + * RDFServiceException, otherwise adds one type assertion to the given + * graph. + * + * @param String individualURI - URI of the individual to be added + * @param String individualTypeURI - URI of the type for the individual + * @param String graphURI - URI of the graph to which to add the individual + */ + @Override + public void newIndividual(String individualURI, + String individualTypeURI, + String graphURI) throws RDFServiceException { + + StringBuffer containsQuery = new StringBuffer("ASK { \n"); if (graphURI != null) { containsQuery.append(" GRAPH <" + graphURI + "> { "); } - containsQuery.append("<"); - containsQuery.append(individualURI); - containsQuery.append("> "); - containsQuery.append("?p ?o"); + containsQuery.append("<"); + containsQuery.append(individualURI); + containsQuery.append("> "); + containsQuery.append("?p ?o"); if (graphURI != null) { containsQuery.append(" } \n"); } containsQuery.append("\n}"); - + if (sparqlAskQuery(containsQuery.toString())) { - throw new RDFServiceException("individual already exists"); + throw new RDFServiceException("individual already exists"); } else { - Triple triple = new Triple(Node.createURI(individualURI), RDF.type.asNode(), Node.createURI(individualTypeURI)); - addTriple(triple, graphURI); - } - } + Triple triple = new Triple(Node.createURI(individualURI), RDF.type.asNode(), Node.createURI(individualTypeURI)); + //addTriple(triple, graphURI); + ChangeSet cs = this.manufactureChangeSet(); + cs.addAddition(new ByteArrayInputStream( + sparqlTriple(triple).getBytes()), ModelSerializationFormat.N3, graphURI); + changeSetUpdate(cs); + } + } - /** - * Performs a SPARQL construct query against the knowledge base. The query may have - * an embedded graph identifier. - * - * @param String query - the SPARQL query to be executed against the RDF store - * @param RDFService.ModelSerializationFormat resultFormat - type of serialization for RDF result of the SPARQL query - * @param OutputStream outputStream - the result of the query - * - */ - @Override - public InputStream sparqlConstructQuery(String queryStr, - RDFServiceImpl.ModelSerializationFormat resultFormat) throws RDFServiceException { - - Model model = ModelFactory.createDefaultModel(); - Query query = QueryFactory.create(queryStr); - QueryExecution qe = QueryExecutionFactory.sparqlService(endpointURI, query); - - try { - qe.execConstruct(model); - } finally { - qe.close(); - } - - ByteArrayOutputStream serializedModel = new ByteArrayOutputStream(); - model.write(serializedModel,getSerializationFormatString(resultFormat)); - InputStream result = new ByteArrayInputStream(serializedModel.toByteArray()); - return result; - } - - /** - * Performs a SPARQL describe query against the knowledge base. The query may have - * an embedded graph identifier. - * - * @param String query - the SPARQL query to be executed against the RDF store - * @param RDFService.ModelSerializationFormat resultFormat - type of serialization for RDF result of the SPARQL query - * - * @return InputStream - the result of the query - * - */ - @Override - public InputStream sparqlDescribeQuery(String queryStr, - RDFServiceImpl.ModelSerializationFormat resultFormat) throws RDFServiceException { - - Model model = ModelFactory.createDefaultModel(); - Query query = QueryFactory.create(queryStr); - QueryExecution qe = QueryExecutionFactory.sparqlService(endpointURI, query); - - try { - qe.execDescribe(model); - } finally { - qe.close(); - } - - ByteArrayOutputStream serializedModel = new ByteArrayOutputStream(); - model.write(serializedModel,getSerializationFormatString(resultFormat)); - InputStream result = new ByteArrayInputStream(serializedModel.toByteArray()); - return result; - } - - /** - * Performs a SPARQL select query against the knowledge base. The query may have - * an embedded graph identifier. - * - * @param String query - the SPARQL query to be executed against the RDF store - * @param RDFService.ResultFormat resultFormat - format for the result of the Select query - * - * @return InputStream - the result of the query - * - */ - @Override - public InputStream sparqlSelectQuery(String queryStr, RDFService.ResultFormat resultFormat) throws RDFServiceException { - - Query query = QueryFactory.create(queryStr); - QueryExecution qe = QueryExecutionFactory.sparqlService(endpointURI, query); - - try { - ResultSet resultSet = qe.execSelect(); - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - - switch (resultFormat) { - case CSV: - ResultSetFormatter.outputAsCSV(outputStream,resultSet); - break; - case TEXT: - ResultSetFormatter.out(outputStream,resultSet); - break; - case JSON: - ResultSetFormatter.outputAsJSON(outputStream, resultSet); - break; - case XML: - ResultSetFormatter.outputAsXML(outputStream, resultSet); - break; - default: - throw new RDFServiceException("unrecognized result format"); - } - - InputStream result = new ByteArrayInputStream(outputStream.toByteArray()); - return result; - } finally { - qe.close(); - } - } - - /** - * Performs a SPARQL ASK query against the knowledge base. The query may have - * an embedded graph identifier. - * - * @param String query - the SPARQL query to be executed against the RDF store - * - * @return boolean - the result of the SPARQL query - */ - @Override - public boolean sparqlAskQuery(String queryStr) throws RDFServiceException { - - Query query = QueryFactory.create(queryStr); - QueryExecution qe = QueryExecutionFactory.sparqlService(endpointURI, query); - - try { - return qe.execAsk(); - } finally { - qe.close(); - } - } - - /** - * Get a list of all the graph URIs in the RDF store. - * - * @return List - list of all the graph URIs in the RDF store - */ - //TODO - need to verify that the sesame getContextIDs method is implemented - // in such a way that it works with all triple stores that support the - // graph update API - @Override - public List getGraphURIs() throws RDFServiceException { - - List graphNodeList = new ArrayList(); - - try { - RepositoryConnection conn = getConnection(); - try { - RepositoryResult conResult = conn.getContextIDs(); - while (conResult.hasNext()) { - Resource res = conResult.next(); - graphNodeList.add(res.stringValue()); - } - } finally { - conn.close(); - } - } catch (RepositoryException re) { - throw new RuntimeException(re); - } - - return graphNodeList; - } - - /** - * TODO - what is the definition of this method? - * @return - */ - @Override - public void getGraphMetadata() throws RDFServiceException { - - } - /** * Get the URI of the default write graph * @@ -363,79 +133,60 @@ public class RDFServiceImpl implements RDFService { @Override public ChangeSet manufactureChangeSet() { return new ChangeSetImpl(); - } - - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // Non-override methods below - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - protected String getEndpointURI() { - return endpointURI; - } - - protected RepositoryConnection getConnection() { - try { - return this.repository.getConnection(); - } catch (RepositoryException e) { - throw new RuntimeException(e); - } - } - - protected void executeUpdate(String updateString) { - try { - RepositoryConnection conn = getConnection(); - try { - Update u = conn.prepareUpdate(QueryLanguage.SPARQL, updateString); - u.execute(); - } catch (MalformedQueryException e) { - throw new RuntimeException(e); - } catch (UpdateExecutionException e) { - log.error(e,e); - log.error("Update command: \n" + updateString); - throw new RuntimeException(e); - } finally { - conn.close(); - } - } catch (RepositoryException re) { - throw new RuntimeException(re); - } - } - - protected void addTriple(Triple t, String graphURI) { - - StringBuffer updateString = new StringBuffer(); - updateString.append("INSERT DATA { "); - updateString.append((graphURI != null) ? "GRAPH <" + graphURI + "> { " : "" ); - updateString.append(sparqlNodeUpdate(t.getSubject(), "")); - updateString.append(" "); - updateString.append(sparqlNodeUpdate(t.getPredicate(), "")); - updateString.append(" "); - updateString.append(sparqlNodeUpdate(t.getObject(), "")); - updateString.append(" }"); - updateString.append((graphURI != null) ? " } " : ""); - - executeUpdate(updateString.toString()); - notifyListeners(t, ModelChange.Operation.ADD, graphURI); - } - - protected void removeTriple(Triple t, String graphURI) { - - StringBuffer updateString = new StringBuffer(); - updateString.append("DELETE DATA { "); - updateString.append((graphURI != null) ? "GRAPH <" + graphURI + "> { " : "" ); - updateString.append(sparqlNodeUpdate(t.getSubject(), "")); - updateString.append(" "); - updateString.append(sparqlNodeUpdate(t.getPredicate(), "")); - updateString.append(" "); - updateString.append(sparqlNodeUpdate(t.getObject(), "")); - updateString.append(" }"); - updateString.append((graphURI != null) ? " } " : ""); - - executeUpdate(updateString.toString()); - notifyListeners(t, ModelChange.Operation.REMOVE, graphURI); - } - - protected synchronized void notifyListeners(Triple triple, ModelChange.Operation operation, String graphURI) { + } + + public synchronized void notifyListeners(Triple triple, ModelChange.Operation operation, String graphURI) { + Iterator iter = registeredListeners.iterator(); + + while (iter.hasNext()) { + ChangeListener listener = iter.next(); + if (operation == ModelChange.Operation.ADD) { + listener.addedStatement(sparqlTriple(triple), graphURI); + } else { + listener.removedStatement(sparqlTriple(triple).toString(), graphURI); + } + } + } + + protected boolean isPreconditionSatisfied(String query, + RDFService.SPARQLQueryType queryType) + throws RDFServiceException { + Model model = ModelFactory.createDefaultModel(); + switch (queryType) { + case DESCRIBE: + model.read(sparqlDescribeQuery(query,RDFService.ModelSerializationFormat.N3), null); + return !model.isEmpty(); + case CONSTRUCT: + model.read(sparqlConstructQuery(query,RDFService.ModelSerializationFormat.N3), null); + return !model.isEmpty(); + case SELECT: + return sparqlSelectQueryHasResults(query); + case ASK: + return sparqlAskQuery(query); + default: + throw new RDFServiceException("unrecognized SPARQL query type"); + } + } + + protected static String getSerializationFormatString(RDFService.ModelSerializationFormat format) { + switch (format) { + case RDFXML: + return "RDFXML"; + case N3: + return "N3"; + default: + log.error("unexpected format in getFormatString"); + return null; + } + } + + protected boolean sparqlSelectQueryHasResults(String queryStr) throws RDFServiceException { + ResultSet rs = XMLInput.fromXML(sparqlSelectQuery(queryStr, ResultFormat.XML)); + return rs.hasNext(); + } + + protected static String sparqlTriple(Triple triple) { StringBuffer serializedTriple = new StringBuffer(); serializedTriple.append(sparqlNodeUpdate(triple.getSubject(), "")); serializedTriple.append(" "); @@ -443,93 +194,10 @@ public class RDFServiceImpl implements RDFService { serializedTriple.append(" "); serializedTriple.append(sparqlNodeUpdate(triple.getObject(), "")); serializedTriple.append(" ."); - - Iterator iter = registeredListeners.iterator(); - - while (iter.hasNext()) { - ChangeListener listener = iter.next(); - if (operation == ModelChange.Operation.ADD) { - listener.addedStatement(serializedTriple.toString(), graphURI); - } else { - listener.removedStatement(serializedTriple.toString(), graphURI); - } - } + return serializedTriple.toString(); + } - protected boolean isPreconditionSatisfied(String query, - RDFService.SPARQLQueryType queryType) - throws RDFServiceException { - Model model = ModelFactory.createDefaultModel(); - - switch (queryType) { - case DESCRIBE: - model.read(sparqlDescribeQuery(query,RDFService.ModelSerializationFormat.N3), null); - return !model.isEmpty(); - case CONSTRUCT: - model.read(sparqlConstructQuery(query,RDFService.ModelSerializationFormat.N3), null); - return !model.isEmpty(); - case SELECT: - return sparqlSelectQueryHasResults(query); - case ASK: - return sparqlAskQuery(query); - default: - throw new RDFServiceException("unrecognized SPARQL query type"); - } - } - - protected boolean sparqlSelectQueryHasResults(String queryStr) throws RDFServiceException { - - Query query = QueryFactory.create(queryStr); - QueryExecution qe = QueryExecutionFactory.sparqlService(endpointURI, query); - - try { - ResultSet resultSet = qe.execSelect(); - return resultSet.hasNext(); - } finally { - qe.close(); - } - } - - protected void performAdd(ModelChange modelChange) throws RDFServiceException { - - Model model = ModelFactory.createDefaultModel(); - model.read(modelChange.getSerializedModel(),getSerializationFormatString(modelChange.getSerializationFormat())); - - StmtIterator stmtIt = model.listStatements(); - - while (stmtIt.hasNext()) { - Statement stmt = stmtIt.next(); - Triple triple = new Triple(stmt.getSubject().asNode(), stmt.getPredicate().asNode(), stmt.getObject().asNode()); - addTriple(triple, modelChange.getGraphURI()); - } - } - - protected void performRemove(ModelChange modelChange) throws RDFServiceException { - - Model model = ModelFactory.createDefaultModel(); - model.read(modelChange.getSerializedModel(),getSerializationFormatString(modelChange.getSerializationFormat())); - - StmtIterator stmtIt = model.listStatements(); - - while (stmtIt.hasNext()) { - Statement stmt = stmtIt.next(); - Triple triple = new Triple(stmt.getSubject().asNode(), stmt.getPredicate().asNode(), stmt.getObject().asNode()); - removeTriple(triple, modelChange.getGraphURI()); - } - } - - protected static String getSerializationFormatString(RDFService.ModelSerializationFormat format) { - switch (format) { - case RDFXML: - return "RDFXML"; - case N3: - return "N3"; - default: - log.error("unexpected format in getFormatString"); - return null; - } - } - protected static String sparqlNodeUpdate(Node node, String varName) { if (node.isBlank()) { return "_:" + node.getBlankNodeLabel().replaceAll("\\W", ""); diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/RDFServiceUtils.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/RDFServiceUtils.java new file mode 100644 index 000000000..b1ab02a76 --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/RDFServiceUtils.java @@ -0,0 +1,22 @@ +package edu.cornell.mannlib.vitro.webapp.rdfservice.impl; + +import javax.servlet.ServletContext; + +import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFServiceFactory; + +public class RDFServiceUtils { + + private static final String RDFSERVICEFACTORY_ATTR = + RDFServiceUtils.class.getName() + ".RDFServiceFactory"; + + public RDFServiceFactory getRDFServiceFactory(ServletContext context) { + Object o = context.getAttribute(RDFSERVICEFACTORY_ATTR); + return (o instanceof RDFServiceFactory) ? (RDFServiceFactory) o : null; + } + + public void setRDFServiceFactory(ServletContext context, + RDFServiceFactory factory) { + context.setAttribute(RDFSERVICEFACTORY_ATTR, factory); + } + +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/sdb/RDFServiceFactorySDB.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/sdb/RDFServiceFactorySDB.java new file mode 100644 index 000000000..7c87359d9 --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/sdb/RDFServiceFactorySDB.java @@ -0,0 +1,23 @@ +package edu.cornell.mannlib.vitro.webapp.rdfservice.impl.sdb; + +import org.apache.commons.dbcp.BasicDataSource; + +import com.hp.hpl.jena.sdb.StoreDesc; + +import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService; + +public class RDFServiceFactorySDB { + + private BasicDataSource bds; + private StoreDesc storeDesc; + + public RDFServiceFactorySDB(BasicDataSource dataSource, StoreDesc storeDesc) { + this.bds = dataSource; + this.storeDesc = storeDesc; + } + + public RDFService getRDFService() { + return new RDFServiceSDB(bds, storeDesc); + } + +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/sdb/RDFServiceSDB.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/sdb/RDFServiceSDB.java new file mode 100644 index 000000000..e2476e3f5 --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/sdb/RDFServiceSDB.java @@ -0,0 +1,267 @@ +package edu.cornell.mannlib.vitro.webapp.rdfservice.impl.sdb; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.apache.commons.dbcp.BasicDataSource; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import com.hp.hpl.jena.query.Dataset; +import com.hp.hpl.jena.query.Query; +import com.hp.hpl.jena.query.QueryExecution; +import com.hp.hpl.jena.query.QueryExecutionFactory; +import com.hp.hpl.jena.query.QueryFactory; +import com.hp.hpl.jena.query.ResultSet; +import com.hp.hpl.jena.query.ResultSetFormatter; +import com.hp.hpl.jena.rdf.listeners.StatementListener; +import com.hp.hpl.jena.rdf.model.Model; +import com.hp.hpl.jena.rdf.model.ModelFactory; +import com.hp.hpl.jena.rdf.model.Statement; +import com.hp.hpl.jena.sdb.SDBFactory; +import com.hp.hpl.jena.sdb.StoreDesc; +import com.hp.hpl.jena.sdb.sql.SDBConnection; + +import edu.cornell.mannlib.vitro.webapp.dao.jena.DatasetWrapper; +import edu.cornell.mannlib.vitro.webapp.rdfservice.ChangeSet; +import edu.cornell.mannlib.vitro.webapp.rdfservice.ModelChange; +import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService; +import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFServiceException; +import edu.cornell.mannlib.vitro.webapp.rdfservice.impl.RDFServiceImpl; + +public class RDFServiceSDB extends RDFServiceImpl implements RDFService { + + private final static Log log = LogFactory.getLog(RDFServiceSDB.class); + + private BasicDataSource bds; + private StoreDesc storeDesc; + + public RDFServiceSDB(BasicDataSource dataSource, StoreDesc storeDesc) { + this.bds = dataSource; + this.storeDesc = storeDesc; + } + + protected DatasetWrapper getDatasetWrapper() { + try { + SDBConnection conn = new SDBConnection(bds.getConnection()); + Dataset dataset = SDBFactory.connectDataset(conn, storeDesc); + return new DatasetWrapper(dataset, conn); + } catch (SQLException sqle) { + log.error(sqle, sqle); + throw new RuntimeException(sqle); + } + } + + @Override + public boolean changeSetUpdate(ChangeSet changeSet) + throws RDFServiceException { + + if (changeSet.getPreconditionQuery() != null + && !isPreconditionSatisfied( + changeSet.getPreconditionQuery(), + changeSet.getPreconditionQueryType())) { + return false; + } + + Iterator csIt = changeSet.getModelChanges().iterator(); + + SDBConnection conn = null; + try { + conn = new SDBConnection(bds.getConnection()); + } catch (SQLException sqle) { + log.error(sqle, sqle); + throw new RuntimeException(sqle); + } + + Dataset dataset = SDBFactory.connectDataset(conn, storeDesc); + boolean transaction = conn.getTransactionHandler().transactionsSupported(); + + try { + if (transaction) { + conn.getTransactionHandler().begin(); + } + while (csIt.hasNext()) { + ModelChange modelChange = csIt.next(); + Model model = dataset.getNamedModel(modelChange.getGraphURI()); + model.register(new ModelListener(modelChange.getGraphURI(), this)); + if (modelChange.getOperation() == ModelChange.Operation.ADD) { + model.add(parseModel(modelChange)); + } else if (modelChange.getOperation() == ModelChange.Operation.REMOVE) { + model.remove(parseModel(modelChange)); + } else { + log.error("unrecognized operation type"); + } + } + } catch (Throwable t) { + if (transaction) { + conn.getTransactionHandler().abort(); + } + throw new RuntimeException(t); + } finally { + if (transaction) { + conn.getTransactionHandler().commit(); + } + conn.close(); + } + + return true; + } + + private Model parseModel(ModelChange modelChange) { + Model model = ModelFactory.createDefaultModel(); + model.read(modelChange.getSerializedModel(), + getSerializationFormatString(modelChange.getSerializationFormat())); + return model; + } + + @Override + public void newIndividual(String individualURI, String individualTypeURI, + String graphURI) throws RDFServiceException { + // TODO Auto-generated method stub + + } + + private InputStream getRDFResultStream(String query, boolean construct, + ModelSerializationFormat resultFormat) throws RDFServiceException { + DatasetWrapper dw = getDatasetWrapper(); + try { + Dataset d = dw.getDataset(); + Query q = QueryFactory.create(query); + QueryExecution qe = QueryExecutionFactory.create(q, d); + ByteArrayOutputStream serializedModel = new ByteArrayOutputStream(); + try { + // TODO pipe this + Model m = construct ? qe.execConstruct() : qe.execDescribe(); + m.write(serializedModel, getSerializationFormatString(resultFormat)); + InputStream result = new ByteArrayInputStream(serializedModel.toByteArray()); + return result; + } finally { + qe.close(); + } + } finally { + dw.close(); + } + } + + private static final boolean CONSTRUCT = true; + + private static final boolean DESCRIBE = false; + + @Override + public InputStream sparqlConstructQuery(String query, + ModelSerializationFormat resultFormat) throws RDFServiceException { + return getRDFResultStream(query, CONSTRUCT, resultFormat); + } + + @Override + public InputStream sparqlDescribeQuery(String query, + ModelSerializationFormat resultFormat) throws RDFServiceException { + return getRDFResultStream(query, DESCRIBE, resultFormat); + } + + @Override + public InputStream sparqlSelectQuery(String query, ResultFormat resultFormat) + throws RDFServiceException { + DatasetWrapper dw = getDatasetWrapper(); + try { + Dataset d = dw.getDataset(); + Query q = QueryFactory.create(query); + QueryExecution qe = QueryExecutionFactory.create(q, d); + try { + ResultSet resultSet = qe.execSelect(); + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + switch (resultFormat) { + case CSV: + ResultSetFormatter.outputAsCSV(outputStream,resultSet); + break; + case TEXT: + ResultSetFormatter.out(outputStream,resultSet); + break; + case JSON: + ResultSetFormatter.outputAsJSON(outputStream, resultSet); + break; + case XML: + ResultSetFormatter.outputAsXML(outputStream, resultSet); + break; + default: + throw new RDFServiceException("unrecognized result format"); + } + InputStream result = new ByteArrayInputStream(outputStream.toByteArray()); + return result; + } finally { + qe.close(); + } + } finally { + dw.close(); + } + } + + @Override + public boolean sparqlAskQuery(String query) throws RDFServiceException { + DatasetWrapper dw = getDatasetWrapper(); + try { + Dataset d = dw.getDataset(); + Query q = QueryFactory.create(query); + QueryExecution qe = QueryExecutionFactory.create(q, d); + try { + return qe.execAsk(); + } finally { + qe.close(); + } + } finally { + dw.close(); + } + } + + @Override + public List getGraphURIs() throws RDFServiceException { + DatasetWrapper dw = getDatasetWrapper(); + try { + Dataset d = dw.getDataset(); + List graphURIs = new ArrayList(); + Iterator nameIt = d.listNames(); + while (nameIt.hasNext()) { + graphURIs.add(nameIt.next()); + } + return graphURIs; + } finally { + dw.close(); + } + } + + @Override + public void getGraphMetadata() throws RDFServiceException { + // TODO Auto-generated method stub + } + + @Override + public void close() { + // nothing + } + + private class ModelListener extends StatementListener { + + private String graphURI; + private RDFServiceImpl s; + + public ModelListener(String graphURI, RDFServiceImpl s) { + this.graphURI = graphURI; + this.s = s; + } + + public void addedStatement(Statement stmt) { + s.notifyListeners(stmt.asTriple(), ModelChange.Operation.ADD, graphURI); + } + + public void removedStatement(Statement stmt) { + s.notifyListeners(stmt.asTriple(), ModelChange.Operation.REMOVE, graphURI); + } + + } + +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/sparql/RDFServiceSparql.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/sparql/RDFServiceSparql.java new file mode 100644 index 000000000..fd0095f4d --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/sparql/RDFServiceSparql.java @@ -0,0 +1,460 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.vitro.webapp.rdfservice.impl.sparql; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.openrdf.model.Resource; +import org.openrdf.query.MalformedQueryException; +import org.openrdf.query.QueryLanguage; +import org.openrdf.query.Update; +import org.openrdf.query.UpdateExecutionException; +import org.openrdf.repository.Repository; +import org.openrdf.repository.RepositoryConnection; +import org.openrdf.repository.RepositoryException; +import org.openrdf.repository.RepositoryResult; +import org.openrdf.repository.http.HTTPRepository; + +import com.hp.hpl.jena.graph.Node; +import com.hp.hpl.jena.graph.Triple; +import com.hp.hpl.jena.query.Query; +import com.hp.hpl.jena.query.QueryExecution; +import com.hp.hpl.jena.query.QueryExecutionFactory; +import com.hp.hpl.jena.query.QueryFactory; +import com.hp.hpl.jena.query.ResultSet; +import com.hp.hpl.jena.query.ResultSetFormatter; +import com.hp.hpl.jena.rdf.model.Model; +import com.hp.hpl.jena.rdf.model.ModelFactory; +import com.hp.hpl.jena.rdf.model.Statement; +import com.hp.hpl.jena.rdf.model.StmtIterator; +import com.hp.hpl.jena.vocabulary.RDF; + +import edu.cornell.mannlib.vitro.webapp.rdfservice.ChangeListener; +import edu.cornell.mannlib.vitro.webapp.rdfservice.ChangeSet; +import edu.cornell.mannlib.vitro.webapp.rdfservice.ModelChange; +import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService; +import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFServiceException; +import edu.cornell.mannlib.vitro.webapp.rdfservice.impl.ChangeSetImpl; +import edu.cornell.mannlib.vitro.webapp.rdfservice.impl.RDFServiceImpl; + +/* + * API to write, read, and update Vitro's RDF store, with support + * to allow listening, logging and auditing. + */ + +public class RDFServiceSparql extends RDFServiceImpl implements RDFService { + + private static final Log log = LogFactory.getLog(RDFServiceImpl.class); + private String endpointURI; + private Repository repository; + + /** + * Returns an RDFService for a remote repository + * @param String - URI of the SPARQL endpoint for the knowledge base + * @param String - URI of the default write graph within the knowledge base. + * this is the graph that will be written to when a graph + * is not explicitly specified. + * + * The default read graph is the union of all graphs in the + * knowledge base + */ + public RDFServiceSparql(String endpointURI, String defaultWriteGraphURI) { + this.endpointURI = endpointURI; + this.repository = new HTTPRepository(endpointURI); + } + + public void close() { + try { + this.repository.shutDown(); + } catch (RepositoryException re) { + log.error(re, re); + } + } + + /** + * Perform a series of additions to and or removals from specified graphs + * in the RDF store. preConditionSparql will be executed against the + * union of all the graphs in the knowledge base before any updates are made. + * If the precondition query returns a non-empty result no updates + * will be made. + * + * @param ChangeSet - a set of changes to be performed on the RDF store. + * + * @return boolean - indicates whether the precondition was satisfied + */ + @Override + public boolean changeSetUpdate(ChangeSet changeSet) throws RDFServiceException { + + if (changeSet.getPreconditionQuery() != null + && !isPreconditionSatisfied( + changeSet.getPreconditionQuery(), + changeSet.getPreconditionQueryType())) { + return false; + } + + Iterator csIt = changeSet.getModelChanges().iterator(); + + while (csIt.hasNext()) { + + ModelChange modelChange = csIt.next(); + + if (modelChange.getOperation() == ModelChange.Operation.ADD) { + performAdd(modelChange); + } else if (modelChange.getOperation() == ModelChange.Operation.REMOVE) { + performRemove(modelChange); + } else { + log.error("unrecognized operation type"); + } + } + + return true; + } + + /** + * Performs a SPARQL construct query against the knowledge base. The query may have + * an embedded graph identifier. + * + * @param String query - the SPARQL query to be executed against the RDF store + * @param RDFService.ModelSerializationFormat resultFormat - type of serialization for RDF result of the SPARQL query + * @param OutputStream outputStream - the result of the query + * + */ + @Override + public InputStream sparqlConstructQuery(String queryStr, + RDFServiceImpl.ModelSerializationFormat resultFormat) throws RDFServiceException { + + Model model = ModelFactory.createDefaultModel(); + Query query = QueryFactory.create(queryStr); + QueryExecution qe = QueryExecutionFactory.sparqlService(endpointURI, query); + + try { + qe.execConstruct(model); + } finally { + qe.close(); + } + + ByteArrayOutputStream serializedModel = new ByteArrayOutputStream(); + model.write(serializedModel,getSerializationFormatString(resultFormat)); + InputStream result = new ByteArrayInputStream(serializedModel.toByteArray()); + return result; + } + + /** + * Performs a SPARQL describe query against the knowledge base. The query may have + * an embedded graph identifier. + * + * @param String query - the SPARQL query to be executed against the RDF store + * @param RDFService.ModelSerializationFormat resultFormat - type of serialization for RDF result of the SPARQL query + * + * @return InputStream - the result of the query + * + */ + @Override + public InputStream sparqlDescribeQuery(String queryStr, + RDFServiceImpl.ModelSerializationFormat resultFormat) throws RDFServiceException { + + Model model = ModelFactory.createDefaultModel(); + Query query = QueryFactory.create(queryStr); + QueryExecution qe = QueryExecutionFactory.sparqlService(endpointURI, query); + + try { + qe.execDescribe(model); + } finally { + qe.close(); + } + + ByteArrayOutputStream serializedModel = new ByteArrayOutputStream(); + model.write(serializedModel,getSerializationFormatString(resultFormat)); + InputStream result = new ByteArrayInputStream(serializedModel.toByteArray()); + return result; + } + + /** + * Performs a SPARQL select query against the knowledge base. The query may have + * an embedded graph identifier. + * + * @param String query - the SPARQL query to be executed against the RDF store + * @param RDFService.ResultFormat resultFormat - format for the result of the Select query + * + * @return InputStream - the result of the query + * + */ + @Override + public InputStream sparqlSelectQuery(String queryStr, RDFService.ResultFormat resultFormat) throws RDFServiceException { + + Query query = QueryFactory.create(queryStr); + QueryExecution qe = QueryExecutionFactory.sparqlService(endpointURI, query); + + try { + ResultSet resultSet = qe.execSelect(); + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + + switch (resultFormat) { + case CSV: + ResultSetFormatter.outputAsCSV(outputStream,resultSet); + break; + case TEXT: + ResultSetFormatter.out(outputStream,resultSet); + break; + case JSON: + ResultSetFormatter.outputAsJSON(outputStream, resultSet); + break; + case XML: + ResultSetFormatter.outputAsXML(outputStream, resultSet); + break; + default: + throw new RDFServiceException("unrecognized result format"); + } + + InputStream result = new ByteArrayInputStream(outputStream.toByteArray()); + return result; + } finally { + qe.close(); + } + } + + /** + * Performs a SPARQL ASK query against the knowledge base. The query may have + * an embedded graph identifier. + * + * @param String query - the SPARQL query to be executed against the RDF store + * + * @return boolean - the result of the SPARQL query + */ + @Override + public boolean sparqlAskQuery(String queryStr) throws RDFServiceException { + + Query query = QueryFactory.create(queryStr); + QueryExecution qe = QueryExecutionFactory.sparqlService(endpointURI, query); + + try { + return qe.execAsk(); + } finally { + qe.close(); + } + } + + /** + * Get a list of all the graph URIs in the RDF store. + * + * @return List - list of all the graph URIs in the RDF store + */ + //TODO - need to verify that the sesame getContextIDs method is implemented + // in such a way that it works with all triple stores that support the + // graph update API + @Override + public List getGraphURIs() throws RDFServiceException { + + List graphNodeList = new ArrayList(); + + try { + RepositoryConnection conn = getConnection(); + try { + RepositoryResult conResult = conn.getContextIDs(); + while (conResult.hasNext()) { + Resource res = conResult.next(); + graphNodeList.add(res.stringValue()); + } + } finally { + conn.close(); + } + } catch (RepositoryException re) { + throw new RuntimeException(re); + } + + return graphNodeList; + } + + /** + * TODO - what is the definition of this method? + * @return + */ + @Override + public void getGraphMetadata() throws RDFServiceException { + + } + + /** + * Get the URI of the default write graph + * + * @return String URI of default write graph + */ + @Override + public String getDefaultWriteGraphURI() throws RDFServiceException { + return defaultWriteGraphURI; + } + + /** + * Register a listener to listen to changes in any graph in + * the RDF store. + * + */ + @Override + public synchronized void registerListener(ChangeListener changeListener) throws RDFServiceException { + + if (!registeredListeners.contains(changeListener)) { + registeredListeners.add(changeListener); + } + } + + /** + * Unregister a listener from listening to changes in any graph + * in the RDF store. + * + */ + @Override + public synchronized void unregisterListener(ChangeListener changeListener) throws RDFServiceException { + registeredListeners.remove(changeListener); + } + + /** + * Create a ChangeSet object + * + * @return a ChangeSet object + */ + @Override + public ChangeSet manufactureChangeSet() { + return new ChangeSetImpl(); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Non-override methods below + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + protected String getEndpointURI() { + return endpointURI; + } + + protected RepositoryConnection getConnection() { + try { + return this.repository.getConnection(); + } catch (RepositoryException e) { + throw new RuntimeException(e); + } + } + + protected void executeUpdate(String updateString) { + try { + RepositoryConnection conn = getConnection(); + try { + Update u = conn.prepareUpdate(QueryLanguage.SPARQL, updateString); + u.execute(); + } catch (MalformedQueryException e) { + throw new RuntimeException(e); + } catch (UpdateExecutionException e) { + log.error(e,e); + log.error("Update command: \n" + updateString); + throw new RuntimeException(e); + } finally { + conn.close(); + } + } catch (RepositoryException re) { + throw new RuntimeException(re); + } + } + + protected void addTriple(Triple t, String graphURI) { + + StringBuffer updateString = new StringBuffer(); + updateString.append("INSERT DATA { "); + updateString.append((graphURI != null) ? "GRAPH <" + graphURI + "> { " : "" ); + updateString.append(sparqlNodeUpdate(t.getSubject(), "")); + updateString.append(" "); + updateString.append(sparqlNodeUpdate(t.getPredicate(), "")); + updateString.append(" "); + updateString.append(sparqlNodeUpdate(t.getObject(), "")); + updateString.append(" }"); + updateString.append((graphURI != null) ? " } " : ""); + + executeUpdate(updateString.toString()); + notifyListeners(t, ModelChange.Operation.ADD, graphURI); + } + + protected void removeTriple(Triple t, String graphURI) { + + StringBuffer updateString = new StringBuffer(); + updateString.append("DELETE DATA { "); + updateString.append((graphURI != null) ? "GRAPH <" + graphURI + "> { " : "" ); + updateString.append(sparqlNodeUpdate(t.getSubject(), "")); + updateString.append(" "); + updateString.append(sparqlNodeUpdate(t.getPredicate(), "")); + updateString.append(" "); + updateString.append(sparqlNodeUpdate(t.getObject(), "")); + updateString.append(" }"); + updateString.append((graphURI != null) ? " } " : ""); + + executeUpdate(updateString.toString()); + notifyListeners(t, ModelChange.Operation.REMOVE, graphURI); + } + + @Override + protected boolean isPreconditionSatisfied(String query, + RDFService.SPARQLQueryType queryType) + throws RDFServiceException { + Model model = ModelFactory.createDefaultModel(); + + switch (queryType) { + case DESCRIBE: + model.read(sparqlDescribeQuery(query,RDFService.ModelSerializationFormat.N3), null); + return !model.isEmpty(); + case CONSTRUCT: + model.read(sparqlConstructQuery(query,RDFService.ModelSerializationFormat.N3), null); + return !model.isEmpty(); + case SELECT: + return sparqlSelectQueryHasResults(query); + case ASK: + return sparqlAskQuery(query); + default: + throw new RDFServiceException("unrecognized SPARQL query type"); + } + } + + @Override + protected boolean sparqlSelectQueryHasResults(String queryStr) throws RDFServiceException { + + Query query = QueryFactory.create(queryStr); + QueryExecution qe = QueryExecutionFactory.sparqlService(endpointURI, query); + + try { + ResultSet resultSet = qe.execSelect(); + return resultSet.hasNext(); + } finally { + qe.close(); + } + } + + protected void performAdd(ModelChange modelChange) throws RDFServiceException { + + Model model = ModelFactory.createDefaultModel(); + model.read(modelChange.getSerializedModel(),getSerializationFormatString(modelChange.getSerializationFormat())); + + StmtIterator stmtIt = model.listStatements(); + + while (stmtIt.hasNext()) { + Statement stmt = stmtIt.next(); + Triple triple = new Triple(stmt.getSubject().asNode(), stmt.getPredicate().asNode(), stmt.getObject().asNode()); + addTriple(triple, modelChange.getGraphURI()); + } + } + + protected void performRemove(ModelChange modelChange) throws RDFServiceException { + + Model model = ModelFactory.createDefaultModel(); + model.read(modelChange.getSerializedModel(),getSerializationFormatString(modelChange.getSerializationFormat())); + + StmtIterator stmtIt = model.listStatements(); + + while (stmtIt.hasNext()) { + Statement stmt = stmtIt.next(); + Triple triple = new Triple(stmt.getSubject().asNode(), stmt.getPredicate().asNode(), stmt.getObject().asNode()); + removeTriple(triple, modelChange.getGraphURI()); + } + } + +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/search/VitroSearchTermNames.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/search/VitroSearchTermNames.java index a98adb5d5..059b7ce3c 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/search/VitroSearchTermNames.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/search/VitroSearchTermNames.java @@ -25,8 +25,6 @@ public class VitroSearchTermNames { public static String ALLTEXTUNSTEMMED = "ALLTEXTUNSTEMMED"; /** Does the individual have a thumbnail image? 1=yes 0=no */ public static final String THUMBNAIL = "THUMBNAIL"; - /** Should individual be included in full text search results? 1=yes 0=no */ - public static final String PROHIBITED_FROM_TEXT_RESULTS = "PROHIBITED_FROM_TEXT_RESULTS"; /** class names in human readable form of an individual*/ public static final String CLASSLOCALNAMELOWERCASE = "classLocalNameLowerCase"; /** class names in human readable form of an individual*/ diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/search/beans/IndividualProhibitedFromSearch.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/search/beans/IndividualProhibitedFromSearch.java deleted file mode 100644 index a75777624..000000000 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/search/beans/IndividualProhibitedFromSearch.java +++ /dev/null @@ -1,8 +0,0 @@ -/* $This file is distributed under the terms of the license in /doc/license.txt$ */ - - -package edu.cornell.mannlib.vitro.webapp.search.beans; - -public interface IndividualProhibitedFromSearch { - public boolean isIndividualProhibited(String uri); -} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/search/beans/IndividualProhibitedFromSearchImpl.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/search/beans/IndividualProhibitedFromSearchImpl.java deleted file mode 100644 index 6080eb0f8..000000000 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/search/beans/IndividualProhibitedFromSearchImpl.java +++ /dev/null @@ -1,84 +0,0 @@ -/* $This file is distributed under the terms of the license in /doc/license.txt$ */ - -package edu.cornell.mannlib.vitro.webapp.search.beans; - -import javax.servlet.ServletContext; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import com.hp.hpl.jena.ontology.OntModel; -import com.hp.hpl.jena.query.Query; -import com.hp.hpl.jena.query.QueryExecution; -import com.hp.hpl.jena.query.QueryExecutionFactory; -import com.hp.hpl.jena.query.QueryFactory; -import com.hp.hpl.jena.shared.Lock; -import com.hp.hpl.jena.vocabulary.OWL; -import com.hp.hpl.jena.vocabulary.RDF; - -import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary; -import edu.cornell.mannlib.vitro.webapp.dao.jena.ModelContext; - -public class IndividualProhibitedFromSearchImpl implements IndividualProhibitedFromSearch { - - protected OntModel fullModel; - - protected static Log log = LogFactory.getLog(IndividualProhibitedFromSearchImpl.class); - - public IndividualProhibitedFromSearchImpl( ServletContext context ){ - this.fullModel = ModelContext.getUnionOntModelSelector(context).getFullModel(); - } - - public IndividualProhibitedFromSearchImpl( OntModel fullModel ){ - this.fullModel = fullModel; - } - - public boolean isIndividualProhibited(String uri){ - if( uri == null || uri.isEmpty() ) - return true; - - boolean prohibited = false; - QueryExecution qexec = null; - try { - fullModel.getLock().enterCriticalSection(Lock.READ); - Query query = makeAskQueryForUri( uri ); - qexec = QueryExecutionFactory.create( query, fullModel); - prohibited = qexec.execAsk(); - } finally { - if( qexec != null ) qexec.close(); - fullModel.getLock().leaveCriticalSection(); - } - if( prohibited ) - log.debug("prohibited " + uri); - - return prohibited; - } - - private Query makeAskQueryForUri( String uri ){ - String queryString = - "PREFIX fn: \n" + - - "ASK { \n" + - " <"+uri+"> <" + RDF.type.getURI() + "> ?type . \n" + - - " FILTER ( \n" + - - " ( fn:starts-with( str(?type), \"" + VitroVocabulary.vitroURI + "\" ) \n" + - " && \n"+ - " ! fn:starts-with( str(?type), \"" + VitroVocabulary.vitroURI + "Flag\" ) ) || \n" + - - " fn:starts-with( str(?type), \"" + VitroVocabulary.PUBLIC + "\" ) || \n" + - - " str(?type) = \"" + OWL.ObjectProperty.getURI() + "\" || \n" + - - " str(?type) = \"" + OWL.DatatypeProperty.getURI() + "\" || \n" + - - " str(?type) = \"" + OWL.AnnotationProperty.getURI() + "\" \n" + - - " )\n" + - "}" ; - - - return QueryFactory.create( queryString ); - } -} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/search/controller/PagedSearchController.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/search/controller/PagedSearchController.java index 20cfc3e08..7b29e95c0 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/search/controller/PagedSearchController.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/search/controller/PagedSearchController.java @@ -51,7 +51,6 @@ import edu.cornell.mannlib.vitro.webapp.search.beans.VitroQueryFactory; import edu.cornell.mannlib.vitro.webapp.search.solr.SolrSetup; import edu.cornell.mannlib.vitro.webapp.web.templatemodels.LinkTemplateModel; import edu.cornell.mannlib.vitro.webapp.web.templatemodels.searchresult.IndividualSearchResult; -import freemarker.template.Configuration; /** * Paged search controller that uses Solr @@ -104,12 +103,11 @@ public class PagedSearchController extends FreemarkerHttpServlet { super.doGet(vreq,response); }else{ try { - Configuration config = getConfig(vreq); ResponseValues rvalues = processRequest(vreq); response.setCharacterEncoding("UTF-8"); response.setContentType("text/xml;charset=UTF-8"); - writeTemplate(rvalues.getTemplateName(), rvalues.getMap(), config, request, response); + writeTemplate(rvalues.getTemplateName(), rvalues.getMap(), request, response); } catch (Exception e) { log.error(e, e); } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/search/solr/ExcludeBasedOnNamespace.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/search/solr/ExcludeBasedOnNamespace.java new file mode 100644 index 000000000..8bf0e2aae --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/search/solr/ExcludeBasedOnNamespace.java @@ -0,0 +1,34 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ +package edu.cornell.mannlib.vitro.webapp.search.solr; + +import java.util.Arrays; +import java.util.List; + +import edu.cornell.mannlib.vitro.webapp.beans.Individual; + +/** + * Skip individual if its URI is from any of the excludeNamepsaces + * + */ +public class ExcludeBasedOnNamespace implements SearchIndexExcluder { + + List excludeNamepsaces; + + + public ExcludeBasedOnNamespace(String ... excludeNamepsaces) { + super(); + this.excludeNamepsaces = Arrays.asList(excludeNamepsaces); + } + + + @Override + public String checkForExclusion(Individual ind) { + for( String ns: excludeNamepsaces){ + if( ns.equals( ind.getNamespace() ) ){ + return "skipping because of namespace " ; + } + } + return null; + } + +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/search/solr/ExcludeBasedOnType.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/search/solr/ExcludeBasedOnType.java new file mode 100644 index 000000000..e61e6f4ce --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/search/solr/ExcludeBasedOnType.java @@ -0,0 +1,60 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ +package edu.cornell.mannlib.vitro.webapp.search.solr; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import edu.cornell.mannlib.vitro.webapp.beans.Individual; +import edu.cornell.mannlib.vitro.webapp.beans.VClass; + +/** + * Exclude individual from search index if + * it is a member of any of the the types. + * @author bdc34 + * + */ +public class ExcludeBasedOnType implements SearchIndexExcluder { + + List typeURIs; + + public ExcludeBasedOnType(String ... typeURIs) { + setExcludedTypes( typeURIs ); + } + + @Override + public String checkForExclusion(Individual ind) { + if( ind != null ) { + List vclasses = ind.getVClasses(); + if( vclasses != null && ! Collections.disjoint(vclasses, typeURIs) ){ + return("skipping due to type."); + } + } + return null; + } + + public void setExcludedTypes(String ... typeURIs){ + setExcludedTypes(Arrays.asList(typeURIs)); + } + + public void setExcludedTypes(List typeURIs){ + synchronized(this){ + this.typeURIs = new ArrayList(typeURIs); + } + } + + protected void addTypeToExclude(String typeURI){ + if( typeURI != null && !typeURI.isEmpty()){ + synchronized(this){ + typeURIs.add(typeURI); + } + } + } + + protected void removeTypeToExclude(String typeURI){ + synchronized(this){ + typeURIs.remove(typeURI); + } + } +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/search/solr/ExcludeBasedOnTypeNamespace.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/search/solr/ExcludeBasedOnTypeNamespace.java new file mode 100644 index 000000000..a2219d8a6 --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/search/solr/ExcludeBasedOnTypeNamespace.java @@ -0,0 +1,58 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ +package edu.cornell.mannlib.vitro.webapp.search.solr; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.solr.common.SolrInputDocument; + +import edu.cornell.mannlib.vitro.webapp.beans.Individual; +import edu.cornell.mannlib.vitro.webapp.beans.VClass; + +/** + * Exclude individuals based on the namespaces of their types. + */ +public class ExcludeBasedOnTypeNamespace implements SearchIndexExcluder { + + final List namespaces; + Pattern nsRegexPattern; + + public ExcludeBasedOnTypeNamespace(String ... namespaces) { + super(); + this.namespaces = Collections.unmodifiableList(Arrays.asList( namespaces )); + String nsOrPattern = ""; + for( int i=0; i vclasses) { + for( VClass type: vclasses ){ + if( type != null && type.getURI() != null ){ + String typeURI = type.getURI(); + + if(typeURI.startsWith( VitroVocabulary.vitroURI ) + && ! typeURI.startsWith(VitroVocabulary.vitroURI + "Flag") ){ + + return "Skipped " + ind.getURI()+" because in " + + VitroVocabulary.vitroURI + " namespace"; + } + } + } + return null; + } + +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/search/solr/IndividualToSolrDocument.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/search/solr/IndividualToSolrDocument.java index 66529aa43..349d1e111 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/search/solr/IndividualToSolrDocument.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/search/solr/IndividualToSolrDocument.java @@ -2,8 +2,6 @@ package edu.cornell.mannlib.vitro.webapp.search.solr; -import org.jsoup.Jsoup; - import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; @@ -14,6 +12,7 @@ import org.apache.commons.logging.LogFactory; import org.apache.solr.common.SolrDocument; import org.apache.solr.common.SolrInputDocument; import org.joda.time.DateTime; +import org.jsoup.Jsoup; import com.hp.hpl.jena.vocabulary.OWL; @@ -26,50 +25,35 @@ import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary; import edu.cornell.mannlib.vitro.webapp.search.IndexingException; import edu.cornell.mannlib.vitro.webapp.search.VitroSearchTermNames; import edu.cornell.mannlib.vitro.webapp.search.beans.ClassProhibitedFromSearch; -import edu.cornell.mannlib.vitro.webapp.search.beans.IndividualProhibitedFromSearch; public class IndividualToSolrDocument { public static final Log log = LogFactory.getLog(IndividualToSolrDocument.class.getName()); - public static VitroSearchTermNames term = new VitroSearchTermNames(); - - protected static String entClassName = Individual.class.getName(); - - protected ClassProhibitedFromSearch classesProhibitedFromSearch; - - protected IndividualProhibitedFromSearch individualProhibitedFromSearch; + public static VitroSearchTermNames term = new VitroSearchTermNames(); protected final String label = "http://www.w3.org/2000/01/rdf-schema#label"; protected List documentModifiers = new ArrayList(); - - public IndividualToSolrDocument( - ClassProhibitedFromSearch classesProhibitedFromSearch, - IndividualProhibitedFromSearch individualProhibitedFromSearch){ - - this( classesProhibitedFromSearch, - individualProhibitedFromSearch, - Collections.EMPTY_LIST); - } - - public IndividualToSolrDocument( - ClassProhibitedFromSearch classesProhibitedFromSearch, - IndividualProhibitedFromSearch individualProhibitedFromSearch, - List docModifiers){ - this.classesProhibitedFromSearch = classesProhibitedFromSearch; - this.individualProhibitedFromSearch = individualProhibitedFromSearch; - this.documentModifiers = docModifiers; - } - + protected List excludes; + + public IndividualToSolrDocument(List excludes, List docModifiers){ + this.excludes = excludes; + this.documentModifiers = docModifiers; + } @SuppressWarnings("static-access") public SolrInputDocument translate(Individual ind) throws IndexingException{ try{ log.debug("translating " + ind.getURI()); - checkForSkipBasedOnNS( ind ); - + + String excludeMsg = checkExcludes( ind ); + if( excludeMsg != DONT_EXCLUDE){ + log.debug(excludeMsg); + return null; + } + SolrInputDocument doc = new SolrInputDocument(); //DocID @@ -77,44 +61,30 @@ public class IndividualToSolrDocument { //vitro id doc.addField(term.URI, ind.getURI()); - - //java class - doc.addField(term.JCLASS, entClassName); - + //Individual Label addLabel( ind, doc ); //add classes, classgroups get if prohibied becasue of its class StringBuffer classPublicNames = new StringBuffer(""); - boolean prohibited = addClasses(ind, doc, classPublicNames); - - //filter out class groups, owl:ObjectProperties etc.. - if(individualProhibitedFromSearch.isIndividualProhibited( ind.getURI() )){ - return null; - } - + addClasses(ind, doc, classPublicNames); + // collecting URIs and rdfs:labels of objects of statements StringBuffer objectNames = new StringBuffer(""); StringBuffer addUri = new StringBuffer(""); - addObjectPropertyText(ind, doc, objectNames, addUri); - - //add if the individual has a thumbnail or not. - addThumbnailExistance(ind, doc); + addObjectPropertyText(ind, doc, objectNames, addUri); //time of index in millis past epoc doc.addField(term.INDEXEDTIME, new Long( (new DateTime()).getMillis() ) ); - - if(!prohibited){ - addAllText( ind, doc, classPublicNames, objectNames ); + + addAllText( ind, doc, classPublicNames, objectNames ); - runAdditionalDocModifers(ind,doc,addUri); - - //boost for entity - if(documentModifiers == null || documentModifiers.isEmpty() && - (ind.getSearchBoost() != null && ind.getSearchBoost() != 0)) { - doc.setDocumentBoost(ind.getSearchBoost()); - } - } + //boost for entity + if(ind.getSearchBoost() != null && ind.getSearchBoost() != 0) { + doc.setDocumentBoost(ind.getSearchBoost()); + } + + runAdditionalDocModifers(ind,doc,addUri); return doc; }catch(SkipIndividualException ex){ @@ -122,7 +92,7 @@ public class IndividualToSolrDocument { log.debug(ex); return null; }catch(Throwable th){ - //Odd exceptions from jena get thrown on shutdown + //Odd exceptions can get thrown on shutdown if( log != null ) log.debug(th); return null; @@ -130,7 +100,20 @@ public class IndividualToSolrDocument { } - protected void runAdditionalDocModifers( Individual ind, SolrInputDocument doc, StringBuffer addUri ) + protected String checkExcludes(Individual ind) { + for( SearchIndexExcluder excluder : excludes){ + try{ + String msg = excluder.checkForExclusion(ind); + if( msg != DONT_EXCLUDE) + return msg; + }catch (Exception e) { + return e.getMessage(); + } + } + return DONT_EXCLUDE; + } + + protected void runAdditionalDocModifers( Individual ind, SolrInputDocument doc, StringBuffer addUri ) throws SkipIndividualException{ //run the document modifiers if( documentModifiers != null && !documentModifiers.isEmpty()){ @@ -140,18 +123,6 @@ public class IndividualToSolrDocument { } } - protected void checkForSkipBasedOnNS(Individual ind) throws SkipIndividualException { - String id = ind.getURI(); - if(id == null){ - throw new SkipIndividualException("cannot add individuals without URIs to search index"); - }else if( id.startsWith(VitroVocabulary.vitroURI) || - id.startsWith(VitroVocabulary.VITRO_PUBLIC) || - id.startsWith(VitroVocabulary.PSEUDO_BNODE_NS) || - id.startsWith(OWL.NS)){ - throw new SkipIndividualException("not indexing because of namespace:" + id); - } - } - protected void addAllText(Individual ind, SolrInputDocument doc, StringBuffer classPublicNames, StringBuffer objectNames) { String t=null; //ALLTEXT, all of the 'full text' @@ -210,19 +181,7 @@ public class IndividualToSolrDocument { // NAME_LOWERCASE, NAME_UNSTEMMED, NAME_STEMMED, NAME_PHONETIC, AC_NAME_UNTOKENIZED, AC_NAME_STEMMED } - /** - * Adds if the individual has a thumbnail image or not. - */ - protected void addThumbnailExistance(Individual ind, SolrInputDocument doc) { - try{ - if(ind.hasThumb()) - doc.addField(term.THUMBNAIL, "1"); - else - doc.addField(term.THUMBNAIL, "0"); - }catch(Exception ex){ - log.debug("could not index thumbnail: " + ex); - } - } + /** * Get the rdfs:labes for objects of statements and put in objectNames. @@ -258,32 +217,24 @@ public class IndividualToSolrDocument { * @returns true if prohibited from search * @throws SkipIndividualException */ - protected boolean addClasses(Individual ind, SolrInputDocument doc, StringBuffer classPublicNames) throws SkipIndividualException{ + protected void addClasses(Individual ind, SolrInputDocument doc, StringBuffer classPublicNames) throws SkipIndividualException{ ArrayList superClassNames = null; - // Types and classgroups - boolean prohibited = false; List vclasses = ind.getVClasses(false); - superClassNames = new ArrayList(); + if( vclasses == null || vclasses.isEmpty() ){ + throw new SkipIndividualException("Not indexing because individual has no super classes"); + } + for(VClass clz : vclasses){ - String superLclName = clz.getLocalName(); - superClassNames.add(superLclName); if(clz.getURI() == null){ continue; }else if(OWL.Thing.getURI().equals(clz.getURI())){ - //index individuals of type owl:Thing, just don't add owl:Thing as the type field in the index + //don't add owl:Thing as the type in the index continue; - } else if(clz.getURI().startsWith(OWL.NS)){ - throw new SkipIndividualException("not indexing " + ind.getURI() + " because of type " + clz.getURI() ); - } - // do not index individuals of type Role, AdvisingRelationShip, Authorship, etc.(see search.n3 for more information) - else if(classesProhibitedFromSearch.isClassProhibitedFromSearch(clz.getURI())){ - throw new SkipIndividualException("not indexing " + ind.getURI() + " because of prohibited type " + clz.getURI() ); - } else { - if( !prohibited && classesProhibitedFromSearch.isClassProhibitedFromSearch(clz.getURI())) - prohibited = true; - if( clz.getSearchBoost() != null) + } else { + if( clz.getSearchBoost() != null){ doc.setDocumentBoost(doc.getDocumentBoost() + clz.getSearchBoost()); + } doc.addField(term.RDFTYPE, clz.getURI()); @@ -302,14 +253,7 @@ public class IndividualToSolrDocument { doc.addField(term.CLASSGROUP_URI,clz.getGroupURI()); } } - } - - if(superClassNames.isEmpty()){ - throw new SkipIndividualException("Not indexing because individual has no super classes"); - } - - doc.addField(term.PROHIBITED_FROM_TEXT_RESULTS, prohibited?"1":"0"); - return prohibited; + } } public Object getIndexId(Object obj) { @@ -318,7 +262,7 @@ public class IndividualToSolrDocument { public String getIdForUri(String uri){ if( uri != null ){ - return entClassName + uri; + return "vitroIndividual:" + uri; }else{ return null; } @@ -352,6 +296,5 @@ public class IndividualToSolrDocument { } } - public static float NAME_BOOST = 1.2F; - + protected static final String DONT_EXCLUDE =null; } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/search/solr/NameBoost.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/search/solr/NameBoost.java index 66ebc6ce2..63aaa8698 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/search/solr/NameBoost.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/search/solr/NameBoost.java @@ -10,10 +10,21 @@ import edu.cornell.mannlib.vitro.webapp.search.VitroSearchTermNames; public class NameBoost implements DocumentModifier { - static VitroSearchTermNames term = new VitroSearchTermNames(); + /** + * These are the fields in the solr Document that + * are related to the name. If you modify the schema, + * please consider if you need to change this list + * of name fields to boost. + */ + static final VitroSearchTermNames term = new VitroSearchTermNames(); String[] fieldsToBoost = {term.NAME_RAW,term.NAME_LOWERCASE,term.NAME_UNSTEMMED,term.NAME_STEMMED}; - static final float NAME_BOOST = (float) 1.2; + + final float boost; + + public NameBoost(float boost){ + this.boost = boost; + } @Override public void modifyDocument(Individual individual, SolrInputDocument doc, @@ -21,8 +32,9 @@ public class NameBoost implements DocumentModifier { for( String fieldName : fieldsToBoost){ SolrInputField field = doc.getField(fieldName); - if( field != null ) - field.setBoost(field.getBoost() * NAME_BOOST); + if( field != null ){ + field.setBoost(field.getBoost() + boost); + } } } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/search/solr/SearchIndexExcluder.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/search/solr/SearchIndexExcluder.java new file mode 100644 index 000000000..1507d9397 --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/search/solr/SearchIndexExcluder.java @@ -0,0 +1,19 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ +package edu.cornell.mannlib.vitro.webapp.search.solr; + +import edu.cornell.mannlib.vitro.webapp.beans.Individual; + +/** + * Interface for classes that check to see if an individual + * should be excluded from the search index. + */ +public interface SearchIndexExcluder { + + /** + * REturn a string message if the individual should + * be excluded from the index. + * + * Return null if ind should not be excluded. + */ + public String checkForExclusion(Individual ind); +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/search/solr/SolrSetup.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/search/solr/SolrSetup.java index a1d37e2e5..a3e4ad92e 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/search/solr/SolrSetup.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/search/solr/SolrSetup.java @@ -18,17 +18,19 @@ import org.apache.solr.client.solrj.impl.CommonsHttpSolrServer; import org.apache.solr.client.solrj.impl.XMLResponseParser; import com.hp.hpl.jena.ontology.OntModel; +import com.hp.hpl.jena.rdf.model.Model; +import com.hp.hpl.jena.vocabulary.OWL; import edu.cornell.mannlib.vitro.webapp.config.ConfigurationProperties; import edu.cornell.mannlib.vitro.webapp.dao.DisplayVocabulary; import edu.cornell.mannlib.vitro.webapp.dao.IndividualDao; +import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary; import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory; import edu.cornell.mannlib.vitro.webapp.dao.filtering.WebappDaoFactoryFiltering; import edu.cornell.mannlib.vitro.webapp.dao.filtering.filters.VitroFilterUtils; import edu.cornell.mannlib.vitro.webapp.dao.filtering.filters.VitroFilters; import edu.cornell.mannlib.vitro.webapp.dao.jena.ModelContext; import edu.cornell.mannlib.vitro.webapp.search.beans.FileBasedProhibitedFromSearch; -import edu.cornell.mannlib.vitro.webapp.search.beans.IndividualProhibitedFromSearchImpl; import edu.cornell.mannlib.vitro.webapp.search.beans.ProhibitedFromSearch; import edu.cornell.mannlib.vitro.webapp.search.beans.StatementToURIsToUpdate; import edu.cornell.mannlib.vitro.webapp.search.indexing.AdditionalURIsForContextNodes; @@ -40,11 +42,32 @@ import edu.cornell.mannlib.vitro.webapp.search.indexing.SearchReindexingListener import edu.cornell.mannlib.vitro.webapp.search.indexing.URIsForClassGroupChange; import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus; -public class SolrSetup implements javax.servlet.ServletContextListener{ - private static final Log log = LogFactory.getLog(SolrSetup.class.getName()); +public class SolrSetup implements javax.servlet.ServletContextListener{ public static final String SOLR_SERVER = "vitro.local.solr.server"; public static final String PROHIBITED_FROM_SEARCH = "edu.cornell.mannlib.vitro.webapp.search.beans.ProhibitedFromSearch"; + + /** Exclude from the search index Individuals with types from these namespaces */ + private static final String[] TYPE_NS_EXCLUDES = { + VitroVocabulary.PUBLIC + //if you do OWL.NS here you will exclude all of owl:Thing. + }; + + /** Exclude from the search index individuals who's URIs start with these namespaces. */ + private static final String[] INDIVIDUAL_NS_EXCLUDES={ + VitroVocabulary.vitroURI, + VitroVocabulary.VITRO_PUBLIC, + VitroVocabulary.PSEUDO_BNODE_NS, + OWL.NS + }; + + + /** Individuals of these types will be excluded from the search index */ + private static final String[] OWL_TYPES_EXCLUDES = { + OWL.ObjectProperty.getURI(), + OWL.DatatypeProperty.getURI(), + OWL.AnnotationProperty.getURI() + }; @Override public void contextInitialized(ServletContextEvent sce) { @@ -85,31 +108,42 @@ public class SolrSetup implements javax.servlet.ServletContextListener{ /* set up the individual to solr doc translation */ OntModel jenaOntModel = ModelContext.getJenaOntModel(context); + Model displayModel = ModelContext.getDisplayModel(context); /* try to get context attribute DocumentModifiers * and use that as the start of the list of DocumentModifier - * objects. This allows other listeners to add to the basic set of - * DocumentModifiers. */ - List modifiers = (List)context.getAttribute("DocumentModifiers"); + * objects. This allows other ContextListeners to add to + * the basic set of DocumentModifiers. */ + @SuppressWarnings("unchecked") + List modifiers = + (List)context.getAttribute("DocumentModifiers"); if( modifiers == null ) modifiers = new ArrayList(); - modifiers.add(new NameBoost()); - modifiers.add(new ThumbnailImageURL(jenaOntModel)); + + modifiers.add(new NameBoost( 1.2f )); + modifiers.add(new ThumbnailImageURL(jenaOntModel)); - // setup prohibited from search based on N3 files in the directory WEB-INF/ontologies/search + /* try to get context attribute SearchIndexExcludes + * and use that as the start of the list of exclude + * objects. This allows other ContextListeners to add to + * the basic set of SearchIndexExcludes . */ + @SuppressWarnings("unchecked") + List excludes = + (List)context.getAttribute("SearchIndexExcludes"); + if( excludes == null ) + excludes = new ArrayList(); - File dir = new File(sce.getServletContext().getRealPath("/WEB-INF/ontologies/search")); - ProhibitedFromSearch pfs = new FileBasedProhibitedFromSearch(DisplayVocabulary.SEARCH_INDEX_URI, dir); - context.setAttribute(PROHIBITED_FROM_SEARCH,pfs); + excludes.add(new ExcludeBasedOnNamespace( INDIVIDUAL_NS_EXCLUDES )); + excludes.add(new ExcludeBasedOnTypeNamespace( TYPE_NS_EXCLUDES ) ); + excludes.add(new ExcludeBasedOnType( OWL_TYPES_EXCLUDES) ); + excludes.add(new ExcludeNonFlagVitro() ); + excludes.add( new SyncingExcludeBasedOnType( displayModel ) ); - IndividualToSolrDocument indToSolrDoc = new IndividualToSolrDocument( - pfs, - new IndividualProhibitedFromSearchImpl(context), - modifiers); - - /* setup solr indexer */ + IndividualToSolrDocument indToSolrDoc = + new IndividualToSolrDocument(excludes, modifiers); + /* setup solr indexer */ SolrIndexer solrIndexer = new SolrIndexer(server, indToSolrDoc); // This is where the builder gets the list of places to try to diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/search/solr/SyncingExcludeBasedOnType.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/search/solr/SyncingExcludeBasedOnType.java new file mode 100644 index 000000000..a6ed8161f --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/search/solr/SyncingExcludeBasedOnType.java @@ -0,0 +1,199 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ +package edu.cornell.mannlib.vitro.webapp.search.solr; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import com.hp.hpl.jena.query.Query; +import com.hp.hpl.jena.query.QueryExecution; +import com.hp.hpl.jena.query.QueryExecutionFactory; +import com.hp.hpl.jena.query.QueryFactory; +import com.hp.hpl.jena.query.QuerySolution; +import com.hp.hpl.jena.query.QuerySolutionMap; +import com.hp.hpl.jena.query.ResultSet; +import com.hp.hpl.jena.rdf.model.Model; +import com.hp.hpl.jena.rdf.model.ModelChangedListener; +import com.hp.hpl.jena.rdf.model.RDFNode; +import com.hp.hpl.jena.rdf.model.Resource; +import com.hp.hpl.jena.rdf.model.ResourceFactory; +import com.hp.hpl.jena.rdf.model.Statement; +import com.hp.hpl.jena.rdf.model.StmtIterator; +import com.hp.hpl.jena.shared.Lock; + +import edu.cornell.mannlib.vitro.webapp.dao.DisplayVocabulary; + +/** + * This excludes based on types defined as EXCLUDE_CLASS in the + * configuration RDF model. + */ +public class SyncingExcludeBasedOnType extends ExcludeBasedOnType implements ModelChangedListener{ + static final Log log = LogFactory.getLog(SyncingExcludeBasedOnType.class); + + private static final String queryForProhibitedClasses = + "SELECT ?prohibited WHERE{" + + "?searchConfig <" + DisplayVocabulary.EXCLUDE_CLASS + "> ?prohibited . " + + "}"; + + String searchIndexURI = DisplayVocabulary.SEARCH_INDEX_URI; + + public SyncingExcludeBasedOnType( Model model){ + this.setExcludedTypes( buildProhibitedClassesList(searchIndexURI, model) ); + } + + private List buildProhibitedClassesList( String URI, Model model){ + List newProhibitedClasses = new ArrayList(); + + QuerySolutionMap initialBinding = new QuerySolutionMap(); + Resource searchConfig = ResourceFactory.createResource(URI); + initialBinding.add("searchConfig", searchConfig); + + Query query = QueryFactory.create(queryForProhibitedClasses); + model.enterCriticalSection(Lock.READ); + try{ + QueryExecution qExec = QueryExecutionFactory.create(query,model,initialBinding); + try{ + ResultSet results = qExec.execSelect(); + for(;results.hasNext();){ + QuerySolution soln = results.nextSolution(); + RDFNode n = soln.get("prohibited"); + if( n.isResource() && !n.isAnon()){ + newProhibitedClasses.add(((Resource) n).getURI()); + }else{ + log.warn("unexpected node in object position for prohibited classes: " + n.toString()); + } + } + }catch(Throwable t){ + log.error(t,t); + }finally{ qExec.close(); } + }finally{ model.leaveCriticalSection(); } + + return newProhibitedClasses; + } + + + /* ************* Methods for ModelChangeListener *************** */ + + @Override + public void addedStatement(Statement s) { + try{ + if( isExcludeClassPredicate( s ) && isAboutSearchIndex(s)){ + if( s.getObject() != null && s.getObject().canAs(Resource.class)){ + String classURI = ((Resource)s.getObject().as(Resource.class)).getURI(); + this.addTypeToExclude(classURI); + } + } + }catch(Exception ex){ + log.error("could not add statement",ex); + } + } + + @Override + public void removedStatement(Statement s) { + try{ + if( isExcludeClassPredicate( s ) && isAboutSearchIndex(s)){ + if( s.getObject() != null && s.getObject().canAs(Resource.class)){ + String classURI = ((Resource)s.getObject().as(Resource.class)).getURI(); + this.removeTypeToExclude(classURI); + } + } + }catch(Exception ex){ + log.error("could not remove statement",ex); + } + } + + private boolean isExcludeClassPredicate(Statement s){ + return s != null + && s.getPredicate() != null + && DisplayVocabulary.EXCLUDE_CLASS.getURI().equals( s.getPredicate().getURI()); + } + + private boolean isAboutSearchIndex(Statement s){ + if( s.getSubject() != null ){ + String subURI = ((Resource) s.getSubject()).getURI() ; + return this.searchIndexURI.equals(subURI); + }else{ + return false; + } + } + + @Override + public void addedStatements(Statement[] stmts) { + if( stmts != null ){ + for( Statement stmt : stmts){ + addedStatement(stmt); + } + } + } + + @Override + public void addedStatements(List stmts) { + if( stmts != null ){ + for( Statement stmt : stmts){ + addedStatement(stmt); + } + } + } + + @Override + public void addedStatements(StmtIterator it) { + while(it.hasNext()){ + Statement stmt = it.nextStatement(); + addedStatement(stmt); + } + } + + @Override + public void addedStatements(Model model) { + if( model != null){ + addedStatements(model.listStatements( + model.createResource(searchIndexURI), + DisplayVocabulary.EXCLUDE_CLASS, + (RDFNode)null)); + } + } + + @Override + public void notifyEvent(Model arg0, Object arg1) { + //nothing + } + + @Override + public void removedStatements(Statement[] stmts) { + if( stmts != null ){ + for( Statement stmt : stmts){ + removedStatement(stmt); + } + } + } + + @Override + public void removedStatements(List stmts) { + if( stmts != null ){ + for( Statement stmt : stmts){ + removedStatement(stmt); + } + } + } + + @Override + public void removedStatements(StmtIterator it) { + while(it.hasNext()){ + Statement stmt = it.nextStatement(); + removedStatement(stmt); + } + } + + @Override + public void removedStatements(Model model) { + if( model != null){ + removedStatements(model.listStatements( + model.createResource(searchIndexURI), + DisplayVocabulary.EXCLUDE_CLASS, + (RDFNode)null)); + } + } + +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/search/solr/ThumbnailImageURL.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/search/solr/ThumbnailImageURL.java index 073d582c0..0cdfbe786 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/search/solr/ThumbnailImageURL.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/search/solr/ThumbnailImageURL.java @@ -61,9 +61,23 @@ public class ThumbnailImageURL implements DocumentModifier { //add a field for storing the location of thumbnail for the individual. doc.addField(fieldForThumbnailURL, runQueryForThumbnailLocation(individual)); - + addThumbnailExistance(individual, doc); } + /** + * Adds if the individual has a thumbnail image or not. + */ + protected void addThumbnailExistance(Individual ind, SolrInputDocument doc) { + try{ + if(ind.hasThumb()) + doc.addField(term.THUMBNAIL, "1"); + else + doc.addField(term.THUMBNAIL, "0"); + }catch(Exception ex){ + log.debug("could not index thumbnail: " + ex); + } + } + protected String runQueryForThumbnailLocation(Individual individual) { StringBuffer result = new StringBuffer(); diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/services/freemarker/FreemarkerProcessingService.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/services/freemarker/FreemarkerProcessingService.java new file mode 100644 index 000000000..88abf65cf --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/services/freemarker/FreemarkerProcessingService.java @@ -0,0 +1,86 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.vitro.webapp.services.freemarker; + +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; + +/** + * Provide the ability to process a Freemarker template outside of the context + * of a FreemarkerHttpServlet. + * + * The most likely place to use this is when rendering a short view that was + * invoked through an AJAX call. + */ +public interface FreemarkerProcessingService { + /** + * Is there an accessible template by this name? + * + * The question is asked in the context of the current request, which + * determines the theme directory. + * + * @throws TemplateProcessingException + * If the template is found, but cannot be parsed. + */ + boolean isTemplateAvailable(String templateName, HttpServletRequest req) + throws TemplateProcessingException; + + /** + * Process a Freemarker template with a data map, producing string of HTML. + * + * This is done in the context of the current HttpServletRequest, which + * provides a wide range of ancillary information, including (but not + * limited to) theme directory, context path, info on logged-in user, + * authorizations for the current user, etc., etc. + */ + String renderTemplate(String templateName, Map map, + HttpServletRequest req) throws TemplateProcessingException; + + /** + * Indicates a failure to render the given template with the given data. + */ + @SuppressWarnings("serial") + public static class TemplateProcessingException extends Exception { + + public TemplateProcessingException() { + super(); + } + + public TemplateProcessingException(String message) { + super(message); + } + + public TemplateProcessingException(Throwable cause) { + super(cause); + } + + public TemplateProcessingException(String message, Throwable cause) { + super(message, cause); + } + } + + /** + * Template parser detected a problem. + */ + @SuppressWarnings("serial") + public static class TemplateParsingException extends + TemplateProcessingException { + + public TemplateParsingException() { + super(); + } + + public TemplateParsingException(String message) { + super(message); + } + + public TemplateParsingException(Throwable cause) { + super(cause); + } + + public TemplateParsingException(String message, Throwable cause) { + super(message, cause); + } + } +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/services/freemarker/FreemarkerProcessingServiceImpl.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/services/freemarker/FreemarkerProcessingServiceImpl.java new file mode 100644 index 000000000..dfcc0156b --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/services/freemarker/FreemarkerProcessingServiceImpl.java @@ -0,0 +1,99 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.vitro.webapp.services.freemarker; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.StringWriter; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; +import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerConfiguration; +import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerConfigurationLoader; +import edu.cornell.mannlib.vitro.webapp.utils.log.LogUtils; +import freemarker.core.Environment; +import freemarker.core.ParseException; +import freemarker.template.Configuration; +import freemarker.template.Template; +import freemarker.template.TemplateException; + +/** + * An implementation of the FreemarkerProcessingService. + */ +public class FreemarkerProcessingServiceImpl implements + FreemarkerProcessingService { + private static final Log log = LogFactory + .getLog(FreemarkerProcessingServiceImpl.class); + + @Override + public boolean isTemplateAvailable(String templateName, + HttpServletRequest req) throws TemplateProcessingException { + return null != getTemplate(templateName, req); + } + + @Override + public String renderTemplate(String templateName, Map map, + HttpServletRequest req) throws TemplateProcessingException { + log.debug("renderTemplate: '" + templateName + "' with " + + LogUtils.deepFormatForLog(log, "debug", map)); + Template template = getTemplate(templateName, req); + return processTemplate(template, map, req); + } + + /** + * Fetch this template from a file and parse it. If there are any problems, + * return "null". + */ + private Template getTemplate(String templateName, HttpServletRequest req) + throws TemplateProcessingException { + Template template = null; + try { + Configuration config = FreemarkerConfigurationLoader + .getConfig(new VitroRequest(req)); + template = config.getTemplate(templateName); + } catch (ParseException e) { + log.warn("Failed to parse the template at '" + templateName + "'" + + e); + throw new TemplateParsingException(e); + } catch (FileNotFoundException e) { + log.debug("No template found for '" + templateName + "'"); + throw new TemplateProcessingException(e); + } catch (IOException e) { + log.warn("Failed to read the template at '" + templateName + "'", e); + throw new TemplateProcessingException(e); + } + return template; + } + + private String processTemplate(Template template, Map map, + HttpServletRequest req) throws TemplateProcessingException { + + StringWriter writer = new StringWriter(); + try { + // Add directives to the map. For some reason, having them in the + // configuration is not enough. + map.putAll(FreemarkerConfiguration.getDirectives()); + + // Add request and servlet context as custom attributes of the + // environment, so they + // can be used in directives. + Environment env = template.createProcessingEnvironment(map, writer); + env.setCustomAttribute("request", req); + env.setCustomAttribute("context", req.getSession() + .getServletContext()); + env.process(); + return writer.toString(); + } catch (TemplateException e) { + throw new TemplateProcessingException( + "TemplateException creating processing environment", e); + } catch (IOException e) { + throw new TemplateProcessingException( + "IOException creating processing environment", e); + } + } +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/services/freemarker/FreemarkerProcessingServiceSetup.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/services/freemarker/FreemarkerProcessingServiceSetup.java new file mode 100644 index 000000000..c3b6e5e1b --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/services/freemarker/FreemarkerProcessingServiceSetup.java @@ -0,0 +1,15 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.vitro.webapp.services.freemarker; + +import javax.servlet.ServletContext; + +/** + * This would be used to create and publish such a service, but for now we can + * simply create a fresh copy every time someone asks for one. + */ +public class FreemarkerProcessingServiceSetup { + public static FreemarkerProcessingService getService(ServletContext ctx) { + return new FreemarkerProcessingServiceImpl(); + } +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/services/shortview/FakeApplicationOntologyService.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/services/shortview/FakeApplicationOntologyService.java new file mode 100644 index 000000000..7171c73a6 --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/services/shortview/FakeApplicationOntologyService.java @@ -0,0 +1,179 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.vitro.webapp.services.shortview; + +import static edu.cornell.mannlib.vitro.webapp.services.shortview.ShortViewService.ShortViewContext.BROWSE; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import javax.servlet.ServletContext; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import com.hp.hpl.jena.ontology.OntModel; +import com.hp.hpl.jena.ontology.OntModelSpec; +import com.hp.hpl.jena.rdf.model.ModelFactory; +import com.hp.hpl.jena.rdf.model.Property; +import com.hp.hpl.jena.rdf.model.Resource; + +import edu.cornell.mannlib.vitro.webapp.beans.Individual; +import edu.cornell.mannlib.vitro.webapp.beans.VClass; +import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; +import edu.cornell.mannlib.vitro.webapp.dao.DisplayVocabulary; +import edu.cornell.mannlib.vitro.webapp.dao.VClassDao; +import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory; +import edu.cornell.mannlib.vitro.webapp.utils.dataGetter.DataGetter; +import edu.cornell.mannlib.vitro.webapp.utils.dataGetter.SparqlQueryDataGetter; + +/** + * TODO + * + * Get rid of this when the Application Ontology is implemented. + */ +public class FakeApplicationOntologyService { + private static final Log log = LogFactory + .getLog(FakeApplicationOntologyService.class); + + private static final String FACULTY_MEMBER_CLASS_URI = "http://vivoweb.org/ontology/core#FacultyMember"; + private static final String PEOPLE_CLASSGROUP_URI = "http://vivoweb.org/ontology#vitroClassGrouppeople"; + + /** + * Return the template name and DataGetter instances associated with this + * class and this short view context. If none, return null. + */ + public TemplateAndDataGetters getShortViewProperties(VitroRequest vreq, + Individual individual, String classUri, String contextName) { + if ((BROWSE.name().equals(contextName)) + && (isClassInPeopleClassGroup(vreq.getWebappDaoFactory(), + classUri))) { + return new TemplateAndDataGetters("view-browse-people.ftl", + new FakeVivoPeopleDataGetter(vreq, individual.getURI())); + } + // A mockup of Tammy's use case. + // if ((SEARCH.name().equals(contextName)) + // && (classUri.equals(FACULTY_MEMBER_CLASS_URI))) { + // return new TemplateAndDataGetters("view-search-faculty.ftl", new + // FakeFacultyDataGetter()); + // } else { + return null; + // } + } + + /** The info associated with a short view. */ + public static class TemplateAndDataGetters { + private final String templateName; + private final Set dataGetters; + + public TemplateAndDataGetters(String templateName, + DataGetter... dataGetters) { + this.templateName = templateName; + this.dataGetters = new HashSet( + Arrays.asList(dataGetters)); + } + + public String getTemplateName() { + return templateName; + } + + public Set getDataGetters() { + return dataGetters; + } + + } + + private boolean isClassInPeopleClassGroup(WebappDaoFactory wadf, + String classUri) { + if (wadf == null) { + log.debug("isClassInPeopleClassGroup: WebappDaoFactory is null."); + return false; + } + + VClassDao vcDao = wadf.getVClassDao(); + if (vcDao == null) { + log.debug("isClassInPeopleClassGroup: VClassDao is null."); + return false; + } + + VClass vclass = vcDao.getVClassByURI(classUri); + if (vclass == null) { + log.debug("isClassInPeopleClassGroup: VClass is null."); + return false; + } + + String vclassGroupUri = vclass.getGroupURI(); + if (vclassGroupUri == null) { + log.debug("isClassInPeopleClassGroup: vclassGroupUri is null."); + return false; + } + + boolean isPeople = PEOPLE_CLASSGROUP_URI.equals(vclassGroupUri); + log.debug("isClassInPeopleClassGroup: isPeople = " + isPeople); + return isPeople; + } + + private static class FakeFacultyDataGetter implements DataGetter { + @Override + public Map getData(Map valueMap) { + Map map = new HashMap(); + Map extras = new HashMap(); + extras.put("departmentName", "Department of Redundancy Department"); + map.put("extra", extras); + return map; + } + } + + /** + * A SPARQL query data getter that initializes itself from its own private + * "display model". The query finds a preferred title for the individual. + */ + private static class FakeVivoPeopleDataGetter extends SparqlQueryDataGetter { + private static final String QUERY_STRING = "SELECT ?uri ?pt WHERE {\n" + + " ?uri ?pt\n" + + "} LIMIT 1"; + + private static final String FAKE_VIVO_PEOPLE_DATA_GETTER_URI = "http://FakeVivoPeopleDataGetter"; + + private static OntModel fakeDisplayModel = initializeFakeDisplayModel(); + + private static OntModel initializeFakeDisplayModel() { + OntModel m = ModelFactory + .createOntologyModel(OntModelSpec.OWL_DL_MEM); + + Resource dataGetter = m + .getResource(FAKE_VIVO_PEOPLE_DATA_GETTER_URI); + Property queryProperty = m.getProperty(DisplayVocabulary.QUERY); + Property saveToVarProperty = m + .getProperty(DisplayVocabulary.SAVE_TO_VAR); + + m.add(dataGetter, queryProperty, QUERY_STRING); + m.add(dataGetter, saveToVarProperty, "extra"); + return m; + } + + private String individualUri; + private VitroRequest vreq; + private ServletContext ctx; + + public FakeVivoPeopleDataGetter(VitroRequest vreq, String individualUri) { + super(vreq, fakeDisplayModel, "http://FakeVivoPeopleDataGetter"); + this.individualUri = individualUri; + this.vreq = vreq; + this.ctx = vreq.getSession().getServletContext(); + } + + @Override + public Map getData(Map pageData) { + Map parms = new HashMap(); + parms.put("uri", new String[] { individualUri }); + + return doQuery(parms, getModel(ctx, vreq, null)); + } + + } + +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/services/shortview/ShortViewService.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/services/shortview/ShortViewService.java new file mode 100644 index 000000000..7a494c375 --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/services/shortview/ShortViewService.java @@ -0,0 +1,97 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.vitro.webapp.services.shortview; + +import java.util.Map; + +import org.apache.commons.lang.StringUtils; + +import edu.cornell.mannlib.vitro.webapp.beans.Individual; +import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; + +/** + * Define a service that will produce HTML snippets for short views on + * Individuals. + */ +public interface ShortViewService { + + /** + * Render the short view template that applies to this individual in this + * context. The data in the modelMap can be used to populate the template, + * along with any additional data returned by custom data getters. + * + * If there are any problems, return a dummy piece of text that includes the + * label of the individual. Never return null or empty string. + * + * This method should not be called from within an ongoing Freemarker + * process. In that case, use getShortViewInfo() instead. + */ + String renderShortView(Individual individual, ShortViewContext context, + Map modelMap, VitroRequest vreq); + + /** + * What template should be used to render the short view of this individual + * in this context? What data is available from custom data getters? + * + * Ask the Application Ontology for short view specifications on each of the + * most specific classes for this individual. If more than one such class + * has an applicable short view, the class with with the first URI + * (alphabetically) will be used. + */ + TemplateAndSupplementalData getShortViewInfo(Individual individual, + ShortViewContext svContext, VitroRequest vreq); + + /** + * The information associated with a particular short view. + */ + public interface TemplateAndSupplementalData { + /** + * The name of the template to be used in the short view. + * + * Either the custom view assigned to the individual and context, or the + * default view. Never empty or null, but it might refer to a template + * that can't be located. + */ + String getTemplateName(); + + /** + * The results of any custom data getters were associated with this + * individual in this short view context. + * + * May be empty, but never null. + */ + Map getSupplementalData(); + } + + /** + * The available contexts for short views. + */ + public enum ShortViewContext { + SEARCH("view-search-default.ftl"), INDEX("listedIndividual.ftl"), BROWSE( + "view-browse-default.ftl"); + + private final String defaultTemplateName; + + ShortViewContext(String defaultTemplateName) { + this.defaultTemplateName = defaultTemplateName; + } + + public String getDefaultTemplateName() { + return defaultTemplateName; + } + + public static ShortViewContext fromString(String string) { + for (ShortViewContext c : ShortViewContext.values()) { + if (c.name().equalsIgnoreCase(string)) { + return c; + } + } + return null; + } + + public static String valueList() { + return StringUtils.join(ShortViewContext.values(), ", "); + } + } + +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/services/shortview/ShortViewServiceImpl.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/services/shortview/ShortViewServiceImpl.java new file mode 100644 index 000000000..078ff45a8 --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/services/shortview/ShortViewServiceImpl.java @@ -0,0 +1,146 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.vitro.webapp.services.shortview; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import edu.cornell.mannlib.vitro.webapp.beans.Individual; +import edu.cornell.mannlib.vitro.webapp.beans.ObjectPropertyStatement; +import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; +import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary; +import edu.cornell.mannlib.vitro.webapp.services.freemarker.FreemarkerProcessingService; +import edu.cornell.mannlib.vitro.webapp.services.freemarker.FreemarkerProcessingService.TemplateParsingException; +import edu.cornell.mannlib.vitro.webapp.services.freemarker.FreemarkerProcessingServiceSetup; +import edu.cornell.mannlib.vitro.webapp.services.shortview.FakeApplicationOntologyService.TemplateAndDataGetters; +import edu.cornell.mannlib.vitro.webapp.utils.dataGetter.DataGetter; + +/** + * The basic implementation of ShortViewService + */ +public class ShortViewServiceImpl implements ShortViewService { + private static final Log log = LogFactory + .getLog(ShortViewServiceImpl.class); + + private static final Map EMPTY_MAP = Collections.emptyMap(); + + private final FakeApplicationOntologyService faker; + + public ShortViewServiceImpl(FakeApplicationOntologyService faker) { + this.faker = faker; + } + + @Override + public String renderShortView(Individual individual, + ShortViewContext context, Map modelMap, + VitroRequest vreq) { + + TemplateAndSupplementalData tsd = getShortViewInfo(individual, context, + vreq); + String templateName = tsd.getTemplateName(); + Map supplementalData = tsd.getSupplementalData(); + + try { + Map fullModelMap = new HashMap( + modelMap); + fullModelMap.putAll(supplementalData); + + FreemarkerProcessingService fps = FreemarkerProcessingServiceSetup + .getService(vreq.getSession().getServletContext()); + + if (!fps.isTemplateAvailable(templateName, vreq)) { + return "

Can't locate short view template '" + templateName + + "' for " + individual.getName() + "

"; + } + + return fps.renderTemplate(templateName, fullModelMap, vreq); + } catch (TemplateParsingException e) { + return "

Can't parse the short view template '" + templateName + + "' for " + individual.getName() + "

"; + } catch (Exception e) { + log.error(e, e); + return "

Failed to render the short view for " + + individual.getName() + "

"; + } + } + + @Override + public TemplateAndSupplementalData getShortViewInfo(Individual individual, + ShortViewContext svContext, VitroRequest vreq) { + TemplateAndDataGetters tdg = fetchTemplateAndDataGetters(individual, + svContext, vreq); + Map gotData = runDataGetters(tdg.getDataGetters()); + return new TemplateAndSupplementalDataImpl(tdg.getTemplateName(), + gotData); + } + + /** Get most specific classes from Individual, sorted by alpha. */ + private SortedSet figureMostSpecificClassUris(Individual individual) { + SortedSet classUris = new TreeSet(); + List stmts = individual + .getObjectPropertyStatements(VitroVocabulary.MOST_SPECIFIC_TYPE); + for (ObjectPropertyStatement stmt : stmts) { + classUris.add(stmt.getObjectURI()); + } + return classUris; + } + + /** Find the template and data getters for this individual in this context. */ + private TemplateAndDataGetters fetchTemplateAndDataGetters( + Individual individual, ShortViewContext svContext, VitroRequest vreq) { + List classUris = new ArrayList(); + classUris.addAll(figureMostSpecificClassUris(individual)); + + for (String classUri : classUris) { + TemplateAndDataGetters tdg = faker.getShortViewProperties(vreq, + individual, classUri, svContext.name()); + if (tdg != null) { + return tdg; + } + } + + // Didn't find one? Use the default values. + return new TemplateAndDataGetters(svContext.getDefaultTemplateName()); + } + + /** Build a data map from the combined results of all data getters. */ + private Map runDataGetters(Set dataGetters) { + Map gotData = new HashMap(); + for (DataGetter dg : dataGetters) { + gotData.putAll(dg.getData(EMPTY_MAP)); + } + return gotData; + } + + private static class TemplateAndSupplementalDataImpl implements + TemplateAndSupplementalData { + private final String templateName; + private final Map customData; + + public TemplateAndSupplementalDataImpl(String templateName, + Map customData) { + this.templateName = templateName; + this.customData = customData; + } + + @Override + public String getTemplateName() { + return templateName; + } + + @Override + public Map getSupplementalData() { + return customData; + } + + } +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/services/shortview/ShortViewServiceSetup.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/services/shortview/ShortViewServiceSetup.java new file mode 100644 index 000000000..d140901e4 --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/services/shortview/ShortViewServiceSetup.java @@ -0,0 +1,39 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.vitro.webapp.services.shortview; + +import javax.servlet.ServletContext; +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; + +import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus; + +/** + * Set up the ShortViewService. + */ +public class ShortViewServiceSetup implements ServletContextListener { + private static final String ATTRIBUTE_NAME = ShortViewService.class + .getName(); + + @Override + public void contextInitialized(ServletContextEvent sce) { + ServletContext ctx = sce.getServletContext(); + StartupStatus ss = StartupStatus.getBean(ctx); + + ShortViewServiceImpl svs = new ShortViewServiceImpl( + new FakeApplicationOntologyService()); + ctx.setAttribute(ATTRIBUTE_NAME, svs); + + ss.info(this, + "Started the Short View Service with a ShortViewServiceImpl"); + } + + @Override + public void contextDestroyed(ServletContextEvent sce) { + sce.getServletContext().removeAttribute(ATTRIBUTE_NAME); + } + + public static ShortViewService getService(ServletContext ctx) { + return (ShortViewService) ctx.getAttribute(ATTRIBUTE_NAME); + } +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/ApplicationModelSetup.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/ApplicationModelSetup.java new file mode 100644 index 000000000..31c07f590 --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/ApplicationModelSetup.java @@ -0,0 +1,252 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ +package edu.cornell.mannlib.vitro.webapp.servlet.setup; + +import static edu.cornell.mannlib.vitro.webapp.dao.DisplayVocabulary.DISPLAY_ONT_MODEL; + +import java.io.File; +import java.io.FileOutputStream; + +import javax.servlet.ServletContext; +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; + +import org.apache.commons.dbcp.BasicDataSource; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.joda.time.DateTime; +import org.joda.time.format.ISODateTimeFormat; + +import com.hp.hpl.jena.ontology.OntDocumentManager; +import com.hp.hpl.jena.ontology.OntModel; +import com.hp.hpl.jena.query.Query; +import com.hp.hpl.jena.query.QueryExecution; +import com.hp.hpl.jena.query.QueryExecutionFactory; +import com.hp.hpl.jena.query.QueryFactory; +import com.hp.hpl.jena.rdf.model.Model; +import com.hp.hpl.jena.rdf.model.ModelFactory; + +import edu.cornell.mannlib.vitro.webapp.dao.jena.ModelContext; +import edu.cornell.mannlib.vitro.webapp.dao.jena.ModelSynchronizer; +import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus; + +/** + * Setups the Application Configuration TBox and ABox. This is sometimes + * called the display model. + * + * @author bdc34 + */ + +public class ApplicationModelSetup extends JenaDataSourceSetupBase +implements ServletContextListener { + + private static final Log log = LogFactory.getLog( + ApplicationModelSetup.class.getName()); + + /** + * Setup the application configuration model. It is frequently called the + * display model. If this is a new DB, populate the display model with the + * initial data. + * + * Also load any files that get loaded to the display model at each tomcat + * startup. + * + * Also, at each start of tomcat, load The display TBox and the + * display/display model. + */ + private void setupDisplayModel(BasicDataSource bds, ServletContext ctx, + StartupStatus ss) { + + // display, editing and navigation Model + try { + Model displayDbModel = makeDBModel(bds, + JENA_DISPLAY_METADATA_MODEL, DB_ONT_MODEL_SPEC, ctx); + if (displayDbModel.size() == 0) { + readOntologyFilesInPathSet(APPPATH, ctx,displayDbModel); + } + OntModel displayModel = ModelFactory.createOntologyModel(MEM_ONT_MODEL_SPEC); + displayModel.add(displayDbModel); + displayModel.getBaseModel().register(new ModelSynchronizer(displayDbModel)); + ModelContext.setDisplayModel(displayModel, ctx); + + //at each startup load all RDF files from directory to sub-models of display model + initializeDisplayLoadedAtStartup(ctx, displayModel); + } catch (Throwable t) { + log.error("Unable to load user application configuration model", t); + ss.fatal(this, "Unable to load user application configuration model", t); + } + + //display tbox - currently reading in every time + try { + Model displayTboxModel = makeDBModel(bds, + JENA_DISPLAY_TBOX_MODEL, DB_ONT_MODEL_SPEC, ctx); + + //Reading in single file every time, needs to be cleared/removed every time + readOntologyFileFromPath(APPPATH_LOAD + "displayTBOX.n3", displayTboxModel, ctx); + OntModel appTBOXModel = ModelFactory.createOntologyModel( + MEM_ONT_MODEL_SPEC); + appTBOXModel.add(displayTboxModel); + appTBOXModel.getBaseModel().register(new ModelSynchronizer(displayTboxModel)); + ctx.setAttribute("displayOntModelTBOX", appTBOXModel); + log.debug("Loaded file " + APPPATH_LOAD + "displayTBOX.n3 into display tbox model"); + } catch (Throwable t) { + log.error("Unable to load user application configuration model TBOX", t); + ss.fatal(this, "Unable to load user application configuration model TBOX", t); + } + + //Display Display model, currently empty, create if doesn't exist but no files to load + try { + Model displayDisplayModel = makeDBModel(bds, + JENA_DISPLAY_DISPLAY_MODEL, DB_ONT_MODEL_SPEC, ctx); + + //Reading in single file every time, needs to be cleared/removed every + readOntologyFileFromPath(APPPATH_LOAD + "displayDisplay.n3", displayDisplayModel, ctx); + OntModel appDisplayDisplayModel = ModelFactory.createOntologyModel( + MEM_ONT_MODEL_SPEC); + appDisplayDisplayModel.add(displayDisplayModel); + appDisplayDisplayModel.getBaseModel().register(new ModelSynchronizer(displayDisplayModel)); + ctx.setAttribute("displayOntModelDisplayModel", appDisplayDisplayModel); + log.debug("Loaded file " + APPPATH_LOAD + "displayDisplay.n3 into display display model"); + } catch (Throwable t) { + log.error("Unable to load user application configuration model Display Model", t); + ss.fatal(this, "Unable to load user application configuration model Display Model", t); + } + } + + /** + * Load the RDF found in the directory DISPLAY_MODEL_LOAD_AT_STARTUP_DIR + * a sub-models of displayModel. The RDF from thes files will not be saved + * in the database and it will be reloaded each time the system starts up. + */ + private void initializeDisplayLoadedAtStartup(ServletContext ctx, OntModel displayModel){ + log.info("loading display model from files in " + ctx.getRealPath(DISPLAY_MODEL_LOAD_AT_STARTUP_DIR) ); + Model displayLoadAtStartup = readInDisplayModelLoadAtStartup(ctx); + + if( log.isDebugEnabled() ){ + log.debug("loaded display model from files in " + ctx.getRealPath(DISPLAY_MODEL_LOAD_AT_STARTUP_DIR) ); + displayLoadAtStartup.write(System.out, "N3-PP"); + } + + checkForOldListViews(ctx,displayModel,displayLoadAtStartup); + displayModel.addSubModel( displayLoadAtStartup ); + } + + protected Model readInDisplayModelLoadAtStartup( ServletContext ctx ){ + return getModelFromDir( new File( ctx.getRealPath( DISPLAY_MODEL_LOAD_AT_STARTUP_DIR ))); + } + + /** + * All of the list views should now reside in files in DISPLAY_MODEL_LOAD_AT_STARTUP_DIR. + * This will check for custom list view annotation statements in the displayModel, check + * if they exist in the files in DISPLAY_MODEL_LOAD_AT_STARTUP_DIR, and write any that don't + * exist there to a file in DISPLAY_MODEL_LOAD_AT_STARTUP_DIR. After that the statements + * will be removed from the displayDBModel. + * + * returns true if there were old list view statements in the DB, returns false + * if there were none. displayLoadAlways should be reloaded from the file system + * if this returns true as this method may have changed the files. + * + * displayLoadAtStartup and displayModel may be modified. + */ + private void checkForOldListViews( ServletContext ctx, OntModel displayModel, Model displayLoadAtStartup){ + // run construct for old custom list view statements from displayModel + Model oldListViewModel = getOldListViewStatements( displayModel ); + if( log.isDebugEnabled() ){ + log.debug("Printing the old list view statements from the display model to System.out."); + oldListViewModel.write(System.out,"N3-PP"); + } + + // find statements in old stmts that are not in loadedAtStartup and + // save them in a new file in DISPLAY_MODEL_LOAD_AT_STARTUP_DIR + // so that in the future they will be in loadedAtStartup + Model stmtsInOldAndFiles = displayLoadAtStartup.intersection( displayModel ); + Model unhandledOldListViewStmts = oldListViewModel.difference( stmtsInOldAndFiles ); + + boolean saved = false; + boolean neededSave = false; + + if( unhandledOldListViewStmts != null && !unhandledOldListViewStmts.isEmpty() ){ + log.debug("need to deal with old list view statements from the display model"); + neededSave = true; + try{ + //create a file for the old statements in the loadAtStartup directory + String newFileName = ctx.getRealPath( + DISPLAY_MODEL_LOAD_AT_STARTUP_DIR + File.separator + + new DateTime().toString(ISODateTimeFormat.basicDateTime()) + ".n3" ); + File file = new File( newFileName ); + file.createNewFile(); + + log.info("Relocating " + unhandledOldListViewStmts.size() + " custom list view statements from DB and saving to " + + file.getAbsolutePath()+ File.separator + file.getName() + + ". These will be loaded from this file when the system starts up."); + + FileOutputStream fileOut = new FileOutputStream(file); + unhandledOldListViewStmts.write(fileOut, "N3-PP"); + fileOut.close(); + saved = true; + }catch(Throwable th){ + log.warn("Could not save old list view statements. Leaving them in the DB",th); + } + + //need to reload displayLoadAlways because DISPLAY_MODEL_LOAD_AT_STARTUP_DIR may have changed + displayLoadAtStartup.removeAll().add(readInDisplayModelLoadAtStartup(ctx)); + } + + + if( oldListViewModel != null && ! oldListViewModel.isEmpty() ){ + //At this point, there are old list view statements in the DB but they + //should are all redundant with ones in DISPLAY_MODEL_LOAD_AT_STARTUP_DIR + if( (neededSave && saved) || (!neededSave) ){ + //if there was nothing to save, just remove the old stuff + //if there was stuff to save, only remove if it was saved. + log.debug("removing old statements from displayModel"); + displayModel.remove(oldListViewModel); + } + } + + } + + private Model getOldListViewStatements(OntModel displayModel) { + //run a construct on displayModel to get all list view statements + Query query = QueryFactory.create ( listViewQuery ); + QueryExecution qexec = QueryExecutionFactory.create(query, displayModel) ; + Model oldModel = null; + + try { + oldModel = qexec.execConstruct(); + } catch( Throwable th ){ + log.error("could not check for old custom list views, query exception",th); + }finally { + qexec.close() ; + } + + if( oldModel != null) + return oldModel; + else + return ModelFactory.createDefaultModel(); + } + + private static final String listViewQuery = "" + + "PREFIX d: \n" + + "CONSTRUCT { \n" + + " ?a d:listViewConfigFile ?b . \n" + + "} WHERE {\n" + + " ?a d:listViewConfigFile ?b . \n" + + "} "; + + @Override + public void contextDestroyed(ServletContextEvent arg0) { + // does nothing. + } + + @Override + public void contextInitialized(ServletContextEvent sce) { + ServletContext ctx = sce.getServletContext(); + StartupStatus ss = StartupStatus.getBean(ctx); + BasicDataSource bds = getApplicationDataSource(ctx); + + setupDisplayModel(bds, ctx, ss); + } + + + +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/JenaDataSourceSetup.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/JenaDataSourceSetup.java index ec092538e..aa4644a59 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/JenaDataSourceSetup.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/JenaDataSourceSetup.java @@ -418,7 +418,7 @@ public class JenaDataSourceSetup extends JenaDataSourceSetupBase // Nothing to do. } - private OntModel ontModelFromContextAttribute(ServletContext ctx, + protected OntModel ontModelFromContextAttribute(ServletContext ctx, String attribute) { OntModel ontModel; Object attributeValue = ctx.getAttribute(attribute); @@ -499,7 +499,7 @@ public class JenaDataSourceSetup extends JenaDataSourceSetupBase return; } - private static void getAppMetadata(Model source, Model target) { + protected static void getAppMetadata(Model source, Model target) { String amdQuery = "DESCRIBE ?x WHERE { " + "{?x a <" + VitroVocabulary.PORTAL +"> } UNION " + @@ -517,7 +517,7 @@ public class JenaDataSourceSetup extends JenaDataSourceSetupBase return; } - private static void repairAppMetadataModel(Model applicationMetadataModel, + protected static void repairAppMetadataModel(Model applicationMetadataModel, Model aboxAssertions, Model aboxInferences) { diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/JenaDataSourceSetupBase.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/JenaDataSourceSetupBase.java index bb5fb97c5..0fe10e493 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/JenaDataSourceSetupBase.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/JenaDataSourceSetupBase.java @@ -19,14 +19,21 @@ import com.hp.hpl.jena.graph.Graph; import com.hp.hpl.jena.ontology.OntModel; import com.hp.hpl.jena.ontology.OntModelSpec; import com.hp.hpl.jena.query.Dataset; +import com.hp.hpl.jena.query.Query; +import com.hp.hpl.jena.query.QueryExecution; +import com.hp.hpl.jena.query.QueryExecutionFactory; +import com.hp.hpl.jena.query.QueryFactory; +import com.hp.hpl.jena.query.Syntax; import com.hp.hpl.jena.rdf.model.Model; import com.hp.hpl.jena.rdf.model.ModelFactory; +import com.hp.hpl.jena.sdb.Store; import com.hp.hpl.jena.sdb.StoreDesc; import com.hp.hpl.jena.sdb.store.DatabaseType; import com.hp.hpl.jena.sdb.store.LayoutType; import edu.cornell.mannlib.vitro.webapp.config.ConfigurationProperties; import edu.cornell.mannlib.vitro.webapp.dao.DisplayVocabulary; +import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary; import edu.cornell.mannlib.vitro.webapp.dao.jena.JenaBaseDaoCon; import edu.cornell.mannlib.vitro.webapp.dao.jena.RDBGraphGenerator; import edu.cornell.mannlib.vitro.webapp.dao.jena.RegeneratingGraph; @@ -63,8 +70,7 @@ public class JenaDataSourceSetupBase extends JenaBaseDaoCon { protected static String USER_ABOX_PATH = BASE+"user/abox"; protected static String USER_TBOX_PATH = BASE+"user/tbox"; protected static String USER_APPMETA_PATH = BASE+"user/applicationMetadata"; - protected static String SYSTEMPATH = BASE+"system/"; - protected static String AUTHPATH = BASE+"auth/"; + protected static String SYSTEMPATH = BASE+"system/"; public static String APPPATH = BASE+"app/"; //these files are loaded everytime the system starts up public static String APPPATH_LOAD = APPPATH + "menuload/"; @@ -282,6 +288,10 @@ public class JenaDataSourceSetupBase extends JenaBaseDaoCon { return firstStartup; } + public static void thisIsFirstStartup(){ + firstStartup = true; + } + protected Model makeDBModel(BasicDataSource ds, String jenaDbModelname, OntModelSpec jenaDbOntModelSpec, @@ -373,10 +383,10 @@ public class JenaDataSourceSetupBase extends JenaBaseDaoCon { } } else { if(!f.exists()) { - log.debug("File for path " + p + " does not exist"); + log.info("File for path " + p + " does not exist"); } else if(f.isDirectory()) { - log.debug("Path " + p + + log.info("Path " + p + " corresponds to directory and not file so was not read in"); } } @@ -419,7 +429,7 @@ public class JenaDataSourceSetupBase extends JenaBaseDaoCon { } else if (TripleStoreType.SDB.equals(type)) { StoreDesc storeDesc = new StoreDesc( LayoutType.LayoutTripleNodesHash, DatabaseType.fetch(dbtypeStr)); - BasicDataSource bds = JenaDataSourceSetup.makeBasicDataSource( + BasicDataSource bds = WebappDaoSDBSetup.makeBasicDataSource( getDbDriverClassName(ctx), jdbcUrl, username, password, ctx); bds.setMaxActive(4); // for now, the SDB model makers should not use more // than a small handful of connections @@ -534,4 +544,68 @@ public class JenaDataSourceSetupBase extends JenaBaseDaoCon { return (o instanceof Dataset) ? ((Dataset) o) : null; } + protected OntModel ontModelFromContextAttribute(ServletContext ctx, + String attribute) { + OntModel ontModel; + Object attributeValue = ctx.getAttribute(attribute); + if (attributeValue != null && attributeValue instanceof OntModel) { + ontModel = (OntModel) attributeValue; + } else { + ontModel = ModelFactory.createOntologyModel(MEM_ONT_MODEL_SPEC); + ctx.setAttribute(attribute, ontModel); + } + return ontModel; + } + + protected static void repairAppMetadataModel(Model applicationMetadataModel, + Model aboxAssertions, + Model aboxInferences) { + + log.info("Moving application metadata from ABox to dedicated model"); + getAppMetadata(aboxAssertions, applicationMetadataModel); + getAppMetadata(aboxInferences, applicationMetadataModel); + aboxAssertions.remove(applicationMetadataModel); + aboxInferences.remove(applicationMetadataModel); + + return; + } + + protected static void getAppMetadata(Model source, Model target) { + + String amdQuery = "DESCRIBE ?x WHERE { " + + "{?x a <" + VitroVocabulary.PORTAL +"> } UNION " + + "{?x a <" + VitroVocabulary.PROPERTYGROUP +"> } UNION " + + "{?x a <" + VitroVocabulary.CLASSGROUP +"> } } "; + + try { + Query q = QueryFactory.create(amdQuery, Syntax.syntaxARQ); + QueryExecution qe = QueryExecutionFactory.create(q, source); + qe.execDescribe(target); + } catch (Exception e) { + log.error("unable to create the application metadata model",e); + } + + return; + } + + private static final String STOREDESC_ATTR = "storeDesc"; + private static final String STORE_ATTR = "kbStore"; + + public static void setApplicationStoreDesc(StoreDesc storeDesc, + ServletContext ctx) { + ctx.setAttribute(STOREDESC_ATTR, storeDesc); + } + + public static StoreDesc getApplicationStoreDesc(ServletContext ctx) { + return (StoreDesc) ctx.getAttribute(STOREDESC_ATTR); + } + + public static void setApplicationStore(Store store, + ServletContext ctx) { + ctx.setAttribute(STORE_ATTR, store); + } + + public static Store getApplicationStore(ServletContext ctx) { + return (Store) ctx.getAttribute(STORE_ATTR); + } } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/JenaDataSourceSetupSparql.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/JenaDataSourceSetupSparql.java index f026687cd..401c95204 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/JenaDataSourceSetupSparql.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/JenaDataSourceSetupSparql.java @@ -432,7 +432,8 @@ public class JenaDataSourceSetupSparql extends JenaDataSourceSetupBase // Nothing to do. } - private OntModel ontModelFromContextAttribute(ServletContext ctx, + @Override + protected OntModel ontModelFromContextAttribute(ServletContext ctx, String attribute) { OntModel ontModel; Object attributeValue = ctx.getAttribute(attribute); @@ -513,7 +514,7 @@ public class JenaDataSourceSetupSparql extends JenaDataSourceSetupBase return; } - private static void getAppMetadata(Model source, Model target) { + protected static void getAppMetadata(Model source, Model target) { String amdQuery = "DESCRIBE ?x WHERE { " + "{?x a <" + VitroVocabulary.PORTAL +"> } UNION " + @@ -531,7 +532,7 @@ public class JenaDataSourceSetupSparql extends JenaDataSourceSetupBase return; } - private static void repairAppMetadataModel(Model applicationMetadataModel, + protected static void repairAppMetadataModel(Model applicationMetadataModel, Model aboxAssertions, Model aboxInferences) { diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/JenaDataSourceSetupSparql2.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/JenaDataSourceSetupSparql2.java index 40fbcc7a7..ad0edf41e 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/JenaDataSourceSetupSparql2.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/JenaDataSourceSetupSparql2.java @@ -417,7 +417,8 @@ public class JenaDataSourceSetupSparql2 extends JenaDataSourceSetupBase // Nothing to do. } - private OntModel ontModelFromContextAttribute(ServletContext ctx, + @Override + protected OntModel ontModelFromContextAttribute(ServletContext ctx, String attribute) { OntModel ontModel; Object attributeValue = ctx.getAttribute(attribute); @@ -498,7 +499,7 @@ public class JenaDataSourceSetupSparql2 extends JenaDataSourceSetupBase return; } - private static void getAppMetadata(Model source, Model target) { + protected static void getAppMetadata(Model source, Model target) { String amdQuery = "DESCRIBE ?x WHERE { " + "{?x a <" + VitroVocabulary.PORTAL +"> } UNION " + @@ -516,7 +517,7 @@ public class JenaDataSourceSetupSparql2 extends JenaDataSourceSetupBase return; } - private static void repairAppMetadataModel(Model applicationMetadataModel, + protected static void repairAppMetadataModel(Model applicationMetadataModel, Model aboxAssertions, Model aboxInferences) { diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/JenaPersistentDataSourceSetup.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/JenaPersistentDataSourceSetup.java index 40f3ed503..c0b5d3320 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/JenaPersistentDataSourceSetup.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/JenaPersistentDataSourceSetup.java @@ -2,11 +2,6 @@ package edu.cornell.mannlib.vitro.webapp.servlet.setup; -import static edu.cornell.mannlib.vitro.webapp.dao.DisplayVocabulary.DISPLAY_ONT_MODEL; - -import java.io.File; -import java.io.FileOutputStream; - import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; @@ -14,21 +9,18 @@ import javax.servlet.ServletContextListener; import org.apache.commons.dbcp.BasicDataSource; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.joda.time.DateTime; -import org.joda.time.format.ISODateTimeFormat; import com.hp.hpl.jena.ontology.OntDocumentManager; import com.hp.hpl.jena.ontology.OntModel; -import com.hp.hpl.jena.query.Query; -import com.hp.hpl.jena.query.QueryExecution; -import com.hp.hpl.jena.query.QueryExecutionFactory; -import com.hp.hpl.jena.query.QueryFactory; import com.hp.hpl.jena.rdf.model.Model; import com.hp.hpl.jena.rdf.model.ModelFactory; import edu.cornell.mannlib.vitro.webapp.dao.jena.ModelSynchronizer; import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus; +/** + * Create connection to DB and DataSource, put them in the context. + */ public class JenaPersistentDataSourceSetup extends JenaDataSourceSetupBase implements ServletContextListener { @@ -44,217 +36,13 @@ public class JenaPersistentDataSourceSetup extends JenaDataSourceSetupBase OntDocumentManager.getInstance().setProcessImports(false); BasicDataSource bds = makeDataSourceFromConfigurationProperties(ctx); - setApplicationDataSource(bds, ctx); - - // user accounts Model - try { - Model userAccountsDbModel = makeDBModel(bds, - JENA_USER_ACCOUNTS_MODEL, DB_ONT_MODEL_SPEC, ctx); - if (userAccountsDbModel.size() == 0) { - firstStartup = true; - readOntologyFilesInPathSet(AUTHPATH, ctx, - userAccountsDbModel); - } - OntModel userAccountsModel = ModelFactory.createOntologyModel( - MEM_ONT_MODEL_SPEC); - userAccountsModel.add(userAccountsDbModel); - userAccountsModel.getBaseModel().register( - new ModelSynchronizer(userAccountsDbModel)); - ctx.setAttribute("userAccountsOntModel", userAccountsModel); - - if (userAccountsModel.isEmpty()) { - initializeUserAccounts(ctx, userAccountsModel); - } - } catch (Throwable t) { - log.error("Unable to load user accounts model from DB", t); - ss.fatal(this, "Unable to load user accounts model from DB", t); - } - - // display, editing and navigation Model - try { - Model displayDbModel = makeDBModel(bds, - JENA_DISPLAY_METADATA_MODEL, DB_ONT_MODEL_SPEC, ctx); - if (displayDbModel.size() == 0) { - readOntologyFilesInPathSet(APPPATH, ctx,displayDbModel); - } - OntModel displayModel = ModelFactory.createOntologyModel(MEM_ONT_MODEL_SPEC); - displayModel.add(displayDbModel); - displayModel.getBaseModel().register(new ModelSynchronizer(displayDbModel)); - ctx.setAttribute(DISPLAY_ONT_MODEL, displayModel); - - //at each startup load all RDF files from directory to sub-models of display model - initializeDisplayLoadedAtStartup(ctx, displayModel); - } catch (Throwable t) { - log.error("Unable to load user application configuration model", t); - ss.fatal(this, "Unable to load user application configuration model", t); - } - - //display tbox - currently reading in every time - try { - Model displayTboxModel = makeDBModel(bds, - JENA_DISPLAY_TBOX_MODEL, DB_ONT_MODEL_SPEC, ctx); - //Reading in single file every time - //TODO: Check if original needs to be cleared/removed every time? - readOntologyFileFromPath(APPPATH_LOAD + "displayTBOX.n3", displayTboxModel, ctx); - OntModel appTBOXModel = ModelFactory.createOntologyModel( - MEM_ONT_MODEL_SPEC); - appTBOXModel.add(displayTboxModel); - appTBOXModel.getBaseModel().register(new ModelSynchronizer(displayTboxModel)); - ctx.setAttribute("displayOntModelTBOX", appTBOXModel); - log.debug("Loaded file " + APPPATH_LOAD + "displayTBOX.n3 into display tbox model"); - } catch (Throwable t) { - log.error("Unable to load user application configuration model TBOX", t); - ss.fatal(this, "Unable to load user application configuration model TBOX", t); - } - - //Display Display model, currently empty, create if doesn't exist but no files to load - try { - Model displayDisplayModel = makeDBModel(bds, - JENA_DISPLAY_DISPLAY_MODEL, DB_ONT_MODEL_SPEC, ctx); - //Reading in single file every time - //TODO: Check if original needs to be cleared/removed every time? - readOntologyFileFromPath(APPPATH_LOAD + "displayDisplay.n3", displayDisplayModel, ctx); - - OntModel appDisplayDisplayModel = ModelFactory.createOntologyModel( - MEM_ONT_MODEL_SPEC); - appDisplayDisplayModel.add(displayDisplayModel); - appDisplayDisplayModel.getBaseModel().register(new ModelSynchronizer(displayDisplayModel)); - ctx.setAttribute("displayOntModelDisplayModel", appDisplayDisplayModel); - log.debug("Loaded file " + APPPATH_LOAD + "displayDisplay.n3 into display display model"); - } catch (Throwable t) { - log.error("Unable to load user application configuration model Display Model", t); - ss.fatal(this, "Unable to load user application configuration model Display Model", t); - } + setApplicationDataSource(bds, ctx); } - @Override + + @Override public void contextDestroyed(ServletContextEvent sce) { // Nothing to do. - } - - private void initializeUserAccounts(ServletContext ctx, - Model userAccountsModel) { - readOntologyFilesInPathSet(AUTHPATH, ctx, userAccountsModel); - } - - /** - * Load the RDF found in the directory DISPLAY_MODEL_LOAD_AT_STARTUP_DIR - * a sub-models of displayModel. The RDF from thes files will not be saved - * in the database and it will be reloaded each time the system starts up. - */ - private void initializeDisplayLoadedAtStartup(ServletContext ctx, OntModel displayModel){ - log.info("loading display model from files in " + ctx.getRealPath(DISPLAY_MODEL_LOAD_AT_STARTUP_DIR) ); - Model displayLoadAtStartup = readInDisplayModelLoadAtStartup(ctx); - - if( log.isDebugEnabled() ){ - log.debug("loaded display model from files in " + ctx.getRealPath(DISPLAY_MODEL_LOAD_AT_STARTUP_DIR) ); - displayLoadAtStartup.write(System.out, "N3-PP"); - } - - checkForOldListViews(ctx,displayModel,displayLoadAtStartup); - displayModel.addSubModel( displayLoadAtStartup ); - } - - /** - * All of the list views should now reside in files in DISPLAY_MODEL_LOAD_AT_STARTUP_DIR. - * This will check for custom list view annotation statements in the displayModel, check - * if they exist in the files in DISPLAY_MODEL_LOAD_AT_STARTUP_DIR, and write any that don't - * exist there to a file in DISPLAY_MODEL_LOAD_AT_STARTUP_DIR. After that the statements - * will be removed from the displayDBModel. - * - * returns true if there were old list view statements in the DB, returns false - * if there were none. displayLoadAlways should be reloaded from the file system - * if this returns true as this method may have changed the files. - * - * displayLoadAtStartup and displayModel may be modified. - */ - private void checkForOldListViews( ServletContext ctx, OntModel displayModel, Model displayLoadAtStartup){ - // run construct for old custom list view statements from displayModel - Model oldListViewModel = getOldListViewStatements( displayModel ); - if( log.isDebugEnabled() ){ - log.debug("Printing the old list view statements from the display model to System.out."); - oldListViewModel.write(System.out,"N3-PP"); - } - - // find statements in old stmts that are not in loadedAtStartup and - // save them in a new file in DISPLAY_MODEL_LOAD_AT_STARTUP_DIR - // so that in the future they will be in loadedAtStartup - Model stmtsInOldAndFiles = displayLoadAtStartup.intersection( displayModel ); - Model unhandledOldListViewStmts = oldListViewModel.difference( stmtsInOldAndFiles ); - - boolean saved = false; - boolean neededSave = false; - - if( unhandledOldListViewStmts != null && !unhandledOldListViewStmts.isEmpty() ){ - log.debug("need to deal with old list view statements from the display model"); - neededSave = true; - try{ - //create a file for the old statements in the loadAtStartup directory - String newFileName = ctx.getRealPath( - DISPLAY_MODEL_LOAD_AT_STARTUP_DIR + File.separator - + new DateTime().toString(ISODateTimeFormat.basicDateTime()) + ".n3" ); - File file = new File( newFileName ); - file.createNewFile(); - - log.info("Relocating " + unhandledOldListViewStmts.size() + " custom list view statements from DB and saving to " - + file.getAbsolutePath()+ File.separator + file.getName() - + ". These will be loaded from this file when the system starts up."); - - FileOutputStream fileOut = new FileOutputStream(file); - unhandledOldListViewStmts.write(fileOut, "N3-PP"); - fileOut.close(); - saved = true; - }catch(Throwable th){ - log.warn("Could not save old list view statements. Leaving them in the DB",th); - } - - //need to reload displayLoadAlways because DISPLAY_MODEL_LOAD_AT_STARTUP_DIR may have changed - displayLoadAtStartup.removeAll().add(readInDisplayModelLoadAtStartup(ctx)); - } - - - if( oldListViewModel != null && ! oldListViewModel.isEmpty() ){ - //At this point, there are old list view statements in the DB but they - //should are all redundant with ones in DISPLAY_MODEL_LOAD_AT_STARTUP_DIR - if( (neededSave && saved) || (!neededSave) ){ - //if there was nothing to save, just remove the old stuff - //if there was stuff to save, only remove if it was saved. - log.debug("removing old statements from displayModel"); - displayModel.remove(oldListViewModel); - } - } - - } - - private Model getOldListViewStatements(OntModel displayModel) { - //run a construct on displayModel to get all list view statements - Query query = QueryFactory.create ( listViewQuery ); - QueryExecution qexec = QueryExecutionFactory.create(query, displayModel) ; - Model oldModel = null; - - try { - oldModel = qexec.execConstruct(); - } catch( Throwable th ){ - log.error("could not check for old custom list views, query exception",th); - }finally { - qexec.close() ; - } - - if( oldModel != null) - return oldModel; - else - return ModelFactory.createDefaultModel(); - } + } - private static final String listViewQuery = "" + - "PREFIX d: \n" + - "CONSTRUCT { \n" + - " ?a d:listViewConfigFile ?b . \n" + - "} WHERE {\n" + - " ?a d:listViewConfigFile ?b . \n" + - "} "; - - protected Model readInDisplayModelLoadAtStartup( ServletContext ctx ){ - return getModelFromDir( new File( ctx.getRealPath( DISPLAY_MODEL_LOAD_AT_STARTUP_DIR ))); - } } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/ModelSetup.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/ModelSetup.java new file mode 100644 index 000000000..7de262fc4 --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/ModelSetup.java @@ -0,0 +1,239 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ +package edu.cornell.mannlib.vitro.webapp.servlet.setup; + +import static edu.cornell.mannlib.vitro.webapp.dao.DisplayVocabulary.DISPLAY_ONT_MODEL; + +import javax.servlet.ServletContext; +import javax.servlet.ServletContextEvent; + +import org.apache.commons.dbcp.BasicDataSource; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import com.hp.hpl.jena.ontology.OntModel; +import com.hp.hpl.jena.ontology.OntModelSpec; +import com.hp.hpl.jena.query.Query; +import com.hp.hpl.jena.query.QueryExecution; +import com.hp.hpl.jena.query.QueryExecutionFactory; +import com.hp.hpl.jena.query.QueryFactory; +import com.hp.hpl.jena.query.Syntax; +import com.hp.hpl.jena.rdf.model.Model; +import com.hp.hpl.jena.rdf.model.ModelFactory; + +import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary; +import edu.cornell.mannlib.vitro.webapp.dao.jena.ModelContext; +import edu.cornell.mannlib.vitro.webapp.dao.jena.ModelSynchronizer; +import edu.cornell.mannlib.vitro.webapp.dao.jena.OntModelSelectorImpl; +import edu.cornell.mannlib.vitro.webapp.servlet.setup.JenaDataSourceSetupBase.TripleStoreType; +import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus; +import edu.cornell.mannlib.vitro.webapp.utils.jena.InitialJenaModelUtils; + +/** + * Setup the ABox, TBox, inference and Union models. + * Also setup the OntModelSelectors. + */ +public class ModelSetup extends JenaDataSourceSetupBase +implements javax.servlet.ServletContextListener { + private static final Log log = LogFactory.getLog(ModelSetup.class); + + @Override + public void contextInitialized(ServletContextEvent sce) { + ServletContext ctx = sce.getServletContext(); + StartupStatus ss = StartupStatus.getBean(ctx); + + BasicDataSource bds = getApplicationDataSource(ctx); + if( bds == null ){ + ss.fatal(this, "A DataSource must be setup before ModelSetup "+ + "is run. Make sure that JenaPersistentDataSourceSetup runs before "+ + "ModelSetup."); + return; + } + + setupModels(ctx,ss,bds); + } + + private void setupModels(ServletContext ctx, StartupStatus ss, BasicDataSource bds){ + log.info("Setting up model makers and union models"); + + /////////////////////////////////////////////////////////////// + //set up the OntModelSelectors + + OntModelSelectorImpl baseOms = new OntModelSelectorImpl(); + OntModelSelectorImpl inferenceOms = new OntModelSelectorImpl(); + OntModelSelectorImpl unionOms = new OntModelSelectorImpl(); + + //Put OntModelSelectorImpl objs into the context + ModelContext.setOntModelSelector(unionOms, ctx); + ModelContext.setUnionOntModelSelector(unionOms, ctx); + // assertions and inferences + ModelContext.setBaseOntModelSelector(baseOms, ctx); + // assertions + ModelContext.setInferenceOntModelSelector(inferenceOms, ctx); + // inferences + + //add userAccountsModel to OntModelSelectors + OntModel userAccountsModel = ontModelFromContextAttribute( + ctx, "userAccountsOntModel"); + baseOms.setUserAccountsModel(userAccountsModel); + inferenceOms.setUserAccountsModel(userAccountsModel); + unionOms.setUserAccountsModel(userAccountsModel); + + //add display to OntModelSelectors + OntModel displayModel = ontModelFromContextAttribute( + ctx,DISPLAY_ONT_MODEL); + baseOms.setDisplayModel(displayModel); + inferenceOms.setDisplayModel(displayModel); + unionOms.setDisplayModel(displayModel); + + // The code below, which sets up the OntModelSelectors, controls whether + // each model is maintained in memory, in the DB, or both while the + // application is running. + + // Populate the three OntModelSelectors (BaseOntModel = assertions, + // InferenceOntModel = inferences and JenaOntModel = union of assertions + // and inferences) with the post-SDB-conversion models. + + // ABox assertions + Model aboxAssertions = makeDBModel( + bds, JenaDataSourceSetupBase.JENA_DB_MODEL, DB_ONT_MODEL_SPEC, + TripleStoreType.SDB, ctx); + Model listenableAboxAssertions = ModelFactory.createUnion( + aboxAssertions, ModelFactory.createDefaultModel()); + baseOms.setABoxModel( + ModelFactory.createOntologyModel( + OntModelSpec.OWL_MEM, listenableAboxAssertions)); + + // ABox inferences + Model aboxInferences = makeDBModel( + bds, JenaDataSourceSetupBase.JENA_INF_MODEL, DB_ONT_MODEL_SPEC, + TripleStoreType.SDB, ctx); + Model listenableAboxInferences = ModelFactory.createUnion( + aboxInferences, ModelFactory.createDefaultModel()); + inferenceOms.setABoxModel(ModelFactory.createOntologyModel( + OntModelSpec.OWL_MEM, listenableAboxInferences)); + + + // Since the TBox models are in memory, they do not have timeout issues + // like the like the ABox models do (and so don't need the extra step + // to make them listenable.) + + // TBox assertions + try { + Model tboxAssertionsDB = makeDBModel( + bds, JENA_TBOX_ASSERTIONS_MODEL, DB_ONT_MODEL_SPEC, + TripleStoreType.SDB, ctx); + OntModel tboxAssertions = ModelFactory.createOntologyModel( + MEM_ONT_MODEL_SPEC); + + if (tboxAssertionsDB != null) { + long startTime = System.currentTimeMillis(); + System.out.println( + "Copying cached tbox assertions into memory"); + tboxAssertions.add(tboxAssertionsDB); + System.out.println((System.currentTimeMillis() - startTime) + / 1000 + " seconds to load tbox assertions"); + } + + tboxAssertions.getBaseModel().register(new ModelSynchronizer( + tboxAssertionsDB)); + baseOms.setTBoxModel(tboxAssertions); + } catch (Throwable e) { + log.error("Unable to load tbox assertion cache from DB", e); + } + + // TBox inferences + try { + Model tboxInferencesDB = makeDBModel( + bds, JENA_TBOX_INF_MODEL, DB_ONT_MODEL_SPEC, + TripleStoreType.SDB, ctx); + OntModel tboxInferences = ModelFactory.createOntologyModel( + MEM_ONT_MODEL_SPEC); + + if (tboxInferencesDB != null) { + long startTime = System.currentTimeMillis(); + System.out.println( + "Copying cached tbox inferences into memory"); + tboxInferences.add(tboxInferencesDB); + System.out.println((System.currentTimeMillis() - startTime) + / 1000 + " seconds to load tbox inferences"); + } + + tboxInferences.getBaseModel().register(new ModelSynchronizer( + tboxInferencesDB)); + inferenceOms.setTBoxModel(tboxInferences); + } catch (Throwable e) { + log.error("Unable to load tbox inference cache from DB", e); + } + + // union ABox + OntModel unionABoxModel = ModelFactory.createOntologyModel( + MEM_ONT_MODEL_SPEC,ModelFactory.createUnion( + baseOms.getABoxModel(), inferenceOms.getABoxModel())); + unionOms.setABoxModel(unionABoxModel); + + // union TBox + OntModel unionTBoxModel = ModelFactory.createOntologyModel( + MEM_ONT_MODEL_SPEC,ModelFactory.createUnion( + baseOms.getTBoxModel(), inferenceOms.getTBoxModel())); + unionOms.setTBoxModel(unionTBoxModel); + + + // Application metadata model is cached in memory. + try { + + Model applicationMetadataModelDB = makeDBModel( + bds, JENA_APPLICATION_METADATA_MODEL, DB_ONT_MODEL_SPEC, + TripleStoreType.SDB, ctx); + OntModel applicationMetadataModel = + ModelFactory.createOntologyModel(MEM_ONT_MODEL_SPEC); + + long startTime = System.currentTimeMillis(); + System.out.println( + "Copying cached application metadata model into memory"); + applicationMetadataModel.add(applicationMetadataModelDB); + System.out.println((System.currentTimeMillis() - startTime) + / 1000 + " seconds to load application metadata model " + + "assertions of size " + applicationMetadataModel.size()); + applicationMetadataModel.getBaseModel().register( + new ModelSynchronizer(applicationMetadataModelDB)); + + if (isFirstStartup()) { + applicationMetadataModel.add( + InitialJenaModelUtils.loadInitialModel( + ctx, getDefaultNamespace(ctx))); + + } else if (applicationMetadataModelDB.size() == 0) { + repairAppMetadataModel( + applicationMetadataModel, aboxAssertions, + aboxInferences); + } + + baseOms.setApplicationMetadataModel(applicationMetadataModel); + inferenceOms.setApplicationMetadataModel( + baseOms.getApplicationMetadataModel()); + unionOms.setApplicationMetadataModel( + baseOms.getApplicationMetadataModel()); + + } catch (Throwable e) { + log.error("Unable to load application metadata model cache from DB" + , e); + } + + // create TBox + ABox union models + OntModel baseUnion = ModelFactory.createOntologyModel( + OntModelSpec.OWL_MEM, + ModelFactory.createUnion(baseOms.getABoxModel(), + baseOms.getTBoxModel())); + baseOms.setFullModel(baseUnion); + ModelContext.setBaseOntModel(baseOms.getFullModel(), ctx); + + log.info("Model makers and union set up"); + } + + @Override + public void contextDestroyed(ServletContextEvent arg0) { + // nothing to do. + + } + +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/SDBSetup.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/SDBSetup.java new file mode 100644 index 000000000..03e1ecf47 --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/SDBSetup.java @@ -0,0 +1,231 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ +package edu.cornell.mannlib.vitro.webapp.servlet.setup; + +import java.sql.SQLException; + +import javax.servlet.ServletContext; +import javax.servlet.ServletContextEvent; + +import org.apache.commons.dbcp.BasicDataSource; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import com.hp.hpl.jena.ontology.OntModel; +import com.hp.hpl.jena.rdf.model.Model; +import com.hp.hpl.jena.rdf.model.ModelFactory; +import com.hp.hpl.jena.rdf.model.Statement; +import com.hp.hpl.jena.rdf.model.StmtIterator; +import com.hp.hpl.jena.sdb.SDB; +import com.hp.hpl.jena.sdb.SDBFactory; +import com.hp.hpl.jena.sdb.Store; +import com.hp.hpl.jena.sdb.StoreDesc; +import com.hp.hpl.jena.sdb.sql.SDBConnection; +import com.hp.hpl.jena.sdb.store.DatabaseType; +import com.hp.hpl.jena.sdb.store.LayoutType; +import com.hp.hpl.jena.sdb.util.StoreUtils; + +import edu.cornell.mannlib.vitro.webapp.config.ConfigurationProperties; +import edu.cornell.mannlib.vitro.webapp.dao.jena.JenaModelUtils; +import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus; + +public class SDBSetup extends JenaDataSourceSetupBase +implements javax.servlet.ServletContextListener { + private static final Log log = LogFactory.getLog(SDBSetup.class); + + @Override + public void contextDestroyed(ServletContextEvent arg0) { + // nothing to do + + } + + @Override + public void contextInitialized(ServletContextEvent sce) { + ServletContext ctx = sce.getServletContext(); + StartupStatus ss = StartupStatus.getBean(ctx); + try { + setupSDB(ctx, ss); + log.info("SDB store ready for use"); + } catch (SQLException e) { + ss.fatal(this, "Exception in setupSDB", e); + } + } + + private void setupSDB(ServletContext ctx, StartupStatus ss) throws SQLException { + BasicDataSource bds = getApplicationDataSource(ctx); + if( bds == null ){ + ss.fatal(this, "A DataSource must be setup before SDBSetup "+ + "is run. Make sure that JenaPersistentDataSourceSetup runs before "+ + "SDBSetup."); + return; + } + + // union default graph + SDB.getContext().set(SDB.unionDefaultGraph, true) ; + + StoreDesc storeDesc = makeStoreDesc(ctx); + setApplicationStoreDesc(storeDesc, ctx); + + Store store = connectStore(bds, storeDesc); + setApplicationStore(store, ctx); + + if (!isSetUp(store)) { + JenaPersistentDataSourceSetup.thisIsFirstStartup(); + setupSDB(ctx, store); + } + } + + + /** + * Tests whether an SDB store has been formatted and populated for use. + * @param store + * @return + */ + private boolean isSetUp(Store store) throws SQLException { + if (!(StoreUtils.isFormatted(store))) { + return false; + } + + // even if the store exists, it may be empty + + try { + return (SDBFactory.connectNamedModel( + store, + JenaDataSourceSetupBase.JENA_TBOX_ASSERTIONS_MODEL)) + .size() > 0; + } catch (Exception e) { + return false; + } + } + + public static StoreDesc makeStoreDesc(ServletContext ctx) { + String layoutStr = ConfigurationProperties.getBean(ctx).getProperty( + "VitroConnection.DataSource.sdb.layout", "layout2/hash"); + String dbtypeStr = ConfigurationProperties.getBean(ctx).getProperty( + "VitroConnection.DataSource.dbtype", "MySQL"); + return new StoreDesc( + LayoutType.fetch(layoutStr), + DatabaseType.fetch(dbtypeStr) ); + } + + public static Store connectStore(BasicDataSource bds, StoreDesc storeDesc) + throws SQLException { + SDBConnection conn = new SDBConnection(bds.getConnection()); + return SDBFactory.connectStore(conn, storeDesc); + } + + protected static void setupSDB(ServletContext ctx, Store store) { + setupSDB(ctx, store, ModelFactory.createDefaultModel(), + ModelFactory.createDefaultModel()); + } + + protected static void setupSDB(ServletContext ctx, Store store, + Model memModel, Model inferenceModel) { + log.info("Initializing SDB store"); + + store.getTableFormatter().create(); + store.getTableFormatter().truncate(); + + store.getTableFormatter().dropIndexes(); // improve load performance + + try { + + // This is a one-time copy of stored KB data - from a Jena RDB store + // to a Jena SDB store. In the process, we will also separate out + // the TBox from the Abox; these are in the same graph in pre-1.2 + // VIVO versions and will now be stored and maintained in separate + // models. Access to the Jena RDB data is through the + // OntModelSelectors that have been set up earlier in the current + // session by JenaPersistentDataSourceSetup.java. In the code + // below, note that the current getABoxModel() methods on the + // OntModelSelectors return a graph with both ABox and TBox data. + + OntModel submodels = ModelFactory + .createOntologyModel(MEM_ONT_MODEL_SPEC); + readOntologyFilesInPathSet(SUBMODELS, ctx, submodels); + + Model tboxAssertions = SDBFactory.connectNamedModel(store, + JenaDataSourceSetupBase.JENA_TBOX_ASSERTIONS_MODEL); + // initially putting the results in memory so we have a + // cheaper way of computing the difference when we copy the ABox + Model memTboxAssertions = ModelFactory.createDefaultModel(); + getTBoxModel(memModel, submodels, memTboxAssertions); + tboxAssertions.add(memTboxAssertions); + + Model tboxInferences = SDBFactory.connectNamedModel(store, + JenaDataSourceSetupBase.JENA_TBOX_INF_MODEL); + // initially putting the results in memory so we have a + // cheaper way of computing the difference when we copy the ABox + Model memTboxInferences = ModelFactory.createDefaultModel(); + getTBoxModel(inferenceModel, submodels, memTboxInferences); + tboxInferences.add(memTboxInferences); + + Model aboxAssertions = SDBFactory.connectNamedModel(store, + JenaDataSourceSetupBase.JENA_DB_MODEL); + copyDifference(memModel, memTboxAssertions, aboxAssertions); + + Model aboxInferences = SDBFactory.connectNamedModel(store, + JenaDataSourceSetupBase.JENA_INF_MODEL); + copyDifference(inferenceModel, memTboxInferences, aboxInferences); + + // Set up the application metadata model + Model applicationMetadataModel = SDBFactory.connectNamedModel( + store, + JenaDataSourceSetupBase.JENA_APPLICATION_METADATA_MODEL); + getAppMetadata(memModel, applicationMetadataModel); + log.info("During initial SDB setup, created an application " + + "metadata model of size " + + applicationMetadataModel.size()); + + // remove application metadata from ABox model + aboxAssertions.remove(applicationMetadataModel); + aboxInferences.remove(applicationMetadataModel); + + // Make sure the reasoner takes into account the newly-set-up data. + SimpleReasonerSetup.setRecomputeRequired(ctx); + + } finally { + log.info("Adding indexes to SDB database tables."); + store.getTableFormatter().addIndexes(); + log.info("Indexes created."); + } + } + + /* + * Copy all statements from model 1 that are not in model 2 to model 3. + */ + private static void copyDifference(Model model1, Model model2, Model model3) { + + StmtIterator iter = model1.listStatements(); + + while (iter.hasNext()) { + Statement stmt = iter.next(); + if (!model2.contains(stmt)) { + model3.add(stmt); + } + } + + return; + } + + private static void getTBoxModel(Model fullModel, Model submodels, + Model tboxModel) { + + JenaModelUtils modelUtils = new JenaModelUtils(); + + Model tempModel = ModelFactory.createUnion(fullModel, submodels); + Model tempTBoxModel = modelUtils.extractTBox(tempModel); + + // copy intersection of tempTBoxModel and fullModel to tboxModel. + StmtIterator iter = tempTBoxModel.listStatements(); + + while (iter.hasNext()) { + Statement stmt = iter.next(); + if (fullModel.contains(stmt)) { + tboxModel.add(stmt); + } + } + + return; + } + +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/UserModelSetup.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/UserModelSetup.java new file mode 100644 index 000000000..8f0f25621 --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/UserModelSetup.java @@ -0,0 +1,69 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ +package edu.cornell.mannlib.vitro.webapp.servlet.setup; + +import javax.servlet.ServletContext; +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; + +import org.apache.commons.dbcp.BasicDataSource; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import com.hp.hpl.jena.ontology.OntModel; +import com.hp.hpl.jena.rdf.model.Model; +import com.hp.hpl.jena.rdf.model.ModelFactory; + +import edu.cornell.mannlib.vitro.webapp.dao.jena.ModelSynchronizer; +import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus; + + +/** + * Setup the user account model. If it does not exist in the + * database, create and populate it. + */ +public class UserModelSetup extends JenaDataSourceSetupBase + implements ServletContextListener { + + private static final Log log = LogFactory.getLog( + UserModelSetup.class.getName()); + + @Override + public void contextInitialized(ServletContextEvent sce) { + ServletContext ctx = sce.getServletContext(); + StartupStatus ss = StartupStatus.getBean(ctx); + + BasicDataSource bds = getApplicationDataSource(ctx); + if( bds == null ){ + ss.fatal(this, "A DataSource must be setup before ModelSetup "+ + "is run. Make sure that JenaPersistentDataSourceSetup runs before "+ + "ModelSetup."); + return; + } + + setupUserAccountModel(bds, ctx, ss); + } + + @Override + public void contextDestroyed(ServletContextEvent arg0) { + // Does nothing. + } + + private void setupUserAccountModel (BasicDataSource bds, ServletContext ctx ,StartupStatus ss){ + try { + Model userAccountsDbModel = makeDBModel(bds, + JENA_USER_ACCOUNTS_MODEL, DB_ONT_MODEL_SPEC, ctx); + OntModel userAccountsModel = + ModelFactory.createOntologyModel( MEM_ONT_MODEL_SPEC); + + userAccountsModel.add(userAccountsDbModel); + userAccountsModel.getBaseModel().register( + new ModelSynchronizer(userAccountsDbModel)); + ctx.setAttribute("userAccountsOntModel", userAccountsModel); + + } catch (Throwable t) { + log.error("Unable to load user accounts model from DB", t); + ss.fatal(this, "Unable to load user accounts model from DB", t); + } + } + +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/WebappDaoSDBSetup.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/WebappDaoSDBSetup.java new file mode 100644 index 000000000..1ab6c92c8 --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/WebappDaoSDBSetup.java @@ -0,0 +1,275 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.vitro.webapp.servlet.setup; + +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +import javax.servlet.ServletContext; +import javax.servlet.ServletContextEvent; + +import org.apache.commons.dbcp.BasicDataSource; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import com.hp.hpl.jena.ontology.OntModel; +import com.hp.hpl.jena.ontology.OntModelSpec; +import com.hp.hpl.jena.rdf.model.Model; +import com.hp.hpl.jena.rdf.model.ModelFactory; +import com.hp.hpl.jena.rdf.model.ResIterator; +import com.hp.hpl.jena.rdf.model.Resource; +import com.hp.hpl.jena.rdf.model.ResourceFactory; +import com.hp.hpl.jena.rdf.model.Statement; +import com.hp.hpl.jena.sdb.StoreDesc; +import com.hp.hpl.jena.shared.Lock; +import com.hp.hpl.jena.util.ResourceUtils; +import com.hp.hpl.jena.util.iterator.ClosableIterator; +import com.hp.hpl.jena.vocabulary.RDF; + +import edu.cornell.mannlib.vitro.webapp.config.ConfigurationProperties; +import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary; +import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory; +import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactoryConfig; +import edu.cornell.mannlib.vitro.webapp.dao.jena.ModelContext; +import edu.cornell.mannlib.vitro.webapp.dao.jena.OntModelSelector; +import edu.cornell.mannlib.vitro.webapp.dao.jena.OntModelSelectorImpl; +import edu.cornell.mannlib.vitro.webapp.dao.jena.VitroJenaModelMaker; +import edu.cornell.mannlib.vitro.webapp.dao.jena.VitroJenaSDBModelMaker; +import edu.cornell.mannlib.vitro.webapp.dao.jena.VitroModelSource; +import edu.cornell.mannlib.vitro.webapp.dao.jena.WebappDaoFactorySDB; +import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus; + +/** + * Primarily sets up webapp DAO factories. + */ +public class WebappDaoSDBSetup extends JenaDataSourceSetupBase + implements javax.servlet.ServletContextListener { + + private static final Log log = LogFactory.getLog(WebappDaoSDBSetup.class); + + @Override + public void contextInitialized(ServletContextEvent sce) { + ServletContext ctx = sce.getServletContext(); + StartupStatus ss = StartupStatus.getBean(ctx); + + try { + long startTime = System.currentTimeMillis(); + setUpJenaDataSource(ctx, ss); + log.info((System.currentTimeMillis() - startTime) / 1000 + + " seconds to set up SDB store"); + + //TODO remove this temporary development scaffolding + if (ConfigurationProperties.getBean(sce).getProperty( + "VitroConnection.DataSource.endpointURI") != null) { + (new JenaDataSourceSetupSparql2()).contextInitialized(sce); + } + + } catch (SQLException sqle) { + // SQL exceptions are fatal and should halt startup + log.error("Error using SQL database; startup aborted.", sqle); + ss.fatal(this, "Error using SQL database; startup aborted.", sqle); + } catch (Throwable t) { + log.error("Throwable in " + this.getClass().getName(), t); + ss.fatal(this, "Throwable in " + this.getClass().getName(), t); + } + + } + + private void setUpJenaDataSource(ServletContext ctx, StartupStatus ss) throws SQLException { + + BasicDataSource bds = getApplicationDataSource(ctx); + if( bds == null ){ + ss.fatal(this, "A DataSource must be setup before "+ WebappDaoSDBSetup.class.getName() + + "is run. Make sure that JenaPersistentDataSourceSetup runs before "+ + WebappDaoSDBSetup.class.getName() ); + return; + } + + //Get the OntModelSelectors + OntModelSelectorImpl baseOms = + (OntModelSelectorImpl) ModelContext.getBaseOntModelSelector(ctx); + OntModelSelectorImpl inferenceOms = + (OntModelSelectorImpl) ModelContext.getInferenceOntModelSelector(ctx); + OntModelSelectorImpl unionOms = + (OntModelSelectorImpl) ModelContext.getUnionOntModelSelector(ctx); + + /////////////////////////////////////////////////////////////// + // Check for namespace mismatch + + checkForNamespaceMismatch( baseOms.getApplicationMetadataModel(), ctx ); + ctx.setAttribute("defaultNamespace", getDefaultNamespace(ctx)); + + /////////////////////////////////////////////////////////////// + // first startup? + + if (isFirstStartup()) { + loadDataFromFilesystem(baseOms, ctx); + } + + log.info("Setting up DAO factories"); + + /////////////////////////////////////////////////////////////// + //create assertions webapp DAO factory + + StoreDesc storeDesc = getApplicationStoreDesc(ctx); + WebappDaoFactoryConfig config = new WebappDaoFactoryConfig(); + config.setDefaultNamespace(getDefaultNamespace(ctx)); + WebappDaoFactory baseWadf = new WebappDaoFactorySDB( + baseOms, bds, storeDesc, config, + WebappDaoFactorySDB.SDBDatasetMode.ASSERTIONS_ONLY); + ctx.setAttribute("assertionsWebappDaoFactory",baseWadf); + + /////////////////////////////////////////////////////////////// + //create inference webapp DAO factory + + OntModel inferenceUnion = ModelFactory.createOntologyModel( + OntModelSpec.OWL_MEM, + ModelFactory.createUnion( + inferenceOms.getABoxModel(), + inferenceOms.getTBoxModel())); + inferenceOms.setFullModel(inferenceUnion); + ModelContext.setInferenceOntModel(inferenceOms.getFullModel(), ctx); + WebappDaoFactory infWadf = new WebappDaoFactorySDB( + inferenceOms, bds, storeDesc, config, + WebappDaoFactorySDB.SDBDatasetMode.INFERENCES_ONLY); + ctx.setAttribute("deductionsWebappDaoFactory", infWadf); + + /////////////////////////////////////////////////////////////// + //create default union webapp DAO factory + + OntModel masterUnion = ModelFactory.createOntologyModel( + DB_ONT_MODEL_SPEC, makeDBModel( + bds, WebappDaoFactorySDB.UNION_GRAPH, + DB_ONT_MODEL_SPEC, TripleStoreType.SDB, ctx)); + unionOms.setFullModel(masterUnion); + ctx.setAttribute("jenaOntModel", masterUnion); + WebappDaoFactory wadf = new WebappDaoFactorySDB( + unionOms, bds, storeDesc, config); + ctx.setAttribute("webappDaoFactory",wadf); + + makeModelMakerFromConnectionProperties(TripleStoreType.RDB, ctx); + VitroJenaModelMaker vjmm = getVitroJenaModelMaker(); + setVitroJenaModelMaker(vjmm, ctx); + makeModelMakerFromConnectionProperties(TripleStoreType.SDB, ctx); + VitroJenaSDBModelMaker vsmm = getVitroJenaSDBModelMaker(); + setVitroJenaSDBModelMaker(vsmm, ctx); + + //bdc34: I have no reason for vsmm vs vjmm. + //I don't know what are the implications of this choice. + setVitroModelSource( new VitroModelSource(vsmm,ctx), ctx); + + log.info("DAOs set up"); + } + + + /** + * If we find a "portal1" portal (and we should), its URI should use the + * default namespace. + */ + private void checkForNamespaceMismatch(OntModel model, ServletContext ctx) { + String expectedNamespace = getDefaultNamespace(ctx); + + List portals = getPortal1s(model); + + if(!portals.isEmpty() && noPortalForNamespace( + portals, expectedNamespace)) { + // There really should be only one portal 1, but if there happen to + // be multiple, just arbitrarily pick the first in the list. + Resource portal = portals.get(0); + String oldNamespace = portal.getNameSpace(); + renamePortal(portal, expectedNamespace, model); + StartupStatus ss = StartupStatus.getBean(ctx); + ss.warning(this, "\nThe default namespace has been changed \n" + + "from " + oldNamespace + + "\nto " + expectedNamespace + ".\n" + + "The application will function normally, but " + + "any individuals in the \n" + oldNamespace + " " + + "namespace will need to have their URIs \n" + + "changed in order to be served as linked data. " + + "You can use the Ingest Tools \nto change the " + + "URIs for a batch of resources."); + } + } + + private List getPortal1s(Model model) { + List portals = new ArrayList(); + try { + model.enterCriticalSection(Lock.READ); + ResIterator portalIt = model.listResourcesWithProperty( + RDF.type, PORTAL); + while (portalIt.hasNext()) { + Resource portal = portalIt.nextResource(); + if ("portal1".equals(portal.getLocalName())) { + portals.add(portal); + } + } + } finally { + model.leaveCriticalSection(); + } + return portals; + } + + private boolean noPortalForNamespace(List portals, + String expectedNamespace) { + for (Resource portal : portals) { + if(expectedNamespace.equals(portal.getNameSpace())) { + return false; + } + } + return true; + } + + private void renamePortal(Resource portal, String namespace, Model model) { + model.enterCriticalSection(Lock.WRITE); + try { + ResourceUtils.renameResource( + portal, namespace + portal.getLocalName()); + } finally { + model.leaveCriticalSection(); + } + } + + + /* ===================================================================== */ + + + @Override + public void contextDestroyed(ServletContextEvent sce) { + // Nothing to do. + } + + private boolean isEmpty(Model model) { + ClosableIterator closeIt = model.listStatements( + null, RDF.type, ResourceFactory.createResource( + VitroVocabulary.PORTAL)); + try { + if (closeIt.hasNext()) { + return false; + } else { + return true; + } + } finally { + closeIt.close(); + } + } + + private void loadDataFromFilesystem(OntModelSelector baseOms, + ServletContext ctx) { + Long startTime = System.currentTimeMillis(); + log.info("Initializing models from RDF files"); + + readOntologyFilesInPathSet(USER_ABOX_PATH, ctx, baseOms.getABoxModel()); + readOntologyFilesInPathSet(USER_TBOX_PATH, ctx, baseOms.getTBoxModel()); + readOntologyFilesInPathSet( + USER_APPMETA_PATH, ctx, baseOms.getApplicationMetadataModel()); + + log.debug(((System.currentTimeMillis() - startTime) / 1000) + + " seconds to read RDF files "); + } + + + + + } + diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/BrowseDataGetter.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/BrowseDataGetter.java index eb1a5560e..34e14477c 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/BrowseDataGetter.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/BrowseDataGetter.java @@ -21,9 +21,9 @@ import com.hp.hpl.jena.rdf.model.Model; import edu.cornell.mannlib.vitro.webapp.beans.Individual; import edu.cornell.mannlib.vitro.webapp.beans.VClass; import edu.cornell.mannlib.vitro.webapp.beans.VClassGroup; -import edu.cornell.mannlib.vitro.webapp.controller.JsonServlet; import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder; +import edu.cornell.mannlib.vitro.webapp.controller.json.JsonServlet; import edu.cornell.mannlib.vitro.webapp.dao.DisplayVocabulary; import edu.cornell.mannlib.vitro.webapp.dao.jena.VClassGroupCache; import edu.cornell.mannlib.vitro.webapp.utils.JsonToFmModel; @@ -34,28 +34,34 @@ import edu.cornell.mannlib.vitro.webapp.web.templatemodels.individuallist.Listed public class BrowseDataGetter extends DataGetterBase implements DataGetter { final static Log log = LogFactory.getLog(BrowseDataGetter.class); String dataGetterURI; + VitroRequest vreq; + ServletContext context; /** * Constructor with display model and data getter URI that will be called by reflection. */ - public BrowseDataGetter(Model displayModel, String dataGetterURI){ - this.configure(displayModel,dataGetterURI); + public BrowseDataGetter(VitroRequest vreq, Model displayModel, String dataGetterURI){ + this.configure(vreq, displayModel,dataGetterURI); } /** * Configure this instance based on the URI and display model. */ - protected void configure(Model displayModel, String dataGetterURI) { + protected void configure(VitroRequest vreq, Model displayModel, String dataGetterURI) { + if( vreq == null ) + throw new IllegalArgumentException("VitroRequest may not be null."); if( displayModel == null ) throw new IllegalArgumentException("Display Model may not be null."); if( dataGetterURI == null ) throw new IllegalArgumentException("PageUri may not be null."); - this.dataGetterURI = dataGetterURI; + this.vreq = vreq; + this.context = vreq.getSession().getServletContext(); + this.dataGetterURI = dataGetterURI; } @Override - public Map getData(ServletContext context, VitroRequest vreq, Map pageData) { + public Map getData(Map pageData) { try{ Map params = vreq.getParameterMap(); diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/ClassGroupPageData.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/ClassGroupPageData.java index cda39ef69..c523e3a5e 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/ClassGroupPageData.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/ClassGroupPageData.java @@ -12,18 +12,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.json.JSONObject; -import com.hp.hpl.jena.query.Query; -import com.hp.hpl.jena.query.QueryExecution; -import com.hp.hpl.jena.query.QueryExecutionFactory; -import com.hp.hpl.jena.query.QueryFactory; -import com.hp.hpl.jena.query.QuerySolution; -import com.hp.hpl.jena.query.QuerySolutionMap; -import com.hp.hpl.jena.query.ResultSet; -import com.hp.hpl.jena.rdf.model.Literal; import com.hp.hpl.jena.rdf.model.Model; -import com.hp.hpl.jena.rdf.model.RDFNode; -import com.hp.hpl.jena.rdf.model.ResourceFactory; -import com.hp.hpl.jena.shared.Lock; import edu.cornell.mannlib.vitro.webapp.beans.VClass; import edu.cornell.mannlib.vitro.webapp.beans.VClassGroup; @@ -43,29 +32,36 @@ public class ClassGroupPageData extends DataGetterBase implements DataGetter{ private static final Log log = LogFactory.getLog(ClassGroupPageData.class); String dataGetterURI; String classGroupUri; + VitroRequest vreq; + ServletContext context; + /** * Constructor with display model and data getter URI that will be called by reflection. */ - public ClassGroupPageData(Model displayModel, String dataGetterURI){ - this.configure(displayModel,dataGetterURI); + public ClassGroupPageData(VitroRequest vreq, Model displayModel, String dataGetterURI){ + this.configure(vreq, displayModel,dataGetterURI); } /** * Configure this instance based on the URI and display model. */ - protected void configure(Model displayModel, String dataGetterURI) { + protected void configure(VitroRequest vreq, Model displayModel, String dataGetterURI) { + if( vreq == null ) + throw new IllegalArgumentException("VitroRequest may not be null."); if( displayModel == null ) throw new IllegalArgumentException("Display Model may not be null."); if( dataGetterURI == null ) throw new IllegalArgumentException("PageUri may not be null."); + this.vreq = vreq; + this.context = vreq.getSession().getServletContext(); this.dataGetterURI = dataGetterURI; this.classGroupUri = DataGetterUtils.getClassGroupForDataGetter(displayModel, dataGetterURI); } @Override - public Map getData(ServletContext context, VitroRequest vreq, Map pageData) { + public Map getData(Map pageData) { HashMap data = new HashMap(); data.put("classGroupUri", this.classGroupUri); @@ -91,24 +87,23 @@ public class ClassGroupPageData extends DataGetterBase implements DataGetter{ break; } } - if( group == null ){ - log.error("Cannot get classgroup '" + classGroupUri); - }else{ - setAllClassCountsToZero(group); - } + + setAllClassCountsToZero(group); + + log.debug("Retrieved class group " + group.getURI() + + " and returning to template"); + if (log.isDebugEnabled()) { + List groupClasses = group.getVitroClassList(); + for (VClass v : groupClasses) { + log.debug("Class " + v.getName() + " - " + v.getURI() + + " has " + v.getEntityCount() + " entities"); + } + } }else{ throw new RuntimeException("classgroup " + classGroupUri + " does not exist in the system"); - } - - } - log.debug("Retrieved class group " + group.getURI() + " and returning to template"); - //if debug enabled, print out the number of entities within each class in the class gorup - if(log.isDebugEnabled()){ - List groupClasses = group.getVitroClassList(); - for(VClass v: groupClasses) { - log.debug("Class " + v.getName() + " - " + v.getURI() + " has " + v.getEntityCount() + " entities"); - } - } + } + } + data.put("vClassGroup", group); //may put null //This page level data getters tries to set its own template, @@ -164,7 +159,7 @@ public class ClassGroupPageData extends DataGetterBase implements DataGetter{ //Get data servuice public String getDataServiceUrl() { - return UrlBuilder.getUrl("/dataservice?getSolrIndividualsByVClass=1&vclassId="); + return UrlBuilder.getUrl("/dataservice?getRenderedSolrIndividualsByVClass=1&vclassId="); } /** diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/DataGetter.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/DataGetter.java index 5836692b3..4f1a8857e 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/DataGetter.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/DataGetter.java @@ -3,16 +3,21 @@ package edu.cornell.mannlib.vitro.webapp.utils.dataGetter; import java.util.Map; -import javax.servlet.ServletContext; - -import com.hp.hpl.jena.rdf.model.Model; - -import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; - /** * A class to get data based on configurations in RDF. These are useful for pages bug not specific to pages. * Consider using this interface when you need data based on RDF configuration. * + * Instances should be short-lived, and only used on a single HTTP request. The getData method accepts only + * a value map, so if stat is required from the request (or the servlet context), the request should be + * passed to the constructor. + * + * Constructors: Objects that implement this interface will be constructed by reflection with the following + * constructor signatures in the following order: + * DataGetter( VitroRequest vreq, Model displayModel, String dataGetterURI ) + * DataGetter( Model displayModel, String dataGetterURI ) + * DataGetter( VitroRequest vreq ) + * DataGetter() + * * The main difference between this and PageDataGetter is that these are configured not based on page URI * but on DataGetter URI. This allows a configuration of a DataGetter to be used in multiple situations. * The DataGetter is not passed information about what page it might be associated with. @@ -20,22 +25,18 @@ import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; * Using this interface is preferred over PageDataGetter because then the DataGetter can be associated with * things other than pages. * - * Constructors: Objects that implement this interface will be constructed by reflection with the following - * constructor signatures in the following order: - * DataGetter( Model displayModel, String dataGetterURI ) - * DataGetter() - * */ public interface DataGetter { - /** - * Get data. Throwing an Exception is acceptable. - * - * @param context - servlet context to get state from - * @param vreq - request to get state from - * @param valueMap - any values already generated by data getters or the controller. - * @return data to add to valueMap. Should not be null. - */ - Map getData(ServletContext context, VitroRequest vreq, Map valueMap ); + /** + * Get data. Throwing an Exception is acceptable. + * + * @param valueMap + * any values already generated by data getters or the controller. + * Might be immutable, and should not be modified within the method. + * + * @return data to add to valueMap. Might be empty, but should not be null. + */ + Map getData( Map valueMap ); } 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 897306641..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 @@ -6,7 +6,6 @@ import java.lang.reflect.InvocationTargetException; import java.net.URLEncoder; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; import java.util.List; @@ -40,11 +39,11 @@ import edu.cornell.mannlib.vitro.webapp.beans.Individual; import edu.cornell.mannlib.vitro.webapp.beans.VClass; import edu.cornell.mannlib.vitro.webapp.beans.VClassGroup; import edu.cornell.mannlib.vitro.webapp.controller.Controllers; -import edu.cornell.mannlib.vitro.webapp.controller.JsonServlet; import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.IndividualListController; -import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.IndividualListController.PageRecord; +import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder; +import edu.cornell.mannlib.vitro.webapp.controller.json.JsonServlet; import edu.cornell.mannlib.vitro.webapp.dao.DisplayVocabulary; import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary; import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory; @@ -60,40 +59,21 @@ 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); } + log.debug("getDataGettersForPage: " + dgList); return dgList; } - /** - * Tests if classInQuestion implements interFace. - */ - public static boolean isInstanceOfInterface( Class classInQuestion, Class interFace){ - if( classInQuestion == null || interFace == null ) - throw new IllegalAccessError("classInQuestion or interFace must not be null"); - - //figure out if it implements interface - Class[] interfaces = classInQuestion.getInterfaces(); - if( interfaces == null ) - return false; - boolean foundIface = false; - for( Class cz : interfaces ){ - if( interFace.equals( cz ) ){ - return true; - } - } - return false; - } - /** * Returns a DataGetter using information in the * displayModel for the individual with the URI given by dataGetterURI @@ -103,42 +83,53 @@ 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 String dgClassName = getJClassForDataGetterURI(displayModel, dataGetterURI); //figure out if it implements interface DataGetter - Class dgClass = Class.forName(dgClassName); - if( ! isInstanceOfInterface( dgClass, DataGetter.class) ){ + Class clz = Class.forName(dgClassName); + if( ! DataGetter.class.isAssignableFrom(clz) ){ + log.debug("Class doesn't implement DataGetter: '" + dgClassName + "'"); return null; } - //try to run constructor with (Model, String) parameters - Class partypes[] = { Model.class , String.class }; - Constructor ct = dgClass.getConstructor( partypes ); + // 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 }, + {} + }; - Object obj = null; - if( ct != null ){ - Object[] initargs = new Object[2]; - initargs[0]= displayModel; - initargs[1] = dataGetterURI; - obj = ct.newInstance(initargs); - } else { - log.debug("no constructor with signature " + - "(Model displayModel,String URI) found, trying empty constructor"); - obj = dgClass.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); + } + } } - if( !(obj instanceof DataGetter) ){ - log.debug("For <" + dataGetterURI + "> the class " + - "for its rdf:type " + dgClassName + " does not implement the interface DataGetter."); - return null; - } - - return (DataGetter)obj; + 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 { @@ -415,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/src/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/IndividualsForClassesDataGetter.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/IndividualsForClassesDataGetter.java index 7a0ae2ef7..1d5c10a3d 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/IndividualsForClassesDataGetter.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/IndividualsForClassesDataGetter.java @@ -5,7 +5,6 @@ package edu.cornell.mannlib.vitro.webapp.utils.dataGetter; import java.net.URLEncoder; import java.util.ArrayList; import java.util.Collections; -import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -17,30 +16,21 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.json.JSONObject; -import com.hp.hpl.jena.query.Query; import com.hp.hpl.jena.query.QueryExecution; import com.hp.hpl.jena.query.QueryExecutionFactory; -import com.hp.hpl.jena.query.QueryFactory; import com.hp.hpl.jena.query.QuerySolution; import com.hp.hpl.jena.query.QuerySolutionMap; import com.hp.hpl.jena.query.ResultSet; import com.hp.hpl.jena.rdf.model.Model; -import com.hp.hpl.jena.rdf.model.RDFNode; import com.hp.hpl.jena.rdf.model.ResourceFactory; -import com.hp.hpl.jena.rdf.model.Statement; -import com.hp.hpl.jena.rdf.model.StmtIterator; import com.hp.hpl.jena.shared.Lock; -import edu.cornell.mannlib.vitro.webapp.beans.Individual; import edu.cornell.mannlib.vitro.webapp.beans.VClass; import edu.cornell.mannlib.vitro.webapp.beans.VClassGroup; import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; -import edu.cornell.mannlib.vitro.webapp.controller.freemarker.IndividualListController; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder; import edu.cornell.mannlib.vitro.webapp.dao.DisplayVocabulary; -import edu.cornell.mannlib.vitro.webapp.dao.PageDao; import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary; -import edu.cornell.mannlib.vitro.webapp.dao.jena.ModelContext; import edu.cornell.mannlib.vitro.webapp.dao.jena.VClassGroupCache; import edu.cornell.mannlib.vitro.webapp.web.templatemodels.VClassGroupTemplateModel; @@ -52,6 +42,8 @@ import edu.cornell.mannlib.vitro.webapp.web.templatemodels.VClassGroupTemplateMo public class IndividualsForClassesDataGetter extends DataGetterBase implements DataGetter{ private static final Log log = LogFactory.getLog(IndividualsForClassesDataGetter.class); protected static String restrictClassesTemplateName = null; + VitroRequest vreq; + ServletContext context; String dataGetterURI; String classGroupURI; Map classIntersectionsMap; @@ -59,19 +51,23 @@ public class IndividualsForClassesDataGetter extends DataGetterBase implements D /** * Constructor with display model and data getter URI that will be called by reflection. */ - public IndividualsForClassesDataGetter(Model displayModel, String dataGetterURI){ - this.configure(displayModel,dataGetterURI); + public IndividualsForClassesDataGetter(VitroRequest vreq, Model displayModel, String dataGetterURI){ + this.configure(vreq,displayModel,dataGetterURI); } /** * Configure this instance based on the URI and display model. */ - protected void configure(Model displayModel, String dataGetterURI) { + protected void configure(VitroRequest vreq, Model displayModel, String dataGetterURI) { + if( vreq == null ) + throw new IllegalArgumentException("VitroRequest may not be null."); if( displayModel == null ) throw new IllegalArgumentException("Display Model may not be null."); if( dataGetterURI == null ) throw new IllegalArgumentException("PageUri may not be null."); + this.vreq = vreq; + this.context = vreq.getSession().getServletContext(); this.dataGetterURI = dataGetterURI; this.classGroupURI = DataGetterUtils.getClassGroupForDataGetter(displayModel, dataGetterURI); this.classIntersectionsMap = getClassIntersectionsMap(displayModel); @@ -122,7 +118,7 @@ public class IndividualsForClassesDataGetter extends DataGetterBase implements D } @Override - public Map getData(ServletContext context, VitroRequest vreq, Map pageData) { + public Map getData(Map pageData) { this.setTemplateName(); HashMap data = new HashMap(); diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/SparqlQueryDataGetter.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/SparqlQueryDataGetter.java index 8563e97f6..ebfe75890 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/SparqlQueryDataGetter.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/SparqlQueryDataGetter.java @@ -35,30 +35,37 @@ public class SparqlQueryDataGetter extends DataGetterBase implements DataGetter{ String queryText; String saveToVar; String modelURI; + VitroRequest vreq; + ServletContext context; + final static Log log = LogFactory.getLog(SparqlQueryDataGetter.class); /** * Constructor with display model and data getter URI that will be called by reflection. */ - public SparqlQueryDataGetter(Model displayModel, String dataGetterURI){ - this.configure(displayModel,dataGetterURI); + public SparqlQueryDataGetter(VitroRequest vreq, Model displayModel, String dataGetterURI){ + this.configure(vreq, displayModel,dataGetterURI); } @Override - public Map getData(ServletContext context, VitroRequest vreq, Map pageData) { + public Map getData(Map pageData) { return doQuery( vreq.getParameterMap(), getModel(context, vreq, modelURI)); } /** * Configure this instance based on the URI and display model. */ - protected void configure(Model displayModel, String dataGetterURI) { + protected void configure(VitroRequest vreq, Model displayModel, String dataGetterURI) { + if( vreq == null ) + throw new IllegalArgumentException("VitroRequest may not be null."); if( displayModel == null ) throw new IllegalArgumentException("Display Model may not be null."); if( dataGetterURI == null ) throw new IllegalArgumentException("PageUri may not be null."); + this.vreq = vreq; + this.context = vreq.getSession().getServletContext(); this.dataGetterURI = dataGetterURI; QuerySolutionMap initBindings = new QuerySolutionMap(); diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/log/LogUtils.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/log/LogUtils.java new file mode 100644 index 000000000..db53b88af --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/log/LogUtils.java @@ -0,0 +1,159 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.vitro.webapp.utils.log; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.TreeSet; + +import javax.servlet.http.HttpServletRequest; + +import org.apache.commons.logging.Log; + +/** + * Some static methods that might help with logging for debug purposes. + */ +public class LogUtils { + // ---------------------------------------------------------------------- + // Public Static methods + // ---------------------------------------------------------------------- + + public static String deepFormatForLog(Log log, String level, Object o) { + if (!isLevelEnabled(log, level)) { + return ""; + } + return new LogUtils(log).deepFormat(o); + } + + public static String formatRequestProperties(Log log, String level, + HttpServletRequest req) { + if (!isLevelEnabled(log, level)) { + return ""; + } + return new LogUtils(log).requestProperties(req); + } + + // ---------------------------------------------------------------------- + // The instance + // ---------------------------------------------------------------------- + + private String requestProperties(HttpServletRequest req) { + @SuppressWarnings("unchecked") + Map map = req.getParameterMap(); + + String s = req.getRequestURL().append('\n').toString(); + for (String name : new TreeSet(map.keySet())) { + s += " " + name + " = " + Arrays.toString(map.get(name)) + '\n'; + } + return s.trim(); + } + + private static boolean isLevelEnabled(Log log, String level) { + if ("fatal".equalsIgnoreCase(level)) { + return log.isFatalEnabled(); + } else if ("error".equalsIgnoreCase(level)) { + return log.isErrorEnabled(); + } else if ("warn".equalsIgnoreCase(level)) { + return log.isWarnEnabled(); + } else if ("info".equalsIgnoreCase(level)) { + return log.isInfoEnabled(); + } else if ("debug".equalsIgnoreCase(level)) { + return log.isDebugEnabled(); + } else { + return log.isTraceEnabled(); + } + } + + private final Log log; + private final List dontFormatAgain = new ArrayList(); + + private LogUtils(Log log) { + this.log = log; + } + + public String deepFormat(Object o) { + if (o == null) { + return "null"; + } + if (o instanceof String) { + return "\"" + o + "\""; + } + if (dontFormatAgain.contains(o)) { + return "..."; + } + + dontFormatAgain.add(o); + + if (o instanceof Collection) { + return formatCollection((Collection) o); + } + if (o instanceof Map) { + return formatMap((Map) (o)); + } + if (o.getClass().isArray()) { + return formatArray(o); + } + return formatObject(o); + } + + private String formatClass(Object o) { + if (o == null) { + return ""; + } + return o.getClass().getName(); + } + + private String formatCollection(Collection collection) { + StringBuilder result = new StringBuilder(formatClass(collection)); + result.append(": "); + + result.append('{'); + for (Iterator it = collection.iterator(); it.hasNext();) { + result.append(deepFormat(it.next())); + if (it.hasNext()) { + result.append(", "); + } + } + result.append('}'); + + return result.toString(); + } + + private String formatMap(Map map) { + StringBuilder result = new StringBuilder(formatClass(map)); + result.append(": "); + + result.append('{'); + for (Iterator it = map.keySet().iterator(); it.hasNext();) { + Object key = it.next(); + result.append(deepFormat(key)); + result.append('='); + result.append(deepFormat(map.get(key))); + if (it.hasNext()) { + result.append(", "); + } + } + result.append('}'); + + return result.toString(); + } + + private String formatArray(Object o) { + return formatClass(o) + ": " + Arrays.deepToString((Object[]) o); + } + + private String formatObject(Object o) { + String className = o.getClass().getName(); + String valueString = String.valueOf(o); + if (valueString.contains(className)) { + return valueString; + } else { + return formatClass(o) + ": " + valueString; + } + } + +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/menuManagement/MenuManagementDataUtils.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/menuManagement/MenuManagementDataUtils.java index 889665b50..5df4b1eae 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/menuManagement/MenuManagementDataUtils.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/menuManagement/MenuManagementDataUtils.java @@ -2,46 +2,12 @@ package edu.cornell.mannlib.vitro.webapp.utils.menuManagement; -import java.net.URLEncoder; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.List; import java.util.Map; import javax.servlet.ServletContext; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.json.JSONArray; -import org.json.JSONObject; - -import com.hp.hpl.jena.ontology.OntModel; -import com.hp.hpl.jena.rdf.model.Model; -import com.hp.hpl.jena.rdf.model.ModelFactory; -import com.hp.hpl.jena.rdf.model.RDFNode; -import com.hp.hpl.jena.rdf.model.Resource; -import com.hp.hpl.jena.rdf.model.ResourceFactory; -import com.hp.hpl.jena.rdf.model.StmtIterator; -import com.hp.hpl.jena.vocabulary.RDF; - -import edu.cornell.mannlib.vitro.webapp.beans.DataProperty; -import edu.cornell.mannlib.vitro.webapp.beans.Individual; -import edu.cornell.mannlib.vitro.webapp.beans.VClass; -import edu.cornell.mannlib.vitro.webapp.beans.VClassGroup; -import edu.cornell.mannlib.vitro.webapp.controller.Controllers; -import edu.cornell.mannlib.vitro.webapp.controller.JsonServlet; -import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; -import edu.cornell.mannlib.vitro.webapp.controller.freemarker.IndividualListController.PageRecord; -import edu.cornell.mannlib.vitro.webapp.controller.freemarker.IndividualListController; -import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder; -import edu.cornell.mannlib.vitro.webapp.dao.DisplayVocabulary; -import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary; -import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory; -import edu.cornell.mannlib.vitro.webapp.dao.jena.ModelContext; -import edu.cornell.mannlib.vitro.webapp.dao.jena.VClassGroupCache; /* * This class includes methods that help in selecting a data getter based on diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/menuManagement/ProcessClassGroup.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/menuManagement/ProcessClassGroup.java index 171c28933..d09c0a5cd 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/menuManagement/ProcessClassGroup.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/menuManagement/ProcessClassGroup.java @@ -2,47 +2,22 @@ package edu.cornell.mannlib.vitro.webapp.utils.menuManagement; -import java.net.URLEncoder; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.List; import java.util.Map; import javax.servlet.ServletContext; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.json.JSONArray; -import org.json.JSONObject; -import com.hp.hpl.jena.ontology.OntModel; import com.hp.hpl.jena.rdf.model.Model; import com.hp.hpl.jena.rdf.model.ModelFactory; -import com.hp.hpl.jena.rdf.model.RDFNode; import com.hp.hpl.jena.rdf.model.Resource; import com.hp.hpl.jena.rdf.model.ResourceFactory; -import com.hp.hpl.jena.rdf.model.StmtIterator; import com.hp.hpl.jena.vocabulary.RDF; -import edu.cornell.mannlib.vitro.webapp.beans.DataProperty; -import edu.cornell.mannlib.vitro.webapp.beans.Individual; -import edu.cornell.mannlib.vitro.webapp.beans.VClass; -import edu.cornell.mannlib.vitro.webapp.beans.VClassGroup; -import edu.cornell.mannlib.vitro.webapp.controller.Controllers; -import edu.cornell.mannlib.vitro.webapp.controller.JsonServlet; import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; -import edu.cornell.mannlib.vitro.webapp.controller.freemarker.IndividualListController.PageRecord; -import edu.cornell.mannlib.vitro.webapp.controller.freemarker.IndividualListController; -import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder; -import edu.cornell.mannlib.vitro.webapp.dao.DisplayVocabulary; -import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary; -import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory; -import edu.cornell.mannlib.vitro.webapp.dao.jena.VClassGroupCache; -import edu.cornell.mannlib.vitro.webapp.utils.dataGetter.DataGetterUtils; import edu.cornell.mannlib.vitro.webapp.utils.dataGetter.ClassGroupPageData; +import edu.cornell.mannlib.vitro.webapp.utils.dataGetter.DataGetterUtils; /* * Handle processing of data retrieved from ClassGroupPage data getter to return to form template diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/menuManagement/ProcessIndividualsForClasses.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/menuManagement/ProcessIndividualsForClasses.java index 52c3c4a6c..802a82e48 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/menuManagement/ProcessIndividualsForClasses.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/menuManagement/ProcessIndividualsForClasses.java @@ -2,12 +2,7 @@ package edu.cornell.mannlib.vitro.webapp.utils.menuManagement; -import java.net.URLEncoder; import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Enumeration; -import java.util.HashMap; import java.util.List; import java.util.Map; @@ -15,32 +10,17 @@ import javax.servlet.ServletContext; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.json.JSONArray; -import org.json.JSONObject; -import com.hp.hpl.jena.ontology.OntModel; import com.hp.hpl.jena.rdf.model.Model; import com.hp.hpl.jena.rdf.model.ModelFactory; -import com.hp.hpl.jena.rdf.model.RDFNode; import com.hp.hpl.jena.rdf.model.Resource; import com.hp.hpl.jena.rdf.model.ResourceFactory; -import com.hp.hpl.jena.rdf.model.StmtIterator; import com.hp.hpl.jena.vocabulary.RDF; -import edu.cornell.mannlib.vitro.webapp.beans.DataProperty; -import edu.cornell.mannlib.vitro.webapp.beans.Individual; import edu.cornell.mannlib.vitro.webapp.beans.VClass; import edu.cornell.mannlib.vitro.webapp.beans.VClassGroup; -import edu.cornell.mannlib.vitro.webapp.controller.Controllers; -import edu.cornell.mannlib.vitro.webapp.controller.JsonServlet; import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; -import edu.cornell.mannlib.vitro.webapp.controller.freemarker.IndividualListController.PageRecord; -import edu.cornell.mannlib.vitro.webapp.controller.freemarker.IndividualListController; -import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder; import edu.cornell.mannlib.vitro.webapp.dao.DisplayVocabulary; -import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary; -import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory; -import edu.cornell.mannlib.vitro.webapp.dao.jena.VClassGroupCache; import edu.cornell.mannlib.vitro.webapp.utils.dataGetter.DataGetterUtils; import edu.cornell.mannlib.vitro.webapp.utils.dataGetter.IndividualsForClassesDataGetter; diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/menuManagement/SelectDataGetterUtils.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/menuManagement/SelectDataGetterUtils.java index 635bd0fe6..692ae4605 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/menuManagement/SelectDataGetterUtils.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/menuManagement/SelectDataGetterUtils.java @@ -2,44 +2,18 @@ package edu.cornell.mannlib.vitro.webapp.utils.menuManagement; -import java.net.URLEncoder; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.List; import java.util.Map; import javax.servlet.ServletContext; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.json.JSONArray; -import org.json.JSONObject; -import com.hp.hpl.jena.ontology.OntModel; import com.hp.hpl.jena.rdf.model.Model; import com.hp.hpl.jena.rdf.model.ModelFactory; -import com.hp.hpl.jena.rdf.model.RDFNode; import com.hp.hpl.jena.rdf.model.Resource; -import com.hp.hpl.jena.rdf.model.ResourceFactory; -import com.hp.hpl.jena.rdf.model.StmtIterator; -import com.hp.hpl.jena.vocabulary.RDF; -import edu.cornell.mannlib.vitro.webapp.beans.DataProperty; -import edu.cornell.mannlib.vitro.webapp.beans.Individual; -import edu.cornell.mannlib.vitro.webapp.beans.VClass; -import edu.cornell.mannlib.vitro.webapp.beans.VClassGroup; -import edu.cornell.mannlib.vitro.webapp.controller.Controllers; -import edu.cornell.mannlib.vitro.webapp.controller.JsonServlet; import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; -import edu.cornell.mannlib.vitro.webapp.controller.freemarker.IndividualListController.PageRecord; -import edu.cornell.mannlib.vitro.webapp.controller.freemarker.IndividualListController; -import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder; -import edu.cornell.mannlib.vitro.webapp.dao.DisplayVocabulary; -import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory; -import edu.cornell.mannlib.vitro.webapp.dao.jena.VClassGroupCache; import edu.cornell.mannlib.vitro.webapp.utils.dataGetter.ClassGroupPageData; import edu.cornell.mannlib.vitro.webapp.utils.dataGetter.IndividualsForClassesDataGetter; diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/pageDataGetter/BrowseDataGetter.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/pageDataGetter/BrowseDataGetter.java index 5fbbee18c..25222968e 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/pageDataGetter/BrowseDataGetter.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/pageDataGetter/BrowseDataGetter.java @@ -19,9 +19,9 @@ import org.json.JSONObject; import edu.cornell.mannlib.vitro.webapp.beans.Individual; import edu.cornell.mannlib.vitro.webapp.beans.VClass; import edu.cornell.mannlib.vitro.webapp.beans.VClassGroup; -import edu.cornell.mannlib.vitro.webapp.controller.JsonServlet; import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder; +import edu.cornell.mannlib.vitro.webapp.controller.json.JsonServlet; import edu.cornell.mannlib.vitro.webapp.dao.DisplayVocabulary; import edu.cornell.mannlib.vitro.webapp.dao.jena.VClassGroupCache; import edu.cornell.mannlib.vitro.webapp.utils.JsonToFmModel; diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/pageDataGetter/PageDataGetterUtils.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/pageDataGetter/PageDataGetterUtils.java index f3db2c8d6..59670bb02 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/pageDataGetter/PageDataGetterUtils.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/pageDataGetter/PageDataGetterUtils.java @@ -24,11 +24,11 @@ import edu.cornell.mannlib.vitro.webapp.beans.Individual; import edu.cornell.mannlib.vitro.webapp.beans.VClass; import edu.cornell.mannlib.vitro.webapp.beans.VClassGroup; import edu.cornell.mannlib.vitro.webapp.controller.Controllers; -import edu.cornell.mannlib.vitro.webapp.controller.JsonServlet; import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; -import edu.cornell.mannlib.vitro.webapp.controller.freemarker.IndividualListController.PageRecord; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.IndividualListController; +import edu.cornell.mannlib.vitro.webapp.controller.freemarker.IndividualListController.PageRecord; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder; +import edu.cornell.mannlib.vitro.webapp.controller.json.JsonServlet; import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory; import edu.cornell.mannlib.vitro.webapp.dao.jena.VClassGroupCache; import edu.cornell.mannlib.vitro.webapp.utils.dataGetter.DataGetterUtils; @@ -126,12 +126,9 @@ public class PageDataGetterUtils { String className = getClassNameFromUri(dgClassName); Class clz = Class.forName(className); - if( DataGetterUtils.isInstanceOfInterface(clz, PageDataGetter.class)){ - Object obj = clz.newInstance(); - if(obj != null && obj instanceof PageDataGetter) { - PageDataGetter pg = (PageDataGetter) obj; - dataGetterObjects.add(pg); - } + if( PageDataGetter.class.isAssignableFrom(clz)){ + PageDataGetter pg = (PageDataGetter) clz.newInstance(); + dataGetterObjects.add(pg); }// else skip if class does not implement PageDataGetter } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/TemplateUtils.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/TemplateUtils.java new file mode 100644 index 000000000..255af39ee --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/TemplateUtils.java @@ -0,0 +1,53 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.vitro.webapp.web; + +import java.util.List; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import freemarker.template.TemplateCollectionModel; +import freemarker.template.TemplateMethodModelEx; +import freemarker.template.TemplateModel; +import freemarker.template.TemplateModelException; +import freemarker.template.TemplateScalarModel; +import freemarker.template.TemplateSequenceModel; +import freemarker.template.utility.DeepUnwrap; + +/** + * TODO + */ +public class TemplateUtils { + private static final Log log = LogFactory.getLog(TemplateUtils.class); + + public static class DropFromSequence implements TemplateMethodModelEx { + @SuppressWarnings({ "rawtypes", "unchecked" }) + @Override + public Object exec(List args) throws TemplateModelException { + if (args.size() != 2) { + throw new TemplateModelException("Wrong number of arguments"); + } + + TemplateModel sequenceWrapper = (TemplateModel) args.get(0); + if (!(sequenceWrapper instanceof TemplateSequenceModel) + && !(sequenceWrapper instanceof TemplateCollectionModel)) { + throw new TemplateModelException( + "First argument must be a sequence or a collection"); + } + TemplateModel unwantedWrapper = (TemplateModel) args.get(1); + if (!(unwantedWrapper instanceof TemplateScalarModel)) { + throw new TemplateModelException( + "Second argument must be a string"); + } + + List sequence = (List) DeepUnwrap + .unwrap(sequenceWrapper); + String unwanted = (String) DeepUnwrap.unwrap(unwantedWrapper); + + sequence.remove(unwanted); + return sequence; + } + + } +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/ViewFinder.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/ViewFinder.java index 966f8df84..1c2337d5c 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/ViewFinder.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/ViewFinder.java @@ -71,7 +71,7 @@ public class ViewFinder { private String findCustomTemplateByVClasses(Individual individual, VitroRequest vreq) { // // Method method = view.getMethod(); -// TemplateLoader templateLoader = ((Configuration) vreq.getAttribute("freemarkerConfig")).getTemplateLoader(); +// TemplateLoader templateLoader = FreemarkerConfigurationLoader.getConfig(vreq).getTemplateLoader(); // // /* RY The logic here is incorrect. The vclasses are // * returned in a random order, whereas we need to diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/directives/BaseTemplateDirectiveModel.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/directives/BaseTemplateDirectiveModel.java index 41536e766..a1500a2c5 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/directives/BaseTemplateDirectiveModel.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/directives/BaseTemplateDirectiveModel.java @@ -4,19 +4,17 @@ package edu.cornell.mannlib.vitro.webapp.web.directives; import java.io.IOException; import java.io.StringWriter; -import java.util.HashMap; import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import freemarker.core.Environment; +import freemarker.template.SimpleScalar; import freemarker.template.Template; import freemarker.template.TemplateDirectiveModel; import freemarker.template.TemplateException; -import freemarker.template.TemplateHashModel; import freemarker.template.TemplateModelException; -import freemarker.template.utility.DeepUnwrap; public abstract class BaseTemplateDirectiveModel implements TemplateDirectiveModel { @@ -48,4 +46,41 @@ public abstract class BaseTemplateDirectiveModel implements TemplateDirectiveMod return template; } + // ---------------------------------------------------------------------- + // Convenience methods for parsing the parameter map + // ---------------------------------------------------------------------- + + /** Get the parameter, or throw an exception. */ + protected String getRequiredSimpleScalarParameter(Map params, + String name) throws TemplateModelException { + Object o = params.get(name); + if (o == null) { + throw new TemplateModelException("The '" + name + + "' parameter is required" + "."); + } + + if (!(o instanceof SimpleScalar)) { + throw new TemplateModelException("The '" + name + + "' parameter must be a string value."); + } + + return o.toString(); + } + + /** Get the parameter, or "null" if the parameter is not provided. */ + protected String getOptionalSimpleScalarParameter(Map params, + String name) throws TemplateModelException { + Object o = params.get(name); + if (o == null) { + return null; + } + + if (!(o instanceof SimpleScalar)) { + throw new TemplateModelException("The '" + name + + "' parameter must be a string value."); + } + + return o.toString(); + } + } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/directives/EmailDirective.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/directives/EmailDirective.java index 58ca99ada..913e69782 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/directives/EmailDirective.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/directives/EmailDirective.java @@ -14,7 +14,6 @@ import org.apache.commons.logging.LogFactory; import edu.cornell.mannlib.vitro.webapp.email.FreemarkerEmailMessage; import freemarker.core.Environment; -import freemarker.template.SimpleScalar; import freemarker.template.TemplateDirectiveBody; import freemarker.template.TemplateException; import freemarker.template.TemplateModel; @@ -60,21 +59,6 @@ public class EmailDirective extends BaseTemplateDirectiveModel { } } - private String getOptionalSimpleScalarParameter(Map params, - String name) throws TemplateModelException { - Object o = params.get(name); - if (o == null) { - return null; - } - - if (!(o instanceof SimpleScalar)) { - throw new TemplateModelException("The '" + name + "' parameter " - + "for the email directive must be a string value."); - } - - return o.toString(); - } - @Override public Map help(String name) { Map map = new LinkedHashMap(); diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/directives/IndividualShortViewDirective.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/directives/IndividualShortViewDirective.java new file mode 100644 index 000000000..981bafbf7 --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/directives/IndividualShortViewDirective.java @@ -0,0 +1,152 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.vitro.webapp.web.directives; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import edu.cornell.mannlib.vitro.webapp.beans.Individual; +import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; +import edu.cornell.mannlib.vitro.webapp.dao.IndividualDao; +import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory; +import edu.cornell.mannlib.vitro.webapp.services.shortview.ShortViewService; +import edu.cornell.mannlib.vitro.webapp.services.shortview.ShortViewServiceSetup; +import edu.cornell.mannlib.vitro.webapp.services.shortview.ShortViewService.ShortViewContext; +import edu.cornell.mannlib.vitro.webapp.services.shortview.ShortViewService.TemplateAndSupplementalData; +import freemarker.core.Environment; +import freemarker.template.ObjectWrapper; +import freemarker.template.Template; +import freemarker.template.TemplateDirectiveBody; +import freemarker.template.TemplateException; +import freemarker.template.TemplateModel; +import freemarker.template.TemplateModelException; + +/** + * Find the short-view template for the specified Individual in the specified + * context. Get any required data, and render the template to HTML. + */ +public class IndividualShortViewDirective extends BaseTemplateDirectiveModel { + private static final Log log = LogFactory + .getLog(IndividualShortViewDirective.class); + + @Override + public void execute(Environment env, Map params, TemplateModel[] loopVars, + TemplateDirectiveBody body) throws TemplateException, IOException { + // Get the Individual URI and check it. + String individualUri = getRequiredSimpleScalarParameter(params, "uri"); + Individual individual = getIndividual(individualUri); + if (individual == null) { + throw new TemplateModelException( + "Can't find individual for URI: \"" + individualUri + "\""); + } + + // Get the view context and check it. + String vcString = getRequiredSimpleScalarParameter(params, + "viewContext"); + ShortViewContext viewContext = ShortViewContext.fromString(vcString); + if (viewContext == null) { + throw new TemplateModelException( + "viewContext must be one of these: " + + ShortViewContext.valueList()); + } + + // Find the details of the short view and include it in the output. + renderShortView(individual, viewContext); + } + + private Individual getIndividual(String individualUri) { + Environment env = Environment.getCurrentEnvironment(); + HttpServletRequest request = (HttpServletRequest) env + .getCustomAttribute("request"); + VitroRequest vreq = new VitroRequest(request); + WebappDaoFactory wdf = vreq.getWebappDaoFactory(); + IndividualDao iDao = wdf.getIndividualDao(); + return iDao.getIndividualByURI(individualUri); + } + + private void renderShortView(Individual individual, + ShortViewContext svContext) { + Environment env = Environment.getCurrentEnvironment(); + + ServletContext ctx = (ServletContext) env.getCustomAttribute("context"); + VitroRequest vreq = new VitroRequest( + (HttpServletRequest) env.getCustomAttribute("request")); + ShortViewService svs = ShortViewServiceSetup.getService(ctx); + TemplateAndSupplementalData svInfo = svs.getShortViewInfo(individual, + svContext, vreq); + + ObjectWrapper objectWrapper = env.getConfiguration().getObjectWrapper(); + + for (String name : svInfo.getSupplementalData().keySet()) { + Object value = svInfo.getSupplementalData().get(name); + try { + env.setVariable(name, objectWrapper.wrap(value)); + } catch (TemplateModelException e) { + log.error("Failed to wrap supplemental data '" + name + "' = '" + + value + "'", e); + } + } + + try { + Template template = env.getTemplateForInclusion( + svInfo.getTemplateName(), null, true); + env.include(template); + } catch (IOException e) { + log.error("Could not load template '" + svInfo.getTemplateName() + + "'", e); + renderErrorMessage(individual); + } catch (TemplateException e) { + log.error("Could not process template '" + svInfo.getTemplateName() + + "'", e); + renderErrorMessage(individual); + } + } + + /** If there is a problem rendering the custom view, do this instead. */ + private void renderErrorMessage(Individual individual) { + Environment env = Environment.getCurrentEnvironment(); + try { + env.getOut().append( + "Can't process the custom short view for " + + individual.getName() + ""); + } catch (IOException e1) { + e1.printStackTrace(); + } + } + + @Override + public Map help(String name) { + Map map = new LinkedHashMap(); + + map.put("effect", "Find the short view that applies " + + "to this individual in this context -- a template and " + + "optional DataGetters. " + + "Execute the DataGetters and render the template."); + + map.put("comments", + "The path should be an absolute path, starting with \"/\"."); + + Map params = new HashMap(); + params.put("uri", "The URI of the individual being displayed."); + params.put("viewContext", + "One of these: " + ShortViewContext.valueList()); + map.put("parameters", params); + + List examples = new ArrayList(); + examples.add("<img src=\"<@shortView uri=individual.uri viewContext=\"SEARCH\" />\" />"); + map.put("examples", examples); + + return map; + } + +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/jsptags/InputElementFormattingTag.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/jsptags/InputElementFormattingTag.java index d5eacd8a5..395c8e08a 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/jsptags/InputElementFormattingTag.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/jsptags/InputElementFormattingTag.java @@ -406,7 +406,7 @@ public class InputElementFormattingTag extends TagSupport { } //get freemarker Configuration - Configuration fmConfig = FreemarkerConfigurationLoader.getConfig(vreq, pageContext.getServletContext()); + Configuration fmConfig = FreemarkerConfigurationLoader.getConfig(vreq); /* populate the pieces */ String classStr = doClass(); diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/customlistview/PropertyListConfig.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/customlistview/PropertyListConfig.java index 8ab6961e0..651114aff 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/customlistview/PropertyListConfig.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/customlistview/PropertyListConfig.java @@ -40,6 +40,7 @@ public class PropertyListConfig { // TODO Lump these together into the PropertyListConfigContext private final ObjectPropertyTemplateModel optm; private final VitroRequest vreq; + private final TemplateLoader templateLoader; private boolean isDefaultConfig; private Set constructQueries; @@ -47,12 +48,14 @@ public class PropertyListConfig { private String templateName; private ObjectPropertyDataPostProcessor postprocessor; // never null - public PropertyListConfig(ObjectPropertyTemplateModel optm, VitroRequest vreq, ObjectProperty op, boolean editing) + public PropertyListConfig(ObjectPropertyTemplateModel optm, TemplateLoader templateLoader, VitroRequest vreq, + ObjectProperty op, boolean editing) throws InvalidConfigurationException { this.optm = optm; this.vreq = vreq; WebappDaoFactory wadf = vreq.getWebappDaoFactory(); + this.templateLoader = templateLoader; // Get the custom config filename String configFileName = wadf.getObjectPropertyDao().getCustomListViewConfigFileName(op); @@ -117,10 +120,8 @@ public class PropertyListConfig { return ConfigError.NO_TEMPLATE; } - Configuration fmConfig = (Configuration) vreq.getAttribute("freemarkerConfig"); - TemplateLoader tl = fmConfig.getTemplateLoader(); try { - if ( tl.findTemplateSource(templateName) == null ) { + if ( templateLoader.findTemplateSource(templateName) == null ) { return ConfigError.TEMPLATE_NOT_FOUND; } } catch (IOException e) { diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/edit/EditConfigurationTemplateModel.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/edit/EditConfigurationTemplateModel.java index 2d442d048..d040d6856 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/edit/EditConfigurationTemplateModel.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/edit/EditConfigurationTemplateModel.java @@ -33,8 +33,8 @@ import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory; import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditConfigurationUtils; import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditConfigurationVTwo; import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditElementVTwo; -import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.FieldVTwo; -import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.SelectListGeneratorVTwo; +import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.fields.FieldVTwo; +import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.fields.SelectListGeneratorVTwo; import edu.cornell.mannlib.vitro.webapp.web.beanswrappers.ReadOnlyBeansWrapper; import edu.cornell.mannlib.vitro.webapp.web.templatemodels.BaseTemplateModel; import edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual.ObjectPropertyStatementTemplateModel; @@ -48,7 +48,7 @@ public class EditConfigurationTemplateModel extends BaseTemplateModel { VitroRequest vreq; private Log log = LogFactory.getLog(EditConfigurationTemplateModel.class); - public EditConfigurationTemplateModel( EditConfigurationVTwo editConfig, VitroRequest vreq){ + public EditConfigurationTemplateModel( EditConfigurationVTwo editConfig, VitroRequest vreq) throws Exception{ this.editConfig = editConfig; this.vreq = vreq; //get additional data that may be required to generate template @@ -72,7 +72,7 @@ public class EditConfigurationTemplateModel extends BaseTemplateModel { * Such as options for a drop-down etc. */ - private void retrieveEditData() { + private void retrieveEditData() throws Exception { //Get vitro request attributes for setFormTitle(); setSubmitLabel(); @@ -89,17 +89,16 @@ public class EditConfigurationTemplateModel extends BaseTemplateModel { //Based on certain pre-set fields/variables, look for what //drop-downs need to be populated - private void populateDropdowns() { + private void populateDropdowns() throws Exception { //For each field with an optionType defined, create the options WebappDaoFactory wdf = vreq.getWebappDaoFactory(); for(String fieldName: editConfig.getFields().keySet()){ FieldVTwo field = editConfig.getField(fieldName); - if( field.getOptionsType() == FieldVTwo.OptionsType.UNDEFINED - || field.getOptionsType() == null ){ + if( field.getFieldOptions() == null ){ continue; } - Map optionsMap = SelectListGeneratorVTwo.getOptions(editConfig, fieldName, wdf); + Map optionsMap = SelectListGeneratorVTwo.getOptions(editConfig, fieldName, wdf); optionsMap = SelectListGeneratorVTwo.getSortedMap(optionsMap); pageData.put(fieldName, optionsMap); } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/ObjectPropertyTemplateModel.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/ObjectPropertyTemplateModel.java index ec0acabf3..b181ae505 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/ObjectPropertyTemplateModel.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/ObjectPropertyTemplateModel.java @@ -22,6 +22,7 @@ import edu.cornell.mannlib.vitro.webapp.beans.Individual; import edu.cornell.mannlib.vitro.webapp.beans.ObjectProperty; import edu.cornell.mannlib.vitro.webapp.beans.Property; import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; +import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerConfigurationLoader; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder.ParamMap; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder.Route; @@ -29,6 +30,7 @@ import edu.cornell.mannlib.vitro.webapp.dao.ObjectPropertyStatementDao; import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary; import edu.cornell.mannlib.vitro.webapp.web.templatemodels.customlistview.InvalidConfigurationException; import edu.cornell.mannlib.vitro.webapp.web.templatemodels.customlistview.PropertyListConfig; +import freemarker.cache.TemplateLoader; public abstract class ObjectPropertyTemplateModel extends PropertyTemplateModel { @@ -87,7 +89,7 @@ public abstract class ObjectPropertyTemplateModel extends PropertyTemplateModel // Get the config for this object property try { - config = new PropertyListConfig(this, vreq, op, editing); + config = new PropertyListConfig(this, getFreemarkerTemplateLoader(), vreq, op, editing); } catch (InvalidConfigurationException e) { throw e; } catch (Exception e) { @@ -128,6 +130,18 @@ public abstract class ObjectPropertyTemplateModel extends PropertyTemplateModel } } + /** + * Pull this into a protected method so we can stub it out in the unit tests. + * Other options: + * 1) receive a TemplateLoader into the constructor of ObjectPropertyTemplateModel, + * 2) provide a service that will check to see whether a given template name is valid, + * 3) skip the test for valid template name until we try to use the thing. + * This will do for now. + */ + protected TemplateLoader getFreemarkerTemplateLoader() { + return FreemarkerConfigurationLoader.getConfig(vreq).getTemplateLoader(); + } + protected List> getStatementData() { ObjectPropertyStatementDao opDao = vreq.getWebappDaoFactory().getObjectPropertyStatementDao(); return opDao.getObjectPropertyStatementsForIndividualByProperty(subjectUri, propertyUri, objectKey, getSelectQuery(), getConstructQueries()); diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/searchresult/BaseIndividualSearchResult.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/searchresult/BaseIndividualSearchResult.java index 1356a8fa3..7fa0fce6d 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/searchresult/BaseIndividualSearchResult.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/searchresult/BaseIndividualSearchResult.java @@ -45,6 +45,10 @@ public abstract class BaseIndividualSearchResult extends BaseTemplateModel { /* Template properties */ + public String getUri() { + return individual.getURI(); + } + public String getProfileUrl() { return UrlBuilder.getIndividualProfileUrl(individual, vreq); } @@ -59,10 +63,6 @@ public abstract class BaseIndividualSearchResult extends BaseTemplateModel { return types.values(); } - public String getSearchView() { - return getView(ClassView.SEARCH); - } - public String getSnippet() { return individual.getSearchSnippet(); } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/widgets/BrowseWidget.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/widgets/BrowseWidget.java index 86fe190c2..d48841ffc 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/widgets/BrowseWidget.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/widgets/BrowseWidget.java @@ -19,9 +19,8 @@ import org.json.JSONObject; import edu.cornell.mannlib.vitro.webapp.beans.Individual; import edu.cornell.mannlib.vitro.webapp.beans.VClass; import edu.cornell.mannlib.vitro.webapp.beans.VClassGroup; -import edu.cornell.mannlib.vitro.webapp.controller.JsonServlet; import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; -import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerHttpServlet; +import edu.cornell.mannlib.vitro.webapp.controller.json.JsonServlet; import edu.cornell.mannlib.vitro.webapp.dao.jena.VClassGroupCache; import edu.cornell.mannlib.vitro.webapp.utils.JsonToFmModel; import edu.cornell.mannlib.vitro.webapp.web.templatemodels.VClassGroupTemplateModel; diff --git a/webapp/test/edu/cornell/mannlib/vitro/webapp/auth/policy/PolicyHelper_ModelsTest.java b/webapp/test/edu/cornell/mannlib/vitro/webapp/auth/policy/PolicyHelper_ModelsTest.java index 888e488cb..e2672dc02 100644 --- a/webapp/test/edu/cornell/mannlib/vitro/webapp/auth/policy/PolicyHelper_ModelsTest.java +++ b/webapp/test/edu/cornell/mannlib/vitro/webapp/auth/policy/PolicyHelper_ModelsTest.java @@ -83,7 +83,7 @@ public class PolicyHelper_ModelsTest extends AbstractTestClass { setLoggerLevel(ServletPolicyList.class, Level.WARN); ServletPolicyList.addPolicy(ctx, new MySimplePolicy()); - setLoggerLevel(PolicyHelper.class, Level.DEBUG); +// setLoggerLevel(PolicyHelper.class, Level.DEBUG); } // ---------------------------------------------------------------------- diff --git a/webapp/test/edu/cornell/mannlib/vitro/webapp/controller/json/JsonServletTest.java b/webapp/test/edu/cornell/mannlib/vitro/webapp/controller/json/JsonServletTest.java new file mode 100644 index 000000000..ee63e2845 --- /dev/null +++ b/webapp/test/edu/cornell/mannlib/vitro/webapp/controller/json/JsonServletTest.java @@ -0,0 +1,250 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.vitro.webapp.controller.json; + +import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR; +import static javax.servlet.http.HttpServletResponse.SC_OK; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +import java.io.IOException; + +import javax.servlet.ServletException; + +import org.apache.log4j.Level; +import org.json.JSONException; +import org.json.JSONObject; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; + +import stubs.edu.cornell.mannlib.vitro.webapp.dao.VClassDaoStub; +import stubs.edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactoryStub; +import stubs.javax.servlet.ServletConfigStub; +import stubs.javax.servlet.ServletContextStub; +import stubs.javax.servlet.http.HttpServletRequestStub; +import stubs.javax.servlet.http.HttpServletResponseStub; +import stubs.javax.servlet.http.HttpSessionStub; +import stubs.org.apache.solr.client.solrj.SolrServerStub; +import edu.cornell.mannlib.vitro.testing.AbstractTestClass; +import edu.cornell.mannlib.vitro.webapp.beans.VClass; +import edu.cornell.mannlib.vitro.webapp.search.solr.SolrSetup; + +/** + * TODO + */ +public class JsonServletTest extends AbstractTestClass { + private static final String GET_SOLR_INDIVIDUALS_BY_VCLASS = "getSolrIndividualsByVClass"; + + private static final String GET_VCLASSES_FOR_VCLASS_GROUP = "getVClassesForVClassGroup"; + + private static final String VCLASS_ID = "vclassId"; + + /** + * Test plan + * + *
+	 * 
+	 * GetEntitiesByVClass, GetEntitiesByVClassContinuation
+	 * 	from ents_edit.js
+	 * 		ents_edit_head.jsp
+	 *  (there is an ents_edit.jsp, invoked from EntityEditController, which does not seem to invoke ents_edit.js)
+	 * 
+	 * GetSolrIndividualsByVClass
+	 * 	Mock out SolrServer (from SolrSetup) and IndividualDao
+	 *  invoked by BrowseDataGetter.java
+	 *  	home page
+	 *  invoked by ClassGroupPageData.java
+	 *  	>>>> Bring up "People" tab.
+	 *  invoked by BrowseWidget.java
+	 * 
+	 * GetSolrIndividualsByVClasses
+	 * 	Mock out SolrServer (from SolrSetup) and IndividualDao
+	 *  invoked by IndividualsForClassesDataGetter.java
+	 *  	ProcessIndividualsForClasses
+	 *  		extended in vivo by ProcessInternalClasses
+	 *  		SelectDataGetterUtils.java
+	 *  	SelectDataGetterUtils
+	 *  		MenuManagementEdit.java
+	 *  		MenuManagementController.java
+	 *  	extended in vivo by InternalClassesDataGetter, also invoked by SelectDataGetterUtils
+	 * 
+	 * GetDataForPage
+	 * 	Mock out PageDao
+	 * 
+ */ + + private JsonServlet servlet; + private ServletConfigStub config; + private ServletContextStub ctx; + private HttpSessionStub session; + private HttpServletRequestStub req; + private HttpServletResponseStub resp; + + private WebappDaoFactoryStub wadf; + private VClassDaoStub vcDao; + + private SolrServerStub solr; + + @Before + public void setup() throws ServletException { + ctx = new ServletContextStub(); + + session = new HttpSessionStub(); + session.setServletContext(ctx); + + config = new ServletConfigStub(); + config.setServletContext(ctx); + + servlet = new JsonServlet(); + servlet.init(config); + + req = new HttpServletRequestStub(); + req.setMethod("GET"); + req.setSession(session); + + resp = new HttpServletResponseStub(); + + wadf = new WebappDaoFactoryStub(); + req.setAttribute("webappDaoFactory", wadf); + ctx.setAttribute("webappDaoFactory", wadf); + + vcDao = new VClassDaoStub(); + wadf.setVClassDao(vcDao); + + solr = new SolrServerStub(); + ctx.setAttribute(SolrSetup.SOLR_SERVER, solr); + } + + @Test + public void noRecognizedRequestParameters() throws ServletException, + IOException { + servlet.service(req, resp); + assertEquals("empty response", "", resp.getOutput()); + assertEquals("status=ok", SC_OK, resp.getStatus()); + } + + @Test + public void vclassesNoClassgroup() throws ServletException, IOException { + setLoggerLevel(JsonServlet.class, Level.FATAL); + setLoggerLevel(JsonObjectProducer.class, Level.FATAL); + req.addParameter(GET_VCLASSES_FOR_VCLASS_GROUP, "true"); + servlet.service(req, resp); + assertFailureWithErrorMessage("java.lang.Exception: no URI passed for classgroupUri"); + assertEquals("status=failure", SC_INTERNAL_SERVER_ERROR, + resp.getStatus()); + } + + /** + * TODO Modify VClassGroupCache so it can be stubbed out. JsonServlet asks + * VClassGroupCache for the current instance, and VClassGroupCache is a + * concrete class instead of an interface, so we can't replace the instance + * with one we like better. Furthermore, VClassGroupCache has a private + * constructor, so we can't change its behavior at all. + * + * Also test: success but no VClasses found, success with one VClass, + * success with multiple VClasses. In each case, confirm proper status, + * character encoding, and content type on the response. + */ + @Ignore + @Test + public void vclassesClassgroupNotRecognized() throws ServletException, + IOException { + req.addParameter(GET_VCLASSES_FOR_VCLASS_GROUP, "true"); + req.addParameter("classgroupUri", "http://bogusUri"); + servlet.service(req, resp); + assertEquals("empty response", "", resp.getOutput()); + assertEquals("status=failure", SC_INTERNAL_SERVER_ERROR, + resp.getStatus()); + } + + @Test + public void individualsByClassNoVClass() throws ServletException, + IOException { + setLoggerLevel(JsonServlet.class, Level.FATAL); + setLoggerLevel(JsonObjectProducer.class, Level.FATAL); + req.addParameter(GET_SOLR_INDIVIDUALS_BY_VCLASS, "true"); + servlet.service(req, resp); + assertFailureWithErrorMessage("java.lang.Exception: " + + "parameter vclassId URI parameter expected "); + } + + @Test + public void individualsByClassUnrecognizedVClass() throws ServletException, + IOException { + setLoggerLevel(JsonServlet.class, Level.FATAL); + setLoggerLevel(JsonObjectProducer.class, Level.FATAL); + String vclassId = "http://bogusVclass"; + req.addParameter(GET_SOLR_INDIVIDUALS_BY_VCLASS, "true"); + req.addParameter(VCLASS_ID, vclassId); + + servlet.service(req, resp); + assertFailureWithErrorMessage("java.lang.Exception: " + "Class " + + vclassId + " not found"); + } + + /** + * TODO test successful responses. This will require figuring out how to + * stub SolrServer. It's an abstract class, so we just need to figure out + * what sort of NamedList is required as a response to a request. + */ + @Test + public void individualsByClassNoIndividuals() throws ServletException, + IOException { + setLoggerLevel(JsonServlet.class, Level.FATAL); + String vclassId = "http://myVclass"; + vcDao.setVClass(vclassId, new VClass(vclassId)); + req.addParameter(GET_SOLR_INDIVIDUALS_BY_VCLASS, "true"); + req.addParameter(VCLASS_ID, vclassId); + + servlet.service(req, resp); + assertSuccessWithIndividuals(vclassId, 0); + } + + // ---------------------------------------------------------------------- + // Helper methods + // ---------------------------------------------------------------------- + + /** + * The response should be a JSONObject that contained this error-message, + * and the status should be set to INTERNAL_SERVER_ERROR. + */ + private void assertFailureWithErrorMessage(String expected) { + try { + JSONObject result = new JSONObject(resp.getOutput()); + assertEquals("errorMessage", expected, + getFieldValue(result, "errorMessage")); + assertEquals("status", SC_INTERNAL_SERVER_ERROR, resp.getStatus()); + } catch (JSONException e) { + fail(e.toString()); + } + } + + private void assertSuccessWithIndividuals(String vclassId, int count) { + try { + JSONObject actual = new JSONObject(resp.getOutput()); + assertEquals("errorMessage", "", + getFieldValue(actual, "errorMessage")); + assertEquals("count", count, getFieldValue(actual, "totalCount")); + + JSONObject vclassObj = (JSONObject) getFieldValue(actual, "vclass"); + assertEquals("vclass name", vclassId.split("://")[1], getFieldValue(vclassObj, "name")); + assertEquals("vclass uri", vclassId, getFieldValue(vclassObj, "URI")); + + assertEquals("status", SC_OK, resp.getStatus()); + } catch (JSONException e) { + fail(e.toString()); + } + } + + private Object getFieldValue(JSONObject json, String fieldName) { + try { + assertEquals("find " + fieldName, true, json.has(fieldName)); + return json.get(fieldName); + } catch (JSONException e) { + fail(e.toString()); + return -1; + } + } + +} diff --git a/webapp/test/edu/cornell/mannlib/vitro/webapp/edit/elements/DateTimeWithPrecisionTest.java b/webapp/test/edu/cornell/mannlib/vitro/webapp/edit/elements/DateTimeWithPrecisionTest.java deleted file mode 100644 index 925eb78b5..000000000 --- a/webapp/test/edu/cornell/mannlib/vitro/webapp/edit/elements/DateTimeWithPrecisionTest.java +++ /dev/null @@ -1,423 +0,0 @@ -/* $This file is distributed under the terms of the license in /doc/license.txt$ */ - -package edu.cornell.mannlib.vitro.webapp.edit.elements; - -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.TimeZone; - -import org.joda.time.DateTime; -import org.joda.time.DateTimeZone; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import org.junit.runners.Parameterized.Parameters; - -import com.hp.hpl.jena.datatypes.xsd.XSDDatatype; -import com.hp.hpl.jena.datatypes.xsd.XSDDateTime; -import com.hp.hpl.jena.rdf.model.Literal; -import com.hp.hpl.jena.rdf.model.ResourceFactory; - -import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary; -import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.EditConfiguration; -import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.Field; -import edu.cornell.mannlib.vitro.webapp.edit.n3editing.processEdit.EditSubmission; - - -@RunWith(value= Parameterized.class) -public class DateTimeWithPrecisionTest { - - TimeZone orginalTimeZone; - TimeZone testZone; - - public DateTimeWithPrecisionTest(TimeZone tz){ - orginalTimeZone = TimeZone.getDefault(); - testZone = tz; - } - - @Parameters - public static Collection data(){ - String allZones[] = TimeZone.getAvailableIDs(); - ArrayList data = new ArrayList( allZones.length ); - for( String zoneId : allZones ){ - Object v[] = new Object[1]; - v[0] = TimeZone.getTimeZone(zoneId); - try{ - DateTimeZone dtz = DateTimeZone.forID(zoneId); - if( dtz != null ){ - data.add(v); - } - }catch(IllegalArgumentException ex){ - //cannot convert to joda datetimezone. - } - } - return data; - } - - @Before - public void beforeTest(){ - TimeZone.setDefault( testZone ); - } - - @After - public void after(){ - if( orginalTimeZone != null){ - TimeZone.setDefault(orginalTimeZone); - } - } - - @Test - public void fieldNameTemplateVariableTest() throws Exception{ - String FIELDNAME = "testfield"; - Field field = new Field(); - field.setName(FIELDNAME); - DateTimeWithPrecision dtwp = new DateTimeWithPrecision(field); - - EditSubmission editSub = null; - EditConfiguration editConfig = new EditConfiguration(); - editConfig.setUrisInScope(Collections.EMPTY_MAP); - editConfig.setLiteralsInScope(Collections.EMPTY_MAP); - - Map templateVars = dtwp.getMapForTemplate(editConfig, editSub); - Assert.assertNotNull(templateVars); - - Assert.assertTrue( templateVars.containsKey("fieldName") ); - Assert.assertEquals(templateVars.get("fieldName"), "testfield"); - } - - @Test - public void precisionSecondsValidationTest() throws Exception{ - String FIELDNAME = "testfield"; - Field field = new Field(); - field.setName(FIELDNAME); - DateTimeWithPrecision dtwp = new DateTimeWithPrecision(field); - - Map queryParameters = new HashMap(); - queryParameters.put(FIELDNAME+"-year", new String[]{"1999" }); - queryParameters.put(FIELDNAME+"-month", new String[]{"12"}); - queryParameters.put(FIELDNAME+"-day", new String[]{"01"}); - queryParameters.put(FIELDNAME+"-hour", new String[]{"12"}); - queryParameters.put(FIELDNAME+"-minute", new String[]{"00"}); - queryParameters.put(FIELDNAME+"-second", new String[]{"00"}); - EditConfiguration editConfig=null; - Map validationMsgs = dtwp.getValidationMessages("testfield", editConfig, queryParameters); - Assert.assertNotNull(validationMsgs); - Assert.assertTrue(validationMsgs.size() == 0 ); - - String precisionURI = null; - precisionURI = dtwp.getSubmittedPrecision( queryParameters); - - Assert.assertNotNull(precisionURI); - Assert.assertEquals(VitroVocabulary.Precision.SECOND.uri(), precisionURI); - } - - @Test - public void precisionMinutesValidationTest() throws Exception{ - String FIELDNAME = "testfield"; - Field field = new Field(); - field.setName(FIELDNAME); - DateTimeWithPrecision dtwp = new DateTimeWithPrecision(field); - - Map queryParameters = new HashMap(); - queryParameters.put(FIELDNAME+"-year", new String[]{"1999" }); - queryParameters.put(FIELDNAME+"-month", new String[]{"12"}); - queryParameters.put(FIELDNAME+"-day", new String[]{"01"}); - queryParameters.put(FIELDNAME+"-hour", new String[]{"12"}); - queryParameters.put(FIELDNAME+"-minute", new String[]{"00"}); - //no seconds - - EditConfiguration editConfig=null; - Map validationMsgs = dtwp.getValidationMessages("testfield", editConfig, queryParameters); - Assert.assertNotNull(validationMsgs); - Assert.assertTrue(validationMsgs.size() == 0 ); - - String precisionURI = null; - precisionURI = dtwp.getSubmittedPrecision( queryParameters); - - Assert.assertNotNull(precisionURI); - Assert.assertEquals(VitroVocabulary.Precision.MINUTE.uri(), precisionURI); - } - - @Test - public void precisionHoursValidationTest() throws Exception{ - String FIELDNAME = "testfield"; - Field field = new Field(); - field.setName(FIELDNAME); - DateTimeWithPrecision dtwp = new DateTimeWithPrecision(field); - - Map queryParameters = new HashMap(); - queryParameters.put(FIELDNAME+"-year", new String[]{"1999" }); - queryParameters.put(FIELDNAME+"-month", new String[]{"12"}); - queryParameters.put(FIELDNAME+"-day", new String[]{"01"}); - queryParameters.put(FIELDNAME+"-hour", new String[]{"12"}); - //no minutes - //no seconds - - EditConfiguration editConfig=null; - Map validationMsgs = dtwp.getValidationMessages("testfield", editConfig, queryParameters); - Assert.assertNotNull(validationMsgs); - Assert.assertTrue(validationMsgs.size() == 0 ); - - String precisionURI = null; - precisionURI = dtwp.getSubmittedPrecision( queryParameters); - - Assert.assertNotNull(precisionURI); - Assert.assertEquals(VitroVocabulary.Precision.HOUR.uri(), precisionURI); - } - - @Test - public void precisionDaysValidationTest() throws Exception{ - String FIELDNAME = "testfield"; - Field field = new Field(); - field.setName(FIELDNAME); - DateTimeWithPrecision dtwp = new DateTimeWithPrecision(field); - - Map queryParameters = new HashMap(); - queryParameters.put(FIELDNAME+"-year", new String[]{"1999" }); - queryParameters.put(FIELDNAME+"-month", new String[]{"12"}); - queryParameters.put(FIELDNAME+"-day", new String[]{"01"}); - //no hours - //no minutes - //no seconds - - EditConfiguration editConfig=null; - Map validationMsgs = dtwp.getValidationMessages("testfield", editConfig, queryParameters); - Assert.assertNotNull(validationMsgs); - Assert.assertTrue(validationMsgs.size() == 0 ); - - String precisionURI = null; - precisionURI = dtwp.getSubmittedPrecision( queryParameters); - - Assert.assertNotNull(precisionURI); - Assert.assertEquals(VitroVocabulary.Precision.DAY.uri(), precisionURI); - } - - @Test - public void precisionMonthsValidationTest()throws Exception{ - String FIELDNAME = "testfield"; - Field field = new Field(); - field.setName(FIELDNAME); - DateTimeWithPrecision dtwp = new DateTimeWithPrecision(field); - - Map queryParameters = new HashMap(); - queryParameters.put(FIELDNAME+"-year", new String[]{"1999" }); - queryParameters.put(FIELDNAME+"-month", new String[]{"12"}); - //no days - //no hours - //no minutes - //no seconds - - EditConfiguration editConfig=null; - Map validationMsgs = dtwp.getValidationMessages("testfield", editConfig, queryParameters); - Assert.assertNotNull(validationMsgs); - Assert.assertTrue(validationMsgs.size() == 0 ); - - String precisionURI = null; - precisionURI = dtwp.getSubmittedPrecision( queryParameters); - - Assert.assertNotNull(precisionURI); - Assert.assertEquals(VitroVocabulary.Precision.MONTH.uri(), precisionURI); - } - - @Test - public void precisionYearValidationTest() throws Exception{ - String FIELDNAME = "testfield"; - Field field = new Field(); - field.setName(FIELDNAME); - DateTimeWithPrecision dtwp = new DateTimeWithPrecision(field); - - Map queryParameters = new HashMap(); - queryParameters.put(FIELDNAME+"-year", new String[]{"1999" }); - //no months - //no days - //no hours - //no minutes - //no seconds - - EditConfiguration editConfig=null; - Map validationMsgs = dtwp.getValidationMessages("testfield", editConfig, queryParameters); - Assert.assertNotNull(validationMsgs); - Assert.assertTrue(validationMsgs.size() == 0 ); - - String precisionURI = null; - precisionURI = dtwp.getSubmittedPrecision( queryParameters); - - Assert.assertNotNull(precisionURI); - Assert.assertEquals(VitroVocabulary.Precision.YEAR.uri(), precisionURI); - } - - @Test - public void precisionNoValueTest() throws Exception{ - String FIELDNAME = "testfield"; - Field field = new Field(); - field.setName(FIELDNAME); - DateTimeWithPrecision dtwp = new DateTimeWithPrecision(field); - - Map queryParameters = new HashMap(); - //field is not filled out at all - //no year - //no months - //no days - //no hours - //no minutes - //no seconds - - EditConfiguration editConfig=null; - Map validationMsgs = dtwp.getValidationMessages("testfield", editConfig, queryParameters); - Assert.assertNotNull(validationMsgs); - Assert.assertTrue(validationMsgs.size() == 0 ); - - String precisionURI = null; - - precisionURI = dtwp.getSubmittedPrecision( queryParameters ); - - Assert.assertNotNull(precisionURI); - Assert.assertEquals(dtwp.BLANK_SENTINEL, precisionURI); - - Literal date = dtwp.getDateTime( queryParameters); - Assert.assertNull(date); - } - - @Test - public void getDateLiteralTest(){ - String FIELDNAME = "testfield"; - Field field = new Field(); - field.setName(FIELDNAME); - DateTimeWithPrecision dtwp = new DateTimeWithPrecision(field); - - Map queryParameters = new HashMap(); - queryParameters.put(FIELDNAME+"-year", new String[]{"1999" }); - //no months - //no days - //no hours - //no minutes - //no seconds - - EditConfiguration editConfig=null; - Map validationMsgs = dtwp.getValidationMessages("testfield", editConfig, queryParameters); - Assert.assertNotNull(validationMsgs); - Assert.assertTrue(validationMsgs.size() == 0 ); - - Literal date = dtwp.getDateTime( queryParameters); - Assert.assertNotNull(date); - Assert.assertEquals( XSDDatatype.XSDdateTime.getURI() ,date.getDatatypeURI() ); - - Object obj = date.getValue(); - Assert.assertNotNull(obj); - Assert.assertEquals(XSDDateTime.class, obj.getClass()); - - DateTime result = new DateTime( date.getLexicalForm()); - DateTime expected = new DateTime(1999,1,1,0,0,0,0 ); - Assert.assertEquals(expected.toInstant() , result.toInstant()); - - Assert.assertEquals("1999-01-01T00:00:00" , date.getLexicalForm() ); - } - - - @Test - public void day30Test() throws Exception{ - String FIELDNAME = "testfield"; - Field field = new Field(); - field.setName(FIELDNAME); - DateTimeWithPrecision dtwp = new DateTimeWithPrecision(field); - - - /* Check if it works with day number under 29 */ - Map queryParameters = new HashMap(); - queryParameters.put(FIELDNAME+"-year", new String[]{"1999" }); - queryParameters.put(FIELDNAME+"-month", new String[]{"12"}); - queryParameters.put(FIELDNAME+"-day", new String[]{"28"}); - - Map validationMsgs = dtwp.getValidationMessages("testfield", (EditConfiguration)null, queryParameters); - Assert.assertNotNull(validationMsgs); - Assert.assertTrue(validationMsgs.size() == 0 ); - - String precisionURI = dtwp.getSubmittedPrecision( queryParameters); - Assert.assertNotNull(precisionURI); - Assert.assertEquals(VitroVocabulary.Precision.DAY.uri(), precisionURI); - - /* Check for days greater than 28 */ - queryParameters = new HashMap(); - queryParameters.put(FIELDNAME+"-year", new String[]{"1999" }); - queryParameters.put(FIELDNAME+"-month", new String[]{"12"}); - queryParameters.put(FIELDNAME+"-day", new String[]{"30"}); - - validationMsgs = dtwp.getValidationMessages("testfield", (EditConfiguration)null, queryParameters); - Assert.assertNotNull(validationMsgs); - Assert.assertTrue(validationMsgs.size() == 0 ); - - precisionURI = dtwp.getSubmittedPrecision( queryParameters); - Assert.assertNotNull(precisionURI); - Assert.assertEquals(VitroVocabulary.Precision.DAY.uri(), precisionURI); - - /* Check for leap year */ - queryParameters = new HashMap(); - queryParameters.put(FIELDNAME+"-year", new String[]{"2000" }); - queryParameters.put(FIELDNAME+"-month", new String[]{"2"}); - queryParameters.put(FIELDNAME+"-day", new String[]{"29"}); - - validationMsgs = dtwp.getValidationMessages("testfield", (EditConfiguration)null, queryParameters); - Assert.assertNotNull(validationMsgs); - Assert.assertTrue(validationMsgs.size() == 0 ); - - precisionURI = dtwp.getSubmittedPrecision( queryParameters); - Assert.assertNotNull(precisionURI); - Assert.assertEquals(VitroVocabulary.Precision.DAY.uri(), precisionURI); - - /* check for non leap year */ - queryParameters = new HashMap(); - queryParameters.put(FIELDNAME+"-year", new String[]{"1999" }); - queryParameters.put(FIELDNAME+"-month", new String[]{"2"}); - queryParameters.put(FIELDNAME+"-day", new String[]{"29"}); - - validationMsgs = dtwp.getValidationMessages("testfield", (EditConfiguration)null, queryParameters); - Assert.assertNotNull(validationMsgs); - Assert.assertTrue(validationMsgs.size() > 0 ); - - precisionURI = dtwp.getSubmittedPrecision( queryParameters); - Assert.assertNotNull(precisionURI); - Assert.assertEquals(VitroVocabulary.Precision.DAY.uri(), precisionURI); - } - - - @Test - public void basicGetMapForTemplateTest() throws Exception{ - String FIELDNAME = "testfield"; - Field field = new Field(); - field.setName(FIELDNAME); - DateTimeWithPrecision dtwp = new DateTimeWithPrecision(field); - - EditConfiguration config = new EditConfiguration(); - EditSubmission sub = null; - - Map urisInScope = new HashMap(); - urisInScope.put(dtwp.getPrecisionVariableName(), - VitroVocabulary.Precision.MINUTE.uri()); - config.setUrisInScope(urisInScope); - - Map literalsInScope = new HashMap(); - literalsInScope.put(dtwp.getValueVariableName(), - ResourceFactory.createTypedLiteral("1999-02-15T10:00",XSDDatatype.XSDdateTime) ); - config.setLiteralsInScope(literalsInScope); - - Map map = dtwp.getMapForTemplate(config,sub); - Assert.assertEquals("year wrong", "1999", map.get("year")); - Assert.assertEquals("month wrong", "2", map.get("month")); - Assert.assertEquals("day wrong", "15", map.get("day")); - Assert.assertEquals("hour wrong", "10", map.get("hour")); - Assert.assertEquals("minute wrong", "0", map.get("minute")); - Assert.assertEquals("second wrong", "", map.get("second")); - - Assert.assertEquals("precision wrong", VitroVocabulary.Precision.MINUTE.uri(), map.get("existingPrecision")); - - Assert.assertEquals("fieldname wrong", FIELDNAME, map.get("fieldName")); - } - -} diff --git a/webapp/test/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/ProcessRdfFormTest.java b/webapp/test/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/ProcessRdfFormTest.java index 47f61d2fa..077a02784 100644 --- a/webapp/test/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/ProcessRdfFormTest.java +++ b/webapp/test/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/ProcessRdfFormTest.java @@ -1,15 +1,17 @@ /* $This file is distributed under the terms of the license in /doc/license.txt$ */ package edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; -import static org.junit.Assert.*; import org.junit.Test; -import com.hp.hpl.jena.rdf.model.Literal; import com.hp.hpl.jena.rdf.model.Model; import com.hp.hpl.jena.rdf.model.ModelFactory; import com.hp.hpl.jena.rdf.model.ResourceFactory; @@ -18,6 +20,7 @@ import com.hp.hpl.jena.vocabulary.RDFS; import edu.cornell.mannlib.vitro.testing.AbstractTestClass; import edu.cornell.mannlib.vitro.webapp.dao.InsertException; +import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.fields.FieldVTwo; import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.EditConfigurationConstants; public class ProcessRdfFormTest extends AbstractTestClass{ diff --git a/webapp/test/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/validators/AntiXssValidationTest.java b/webapp/test/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/validators/AntiXssValidationTest.java index ee11903e1..b46eeb19d 100644 --- a/webapp/test/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/validators/AntiXssValidationTest.java +++ b/webapp/test/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/validators/AntiXssValidationTest.java @@ -10,8 +10,8 @@ import org.junit.Assert; import org.junit.Test; import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditConfigurationVTwo; -import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.FieldVTwo; import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.MultiValueEditSubmission; +import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.fields.FieldVTwo; public class AntiXssValidationTest { 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(), diff --git a/webapp/test/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/ObjectPropertyTemplateModel_PropertyListConfigTest.java b/webapp/test/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/ObjectPropertyTemplateModel_PropertyListConfigTest.java index 9c92eb280..1ab3f53f2 100644 --- a/webapp/test/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/ObjectPropertyTemplateModel_PropertyListConfigTest.java +++ b/webapp/test/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/ObjectPropertyTemplateModel_PropertyListConfigTest.java @@ -37,10 +37,9 @@ import edu.cornell.mannlib.vitro.webapp.beans.IndividualImpl; import edu.cornell.mannlib.vitro.webapp.beans.ObjectProperty; import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory; -import edu.cornell.mannlib.vitro.webapp.web.templatemodels.BaseTemplateModel; import edu.cornell.mannlib.vitro.webapp.web.templatemodels.customlistview.InvalidConfigurationException; import edu.cornell.mannlib.vitro.webapp.web.templatemodels.customlistview.PropertyListConfig; -import freemarker.template.Configuration; +import freemarker.cache.TemplateLoader; public class ObjectPropertyTemplateModel_PropertyListConfigTest extends AbstractTestClass { @@ -83,22 +82,15 @@ public class ObjectPropertyTemplateModel_PropertyListConfigTest extends createConfigFile("constructQueryMissing"); createConfigFile("constructQueryMultiple"); createConfigFile("default"); - createConfigFile("notValidXml"); createConfigFile("postProcessorClassNotFound"); createConfigFile("postProcessorClassNotSuitable"); createConfigFile("postProcessorConstructorThrowsException"); createConfigFile("postProcessorNameEmpty"); createConfigFile("postProcessorOK"); createConfigFile("postProcessorWrongConstructor"); - createConfigFile("selectQueryNodeBlank"); - createConfigFile("selectQueryNodeNotFound"); - createConfigFile("selectQuerySubNodes"); - createConfigFile("selectQueryNoSubNodes"); createConfigFile("selectQueryCollatedValid"); createConfigFile("selectQueryCollatedNoSelect"); createConfigFile("selectQueryCollatedNoOrder"); - createConfigFile("templateNodeIsEmpty"); - createConfigFile("templateNodeNotFound"); createConfigFile("templateDoesNotExist"); } @@ -135,11 +127,11 @@ public class ObjectPropertyTemplateModel_PropertyListConfigTest extends subject = new IndividualImpl(); - Configuration fmConfig = new Configuration(); - vreq.setAttribute("freemarkerConfig", fmConfig); + // We need a stub TemplateLoader because PropertyListConfig will check + // to see whether the template name is recognized. How can we get around + // that? This will do for now. tl = new TemplateLoaderStub(); tl.createTemplate("propStatement-default.ftl", ""); - fmConfig.setTemplateLoader(tl); } @AfterClass @@ -153,12 +145,13 @@ public class ObjectPropertyTemplateModel_PropertyListConfigTest extends // TODO - baseTemplateModel shouldn't require the servlet context to be set // statically!!! ServletContext shouldn't be a static field. - // ---------------------------------------------------------------------- - // The tests - // - // TODO - remove any tests that are covered by the newer - // CustomListViewConfigFileTest. - // ---------------------------------------------------------------------- + /* + * These tests were removed because the newer CustomListViewConfigTest + * covered them: configFileNotValidXml(), selectQueryNodeIsNotFound(), + * selectQueryNodeIsBlank(), selectSubNodesCollatedCritical(), + * selectSubNodesCollatedUncritical(), selectSubNodesUncollatedCritical(), + * selectSubNodesUncollatedUncritical(), selectNoSubNodesCollatedCritical() + */ // // Null arguments @@ -228,68 +221,9 @@ public class ObjectPropertyTemplateModel_PropertyListConfigTest extends assertLogMessagesContains("file not found", "Can't find config file"); } - @Test - public void configFileNotValidXml() throws InvalidConfigurationException { - suppressSyserr(); - captureLogsFromPropertyListConfig(); - - op = buildOperation("notValidXml"); - optm = new NonCollatingOPTM(op, subject, vreq, false); - - assertLogMessagesContains("not valid XML", "SAXParseException"); - } - - // - // Problems with the node - // - - @Test - public void selectQueryNodeIsNotFound() - throws InvalidConfigurationException { - captureLogsFromPropertyListConfig(); - - op = buildOperation("selectQueryNodeNotFound"); - optm = new NonCollatingOPTM(op, subject, vreq, false); - - assertLogMessagesContains("no select query", - "Missing select query specification"); - } - - @Test - public void selectQueryNodeIsBlank() throws InvalidConfigurationException { - captureLogsFromPropertyListConfig(); - - op = buildOperation("selectQueryNodeBlank"); - optm = new NonCollatingOPTM(op, subject, vreq, false); - - assertLogMessagesContains("blank select query", - "Missing select query specification"); - } - // // Problems with the