From cedf17e1e654430ec39023c012337d0191d7d52b Mon Sep 17 00:00:00 2001 From: Stefan Wolff Date: Thu, 22 Sep 2016 15:43:51 +0200 Subject: [PATCH 01/49] fix hard coded label "more..." --- .../freemarker/IndividualListController.java | 31 ++++++++++--------- .../webapp/controller/json/JsonServlet.java | 4 +-- .../SearchIndividualsDataGetter.java | 2 +- 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/IndividualListController.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/IndividualListController.java index 728a4c77c..8290df18f 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/IndividualListController.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/IndividualListController.java @@ -22,6 +22,7 @@ import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.Res import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues; import edu.cornell.mannlib.vitro.webapp.controller.individuallist.IndividualListResults; import edu.cornell.mannlib.vitro.webapp.dao.IndividualDao; +import edu.cornell.mannlib.vitro.webapp.i18n.I18n; import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchEngineException; import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchQuery; import edu.cornell.mannlib.vitro.webapp.utils.searchengine.SearchQueryUtils; @@ -94,7 +95,7 @@ public class IndividualListController extends FreemarkerHttpServlet { vclass.getURI(), page, alpha, - vreq.getWebappDaoFactory().getIndividualDao()); + vreq); body.putAll(vcResults.asFreemarkerMap()); List inds = vcResults.getEntities(); @@ -148,12 +149,12 @@ public class IndividualListController extends FreemarkerHttpServlet { return SearchQueryUtils.getPageParameter(request); } - public static IndividualListResults getResultsForVClass(String vclassURI, int page, String alpha, IndividualDao indDao) + public static IndividualListResults getResultsForVClass(String vclassURI, int page, String alpha, VitroRequest vreq) throws SearchException{ try{ List classUris = Collections.singletonList(vclassURI); - IndividualListQueryResults results = buildAndExecuteVClassQuery(classUris, alpha, page, INDIVIDUALS_PER_PAGE, indDao); - return getResultsForVClassQuery(results, page, INDIVIDUALS_PER_PAGE, alpha); + IndividualListQueryResults results = buildAndExecuteVClassQuery(classUris, alpha, page, INDIVIDUALS_PER_PAGE, vreq.getWebappDaoFactory().getIndividualDao()); + return getResultsForVClassQuery(results, page, INDIVIDUALS_PER_PAGE, alpha, vreq); } catch (SearchEngineException e) { String msg = "An error occurred retrieving results for vclass query"; log.error(msg, e); @@ -165,31 +166,31 @@ public class IndividualListController extends FreemarkerHttpServlet { } } - public static IndividualListResults getResultsForVClassIntersections(List vclassURIs, int page, int pageSize, String alpha, IndividualDao indDao) { + public static IndividualListResults getResultsForVClassIntersections(List vclassURIs, int page, int pageSize, String alpha, VitroRequest vreq) { try{ - IndividualListQueryResults results = buildAndExecuteVClassQuery(vclassURIs, alpha, page, pageSize, indDao); - return getResultsForVClassQuery(results, page, pageSize, alpha); + IndividualListQueryResults results = buildAndExecuteVClassQuery(vclassURIs, alpha, page, pageSize, vreq.getWebappDaoFactory().getIndividualDao()); + return getResultsForVClassQuery(results, page, pageSize, alpha, vreq); } catch(Throwable th) { log.error("Error retrieving individuals corresponding to intersection multiple classes." + vclassURIs.toString(), th); return IndividualListResults.EMPTY; } } - public static IndividualListResults getRandomResultsForVClass(String vclassURI, int page, int pageSize, IndividualDao indDao) { + public static IndividualListResults getRandomResultsForVClass(String vclassURI, int page, int pageSize, VitroRequest vreq) { try{ List classUris = Collections.singletonList(vclassURI); - IndividualListQueryResults results = buildAndExecuteRandomVClassQuery(classUris, page, pageSize, indDao); - return getResultsForVClassQuery(results, page, pageSize, ""); + IndividualListQueryResults results = buildAndExecuteRandomVClassQuery(classUris, page, pageSize, vreq.getWebappDaoFactory().getIndividualDao()); + return getResultsForVClassQuery(results, page, pageSize, "", vreq); } catch(Throwable th) { log.error("An error occurred retrieving random results for vclass query", th); return IndividualListResults.EMPTY; } } - private static IndividualListResults getResultsForVClassQuery(IndividualListQueryResults results, int page, int pageSize, String alpha) { + private static IndividualListResults getResultsForVClassQuery(IndividualListQueryResults results, int page, int pageSize, String alpha, VitroRequest vreq) { long hitCount = results.getHitCount(); if ( hitCount > pageSize ){ - return new IndividualListResults(hitCount, results.getIndividuals(), alpha, true, makePagesList(hitCount, pageSize, page)); + return new IndividualListResults(hitCount, results.getIndividuals(), alpha, true, makePagesList(hitCount, pageSize, page, vreq)); }else{ return new IndividualListResults(hitCount, results.getIndividuals(), alpha, false, Collections.emptyList()); } @@ -221,7 +222,7 @@ public class IndividualListController extends FreemarkerHttpServlet { } - public static List makePagesList( long size, int pageSize, int selectedPage ) { + public static List makePagesList( long size, int pageSize, int selectedPage , VitroRequest vreq) { List records = new ArrayList( MAX_PAGES + 1 ); int requiredPages = (int) (size/pageSize) ; @@ -234,7 +235,7 @@ public class IndividualListController extends FreemarkerHttpServlet { for(int page = 1; page < requiredPages && page <= MAX_PAGES ; page++ ){ records.add( new PageRecord( "page=" + page, Integer.toString(page), Integer.toString(page), selectedPage == page ) ); } - records.add( new PageRecord( "page="+ (MAX_PAGES+1), Integer.toString(MAX_PAGES+1), "more...", false)); + records.add( new PageRecord( "page="+ (MAX_PAGES+1), Integer.toString(MAX_PAGES+1), I18n.text(vreq, "paging_link_more"), false)); }else if( requiredPages > MAX_PAGES && selectedPage+1 > MAX_PAGES && selectedPage < requiredPages - MAX_PAGES){ //the selected pages is in the middle of the list of page int startPage = selectedPage - MAX_PAGES / 2; @@ -242,7 +243,7 @@ public class IndividualListController extends FreemarkerHttpServlet { for(int page = startPage; page <= endPage ; page++ ){ records.add( new PageRecord( "page=" + page, Integer.toString(page), Integer.toString(page), selectedPage == page ) ); } - records.add( new PageRecord( "page="+ (endPage+1), Integer.toString(endPage+1), "more...", false)); + records.add( new PageRecord( "page="+ (endPage+1), Integer.toString(endPage+1), I18n.text(vreq, "paging_link_more"), false)); }else if ( requiredPages > MAX_PAGES && selectedPage > requiredPages - MAX_PAGES ){ //the selected page is in the end of the list int startPage = requiredPages - MAX_PAGES; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/json/JsonServlet.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/json/JsonServlet.java index c479f5a09..a1c9f27e3 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/json/JsonServlet.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/json/JsonServlet.java @@ -109,7 +109,7 @@ public class JsonServlet extends VitroHttpServlet { vclassURIs, page, INDIVIDUALS_PER_PAGE, alpha, - vreq.getWebappDaoFactory().getIndividualDao()); + vreq); } catch(Exception ex) { log.error("Error in retrieval of search results for VClass " + vclassURIs.toString(), ex); return IndividualListResults.EMPTY; @@ -144,7 +144,7 @@ public class JsonServlet extends VitroHttpServlet { vclassURI, page, pageSize, - vreq.getWebappDaoFactory().getIndividualDao()); + vreq); } catch(Exception ex) { log.error("Error in retrieval of search results for VClass " + vclassURI, ex); return IndividualListResults.EMPTY; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/SearchIndividualsDataGetter.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/SearchIndividualsDataGetter.java index 739b9f309..b0bfed510 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/SearchIndividualsDataGetter.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/SearchIndividualsDataGetter.java @@ -177,7 +177,7 @@ public class SearchIndividualsDataGetter extends DataGetterBase implements DataG vclass.getURI(), page, alpha, - vreq.getWebappDaoFactory().getIndividualDao()); + vreq); body.putAll(vcResults.asFreemarkerMap()); List inds = vcResults.getEntities(); From 3ab448a926ff029f2a32022779e7c23bf53303b2 Mon Sep 17 00:00:00 2001 From: Stefan Wolff Date: Fri, 23 Sep 2016 16:29:43 +0200 Subject: [PATCH 02/49] fix hard coded label "pages" --- .../templates/freemarker/body/search/search-pagedResults.ftl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webapp/src/main/webapp/templates/freemarker/body/search/search-pagedResults.ftl b/webapp/src/main/webapp/templates/freemarker/body/search/search-pagedResults.ftl index 0c8ed5ed2..d0805bc3d 100644 --- a/webapp/src/main/webapp/templates/freemarker/body/search/search-pagedResults.ftl +++ b/webapp/src/main/webapp/templates/freemarker/body/search/search-pagedResults.ftl @@ -67,7 +67,7 @@ <#-- Paging controls --> <#if (pagingLinks?size > 0)>
- Pages: + ${i18n().pages}: <#if prevPage??> <#list pagingLinks as link> <#if link.url??> From 5539034f005681204e97a9635c79ba19db975925 Mon Sep 17 00:00:00 2001 From: Stefan Wolff Date: Fri, 23 Sep 2016 16:44:14 +0200 Subject: [PATCH 03/49] fix hard coded labels "pages" and "to" --- legacy/webapp/languages/es_GO/i18n/all_es_GO.properties | 2 ++ webapp/src/main/webapp/i18n/all.properties | 2 ++ .../templates/freemarker/body/search/search-pagedResults.ftl | 4 ++-- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/legacy/webapp/languages/es_GO/i18n/all_es_GO.properties b/legacy/webapp/languages/es_GO/i18n/all_es_GO.properties index a62a3a29d..510718694 100644 --- a/legacy/webapp/languages/es_GO/i18n/all_es_GO.properties +++ b/legacy/webapp/languages/es_GO/i18n/all_es_GO.properties @@ -518,6 +518,8 @@ class_link = Enlace clase previous = Anterior page_link = enlace de la página next_capitalized = Próximo +download_results = resultados de la transferencia directa +to = a # # shortview templates ( /templates/freemarker/body/partials/shortview ) diff --git a/webapp/src/main/webapp/i18n/all.properties b/webapp/src/main/webapp/i18n/all.properties index 4c0ead6af..fe311f533 100644 --- a/webapp/src/main/webapp/i18n/all.properties +++ b/webapp/src/main/webapp/i18n/all.properties @@ -531,6 +531,8 @@ class_link = class link previous = Previous page_link = page link next_capitalized = Next +download_results = Download Results +to = to # # shortview templates ( /templates/freemarker/body/partials/shortview ) diff --git a/webapp/src/main/webapp/templates/freemarker/body/search/search-pagedResults.ftl b/webapp/src/main/webapp/templates/freemarker/body/search/search-pagedResults.ftl index d0805bc3d..b701ccb57 100644 --- a/webapp/src/main/webapp/templates/freemarker/body/search/search-pagedResults.ftl +++ b/webapp/src/main/webapp/templates/freemarker/body/search/search-pagedResults.ftl @@ -20,7 +20,7 @@ var urlsBase = '${urls.base}'; - Download Results + ${i18n().download_results} <#-- --> @@ -42,7 +42,7 @@ <#if classLinks?has_content>
<#if classGroupName?has_content> -

${i18n().limit} ${classGroupName} to

+

${i18n().limit} ${classGroupName} ${i18n().to}

<#else>

${i18n().limit_to}

From 8c8985bdc21cbfd036e7676751f4aa9bf3f9f391 Mon Sep 17 00:00:00 2001 From: Stefan Wolff Date: Fri, 23 Sep 2016 17:25:05 +0200 Subject: [PATCH 04/49] fix some hard coded page titles and messages --- .../controller/admin/RestrictLoginsController.java | 3 ++- .../controller/admin/StartupStatusController.java | 3 ++- .../controller/freemarker/PageController.java | 13 +++++++------ .../controller/individual/IndividualController.java | 9 +++++---- .../languages/es_GO/i18n/all_es_GO.properties | 8 ++++++++ webapp/src/main/webapp/i18n/all.properties | 8 ++++++++ 6 files changed, 32 insertions(+), 12 deletions(-) diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/admin/RestrictLoginsController.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/admin/RestrictLoginsController.java index a3f04be48..e80d7f2d5 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/admin/RestrictLoginsController.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/admin/RestrictLoginsController.java @@ -16,6 +16,7 @@ import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerHttpServ import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues; +import edu.cornell.mannlib.vitro.webapp.i18n.I18n; /** * Offer the user the ability to apply a RestrictedAuthenticator or revert to a @@ -80,7 +81,7 @@ public class RestrictLoginsController extends FreemarkerHttpServlet { boolean restricted = figureCurrentlyState() == State.RESTRICTED; Map body = new HashMap(); - body.put("title", "Restrict Logins"); + body.put("title", I18n.text(vreq, "restrict_logins")); body.put("restricted", restricted); if (!MESSAGE_NO_MESSAGE.equals(messageCode)) { body.put(messageCode, Boolean.TRUE); diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/admin/StartupStatusController.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/admin/StartupStatusController.java index 991f53792..ae295ed35 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/admin/StartupStatusController.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/admin/StartupStatusController.java @@ -11,6 +11,7 @@ import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerHttpServlet; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues; +import edu.cornell.mannlib.vitro.webapp.i18n.I18n; import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus; /** @@ -27,7 +28,7 @@ public class StartupStatusController extends FreemarkerHttpServlet { protected ResponseValues processRequest(VitroRequest vreq) { Map body = new HashMap(); - body.put("title", "Startup Status"); + body.put("title", I18n.text(vreq, "startup_status")); body.put("status", StartupStatus.getBean(getServletContext())); body.put("contextPath", getContextPath()); body.put("applicationName", getApplicationName(vreq)); diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/PageController.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/PageController.java index f772537c7..13595fd1d 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/PageController.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/PageController.java @@ -27,6 +27,7 @@ import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues; import edu.cornell.mannlib.vitro.webapp.dao.DisplayVocabulary; +import edu.cornell.mannlib.vitro.webapp.i18n.I18n; import edu.cornell.mannlib.vitro.webapp.utils.dataGetter.DataGetter; import edu.cornell.mannlib.vitro.webapp.utils.dataGetter.DataGetterUtils; /** @@ -188,23 +189,23 @@ public class PageController extends FreemarkerHttpServlet{ private ResponseValues doError(VitroRequest vreq) { Map body = new HashMap(); - body.put("title","Page could not be created"); - body.put("errorMessage", "There was an error while creating the page, please check the logs."); + body.put("title", I18n.text(vreq, "page_not_created")); + body.put("errorMessage", I18n.text(vreq, "page_not_created_msg")); return new TemplateResponseValues(Template.TITLED_ERROR_MESSAGE.toString(), body, HttpServletResponse.SC_INTERNAL_SERVER_ERROR); } private ResponseValues doNotFound(VitroRequest vreq) { Map body = new HashMap(); - body.put("title","Page Not Found"); - body.put("errorMessage", "The page was not found in the system."); + body.put("title", I18n.text(vreq, "page_not_found")); + body.put("errorMessage", I18n.text(vreq, "page_not_found_msg")); return new TemplateResponseValues(Template.TITLED_ERROR_MESSAGE.toString(), body, HttpServletResponse.SC_NOT_FOUND); } private ResponseValues doNoPageSpecified(VitroRequest vreq) { Map body = new HashMap(); - body.put("title","No page URI specified"); - body.put("errorMessage", "Could not generate page beacause it was unclear what page was being requested. A URL mapping may be missing."); + body.put("title",I18n.text(vreq, "page_uri_missing")); + body.put("errorMessage", I18n.text(vreq, "page_uri_missing_msg")); return new TemplateResponseValues(Template.TITLED_ERROR_MESSAGE.toString(), body, HttpServletResponse.SC_NOT_FOUND); } diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/individual/IndividualController.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/individual/IndividualController.java index 4c14f4a9c..5abf27a70 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/individual/IndividualController.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/individual/IndividualController.java @@ -21,6 +21,7 @@ import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.Exc import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.RedirectResponseValues; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues; +import edu.cornell.mannlib.vitro.webapp.i18n.I18n; /** * Handles requests for entity information. @@ -74,7 +75,7 @@ public class IndividualController extends FreemarkerHttpServlet { * If we can't figure out what individual you want, or if there * is no such individual, show an informative error page. */ - return doNotFound(); + return doNotFound(vreq); case BYTESTREAM_REDIRECT: /* * If the Individual requested is a FileBytestream, redirect @@ -116,10 +117,10 @@ public class IndividualController extends FreemarkerHttpServlet { new IndividualRequestAnalysisContextImpl(vreq)).analyze(); } - private ResponseValues doNotFound() { + private ResponseValues doNotFound(VitroRequest vreq) { Map body = new HashMap(); - body.put("title", "Individual Not Found"); - body.put("errorMessage", "The individual was not found in the system."); + body.put("title", I18n.text(vreq, "individual_not_found")); + body.put("errorMessage", I18n.text(vreq, "individual_not_found_msg")); return new TemplateResponseValues(TEMPLATE_HELP, body, HttpServletResponse.SC_NOT_FOUND); diff --git a/legacy/webapp/languages/es_GO/i18n/all_es_GO.properties b/legacy/webapp/languages/es_GO/i18n/all_es_GO.properties index 510718694..3741d22d6 100644 --- a/legacy/webapp/languages/es_GO/i18n/all_es_GO.properties +++ b/legacy/webapp/languages/es_GO/i18n/all_es_GO.properties @@ -234,6 +234,7 @@ verbose_turn_off = Apagar resource_uri = URI de recursos individual_not_found = Individual no encontrado +individual_not_found_msg = El individuo no se encontr en el sistema. entity_to_query_for = Este id es el identificador de la entidad para consultar. netid también funciona. menu_ordering = Menú pedidos @@ -423,6 +424,13 @@ run_sdb_setup = Ejecutar la instalación SDB unrecognized_user = Usuario no reconocido no_individual_associated_with_id = Por alguna razón, no hay ninguna persona en VIVO que se asocia con su ID de red. Tal vez usted debería ponerse en contacto con el administrador de VIVO. +page_not_created = pgina no pudo ser creado +page_not_created_msg = Se ha producido un error al crear la pgina, por favor, compruebe los registros. +page_not_found = Pgina no encontrada +page_not_found_msg = La pgina no se ha encontrado en el sistema. +page_uri_missing = No se especifica la pgina URI +page_uri_missing_msg = No se pudo generar la pgina pd no estaba claro en qu pgina se est solicitando. Una asignacin de direccin URL es posible que falte. + # # site admin templates ( /templates/freemarker/body/siteAdmin ) # diff --git a/webapp/src/main/webapp/i18n/all.properties b/webapp/src/main/webapp/i18n/all.properties index fe311f533..a980cc36d 100644 --- a/webapp/src/main/webapp/i18n/all.properties +++ b/webapp/src/main/webapp/i18n/all.properties @@ -246,6 +246,7 @@ verbose_turn_off = Turn off resource_uri = Resource URI individual_not_found = Individual not found +individual_not_found_msg = The individual was not found in the system. entity_to_query_for = This id is the id of the entity to query for. netid also works. menu_ordering = Menu Ordering @@ -435,6 +436,13 @@ run_sdb_setup = Run SDB Setup unrecognized_user = Unrecognized user no_individual_associated_with_id = For some reason, there is no individual in VIVO that is associated with your Net ID. Perhaps you should contact your VIVO administrator. +page_not_created = Page could not be created +page_not_created_msg = There was an error while creating the page, please check the logs. +page_not_found = Page Not Found +page_not_found_msg = The page was not found in the system. +page_uri_missing = No page URI specified +page_uri_missing_msg = Could not generate page beacause it was unclear what page was being requested. A URL mapping may be missing. + # # site admin templates ( /templates/freemarker/body/siteAdmin ) # From ed4e42c98f0958d17d168c658f4831a2842755fc Mon Sep 17 00:00:00 2001 From: Graham Triggs Date: Mon, 31 Oct 2016 19:46:39 +0000 Subject: [PATCH 05/49] Update version numbers --- api/pom.xml | 6 +++--- dependencies/pom.xml | 4 ++-- home/pom.xml | 4 ++-- installer/home/pom.xml | 4 ++-- installer/pom.xml | 2 +- installer/solr/pom.xml | 4 ++-- installer/webapp/pom.xml | 4 ++-- pom.xml | 2 +- solr/pom.xml | 4 ++-- webapp/pom.xml | 6 +++--- 10 files changed, 20 insertions(+), 20 deletions(-) diff --git a/api/pom.xml b/api/pom.xml index 0ae50bbd3..8d799cc18 100644 --- a/api/pom.xml +++ b/api/pom.xml @@ -7,13 +7,13 @@ org.vivoweb vitro-api - 1.9.0-SNAPSHOT + 1.10.0-SNAPSHOT jar org.vivoweb vitro-project - 1.9.0-SNAPSHOT + 1.10.0-SNAPSHOT .. @@ -39,7 +39,7 @@ org.vivoweb vitro-dependencies - 1.9.0-SNAPSHOT + 1.10.0-SNAPSHOT pom diff --git a/dependencies/pom.xml b/dependencies/pom.xml index cb40a949f..5a5a45909 100644 --- a/dependencies/pom.xml +++ b/dependencies/pom.xml @@ -7,13 +7,13 @@ org.vivoweb vitro-dependencies - 1.9.0-SNAPSHOT + 1.10.0-SNAPSHOT pom org.vivoweb vitro-project - 1.9.0-SNAPSHOT + 1.10.0-SNAPSHOT .. diff --git a/home/pom.xml b/home/pom.xml index 596eb44f1..0121397b2 100644 --- a/home/pom.xml +++ b/home/pom.xml @@ -7,13 +7,13 @@ org.vivoweb vitro-home - 1.9.0-SNAPSHOT + 1.10.0-SNAPSHOT pom org.vivoweb vitro-project - 1.9.0-SNAPSHOT + 1.10.0-SNAPSHOT .. diff --git a/installer/home/pom.xml b/installer/home/pom.xml index ce88261b2..345563376 100644 --- a/installer/home/pom.xml +++ b/installer/home/pom.xml @@ -7,13 +7,13 @@ org.vivoweb vitro-installer-home - 1.9.0-SNAPSHOT + 1.10.0-SNAPSHOT pom org.vivoweb vitro-installer - 1.9.0-SNAPSHOT + 1.10.0-SNAPSHOT .. diff --git a/installer/pom.xml b/installer/pom.xml index 18ba447a2..2c1d6f5c5 100644 --- a/installer/pom.xml +++ b/installer/pom.xml @@ -7,7 +7,7 @@ org.vivoweb vitro-installer - 1.9.0-SNAPSHOT + 1.10.0-SNAPSHOT pom Vitro Installer diff --git a/installer/solr/pom.xml b/installer/solr/pom.xml index f70cc91c3..e374a9b0c 100644 --- a/installer/solr/pom.xml +++ b/installer/solr/pom.xml @@ -7,13 +7,13 @@ org.vivoweb vitro-installer-solr - 1.9.0-SNAPSHOT + 1.10.0-SNAPSHOT war org.vivoweb vitro-installer - 1.9.0-SNAPSHOT + 1.10.0-SNAPSHOT .. diff --git a/installer/webapp/pom.xml b/installer/webapp/pom.xml index bd8cf44e9..48a72d194 100644 --- a/installer/webapp/pom.xml +++ b/installer/webapp/pom.xml @@ -7,13 +7,13 @@ org.vivoweb vitro-installer-webapp - 1.9.0-SNAPSHOT + 1.10.0-SNAPSHOT war org.vivoweb vitro-installer - 1.9.0-SNAPSHOT + 1.10.0-SNAPSHOT .. diff --git a/pom.xml b/pom.xml index d23cfc925..392472d4a 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ org.vivoweb vitro-project - 1.9.0-SNAPSHOT + 1.10.0-SNAPSHOT pom Vitro diff --git a/solr/pom.xml b/solr/pom.xml index fd46f3bde..572d48fcd 100644 --- a/solr/pom.xml +++ b/solr/pom.xml @@ -7,13 +7,13 @@ org.vivoweb vitro-solr - 1.9.0-SNAPSHOT + 1.10.0-SNAPSHOT war org.vivoweb vitro-project - 1.9.0-SNAPSHOT + 1.10.0-SNAPSHOT .. diff --git a/webapp/pom.xml b/webapp/pom.xml index 1f54ddedf..b407d9cbf 100644 --- a/webapp/pom.xml +++ b/webapp/pom.xml @@ -7,13 +7,13 @@ org.vivoweb vitro-webapp - 1.9.0-SNAPSHOT + 1.10.0-SNAPSHOT war org.vivoweb vitro-project - 1.9.0-SNAPSHOT + 1.10.0-SNAPSHOT .. @@ -41,7 +41,7 @@ org.vivoweb vitro-api - 1.9.0-SNAPSHOT + 1.10.0-SNAPSHOT From f518e78760a0b7c2d7ba2a2984adbd610b4a4a79 Mon Sep 17 00:00:00 2001 From: Stefan Wolff Date: Tue, 1 Nov 2016 15:48:49 +0100 Subject: [PATCH 06/49] show class names in list views corresponding to preferred languages --- .../vitro/webapp/dao/jena/JenaBaseDao.java | 22 +++++++++++++ .../jena/ObjectPropertyStatementDaoJena.java | 31 +++++++++++++------ 2 files changed, 44 insertions(+), 9 deletions(-) diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/JenaBaseDao.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/JenaBaseDao.java index 74a224829..c6b9edade 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/JenaBaseDao.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/JenaBaseDao.java @@ -868,6 +868,28 @@ public class JenaBaseDao extends JenaBaseDaoCon { return label; } + /** + * Searches for literal in preferred language. + * @param labels + * the literals to search; must not be null + * @return the literal in preferred language if its containing in given list; + * otherwise the first entry will returned; returns null if an empty list was given + */ + protected Literal tryLiteralForPreferredLanguages(List labels) { + + // search for literal of preferred language + for (Literal literal : labels) { + for (String lang : PREFERRED_LANGUAGES) { + if (lang.equals(literal.getLanguage())) { + return literal; + } + } + } + + // return first literal as last resort + return 0 == labels.size() ? null : labels.get(0); + } + private Literal tryPropertyForPreferredLanguages( OntResource r, Property p, boolean alsoTryNoLang ) { Literal label = null; List labels = r.listPropertyValues(p).toList(); diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/ObjectPropertyStatementDaoJena.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/ObjectPropertyStatementDaoJena.java index 43c43699c..7985a4932 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/ObjectPropertyStatementDaoJena.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/ObjectPropertyStatementDaoJena.java @@ -7,7 +7,9 @@ import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; +import java.util.Locale; import java.util.Map; +import java.util.Map.Entry; import java.util.Objects; import java.util.Set; @@ -17,6 +19,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.jena.ontology.OntModel; +import org.apache.jena.ontology.OntResource; import org.apache.jena.query.Dataset; import org.apache.jena.query.Query; import org.apache.jena.query.QueryExecution; @@ -26,6 +29,7 @@ import org.apache.jena.query.QuerySolution; import org.apache.jena.query.QuerySolutionMap; import org.apache.jena.query.ResultSet; import org.apache.jena.query.Syntax; +import org.apache.jena.rdf.model.Literal; import org.apache.jena.rdf.model.Model; import org.apache.jena.rdf.model.ModelFactory; import org.apache.jena.rdf.model.Property; @@ -503,7 +507,8 @@ public class ObjectPropertyStatementDaoJena extends JenaBaseDao implements Objec return Collections.emptyMap(); } - Map types = new LinkedHashMap(); + Map result = new LinkedHashMap(); + Map> types = new LinkedHashMap>(); DatasetWrapper w = dwf.getDatasetWrapper(); Dataset dataset = w.getDataset(); dataset.getLock().enterCriticalSection(Lock.READ); @@ -521,16 +526,24 @@ public class ObjectPropertyStatementDaoJena extends JenaBaseDao implements Objec } RDFNode labelNode = soln.get("label"); - String label = null; - if (labelNode.isLiteral()) { - label = labelNode.asLiteral().getLexicalForm(); - } - - if (StringUtils.isNotBlank(type) && StringUtils.isNotBlank(label)) { - types.put(type, label); + if (StringUtils.isNotBlank(type) && labelNode.isLiteral()) { + + List langLabels = types.get(type); + if (null == langLabels) { + types.put(type, langLabels = new ArrayList()); + } + langLabels.add(labelNode.asLiteral()); + } } - return types; + + // choose labels corresponding to preferred languages + Set>> typeEntries = types.entrySet(); + for (Entry> current : typeEntries) { + result.put(current.getKey(), tryLiteralForPreferredLanguages(current.getValue()).getLexicalForm()); + } + + return result; } catch (Exception e) { log.error("Error getting most specific types for subject " + subjectUri); From 71db92490dc5f5055170a9e8499822d1b976cab3 Mon Sep 17 00:00:00 2001 From: Stefan Wolff Date: Tue, 1 Nov 2016 16:38:41 +0100 Subject: [PATCH 07/49] translate page titles of search result page and login page --- .../webapp/controller/freemarker/StaticPageController.java | 4 +++- .../vitro/webapp/search/controller/PagedSearchController.java | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/StaticPageController.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/StaticPageController.java index b4c115f6a..09ea8ded9 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/StaticPageController.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/StaticPageController.java @@ -5,12 +5,14 @@ package edu.cornell.mannlib.vitro.webapp.controller.freemarker; import java.util.HashMap; import java.util.Map; +import org.apache.commons.lang.StringUtils; 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.responsevalues.ResponseValues; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues; +import edu.cornell.mannlib.vitro.webapp.i18n.I18n; /* * Servlet that only specifies a template, without putting any data @@ -33,7 +35,7 @@ public class StaticPageController extends FreemarkerHttpServlet { String requestedUrl = vreq.getServletPath(); String title = null; if (requestedUrl.equals("/login")) { - title = "Log in to " + siteName; + title = StringUtils.capitalize(I18n.text(vreq, "log_in")) + " - " + siteName; } return title; } diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/search/controller/PagedSearchController.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/search/controller/PagedSearchController.java index 57fcc63a2..6a313e409 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/search/controller/PagedSearchController.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/search/controller/PagedSearchController.java @@ -262,8 +262,8 @@ public class PagedSearchController extends FreemarkerHttpServlet { .getIndividualTemplateModels(individuals, vreq)); body.put("querytext", queryText); - body.put("title", queryText + " - " + appBean.getApplicationName() - + " Search Results"); + body.put("title", new StringBuilder().append(appBean.getApplicationName()).append(" - "). + append(I18n.text(vreq, "search_results_for")).append(" '").append(queryText).append("'").toString()); body.put("hitCount", hitCount); body.put("startIndex", startIndex); From 2dd25a6e45359e4be5c01c796bbb001a04e1a61f Mon Sep 17 00:00:00 2001 From: Graham Triggs Date: Mon, 14 Nov 2016 19:09:35 +0000 Subject: [PATCH 08/49] =?UTF-8?q?[VIVO-1289]=20Fix=20=E2=80=9Cadd=20a=20ne?= =?UTF-8?q?w=20item=20of=20this=20type=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../generators/DefaultAddMissingIndividualFormGenerator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/DefaultAddMissingIndividualFormGenerator.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/DefaultAddMissingIndividualFormGenerator.java index 1218ee7a6..c81ec1008 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/DefaultAddMissingIndividualFormGenerator.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/DefaultAddMissingIndividualFormGenerator.java @@ -226,7 +226,7 @@ public class DefaultAddMissingIndividualFormGenerator implements EditConfigurati return prefixes; } - private String getN3ForName() { + protected String getN3ForName() { return "?" + objectVarName + " rdfs:label ?name ."; } From 20ac3a3514264bc2ef6e7fcf01fd25d4b792573e Mon Sep 17 00:00:00 2001 From: grahamtriggs Date: Tue, 13 Dec 2016 19:57:05 +0000 Subject: [PATCH 09/49] [VIVO-1063] Update jQuery to 1.12.4 and associated upgrades (#51) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Initial jQuery 1.12.4 upgrade * Upgrade jQuery UI to 1.12.1 * Upgrade to qTip2 * Update property handling * Update property handling * Update jCrop script and fix rounding of floating point co-ordinates * Fix missing confirmation message * Return empty JSON so that jQuery doesn’t complain * Fix JavaScript error --- .../controller/edit/ReorderController.java | 13 +- .../controller/freemarker/UrlBuilder.java | 7 +- .../URLRewritingHttpServletResponseTest.java | 64 +- .../config/licenser/known_exceptions.txt | 2 +- .../jquery_plugins/qtip/jquery.qtip.min.css | 1 + .../main/webapp/js/account/accountUtils.js | 6 +- .../main/webapp/js/imageUpload/cropImage.js | 10 +- .../webapp/js/individual/individualUriRdf.js | 67 +- .../src/main/webapp/js/jquery-1.12.4.min.js | 5 + .../main/webapp/js/jquery-migrate-1.4.1.js | 752 +++++ .../images/ui-bg_flat_0_aaaaaa_40x100.png | Bin 180 -> 0 bytes .../images/ui-bg_flat_75_ffffff_40x100.png | Bin 178 -> 0 bytes .../images/ui-bg_glass_55_fbf9ee_1x400.png | Bin 120 -> 0 bytes .../images/ui-bg_glass_65_ffffff_1x400.png | Bin 105 -> 0 bytes .../images/ui-bg_glass_75_dadada_1x400.png | Bin 111 -> 0 bytes .../images/ui-bg_glass_75_e6e6e6_1x400.png | Bin 110 -> 0 bytes .../images/ui-bg_glass_95_fef1ec_1x400.png | Bin 119 -> 0 bytes .../ui-bg_highlight-soft_75_cccccc_1x100.png | Bin 101 -> 0 bytes .../images/ui-icons_222222_256x240.png | Bin 4369 -> 0 bytes .../images/ui-icons_2e83ff_256x240.png | Bin 4369 -> 0 bytes .../images/ui-icons_444444_256x240.png | Bin 0 -> 7006 bytes .../images/ui-icons_454545_256x240.png | Bin 4369 -> 0 bytes .../images/ui-icons_555555_256x240.png | Bin 0 -> 7074 bytes .../images/ui-icons_777620_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_777777_256x240.png | Bin 0 -> 7013 bytes .../images/ui-icons_888888_256x240.png | Bin 4369 -> 0 bytes .../images/ui-icons_cc0000_256x240.png | Bin 0 -> 4632 bytes .../images/ui-icons_cd0a0a_256x240.png | Bin 4369 -> 0 bytes .../images/ui-icons_ffffff_256x240.png | Bin 0 -> 6313 bytes .../css/smoothness/jquery-ui-1.12.1.css | 1312 ++++++++ .../css/smoothness/jquery-ui-1.8.9.custom.css | 573 ---- .../js/jquery-ui/js/jquery-ui-1.12.1.min.js | 13 + .../js/jquery-ui-1.8.9.custom.min.js | 781 ----- webapp/src/main/webapp/js/jquery.js | 16 - .../js/jquery_plugins/jcrop/jquery.Jcrop.css | 183 +- .../js/jquery_plugins/jcrop/jquery.Jcrop.js | 2743 ++++++++++------- .../js/jquery_plugins/jquery.realperson.js | 2 +- .../qtip/jquery.qtip-1.0.0-rc3.min.js | 15 - .../js/jquery_plugins/qtip/jquery.qtip.min.js | 5 + .../webapp/js/menupage/menumanagement_edit.js | 6 +- .../webapp/js/menupage/pageManagementUtils.js | 28 +- .../processClassGroupDataGetterContent.js | 10 +- ...sIndividualsForClassesDataGetterContent.js | 6 +- webapp/src/main/webapp/js/searchDownload.js | 38 +- .../userAccounts-associateProfilePanel.ftl | 7 +- .../body/accounts/userAccounts-edit.ftl | 5 +- .../body/accounts/userAccounts-myAccount.ftl | 2 +- .../accounts/userAccounts-myProxiesPanel.ftl | 4 +- .../freemarker/body/admin/searchIndex.ftl | 2 +- .../body/contactForm/contactForm-form.ftl | 2 +- .../imageUpload/imageUpload-cropImage.ftl | 3 +- .../body/imageUpload/imageUpload-newImage.ftl | 5 +- .../imageUpload/imageUpload-replaceImage.ftl | 5 +- .../body/individual/individual-menu.ftl | 2 +- .../body/individual/individual-vitro.ftl | 7 +- .../individual/manageLabelsForIndividual.ftl | 4 +- .../individual/viewLabelsForIndividual.ftl | 4 +- .../body/manageproxies/manageProxies-list.ftl | 7 +- .../body/pagemanagement/pageList.ftl | 4 +- .../body/search/search-pagedResults.ftl | 5 +- .../siteAdmin/siteAdmin-classHierarchy.ftl | 2 +- .../body/siteAdmin/siteAdmin-dataInput.ftl | 4 +- .../siteAdmin-fauxPropertiesList.ftl | 6 +- .../siteAdmin-objectPropHierarchy.ftl | 2 +- .../edit/forms/autoCompleteObjectPropForm.ftl | 4 +- .../freemarker/edit/forms/pageManagement.ftl | 2 +- .../freemarker/page/partials/developer.ftl | 4 +- .../freemarker/page/partials/headScripts.ftl | 3 +- 68 files changed, 4031 insertions(+), 2722 deletions(-) create mode 100644 webapp/src/main/webapp/css/jquery_plugins/qtip/jquery.qtip.min.css create mode 100644 webapp/src/main/webapp/js/jquery-1.12.4.min.js create mode 100644 webapp/src/main/webapp/js/jquery-migrate-1.4.1.js delete mode 100755 webapp/src/main/webapp/js/jquery-ui/css/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png delete mode 100755 webapp/src/main/webapp/js/jquery-ui/css/smoothness/images/ui-bg_flat_75_ffffff_40x100.png delete mode 100755 webapp/src/main/webapp/js/jquery-ui/css/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png delete mode 100755 webapp/src/main/webapp/js/jquery-ui/css/smoothness/images/ui-bg_glass_65_ffffff_1x400.png delete mode 100755 webapp/src/main/webapp/js/jquery-ui/css/smoothness/images/ui-bg_glass_75_dadada_1x400.png delete mode 100755 webapp/src/main/webapp/js/jquery-ui/css/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png delete mode 100755 webapp/src/main/webapp/js/jquery-ui/css/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png delete mode 100755 webapp/src/main/webapp/js/jquery-ui/css/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png delete mode 100755 webapp/src/main/webapp/js/jquery-ui/css/smoothness/images/ui-icons_222222_256x240.png delete mode 100755 webapp/src/main/webapp/js/jquery-ui/css/smoothness/images/ui-icons_2e83ff_256x240.png create mode 100644 webapp/src/main/webapp/js/jquery-ui/css/smoothness/images/ui-icons_444444_256x240.png delete mode 100755 webapp/src/main/webapp/js/jquery-ui/css/smoothness/images/ui-icons_454545_256x240.png create mode 100644 webapp/src/main/webapp/js/jquery-ui/css/smoothness/images/ui-icons_555555_256x240.png create mode 100644 webapp/src/main/webapp/js/jquery-ui/css/smoothness/images/ui-icons_777620_256x240.png create mode 100644 webapp/src/main/webapp/js/jquery-ui/css/smoothness/images/ui-icons_777777_256x240.png delete mode 100755 webapp/src/main/webapp/js/jquery-ui/css/smoothness/images/ui-icons_888888_256x240.png create mode 100644 webapp/src/main/webapp/js/jquery-ui/css/smoothness/images/ui-icons_cc0000_256x240.png delete mode 100755 webapp/src/main/webapp/js/jquery-ui/css/smoothness/images/ui-icons_cd0a0a_256x240.png create mode 100644 webapp/src/main/webapp/js/jquery-ui/css/smoothness/images/ui-icons_ffffff_256x240.png create mode 100644 webapp/src/main/webapp/js/jquery-ui/css/smoothness/jquery-ui-1.12.1.css delete mode 100755 webapp/src/main/webapp/js/jquery-ui/css/smoothness/jquery-ui-1.8.9.custom.css create mode 100644 webapp/src/main/webapp/js/jquery-ui/js/jquery-ui-1.12.1.min.js delete mode 100755 webapp/src/main/webapp/js/jquery-ui/js/jquery-ui-1.8.9.custom.min.js delete mode 100644 webapp/src/main/webapp/js/jquery.js delete mode 100644 webapp/src/main/webapp/js/jquery_plugins/qtip/jquery.qtip-1.0.0-rc3.min.js create mode 100644 webapp/src/main/webapp/js/jquery_plugins/qtip/jquery.qtip.min.js diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/ReorderController.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/ReorderController.java index 160a65cd4..0130aec51 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/ReorderController.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/ReorderController.java @@ -32,6 +32,8 @@ import edu.cornell.mannlib.vitro.webapp.dao.DataPropertyStatementDao; import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory; import edu.cornell.mannlib.vitro.webapp.dao.jena.event.EditEvent; +import java.io.IOException; + /** * This controller receives Ajax requests for reordering a list of individuals. * Parameters: @@ -102,10 +104,13 @@ public class ReorderController extends VitroAjaxController { // This may not be the most efficient way. Should we instead build up a Model of retractions and additions, so // we only hit the database once? reorderIndividuals(individualUris, vreq, rankPredicate); - - - response.setStatus(SC_OK); - + + response.setStatus(SC_OK); + try { + response.getWriter().write("{}"); + } catch (IOException e) { + e.printStackTrace(); + } } private void reorderIndividuals(String[] individualUris, VitroRequest vreq, String rankPredicate) { diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/UrlBuilder.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/UrlBuilder.java index b4b6a8164..efbe66f2c 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/UrlBuilder.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/UrlBuilder.java @@ -71,7 +71,7 @@ public class UrlBuilder { public enum Css { CUSTOM_FORM("/edit/forms/css/customForm.css"), - JQUERY_UI("/js/jquery-ui/css/smoothness/jquery-ui-1.8.9.custom.css"); + JQUERY_UI("/js/jquery-ui/css/smoothness/jquery-ui-1.12.1.css"); private final String path; @@ -90,8 +90,9 @@ public class UrlBuilder { public enum JavaScript { CUSTOM_FORM_UTILS("/js/customFormUtils.js"), - JQUERY("/js/jquery.js"), - JQUERY_UI("/js/jquery-ui/js/jquery-ui-1.8.9.custom.min.js"), + JQUERY("/js/jquery-1.12.4.min.js"), + JQUERY_MIGRATE("/js/jquery-migrate-1.4.1.js"), + JQUERY_UI("/js/jquery-ui/js/jquery-ui-1.12.1.min.js"), UTILS("/js/utils.js"); private final String path; diff --git a/api/src/test/java/edu/cornell/mannlib/vitro/webapp/filters/URLRewritingHttpServletResponseTest.java b/api/src/test/java/edu/cornell/mannlib/vitro/webapp/filters/URLRewritingHttpServletResponseTest.java index 416b26c0a..ae5f6dedf 100644 --- a/api/src/test/java/edu/cornell/mannlib/vitro/webapp/filters/URLRewritingHttpServletResponseTest.java +++ b/api/src/test/java/edu/cornell/mannlib/vitro/webapp/filters/URLRewritingHttpServletResponseTest.java @@ -58,8 +58,8 @@ public class URLRewritingHttpServletResponseTest { @Test - public void test40984(){ urlEncodingStyleA( "/vivo/js/jquery.js", - "/vivo/js/jquery.js"); } + public void test40984(){ urlEncodingStyleA( "/vivo/js/jquery-1.12.4.min.js", + "/vivo/js/jquery-1.12.4.min.js"); } @Test public void test40988(){ urlEncodingStyleA( @@ -289,8 +289,8 @@ public class URLRewritingHttpServletResponseTest { public void test39472(){ urlEncodingStyleA( "/vivo/js/extensions/String.js", "/vivo/js/extensions/String.js"); } @Test - public void test394730(){ urlEncodingStyleA( "/vivo/js/jquery.js", - "/vivo/js/jquery.js"); } + public void test394730(){ urlEncodingStyleA( "/vivo/js/jquery-1.12.4.min.js", + "/vivo/js/jquery-1.12.4.min.js"); } @Test public void test39473(){ urlEncodingStyleA( "/vivo/js/jquery_plugins/jquery.bgiframe.pack.js", @@ -304,8 +304,8 @@ public class URLRewritingHttpServletResponseTest { "/vivo/js/jquery_plugins/ui.datepicker.js", "/vivo/js/jquery_plugins/ui.datepicker.js"); } @Test - public void test14958(){ urlEncodingStyleA( "/vivo/js/jquery.js", - "/vivo/js/jquery.js"); } + public void test14958(){ urlEncodingStyleA( "/vivo/js/jquery-1.12.4.min.js", + "/vivo/js/jquery-1.12.4.min.js"); } @Test public void test14968(){ urlEncodingStyleA( "/vivo/js/jquery_plugins/getURLParam.js", @@ -347,8 +347,8 @@ public class URLRewritingHttpServletResponseTest { "/vivo/js/imageUpload/imageUploadUtils.js"); } @Test public void test184670(){ urlEncodingStyleA( - "/vivo/js/jquery-ui/css/smoothness/jquery-ui-1.8.9.custom.css", - "/vivo/js/jquery-ui/css/smoothness/jquery-ui-1.8.9.custom.css"); } + "/vivo/js/jquery-ui/css/smoothness/jquery-ui-1.12.1.css", + "/vivo/js/jquery-ui/css/smoothness/jquery-ui-1.12.1.css"); } @Test public void test18467(){ urlEncodingStyleA( "/vivo/edit/forms/css/customForm.css", @@ -375,8 +375,8 @@ public class URLRewritingHttpServletResponseTest { public void test18516(){ urlEncodingStyleA( "/vivo/js/extensions/String.js", "/vivo/js/extensions/String.js"); } @Test - public void test18543(){ urlEncodingStyleA( "/vivo/js/jquery.js", - "/vivo/js/jquery.js"); } + public void test18543(){ urlEncodingStyleA( "/vivo/js/jquery-1.12.4.min.js", + "/vivo/js/jquery-1.12.4.min.js"); } @Test public void test185440(){ urlEncodingStyleA( "/vivo/js/jquery_plugins/jquery.bgiframe.pack.js", @@ -391,8 +391,8 @@ public class URLRewritingHttpServletResponseTest { "/vivo/js/jquery_plugins/ui.datepicker.js"); } @Test public void test18546(){ urlEncodingStyleA( - "/vivo/js/jquery-ui/js/jquery-ui-1.8.9.custom.min.js", - "/vivo/js/jquery-ui/js/jquery-ui-1.8.9.custom.min.js"); } + "/vivo/js/jquery-ui/js/jquery-ui-1.12.1.min.js", + "/vivo/js/jquery-ui/js/jquery-ui-1.12.1.min.js"); } @Test public void test185470(){ urlEncodingStyleA( "/vivo/js/customFormUtils.js", "/vivo/js/customFormUtils.js"); } @@ -412,8 +412,8 @@ public class URLRewritingHttpServletResponseTest { public void test271590(){ urlEncodingStyleA( "/vivo/js/extensions/String.js", "/vivo/js/extensions/String.js"); } @Test - public void test27159(){ urlEncodingStyleA( "/vivo/js/jquery.js", - "/vivo/js/jquery.js"); } + public void test27159(){ urlEncodingStyleA( "/vivo/js/jquery-1.12.4.min.js", + "/vivo/js/jquery-1.12.4.min.js"); } @Test public void test27160(){ urlEncodingStyleA( "/vivo/js/jquery_plugins/jquery.bgiframe.pack.js", @@ -438,8 +438,8 @@ public class URLRewritingHttpServletResponseTest { public void test148510(){ urlEncodingStyleA( "/vivo/js/extensions/String.js", "/vivo/js/extensions/String.js"); } @Test - public void test14851(){ urlEncodingStyleA( "/vivo/js/jquery.js", - "/vivo/js/jquery.js"); } + public void test14851(){ urlEncodingStyleA( "/vivo/js/jquery-1.12.4.min.js", + "/vivo/js/jquery-1.12.4.min.js"); } @Test public void test14852(){ urlEncodingStyleA( "/vivo/js/jquery_plugins/jquery.bgiframe.pack.js", @@ -454,8 +454,8 @@ public class URLRewritingHttpServletResponseTest { "/vivo/js/jquery_plugins/ui.datepicker.js"); } @Test public void test43748(){ urlEncodingStyleA( - "/vivo/js/jquery-ui/css/smoothness/jquery-ui-1.8.9.custom.css", - "/vivo/js/jquery-ui/css/smoothness/jquery-ui-1.8.9.custom.css"); } + "/vivo/js/jquery-ui/css/smoothness/jquery-ui-1.12.1.css", + "/vivo/js/jquery-ui/css/smoothness/jquery-ui-1.12.1.css"); } @Test public void test43749(){ urlEncodingStyleA( "/vivo/edit/forms/css/customForm.css", @@ -482,8 +482,8 @@ public class URLRewritingHttpServletResponseTest { public void test43760(){ urlEncodingStyleA( "/vivo/js/extensions/String.js", "/vivo/js/extensions/String.js"); } @Test - public void test437610(){ urlEncodingStyleA( "/vivo/js/jquery.js", - "/vivo/js/jquery.js"); } + public void test437610(){ urlEncodingStyleA( "/vivo/js/jquery-1.12.4.min.js", + "/vivo/js/jquery-1.12.4.min.js"); } @Test public void test43761(){ urlEncodingStyleA( "/vivo/js/jquery_plugins/jquery.bgiframe.pack.js", @@ -498,8 +498,8 @@ public class URLRewritingHttpServletResponseTest { "/vivo/js/jquery_plugins/ui.datepicker.js"); } @Test public void test43763(){ urlEncodingStyleA( - "/vivo/js/jquery-ui/js/jquery-ui-1.8.9.custom.min.js", - "/vivo/js/jquery-ui/js/jquery-ui-1.8.9.custom.min.js"); } + "/vivo/js/jquery-ui/js/jquery-ui-1.12.1.min.js", + "/vivo/js/jquery-ui/js/jquery-ui-1.12.1.min.js"); } @Test public void test437640(){ urlEncodingStyleA( "/vivo/js/customFormUtils.js", "/vivo/js/customFormUtils.js"); } @@ -509,8 +509,8 @@ public class URLRewritingHttpServletResponseTest { "/vivo/edit/forms/js/customFormWithAutocomplete.js"); } @Test public void test14550(){ urlEncodingStyleA( - "/vivo/js/jquery-ui/css/smoothness/jquery-ui-1.8.9.custom.css", - "/vivo/js/jquery-ui/css/smoothness/jquery-ui-1.8.9.custom.css"); } + "/vivo/js/jquery-ui/css/smoothness/jquery-ui-1.12.1.css", + "/vivo/js/jquery-ui/css/smoothness/jquery-ui-1.12.1.css"); } @Test public void test14551(){ urlEncodingStyleA( "/vivo/edit/forms/css/customForm.css", @@ -540,8 +540,8 @@ public class URLRewritingHttpServletResponseTest { public void test14565(){ urlEncodingStyleA( "/vivo/js/extensions/String.js", "/vivo/js/extensions/String.js"); } @Test - public void test145650(){ urlEncodingStyleA( "/vivo/js/jquery.js", - "/vivo/js/jquery.js"); } + public void test145650(){ urlEncodingStyleA( "/vivo/js/jquery-1.12.4.min.js", + "/vivo/js/jquery-1.12.4.min.js"); } @Test public void test145660(){ urlEncodingStyleA( "/vivo/js/jquery_plugins/jquery.bgiframe.pack.js", @@ -556,8 +556,8 @@ public class URLRewritingHttpServletResponseTest { "/vivo/js/jquery_plugins/ui.datepicker.js"); } @Test public void test145680(){ urlEncodingStyleA( - "/vivo/js/jquery-ui/js/jquery-ui-1.8.9.custom.min.js", - "/vivo/js/jquery-ui/js/jquery-ui-1.8.9.custom.min.js"); } + "/vivo/js/jquery-ui/js/jquery-ui-1.12.1.min.js", + "/vivo/js/jquery-ui/js/jquery-ui-1.12.1.min.js"); } @Test public void test14568(){ urlEncodingStyleA( "/vivo/js/customFormUtils.js", "/vivo/js/customFormUtils.js"); } @@ -580,8 +580,8 @@ public class URLRewritingHttpServletResponseTest { public void test29084(){ urlEncodingStyleA( "/vivo/js/extensions/String.js", "/vivo/js/extensions/String.js"); } @Test - public void test29085(){ urlEncodingStyleA( "/vivo/js/jquery.js", - "/vivo/js/jquery.js"); } + public void test29085(){ urlEncodingStyleA( "/vivo/js/jquery-1.12.4.min.js", + "/vivo/js/jquery-1.12.4.min.js"); } @Test public void test290860(){ urlEncodingStyleA( "/vivo/js/jquery_plugins/jquery.bgiframe.pack.js", @@ -599,8 +599,8 @@ public class URLRewritingHttpServletResponseTest { @Test - public void test35560(){ urlEncodingStyleB( "/js/jquery.js", - "/js/jquery.js"); } + public void test35560(){ urlEncodingStyleB( "/js/jquery-1.12.4.min.js", + "/js/jquery-1.12.4.min.js"); } @Test public void test35562(){ urlEncodingStyleB( "/js/jquery_plugins/getURLParam.js", diff --git a/legacy/webapp/config/licenser/known_exceptions.txt b/legacy/webapp/config/licenser/known_exceptions.txt index 2bf0a056d..e7cbc989d 100644 --- a/legacy/webapp/config/licenser/known_exceptions.txt +++ b/legacy/webapp/config/licenser/known_exceptions.txt @@ -35,7 +35,7 @@ webapp/web/js/tiny_mce/* webapp/web/js/tiny_mce/**/* # See /doc/3rd-party-licenses.txt for LICENSE file -webapp/web/js/jquery.js +webapp/web/js/jquery-1.12.4.min.js webapp/web/js/jquery-ui/* webapp/web/js/jquery_plugins/* webapp/web/js/jquery.fix.clone.js diff --git a/webapp/src/main/webapp/css/jquery_plugins/qtip/jquery.qtip.min.css b/webapp/src/main/webapp/css/jquery_plugins/qtip/jquery.qtip.min.css new file mode 100644 index 000000000..5adc4b755 --- /dev/null +++ b/webapp/src/main/webapp/css/jquery_plugins/qtip/jquery.qtip.min.css @@ -0,0 +1 @@ +#qtip-overlay.blurs,.qtip-close{cursor:pointer}.qtip{position:absolute;left:-28000px;top:-28000px;display:none;max-width:280px;min-width:50px;font-size:10.5px;line-height:12px;direction:ltr;box-shadow:none;padding:0}.qtip-content,.qtip-titlebar{position:relative;overflow:hidden}.qtip-content{padding:5px 9px;text-align:left;word-wrap:break-word}.qtip-titlebar{padding:5px 35px 5px 10px;border-width:0 0 1px;font-weight:700}.qtip-titlebar+.qtip-content{border-top-width:0!important}.qtip-close{position:absolute;right:-9px;top:-9px;z-index:11;outline:0;border:1px solid transparent}.qtip-titlebar .qtip-close{right:4px;top:50%;margin-top:-9px}* html .qtip-titlebar .qtip-close{top:16px}.qtip-icon .ui-icon,.qtip-titlebar .ui-icon{display:block;text-indent:-1000em;direction:ltr}.qtip-icon,.qtip-icon .ui-icon{-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;text-decoration:none}.qtip-icon .ui-icon{width:18px;height:14px;line-height:14px;text-align:center;text-indent:0;font:normal 700 10px/13px Tahoma,sans-serif;color:inherit;background:-100em -100em no-repeat}.qtip-default{border:1px solid #F1D031;background-color:#FFFFA3;color:#555}.qtip-default .qtip-titlebar{background-color:#FFEF93}.qtip-default .qtip-icon{border-color:#CCC;background:#F1F1F1;color:#777}.qtip-default .qtip-titlebar .qtip-close{border-color:#AAA;color:#111}.qtip-light{background-color:#fff;border-color:#E2E2E2;color:#454545}.qtip-light .qtip-titlebar{background-color:#f1f1f1}.qtip-dark{background-color:#505050;border-color:#303030;color:#f3f3f3}.qtip-dark .qtip-titlebar{background-color:#404040}.qtip-dark .qtip-icon{border-color:#444}.qtip-dark .qtip-titlebar .ui-state-hover{border-color:#303030}.qtip-cream{background-color:#FBF7AA;border-color:#F9E98E;color:#A27D35}.qtip-red,.qtip-red .qtip-icon,.qtip-red .qtip-titlebar .ui-state-hover{border-color:#D95252}.qtip-cream .qtip-titlebar{background-color:#F0DE7D}.qtip-cream .qtip-close .qtip-icon{background-position:-82px 0}.qtip-red{background-color:#F78B83;color:#912323}.qtip-red .qtip-titlebar{background-color:#F06D65}.qtip-red .qtip-close .qtip-icon{background-position:-102px 0}.qtip-green{background-color:#CAED9E;border-color:#90D93F;color:#3F6219}.qtip-green .qtip-titlebar{background-color:#B0DE78}.qtip-green .qtip-close .qtip-icon{background-position:-42px 0}.qtip-blue{background-color:#E5F6FE;border-color:#ADD9ED;color:#5E99BD}.qtip-blue .qtip-titlebar{background-color:#D0E9F5}.qtip-blue .qtip-close .qtip-icon{background-position:-2px 0}.qtip-shadow{-webkit-box-shadow:1px 1px 3px 1px rgba(0,0,0,.15);-moz-box-shadow:1px 1px 3px 1px rgba(0,0,0,.15);box-shadow:1px 1px 3px 1px rgba(0,0,0,.15)}.qtip-bootstrap,.qtip-rounded,.qtip-tipsy{-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px}.qtip-rounded .qtip-titlebar{-moz-border-radius:4px 4px 0 0;-webkit-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0}.qtip-youtube{-moz-border-radius:2px;-webkit-border-radius:2px;border-radius:2px;-webkit-box-shadow:0 0 3px #333;-moz-box-shadow:0 0 3px #333;box-shadow:0 0 3px #333;color:#fff;border:0 solid transparent;background:#4A4A4A;background-image:-webkit-gradient(linear,left top,left bottom,color-stop(0,#4A4A4A),color-stop(100%,#000));background-image:-webkit-linear-gradient(top,#4A4A4A 0,#000 100%);background-image:-moz-linear-gradient(top,#4A4A4A 0,#000 100%);background-image:-ms-linear-gradient(top,#4A4A4A 0,#000 100%);background-image:-o-linear-gradient(top,#4A4A4A 0,#000 100%)}.qtip-youtube .qtip-titlebar{background-color:#4A4A4A;background-color:rgba(0,0,0,0)}.qtip-youtube .qtip-content{padding:.75em;font:12px arial,sans-serif;filter:progid:DXImageTransform.Microsoft.Gradient(GradientType=0, StartColorStr=#4a4a4a, EndColorStr=#000000);-ms-filter:"progid:DXImageTransform.Microsoft.Gradient(GradientType=0,StartColorStr=#4a4a4a,EndColorStr=#000000);"}.qtip-youtube .qtip-icon{border-color:#222}.qtip-youtube .qtip-titlebar .ui-state-hover{border-color:#303030}.qtip-jtools{background:#232323;background:rgba(0,0,0,.7);background-image:-webkit-gradient(linear,left top,left bottom,from(#717171),to(#232323));background-image:-moz-linear-gradient(top,#717171,#232323);background-image:-webkit-linear-gradient(top,#717171,#232323);background-image:-ms-linear-gradient(top,#717171,#232323);background-image:-o-linear-gradient(top,#717171,#232323);border:2px solid #ddd;border:2px solid rgba(241,241,241,1);-moz-border-radius:2px;-webkit-border-radius:2px;border-radius:2px;-webkit-box-shadow:0 0 12px #333;-moz-box-shadow:0 0 12px #333;box-shadow:0 0 12px #333}.qtip-jtools .qtip-titlebar{background-color:transparent;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#717171, endColorstr=#4A4A4A);-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorstr=#717171,endColorstr=#4A4A4A)"}.qtip-jtools .qtip-content{filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#4A4A4A, endColorstr=#232323);-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorstr=#4A4A4A,endColorstr=#232323)"}.qtip-jtools .qtip-content,.qtip-jtools .qtip-titlebar{background:0 0;color:#fff;border:0 dashed transparent}.qtip-jtools .qtip-icon{border-color:#555}.qtip-jtools .qtip-titlebar .ui-state-hover{border-color:#333}.qtip-cluetip{-webkit-box-shadow:4px 4px 5px rgba(0,0,0,.4);-moz-box-shadow:4px 4px 5px rgba(0,0,0,.4);box-shadow:4px 4px 5px rgba(0,0,0,.4);background-color:#D9D9C2;color:#111;border:0 dashed transparent}.qtip-cluetip .qtip-titlebar{background-color:#87876A;color:#fff;border:0 dashed transparent}.qtip-cluetip .qtip-icon{border-color:#808064}.qtip-cluetip .qtip-titlebar .ui-state-hover{border-color:#696952;color:#696952}.qtip-tipsy{background:#000;background:rgba(0,0,0,.87);color:#fff;border:0 solid transparent;font-size:11px;font-family:'Lucida Grande',sans-serif;font-weight:700;line-height:16px;text-shadow:0 1px #000}.qtip-tipsy .qtip-titlebar{padding:6px 35px 0 10px;background-color:transparent}.qtip-tipsy .qtip-content{padding:6px 10px}.qtip-tipsy .qtip-icon{border-color:#222;text-shadow:none}.qtip-tipsy .qtip-titlebar .ui-state-hover{border-color:#303030}.qtip-tipped{border:3px solid #959FA9;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;background-color:#F9F9F9;color:#454545;font-weight:400;font-family:serif}.qtip-tipped .qtip-titlebar{border-bottom-width:0;color:#fff;background:#3A79B8;background-image:-webkit-gradient(linear,left top,left bottom,from(#3A79B8),to(#2E629D));background-image:-webkit-linear-gradient(top,#3A79B8,#2E629D);background-image:-moz-linear-gradient(top,#3A79B8,#2E629D);background-image:-ms-linear-gradient(top,#3A79B8,#2E629D);background-image:-o-linear-gradient(top,#3A79B8,#2E629D);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#3A79B8, endColorstr=#2E629D);-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorstr=#3A79B8,endColorstr=#2E629D)"}.qtip-tipped .qtip-icon{border:2px solid #285589;background:#285589}.qtip-tipped .qtip-icon .ui-icon{background-color:#FBFBFB;color:#555}.qtip-bootstrap{font-size:14px;line-height:20px;color:#333;padding:1px;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box}.qtip-bootstrap .qtip-titlebar{padding:8px 14px;margin:0;font-size:14px;font-weight:400;line-height:18px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;-webkit-border-radius:5px 5px 0 0;-moz-border-radius:5px 5px 0 0;border-radius:5px 5px 0 0}.qtip-bootstrap .qtip-titlebar .qtip-close{right:11px;top:45%;border-style:none}.qtip-bootstrap .qtip-content{padding:9px 14px}.qtip-bootstrap .qtip-icon{background:0 0}.qtip-bootstrap .qtip-icon .ui-icon{width:auto;height:auto;float:right;font-size:20px;font-weight:700;line-height:18px;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}#qtip-overlay,#qtip-overlay div{left:0;top:0;width:100%;height:100%}.qtip-bootstrap .qtip-icon .ui-icon:hover{color:#000;text-decoration:none;cursor:pointer;opacity:.4;filter:alpha(opacity=40)}.qtip:not(.ie9haxors) div.qtip-content,.qtip:not(.ie9haxors) div.qtip-titlebar{filter:none;-ms-filter:none}.qtip .qtip-tip{margin:0 auto;overflow:hidden;z-index:10}.qtip .qtip-tip,x:-o-prefocus{visibility:hidden}.qtip .qtip-tip,.qtip .qtip-tip .qtip-vml,.qtip .qtip-tip canvas{position:absolute;color:#123456;background:0 0;border:0 dashed transparent}.qtip .qtip-tip canvas{top:0;left:0}.qtip .qtip-tip .qtip-vml{behavior:url(#default#VML);display:inline-block;visibility:visible}#qtip-overlay{position:fixed}#qtip-overlay div{position:absolute;background-color:#000;opacity:.7;filter:alpha(opacity=70);-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=70)"}.qtipmodal-ie6fix{position:absolute!important} \ No newline at end of file diff --git a/webapp/src/main/webapp/js/account/accountUtils.js b/webapp/src/main/webapp/js/account/accountUtils.js index b3429d401..c5e79dfab 100644 --- a/webapp/src/main/webapp/js/account/accountUtils.js +++ b/webapp/src/main/webapp/js/account/accountUtils.js @@ -41,16 +41,16 @@ $(document).ready(function(){ $('input:checkbox[name=delete-all]').click(function(){ if ( this.checked ) { // if checked, select all the checkboxes - $('input:checkbox[name=deleteAccount]').attr('checked','checked'); + $('input:checkbox[name=deleteAccount]').prop('checked','checked'); } else { // if not checked, deselect all the checkboxes - $('input:checkbox[name=deleteAccount]').removeAttr('checked'); + $('input:checkbox[name=deleteAccount]').prop('checked', null); } }); $('input:checkbox[name=deleteAccount]').click(function(){ - $('input:checkbox[name=delete-all]').removeAttr('checked'); + $('input:checkbox[name=delete-all]').prop('checked', null); }); // Confirmation alert for account deletion in userAccounts-list.ftl template diff --git a/webapp/src/main/webapp/js/imageUpload/cropImage.js b/webapp/src/main/webapp/js/imageUpload/cropImage.js index 243d71a96..f30a929cf 100644 --- a/webapp/src/main/webapp/js/imageUpload/cropImage.js +++ b/webapp/src/main/webapp/js/imageUpload/cropImage.js @@ -2,7 +2,7 @@ (function($) { - $(window).load(function(){ + $(window).on("load", function(){ var jcrop_api = $.Jcrop('#cropbox',{ /*onChange: showPreview,*/ @@ -35,10 +35,10 @@ marginTop: '-' + Math.round(ry * coords.y) + 'px' }); - $('input[name=x]').val(coords.x); - $('input[name=y]').val(coords.y); - $('input[name=w]').val(coords.w); - $('input[name=h]').val(coords.h); + $('input[name=x]').val(Math.round(coords.x)); + $('input[name=y]').val(Math.round(coords.y)); + $('input[name=w]').val(Math.round(coords.w)); + $('input[name=h]').val(Math.round(coords.h)); } }; diff --git a/webapp/src/main/webapp/js/individual/individualUriRdf.js b/webapp/src/main/webapp/js/individual/individualUriRdf.js index 422d1db88..634e8c3df 100644 --- a/webapp/src/main/webapp/js/individual/individualUriRdf.js +++ b/webapp/src/main/webapp/js/individual/individualUriRdf.js @@ -3,36 +3,31 @@ $(document).ready(function(){ $.extend(this, i18nStringsUriRdf); - + + $('head').append(''); + // This function creates and styles the "qTip" tooltip that displays the resource uri and the rdf link when the user clicks the uri/rdf icon. $('span#iconControlsLeftSide').children('img#uriIcon').each(function() { $(this).qtip( { + prerender: true, // We need this for the .click() event listener on 'a.close' content: { - prerender: true, // We need this for the .click() event listener on 'a.close' text: '
' + i18nStringsUriRdf.shareProfileUri + '
' + i18nStringsUriRdf.viewRDFProfile + '
' + i18nStringsUriRdf.closeString + '' }, position: { - corner: { - target: 'bottomLeft', - tooltip: 'topLeft' - } + my: 'top left', + at: 'bottom left' }, show: { - when: {event: 'click'} + event: 'click' }, hide: { - fixed: true, // Make it fixed so it can be hovered over and interacted with - when: { - target: $('a.close'), - event: 'click' - } + event: 'click' }, style: { - padding: '1em', - width: 400, - backgroundColor: '#f1f2ee' + classes: 'uriIconTip', + width: 400 } }); }); @@ -41,30 +36,23 @@ $(document).ready(function(){ { $(this).qtip( { + prerender: true, // We need this for the .click() event listener on 'a.close' content: { - prerender: true, // We need this for the .click() event listener on 'a.close' text: '
' + i18nStringsUriRdf.shareProfileUri + '
' + i18nStringsUriRdf.viewRDFProfile + '
' + i18nStringsUriRdf.closeString + '' }, position: { - corner: { - target: 'bottomLeft', - tooltip: 'topLeft' - } + my: 'top left', + at: 'bottom left' }, show: { - when: {event: 'click'} + event: 'click' }, hide: { - fixed: true, // Make it fixed so it can be hovered over and interacted with - when: { - target: $('a.close'), - event: 'click' - } + event: 'click' }, style: { - padding: '1em', - width: 400, - backgroundColor: '#f1f2ee' + classes: 'uriIconTip', + width: 400 } }); }); @@ -73,30 +61,23 @@ $(document).ready(function(){ { $(this).qtip( { + prerender: true, // We need this for the .click() event listener on 'a.close' content: { - prerender: true, // We need this for the .click() event listener on 'a.close' text: '
' + i18nStringsUriRdf.shareProfileUri + '
' + i18nStringsUriRdf.viewRDFProfile + '
' + i18nStringsUriRdf.closeString + '' }, position: { - corner: { - target: 'bottomRight', - tooltip: 'topRight' - } + my: 'top right', + at: 'bottom right' }, show: { - when: {event: 'click'} + event: 'click' }, hide: { - fixed: true, // Make it fixed so it can be hovered over and interacted with - when: { - target: $('a.close'), - event: 'click' - } + event: 'click' }, style: { - padding: '1em', - width: 400, - backgroundColor: '#f1f2ee' + classes: 'uriIconTip', + width: 400 } }); }); diff --git a/webapp/src/main/webapp/js/jquery-1.12.4.min.js b/webapp/src/main/webapp/js/jquery-1.12.4.min.js new file mode 100644 index 000000000..e83647587 --- /dev/null +++ b/webapp/src/main/webapp/js/jquery-1.12.4.min.js @@ -0,0 +1,5 @@ +/*! jQuery v1.12.4 | (c) jQuery Foundation | jquery.org/license */ +!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=a.document,e=c.slice,f=c.concat,g=c.push,h=c.indexOf,i={},j=i.toString,k=i.hasOwnProperty,l={},m="1.12.4",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return e.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:e.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a){return n.each(this,a)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(e.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor()},push:g,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(n.isPlainObject(c)||(b=n.isArray(c)))?(b?(b=!1,f=a&&n.isArray(a)?a:[]):f=a&&n.isPlainObject(a)?a:{},g[d]=n.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray||function(a){return"array"===n.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){var b=a&&a.toString();return!n.isArray(a)&&b-parseFloat(b)+1>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==n.type(a)||a.nodeType||n.isWindow(a))return!1;try{if(a.constructor&&!k.call(a,"constructor")&&!k.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(!l.ownFirst)for(b in a)return k.call(a,b);for(b in a);return void 0===b||k.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?i[j.call(a)]||"object":typeof a},globalEval:function(b){b&&n.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b){var c,d=0;if(s(a)){for(c=a.length;c>d;d++)if(b.call(a[d],d,a[d])===!1)break}else for(d in a)if(b.call(a[d],d,a[d])===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):g.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(h)return h.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,e,g=0,h=[];if(s(a))for(d=a.length;d>g;g++)e=b(a[g],g,c),null!=e&&h.push(e);else for(g in a)e=b(a[g],g,c),null!=e&&h.push(e);return f.apply([],h)},guid:1,proxy:function(a,b){var c,d,f;return"string"==typeof b&&(f=a[b],b=a,a=f),n.isFunction(a)?(c=e.call(arguments,2),d=function(){return a.apply(b||this,c.concat(e.call(arguments)))},d.guid=a.guid=a.guid||n.guid++,d):void 0},now:function(){return+new Date},support:l}),"function"==typeof Symbol&&(n.fn[Symbol.iterator]=c[Symbol.iterator]),n.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(a,b){i["[object "+b+"]"]=b.toLowerCase()});function s(a){var b=!!a&&"length"in a&&a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ga(),z=ga(),A=ga(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+M+"))|)"+L+"*\\]",O=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+N+")*)|.*)\\)|)",P=new RegExp(L+"+","g"),Q=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),R=new RegExp("^"+L+"*,"+L+"*"),S=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),T=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),U=new RegExp(O),V=new RegExp("^"+M+"$"),W={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M+"|[*])"),ATTR:new RegExp("^"+N),PSEUDO:new RegExp("^"+O),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},X=/^(?:input|select|textarea|button)$/i,Y=/^h\d$/i,Z=/^[^{]+\{\s*\[native \w/,$=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,_=/[+~]/,aa=/'|\\/g,ba=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),ca=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},da=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(ea){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function fa(a,b,d,e){var f,h,j,k,l,o,r,s,w=b&&b.ownerDocument,x=b?b.nodeType:9;if(d=d||[],"string"!=typeof a||!a||1!==x&&9!==x&&11!==x)return d;if(!e&&((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,p)){if(11!==x&&(o=$.exec(a)))if(f=o[1]){if(9===x){if(!(j=b.getElementById(f)))return d;if(j.id===f)return d.push(j),d}else if(w&&(j=w.getElementById(f))&&t(b,j)&&j.id===f)return d.push(j),d}else{if(o[2])return H.apply(d,b.getElementsByTagName(a)),d;if((f=o[3])&&c.getElementsByClassName&&b.getElementsByClassName)return H.apply(d,b.getElementsByClassName(f)),d}if(c.qsa&&!A[a+" "]&&(!q||!q.test(a))){if(1!==x)w=b,s=a;else if("object"!==b.nodeName.toLowerCase()){(k=b.getAttribute("id"))?k=k.replace(aa,"\\$&"):b.setAttribute("id",k=u),r=g(a),h=r.length,l=V.test(k)?"#"+k:"[id='"+k+"']";while(h--)r[h]=l+" "+qa(r[h]);s=r.join(","),w=_.test(a)&&oa(b.parentNode)||b}if(s)try{return H.apply(d,w.querySelectorAll(s)),d}catch(y){}finally{k===u&&b.removeAttribute("id")}}}return i(a.replace(Q,"$1"),b,d,e)}function ga(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ha(a){return a[u]=!0,a}function ia(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ja(a,b){var c=a.split("|"),e=c.length;while(e--)d.attrHandle[c[e]]=b}function ka(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function la(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function na(a){return ha(function(b){return b=+b,ha(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function oa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=fa.support={},f=fa.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=fa.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=n.documentElement,p=!f(n),(e=n.defaultView)&&e.top!==e&&(e.addEventListener?e.addEventListener("unload",da,!1):e.attachEvent&&e.attachEvent("onunload",da)),c.attributes=ia(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ia(function(a){return a.appendChild(n.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Z.test(n.getElementsByClassName),c.getById=ia(function(a){return o.appendChild(a).id=u,!n.getElementsByName||!n.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ba,ca);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ba,ca);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return"undefined"!=typeof b.getElementsByClassName&&p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=Z.test(n.querySelectorAll))&&(ia(function(a){o.appendChild(a).innerHTML="",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ia(function(a){var b=n.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=Z.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ia(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",O)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=Z.test(o.compareDocumentPosition),t=b||Z.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===n||a.ownerDocument===v&&t(v,a)?-1:b===n||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,g=[a],h=[b];if(!e||!f)return a===n?-1:b===n?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return ka(a,b);c=a;while(c=c.parentNode)g.unshift(c);c=b;while(c=c.parentNode)h.unshift(c);while(g[d]===h[d])d++;return d?ka(g[d],h[d]):g[d]===v?-1:h[d]===v?1:0},n):n},fa.matches=function(a,b){return fa(a,null,null,b)},fa.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(T,"='$1']"),c.matchesSelector&&p&&!A[b+" "]&&(!r||!r.test(b))&&(!q||!q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return fa(b,n,null,[a]).length>0},fa.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},fa.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},fa.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},fa.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=fa.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=fa.selectors={cacheLength:50,createPseudo:ha,match:W,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ba,ca),a[3]=(a[3]||a[4]||a[5]||"").replace(ba,ca),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||fa.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&fa.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return W.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&U.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ba,ca).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=fa.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(P," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h,t=!1;if(q){if(f){while(p){m=b;while(m=m[p])if(h?m.nodeName.toLowerCase()===r:1===m.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){m=q,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n&&j[2],m=n&&q.childNodes[n];while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if(1===m.nodeType&&++t&&m===b){k[a]=[w,n,t];break}}else if(s&&(m=b,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n),t===!1)while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if((h?m.nodeName.toLowerCase()===r:1===m.nodeType)&&++t&&(s&&(l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),k[a]=[w,t]),m===b))break;return t-=e,t===d||t%d===0&&t/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||fa.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ha(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ha(function(a){var b=[],c=[],d=h(a.replace(Q,"$1"));return d[u]?ha(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ha(function(a){return function(b){return fa(a,b).length>0}}),contains:ha(function(a){return a=a.replace(ba,ca),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ha(function(a){return V.test(a||"")||fa.error("unsupported lang: "+a),a=a.replace(ba,ca).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Y.test(a.nodeName)},input:function(a){return X.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:na(function(){return[0]}),last:na(function(a,b){return[b-1]}),eq:na(function(a,b,c){return[0>c?c+b:c]}),even:na(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:na(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:na(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:na(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function ra(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j,k=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(j=b[u]||(b[u]={}),i=j[b.uniqueID]||(j[b.uniqueID]={}),(h=i[d])&&h[0]===w&&h[1]===f)return k[2]=h[2];if(i[d]=k,k[2]=a(b,c,g))return!0}}}function sa(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ta(a,b,c){for(var d=0,e=b.length;e>d;d++)fa(a,b[d],c);return c}function ua(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(c&&!c(f,d,e)||(g.push(f),j&&b.push(h)));return g}function va(a,b,c,d,e,f){return d&&!d[u]&&(d=va(d)),e&&!e[u]&&(e=va(e,f)),ha(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ta(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:ua(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=ua(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=ua(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function wa(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=ra(function(a){return a===b},h,!0),l=ra(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[ra(sa(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return va(i>1&&sa(m),i>1&&qa(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(Q,"$1"),c,e>i&&wa(a.slice(i,e)),f>e&&wa(a=a.slice(e)),f>e&&qa(a))}m.push(c)}return sa(m)}function xa(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,o,q,r=0,s="0",t=f&&[],u=[],v=j,x=f||e&&d.find.TAG("*",k),y=w+=null==v?1:Math.random()||.1,z=x.length;for(k&&(j=g===n||g||k);s!==z&&null!=(l=x[s]);s++){if(e&&l){o=0,g||l.ownerDocument===n||(m(l),h=!p);while(q=a[o++])if(q(l,g||n,h)){i.push(l);break}k&&(w=y)}c&&((l=!q&&l)&&r--,f&&t.push(l))}if(r+=s,c&&s!==r){o=0;while(q=b[o++])q(t,u,g,h);if(f){if(r>0)while(s--)t[s]||u[s]||(u[s]=F.call(i));u=ua(u)}H.apply(i,u),k&&!f&&u.length>0&&r+b.length>1&&fa.uniqueSort(i)}return k&&(w=y,j=v),t};return c?ha(f):f}return h=fa.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=wa(b[c]),f[u]?d.push(f):e.push(f);f=A(a,xa(e,d)),f.selector=a}return f},i=fa.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(ba,ca),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=W.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(ba,ca),_.test(j[0].type)&&oa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&qa(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,!b||_.test(a)&&oa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ia(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ia(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||ja("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ia(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ja("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ia(function(a){return null==a.getAttribute("disabled")})||ja(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),fa}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.uniqueSort=n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&n(a).is(c))break;d.push(a)}return d},v=function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c},w=n.expr.match.needsContext,x=/^<([\w-]+)\s*\/?>(?:<\/\1>|)$/,y=/^.[^:#\[\.,]*$/;function z(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(y.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return n.inArray(a,b)>-1!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;e>b;b++)if(n.contains(d[b],this))return!0}));for(b=0;e>b;b++)n.find(a,d[b],c);return c=this.pushStack(e>1?n.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(z(this,a||[],!1))},not:function(a){return this.pushStack(z(this,a||[],!0))},is:function(a){return!!z(this,"string"==typeof a&&w.test(a)?n(a):a||[],!1).length}});var A,B=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,C=n.fn.init=function(a,b,c){var e,f;if(!a)return this;if(c=c||A,"string"==typeof a){if(e="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:B.exec(a),!e||!e[1]&&b)return!b||b.jquery?(b||c).find(a):this.constructor(b).find(a);if(e[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(e[1],b&&b.nodeType?b.ownerDocument||b:d,!0)),x.test(e[1])&&n.isPlainObject(b))for(e in b)n.isFunction(this[e])?this[e](b[e]):this.attr(e,b[e]);return this}if(f=d.getElementById(e[2]),f&&f.parentNode){if(f.id!==e[2])return A.find(a);this.length=1,this[0]=f}return this.context=d,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?"undefined"!=typeof c.ready?c.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};C.prototype=n.fn,A=n(d);var D=/^(?:parents|prev(?:Until|All))/,E={children:!0,contents:!0,next:!0,prev:!0};n.fn.extend({has:function(a){var b,c=n(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(n.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=w.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.uniqueSort(f):f)},index:function(a){return a?"string"==typeof a?n.inArray(this[0],n(a)):n.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.uniqueSort(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function F(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return u(a,"parentNode")},parentsUntil:function(a,b,c){return u(a,"parentNode",c)},next:function(a){return F(a,"nextSibling")},prev:function(a){return F(a,"previousSibling")},nextAll:function(a){return u(a,"nextSibling")},prevAll:function(a){return u(a,"previousSibling")},nextUntil:function(a,b,c){return u(a,"nextSibling",c)},prevUntil:function(a,b,c){return u(a,"previousSibling",c)},siblings:function(a){return v((a.parentNode||{}).firstChild,a)},children:function(a){return v(a.firstChild)},contents:function(a){return n.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(E[a]||(e=n.uniqueSort(e)),D.test(a)&&(e=e.reverse())),this.pushStack(e)}});var G=/\S+/g;function H(a){var b={};return n.each(a.match(G)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?H(a):n.extend({},a);var b,c,d,e,f=[],g=[],h=-1,i=function(){for(e=a.once,d=b=!0;g.length;h=-1){c=g.shift();while(++h-1)f.splice(c,1),h>=c&&h--}),this},has:function(a){return a?n.inArray(a,f)>-1:f.length>0},empty:function(){return f&&(f=[]),this},disable:function(){return e=g=[],f=c="",this},disabled:function(){return!f},lock:function(){return e=!0,c||j.disable(),this},locked:function(){return!!e},fireWith:function(a,c){return e||(c=c||[],c=[a,c.slice?c.slice():c],g.push(c),b||i()),this},fire:function(){return j.fireWith(this,arguments),this},fired:function(){return!!d}};return j},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().progress(c.notify).done(c.resolve).fail(c.reject):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=e.call(arguments),d=c.length,f=1!==d||a&&n.isFunction(a.promise)?d:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?e.call(arguments):d,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(d>1)for(i=new Array(d),j=new Array(d),k=new Array(d);d>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().progress(h(b,j,i)).done(h(b,k,c)).fail(g.reject):--f;return f||g.resolveWith(k,c),g.promise()}});var I;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){(a===!0?--n.readyWait:n.isReady)||(n.isReady=!0,a!==!0&&--n.readyWait>0||(I.resolveWith(d,[n]),n.fn.triggerHandler&&(n(d).triggerHandler("ready"),n(d).off("ready"))))}});function J(){d.addEventListener?(d.removeEventListener("DOMContentLoaded",K),a.removeEventListener("load",K)):(d.detachEvent("onreadystatechange",K),a.detachEvent("onload",K))}function K(){(d.addEventListener||"load"===a.event.type||"complete"===d.readyState)&&(J(),n.ready())}n.ready.promise=function(b){if(!I)if(I=n.Deferred(),"complete"===d.readyState||"loading"!==d.readyState&&!d.documentElement.doScroll)a.setTimeout(n.ready);else if(d.addEventListener)d.addEventListener("DOMContentLoaded",K),a.addEventListener("load",K);else{d.attachEvent("onreadystatechange",K),a.attachEvent("onload",K);var c=!1;try{c=null==a.frameElement&&d.documentElement}catch(e){}c&&c.doScroll&&!function f(){if(!n.isReady){try{c.doScroll("left")}catch(b){return a.setTimeout(f,50)}J(),n.ready()}}()}return I.promise(b)},n.ready.promise();var L;for(L in n(l))break;l.ownFirst="0"===L,l.inlineBlockNeedsLayout=!1,n(function(){var a,b,c,e;c=d.getElementsByTagName("body")[0],c&&c.style&&(b=d.createElement("div"),e=d.createElement("div"),e.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(e).appendChild(b),"undefined"!=typeof b.style.zoom&&(b.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",l.inlineBlockNeedsLayout=a=3===b.offsetWidth,a&&(c.style.zoom=1)),c.removeChild(e))}),function(){var a=d.createElement("div");l.deleteExpando=!0;try{delete a.test}catch(b){l.deleteExpando=!1}a=null}();var M=function(a){var b=n.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b},N=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,O=/([A-Z])/g;function P(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(O,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:N.test(c)?n.parseJSON(c):c}catch(e){}n.data(a,b,c)}else c=void 0; +}return c}function Q(a){var b;for(b in a)if(("data"!==b||!n.isEmptyObject(a[b]))&&"toJSON"!==b)return!1;return!0}function R(a,b,d,e){if(M(a)){var f,g,h=n.expando,i=a.nodeType,j=i?n.cache:a,k=i?a[h]:a[h]&&h;if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||n.guid++:h),j[k]||(j[k]=i?{}:{toJSON:n.noop}),"object"!=typeof b&&"function"!=typeof b||(e?j[k]=n.extend(j[k],b):j[k].data=n.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[n.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[n.camelCase(b)])):f=g,f}}function S(a,b,c){if(M(a)){var d,e,f=a.nodeType,g=f?n.cache:a,h=f?a[n.expando]:n.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){n.isArray(b)?b=b.concat(n.map(b,n.camelCase)):b in d?b=[b]:(b=n.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!Q(d):!n.isEmptyObject(d))return}(c||(delete g[h].data,Q(g[h])))&&(f?n.cleanData([a],!0):l.deleteExpando||g!=g.window?delete g[h]:g[h]=void 0)}}}n.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?n.cache[a[n.expando]]:a[n.expando],!!a&&!Q(a)},data:function(a,b,c){return R(a,b,c)},removeData:function(a,b){return S(a,b)},_data:function(a,b,c){return R(a,b,c,!0)},_removeData:function(a,b){return S(a,b,!0)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=n.data(f),1===f.nodeType&&!n._data(f,"parsedAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),P(f,d,e[d])));n._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){n.data(this,a)}):arguments.length>1?this.each(function(){n.data(this,a,b)}):f?P(f,a,n.data(f,a)):void 0},removeData:function(a){return this.each(function(){n.removeData(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=n._data(a,b),c&&(!d||n.isArray(c)?d=n._data(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return n._data(a,c)||n._data(a,c,{empty:n.Callbacks("once memory").add(function(){n._removeData(a,b+"queue"),n._removeData(a,c)})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.lengthh;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},Z=/^(?:checkbox|radio)$/i,$=/<([\w:-]+)/,_=/^$|\/(?:java|ecma)script/i,aa=/^\s+/,ba="abbr|article|aside|audio|bdi|canvas|data|datalist|details|dialog|figcaption|figure|footer|header|hgroup|main|mark|meter|nav|output|picture|progress|section|summary|template|time|video";function ca(a){var b=ba.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}!function(){var a=d.createElement("div"),b=d.createDocumentFragment(),c=d.createElement("input");a.innerHTML="
a",l.leadingWhitespace=3===a.firstChild.nodeType,l.tbody=!a.getElementsByTagName("tbody").length,l.htmlSerialize=!!a.getElementsByTagName("link").length,l.html5Clone="<:nav>"!==d.createElement("nav").cloneNode(!0).outerHTML,c.type="checkbox",c.checked=!0,b.appendChild(c),l.appendChecked=c.checked,a.innerHTML="",l.noCloneChecked=!!a.cloneNode(!0).lastChild.defaultValue,b.appendChild(a),c=d.createElement("input"),c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),a.appendChild(c),l.checkClone=a.cloneNode(!0).cloneNode(!0).lastChild.checked,l.noCloneEvent=!!a.addEventListener,a[n.expando]=1,l.attributes=!a.getAttribute(n.expando)}();var da={option:[1,""],legend:[1,"
","
"],area:[1,"",""],param:[1,"",""],thead:[1,"","
"],tr:[2,"","
"],col:[2,"","
"],td:[3,"","
"],_default:l.htmlSerialize?[0,"",""]:[1,"X
","
"]};da.optgroup=da.option,da.tbody=da.tfoot=da.colgroup=da.caption=da.thead,da.th=da.td;function ea(a,b){var c,d,e=0,f="undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||n.nodeName(d,b)?f.push(d):n.merge(f,ea(d,b));return void 0===b||b&&n.nodeName(a,b)?n.merge([a],f):f}function fa(a,b){for(var c,d=0;null!=(c=a[d]);d++)n._data(c,"globalEval",!b||n._data(b[d],"globalEval"))}var ga=/<|&#?\w+;/,ha=/r;r++)if(g=a[r],g||0===g)if("object"===n.type(g))n.merge(q,g.nodeType?[g]:g);else if(ga.test(g)){i=i||p.appendChild(b.createElement("div")),j=($.exec(g)||["",""])[1].toLowerCase(),m=da[j]||da._default,i.innerHTML=m[1]+n.htmlPrefilter(g)+m[2],f=m[0];while(f--)i=i.lastChild;if(!l.leadingWhitespace&&aa.test(g)&&q.push(b.createTextNode(aa.exec(g)[0])),!l.tbody){g="table"!==j||ha.test(g)?""!==m[1]||ha.test(g)?0:i:i.firstChild,f=g&&g.childNodes.length;while(f--)n.nodeName(k=g.childNodes[f],"tbody")&&!k.childNodes.length&&g.removeChild(k)}n.merge(q,i.childNodes),i.textContent="";while(i.firstChild)i.removeChild(i.firstChild);i=p.lastChild}else q.push(b.createTextNode(g));i&&p.removeChild(i),l.appendChecked||n.grep(ea(q,"input"),ia),r=0;while(g=q[r++])if(d&&n.inArray(g,d)>-1)e&&e.push(g);else if(h=n.contains(g.ownerDocument,g),i=ea(p.appendChild(g),"script"),h&&fa(i),c){f=0;while(g=i[f++])_.test(g.type||"")&&c.push(g)}return i=null,p}!function(){var b,c,e=d.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(l[b]=c in a)||(e.setAttribute(c,"t"),l[b]=e.attributes[c].expando===!1);e=null}();var ka=/^(?:input|select|textarea)$/i,la=/^key/,ma=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,na=/^(?:focusinfocus|focusoutblur)$/,oa=/^([^.]*)(?:\.(.+)|)/;function pa(){return!0}function qa(){return!1}function ra(){try{return d.activeElement}catch(a){}}function sa(a,b,c,d,e,f){var g,h;if("object"==typeof b){"string"!=typeof c&&(d=d||c,c=void 0);for(h in b)sa(a,h,c,d,b[h],f);return a}if(null==d&&null==e?(e=c,d=c=void 0):null==e&&("string"==typeof c?(e=d,d=void 0):(e=d,d=c,c=void 0)),e===!1)e=qa;else if(!e)return a;return 1===f&&(g=e,e=function(a){return n().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=n.guid++)),a.each(function(){n.event.add(this,b,e,d,c)})}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=n._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=n.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return"undefined"==typeof n||a&&n.event.triggered===a.type?void 0:n.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(G)||[""],h=b.length;while(h--)f=oa.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=n.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=n.event.special[o]||{},l=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},i),(m=g[o])||(m=g[o]=[],m.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,l):m.push(l),n.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=n.hasData(a)&&n._data(a);if(r&&(k=r.events)){b=(b||"").match(G)||[""],j=b.length;while(j--)if(h=oa.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=m.length;while(f--)g=m[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(m.splice(f,1),g.selector&&m.delegateCount--,l.remove&&l.remove.call(a,g));i&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(k)&&(delete r.handle,n._removeData(a,"events"))}},trigger:function(b,c,e,f){var g,h,i,j,l,m,o,p=[e||d],q=k.call(b,"type")?b.type:b,r=k.call(b,"namespace")?b.namespace.split("."):[];if(i=m=e=e||d,3!==e.nodeType&&8!==e.nodeType&&!na.test(q+n.event.triggered)&&(q.indexOf(".")>-1&&(r=q.split("."),q=r.shift(),r.sort()),h=q.indexOf(":")<0&&"on"+q,b=b[n.expando]?b:new n.Event(q,"object"==typeof b&&b),b.isTrigger=f?2:3,b.namespace=r.join("."),b.rnamespace=b.namespace?new RegExp("(^|\\.)"+r.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=e),c=null==c?[b]:n.makeArray(c,[b]),l=n.event.special[q]||{},f||!l.trigger||l.trigger.apply(e,c)!==!1)){if(!f&&!l.noBubble&&!n.isWindow(e)){for(j=l.delegateType||q,na.test(j+q)||(i=i.parentNode);i;i=i.parentNode)p.push(i),m=i;m===(e.ownerDocument||d)&&p.push(m.defaultView||m.parentWindow||a)}o=0;while((i=p[o++])&&!b.isPropagationStopped())b.type=o>1?j:l.bindType||q,g=(n._data(i,"events")||{})[b.type]&&n._data(i,"handle"),g&&g.apply(i,c),g=h&&i[h],g&&g.apply&&M(i)&&(b.result=g.apply(i,c),b.result===!1&&b.preventDefault());if(b.type=q,!f&&!b.isDefaultPrevented()&&(!l._default||l._default.apply(p.pop(),c)===!1)&&M(e)&&h&&e[q]&&!n.isWindow(e)){m=e[h],m&&(e[h]=null),n.event.triggered=q;try{e[q]()}catch(s){}n.event.triggered=void 0,m&&(e[h]=m)}return b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,d,f,g,h=[],i=e.call(arguments),j=(n._data(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())a.rnamespace&&!a.rnamespace.test(g.namespace)||(a.handleObj=g,a.data=g.data,d=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==d&&(a.result=d)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&("click"!==a.type||isNaN(a.button)||a.button<1))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>-1:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h]","i"),va=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi,wa=/\s*$/g,Aa=ca(d),Ba=Aa.appendChild(d.createElement("div"));function Ca(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function Da(a){return a.type=(null!==n.find.attr(a,"type"))+"/"+a.type,a}function Ea(a){var b=ya.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function Fa(a,b){if(1===b.nodeType&&n.hasData(a)){var c,d,e,f=n._data(a),g=n._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)n.event.add(b,c,h[c][d])}g.data&&(g.data=n.extend({},g.data))}}function Ga(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!l.noCloneEvent&&b[n.expando]){e=n._data(b);for(d in e.events)n.removeEvent(b,d,e.handle);b.removeAttribute(n.expando)}"script"===c&&b.text!==a.text?(Da(b).text=a.text,Ea(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),l.html5Clone&&a.innerHTML&&!n.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&Z.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:"input"!==c&&"textarea"!==c||(b.defaultValue=a.defaultValue)}}function Ha(a,b,c,d){b=f.apply([],b);var e,g,h,i,j,k,m=0,o=a.length,p=o-1,q=b[0],r=n.isFunction(q);if(r||o>1&&"string"==typeof q&&!l.checkClone&&xa.test(q))return a.each(function(e){var f=a.eq(e);r&&(b[0]=q.call(this,e,f.html())),Ha(f,b,c,d)});if(o&&(k=ja(b,a[0].ownerDocument,!1,a,d),e=k.firstChild,1===k.childNodes.length&&(k=e),e||d)){for(i=n.map(ea(k,"script"),Da),h=i.length;o>m;m++)g=k,m!==p&&(g=n.clone(g,!0,!0),h&&n.merge(i,ea(g,"script"))),c.call(a[m],g,m);if(h)for(j=i[i.length-1].ownerDocument,n.map(i,Ea),m=0;h>m;m++)g=i[m],_.test(g.type||"")&&!n._data(g,"globalEval")&&n.contains(j,g)&&(g.src?n._evalUrl&&n._evalUrl(g.src):n.globalEval((g.text||g.textContent||g.innerHTML||"").replace(za,"")));k=e=null}return a}function Ia(a,b,c){for(var d,e=b?n.filter(b,a):a,f=0;null!=(d=e[f]);f++)c||1!==d.nodeType||n.cleanData(ea(d)),d.parentNode&&(c&&n.contains(d.ownerDocument,d)&&fa(ea(d,"script")),d.parentNode.removeChild(d));return a}n.extend({htmlPrefilter:function(a){return a.replace(va,"<$1>")},clone:function(a,b,c){var d,e,f,g,h,i=n.contains(a.ownerDocument,a);if(l.html5Clone||n.isXMLDoc(a)||!ua.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(Ba.innerHTML=a.outerHTML,Ba.removeChild(f=Ba.firstChild)),!(l.noCloneEvent&&l.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(d=ea(f),h=ea(a),g=0;null!=(e=h[g]);++g)d[g]&&Ga(e,d[g]);if(b)if(c)for(h=h||ea(a),d=d||ea(f),g=0;null!=(e=h[g]);g++)Fa(e,d[g]);else Fa(a,f);return d=ea(f,"script"),d.length>0&&fa(d,!i&&ea(a,"script")),d=h=e=null,f},cleanData:function(a,b){for(var d,e,f,g,h=0,i=n.expando,j=n.cache,k=l.attributes,m=n.event.special;null!=(d=a[h]);h++)if((b||M(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)m[e]?n.event.remove(d,e):n.removeEvent(d,e,g.handle);j[f]&&(delete j[f],k||"undefined"==typeof d.removeAttribute?d[i]=void 0:d.removeAttribute(i),c.push(f))}}}),n.fn.extend({domManip:Ha,detach:function(a){return Ia(this,a,!0)},remove:function(a){return Ia(this,a)},text:function(a){return Y(this,function(a){return void 0===a?n.text(this):this.empty().append((this[0]&&this[0].ownerDocument||d).createTextNode(a))},null,a,arguments.length)},append:function(){return Ha(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ca(this,a);b.appendChild(a)}})},prepend:function(){return Ha(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ca(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return Ha(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return Ha(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&n.cleanData(ea(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&n.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return Y(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(ta,""):void 0;if("string"==typeof a&&!wa.test(a)&&(l.htmlSerialize||!ua.test(a))&&(l.leadingWhitespace||!aa.test(a))&&!da[($.exec(a)||["",""])[1].toLowerCase()]){a=n.htmlPrefilter(a);try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(ea(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=[];return Ha(this,arguments,function(b){var c=this.parentNode;n.inArray(this,a)<0&&(n.cleanData(ea(this)),c&&c.replaceChild(b,this))},a)}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=0,e=[],f=n(a),h=f.length-1;h>=d;d++)c=d===h?this:this.clone(!0),n(f[d])[b](c),g.apply(e,c.get());return this.pushStack(e)}});var Ja,Ka={HTML:"block",BODY:"block"};function La(a,b){var c=n(b.createElement(a)).appendTo(b.body),d=n.css(c[0],"display");return c.detach(),d}function Ma(a){var b=d,c=Ka[a];return c||(c=La(a,b),"none"!==c&&c||(Ja=(Ja||n("':"");a._keyEvent=false;return I},_generateMonthYearHeader:function(a,b,c,e,f,h,i,g){var j=this._get(a,"changeMonth"),l=this._get(a,"changeYear"),u=this._get(a,"showMonthAfterYear"),k='
', -o="";if(h||!j)o+=''+i[b]+"";else{i=e&&e.getFullYear()==c;var m=f&&f.getFullYear()==c;o+='"}u||(k+=o+(h||!(j&& -l)?" ":""));a.yearshtml="";if(h||!l)k+=''+c+"";else{g=this._get(a,"yearRange").split(":");var r=(new Date).getFullYear();i=function(s){s=s.match(/c[+-].*/)?c+parseInt(s.substring(1),10):s.match(/[+-].*/)?r+parseInt(s,10):parseInt(s,10);return isNaN(s)?r:s};b=i(g[0]);g=Math.max(b,i(g[1]||""));b=e?Math.max(b,e.getFullYear()):b;g=f?Math.min(g,f.getFullYear()):g;for(a.yearshtml+='";if(d.browser.mozilla)k+='";else{k+=a.yearshtml;a.yearshtml=null}}k+=this._get(a,"yearSuffix");if(u)k+=(h||!(j&&l)?" ":"")+o;k+="
";return k},_adjustInstDate:function(a,b,c){var e= -a.drawYear+(c=="Y"?b:0),f=a.drawMonth+(c=="M"?b:0);b=Math.min(a.selectedDay,this._getDaysInMonth(e,f))+(c=="D"?b:0);e=this._restrictMinMax(a,this._daylightSavingAdjust(new Date(e,f,b)));a.selectedDay=e.getDate();a.drawMonth=a.selectedMonth=e.getMonth();a.drawYear=a.selectedYear=e.getFullYear();if(c=="M"||c=="Y")this._notifyChange(a)},_restrictMinMax:function(a,b){var c=this._getMinMaxDate(a,"min");a=this._getMinMaxDate(a,"max");b=c&&ba?a:b},_notifyChange:function(a){var b=this._get(a, -"onChangeMonthYear");if(b)b.apply(a.input?a.input[0]:null,[a.selectedYear,a.selectedMonth+1,a])},_getNumberOfMonths:function(a){a=this._get(a,"numberOfMonths");return a==null?[1,1]:typeof a=="number"?[1,a]:a},_getMinMaxDate:function(a,b){return this._determineDate(a,this._get(a,b+"Date"),null)},_getDaysInMonth:function(a,b){return 32-(new Date(a,b,32)).getDate()},_getFirstDayOfMonth:function(a,b){return(new Date(a,b,1)).getDay()},_canAdjustMonth:function(a,b,c,e){var f=this._getNumberOfMonths(a); -c=this._daylightSavingAdjust(new Date(c,e+(b<0?b:f[0]*f[1]),1));b<0&&c.setDate(this._getDaysInMonth(c.getFullYear(),c.getMonth()));return this._isInRange(a,c)},_isInRange:function(a,b){var c=this._getMinMaxDate(a,"min");a=this._getMinMaxDate(a,"max");return(!c||b.getTime()>=c.getTime())&&(!a||b.getTime()<=a.getTime())},_getFormatConfig:function(a){var b=this._get(a,"shortYearCutoff");b=typeof b!="string"?b:(new Date).getFullYear()%100+parseInt(b,10);return{shortYearCutoff:b,dayNamesShort:this._get(a, -"dayNamesShort"),dayNames:this._get(a,"dayNames"),monthNamesShort:this._get(a,"monthNamesShort"),monthNames:this._get(a,"monthNames")}},_formatDate:function(a,b,c,e){if(!b){a.currentDay=a.selectedDay;a.currentMonth=a.selectedMonth;a.currentYear=a.selectedYear}b=b?typeof b=="object"?b:this._daylightSavingAdjust(new Date(e,c,b)):this._daylightSavingAdjust(new Date(a.currentYear,a.currentMonth,a.currentDay));return this.formatDate(this._get(a,"dateFormat"),b,this._getFormatConfig(a))}});d.fn.datepicker= -function(a){if(!d.datepicker.initialized){d(document).mousedown(d.datepicker._checkExternalClick).find("body").append(d.datepicker.dpDiv);d.datepicker.initialized=true}var b=Array.prototype.slice.call(arguments,1);if(typeof a=="string"&&(a=="isDisabled"||a=="getDate"||a=="widget"))return d.datepicker["_"+a+"Datepicker"].apply(d.datepicker,[this[0]].concat(b));if(a=="option"&&arguments.length==2&&typeof arguments[1]=="string")return d.datepicker["_"+a+"Datepicker"].apply(d.datepicker,[this[0]].concat(b)); -return this.each(function(){typeof a=="string"?d.datepicker["_"+a+"Datepicker"].apply(d.datepicker,[this].concat(b)):d.datepicker._attachDatepicker(this,a)})};d.datepicker=new K;d.datepicker.initialized=false;d.datepicker.uuid=(new Date).getTime();d.datepicker.version="1.8.9";window["DP_jQuery_"+y]=d})(jQuery); -;/* - * jQuery UI Progressbar 1.8.9 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Progressbar - * - * Depends: - * jquery.ui.core.js - * jquery.ui.widget.js - */ -(function(b,d){b.widget("ui.progressbar",{options:{value:0,max:100},min:0,_create:function(){this.element.addClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").attr({role:"progressbar","aria-valuemin":this.min,"aria-valuemax":this.options.max,"aria-valuenow":this._value()});this.valueDiv=b("
").appendTo(this.element);this.oldValue=this._value();this._refreshValue()},destroy:function(){this.element.removeClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"); -this.valueDiv.remove();b.Widget.prototype.destroy.apply(this,arguments)},value:function(a){if(a===d)return this._value();this._setOption("value",a);return this},_setOption:function(a,c){if(a==="value"){this.options.value=c;this._refreshValue();this._value()===this.options.max&&this._trigger("complete")}b.Widget.prototype._setOption.apply(this,arguments)},_value:function(){var a=this.options.value;if(typeof a!=="number")a=0;return Math.min(this.options.max,Math.max(this.min,a))},_percentage:function(){return 100* -this._value()/this.options.max},_refreshValue:function(){var a=this.value(),c=this._percentage();if(this.oldValue!==a){this.oldValue=a;this._trigger("change")}this.valueDiv.toggleClass("ui-corner-right",a===this.options.max).width(c.toFixed(0)+"%");this.element.attr("aria-valuenow",a)}});b.extend(b.ui.progressbar,{version:"1.8.9"})})(jQuery); -;/* - * jQuery UI Effects 1.8.9 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Effects/ - */ -jQuery.effects||function(f,j){function n(c){var a;if(c&&c.constructor==Array&&c.length==3)return c;if(a=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(c))return[parseInt(a[1],10),parseInt(a[2],10),parseInt(a[3],10)];if(a=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(c))return[parseFloat(a[1])*2.55,parseFloat(a[2])*2.55,parseFloat(a[3])*2.55];if(a=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(c))return[parseInt(a[1], -16),parseInt(a[2],16),parseInt(a[3],16)];if(a=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(c))return[parseInt(a[1]+a[1],16),parseInt(a[2]+a[2],16),parseInt(a[3]+a[3],16)];if(/rgba\(0, 0, 0, 0\)/.exec(c))return o.transparent;return o[f.trim(c).toLowerCase()]}function s(c,a){var b;do{b=f.curCSS(c,a);if(b!=""&&b!="transparent"||f.nodeName(c,"body"))break;a="backgroundColor"}while(c=c.parentNode);return n(b)}function p(){var c=document.defaultView?document.defaultView.getComputedStyle(this,null):this.currentStyle, -a={},b,d;if(c&&c.length&&c[0]&&c[c[0]])for(var e=c.length;e--;){b=c[e];if(typeof c[b]=="string"){d=b.replace(/\-(\w)/g,function(g,h){return h.toUpperCase()});a[d]=c[b]}}else for(b in c)if(typeof c[b]==="string")a[b]=c[b];return a}function q(c){var a,b;for(a in c){b=c[a];if(b==null||f.isFunction(b)||a in t||/scrollbar/.test(a)||!/color/i.test(a)&&isNaN(parseFloat(b)))delete c[a]}return c}function u(c,a){var b={_:0},d;for(d in a)if(c[d]!=a[d])b[d]=a[d];return b}function k(c,a,b,d){if(typeof c=="object"){d= -a;b=null;a=c;c=a.effect}if(f.isFunction(a)){d=a;b=null;a={}}if(typeof a=="number"||f.fx.speeds[a]){d=b;b=a;a={}}if(f.isFunction(b)){d=b;b=null}a=a||{};b=b||a.duration;b=f.fx.off?0:typeof b=="number"?b:b in f.fx.speeds?f.fx.speeds[b]:f.fx.speeds._default;d=d||a.complete;return[c,a,b,d]}function m(c){if(!c||typeof c==="number"||f.fx.speeds[c])return true;if(typeof c==="string"&&!f.effects[c])return true;return false}f.effects={};f.each(["backgroundColor","borderBottomColor","borderLeftColor","borderRightColor", -"borderTopColor","borderColor","color","outlineColor"],function(c,a){f.fx.step[a]=function(b){if(!b.colorInit){b.start=s(b.elem,a);b.end=n(b.end);b.colorInit=true}b.elem.style[a]="rgb("+Math.max(Math.min(parseInt(b.pos*(b.end[0]-b.start[0])+b.start[0],10),255),0)+","+Math.max(Math.min(parseInt(b.pos*(b.end[1]-b.start[1])+b.start[1],10),255),0)+","+Math.max(Math.min(parseInt(b.pos*(b.end[2]-b.start[2])+b.start[2],10),255),0)+")"}});var o={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0, -0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211, -211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0],transparent:[255,255,255]},r=["add","remove","toggle"],t={border:1,borderBottom:1,borderColor:1,borderLeft:1,borderRight:1,borderTop:1,borderWidth:1,margin:1,padding:1};f.effects.animateClass=function(c,a,b, -d){if(f.isFunction(b)){d=b;b=null}return this.queue("fx",function(){var e=f(this),g=e.attr("style")||" ",h=q(p.call(this)),l,v=e.attr("className");f.each(r,function(w,i){c[i]&&e[i+"Class"](c[i])});l=q(p.call(this));e.attr("className",v);e.animate(u(h,l),a,b,function(){f.each(r,function(w,i){c[i]&&e[i+"Class"](c[i])});if(typeof e.attr("style")=="object"){e.attr("style").cssText="";e.attr("style").cssText=g}else e.attr("style",g);d&&d.apply(this,arguments)});h=f.queue(this);l=h.splice(h.length-1,1)[0]; -h.splice(1,0,l);f.dequeue(this)})};f.fn.extend({_addClass:f.fn.addClass,addClass:function(c,a,b,d){return a?f.effects.animateClass.apply(this,[{add:c},a,b,d]):this._addClass(c)},_removeClass:f.fn.removeClass,removeClass:function(c,a,b,d){return a?f.effects.animateClass.apply(this,[{remove:c},a,b,d]):this._removeClass(c)},_toggleClass:f.fn.toggleClass,toggleClass:function(c,a,b,d,e){return typeof a=="boolean"||a===j?b?f.effects.animateClass.apply(this,[a?{add:c}:{remove:c},b,d,e]):this._toggleClass(c, -a):f.effects.animateClass.apply(this,[{toggle:c},a,b,d])},switchClass:function(c,a,b,d,e){return f.effects.animateClass.apply(this,[{add:a,remove:c},b,d,e])}});f.extend(f.effects,{version:"1.8.9",save:function(c,a){for(var b=0;b").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent", -border:"none",margin:0,padding:0});c.wrap(b);b=c.parent();if(c.css("position")=="static"){b.css({position:"relative"});c.css({position:"relative"})}else{f.extend(a,{position:c.css("position"),zIndex:c.css("z-index")});f.each(["top","left","bottom","right"],function(d,e){a[e]=c.css(e);if(isNaN(parseInt(a[e],10)))a[e]="auto"});c.css({position:"relative",top:0,left:0,right:"auto",bottom:"auto"})}return b.css(a).show()},removeWrapper:function(c){if(c.parent().is(".ui-effects-wrapper"))return c.parent().replaceWith(c); -return c},setTransition:function(c,a,b,d){d=d||{};f.each(a,function(e,g){unit=c.cssUnit(g);if(unit[0]>0)d[g]=unit[0]*b+unit[1]});return d}});f.fn.extend({effect:function(c){var a=k.apply(this,arguments),b={options:a[1],duration:a[2],callback:a[3]};a=b.options.mode;var d=f.effects[c];if(f.fx.off||!d)return a?this[a](b.duration,b.callback):this.each(function(){b.callback&&b.callback.call(this)});return d.call(this,b)},_show:f.fn.show,show:function(c){if(m(c))return this._show.apply(this,arguments); -else{var a=k.apply(this,arguments);a[1].mode="show";return this.effect.apply(this,a)}},_hide:f.fn.hide,hide:function(c){if(m(c))return this._hide.apply(this,arguments);else{var a=k.apply(this,arguments);a[1].mode="hide";return this.effect.apply(this,a)}},__toggle:f.fn.toggle,toggle:function(c){if(m(c)||typeof c==="boolean"||f.isFunction(c))return this.__toggle.apply(this,arguments);else{var a=k.apply(this,arguments);a[1].mode="toggle";return this.effect.apply(this,a)}},cssUnit:function(c){var a=this.css(c), -b=[];f.each(["em","px","%","pt"],function(d,e){if(a.indexOf(e)>0)b=[parseFloat(a),e]});return b}});f.easing.jswing=f.easing.swing;f.extend(f.easing,{def:"easeOutQuad",swing:function(c,a,b,d,e){return f.easing[f.easing.def](c,a,b,d,e)},easeInQuad:function(c,a,b,d,e){return d*(a/=e)*a+b},easeOutQuad:function(c,a,b,d,e){return-d*(a/=e)*(a-2)+b},easeInOutQuad:function(c,a,b,d,e){if((a/=e/2)<1)return d/2*a*a+b;return-d/2*(--a*(a-2)-1)+b},easeInCubic:function(c,a,b,d,e){return d*(a/=e)*a*a+b},easeOutCubic:function(c, -a,b,d,e){return d*((a=a/e-1)*a*a+1)+b},easeInOutCubic:function(c,a,b,d,e){if((a/=e/2)<1)return d/2*a*a*a+b;return d/2*((a-=2)*a*a+2)+b},easeInQuart:function(c,a,b,d,e){return d*(a/=e)*a*a*a+b},easeOutQuart:function(c,a,b,d,e){return-d*((a=a/e-1)*a*a*a-1)+b},easeInOutQuart:function(c,a,b,d,e){if((a/=e/2)<1)return d/2*a*a*a*a+b;return-d/2*((a-=2)*a*a*a-2)+b},easeInQuint:function(c,a,b,d,e){return d*(a/=e)*a*a*a*a+b},easeOutQuint:function(c,a,b,d,e){return d*((a=a/e-1)*a*a*a*a+1)+b},easeInOutQuint:function(c, -a,b,d,e){if((a/=e/2)<1)return d/2*a*a*a*a*a+b;return d/2*((a-=2)*a*a*a*a+2)+b},easeInSine:function(c,a,b,d,e){return-d*Math.cos(a/e*(Math.PI/2))+d+b},easeOutSine:function(c,a,b,d,e){return d*Math.sin(a/e*(Math.PI/2))+b},easeInOutSine:function(c,a,b,d,e){return-d/2*(Math.cos(Math.PI*a/e)-1)+b},easeInExpo:function(c,a,b,d,e){return a==0?b:d*Math.pow(2,10*(a/e-1))+b},easeOutExpo:function(c,a,b,d,e){return a==e?b+d:d*(-Math.pow(2,-10*a/e)+1)+b},easeInOutExpo:function(c,a,b,d,e){if(a==0)return b;if(a== -e)return b+d;if((a/=e/2)<1)return d/2*Math.pow(2,10*(a-1))+b;return d/2*(-Math.pow(2,-10*--a)+2)+b},easeInCirc:function(c,a,b,d,e){return-d*(Math.sqrt(1-(a/=e)*a)-1)+b},easeOutCirc:function(c,a,b,d,e){return d*Math.sqrt(1-(a=a/e-1)*a)+b},easeInOutCirc:function(c,a,b,d,e){if((a/=e/2)<1)return-d/2*(Math.sqrt(1-a*a)-1)+b;return d/2*(Math.sqrt(1-(a-=2)*a)+1)+b},easeInElastic:function(c,a,b,d,e){c=1.70158;var g=0,h=d;if(a==0)return b;if((a/=e)==1)return b+d;g||(g=e*0.3);if(h").css({position:"absolute",visibility:"visible",left:-f*(h/d),top:-e*(i/c)}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:h/d,height:i/c,left:g.left+f*(h/d)+(a.options.mode=="show"?(f-Math.floor(d/2))*(h/d):0),top:g.top+e*(i/c)+(a.options.mode=="show"?(e-Math.floor(c/2))*(i/c):0),opacity:a.options.mode=="show"?0:1}).animate({left:g.left+f*(h/d)+(a.options.mode=="show"?0:(f-Math.floor(d/2))*(h/d)),top:g.top+ -e*(i/c)+(a.options.mode=="show"?0:(e-Math.floor(c/2))*(i/c)),opacity:a.options.mode=="show"?1:0},a.duration||500);setTimeout(function(){a.options.mode=="show"?b.css({visibility:"visible"}):b.css({visibility:"visible"}).hide();a.callback&&a.callback.apply(b[0]);b.dequeue();j("div.ui-effects-explode").remove()},a.duration||500)})}})(jQuery); -;/* - * jQuery UI Effects Fade 1.8.9 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Effects/Fade - * - * Depends: - * jquery.effects.core.js - */ -(function(b){b.effects.fade=function(a){return this.queue(function(){var c=b(this),d=b.effects.setMode(c,a.options.mode||"hide");c.animate({opacity:d},{queue:false,duration:a.duration,easing:a.options.easing,complete:function(){a.callback&&a.callback.apply(this,arguments);c.dequeue()}})})}})(jQuery); -;/* - * jQuery UI Effects Fold 1.8.9 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Effects/Fold - * - * Depends: - * jquery.effects.core.js - */ -(function(c){c.effects.fold=function(a){return this.queue(function(){var b=c(this),j=["position","top","bottom","left","right"],d=c.effects.setMode(b,a.options.mode||"hide"),g=a.options.size||15,h=!!a.options.horizFirst,k=a.duration?a.duration/2:c.fx.speeds._default/2;c.effects.save(b,j);b.show();var e=c.effects.createWrapper(b).css({overflow:"hidden"}),f=d=="show"!=h,l=f?["width","height"]:["height","width"];f=f?[e.width(),e.height()]:[e.height(),e.width()];var i=/([0-9]+)%/.exec(g);if(i)g=parseInt(i[1], -10)/100*f[d=="hide"?0:1];if(d=="show")e.css(h?{height:0,width:g}:{height:g,width:0});h={};i={};h[l[0]]=d=="show"?f[0]:g;i[l[1]]=d=="show"?f[1]:0;e.animate(h,k,a.options.easing).animate(i,k,a.options.easing,function(){d=="hide"&&b.hide();c.effects.restore(b,j);c.effects.removeWrapper(b);a.callback&&a.callback.apply(b[0],arguments);b.dequeue()})})}})(jQuery); -;/* - * jQuery UI Effects Highlight 1.8.9 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Effects/Highlight - * - * Depends: - * jquery.effects.core.js - */ -(function(b){b.effects.highlight=function(c){return this.queue(function(){var a=b(this),e=["backgroundImage","backgroundColor","opacity"],d=b.effects.setMode(a,c.options.mode||"show"),f={backgroundColor:a.css("backgroundColor")};if(d=="hide")f.opacity=0;b.effects.save(a,e);a.show().css({backgroundImage:"none",backgroundColor:c.options.color||"#ffff99"}).animate(f,{queue:false,duration:c.duration,easing:c.options.easing,complete:function(){d=="hide"&&a.hide();b.effects.restore(a,e);d=="show"&&!b.support.opacity&& -this.style.removeAttribute("filter");c.callback&&c.callback.apply(this,arguments);a.dequeue()}})})}})(jQuery); -;/* - * jQuery UI Effects Pulsate 1.8.9 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Effects/Pulsate - * - * Depends: - * jquery.effects.core.js - */ -(function(d){d.effects.pulsate=function(a){return this.queue(function(){var b=d(this),c=d.effects.setMode(b,a.options.mode||"show");times=(a.options.times||5)*2-1;duration=a.duration?a.duration/2:d.fx.speeds._default/2;isVisible=b.is(":visible");animateTo=0;if(!isVisible){b.css("opacity",0).show();animateTo=1}if(c=="hide"&&isVisible||c=="show"&&!isVisible)times--;for(c=0;c').appendTo(document.body).addClass(a.options.className).css({top:d.top,left:d.left,height:b.innerHeight(),width:b.innerWidth(),position:"absolute"}).animate(c,a.duration,a.options.easing,function(){f.remove();a.callback&&a.callback.apply(b[0],arguments); -b.dequeue()})})}})(jQuery); -; \ No newline at end of file diff --git a/webapp/src/main/webapp/js/jquery.js b/webapp/src/main/webapp/js/jquery.js deleted file mode 100644 index 14fd6470f..000000000 --- a/webapp/src/main/webapp/js/jquery.js +++ /dev/null @@ -1,16 +0,0 @@ -/*! - * jQuery JavaScript Library v1.5.1 - * http://jquery.com/ - * - * Copyright 2011, John Resig - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * Includes Sizzle.js - * http://sizzlejs.com/ - * Copyright 2011, The Dojo Foundation - * Released under the MIT, BSD, and GPL Licenses. - * - * Date: Wed Feb 23 13:55:29 2011 -0500 - */ -(function(a,b){function cg(a){return d.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cd(a){if(!bZ[a]){var b=d("<"+a+">").appendTo("body"),c=b.css("display");b.remove();if(c==="none"||c==="")c="block";bZ[a]=c}return bZ[a]}function cc(a,b){var c={};d.each(cb.concat.apply([],cb.slice(0,b)),function(){c[this]=a});return c}function bY(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function bX(){try{return new a.XMLHttpRequest}catch(b){}}function bW(){d(a).unload(function(){for(var a in bU)bU[a](0,1)})}function bQ(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var e=a.dataTypes,f={},g,h,i=e.length,j,k=e[0],l,m,n,o,p;for(g=1;g=0===c})}function N(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function F(a,b){return(a&&a!=="*"?a+".":"")+b.replace(r,"`").replace(s,"&")}function E(a){var b,c,e,f,g,h,i,j,k,l,m,n,o,q=[],r=[],s=d._data(this,"events");if(a.liveFired!==this&&s&&s.live&&!a.target.disabled&&(!a.button||a.type!=="click")){a.namespace&&(n=new RegExp("(^|\\.)"+a.namespace.split(".").join("\\.(?:.*\\.)?")+"(\\.|$)")),a.liveFired=this;var t=s.live.slice(0);for(i=0;ic)break;a.currentTarget=f.elem,a.data=f.handleObj.data,a.handleObj=f.handleObj,o=f.handleObj.origHandler.apply(f.elem,arguments);if(o===!1||a.isPropagationStopped()){c=f.level,o===!1&&(b=!1);if(a.isImmediatePropagationStopped())break}}return b}}function C(a,c,e){var f=d.extend({},e[0]);f.type=a,f.originalEvent={},f.liveFired=b,d.event.handle.call(c,f),f.isDefaultPrevented()&&e[0].preventDefault()}function w(){return!0}function v(){return!1}function g(a){for(var b in a)if(b!=="toJSON")return!1;return!0}function f(a,c,f){if(f===b&&a.nodeType===1){f=a.getAttribute("data-"+c);if(typeof f==="string"){try{f=f==="true"?!0:f==="false"?!1:f==="null"?null:d.isNaN(f)?e.test(f)?d.parseJSON(f):f:parseFloat(f)}catch(g){}d.data(a,c,f)}else f=b}return f}var c=a.document,d=function(){function I(){if(!d.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(I,1);return}d.ready()}}var d=function(a,b){return new d.fn.init(a,b,g)},e=a.jQuery,f=a.$,g,h=/^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/,i=/\S/,j=/^\s+/,k=/\s+$/,l=/\d/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=navigator.userAgent,w,x=!1,y,z="then done fail isResolved isRejected promise".split(" "),A,B=Object.prototype.toString,C=Object.prototype.hasOwnProperty,D=Array.prototype.push,E=Array.prototype.slice,F=String.prototype.trim,G=Array.prototype.indexOf,H={};d.fn=d.prototype={constructor:d,init:function(a,e,f){var g,i,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!e&&c.body){this.context=c,this[0]=c.body,this.selector="body",this.length=1;return this}if(typeof a==="string"){g=h.exec(a);if(!g||!g[1]&&e)return!e||e.jquery?(e||f).find(a):this.constructor(e).find(a);if(g[1]){e=e instanceof d?e[0]:e,k=e?e.ownerDocument||e:c,j=m.exec(a),j?d.isPlainObject(e)?(a=[c.createElement(j[1])],d.fn.attr.call(a,e,!0)):a=[k.createElement(j[1])]:(j=d.buildFragment([g[1]],[k]),a=(j.cacheable?d.clone(j.fragment):j.fragment).childNodes);return d.merge(this,a)}i=c.getElementById(g[2]);if(i&&i.parentNode){if(i.id!==g[2])return f.find(a);this.length=1,this[0]=i}this.context=c,this.selector=a;return this}if(d.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return d.makeArray(a,this)},selector:"",jquery:"1.5.1",length:0,size:function(){return this.length},toArray:function(){return E.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var e=this.constructor();d.isArray(a)?D.apply(e,a):d.merge(e,a),e.prevObject=this,e.context=this.context,b==="find"?e.selector=this.selector+(this.selector?" ":"")+c:b&&(e.selector=this.selector+"."+b+"("+c+")");return e},each:function(a,b){return d.each(this,a,b)},ready:function(a){d.bindReady(),y.done(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(E.apply(this,arguments),"slice",E.call(arguments).join(","))},map:function(a){return this.pushStack(d.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:D,sort:[].sort,splice:[].splice},d.fn.init.prototype=d.fn,d.extend=d.fn.extend=function(){var a,c,e,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i==="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!=="object"&&!d.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j0)return;y.resolveWith(c,[d]),d.fn.trigger&&d(c).trigger("ready").unbind("ready")}},bindReady:function(){if(!x){x=!0;if(c.readyState==="complete")return setTimeout(d.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",A,!1),a.addEventListener("load",d.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",A),a.attachEvent("onload",d.ready);var b=!1;try{b=a.frameElement==null}catch(e){}c.documentElement.doScroll&&b&&I()}}},isFunction:function(a){return d.type(a)==="function"},isArray:Array.isArray||function(a){return d.type(a)==="array"},isWindow:function(a){return a&&typeof a==="object"&&"setInterval"in a},isNaN:function(a){return a==null||!l.test(a)||isNaN(a)},type:function(a){return a==null?String(a):H[B.call(a)]||"object"},isPlainObject:function(a){if(!a||d.type(a)!=="object"||a.nodeType||d.isWindow(a))return!1;if(a.constructor&&!C.call(a,"constructor")&&!C.call(a.constructor.prototype,"isPrototypeOf"))return!1;var c;for(c in a){}return c===b||C.call(a,c)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw a},parseJSON:function(b){if(typeof b!=="string"||!b)return null;b=d.trim(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return a.JSON&&a.JSON.parse?a.JSON.parse(b):(new Function("return "+b))();d.error("Invalid JSON: "+b)},parseXML:function(b,c,e){a.DOMParser?(e=new DOMParser,c=e.parseFromString(b,"text/xml")):(c=new ActiveXObject("Microsoft.XMLDOM"),c.async="false",c.loadXML(b)),e=c.documentElement,(!e||!e.nodeName||e.nodeName==="parsererror")&&d.error("Invalid XML: "+b);return c},noop:function(){},globalEval:function(a){if(a&&i.test(a)){var b=c.head||c.getElementsByTagName("head")[0]||c.documentElement,e=c.createElement("script");d.support.scriptEval()?e.appendChild(c.createTextNode(a)):e.text=a,b.insertBefore(e,b.firstChild),b.removeChild(e)}},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,e){var f,g=0,h=a.length,i=h===b||d.isFunction(a);if(e){if(i){for(f in a)if(c.apply(a[f],e)===!1)break}else for(;g1){var f=E.call(arguments,0),g=b,h=function(a){return function(b){f[a]=arguments.length>1?E.call(arguments,0):b,--g||c.resolveWith(e,f)}};while(b--)a=f[b],a&&d.isFunction(a.promise)?a.promise().then(h(b),c.reject):--g;g||c.resolveWith(e,f)}else c!==a&&c.resolve(a);return e},uaMatch:function(a){a=a.toLowerCase();var b=r.exec(a)||s.exec(a)||t.exec(a)||a.indexOf("compatible")<0&&u.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}d.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.subclass=this.subclass,a.fn.init=function b(b,c){c&&c instanceof d&&!(c instanceof a)&&(c=a(c));return d.fn.init.call(this,b,c,e)},a.fn.init.prototype=a.fn;var e=a(c);return a},browser:{}}),y=d._Deferred(),d.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){H["[object "+b+"]"]=b.toLowerCase()}),w=d.uaMatch(v),w.browser&&(d.browser[w.browser]=!0,d.browser.version=w.version),d.browser.webkit&&(d.browser.safari=!0),G&&(d.inArray=function(a,b){return G.call(b,a)}),i.test(" ")&&(j=/^[\s\xA0]+/,k=/[\s\xA0]+$/),g=d(c),c.addEventListener?A=function(){c.removeEventListener("DOMContentLoaded",A,!1),d.ready()}:c.attachEvent&&(A=function(){c.readyState==="complete"&&(c.detachEvent("onreadystatechange",A),d.ready())});return d}();(function(){d.support={};var b=c.createElement("div");b.style.display="none",b.innerHTML="
a";var e=b.getElementsByTagName("*"),f=b.getElementsByTagName("a")[0],g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=b.getElementsByTagName("input")[0];if(e&&e.length&&f){d.support={leadingWhitespace:b.firstChild.nodeType===3,tbody:!b.getElementsByTagName("tbody").length,htmlSerialize:!!b.getElementsByTagName("link").length,style:/red/.test(f.getAttribute("style")),hrefNormalized:f.getAttribute("href")==="/a",opacity:/^0.55$/.test(f.style.opacity),cssFloat:!!f.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,deleteExpando:!0,optDisabled:!1,checkClone:!1,noCloneEvent:!0,noCloneChecked:!0,boxModel:null,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableHiddenOffsets:!0},i.checked=!0,d.support.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,d.support.optDisabled=!h.disabled;var j=null;d.support.scriptEval=function(){if(j===null){var b=c.documentElement,e=c.createElement("script"),f="script"+d.now();try{e.appendChild(c.createTextNode("window."+f+"=1;"))}catch(g){}b.insertBefore(e,b.firstChild),a[f]?(j=!0,delete a[f]):j=!1,b.removeChild(e),b=e=f=null}return j};try{delete b.test}catch(k){d.support.deleteExpando=!1}!b.addEventListener&&b.attachEvent&&b.fireEvent&&(b.attachEvent("onclick",function l(){d.support.noCloneEvent=!1,b.detachEvent("onclick",l)}),b.cloneNode(!0).fireEvent("onclick")),b=c.createElement("div"),b.innerHTML="";var m=c.createDocumentFragment();m.appendChild(b.firstChild),d.support.checkClone=m.cloneNode(!0).cloneNode(!0).lastChild.checked,d(function(){var a=c.createElement("div"),b=c.getElementsByTagName("body")[0];if(b){a.style.width=a.style.paddingLeft="1px",b.appendChild(a),d.boxModel=d.support.boxModel=a.offsetWidth===2,"zoom"in a.style&&(a.style.display="inline",a.style.zoom=1,d.support.inlineBlockNeedsLayout=a.offsetWidth===2,a.style.display="",a.innerHTML="
",d.support.shrinkWrapBlocks=a.offsetWidth!==2),a.innerHTML="
t
";var e=a.getElementsByTagName("td");d.support.reliableHiddenOffsets=e[0].offsetHeight===0,e[0].style.display="",e[1].style.display="none",d.support.reliableHiddenOffsets=d.support.reliableHiddenOffsets&&e[0].offsetHeight===0,a.innerHTML="",b.removeChild(a).style.display="none",a=e=null}});var n=function(a){var b=c.createElement("div");a="on"+a;if(!b.attachEvent)return!0;var d=a in b;d||(b.setAttribute(a,"return;"),d=typeof b[a]==="function"),b=null;return d};d.support.submitBubbles=n("submit"),d.support.changeBubbles=n("change"),b=e=f=null}})();var e=/^(?:\{.*\}|\[.*\])$/;d.extend({cache:{},uuid:0,expando:"jQuery"+(d.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?d.cache[a[d.expando]]:a[d.expando];return!!a&&!g(a)},data:function(a,c,e,f){if(d.acceptData(a)){var g=d.expando,h=typeof c==="string",i,j=a.nodeType,k=j?d.cache:a,l=j?a[d.expando]:a[d.expando]&&d.expando;if((!l||f&&l&&!k[l][g])&&h&&e===b)return;l||(j?a[d.expando]=l=++d.uuid:l=d.expando),k[l]||(k[l]={},j||(k[l].toJSON=d.noop));if(typeof c==="object"||typeof c==="function")f?k[l][g]=d.extend(k[l][g],c):k[l]=d.extend(k[l],c);i=k[l],f&&(i[g]||(i[g]={}),i=i[g]),e!==b&&(i[c]=e);if(c==="events"&&!i[c])return i[g]&&i[g].events;return h?i[c]:i}},removeData:function(b,c,e){if(d.acceptData(b)){var f=d.expando,h=b.nodeType,i=h?d.cache:b,j=h?b[d.expando]:d.expando;if(!i[j])return;if(c){var k=e?i[j][f]:i[j];if(k){delete k[c];if(!g(k))return}}if(e){delete i[j][f];if(!g(i[j]))return}var l=i[j][f];d.support.deleteExpando||i!=a?delete i[j]:i[j]=null,l?(i[j]={},h||(i[j].toJSON=d.noop),i[j][f]=l):h&&(d.support.deleteExpando?delete b[d.expando]:b.removeAttribute?b.removeAttribute(d.expando):b[d.expando]=null)}},_data:function(a,b,c){return d.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=d.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),d.fn.extend({data:function(a,c){var e=null;if(typeof a==="undefined"){if(this.length){e=d.data(this[0]);if(this[0].nodeType===1){var g=this[0].attributes,h;for(var i=0,j=g.length;i-1)return!0;return!1},val:function(a){if(!arguments.length){var c=this[0];if(c){if(d.nodeName(c,"option")){var e=c.attributes.value;return!e||e.specified?c.value:c.text}if(d.nodeName(c,"select")){var f=c.selectedIndex,g=[],h=c.options,i=c.type==="select-one";if(f<0)return null;for(var k=i?f:0,l=i?f+1:h.length;k=0;else if(d.nodeName(this,"select")){var f=d.makeArray(e);d("option",this).each(function(){this.selected=d.inArray(d(this).val(),f)>=0}),f.length||(this.selectedIndex=-1)}else this.value=e}})}}),d.extend({attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,e,f){if(!a||a.nodeType===3||a.nodeType===8||a.nodeType===2)return b;if(f&&c in d.attrFn)return d(a)[c](e);var g=a.nodeType!==1||!d.isXMLDoc(a),h=e!==b;c=g&&d.props[c]||c;if(a.nodeType===1){var i=k.test(c);if(c==="selected"&&!d.support.optSelected){var j=a.parentNode;j&&(j.selectedIndex,j.parentNode&&j.parentNode.selectedIndex)}if((c in a||a[c]!==b)&&g&&!i){h&&(c==="type"&&l.test(a.nodeName)&&a.parentNode&&d.error("type property can't be changed"),e===null?a.nodeType===1&&a.removeAttribute(c):a[c]=e);if(d.nodeName(a,"form")&&a.getAttributeNode(c))return a.getAttributeNode(c).nodeValue;if(c==="tabIndex"){var o=a.getAttributeNode("tabIndex");return o&&o.specified?o.value:m.test(a.nodeName)||n.test(a.nodeName)&&a.href?0:b}return a[c]}if(!d.support.style&&g&&c==="style"){h&&(a.style.cssText=""+e);return a.style.cssText}h&&a.setAttribute(c,""+e);if(!a.attributes[c]&&(a.hasAttribute&&!a.hasAttribute(c)))return b;var p=!d.support.hrefNormalized&&g&&i?a.getAttribute(c,2):a.getAttribute(c);return p===null?b:p}h&&(a[c]=e);return a[c]}});var p=/\.(.*)$/,q=/^(?:textarea|input|select)$/i,r=/\./g,s=/ /g,t=/[^\w\s.|`]/g,u=function(a){return a.replace(t,"\\$&")};d.event={add:function(c,e,f,g){if(c.nodeType!==3&&c.nodeType!==8){try{d.isWindow(c)&&(c!==a&&!c.frameElement)&&(c=a)}catch(h){}if(f===!1)f=v;else if(!f)return;var i,j;f.handler&&(i=f,f=i.handler),f.guid||(f.guid=d.guid++);var k=d._data(c);if(!k)return;var l=k.events,m=k.handle;l||(k.events=l={}),m||(k.handle=m=function(){return typeof d!=="undefined"&&!d.event.triggered?d.event.handle.apply(m.elem,arguments):b}),m.elem=c,e=e.split(" ");var n,o=0,p;while(n=e[o++]){j=i?d.extend({},i):{handler:f,data:g},n.indexOf(".")>-1?(p=n.split("."),n=p.shift(),j.namespace=p.slice(0).sort().join(".")):(p=[],j.namespace=""),j.type=n,j.guid||(j.guid=f.guid);var q=l[n],r=d.event.special[n]||{};if(!q){q=l[n]=[];if(!r.setup||r.setup.call(c,g,p,m)===!1)c.addEventListener?c.addEventListener(n,m,!1):c.attachEvent&&c.attachEvent("on"+n,m)}r.add&&(r.add.call(c,j),j.handler.guid||(j.handler.guid=f.guid)),q.push(j),d.event.global[n]=!0}c=null}},global:{},remove:function(a,c,e,f){if(a.nodeType!==3&&a.nodeType!==8){e===!1&&(e=v);var g,h,i,j,k=0,l,m,n,o,p,q,r,s=d.hasData(a)&&d._data(a),t=s&&s.events;if(!s||!t)return;c&&c.type&&(e=c.handler,c=c.type);if(!c||typeof c==="string"&&c.charAt(0)==="."){c=c||"";for(h in t)d.event.remove(a,h+c);return}c=c.split(" ");while(h=c[k++]){r=h,q=null,l=h.indexOf(".")<0,m=[],l||(m=h.split("."),h=m.shift(),n=new RegExp("(^|\\.)"+d.map(m.slice(0).sort(),u).join("\\.(?:.*\\.)?")+"(\\.|$)")),p=t[h];if(!p)continue;if(!e){for(j=0;j=0&&(a.type=f=f.slice(0,-1),a.exclusive=!0),e||(a.stopPropagation(),d.event.global[f]&&d.each(d.cache,function(){var b=d.expando,e=this[b];e&&e.events&&e.events[f]&&d.event.trigger(a,c,e.handle.elem)}));if(!e||e.nodeType===3||e.nodeType===8)return b;a.result=b,a.target=e,c=d.makeArray(c),c.unshift(a)}a.currentTarget=e;var h=d._data(e,"handle");h&&h.apply(e,c);var i=e.parentNode||e.ownerDocument;try{e&&e.nodeName&&d.noData[e.nodeName.toLowerCase()]||e["on"+f]&&e["on"+f].apply(e,c)===!1&&(a.result=!1,a.preventDefault())}catch(j){}if(!a.isPropagationStopped()&&i)d.event.trigger(a,c,i,!0);else if(!a.isDefaultPrevented()){var k,l=a.target,m=f.replace(p,""),n=d.nodeName(l,"a")&&m==="click",o=d.event.special[m]||{};if((!o._default||o._default.call(e,a)===!1)&&!n&&!(l&&l.nodeName&&d.noData[l.nodeName.toLowerCase()])){try{l[m]&&(k=l["on"+m],k&&(l["on"+m]=null),d.event.triggered=!0,l[m]())}catch(q){}k&&(l["on"+m]=k),d.event.triggered=!1}}},handle:function(c){var e,f,g,h,i,j=[],k=d.makeArray(arguments);c=k[0]=d.event.fix(c||a.event),c.currentTarget=this,e=c.type.indexOf(".")<0&&!c.exclusive,e||(g=c.type.split("."),c.type=g.shift(),j=g.slice(0).sort(),h=new RegExp("(^|\\.)"+j.join("\\.(?:.*\\.)?")+"(\\.|$)")),c.namespace=c.namespace||j.join("."),i=d._data(this,"events"),f=(i||{})[c.type];if(i&&f){f=f.slice(0);for(var l=0,m=f.length;l-1?d.map(a.options,function(a){return a.selected}).join("-"):"":a.nodeName.toLowerCase()==="select"&&(c=a.selectedIndex);return c},B=function B(a){var c=a.target,e,f;if(q.test(c.nodeName)&&!c.readOnly){e=d._data(c,"_change_data"),f=A(c),(a.type!=="focusout"||c.type!=="radio")&&d._data(c,"_change_data",f);if(e===b||f===e)return;if(e!=null||f)a.type="change",a.liveFired=b,d.event.trigger(a,arguments[1],c)}};d.event.special.change={filters:{focusout:B,beforedeactivate:B,click:function(a){var b=a.target,c=b.type;(c==="radio"||c==="checkbox"||b.nodeName.toLowerCase()==="select")&&B.call(this,a)},keydown:function(a){var b=a.target,c=b.type;(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(c==="checkbox"||c==="radio")||c==="select-multiple")&&B.call(this,a)},beforeactivate:function(a){var b=a.target;d._data(b,"_change_data",A(b))}},setup:function(a,b){if(this.type==="file")return!1;for(var c in z)d.event.add(this,c+".specialChange",z[c]);return q.test(this.nodeName)},teardown:function(a){d.event.remove(this,".specialChange");return q.test(this.nodeName)}},z=d.event.special.change.filters,z.focus=z.beforeactivate}c.addEventListener&&d.each({focus:"focusin",blur:"focusout"},function(a,b){function c(a){a=d.event.fix(a),a.type=b;return d.event.handle.call(this,a)}d.event.special[b]={setup:function(){this.addEventListener(a,c,!0)},teardown:function(){this.removeEventListener(a,c,!0)}}}),d.each(["bind","one"],function(a,c){d.fn[c]=function(a,e,f){if(typeof a==="object"){for(var g in a)this[c](g,e,a[g],f);return this}if(d.isFunction(e)||e===!1)f=e,e=b;var h=c==="one"?d.proxy(f,function(a){d(this).unbind(a,h);return f.apply(this,arguments)}):f;if(a==="unload"&&c!=="one")this.one(a,e,f);else for(var i=0,j=this.length;i0?this.bind(b,a,c):this.trigger(b)},d.attrFn&&(d.attrFn[b]=!0)}),function(){function u(a,b,c,d,e,f){for(var g=0,h=d.length;g0){j=i;break}}i=i[a]}d[g]=j}}}function t(a,b,c,d,e,f){for(var g=0,h=d.length;g+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,e=0,f=Object.prototype.toString,g=!1,h=!0,i=/\\/g,j=/\W/;[0,0].sort(function(){h=!1;return 0});var k=function(b,d,e,g){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!=="string")return e;var i,j,n,o,q,r,s,t,u=!0,w=k.isXML(d),x=[],y=b;do{a.exec(""),i=a.exec(y);if(i){y=i[3],x.push(i[1]);if(i[2]){o=i[3];break}}}while(i);if(x.length>1&&m.exec(b))if(x.length===2&&l.relative[x[0]])j=v(x[0]+x[1],d);else{j=l.relative[x[0]]?[d]:k(x.shift(),d);while(x.length)b=x.shift(),l.relative[b]&&(b+=x.shift()),j=v(b,j)}else{!g&&x.length>1&&d.nodeType===9&&!w&&l.match.ID.test(x[0])&&!l.match.ID.test(x[x.length-1])&&(q=k.find(x.shift(),d,w),d=q.expr?k.filter(q.expr,q.set)[0]:q.set[0]);if(d){q=g?{expr:x.pop(),set:p(g)}:k.find(x.pop(),x.length===1&&(x[0]==="~"||x[0]==="+")&&d.parentNode?d.parentNode:d,w),j=q.expr?k.filter(q.expr,q.set):q.set,x.length>0?n=p(j):u=!1;while(x.length)r=x.pop(),s=r,l.relative[r]?s=x.pop():r="",s==null&&(s=d),l.relative[r](n,s,w)}else n=x=[]}n||(n=j),n||k.error(r||b);if(f.call(n)==="[object Array]")if(u)if(d&&d.nodeType===1)for(t=0;n[t]!=null;t++)n[t]&&(n[t]===!0||n[t].nodeType===1&&k.contains(d,n[t]))&&e.push(j[t]);else for(t=0;n[t]!=null;t++)n[t]&&n[t].nodeType===1&&e.push(j[t]);else e.push.apply(e,n);else p(n,e);o&&(k(o,h,e,g),k.uniqueSort(e));return e};k.uniqueSort=function(a){if(r){g=h,a.sort(r);if(g)for(var b=1;b0},k.find=function(a,b,c){var d;if(!a)return[];for(var e=0,f=l.order.length;e":function(a,b){var c,d=typeof b==="string",e=0,f=a.length;if(d&&!j.test(b)){b=b.toLowerCase();for(;e=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(i,"")},TAG:function(a,b){return a[1].replace(i,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||k.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&k.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(i,"");!f&&l.attrMap[g]&&(a[1]=l.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(i,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=k(b[3],null,null,c);else{var g=k.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(l.match.POS.test(b[0])||l.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!k(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){return"text"===a.getAttribute("type")},radio:function(a){return"radio"===a.type},checkbox:function(a){return"checkbox"===a.type},file:function(a){return"file"===a.type},password:function(a){return"password"===a.type},submit:function(a){return"submit"===a.type},image:function(a){return"image"===a.type},reset:function(a){return"reset"===a.type},button:function(a){return"button"===a.type||a.nodeName.toLowerCase()==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return bc[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=l.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||k.getText([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=l.attrHandle[c]?l.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=l.setFilters[e];if(f)return f(a,c,b,d)}}},m=l.match.POS,n=function(a,b){return"\\"+(b-0+1)};for(var o in l.match)l.match[o]=new RegExp(l.match[o].source+/(?![^\[]*\])(?![^\(]*\))/.source),l.leftMatch[o]=new RegExp(/(^(?:.|\r|\n)*?)/.source+l.match[o].source.replace(/\\(\d+)/g,n));var p=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(q){p=function(a,b){var c=0,d=b||[];if(f.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length==="number")for(var e=a.length;c",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(l.find.ID=function(a,c,d){if(typeof c.getElementById!=="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!=="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},l.filter.ID=function(a,b){var c=typeof a.getAttributeNode!=="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(l.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="",a.firstChild&&typeof a.firstChild.getAttribute!=="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(l.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=k,b=c.createElement("div"),d="__sizzle__";b.innerHTML="

";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){k=function(b,e,f,g){e=e||c;if(!g&&!k.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return p(e.getElementsByTagName(b),f);if(h[2]&&l.find.CLASS&&e.getElementsByClassName)return p(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return p([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return p([],f);if(i.id===h[3])return p([i],f)}try{return p(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var m=e,n=e.getAttribute("id"),o=n||d,q=e.parentNode,r=/^\s*[+~]/.test(b);n?o=o.replace(/'/g,"\\$&"):e.setAttribute("id",o),r&&q&&(e=e.parentNode);try{if(!r||q)return p(e.querySelectorAll("[id='"+o+"'] "+b),f)}catch(s){}finally{n||m.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)k[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector,d=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(e){d=!0}b&&(k.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!k.isXML(a))try{if(d||!l.match.PSEUDO.test(c)&&!/!=/.test(c))return b.call(a,c)}catch(e){}return k(c,null,null,[a]).length>0})}(),function(){var a=c.createElement("div");a.innerHTML="
";if(a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;l.order.splice(1,0,"CLASS"),l.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!=="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?k.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?k.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:k.contains=function(){return!1},k.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var v=function(a,b){var c,d=[],e="",f=b.nodeType?[b]:b;while(c=l.match.PSEUDO.exec(a))e+=c[0],a=a.replace(l.match.PSEUDO,"");a=l.relative[a]?a+"*":a;for(var g=0,h=f.length;g0)for(var g=c;g0},closest:function(a,b){var c=[],e,f,g=this[0];if(d.isArray(a)){var h,i,j={},k=1;if(g&&a.length){for(e=0,f=a.length;e-1:d(g).is(h))&&c.push({selector:i,elem:g,level:k});g=g.parentNode,k++}}return c}var l=L.test(a)?d(a,b||this.context):null;for(e=0,f=this.length;e-1:d.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b)break}}c=c.length>1?d.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a||typeof a==="string")return d.inArray(this[0],a?d(a):this.parent().children());return d.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a==="string"?d(a,b):d.makeArray(a),e=d.merge(this.get(),c);return this.pushStack(N(c[0])||N(e[0])?e:d.unique(e))},andSelf:function(){return this.add(this.prevObject)}}),d.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return d.dir(a,"parentNode")},parentsUntil:function(a,b,c){return d.dir(a,"parentNode",c)},next:function(a){return d.nth(a,2,"nextSibling")},prev:function(a){return d.nth(a,2,"previousSibling")},nextAll:function(a){return d.dir(a,"nextSibling")},prevAll:function(a){return d.dir(a,"previousSibling")},nextUntil:function(a,b,c){return d.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return d.dir(a,"previousSibling",c)},siblings:function(a){return d.sibling(a.parentNode.firstChild,a)},children:function(a){return d.sibling(a.firstChild)},contents:function(a){return d.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:d.makeArray(a.childNodes)}},function(a,b){d.fn[a]=function(c,e){var f=d.map(this,b,c),g=K.call(arguments);G.test(a)||(e=c),e&&typeof e==="string"&&(f=d.filter(e,f)),f=this.length>1&&!M[a]?d.unique(f):f,(this.length>1||I.test(e))&&H.test(a)&&(f=f.reverse());return this.pushStack(f,a,g.join(","))}}),d.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?d.find.matchesSelector(b[0],a)?[b[0]]:[]:d.find.matches(a,b)},dir:function(a,c,e){var f=[],g=a[c];while(g&&g.nodeType!==9&&(e===b||g.nodeType!==1||!d(g).is(e)))g.nodeType===1&&f.push(g),g=g[c];return f},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var P=/ jQuery\d+="(?:\d+|null)"/g,Q=/^\s+/,R=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,S=/<([\w:]+)/,T=/",""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]};X.optgroup=X.option,X.tbody=X.tfoot=X.colgroup=X.caption=X.thead,X.th=X.td,d.support.htmlSerialize||(X._default=[1,"div
","
"]),d.fn.extend({text:function(a){if(d.isFunction(a))return this.each(function(b){var c=d(this);c.text(a.call(this,b,c.text()))});if(typeof a!=="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return d.text(this)},wrapAll:function(a){if(d.isFunction(a))return this.each(function(b){d(this).wrapAll(a.call(this,b))});if(this[0]){var b=d(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(d.isFunction(a))return this.each(function(b){d(this).wrapInner(a.call(this,b))});return this.each(function(){var b=d(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){d(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){d.nodeName(this,"body")||d(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=d(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,d(arguments[0]).toArray());return a}},remove:function(a,b){for(var c=0,e;(e=this[c])!=null;c++)if(!a||d.filter(a,[e]).length)!b&&e.nodeType===1&&(d.cleanData(e.getElementsByTagName("*")),d.cleanData([e])),e.parentNode&&e.parentNode.removeChild(e);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&d.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return d.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(P,""):null;if(typeof a!=="string"||V.test(a)||!d.support.leadingWhitespace&&Q.test(a)||X[(S.exec(a)||["",""])[1].toLowerCase()])d.isFunction(a)?this.each(function(b){var c=d(this);c.html(a.call(this,b,c.html()))}):this.empty().append(a);else{a=a.replace(R,"<$1>");try{for(var c=0,e=this.length;c1&&l0?this.clone(!0):this).get();d(f[h])[b](j),e=e.concat(j)}return this.pushStack(e,a,f.selector)}}),d.extend({clone:function(a,b,c){var e=a.cloneNode(!0),f,g,h;if((!d.support.noCloneEvent||!d.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!d.isXMLDoc(a)){$(a,e),f=_(a),g=_(e);for(h=0;f[h];++h)$(f[h],g[h])}if(b){Z(a,e);if(c){f=_(a),g=_(e);for(h=0;f[h];++h)Z(f[h],g[h])}}return e},clean:function(a,b,e,f){b=b||c,typeof b.createElement==="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var g=[];for(var h=0,i;(i=a[h])!=null;h++){typeof i==="number"&&(i+="");if(!i)continue;if(typeof i!=="string"||U.test(i)){if(typeof i==="string"){i=i.replace(R,"<$1>");var j=(S.exec(i)||["",""])[1].toLowerCase(),k=X[j]||X._default,l=k[0],m=b.createElement("div");m.innerHTML=k[1]+i+k[2];while(l--)m=m.lastChild;if(!d.support.tbody){var n=T.test(i),o=j==="table"&&!n?m.firstChild&&m.firstChild.childNodes:k[1]===""&&!n?m.childNodes:[];for(var p=o.length-1;p>=0;--p)d.nodeName(o[p],"tbody")&&!o[p].childNodes.length&&o[p].parentNode.removeChild(o[p])}!d.support.leadingWhitespace&&Q.test(i)&&m.insertBefore(b.createTextNode(Q.exec(i)[0]),m.firstChild),i=m.childNodes}}else i=b.createTextNode(i);i.nodeType?g.push(i):g=d.merge(g,i)}if(e)for(h=0;g[h];h++)!f||!d.nodeName(g[h],"script")||g[h].type&&g[h].type.toLowerCase()!=="text/javascript"?(g[h].nodeType===1&&g.splice.apply(g,[h+1,0].concat(d.makeArray(g[h].getElementsByTagName("script")))),e.appendChild(g[h])):f.push(g[h].parentNode?g[h].parentNode.removeChild(g[h]):g[h]);return g},cleanData:function(a){var b,c,e=d.cache,f=d.expando,g=d.event.special,h=d.support.deleteExpando;for(var i=0,j;(j=a[i])!=null;i++){if(j.nodeName&&d.noData[j.nodeName.toLowerCase()])continue;c=j[d.expando];if(c){b=e[c]&&e[c][f];if(b&&b.events){for(var k in b.events)g[k]?d.event.remove(j,k):d.removeEvent(j,k,b.handle);b.handle&&(b.handle.elem=null)}h?delete j[d.expando]:j.removeAttribute&&j.removeAttribute(d.expando),delete e[c]}}}});var bb=/alpha\([^)]*\)/i,bc=/opacity=([^)]*)/,bd=/-([a-z])/ig,be=/([A-Z])/g,bf=/^-?\d+(?:px)?$/i,bg=/^-?\d/,bh={position:"absolute",visibility:"hidden",display:"block"},bi=["Left","Right"],bj=["Top","Bottom"],bk,bl,bm,bn=function(a,b){return b.toUpperCase()};d.fn.css=function(a,c){if(arguments.length===2&&c===b)return this;return d.access(this,a,c,!0,function(a,c,e){return e!==b?d.style(a,c,e):d.css(a,c)})},d.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bk(a,"opacity","opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{zIndex:!0,fontWeight:!0,opacity:!0,zoom:!0,lineHeight:!0},cssProps:{"float":d.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,e,f){if(a&&a.nodeType!==3&&a.nodeType!==8&&a.style){var g,h=d.camelCase(c),i=a.style,j=d.cssHooks[h];c=d.cssProps[h]||h;if(e===b){if(j&&"get"in j&&(g=j.get(a,!1,f))!==b)return g;return i[c]}if(typeof e==="number"&&isNaN(e)||e==null)return;typeof e==="number"&&!d.cssNumber[h]&&(e+="px");if(!j||!("set"in j)||(e=j.set(a,e))!==b)try{i[c]=e}catch(k){}}},css:function(a,c,e){var f,g=d.camelCase(c),h=d.cssHooks[g];c=d.cssProps[g]||g;if(h&&"get"in h&&(f=h.get(a,!0,e))!==b)return f;if(bk)return bk(a,c,g)},swap:function(a,b,c){var d={};for(var e in b)d[e]=a.style[e],a.style[e]=b[e];c.call(a);for(e in b)a.style[e]=d[e]},camelCase:function(a){return a.replace(bd,bn)}}),d.curCSS=d.css,d.each(["height","width"],function(a,b){d.cssHooks[b]={get:function(a,c,e){var f;if(c){a.offsetWidth!==0?f=bo(a,b,e):d.swap(a,bh,function(){f=bo(a,b,e)});if(f<=0){f=bk(a,b,b),f==="0px"&&bm&&(f=bm(a,b,b));if(f!=null)return f===""||f==="auto"?"0px":f}if(f<0||f==null){f=a.style[b];return f===""||f==="auto"?"0px":f}return typeof f==="string"?f:f+"px"}},set:function(a,b){if(!bf.test(b))return b;b=parseFloat(b);if(b>=0)return b+"px"}}}),d.support.opacity||(d.cssHooks.opacity={get:function(a,b){return bc.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style;c.zoom=1;var e=d.isNaN(b)?"":"alpha(opacity="+b*100+")",f=c.filter||"";c.filter=bb.test(f)?f.replace(bb,e):c.filter+" "+e}}),c.defaultView&&c.defaultView.getComputedStyle&&(bl=function(a,c,e){var f,g,h;e=e.replace(be,"-$1").toLowerCase();if(!(g=a.ownerDocument.defaultView))return b;if(h=g.getComputedStyle(a,null))f=h.getPropertyValue(e),f===""&&!d.contains(a.ownerDocument.documentElement,a)&&(f=d.style(a,e));return f}),c.documentElement.currentStyle&&(bm=function(a,b){var c,d=a.currentStyle&&a.currentStyle[b],e=a.runtimeStyle&&a.runtimeStyle[b],f=a.style;!bf.test(d)&&bg.test(d)&&(c=f.left,e&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":d||0,d=f.pixelLeft+"px",f.left=c,e&&(a.runtimeStyle.left=e));return d===""?"auto":d}),bk=bl||bm,d.expr&&d.expr.filters&&(d.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!d.support.reliableHiddenOffsets&&(a.style.display||d.css(a,"display"))==="none"},d.expr.filters.visible=function(a){return!d.expr.filters.hidden(a)});var bp=/%20/g,bq=/\[\]$/,br=/\r?\n/g,bs=/#.*$/,bt=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bu=/^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bv=/(?:^file|^widget|\-extension):$/,bw=/^(?:GET|HEAD)$/,bx=/^\/\//,by=/\?/,bz=/)<[^<]*)*<\/script>/gi,bA=/^(?:select|textarea)/i,bB=/\s+/,bC=/([?&])_=[^&]*/,bD=/(^|\-)([a-z])/g,bE=function(a,b,c){return b+c.toUpperCase()},bF=/^([\w\+\.\-]+:)\/\/([^\/?#:]*)(?::(\d+))?/,bG=d.fn.load,bH={},bI={},bJ,bK;try{bJ=c.location.href}catch(bL){bJ=c.createElement("a"),bJ.href="",bJ=bJ.href}bK=bF.exec(bJ.toLowerCase()),d.fn.extend({load:function(a,c,e){if(typeof a!=="string"&&bG)return bG.apply(this,arguments);if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var g=a.slice(f,a.length);a=a.slice(0,f)}var h="GET";c&&(d.isFunction(c)?(e=c,c=b):typeof c==="object"&&(c=d.param(c,d.ajaxSettings.traditional),h="POST"));var i=this;d.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?d("
").append(c.replace(bz,"")).find(g):c)),e&&i.each(e,[c,b,a])}});return this},serialize:function(){return d.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?d.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bA.test(this.nodeName)||bu.test(this.type))}).map(function(a,b){var c=d(this).val();return c==null?null:d.isArray(c)?d.map(c,function(a,c){return{name:b.name,value:a.replace(br,"\r\n")}}):{name:b.name,value:c.replace(br,"\r\n")}}).get()}}),d.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){d.fn[b]=function(a){return this.bind(b,a)}}),d.each(["get","post"],function(a,c){d[c]=function(a,e,f,g){d.isFunction(e)&&(g=g||f,f=e,e=b);return d.ajax({type:c,url:a,data:e,success:f,dataType:g})}}),d.extend({getScript:function(a,c){return d.get(a,b,c,"script")},getJSON:function(a,b,c){return d.get(a,b,c,"json")},ajaxSetup:function(a,b){b?d.extend(!0,a,d.ajaxSettings,b):(b=a,a=d.extend(!0,d.ajaxSettings,b));for(var c in {context:1,url:1})c in b?a[c]=b[c]:c in d.ajaxSettings&&(a[c]=d.ajaxSettings[c]);return a},ajaxSettings:{url:bJ,isLocal:bv.test(bK[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":"*/*"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":d.parseJSON,"text xml":d.parseXML}},ajaxPrefilter:bM(bH),ajaxTransport:bM(bI),ajax:function(a,c){function v(a,c,l,n){if(r!==2){r=2,p&&clearTimeout(p),o=b,m=n||"",u.readyState=a?4:0;var q,t,v,w=l?bP(e,u,l):b,x,y;if(a>=200&&a<300||a===304){if(e.ifModified){if(x=u.getResponseHeader("Last-Modified"))d.lastModified[k]=x;if(y=u.getResponseHeader("Etag"))d.etag[k]=y}if(a===304)c="notmodified",q=!0;else try{t=bQ(e,w),c="success",q=!0}catch(z){c="parsererror",v=z}}else{v=c;if(!c||a)c="error",a<0&&(a=0)}u.status=a,u.statusText=c,q?h.resolveWith(f,[t,c,u]):h.rejectWith(f,[u,c,v]),u.statusCode(j),j=b,s&&g.trigger("ajax"+(q?"Success":"Error"),[u,e,q?t:v]),i.resolveWith(f,[u,c]),s&&(g.trigger("ajaxComplete",[u,e]),--d.active||d.event.trigger("ajaxStop"))}}typeof a==="object"&&(c=a,a=b),c=c||{};var e=d.ajaxSetup({},c),f=e.context||e,g=f!==e&&(f.nodeType||f instanceof d)?d(f):d.event,h=d.Deferred(),i=d._Deferred(),j=e.statusCode||{},k,l={},m,n,o,p,q,r=0,s,t,u={readyState:0,setRequestHeader:function(a,b){r||(l[a.toLowerCase().replace(bD,bE)]=b);return this},getAllResponseHeaders:function(){return r===2?m:null},getResponseHeader:function(a){var c;if(r===2){if(!n){n={};while(c=bt.exec(m))n[c[1].toLowerCase()]=c[2]}c=n[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){r||(e.mimeType=a);return this},abort:function(a){a=a||"abort",o&&o.abort(a),v(0,a);return this}};h.promise(u),u.success=u.done,u.error=u.fail,u.complete=i.done,u.statusCode=function(a){if(a){var b;if(r<2)for(b in a)j[b]=[j[b],a[b]];else b=a[u.status],u.then(b,b)}return this},e.url=((a||e.url)+"").replace(bs,"").replace(bx,bK[1]+"//"),e.dataTypes=d.trim(e.dataType||"*").toLowerCase().split(bB),e.crossDomain||(q=bF.exec(e.url.toLowerCase()),e.crossDomain=q&&(q[1]!=bK[1]||q[2]!=bK[2]||(q[3]||(q[1]==="http:"?80:443))!=(bK[3]||(bK[1]==="http:"?80:443)))),e.data&&e.processData&&typeof e.data!=="string"&&(e.data=d.param(e.data,e.traditional)),bN(bH,e,c,u);if(r===2)return!1;s=e.global,e.type=e.type.toUpperCase(),e.hasContent=!bw.test(e.type),s&&d.active++===0&&d.event.trigger("ajaxStart");if(!e.hasContent){e.data&&(e.url+=(by.test(e.url)?"&":"?")+e.data),k=e.url;if(e.cache===!1){var w=d.now(),x=e.url.replace(bC,"$1_="+w);e.url=x+(x===e.url?(by.test(e.url)?"&":"?")+"_="+w:"")}}if(e.data&&e.hasContent&&e.contentType!==!1||c.contentType)l["Content-Type"]=e.contentType;e.ifModified&&(k=k||e.url,d.lastModified[k]&&(l["If-Modified-Since"]=d.lastModified[k]),d.etag[k]&&(l["If-None-Match"]=d.etag[k])),l.Accept=e.dataTypes[0]&&e.accepts[e.dataTypes[0]]?e.accepts[e.dataTypes[0]]+(e.dataTypes[0]!=="*"?", */*; q=0.01":""):e.accepts["*"];for(t in e.headers)u.setRequestHeader(t,e.headers[t]);if(e.beforeSend&&(e.beforeSend.call(f,u,e)===!1||r===2)){u.abort();return!1}for(t in {success:1,error:1,complete:1})u[t](e[t]);o=bN(bI,e,c,u);if(o){u.readyState=1,s&&g.trigger("ajaxSend",[u,e]),e.async&&e.timeout>0&&(p=setTimeout(function(){u.abort("timeout")},e.timeout));try{r=1,o.send(l,v)}catch(y){status<2?v(-1,y):d.error(y)}}else v(-1,"No Transport");return u},param:function(a,c){var e=[],f=function(a,b){b=d.isFunction(b)?b():b,e[e.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=d.ajaxSettings.traditional);if(d.isArray(a)||a.jquery&&!d.isPlainObject(a))d.each(a,function(){f(this.name,this.value)});else for(var g in a)bO(g,a[g],c,f);return e.join("&").replace(bp,"+")}}),d.extend({active:0,lastModified:{},etag:{}});var bR=d.now(),bS=/(\=)\?(&|$)|()\?\?()/i;d.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return d.expando+"_"+bR++}}),d.ajaxPrefilter("json jsonp",function(b,c,e){var f=typeof b.data==="string";if(b.dataTypes[0]==="jsonp"||c.jsonpCallback||c.jsonp!=null||b.jsonp!==!1&&(bS.test(b.url)||f&&bS.test(b.data))){var g,h=b.jsonpCallback=d.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2",m=function(){a[h]=i,g&&d.isFunction(i)&&a[h](g[0])};b.jsonp!==!1&&(j=j.replace(bS,l),b.url===j&&(f&&(k=k.replace(bS,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},e.then(m,m),b.converters["script json"]=function(){g||d.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),d.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){d.globalEval(a);return a}}}),d.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),d.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var bT=d.now(),bU,bV;d.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&bX()||bY()}:bX,bV=d.ajaxSettings.xhr(),d.support.ajax=!!bV,d.support.cors=bV&&"withCredentials"in bV,bV=b,d.support.ajax&&d.ajaxTransport(function(a){if(!a.crossDomain||d.support.cors){var c;return{send:function(e,f){var g=a.xhr(),h,i;a.username?g.open(a.type,a.url,a.async,a.username,a.password):g.open(a.type,a.url,a.async);if(a.xhrFields)for(i in a.xhrFields)g[i]=a.xhrFields[i];a.mimeType&&g.overrideMimeType&&g.overrideMimeType(a.mimeType),(!a.crossDomain||a.hasContent)&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(i in e)g.setRequestHeader(i,e[i])}catch(j){}g.send(a.hasContent&&a.data||null),c=function(e,i){var j,k,l,m,n;try{if(c&&(i||g.readyState===4)){c=b,h&&(g.onreadystatechange=d.noop,delete bU[h]);if(i)g.readyState!==4&&g.abort();else{j=g.status,l=g.getAllResponseHeaders(),m={},n=g.responseXML,n&&n.documentElement&&(m.xml=n),m.text=g.responseText;try{k=g.statusText}catch(o){k=""}j||!a.isLocal||a.crossDomain?j===1223&&(j=204):j=m.text?200:404}}}catch(p){i||f(-1,p)}m&&f(j,k,m,l)},a.async&&g.readyState!==4?(bU||(bU={},bW()),h=bT++,g.onreadystatechange=bU[h]=c):c()},abort:function(){c&&c(0,1)}}}});var bZ={},b$=/^(?:toggle|show|hide)$/,b_=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,ca,cb=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];d.fn.extend({show:function(a,b,c){var e,f;if(a||a===0)return this.animate(cc("show",3),a,b,c);for(var g=0,h=this.length;g=0;a--)c[a].elem===this&&(b&&c[a](!0),c.splice(a,1))}),b||this.dequeue();return this}}),d.each({slideDown:cc("show",1),slideUp:cc("hide",1),slideToggle:cc("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){d.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),d.extend({speed:function(a,b,c){var e=a&&typeof a==="object"?d.extend({},a):{complete:c||!c&&b||d.isFunction(a)&&a,duration:a,easing:c&&b||b&&!d.isFunction(b)&&b};e.duration=d.fx.off?0:typeof e.duration==="number"?e.duration:e.duration in d.fx.speeds?d.fx.speeds[e.duration]:d.fx.speeds._default,e.old=e.complete,e.complete=function(){e.queue!==!1&&d(this).dequeue(),d.isFunction(e.old)&&e.old.call(this)};return e},easing:{linear:function(a,b,c,d){return c+d*a},swing:function(a,b,c,d){return(-Math.cos(a*Math.PI)/2+.5)*d+c}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig||(b.orig={})}}),d.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(d.fx.step[this.prop]||d.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a,b=d.css(this.elem,this.prop);return isNaN(a=parseFloat(b))?!b||b==="auto"?0:b:a},custom:function(a,b,c){function g(a){return e.step(a)}var e=this,f=d.fx;this.startTime=d.now(),this.start=a,this.end=b,this.unit=c||this.unit||(d.cssNumber[this.prop]?"":"px"),this.now=this.start,this.pos=this.state=0,g.elem=this.elem,g()&&d.timers.push(g)&&!ca&&(ca=setInterval(f.tick,f.interval))},show:function(){this.options.orig[this.prop]=d.style(this.elem,this.prop),this.options.show=!0,this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur()),d(this.elem).show()},hide:function(){this.options.orig[this.prop]=d.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b=d.now(),c=!0;if(a||b>=this.options.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),this.options.curAnim[this.prop]=!0;for(var e in this.options.curAnim)this.options.curAnim[e]!==!0&&(c=!1);if(c){if(this.options.overflow!=null&&!d.support.shrinkWrapBlocks){var f=this.elem,g=this.options;d.each(["","X","Y"],function(a,b){f.style["overflow"+b]=g.overflow[a]})}this.options.hide&&d(this.elem).hide();if(this.options.hide||this.options.show)for(var h in this.options.curAnim)d.style(this.elem,h,this.options.orig[h]);this.options.complete.call(this.elem)}return!1}var i=b-this.startTime;this.state=i/this.options.duration;var j=this.options.specialEasing&&this.options.specialEasing[this.prop],k=this.options.easing||(d.easing.swing?"swing":"linear");this.pos=d.easing[j||k](this.state,i,0,1,this.options.duration),this.now=this.start+(this.end-this.start)*this.pos,this.update();return!0}},d.extend(d.fx,{tick:function(){var a=d.timers;for(var b=0;b
";d.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"}),b.innerHTML=j,a.insertBefore(b,a.firstChild),e=b.firstChild,f=e.firstChild,h=e.nextSibling.firstChild.firstChild,this.doesNotAddBorder=f.offsetTop!==5,this.doesAddBorderForTableAndCells=h.offsetTop===5,f.style.position="fixed",f.style.top="20px",this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15,f.style.position=f.style.top="",e.style.overflow="hidden",e.style.position="relative",this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5,this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==i,a.removeChild(b),a=b=e=f=g=h=null,d.offset.initialize=d.noop},bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;d.offset.initialize(),d.offset.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(d.css(a,"marginTop"))||0,c+=parseFloat(d.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var e=d.css(a,"position");e==="static"&&(a.style.position="relative");var f=d(a),g=f.offset(),h=d.css(a,"top"),i=d.css(a,"left"),j=e==="absolute"&&d.inArray("auto",[h,i])>-1,k={},l={},m,n;j&&(l=f.position()),m=j?l.top:parseInt(h,10)||0,n=j?l.left:parseInt(i,10)||0,d.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):f.css(k)}},d.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),e=cf.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(d.css(a,"marginTop"))||0,c.left-=parseFloat(d.css(a,"marginLeft"))||0,e.top+=parseFloat(d.css(b[0],"borderTopWidth"))||0,e.left+=parseFloat(d.css(b[0],"borderLeftWidth"))||0;return{top:c.top-e.top,left:c.left-e.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&(!cf.test(a.nodeName)&&d.css(a,"position")==="static"))a=a.offsetParent;return a})}}),d.each(["Left","Top"],function(a,c){var e="scroll"+c;d.fn[e]=function(c){var f=this[0],g;if(!f)return null;if(c!==b)return this.each(function(){g=cg(this),g?g.scrollTo(a?d(g).scrollLeft():c,a?c:d(g).scrollTop()):this[e]=c});g=cg(f);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:d.support.boxModel&&g.document.documentElement[e]||g.document.body[e]:f[e]}}),d.each(["Height","Width"],function(a,c){var e=c.toLowerCase();d.fn["inner"+c]=function(){return this[0]?parseFloat(d.css(this[0],e,"padding")):null},d.fn["outer"+c]=function(a){return this[0]?parseFloat(d.css(this[0],e,a?"margin":"border")):null},d.fn[e]=function(a){var f=this[0];if(!f)return a==null?null:this;if(d.isFunction(a))return this.each(function(b){var c=d(this);c[e](a.call(this,b,c[e]()))});if(d.isWindow(f)){var g=f.document.documentElement["client"+c];return f.document.compatMode==="CSS1Compat"&&g||f.document.body["client"+c]||g}if(f.nodeType===9)return Math.max(f.documentElement["client"+c],f.body["scroll"+c],f.documentElement["scroll"+c],f.body["offset"+c],f.documentElement["offset"+c]);if(a===b){var h=d.css(f,e),i=parseFloat(h);return d.isNaN(i)?h:i}return this.css(e,typeof a==="string"?a:a+"px")}}),a.jQuery=a.$=d})(window); \ No newline at end of file diff --git a/webapp/src/main/webapp/js/jquery_plugins/jcrop/jquery.Jcrop.css b/webapp/src/main/webapp/js/jquery_plugins/jcrop/jquery.Jcrop.css index 2c5934e25..31636fee2 100644 --- a/webapp/src/main/webapp/js/jquery_plugins/jcrop/jquery.Jcrop.css +++ b/webapp/src/main/webapp/js/jquery_plugins/jcrop/jquery.Jcrop.css @@ -1,40 +1,165 @@ -/* Fixes issue here http://code.google.com/p/jcrop/issues/detail?id=1 */ -.jcrop-holder { text-align: left; } +/* jquery.Jcrop.css v0.9.12 - MIT License */ +/* + The outer-most container in a typical Jcrop instance + If you are having difficulty with formatting related to styles + on a parent element, place any fixes here or in a like selector -.jcrop-vline, .jcrop-hline -{ + You can also style this element if you want to add a border, etc + A better method for styling can be seen below with .jcrop-light + (Add a class to the holder and style elements for that extended class) +*/ +.jcrop-holder { + direction: ltr; + text-align: left; +} +/* Selection Border */ +.jcrop-vline, +.jcrop-hline { + background: #ffffff url("Jcrop.gif"); font-size: 0; position: absolute; - background: white url('Jcrop.gif') top left repeat; } -.jcrop-vline { height: 100%; width: 1px !important; } -.jcrop-hline { width: 100%; height: 1px !important; } +.jcrop-vline { + height: 100%; + width: 1px !important; +} +.jcrop-vline.right { + right: 0; +} +.jcrop-hline { + height: 1px !important; + width: 100%; +} +.jcrop-hline.bottom { + bottom: 0; +} +/* Invisible click targets */ +.jcrop-tracker { + height: 100%; + width: 100%; + /* "turn off" link highlight */ + -webkit-tap-highlight-color: transparent; + /* disable callout, image save panel */ + -webkit-touch-callout: none; + /* disable cut copy paste */ + -webkit-user-select: none; +} +/* Selection Handles */ .jcrop-handle { + background-color: #333333; + border: 1px #eeeeee solid; + width: 7px; + height: 7px; font-size: 1px; - width: 7px !important; - height: 7px !important; - border: 1px #eee solid; - background-color: #333; - *width: 9px; - *height: 9px; } - -.jcrop-tracker { width: 100%; height: 100%; } - -.custom .jcrop-vline, -.custom .jcrop-hline -{ - background: yellow; +.jcrop-handle.ord-n { + left: 50%; + margin-left: -4px; + margin-top: -4px; + top: 0; } -.custom .jcrop-handle -{ - border-color: black; - background-color: #C7BB00; +.jcrop-handle.ord-s { + bottom: 0; + left: 50%; + margin-bottom: -4px; + margin-left: -4px; +} +.jcrop-handle.ord-e { + margin-right: -4px; + margin-top: -4px; + right: 0; + top: 50%; +} +.jcrop-handle.ord-w { + left: 0; + margin-left: -4px; + margin-top: -4px; + top: 50%; +} +.jcrop-handle.ord-nw { + left: 0; + margin-left: -4px; + margin-top: -4px; + top: 0; +} +.jcrop-handle.ord-ne { + margin-right: -4px; + margin-top: -4px; + right: 0; + top: 0; +} +.jcrop-handle.ord-se { + bottom: 0; + margin-bottom: -4px; + margin-right: -4px; + right: 0; +} +.jcrop-handle.ord-sw { + bottom: 0; + left: 0; + margin-bottom: -4px; + margin-left: -4px; +} +/* Dragbars */ +.jcrop-dragbar.ord-n, +.jcrop-dragbar.ord-s { + height: 7px; + width: 100%; +} +.jcrop-dragbar.ord-e, +.jcrop-dragbar.ord-w { + height: 100%; + width: 7px; +} +.jcrop-dragbar.ord-n { + margin-top: -4px; +} +.jcrop-dragbar.ord-s { + bottom: 0; + margin-bottom: -4px; +} +.jcrop-dragbar.ord-e { + margin-right: -4px; + right: 0; +} +.jcrop-dragbar.ord-w { + margin-left: -4px; +} +/* The "jcrop-light" class/extension */ +.jcrop-light .jcrop-vline, +.jcrop-light .jcrop-hline { + background: #ffffff; + filter: alpha(opacity=70) !important; + opacity: .70!important; +} +.jcrop-light .jcrop-handle { -moz-border-radius: 3px; -webkit-border-radius: 3px; + background-color: #000000; + border-color: #ffffff; + border-radius: 3px; } - - - - - +/* The "jcrop-dark" class/extension */ +.jcrop-dark .jcrop-vline, +.jcrop-dark .jcrop-hline { + background: #000000; + filter: alpha(opacity=70) !important; + opacity: 0.7 !important; +} +.jcrop-dark .jcrop-handle { + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + background-color: #ffffff; + border-color: #000000; + border-radius: 3px; +} +/* Simple macro to turn off the antlines */ +.solid-line .jcrop-vline, +.solid-line .jcrop-hline { + background: #ffffff; +} +/* Fix for twitter bootstrap et al. */ +.jcrop-holder img, +img.jcrop-preview { + max-width: none; +} \ No newline at end of file diff --git a/webapp/src/main/webapp/js/jquery_plugins/jcrop/jquery.Jcrop.js b/webapp/src/main/webapp/js/jquery_plugins/jcrop/jquery.Jcrop.js index ad261f97a..7eaaaba98 100644 --- a/webapp/src/main/webapp/js/jquery_plugins/jcrop/jquery.Jcrop.js +++ b/webapp/src/main/webapp/js/jquery_plugins/jcrop/jquery.Jcrop.js @@ -1,8 +1,9 @@ /** - * jquery.Jcrop.js v0.9.8 - * jQuery Image Cropping Plugin - * @author Kelly Hallman - * Copyright (c) 2008-2009 Kelly Hallman - released under MIT License {{{ + * jquery.Jcrop.js v0.9.12 + * jQuery Image Cropping Plugin - released under MIT License + * Author: Kelly Hallman + * http://github.com/tapmodo/Jcrop + * Copyright (c) 2008-2013 Tapmodo Interactive LLC {{{ * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -12,10 +13,10 @@ * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: - + * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. - + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND @@ -24,1174 +25,1670 @@ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. - + * * }}} */ -(function($) { - -$.Jcrop = function(obj,opt) -{ - // Initialization {{{ - - // Sanitize some options {{{ - var obj = obj, opt = opt; - - if (typeof(obj) !== 'object') obj = $(obj)[0]; - if (typeof(opt) !== 'object') opt = { }; - - // Some on-the-fly fixes for MSIE...sigh - if (!('trackDocument' in opt)) - { - opt.trackDocument = $.browser.msie ? false : true; - if ($.browser.msie && $.browser.version.split('.')[0] == '8') - opt.trackDocument = true; - } - - if (!('keySupport' in opt)) - opt.keySupport = $.browser.msie ? false : true; - - // }}} - // Extend the default options {{{ - var defaults = { - - // Basic Settings - trackDocument: false, - baseClass: 'jcrop', - addClass: null, - - // Styling Options - bgColor: 'black', - bgOpacity: .6, - borderOpacity: .4, - handleOpacity: .5, - - handlePad: 5, - handleSize: 9, - handleOffset: 5, - edgeMargin: 14, - - aspectRatio: 0, - keySupport: true, - cornerHandles: true, - sideHandles: true, - drawBorders: true, - dragEdges: true, - - boxWidth: 0, - boxHeight: 0, - - boundary: 8, - animationDelay: 20, - swingSpeed: 3, - - allowSelect: true, - allowMove: true, - allowResize: true, - - minSelect: [ 0, 0 ], - maxSize: [ 0, 0 ], - minSize: [ 0, 0 ], - - // Callbacks / Event Handlers - onChange: function() { }, - onSelect: function() { } - - }; - var options = defaults; - setOptions(opt); - - // }}} - // Initialize some jQuery objects {{{ - - var $origimg = $(obj); - var $img = $origimg.clone().removeAttr('id').css({ position: 'absolute' }); - - $img.width($origimg.width()); - $img.height($origimg.height()); - $origimg.after($img).hide(); - - presize($img,options.boxWidth,options.boxHeight); - - var boundx = $img.width(), - boundy = $img.height(), - - $div = $('
') - .width(boundx).height(boundy) - .addClass(cssClass('holder')) - .css({ - position: 'relative', - backgroundColor: options.bgColor - }).insertAfter($origimg).append($img); - ; - - if (options.addClass) $div.addClass(options.addClass); - //$img.wrap($div); - - var $img2 = $('')/*{{{*/ - .attr('src',$img.attr('src')) - .css('position','absolute') - .width(boundx).height(boundy) - ;/*}}}*/ - var $img_holder = $('
')/*{{{*/ - .width(pct(100)).height(pct(100)) - .css({ - zIndex: 310, - position: 'absolute', - overflow: 'hidden' - }) - .append($img2) - ;/*}}}*/ - var $hdl_holder = $('
')/*{{{*/ - .width(pct(100)).height(pct(100)) - .css('zIndex',320); - /*}}}*/ - var $sel = $('
')/*{{{*/ - .css({ - position: 'absolute', - zIndex: 300 - }) - .insertBefore($img) - .append($img_holder,$hdl_holder) - ;/*}}}*/ - - var bound = options.boundary; - var $trk = newTracker().width(boundx+(bound*2)).height(boundy+(bound*2)) - .css({ position: 'absolute', top: px(-bound), left: px(-bound), zIndex: 290 }) - .mousedown(newSelection); - - /* }}} */ - // Set more variables {{{ - - var xlimit, ylimit, xmin, ymin; - var xscale, yscale, enabled = true; - var docOffset = getPos($img), - // Internal states - btndown, lastcurs, dimmed, animating, - shift_down; - - // }}} - - - // }}} - // Internal Modules {{{ - - var Coords = function()/*{{{*/ - { - var x1 = 0, y1 = 0, x2 = 0, y2 = 0, ox, oy; - - function setPressed(pos)/*{{{*/ - { - var pos = rebound(pos); - x2 = x1 = pos[0]; - y2 = y1 = pos[1]; - }; - /*}}}*/ - function setCurrent(pos)/*{{{*/ - { - var pos = rebound(pos); - ox = pos[0] - x2; - oy = pos[1] - y2; - x2 = pos[0]; - y2 = pos[1]; - }; - /*}}}*/ - function getOffset()/*{{{*/ - { - return [ ox, oy ]; - }; - /*}}}*/ - function moveOffset(offset)/*{{{*/ - { - var ox = offset[0], oy = offset[1]; - - if (0 > x1 + ox) ox -= ox + x1; - if (0 > y1 + oy) oy -= oy + y1; - - if (boundy < y2 + oy) oy += boundy - (y2 + oy); - if (boundx < x2 + ox) ox += boundx - (x2 + ox); - - x1 += ox; - x2 += ox; - y1 += oy; - y2 += oy; - }; - /*}}}*/ - function getCorner(ord)/*{{{*/ - { - var c = getFixed(); - switch(ord) - { - case 'ne': return [ c.x2, c.y ]; - case 'nw': return [ c.x, c.y ]; - case 'se': return [ c.x2, c.y2 ]; - case 'sw': return [ c.x, c.y2 ]; - } - }; - /*}}}*/ - function getFixed()/*{{{*/ - { - if (!options.aspectRatio) return getRect(); - // This function could use some optimization I think... - var aspect = options.aspectRatio, - min_x = options.minSize[0]/xscale, - min_y = options.minSize[1]/yscale, - max_x = options.maxSize[0]/xscale, - max_y = options.maxSize[1]/yscale, - rw = x2 - x1, - rh = y2 - y1, - rwa = Math.abs(rw), - rha = Math.abs(rh), - real_ratio = rwa / rha, - xx, yy - ; - if (max_x == 0) { max_x = boundx * 10 } - if (max_y == 0) { max_y = boundy * 10 } - if (real_ratio < aspect) - { - yy = y2; - w = rha * aspect; - xx = rw < 0 ? x1 - w : w + x1; - - if (xx < 0) - { - xx = 0; - h = Math.abs((xx - x1) / aspect); - yy = rh < 0 ? y1 - h: h + y1; - } - else if (xx > boundx) - { - xx = boundx; - h = Math.abs((xx - x1) / aspect); - yy = rh < 0 ? y1 - h : h + y1; - } - } - else - { - xx = x2; - h = rwa / aspect; - yy = rh < 0 ? y1 - h : y1 + h; - if (yy < 0) - { - yy = 0; - w = Math.abs((yy - y1) * aspect); - xx = rw < 0 ? x1 - w : w + x1; - } - else if (yy > boundy) - { - yy = boundy; - w = Math.abs(yy - y1) * aspect; - xx = rw < 0 ? x1 - w : w + x1; - } - } - - // Magic %-) - if(xx > x1) { // right side - if(xx - x1 < min_x) { - xx = x1 + min_x; - } else if (xx - x1 > max_x) { - xx = x1 + max_x; - } - if(yy > y1) { - yy = y1 + (xx - x1)/aspect; - } else { - yy = y1 - (xx - x1)/aspect; - } - } else if (xx < x1) { // left side - if(x1 - xx < min_x) { - xx = x1 - min_x - } else if (x1 - xx > max_x) { - xx = x1 - max_x; - } - if(yy > y1) { - yy = y1 + (x1 - xx)/aspect; - } else { - yy = y1 - (x1 - xx)/aspect; - } - } - - if(xx < 0) { - x1 -= xx; - xx = 0; - } else if (xx > boundx) { - x1 -= xx - boundx; - xx = boundx; - } - - if(yy < 0) { - y1 -= yy; - yy = 0; - } else if (yy > boundy) { - y1 -= yy - boundy; - yy = boundy; - } - - return last = makeObj(flipCoords(x1,y1,xx,yy)); - }; - /*}}}*/ - function rebound(p)/*{{{*/ - { - if (p[0] < 0) p[0] = 0; - if (p[1] < 0) p[1] = 0; - - if (p[0] > boundx) p[0] = boundx; - if (p[1] > boundy) p[1] = boundy; - - return [ p[0], p[1] ]; - }; - /*}}}*/ - function flipCoords(x1,y1,x2,y2)/*{{{*/ - { - var xa = x1, xb = x2, ya = y1, yb = y2; - if (x2 < x1) - { - xa = x2; - xb = x1; - } - if (y2 < y1) - { - ya = y2; - yb = y1; - } - return [ Math.round(xa), Math.round(ya), Math.round(xb), Math.round(yb) ]; - }; - /*}}}*/ - function getRect()/*{{{*/ - { - var xsize = x2 - x1; - var ysize = y2 - y1; - - if (xlimit && (Math.abs(xsize) > xlimit)) - x2 = (xsize > 0) ? (x1 + xlimit) : (x1 - xlimit); - if (ylimit && (Math.abs(ysize) > ylimit)) - y2 = (ysize > 0) ? (y1 + ylimit) : (y1 - ylimit); - - if (ymin && (Math.abs(ysize) < ymin)) - y2 = (ysize > 0) ? (y1 + ymin) : (y1 - ymin); - if (xmin && (Math.abs(xsize) < xmin)) - x2 = (xsize > 0) ? (x1 + xmin) : (x1 - xmin); - - if (x1 < 0) { x2 -= x1; x1 -= x1; } - if (y1 < 0) { y2 -= y1; y1 -= y1; } - if (x2 < 0) { x1 -= x2; x2 -= x2; } - if (y2 < 0) { y1 -= y2; y2 -= y2; } - if (x2 > boundx) { var delta = x2 - boundx; x1 -= delta; x2 -= delta; } - if (y2 > boundy) { var delta = y2 - boundy; y1 -= delta; y2 -= delta; } - if (x1 > boundx) { var delta = x1 - boundy; y2 -= delta; y1 -= delta; } - if (y1 > boundy) { var delta = y1 - boundy; y2 -= delta; y1 -= delta; } - - return makeObj(flipCoords(x1,y1,x2,y2)); - }; - /*}}}*/ - function makeObj(a)/*{{{*/ - { - return { x: a[0], y: a[1], x2: a[2], y2: a[3], - w: a[2] - a[0], h: a[3] - a[1] }; - }; - /*}}}*/ - - return { - flipCoords: flipCoords, - setPressed: setPressed, - setCurrent: setCurrent, - getOffset: getOffset, - moveOffset: moveOffset, - getCorner: getCorner, - getFixed: getFixed - }; - }(); - - /*}}}*/ - var Selection = function()/*{{{*/ - { - var start, end, dragmode, awake, hdep = 370; - var borders = { }; - var handle = { }; - var seehandles = false; - var hhs = options.handleOffset; - - /* Insert draggable elements {{{*/ - - // Insert border divs for outline - if (options.drawBorders) { - borders = { - top: insertBorder('hline') - .css('top',$.browser.msie?px(-1):px(0)), - bottom: insertBorder('hline'), - left: insertBorder('vline'), - right: insertBorder('vline') - }; - } - - // Insert handles on edges - if (options.dragEdges) { - handle.t = insertDragbar('n'); - handle.b = insertDragbar('s'); - handle.r = insertDragbar('e'); - handle.l = insertDragbar('w'); - } - - // Insert side handles - options.sideHandles && - createHandles(['n','s','e','w']); - - // Insert corner handles - options.cornerHandles && - createHandles(['sw','nw','ne','se']); - - /*}}}*/ - // Private Methods - function insertBorder(type)/*{{{*/ - { - var jq = $('
') - .css({position: 'absolute', opacity: options.borderOpacity }) - .addClass(cssClass(type)); - $img_holder.append(jq); - return jq; - }; - /*}}}*/ - function dragDiv(ord,zi)/*{{{*/ - { - var jq = $('
') - .mousedown(createDragger(ord)) - .css({ - cursor: ord+'-resize', - position: 'absolute', - zIndex: zi - }) - ; - $hdl_holder.append(jq); - return jq; - }; - /*}}}*/ - function insertHandle(ord)/*{{{*/ - { - return dragDiv(ord,hdep++) - .css({ top: px(-hhs+1), left: px(-hhs+1), opacity: options.handleOpacity }) - .addClass(cssClass('handle')); - }; - /*}}}*/ - function insertDragbar(ord)/*{{{*/ - { - var s = options.handleSize, - o = hhs, - h = s, w = s, - t = o, l = o; - - switch(ord) - { - case 'n': case 's': w = pct(100); break; - case 'e': case 'w': h = pct(100); break; - } - - return dragDiv(ord,hdep++).width(w).height(h) - .css({ top: px(-t+1), left: px(-l+1)}); - }; - /*}}}*/ - function createHandles(li)/*{{{*/ - { - for(i in li) handle[li[i]] = insertHandle(li[i]); - }; - /*}}}*/ - function moveHandles(c)/*{{{*/ - { - var midvert = Math.round((c.h / 2) - hhs), - midhoriz = Math.round((c.w / 2) - hhs), - north = west = -hhs+1, - east = c.w - hhs, - south = c.h - hhs, - x, y; - - 'e' in handle && - handle.e.css({ top: px(midvert), left: px(east) }) && - handle.w.css({ top: px(midvert) }) && - handle.s.css({ top: px(south), left: px(midhoriz) }) && - handle.n.css({ left: px(midhoriz) }); - - 'ne' in handle && - handle.ne.css({ left: px(east) }) && - handle.se.css({ top: px(south), left: px(east) }) && - handle.sw.css({ top: px(south) }); - - 'b' in handle && - handle.b.css({ top: px(south) }) && - handle.r.css({ left: px(east) }); - }; - /*}}}*/ - function moveto(x,y)/*{{{*/ - { - $img2.css({ top: px(-y), left: px(-x) }); - $sel.css({ top: px(y), left: px(x) }); - }; - /*}}}*/ - function resize(w,h)/*{{{*/ - { - $sel.width(w).height(h); - }; - /*}}}*/ - function refresh()/*{{{*/ - { - var c = Coords.getFixed(); - - Coords.setPressed([c.x,c.y]); - Coords.setCurrent([c.x2,c.y2]); - - updateVisible(); - }; - /*}}}*/ - - // Internal Methods - function updateVisible()/*{{{*/ - { if (awake) return update(); }; - /*}}}*/ - function update()/*{{{*/ - { - var c = Coords.getFixed(); - - resize(c.w,c.h); - moveto(c.x,c.y); - - options.drawBorders && - borders['right'].css({ left: px(c.w-1) }) && - borders['bottom'].css({ top: px(c.h-1) }); - - seehandles && moveHandles(c); - awake || show(); - - options.onChange(unscale(c)); - }; - /*}}}*/ - function show()/*{{{*/ - { - $sel.show(); - $img.css('opacity',options.bgOpacity); - awake = true; - }; - /*}}}*/ - function release()/*{{{*/ - { - disableHandles(); - $sel.hide(); - $img.css('opacity',1); - awake = false; - }; - /*}}}*/ - function showHandles()//{{{ - { - if (seehandles) - { - moveHandles(Coords.getFixed()); - $hdl_holder.show(); - } - }; - //}}} - function enableHandles()/*{{{*/ - { - seehandles = true; - if (options.allowResize) - { - moveHandles(Coords.getFixed()); - $hdl_holder.show(); - return true; - } - }; - /*}}}*/ - function disableHandles()/*{{{*/ - { - seehandles = false; - $hdl_holder.hide(); - }; - /*}}}*/ - function animMode(v)/*{{{*/ - { - (animating = v) ? disableHandles(): enableHandles(); - }; - /*}}}*/ - function done()/*{{{*/ - { - animMode(false); - refresh(); - }; - /*}}}*/ - - var $track = newTracker().mousedown(createDragger('move')) - .css({ cursor: 'move', position: 'absolute', zIndex: 360 }) - - $img_holder.append($track); - disableHandles(); - - return { - updateVisible: updateVisible, - update: update, - release: release, - refresh: refresh, - setCursor: function (cursor) { $track.css('cursor',cursor); }, - enableHandles: enableHandles, - enableOnly: function() { seehandles = true; }, - showHandles: showHandles, - disableHandles: disableHandles, - animMode: animMode, - done: done - }; - }(); - /*}}}*/ - var Tracker = function()/*{{{*/ - { - var onMove = function() { }, - onDone = function() { }, - trackDoc = options.trackDocument; - - if (!trackDoc) - { - $trk - .mousemove(trackMove) - .mouseup(trackUp) - .mouseout(trackUp) - ; - } - - function toFront()/*{{{*/ - { - $trk.css({zIndex:450}); - if (trackDoc) - { - $(document) - .mousemove(trackMove) - .mouseup(trackUp) - ; - } - } - /*}}}*/ - function toBack()/*{{{*/ - { - $trk.css({zIndex:290}); - if (trackDoc) - { - $(document) - .unbind('mousemove',trackMove) - .unbind('mouseup',trackUp) - ; - } - } - /*}}}*/ - function trackMove(e)/*{{{*/ - { - onMove(mouseAbs(e)); - }; - /*}}}*/ - function trackUp(e)/*{{{*/ - { - e.preventDefault(); - e.stopPropagation(); - - if (btndown) - { - btndown = false; - - onDone(mouseAbs(e)); - options.onSelect(unscale(Coords.getFixed())); - toBack(); - onMove = function() { }; - onDone = function() { }; - } - - return false; - }; - /*}}}*/ - - function activateHandlers(move,done)/* {{{ */ - { - btndown = true; - onMove = move; - onDone = done; - toFront(); - return false; - }; +(function ($) { + + $.Jcrop = function (obj, opt) { + var options = $.extend({}, $.Jcrop.defaults), + docOffset, + _ua = navigator.userAgent.toLowerCase(), + is_msie = /msie/.test(_ua), + ie6mode = /msie [1-6]\./.test(_ua); + + // Internal Methods {{{ + function px(n) { + return Math.round(n) + 'px'; + } + function cssClass(cl) { + return options.baseClass + '-' + cl; + } + function supportsColorFade() { + return $.fx.step.hasOwnProperty('backgroundColor'); + } + function getPos(obj) //{{{ + { + var pos = $(obj).offset(); + return [pos.left, pos.top]; + } + //}}} + function mouseAbs(e) //{{{ + { + return [(e.pageX - docOffset[0]), (e.pageY - docOffset[1])]; + } + //}}} + function setOptions(opt) //{{{ + { + if (typeof(opt) !== 'object') opt = {}; + options = $.extend(options, opt); + + $.each(['onChange','onSelect','onRelease','onDblClick'],function(i,e) { + if (typeof(options[e]) !== 'function') options[e] = function () {}; + }); + } + //}}} + function startDragMode(mode, pos, touch) //{{{ + { + docOffset = getPos($img); + Tracker.setCursor(mode === 'move' ? mode : mode + '-resize'); + + if (mode === 'move') { + return Tracker.activateHandlers(createMover(pos), doneSelect, touch); + } + + var fc = Coords.getFixed(); + var opp = oppLockCorner(mode); + var opc = Coords.getCorner(oppLockCorner(opp)); + + Coords.setPressed(Coords.getCorner(opp)); + Coords.setCurrent(opc); + + Tracker.activateHandlers(dragmodeHandler(mode, fc), doneSelect, touch); + } + //}}} + function dragmodeHandler(mode, f) //{{{ + { + return function (pos) { + if (!options.aspectRatio) { + switch (mode) { + case 'e': + pos[1] = f.y2; + break; + case 'w': + pos[1] = f.y2; + break; + case 'n': + pos[0] = f.x2; + break; + case 's': + pos[0] = f.x2; + break; + } + } else { + switch (mode) { + case 'e': + pos[1] = f.y + 1; + break; + case 'w': + pos[1] = f.y + 1; + break; + case 'n': + pos[0] = f.x + 1; + break; + case 's': + pos[0] = f.x + 1; + break; + } + } + Coords.setCurrent(pos); + Selection.update(); + }; + } + //}}} + function createMover(pos) //{{{ + { + var lloc = pos; + KeyManager.watchKeys(); + + return function (pos) { + Coords.moveOffset([pos[0] - lloc[0], pos[1] - lloc[1]]); + lloc = pos; + + Selection.update(); + }; + } + //}}} + function oppLockCorner(ord) //{{{ + { + switch (ord) { + case 'n': + return 'sw'; + case 's': + return 'nw'; + case 'e': + return 'nw'; + case 'w': + return 'ne'; + case 'ne': + return 'sw'; + case 'nw': + return 'se'; + case 'se': + return 'nw'; + case 'sw': + return 'ne'; + } + } + //}}} + function createDragger(ord) //{{{ + { + return function (e) { + if (options.disabled) { + return false; + } + if ((ord === 'move') && !options.allowMove) { + return false; + } + + // Fix position of crop area when dragged the very first time. + // Necessary when crop image is in a hidden element when page is loaded. + docOffset = getPos($img); + + btndown = true; + startDragMode(ord, mouseAbs(e)); + e.stopPropagation(); + e.preventDefault(); + return false; + }; + } + //}}} + function presize($obj, w, h) //{{{ + { + var nw = $obj.width(), + nh = $obj.height(); + if ((nw > w) && w > 0) { + nw = w; + nh = (w / $obj.width()) * $obj.height(); + } + if ((nh > h) && h > 0) { + nh = h; + nw = (h / $obj.height()) * $obj.width(); + } + xscale = $obj.width() / nw; + yscale = $obj.height() / nh; + $obj.width(nw).height(nh); + } + //}}} + function unscale(c) //{{{ + { + return { + x: c.x * xscale, + y: c.y * yscale, + x2: c.x2 * xscale, + y2: c.y2 * yscale, + w: c.w * xscale, + h: c.h * yscale + }; + } + //}}} + function doneSelect(pos) //{{{ + { + var c = Coords.getFixed(); + if ((c.w > options.minSelect[0]) && (c.h > options.minSelect[1])) { + Selection.enableHandles(); + Selection.done(); + } else { + Selection.release(); + } + Tracker.setCursor(options.allowSelect ? 'crosshair' : 'default'); + } + //}}} + function newSelection(e) //{{{ + { + if (options.disabled) { + return false; + } + if (!options.allowSelect) { + return false; + } + btndown = true; + docOffset = getPos($img); + Selection.disableHandles(); + Tracker.setCursor('crosshair'); + var pos = mouseAbs(e); + Coords.setPressed(pos); + Selection.update(); + Tracker.activateHandlers(selectDrag, doneSelect, e.type.substring(0,5)==='touch'); + KeyManager.watchKeys(); + + e.stopPropagation(); + e.preventDefault(); + return false; + } + //}}} + function selectDrag(pos) //{{{ + { + Coords.setCurrent(pos); + Selection.update(); + } + //}}} + function newTracker() //{{{ + { + var trk = $('
').addClass(cssClass('tracker')); + if (is_msie) { + trk.css({ + opacity: 0, + backgroundColor: 'white' + }); + } + return trk; + } + //}}} + + // }}} + // Initialization {{{ + // Sanitize some options {{{ + if (typeof(obj) !== 'object') { + obj = $(obj)[0]; + } + if (typeof(opt) !== 'object') { + opt = {}; + } + // }}} + setOptions(opt); + // Initialize some jQuery objects {{{ + // The values are SET on the image(s) for the interface + // If the original image has any of these set, they will be reset + // However, if you destroy() the Jcrop instance the original image's + // character in the DOM will be as you left it. + var img_css = { + border: 'none', + visibility: 'visible', + margin: 0, + padding: 0, + position: 'absolute', + top: 0, + left: 0 + }; + + var $origimg = $(obj), + img_mode = true; + + if (obj.tagName == 'IMG') { + // Fix size of crop image. + // Necessary when crop image is within a hidden element when page is loaded. + if ($origimg[0].width != 0 && $origimg[0].height != 0) { + // Obtain dimensions from contained img element. + $origimg.width($origimg[0].width); + $origimg.height($origimg[0].height); + } else { + // Obtain dimensions from temporary image in case the original is not loaded yet (e.g. IE 7.0). + var tempImage = new Image(); + tempImage.src = $origimg[0].src; + $origimg.width(tempImage.width); + $origimg.height(tempImage.height); + } + + var $img = $origimg.clone().removeAttr('id').css(img_css).show(); + + $img.width($origimg.width()); + $img.height($origimg.height()); + $origimg.after($img).hide(); + + } else { + $img = $origimg.css(img_css).show(); + img_mode = false; + if (options.shade === null) { options.shade = true; } + } + + presize($img, options.boxWidth, options.boxHeight); + + var boundx = $img.width(), + boundy = $img.height(), + + + $div = $('
').width(boundx).height(boundy).addClass(cssClass('holder')).css({ + position: 'relative', + backgroundColor: options.bgColor + }).insertAfter($origimg).append($img); + + if (options.addClass) { + $div.addClass(options.addClass); + } + + var $img2 = $('
'), + + $img_holder = $('
') + .width('100%').height('100%').css({ + zIndex: 310, + position: 'absolute', + overflow: 'hidden' + }), + + $hdl_holder = $('
') + .width('100%').height('100%').css('zIndex', 320), + + $sel = $('
') + .css({ + position: 'absolute', + zIndex: 600 + }).dblclick(function(){ + var c = Coords.getFixed(); + options.onDblClick.call(api,c); + }).insertBefore($img).append($img_holder, $hdl_holder); + + if (img_mode) { + + $img2 = $('') + .attr('src', $img.attr('src')).css(img_css).width(boundx).height(boundy), + + $img_holder.append($img2); + + } + + if (ie6mode) { + $sel.css({ + overflowY: 'hidden' + }); + } + + var bound = options.boundary; + var $trk = newTracker().width(boundx + (bound * 2)).height(boundy + (bound * 2)).css({ + position: 'absolute', + top: px(-bound), + left: px(-bound), + zIndex: 290 + }).mousedown(newSelection); + /* }}} */ + // Set more variables {{{ + var bgcolor = options.bgColor, + bgopacity = options.bgOpacity, + xlimit, ylimit, xmin, ymin, xscale, yscale, enabled = true, + btndown, animating, shift_down; - function setCursor(t) { $trk.css('cursor',t); }; + docOffset = getPos($img); + // }}} + // }}} + // Internal Modules {{{ + // Touch Module {{{ + var Touch = (function () { + // Touch support detection function adapted (under MIT License) + // from code by Jeffrey Sambells - http://github.com/iamamused/ + function hasTouchSupport() { + var support = {}, events = ['touchstart', 'touchmove', 'touchend'], + el = document.createElement('div'), i; - $img.before($trk); - return { - activateHandlers: activateHandlers, - setCursor: setCursor - }; - }(); - /*}}}*/ - var KeyManager = function()/*{{{*/ - { - var $keymgr = $('') - .css({ position: 'absolute', left: '-30px' }) - .keypress(parseKey) - .blur(onBlur), + try { + for(i=0; i') - .css({ - position: 'absolute', - overflow: 'hidden' - }) - .append($keymgr) - ; + function detectSupport() { + if ((options.touchSupport === true) || (options.touchSupport === false)) return options.touchSupport; + else return hasTouchSupport(); + } + return { + createDragger: function (ord) { + return function (e) { + if (options.disabled) { + return false; + } + if ((ord === 'move') && !options.allowMove) { + return false; + } + docOffset = getPos($img); + btndown = true; + startDragMode(ord, mouseAbs(Touch.cfilter(e)), true); + e.stopPropagation(); + e.preventDefault(); + return false; + }; + }, + newSelection: function (e) { + return newSelection(Touch.cfilter(e)); + }, + cfilter: function (e){ + e.pageX = e.originalEvent.changedTouches[0].pageX; + e.pageY = e.originalEvent.changedTouches[0].pageY; + return e; + }, + isSupported: hasTouchSupport, + support: detectSupport() + }; + }()); + // }}} + // Coords Module {{{ + var Coords = (function () { + var x1 = 0, + y1 = 0, + x2 = 0, + y2 = 0, + ox, oy; - function watchKeys()/*{{{*/ - { - if (options.keySupport) - { - $keymgr.show(); - $keymgr.focus(); - } - }; - /*}}}*/ - function onBlur(e)/*{{{*/ - { - $keymgr.hide(); - }; - /*}}}*/ - function doNudge(e,x,y)/*{{{*/ - { - if (options.allowMove) { - Coords.moveOffset([x,y]); - Selection.updateVisible(); - }; - e.preventDefault(); - e.stopPropagation(); - }; - /*}}}*/ - function parseKey(e)/*{{{*/ - { - if (e.ctrlKey) return true; - shift_down = e.shiftKey ? true : false; - var nudge = shift_down ? 10 : 1; - switch(e.keyCode) - { - case 37: doNudge(e,-nudge,0); break; - case 39: doNudge(e,nudge,0); break; - case 38: doNudge(e,0,-nudge); break; - case 40: doNudge(e,0,nudge); break; + function setPressed(pos) //{{{ + { + pos = rebound(pos); + x2 = x1 = pos[0]; + y2 = y1 = pos[1]; + } + //}}} + function setCurrent(pos) //{{{ + { + pos = rebound(pos); + ox = pos[0] - x2; + oy = pos[1] - y2; + x2 = pos[0]; + y2 = pos[1]; + } + //}}} + function getOffset() //{{{ + { + return [ox, oy]; + } + //}}} + function moveOffset(offset) //{{{ + { + var ox = offset[0], + oy = offset[1]; - case 27: Selection.release(); break; + if (0 > x1 + ox) { + ox -= ox + x1; + } + if (0 > y1 + oy) { + oy -= oy + y1; + } - case 9: return true; - } + if (boundy < y2 + oy) { + oy += boundy - (y2 + oy); + } + if (boundx < x2 + ox) { + ox += boundx - (x2 + ox); + } - return nothing(e); - }; - /*}}}*/ - - if (options.keySupport) $keywrap.insertBefore($img); - return { - watchKeys: watchKeys - }; - }(); - /*}}}*/ + x1 += ox; + x2 += ox; + y1 += oy; + y2 += oy; + } + //}}} + function getCorner(ord) //{{{ + { + var c = getFixed(); + switch (ord) { + case 'ne': + return [c.x2, c.y]; + case 'nw': + return [c.x, c.y]; + case 'se': + return [c.x2, c.y2]; + case 'sw': + return [c.x, c.y2]; + } + } + //}}} + function getFixed() //{{{ + { + if (!options.aspectRatio) { + return getRect(); + } + // This function could use some optimization I think... + var aspect = options.aspectRatio, + min_x = options.minSize[0] / xscale, - // }}} - // Internal Methods {{{ - function px(n) { return '' + parseInt(n) + 'px'; }; - function pct(n) { return '' + parseInt(n) + '%'; }; - function cssClass(cl) { return options.baseClass + '-' + cl; }; - function getPos(obj)/*{{{*/ - { - // Updated in v0.9.4 to use built-in dimensions plugin - var pos = $(obj).offset(); - return [ pos.left, pos.top ]; - }; - /*}}}*/ - function mouseAbs(e)/*{{{*/ - { - return [ (e.pageX - docOffset[0]), (e.pageY - docOffset[1]) ]; - }; - /*}}}*/ - function myCursor(type)/*{{{*/ - { - if (type != lastcurs) - { - Tracker.setCursor(type); - //Handles.xsetCursor(type); - lastcurs = type; - } - }; - /*}}}*/ - function startDragMode(mode,pos)/*{{{*/ - { - docOffset = getPos($img); - Tracker.setCursor(mode=='move'?mode:mode+'-resize'); + //min_y = options.minSize[1]/yscale, + max_x = options.maxSize[0] / xscale, + max_y = options.maxSize[1] / yscale, + rw = x2 - x1, + rh = y2 - y1, + rwa = Math.abs(rw), + rha = Math.abs(rh), + real_ratio = rwa / rha, + xx, yy, w, h; - if (mode == 'move') - return Tracker.activateHandlers(createMover(pos), doneSelect); + if (max_x === 0) { + max_x = boundx * 10; + } + if (max_y === 0) { + max_y = boundy * 10; + } + if (real_ratio < aspect) { + yy = y2; + w = rha * aspect; + xx = rw < 0 ? x1 - w : w + x1; - var fc = Coords.getFixed(); - var opp = oppLockCorner(mode); - var opc = Coords.getCorner(oppLockCorner(opp)); + if (xx < 0) { + xx = 0; + h = Math.abs((xx - x1) / aspect); + yy = rh < 0 ? y1 - h : h + y1; + } else if (xx > boundx) { + xx = boundx; + h = Math.abs((xx - x1) / aspect); + yy = rh < 0 ? y1 - h : h + y1; + } + } else { + xx = x2; + h = rwa / aspect; + yy = rh < 0 ? y1 - h : y1 + h; + if (yy < 0) { + yy = 0; + w = Math.abs((yy - y1) * aspect); + xx = rw < 0 ? x1 - w : w + x1; + } else if (yy > boundy) { + yy = boundy; + w = Math.abs(yy - y1) * aspect; + xx = rw < 0 ? x1 - w : w + x1; + } + } - Coords.setPressed(Coords.getCorner(opp)); - Coords.setCurrent(opc); + // Magic %-) + if (xx > x1) { // right side + if (xx - x1 < min_x) { + xx = x1 + min_x; + } else if (xx - x1 > max_x) { + xx = x1 + max_x; + } + if (yy > y1) { + yy = y1 + (xx - x1) / aspect; + } else { + yy = y1 - (xx - x1) / aspect; + } + } else if (xx < x1) { // left side + if (x1 - xx < min_x) { + xx = x1 - min_x; + } else if (x1 - xx > max_x) { + xx = x1 - max_x; + } + if (yy > y1) { + yy = y1 + (x1 - xx) / aspect; + } else { + yy = y1 - (x1 - xx) / aspect; + } + } - Tracker.activateHandlers(dragmodeHandler(mode,fc),doneSelect); - }; - /*}}}*/ - function dragmodeHandler(mode,f)/*{{{*/ - { - return function(pos) { - if (!options.aspectRatio) switch(mode) - { - case 'e': pos[1] = f.y2; break; - case 'w': pos[1] = f.y2; break; - case 'n': pos[0] = f.x2; break; - case 's': pos[0] = f.x2; break; - } - else switch(mode) - { - case 'e': pos[1] = f.y+1; break; - case 'w': pos[1] = f.y+1; break; - case 'n': pos[0] = f.x+1; break; - case 's': pos[0] = f.x+1; break; - } - Coords.setCurrent(pos); - Selection.update(); - }; - }; - /*}}}*/ - function createMover(pos)/*{{{*/ - { - var lloc = pos; - KeyManager.watchKeys(); + if (xx < 0) { + x1 -= xx; + xx = 0; + } else if (xx > boundx) { + x1 -= xx - boundx; + xx = boundx; + } - return function(pos) - { - Coords.moveOffset([pos[0] - lloc[0], pos[1] - lloc[1]]); - lloc = pos; - - Selection.update(); - }; - }; - /*}}}*/ - function oppLockCorner(ord)/*{{{*/ - { - switch(ord) - { - case 'n': return 'sw'; - case 's': return 'nw'; - case 'e': return 'nw'; - case 'w': return 'ne'; - case 'ne': return 'sw'; - case 'nw': return 'se'; - case 'se': return 'nw'; - case 'sw': return 'ne'; - }; - }; - /*}}}*/ - function createDragger(ord)/*{{{*/ - { - return function(e) { - if (options.disabled) return false; - if ((ord == 'move') && !options.allowMove) return false; - btndown = true; - startDragMode(ord,mouseAbs(e)); - e.stopPropagation(); - e.preventDefault(); - return false; - }; - }; - /*}}}*/ - function presize($obj,w,h)/*{{{*/ - { - var nw = $obj.width(), nh = $obj.height(); - if ((nw > w) && w > 0) - { - nw = w; - nh = (w/$obj.width()) * $obj.height(); - } - if ((nh > h) && h > 0) - { - nh = h; - nw = (h/$obj.height()) * $obj.width(); - } - xscale = $obj.width() / nw; - yscale = $obj.height() / nh; - $obj.width(nw).height(nh); - }; - /*}}}*/ - function unscale(c)/*{{{*/ - { - return { - x: parseInt(c.x * xscale), y: parseInt(c.y * yscale), - x2: parseInt(c.x2 * xscale), y2: parseInt(c.y2 * yscale), - w: parseInt(c.w * xscale), h: parseInt(c.h * yscale) - }; - }; - /*}}}*/ - function doneSelect(pos)/*{{{*/ - { - var c = Coords.getFixed(); - if (c.w > options.minSelect[0] && c.h > options.minSelect[1]) - { - Selection.enableHandles(); - Selection.done(); - } - else - { - Selection.release(); - } - Tracker.setCursor( options.allowSelect?'crosshair':'default' ); - }; - /*}}}*/ - function newSelection(e)/*{{{*/ - { - if (options.disabled) return false; - if (!options.allowSelect) return false; - btndown = true; - docOffset = getPos($img); - Selection.disableHandles(); - myCursor('crosshair'); - var pos = mouseAbs(e); - Coords.setPressed(pos); - Tracker.activateHandlers(selectDrag,doneSelect); - KeyManager.watchKeys(); - Selection.update(); + if (yy < 0) { + y1 -= yy; + yy = 0; + } else if (yy > boundy) { + y1 -= yy - boundy; + yy = boundy; + } - e.stopPropagation(); - e.preventDefault(); - return false; - }; - /*}}}*/ - function selectDrag(pos)/*{{{*/ - { - Coords.setCurrent(pos); - Selection.update(); - }; - /*}}}*/ - function newTracker() - { - var trk = $('
').addClass(cssClass('tracker')); - $.browser.msie && trk.css({ opacity: 0, backgroundColor: 'white' }); - return trk; - }; + return makeObj(flipCoords(x1, y1, xx, yy)); + } + //}}} + function rebound(p) //{{{ + { + if (p[0] < 0) p[0] = 0; + if (p[1] < 0) p[1] = 0; - // }}} - // API methods {{{ - - function animateTo(a)/*{{{*/ - { - var x1 = a[0] / xscale, - y1 = a[1] / yscale, - x2 = a[2] / xscale, - y2 = a[3] / yscale; + if (p[0] > boundx) p[0] = boundx; + if (p[1] > boundy) p[1] = boundy; - if (animating) return; + return [Math.round(p[0]), Math.round(p[1])]; + } + //}}} + function flipCoords(x1, y1, x2, y2) //{{{ + { + var xa = x1, + xb = x2, + ya = y1, + yb = y2; + if (x2 < x1) { + xa = x2; + xb = x1; + } + if (y2 < y1) { + ya = y2; + yb = y1; + } + return [xa, ya, xb, yb]; + } + //}}} + function getRect() //{{{ + { + var xsize = x2 - x1, + ysize = y2 - y1, + delta; - var animto = Coords.flipCoords(x1,y1,x2,y2); - var c = Coords.getFixed(); - var animat = initcr = [ c.x, c.y, c.x2, c.y2 ]; - var interv = options.animationDelay; + if (xlimit && (Math.abs(xsize) > xlimit)) { + x2 = (xsize > 0) ? (x1 + xlimit) : (x1 - xlimit); + } + if (ylimit && (Math.abs(ysize) > ylimit)) { + y2 = (ysize > 0) ? (y1 + ylimit) : (y1 - ylimit); + } - var x = animat[0]; - var y = animat[1]; - var x2 = animat[2]; - var y2 = animat[3]; - var ix1 = animto[0] - initcr[0]; - var iy1 = animto[1] - initcr[1]; - var ix2 = animto[2] - initcr[2]; - var iy2 = animto[3] - initcr[3]; - var pcent = 0; - var velocity = options.swingSpeed; + if (ymin / yscale && (Math.abs(ysize) < ymin / yscale)) { + y2 = (ysize > 0) ? (y1 + ymin / yscale) : (y1 - ymin / yscale); + } + if (xmin / xscale && (Math.abs(xsize) < xmin / xscale)) { + x2 = (xsize > 0) ? (x1 + xmin / xscale) : (x1 - xmin / xscale); + } - Selection.animMode(true); + if (x1 < 0) { + x2 -= x1; + x1 -= x1; + } + if (y1 < 0) { + y2 -= y1; + y1 -= y1; + } + if (x2 < 0) { + x1 -= x2; + x2 -= x2; + } + if (y2 < 0) { + y1 -= y2; + y2 -= y2; + } + if (x2 > boundx) { + delta = x2 - boundx; + x1 -= delta; + x2 -= delta; + } + if (y2 > boundy) { + delta = y2 - boundy; + y1 -= delta; + y2 -= delta; + } + if (x1 > boundx) { + delta = x1 - boundy; + y2 -= delta; + y1 -= delta; + } + if (y1 > boundy) { + delta = y1 - boundy; + y2 -= delta; + y1 -= delta; + } - var animator = function() - { - return function() - { - pcent += (100 - pcent) / velocity; + return makeObj(flipCoords(x1, y1, x2, y2)); + } + //}}} + function makeObj(a) //{{{ + { + return { + x: a[0], + y: a[1], + x2: a[2], + y2: a[3], + w: a[2] - a[0], + h: a[3] - a[1] + }; + } + //}}} - animat[0] = x + ((pcent / 100) * ix1); - animat[1] = y + ((pcent / 100) * iy1); - animat[2] = x2 + ((pcent / 100) * ix2); - animat[3] = y2 + ((pcent / 100) * iy2); + return { + flipCoords: flipCoords, + setPressed: setPressed, + setCurrent: setCurrent, + getOffset: getOffset, + moveOffset: moveOffset, + getCorner: getCorner, + getFixed: getFixed + }; + }()); - if (pcent < 100) animateStart(); - else Selection.done(); + //}}} + // Shade Module {{{ + var Shade = (function() { + var enabled = false, + holder = $('
').css({ + position: 'absolute', + zIndex: 240, + opacity: 0 + }), + shades = { + top: createShade(), + left: createShade().height(boundy), + right: createShade().height(boundy), + bottom: createShade() + }; - if (pcent >= 99.8) pcent = 100; + function resizeShades(w,h) { + shades.left.css({ height: px(h) }); + shades.right.css({ height: px(h) }); + } + function updateAuto() + { + return updateShade(Coords.getFixed()); + } + function updateShade(c) + { + shades.top.css({ + left: px(c.x), + width: px(c.w), + height: px(c.y) + }); + shades.bottom.css({ + top: px(c.y2), + left: px(c.x), + width: px(c.w), + height: px(boundy-c.y2) + }); + shades.right.css({ + left: px(c.x2), + width: px(boundx-c.x2) + }); + shades.left.css({ + width: px(c.x) + }); + } + function createShade() { + return $('
').css({ + position: 'absolute', + backgroundColor: options.shadeColor||options.bgColor + }).appendTo(holder); + } + function enableShade() { + if (!enabled) { + enabled = true; + holder.insertBefore($img); + updateAuto(); + Selection.setBgOpacity(1,0,1); + $img2.hide(); - setSelectRaw(animat); - }; - }(); + setBgColor(options.shadeColor||options.bgColor,1); + if (Selection.isAwake()) + { + setOpacity(options.bgOpacity,1); + } + else setOpacity(1,1); + } + } + function setBgColor(color,now) { + colorChangeMacro(getShades(),color,now); + } + function disableShade() { + if (enabled) { + holder.remove(); + $img2.show(); + enabled = false; + if (Selection.isAwake()) { + Selection.setBgOpacity(options.bgOpacity,1,1); + } else { + Selection.setBgOpacity(1,1,1); + Selection.disableHandles(); + } + colorChangeMacro($div,0,1); + } + } + function setOpacity(opacity,now) { + if (enabled) { + if (options.bgFade && !now) { + holder.animate({ + opacity: 1-opacity + },{ + queue: false, + duration: options.fadeTime + }); + } + else holder.css({opacity:1-opacity}); + } + } + function refreshAll() { + options.shade ? enableShade() : disableShade(); + if (Selection.isAwake()) setOpacity(options.bgOpacity); + } + function getShades() { + return holder.children(); + } - function animateStart() - { window.setTimeout(animator,interv); }; + return { + update: updateAuto, + updateRaw: updateShade, + getShades: getShades, + setBgColor: setBgColor, + enable: enableShade, + disable: disableShade, + resize: resizeShades, + refresh: refreshAll, + opacity: setOpacity + }; + }()); + // }}} + // Selection Module {{{ + var Selection = (function () { + var awake, + hdep = 370, + borders = {}, + handle = {}, + dragbar = {}, + seehandles = false; - animateStart(); - }; - /*}}}*/ - function setSelect(rect)//{{{ - { - setSelectRaw([rect[0]/xscale,rect[1]/yscale,rect[2]/xscale,rect[3]/yscale]); - }; - //}}} - function setSelectRaw(l) /*{{{*/ - { - Coords.setPressed([l[0],l[1]]); - Coords.setCurrent([l[2],l[3]]); - Selection.update(); - }; - /*}}}*/ - function setOptions(opt)/*{{{*/ - { - if (typeof(opt) != 'object') opt = { }; - options = $.extend(options,opt); + // Private Methods + function insertBorder(type) //{{{ + { + var jq = $('
').css({ + position: 'absolute', + opacity: options.borderOpacity + }).addClass(cssClass(type)); + $img_holder.append(jq); + return jq; + } + //}}} + function dragDiv(ord, zi) //{{{ + { + var jq = $('
').mousedown(createDragger(ord)).css({ + cursor: ord + '-resize', + position: 'absolute', + zIndex: zi + }).addClass('ord-'+ord); - if (typeof(options.onChange)!=='function') - options.onChange = function() { }; + if (Touch.support) { + jq.bind('touchstart.jcrop', Touch.createDragger(ord)); + } - if (typeof(options.onSelect)!=='function') - options.onSelect = function() { }; + $hdl_holder.append(jq); + return jq; + } + //}}} + function insertHandle(ord) //{{{ + { + var hs = options.handleSize, - }; - /*}}}*/ - function tellSelect()/*{{{*/ - { - return unscale(Coords.getFixed()); - }; - /*}}}*/ - function tellScaled()/*{{{*/ - { - return Coords.getFixed(); - }; - /*}}}*/ - function setOptionsNew(opt)/*{{{*/ - { - setOptions(opt); - interfaceUpdate(); - }; - /*}}}*/ - function disableCrop()//{{{ - { - options.disabled = true; - Selection.disableHandles(); - Selection.setCursor('default'); - Tracker.setCursor('default'); - }; - //}}} - function enableCrop()//{{{ - { - options.disabled = false; - interfaceUpdate(); - }; - //}}} - function cancelCrop()//{{{ - { - Selection.done(); - Tracker.activateHandlers(null,null); - }; - //}}} - function destroy()//{{{ - { - $div.remove(); - $origimg.show(); - }; - //}}} + div = dragDiv(ord, hdep++).css({ + opacity: options.handleOpacity + }).addClass(cssClass('handle')); - function interfaceUpdate(alt)//{{{ - // This method tweaks the interface based on options object. - // Called when options are changed and at end of initialization. - { - options.allowResize ? - alt?Selection.enableOnly():Selection.enableHandles(): - Selection.disableHandles(); + if (hs) { div.width(hs).height(hs); } - Tracker.setCursor( options.allowSelect? 'crosshair': 'default' ); - Selection.setCursor( options.allowMove? 'move': 'default' ); + return div; + } + //}}} + function insertDragbar(ord) //{{{ + { + return dragDiv(ord, hdep++).addClass('jcrop-dragbar'); + } + //}}} + function createDragbars(li) //{{{ + { + var i; + for (i = 0; i < li.length; i++) { + dragbar[li[i]] = insertDragbar(li[i]); + } + } + //}}} + function createBorders(li) //{{{ + { + var cl,i; + for (i = 0; i < li.length; i++) { + switch(li[i]){ + case'n': cl='hline'; break; + case's': cl='hline bottom'; break; + case'e': cl='vline right'; break; + case'w': cl='vline'; break; + } + borders[li[i]] = insertBorder(cl); + } + } + //}}} + function createHandles(li) //{{{ + { + var i; + for (i = 0; i < li.length; i++) { + handle[li[i]] = insertHandle(li[i]); + } + } + //}}} + function moveto(x, y) //{{{ + { + if (!options.shade) { + $img2.css({ + top: px(-y), + left: px(-x) + }); + } + $sel.css({ + top: px(y), + left: px(x) + }); + } + //}}} + function resize(w, h) //{{{ + { + $sel.width(Math.round(w)).height(Math.round(h)); + } + //}}} + function refresh() //{{{ + { + var c = Coords.getFixed(); - $div.css('backgroundColor',options.bgColor); + Coords.setPressed([c.x, c.y]); + Coords.setCurrent([c.x2, c.y2]); - if ('setSelect' in options) { - setSelect(opt.setSelect); - Selection.done(); - delete(options.setSelect); - } + updateVisible(); + } + //}}} - if ('trueSize' in options) { - xscale = options.trueSize[0] / boundx; - yscale = options.trueSize[1] / boundy; - } + // Internal Methods + function updateVisible(select) //{{{ + { + if (awake) { + return update(select); + } + } + //}}} + function update(select) //{{{ + { + var c = Coords.getFixed(); - xlimit = options.maxSize[0] || 0; - ylimit = options.maxSize[1] || 0; - xmin = options.minSize[0] || 0; - ymin = options.minSize[1] || 0; + resize(c.w, c.h); + moveto(c.x, c.y); + if (options.shade) Shade.updateRaw(c); - if ('outerImage' in options) - { - $img.attr('src',options.outerImage); - delete(options.outerImage); - } + awake || show(); - Selection.refresh(); - }; - //}}} + if (select) { + options.onSelect.call(api, unscale(c)); + } else { + options.onChange.call(api, unscale(c)); + } + } + //}}} + function setBgOpacity(opacity,force,now) //{{{ + { + if (!awake && !force) return; + if (options.bgFade && !now) { + $img.animate({ + opacity: opacity + },{ + queue: false, + duration: options.fadeTime + }); + } else { + $img.css('opacity', opacity); + } + } + //}}} + function show() //{{{ + { + $sel.show(); - // }}} + if (options.shade) Shade.opacity(bgopacity); + else setBgOpacity(bgopacity,true); - $hdl_holder.hide(); - interfaceUpdate(true); - - var api = { - animateTo: animateTo, - setSelect: setSelect, - setOptions: setOptionsNew, - tellSelect: tellSelect, - tellScaled: tellScaled, + awake = true; + } + //}}} + function release() //{{{ + { + disableHandles(); + $sel.hide(); - disable: disableCrop, - enable: enableCrop, - cancel: cancelCrop, + if (options.shade) Shade.opacity(1); + else setBgOpacity(1); - focus: KeyManager.watchKeys, + awake = false; + options.onRelease.call(api); + } + //}}} + function showHandles() //{{{ + { + if (seehandles) { + $hdl_holder.show(); + } + } + //}}} + function enableHandles() //{{{ + { + seehandles = true; + if (options.allowResize) { + $hdl_holder.show(); + return true; + } + } + //}}} + function disableHandles() //{{{ + { + seehandles = false; + $hdl_holder.hide(); + } + //}}} + function animMode(v) //{{{ + { + if (v) { + animating = true; + disableHandles(); + } else { + animating = false; + enableHandles(); + } + } + //}}} + function done() //{{{ + { + animMode(false); + refresh(); + } + //}}} + // Insert draggable elements {{{ + // Insert border divs for outline - getBounds: function() { return [ boundx * xscale, boundy * yscale ]; }, - getWidgetSize: function() { return [ boundx, boundy ]; }, + if (options.dragEdges && $.isArray(options.createDragbars)) + createDragbars(options.createDragbars); - release: Selection.release, - destroy: destroy + if ($.isArray(options.createHandles)) + createHandles(options.createHandles); - }; + if (options.drawBorders && $.isArray(options.createBorders)) + createBorders(options.createBorders); - $origimg.data('Jcrop',api); - return api; -}; + //}}} -$.fn.Jcrop = function(options)/*{{{*/ -{ - function attachWhenDone(from)/*{{{*/ - { - var loadsrc = options.useImg || from.src; - var img = new Image(); - img.onload = function() { $.Jcrop(from,options); }; - img.src = loadsrc; - }; - /*}}}*/ - if (typeof(options) !== 'object') options = { }; + // This is a hack for iOS5 to support drag/move touch functionality + $(document).bind('touchstart.jcrop-ios',function(e) { + if ($(e.currentTarget).hasClass('jcrop-tracker')) e.stopPropagation(); + }); - // Iterate over each object, attach Jcrop - this.each(function() - { - // If we've already attached to this object - if ($(this).data('Jcrop')) - { - // The API can be requested this way (undocumented) - if (options == 'api') return $(this).data('Jcrop'); - // Otherwise, we just reset the options... - else $(this).data('Jcrop').setOptions(options); - } - // If we haven't been attached, preload and attach - else attachWhenDone(this); - }); + var $track = newTracker().mousedown(createDragger('move')).css({ + cursor: 'move', + position: 'absolute', + zIndex: 360 + }); - // Return "this" so we're chainable a la jQuery plugin-style! - return this; -}; -/*}}}*/ + if (Touch.support) { + $track.bind('touchstart.jcrop', Touch.createDragger('move')); + } -})(jQuery); + $img_holder.append($track); + disableHandles(); + + return { + updateVisible: updateVisible, + update: update, + release: release, + refresh: refresh, + isAwake: function () { + return awake; + }, + setCursor: function (cursor) { + $track.css('cursor', cursor); + }, + enableHandles: enableHandles, + enableOnly: function () { + seehandles = true; + }, + showHandles: showHandles, + disableHandles: disableHandles, + animMode: animMode, + setBgOpacity: setBgOpacity, + done: done + }; + }()); + + //}}} + // Tracker Module {{{ + var Tracker = (function () { + var onMove = function () {}, + onDone = function () {}, + trackDoc = options.trackDocument; + + function toFront(touch) //{{{ + { + $trk.css({ + zIndex: 450 + }); + + if (touch) + $(document) + .bind('touchmove.jcrop', trackTouchMove) + .bind('touchend.jcrop', trackTouchEnd); + + else if (trackDoc) + $(document) + .bind('mousemove.jcrop',trackMove) + .bind('mouseup.jcrop',trackUp); + } + //}}} + function toBack() //{{{ + { + $trk.css({ + zIndex: 290 + }); + $(document).unbind('.jcrop'); + } + //}}} + function trackMove(e) //{{{ + { + onMove(mouseAbs(e)); + return false; + } + //}}} + function trackUp(e) //{{{ + { + e.preventDefault(); + e.stopPropagation(); + + if (btndown) { + btndown = false; + + onDone(mouseAbs(e)); + + if (Selection.isAwake()) { + options.onSelect.call(api, unscale(Coords.getFixed())); + } + + toBack(); + onMove = function () {}; + onDone = function () {}; + } + + return false; + } + //}}} + function activateHandlers(move, done, touch) //{{{ + { + btndown = true; + onMove = move; + onDone = done; + toFront(touch); + return false; + } + //}}} + function trackTouchMove(e) //{{{ + { + onMove(mouseAbs(Touch.cfilter(e))); + return false; + } + //}}} + function trackTouchEnd(e) //{{{ + { + return trackUp(Touch.cfilter(e)); + } + //}}} + function setCursor(t) //{{{ + { + $trk.css('cursor', t); + } + //}}} + + if (!trackDoc) { + $trk.mousemove(trackMove).mouseup(trackUp).mouseout(trackUp); + } + + $img.before($trk); + return { + activateHandlers: activateHandlers, + setCursor: setCursor + }; + }()); + //}}} + // KeyManager Module {{{ + var KeyManager = (function () { + var $keymgr = $('').css({ + position: 'fixed', + left: '-120px', + width: '12px' + }).addClass('jcrop-keymgr'), + + $keywrap = $('
').css({ + position: 'absolute', + overflow: 'hidden' + }).append($keymgr); + + function watchKeys() //{{{ + { + if (options.keySupport) { + $keymgr.show(); + $keymgr.focus(); + } + } + //}}} + function onBlur(e) //{{{ + { + $keymgr.hide(); + } + //}}} + function doNudge(e, x, y) //{{{ + { + if (options.allowMove) { + Coords.moveOffset([x, y]); + Selection.updateVisible(true); + } + e.preventDefault(); + e.stopPropagation(); + } + //}}} + function parseKey(e) //{{{ + { + if (e.ctrlKey || e.metaKey) { + return true; + } + shift_down = e.shiftKey ? true : false; + var nudge = shift_down ? 10 : 1; + + switch (e.keyCode) { + case 37: + doNudge(e, -nudge, 0); + break; + case 39: + doNudge(e, nudge, 0); + break; + case 38: + doNudge(e, 0, -nudge); + break; + case 40: + doNudge(e, 0, nudge); + break; + case 27: + if (options.allowSelect) Selection.release(); + break; + case 9: + return true; + } + + return false; + } + //}}} + + if (options.keySupport) { + $keymgr.keydown(parseKey).blur(onBlur); + if (ie6mode || !options.fixedSupport) { + $keymgr.css({ + position: 'absolute', + left: '-20px' + }); + $keywrap.append($keymgr).insertBefore($img); + } else { + $keymgr.insertBefore($img); + } + } + + + return { + watchKeys: watchKeys + }; + }()); + //}}} + // }}} + // API methods {{{ + function setClass(cname) //{{{ + { + $div.removeClass().addClass(cssClass('holder')).addClass(cname); + } + //}}} + function animateTo(a, callback) //{{{ + { + var x1 = a[0] / xscale, + y1 = a[1] / yscale, + x2 = a[2] / xscale, + y2 = a[3] / yscale; + + if (animating) { + return; + } + + var animto = Coords.flipCoords(x1, y1, x2, y2), + c = Coords.getFixed(), + initcr = [c.x, c.y, c.x2, c.y2], + animat = initcr, + interv = options.animationDelay, + ix1 = animto[0] - initcr[0], + iy1 = animto[1] - initcr[1], + ix2 = animto[2] - initcr[2], + iy2 = animto[3] - initcr[3], + pcent = 0, + velocity = options.swingSpeed; + + x1 = animat[0]; + y1 = animat[1]; + x2 = animat[2]; + y2 = animat[3]; + + Selection.animMode(true); + var anim_timer; + + function queueAnimator() { + window.setTimeout(animator, interv); + } + var animator = (function () { + return function () { + pcent += (100 - pcent) / velocity; + + animat[0] = Math.round(x1 + ((pcent / 100) * ix1)); + animat[1] = Math.round(y1 + ((pcent / 100) * iy1)); + animat[2] = Math.round(x2 + ((pcent / 100) * ix2)); + animat[3] = Math.round(y2 + ((pcent / 100) * iy2)); + + if (pcent >= 99.8) { + pcent = 100; + } + if (pcent < 100) { + setSelectRaw(animat); + queueAnimator(); + } else { + Selection.done(); + Selection.animMode(false); + if (typeof(callback) === 'function') { + callback.call(api); + } + } + }; + }()); + queueAnimator(); + } + //}}} + function setSelect(rect) //{{{ + { + setSelectRaw([rect[0] / xscale, rect[1] / yscale, rect[2] / xscale, rect[3] / yscale]); + options.onSelect.call(api, unscale(Coords.getFixed())); + Selection.enableHandles(); + } + //}}} + function setSelectRaw(l) //{{{ + { + Coords.setPressed([l[0], l[1]]); + Coords.setCurrent([l[2], l[3]]); + Selection.update(); + } + //}}} + function tellSelect() //{{{ + { + return unscale(Coords.getFixed()); + } + //}}} + function tellScaled() //{{{ + { + return Coords.getFixed(); + } + //}}} + function setOptionsNew(opt) //{{{ + { + setOptions(opt); + interfaceUpdate(); + } + //}}} + function disableCrop() //{{{ + { + options.disabled = true; + Selection.disableHandles(); + Selection.setCursor('default'); + Tracker.setCursor('default'); + } + //}}} + function enableCrop() //{{{ + { + options.disabled = false; + interfaceUpdate(); + } + //}}} + function cancelCrop() //{{{ + { + Selection.done(); + Tracker.activateHandlers(null, null); + } + //}}} + function destroy() //{{{ + { + $div.remove(); + $origimg.show(); + $origimg.css('visibility','visible'); + $(obj).removeData('Jcrop'); + } + //}}} + function setImage(src, callback) //{{{ + { + Selection.release(); + disableCrop(); + var img = new Image(); + img.onload = function () { + var iw = img.width; + var ih = img.height; + var bw = options.boxWidth; + var bh = options.boxHeight; + $img.width(iw).height(ih); + $img.attr('src', src); + $img2.attr('src', src); + presize($img, bw, bh); + boundx = $img.width(); + boundy = $img.height(); + $img2.width(boundx).height(boundy); + $trk.width(boundx + (bound * 2)).height(boundy + (bound * 2)); + $div.width(boundx).height(boundy); + Shade.resize(boundx,boundy); + enableCrop(); + + if (typeof(callback) === 'function') { + callback.call(api); + } + }; + img.src = src; + } + //}}} + function colorChangeMacro($obj,color,now) { + var mycolor = color || options.bgColor; + if (options.bgFade && supportsColorFade() && options.fadeTime && !now) { + $obj.animate({ + backgroundColor: mycolor + }, { + queue: false, + duration: options.fadeTime + }); + } else { + $obj.css('backgroundColor', mycolor); + } + } + function interfaceUpdate(alt) //{{{ + // This method tweaks the interface based on options object. + // Called when options are changed and at end of initialization. + { + if (options.allowResize) { + if (alt) { + Selection.enableOnly(); + } else { + Selection.enableHandles(); + } + } else { + Selection.disableHandles(); + } + + Tracker.setCursor(options.allowSelect ? 'crosshair' : 'default'); + Selection.setCursor(options.allowMove ? 'move' : 'default'); + + if (options.hasOwnProperty('trueSize')) { + xscale = options.trueSize[0] / boundx; + yscale = options.trueSize[1] / boundy; + } + + if (options.hasOwnProperty('setSelect')) { + setSelect(options.setSelect); + Selection.done(); + delete(options.setSelect); + } + + Shade.refresh(); + + if (options.bgColor != bgcolor) { + colorChangeMacro( + options.shade? Shade.getShades(): $div, + options.shade? + (options.shadeColor || options.bgColor): + options.bgColor + ); + bgcolor = options.bgColor; + } + + if (bgopacity != options.bgOpacity) { + bgopacity = options.bgOpacity; + if (options.shade) Shade.refresh(); + else Selection.setBgOpacity(bgopacity); + } + + xlimit = options.maxSize[0] || 0; + ylimit = options.maxSize[1] || 0; + xmin = options.minSize[0] || 0; + ymin = options.minSize[1] || 0; + + if (options.hasOwnProperty('outerImage')) { + $img.attr('src', options.outerImage); + delete(options.outerImage); + } + + Selection.refresh(); + } + //}}} + //}}} + + if (Touch.support) $trk.bind('touchstart.jcrop', Touch.newSelection); + + $hdl_holder.hide(); + interfaceUpdate(true); + + var api = { + setImage: setImage, + animateTo: animateTo, + setSelect: setSelect, + setOptions: setOptionsNew, + tellSelect: tellSelect, + tellScaled: tellScaled, + setClass: setClass, + + disable: disableCrop, + enable: enableCrop, + cancel: cancelCrop, + release: Selection.release, + destroy: destroy, + + focus: KeyManager.watchKeys, + + getBounds: function () { + return [boundx * xscale, boundy * yscale]; + }, + getWidgetSize: function () { + return [boundx, boundy]; + }, + getScaleFactor: function () { + return [xscale, yscale]; + }, + getOptions: function() { + // careful: internal values are returned + return options; + }, + + ui: { + holder: $div, + selection: $sel + } + }; + + if (is_msie) $div.bind('selectstart', function () { return false; }); + + $origimg.data('Jcrop', api); + return api; + }; + $.fn.Jcrop = function (options, callback) //{{{ + { + var api; + // Iterate over each object, attach Jcrop + this.each(function () { + // If we've already attached to this object + if ($(this).data('Jcrop')) { + // The API can be requested this way (undocumented) + if (options === 'api') return $(this).data('Jcrop'); + // Otherwise, we just reset the options... + else $(this).data('Jcrop').setOptions(options); + } + // If we haven't been attached, preload and attach + else { + if (this.tagName == 'IMG') + $.Jcrop.Loader(this,function(){ + $(this).css({display:'block',visibility:'hidden'}); + api = $.Jcrop(this, options); + if ($.isFunction(callback)) callback.call(api); + }); + else { + $(this).css({display:'block',visibility:'hidden'}); + api = $.Jcrop(this, options); + if ($.isFunction(callback)) callback.call(api); + } + } + }); + + // Return "this" so the object is chainable (jQuery-style) + return this; + }; + //}}} + // $.Jcrop.Loader - basic image loader {{{ + + $.Jcrop.Loader = function(imgobj,success,error){ + var $img = $(imgobj), img = $img[0]; + + function completeCheck(){ + if (img.complete) { + $img.unbind('.jcloader'); + if ($.isFunction(success)) success.call(img); + } + else window.setTimeout(completeCheck,50); + } + + $img + .bind('load.jcloader',completeCheck) + .bind('error.jcloader',function(e){ + $img.unbind('.jcloader'); + if ($.isFunction(error)) error.call(img); + }); + + if (img.complete && $.isFunction(success)){ + $img.unbind('.jcloader'); + success.call(img); + } + }; + + //}}} + // Global Defaults {{{ + $.Jcrop.defaults = { + + // Basic Settings + allowSelect: true, + allowMove: true, + allowResize: true, + + trackDocument: true, + + // Styling Options + baseClass: 'jcrop', + addClass: null, + bgColor: 'black', + bgOpacity: 0.6, + bgFade: false, + borderOpacity: 0.4, + handleOpacity: 0.5, + handleSize: null, + + aspectRatio: 0, + keySupport: true, + createHandles: ['n','s','e','w','nw','ne','se','sw'], + createDragbars: ['n','s','e','w'], + createBorders: ['n','s','e','w'], + drawBorders: true, + dragEdges: true, + fixedSupport: true, + touchSupport: null, + + shade: null, + + boxWidth: 0, + boxHeight: 0, + boundary: 2, + fadeTime: 400, + animationDelay: 20, + swingSpeed: 3, + + minSelect: [0, 0], + maxSize: [0, 0], + minSize: [0, 0], + + // Callbacks / Event Handlers + onChange: function () {}, + onSelect: function () {}, + onDblClick: function () {}, + onRelease: function () {} + }; + + // }}} +}(jQuery)); \ No newline at end of file diff --git a/webapp/src/main/webapp/js/jquery_plugins/jquery.realperson.js b/webapp/src/main/webapp/js/jquery_plugins/jquery.realperson.js index 29f7c4c37..256ccc830 100644 --- a/webapp/src/main/webapp/js/jquery_plugins/jquery.realperson.js +++ b/webapp/src/main/webapp/js/jquery_plugins/jquery.realperson.js @@ -176,7 +176,7 @@ $.fn.realperson = function(options) { /* Initialise the real person functionality. */ $.realperson = new RealPerson(); // singleton instance -$('.realperson-challenge').live('click', function() { +$( document ).on('click', '.realperson-challenge', function() { $(this).next().next().realperson('change'); }); diff --git a/webapp/src/main/webapp/js/jquery_plugins/qtip/jquery.qtip-1.0.0-rc3.min.js b/webapp/src/main/webapp/js/jquery_plugins/qtip/jquery.qtip-1.0.0-rc3.min.js deleted file mode 100644 index f50d843fc..000000000 --- a/webapp/src/main/webapp/js/jquery_plugins/qtip/jquery.qtip-1.0.0-rc3.min.js +++ /dev/null @@ -1,15 +0,0 @@ -/* - * jquery.qtip. The jQuery tooltip plugin - * - * Copyright (c) 2009 Craig Thompson - * http://craigsworks.com - * - * Licensed under MIT - * http://www.opensource.org/licenses/mit-license.php - * - * Launch : February 2009 - * Version : 1.0.0-rc3 - * Released: Tuesday 12th May, 2009 - 00:00 - * Debug: jquery.qtip.debug.js - */ -(function(f){f.fn.qtip=function(B,u){var y,t,A,s,x,w,v,z;if(typeof B=="string"){if(typeof f(this).data("qtip")!=="object"){f.fn.qtip.log.error.call(self,1,f.fn.qtip.constants.NO_TOOLTIP_PRESENT,false)}if(B=="api"){return f(this).data("qtip").interfaces[f(this).data("qtip").current]}else{if(B=="interfaces"){return f(this).data("qtip").interfaces}}}else{if(!B){B={}}if(typeof B.content!=="object"||(B.content.jquery&&B.content.length>0)){B.content={text:B.content}}if(typeof B.content.title!=="object"){B.content.title={text:B.content.title}}if(typeof B.position!=="object"){B.position={corner:B.position}}if(typeof B.position.corner!=="object"){B.position.corner={target:B.position.corner,tooltip:B.position.corner}}if(typeof B.show!=="object"){B.show={when:B.show}}if(typeof B.show.when!=="object"){B.show.when={event:B.show.when}}if(typeof B.show.effect!=="object"){B.show.effect={type:B.show.effect}}if(typeof B.hide!=="object"){B.hide={when:B.hide}}if(typeof B.hide.when!=="object"){B.hide.when={event:B.hide.when}}if(typeof B.hide.effect!=="object"){B.hide.effect={type:B.hide.effect}}if(typeof B.style!=="object"){B.style={name:B.style}}B.style=c(B.style);s=f.extend(true,{},f.fn.qtip.defaults,B);s.style=a.call({options:s},s.style);s.user=f.extend(true,{},B)}return f(this).each(function(){if(typeof B=="string"){w=B.toLowerCase();A=f(this).qtip("interfaces");if(typeof A=="object"){if(u===true&&w=="destroy"){while(A.length>0){A[A.length-1].destroy()}}else{if(u!==true){A=[f(this).qtip("api")]}for(y=0;y0))}if(typeof s.options.show.solo=="object"){z=f(s.options.show.solo)}else{if(s.options.show.solo===true){z=f("div.qtip").not(s.elements.tooltip)}}if(z){z.each(function(){if(f(this).qtip("api").status.rendered===true){f(this).qtip("api").hide()}})}if(typeof s.options.show.effect.type=="function"){s.options.show.effect.type.call(s.elements.tooltip,s.options.show.effect.length);s.elements.tooltip.queue(function(){w();f(this).dequeue()})}else{switch(s.options.show.effect.type.toLowerCase()){case"fade":s.elements.tooltip.fadeIn(s.options.show.effect.length,w);break;case"slide":s.elements.tooltip.slideDown(s.options.show.effect.length,function(){w();if(s.options.position.type!=="static"){s.updatePosition(y,true)}});break;case"grow":s.elements.tooltip.show(s.options.show.effect.length,w);break;default:s.elements.tooltip.show(null,w);break}s.elements.tooltip.addClass(s.options.style.classes.active)}return f.fn.qtip.log.error.call(s,1,f.fn.qtip.constants.EVENT_SHOWN,"show")},hide:function(y){var x;if(!s.status.rendered){return f.fn.qtip.log.error.call(s,2,f.fn.qtip.constants.TOOLTIP_NOT_RENDERED,"hide")}else{if(s.elements.tooltip.css("display")==="none"){return s}}clearTimeout(s.timers.show);s.elements.tooltip.stop(true,false);x=s.beforeHide.call(s,y);if(x===false){return s}function w(){s.onHide.call(s,y)}s.cache.toggle=0;if(typeof s.options.hide.effect.type=="function"){s.options.hide.effect.type.call(s.elements.tooltip,s.options.hide.effect.length);s.elements.tooltip.queue(function(){w();f(this).dequeue()})}else{switch(s.options.hide.effect.type.toLowerCase()){case"fade":s.elements.tooltip.fadeOut(s.options.hide.effect.length,w);break;case"slide":s.elements.tooltip.slideUp(s.options.hide.effect.length,w);break;case"grow":s.elements.tooltip.hide(s.options.hide.effect.length,w);break;default:s.elements.tooltip.hide(null,w);break}s.elements.tooltip.removeClass(s.options.style.classes.active)}return f.fn.qtip.log.error.call(s,1,f.fn.qtip.constants.EVENT_HIDDEN,"hide")},updatePosition:function(w,x){var C,G,L,J,H,E,y,I,B,D,K,A,F,z;if(!s.status.rendered){return f.fn.qtip.log.error.call(s,2,f.fn.qtip.constants.TOOLTIP_NOT_RENDERED,"updatePosition")}else{if(s.options.position.type=="static"){return f.fn.qtip.log.error.call(s,1,f.fn.qtip.constants.CANNOT_POSITION_STATIC,"updatePosition")}}G={position:{left:0,top:0},dimensions:{height:0,width:0},corner:s.options.position.corner.target};L={position:s.getPosition(),dimensions:s.getDimensions(),corner:s.options.position.corner.tooltip};if(s.options.position.target!=="mouse"){if(s.options.position.target.get(0).nodeName.toLowerCase()=="area"){J=s.options.position.target.attr("coords").split(",");for(C=0;CG.dimensions.width){G.dimensions.width=J[C]}if(J[C]G.dimensions.height){G.dimensions.height=J[C]}if(J[C]0){if(L.corner.search(/Left/)!==-1){y.left-=s.options.style.border.radius}else{if(L.corner.search(/Right/)!==-1){y.left+=s.options.style.border.radius}}if(L.corner.search(/Top/)!==-1){y.top-=s.options.style.border.radius}else{if(L.corner.search(/Bottom/)!==-1){y.top+=s.options.style.border.radius}}}if(I){if(L.corner.search(/top/)!==-1){y.top-=I}else{if(L.corner.search(/bottom/)!==-1){y.top+=I}}if(L.corner.search(/left/)!==-1){y.left-=I}else{if(L.corner.search(/right/)!==-1){y.left+=I}}if(L.corner.search(/leftMiddle|rightMiddle/)!==-1){y.top-=1}}if(s.options.position.adjust.screen===true){y=o.call(s,y,G,L)}if(s.options.position.target==="mouse"&&s.options.position.adjust.mouse===true){if(s.options.position.adjust.screen===true&&s.elements.tip){K=s.elements.tip.attr("rel")}else{K=s.options.position.corner.tooltip}y.left+=(K.search(/right/i)!==-1)?-6:6;y.top+=(K.search(/bottom/i)!==-1)?-6:6}if(!s.elements.bgiframe&&f.browser.msie&&parseInt(f.browser.version.charAt(0))==6){f("select, object").each(function(){A=f(this).offset();A.bottom=A.top+f(this).height();A.right=A.left+f(this).width();if(y.top+L.dimensions.height>=A.top&&y.left+L.dimensions.width>=A.left){k.call(s)}})}y.left+=s.options.position.adjust.x;y.top+=s.options.position.adjust.y;F=s.getPosition();if(y.left!=F.left||y.top!=F.top){z=s.beforePositionUpdate.call(s,w);if(z===false){return s}s.cache.position=y;if(x===true){s.status.animated=true;s.elements.tooltip.animate(y,200,"swing",function(){s.status.animated=false})}else{s.elements.tooltip.css(y)}s.onPositionUpdate.call(s,w);if(typeof w!=="undefined"&&w.type&&w.type!=="mousemove"){f.fn.qtip.log.error.call(s,1,f.fn.qtip.constants.EVENT_POSITION_UPDATED,"updatePosition")}}return s},updateWidth:function(w){var x;if(!s.status.rendered){return f.fn.qtip.log.error.call(s,2,f.fn.qtip.constants.TOOLTIP_NOT_RENDERED,"updateWidth")}else{if(w&&typeof w!=="number"){return f.fn.qtip.log.error.call(s,2,"newWidth must be of type number","updateWidth")}}x=s.elements.contentWrapper.siblings().add(s.elements.tip).add(s.elements.button);if(!w){if(typeof s.options.style.width.value=="number"){w=s.options.style.width.value}else{s.elements.tooltip.css({width:"auto"});x.hide();if(f.browser.msie){s.elements.wrapper.add(s.elements.contentWrapper.children()).css({zoom:"normal"})}w=s.getDimensions().width+1;if(!s.options.style.width.value){if(w>s.options.style.width.max){w=s.options.style.width.max}if(w").get(0).getContext){z=s.elements.tooltip.find(".qtip-tip canvas:first");x=z.get(0).getContext("2d");x.clearRect(0,0,300,300);y=z.parent("div[rel]:first").attr("rel");B=b(y,s.options.style.tip.size.width,s.options.style.tip.size.height);h.call(s,z,B,s.options.style.tip.color||s.options.style.border.color)}else{if(f.browser.msie){z=s.elements.tooltip.find('.qtip-tip [nodeName="shape"]');z.attr("fillcolor",s.options.style.tip.color||s.options.style.border.color)}}}if(s.options.style.border.radius>0){s.elements.tooltip.find(".qtip-betweenCorners").css({backgroundColor:s.options.style.border.color});if(f("").get(0).getContext){A=g(s.options.style.border.radius);s.elements.tooltip.find(".qtip-wrapper canvas").each(function(){x=f(this).get(0).getContext("2d");x.clearRect(0,0,300,300);y=f(this).parent("div[rel]:first").attr("rel");r.call(s,f(this),A[y],s.options.style.border.radius,s.options.style.border.color)})}else{if(f.browser.msie){s.elements.tooltip.find('.qtip-wrapper [nodeName="arc"]').each(function(){f(this).attr("fillcolor",s.options.style.border.color)})}}}return f.fn.qtip.log.error.call(s,1,f.fn.qtip.constants.EVENT_STYLE_UPDATED,"updateStyle")},updateContent:function(A,y){var z,x,w;if(!s.status.rendered){return f.fn.qtip.log.error.call(s,2,f.fn.qtip.constants.TOOLTIP_NOT_RENDERED,"updateContent")}else{if(!A){return f.fn.qtip.log.error.call(s,2,f.fn.qtip.constants.NO_CONTENT_PROVIDED,"updateContent")}}z=s.beforeContentUpdate.call(s,A);if(typeof z=="string"){A=z}else{if(z===false){return}}if(f.browser.msie){s.elements.contentWrapper.children().css({zoom:"normal"})}if(A.jquery&&A.length>0){A.clone(true).appendTo(s.elements.content).show()}else{s.elements.content.html(A)}x=s.elements.content.find("img[complete=false]");if(x.length>0){w=0;x.each(function(C){f('').load(function(){if(++w==x.length){B()}})})}else{B()}function B(){s.updateWidth();if(y!==false){if(s.options.position.type!=="static"){s.updatePosition(s.elements.tooltip.is(":visible"),true)}if(s.options.style.tip.corner!==false){n.call(s)}}}s.onContentUpdate.call(s);return f.fn.qtip.log.error.call(s,1,f.fn.qtip.constants.EVENT_CONTENT_UPDATED,"loadContent")},loadContent:function(w,z,A){var y;if(!s.status.rendered){return f.fn.qtip.log.error.call(s,2,f.fn.qtip.constants.TOOLTIP_NOT_RENDERED,"loadContent")}y=s.beforeContentLoad.call(s);if(y===false){return s}if(A=="post"){f.post(w,z,x)}else{f.get(w,z,x)}function x(B){s.onContentLoad.call(s);f.fn.qtip.log.error.call(s,1,f.fn.qtip.constants.EVENT_CONTENT_LOADED,"loadContent");s.updateContent(B)}return s},updateTitle:function(w){if(!s.status.rendered){return f.fn.qtip.log.error.call(s,2,f.fn.qtip.constants.TOOLTIP_NOT_RENDERED,"updateTitle")}else{if(!w){return f.fn.qtip.log.error.call(s,2,f.fn.qtip.constants.NO_CONTENT_PROVIDED,"updateTitle")}}returned=s.beforeTitleUpdate.call(s);if(returned===false){return s}if(s.elements.button){s.elements.button=s.elements.button.clone(true)}s.elements.title.html(w);if(s.elements.button){s.elements.title.prepend(s.elements.button)}s.onTitleUpdate.call(s);return f.fn.qtip.log.error.call(s,1,f.fn.qtip.constants.EVENT_TITLE_UPDATED,"updateTitle")},focus:function(A){var y,x,w,z;if(!s.status.rendered){return f.fn.qtip.log.error.call(s,2,f.fn.qtip.constants.TOOLTIP_NOT_RENDERED,"focus")}else{if(s.options.position.type=="static"){return f.fn.qtip.log.error.call(s,1,f.fn.qtip.constants.CANNOT_FOCUS_STATIC,"focus")}}y=parseInt(s.elements.tooltip.css("z-index"));x=6000+f("div.qtip[qtip]").length-1;if(!s.status.focused&&y!==x){z=s.beforeFocus.call(s,A);if(z===false){return s}f("div.qtip[qtip]").not(s.elements.tooltip).each(function(){if(f(this).qtip("api").status.rendered===true){w=parseInt(f(this).css("z-index"));if(typeof w=="number"&&w>-1){f(this).css({zIndex:parseInt(f(this).css("z-index"))-1})}f(this).qtip("api").status.focused=false}});s.elements.tooltip.css({zIndex:x});s.status.focused=true;s.onFocus.call(s,A);f.fn.qtip.log.error.call(s,1,f.fn.qtip.constants.EVENT_FOCUSED,"focus")}return s},disable:function(w){if(!s.status.rendered){return f.fn.qtip.log.error.call(s,2,f.fn.qtip.constants.TOOLTIP_NOT_RENDERED,"disable")}if(w){if(!s.status.disabled){s.status.disabled=true;f.fn.qtip.log.error.call(s,1,f.fn.qtip.constants.EVENT_DISABLED,"disable")}else{f.fn.qtip.log.error.call(s,1,f.fn.qtip.constants.TOOLTIP_ALREADY_DISABLED,"disable")}}else{if(s.status.disabled){s.status.disabled=false;f.fn.qtip.log.error.call(s,1,f.fn.qtip.constants.EVENT_ENABLED,"disable")}else{f.fn.qtip.log.error.call(s,1,f.fn.qtip.constants.TOOLTIP_ALREADY_ENABLED,"disable")}}return s},destroy:function(){var w,x,y;x=s.beforeDestroy.call(s);if(x===false){return s}if(s.status.rendered){s.options.show.when.target.unbind("mousemove.qtip",s.updatePosition);s.options.show.when.target.unbind("mouseout.qtip",s.hide);s.options.show.when.target.unbind(s.options.show.when.event+".qtip");s.options.hide.when.target.unbind(s.options.hide.when.event+".qtip");s.elements.tooltip.unbind(s.options.hide.when.event+".qtip");s.elements.tooltip.unbind("mouseover.qtip",s.focus);s.elements.tooltip.remove()}else{s.options.show.when.target.unbind(s.options.show.when.event+".qtip-create")}if(typeof s.elements.target.data("qtip")=="object"){y=s.elements.target.data("qtip").interfaces;if(typeof y=="object"&&y.length>0){for(w=0;w0){s.elements.target.data("qtip").current=y.length-1}else{s.elements.target.removeData("qtip")}s.onDestroy.call(s);f.fn.qtip.log.error.call(s,1,f.fn.qtip.constants.EVENT_DESTROYED,"destroy");return s.elements.target},getPosition:function(){var w,x;if(!s.status.rendered){return f.fn.qtip.log.error.call(s,2,f.fn.qtip.constants.TOOLTIP_NOT_RENDERED,"getPosition")}w=(s.elements.tooltip.css("display")!=="none")?false:true;if(w){s.elements.tooltip.css({visiblity:"hidden"}).show()}x=s.elements.tooltip.offset();if(w){s.elements.tooltip.css({visiblity:"visible"}).hide()}return x},getDimensions:function(){var w,x;if(!s.status.rendered){return f.fn.qtip.log.error.call(s,2,f.fn.qtip.constants.TOOLTIP_NOT_RENDERED,"getDimensions")}w=(!s.elements.tooltip.is(":visible"))?true:false;if(w){s.elements.tooltip.css({visiblity:"hidden"}).show()}x={height:s.elements.tooltip.outerHeight(),width:s.elements.tooltip.outerWidth()};if(w){s.elements.tooltip.css({visiblity:"visible"}).hide()}return x}})}function p(){var s,w,u,t,v,y,x;s=this;s.beforeRender.call(s);s.status.rendered=true;s.elements.tooltip='';s.elements.tooltip=f(s.elements.tooltip);s.elements.tooltip.appendTo(s.options.position.container);s.elements.tooltip.data("qtip",{current:0,interfaces:[s]});s.elements.wrapper=s.elements.tooltip.children("div:first");s.elements.contentWrapper=s.elements.wrapper.children("div:first").css({background:s.options.style.background});s.elements.content=s.elements.contentWrapper.children("div:first").css(q(s.options.style));if(f.browser.msie){s.elements.wrapper.add(s.elements.content).css({zoom:1})}if(s.options.hide.when.event=="unfocus"){s.elements.tooltip.attr("unfocus",true)}if(typeof s.options.style.width.value=="number"){s.updateWidth()}if(f("").get(0).getContext||f.browser.msie){if(s.options.style.border.radius>0){m.call(s)}else{s.elements.contentWrapper.css({border:s.options.style.border.width+"px solid "+s.options.style.border.color})}if(s.options.style.tip.corner!==false){e.call(s)}}else{s.elements.contentWrapper.css({border:s.options.style.border.width+"px solid "+s.options.style.border.color});s.options.style.border.radius=0;s.options.style.tip.corner=false;f.fn.qtip.log.error.call(s,2,f.fn.qtip.constants.CANVAS_VML_NOT_SUPPORTED,"render")}if((typeof s.options.content.text=="string"&&s.options.content.text.length>0)||(s.options.content.text.jquery&&s.options.content.text.length>0)){u=s.options.content.text}else{if(typeof s.elements.target.attr("title")=="string"&&s.elements.target.attr("title").length>0){u=s.elements.target.attr("title").replace("\\n","
");s.elements.target.attr("title","")}else{if(typeof s.elements.target.attr("alt")=="string"&&s.elements.target.attr("alt").length>0){u=s.elements.target.attr("alt").replace("\\n","
");s.elements.target.attr("alt","")}else{u=" ";f.fn.qtip.log.error.call(s,1,f.fn.qtip.constants.NO_VALID_CONTENT,"render")}}}if(s.options.content.title.text!==false){j.call(s)}s.updateContent(u);l.call(s);if(s.options.show.ready===true){s.show()}if(s.options.content.url!==false){t=s.options.content.url;v=s.options.content.data;y=s.options.content.method||"get";s.loadContent(t,v,y)}s.onRender.call(s);f.fn.qtip.log.error.call(s,1,f.fn.qtip.constants.EVENT_RENDERED,"render")}function m(){var F,z,t,B,x,E,u,G,D,y,w,C,A,s,v;F=this;F.elements.wrapper.find(".qtip-borderBottom, .qtip-borderTop").remove();t=F.options.style.border.width;B=F.options.style.border.radius;x=F.options.style.border.color||F.options.style.tip.color;E=g(B);u={};for(z in E){u[z]='
';if(f("").get(0).getContext){u[z]+=''}else{if(f.browser.msie){G=B*2+3;u[z]+=''}}u[z]+="
"}D=F.getDimensions().width-(Math.max(t,B)*2);y='
';w='
'+u.topLeft+u.topRight+y;F.elements.wrapper.prepend(w);C='
'+u.bottomLeft+u.bottomRight+y;F.elements.wrapper.append(C);if(f("").get(0).getContext){F.elements.wrapper.find("canvas").each(function(){A=E[f(this).parent("[rel]:first").attr("rel")];r.call(F,f(this),A,B,x)})}else{if(f.browser.msie){F.elements.tooltip.append('')}}s=Math.max(B,(B+(t-B)));v=Math.max(t-B,0);F.elements.contentWrapper.css({border:"0px solid "+x,borderWidth:v+"px "+s+"px"})}function r(u,w,s,t){var v=u.get(0).getContext("2d");v.fillStyle=t;v.beginPath();v.arc(w[0],w[1],s,0,Math.PI*2,false);v.fill()}function e(v){var t,s,x,u,w;t=this;if(t.elements.tip!==null){t.elements.tip.remove()}s=t.options.style.tip.color||t.options.style.border.color;if(t.options.style.tip.corner===false){return}else{if(!v){v=t.options.style.tip.corner}}x=b(v,t.options.style.tip.size.width,t.options.style.tip.size.height);t.elements.tip='
';if(f("").get(0).getContext){t.elements.tip+=''}else{if(f.browser.msie){u=t.options.style.tip.size.width+","+t.options.style.tip.size.height;w="m"+x[0][0]+","+x[0][1];w+=" l"+x[1][0]+","+x[1][1];w+=" "+x[2][0]+","+x[2][1];w+=" xe";t.elements.tip+='';t.elements.tip+='';t.elements.contentWrapper.css("position","relative")}}t.elements.tooltip.prepend(t.elements.tip+"
");t.elements.tip=t.elements.tooltip.find("."+t.options.style.classes.tip).eq(0);if(f("").get(0).getContext){h.call(t,t.elements.tip.find("canvas:first"),x,s)}if(v.search(/top/)!==-1&&f.browser.msie&&parseInt(f.browser.version.charAt(0))===6){t.elements.tip.css({marginTop:-4})}n.call(t,v)}function h(t,v,s){var u=t.get(0).getContext("2d");u.fillStyle=s;u.beginPath();u.moveTo(v[0][0],v[0][1]);u.lineTo(v[1][0],v[1][1]);u.lineTo(v[2][0],v[2][1]);u.fill()}function n(u){var t,w,s,x,v;t=this;if(t.options.style.tip.corner===false||!t.elements.tip){return}if(!u){u=t.elements.tip.attr("rel")}w=positionAdjust=(f.browser.msie)?1:0;t.elements.tip.css(u.match(/left|right|top|bottom/)[0],0);if(u.search(/top|bottom/)!==-1){if(f.browser.msie){if(parseInt(f.browser.version.charAt(0))===6){positionAdjust=(u.search(/top/)!==-1)?-3:1}else{positionAdjust=(u.search(/top/)!==-1)?1:2}}if(u.search(/Middle/)!==-1){t.elements.tip.css({left:"50%",marginLeft:-(t.options.style.tip.size.width/2)})}else{if(u.search(/Left/)!==-1){t.elements.tip.css({left:t.options.style.border.radius-w})}else{if(u.search(/Right/)!==-1){t.elements.tip.css({right:t.options.style.border.radius+w})}}}if(u.search(/top/)!==-1){t.elements.tip.css({top:-positionAdjust})}else{t.elements.tip.css({bottom:positionAdjust})}}else{if(u.search(/left|right/)!==-1){if(f.browser.msie){positionAdjust=(parseInt(f.browser.version.charAt(0))===6)?1:((u.search(/left/)!==-1)?1:2)}if(u.search(/Middle/)!==-1){t.elements.tip.css({top:"50%",marginTop:-(t.options.style.tip.size.height/2)})}else{if(u.search(/Top/)!==-1){t.elements.tip.css({top:t.options.style.border.radius-w})}else{if(u.search(/Bottom/)!==-1){t.elements.tip.css({bottom:t.options.style.border.radius+w})}}}if(u.search(/left/)!==-1){t.elements.tip.css({left:-positionAdjust})}else{t.elements.tip.css({right:positionAdjust})}}}s="padding-"+u.match(/left|right|top|bottom/)[0];x=t.options.style.tip.size[(s.search(/left|right/)!==-1)?"width":"height"];t.elements.tooltip.css("padding",0);t.elements.tooltip.css(s,x);if(f.browser.msie&&parseInt(f.browser.version.charAt(0))==6){v=parseInt(t.elements.tip.css("margin-top"))||0;v+=parseInt(t.elements.content.css("margin-top"))||0;t.elements.tip.css({marginTop:v})}}function j(){var s=this;if(s.elements.title!==null){s.elements.title.remove()}s.elements.title=f('
').css(q(s.options.style.title,true)).css({zoom:(f.browser.msie)?1:0}).prependTo(s.elements.contentWrapper);if(s.options.content.title.text){s.updateTitle.call(s,s.options.content.title.text)}if(s.options.content.title.button!==false&&typeof s.options.content.title.button=="string"){s.elements.button=f('').css(q(s.options.style.button,true)).html(s.options.content.title.button).prependTo(s.elements.title).click(function(t){if(!s.status.disabled){s.hide(t)}})}}function l(){var t,v,u,s;t=this;v=t.options.show.when.target;u=t.options.hide.when.target;if(t.options.hide.fixed){u=u.add(t.elements.tooltip)}if(t.options.hide.when.event=="inactive"){s=["click","dblclick","mousedown","mouseup","mousemove","mouseout","mouseenter","mouseleave","mouseover"];function y(z){if(t.status.disabled===true){return}clearTimeout(t.timers.inactive);t.timers.inactive=setTimeout(function(){f(s).each(function(){u.unbind(this+".qtip-inactive");t.elements.content.unbind(this+".qtip-inactive")});t.hide(z)},t.options.hide.delay)}}else{if(t.options.hide.fixed===true){t.elements.tooltip.bind("mouseover.qtip",function(){if(t.status.disabled===true){return}clearTimeout(t.timers.hide)})}}function x(z){if(t.status.disabled===true){return}if(t.options.hide.when.event=="inactive"){f(s).each(function(){u.bind(this+".qtip-inactive",y);t.elements.content.bind(this+".qtip-inactive",y)});y()}clearTimeout(t.timers.show);clearTimeout(t.timers.hide);t.timers.show=setTimeout(function(){t.show(z)},t.options.show.delay)}function w(z){if(t.status.disabled===true){return}if(t.options.hide.fixed===true&&t.options.hide.when.event.search(/mouse(out|leave)/i)!==-1&&f(z.relatedTarget).parents("div.qtip[qtip]").length>0){z.stopPropagation();z.preventDefault();clearTimeout(t.timers.hide);return false}clearTimeout(t.timers.show);clearTimeout(t.timers.hide);t.elements.tooltip.stop(true,true);t.timers.hide=setTimeout(function(){t.hide(z)},t.options.hide.delay)}if((t.options.show.when.target.add(t.options.hide.when.target).length===1&&t.options.show.when.event==t.options.hide.when.event&&t.options.hide.when.event!=="inactive")||t.options.hide.when.event=="unfocus"){t.cache.toggle=0;v.bind(t.options.show.when.event+".qtip",function(z){if(t.cache.toggle==0){x(z)}else{w(z)}})}else{v.bind(t.options.show.when.event+".qtip",x);if(t.options.hide.when.event!=="inactive"){u.bind(t.options.hide.when.event+".qtip",w)}}if(t.options.position.type.search(/(fixed|absolute)/)!==-1){t.elements.tooltip.bind("mouseover.qtip",t.focus)}if(t.options.position.target==="mouse"&&t.options.position.type!=="static"){v.bind("mousemove.qtip",function(z){t.cache.mouse={x:z.pageX,y:z.pageY};if(t.status.disabled===false&&t.options.position.adjust.mouse===true&&t.options.position.type!=="static"&&t.elements.tooltip.css("display")!=="none"){t.updatePosition(z)}})}}function o(u,v,A){var z,s,x,y,t,w;z=this;if(A.corner=="center"){return v.position}s=f.extend({},u);y={x:false,y:false};t={left:(s.left=f.fn.qtip.cache.screen.width+f.fn.qtip.cache.screen.scroll.left),top:(s.top=f.fn.qtip.cache.screen.height+f.fn.qtip.cache.screen.scroll.top)};x={left:(t.left&&(A.corner.search(/right/i)!=-1||(A.corner.search(/right/i)==-1&&!t.right))),right:(t.right&&(A.corner.search(/left/i)!=-1||(A.corner.search(/left/i)==-1&&!t.left))),top:(t.top&&A.corner.search(/top/i)==-1),bottom:(t.bottom&&A.corner.search(/bottom/i)==-1)};if(x.left){if(z.options.position.target!=="mouse"){s.left=v.position.left+v.dimensions.width}else{s.left=z.cache.mouse.x}y.x="Left"}else{if(x.right){if(z.options.position.target!=="mouse"){s.left=v.position.left-A.dimensions.width}else{s.left=z.cache.mouse.x-A.dimensions.width}y.x="Right"}}if(x.top){if(z.options.position.target!=="mouse"){s.top=v.position.top+v.dimensions.height}else{s.top=z.cache.mouse.y}y.y="top"}else{if(x.bottom){if(z.options.position.target!=="mouse"){s.top=v.position.top-A.dimensions.height}else{s.top=z.cache.mouse.y-A.dimensions.height}y.y="bottom"}}if(s.left<0){s.left=u.left;y.x=false}if(s.top<0){s.top=u.top;y.y=false}if(z.options.style.tip.corner!==false){s.corner=new String(A.corner);if(y.x!==false){s.corner=s.corner.replace(/Left|Right|Middle/,y.x)}if(y.y!==false){s.corner=s.corner.replace(/top|bottom/,y.y)}if(s.corner!==z.elements.tip.attr("rel")){e.call(z,s.corner)}}return s}function q(u,t){var v,s;v=f.extend(true,{},u);for(s in v){if(t===true&&s.search(/(tip|classes)/i)!==-1){delete v[s]}else{if(!t&&s.search(/(width|border|tip|title|classes|user)/i)!==-1){delete v[s]}}}return v}function c(s){if(typeof s.tip!=="object"){s.tip={corner:s.tip}}if(typeof s.tip.size!=="object"){s.tip.size={width:s.tip.size,height:s.tip.size}}if(typeof s.border!=="object"){s.border={width:s.border}}if(typeof s.width!=="object"){s.width={value:s.width}}if(typeof s.width.max=="string"){s.width.max=parseInt(s.width.max.replace(/([0-9]+)/i,"$1"))}if(typeof s.width.min=="string"){s.width.min=parseInt(s.width.min.replace(/([0-9]+)/i,"$1"))}if(typeof s.tip.size.x=="number"){s.tip.size.width=s.tip.size.x;delete s.tip.size.x}if(typeof s.tip.size.y=="number"){s.tip.size.height=s.tip.size.y;delete s.tip.size.y}return s}function a(){var s,t,u,x,v,w;s=this;u=[true,{}];for(t=0;t0){v.tip.size.width+=1}if(v.tip.size.height%2>0){v.tip.size.height+=1}if(v.tip.corner===true){v.tip.corner=(s.options.position.corner.tooltip==="center")?false:s.options.position.corner.tooltip}return v}function b(v,u,t){var s={bottomRight:[[0,0],[u,t],[u,0]],bottomLeft:[[0,0],[u,0],[0,t]],topRight:[[0,t],[u,0],[u,t]],topLeft:[[0,0],[0,t],[u,t]],topMiddle:[[0,t],[u/2,0],[u,t]],bottomMiddle:[[0,0],[u,0],[u/2,t]],rightMiddle:[[0,0],[u,t/2],[0,t]],leftMiddle:[[u,0],[u,t],[0,t/2]]};s.leftTop=s.bottomRight;s.rightTop=s.bottomLeft;s.leftBottom=s.topRight;s.rightBottom=s.topLeft;return s[v]}function g(s){var t;if(f("").get(0).getContext){t={topLeft:[s,s],topRight:[0,s],bottomLeft:[s,0],bottomRight:[0,0]}}else{if(f.browser.msie){t={topLeft:[-90,90,0],topRight:[-90,90,-s],bottomLeft:[90,270,0],bottomRight:[90,270,-s]}}}return t}function k(){var s,t,u;s=this;u=s.getDimensions();t='';d.extend(x.prototype,{_scroll:function(){var b=this.qtip.elements.overlay;b&&(b[0].style.top=d(a).scrollTop()+"px")},init:function(c){var e=c.tooltip;d("select, object").length<1&&(this.bgiframe=c.elements.bgiframe=d(Ba).appendTo(e),c._bind(e,"tooltipmove",this.adjustBGIFrame,this._ns,this)),this.redrawContainer=d("
",{id:S+"-rcontainer"}).appendTo(b.body),c.elements.overlay&&c.elements.overlay.addClass("qtipmodal-ie6fix")&&(c._bind(a,["scroll","resize"],this._scroll,this._ns,this),c._bind(e,["tooltipshow"],this._scroll,this._ns,this)),this.redraw()},adjustBGIFrame:function(){var a,b,c=this.qtip.tooltip,d={height:c.outerHeight(E),width:c.outerWidth(E)},e=this.qtip.plugins.tip,f=this.qtip.elements.tip;b=parseInt(c.css("borderLeftWidth"),10)||0,b={left:-b,top:-b},e&&f&&(a="x"===e.corner.precedance?[I,L]:[J,K],b[a[1]]-=f[a[0]]()),this.bgiframe.css(b).css(d)},redraw:function(){if(this.qtip.rendered<1||this.drawing)return this;var a,b,c,d,e=this.qtip.tooltip,f=this.qtip.options.style,g=this.qtip.options.position.container;return this.qtip.drawing=1,f.height&&e.css(J,f.height),f.width?e.css(I,f.width):(e.css(I,"").appendTo(this.redrawContainer),b=e.width(),1>b%2&&(b+=1),c=e.css("maxWidth")||"",d=e.css("minWidth")||"",a=(c+d).indexOf("%")>-1?g.width()/100:0,c=(c.indexOf("%")>-1?a:1*parseInt(c,10))||b,d=(d.indexOf("%")>-1?a:1*parseInt(d,10))||0,b=c+d?Math.min(Math.max(b,d),c):b,e.css(I,Math.round(b)).appendTo(g)),this.drawing=0,this},destroy:function(){this.bgiframe&&this.bgiframe.remove(),this.qtip._unbind([a,this.qtip.tooltip],this._ns)}}),Aa=R.ie6=function(a){return 6===da.ie?new x(a):E},Aa.initialize="render",B.ie6={"^content|style$":function(){this.redraw()}}})}(window,document); +//# sourceMappingURL=jquery.qtip.min.map \ No newline at end of file diff --git a/webapp/src/main/webapp/js/menupage/menumanagement_edit.js b/webapp/src/main/webapp/js/menupage/menumanagement_edit.js index e5266bdde..aef6bd54c 100644 --- a/webapp/src/main/webapp/js/menupage/menumanagement_edit.js +++ b/webapp/src/main/webapp/js/menupage/menumanagement_edit.js @@ -77,16 +77,16 @@ var menuManagementEdit = { $('input:checkbox[name=allSelected]').click(function(){ if ( this.checked ) { // if checked, select all the checkboxes - $('input:checkbox[name=classInClassGroup]').attr('checked','checked'); + $('input:checkbox[name=classInClassGroup]').prop('checked','checked'); } else { // if not checked, deselect all the checkboxes - $('input:checkbox[name=classInClassGroup]').removeAttr('checked'); + $('input:checkbox[name=classInClassGroup]').prop('checked', null); } }); $('input:checkbox[name=classInClassGroup]').click(function(){ - $('input:checkbox[name=allSelected]').removeAttr('checked'); + $('input:checkbox[name=allSelected]').prop('checked', null); }); }, validateMenuItemForm: function() { diff --git a/webapp/src/main/webapp/js/menupage/pageManagementUtils.js b/webapp/src/main/webapp/js/menupage/pageManagementUtils.js index 456092bbb..cebf38899 100644 --- a/webapp/src/main/webapp/js/menupage/pageManagementUtils.js +++ b/webapp/src/main/webapp/js/menupage/pageManagementUtils.js @@ -138,8 +138,8 @@ var pageManagementUtils = { }, initDisplay: function(){ //right side components - this.contentTypeSelectOptions.eq(0).attr('selected', 'selected'); - $('select#selectClassGroup option').eq(0).attr('selected', 'selected'); + this.contentTypeSelectOptions.eq(0).prop('selected', 'selected'); + $('select#selectClassGroup option').eq(0).prop('selected', 'selected'); //Why would you want to hide this? This hides everything // $("section#pageDetails").hide(); @@ -152,11 +152,11 @@ var pageManagementUtils = { //left side components //These depend on whether or not this is an existing item or not if(this.isAdd()) { - this.defaultTemplateRadio.attr('checked',true); + this.defaultTemplateRadio.prop('checked',true); //disable save button this.disablePageSave(); if(!this.isAddMenuItem()) { - this.isMenuCheckbox.attr('checked',false); + this.isMenuCheckbox.prop('checked',false); this.menuSection.hide(); } } @@ -243,7 +243,7 @@ var pageManagementUtils = { pageManagementUtils.classGroupSection.hide(); pageManagementUtils.fixedHTMLSection.hide(); pageManagementUtils.sparqlQuerySection.hide(); - pageManagementUtils.contentTypeSelectOptions.eq(0).attr('selected', 'selected'); + pageManagementUtils.contentTypeSelectOptions.eq(0).prop('selected', 'selected'); pageManagementUtils.contentTypeSelect.focus(); pageManagementUtils.adjustSaveButtonHeight(); pageManagementUtils.checkSelfContainedRadio(); @@ -287,7 +287,7 @@ var pageManagementUtils = { pageManagementUtils.sparqlQuerySection.hide(); pageManagementUtils.searchIndividualsSection.hide(); //Reset main content type drop-down - pageManagementUtils.contentTypeSelectOptions.eq(0).attr('selected', 'selected'); + pageManagementUtils.contentTypeSelectOptions.eq(0).prop('selected', 'selected'); if ( pageManagementUtils.leftSideDiv.css("height") != undefined ) { pageManagementUtils.leftSideDiv.css("height",""); if ( pageManagementUtils.leftSideDiv.height() < pageManagementUtils.rightSideDiv.height() ) { @@ -442,7 +442,7 @@ var pageManagementUtils = { }); $el.find("textarea").val(""); //resetting class group section as well so selection is reset if type changes - $el.find("select option:eq(0)").attr("selected", "selected"); + $el.find("select option:eq(0)").prop("selected", "selected"); }, checkTemplateForMultipleContent:function(contentTypeSelected) { @@ -454,7 +454,7 @@ var pageManagementUtils = { //alert the user that they should be picking custom template instead alert(pageManagementUtils.multipleContentWithDefaultTemplateError); //pick custom template - $('input:radio[name=selectedTemplate][value="custom"]').attr("checked", true); + $('input:radio[name=selectedTemplate][value="custom"]').prop("checked", true); pageManagementUtils.handleSelectCustomTemplate(); } @@ -698,7 +698,7 @@ var pageManagementUtils = { //doing this in clear inputs instead which will be triggered //every time content type is changed AS well as on more content button after //original content is cloned and stored - //$('select#selectClassGroup option').eq(0).attr('selected', 'selected'); + //$('select#selectClassGroup option').eq(0).prop('selected', 'selected'); pageManagementUtils.classesForClassGroup.addClass('hidden'); }, chooseClassGroup: function() { @@ -761,19 +761,19 @@ var pageManagementUtils = { $('input:checkbox[name=allSelected]').click(function(){ if ( this.checked ) { // if checked, select all the checkboxes for this particular section - $(this).closest("ul").find('input:checkbox[name=classInClassGroup]').attr('checked','checked'); - //$('input:checkbox[name=classInClassGroup]').attr('checked','checked'); + $(this).closest("ul").find('input:checkbox[name=classInClassGroup]').prop('checked','checked'); + //$('input:checkbox[name=classInClassGroup]').prop('checked','checked'); } else { // if not checked, deselect all the checkboxes - $(this).closest("ul").find('input:checkbox[name=classInClassGroup]').removeAttr('checked'); + $(this).closest("ul").find('input:checkbox[name=classInClassGroup]').prop('checked', null); - // $('input:checkbox[name=classInClassGroup]').removeAttr('checked'); + // $('input:checkbox[name=classInClassGroup]').prop('checked', null); } }); $('input:checkbox[name=classInClassGroup]').click(function(){ - $(this).closest("ul").find('input:checkbox[name=allSelected]').removeAttr('checked'); + $(this).closest("ul").find('input:checkbox[name=allSelected]').prop('checked', null); }); }, //This is SPECIFIC to VIVO so should be moved there updateInternalClassMessage:function(classGroupName) { //User has changed content type diff --git a/webapp/src/main/webapp/js/menupage/processClassGroupDataGetterContent.js b/webapp/src/main/webapp/js/menupage/processClassGroupDataGetterContent.js index 065e9583e..467ff6b99 100644 --- a/webapp/src/main/webapp/js/menupage/processClassGroupDataGetterContent.js +++ b/webapp/src/main/webapp/js/menupage/processClassGroupDataGetterContent.js @@ -95,19 +95,19 @@ var processClassGroupDataGetterContent = { pageContentSection.find('input:checkbox[name=allSelected]').click(function(){ if ( this.checked ) { // if checked, select all the checkboxes for this particular section - $(this).closest("ul").find('input:checkbox[name=classInClassGroup]').attr('checked','checked'); - //$('input:checkbox[name=classInClassGroup]').attr('checked','checked'); + $(this).closest("ul").find('input:checkbox[name=classInClassGroup]').prop('checked','checked'); + //$('input:checkbox[name=classInClassGroup]').prop('checked','checked'); } else { // if not checked, deselect all the checkboxes - $(this).closest("ul").find('input:checkbox[name=classInClassGroup]').removeAttr('checked'); + $(this).closest("ul").find('input:checkbox[name=classInClassGroup]').prop('checked', null); - // $('input:checkbox[name=classInClassGroup]').removeAttr('checked'); + // $('input:checkbox[name=classInClassGroup]').prop('checked', null); } }); pageContentSection.find('input:checkbox[name=classInClassGroup]').click(function(){ - $(this).closest("ul").find('input:checkbox[name=allSelected]').removeAttr('checked'); + $(this).closest("ul").find('input:checkbox[name=allSelected]').prop('checked', null); }); }, bindEventHandlers:function(pageContentSection) { diff --git a/webapp/src/main/webapp/js/menupage/processIndividualsForClassesDataGetterContent.js b/webapp/src/main/webapp/js/menupage/processIndividualsForClassesDataGetterContent.js index a50423657..c79f63a2f 100644 --- a/webapp/src/main/webapp/js/menupage/processIndividualsForClassesDataGetterContent.js +++ b/webapp/src/main/webapp/js/menupage/processIndividualsForClassesDataGetterContent.js @@ -32,10 +32,10 @@ var processIndividualsForClassesDataGetterContent = { var numberSelected = classesSelected.length; var i; //Uncheck all since default is checked - pageContentSection.find("input[name='classInClassGroup']").removeAttr("checked"); + pageContentSection.find("input[name='classInClassGroup']").prop("checked", null); for(i = 0; i < numberSelected; i++) { var classSelected = classesSelected[i]; - pageContentSection.find("input[name='classInClassGroup'][value='" + classSelected + "']").attr("checked", "checked"); + pageContentSection.find("input[name='classInClassGroup'][value='" + classSelected + "']").prop("checked", "checked"); } //If number of classes selected is not equal to total number of classes, uncheck all @@ -45,7 +45,7 @@ var processIndividualsForClassesDataGetterContent = { if(resultsClasses != null) { var numberClasses = resultsClasses.length; if(numberClasses != numberSelected) { - pageContentSection.find("input[name='allSelected']").removeAttr("checked"); + pageContentSection.find("input[name='allSelected']").prop("checked", null); } } } diff --git a/webapp/src/main/webapp/js/searchDownload.js b/webapp/src/main/webapp/js/searchDownload.js index 889bf9c2f..d449cb045 100644 --- a/webapp/src/main/webapp/js/searchDownload.js +++ b/webapp/src/main/webapp/js/searchDownload.js @@ -2,49 +2,39 @@ $(document).ready(function(){ // This function creates and styles the "qTip" tooltip that displays the resource uri and the rdf link when the user clicks the uri/rdf icon. - - $('img#downloadIcon').each(function() - { - $(this).qtip( + + $('head').append(''); + + $('img#downloadIcon').qtip( { + prerender: true, // We need this for the .click() event listener on 'a.close' content: { - prerender: true, // We need this for the .click() event listener on 'a.close' text: '
' +'

' +'

' +'
' +'
close
' - +'
Download the results from this search
' - +'
download results in XML format
' - +'
download results in CSV format
' + +'

' + +'

download results in XML format

' + +'

download results in CSV format

' +'
' - }, position: { - corner: { - target: 'bottomLeft', - tooltip: 'topLeft' - } + my: 'top left', + at: 'bottom left' }, show: { - when: {event: 'click'} + event: 'click' }, hide: { - fixed: true, // Make it fixed so it can be hovered over and interacted with - when: { - target: $('a.close'), - event: 'click' - } + event: 'click' }, style: { - padding: '1em', - width: 500, - backgroundColor: '#f1f2ee' + classes: 'downloadTip', + width: 500 } }); - }); - $( "#slider-vertical" ).slider({ orientation: "vertical", range: "min", diff --git a/webapp/src/main/webapp/templates/freemarker/body/accounts/userAccounts-associateProfilePanel.ftl b/webapp/src/main/webapp/templates/freemarker/body/accounts/userAccounts-associateProfilePanel.ftl index d768e6355..074fe546b 100644 --- a/webapp/src/main/webapp/templates/freemarker/body/accounts/userAccounts-associateProfilePanel.ftl +++ b/webapp/src/main/webapp/templates/freemarker/body/accounts/userAccounts-associateProfilePanel.ftl @@ -5,7 +5,7 @@ <#assign strings = i18n() /> ${stylesheets.add('', - '')} + '')}
@@ -85,7 +85,8 @@ var associateProfileFieldsData = { }; -${scripts.add('', - '', +${scripts.add('', + '', + '', '')} diff --git a/webapp/src/main/webapp/templates/freemarker/body/accounts/userAccounts-edit.ftl b/webapp/src/main/webapp/templates/freemarker/body/accounts/userAccounts-edit.ftl index 82a6fd225..fab709078 100644 --- a/webapp/src/main/webapp/templates/freemarker/body/accounts/userAccounts-edit.ftl +++ b/webapp/src/main/webapp/templates/freemarker/body/accounts/userAccounts-edit.ftl @@ -89,7 +89,8 @@ ${stylesheets.add('')} ${stylesheets.add('')} -${scripts.add('', - '', +${scripts.add('', + '', + '', '', '')} diff --git a/webapp/src/main/webapp/templates/freemarker/body/accounts/userAccounts-myAccount.ftl b/webapp/src/main/webapp/templates/freemarker/body/accounts/userAccounts-myAccount.ftl index f116f2b3d..3802c7d39 100644 --- a/webapp/src/main/webapp/templates/freemarker/body/accounts/userAccounts-myAccount.ftl +++ b/webapp/src/main/webapp/templates/freemarker/body/accounts/userAccounts-myAccount.ftl @@ -87,5 +87,5 @@ ${stylesheets.add('')} ${stylesheets.add('')} -${scripts.add('', +${scripts.add('', '')} \ No newline at end of file diff --git a/webapp/src/main/webapp/templates/freemarker/body/accounts/userAccounts-myProxiesPanel.ftl b/webapp/src/main/webapp/templates/freemarker/body/accounts/userAccounts-myProxiesPanel.ftl index 7ab9f1b19..d36aeb428 100644 --- a/webapp/src/main/webapp/templates/freemarker/body/accounts/userAccounts-myProxiesPanel.ftl +++ b/webapp/src/main/webapp/templates/freemarker/body/accounts/userAccounts-myProxiesPanel.ftl @@ -61,9 +61,9 @@ var i18nStrings = { ${stylesheets.add('', - '')} + '')} ${scripts.add('', '', '', - '')} \ No newline at end of file + '')} \ No newline at end of file diff --git a/webapp/src/main/webapp/templates/freemarker/body/admin/searchIndex.ftl b/webapp/src/main/webapp/templates/freemarker/body/admin/searchIndex.ftl index d93233bbc..71ac5907d 100644 --- a/webapp/src/main/webapp/templates/freemarker/body/admin/searchIndex.ftl +++ b/webapp/src/main/webapp/templates/freemarker/body/admin/searchIndex.ftl @@ -20,4 +20,4 @@ ${stylesheets.add('')} ${scripts.add('')} -${scripts.add('')} +${scripts.add('')} diff --git a/webapp/src/main/webapp/templates/freemarker/body/contactForm/contactForm-form.ftl b/webapp/src/main/webapp/templates/freemarker/body/contactForm/contactForm-form.ftl index 186e383dc..d6fc209c0 100644 --- a/webapp/src/main/webapp/templates/freemarker/body/contactForm/contactForm-form.ftl +++ b/webapp/src/main/webapp/templates/freemarker/body/contactForm/contactForm-form.ftl @@ -52,7 +52,7 @@ ${stylesheets.add('')} ${scripts.add('', '', - '')} + '')} ', +${scripts.add('', + '', '', '')} diff --git a/webapp/src/main/webapp/templates/freemarker/body/imageUpload/imageUpload-newImage.ftl b/webapp/src/main/webapp/templates/freemarker/body/imageUpload/imageUpload-newImage.ftl index 970eca691..35658839e 100644 --- a/webapp/src/main/webapp/templates/freemarker/body/imageUpload/imageUpload-newImage.ftl +++ b/webapp/src/main/webapp/templates/freemarker/body/imageUpload/imageUpload-newImage.ftl @@ -2,7 +2,8 @@ <#-- Upload a replacement main image for an Individual. --> -${scripts.add('', +${scripts.add('', + '', '')} ${stylesheets.add('')} @@ -37,5 +38,5 @@ ${stylesheets.add(' - i18n_confirmDelete = ${i18n.confirm_delete} + i18n_confirmDelete = "${i18n.confirm_delete}"; diff --git a/webapp/src/main/webapp/templates/freemarker/body/imageUpload/imageUpload-replaceImage.ftl b/webapp/src/main/webapp/templates/freemarker/body/imageUpload/imageUpload-replaceImage.ftl index d4adf239e..fd1378bf3 100644 --- a/webapp/src/main/webapp/templates/freemarker/body/imageUpload/imageUpload-replaceImage.ftl +++ b/webapp/src/main/webapp/templates/freemarker/body/imageUpload/imageUpload-replaceImage.ftl @@ -2,7 +2,8 @@ <#-- Upload a replacement main image for an Individual. --> -${scripts.add('', +${scripts.add('', + '', '')} ${stylesheets.add('')} @@ -38,5 +39,5 @@ ${stylesheets.add(' - i18n_confirmDelete = "${i18n.confirm_delete}" + i18n_confirmDelete = "${i18n.confirm_delete}"; diff --git a/webapp/src/main/webapp/templates/freemarker/body/individual/individual-menu.ftl b/webapp/src/main/webapp/templates/freemarker/body/individual/individual-menu.ftl index 40a901d1b..217e91d91 100644 --- a/webapp/src/main/webapp/templates/freemarker/body/individual/individual-menu.ftl +++ b/webapp/src/main/webapp/templates/freemarker/body/individual/individual-menu.ftl @@ -43,7 +43,7 @@ ${stylesheets.add('', '')} - ${headScripts.add('')} + ${headScripts.add('')} <#assign positionPredicate = "${namespaces.display}menuPosition" /> diff --git a/webapp/src/main/webapp/templates/freemarker/body/individual/individual-vitro.ftl b/webapp/src/main/webapp/templates/freemarker/body/individual/individual-vitro.ftl index 13c7373d9..c421460bf 100644 --- a/webapp/src/main/webapp/templates/freemarker/body/individual/individual-vitro.ftl +++ b/webapp/src/main/webapp/templates/freemarker/body/individual/individual-vitro.ftl @@ -98,9 +98,10 @@ -${stylesheets.add('')} +${stylesheets.add('', + '')} -${headScripts.add('', +${headScripts.add('', '')} ${scripts.add('', @@ -108,5 +109,5 @@ ${scripts.add('')} diff --git a/webapp/src/main/webapp/templates/freemarker/body/individual/manageLabelsForIndividual.ftl b/webapp/src/main/webapp/templates/freemarker/body/individual/manageLabelsForIndividual.ftl index ec0b78a2a..24fe1f2ce 100644 --- a/webapp/src/main/webapp/templates/freemarker/body/individual/manageLabelsForIndividual.ftl +++ b/webapp/src/main/webapp/templates/freemarker/body/individual/manageLabelsForIndividual.ftl @@ -102,9 +102,9 @@ var i18nStrings = { }; -${stylesheets.add('')} +${stylesheets.add('')} ${scripts.add('', - '', + '', '')} diff --git a/webapp/src/main/webapp/templates/freemarker/body/individual/viewLabelsForIndividual.ftl b/webapp/src/main/webapp/templates/freemarker/body/individual/viewLabelsForIndividual.ftl index 4a55168f2..abdce527e 100644 --- a/webapp/src/main/webapp/templates/freemarker/body/individual/viewLabelsForIndividual.ftl +++ b/webapp/src/main/webapp/templates/freemarker/body/individual/viewLabelsForIndividual.ftl @@ -38,8 +38,8 @@ -${stylesheets.add('')} +${stylesheets.add('')} ${scripts.add('', - '')} + '')} diff --git a/webapp/src/main/webapp/templates/freemarker/body/manageproxies/manageProxies-list.ftl b/webapp/src/main/webapp/templates/freemarker/body/manageproxies/manageProxies-list.ftl index 8405b3096..c1752bae4 100644 --- a/webapp/src/main/webapp/templates/freemarker/body/manageproxies/manageProxies-list.ftl +++ b/webapp/src/main/webapp/templates/freemarker/body/manageproxies/manageProxies-list.ftl @@ -196,10 +196,11 @@ var i18nStrings = { ${stylesheets.add('')} ${stylesheets.add('')} ${stylesheets.add('')} -${stylesheets.add('')} +${stylesheets.add('')} -${scripts.add('', - '')} +${scripts.add('', + '', + '')} ${scripts.add('', '', '')} diff --git a/webapp/src/main/webapp/templates/freemarker/body/pagemanagement/pageList.ftl b/webapp/src/main/webapp/templates/freemarker/body/pagemanagement/pageList.ftl index d149f60cb..9a7a44e80 100644 --- a/webapp/src/main/webapp/templates/freemarker/body/pagemanagement/pageList.ftl +++ b/webapp/src/main/webapp/templates/freemarker/body/pagemanagement/pageList.ftl @@ -78,10 +78,10 @@ confirmPageDeletion: '${i18n().confirm_page_deletion}' }; -${stylesheets.add('', +${stylesheets.add('', '')} -${scripts.add('')} +${scripts.add('')} ${scripts.add('')} ${scripts.add('')} ${scripts.add('')} diff --git a/webapp/src/main/webapp/templates/freemarker/body/search/search-pagedResults.ftl b/webapp/src/main/webapp/templates/freemarker/body/search/search-pagedResults.ftl index b701ccb57..baa2dc6a4 100644 --- a/webapp/src/main/webapp/templates/freemarker/body/search/search-pagedResults.ftl +++ b/webapp/src/main/webapp/templates/freemarker/body/search/search-pagedResults.ftl @@ -109,10 +109,11 @@
${stylesheets.add('', - '')} + '', + '')} ${headScripts.add('', - '', + '', '' )} diff --git a/webapp/src/main/webapp/templates/freemarker/body/siteAdmin/siteAdmin-classHierarchy.ftl b/webapp/src/main/webapp/templates/freemarker/body/siteAdmin/siteAdmin-classHierarchy.ftl index 123322d67..6c2c80340 100644 --- a/webapp/src/main/webapp/templates/freemarker/body/siteAdmin/siteAdmin-classHierarchy.ftl +++ b/webapp/src/main/webapp/templates/freemarker/body/siteAdmin/siteAdmin-classHierarchy.ftl @@ -59,6 +59,6 @@ $(document).ready(function() { ${stylesheets.add('')} -${scripts.add('', +${scripts.add('', '')} diff --git a/webapp/src/main/webapp/templates/freemarker/body/siteAdmin/siteAdmin-dataInput.ftl b/webapp/src/main/webapp/templates/freemarker/body/siteAdmin/siteAdmin-dataInput.ftl index c79a7c90b..d53727723 100644 --- a/webapp/src/main/webapp/templates/freemarker/body/siteAdmin/siteAdmin-dataInput.ftl +++ b/webapp/src/main/webapp/templates/freemarker/body/siteAdmin/siteAdmin-dataInput.ftl @@ -23,7 +23,7 @@
-${stylesheets.add('')} +${stylesheets.add('')} -${scripts.add('', +${scripts.add('', '')} \ No newline at end of file diff --git a/webapp/src/main/webapp/templates/freemarker/body/siteAdmin/siteAdmin-fauxPropertiesList.ftl b/webapp/src/main/webapp/templates/freemarker/body/siteAdmin/siteAdmin-fauxPropertiesList.ftl index 3f3260eb4..f3618ba02 100644 --- a/webapp/src/main/webapp/templates/freemarker/body/siteAdmin/siteAdmin-fauxPropertiesList.ftl +++ b/webapp/src/main/webapp/templates/freemarker/body/siteAdmin/siteAdmin-fauxPropertiesList.ftl @@ -103,9 +103,7 @@ @@ -118,6 +116,6 @@ $(document).ready(function() { ${stylesheets.add('')} -${scripts.add('', +${scripts.add('', '')} diff --git a/webapp/src/main/webapp/templates/freemarker/body/siteAdmin/siteAdmin-objectPropHierarchy.ftl b/webapp/src/main/webapp/templates/freemarker/body/siteAdmin/siteAdmin-objectPropHierarchy.ftl index b0f60fa25..457eb8f42 100644 --- a/webapp/src/main/webapp/templates/freemarker/body/siteAdmin/siteAdmin-objectPropHierarchy.ftl +++ b/webapp/src/main/webapp/templates/freemarker/body/siteAdmin/siteAdmin-objectPropHierarchy.ftl @@ -73,6 +73,6 @@ $(document).ready(function() { ${stylesheets.add('')} -${scripts.add('', +${scripts.add('', '')} diff --git a/webapp/src/main/webapp/templates/freemarker/edit/forms/autoCompleteObjectPropForm.ftl b/webapp/src/main/webapp/templates/freemarker/edit/forms/autoCompleteObjectPropForm.ftl index 457a02d31..0d5040d33 100644 --- a/webapp/src/main/webapp/templates/freemarker/edit/forms/autoCompleteObjectPropForm.ftl +++ b/webapp/src/main/webapp/templates/freemarker/edit/forms/autoCompleteObjectPropForm.ftl @@ -134,12 +134,12 @@ Also multiple types parameter set to true only if more than one type returned--> edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.generators.AddAttendeeRoleToPersonGenerator --> -${stylesheets.add('')} +${stylesheets.add('')} ${stylesheets.add('')} ${stylesheets.add('')} - ${scripts.add('', + ${scripts.add('', '', '', '')} diff --git a/webapp/src/main/webapp/templates/freemarker/edit/forms/pageManagement.ftl b/webapp/src/main/webapp/templates/freemarker/edit/forms/pageManagement.ftl index c63a0fa6f..86e7ac3c0 100644 --- a/webapp/src/main/webapp/templates/freemarker/edit/forms/pageManagement.ftl +++ b/webapp/src/main/webapp/templates/freemarker/edit/forms/pageManagement.ftl @@ -196,7 +196,7 @@ ${stylesheets.add('')} ${stylesheets.add('')} -${scripts.add('')} +${scripts.add('')} ${scripts.add('')} ${scripts.add('')} ${scripts.add('')} diff --git a/webapp/src/main/webapp/templates/freemarker/page/partials/developer.ftl b/webapp/src/main/webapp/templates/freemarker/page/partials/developer.ftl index efc60beee..54ea51f45 100644 --- a/webapp/src/main/webapp/templates/freemarker/page/partials/developer.ftl +++ b/webapp/src/main/webapp/templates/freemarker/page/partials/developer.ftl @@ -3,7 +3,7 @@
${scripts.add('')} -${scripts.add('')} +${scripts.add('')} diff --git a/webapp/src/main/webapp/templates/freemarker/page/partials/headScripts.ftl b/webapp/src/main/webapp/templates/freemarker/page/partials/headScripts.ftl index 61c7df455..bd45f204e 100644 --- a/webapp/src/main/webapp/templates/freemarker/page/partials/headScripts.ftl +++ b/webapp/src/main/webapp/templates/freemarker/page/partials/headScripts.ftl @@ -6,7 +6,8 @@ var i18nStrings = { allCapitalized: '${i18n().all_capitalized}', }; - + + <#-- script for enabling new HTML5 semantic markup in IE browsers --> From 1c0dcd040c8fe7e53efa61eb27fbb3e42f4da1a0 Mon Sep 17 00:00:00 2001 From: Graham Triggs Date: Wed, 14 Dec 2016 19:23:54 +0000 Subject: [PATCH 10/49] Update Jena to 3.1.1, JFact to 4.0.4 and httpcomponents to 4.4 --- .../webapp/dao/jena/RDFServiceGraph.java | 11 +++++++ .../adapters/AbstractModelDecorator.java | 30 ++++++++++++++++++ .../adapters/AbstractOntModelDecorator.java | 31 +++++++++++++++++++ .../impl/virtuoso/RDFServiceVirtuoso.java | 7 +---- dependencies/pom.xml | 21 +++++++------ 5 files changed, 84 insertions(+), 16 deletions(-) diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/RDFServiceGraph.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/RDFServiceGraph.java index 651a4e368..e591f4fa2 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/RDFServiceGraph.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/RDFServiceGraph.java @@ -7,6 +7,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; +import java.util.function.Supplier; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -524,6 +525,16 @@ public class RDFServiceGraph implements GraphWithPerform { return null; } + @Override + public void execute(Runnable runnable) { + + } + + @Override + public T calculate(Supplier supplier) { + return null; + } + @Override public boolean transactionsSupported() { return true; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/adapters/AbstractModelDecorator.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/adapters/AbstractModelDecorator.java index e9c19a486..c9d6c384f 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/adapters/AbstractModelDecorator.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/adapters/AbstractModelDecorator.java @@ -10,6 +10,7 @@ import java.util.Calendar; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.function.Supplier; import org.apache.jena.datatypes.RDFDatatype; import org.apache.jena.graph.Graph; @@ -1078,4 +1079,33 @@ public abstract class AbstractModelDecorator implements Model { return inner.isClosed(); } + @Override + public Statement getRequiredProperty(Resource resource, Property property, String s) { + return inner.getRequiredProperty(resource, property, s); + } + + @Override + public Statement getProperty(Resource resource, Property property, String s) { + return inner.getProperty(resource, property, s); + } + + @Override + public void executeInTxn(Runnable runnable) { + inner.executeInTxn(runnable); + } + + @Override + public T calculateInTxn(Supplier supplier) { + return inner.calculateInTxn(supplier); + } + + @Override + public PrefixMapping clearNsPrefixMap() { + return inner.clearNsPrefixMap(); + } + + @Override + public int numPrefixes() { + return inner.numPrefixes(); + } } diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/adapters/AbstractOntModelDecorator.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/adapters/AbstractOntModelDecorator.java index 653f5372b..6712b9501 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/adapters/AbstractOntModelDecorator.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/adapters/AbstractOntModelDecorator.java @@ -11,6 +11,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.function.Supplier; import org.apache.jena.datatypes.RDFDatatype; import org.apache.jena.graph.Graph; @@ -1775,4 +1776,34 @@ public abstract class AbstractOntModelDecorator implements OntModel { public Model writeAll(OutputStream out, String lang, String base) { return inner.writeAll(out, lang, base); } + + @Override + public Statement getRequiredProperty(Resource resource, Property property, String s) { + return inner.getRequiredProperty(resource, property, s); + } + + @Override + public Statement getProperty(Resource resource, Property property, String s) { + return inner.getProperty(resource, property, s); + } + + @Override + public void executeInTxn(Runnable runnable) { + inner.executeInTxn(runnable); + } + + @Override + public T calculateInTxn(Supplier supplier) { + return inner.calculateInTxn(supplier); + } + + @Override + public PrefixMapping clearNsPrefixMap() { + return inner.clearNsPrefixMap(); + } + + @Override + public int numPrefixes() { + return inner.numPrefixes(); + } } diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/virtuoso/RDFServiceVirtuoso.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/virtuoso/RDFServiceVirtuoso.java index 1c7ff10a0..08ab76046 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/virtuoso/RDFServiceVirtuoso.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/virtuoso/RDFServiceVirtuoso.java @@ -127,12 +127,7 @@ public class RDFServiceVirtuoso extends RDFServiceSparql { private HttpPost createHttpRequest(String updateString) { HttpPost meth = new HttpPost(updateEndpointURI); meth.addHeader("Content-Type", "application/sparql-query"); - try { - meth.setEntity(new StringEntity(updateString, "UTF-8")); - } catch (UnsupportedEncodingException e) { - // UTF-8 is unsupported? - throw new RuntimeException(e); - } + meth.setEntity(new StringEntity(updateString, "UTF-8")); return meth; } diff --git a/dependencies/pom.xml b/dependencies/pom.xml index 5a5a45909..1246f2f0e 100644 --- a/dependencies/pom.xml +++ b/dependencies/pom.xml @@ -150,48 +150,49 @@ net.sourceforge.owlapi jfact - 4.0.0 + 4.0.4 net.sourceforge.owlapi owlapi-distribution - 4.0.1 - + 4.2.7 + + org.apache.httpcomponents httpcore - 4.2.4 + 4.4 org.apache.httpcomponents httpmime - 4.2.5 + 4.4 org.apache.jena jena-arq - 3.1.0 + 3.1.1 org.apache.jena jena-core - 3.1.0 + 3.1.1 org.apache.jena jena-sdb - 3.1.0 + 3.1.1 org.apache.jena jena-tdb - 3.1.0 + 3.1.1 org.apache.solr From 2efe4b4a87c9da313590f394013e849314139cfc Mon Sep 17 00:00:00 2001 From: Graham Triggs Date: Wed, 14 Dec 2016 22:04:13 +0000 Subject: [PATCH 11/49] Update ARQ URLs for Jena 3 --- .../edu/cornell/mannlib/vitro/webapp/dao/VitroVocabulary.java | 2 +- .../cornell/mannlib/vitro/webapp/dao/jena/JenaBaseDao.java | 2 +- .../cornell/mannlib/vitro/webapp/dao/jena/JenaModelUtils.java | 4 ++-- webapp/src/main/webapp/admin/conceptRepair.jsp | 2 +- webapp/src/main/webapp/admin/removeBadRestrictions.jsp | 2 +- webapp/src/main/webapp/config/listViewConfig-default.xml | 2 +- webapp/src/main/webapp/config/listViewConfig-hasElement.xml | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/VitroVocabulary.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/VitroVocabulary.java index 1b9054933..0234a8913 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/VitroVocabulary.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/VitroVocabulary.java @@ -33,7 +33,7 @@ public class VitroVocabulary { public static final String OWL_ONTOLOGY = OWL+"Ontology"; public static final String OWL_THING = OWL+"Thing"; - public static final String AFN = "http://jena.hpl.hp.com/ARQ/function#"; + public static final String AFN = "http://jena.apache.org/ARQ/function#"; public static final String label = vitroURI + "label"; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/JenaBaseDao.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/JenaBaseDao.java index c6b9edade..cb7214c8c 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/JenaBaseDao.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/JenaBaseDao.java @@ -1171,7 +1171,7 @@ public class JenaBaseDao extends JenaBaseDaoCon { String describeQueryStr = "DESCRIBE <" + res.getURI() + ">" ; -// ? "PREFIX afn: \n\n" + +// ? "PREFIX afn: \n\n" + // "DESCRIBE ?bnode \n" + // "WHERE { \n" + // " FILTER(afn:bnode(?bnode) = \"" + res.getId().toString() + "\")\n" + diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/JenaModelUtils.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/JenaModelUtils.java index ca1aac69a..cc933e02f 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/JenaModelUtils.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/JenaModelUtils.java @@ -262,7 +262,7 @@ public class JenaModelUtils { dataset.getLock().enterCriticalSection(Lock.READ); try { StringBuffer buff = new StringBuffer(); - buff.append("PREFIX afn: \n") + buff.append("PREFIX afn: \n") .append("CONSTRUCT { \n") .append(" ?res <" + property.getURI() + "> ?o } WHERE { \n"); if (graphURI != null) { @@ -294,7 +294,7 @@ public class JenaModelUtils { StringBuffer describeQueryStrBuff = new StringBuffer() .append("PREFIX rdf: \n") - .append("PREFIX afn: \n") + .append("PREFIX afn: \n") .append("DESCRIBE ?res WHERE { \n"); if (graphURI != null) { describeQueryStrBuff diff --git a/webapp/src/main/webapp/admin/conceptRepair.jsp b/webapp/src/main/webapp/admin/conceptRepair.jsp index 548daa5c1..09c67e7c3 100644 --- a/webapp/src/main/webapp/admin/conceptRepair.jsp +++ b/webapp/src/main/webapp/admin/conceptRepair.jsp @@ -17,7 +17,7 @@ if (conceptIdStr != null) { String describeQueryStr = - "PREFIX afn: \n\n" + + "PREFIX afn: \n\n" + "DESCRIBE ?bnode \n" + "WHERE { \n" + " FILTER(afn:bnode(?bnode) = \"" + conceptIdStr + "\")\n" + diff --git a/webapp/src/main/webapp/admin/removeBadRestrictions.jsp b/webapp/src/main/webapp/admin/removeBadRestrictions.jsp index e0a9a8fe8..355dfe1c7 100644 --- a/webapp/src/main/webapp/admin/removeBadRestrictions.jsp +++ b/webapp/src/main/webapp/admin/removeBadRestrictions.jsp @@ -63,7 +63,7 @@ private Model describeBnode(String bnodeId) { String describeQueryStr = - "PREFIX afn: \n\n" + + "PREFIX afn: \n\n" + "DESCRIBE ?bnode \n" + "WHERE { \n" + " FILTER(afn:bnode(?bnode) = \"" + bnodeId + "\")\n" + diff --git a/webapp/src/main/webapp/config/listViewConfig-default.xml b/webapp/src/main/webapp/config/listViewConfig-default.xml index 7c7327152..3460f6f66 100644 --- a/webapp/src/main/webapp/config/listViewConfig-default.xml +++ b/webapp/src/main/webapp/config/listViewConfig-default.xml @@ -7,7 +7,7 @@ - PREFIX afn: <http://jena.hpl.hp.com/ARQ/function#> + PREFIX afn: <http://jena.apache.org/ARQ/function#> PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> PREFIX vitro: <http://vitro.mannlib.cornell.edu/ns/vitro/0.7#> diff --git a/webapp/src/main/webapp/config/listViewConfig-hasElement.xml b/webapp/src/main/webapp/config/listViewConfig-hasElement.xml index 04b4ee24e..6ab0c5ab4 100644 --- a/webapp/src/main/webapp/config/listViewConfig-hasElement.xml +++ b/webapp/src/main/webapp/config/listViewConfig-hasElement.xml @@ -8,7 +8,7 @@ PREFIX display: <http://vitro.mannlib.cornell.edu/ontologies/display/1.1#> - PREFIX afn: <http://jena.hpl.hp.com/ARQ/function#> + PREFIX afn: <http://jena.apache.org/ARQ/function#> SELECT ?menuItem (afn:localname(?menuItem) AS ?menuItemName) From 1a292d80111112fbfc7a3d234662ede7a489b120 Mon Sep 17 00:00:00 2001 From: Graham Triggs Date: Fri, 16 Dec 2016 18:47:17 +0000 Subject: [PATCH 12/49] [VIVO-1309] [VIVO-1307] Update DWR to version 3.0.2 and remove dom4j --- dependencies/pom.xml | 8 +- webapp/src/main/webapp/WEB-INF/dwr.xml | 2 + webapp/src/main/webapp/WEB-INF/web.xml | 2 +- webapp/src/main/webapp/js/edit/entityRetry.js | 6 +- webapp/src/main/webapp/js/ents_edit.js | 95 ++++++++++--------- webapp/src/main/webapp/js/ents_retry.js | 6 +- webapp/src/main/webapp/js/vitro.js | 26 ++--- .../edit/specific/ents_edit_head.jsp | 10 +- 8 files changed, 81 insertions(+), 74 deletions(-) diff --git a/dependencies/pom.xml b/dependencies/pom.xml index 1246f2f0e..9742a0fdf 100644 --- a/dependencies/pom.xml +++ b/dependencies/pom.xml @@ -56,12 +56,12 @@ cxf-xjc-ts 2.6.2 - - + + @@ -202,7 +202,7 @@ org.directwebremoting dwr - 2.0.M2.8 + 3.0.2-RELEASE org.freemarker diff --git a/webapp/src/main/webapp/WEB-INF/dwr.xml b/webapp/src/main/webapp/WEB-INF/dwr.xml index 21fd9445c..b17f2de58 100755 --- a/webapp/src/main/webapp/WEB-INF/dwr.xml +++ b/webapp/src/main/webapp/WEB-INF/dwr.xml @@ -48,6 +48,8 @@ + + diff --git a/webapp/src/main/webapp/WEB-INF/web.xml b/webapp/src/main/webapp/WEB-INF/web.xml index 04ee7bc23..1eb6dd626 100644 --- a/webapp/src/main/webapp/WEB-INF/web.xml +++ b/webapp/src/main/webapp/WEB-INF/web.xml @@ -939,7 +939,7 @@ dwr-invoker - uk.ltd.getahead.dwr.DWRServlet + org.directwebremoting.servlet.DwrServlet debug true diff --git a/webapp/src/main/webapp/js/edit/entityRetry.js b/webapp/src/main/webapp/js/edit/entityRetry.js index 3087d9090..a2be916b8 100644 --- a/webapp/src/main/webapp/js/edit/entityRetry.js +++ b/webapp/src/main/webapp/js/edit/entityRetry.js @@ -42,7 +42,7 @@ function monikerInit(){ function update(){ //updates moniker list when type is changed - DWRUtil.useLoadingMessage(); + dwr.util.useLoadingMessage(); EntityDWR.monikers(createList, document.getElementById("VClassURI").value ); @@ -62,7 +62,7 @@ function createList(data) { //puts options in moniker select list var opt = new Option("[new moniker]",""); ele.options[ele.options.length] = opt; - DWRUtil.setValue("Moniker",getCurrentMoniker()); // getCurrentMoniker() is defined on jsp + dwr.util.setValue("Moniker",getCurrentMoniker()); // getCurrentMoniker() is defined on jsp checkMonikers(); } @@ -111,7 +111,7 @@ function fillList(id, data, selectedtext) { for (var i = 0; i < data.length; i++) { - var text = DWRUtil.toDescriptiveString(data[i]); + var text = dwr.util.toDescriptiveString(data[i]); var value = text; diff --git a/webapp/src/main/webapp/js/ents_edit.js b/webapp/src/main/webapp/js/ents_edit.js index 04ef980de..7bed21719 100644 --- a/webapp/src/main/webapp/js/ents_edit.js +++ b/webapp/src/main/webapp/js/ents_edit.js @@ -1,15 +1,15 @@ /* $This file is distributed under the terms of the license in /doc/license.txt$ */ /* this code uses: - dwrutil in util.js + dwr.util in util.js vitro.js detect.js */ dojo.require("dojo.io.*"); dojo.require("dojo.event.*"); -//DWREngine.setErrorHandler(function(data){alert("DWREngine error: " + data);}); -//DWREngine.setWarningHandler(function(data){alert("DWREngine warning: " + data);}); +//dwr.engine.setErrorHandler(function(data){alert("dwr.engine error: " + data);}); +//dwr.engine.setWarningHandler(function(data){alert("dwr.engine warning: " + data);}); /* ents_edit.js has several tasks: @@ -68,7 +68,7 @@ function update( ) { clearProp(); updateTable(); updateEntityAndPropHash(); - var but = $("newPropButton"); + var but = dwr.util.byId("newPropButton"); if( but ) { but.disabled = false; } } @@ -78,11 +78,11 @@ function clearProp() { var clearMap={sunrise:"",sunset: ""}; editingNewProp = false; gVClassUri = null; - DWRUtil.setValues( clearMap ); - clear($("propertyList")); - clear($("vClassList")); + dwr.util.setValues( clearMap ); + clear(dwr.util.byId("propertyList")); + clear(dwr.util.byId("vClassList")); - var ele = $("entitiesList"); + var ele = dwr.util.byId("entitiesList"); while( ele != null && ele.length > 0){ ele.remove(0); } @@ -102,7 +102,7 @@ function updateEntityAndPropHash(){ //once we set the gEntity we can get the ents2ents properties. //PropertyDWR.getAllPropInstByVClass(setPropertyHash, entityObj.VClassURI ); if( entityObj != null && 'URI' in entityObj ) - PropertyDWR.getAllPossiblePropInstForIndividual(setPropertyHash, entityObj.URI); + PropertyDWR.getAllPossiblePropInstForIndividual(entityObj.URI, { callback:setPropertyHash }); //else //alert("could not find an individual, usually this means that there is no type for the URI"); }; @@ -126,7 +126,7 @@ function updateEntityAndPropHash(){ }; //get the gEntity and then build the gPropertyHash - EntityDWR.entityByURI(setGEntity, gEntityURI); + EntityDWR.entityByURI(gEntityURI, { callback:setGEntity }); } /***************************************************************** @@ -139,7 +139,7 @@ function doNoPropsWarning(){ "The button you have clicked adds a new object property statement relating this individual " + "to another individual. If you are looking to add new object properties to the " + "system, look under the 'About' menu."); - var but = $("newPropButton"); + var but = dwr.util.byId("newPropButton"); if( but ) { but.disabled = true; } } @@ -149,18 +149,18 @@ because dwr calls are async we have a callback function updateTable(callback) { var cb = callback; function fillTable(props) { - DWRUtil.removeAllRows("propbody"); + dwr.util.removeAllRows("propbody"); /* This makes the row that gets added to the ents_edit form for each ents2ents object. */ - addRows($("propbody"), props, + addRows(dwr.util.byId("propbody"), props, [getDomain, getProperty, getRange, getEdit, getDelete], makeTr); - var newPropTr = $("justwritenTr"); + var newPropTr = dwr.util.byId("justwritenTr"); if( newPropTr != null ){ Fat.fade_element( "justwritenTr" ); } if(cb !== undefined && cb !== null ) { cb(); } } - PropertyDWR.getExistingProperties(fillTable,gEntityURI); + PropertyDWR.getExistingProperties(gEntityURI, { callback: fillTable }); } /**************************************************************************/ @@ -252,7 +252,7 @@ var makeTr = (function(){ /* outer func */ /* called when Edit button is clicked */ function editTable(inputElement, subjectURI, predicateURI, objectURI){ var rowIndex = inputElement.parentNode.parentNode.rowIndex-1 ; - var table = $("propbody"); + var table = dwr.util.byId("propbody"); table.deleteRow( rowIndex ); table.insertRow(rowIndex); table.rows[rowIndex].insertCell(0); @@ -261,7 +261,7 @@ function editTable(inputElement, subjectURI, predicateURI, objectURI){ table.rows[rowIndex].cells[0].colSpan = tableMaxColspan( table ); vform.style.display="block"; - PropertyDWR.getProperty(fillForm, subjectURI, predicateURI, objectURI); + PropertyDWR.getProperty(subjectURI, predicateURI, objectURI, { callback: fillForm }); inputElement.parentNode.parentNode.style.display="none"; } @@ -270,7 +270,7 @@ function deleteProp( subjectURI, predicateURI, objectURI, objectName, predicateN if( PropertyDWR.deleteProp ){ if (confirm("Are you sure you want to delete the property\n" + objectName + " " + predicateName + "?")) { - PropertyDWR.deleteProp(update, subjectURI, predicateURI, objectURI); + PropertyDWR.deleteProp(subjectURI, predicateURI, objectURI, { callback:update }); } } else { alert("Deletion of object property statements is disabled."); @@ -312,7 +312,7 @@ function newProp() { fillForm( newP ); editingNewProp = true; fillRangeVClassList(); - var table = $("propbody"); + var table = dwr.util.byId("propbody"); var tr = table.insertRow(0); tr.id = "newrow"; appendPropForm( tr, tableMaxColspan( table ) ); @@ -331,7 +331,7 @@ function fillForm(aprop) { gProperty = aprop; var vclass = gProperty.domainClass; - DWRUtil.setValues(gProperty); + dwr.util.setValues(gProperty); toggleDisabled("newPropButton"); @@ -346,7 +346,7 @@ function fillPropList(classId) { /* This function fills up the form's select list with options Notice that the option id is the propertyid + 'D' or 'R' so that domain and range properties can be distinguished */ - var propList = $("propertyList"); + var propList = dwr.util.byId("propertyList"); clear(propList); //add properties as options @@ -383,10 +383,10 @@ function fillPropList(classId) { *****************************************************************/ function fillRangeVClassList( propId ){ //If propId is null then the one on the property select list will be used - if( propId == null ) { propId = DWRUtil.getValue("propertyList");} + if( propId == null ) { propId = dwr.util.getValue("propertyList");} //clear the list and put the loading message up - var vclassListEle = $("vClassList"); + var vclassListEle = dwr.util.byId("vClassList"); clear(vclassListEle); vclassListEle.options[vclassListEle.options.length] = new Option("Loading...",-10); //vclassListEle.options[0].selected = true; @@ -394,11 +394,11 @@ function fillRangeVClassList( propId ){ var prop = gPropertyHash[propId]; - VClassDWR.getVClasses( - function(vclasses){ - addVClassOptions( vclasses ); - }, - prop.domainClassURI, prop.propertyURI, prop.subjectSide); + VClassDWR.getVClasses(prop.domainClassURI, prop.propertyURI, prop.subjectSide, + function(vclasses){ + addVClassOptions( vclasses ); + } + ); } /**************************************************************** @@ -406,14 +406,14 @@ function fillRangeVClassList( propId ){ the entitiesList. ****************************************************************/ function addVClassOptions( vclassArray ){ - // DWRUtil.addOptions("entitiesList",null); - var vclassEle = $("vClassList"); + // dwr.util.addOptions("entitiesList",null); + var vclassEle = dwr.util.byId("vClassList"); clear( vclassEle ); vclassEle.disabled = false; if( vclassArray == null || vclassArray.length < 1){ vclassEle.disabled = true; - entsEle = $("entitiesList"); + entsEle = dwr.util.byId("entitiesList"); clear(entsEle); var msg="There are no entities defined yet that could fill this role"; var opt = new Option(msg,-1); @@ -435,15 +435,15 @@ function addVClassOptions( vclassArray ){ //attempt to set the selected option to the current vclass var vclassURI = null; - var prop = gPropertyHash[ DWRUtil.getValue("propertyList") ]; + var prop = gPropertyHash[ dwr.util.getValue("propertyList") ]; if( gProperty.propertyURI == prop.propertyURI ){ vclassURI = gProperty.rangeClassURI; - DWRUtil.setValue(vclassEle, vclassURI ); + dwr.util.setValue(vclassEle, vclassURI ); //here we were unable to set the vclass select option to the vclassid //of the entity. this means that the vclass of the entity is not one that //is permited by the PropertyInheritance and other restrictions. - if( DWRUtil.getValue(vclassEle) != vclassURI){ + if( dwr.util.getValue(vclassEle) != vclassURI){ alert("This entity's class does not match the class of this property. This is usually the "+ "result of the class of the entity having been changed. Properties that were added when " + "this entity had the old class still reflect that value.\n" + @@ -461,15 +461,15 @@ function addVClassOptions( vclassArray ){ *****************************************************************/ function fillEntsList( vclassEle ){ if( vclassEle == null ) - vclassEle = $("vClassList"); - var vclassUri = DWRUtil.getValue( vclassEle ); + vclassEle = dwr.util.byId("vClassList"); + var vclassUri = dwr.util.getValue( vclassEle ); if( vclassUri == gVClassUri ) return; else gVClassUri = vclassUri; - var entsListEle = $("entitiesList"); + var entsListEle = dwr.util.byId("entitiesList"); clear(entsListEle); entityOptToSelect = null; @@ -494,7 +494,7 @@ function fillEntsList( vclassEle ){ }, load: function(type, data, evt){ //clear here since we will be using addEntOptions for multiple adds -// var entsListEle = $("entitiesList"); +// var entsListEle = dwr.util.byId("entitiesList"); // clear(entsListEle); addEntOptions(data, -1); }, @@ -509,7 +509,7 @@ function fillEntsList( vclassEle ){ /** add entities in entArray as options elements to select element "Individual" */ function addEntOptions( entArray ){ - var entsListEle = $("entitiesList"); + var entsListEle = dwr.util.byId("entitiesList"); if( entArray == null || entArray.length == 0){ clear(entsListEle); @@ -623,12 +623,12 @@ function writeProp() { return; } if( !validateForm() ) { return; } - var prop = gPropertyHash[DWRUtil.getValue("propertyList")]; + var prop = gPropertyHash[dwr.util.getValue("propertyList")]; var newP = {}; var oldP = gProperty; newP.propertyURI = prop.propertyURI; - var selected = DWRUtil.getValue("entitiesList"); + var selected = dwr.util.getValue("entitiesList"); newP.subjectEntURI= gEntity.URI; newP.objectEntURI = selected ; @@ -639,16 +639,17 @@ function writeProp() { if( editingNewProp ){ newP.ents2entsId = -1; - PropertyDWR.insertProp(callback, newP ); + PropertyDWR.insertProp(newP, { callback:callback } ); } else { var afterDelete= function(result){ - PropertyDWR.insertProp(callback, newP); + PropertyDWR.insertProp(newP, { callback:callback }); }; - PropertyDWR.deleteProp(afterDelete, + PropertyDWR.deleteProp( gProperty.subjectEntURI, gProperty.propertyURI, - gProperty.objectEntURI); + gProperty.objectEntURI, + { callback:afterDelete }); } } @@ -657,10 +658,10 @@ addEvent(window, 'load', update); /********************* some utilities ***********************************/ /* this clones the property edit from a div on the ents_edit.jsp */ -function getForm(){ return $("propeditdiv").cloneNode(true); } +function getForm(){ return dwr.util.byId("propeditdiv").cloneNode(true); } /* a function to display a lot of info about an object */ -function disy( obj, note ){ alert( (note!==null?note:"") + DWRUtil.toDescriptiveString(obj, 3));} +function disy( obj, note ){ alert( (note!==null?note:"") + dwr.util.toDescriptiveString(obj, 3));} /* attempts to get the URI of the entity being edited */ function getEntityUriFromPage(){ diff --git a/webapp/src/main/webapp/js/ents_retry.js b/webapp/src/main/webapp/js/ents_retry.js index d0aa8def9..d4cecd0ac 100644 --- a/webapp/src/main/webapp/js/ents_retry.js +++ b/webapp/src/main/webapp/js/ents_retry.js @@ -30,7 +30,7 @@ function init(){ function update(){ //updates moniker list when type is changed - DWRUtil.useLoadingMessage(); + dwr.util.useLoadingMessage(); EntityDWR.monikers(createList, document.getElementById("field2Value").value ); @@ -50,7 +50,7 @@ function createList(data) { //puts options in moniker select list var opt = new Option("[new moniker]",""); ele.options[ele.options.length] = opt; - DWRUtil.setValue("monikerSelect",getCurrentMoniker()); // getCurrentMoniker() is defined on jsp + dwr.util.setValue("monikerSelect",getCurrentMoniker()); // getCurrentMoniker() is defined on jsp checkMonikers(); } @@ -96,7 +96,7 @@ function fillList(id, data, selectedtext) { for (var i = 0; i < data.length; i++) { - var text = DWRUtil.toDescriptiveString(data[i]); + var text = dwr.util.toDescriptiveString(data[i]); var value = text; diff --git a/webapp/src/main/webapp/js/vitro.js b/webapp/src/main/webapp/js/vitro.js index e57e85ce2..5625840f3 100755 --- a/webapp/src/main/webapp/js/vitro.js +++ b/webapp/src/main/webapp/js/vitro.js @@ -54,7 +54,7 @@ function encodeUrl(pstrString) { */ function addRows(ele, data, cellFuncs, rowFunc) { var frag = document.createDocumentFragment(); - if (DWRUtil._isArray(data)) { + if (dwr.util._isArray(data)) { for (var i = 0; i < data.length; i++) { frag.appendChild( makeRow( data[i], cellFuncs, rowFunc) ); } @@ -77,9 +77,9 @@ function makeRow( row, cellFuncs, rowFunc){ var func = cellFuncs[j] var td var reply = func(row) - if (DWRUtil._isHTMLElement(reply, "td")) { + if (dwr.util._isHTMLElement(reply, "td")) { td = reply; - } else if (DWRUtil._isHTMLElement(reply, "a")) { + } else if (dwr.util._isHTMLElement(reply, "a")) { td = document.createElement("td"); td.appendChild( reply ); } else { @@ -91,7 +91,7 @@ function makeRow( row, cellFuncs, rowFunc){ return tr; } -/** added this from the DWRUtil.js */ +/** added this from the dwr.util.js */ isDate = function(data) { return (data && data.toUTCString) ? true : false; }; @@ -147,8 +147,8 @@ function date2iso8601( jdate ){ function setDateValue(ele, date, date2StrFunc){ if( date == null || ! isDate(date)) { return; } if( date2StrFunc == null ) { date2StrFunc = date2iso8601; } - ele = $(ele); - DWRUtil.setValue(ele, date2StrFunc( date )); + ele = dwr.util.byId(ele); + dwr.util.setValue(ele, date2StrFunc( date )); } /* removes all children and if it can, removes options */ @@ -160,7 +160,7 @@ function clear(ele){ } function hideElementById(eleId){ - var ele = $(eleId); + var ele = dwr.util.byId(eleId); if( ele != null ){ ele.style.display="none"; } } @@ -168,7 +168,7 @@ function makeEntLinkElement(entityURI, text){ link = document.createElement("a"); link.href = "entityEdit?uri=" + encodeUrl(entityURI); link.innerHTML = text; - //DWRUtil.setValue(link, "test" + text); + //dwr.util.setValue(link, "test" + text); return link; } @@ -375,7 +375,7 @@ function adjustIFrameSize(id) { } function toggleDisabled(ele){ - ele = $(ele); + ele = dwr.util.byId(ele); if(ele == null) {return;} ele.disabled = !ele.disabled ; } @@ -403,16 +403,16 @@ and returns a value for use in the select option value. textFun is a function that takes one parameter, an object, and returns a value for use in the select option text. -This is based on the code in DWRUtil but lacks the error checking. +This is based on the code in dwr.util but lacks the error checking. */ addOptions = function(ele, data, valueFunc, textFunc) { var orig = ele; - ele = $(ele); + ele = dwr.util.byId(ele); if (ele == null) { - DWRUtil.debug("addOptions() can't find an element with id: " + orig + "."); + dwr.util.debug("addOptions() can't find an element with id: " + orig + "."); return; } - var useOptions = DWRUtil._isHTMLElement(ele, "select"); + var useOptions = dwr.util._isHTMLElement(ele, "select"); if (data == null) return; var text; diff --git a/webapp/src/main/webapp/templates/edit/specific/ents_edit_head.jsp b/webapp/src/main/webapp/templates/edit/specific/ents_edit_head.jsp index 31bf303fb..2f226cac1 100644 --- a/webapp/src/main/webapp/templates/edit/specific/ents_edit_head.jsp +++ b/webapp/src/main/webapp/templates/edit/specific/ents_edit_head.jsp @@ -12,19 +12,23 @@ String context = request.getContextPath(); if (!(Boolean)request.getAttribute("dwrDisabled")) { %> + + - - From a13e353228f9579da05f0799e84a19ef51f70ee8 Mon Sep 17 00:00:00 2001 From: Graham Triggs Date: Fri, 16 Dec 2016 21:04:08 +0000 Subject: [PATCH 13/49] Update DWR XML DTD --- webapp/src/main/webapp/WEB-INF/dwr.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/webapp/src/main/webapp/WEB-INF/dwr.xml b/webapp/src/main/webapp/WEB-INF/dwr.xml index b17f2de58..eb238891d 100755 --- a/webapp/src/main/webapp/WEB-INF/dwr.xml +++ b/webapp/src/main/webapp/WEB-INF/dwr.xml @@ -1,5 +1,4 @@ - + From 56dc6cf750c320c38f396f40a64d71f999ff279e Mon Sep 17 00:00:00 2001 From: Graham Triggs Date: Sat, 17 Dec 2016 18:23:02 +0000 Subject: [PATCH 14/49] Fix deprecated use of Freemarker --- .../beanswrappers/ReadOnlyBeansWrapper.java | 53 ++++++++++--------- .../vitro/webapp/web/templatemodels/Tags.java | 26 ++++----- 2 files changed, 40 insertions(+), 39 deletions(-) diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/beanswrappers/ReadOnlyBeansWrapper.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/beanswrappers/ReadOnlyBeansWrapper.java index d31ff1d15..d0050d6c8 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/beanswrappers/ReadOnlyBeansWrapper.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/beanswrappers/ReadOnlyBeansWrapper.java @@ -4,6 +4,7 @@ package edu.cornell.mannlib.vitro.webapp.web.beanswrappers; import java.lang.reflect.Method; +import freemarker.ext.beans.MethodAppearanceFineTuner; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -26,35 +27,35 @@ public class ReadOnlyBeansWrapper extends BeansWrapper { public ReadOnlyBeansWrapper() { // Start by exposing all safe methods. setExposureLevel(EXPOSE_SAFE); - } - - @SuppressWarnings("rawtypes") - @Override - protected void finetuneMethodAppearance(Class cls, Method method, MethodAppearanceDecision decision) { - - // How to define a setter? This is a weak approximation: a method whose name - // starts with "set" or returns void. - if ( method.getName().startsWith("set") ) { - decision.setExposeMethodAs(null); - - } else if ( method.getReturnType().getName().equals("void") ) { - decision.setExposeMethodAs(null); - - } else { - - Class declaringClass = method.getDeclaringClass(); - if (declaringClass.equals(java.lang.Object.class)) { - decision.setExposeMethodAs(null); - - } else { - Package pkg = declaringClass.getPackage(); - if (pkg.getName().equals("java.util")) { - decision.setExposeMethodAs(null); + setMethodAppearanceFineTuner(new MethodAppearanceFineTuner() { + @Override + public void process(MethodAppearanceDecisionInput methodAppearanceDecisionInput, MethodAppearanceDecision methodAppearanceDecision) { + Method method = methodAppearanceDecisionInput.getMethod(); + // How to define a setter? This is a weak approximation: a method whose name + // starts with "set" or returns void. + if ( method.getName().startsWith("set") ) { + methodAppearanceDecision.setExposeMethodAs(null); + + } else if ( method.getReturnType().getName().equals("void") ) { + methodAppearanceDecision.setExposeMethodAs(null); + + } else { + + Class declaringClass = method.getDeclaringClass(); + if (declaringClass.equals(java.lang.Object.class)) { + methodAppearanceDecision.setExposeMethodAs(null); + + } else { + Package pkg = declaringClass.getPackage(); + if (pkg.getName().equals("java.util")) { + methodAppearanceDecision.setExposeMethodAs(null); + } + } } } - } + }); } - + // For exposing a method as a property (when it's not named getX or isX). Note that this is not // just a syntactic change in the template from X() to X, but also makes the value get precomputed. // private void exposeAsProperty(Method method, MethodAppearanceDecision decision) { diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/templatemodels/Tags.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/templatemodels/Tags.java index ce1522f78..07e769e56 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/templatemodels/Tags.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/templatemodels/Tags.java @@ -5,6 +5,7 @@ package edu.cornell.mannlib.vitro.webapp.web.templatemodels; import java.lang.reflect.Method; import java.util.LinkedHashSet; +import freemarker.ext.beans.MethodAppearanceFineTuner; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -46,20 +47,19 @@ public class Tags extends BaseTemplateModel { public TagsWrapper() { // Start by exposing all safe methods. setExposureLevel(EXPOSE_SAFE); - } - - @SuppressWarnings("rawtypes") - @Override - protected void finetuneMethodAppearance(Class cls, Method method, MethodAppearanceDecision decision) { - - try { - String methodName = method.getName(); - if ( ! ( methodName.equals("add") || methodName.equals("list")) ) { - decision.setExposeMethodAs(null); + setMethodAppearanceFineTuner(new MethodAppearanceFineTuner() { + @Override + public void process(MethodAppearanceDecisionInput methodAppearanceDecisionInput, MethodAppearanceDecision methodAppearanceDecision) { + try { + String methodName = methodAppearanceDecisionInput.getMethod().getName(); + if ( ! ( methodName.equals("add") || methodName.equals("list")) ) { + methodAppearanceDecision.setExposeMethodAs(null); + } + } catch (Exception e) { + log.error(e, e); + } } - } catch (Exception e) { - log.error(e, e); - } + }); } } From fb8da504e21815bd8ee5f9fc259b20b0e00cf470 Mon Sep 17 00:00:00 2001 From: Graham Triggs Date: Sat, 17 Dec 2016 18:23:26 +0000 Subject: [PATCH 15/49] Update C3P0 and image library dependencies --- dependencies/pom.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dependencies/pom.xml b/dependencies/pom.xml index 9742a0fdf..77f8afc09 100644 --- a/dependencies/pom.xml +++ b/dependencies/pom.xml @@ -73,22 +73,22 @@ com.mchange c3p0 - 0.9.2-pre4 + 0.9.5.2 com.twelvemonkeys.imageio imageio-jpeg - 3.2.1 + 3.3.1 com.twelvemonkeys.imageio imageio-tiff - 3.2.1 + 3.3.1 com.twelvemonkeys.servlet servlet - 3.2.1 + 3.3.1 commons-dbcp From 0665f3ee21f32d7d96ceae0c718076838d142db0 Mon Sep 17 00:00:00 2001 From: Graham Triggs Date: Sat, 17 Dec 2016 19:07:15 +0000 Subject: [PATCH 16/49] Update file upload / io --- dependencies/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dependencies/pom.xml b/dependencies/pom.xml index 77f8afc09..15e853c50 100644 --- a/dependencies/pom.xml +++ b/dependencies/pom.xml @@ -98,12 +98,12 @@ commons-fileupload commons-fileupload - 1.2.1 + 1.3.2 commons-io commons-io - 2.4 + 2.5 commons-lang From 39e0dc438c2c4371593fbecdccf6c670b8d74158 Mon Sep 17 00:00:00 2001 From: Graham Triggs Date: Sat, 17 Dec 2016 20:10:37 +0000 Subject: [PATCH 17/49] Update commons-lang to 3.4 (same as used by Jena 3.1.1) --- .../mannlib/vedit/tags/DynamicFieldsTag.java | 2 +- .../cornell/mannlib/vedit/tags/EditTag.java | 2 +- .../cornell/mannlib/vedit/tags/ErrorTag.java | 4 ++-- .../cornell/mannlib/vedit/tags/OptionTag.java | 8 +++---- .../cornell/mannlib/vedit/tags/ValueTag.java | 4 ++-- .../auth/identifier/common/IsBlacklisted.java | 2 +- .../ConfigurationPropertiesSmokeTests.java | 2 +- .../UserAccountsFirstTimeExternalPage.java | 2 +- .../admin/SparqlQueryController.java | 2 +- .../api/SparqlUpdateApiController.java | 2 +- .../authenticate/LoginRedirector.java | 2 +- .../dumprestore/DumpRestoreController.java | 2 +- .../controller/edit/PrimitiveDelete.java | 2 +- .../AllClassGroupsListingController.java | 2 +- .../PropertyGroupsListingController.java | 2 +- .../freemarker/ContactFormController.java | 2 +- .../freemarker/DumpTestController.java | 2 +- .../FreemarkerComponentGenerator.java | 2 +- .../freemarker/FreemarkerHttpServlet.java | 2 +- .../freemarker/IndividualListController.java | 2 +- .../freemarker/ListClassGroupsController.java | 2 +- .../ListPropertyGroupsController.java | 2 +- .../controller/freemarker/PageController.java | 2 +- .../freemarker/StaticPageController.java | 2 +- .../grefine/JSONReconcileServlet.java | 2 +- .../individual/IndividualRdfAssembler.java | 2 +- .../IndividualListResultsUtils.java | 2 +- .../controller/jena/JenaIngestController.java | 4 ++-- .../webapp/controller/json/JsonProducer.java | 2 +- .../webapp/dao/jena/DataPropertyDaoJena.java | 2 +- .../webapp/dao/jena/IndividualDaoJena.java | 6 ++--- .../webapp/dao/jena/IndividualDaoSDB.java | 2 +- .../dao/jena/ObjectPropertyDaoJena.java | 2 +- .../jena/ObjectPropertyStatementDaoJena.java | 2 +- .../vitro/webapp/dao/jena/QueryUtils.java | 4 ++-- .../dao/jena/SparqlGraphMultilingual.java | 2 +- .../webapp/dao/jena/VitroModelSource.java | 2 +- .../n3editing/VTwo/EditConfigurationVTwo.java | 4 ++-- .../n3editing/VTwo/EditN3GeneratorVTwo.java | 2 +- .../VTwo/MultiValueEditSubmission.java | 6 ++--- .../VTwo/fields/ChildVClassesWithParent.java | 2 +- .../edit/n3editing/VTwo/fields/FieldVTwo.java | 4 ++-- .../IndividualsViaObjectPropetyOptions.java | 2 +- .../BaseEditConfigurationGenerator.java | 2 +- ...aultAddMissingIndividualFormGenerator.java | 2 +- .../validators/AntiXssValidation.java | 2 +- .../DefaultDataPropertyFormValidator.java | 2 +- .../controller/ProcessRdfFormController.java | 2 +- .../vitro/webapp/filters/ModelSwitcher.java | 2 +- .../filters/StartupStatusDisplayFilter.java | 2 +- .../vitro/webapp/filters/VitroURL.java | 2 +- .../config/FreemarkerConfiguration.java | 2 +- .../loader/FreemarkerTemplateLoader.java | 2 +- .../selection/LocaleSelectionController.java | 4 ++-- .../i18n/selection/LocaleSelectionSetup.java | 10 ++++++-- .../impl/logging/RDFServiceLogger.java | 2 +- .../controller/AutocompleteController.java | 2 +- .../controller/PagedSearchController.java | 2 +- .../search/controller/UpdateUrisInIndex.java | 2 +- .../searchengine/SearchEngineLogger.java | 2 +- .../tasks/UpdateDocumentWorkUnit.java | 2 +- .../services/shortview/ShortViewService.java | 2 +- .../triplesource/impl/sdb/SDBDataSource.java | 2 +- .../utils/dataGetter/DataGetterBase.java | 2 +- .../utils/dataGetter/DataGetterUtils.java | 2 +- .../IndividualsForClassesDataGetter.java | 2 +- .../developer/loggers/StackTraceUtility.java | 2 +- .../vitro/webapp/utils/logging/ToString.java | 2 +- .../utils/searchengine/AutoCompleteWords.java | 2 +- .../utils/searchengine/SearchQueryUtils.java | 2 +- .../utils/sparql/RdfServiceQueryContext.java | 2 +- .../vitro/webapp/web/MiscWebUtils.java | 8 +++---- .../web/directives/WidgetDirective.java | 2 +- .../web/jsptags/OptionsForClassTag.java | 6 ++--- .../web/jsptags/OptionsForPropertyTag.java | 6 ++--- .../web/templatemodels/LinkTemplateModel.java | 4 ++-- .../vitro/webapp/web/templatemodels/Tags.java | 2 +- .../VClassGroupTemplateModel.java | 2 +- .../DataPropertyListConfig.java | 2 +- .../customlistview/PropertyListConfig.java | 2 +- .../edit/EditConfigurationTemplateModel.java | 2 +- .../BaseIndividualTemplateModel.java | 2 +- .../CollatedObjectPropertyTemplateModel.java | 2 +- .../individual/DataPropertyTemplateModel.java | 2 +- .../ObjectPropertyTemplateModel.java | 2 +- .../individual/SubclassTemplateModel.java | 2 +- .../vitro/webapp/web/widgets/LoginWidget.java | 2 +- .../opensocial/OpenSocialSmokeTests.java | 2 +- .../ext/dump/BaseDumpDirective.java | 2 +- .../SparqlQueryApiExecutorTest.java | 2 +- .../loader/FreemarkerTemplateLoaderTest.java | 2 +- .../selection/LocaleSelectionSetupTest.java | 24 ++++++++++--------- .../utils/dataGetter/DataGetterUtilsTest.java | 2 +- .../ext/dump/DumpDirectiveTest.java | 2 +- dependencies/pom.xml | 7 +++--- .../CheckContainerNeutrality.java | 2 +- .../utilities/rdbmigration/RdbMigrator.java | 2 +- 97 files changed, 141 insertions(+), 132 deletions(-) diff --git a/api/src/main/java/edu/cornell/mannlib/vedit/tags/DynamicFieldsTag.java b/api/src/main/java/edu/cornell/mannlib/vedit/tags/DynamicFieldsTag.java index d9920ae8e..835fc0117 100644 --- a/api/src/main/java/edu/cornell/mannlib/vedit/tags/DynamicFieldsTag.java +++ b/api/src/main/java/edu/cornell/mannlib/vedit/tags/DynamicFieldsTag.java @@ -27,7 +27,7 @@ import edu.cornell.mannlib.vedit.beans.FormObject; import edu.cornell.mannlib.vedit.beans.DynamicField; import edu.cornell.mannlib.vedit.beans.DynamicFieldRow; import org.apache.commons.codec.binary.Base64; -import org.apache.commons.lang.StringEscapeUtils; +import org.apache.commons.lang3.StringEscapeUtils; import edu.cornell.mannlib.vedit.tags.EditTag; public class DynamicFieldsTag extends EditTag { diff --git a/api/src/main/java/edu/cornell/mannlib/vedit/tags/EditTag.java b/api/src/main/java/edu/cornell/mannlib/vedit/tags/EditTag.java index 5ff13b6b3..6ebf3f647 100644 --- a/api/src/main/java/edu/cornell/mannlib/vedit/tags/EditTag.java +++ b/api/src/main/java/edu/cornell/mannlib/vedit/tags/EditTag.java @@ -11,7 +11,7 @@ import javax.servlet.jsp.JspWriter; import edu.cornell.mannlib.vedit.beans.EditProcessObject; import edu.cornell.mannlib.vedit.beans.FormObject; -import org.apache.commons.lang.StringEscapeUtils; +import org.apache.commons.lang3.StringEscapeUtils; public class EditTag extends TagSupport { private String name = null; diff --git a/api/src/main/java/edu/cornell/mannlib/vedit/tags/ErrorTag.java b/api/src/main/java/edu/cornell/mannlib/vedit/tags/ErrorTag.java index 5b9f533dc..b61ff9884 100644 --- a/api/src/main/java/edu/cornell/mannlib/vedit/tags/ErrorTag.java +++ b/api/src/main/java/edu/cornell/mannlib/vedit/tags/ErrorTag.java @@ -7,7 +7,7 @@ import javax.servlet.jsp.tagext.TagSupport; import javax.servlet.jsp.JspWriter; import edu.cornell.mannlib.vedit.beans.FormObject; import edu.cornell.mannlib.vedit.tags.EditTag; -import org.apache.commons.lang.StringEscapeUtils; +import org.apache.commons.lang3.StringEscapeUtils; /** This tag allows validation error messages to be displayed on a form JSP **/ public class ErrorTag extends EditTag { @@ -29,7 +29,7 @@ public class ErrorTag extends EditTag { } if (errors != null){ - out.print(StringEscapeUtils.escapeHtml((String) errors)); + out.print(StringEscapeUtils.ESCAPE_HTML4.translate((String) errors)); } } catch(Exception ex) { diff --git a/api/src/main/java/edu/cornell/mannlib/vedit/tags/OptionTag.java b/api/src/main/java/edu/cornell/mannlib/vedit/tags/OptionTag.java index 8036c3082..13b7696f2 100644 --- a/api/src/main/java/edu/cornell/mannlib/vedit/tags/OptionTag.java +++ b/api/src/main/java/edu/cornell/mannlib/vedit/tags/OptionTag.java @@ -12,7 +12,7 @@ import javax.servlet.jsp.JspWriter; import edu.cornell.mannlib.vedit.beans.Option; import edu.cornell.mannlib.vedit.tags.EditTag; -import org.apache.commons.lang.StringEscapeUtils; +import org.apache.commons.lang3.StringEscapeUtils; public class OptionTag extends EditTag { private String name = null; @@ -29,11 +29,11 @@ public class OptionTag extends EditTag { opt.setValue(""); if (opt.getBody() == null) opt.setBody(""); - out.print("\n"); } } @@ -54,7 +54,7 @@ public class OptionTag extends EditTag { OrderedMapIterator ogKey = optGroups.orderedMapIterator(); while (ogKey.hasNext()) { String optGroupName = (String) ogKey.next(); - out.println(""); + out.println(""); outputOptionsMarkup((List)optGroups.get(optGroupName),out); out.println(""); } diff --git a/api/src/main/java/edu/cornell/mannlib/vedit/tags/ValueTag.java b/api/src/main/java/edu/cornell/mannlib/vedit/tags/ValueTag.java index 92619693d..48c38be1e 100644 --- a/api/src/main/java/edu/cornell/mannlib/vedit/tags/ValueTag.java +++ b/api/src/main/java/edu/cornell/mannlib/vedit/tags/ValueTag.java @@ -8,7 +8,7 @@ import javax.servlet.jsp.JspException; import javax.servlet.jsp.tagext.TagSupport; import javax.servlet.jsp.JspWriter; import edu.cornell.mannlib.vedit.beans.FormObject; -import org.apache.commons.lang.StringEscapeUtils; +import org.apache.commons.lang3.StringEscapeUtils; import edu.cornell.mannlib.vedit.tags.EditTag; public class ValueTag extends EditTag { @@ -35,7 +35,7 @@ public class ValueTag extends EditTag { if (values != null){ String value = (String) values.get(name); if (value != null) - out.print(StringEscapeUtils.escapeHtml(value)); + out.print(StringEscapeUtils.ESCAPE_HTML4.translate(value)); } else { System.out.println("ValueTag unable to get HashMap of form values"); } diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/auth/identifier/common/IsBlacklisted.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/auth/identifier/common/IsBlacklisted.java index 8cb3f7e19..19968094b 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/auth/identifier/common/IsBlacklisted.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/auth/identifier/common/IsBlacklisted.java @@ -12,7 +12,7 @@ import java.util.Set; import javax.servlet.ServletContext; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/config/ConfigurationPropertiesSmokeTests.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/config/ConfigurationPropertiesSmokeTests.java index 31e21da32..e642cc9a6 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/config/ConfigurationPropertiesSmokeTests.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/config/ConfigurationPropertiesSmokeTests.java @@ -10,7 +10,7 @@ import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsFirstTimeExternalPage.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsFirstTimeExternalPage.java index c48ba8691..ffffc1b1a 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsFirstTimeExternalPage.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsFirstTimeExternalPage.java @@ -9,7 +9,7 @@ import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import edu.cornell.mannlib.vitro.webapp.auth.permissions.PermissionSets; import edu.cornell.mannlib.vitro.webapp.beans.UserAccount; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/admin/SparqlQueryController.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/admin/SparqlQueryController.java index da4fc589f..1b572a5b6 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/admin/SparqlQueryController.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/admin/SparqlQueryController.java @@ -16,7 +16,7 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/api/SparqlUpdateApiController.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/api/SparqlUpdateApiController.java index 7feecbc1e..b045b118c 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/api/SparqlUpdateApiController.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/api/SparqlUpdateApiController.java @@ -14,7 +14,7 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/LoginRedirector.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/LoginRedirector.java index 4b3dd4769..05197a731 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/LoginRedirector.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/LoginRedirector.java @@ -11,7 +11,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/datatools/dumprestore/DumpRestoreController.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/datatools/dumprestore/DumpRestoreController.java index f9ca53732..38eb933e2 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/datatools/dumprestore/DumpRestoreController.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/datatools/dumprestore/DumpRestoreController.java @@ -11,7 +11,7 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import edu.cornell.mannlib.vitro.webapp.auth.permissions.SimplePermission; import edu.cornell.mannlib.vitro.webapp.auth.policy.PolicyHelper; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/PrimitiveDelete.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/PrimitiveDelete.java index 9e4b0b389..8b520de78 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/PrimitiveDelete.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/PrimitiveDelete.java @@ -6,7 +6,7 @@ import static javax.servlet.http.HttpServletResponse.SC_UNAUTHORIZED; import javax.servlet.http.HttpServletResponse; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/listing/AllClassGroupsListingController.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/listing/AllClassGroupsListingController.java index 971b0b301..6423387d4 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/listing/AllClassGroupsListingController.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/listing/AllClassGroupsListingController.java @@ -11,7 +11,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import edu.cornell.mannlib.vitro.webapp.utils.JSPPageHandler; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import edu.cornell.mannlib.vedit.controller.BaseEditController; import edu.cornell.mannlib.vitro.webapp.auth.permissions.SimplePermission; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/listing/PropertyGroupsListingController.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/listing/PropertyGroupsListingController.java index 7769e521c..092c1396b 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/listing/PropertyGroupsListingController.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/listing/PropertyGroupsListingController.java @@ -14,7 +14,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import edu.cornell.mannlib.vitro.webapp.utils.JSPPageHandler; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/ContactFormController.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/ContactFormController.java index 82b4eea0d..239940e54 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/ContactFormController.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/ContactFormController.java @@ -5,7 +5,7 @@ package edu.cornell.mannlib.vitro.webapp.controller.freemarker; import java.util.HashMap; import java.util.Map; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/DumpTestController.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/DumpTestController.java index 4c09a40ab..4ba3ee4e6 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/DumpTestController.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/DumpTestController.java @@ -13,7 +13,7 @@ import java.util.List; import java.util.Map; import java.util.Set; -import org.apache.commons.lang.time.DateUtils; +import org.apache.commons.lang3.time.DateUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/FreemarkerComponentGenerator.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/FreemarkerComponentGenerator.java index e01b14cd9..29785c64f 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/FreemarkerComponentGenerator.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/FreemarkerComponentGenerator.java @@ -7,7 +7,7 @@ import java.util.Map; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/FreemarkerHttpServlet.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/FreemarkerHttpServlet.java index 5a8a7fa20..5d97c7b98 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/FreemarkerHttpServlet.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/FreemarkerHttpServlet.java @@ -17,7 +17,7 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/IndividualListController.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/IndividualListController.java index 8290df18f..d200bc95d 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/IndividualListController.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/IndividualListController.java @@ -9,7 +9,7 @@ import java.util.List; import java.util.Map; import edu.cornell.mannlib.vitro.webapp.web.templatemodels.individuallist.ListedIndividualBuilder; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/ListClassGroupsController.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/ListClassGroupsController.java index 75a728df9..097212e0e 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/ListClassGroupsController.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/ListClassGroupsController.java @@ -9,7 +9,7 @@ import java.util.Map; import net.sf.json.util.JSONUtils; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/ListPropertyGroupsController.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/ListPropertyGroupsController.java index 5ac98a5bd..35d37468d 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/ListPropertyGroupsController.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/ListPropertyGroupsController.java @@ -10,7 +10,7 @@ import java.util.Map; import net.sf.json.util.JSONUtils; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/PageController.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/PageController.java index 13595fd1d..7b89e08e1 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/PageController.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/PageController.java @@ -14,7 +14,7 @@ import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/StaticPageController.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/StaticPageController.java index 09ea8ded9..ed02c9810 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/StaticPageController.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/StaticPageController.java @@ -5,7 +5,7 @@ package edu.cornell.mannlib.vitro.webapp.controller.freemarker; import java.util.HashMap; import java.util.Map; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/grefine/JSONReconcileServlet.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/grefine/JSONReconcileServlet.java index 29b005548..a938c3c3e 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/grefine/JSONReconcileServlet.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/grefine/JSONReconcileServlet.java @@ -15,7 +15,7 @@ import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.json.JSONArray; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/individual/IndividualRdfAssembler.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/individual/IndividualRdfAssembler.java index b2df86aa5..e55e8a7d1 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/individual/IndividualRdfAssembler.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/individual/IndividualRdfAssembler.java @@ -10,7 +10,7 @@ import java.util.Set; import javax.servlet.ServletContext; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/individuallist/IndividualListResultsUtils.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/individuallist/IndividualListResultsUtils.java index e06f35af9..bb4c333a5 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/individuallist/IndividualListResultsUtils.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/individuallist/IndividualListResultsUtils.java @@ -8,7 +8,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; -import org.apache.commons.lang.ArrayUtils; +import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.json.JSONArray; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/jena/JenaIngestController.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/jena/JenaIngestController.java index 81e36b0e4..344dfdcc2 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/jena/JenaIngestController.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/jena/JenaIngestController.java @@ -33,7 +33,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import edu.cornell.mannlib.vitro.webapp.utils.JSPPageHandler; -import org.apache.commons.lang.StringEscapeUtils; +import org.apache.commons.lang3.StringEscapeUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.semanticweb.owlapi.reasoner.InconsistentOntologyException; @@ -861,7 +861,7 @@ public class JenaIngestController extends BaseEditController { Individual ind = jenaOntModel.getIndividual(savedQueryURIStr); log.debug("Using query "+savedQueryURIStr); queryStr = ( (Literal) ind.getPropertyValue(queryStrProp)).getLexicalForm(); - queryStr = StringEscapeUtils.unescapeHtml(queryStr); // !!! We need to turn off automatic HTML-escaping for data property editing. + queryStr = StringEscapeUtils.UNESCAPE_HTML4.translate(queryStr); // !!! We need to turn off automatic HTML-escaping for data property editing. } finally { jenaOntModel.leaveCriticalSection(); } diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/json/JsonProducer.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/json/JsonProducer.java index a1a5e2c0d..3cf430120 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/json/JsonProducer.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/json/JsonProducer.java @@ -7,7 +7,7 @@ import java.util.List; import javax.servlet.ServletException; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.json.JSONArray; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/DataPropertyDaoJena.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/DataPropertyDaoJena.java index ddf1396a7..a34c6bf41 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/DataPropertyDaoJena.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/DataPropertyDaoJena.java @@ -13,7 +13,7 @@ import java.util.List; import java.util.Map; import edu.cornell.mannlib.vitro.webapp.rdfservice.ResultSetConsumer; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualDaoJena.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualDaoJena.java index 9651f308f..bb5fa217e 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualDaoJena.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualDaoJena.java @@ -13,7 +13,7 @@ import java.util.List; import java.util.Random; import java.util.Set; -import org.apache.commons.lang.NotImplementedException; +import org.apache.commons.lang3.NotImplementedException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -605,12 +605,12 @@ public class IndividualDaoJena extends JenaBaseDao implements IndividualDao { public Collection getAllIndividualUris() { //this is implemented in IndivdiualSDB - throw new NotImplementedException(); + throw new NotImplementedException(""); } public Iterator getUpdatedSinceIterator(long updatedSince){ //this is implemented in IndivdiualSDB - throw new NotImplementedException(); + throw new NotImplementedException(""); } public boolean isIndividualOfClass(String vclassURI, String indURI) { diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualDaoSDB.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualDaoSDB.java index 0abe07421..94e816891 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualDaoSDB.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualDaoSDB.java @@ -13,7 +13,7 @@ import java.util.LinkedList; import java.util.List; import edu.cornell.mannlib.vitro.webapp.rdfservice.ResultSetConsumer; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.joda.time.DateTime; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/ObjectPropertyDaoJena.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/ObjectPropertyDaoJena.java index 97b68557f..8e532f580 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/ObjectPropertyDaoJena.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/ObjectPropertyDaoJena.java @@ -11,7 +11,7 @@ import java.util.List; import java.util.Map; import edu.cornell.mannlib.vitro.webapp.rdfservice.ResultSetConsumer; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/ObjectPropertyStatementDaoJena.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/ObjectPropertyStatementDaoJena.java index 7985a4932..3e75e5687 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/ObjectPropertyStatementDaoJena.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/ObjectPropertyStatementDaoJena.java @@ -14,7 +14,7 @@ import java.util.Objects; import java.util.Set; import edu.cornell.mannlib.vitro.webapp.rdfservice.ResultSetConsumer; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/QueryUtils.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/QueryUtils.java index 9afe1c049..4ca95de30 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/QueryUtils.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/QueryUtils.java @@ -9,8 +9,8 @@ import java.util.Iterator; import java.util.List; import java.util.Map; -import org.apache.commons.lang.ObjectUtils; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/SparqlGraphMultilingual.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/SparqlGraphMultilingual.java index ac1a8c71b..b05c3faec 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/SparqlGraphMultilingual.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/SparqlGraphMultilingual.java @@ -8,7 +8,7 @@ import java.util.Comparator; import java.util.LinkedList; import java.util.List; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/VitroModelSource.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/VitroModelSource.java index cd333df4e..cac045b14 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/VitroModelSource.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/VitroModelSource.java @@ -3,7 +3,7 @@ package edu.cornell.mannlib.vitro.webapp.dao.jena; import javax.servlet.ServletContext; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.jena.rdf.model.Model; import org.apache.jena.rdf.model.ModelReader; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/EditConfigurationVTwo.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/EditConfigurationVTwo.java index 536b531c0..e49805e6f 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/EditConfigurationVTwo.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/EditConfigurationVTwo.java @@ -16,8 +16,8 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import org.apache.commons.fileupload.servlet.ServletFileUpload; -import org.apache.commons.lang.builder.ToStringBuilder; -import org.apache.commons.lang.builder.ToStringStyle; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.joda.time.DateTime; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/EditN3GeneratorVTwo.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/EditN3GeneratorVTwo.java index 370268905..ebcbf100d 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/EditN3GeneratorVTwo.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/EditN3GeneratorVTwo.java @@ -11,7 +11,7 @@ import java.util.Map; import java.util.Set; import java.util.regex.Matcher; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/MultiValueEditSubmission.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/MultiValueEditSubmission.java index 4c313bc46..9d978ec89 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/MultiValueEditSubmission.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/MultiValueEditSubmission.java @@ -11,9 +11,9 @@ import java.util.List; import java.util.Map; import org.apache.commons.fileupload.FileItem; -import org.apache.commons.lang.StringUtils; -import org.apache.commons.lang.builder.ToStringBuilder; -import org.apache.commons.lang.builder.ToStringStyle; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.joda.time.format.DateTimeFormat; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/ChildVClassesWithParent.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/ChildVClassesWithParent.java index f19eb0b09..f129b2541 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/ChildVClassesWithParent.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/ChildVClassesWithParent.java @@ -7,7 +7,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.jena.vocabulary.OWL; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/FieldVTwo.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/FieldVTwo.java index d12551420..4f0be8bd3 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/FieldVTwo.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/FieldVTwo.java @@ -5,8 +5,8 @@ package edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.fields; import java.util.ArrayList; import java.util.List; -import org.apache.commons.lang.builder.ToStringBuilder; -import org.apache.commons.lang.builder.ToStringStyle; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.BaseEditElementVTwo; import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditElementVTwo; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/IndividualsViaObjectPropetyOptions.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/IndividualsViaObjectPropetyOptions.java index dbbe5d630..9dcba93ec 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/IndividualsViaObjectPropetyOptions.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/IndividualsViaObjectPropetyOptions.java @@ -14,7 +14,7 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/BaseEditConfigurationGenerator.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/BaseEditConfigurationGenerator.java index 9f0d691b1..b3917921c 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/BaseEditConfigurationGenerator.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/BaseEditConfigurationGenerator.java @@ -6,7 +6,7 @@ import java.util.List; import javax.servlet.http.HttpSession; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.jena.ontology.OntModel; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/DefaultAddMissingIndividualFormGenerator.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/DefaultAddMissingIndividualFormGenerator.java index c81ec1008..e53382bd1 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/DefaultAddMissingIndividualFormGenerator.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/DefaultAddMissingIndividualFormGenerator.java @@ -11,7 +11,7 @@ import java.util.Map; import javax.servlet.http.HttpSession; import edu.cornell.mannlib.vitro.webapp.web.templatemodels.searchresult.IndividualSearchResult; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/validators/AntiXssValidation.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/validators/AntiXssValidation.java index 854235984..29db68047 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/validators/AntiXssValidation.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/validators/AntiXssValidation.java @@ -7,7 +7,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.owasp.validator.html.AntiSamy; import org.owasp.validator.html.CleanResults; import org.owasp.validator.html.PolicyException; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/validators/DefaultDataPropertyFormValidator.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/validators/DefaultDataPropertyFormValidator.java index 665426cdc..a6d7125ac 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/validators/DefaultDataPropertyFormValidator.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/validators/DefaultDataPropertyFormValidator.java @@ -6,7 +6,7 @@ import java.util.List; import java.util.Map; import java.util.regex.Pattern; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/controller/ProcessRdfFormController.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/controller/ProcessRdfFormController.java index 7ba226297..c73519c30 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/controller/ProcessRdfFormController.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/controller/ProcessRdfFormController.java @@ -8,7 +8,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/filters/ModelSwitcher.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/filters/ModelSwitcher.java index a8638e2e1..4ff84d94c 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/filters/ModelSwitcher.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/filters/ModelSwitcher.java @@ -15,7 +15,7 @@ import static edu.cornell.mannlib.vitro.webapp.modelaccess.ModelNames.DISPLAY_TB import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/filters/StartupStatusDisplayFilter.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/filters/StartupStatusDisplayFilter.java index f618c9e24..d1f127f27 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/filters/StartupStatusDisplayFilter.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/filters/StartupStatusDisplayFilter.java @@ -18,7 +18,7 @@ import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import edu.cornell.mannlib.vitro.webapp.beans.ApplicationBean; import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/filters/VitroURL.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/filters/VitroURL.java index ba5b2d03f..37dc6b828 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/filters/VitroURL.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/filters/VitroURL.java @@ -12,7 +12,7 @@ import java.util.List; import java.util.regex.Pattern; import java.util.regex.Matcher; -import org.apache.commons.lang.StringEscapeUtils; +import org.apache.commons.lang3.StringEscapeUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/freemarker/config/FreemarkerConfiguration.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/freemarker/config/FreemarkerConfiguration.java index 3fc8e3c83..0658d9aef 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/freemarker/config/FreemarkerConfiguration.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/freemarker/config/FreemarkerConfiguration.java @@ -13,7 +13,7 @@ import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import javax.servlet.http.HttpServletRequest; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/freemarker/loader/FreemarkerTemplateLoader.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/freemarker/loader/FreemarkerTemplateLoader.java index 1dd73816a..1b784ed7f 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/freemarker/loader/FreemarkerTemplateLoader.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/freemarker/loader/FreemarkerTemplateLoader.java @@ -18,7 +18,7 @@ import java.util.TreeSet; import java.util.regex.Matcher; import java.util.regex.Pattern; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/i18n/selection/LocaleSelectionController.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/i18n/selection/LocaleSelectionController.java index f57139fb3..e90034f08 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/i18n/selection/LocaleSelectionController.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/i18n/selection/LocaleSelectionController.java @@ -11,8 +11,8 @@ import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.apache.commons.lang.LocaleUtils; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.LocaleUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/i18n/selection/LocaleSelectionSetup.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/i18n/selection/LocaleSelectionSetup.java index 081019a04..9687cdd75 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/i18n/selection/LocaleSelectionSetup.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/i18n/selection/LocaleSelectionSetup.java @@ -10,8 +10,8 @@ import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; -import org.apache.commons.lang.LocaleUtils; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.LocaleUtils; +import org.apache.commons.lang3.StringUtils; import edu.cornell.mannlib.vitro.webapp.config.ConfigurationProperties; import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus; @@ -132,6 +132,12 @@ public class LocaleSelectionSetup implements ServletContextListener { private Locale buildLocale(String localeString) throws IllegalArgumentException { + + // Replicate exception from lang2 with empty strings + if ("".equals(localeString)) { + throw new IllegalArgumentException("Invalid locale format"); + } + Locale locale = LocaleUtils.toLocale(localeString); if (!"es_GO".equals(localeString) && // No complaint about bogus locale diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/logging/RDFServiceLogger.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/logging/RDFServiceLogger.java index 4daebd9fe..6188a4378 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/logging/RDFServiceLogger.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/logging/RDFServiceLogger.java @@ -7,7 +7,7 @@ import java.util.Arrays; import java.util.List; import java.util.regex.Pattern; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/search/controller/AutocompleteController.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/search/controller/AutocompleteController.java index 294970953..a0e349c6f 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/search/controller/AutocompleteController.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/search/controller/AutocompleteController.java @@ -15,7 +15,7 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.json.JSONArray; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/search/controller/PagedSearchController.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/search/controller/PagedSearchController.java index 6a313e409..64911f65c 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/search/controller/PagedSearchController.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/search/controller/PagedSearchController.java @@ -18,7 +18,7 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/search/controller/UpdateUrisInIndex.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/search/controller/UpdateUrisInIndex.java index c8cf04478..1d86082e7 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/search/controller/UpdateUrisInIndex.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/search/controller/UpdateUrisInIndex.java @@ -16,7 +16,7 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import org.apache.commons.fileupload.FileItem; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/searchengine/SearchEngineLogger.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/searchengine/SearchEngineLogger.java index f3821ea77..d4b1cbf8f 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/searchengine/SearchEngineLogger.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/searchengine/SearchEngineLogger.java @@ -12,7 +12,7 @@ import java.util.Collection; import java.util.List; import java.util.regex.Pattern; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/searchindex/tasks/UpdateDocumentWorkUnit.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/searchindex/tasks/UpdateDocumentWorkUnit.java index cbab202e2..239812746 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/searchindex/tasks/UpdateDocumentWorkUnit.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/searchindex/tasks/UpdateDocumentWorkUnit.java @@ -18,7 +18,7 @@ import java.util.HashSet; import java.util.List; import java.util.Set; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.joda.time.DateTime; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/services/shortview/ShortViewService.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/services/shortview/ShortViewService.java index 13b04e32f..af0049767 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/services/shortview/ShortViewService.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/services/shortview/ShortViewService.java @@ -4,7 +4,7 @@ package edu.cornell.mannlib.vitro.webapp.services.shortview; import java.util.Map; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import edu.cornell.mannlib.vitro.webapp.beans.Individual; import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/triplesource/impl/sdb/SDBDataSource.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/triplesource/impl/sdb/SDBDataSource.java index 4131f91e2..4bbc7a839 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/triplesource/impl/sdb/SDBDataSource.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/triplesource/impl/sdb/SDBDataSource.java @@ -6,7 +6,7 @@ import java.beans.PropertyVetoException; import javax.servlet.ServletContext; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/DataGetterBase.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/DataGetterBase.java index 5545534ac..2f34b810e 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/DataGetterBase.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/DataGetterBase.java @@ -5,7 +5,7 @@ import static edu.cornell.mannlib.vitro.webapp.modelaccess.ModelNames.DISPLAY; import javax.servlet.ServletContext; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.jena.rdf.model.Model; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/DataGetterUtils.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/DataGetterUtils.java index b83c366fc..53e6ccea9 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/DataGetterUtils.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/DataGetterUtils.java @@ -10,7 +10,7 @@ import java.util.Map; import javax.servlet.http.HttpServletRequest; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.json.JSONObject; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/IndividualsForClassesDataGetter.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/IndividualsForClassesDataGetter.java index 782e928db..27ef8f9de 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/IndividualsForClassesDataGetter.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/IndividualsForClassesDataGetter.java @@ -11,7 +11,7 @@ import java.util.Map; import javax.servlet.ServletContext; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.json.JSONObject; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/developer/loggers/StackTraceUtility.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/developer/loggers/StackTraceUtility.java index ac63f22df..13b7e6358 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/developer/loggers/StackTraceUtility.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/developer/loggers/StackTraceUtility.java @@ -9,7 +9,7 @@ import java.util.List; import java.util.ListIterator; import java.util.regex.Pattern; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/logging/ToString.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/logging/ToString.java index 223206ad8..29fcb8ac6 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/logging/ToString.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/logging/ToString.java @@ -10,7 +10,7 @@ import java.util.List; import java.util.Map.Entry; import java.util.Set; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.jena.graph.Graph; import org.apache.jena.graph.compose.Polyadic; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/searchengine/AutoCompleteWords.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/searchengine/AutoCompleteWords.java index 0027c973d..2748f4758 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/searchengine/AutoCompleteWords.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/searchengine/AutoCompleteWords.java @@ -6,7 +6,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/searchengine/SearchQueryUtils.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/searchengine/SearchQueryUtils.java index 3c61a06fa..2abf76471 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/searchengine/SearchQueryUtils.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/searchengine/SearchQueryUtils.java @@ -7,7 +7,7 @@ import java.util.Collection; import java.util.List; import java.util.Map; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/sparql/RdfServiceQueryContext.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/sparql/RdfServiceQueryContext.java index e27f3ca9f..a3cdce5c7 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/sparql/RdfServiceQueryContext.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/sparql/RdfServiceQueryContext.java @@ -9,7 +9,7 @@ import java.util.Iterator; import java.util.Map; import java.util.Set; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/MiscWebUtils.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/MiscWebUtils.java index 743193c1e..81f1a6bf8 100755 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/MiscWebUtils.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/MiscWebUtils.java @@ -12,7 +12,7 @@ import javax.servlet.ServletRequest; import javax.servlet.http.HttpServletRequest; import javax.servlet.jsp.JspException; -import org.apache.commons.lang.StringEscapeUtils; +import org.apache.commons.lang3.StringEscapeUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -153,7 +153,7 @@ public class MiscWebUtils { Object obj = req.getAttribute(name); value = (obj instanceof Model || obj instanceof ModelCom) ? "[Jena model object]" : (obj == null) ? "[null]" : - StringEscapeUtils.escapeHtml(obj.toString()); + StringEscapeUtils.ESCAPE_HTML4.translate(obj.toString()); }catch(Exception ex){ value = "unable to get value" ; } catch (Error er){ @@ -177,7 +177,7 @@ public class MiscWebUtils { try{ Object obj = req.getParameter(name); value = (obj == null) ? "[null]" : - StringEscapeUtils.escapeHtml(obj.toString()); + StringEscapeUtils.ESCAPE_HTML4.translate(obj.toString()); }catch(Exception ex){ value = "unable to get value" ; } catch (Error er){ @@ -201,7 +201,7 @@ public class MiscWebUtils { Object obj = req.getSession().getAttribute(name); value = (obj instanceof Model || obj instanceof ModelCom) ? "[Jena model object]" : (obj == null) ? "[null]" : - StringEscapeUtils.escapeHtml(obj.toString()); + StringEscapeUtils.ESCAPE_HTML4.translate(obj.toString()); }catch(Exception ex){ value = "unable to get value" ; } catch (Error er){ diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/directives/WidgetDirective.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/directives/WidgetDirective.java index dff8eae6c..298a0be07 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/directives/WidgetDirective.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/directives/WidgetDirective.java @@ -11,7 +11,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/jsptags/OptionsForClassTag.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/jsptags/OptionsForClassTag.java index 3939a29c9..daa6ff814 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/jsptags/OptionsForClassTag.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/jsptags/OptionsForClassTag.java @@ -8,7 +8,7 @@ import edu.cornell.mannlib.vitro.webapp.beans.ObjectPropertyStatement; import edu.cornell.mannlib.vitro.webapp.beans.VClass; import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory; -import org.apache.commons.lang.StringEscapeUtils; +import org.apache.commons.lang3.StringEscapeUtils; import javax.servlet.http.HttpServletRequest; import javax.servlet.jsp.JspWriter; @@ -58,11 +58,11 @@ public class OptionsForClassTag extends TagSupport { for( Individual ind : individuals ){ String uri = ind.getURI() ; if( uri != null ){ - out.print(""); } diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/jsptags/OptionsForPropertyTag.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/jsptags/OptionsForPropertyTag.java index b3d90e8fb..261f42bdd 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/jsptags/OptionsForPropertyTag.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/jsptags/OptionsForPropertyTag.java @@ -14,7 +14,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.jsp.JspWriter; import javax.servlet.jsp.tagext.TagSupport; -import org.apache.commons.lang.StringEscapeUtils; +import org.apache.commons.lang3.StringEscapeUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -95,11 +95,11 @@ public class OptionsForPropertyTag extends TagSupport { for( Individual ind : individuals ){ String uri = ind.getURI() ; if( uri != null ){ - out.print(""); ++optionsCount; } diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/templatemodels/LinkTemplateModel.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/templatemodels/LinkTemplateModel.java index bab908947..edf9f9e2d 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/templatemodels/LinkTemplateModel.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/templatemodels/LinkTemplateModel.java @@ -2,7 +2,7 @@ package edu.cornell.mannlib.vitro.webapp.web.templatemodels; -import org.apache.commons.lang.StringEscapeUtils; +import org.apache.commons.lang3.StringEscapeUtils; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder.ParamMap; @@ -42,7 +42,7 @@ public class LinkTemplateModel extends BaseTemplateModel { } protected void setText(String text) { - this.text = StringEscapeUtils.escapeHtml(text); + this.text = StringEscapeUtils.ESCAPE_HTML4.translate(text); } /* Template properties */ diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/templatemodels/Tags.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/templatemodels/Tags.java index 07e769e56..359b37c21 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/templatemodels/Tags.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/templatemodels/Tags.java @@ -6,7 +6,7 @@ import java.lang.reflect.Method; import java.util.LinkedHashSet; import freemarker.ext.beans.MethodAppearanceFineTuner; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/templatemodels/VClassGroupTemplateModel.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/templatemodels/VClassGroupTemplateModel.java index a8db892ed..c0335b821 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/templatemodels/VClassGroupTemplateModel.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/templatemodels/VClassGroupTemplateModel.java @@ -5,7 +5,7 @@ package edu.cornell.mannlib.vitro.webapp.web.templatemodels; import java.util.ArrayList; import java.util.List; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/templatemodels/customlistview/DataPropertyListConfig.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/templatemodels/customlistview/DataPropertyListConfig.java index b88b9ab38..6d34ccef8 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/templatemodels/customlistview/DataPropertyListConfig.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/templatemodels/customlistview/DataPropertyListConfig.java @@ -8,7 +8,7 @@ import java.io.IOException; import java.lang.reflect.Constructor; import java.util.Set; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/templatemodels/customlistview/PropertyListConfig.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/templatemodels/customlistview/PropertyListConfig.java index fa212fd64..f2dda64dd 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/templatemodels/customlistview/PropertyListConfig.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/templatemodels/customlistview/PropertyListConfig.java @@ -8,7 +8,7 @@ import java.io.IOException; import java.lang.reflect.Constructor; import java.util.Set; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/templatemodels/edit/EditConfigurationTemplateModel.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/templatemodels/edit/EditConfigurationTemplateModel.java index 4990cdf03..02c2eb0a1 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/templatemodels/edit/EditConfigurationTemplateModel.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/templatemodels/edit/EditConfigurationTemplateModel.java @@ -15,7 +15,7 @@ import java.util.List; import java.util.Map; import java.util.Set; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/BaseIndividualTemplateModel.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/BaseIndividualTemplateModel.java index a233014fc..76c10a5a9 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/BaseIndividualTemplateModel.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/BaseIndividualTemplateModel.java @@ -12,7 +12,7 @@ import java.util.Map; import javax.servlet.ServletContext; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/CollatedObjectPropertyTemplateModel.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/CollatedObjectPropertyTemplateModel.java index 81dd48ad0..2f449cf0a 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/CollatedObjectPropertyTemplateModel.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/CollatedObjectPropertyTemplateModel.java @@ -15,7 +15,7 @@ import java.util.regex.Pattern; import javax.servlet.ServletContext; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/DataPropertyTemplateModel.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/DataPropertyTemplateModel.java index c49d17f47..b24c49e77 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/DataPropertyTemplateModel.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/DataPropertyTemplateModel.java @@ -8,7 +8,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Set; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/ObjectPropertyTemplateModel.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/ObjectPropertyTemplateModel.java index e26c43545..a0434968d 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/ObjectPropertyTemplateModel.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/ObjectPropertyTemplateModel.java @@ -12,7 +12,7 @@ import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/SubclassTemplateModel.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/SubclassTemplateModel.java index 05768ab10..b3bcee240 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/SubclassTemplateModel.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/SubclassTemplateModel.java @@ -4,7 +4,7 @@ package edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual; import java.util.List; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import edu.cornell.mannlib.vitro.webapp.beans.ObjectPropertyStatement; import edu.cornell.mannlib.vitro.webapp.beans.VClass; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/widgets/LoginWidget.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/widgets/LoginWidget.java index 347089b2e..5a62f7c32 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/widgets/LoginWidget.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/widgets/LoginWidget.java @@ -7,7 +7,7 @@ import java.util.Map; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/api/src/main/java/edu/ucsf/vitro/opensocial/OpenSocialSmokeTests.java b/api/src/main/java/edu/ucsf/vitro/opensocial/OpenSocialSmokeTests.java index 7e3d3cc9d..56010863e 100644 --- a/api/src/main/java/edu/ucsf/vitro/opensocial/OpenSocialSmokeTests.java +++ b/api/src/main/java/edu/ucsf/vitro/opensocial/OpenSocialSmokeTests.java @@ -20,7 +20,7 @@ import javax.servlet.ServletContextListener; import edu.cornell.mannlib.vitro.webapp.utils.http.HttpClientFactory; import org.apache.commons.dbcp.BasicDataSource; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.http.HttpResponse; diff --git a/api/src/main/java/freemarker/ext/dump/BaseDumpDirective.java b/api/src/main/java/freemarker/ext/dump/BaseDumpDirective.java index a2ff4b473..fc3e90247 100644 --- a/api/src/main/java/freemarker/ext/dump/BaseDumpDirective.java +++ b/api/src/main/java/freemarker/ext/dump/BaseDumpDirective.java @@ -17,7 +17,7 @@ import java.util.TreeMap; import java.util.regex.Matcher; import java.util.regex.Pattern; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/api/src/test/java/edu/cornell/mannlib/vitro/webapp/controller/api/sparqlquery/SparqlQueryApiExecutorTest.java b/api/src/test/java/edu/cornell/mannlib/vitro/webapp/controller/api/sparqlquery/SparqlQueryApiExecutorTest.java index 7938cf0bd..c9a402b53 100644 --- a/api/src/test/java/edu/cornell/mannlib/vitro/webapp/controller/api/sparqlquery/SparqlQueryApiExecutorTest.java +++ b/api/src/test/java/edu/cornell/mannlib/vitro/webapp/controller/api/sparqlquery/SparqlQueryApiExecutorTest.java @@ -14,7 +14,7 @@ import java.util.TreeSet; import java.util.regex.Matcher; import java.util.regex.Pattern; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.junit.Before; import org.junit.Test; diff --git a/api/src/test/java/edu/cornell/mannlib/vitro/webapp/freemarker/loader/FreemarkerTemplateLoaderTest.java b/api/src/test/java/edu/cornell/mannlib/vitro/webapp/freemarker/loader/FreemarkerTemplateLoaderTest.java index 0ed381c79..f4fa33767 100644 --- a/api/src/test/java/edu/cornell/mannlib/vitro/webapp/freemarker/loader/FreemarkerTemplateLoaderTest.java +++ b/api/src/test/java/edu/cornell/mannlib/vitro/webapp/freemarker/loader/FreemarkerTemplateLoaderTest.java @@ -11,7 +11,7 @@ import java.nio.file.Paths; import java.util.Arrays; import java.util.SortedSet; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.junit.Test; import edu.cornell.mannlib.vitro.webapp.freemarker.loader.FreemarkerTemplateLoader.PathPieces; diff --git a/api/src/test/java/edu/cornell/mannlib/vitro/webapp/i18n/selection/LocaleSelectionSetupTest.java b/api/src/test/java/edu/cornell/mannlib/vitro/webapp/i18n/selection/LocaleSelectionSetupTest.java index 3709d8a43..6d47d889f 100644 --- a/api/src/test/java/edu/cornell/mannlib/vitro/webapp/i18n/selection/LocaleSelectionSetupTest.java +++ b/api/src/test/java/edu/cornell/mannlib/vitro/webapp/i18n/selection/LocaleSelectionSetupTest.java @@ -14,8 +14,8 @@ import java.util.Locale; import javax.servlet.ServletContextEvent; -import org.apache.commons.lang.LocaleUtils; -import org.apache.commons.lang.ObjectUtils; +import org.apache.commons.lang3.LocaleUtils; +import org.apache.commons.lang3.ObjectUtils; import org.apache.log4j.Level; import org.junit.After; import org.junit.Before; @@ -66,7 +66,7 @@ public class LocaleSelectionSetupTest extends AbstractTestClass { @After public void checkExpectations() { if (expectedMessageCounts == null) { - fail("expecteMessages() was not called"); + fail("expectedMessages() was not called"); } String message = compareMessageCount("info", ss.getInfoCount(), @@ -194,7 +194,8 @@ public class LocaleSelectionSetupTest extends AbstractTestClass { public void langaugeIsEmpty() { props.setProperty(PROPERTY_FORCE_LOCALE, "_ES"); lss.contextInitialized(sce); - expectMessages(0, 1, 0); + expectForced("_ES"); + expectMessages(1, 1, 0); } @Test @@ -253,13 +254,14 @@ public class LocaleSelectionSetupTest extends AbstractTestClass { expectMessages(0, 1, 0); } - @Test - public void funkyVariantIsAcceptable() { - props.setProperty(PROPERTY_FORCE_LOCALE, "es_ES_123_aa"); - lss.contextInitialized(sce); - expectForced("es_ES_123_aa"); - expectMessages(1, 1, 0); - } + // This shouldn't really be acceptable, so we won't test that it is +// @Test +// public void funkyVariantIsAcceptable() { +// props.setProperty(PROPERTY_FORCE_LOCALE, "es_ES_123_aa"); +// lss.contextInitialized(sce); +// expectForced("es_ES_123_aa"); +// expectMessages(1, 1, 0); +// } @Test public void localeNotRecognizedProducesWarning() { diff --git a/api/src/test/java/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/DataGetterUtilsTest.java b/api/src/test/java/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/DataGetterUtilsTest.java index 2f556b6a0..2fbf225cd 100644 --- a/api/src/test/java/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/DataGetterUtilsTest.java +++ b/api/src/test/java/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/DataGetterUtilsTest.java @@ -5,7 +5,7 @@ import java.io.InputStream; import java.lang.reflect.InvocationTargetException; import java.util.List; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Level; import org.junit.Assert; import org.junit.Before; diff --git a/api/src/test/java/freemarker/ext/dump/DumpDirectiveTest.java b/api/src/test/java/freemarker/ext/dump/DumpDirectiveTest.java index 54916c659..0c8dcb21f 100644 --- a/api/src/test/java/freemarker/ext/dump/DumpDirectiveTest.java +++ b/api/src/test/java/freemarker/ext/dump/DumpDirectiveTest.java @@ -22,7 +22,7 @@ import java.util.Set; import java.util.SortedMap; import java.util.TreeMap; -import org.apache.commons.lang.time.DateUtils; +import org.apache.commons.lang3.time.DateUtils; import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.junit.Before; diff --git a/dependencies/pom.xml b/dependencies/pom.xml index 15e853c50..742bce735 100644 --- a/dependencies/pom.xml +++ b/dependencies/pom.xml @@ -106,9 +106,10 @@ 2.5 - commons-lang - commons-lang - 2.6 + + org.apache.commons + commons-lang3 + 3.4 commons-logging diff --git a/legacy/utilities/buildutils/src/edu/cornell/mannlib/vitro/utilities/containerneutral/CheckContainerNeutrality.java b/legacy/utilities/buildutils/src/edu/cornell/mannlib/vitro/utilities/containerneutral/CheckContainerNeutrality.java index 4b2c4bfa1..cdc517d33 100644 --- a/legacy/utilities/buildutils/src/edu/cornell/mannlib/vitro/utilities/containerneutral/CheckContainerNeutrality.java +++ b/legacy/utilities/buildutils/src/edu/cornell/mannlib/vitro/utilities/containerneutral/CheckContainerNeutrality.java @@ -26,7 +26,7 @@ import javax.xml.xpath.XPathExpression; import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; diff --git a/legacy/utilities/rdbmigration/src/edu/cornell/mannlib/vivo/utilities/rdbmigration/RdbMigrator.java b/legacy/utilities/rdbmigration/src/edu/cornell/mannlib/vivo/utilities/rdbmigration/RdbMigrator.java index 2381f16dd..b06b5d601 100644 --- a/legacy/utilities/rdbmigration/src/edu/cornell/mannlib/vivo/utilities/rdbmigration/RdbMigrator.java +++ b/legacy/utilities/rdbmigration/src/edu/cornell/mannlib/vivo/utilities/rdbmigration/RdbMigrator.java @@ -19,7 +19,7 @@ import java.util.Arrays; import java.util.List; import java.util.Properties; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.jena.db.DBConnection; import org.apache.jena.db.GraphRDB; From 05c4c6ce84eff1bee150bde8c44089451d21e4eb Mon Sep 17 00:00:00 2001 From: Graham Triggs Date: Sat, 17 Dec 2016 23:17:43 +0000 Subject: [PATCH 18/49] Update jSoup and Antisamy --- dependencies/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dependencies/pom.xml b/dependencies/pom.xml index 742bce735..79a9ff0e0 100644 --- a/dependencies/pom.xml +++ b/dependencies/pom.xml @@ -218,12 +218,12 @@ org.jsoup jsoup - 1.6.1 + 1.10.1 org.owasp.antisamy antisamy - 1.4.4 + 1.5.3 From 45eef7e9f7e7ba040b9f316a73a4de2ffdd9c339 Mon Sep 17 00:00:00 2001 From: Graham Triggs Date: Sun, 18 Dec 2016 19:01:15 +0000 Subject: [PATCH 19/49] Remove JAI dependencies from ImageIO Image Processor --- .../imageio/IIOImageProcessor.java | 45 +++---------------- 1 file changed, 6 insertions(+), 39 deletions(-) diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/imageprocessor/imageio/IIOImageProcessor.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/imageprocessor/imageio/IIOImageProcessor.java index 7add5de92..f7ddc725e 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/imageprocessor/imageio/IIOImageProcessor.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/imageprocessor/imageio/IIOImageProcessor.java @@ -2,7 +2,6 @@ package edu.cornell.mannlib.vitro.webapp.imageprocessor.imageio; -import com.sun.media.jai.codec.MemoryCacheSeekableStream; import edu.cornell.mannlib.vitro.webapp.modules.Application; import edu.cornell.mannlib.vitro.webapp.modules.ComponentStartupStatus; import edu.cornell.mannlib.vitro.webapp.modules.imageProcessor.ImageProcessor; @@ -10,11 +9,8 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import javax.imageio.ImageIO; -import javax.media.jai.JAI; -import javax.media.jai.RenderedOp; -import javax.media.jai.operator.BandSelectDescriptor; -import javax.media.jai.operator.StreamDescriptor; -import javax.media.jai.util.ImagingListener; +import javax.imageio.stream.ImageInputStream; +import javax.imageio.stream.MemoryCacheImageInputStream; import java.awt.geom.AffineTransform; import java.awt.image.AffineTransformOp; import java.awt.image.BufferedImage; @@ -55,8 +51,8 @@ public class IIOImageProcessor implements ImageProcessor { */ @Override public void startup(Application application, ComponentStartupStatus ss) { - JAI.getDefaultInstance().setImagingListener( - new NonNoisyImagingListener()); +// JAI.getDefaultInstance().setImagingListener( +// new NonNoisyImagingListener()); } @Override @@ -66,7 +62,7 @@ public class IIOImageProcessor implements ImageProcessor { @Override public Dimensions getDimensions(InputStream imageStream) throws ImageProcessorException, IOException { - MemoryCacheSeekableStream stream = new MemoryCacheSeekableStream(imageStream); + ImageInputStream stream = new MemoryCacheImageInputStream(imageStream); BufferedImage image = ImageIO.read(stream); return new Dimensions(image.getWidth(), image.getHeight()); } @@ -80,7 +76,7 @@ public class IIOImageProcessor implements ImageProcessor { CropRectangle crop, Dimensions limits) throws ImageProcessorException, IOException { try { - MemoryCacheSeekableStream stream = new MemoryCacheSeekableStream(mainImageStream); + ImageInputStream stream = new MemoryCacheImageInputStream(mainImageStream); BufferedImage mainImage = ImageIO.read(stream); BufferedImage bufferedImage = new BufferedImage(mainImage.getWidth(), mainImage.getHeight(), BufferedImage.TYPE_3BYTE_BGR); // BufferedImage.TYPE_INT_RGB @@ -176,33 +172,4 @@ public class IIOImageProcessor implements ImageProcessor { ImageIO.write(image, "JPG", bytes); return bytes.toByteArray(); } - - /** - * This ImagingListener means that Java Advanced Imaging won't dump an - * exception log to System.out. It writes to the log, instead. - * - * Further, since the lack of native accelerator classes isn't an error, it - * is written as a simple log message. - */ - static class NonNoisyImagingListener implements ImagingListener { - @Override - public boolean errorOccurred(String message, Throwable thrown, - Object where, boolean isRetryable) throws RuntimeException { - if (thrown instanceof RuntimeException) { - throw (RuntimeException) thrown; - } - if ((thrown instanceof NoClassDefFoundError) - && (thrown.getMessage() - .contains("com/sun/medialib/mlib/Image"))) { - log.info("Java Advanced Imaging: Could not find mediaLib " - + "accelerator wrapper classes. " - + "Continuing in pure Java mode."); - return false; - } - log.error(thrown, thrown); - return false; - } - - } - } From 6351e6ba1ddd04c56cfacb46b7772e166abccde8 Mon Sep 17 00:00:00 2001 From: Graham Triggs Date: Mon, 19 Dec 2016 10:52:29 +0000 Subject: [PATCH 20/49] Replace JAI image processor with IIO image processor and log warnings to update configuration --- .../imageprocessor/jai/JaiImageProcessor.java | 236 ++---------------- 1 file changed, 23 insertions(+), 213 deletions(-) diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/imageprocessor/jai/JaiImageProcessor.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/imageprocessor/jai/JaiImageProcessor.java index b5d4a7cae..dc8e8f674 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/imageprocessor/jai/JaiImageProcessor.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/imageprocessor/jai/JaiImageProcessor.java @@ -2,234 +2,44 @@ package edu.cornell.mannlib.vitro.webapp.imageprocessor.jai; -import java.awt.geom.AffineTransform; -import java.awt.image.AffineTransformOp; -import java.awt.image.BufferedImage; -import java.awt.image.ColorConvertOp; -import java.awt.image.ColorModel; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; - -import javax.imageio.ImageIO; -import javax.media.jai.JAI; -import javax.media.jai.RenderedOp; -import javax.media.jai.operator.BandSelectDescriptor; -import javax.media.jai.operator.StreamDescriptor; -import javax.media.jai.util.ImagingListener; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import com.sun.media.jai.codec.MemoryCacheSeekableStream; - +import edu.cornell.mannlib.vitro.webapp.imageprocessor.imageio.IIOImageProcessor; import edu.cornell.mannlib.vitro.webapp.modules.Application; import edu.cornell.mannlib.vitro.webapp.modules.ComponentStartupStatus; import edu.cornell.mannlib.vitro.webapp.modules.imageProcessor.ImageProcessor; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.io.IOException; +import java.io.InputStream; /** - * Crop the main image as specified, and scale it to the correct size for a - * thumbnail. - * - * Use the JAI library to read the file because the javax.imageio package - * doesn't read extended JPEG properly. Use JAI to remove transparency from - * JPEGs and PNGs, simply by removing the alpha channel. Annoyingly, this will - * not work with GIFs with transparent pixels. - * - * The transforms in the JAI library are buggy, so standard AWT operations do - * the scaling and cropping. The most obvious problem in the JAI library is the - * refusal to crop after scaling an image. - * - * Scale first to avoid the boundary error that produces black lines along the - * edge of the image. - * - * Use the javax.imagio pacakge to write the thumbnail image as a JPEG file. + * Re-implemented as ImageIO / TwelveMonkeys plugin for better OpenJDK compatibility and to remove + * JAI codec dependencies that are not distributed via Maven + * + * This transitional stub extends the new class, and logs warnings for people to update their config */ -public class JaiImageProcessor implements ImageProcessor { +@Deprecated +public class JaiImageProcessor extends IIOImageProcessor { private static final Log log = LogFactory.getLog(JaiImageProcessor.class); - /** If an image has 3 color bands and 1 alpha band, we want these. */ - private static final int[] COLOR_BAND_INDEXES = new int[] { 0, 1, 2 }; - - /** - * Prevent Java Advanced Imaging from complaining about the lack of - * accelerator classes. - */ + @Deprecated @Override public void startup(Application application, ComponentStartupStatus ss) { - JAI.getDefaultInstance().setImagingListener( - new NonNoisyImagingListener()); + log.warn("JaiImageProcessor is deprecated and will be removed - please update config/applicationSetup.n3 to use edu.cornell.mannlib.vitro.webapp.imageprocessor.imageio.IIOImageProcessor"); + super.startup(application, ss); } + @Deprecated @Override - public void shutdown(Application application) { - // Nothing to tear down. + public Dimensions getDimensions(InputStream imageStream) throws ImageProcessorException, IOException { + log.warn("JaiImageProcessor is deprecated and will be removed - please update config/applicationSetup.n3 to use edu.cornell.mannlib.vitro.webapp.imageprocessor.imageio.IIOImageProcessor"); + return super.getDimensions(imageStream); } + @Deprecated @Override - public Dimensions getDimensions(InputStream imageStream) - throws ImageProcessorException, IOException { - MemoryCacheSeekableStream stream = new MemoryCacheSeekableStream( - imageStream); - RenderedOp image = JAI.create("stream", stream); - return new Dimensions(image.getWidth(), image.getHeight()); + public InputStream cropAndScale(InputStream mainImageStream, CropRectangle crop, Dimensions limits) throws ImageProcessorException, IOException { + log.warn("JaiImageProcessor is deprecated and will be removed - please update config/applicationSetup.n3 to use edu.cornell.mannlib.vitro.webapp.imageprocessor.imageio.IIOImageProcessor"); + return super.cropAndScale(mainImageStream, crop, limits); } - - /** - * Crop the main image according to this rectangle, and scale it to the - * correct size for a thumbnail. - */ - @Override - public InputStream cropAndScale(InputStream mainImageStream, - CropRectangle crop, Dimensions limits) - throws ImageProcessorException, IOException { - try { - RenderedOp mainImage = loadImage(mainImageStream); - - BufferedImage bufferedImage = new BufferedImage(mainImage.getWidth(), mainImage.getHeight(), BufferedImage.TYPE_3BYTE_BGR); // BufferedImage.TYPE_INT_RGB - new ColorConvertOp(null).filter(mainImage.getAsBufferedImage(), bufferedImage); - - log.debug("initial image: " + imageSize(bufferedImage)); - - log.debug("initial crop: " + crop); - CropRectangle boundedCrop = limitCropRectangleToImageBounds( - bufferedImage, crop); - log.debug("bounded crop: " + boundedCrop); - - float scaleFactor = figureScaleFactor(boundedCrop, limits); - log.debug("scale factor: " + scaleFactor); - - BufferedImage scaledImage = scaleImage(bufferedImage, scaleFactor); - log.debug("scaled image: " + imageSize(scaledImage)); - - CropRectangle rawScaledCrop = adjustCropRectangleToScaledImage( - boundedCrop, scaleFactor); - log.debug("scaled crop: " + rawScaledCrop); - CropRectangle scaledCrop = limitCropRectangleToImageBounds( - scaledImage, rawScaledCrop); - log.debug("bounded scaled crop: " + scaledCrop); - - BufferedImage croppedImage = cropImage(scaledImage, scaledCrop); - log.debug("cropped image: " + imageSize(croppedImage)); - - byte[] jpegBytes = encodeAsJpeg(croppedImage); - return new ByteArrayInputStream(jpegBytes); - } catch (Exception e) { - throw new IllegalStateException("Failed to scale the image", e); - } - } - - private RenderedOp loadImage(InputStream imageStream) { - return StreamDescriptor.create(new MemoryCacheSeekableStream( - imageStream), null, null); - } - - private RenderedOp makeImageOpaque(RenderedOp image) { - ColorModel colorModel = image.getColorModel(); - - if (!colorModel.hasAlpha()) { - // The image is already opaque. - return image; - } - - if (image.getNumBands() == 4) { - // The image has a separate alpha channel. Drop the alpha channel. - return BandSelectDescriptor.create(image, COLOR_BAND_INDEXES, null); - } - - // Don't know how to handle it. Probably a GIF with a transparent - // background. Give up. - return image; - } - - private String imageSize(BufferedImage image) { - return image.getWidth() + " by " + image.getHeight(); - } - - private CropRectangle limitCropRectangleToImageBounds(BufferedImage image, - CropRectangle crop) { - - int imageWidth = image.getWidth(); - int imageHeight = image.getHeight(); - - // Ensure that x and y are at least zero, but not big enough to push the - // crop rectangle out of the image. - int greatestX = imageWidth - MINIMUM_CROP_SIZE; - int greatestY = imageHeight - MINIMUM_CROP_SIZE; - int x = Math.max(0, Math.min(greatestX, Math.abs(crop.x))); - int y = Math.max(0, Math.min(greatestY, Math.abs(crop.y))); - - // Ensure that width and height are at least as big as the minimum, but - // no so big as to extend beyond the image. - int greatestW = imageWidth - x; - int greatestH = imageHeight - y; - int w = Math.max(MINIMUM_CROP_SIZE, Math.min(greatestW, crop.width)); - int h = Math.max(MINIMUM_CROP_SIZE, Math.min(greatestH, crop.height)); - - return new CropRectangle(x, y, h, w); - } - - private float figureScaleFactor(CropRectangle boundedCrop, Dimensions limits) { - float horizontalScale = ((float) limits.width) - / ((float) boundedCrop.width); - float verticalScale = ((float) limits.height) - / ((float) boundedCrop.height); - return Math.min(horizontalScale, verticalScale); - } - - private BufferedImage scaleImage(BufferedImage image, float scaleFactor) { - AffineTransform transform = AffineTransform.getScaleInstance( - scaleFactor, scaleFactor); - AffineTransformOp atoOp = new AffineTransformOp(transform, null); - return atoOp.filter(image, null); - } - - private CropRectangle adjustCropRectangleToScaledImage(CropRectangle crop, - float scaleFactor) { - int newX = (int) (crop.x * scaleFactor); - int newY = (int) (crop.y * scaleFactor); - int newHeight = (int) (crop.height * scaleFactor); - int newWidth = (int) (crop.width * scaleFactor); - return new CropRectangle(newX, newY, newHeight, newWidth); - } - - private BufferedImage cropImage(BufferedImage image, CropRectangle crop) { - return image.getSubimage(crop.x, crop.y, crop.width, crop.height); - } - - private byte[] encodeAsJpeg(BufferedImage image) throws IOException { - ByteArrayOutputStream bytes = new ByteArrayOutputStream(); - ImageIO.write(image, "JPG", bytes); - return bytes.toByteArray(); - } - - /** - * This ImagingListener means that Java Advanced Imaging won't dump an - * exception log to System.out. It writes to the log, instead. - * - * Further, since the lack of native accelerator classes isn't an error, it - * is written as a simple log message. - */ - static class NonNoisyImagingListener implements ImagingListener { - @Override - public boolean errorOccurred(String message, Throwable thrown, - Object where, boolean isRetryable) throws RuntimeException { - if (thrown instanceof RuntimeException) { - throw (RuntimeException) thrown; - } - if ((thrown instanceof NoClassDefFoundError) - && (thrown.getMessage() - .contains("com/sun/medialib/mlib/Image"))) { - log.info("Java Advanced Imaging: Could not find mediaLib " - + "accelerator wrapper classes. " - + "Continuing in pure Java mode."); - return false; - } - log.error(thrown, thrown); - return false; - } - - } - } From aaa9ac6989bbe38bcf689e62fb943d34804750be Mon Sep 17 00:00:00 2001 From: Graham Triggs Date: Mon, 19 Dec 2016 10:59:28 +0000 Subject: [PATCH 21/49] =?UTF-8?q?Migrating=20image=20processor=20testers?= =?UTF-8?q?=20for=20the=20ImageIO=20implementation=20-=20stage=201,=20remo?= =?UTF-8?q?ve=20the=20old=20testers=20from=20branch=20so=20build=20doesn?= =?UTF-8?q?=E2=80=99t=20break?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../imageio/JaiImageProcessorTester.java | 134 +++++++++ .../imageio/JaiImageProcessorTester2.java | 272 ++++++++++++++++++ 2 files changed, 406 insertions(+) create mode 100644 api/src/test/java/edu/cornell/mannlib/vitro/webapp/imageprocessor/imageio/JaiImageProcessorTester.java create mode 100644 api/src/test/java/edu/cornell/mannlib/vitro/webapp/imageprocessor/imageio/JaiImageProcessorTester2.java diff --git a/api/src/test/java/edu/cornell/mannlib/vitro/webapp/imageprocessor/imageio/JaiImageProcessorTester.java b/api/src/test/java/edu/cornell/mannlib/vitro/webapp/imageprocessor/imageio/JaiImageProcessorTester.java new file mode 100644 index 000000000..8dbccf723 --- /dev/null +++ b/api/src/test/java/edu/cornell/mannlib/vitro/webapp/imageprocessor/imageio/JaiImageProcessorTester.java @@ -0,0 +1,134 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.vitro.webapp.imageprocessor.imageio; + +import static edu.cornell.mannlib.vitro.webapp.controller.freemarker.ImageUploadController.THUMBNAIL_HEIGHT; +import static edu.cornell.mannlib.vitro.webapp.controller.freemarker.ImageUploadController.THUMBNAIL_WIDTH; + +import java.awt.Frame; +import java.awt.GridLayout; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import javax.media.jai.RenderedOp; +import javax.media.jai.operator.StreamDescriptor; + +import org.apache.log4j.Level; +import org.apache.log4j.Logger; + +import com.sun.media.jai.codec.MemoryCacheSeekableStream; + +import edu.cornell.mannlib.vitro.webapp.imageprocessor.jai.JaiImageProcessor; +import edu.cornell.mannlib.vitro.webapp.modules.imageProcessor.ImageProcessor.CropRectangle; +import edu.cornell.mannlib.vitro.webapp.modules.imageProcessor.ImageProcessor.Dimensions; + +/** + * This is not a unit test, so it is not named BlahBlahTest. + * + * Instead, it's a test harness that creates thumbnails and writes them to + * files, while also displaying them in a window on the screen. It takes human + * intervention to evaluate. + * + * This is especially true because the images on the screen look color-correct, + * but when viewed in the browser, they might not be. + */ +public class JaiImageProcessorTester extends Frame { + + /** Big enough to hold the JPEG file, certainly. */ + private final static int BUFFER_SIZE = 200 * 200 * 4; + + private final static Dimensions THUMBNAIL_SIZE = new Dimensions( + THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT); + + private final static ImageCropData[] THUMBNAIL_DATA = new ImageCropData[] { + new ImageCropData("/Users/jeb228/Pictures/JimBlake_20010915.jpg", + 50, 50, 115), + new ImageCropData("/Users/jeb228/Pictures/brazil_collab.png", 600, + 250, 400), + new ImageCropData("/Users/jeb228/Pictures/wheel.png", 0, 0, 195), + new ImageCropData("/Users/jeb228/Pictures/DSC04203w-trans.gif", + 400, 1200, 800) }; + + private final JaiImageProcessor thumbnailer = new JaiImageProcessor(); + + @SuppressWarnings("deprecation") + private JaiImageProcessorTester() { + setTitle("Alpha Killer Test"); + addWindowListener(new CloseWindowListener()); + setLayout(createLayout()); + for (ImageCropData icd : THUMBNAIL_DATA) { + try { + InputStream mainStream = new FileInputStream(icd.filename); + File thumbFile = writeToTempFile(thumbnailer.cropAndScale( + mainStream, icd.crop, THUMBNAIL_SIZE)); + System.out.println(thumbFile.getAbsolutePath()); + + MemoryCacheSeekableStream thumbFileStream = new MemoryCacheSeekableStream( + new FileInputStream(thumbFile)); + RenderedOp thumbImage = StreamDescriptor.create( + thumbFileStream, null, null); + add(new javax.media.jai.widget.ImageCanvas(thumbImage)); + } catch (Exception e) { + e.printStackTrace(); + } + } + pack(); + setVisible(true); + } + + /** + * @param thumbStream Thumbnail stream + * @throws IOException + * @throws FileNotFoundException + */ + private File writeToTempFile(InputStream thumbStream) throws IOException, + FileNotFoundException { + File thumbFile = File.createTempFile("ImageUploaderThumbnailerTester", + ""); + OutputStream imageOutputStream = new FileOutputStream(thumbFile); + byte[] buffer = new byte[BUFFER_SIZE]; + int howMany = thumbStream.read(buffer); + imageOutputStream.write(buffer, 0, howMany); + imageOutputStream.close(); + return thumbFile; + } + + private GridLayout createLayout() { + GridLayout layout = new GridLayout(1, THUMBNAIL_DATA.length); + layout.setHgap(10); + return layout; + } + + @SuppressWarnings("unused") + public static void main(String[] args) { + Logger.getLogger(JaiImageProcessor.class).setLevel(Level.DEBUG); + new JaiImageProcessorTester(); + } + + private static class ImageCropData { + final String filename; + final CropRectangle crop; + + ImageCropData(String filename, int x, int y, int size) { + this.filename = filename; + this.crop = new CropRectangle(x, y, size, + size); + } + } + + private class CloseWindowListener extends WindowAdapter { + @Override + public void windowClosing(WindowEvent e) { + setVisible(false); + dispose(); + System.exit(0); + } + } +} diff --git a/api/src/test/java/edu/cornell/mannlib/vitro/webapp/imageprocessor/imageio/JaiImageProcessorTester2.java b/api/src/test/java/edu/cornell/mannlib/vitro/webapp/imageprocessor/imageio/JaiImageProcessorTester2.java new file mode 100644 index 000000000..87e89c147 --- /dev/null +++ b/api/src/test/java/edu/cornell/mannlib/vitro/webapp/imageprocessor/imageio/JaiImageProcessorTester2.java @@ -0,0 +1,272 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.vitro.webapp.imageprocessor.imageio; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Frame; +import java.awt.GridLayout; +import java.awt.Label; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.awt.image.Raster; +import java.io.FileInputStream; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import javax.media.jai.JAI; +import javax.media.jai.RenderedOp; +import javax.media.jai.operator.StreamDescriptor; +import javax.swing.BorderFactory; +import javax.swing.JPanel; + +import edu.cornell.mannlib.vitro.webapp.imageprocessor.jai.JaiImageProcessor; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.log4j.Appender; +import org.apache.log4j.Level; +import org.apache.log4j.Logger; +import org.apache.log4j.PatternLayout; + +import com.sun.media.jai.codec.MemoryCacheSeekableStream; + +import edu.cornell.mannlib.vitro.webapp.imageprocessor.imageio.JaiImageProcessorTester2.CropDataSet.CropData; +import edu.cornell.mannlib.vitro.webapp.imageprocessor.jai.JaiImageProcessor.NonNoisyImagingListener; +import edu.cornell.mannlib.vitro.webapp.modules.imageProcessor.ImageProcessor.CropRectangle; +import edu.cornell.mannlib.vitro.webapp.modules.imageProcessor.ImageProcessor.Dimensions; + +/** + * This is not a unit test, so it is not named BlahBlahTest. + * + * Instead, it's a test harness that creates thumbnails and displays them in a + * window on the screen. It takes human intervention to evaluate. + * + * The goal here is to see whether differences in crop dimensions might cause + * one or more black edges on the thumbnails. + */ +@SuppressWarnings("deprecation") +public class JaiImageProcessorTester2 extends Frame { + private static final Log log = LogFactory + .getLog(JaiImageProcessorTester2.class); + + private static final int ROWS = 6; + private static final int COLUMNS = 9; + + private static final int EDGE_THRESHOLD = 6000; + + private static final Dimensions THUMBNAIL_SIZE = new Dimensions(200, 200); + + /** Keep things quiet. */ + static { + JAI.getDefaultInstance().setImagingListener( + new NonNoisyImagingListener()); + } + + private final String imagePath; + private final JaiImageProcessor thumbnailer; + + public JaiImageProcessorTester2(String imagePath, + CropDataSet cropDataSet) { + this.imagePath = imagePath; + this.thumbnailer = new JaiImageProcessor(); + + setTitle("Cropping edging test"); + addWindowListener(new CloseWindowListener()); + setLayout(new GridLayout(ROWS, COLUMNS)); + + for (CropData cropData : cropDataSet.crops()) { + add(createImagePanel(cropData)); + } + + pack(); + setVisible(true); + } + + private Component createImagePanel(CropData cropData) { + RenderedOp image = createCroppedImage(cropData); + + + Set blackSides = checkBlackEdges(image); + if (!blackSides.isEmpty()) { + log.warn("edges at " + cropData + ", " + blackSides); + } + + String legend = "left=" + cropData.left + ", top=" + cropData.top + + ", size=" + cropData.size; + Label l = new Label(); + l.setAlignment(Label.CENTER); + if (!blackSides.isEmpty()) { + l.setBackground(new Color(0xFFDDDD)); + legend += " " + blackSides; + } + l.setText(legend); + + JPanel p = new JPanel(); + p.setLayout(new BorderLayout()); + p.add("South", l); + p.add("Center", new javax.media.jai.widget.ImageCanvas(image)); + p.setBackground(new Color(0xFFFFFF)); + p.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + + return p; + } + + private RenderedOp createCroppedImage(CropData cropData) { + try { + InputStream mainStream = new FileInputStream(imagePath); + CropRectangle rectangle = new CropRectangle(cropData.left, + cropData.top, cropData.size, cropData.size); + InputStream thumbnailStream = thumbnailer.cropAndScale(mainStream, + rectangle, THUMBNAIL_SIZE); + + return StreamDescriptor.create(new MemoryCacheSeekableStream( + thumbnailStream), null, null); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private Set checkBlackEdges(RenderedOp image) { + Raster imageData = image.getData(); + + int minX = imageData.getMinX(); + int minY = imageData.getMinY(); + int maxX = minX + imageData.getWidth() - 1; + int maxY = minY + imageData.getHeight() - 1; + + Set blackSides = new HashSet(); + if (isBlackEdge(minX, minX, minY, maxY, imageData)) { + blackSides.add("left"); + } + if (isBlackEdge(minX, maxX, minY, minY, imageData)) { + blackSides.add("top"); + } + if (isBlackEdge(maxX, maxX, minY, maxY, imageData)) { + blackSides.add("right"); + } + if (isBlackEdge(minX, maxX, maxY, maxY, imageData)) { + blackSides.add("bottom"); + } + return blackSides; + } + + private boolean isBlackEdge(int fromX, int toX, int fromY, int toY, + Raster imageData) { + int edgeTotal = 0; + try { + for (int col = fromX; col <= toX; col++) { + for (int row = fromY; row <= toY; row++) { + edgeTotal += sumPixel(imageData, col, row); + } + } + } catch (Exception e) { + log.error("can't sum edge: fromX=" + fromX + ", toX=" + toX + + ", fromY=" + fromY + ", toY=" + toY + ", imageWidth=" + + imageData.getWidth() + ", imageHeight=" + + imageData.getHeight() + ": " + e); + } + + log.debug("edge total = " + edgeTotal); + return edgeTotal < EDGE_THRESHOLD; + } + + private int sumPixel(Raster imageData, int col, int row) { + int pixelSum = 0; + int[] pixel = imageData.getPixel(col, row, new int[0]); + for (int value : pixel) { + pixelSum += value; + } + return pixelSum; + } + + /** + *
+	 * The plan:
+	 * 
+	 * Provide the path to an image file.
+	 * Figure how many images can fit on the screen.
+	 * Crop in increments, starting at 0,0 and varying the size of the crop.
+	 * Crop in increments, incrementing from 0,0 downward, and varying the size of the crop.
+	 * 
+	 * Start by creating 4 x 4 images in a window, and incrementing from 201 to 216.
+	 * 
+ */ + + public static void main(String[] args) { + Logger rootLogger = Logger.getRootLogger(); + Appender appender = (Appender) rootLogger.getAllAppenders() + .nextElement(); + appender.setLayout(new PatternLayout("%-5p [%c{1}] %m%n")); + + Logger.getLogger(JaiImageProcessor.class).setLevel(Level.DEBUG); + Logger.getLogger(JaiImageProcessorTester2.class).setLevel( + Level.INFO); + + CropDataSet cropDataSet = new CropDataSet(); + for (int i = 0; i < ROWS * COLUMNS; i++) { +// cropDataSet.add(i, i, 201 + i); + cropDataSet.add(0, 0, 201 + i); + } + + new JaiImageProcessorTester2( + "C:/Users/jeb228/Pictures/wheel.png", cropDataSet); + +// new ImageUploaderThumbnailerTester_2( +// "C:/Users/jeb228/Pictures/DSC04203w-trans.jpg", cropDataSet); + + // new ImageUploaderThumbnailerTester_2( +// "C:/Development/JIRA issues/NIHVIVO-2477 Black borders on thumbnails/" +// + "images from Alex/uploads/file_storage_root/a~n/411/9/" +// + "De^20Bartolome^2c^20Charles^20A^20M_100037581.jpg", +// cropDataSet); + } + + // ---------------------------------------------------------------------- + // helper classes + // ---------------------------------------------------------------------- + + private class CloseWindowListener extends WindowAdapter { + @Override + public void windowClosing(WindowEvent e) { + setVisible(false); + dispose(); + System.exit(0); + } + } + + public static class CropDataSet { + private final List crops = new ArrayList(); + + CropDataSet add(int left, int top, int size) { + crops.add(new CropData(left, top, size)); + return this; + } + + Collection crops() { + return Collections.unmodifiableCollection(crops); + } + + public static class CropData { + final int left; + final int top; + final int size; + + CropData(int left, int top, int size) { + this.left = left; + this.top = top; + this.size = size; + } + + @Override + public String toString() { + return "CropData[" + left + ", " + top + ", " + size + "]"; + } + } + } +} From 05366f7ebe700ccc3aa37973a7babb611609fcc8 Mon Sep 17 00:00:00 2001 From: Graham Triggs Date: Mon, 19 Dec 2016 11:02:03 +0000 Subject: [PATCH 22/49] Help Travis by caching Maven dependencies --- .travis.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.travis.yml b/.travis.yml index 04c61e69a..0d23476e4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,6 +8,11 @@ env: # Give Maven 1GB of memory to work with - MAVEN_OPTS=-Xmx1024M +cache: + directories: + - .autoconf + - $HOME/.m2 + install: - "echo 'Skipping install stage, dependencies will be downloaded during build and test stages.'" From e24943aa507e1ec992363ff7ae5152d2f701adbf Mon Sep 17 00:00:00 2001 From: Graham Triggs Date: Mon, 19 Dec 2016 11:06:02 +0000 Subject: [PATCH 23/49] Committed wrong files - removing incomplete image processor testers from image --- .../imageio/JaiImageProcessorTester.java | 134 --------- .../imageio/JaiImageProcessorTester2.java | 272 ------------------ 2 files changed, 406 deletions(-) delete mode 100644 api/src/test/java/edu/cornell/mannlib/vitro/webapp/imageprocessor/imageio/JaiImageProcessorTester.java delete mode 100644 api/src/test/java/edu/cornell/mannlib/vitro/webapp/imageprocessor/imageio/JaiImageProcessorTester2.java diff --git a/api/src/test/java/edu/cornell/mannlib/vitro/webapp/imageprocessor/imageio/JaiImageProcessorTester.java b/api/src/test/java/edu/cornell/mannlib/vitro/webapp/imageprocessor/imageio/JaiImageProcessorTester.java deleted file mode 100644 index 8dbccf723..000000000 --- a/api/src/test/java/edu/cornell/mannlib/vitro/webapp/imageprocessor/imageio/JaiImageProcessorTester.java +++ /dev/null @@ -1,134 +0,0 @@ -/* $This file is distributed under the terms of the license in /doc/license.txt$ */ - -package edu.cornell.mannlib.vitro.webapp.imageprocessor.imageio; - -import static edu.cornell.mannlib.vitro.webapp.controller.freemarker.ImageUploadController.THUMBNAIL_HEIGHT; -import static edu.cornell.mannlib.vitro.webapp.controller.freemarker.ImageUploadController.THUMBNAIL_WIDTH; - -import java.awt.Frame; -import java.awt.GridLayout; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -import javax.media.jai.RenderedOp; -import javax.media.jai.operator.StreamDescriptor; - -import org.apache.log4j.Level; -import org.apache.log4j.Logger; - -import com.sun.media.jai.codec.MemoryCacheSeekableStream; - -import edu.cornell.mannlib.vitro.webapp.imageprocessor.jai.JaiImageProcessor; -import edu.cornell.mannlib.vitro.webapp.modules.imageProcessor.ImageProcessor.CropRectangle; -import edu.cornell.mannlib.vitro.webapp.modules.imageProcessor.ImageProcessor.Dimensions; - -/** - * This is not a unit test, so it is not named BlahBlahTest. - * - * Instead, it's a test harness that creates thumbnails and writes them to - * files, while also displaying them in a window on the screen. It takes human - * intervention to evaluate. - * - * This is especially true because the images on the screen look color-correct, - * but when viewed in the browser, they might not be. - */ -public class JaiImageProcessorTester extends Frame { - - /** Big enough to hold the JPEG file, certainly. */ - private final static int BUFFER_SIZE = 200 * 200 * 4; - - private final static Dimensions THUMBNAIL_SIZE = new Dimensions( - THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT); - - private final static ImageCropData[] THUMBNAIL_DATA = new ImageCropData[] { - new ImageCropData("/Users/jeb228/Pictures/JimBlake_20010915.jpg", - 50, 50, 115), - new ImageCropData("/Users/jeb228/Pictures/brazil_collab.png", 600, - 250, 400), - new ImageCropData("/Users/jeb228/Pictures/wheel.png", 0, 0, 195), - new ImageCropData("/Users/jeb228/Pictures/DSC04203w-trans.gif", - 400, 1200, 800) }; - - private final JaiImageProcessor thumbnailer = new JaiImageProcessor(); - - @SuppressWarnings("deprecation") - private JaiImageProcessorTester() { - setTitle("Alpha Killer Test"); - addWindowListener(new CloseWindowListener()); - setLayout(createLayout()); - for (ImageCropData icd : THUMBNAIL_DATA) { - try { - InputStream mainStream = new FileInputStream(icd.filename); - File thumbFile = writeToTempFile(thumbnailer.cropAndScale( - mainStream, icd.crop, THUMBNAIL_SIZE)); - System.out.println(thumbFile.getAbsolutePath()); - - MemoryCacheSeekableStream thumbFileStream = new MemoryCacheSeekableStream( - new FileInputStream(thumbFile)); - RenderedOp thumbImage = StreamDescriptor.create( - thumbFileStream, null, null); - add(new javax.media.jai.widget.ImageCanvas(thumbImage)); - } catch (Exception e) { - e.printStackTrace(); - } - } - pack(); - setVisible(true); - } - - /** - * @param thumbStream Thumbnail stream - * @throws IOException - * @throws FileNotFoundException - */ - private File writeToTempFile(InputStream thumbStream) throws IOException, - FileNotFoundException { - File thumbFile = File.createTempFile("ImageUploaderThumbnailerTester", - ""); - OutputStream imageOutputStream = new FileOutputStream(thumbFile); - byte[] buffer = new byte[BUFFER_SIZE]; - int howMany = thumbStream.read(buffer); - imageOutputStream.write(buffer, 0, howMany); - imageOutputStream.close(); - return thumbFile; - } - - private GridLayout createLayout() { - GridLayout layout = new GridLayout(1, THUMBNAIL_DATA.length); - layout.setHgap(10); - return layout; - } - - @SuppressWarnings("unused") - public static void main(String[] args) { - Logger.getLogger(JaiImageProcessor.class).setLevel(Level.DEBUG); - new JaiImageProcessorTester(); - } - - private static class ImageCropData { - final String filename; - final CropRectangle crop; - - ImageCropData(String filename, int x, int y, int size) { - this.filename = filename; - this.crop = new CropRectangle(x, y, size, - size); - } - } - - private class CloseWindowListener extends WindowAdapter { - @Override - public void windowClosing(WindowEvent e) { - setVisible(false); - dispose(); - System.exit(0); - } - } -} diff --git a/api/src/test/java/edu/cornell/mannlib/vitro/webapp/imageprocessor/imageio/JaiImageProcessorTester2.java b/api/src/test/java/edu/cornell/mannlib/vitro/webapp/imageprocessor/imageio/JaiImageProcessorTester2.java deleted file mode 100644 index 87e89c147..000000000 --- a/api/src/test/java/edu/cornell/mannlib/vitro/webapp/imageprocessor/imageio/JaiImageProcessorTester2.java +++ /dev/null @@ -1,272 +0,0 @@ -/* $This file is distributed under the terms of the license in /doc/license.txt$ */ - -package edu.cornell.mannlib.vitro.webapp.imageprocessor.imageio; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Component; -import java.awt.Frame; -import java.awt.GridLayout; -import java.awt.Label; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.awt.image.Raster; -import java.io.FileInputStream; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import javax.media.jai.JAI; -import javax.media.jai.RenderedOp; -import javax.media.jai.operator.StreamDescriptor; -import javax.swing.BorderFactory; -import javax.swing.JPanel; - -import edu.cornell.mannlib.vitro.webapp.imageprocessor.jai.JaiImageProcessor; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.log4j.Appender; -import org.apache.log4j.Level; -import org.apache.log4j.Logger; -import org.apache.log4j.PatternLayout; - -import com.sun.media.jai.codec.MemoryCacheSeekableStream; - -import edu.cornell.mannlib.vitro.webapp.imageprocessor.imageio.JaiImageProcessorTester2.CropDataSet.CropData; -import edu.cornell.mannlib.vitro.webapp.imageprocessor.jai.JaiImageProcessor.NonNoisyImagingListener; -import edu.cornell.mannlib.vitro.webapp.modules.imageProcessor.ImageProcessor.CropRectangle; -import edu.cornell.mannlib.vitro.webapp.modules.imageProcessor.ImageProcessor.Dimensions; - -/** - * This is not a unit test, so it is not named BlahBlahTest. - * - * Instead, it's a test harness that creates thumbnails and displays them in a - * window on the screen. It takes human intervention to evaluate. - * - * The goal here is to see whether differences in crop dimensions might cause - * one or more black edges on the thumbnails. - */ -@SuppressWarnings("deprecation") -public class JaiImageProcessorTester2 extends Frame { - private static final Log log = LogFactory - .getLog(JaiImageProcessorTester2.class); - - private static final int ROWS = 6; - private static final int COLUMNS = 9; - - private static final int EDGE_THRESHOLD = 6000; - - private static final Dimensions THUMBNAIL_SIZE = new Dimensions(200, 200); - - /** Keep things quiet. */ - static { - JAI.getDefaultInstance().setImagingListener( - new NonNoisyImagingListener()); - } - - private final String imagePath; - private final JaiImageProcessor thumbnailer; - - public JaiImageProcessorTester2(String imagePath, - CropDataSet cropDataSet) { - this.imagePath = imagePath; - this.thumbnailer = new JaiImageProcessor(); - - setTitle("Cropping edging test"); - addWindowListener(new CloseWindowListener()); - setLayout(new GridLayout(ROWS, COLUMNS)); - - for (CropData cropData : cropDataSet.crops()) { - add(createImagePanel(cropData)); - } - - pack(); - setVisible(true); - } - - private Component createImagePanel(CropData cropData) { - RenderedOp image = createCroppedImage(cropData); - - - Set blackSides = checkBlackEdges(image); - if (!blackSides.isEmpty()) { - log.warn("edges at " + cropData + ", " + blackSides); - } - - String legend = "left=" + cropData.left + ", top=" + cropData.top - + ", size=" + cropData.size; - Label l = new Label(); - l.setAlignment(Label.CENTER); - if (!blackSides.isEmpty()) { - l.setBackground(new Color(0xFFDDDD)); - legend += " " + blackSides; - } - l.setText(legend); - - JPanel p = new JPanel(); - p.setLayout(new BorderLayout()); - p.add("South", l); - p.add("Center", new javax.media.jai.widget.ImageCanvas(image)); - p.setBackground(new Color(0xFFFFFF)); - p.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); - - return p; - } - - private RenderedOp createCroppedImage(CropData cropData) { - try { - InputStream mainStream = new FileInputStream(imagePath); - CropRectangle rectangle = new CropRectangle(cropData.left, - cropData.top, cropData.size, cropData.size); - InputStream thumbnailStream = thumbnailer.cropAndScale(mainStream, - rectangle, THUMBNAIL_SIZE); - - return StreamDescriptor.create(new MemoryCacheSeekableStream( - thumbnailStream), null, null); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - private Set checkBlackEdges(RenderedOp image) { - Raster imageData = image.getData(); - - int minX = imageData.getMinX(); - int minY = imageData.getMinY(); - int maxX = minX + imageData.getWidth() - 1; - int maxY = minY + imageData.getHeight() - 1; - - Set blackSides = new HashSet(); - if (isBlackEdge(minX, minX, minY, maxY, imageData)) { - blackSides.add("left"); - } - if (isBlackEdge(minX, maxX, minY, minY, imageData)) { - blackSides.add("top"); - } - if (isBlackEdge(maxX, maxX, minY, maxY, imageData)) { - blackSides.add("right"); - } - if (isBlackEdge(minX, maxX, maxY, maxY, imageData)) { - blackSides.add("bottom"); - } - return blackSides; - } - - private boolean isBlackEdge(int fromX, int toX, int fromY, int toY, - Raster imageData) { - int edgeTotal = 0; - try { - for (int col = fromX; col <= toX; col++) { - for (int row = fromY; row <= toY; row++) { - edgeTotal += sumPixel(imageData, col, row); - } - } - } catch (Exception e) { - log.error("can't sum edge: fromX=" + fromX + ", toX=" + toX - + ", fromY=" + fromY + ", toY=" + toY + ", imageWidth=" - + imageData.getWidth() + ", imageHeight=" - + imageData.getHeight() + ": " + e); - } - - log.debug("edge total = " + edgeTotal); - return edgeTotal < EDGE_THRESHOLD; - } - - private int sumPixel(Raster imageData, int col, int row) { - int pixelSum = 0; - int[] pixel = imageData.getPixel(col, row, new int[0]); - for (int value : pixel) { - pixelSum += value; - } - return pixelSum; - } - - /** - *
-	 * The plan:
-	 * 
-	 * Provide the path to an image file.
-	 * Figure how many images can fit on the screen.
-	 * Crop in increments, starting at 0,0 and varying the size of the crop.
-	 * Crop in increments, incrementing from 0,0 downward, and varying the size of the crop.
-	 * 
-	 * Start by creating 4 x 4 images in a window, and incrementing from 201 to 216.
-	 * 
- */ - - public static void main(String[] args) { - Logger rootLogger = Logger.getRootLogger(); - Appender appender = (Appender) rootLogger.getAllAppenders() - .nextElement(); - appender.setLayout(new PatternLayout("%-5p [%c{1}] %m%n")); - - Logger.getLogger(JaiImageProcessor.class).setLevel(Level.DEBUG); - Logger.getLogger(JaiImageProcessorTester2.class).setLevel( - Level.INFO); - - CropDataSet cropDataSet = new CropDataSet(); - for (int i = 0; i < ROWS * COLUMNS; i++) { -// cropDataSet.add(i, i, 201 + i); - cropDataSet.add(0, 0, 201 + i); - } - - new JaiImageProcessorTester2( - "C:/Users/jeb228/Pictures/wheel.png", cropDataSet); - -// new ImageUploaderThumbnailerTester_2( -// "C:/Users/jeb228/Pictures/DSC04203w-trans.jpg", cropDataSet); - - // new ImageUploaderThumbnailerTester_2( -// "C:/Development/JIRA issues/NIHVIVO-2477 Black borders on thumbnails/" -// + "images from Alex/uploads/file_storage_root/a~n/411/9/" -// + "De^20Bartolome^2c^20Charles^20A^20M_100037581.jpg", -// cropDataSet); - } - - // ---------------------------------------------------------------------- - // helper classes - // ---------------------------------------------------------------------- - - private class CloseWindowListener extends WindowAdapter { - @Override - public void windowClosing(WindowEvent e) { - setVisible(false); - dispose(); - System.exit(0); - } - } - - public static class CropDataSet { - private final List crops = new ArrayList(); - - CropDataSet add(int left, int top, int size) { - crops.add(new CropData(left, top, size)); - return this; - } - - Collection crops() { - return Collections.unmodifiableCollection(crops); - } - - public static class CropData { - final int left; - final int top; - final int size; - - CropData(int left, int top, int size) { - this.left = left; - this.top = top; - this.size = size; - } - - @Override - public String toString() { - return "CropData[" + left + ", " + top + ", " + size + "]"; - } - } - } -} From 28c99c9408433bfb0902d65f927b2460a91aa8f6 Mon Sep 17 00:00:00 2001 From: Graham Triggs Date: Mon, 19 Dec 2016 11:08:57 +0000 Subject: [PATCH 24/49] Correct stage 1 migration - remove old JAI processor testers to fix the build --- .../jai/JaiImageProcessorTester.java | 134 --------- .../jai/JaiImageProcessorTester2.java | 271 ------------------ 2 files changed, 405 deletions(-) delete mode 100644 api/src/test/java/edu/cornell/mannlib/vitro/webapp/imageprocessor/jai/JaiImageProcessorTester.java delete mode 100644 api/src/test/java/edu/cornell/mannlib/vitro/webapp/imageprocessor/jai/JaiImageProcessorTester2.java diff --git a/api/src/test/java/edu/cornell/mannlib/vitro/webapp/imageprocessor/jai/JaiImageProcessorTester.java b/api/src/test/java/edu/cornell/mannlib/vitro/webapp/imageprocessor/jai/JaiImageProcessorTester.java deleted file mode 100644 index 016ebfb1f..000000000 --- a/api/src/test/java/edu/cornell/mannlib/vitro/webapp/imageprocessor/jai/JaiImageProcessorTester.java +++ /dev/null @@ -1,134 +0,0 @@ -/* $This file is distributed under the terms of the license in /doc/license.txt$ */ - -package edu.cornell.mannlib.vitro.webapp.imageprocessor.jai; - -import static edu.cornell.mannlib.vitro.webapp.controller.freemarker.ImageUploadController.THUMBNAIL_HEIGHT; -import static edu.cornell.mannlib.vitro.webapp.controller.freemarker.ImageUploadController.THUMBNAIL_WIDTH; - -import java.awt.Frame; -import java.awt.GridLayout; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -import javax.media.jai.RenderedOp; -import javax.media.jai.operator.StreamDescriptor; - -import org.apache.log4j.Level; -import org.apache.log4j.Logger; - -import com.sun.media.jai.codec.MemoryCacheSeekableStream; - -import edu.cornell.mannlib.vitro.webapp.imageprocessor.jai.JaiImageProcessor; -import edu.cornell.mannlib.vitro.webapp.modules.imageProcessor.ImageProcessor.CropRectangle; -import edu.cornell.mannlib.vitro.webapp.modules.imageProcessor.ImageProcessor.Dimensions; - -/** - * This is not a unit test, so it is not named BlahBlahTest. - * - * Instead, it's a test harness that creates thumbnails and writes them to - * files, while also displaying them in a window on the screen. It takes human - * intervention to evaluate. - * - * This is especially true because the images on the screen look color-correct, - * but when viewed in the browser, they might not be. - */ -public class JaiImageProcessorTester extends Frame { - - /** Big enough to hold the JPEG file, certainly. */ - private final static int BUFFER_SIZE = 200 * 200 * 4; - - private final static Dimensions THUMBNAIL_SIZE = new Dimensions( - THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT); - - private final static ImageCropData[] THUMBNAIL_DATA = new ImageCropData[] { - new ImageCropData("/Users/jeb228/Pictures/JimBlake_20010915.jpg", - 50, 50, 115), - new ImageCropData("/Users/jeb228/Pictures/brazil_collab.png", 600, - 250, 400), - new ImageCropData("/Users/jeb228/Pictures/wheel.png", 0, 0, 195), - new ImageCropData("/Users/jeb228/Pictures/DSC04203w-trans.gif", - 400, 1200, 800) }; - - private final JaiImageProcessor thumbnailer = new JaiImageProcessor(); - - @SuppressWarnings("deprecation") - private JaiImageProcessorTester() { - setTitle("Alpha Killer Test"); - addWindowListener(new CloseWindowListener()); - setLayout(createLayout()); - for (ImageCropData icd : THUMBNAIL_DATA) { - try { - InputStream mainStream = new FileInputStream(icd.filename); - File thumbFile = writeToTempFile(thumbnailer.cropAndScale( - mainStream, icd.crop, THUMBNAIL_SIZE)); - System.out.println(thumbFile.getAbsolutePath()); - - MemoryCacheSeekableStream thumbFileStream = new MemoryCacheSeekableStream( - new FileInputStream(thumbFile)); - RenderedOp thumbImage = StreamDescriptor.create( - thumbFileStream, null, null); - add(new javax.media.jai.widget.ImageCanvas(thumbImage)); - } catch (Exception e) { - e.printStackTrace(); - } - } - pack(); - setVisible(true); - } - - /** - * @param thumbStream Thumbnail stream - * @throws IOException - * @throws FileNotFoundException - */ - private File writeToTempFile(InputStream thumbStream) throws IOException, - FileNotFoundException { - File thumbFile = File.createTempFile("ImageUploaderThumbnailerTester", - ""); - OutputStream imageOutputStream = new FileOutputStream(thumbFile); - byte[] buffer = new byte[BUFFER_SIZE]; - int howMany = thumbStream.read(buffer); - imageOutputStream.write(buffer, 0, howMany); - imageOutputStream.close(); - return thumbFile; - } - - private GridLayout createLayout() { - GridLayout layout = new GridLayout(1, THUMBNAIL_DATA.length); - layout.setHgap(10); - return layout; - } - - @SuppressWarnings("unused") - public static void main(String[] args) { - Logger.getLogger(JaiImageProcessor.class).setLevel(Level.DEBUG); - new JaiImageProcessorTester(); - } - - private static class ImageCropData { - final String filename; - final CropRectangle crop; - - ImageCropData(String filename, int x, int y, int size) { - this.filename = filename; - this.crop = new CropRectangle(x, y, size, - size); - } - } - - private class CloseWindowListener extends WindowAdapter { - @Override - public void windowClosing(WindowEvent e) { - setVisible(false); - dispose(); - System.exit(0); - } - } -} diff --git a/api/src/test/java/edu/cornell/mannlib/vitro/webapp/imageprocessor/jai/JaiImageProcessorTester2.java b/api/src/test/java/edu/cornell/mannlib/vitro/webapp/imageprocessor/jai/JaiImageProcessorTester2.java deleted file mode 100644 index 0def41eec..000000000 --- a/api/src/test/java/edu/cornell/mannlib/vitro/webapp/imageprocessor/jai/JaiImageProcessorTester2.java +++ /dev/null @@ -1,271 +0,0 @@ -/* $This file is distributed under the terms of the license in /doc/license.txt$ */ - -package edu.cornell.mannlib.vitro.webapp.imageprocessor.jai; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Component; -import java.awt.Frame; -import java.awt.GridLayout; -import java.awt.Label; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.awt.image.Raster; -import java.io.FileInputStream; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import javax.media.jai.JAI; -import javax.media.jai.RenderedOp; -import javax.media.jai.operator.StreamDescriptor; -import javax.swing.BorderFactory; -import javax.swing.JPanel; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.log4j.Appender; -import org.apache.log4j.Level; -import org.apache.log4j.Logger; -import org.apache.log4j.PatternLayout; - -import com.sun.media.jai.codec.MemoryCacheSeekableStream; - -import edu.cornell.mannlib.vitro.webapp.imageprocessor.jai.JaiImageProcessorTester2.CropDataSet.CropData; -import edu.cornell.mannlib.vitro.webapp.imageprocessor.jai.JaiImageProcessor.NonNoisyImagingListener; -import edu.cornell.mannlib.vitro.webapp.modules.imageProcessor.ImageProcessor.CropRectangle; -import edu.cornell.mannlib.vitro.webapp.modules.imageProcessor.ImageProcessor.Dimensions; - -/** - * This is not a unit test, so it is not named BlahBlahTest. - * - * Instead, it's a test harness that creates thumbnails and displays them in a - * window on the screen. It takes human intervention to evaluate. - * - * The goal here is to see whether differences in crop dimensions might cause - * one or more black edges on the thumbnails. - */ -@SuppressWarnings("deprecation") -public class JaiImageProcessorTester2 extends Frame { - private static final Log log = LogFactory - .getLog(JaiImageProcessorTester2.class); - - private static final int ROWS = 6; - private static final int COLUMNS = 9; - - private static final int EDGE_THRESHOLD = 6000; - - private static final Dimensions THUMBNAIL_SIZE = new Dimensions(200, 200); - - /** Keep things quiet. */ - static { - JAI.getDefaultInstance().setImagingListener( - new NonNoisyImagingListener()); - } - - private final String imagePath; - private final JaiImageProcessor thumbnailer; - - public JaiImageProcessorTester2(String imagePath, - CropDataSet cropDataSet) { - this.imagePath = imagePath; - this.thumbnailer = new JaiImageProcessor(); - - setTitle("Cropping edging test"); - addWindowListener(new CloseWindowListener()); - setLayout(new GridLayout(ROWS, COLUMNS)); - - for (CropData cropData : cropDataSet.crops()) { - add(createImagePanel(cropData)); - } - - pack(); - setVisible(true); - } - - private Component createImagePanel(CropData cropData) { - RenderedOp image = createCroppedImage(cropData); - - - Set blackSides = checkBlackEdges(image); - if (!blackSides.isEmpty()) { - log.warn("edges at " + cropData + ", " + blackSides); - } - - String legend = "left=" + cropData.left + ", top=" + cropData.top - + ", size=" + cropData.size; - Label l = new Label(); - l.setAlignment(Label.CENTER); - if (!blackSides.isEmpty()) { - l.setBackground(new Color(0xFFDDDD)); - legend += " " + blackSides; - } - l.setText(legend); - - JPanel p = new JPanel(); - p.setLayout(new BorderLayout()); - p.add("South", l); - p.add("Center", new javax.media.jai.widget.ImageCanvas(image)); - p.setBackground(new Color(0xFFFFFF)); - p.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); - - return p; - } - - private RenderedOp createCroppedImage(CropData cropData) { - try { - InputStream mainStream = new FileInputStream(imagePath); - CropRectangle rectangle = new CropRectangle(cropData.left, - cropData.top, cropData.size, cropData.size); - InputStream thumbnailStream = thumbnailer.cropAndScale(mainStream, - rectangle, THUMBNAIL_SIZE); - - return StreamDescriptor.create(new MemoryCacheSeekableStream( - thumbnailStream), null, null); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - private Set checkBlackEdges(RenderedOp image) { - Raster imageData = image.getData(); - - int minX = imageData.getMinX(); - int minY = imageData.getMinY(); - int maxX = minX + imageData.getWidth() - 1; - int maxY = minY + imageData.getHeight() - 1; - - Set blackSides = new HashSet(); - if (isBlackEdge(minX, minX, minY, maxY, imageData)) { - blackSides.add("left"); - } - if (isBlackEdge(minX, maxX, minY, minY, imageData)) { - blackSides.add("top"); - } - if (isBlackEdge(maxX, maxX, minY, maxY, imageData)) { - blackSides.add("right"); - } - if (isBlackEdge(minX, maxX, maxY, maxY, imageData)) { - blackSides.add("bottom"); - } - return blackSides; - } - - private boolean isBlackEdge(int fromX, int toX, int fromY, int toY, - Raster imageData) { - int edgeTotal = 0; - try { - for (int col = fromX; col <= toX; col++) { - for (int row = fromY; row <= toY; row++) { - edgeTotal += sumPixel(imageData, col, row); - } - } - } catch (Exception e) { - log.error("can't sum edge: fromX=" + fromX + ", toX=" + toX - + ", fromY=" + fromY + ", toY=" + toY + ", imageWidth=" - + imageData.getWidth() + ", imageHeight=" - + imageData.getHeight() + ": " + e); - } - - log.debug("edge total = " + edgeTotal); - return edgeTotal < EDGE_THRESHOLD; - } - - private int sumPixel(Raster imageData, int col, int row) { - int pixelSum = 0; - int[] pixel = imageData.getPixel(col, row, new int[0]); - for (int value : pixel) { - pixelSum += value; - } - return pixelSum; - } - - /** - *
-	 * The plan:
-	 * 
-	 * Provide the path to an image file.
-	 * Figure how many images can fit on the screen.
-	 * Crop in increments, starting at 0,0 and varying the size of the crop.
-	 * Crop in increments, incrementing from 0,0 downward, and varying the size of the crop.
-	 * 
-	 * Start by creating 4 x 4 images in a window, and incrementing from 201 to 216.
-	 * 
- */ - - public static void main(String[] args) { - Logger rootLogger = Logger.getRootLogger(); - Appender appender = (Appender) rootLogger.getAllAppenders() - .nextElement(); - appender.setLayout(new PatternLayout("%-5p [%c{1}] %m%n")); - - Logger.getLogger(JaiImageProcessor.class).setLevel(Level.DEBUG); - Logger.getLogger(JaiImageProcessorTester2.class).setLevel( - Level.INFO); - - CropDataSet cropDataSet = new CropDataSet(); - for (int i = 0; i < ROWS * COLUMNS; i++) { -// cropDataSet.add(i, i, 201 + i); - cropDataSet.add(0, 0, 201 + i); - } - - new JaiImageProcessorTester2( - "C:/Users/jeb228/Pictures/wheel.png", cropDataSet); - -// new ImageUploaderThumbnailerTester_2( -// "C:/Users/jeb228/Pictures/DSC04203w-trans.jpg", cropDataSet); - - // new ImageUploaderThumbnailerTester_2( -// "C:/Development/JIRA issues/NIHVIVO-2477 Black borders on thumbnails/" -// + "images from Alex/uploads/file_storage_root/a~n/411/9/" -// + "De^20Bartolome^2c^20Charles^20A^20M_100037581.jpg", -// cropDataSet); - } - - // ---------------------------------------------------------------------- - // helper classes - // ---------------------------------------------------------------------- - - private class CloseWindowListener extends WindowAdapter { - @Override - public void windowClosing(WindowEvent e) { - setVisible(false); - dispose(); - System.exit(0); - } - } - - public static class CropDataSet { - private final List crops = new ArrayList(); - - CropDataSet add(int left, int top, int size) { - crops.add(new CropData(left, top, size)); - return this; - } - - Collection crops() { - return Collections.unmodifiableCollection(crops); - } - - public static class CropData { - final int left; - final int top; - final int size; - - CropData(int left, int top, int size) { - this.left = left; - this.top = top; - this.size = size; - } - - @Override - public String toString() { - return "CropData[" + left + ", " + top + ", " + size + "]"; - } - } - } -} From 17b323649dbdc84529b521c10f3b7ccae2b17b6d Mon Sep 17 00:00:00 2001 From: Graham Triggs Date: Mon, 19 Dec 2016 19:08:13 +0000 Subject: [PATCH 25/49] Remove unused Fedora connection --- .../FedoraDatastreamController.java | 713 ------------------ .../webapp/utils/FedoraConfiguration.java | 198 ----- dependencies/pom.xml | 5 - .../fileupload/datastreamModification.jsp | 24 - .../datastreamModificationSuccess.jsp | 16 - webapp/src/main/webapp/fileupload/md5.jsp | 11 - 6 files changed, 967 deletions(-) delete mode 100644 api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/FedoraDatastreamController.java delete mode 100644 api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/FedoraConfiguration.java delete mode 100644 webapp/src/main/webapp/fileupload/datastreamModification.jsp delete mode 100644 webapp/src/main/webapp/fileupload/datastreamModificationSuccess.jsp delete mode 100644 webapp/src/main/webapp/fileupload/md5.jsp diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/FedoraDatastreamController.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/FedoraDatastreamController.java deleted file mode 100644 index 110f6f873..000000000 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/FedoraDatastreamController.java +++ /dev/null @@ -1,713 +0,0 @@ -/* $This file is distributed under the terms of the license in /doc/license.txt$ */ - -package edu.cornell.mannlib.vitro.webapp.controller; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.net.MalformedURLException; -import java.security.MessageDigest; -import java.text.SimpleDateFormat; -import java.util.List; -import java.util.Properties; - -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import edu.cornell.mannlib.vitro.webapp.utils.JSPPageHandler; -import org.apache.commons.fileupload.FileItem; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.joda.time.DateTime; - -import org.apache.jena.datatypes.xsd.XSDDatatype; -import org.apache.jena.ontology.DatatypeProperty; -import org.apache.jena.ontology.ObjectProperty; -import org.apache.jena.ontology.OntModel; -import org.apache.jena.rdf.model.Resource; -import org.apache.jena.rdf.model.Statement; -import org.apache.jena.vocabulary.RDFS; -import org.apache.jena.vocabulary.XSD; -import com.ibm.icu.util.Calendar; - -import edu.cornell.mannlib.vedit.beans.LoginStatusBean; -import edu.cornell.mannlib.vitro.webapp.beans.DataProperty; -import edu.cornell.mannlib.vitro.webapp.beans.DataPropertyStatement; -import edu.cornell.mannlib.vitro.webapp.beans.DataPropertyStatementImpl; -import edu.cornell.mannlib.vitro.webapp.beans.Individual; -import edu.cornell.mannlib.vitro.webapp.beans.ObjectPropertyStatement; -import edu.cornell.mannlib.vitro.webapp.config.ConfigurationProperties; -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.modelaccess.ModelAccess; -import fedora.client.FedoraClient; -import fedora.common.Constants; -import fedora.server.management.FedoraAPIM; -import fedora.server.types.gen.Datastream; - - -/** - * Handles a request to change a datastream in a fedora repository. - * Some of this code is copied from N3MultiPartUpload.java - * - * @author bdc34 - * - */ -public class FedoraDatastreamController extends VitroHttpServlet implements Constants{ - private static String FEDORA_PROPERTIES = "/WEB-INF/fedora.properties"; - private static String DEFAULT_DSID = "DS1"; - - private String fedoraUrl = null; - private String adminUser = null; - private String adminPassword = null; - private String pidNamespace = null; - private String configurationStatus = "

Fedora configuration not yet loaded

"; - private boolean configured = false; - private boolean connected = false; - - private static final int DEFAULT_MAX_SIZE = 1024 * 1024 * 50;//Shoudl this be changed to 1 GB to be consistent - private static final String DEFAULT_BASE_DIR = "/usr/local/vitrofiles"; - private static String baseDirectoryForFiles = DEFAULT_BASE_DIR; - private static int maxFileSize = DEFAULT_MAX_SIZE; - - protected String contentTypeProperty = VitroVocabulary.CONTENT_TYPE; - protected String fileSizeProperty = VitroVocabulary.FILE_SIZE; - protected String fileNameProperty = VitroVocabulary.FILE_NAME; - protected String fileLocationProperty = VitroVocabulary.FILE_LOCATION; - protected String fileLabelProperty = RDFS.label.getURI(); - protected String checksumNodeProperty = "";//Object property linking file to check sum node object - protected String checksumNodeDateTimeProperty = ""; - protected String checksumNodeValueProperty = ""; - protected String checksumDataProperty = ""; //is there a vitro equivalent? - - protected String deleteNs = ""; - protected String individualPrefix = ""; - protected String fedoraNs = VitroVocabulary.VITRO_FEDORA; - - - /** - * The get will present a form to the user. - */ - @Override - public void doGet(HttpServletRequest req, HttpServletResponse res) - throws IOException, ServletException { - try { - super.doGet(req, res); - log.debug("In doGet"); - - VitroRequest vreq = new VitroRequest(req); - OntModel sessionOntModel = ModelAccess.on(getServletContext()).getOntModel(); - - synchronized (FedoraDatastreamController.class) { - if( fedoraUrl == null ){ - setup( sessionOntModel, getServletContext() ); - if( fedoraUrl == null ) - throw new FdcException("Connection to the file repository is " + - "not setup correctly. Could not read fedora.properties file"); - }else{ - if( !canConnectToFedoraServer() ){ - fedoraUrl = null; - throw new FdcException("Could not connect to Fedora."); - } - } - } - FedoraClient fedora; - try { fedora = new FedoraClient(fedoraUrl,adminUser,adminPassword); } - catch (MalformedURLException e) { - throw new FdcException("Malformed URL for fedora Repository location: " + fedoraUrl); - } - - FedoraAPIM apim; - try { apim = fedora.getAPIM(); } catch (Exception e) { - throw new FdcException("could not create fedora APIM:" + e.getMessage()); - } - - //check if logged in - - //get URI for file individual - if( req.getParameter("uri") == null || "".equals(req.getParameter("uri"))) - throw new FdcException("No file uri specified in request"); - - boolean isDelete = (req.getParameter("delete") != null && "true".equals(req.getParameter("delete"))); - - String fileUri = req.getParameter("uri"); - //check if file individual has a fedora:PID for a data stream - IndividualDao iwDao = vreq.getWebappDaoFactory().getIndividualDao(); - Individual entity = iwDao.getIndividualByURI(fileUri); - - - - if( entity == null ) - throw new FdcException( "No entity found in system for file uri " + fileUri); - //System.out.println("Entity == null:" + (entity == null)); - //get the fedora PID - //System.out.println("entity data property " + entity.getDataPropertyMap().get(VitroVocabulary.FEDORA_PID)); - if( entity.getDataPropertyMap().get(VitroVocabulary.FEDORA_PID ) == null ) - throw new FdcException( "No fedora:pid found in system for file uri " + fileUri); - List stmts = entity.getDataPropertyMap().get(VitroVocabulary.FEDORA_PID).getDataPropertyStatements(); - if( stmts == null || stmts.size() == 0) - throw new FdcException( "No fedora:pid found in system for file uri " + fileUri); - String pid = null; - for(DataPropertyStatement stmt : stmts){ - if( stmt.getData() != null && stmt.getData().length() > 0){ - pid = stmt.getData(); - break; - } - } - //System.out.println("pid is " + pid + " and comparison is " + (pid == null)); - if( pid == null ) - throw new FdcException( "No fedora:pid found in system for file uri " + fileUri); - req.setAttribute("pid", pid); - req.setAttribute("fileUri", fileUri); - //get current file name to use on form - req.setAttribute("fileName", entity.getName()); - - if(isDelete) - { - //Execute a 'deletion', i.e. unlink dataset and file, without removing file - //Also save deletion as a deleteEvent entity which can later be queried - - String datasetUri = null; - //Get dataset uri by getting the fromDataSet property - edu.cornell.mannlib.vitro.webapp.beans.ObjectProperty fromDataSet = entity.getObjectPropertyMap().get(fedoraNs + "fromDataSet"); - if(fromDataSet != null) - { - List fromDsStmts = fromDataSet.getObjectPropertyStatements(); - if(fromDsStmts.size() > 0) { - datasetUri = fromDsStmts.get(0).getObjectURI(); - //System.out.println("object uri should be " + datasetUri); - } else { - //System.out.println("No matching dataset uri could be found"); - } - } else { - //System.out.println("From dataset is null"); - } - - req.setAttribute("dataseturi", datasetUri); - boolean success = deleteFile(req, entity, iwDao, sessionOntModel); - req.setAttribute("deletesuccess", (success)?"success":"error"); - JSPPageHandler.renderBasicPage(req, res, "/edit/fileDeleteConfirm.jsp"); - } - else{ - //check if the data stream exists in the fedora repository - Datastream ds = apim.getDatastream(pid,DEFAULT_DSID,null); - if( ds == null ) - throw new FdcException("There was no datastream in the " + - "repository for " + pid + " " + DEFAULT_DSID); - req.setAttribute("dsid", DEFAULT_DSID); - - - - //forward to form - JSPPageHandler.renderBasicPage(req, res, "/fileupload/datastreamModification.jsp"); - } - }catch(FdcException ex){ - req.setAttribute("errors", ex.getMessage()); - JSPPageHandler.renderPlainPage(req, res, "/edit/fileUploadError.jsp"); - return; - } - } - - @Override - public long maximumMultipartFileSize() { - return maxFileSize; - } - - @Override - public boolean stashFileSizeException() { - return true; - } - - @Override - public void doPost(HttpServletRequest rawRequest, HttpServletResponse res) - throws ServletException, IOException { - try{ - VitroRequest req = new VitroRequest(rawRequest); - if (req.hasFileSizeException()) { - throw new FdcException("Size limit exceeded: " + req.getFileSizeException().getLocalizedMessage()); - } - if (!req.isMultipart()) { - throw new FdcException("Must POST a multipart encoded request"); - } - - //check if fedora is on line - OntModel sessionOntModel = ModelAccess.on(getServletContext()).getOntModel(); - synchronized (FedoraDatastreamController.class) { - if( fedoraUrl == null ){ - setup( sessionOntModel, getServletContext() ); - if( fedoraUrl == null ) - throw new FdcException("Connection to the file repository is " + - "not setup correctly. Could not read fedora.properties file"); - }else{ - if( !canConnectToFedoraServer() ){ - fedoraUrl = null; - throw new FdcException("Could not connect to Fedora."); - } - } - } - FedoraClient fedora; - try { fedora = new FedoraClient(fedoraUrl,adminUser,adminPassword); } - catch (MalformedURLException e) { - throw new FdcException("Malformed URL for fedora Repository location: " + fedoraUrl); - } - FedoraAPIM apim; - try { apim = fedora.getAPIM(); } catch (Exception e) { - throw new FdcException("could not create fedora APIM:" + e.getMessage()); - } - - //get the parameters from the request - String pId=req.getParameter("pid"); - String dsId=req.getParameter("dsid"); - String fileUri=req.getParameter("fileUri"); - - boolean useNewName=false; - if( "true".equals(req.getParameter("useNewName"))){ - useNewName = true; - } - if( pId == null || pId.length() == 0 ) - throw new FdcException("Your form submission did not contain " + - "enough information to complete your request.(Missing pid parameter)"); - if( dsId == null || dsId.length() == 0 ) - throw new FdcException("Your form submission did not contain " + - "enough information to complete your request.(Missing dsid parameter)"); - if( fileUri == null || fileUri.length() == 0 ) - throw new FdcException("Your form submission did not contain " + - "enough information to complete your request.(Missing fileUri parameter)"); - - FileItem fileRes = req.getFileItem("fileRes"); - if( fileRes == null ) - throw new FdcException("Your form submission did not contain " + - "enough information to complete your request.(Missing fileRes)"); - - //check if file individual has a fedora:PID for a data stream - VitroRequest vreq = new VitroRequest(rawRequest); - IndividualDao iwDao = vreq.getWebappDaoFactory().getIndividualDao(); - Individual fileEntity = iwDao.getIndividualByURI(fileUri); - - //check if logged in - //TODO: check if logged in - - //check if user is allowed to edit datastream - //TODO:check if can edit datastream - - //check if digital object and data stream exist in fedora - Datastream ds = apim.getDatastream(pId,dsId,null); - if( ds == null ) - throw new FdcException("There was no datastream in the " + - "repository for " + pId + " " + DEFAULT_DSID); - - //upload to temp holding area - String originalName = fileRes.getName(); - String name = originalName.replaceAll("[,+\\\\/$%^&*#@!<>'\"~;]", "_"); - name = name.replace("..", "_"); - name = name.trim().toLowerCase(); - - String saveLocation = baseDirectoryForFiles + File.separator + name; - String savedName = name; - int next = 0; - boolean foundUnusedName = false; - while (!foundUnusedName) { - File test = new File(saveLocation); - if (test.exists()) { - next++; - savedName = name + '(' + next + ')'; - saveLocation = baseDirectoryForFiles + File.separator + savedName; - } else { - foundUnusedName = true; - } - } - - File uploadedFile = new File(saveLocation); - - try { - fileRes.write(uploadedFile); - } catch (Exception ex) { - log.error("Unable to save POSTed file. " + ex.getMessage()); - throw new FdcException("Unable to save file to the disk. " - + ex.getMessage()); - } - - //upload to temp area on fedora - File file = new File(saveLocation); - String uploadFileUri = fedora.uploadFile( file ); - // System.out.println("Fedora upload temp = upload file uri is " + uploadFileUri); - String md5 = md5hashForFile( file ); - md5 = md5.toLowerCase(); - - //make change to data stream on fedora - apim.modifyDatastreamByReference(pId, dsId, - null, null, - fileRes.getContentType(), null, - uploadFileUri, - "MD5", null, - null, false); - - String checksum = - apim.compareDatastreamChecksum(pId,dsId,null); - - //update properties like checksum, file size, and content type - - WebappDaoFactory wdf = vreq.getWebappDaoFactory(); - DataPropertyStatement dps = null; - DataProperty contentType = wdf.getDataPropertyDao().getDataPropertyByURI(this.contentTypeProperty); - if(contentType != null) - { - wdf.getDataPropertyStatementDao().deleteDataPropertyStatementsForIndividualByDataProperty(fileEntity, contentType); - dps = new DataPropertyStatementImpl(); - dps.setIndividualURI(fileEntity.getURI()); - dps.setDatapropURI(contentType.getURI()); - dps.setData(fileRes.getContentType()); - wdf.getDataPropertyStatementDao().insertNewDataPropertyStatement(dps); - } - - DataProperty fileSize = wdf.getDataPropertyDao().getDataPropertyByURI(this.fileSizeProperty); - if(fileSize != null) - { - wdf.getDataPropertyStatementDao().deleteDataPropertyStatementsForIndividualByDataProperty(fileEntity, fileSize); - dps = new DataPropertyStatementImpl(); - dps.setIndividualURI(fileEntity.getURI()); - dps.setDatapropURI(fileSize.getURI()); - dps.setData(Long.toString(fileRes.getSize())); - wdf.getDataPropertyStatementDao().insertNewDataPropertyStatement(dps); - //System.out.println("Updated file size with " + fileRes.getSize()); - } - - DataProperty checksumDp = wdf.getDataPropertyDao().getDataPropertyByURI(this.checksumDataProperty); - if(checksumDp != null) - { - //System.out.println("Checksum data property is also not null"); - wdf.getDataPropertyStatementDao().deleteDataPropertyStatementsForIndividualByDataProperty(fileEntity, checksumDp); - dps = new DataPropertyStatementImpl(); - dps.setIndividualURI(fileEntity.getURI()); - dps.setDatapropURI(checksumDp.getURI()); - dps.setData(checksum); - wdf.getDataPropertyStatementDao().insertNewDataPropertyStatement(dps); - } - - //I'm leaving if statement out for now as the above properties are obviously being replaced as well - //if( "true".equals(useNewName)){ - //Do we need to encapuslate in this if OR is this path always for replacing a file - //TODO: Put in check to see if file name has changed and only execute these statements if file name has changed - DataProperty fileNameProperty = wdf.getDataPropertyDao().getDataPropertyByURI(this.fileNameProperty); - if(fileNameProperty != null) { - wdf.getDataPropertyStatementDao().deleteDataPropertyStatementsForIndividualByDataProperty(fileEntity, fileNameProperty); - dps = new DataPropertyStatementImpl(); - dps.setIndividualURI(fileEntity.getURI()); - dps.setDatapropURI(fileNameProperty.getURI()); - dps.setData(originalName); //This follows the pattern of the original file upload - the name returned from the uploaded file object - wdf.getDataPropertyStatementDao().insertNewDataPropertyStatement(dps); - //System.out.println("File name property is not null = " + fileNameProperty.getURI() + " updating to " + originalName); - } else { - //System.out.println("file name property is null"); - } - - //Need to also update the check sum node - how would we do that - //Find checksum node related to this particular file uri, then go ahead and update two specific fields - - ListcsNodeStatements = fileEntity.getObjectPropertyMap().get(this.checksumNodeProperty).getObjectPropertyStatements(); - if(csNodeStatements.size() == 0) { - System.out.println("No object property statements correspond to this property"); - } else { - ObjectPropertyStatement cnodeStatement = csNodeStatements.get(0); - String cnodeUri = cnodeStatement.getObjectURI(); - //System.out.println("Checksum node uri is " + cnodeUri); - - Individual checksumNodeObject = iwDao.getIndividualByURI(cnodeUri); - - DataProperty checksumDateTime = wdf.getDataPropertyDao().getDataPropertyByURI(this.checksumNodeDateTimeProperty); - if(checksumDateTime != null) { - String newDatetime = sessionOntModel.createTypedLiteral(new DateTime()).getString(); - //Review how to update date time - wdf.getDataPropertyStatementDao().deleteDataPropertyStatementsForIndividualByDataProperty(checksumNodeObject, checksumDateTime); - dps = new DataPropertyStatementImpl(); - dps.setIndividualURI(checksumNodeObject.getURI()); - dps.setDatapropURI(checksumDateTime.getURI()); - dps.setData(newDatetime); - wdf.getDataPropertyStatementDao().insertNewDataPropertyStatement(dps); - - } - DataProperty checksumNodeValue = wdf.getDataPropertyDao().getDataPropertyByURI(this.checksumDataProperty); - if(checksumNodeValue != null) { - wdf.getDataPropertyStatementDao().deleteDataPropertyStatementsForIndividualByDataProperty(checksumNodeObject, checksumNodeValue); - dps = new DataPropertyStatementImpl(); - dps.setIndividualURI(checksumNodeObject.getURI()); - dps.setDatapropURI(checksumNodeValue.getURI()); - dps.setData(checksum); //Same as fileName above - change if needed - wdf.getDataPropertyStatementDao().insertNewDataPropertyStatement(dps); - } - - } - - //Assumes original entity name is equal to the location - as occurs with regular file upload - String originalEntityName = fileEntity.getName(); - if(originalEntityName != originalName) { - //System.out.println("Setting file entity to name of uploaded file"); - fileEntity.setName(originalName); - } else { - //System.out.println("Conditional for file entity name and uploaded name is saying same"); - } - iwDao.updateIndividual(fileEntity); - //} - - req.setAttribute("fileUri", fileUri); - req.setAttribute("originalFileName", fileEntity.getName()); - req.setAttribute("checksum", checksum); - if( "true".equals(useNewName)){ - req.setAttribute("useNewName", "true"); - req.setAttribute("newFileName", originalName); - }else{ - req.setAttribute("newFileName", fileEntity.getName()); - } - - //forward to form - JSPPageHandler.renderBasicPage(req, res, "/fileupload/datastreamModificationSuccess.jsp"); - }catch(FdcException ex){ - rawRequest.setAttribute("errors", ex.getMessage()); - JSPPageHandler.renderPlainPage(rawRequest, res, "/edit/fileUploadError.jsp"); - return; - } - } - - //Delete method - public boolean deleteFile(HttpServletRequest req, Individual entity, IndividualDao iwDao, OntModel sessionOntModel) { - boolean success = false; - String fileUri = entity.getURI(); - //Create uri based on milliseconds etc.? - Calendar c = Calendar.getInstance(); - long timeMs = c.getTimeInMillis(); - //Cuirrent date - SimpleDateFormat dateTime = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS"); - String formattedDeleteDate = dateTime.format(c.getTime()); - String deleteEventName = "deleteEvent" + timeMs; - //System.out.println("Delete event name is " +deleteEventName + " - delete time is " + formattedDeleteDate); - - //Get current user - String userURI = LoginStatusBean.getBean(req).getUserURI(); - //System.out.println("Current logged in user uri is " + userURI); - - //Update model - sessionOntModel.enterCriticalSection(true); - - try { - - //Dataset Uri - String datasetUri = (String) req.getAttribute("dataseturi"); - //System.out.println("Dataset uri is " + datasetUri); - //Remove the actual relationships: dsr:hasFile and fedora:fromDataSet - ObjectProperty hasFileProperty = sessionOntModel.getObjectProperty(fedoraNs + "hasFile"); - - ObjectProperty fromDatasetProperty = sessionOntModel.getObjectProperty(fedoraNs + "fromDataSet"); - if(hasFileProperty != null) { - //System.out.println("Has file property does exist"); - sessionOntModel.remove(sessionOntModel.createStatement(sessionOntModel.getResource(datasetUri), hasFileProperty, sessionOntModel.getResource(fileUri))); - } else{ - //System.out.println("Has file property does not exist"); - } - - if(fromDatasetProperty != null) { - //System.out.println("From dataset property exists "); - sessionOntModel.remove(sessionOntModel.createStatement(sessionOntModel.getResource(fileUri), fromDatasetProperty, sessionOntModel.getResource(datasetUri))); - } else{ - //System.out.println("From dataset property does not exist"); - } - - - //Create delete event entity and update with the correct information - //Type of Event - Resource deleteEventType = sessionOntModel.createResource(deleteNs + "DeleteEvent"); - //Individual event - Resource eventIndividual = sessionOntModel.createResource(individualPrefix + deleteEventName); - //Event is of type DeleteEvent - Statement rType = sessionOntModel.createStatement(eventIndividual, org.apache.jena.vocabulary.RDF.type, deleteEventType); - sessionOntModel.add(rType); - //Add properties to individual - deleteDateTime, deletedBy, forDataSet, forFile - DatatypeProperty dateTimeProp = sessionOntModel.createDatatypeProperty(deleteNs + "deleteDateTime"); - dateTimeProp.setRange(XSD.dateTime); - - ObjectProperty deletedByProp = sessionOntModel.createObjectProperty(deleteNs + "deletedBy"); - ObjectProperty forDatasetProp = sessionOntModel.createObjectProperty(deleteNs + "forDataset"); - ObjectProperty forFileProp = sessionOntModel.createObjectProperty(deleteNs + "forFile"); - //Need to make sure date time property is set to correct xsd:DateTime - //XSDDateTime now = new XSDDateTime(c); - //XSDDateTime now = new XSDDateTime(java.util.Calendar.getInstance()); - eventIndividual.addProperty(dateTimeProp, sessionOntModel.createTypedLiteral(formattedDeleteDate, XSDDatatype.XSDdateTime)); - //eventIndividual.addProperty(dateTimeProp, sessionOntModel.createTypedLiteral(now, XSDDatatype.XSDdateTime)); - eventIndividual.addProperty(deletedByProp, sessionOntModel.getResource(userURI)); - if(datasetUri != null){ - //System.out.println("Dataset uri is " + datasetUri); - eventIndividual.addProperty(forDatasetProp, sessionOntModel.getResource(datasetUri)); - } - eventIndividual.addProperty(forFileProp, sessionOntModel.getResource(fileUri)); - success = true; - - } finally { - sessionOntModel.leaveCriticalSection(); - } - return success; - } - - @Override - public void init() throws ServletException { - super.init(); - - ConfigurationProperties configProperties = ConfigurationProperties - .getBean(getServletContext()); - baseDirectoryForFiles = configProperties.getProperty( - "n3.baseDirectoryForFiles", DEFAULT_BASE_DIR); - - String maxSize = configProperties.getProperty("n3.maxSize", Long - .toString(DEFAULT_MAX_SIZE)); - try { - maxFileSize = Integer.parseInt(maxSize); - } catch (NumberFormatException nfe) { - log.error(nfe); - maxFileSize = DEFAULT_MAX_SIZE; - } - } - - public void setup(OntModel model, ServletContext context) { - this.configurationStatus = ""; - StringBuffer status = new StringBuffer(""); - - if( connected && configured ) - return; - - Properties props = new Properties(); - String path = context.getRealPath(FEDORA_PROPERTIES); - try{ - InputStream in = new FileInputStream(new File( path )); - props.load( in ); - fedoraUrl = props.getProperty("fedoraUrl"); - adminUser = props.getProperty("adminUser"); - adminPassword = props.getProperty("adminPassword"); - pidNamespace = props.getProperty("pidNamespace"); - - if( fedoraUrl == null || adminUser == null || adminPassword == null ){ - if( fedoraUrl == null ){ - log.error("'fedoraUrl' not found in properties file"); - status.append("

'fedoraUrl' not found in properties file.

\n"); - } - if( adminUser == null ) { - log.error("'adminUser' was not found in properties file, the " + - "user name of the fedora admin is needed to access the " + - "fedora API-M services."); - status.append("

'adminUser' was not found in properties file, the " + - "user name of the fedora admin is needed to access the " + - "fedora API-M services.

\n"); - } - if( adminPassword == null ){ - log.error("'adminPassword' was not found in properties file, the " + - "admin password is needed to access the fedora API-M services."); - status.append("

'adminPassword' was not found in properties file, the " + - "admin password is needed to access the fedora API-M services.

\n"); - } - if( pidNamespace == null ){ - log.error("'pidNamespace' was not found in properties file, the " + - "PID namespace indicates which namespace to use when creating " + - "new fedor digital objects."); - status.append("

'pidNamespace' was not found in properties file, the " + - "PID namespace indicates which namespace to use when creating " + - "new fedor digital objects.

\n"); - } - fedoraUrl = null; adminUser = null; adminPassword = null; - configured = false; - } else { - configured = true; - } - }catch(FileNotFoundException e) { - log.error("No fedora.properties file found,"+ - "it should be located at " + path); - status.append("

Fedora configuration failed.

\n"); - status.append("

No fedora.properties file found,"+ - "it should be located at " + path + "

\n"); - configured = false; - return; - }catch(Exception ex){ - status.append("

Fedora configuration failed.

\n"); - status.append("

Exception while loading" + path + "

\n"); - status.append("

" + ex.getMessage() + "

\n"); - log.error("could not load fedora properties", ex); - fedoraUrl = null; adminUser = null; adminPassword = null; - configured = false; - return; - } - - - status.append(RELOAD_MSG); - this.configurationStatus += status.toString(); -// else{ -// status.append("

Fedora configuration file ").append(path).append(" was loaded

"); -// status.append("

fedoraUrl: ").append(fedoraUrl).append("

\n"); -// checkFedoraServer(); -// } - } - - private boolean canConnectToFedoraServer( ){ - try{ - FedoraClient fc = new FedoraClient(fedoraUrl,adminUser, adminPassword); - String fedoraVersion = fc.getServerVersion(); - if( fedoraVersion != null && fedoraVersion.length() > 0 ){ - configurationStatus += "

Fedora server is live and is running " + - "fedora version " + fedoraVersion + "

\n"; - connected = true; - return true; - } else { - configurationStatus += "

Unable to reach fedora server

\n"; - connected = false; - return false; - } - }catch (Exception e) { - configurationStatus += "

There was an error while checking the " + - "fedora server version

\n

"+ e.getMessage() + "

\n"; - connected = false; - return false; - } - } - - public boolean isConfigured(){ return configured; } - public boolean isConnected(){ return connected; } - - private class FdcException extends Exception { - public FdcException(String message) { - super(message); - } - } - - private static final String RELOAD_MSG = - "

The fedora configuartion file will be reloaded if " + - "you edit the properties file and check the status.

\n"; - - public static String md5hashForFile(File file){ - try { - InputStream fin = new FileInputStream(file); - java.security.MessageDigest md5er = - MessageDigest.getInstance("MD5"); - byte[] buffer = new byte[1024]; - int read; - do { - read = fin.read(buffer); - if (read > 0) - md5er.update(buffer, 0, read); - } while (read != -1); - fin.close(); - byte[] digest = md5er.digest(); - if (digest == null) - return null; - String strDigest = "0x"; - for (int i = 0; i < digest.length; i++) { - strDigest += Integer.toString((digest[i] & 0xff) - + 0x100, 16).substring(1); - } - return strDigest; - } catch (Exception e) { - return null; - } - } - - private static final Log log = LogFactory.getLog(FedoraDatastreamController.class.getName()); -} diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/FedoraConfiguration.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/FedoraConfiguration.java deleted file mode 100644 index d014e0688..000000000 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/FedoraConfiguration.java +++ /dev/null @@ -1,198 +0,0 @@ -/* $This file is distributed under the terms of the license in /doc/license.txt$ */ - -package edu.cornell.mannlib.vitro.webapp.utils; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.InputStream; -import java.util.Properties; - -import javax.servlet.ServletContext; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.joda.time.format.DateTimeFormatter; -import org.joda.time.format.ISODateTimeFormat; - -import org.apache.jena.rdf.model.Property; -import org.apache.jena.rdf.model.ResourceFactory; - -import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary; -import fedora.client.FedoraClient; - -public class FedoraConfiguration { - - private static String FEDORA_PROPERTIES = "/WEB-INF/fedora.properties"; - - public String fedoraUrl = null; - private String adminUser = null; - private String adminPassword = null; - private String pidNamespace = null; - private String configurationStatus = "

Fedora configuration not yet loaded

"; - private boolean configured = false; - private boolean connected = false; - - public FedoraConfiguration(ServletContext context){ - setup( context ); - } - - public boolean isConfigured(){ return configured; } - public boolean isConnected(){ return connected; } - - public String setup(ServletContext context ){ - internalSetup( context); - if( ! configured ) - return configurationStatus; - canConnectToFedoraServer(); - return configurationStatus; - } - - private void internalSetup(ServletContext context) { - this.configurationStatus = ""; - StringBuffer status = new StringBuffer(""); - - if( connected && configured ) - return; - - Properties props = new Properties(); - String path = context.getRealPath(FEDORA_PROPERTIES); - try{ - InputStream in = new FileInputStream(new File( path )); - props.load( in ); - fedoraUrl = props.getProperty("fedoraUrl"); - adminUser = props.getProperty("adminUser"); - adminPassword = props.getProperty("adminPassword"); - pidNamespace = props.getProperty("pidNamespace"); - if( fedoraUrl == null || adminUser == null || adminPassword == null ){ - if( fedoraUrl == null ){ - log.error("'fedoraUrl' not found in properties file"); - status.append("

'fedoraUrl' not found in properties file.

\n"); - } - if( adminUser == null ) { - log.error("'adminUser' was not found in properties file, the " + - "user name of the fedora admin is needed to access the " + - "fedora API-M services."); - status.append("

'adminUser' was not found in properties file, the " + - "user name of the fedora admin is needed to access the " + - "fedora API-M services.

\n"); - } - if( adminPassword == null ){ - log.error("'adminPassword' was not found in properties file, the " + - "admin password is needed to access the fedora API-M services."); - status.append("

'adminPassword' was not found in properties file, the " + - "admin password is needed to access the fedora API-M services.

\n"); - } - if( pidNamespace == null ){ - log.error("'pidNamespace' was not found in properties file, the " + - "PID namespace indicates which namespace to use when creating " + - "new fedor digital objects."); - status.append("

'pidNamespace' was not found in properties file, the " + - "PID namespace indicates which namespace to use when creating " + - "new fedor digital objects.

\n"); - } - fedoraUrl = null; adminUser = null; adminPassword = null; - configured = false; - } else { - configured = true; - } - }catch(FileNotFoundException e){ - log.error("No fedora.properties file found,"+ - "it should be located at " + path); - status.append("

Fedora configuration failed.

\n"); - status.append("

No fedora.properties file found,"+ - "it should be located at " + path + "

\n"); - configured = false; - return; - }catch(Exception ex){ - status.append("

Fedora configuration failed.

\n"); - status.append("

Exception while loading" + path + "

\n"); - status.append("

" + ex.getMessage() + "

\n"); - log.error("could not load fedora properties", ex); - fedoraUrl = null; adminUser = null; adminPassword = null; - configured = false; - return; - } - - status.append(RELOAD_MSG); - this.configurationStatus += status.toString(); - } - - public boolean canConnectToFedoraServer( ){ - try{ - FedoraClient fc = new FedoraClient(fedoraUrl,adminUser, adminPassword); - String fedoraVersion = fc.getServerVersion(); - if( fedoraVersion != null && fedoraVersion.length() > 0 ){ - configurationStatus += "

Fedora server is live and is running " + - "fedora version " + fedoraVersion + "

\n"; - connected = true; - return true; - } else { - configurationStatus += "

Unable to reach fedora server

\n"; - connected = false; - return false; - } - }catch (Exception e) { - configurationStatus += "

There was an error while checking the " + - "fedora server version

\n

"+ e.getMessage() + "

\n"; - connected = false; - return false; - } - } - - - - public static final Property FILE_NAME = ResourceFactory.createProperty(VitroVocabulary.FILE_NAME); - public static final Property CONTENT_TYPE = ResourceFactory.createProperty(VitroVocabulary.CONTENT_TYPE); - public static final Property FILE_LOCATION = ResourceFactory.createProperty(VitroVocabulary.FILE_LOCATION); - //public static final Property FEDORA_ID = ResourceFactory.createProperty(VitroVocabulary.FEDORA_PID); - - DateTimeFormatter isoFormatter = ISODateTimeFormat.dateTime(); - - private static Log log = LogFactory.getLog(FedoraConfiguration.class); - - private static final String RELOAD_MSG = - "

The fedora configuartion file will be reloaded if " + - "you edit the properties file and check the status.

\n"; - - public String getFedoraUrl() { - return fedoraUrl; - } - - public void setFedoraUrl(String fedoraUrl) { - this.fedoraUrl = fedoraUrl; - } - - public String getAdminUser() { - return adminUser; - } - - public void setAdminUser(String adminUser) { - this.adminUser = adminUser; - } - - public String getAdminPassword() { - return adminPassword; - } - - public void setAdminPassword(String adminPassword) { - this.adminPassword = adminPassword; - } - - public String getPidNamespace() { - return pidNamespace; - } - - public void setPidNamespace(String pidNamespace) { - this.pidNamespace = pidNamespace; - } - - public String getConfigurationStatus() { - return configurationStatus; - } - - public void setConfigurationStatus(String configurationStatus) { - this.configurationStatus = configurationStatus; - } - -} diff --git a/dependencies/pom.xml b/dependencies/pom.xml index 79a9ff0e0..d5717f500 100644 --- a/dependencies/pom.xml +++ b/dependencies/pom.xml @@ -248,11 +248,6 @@ csv 1.0
- - org.vivoweb.dependencies - fedora-client - 1.0 - org.vivoweb.dependencies jai_codec diff --git a/webapp/src/main/webapp/fileupload/datastreamModification.jsp b/webapp/src/main/webapp/fileupload/datastreamModification.jsp deleted file mode 100644 index 0a134f8f8..000000000 --- a/webapp/src/main/webapp/fileupload/datastreamModification.jsp +++ /dev/null @@ -1,24 +0,0 @@ -<%-- $This file is distributed under the terms of the license in /doc/license.txt$ --%> - -<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> - -<%/* this is used by the FedoraDatastreamController and not by the N3 editing system.*/%> - -

Upload a replacement for ${fileName}

-
" - enctype="multipart/form-data" method="POST"> - -

File

- - <%/*

- use existing file name

-

- rename file to name of file being uploaded

*/%> - - - - - - - -
diff --git a/webapp/src/main/webapp/fileupload/datastreamModificationSuccess.jsp b/webapp/src/main/webapp/fileupload/datastreamModificationSuccess.jsp deleted file mode 100644 index 663991cbe..000000000 --- a/webapp/src/main/webapp/fileupload/datastreamModificationSuccess.jsp +++ /dev/null @@ -1,16 +0,0 @@ -<%-- $This file is distributed under the terms of the license in /doc/license.txt$ --%> - -<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> - -
The file ${orginalFileName} was updated. The file received from you had the MD5 checksum ${checksum}.
- - -
The name of the file was also changed to ${newFileName}.
-
- - - - - - - \ No newline at end of file diff --git a/webapp/src/main/webapp/fileupload/md5.jsp b/webapp/src/main/webapp/fileupload/md5.jsp deleted file mode 100644 index 9ace23a43..000000000 --- a/webapp/src/main/webapp/fileupload/md5.jsp +++ /dev/null @@ -1,11 +0,0 @@ -<%-- $This file is distributed under the terms of the license in /doc/license.txt$ --%> - -<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> - -
${checksum} "${fileName}"
- - - - -
return to ${name}
- \ No newline at end of file From 47a18844c460def2001290ade3c08d62bf17e660 Mon Sep 17 00:00:00 2001 From: Graham Triggs Date: Mon, 19 Dec 2016 19:09:00 +0000 Subject: [PATCH 26/49] Remove unused JAI dependencies --- dependencies/pom.xml | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/dependencies/pom.xml b/dependencies/pom.xml index d5717f500..17509a5a9 100644 --- a/dependencies/pom.xml +++ b/dependencies/pom.xml @@ -248,16 +248,6 @@ csv 1.0
- - org.vivoweb.dependencies - jai_codec - 1.1.3 - - - org.vivoweb.dependencies - jai_core - 1.1.3 - javax.json From 45bad8174dc9c761587123b2e737d102b3b247bd Mon Sep 17 00:00:00 2001 From: Graham Triggs Date: Mon, 19 Dec 2016 22:24:12 +0000 Subject: [PATCH 27/49] Replace old, undistributed CSV parser library with Commons CSV --- .../jena/JenaCsv2RdfController.java | 4 +- .../ontology/update/OntologyChangeParser.java | 66 +++++++-------- .../mannlib/vitro/webapp/utils/Csv2Rdf.java | 82 ++++++++++--------- dependencies/pom.xml | 11 ++- 4 files changed, 83 insertions(+), 80 deletions(-) diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/jena/JenaCsv2RdfController.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/jena/JenaCsv2RdfController.java index f15808f24..20ad69c7d 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/jena/JenaCsv2RdfController.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/jena/JenaCsv2RdfController.java @@ -141,7 +141,7 @@ public class JenaCsv2RdfController extends JenaIngestController { } public Model doExecuteCsv2Rdf(VitroRequest vreq, FileItem fileStream, String filePath) throws Exception { - char[] quoteChars = {'"'}; + char quoteChar = '"'; String namespace = ""; String tboxNamespace = vreq.getParameter("tboxNamespace"); String typeName = vreq.getParameter("typeName"); @@ -162,7 +162,7 @@ public class JenaCsv2RdfController extends JenaIngestController { separatorChar = '\t'; } - Csv2Rdf c2r = new Csv2Rdf(separatorChar, quoteChars,namespace,tboxNamespace,typeName); + Csv2Rdf c2r = new Csv2Rdf(separatorChar, quoteChar,namespace,tboxNamespace,typeName); InputStream is = null; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/ontology/update/OntologyChangeParser.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/ontology/update/OntologyChangeParser.java index fc3327762..40f84722d 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/ontology/update/OntologyChangeParser.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/ontology/update/OntologyChangeParser.java @@ -5,14 +5,16 @@ package edu.cornell.mannlib.vitro.webapp.ontology.update; import java.io.File; import java.io.FileInputStream; import java.io.IOException; +import java.io.InputStreamReader; import java.util.ArrayList; import java.util.List; import java.util.StringTokenizer; +import org.apache.commons.csv.CSVFormat; +import org.apache.commons.csv.CSVParser; +import org.apache.commons.csv.CSVRecord; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.skife.csv.CSVReader; -import org.skife.csv.SimpleReader; import edu.cornell.mannlib.vitro.webapp.ontology.update.AtomicOntologyChange.AtomicChangeType; @@ -35,7 +37,6 @@ public class OntologyChangeParser { /** * @param diffPath Diff path - * @throws IOException */ @SuppressWarnings({ "unchecked", "null", "static-access" }) @@ -50,52 +51,53 @@ public class OntologyChangeParser { String destinationURI = null; StringTokenizer stArr = null; FileInputStream in = new FileInputStream(new File(diffPath)); - CSVReader readFile = new SimpleReader(); - readFile.setSeperator('\t'); - - List rows = readFile.parse(in); - - for(int rowNum = 0; rowNum < rows.size(); rowNum++){ - - String[] cols = rows.get(rowNum); - if (cols.length != 5) { - logger.logError("Invalid PromptDiff data at row " + (rowNum + 1) - + ". Expected 5 columns; found " + cols.length ); + + CSVParser readFile = new CSVParser(new InputStreamReader(in), + CSVFormat.DEFAULT.withRecordSeparator('\t')); + + int rowNum = 0; + for (CSVRecord record : readFile) { + rowNum++; + if (record.size() != 5) { + logger.logError("Invalid PromptDiff data at row " + (rowNum) + + ". Expected 5 columns; found " + record.size() ); } else { - + String col = null; changeObj = new AtomicOntologyChange(); - - if (cols[0] != null && cols[0].length() > 0) { - changeObj.setSourceURI(cols[0]); - } - - if (cols[1] != null && cols[1].length() > 0) { - changeObj.setDestinationURI(cols[1]); + + col = record.get(0); + if (col != null && col.length() > 0) { + changeObj.setSourceURI(col); } - if (cols[4] != null && cols[4].length() > 0) { - changeObj.setNotes(cols[4]); + col = record.get(1); + if (col != null && col.length() > 0) { + changeObj.setDestinationURI(col); + } + + col = record.get(4); + if (col != null && col.length() > 0) { + changeObj.setNotes(col); } - if ("Yes".equals(cols[2])) { + if ("Yes".equals(record.get(2))) { changeObj.setAtomicChangeType(AtomicChangeType.RENAME); - } else if ("Delete".equals(cols[3])) { + } else if ("Delete".equals(record.get(3))) { changeObj.setAtomicChangeType(AtomicChangeType.DELETE); - } else if ("Add".equals(cols[3])) { + } else if ("Add".equals(record.get(3))) { changeObj.setAtomicChangeType(AtomicChangeType.ADD); } else { logger.logError("Invalid rename or change type data: '" + - cols[2] + " " + cols[3] + "'"); + record.get(2) + " " + record.get(3) + "'"); } - - + log.debug(changeObj); changeObjects.add(changeObj); - } - } + + readFile.close(); if (changeObjects.size() == 0) { logger.log("No ABox updates are required."); diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/Csv2Rdf.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/Csv2Rdf.java index 0f9d90cc7..eb5c63b98 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/Csv2Rdf.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/Csv2Rdf.java @@ -4,14 +4,15 @@ package edu.cornell.mannlib.vitro.webapp.utils; import java.io.IOException; import java.io.InputStream; +import java.io.InputStreamReader; import java.util.List; import java.util.Random; import javax.servlet.http.HttpServletRequest; -import org.skife.csv.CSVReader; -import org.skife.csv.SimpleReader; - +import org.apache.commons.csv.CSVFormat; +import org.apache.commons.csv.CSVParser; +import org.apache.commons.csv.CSVRecord; import org.apache.jena.datatypes.xsd.XSDDatatype; import org.apache.jena.ontology.DatatypeProperty; import org.apache.jena.ontology.Individual; @@ -34,11 +35,11 @@ public class Csv2Rdf { private String individualNameBase; private String propertyNameBase; private char separatorChar; - private char[] quoteChars; + private char quoteChar; - public Csv2Rdf(char[] quoteChars, String namespace, String tboxNamespace, String typeName) { + public Csv2Rdf(char quoteChar, String namespace, String tboxNamespace, String typeName) { this.separatorChar = ','; - this.quoteChars = quoteChars; + this.quoteChar = quoteChar; this.namespace = namespace; this.tboxNamespace = tboxNamespace; this.typeName = typeName; @@ -46,9 +47,9 @@ public class Csv2Rdf { this.propertyNameBase = individualNameBase+"_"; } - public Csv2Rdf(char separatorChar, char[] quoteChars, String namespace, String tboxNamespace, String typeName) { + public Csv2Rdf(char separatorChar, char quoteChar, String namespace, String tboxNamespace, String typeName) { this.separatorChar = separatorChar; - this.quoteChars = quoteChars; + this.quoteChar = quoteChar; this.namespace = namespace; this.tboxNamespace = tboxNamespace; this.typeName = typeName; @@ -66,47 +67,48 @@ public class Csv2Rdf { ontModel.addSubModel(tboxOntModel); OntClass theClass = tboxOntModel.createClass(tboxNamespace+typeName); - CSVReader cReader = new SimpleReader(); - cReader.setSeperator(separatorChar); - cReader.setQuoteCharacters(quoteChars); - - URIGenerator uriGen = (wadf != null && destination != null) + URIGenerator uriGen = (wadf != null && destination != null) ? new RandomURIGenerator(wadf, destination) - : new SequentialURIGenerator(); - - List fileRows = cReader.parse(fis); - - String[] columnHeaders = fileRows.get(0); + : new SequentialURIGenerator(); - DatatypeProperty[] dpArray = new DatatypeProperty[columnHeaders.length]; + CSVParser cReader = new CSVParser(new InputStreamReader(fis), + CSVFormat.DEFAULT.withRecordSeparator(separatorChar) + .withQuote(quoteChar)); - for (int i=0; i0) { - ind.addProperty(dpArray[col], value); // no longer using: , XSDDatatype.XSDstring); - // TODO: specification of datatypes for columns - } - } - } - + DatatypeProperty[] dpArray = null; + + for (CSVRecord cRecord : cReader) { + if (dpArray == null) { + dpArray = new DatatypeProperty[cRecord.size()]; + + for (int i = 0; i < dpArray.length; i++) { + dpArray[i] = tboxOntModel.createDatatypeProperty(tboxNamespace+propertyNameBase+cRecord.get(i).replaceAll("\\W","")); + } + } else { + Individual ind = null; + String uri = uriGen.getNextURI(); + if (uri!=null) { + ind = ontModel.createIndividual(uri, theClass); + } else { + ind = ontModel.createIndividual(theClass); + } + for (int col = 0; col0) { + ind.addProperty(dpArray[col], value); // no longer using: , XSDDatatype.XSDstring); + // TODO: specification of datatypes for columns + } + } + } + } + + cReader.close(); ontModel.removeSubModel(tboxOntModel); Model[] resultModels = new Model[2]; resultModels[0] = ontModel; resultModels[1] = tboxOntModel; return resultModels; - } private interface URIGenerator { diff --git a/dependencies/pom.xml b/dependencies/pom.xml index 17509a5a9..a250f0a09 100644 --- a/dependencies/pom.xml +++ b/dependencies/pom.xml @@ -111,6 +111,11 @@ commons-lang3 3.4 + + org.apache.commons + commons-csv + 1.4 + commons-logging commons-logging @@ -243,12 +248,6 @@ 1.2.1 - - org.vivoweb.dependencies - csv - 1.0 - - javax.json javax.json-api From c7bbe0a8c3200c98cfb0c12d65834c2a851a898c Mon Sep 17 00:00:00 2001 From: Graham Triggs Date: Tue, 20 Dec 2016 08:53:36 +0000 Subject: [PATCH 28/49] Remove VIVOWEB Maven repository as Vitro no longer requires dependencies that are not in Maven central --- pom.xml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/pom.xml b/pom.xml index 392472d4a..fef389718 100644 --- a/pom.xml +++ b/pom.xml @@ -248,14 +248,6 @@ - - - vivo-dependencies - VIVO Dependencies - https://raw.github.com/vivo-project/dependencies/master/ - - - ossrh From 4e3d37356286563bc6d28e8e049a44abb056ee12 Mon Sep 17 00:00:00 2001 From: Graham Triggs Date: Wed, 21 Dec 2016 09:57:51 +0000 Subject: [PATCH 29/49] Update httpclient to 4.5.2 to resolve a nonsuchmethoderrror --- dependencies/pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dependencies/pom.xml b/dependencies/pom.xml index a250f0a09..3fdde25a1 100644 --- a/dependencies/pom.xml +++ b/dependencies/pom.xml @@ -172,13 +172,13 @@ org.apache.httpcomponents - httpcore - 4.4 + httpclient + 4.5.2 org.apache.httpcomponents httpmime - 4.4 + 4.5.2 org.apache.jena From 4304d2367ffc7d71571e179ca329c23e2d12a177 Mon Sep 17 00:00:00 2001 From: Graham Triggs Date: Wed, 21 Dec 2016 12:16:44 +0000 Subject: [PATCH 30/49] =?UTF-8?q?Explode=20the=20OWLAPI=20OSGi=20distribut?= =?UTF-8?q?ion=20to=20separate=20JARs=20so=20that=20we=20don=E2=80=99t=20b?= =?UTF-8?q?ring=20in=20the=20embedded=20dependencies?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dependencies/pom.xml | 63 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 55 insertions(+), 8 deletions(-) diff --git a/dependencies/pom.xml b/dependencies/pom.xml index 3fdde25a1..6825b6e79 100644 --- a/dependencies/pom.xml +++ b/dependencies/pom.xml @@ -157,18 +157,65 @@ net.sourceforge.owlapi jfact 4.0.4 + + + + net.sourceforge.owlapi + owlapi-distribution + + + + + + net.sourceforge.owlapi + owlapi-api + 4.2.7 net.sourceforge.owlapi - owlapi-distribution + owlapi-apibinding 4.2.7 - - + + + net.sourceforge.owlapi + owlapi-fixers + 4.2.7 + + + net.sourceforge.owlapi + owlapi-impl + 4.2.7 + + + net.sourceforge.owlapi + owlapi-parsers + 4.2.7 + + + net.sourceforge.owlapi + owlapi-rio + 4.2.7 + + + net.sourceforge.owlapi + owlapi-compatibility + 4.2.7 + + + net.sourceforge.owlapi + owlapi-tools + 4.2.7 + + + net.sourceforge.owlapi + owlapi-apibinding + 4.2.7 + + + + com.fasterxml.jackson.core + jackson-core + 2.7.4 org.apache.httpcomponents From d45f70bcc8cdb6d50e41ded2393234866dc76c28 Mon Sep 17 00:00:00 2001 From: Graham Triggs Date: Wed, 21 Dec 2016 12:41:55 +0000 Subject: [PATCH 31/49] Update JFact, OWLAPI and jsonld-java --- dependencies/pom.xml | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/dependencies/pom.xml b/dependencies/pom.xml index 6825b6e79..5f62ccb55 100644 --- a/dependencies/pom.xml +++ b/dependencies/pom.xml @@ -156,7 +156,7 @@ net.sourceforge.owlapi jfact - 4.0.4 + 5.0.1 @@ -169,47 +169,47 @@ net.sourceforge.owlapi owlapi-api - 4.2.7 + 5.0.4 net.sourceforge.owlapi owlapi-apibinding - 4.2.7 - - - net.sourceforge.owlapi - owlapi-fixers - 4.2.7 + 5.0.4 net.sourceforge.owlapi owlapi-impl - 4.2.7 + 5.0.4 + + + net.sourceforge.owlapi + owlapi-oboformat + 5.0.4 net.sourceforge.owlapi owlapi-parsers - 4.2.7 + 5.0.4 net.sourceforge.owlapi owlapi-rio - 4.2.7 - - - net.sourceforge.owlapi - owlapi-compatibility - 4.2.7 + 5.0.4 net.sourceforge.owlapi owlapi-tools - 4.2.7 + 5.0.4 - net.sourceforge.owlapi - owlapi-apibinding - 4.2.7 + org.semarglproject + semargl-sesame + 0.6.1 + + + com.github.jsonld-java + jsonld-java + 0.8.3 From 5ccba0e0c4139f9a1a2adb0910730de281a5d33a Mon Sep 17 00:00:00 2001 From: Graham Triggs Date: Wed, 21 Dec 2016 14:12:27 +0000 Subject: [PATCH 32/49] Update POM to require Java 8 (Jena 3.x does not support earlier versions) --- installer/pom.xml | 4 ++-- pom.xml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/installer/pom.xml b/installer/pom.xml index 2c1d6f5c5..b21dd3f9f 100644 --- a/installer/pom.xml +++ b/installer/pom.xml @@ -21,8 +21,8 @@ maven-compiler-plugin - 1.7 - 1.7 + 1.8 + 1.8 UTF-8 diff --git a/pom.xml b/pom.xml index fef389718..d8de4fed8 100644 --- a/pom.xml +++ b/pom.xml @@ -166,8 +166,8 @@ org.apache.maven.plugins maven-compiler-plugin - 1.7 - 1.7 + 1.8 + 1.8 UTF-8 From e9cb3de52e5c592b25a0a9395c919e47c54755e9 Mon Sep 17 00:00:00 2001 From: Graham Triggs Date: Wed, 21 Dec 2016 18:51:34 +0000 Subject: [PATCH 33/49] =?UTF-8?q?Exclude=20rio=20dependencies=20so=20that?= =?UTF-8?q?=20Sesame=20isn=E2=80=99t=20included?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dependencies/pom.xml | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/dependencies/pom.xml b/dependencies/pom.xml index 5f62ccb55..df30c3970 100644 --- a/dependencies/pom.xml +++ b/dependencies/pom.xml @@ -175,6 +175,13 @@ net.sourceforge.owlapi owlapi-apibinding 5.0.4 + + + + net.sourceforge.owlapi + owlapi-rio + + net.sourceforge.owlapi @@ -191,11 +198,6 @@ owlapi-parsers 5.0.4 - - net.sourceforge.owlapi - owlapi-rio - 5.0.4 - net.sourceforge.owlapi owlapi-tools @@ -203,7 +205,12 @@ org.semarglproject - semargl-sesame + semargl-core + 0.6.1 + + + org.semarglproject + semargl-rdfa 0.6.1 From 68a462b05a5ceefd61784c7216f1c099f1f3f8bf Mon Sep 17 00:00:00 2001 From: grahamtriggs Date: Fri, 23 Dec 2016 21:55:08 +0000 Subject: [PATCH 34/49] [VIVO-1312] Implement Linked Data Fragment Server (#53) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [VIVO-1312] Linked Data Fragments initial implementation * [VIVO-1312] Use known ontologies in the prefixes config * [VIVO-1312] Simplify SPARQL as when restricted to specific values, they don’t need ordering * [VIVO-1312] Freemarker fixes * [VIVO-1312] Remove blank nodes * [VIVO-1312] Add access control header and standard prefixes for TPF * [VIVO-1312] Render literals in form so that they will work on resubmit * [VIVO-1312] Minor template update * [VIVO-1312] Minor template update --- .../config/ConfigReader.java | 119 +++++++ .../datasource/AbstractRequestProcessor.java | 76 +++++ ...ractRequestProcessorForTriplePatterns.java | 158 +++++++++ .../datasource/DataSourceBase.java | 54 ++++ .../datasource/DataSourceFactory.java | 35 ++ .../datasource/DataSourceTypesRegistry.java | 51 +++ .../datasource/IDataSource.java | 38 +++ .../datasource/IDataSourceType.java | 33 ++ .../datasource/IFragmentRequestProcessor.java | 26 ++ .../datasource/index/IndexDataSource.java | 47 +++ .../index/IndexRequestProcessorForTPFs.java | 146 +++++++++ .../JenaTDBBasedRequestProcessorForTPFs.java | 165 ++++++++++ .../datasource/tdb/JenaTDBDataSource.java | 47 +++ .../datasource/tdb/JenaTDBDataSourceType.java | 34 ++ .../DataSourceCreationException.java | 25 ++ .../exceptions/DataSourceException.java | 37 +++ .../DataSourceNotFoundException.java | 16 + .../NoRegisteredMimeTypesException.java | 17 + .../UnknownDataSourceTypeException.java | 16 + .../fragments/FragmentRequestParserBase.java | 141 +++++++++ .../fragments/IFragmentRequestParser.java | 29 ++ .../fragments/ILinkedDataFragment.java | 79 +++++ .../fragments/ILinkedDataFragmentRequest.java | 48 +++ .../fragments/LinkedDataFragmentBase.java | 189 +++++++++++ .../LinkedDataFragmentRequestBase.java | 81 +++++ .../fragments/tpf/ITriplePatternElement.java | 89 ++++++ .../fragments/tpf/ITriplePatternFragment.java | 15 + .../tpf/ITriplePatternFragmentRequest.java | 52 +++ .../fragments/tpf/TPFRequestParser.java | 127 ++++++++ .../tpf/TPFRequestParserForJenaBackends.java | 35 ++ .../tpf/TriplePatternElementFactory.java | 214 +++++++++++++ .../tpf/TriplePatternFragmentBase.java | 164 ++++++++++ .../tpf/TriplePatternFragmentImpl.java | 72 +++++ .../tpf/TriplePatternFragmentRequestImpl.java | 96 ++++++ .../servlet/LinkedDataFragmentServlet.java | 213 +++++++++++++ .../util/CommonResources.java | 139 ++++++++ .../linkeddatafragments/util/MIMEParse.java | 299 ++++++++++++++++++ .../util/RDFTermParser.java | 116 +++++++ .../util/TriplePatternElementParser.java | 80 +++++ .../TriplePatternElementParserForJena.java | 128 ++++++++ .../HtmlTriplePatternFragmentWriterImpl.java | 145 +++++++++ .../views/ILinkedDataFragmentWriter.java | 44 +++ .../views/LinkedDataFragmentWriterBase.java | 42 +++ .../LinkedDataFragmentWriterFactory.java | 35 ++ .../views/RdfWriterImpl.java | 55 ++++ .../TriplePatternFragmentWriterBase.java | 46 +++ ...DFServiceBasedRequestProcessorForTPFs.java | 201 ++++++++++++ .../rdfservice/RDFServiceDataSource.java | 46 +++ .../rdfservice/RDFServiceDataSourceType.java | 31 ++ .../VitroLinkedDataFragmentServlet.java | 270 ++++++++++++++++ .../HtmlTriplePatternFragmentWriterImpl.java | 221 +++++++++++++ .../LinkedDataFragmentWriterFactory.java | 36 +++ .../linkeddatafragments/servlet/favicon.ico | Bin 0 -> 318 bytes .../linkeddatafragments/servlet/logo.svg | 67 ++++ .../linkeddatafragments/servlet/style.css | 247 +++++++++++++++ api/src/main/resources/tpf/base.ftl.html | 30 ++ .../main/resources/tpf/datasource.ftl.html | 7 + api/src/main/resources/tpf/error.ftl.html | 11 + api/src/main/resources/tpf/fragment.ftl.html | 83 +++++ api/src/main/resources/tpf/index.ftl.html | 21 ++ api/src/main/resources/tpf/notfound.ftl.html | 16 + dependencies/pom.xml | 5 + webapp/src/main/webapp/WEB-INF/web.xml | 10 + 63 files changed, 5215 insertions(+) create mode 100644 api/src/main/java/org/linkeddatafragments/config/ConfigReader.java create mode 100644 api/src/main/java/org/linkeddatafragments/datasource/AbstractRequestProcessor.java create mode 100644 api/src/main/java/org/linkeddatafragments/datasource/AbstractRequestProcessorForTriplePatterns.java create mode 100644 api/src/main/java/org/linkeddatafragments/datasource/DataSourceBase.java create mode 100644 api/src/main/java/org/linkeddatafragments/datasource/DataSourceFactory.java create mode 100644 api/src/main/java/org/linkeddatafragments/datasource/DataSourceTypesRegistry.java create mode 100644 api/src/main/java/org/linkeddatafragments/datasource/IDataSource.java create mode 100644 api/src/main/java/org/linkeddatafragments/datasource/IDataSourceType.java create mode 100644 api/src/main/java/org/linkeddatafragments/datasource/IFragmentRequestProcessor.java create mode 100644 api/src/main/java/org/linkeddatafragments/datasource/index/IndexDataSource.java create mode 100644 api/src/main/java/org/linkeddatafragments/datasource/index/IndexRequestProcessorForTPFs.java create mode 100644 api/src/main/java/org/linkeddatafragments/datasource/tdb/JenaTDBBasedRequestProcessorForTPFs.java create mode 100644 api/src/main/java/org/linkeddatafragments/datasource/tdb/JenaTDBDataSource.java create mode 100644 api/src/main/java/org/linkeddatafragments/datasource/tdb/JenaTDBDataSourceType.java create mode 100644 api/src/main/java/org/linkeddatafragments/exceptions/DataSourceCreationException.java create mode 100644 api/src/main/java/org/linkeddatafragments/exceptions/DataSourceException.java create mode 100644 api/src/main/java/org/linkeddatafragments/exceptions/DataSourceNotFoundException.java create mode 100644 api/src/main/java/org/linkeddatafragments/exceptions/NoRegisteredMimeTypesException.java create mode 100644 api/src/main/java/org/linkeddatafragments/exceptions/UnknownDataSourceTypeException.java create mode 100644 api/src/main/java/org/linkeddatafragments/fragments/FragmentRequestParserBase.java create mode 100644 api/src/main/java/org/linkeddatafragments/fragments/IFragmentRequestParser.java create mode 100644 api/src/main/java/org/linkeddatafragments/fragments/ILinkedDataFragment.java create mode 100644 api/src/main/java/org/linkeddatafragments/fragments/ILinkedDataFragmentRequest.java create mode 100644 api/src/main/java/org/linkeddatafragments/fragments/LinkedDataFragmentBase.java create mode 100644 api/src/main/java/org/linkeddatafragments/fragments/LinkedDataFragmentRequestBase.java create mode 100644 api/src/main/java/org/linkeddatafragments/fragments/tpf/ITriplePatternElement.java create mode 100644 api/src/main/java/org/linkeddatafragments/fragments/tpf/ITriplePatternFragment.java create mode 100644 api/src/main/java/org/linkeddatafragments/fragments/tpf/ITriplePatternFragmentRequest.java create mode 100644 api/src/main/java/org/linkeddatafragments/fragments/tpf/TPFRequestParser.java create mode 100644 api/src/main/java/org/linkeddatafragments/fragments/tpf/TPFRequestParserForJenaBackends.java create mode 100644 api/src/main/java/org/linkeddatafragments/fragments/tpf/TriplePatternElementFactory.java create mode 100644 api/src/main/java/org/linkeddatafragments/fragments/tpf/TriplePatternFragmentBase.java create mode 100644 api/src/main/java/org/linkeddatafragments/fragments/tpf/TriplePatternFragmentImpl.java create mode 100644 api/src/main/java/org/linkeddatafragments/fragments/tpf/TriplePatternFragmentRequestImpl.java create mode 100644 api/src/main/java/org/linkeddatafragments/servlet/LinkedDataFragmentServlet.java create mode 100644 api/src/main/java/org/linkeddatafragments/util/CommonResources.java create mode 100644 api/src/main/java/org/linkeddatafragments/util/MIMEParse.java create mode 100644 api/src/main/java/org/linkeddatafragments/util/RDFTermParser.java create mode 100644 api/src/main/java/org/linkeddatafragments/util/TriplePatternElementParser.java create mode 100644 api/src/main/java/org/linkeddatafragments/util/TriplePatternElementParserForJena.java create mode 100644 api/src/main/java/org/linkeddatafragments/views/HtmlTriplePatternFragmentWriterImpl.java create mode 100644 api/src/main/java/org/linkeddatafragments/views/ILinkedDataFragmentWriter.java create mode 100644 api/src/main/java/org/linkeddatafragments/views/LinkedDataFragmentWriterBase.java create mode 100644 api/src/main/java/org/linkeddatafragments/views/LinkedDataFragmentWriterFactory.java create mode 100644 api/src/main/java/org/linkeddatafragments/views/RdfWriterImpl.java create mode 100644 api/src/main/java/org/linkeddatafragments/views/TriplePatternFragmentWriterBase.java create mode 100644 api/src/main/java/org/vivoweb/linkeddatafragments/datasource/rdfservice/RDFServiceBasedRequestProcessorForTPFs.java create mode 100644 api/src/main/java/org/vivoweb/linkeddatafragments/datasource/rdfservice/RDFServiceDataSource.java create mode 100644 api/src/main/java/org/vivoweb/linkeddatafragments/datasource/rdfservice/RDFServiceDataSourceType.java create mode 100644 api/src/main/java/org/vivoweb/linkeddatafragments/servlet/VitroLinkedDataFragmentServlet.java create mode 100644 api/src/main/java/org/vivoweb/linkeddatafragments/views/HtmlTriplePatternFragmentWriterImpl.java create mode 100644 api/src/main/java/org/vivoweb/linkeddatafragments/views/LinkedDataFragmentWriterFactory.java create mode 100644 api/src/main/resources/org/vivoweb/linkeddatafragments/servlet/favicon.ico create mode 100644 api/src/main/resources/org/vivoweb/linkeddatafragments/servlet/logo.svg create mode 100644 api/src/main/resources/org/vivoweb/linkeddatafragments/servlet/style.css create mode 100644 api/src/main/resources/tpf/base.ftl.html create mode 100644 api/src/main/resources/tpf/datasource.ftl.html create mode 100644 api/src/main/resources/tpf/error.ftl.html create mode 100644 api/src/main/resources/tpf/fragment.ftl.html create mode 100644 api/src/main/resources/tpf/index.ftl.html create mode 100644 api/src/main/resources/tpf/notfound.ftl.html diff --git a/api/src/main/java/org/linkeddatafragments/config/ConfigReader.java b/api/src/main/java/org/linkeddatafragments/config/ConfigReader.java new file mode 100644 index 000000000..3db1d638f --- /dev/null +++ b/api/src/main/java/org/linkeddatafragments/config/ConfigReader.java @@ -0,0 +1,119 @@ +package org.linkeddatafragments.config; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import org.linkeddatafragments.datasource.IDataSourceType; + +import java.io.Reader; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; + +/** + * Reads the configuration of a Linked Data Fragments server. + * + * @author Ruben Verborgh + * @author Olaf Hartig + */ +public class ConfigReader { + private final Map dataSourceTypes = new HashMap<>(); + private final Map dataSources = new HashMap<>(); + private final Map prefixes = new HashMap<>(); + private final String baseURL; + + /** + * Creates a new configuration reader. + * + * @param configReader the configuration + */ + public ConfigReader(Reader configReader) { + JsonObject root = new JsonParser().parse(configReader).getAsJsonObject(); + this.baseURL = root.has("baseURL") ? root.getAsJsonPrimitive("baseURL").getAsString() : null; + + for (Entry entry : root.getAsJsonObject("datasourcetypes").entrySet()) { + final String className = entry.getValue().getAsString(); + dataSourceTypes.put(entry.getKey(), initDataSouceType(className) ); + } + for (Entry entry : root.getAsJsonObject("datasources").entrySet()) { + JsonObject dataSource = entry.getValue().getAsJsonObject(); + this.dataSources.put(entry.getKey(), dataSource); + } + for (Entry entry : root.getAsJsonObject("prefixes").entrySet()) { + this.prefixes.put(entry.getKey(), entry.getValue().getAsString()); + } + } + + /** + * Gets the data source types. + * + * @return a mapping of names of data source types to these types + */ + public Map getDataSourceTypes() { + return dataSourceTypes; + } + + /** + * Gets the data sources. + * + * @return the data sources + */ + public Map getDataSources() { + return dataSources; + } + + /** + * Gets the prefixes. + * + * @return the prefixes + */ + public Map getPrefixes() { + return prefixes; + } + + /** + * Gets the base URL + * + * @return the base URL + */ + public String getBaseURL() { + return baseURL; + } + + /** + * Loads a certain {@link IDataSourceType} class at runtime + * + * @param className IDataSourceType class + * @return the created IDataSourceType object + */ + protected IDataSourceType initDataSouceType(final String className ) + { + final Class c; + try { + c = Class.forName( className ); + } + catch ( ClassNotFoundException e ) { + throw new IllegalArgumentException( "Class not found: " + className, + e ); + } + + final Object o; + try { + o = c.newInstance(); + } + catch ( Exception e ) { + throw new IllegalArgumentException( + "Creating an instance of class '" + className + "' " + + "caused a " + e.getClass().getSimpleName() + ": " + + e.getMessage(), e ); + } + + if ( ! (o instanceof IDataSourceType) ) + throw new IllegalArgumentException( + "Class '" + className + "' is not an implementation " + + "of IDataSourceType." ); + + return (IDataSourceType) o; + } + +} diff --git a/api/src/main/java/org/linkeddatafragments/datasource/AbstractRequestProcessor.java b/api/src/main/java/org/linkeddatafragments/datasource/AbstractRequestProcessor.java new file mode 100644 index 000000000..6cfa14ef8 --- /dev/null +++ b/api/src/main/java/org/linkeddatafragments/datasource/AbstractRequestProcessor.java @@ -0,0 +1,76 @@ +package org.linkeddatafragments.datasource; + +import org.linkeddatafragments.fragments.ILinkedDataFragment; +import org.linkeddatafragments.fragments.ILinkedDataFragmentRequest; + +/** + * Base class for implementations of {@link IFragmentRequestProcessor}. + * + * @author Olaf Hartig + */ +abstract public class AbstractRequestProcessor + implements IFragmentRequestProcessor +{ + @Override + public void close() {} + + /** + * Create an {@link ILinkedDataFragment} from {@link ILinkedDataFragmentRequest} + * + * @param request + * @return + * @throws IllegalArgumentException + */ + @Override + final public ILinkedDataFragment createRequestedFragment( + final ILinkedDataFragmentRequest request ) + throws IllegalArgumentException + { + return getWorker( request ).createRequestedFragment(); + } + + /** + * Get the {@link Worker} from {@link ILinkedDataFragmentRequest} + * + * @param request + * @return + * @throws IllegalArgumentException + */ + abstract protected Worker getWorker( + final ILinkedDataFragmentRequest request ) + throws IllegalArgumentException; + + /** + * Processes {@link ILinkedDataFragmentRequest}s + * + */ + abstract static protected class Worker + { + + /** + * The {@link ILinkedDataFragmentRequest} to process + */ + public final ILinkedDataFragmentRequest request; + + /** + * Create a Worker + * + * @param request + */ + public Worker( final ILinkedDataFragmentRequest request ) + { + this.request = request; + } + + /** + * Create the requested {@link ILinkedDataFragment} + * + * @return The ILinkedDataFragment + * @throws IllegalArgumentException + */ + abstract public ILinkedDataFragment createRequestedFragment() + throws IllegalArgumentException; + + } // end of class Worker + +} diff --git a/api/src/main/java/org/linkeddatafragments/datasource/AbstractRequestProcessorForTriplePatterns.java b/api/src/main/java/org/linkeddatafragments/datasource/AbstractRequestProcessorForTriplePatterns.java new file mode 100644 index 000000000..de8070b7d --- /dev/null +++ b/api/src/main/java/org/linkeddatafragments/datasource/AbstractRequestProcessorForTriplePatterns.java @@ -0,0 +1,158 @@ +package org.linkeddatafragments.datasource; + +import org.apache.jena.rdf.model.Model; +import org.linkeddatafragments.fragments.ILinkedDataFragment; +import org.linkeddatafragments.fragments.ILinkedDataFragmentRequest; +import org.linkeddatafragments.fragments.tpf.ITriplePatternElement; +import org.linkeddatafragments.fragments.tpf.ITriplePatternFragment; +import org.linkeddatafragments.fragments.tpf.ITriplePatternFragmentRequest; +import org.linkeddatafragments.fragments.tpf.TriplePatternFragmentImpl; + +/** + * Base class for implementations of {@link IFragmentRequestProcessor} that + * process {@link ITriplePatternFragmentRequest}s. + * + * @param + * type for representing constants in triple patterns (i.e., URIs and + * literals) + * @param + * type for representing named variables in triple patterns + * @param + * type for representing anonymous variables in triple patterns (i.e., + * variables denoted by a blank node) + * + * @author Olaf Hartig + */ +public abstract class + AbstractRequestProcessorForTriplePatterns + extends AbstractRequestProcessor +{ + + /** + * + * @param request + * @return + * @throws IllegalArgumentException + */ + @Override + protected final Worker getWorker( + final ILinkedDataFragmentRequest request ) + throws IllegalArgumentException + { + if ( request instanceof ITriplePatternFragmentRequest) { + @SuppressWarnings("unchecked") + final ITriplePatternFragmentRequest tpfRequest = + (ITriplePatternFragmentRequest) request; + return getTPFSpecificWorker( tpfRequest ); + } + else + throw new IllegalArgumentException( request.getClass().getName() ); + } + + /** + * + * @param request + * @return + * @throws IllegalArgumentException + */ + abstract protected Worker getTPFSpecificWorker( + final ITriplePatternFragmentRequest request ) + throws IllegalArgumentException; + + /** + * + * @param + * @param + * @param + */ + abstract static protected class Worker + extends AbstractRequestProcessor.Worker + { + + /** + * + * @param request + */ + public Worker( + final ITriplePatternFragmentRequest request ) + { + super( request ); + } + + /** + * + * @return + * @throws IllegalArgumentException + */ + @Override + public ILinkedDataFragment createRequestedFragment() + throws IllegalArgumentException + { + final long limit = ILinkedDataFragmentRequest.TRIPLESPERPAGE; + final long offset; + if ( request.isPageRequest() ) + offset = limit * ( request.getPageNumber() - 1L ); + else + offset = 0L; + + @SuppressWarnings("unchecked") + final ITriplePatternFragmentRequest tpfRequest = + (ITriplePatternFragmentRequest) request; + + return createFragment( tpfRequest.getSubject(), + tpfRequest.getPredicate(), + tpfRequest.getObject(), + offset, limit ); + } + + /** + * + * @param subj + * @param pred + * @param obj + * @param offset + * @param limit + * @return + * @throws IllegalArgumentException + */ + abstract protected ILinkedDataFragment createFragment( + final ITriplePatternElement subj, + final ITriplePatternElement pred, + final ITriplePatternElement obj, + final long offset, + final long limit ) + throws IllegalArgumentException; + + /** + * + * @return + */ + protected ITriplePatternFragment createEmptyTriplePatternFragment() + { + return new TriplePatternFragmentImpl( request.getFragmentURL(), + request.getDatasetURL() ); + } + + /** + * + * @param triples + * @param totalSize + * @param isLastPage + * @return + */ + protected ITriplePatternFragment createTriplePatternFragment( + final Model triples, + final long totalSize, + final boolean isLastPage ) + { + return new TriplePatternFragmentImpl( triples, + totalSize, + request.getFragmentURL(), + request.getDatasetURL(), + request.getPageNumber(), + isLastPage ); + } + + } // end of class Worker + +} diff --git a/api/src/main/java/org/linkeddatafragments/datasource/DataSourceBase.java b/api/src/main/java/org/linkeddatafragments/datasource/DataSourceBase.java new file mode 100644 index 000000000..45b669f6a --- /dev/null +++ b/api/src/main/java/org/linkeddatafragments/datasource/DataSourceBase.java @@ -0,0 +1,54 @@ +package org.linkeddatafragments.datasource; + +/** + * The base class for an {@link IDataSource} + * + * @author Miel Vander Sande + * @author Bart Hanssens + */ +public abstract class DataSourceBase implements IDataSource { + + /** + * Get the datasource title + */ + protected String title; + + /** + * Get the datasource description + */ + protected String description; + + /** + * Create a base for a {@link IDataSource} + * + * @param title the datasource title + * @param description the datasource description + */ + public DataSourceBase(String title, String description) { + this.title = title; + this.description = description; + } + + /** + * Get the datasource description + * + * @return + */ + @Override + public String getDescription() { + return this.description; + }; + + /** + * Get the datasource title + * + * @return + */ + @Override + public String getTitle() { + return this.title; + }; + + @Override + public void close() {} +} diff --git a/api/src/main/java/org/linkeddatafragments/datasource/DataSourceFactory.java b/api/src/main/java/org/linkeddatafragments/datasource/DataSourceFactory.java new file mode 100644 index 000000000..d23741d54 --- /dev/null +++ b/api/src/main/java/org/linkeddatafragments/datasource/DataSourceFactory.java @@ -0,0 +1,35 @@ +package org.linkeddatafragments.datasource; + +import com.google.gson.JsonObject; +import org.linkeddatafragments.exceptions.DataSourceCreationException; +import org.linkeddatafragments.exceptions.UnknownDataSourceTypeException; + +/** + * + * @author Miel Vander Sande + * @author Bart Hanssens + * @author Olaf Hartig + */ +public class DataSourceFactory { + /** + * Create a datasource using a JSON config + * + * @param config + * @return datasource interface + * @throws DataSourceCreationException + */ + public static IDataSource create(JsonObject config) throws DataSourceCreationException { + String title = config.getAsJsonPrimitive("title").getAsString(); + String description = config.getAsJsonPrimitive("description").getAsString(); + String typeName = config.getAsJsonPrimitive("type").getAsString(); + + JsonObject settings = config.getAsJsonObject("settings"); + + final IDataSourceType type = DataSourceTypesRegistry.getType(typeName); + if ( type == null ) + throw new UnknownDataSourceTypeException(typeName); + + return type.createDataSource( title, description, settings ); + } + +} diff --git a/api/src/main/java/org/linkeddatafragments/datasource/DataSourceTypesRegistry.java b/api/src/main/java/org/linkeddatafragments/datasource/DataSourceTypesRegistry.java new file mode 100644 index 000000000..f502c6f69 --- /dev/null +++ b/api/src/main/java/org/linkeddatafragments/datasource/DataSourceTypesRegistry.java @@ -0,0 +1,51 @@ +package org.linkeddatafragments.datasource; + +import java.util.HashMap; +import java.util.Map; + +/** + * A registry of {@link IDataSourceType}s. + * + * @author Olaf Hartig + */ +public class DataSourceTypesRegistry +{ + private static Map registry = + new HashMap(); + + /** + * + * @param typeName + * @return + */ + public static synchronized IDataSourceType getType( final String typeName ) + { + return registry.get( typeName ); + } + + /** + * + * @param typeName + * @return + */ + public static synchronized boolean isRegistered( final String typeName ) + { + return registry.containsKey( typeName ); + } + + /** + * + * @param typeName + * @param type + */ + public static synchronized void register( final String typeName, + final IDataSourceType type ) + { + if ( registry.containsKey(typeName) ) { + throw new IllegalArgumentException( "The registry already " + + "contains a type with the name '" + typeName + "'." ); + } + registry.put( typeName, type ); + } + +} diff --git a/api/src/main/java/org/linkeddatafragments/datasource/IDataSource.java b/api/src/main/java/org/linkeddatafragments/datasource/IDataSource.java new file mode 100644 index 000000000..971e18422 --- /dev/null +++ b/api/src/main/java/org/linkeddatafragments/datasource/IDataSource.java @@ -0,0 +1,38 @@ +package org.linkeddatafragments.datasource; + +import org.linkeddatafragments.fragments.IFragmentRequestParser; + +import java.io.Closeable; + +/** + * A data source of Linked Data Fragments. + * + * @author Ruben Verborgh + * @author Olaf Hartig + */ +public interface IDataSource extends Closeable { + + /** + * + * @return + */ + public String getTitle(); + + /** + * + * @return + */ + public String getDescription(); + + /** + * Returns a data source specific {@link IFragmentRequestParser}. + * @return + */ + IFragmentRequestParser getRequestParser(); + + /** + * Returns a data source specific {@link IFragmentRequestProcessor}. + * @return + */ + IFragmentRequestProcessor getRequestProcessor(); +} diff --git a/api/src/main/java/org/linkeddatafragments/datasource/IDataSourceType.java b/api/src/main/java/org/linkeddatafragments/datasource/IDataSourceType.java new file mode 100644 index 000000000..b9a19f760 --- /dev/null +++ b/api/src/main/java/org/linkeddatafragments/datasource/IDataSourceType.java @@ -0,0 +1,33 @@ +package org.linkeddatafragments.datasource; + +import com.google.gson.JsonObject; +import org.linkeddatafragments.exceptions.DataSourceCreationException; + +/** + * Represents types of {@link IDataSource}s that can be used to provide some + * Linked Data Fragments interface. + * + * @author Olaf Hartig + */ +public interface IDataSourceType +{ + /** + * Creates a data source of this type. + * + * @param title + * The title of the data source (as given in the config file). + * + * @param description + * The description of the data source (as given in the config file). + * + * @param settings + * The properties of the data source to be created; usually, these + * properties are given in the config file of the LDF server. + * @return + * @throws org.linkeddatafragments.exceptions.DataSourceCreationException + */ + IDataSource createDataSource(final String title, + final String description, + final JsonObject settings) + throws DataSourceCreationException; +} diff --git a/api/src/main/java/org/linkeddatafragments/datasource/IFragmentRequestProcessor.java b/api/src/main/java/org/linkeddatafragments/datasource/IFragmentRequestProcessor.java new file mode 100644 index 000000000..b3f48bef1 --- /dev/null +++ b/api/src/main/java/org/linkeddatafragments/datasource/IFragmentRequestProcessor.java @@ -0,0 +1,26 @@ +package org.linkeddatafragments.datasource; + +import org.linkeddatafragments.fragments.ILinkedDataFragment; +import org.linkeddatafragments.fragments.ILinkedDataFragmentRequest; + +import java.io.Closeable; + +/** + * Processes {@link ILinkedDataFragmentRequest}s and returns + * the requested {@link ILinkedDataFragment}s. + * + * @author Olaf Hartig + */ +public interface IFragmentRequestProcessor extends Closeable +{ + + /** + * + * @param request + * @return + * @throws IllegalArgumentException + */ + ILinkedDataFragment createRequestedFragment( + final ILinkedDataFragmentRequest request) + throws IllegalArgumentException; +} diff --git a/api/src/main/java/org/linkeddatafragments/datasource/index/IndexDataSource.java b/api/src/main/java/org/linkeddatafragments/datasource/index/IndexDataSource.java new file mode 100644 index 000000000..90536702e --- /dev/null +++ b/api/src/main/java/org/linkeddatafragments/datasource/index/IndexDataSource.java @@ -0,0 +1,47 @@ +package org.linkeddatafragments.datasource.index; + +import org.linkeddatafragments.datasource.DataSourceBase; +import org.linkeddatafragments.datasource.IDataSource; +import org.linkeddatafragments.datasource.IFragmentRequestProcessor; +import org.linkeddatafragments.fragments.IFragmentRequestParser; +import org.linkeddatafragments.fragments.tpf.TPFRequestParserForJenaBackends; + +import java.util.HashMap; + +/** + * An Index data source provides an overview of all available datasets. + * + * @author Miel Vander Sande + * @author Olaf Hartig + */ +public class IndexDataSource extends DataSourceBase { + + /** + * The request processor + * + */ + protected final IndexRequestProcessorForTPFs requestProcessor; + + /** + * + * @param baseUrl + * @param datasources + */ + public IndexDataSource(String baseUrl, HashMap datasources) { + super("Index", "List of all datasources"); + requestProcessor = new IndexRequestProcessorForTPFs( baseUrl, datasources ); + } + + @Override + public IFragmentRequestParser getRequestParser() + { + return TPFRequestParserForJenaBackends.getInstance(); + } + + @Override + public IFragmentRequestProcessor getRequestProcessor() + { + return requestProcessor; + } + +} diff --git a/api/src/main/java/org/linkeddatafragments/datasource/index/IndexRequestProcessorForTPFs.java b/api/src/main/java/org/linkeddatafragments/datasource/index/IndexRequestProcessorForTPFs.java new file mode 100644 index 000000000..35e632ab1 --- /dev/null +++ b/api/src/main/java/org/linkeddatafragments/datasource/index/IndexRequestProcessorForTPFs.java @@ -0,0 +1,146 @@ +package org.linkeddatafragments.datasource.index; + + +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.ModelFactory; +import org.apache.jena.rdf.model.Property; +import org.apache.jena.rdf.model.RDFNode; +import org.apache.jena.rdf.model.Resource; +import org.apache.jena.rdf.model.ResourceFactory; +import org.apache.jena.rdf.model.StmtIterator; +import org.apache.jena.rdf.model.impl.PropertyImpl; +import org.apache.jena.rdf.model.impl.ResourceImpl; +import org.linkeddatafragments.datasource.AbstractRequestProcessorForTriplePatterns; +import org.linkeddatafragments.datasource.IDataSource; +import org.linkeddatafragments.datasource.IFragmentRequestProcessor; +import org.linkeddatafragments.fragments.ILinkedDataFragment; +import org.linkeddatafragments.fragments.tpf.ITriplePatternElement; +import org.linkeddatafragments.fragments.tpf.ITriplePatternFragmentRequest; + +import java.util.HashMap; +import java.util.Map; + +/** + * Implementation of {@link IFragmentRequestProcessor} that processes + * {@link ITriplePatternFragmentRequest}s over an index that provides + * an overview of all available datasets. + * + * @author Miel Vander Sande + * @author Olaf Hartig + */ +public class IndexRequestProcessorForTPFs + extends AbstractRequestProcessorForTriplePatterns +{ + final static String RDF = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"; + final static String RDFS = "http://www.w3.org/2000/01/rdf-schema#"; + final static String DC = "http://purl.org/dc/terms/"; + final static String VOID = "http://rdfs.org/ns/void#"; + + private final Model model; + + /** + * + * @param baseUrl + * @param datasources + */ + public IndexRequestProcessorForTPFs( + final String baseUrl, + final HashMap datasources ) + { + this.model = ModelFactory.createDefaultModel(); + + for (Map.Entry entry : datasources.entrySet()) { + String datasourceName = entry.getKey(); + IDataSource datasource = entry.getValue(); + + Resource datasourceUrl = new ResourceImpl(baseUrl + "/" + datasourceName); + + model.add(datasourceUrl, new PropertyImpl(RDF + "type"), VOID + "Dataset"); + model.add(datasourceUrl, new PropertyImpl(RDFS + "label"), datasource.getTitle()); + model.add(datasourceUrl, new PropertyImpl(DC + "title"), datasource.getTitle()); + model.add(datasourceUrl, new PropertyImpl(DC + "description"), datasource.getDescription()); + } + } + + /** + * + * @param request + * @return + * @throws IllegalArgumentException + */ + @Override + protected Worker getTPFSpecificWorker( + final ITriplePatternFragmentRequest request ) + throws IllegalArgumentException + { + return new Worker( request ); + } + + /** + * Worker for the index + */ + protected class Worker + extends AbstractRequestProcessorForTriplePatterns.Worker + { + + /** + * Creates a Worker for the datasource index + * + * @param req + */ + public Worker( + final ITriplePatternFragmentRequest req ) + { + super( req ); + } + + /** + * + * @param s + * @param p + * @param o + * @param offset + * @param limit + * @return + */ + @Override + protected ILinkedDataFragment createFragment( + final ITriplePatternElement s, + final ITriplePatternElement p, + final ITriplePatternElement o, + final long offset, + final long limit ) + { + // FIXME: The following algorithm is incorrect for cases in which + // the requested triple pattern contains a specific variable + // multiple times; + // e.g., (?x foaf:knows ?x ) or (_:bn foaf:knows _:bn) + // see https://github.com/LinkedDataFragments/Server.Java/issues/25 + + final Resource subject = s.isVariable() ? null + : s.asConstantTerm().asResource(); + final Property predicate = p.isVariable() ? null + : ResourceFactory.createProperty(p.asConstantTerm().asResource().getURI()); + final RDFNode object = o.isVariable() ? null + : o.asConstantTerm(); + + StmtIterator listStatements = model.listStatements(subject, predicate, object); + Model result = ModelFactory.createDefaultModel(); + + long index = 0; + while (listStatements.hasNext() && index < offset) { + listStatements.next(); + index++; + } + + while (listStatements.hasNext() && index < (offset + limit)) { + result.add(listStatements.next()); + } + + final boolean isLastPage = ( result.size() < offset + limit ); + return createTriplePatternFragment( result, result.size(), isLastPage ); + } + + } // end of class Worker + +} diff --git a/api/src/main/java/org/linkeddatafragments/datasource/tdb/JenaTDBBasedRequestProcessorForTPFs.java b/api/src/main/java/org/linkeddatafragments/datasource/tdb/JenaTDBBasedRequestProcessorForTPFs.java new file mode 100644 index 000000000..804d9482c --- /dev/null +++ b/api/src/main/java/org/linkeddatafragments/datasource/tdb/JenaTDBBasedRequestProcessorForTPFs.java @@ -0,0 +1,165 @@ +package org.linkeddatafragments.datasource.tdb; + +import org.apache.jena.query.Dataset; +import org.apache.jena.query.Query; +import org.apache.jena.query.QueryExecution; +import org.apache.jena.query.QueryExecutionFactory; +import org.apache.jena.query.QueryFactory; +import org.apache.jena.query.QuerySolution; +import org.apache.jena.query.QuerySolutionMap; +import org.apache.jena.query.ResultSet; +import org.apache.jena.query.Syntax; +import org.apache.jena.rdf.model.Literal; +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.ModelFactory; +import org.apache.jena.rdf.model.RDFNode; +import org.apache.jena.tdb.TDBFactory; +import org.linkeddatafragments.datasource.AbstractRequestProcessorForTriplePatterns; +import org.linkeddatafragments.datasource.IFragmentRequestProcessor; +import org.linkeddatafragments.fragments.ILinkedDataFragment; +import org.linkeddatafragments.fragments.tpf.ITriplePatternElement; +import org.linkeddatafragments.fragments.tpf.ITriplePatternFragmentRequest; + +import java.io.File; + +/** + * Implementation of {@link IFragmentRequestProcessor} that processes + * {@link ITriplePatternFragmentRequest}s over data stored in Jena TDB. + * + * @author Bart Hanssens + * @author Olaf Hartig + */ +public class JenaTDBBasedRequestProcessorForTPFs + extends AbstractRequestProcessorForTriplePatterns +{ + private final Dataset tdb; + private final String sparql = "CONSTRUCT WHERE { ?s ?p ?o } " + + "ORDER BY ?s ?p ?o"; + + private final String count = "SELECT (COUNT(?s) AS ?count) WHERE { ?s ?p ?o }"; + + private final Query query = QueryFactory.create(sparql, Syntax.syntaxSPARQL_11); + private final Query countQuery = QueryFactory.create(count, Syntax.syntaxSPARQL_11); + + /** + * + * @param request + * @return + * @throws IllegalArgumentException + */ + @Override + protected Worker getTPFSpecificWorker( + final ITriplePatternFragmentRequest request ) + throws IllegalArgumentException + { + return new Worker( request ); + } + + /** + * + */ + protected class Worker + extends AbstractRequestProcessorForTriplePatterns.Worker + { + + /** + * + * @param req + */ + public Worker( + final ITriplePatternFragmentRequest req ) + { + super( req ); + } + + /** + * + * @param subject + * @param predicate + * @param object + * @param offset + * @param limit + * @return + */ + @Override + protected ILinkedDataFragment createFragment( + final ITriplePatternElement subject, + final ITriplePatternElement predicate, + final ITriplePatternElement object, + final long offset, + final long limit ) + { + // FIXME: The following algorithm is incorrect for cases in which + // the requested triple pattern contains a specific variable + // multiple times; + // e.g., (?x foaf:knows ?x ) or (_:bn foaf:knows _:bn) + // see https://github.com/LinkedDataFragments/Server.Java/issues/24 + + Model model = tdb.getDefaultModel(); + QuerySolutionMap map = new QuerySolutionMap(); + if ( ! subject.isVariable() ) { + map.add("s", subject.asConstantTerm()); + } + if ( ! predicate.isVariable() ) { + map.add("p", predicate.asConstantTerm()); + } + if ( ! object.isVariable() ) { + map.add("o", object.asConstantTerm()); + } + + query.setOffset(offset); + query.setLimit(limit); + + Model triples = ModelFactory.createDefaultModel(); + + try (QueryExecution qexec = QueryExecutionFactory.create(query, model, map)) { + qexec.execConstruct(triples); + } + + if (triples.isEmpty()) { + return createEmptyTriplePatternFragment(); + } + + // Try to get an estimate + long size = triples.size(); + long estimate = -1; + + try (QueryExecution qexec = QueryExecutionFactory.create(countQuery, model, map)) { + ResultSet results = qexec.execSelect(); + if (results.hasNext()) { + QuerySolution soln = results.nextSolution() ; + Literal literal = soln.getLiteral("count"); + estimate = literal.getLong(); + } + } + + /*GraphStatisticsHandler stats = model.getGraph().getStatisticsHandler(); + if (stats != null) { + Node s = (subject != null) ? subject.asNode() : null; + Node p = (predicate != null) ? predicate.asNode() : null; + Node o = (object != null) ? object.asNode() : null; + estimate = stats.getStatistic(s, p, o); + }*/ + + // No estimate or incorrect + if (estimate < offset + size) { + estimate = (size == limit) ? offset + size + 1 : offset + size; + } + + // create the fragment + final boolean isLastPage = ( estimate < offset + limit ); + return createTriplePatternFragment( triples, estimate, isLastPage ); + } + + } // end of class Worker + + + /** + * Constructor + * + * @param tdbdir directory used for TDB backing + */ + public JenaTDBBasedRequestProcessorForTPFs(File tdbdir) { + this.tdb = TDBFactory.createDataset(tdbdir.getAbsolutePath()); + } +} diff --git a/api/src/main/java/org/linkeddatafragments/datasource/tdb/JenaTDBDataSource.java b/api/src/main/java/org/linkeddatafragments/datasource/tdb/JenaTDBDataSource.java new file mode 100644 index 000000000..58e35b3ae --- /dev/null +++ b/api/src/main/java/org/linkeddatafragments/datasource/tdb/JenaTDBDataSource.java @@ -0,0 +1,47 @@ +package org.linkeddatafragments.datasource.tdb; + +import org.linkeddatafragments.datasource.DataSourceBase; +import org.linkeddatafragments.datasource.IFragmentRequestProcessor; +import org.linkeddatafragments.fragments.IFragmentRequestParser; +import org.linkeddatafragments.fragments.tpf.TPFRequestParserForJenaBackends; + +import java.io.File; + +/** + * Experimental Jena TDB-backed data source of Basic Linked Data Fragments. + * + * @author Bart Hanssens + * @author Olaf Hartig + */ +public class JenaTDBDataSource extends DataSourceBase { + + /** + * The request processor + * + */ + protected final JenaTDBBasedRequestProcessorForTPFs requestProcessor; + + @Override + public IFragmentRequestParser getRequestParser() + { + return TPFRequestParserForJenaBackends.getInstance(); + } + + @Override + public IFragmentRequestProcessor getRequestProcessor() + { + return requestProcessor; + } + + /** + * Constructor + * + * @param title + * @param description + * @param tdbdir directory used for TDB backing + */ + public JenaTDBDataSource(String title, String description, File tdbdir) { + super(title, description); + requestProcessor = new JenaTDBBasedRequestProcessorForTPFs( tdbdir ); + } +} diff --git a/api/src/main/java/org/linkeddatafragments/datasource/tdb/JenaTDBDataSourceType.java b/api/src/main/java/org/linkeddatafragments/datasource/tdb/JenaTDBDataSourceType.java new file mode 100644 index 000000000..bbebca71f --- /dev/null +++ b/api/src/main/java/org/linkeddatafragments/datasource/tdb/JenaTDBDataSourceType.java @@ -0,0 +1,34 @@ +package org.linkeddatafragments.datasource.tdb; + +import com.google.gson.JsonObject; +import org.linkeddatafragments.datasource.IDataSource; +import org.linkeddatafragments.datasource.IDataSourceType; +import org.linkeddatafragments.exceptions.DataSourceCreationException; + +import java.io.File; + +/** + * The type of Triple Pattern Fragment data sources that are backed by + * a Jena TDB instance. + * + * @author Olaf Hartig + */ +public class JenaTDBDataSourceType implements IDataSourceType +{ + @Override + public IDataSource createDataSource( final String title, + final String description, + final JsonObject settings ) + throws DataSourceCreationException + { + final String dname = settings.getAsJsonPrimitive("directory").getAsString(); + final File dir = new File( dname ); + + try { + return new JenaTDBDataSource(title, description, dir); + } catch (Exception ex) { + throw new DataSourceCreationException(ex); + } + } + +} diff --git a/api/src/main/java/org/linkeddatafragments/exceptions/DataSourceCreationException.java b/api/src/main/java/org/linkeddatafragments/exceptions/DataSourceCreationException.java new file mode 100644 index 000000000..ea4924ecf --- /dev/null +++ b/api/src/main/java/org/linkeddatafragments/exceptions/DataSourceCreationException.java @@ -0,0 +1,25 @@ +package org.linkeddatafragments.exceptions; + +/** + * + * @author Miel Vander Sande + */ +public class DataSourceCreationException extends DataSourceException { + + /** + * + * @param cause + */ + public DataSourceCreationException(Throwable cause) { + super(cause); + } + + /** + * + * @param datasourceName + * @param message + */ + public DataSourceCreationException(String datasourceName, String message) { + super(datasourceName, "Could not create DataSource - " + message); + } +} diff --git a/api/src/main/java/org/linkeddatafragments/exceptions/DataSourceException.java b/api/src/main/java/org/linkeddatafragments/exceptions/DataSourceException.java new file mode 100644 index 000000000..2f5973de7 --- /dev/null +++ b/api/src/main/java/org/linkeddatafragments/exceptions/DataSourceException.java @@ -0,0 +1,37 @@ +package org.linkeddatafragments.exceptions; + +import org.linkeddatafragments.datasource.IDataSource; + +/** + * + * @author Miel Vander Sande + */ +abstract public class DataSourceException extends Exception { + + /** + * + * @param cause + */ + public DataSourceException(Throwable cause) { + super(cause); + } + + /** + * + * @param datasourceName + * @param message + */ + public DataSourceException(String datasourceName, String message) { + super("Error for datasource '" + datasourceName + "': " + message); + } + + /** + * + * @param datasource + * @param message + */ + public DataSourceException(IDataSource datasource, String message) { + this(datasource.getTitle(), message); + } + +} diff --git a/api/src/main/java/org/linkeddatafragments/exceptions/DataSourceNotFoundException.java b/api/src/main/java/org/linkeddatafragments/exceptions/DataSourceNotFoundException.java new file mode 100644 index 000000000..08dca003c --- /dev/null +++ b/api/src/main/java/org/linkeddatafragments/exceptions/DataSourceNotFoundException.java @@ -0,0 +1,16 @@ +package org.linkeddatafragments.exceptions; + +/** + * + * @author Miel Vander Sande + */ +public class DataSourceNotFoundException extends DataSourceException { + + /** + * + * @param dataSourceName + */ + public DataSourceNotFoundException(String dataSourceName) { + super(dataSourceName, "Datasource not found."); + } +} diff --git a/api/src/main/java/org/linkeddatafragments/exceptions/NoRegisteredMimeTypesException.java b/api/src/main/java/org/linkeddatafragments/exceptions/NoRegisteredMimeTypesException.java new file mode 100644 index 000000000..ad278a64c --- /dev/null +++ b/api/src/main/java/org/linkeddatafragments/exceptions/NoRegisteredMimeTypesException.java @@ -0,0 +1,17 @@ +package org.linkeddatafragments.exceptions; + +/** + * Exception thrown when no mimeTypes are known to the system + * + * @author Miel Vander Sande + */ +public class NoRegisteredMimeTypesException extends Exception { + + /** + * Constructs the exception + */ + public NoRegisteredMimeTypesException() { + super("List of supported mimeTypes is empty."); + } + +} diff --git a/api/src/main/java/org/linkeddatafragments/exceptions/UnknownDataSourceTypeException.java b/api/src/main/java/org/linkeddatafragments/exceptions/UnknownDataSourceTypeException.java new file mode 100644 index 000000000..1b631a09d --- /dev/null +++ b/api/src/main/java/org/linkeddatafragments/exceptions/UnknownDataSourceTypeException.java @@ -0,0 +1,16 @@ +package org.linkeddatafragments.exceptions; + +/** + * + * @author Miel Vander Sande + */ +public class UnknownDataSourceTypeException extends DataSourceCreationException { + + /** + * + * @param type + */ + public UnknownDataSourceTypeException(String type) { + super("", "Type " + type + " does not exist."); + } +} diff --git a/api/src/main/java/org/linkeddatafragments/fragments/FragmentRequestParserBase.java b/api/src/main/java/org/linkeddatafragments/fragments/FragmentRequestParserBase.java new file mode 100644 index 000000000..7d6c8b8c0 --- /dev/null +++ b/api/src/main/java/org/linkeddatafragments/fragments/FragmentRequestParserBase.java @@ -0,0 +1,141 @@ +package org.linkeddatafragments.fragments; + +import org.linkeddatafragments.config.ConfigReader; + +import javax.servlet.http.HttpServletRequest; + +/** + * Base class for implementations of {@link IFragmentRequestParser}. + * + * @author Olaf Hartig + */ +abstract public class FragmentRequestParserBase implements IFragmentRequestParser +{ + @Override + final public ILinkedDataFragmentRequest parseIntoFragmentRequest( + final HttpServletRequest httpRequest, + final ConfigReader config ) + throws IllegalArgumentException + { + return getWorker( httpRequest, config ).createFragmentRequest(); + } + + /** + * + * @param httpRequest + * @param config + * @return + * @throws IllegalArgumentException + */ + abstract protected Worker getWorker( final HttpServletRequest httpRequest, + final ConfigReader config ) + throws IllegalArgumentException; + + /** + * + */ + abstract static protected class Worker + { + + /** + * + */ + public final HttpServletRequest request; + + /** + * + */ + public final ConfigReader config; + + /** + * + */ + public final boolean pageNumberWasRequested; + + /** + * + */ + public final long pageNumber; + + /** + * + * @param request + * @param config + */ + public Worker( final HttpServletRequest request, + final ConfigReader config ) + { + this.request = request; + this.config = config; + + final String givenPageNumber = request.getParameter( + ILinkedDataFragmentRequest.PARAMETERNAME_PAGE ); + if ( givenPageNumber != null ) { + long pageNumber; + try { + pageNumber = Long.parseLong( givenPageNumber ); + } catch (NumberFormatException ex) { + pageNumber = 1L; + } + this.pageNumber = ( pageNumber > 0 ) ? pageNumber : 1L; + this.pageNumberWasRequested = true; + } + else { + this.pageNumber = 1L; + this.pageNumberWasRequested = false; + } + } + + /** + * + * @return + * @throws IllegalArgumentException + */ + abstract public ILinkedDataFragmentRequest createFragmentRequest() + throws IllegalArgumentException; + + /** + * + * @return + */ + public String getFragmentURL() { + final String datasetURL = getDatasetURL(); + final String query = request.getQueryString(); + return query == null ? datasetURL : (datasetURL + "?" + query); + } + + /** + * + * @return + */ + public String getDatasetURL() { + return extractBaseURL( request, config ) + request.getRequestURI(); + } + + } // end of class Worker + + + // ----- HELPERS --------- + + /** + * + * @param request + * @param config + * @return + */ + + public static String extractBaseURL( final HttpServletRequest request, + final ConfigReader config ) { + if (config.getBaseURL() != null) { + return config.getBaseURL(); + } else if ((request.getServerPort() == 80) + || (request.getServerPort() == 443)) { + return request.getScheme() + "://" + + request.getServerName(); + } else { + return request.getScheme() + "://" + + request.getServerName() + ":" + request.getServerPort(); + } + } + +} diff --git a/api/src/main/java/org/linkeddatafragments/fragments/IFragmentRequestParser.java b/api/src/main/java/org/linkeddatafragments/fragments/IFragmentRequestParser.java new file mode 100644 index 000000000..113621076 --- /dev/null +++ b/api/src/main/java/org/linkeddatafragments/fragments/IFragmentRequestParser.java @@ -0,0 +1,29 @@ +package org.linkeddatafragments.fragments; + +import org.linkeddatafragments.config.ConfigReader; + +import javax.servlet.http.HttpServletRequest; + +/** + * Parses HTTP requests into specific {@link ILinkedDataFragmentRequest}s. + * + * @author Olaf Hartig + */ +public interface IFragmentRequestParser +{ + /** + * Parses the given HTTP request into a specific + * {@link ILinkedDataFragmentRequest}. + * + * @param httpRequest + * @param config + * @return + * @throws IllegalArgumentException + * If the given HTTP request cannot be interpreted (perhaps due to + * missing request parameters). + */ + ILinkedDataFragmentRequest parseIntoFragmentRequest( + final HttpServletRequest httpRequest, + final ConfigReader config) + throws IllegalArgumentException; +} diff --git a/api/src/main/java/org/linkeddatafragments/fragments/ILinkedDataFragment.java b/api/src/main/java/org/linkeddatafragments/fragments/ILinkedDataFragment.java new file mode 100644 index 000000000..5fa14aa98 --- /dev/null +++ b/api/src/main/java/org/linkeddatafragments/fragments/ILinkedDataFragment.java @@ -0,0 +1,79 @@ +package org.linkeddatafragments.fragments; + +import org.apache.jena.rdf.model.StmtIterator; + +import java.io.Closeable; + +/** + * Represents any possible Linked Data Fragment. + * + * @author Olaf Hartig + */ +public interface ILinkedDataFragment extends Closeable +{ + /** + * Returns an iterator over the RDF data of this fragment (possibly only + * partial if the data is paged, as indicated by {@link #isPageOnly()}). + * @return + */ + StmtIterator getTriples(); + + /** + * Returns true if {@link #getTriples()} returns a page of data only. + * In this case, {@link #getPageNumber()} can be used to obtain the + * corresponding page number. + * @return + */ + boolean isPageOnly(); + + /** + * Returns the number of the page of data returned by {@link #getTriples()} + * if the data is paged (that is, if {@link #isPageOnly()} returns true). + * + * If the data is not paged, this method throws an exception. + * + * @return + * @throws UnsupportedOperationException + * If the data of this fragment is not paged. + */ + long getPageNumber() throws UnsupportedOperationException; + + /** + * Returns true if {@link #getTriples()} returns a page of data only and + * this is the last page of the fragment. + * + * If the data is not paged (i.e., if {@link #isPageOnly()} returns false), + * this method throws an exception. + * + * @return + * @throws UnsupportedOperationException + * If the data of this fragment is not paged. + */ + boolean isLastPage() throws UnsupportedOperationException; + + /** + * Returns the maximum number of triples per page if {@link #getTriples()} + * returns a page of data only (that is, if {@link #isPageOnly()} returns + * true). + * + * If the data is not paged, this method throws an exception. + * + * @return + * @throws UnsupportedOperationException + * If the data of this fragment is not paged. + */ + long getMaxPageSize() throws UnsupportedOperationException; + + /** + * Returns an iterator over the metadata of this fragment. + * @return + */ + StmtIterator getMetadata(); + + /** + * Returns an iterator over an RDF description of the controls associated + * with this fragment. + * @return + */ + StmtIterator getControls(); +} diff --git a/api/src/main/java/org/linkeddatafragments/fragments/ILinkedDataFragmentRequest.java b/api/src/main/java/org/linkeddatafragments/fragments/ILinkedDataFragmentRequest.java new file mode 100644 index 000000000..ed9aa5df5 --- /dev/null +++ b/api/src/main/java/org/linkeddatafragments/fragments/ILinkedDataFragmentRequest.java @@ -0,0 +1,48 @@ +package org.linkeddatafragments.fragments; + +/** + * Basis for representing a request of some type of Linked Data Fragment (LDF). + * + * @author Olaf Hartig + */ +public interface ILinkedDataFragmentRequest +{ + + /** + * + */ + public final static long TRIPLESPERPAGE = 100L; + + /** + * + */ + public final static String PARAMETERNAME_PAGE = "page"; + + /** + * Returns the URL of the requested LDF. + * @return + */ + String getFragmentURL(); + + /** + * Returns the URL of the dataset to which the requested LDF belongs. + * @return + */ + String getDatasetURL(); + + /** + * Returns true if the request is for a specific page of the requested + * fragment. In this case, {@link #getPageNumber()} can be used to obtain + * the requested page number. + * @return + */ + boolean isPageRequest(); + + /** + * Returns the number of the page requested for the LDF; if this is not a + * page-based request (that is, if {@link #isPageRequest()} returns true), + * then this method returns 1. + * @return + */ + long getPageNumber(); +} diff --git a/api/src/main/java/org/linkeddatafragments/fragments/LinkedDataFragmentBase.java b/api/src/main/java/org/linkeddatafragments/fragments/LinkedDataFragmentBase.java new file mode 100644 index 000000000..9ac16bd9b --- /dev/null +++ b/api/src/main/java/org/linkeddatafragments/fragments/LinkedDataFragmentBase.java @@ -0,0 +1,189 @@ +package org.linkeddatafragments.fragments; + +import org.apache.http.client.utils.URIBuilder; +import org.apache.jena.rdf.model.Literal; +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.ModelFactory; +import org.apache.jena.rdf.model.Resource; +import org.apache.jena.rdf.model.StmtIterator; +import org.linkeddatafragments.util.CommonResources; + +import java.net.URISyntaxException; + + +/** + * Base class of any implementation of {@link ILinkedDataFragment} that uses + * paging. + * + * @author Olaf Hartig + */ +public abstract class LinkedDataFragmentBase implements ILinkedDataFragment +{ + + /** + * + */ + public final String fragmentURL; + + /** + * + */ + public final String datasetURL; + + /** + * + */ + public final long pageNumber; + + /** + * + */ + public final boolean isLastPage; + + /** + * + * @param fragmentURL + * @param datasetURL + * @param pageNumber + * @param isLastPage + */ + protected LinkedDataFragmentBase( final String fragmentURL, + final String datasetURL, + final long pageNumber, + final boolean isLastPage ) + { + this.fragmentURL = fragmentURL; + this.datasetURL = datasetURL; + this.pageNumber = pageNumber; + this.isLastPage = isLastPage; + } + + /** + * Does nothing. May be overridden by subclasses that hold some objects + * that need to be closed (such as iterators from the underlying data + * source). + */ + @Override + public void close() {} + + @Override + public boolean isPageOnly() { + return true; + } + + @Override + public long getPageNumber() { + return pageNumber; + } + + @Override + public boolean isLastPage() { + return isLastPage; + } + + @Override + public long getMaxPageSize() { + return ILinkedDataFragmentRequest.TRIPLESPERPAGE; + } + + /** + * This implementation uses {@link #addMetadata(Model)}, which should be + * overridden in subclasses (instead of overriding this method). + * @return + */ + @Override + public StmtIterator getMetadata() + { + final Model output = ModelFactory.createDefaultModel(); + addMetadata( output ); + return output.listStatements(); + } + + /** + * This implementation uses {@link #addControls(Model)}, which should be + * overridden in subclasses (instead of overriding this method). + * @return + */ + @Override + public StmtIterator getControls() + { + final Model output = ModelFactory.createDefaultModel(); + addControls( output ); + return output.listStatements(); + } + + /** + * Adds some basic metadata to the given RDF model. + * This method may be overridden in subclasses. + * @param model + */ + public void addMetadata( final Model model ) + { + final Resource datasetId = model.createResource( getDatasetURI() ); + final Resource fragmentId = model.createResource( fragmentURL ); + + datasetId.addProperty( CommonResources.RDF_TYPE, CommonResources.VOID_DATASET ); + datasetId.addProperty( CommonResources.RDF_TYPE, CommonResources.HYDRA_COLLECTION ); + datasetId.addProperty( CommonResources.VOID_SUBSET, fragmentId ); + + Literal itemsPerPage = model.createTypedLiteral(this.getMaxPageSize()); + datasetId.addProperty( CommonResources.HYDRA_ITEMSPERPAGE, itemsPerPage); + + fragmentId.addProperty( CommonResources.RDF_TYPE, CommonResources.HYDRA_COLLECTION ); + fragmentId.addProperty( CommonResources.RDF_TYPE, CommonResources.HYDRA_PAGEDCOLLECTION ); + } + + /** + * Adds an RDF description of page links to the given RDF model. + * This method may be overridden in subclasses. + * @param model + */ + public void addControls( final Model model ) + { + final URIBuilder pagedURL; + try { + pagedURL = new URIBuilder( fragmentURL ); + } + catch ( URISyntaxException e ) { + throw new IllegalArgumentException( e ); + } + + final Resource fragmentId = model.createResource( fragmentURL ); + + final Resource firstPageId = + model.createResource( + pagedURL.setParameter(ILinkedDataFragmentRequest.PARAMETERNAME_PAGE, + "1").toString() ); + + fragmentId.addProperty( CommonResources.HYDRA_FIRSTPAGE, firstPageId ); + + if ( pageNumber > 1) { + final String prevPageNumber = Long.toString( pageNumber - 1 ); + final Resource prevPageId = + model.createResource( + pagedURL.setParameter(ILinkedDataFragmentRequest.PARAMETERNAME_PAGE, + prevPageNumber).toString() ); + + fragmentId.addProperty( CommonResources.HYDRA_PREVIOUSPAGE, prevPageId ); + } + + if ( ! isLastPage ) { + final String nextPageNumber = Long.toString( pageNumber + 1 ); + final Resource nextPageId = + model.createResource( + pagedURL.setParameter(ILinkedDataFragmentRequest.PARAMETERNAME_PAGE, + nextPageNumber).toString() ); + + fragmentId.addProperty( CommonResources.HYDRA_NEXTPAGE, nextPageId ); + } + } + + /** + * + * @return + */ + public String getDatasetURI() { + return datasetURL + "#dataset"; + } + +} diff --git a/api/src/main/java/org/linkeddatafragments/fragments/LinkedDataFragmentRequestBase.java b/api/src/main/java/org/linkeddatafragments/fragments/LinkedDataFragmentRequestBase.java new file mode 100644 index 000000000..c53ae5a45 --- /dev/null +++ b/api/src/main/java/org/linkeddatafragments/fragments/LinkedDataFragmentRequestBase.java @@ -0,0 +1,81 @@ +package org.linkeddatafragments.fragments; + +/** + * Base class for implementations of {@link ILinkedDataFragmentRequest}. + * + * @author Olaf Hartig + */ +public abstract class LinkedDataFragmentRequestBase + implements ILinkedDataFragmentRequest +{ + + /** + * + */ + public final String fragmentURL; + + /** + * + */ + public final String datasetURL; + + /** + * + */ + public final boolean pageNumberWasRequested; + + /** + * + */ + public final long pageNumber; + + /** + * + * @param fragmentURL + * @param datasetURL + * @param pageNumberWasRequested + * @param pageNumber + */ + public LinkedDataFragmentRequestBase( final String fragmentURL, + final String datasetURL, + final boolean pageNumberWasRequested, + final long pageNumber ) + { + this.fragmentURL = fragmentURL; + this.datasetURL = datasetURL; + this.pageNumberWasRequested = pageNumberWasRequested; + this.pageNumber = (pageNumberWasRequested) ? pageNumber : 1L; + } + + @Override + public String getFragmentURL() { + return fragmentURL; + } + + @Override + public String getDatasetURL() { + return datasetURL; + } + + @Override + public boolean isPageRequest() { + return pageNumberWasRequested; + } + + @Override + public long getPageNumber() { + return pageNumber; + } + + @Override + public String toString() + { + return "LinkedDataFragmentRequest(" + + "class: " + getClass().getName() + + ", fragmentURL: " + fragmentURL + + ", isPageRequest: " + pageNumberWasRequested + + ", pageNumber: " + pageNumber + + ")"; + } + +} diff --git a/api/src/main/java/org/linkeddatafragments/fragments/tpf/ITriplePatternElement.java b/api/src/main/java/org/linkeddatafragments/fragments/tpf/ITriplePatternElement.java new file mode 100644 index 000000000..6c6d928aa --- /dev/null +++ b/api/src/main/java/org/linkeddatafragments/fragments/tpf/ITriplePatternElement.java @@ -0,0 +1,89 @@ +package org.linkeddatafragments.fragments.tpf; + +/** + * Represents an element of a triple pattern (i.e., subject, predicate, object). + * + * @param type for representing constants in triple patterns + * (i.e., URIs and literals) + * @param type for representing named variables in triple patterns + * @param type for representing anonymous variables in triple + * patterns (i.e., variables denoted by a blank node) + * + * @author Olaf Hartig + */ +public interface ITriplePatternElement +{ + /** + * Returns true if this element is a variable (specific or unspecified). + * @return + */ + boolean isVariable(); + + /** + * Returns true if this element is a specific variable, and false if either + * it is not a variable (but a URI or literal) or it is some variable that + * is not specified. The latter (unspecified variables) is possible because + * when a client requests a triple pattern fragment, it may omit triple + * pattern related parameters. + * @return + */ + boolean isSpecificVariable(); + + /** + * Returns true if this element is a specific variable that has a name + * (i.e., it is denoted by a string that begins with a question mark), + * and false if either it is not a specific variable or it is a specific + * variable that is denoted by a blank node. + * + * If this element is a specific variable that has a name (that is, this + * method returns true), the named variable can be obtained by the method + * {@link #asNamedVariable()}. + * @return + */ + boolean isNamedVariable(); + + /** + * Returns a representation of this element as a named variable (assuming + * it is a specific variable that has a name). + * + * @return + * @throws UnsupportedOperationException + * If this element is not a specific variable that has a name + * (i.e., if {@link #isNamedVariable()} returns false). + */ + NamedVarType asNamedVariable() throws UnsupportedOperationException; + + /** + * Returns true if this element is a specific variable that does not have + * a name (i.e., it is denoted by a blank node), and false if either it is + * not a specific variable or it is a specific variable that has a name. + * + * If this element is a specific variable denoted by a blank node (that is, + * this method returns true), the blank node can be obtained by the method + * {@link #asAnonymousVariable()}. + * @return + */ + boolean isAnonymousVariable(); + + /** + * Returns a representation of this element as a blank node (assuming + * it is a specific, but non-named variable). + * + * @return + * @throws UnsupportedOperationException + * If this element is not a specific anonymous variable (i.e., + * if {@link #isAnonymousVariable()} returns false). + */ + AnonVarType asAnonymousVariable() throws UnsupportedOperationException; + + /** + * Returns a representation of this element as a constant RDF term (i.e., + * a URI or a literal). + * + * @return + * @throws UnsupportedOperationException + * If this element is not a constant RDF term but a variable + * (i.e., if {@link #isVariable()} returns true). + */ + ConstantTermType asConstantTerm() throws UnsupportedOperationException; +} diff --git a/api/src/main/java/org/linkeddatafragments/fragments/tpf/ITriplePatternFragment.java b/api/src/main/java/org/linkeddatafragments/fragments/tpf/ITriplePatternFragment.java new file mode 100644 index 000000000..9f51b34a7 --- /dev/null +++ b/api/src/main/java/org/linkeddatafragments/fragments/tpf/ITriplePatternFragment.java @@ -0,0 +1,15 @@ +package org.linkeddatafragments.fragments.tpf; + +import org.linkeddatafragments.fragments.ILinkedDataFragment; + +/** + * A Triple Pattern Fragment. + * @author Ruben Verborgh + */ +public interface ITriplePatternFragment extends ILinkedDataFragment { + /** + * Gets the total number of triples in the fragment (can be an estimate). + * @return the total number of triples + */ + public long getTotalSize(); +} diff --git a/api/src/main/java/org/linkeddatafragments/fragments/tpf/ITriplePatternFragmentRequest.java b/api/src/main/java/org/linkeddatafragments/fragments/tpf/ITriplePatternFragmentRequest.java new file mode 100644 index 000000000..ae6d15107 --- /dev/null +++ b/api/src/main/java/org/linkeddatafragments/fragments/tpf/ITriplePatternFragmentRequest.java @@ -0,0 +1,52 @@ +package org.linkeddatafragments.fragments.tpf; + +import org.linkeddatafragments.fragments.ILinkedDataFragmentRequest; + +/** + * Represents a request of a Triple Pattern Fragment (TPF). + * + * @param type for representing constants in triple patterns + * (i.e., URIs and literals) + * @param type for representing named variables in triple patterns + * @param type for representing anonymous variables in triple + * patterns (i.e., variables denoted by a blank node) + * + * @author Olaf Hartig + */ +public interface ITriplePatternFragmentRequest + extends ILinkedDataFragmentRequest +{ + + /** + * + */ + public final static String PARAMETERNAME_SUBJ = "subject"; + + /** + * + */ + public final static String PARAMETERNAME_PRED = "predicate"; + + /** + * + */ + public final static String PARAMETERNAME_OBJ = "object"; + + /** + * Returns the subject position of the requested triple pattern. + * @return + */ + ITriplePatternElement getSubject(); + + /** + * Returns the predicate position of the requested triple pattern. + * @return + */ + ITriplePatternElement getPredicate(); + + /** + * Returns the object position of the requested triple pattern. + * @return + */ + ITriplePatternElement getObject(); +} diff --git a/api/src/main/java/org/linkeddatafragments/fragments/tpf/TPFRequestParser.java b/api/src/main/java/org/linkeddatafragments/fragments/tpf/TPFRequestParser.java new file mode 100644 index 000000000..55270f251 --- /dev/null +++ b/api/src/main/java/org/linkeddatafragments/fragments/tpf/TPFRequestParser.java @@ -0,0 +1,127 @@ +package org.linkeddatafragments.fragments.tpf; + +import org.linkeddatafragments.config.ConfigReader; +import org.linkeddatafragments.fragments.FragmentRequestParserBase; +import org.linkeddatafragments.fragments.IFragmentRequestParser; +import org.linkeddatafragments.fragments.ILinkedDataFragmentRequest; +import org.linkeddatafragments.util.TriplePatternElementParser; + +import javax.servlet.http.HttpServletRequest; + +/** + * An {@link IFragmentRequestParser} for {@link ITriplePatternFragmentRequest}s. + * + * @param + * @param + * + * @author Olaf Hartig + * @param + */ +public class TPFRequestParser + extends FragmentRequestParserBase +{ + public final TriplePatternElementParser elmtParser; + + /** + * + * @param elmtParser + */ + public TPFRequestParser( + final TriplePatternElementParser elmtParser ) + { + this.elmtParser = elmtParser; + } + + /** + * + * @param httpRequest + * @param config + * @return + * @throws IllegalArgumentException + */ + @Override + protected Worker getWorker( final HttpServletRequest httpRequest, + final ConfigReader config ) + throws IllegalArgumentException + { + return new Worker( httpRequest, config ); + } + + /** + * + */ + protected class Worker extends FragmentRequestParserBase.Worker + { + + /** + * + * @param request + * @param config + */ + public Worker( final HttpServletRequest request, + final ConfigReader config ) + { + super( request, config ); + } + + /** + * + * @return + * @throws IllegalArgumentException + */ + @Override + public ILinkedDataFragmentRequest createFragmentRequest() + throws IllegalArgumentException + { + return new TriplePatternFragmentRequestImpl( + getFragmentURL(), + getDatasetURL(), + pageNumberWasRequested, + pageNumber, + getSubject(), + getPredicate(), + getObject() ); + } + + /** + * + * @return + */ + public ITriplePatternElement getSubject() { + return getParameterAsTriplePatternElement( + ITriplePatternFragmentRequest.PARAMETERNAME_SUBJ ); + } + + /** + * + * @return + */ + public ITriplePatternElement getPredicate() { + return getParameterAsTriplePatternElement( + ITriplePatternFragmentRequest.PARAMETERNAME_PRED ); + } + + /** + * + * @return + */ + public ITriplePatternElement getObject() { + return getParameterAsTriplePatternElement( + ITriplePatternFragmentRequest.PARAMETERNAME_OBJ ); + } + + /** + * + * @param paramName + * @return + */ + public ITriplePatternElement + getParameterAsTriplePatternElement( final String paramName ) + { + final String parameter = request.getParameter( paramName ); + return elmtParser.parseIntoTriplePatternElement( parameter ); + } + + } // end of class Worker + +} diff --git a/api/src/main/java/org/linkeddatafragments/fragments/tpf/TPFRequestParserForJenaBackends.java b/api/src/main/java/org/linkeddatafragments/fragments/tpf/TPFRequestParserForJenaBackends.java new file mode 100644 index 000000000..cbd38b9a3 --- /dev/null +++ b/api/src/main/java/org/linkeddatafragments/fragments/tpf/TPFRequestParserForJenaBackends.java @@ -0,0 +1,35 @@ +package org.linkeddatafragments.fragments.tpf; + +import org.apache.jena.rdf.model.RDFNode; +import org.linkeddatafragments.util.TriplePatternElementParserForJena; + +/** + * An {@link TPFRequestParser} for Jena-based backends. + * + * @author Olaf Hartig + */ +public class TPFRequestParserForJenaBackends + extends TPFRequestParser +{ + private static TPFRequestParserForJenaBackends instance = null; + + /** + * + * @return + */ + public static TPFRequestParserForJenaBackends getInstance() + { + if ( instance == null ) { + instance = new TPFRequestParserForJenaBackends(); + } + return instance; + } + + /** + * + */ + protected TPFRequestParserForJenaBackends() + { + super( TriplePatternElementParserForJena.getInstance() ); + } +} diff --git a/api/src/main/java/org/linkeddatafragments/fragments/tpf/TriplePatternElementFactory.java b/api/src/main/java/org/linkeddatafragments/fragments/tpf/TriplePatternElementFactory.java new file mode 100644 index 000000000..3537bdf59 --- /dev/null +++ b/api/src/main/java/org/linkeddatafragments/fragments/tpf/TriplePatternElementFactory.java @@ -0,0 +1,214 @@ +package org.linkeddatafragments.fragments.tpf; + +/** + * A factory for {@link ITriplePatternElement}s. + * + * @param + * type for representing constants in triple patterns (i.e., URIs and + * literals) + * @param + * type for representing named variables in triple patterns + * @param + * type for representing anonymous variables in triple patterns (i.e., + * variables denoted by a blank node) + * + * @author Olaf Hartig + */ +public class TriplePatternElementFactory +{ + + /** + * + * @return + */ + public ITriplePatternElement createUnspecifiedVariable() + { + return new UnspecifiedVariable(); + } + + /** + * + * @param v + * @return + */ + public ITriplePatternElement createNamedVariable(final NVT v ) + { + return new NamedVariable( v ); + } + + /** + * + * @param bnode + * @return + */ + public ITriplePatternElement createAnonymousVariable( + final AVT bnode ) + { + return new AnonymousVariable( bnode ); + } + + /** + * + * @param term + * @return + */ + public ITriplePatternElement createConstantRDFTerm( + final CTT term ) + { + return new ConstantRDFTerm( term ); + } + + /** + * + * @param + * @param + * @param + */ + static abstract public class Variable + implements ITriplePatternElement + { + @Override + public boolean isVariable() { return true; } + @Override + public CTT asConstantTerm() { throw new UnsupportedOperationException(); } + } + + /** + * + * @param + * @param + * @param + */ + static public class UnspecifiedVariable + extends Variable + { + @Override + public boolean isSpecificVariable() { return false; } + @Override + public boolean isNamedVariable() { return false; } + @Override + public NVT asNamedVariable() { throw new UnsupportedOperationException(); } + @Override + public boolean isAnonymousVariable() { return false; } + @Override + public AVT asAnonymousVariable() { throw new UnsupportedOperationException(); } + @Override + public String toString() { return "UnspecifiedVariable"; } + } + + /** + * + * @param + * @param + * @param + */ + static abstract public class SpecificVariable + extends Variable + { + @Override + public boolean isSpecificVariable() { return true; } + } + + /** + * + * @param + * @param + * @param + */ + static public class NamedVariable + extends SpecificVariable + { + + /** + * + */ + protected final NVT v; + + /** + * + * @param variable + */ + public NamedVariable( final NVT variable ) { v = variable; } + @Override + public boolean isNamedVariable() { return true; } + @Override + public NVT asNamedVariable() { return v; } + @Override + public boolean isAnonymousVariable() { return false; } + @Override + public AVT asAnonymousVariable() { throw new UnsupportedOperationException(); } + @Override + public String toString() { return "NamedVariable(" + v.toString() + ")"; } + } + + /** + * + * @param + * @param + * @param + */ + static public class AnonymousVariable + extends SpecificVariable + { + + /** + * + */ + protected final AVT bn; + + /** + * + * @param bnode + */ + public AnonymousVariable( final AVT bnode ) { bn = bnode; } + @Override + public boolean isNamedVariable() { return false; } + @Override + public NVT asNamedVariable() { throw new UnsupportedOperationException(); } + @Override + public boolean isAnonymousVariable() { return true; } + @Override + public AVT asAnonymousVariable() { return bn; } + @Override + public String toString() { return "AnonymousVariable(" + bn.toString() + ")"; } + } + + /** + * + * @param + * @param + * @param + */ + static public class ConstantRDFTerm + implements ITriplePatternElement + { + + /** + * + */ + protected final CTT t; + + /** + * + * @param term + */ + public ConstantRDFTerm( final CTT term ) { t = term; } + @Override + public boolean isVariable() { return false; } + @Override + public boolean isSpecificVariable() { return false; } + @Override + public boolean isNamedVariable() { return false; } + @Override + public NVT asNamedVariable() { throw new UnsupportedOperationException(); } + @Override + public boolean isAnonymousVariable() { return false; } + @Override + public AVT asAnonymousVariable() { throw new UnsupportedOperationException(); } + @Override + public CTT asConstantTerm() { return t; } + @Override + public String toString() { return "ConstantRDFTerm(" + t.toString() + ")(type: " + t.getClass().getSimpleName() + ")"; } + } + +} diff --git a/api/src/main/java/org/linkeddatafragments/fragments/tpf/TriplePatternFragmentBase.java b/api/src/main/java/org/linkeddatafragments/fragments/tpf/TriplePatternFragmentBase.java new file mode 100644 index 000000000..132e8ed98 --- /dev/null +++ b/api/src/main/java/org/linkeddatafragments/fragments/tpf/TriplePatternFragmentBase.java @@ -0,0 +1,164 @@ +package org.linkeddatafragments.fragments.tpf; + +import org.apache.jena.datatypes.xsd.XSDDatatype; +import org.apache.jena.rdf.model.Literal; +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.Resource; +import org.apache.jena.rdf.model.Statement; +import org.apache.jena.rdf.model.StmtIterator; +import org.apache.jena.util.iterator.NiceIterator; +import org.linkeddatafragments.fragments.LinkedDataFragmentBase; +import org.linkeddatafragments.util.CommonResources; + +import java.util.NoSuchElementException; + + +/** + * Base class for implementations of {@link ITriplePatternFragment}. + * + * @author Ruben Verborgh + * @author Olaf Hartig + */ +abstract public class TriplePatternFragmentBase extends LinkedDataFragmentBase + implements ITriplePatternFragment +{ + private final long totalSize; + + /** + * Creates an empty Triple Pattern Fragment. + * @param fragmentURL + * @param datasetURL + */ + public TriplePatternFragmentBase( final String fragmentURL, + final String datasetURL ) { + this( 0L, fragmentURL, datasetURL, 1, true ); + } + + /** + * Creates an empty Triple Pattern Fragment page. + * @param fragmentURL + * @param isLastPage + * @param datasetURL + * @param pageNumber + */ + public TriplePatternFragmentBase( final String fragmentURL, + final String datasetURL, + final long pageNumber, + final boolean isLastPage ) { + this( 0L, fragmentURL, datasetURL, pageNumber, isLastPage ); + } + + /** + * Creates a new Triple Pattern Fragment. + * @param totalSize the total size + * @param fragmentURL + * @param datasetURL + * @param pageNumber + * @param isLastPage + */ + public TriplePatternFragmentBase( long totalSize, + final String fragmentURL, + final String datasetURL, + final long pageNumber, + final boolean isLastPage ) { + super( fragmentURL, datasetURL, pageNumber, isLastPage ); + this.totalSize = totalSize < 0L ? 0L : totalSize; + } + + @Override + public StmtIterator getTriples() { + if ( totalSize == 0L ) + return emptyStmtIterator; + else + return getNonEmptyStmtIterator(); + } + + /** + * + * @return + */ + abstract protected StmtIterator getNonEmptyStmtIterator(); + + @Override + public long getTotalSize() { + return totalSize; + } + + @Override + public void addMetadata( final Model model ) + { + super.addMetadata( model ); + + final Resource fragmentId = model.createResource( fragmentURL ); + + final Literal totalTyped = model.createTypedLiteral( totalSize, + XSDDatatype.XSDinteger ); + final Literal limitTyped = model.createTypedLiteral( getMaxPageSize(), + XSDDatatype.XSDinteger ); + + fragmentId.addLiteral( CommonResources.VOID_TRIPLES, totalTyped ); + fragmentId.addLiteral( CommonResources.HYDRA_TOTALITEMS, totalTyped ); + fragmentId.addLiteral( CommonResources.HYDRA_ITEMSPERPAGE, limitTyped ); + } + + @Override + public void addControls( final Model model ) + { + super.addControls( model ); + + final Resource datasetId = model.createResource( getDatasetURI() ); + + final Resource triplePattern = model.createResource(); + final Resource subjectMapping = model.createResource(); + final Resource predicateMapping = model.createResource(); + final Resource objectMapping = model.createResource(); + + datasetId.addProperty( CommonResources.HYDRA_SEARCH, triplePattern ); + + triplePattern.addProperty( CommonResources.HYDRA_TEMPLATE, getTemplate() ); + triplePattern.addProperty( CommonResources.HYDRA_MAPPING, subjectMapping ); + triplePattern.addProperty( CommonResources.HYDRA_MAPPING, predicateMapping ); + triplePattern.addProperty( CommonResources.HYDRA_MAPPING, objectMapping ); + + subjectMapping.addProperty( CommonResources.HYDRA_VARIABLE, ITriplePatternFragmentRequest.PARAMETERNAME_SUBJ ); + subjectMapping.addProperty( CommonResources.HYDRA_PROPERTY, CommonResources.RDF_SUBJECT ); + + predicateMapping.addProperty( CommonResources.HYDRA_VARIABLE, ITriplePatternFragmentRequest.PARAMETERNAME_PRED ); + predicateMapping.addProperty( CommonResources.HYDRA_PROPERTY, CommonResources.RDF_PREDICATE ); + + objectMapping.addProperty( CommonResources.HYDRA_VARIABLE, ITriplePatternFragmentRequest.PARAMETERNAME_OBJ ); + objectMapping.addProperty( CommonResources.HYDRA_PROPERTY, CommonResources.RDF_OBJECT ); + } + + /** + * + * @return + */ + public String getTemplate() { + return datasetURL + "{?" + + ITriplePatternFragmentRequest.PARAMETERNAME_SUBJ + "," + + ITriplePatternFragmentRequest.PARAMETERNAME_PRED + "," + + ITriplePatternFragmentRequest.PARAMETERNAME_OBJ + "}"; + } + + /** + * + */ + public static final StmtIterator emptyStmtIterator = new EmptyStmtIterator(); + + /** + * + */ + public static class EmptyStmtIterator + extends NiceIterator + implements StmtIterator + { + + /** + * + * @return + */ + public Statement nextStatement() { throw new NoSuchElementException(); } + } + +} diff --git a/api/src/main/java/org/linkeddatafragments/fragments/tpf/TriplePatternFragmentImpl.java b/api/src/main/java/org/linkeddatafragments/fragments/tpf/TriplePatternFragmentImpl.java new file mode 100644 index 000000000..3c78d4b52 --- /dev/null +++ b/api/src/main/java/org/linkeddatafragments/fragments/tpf/TriplePatternFragmentImpl.java @@ -0,0 +1,72 @@ +package org.linkeddatafragments.fragments.tpf; + +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.StmtIterator; + + +/** + * Implementation of {@link ITriplePatternFragment}. + * + * @author Olaf Hartig + */ +public class TriplePatternFragmentImpl extends TriplePatternFragmentBase +{ + + /** + * + */ + protected final Model triples; + + /** + * Creates an empty Triple Pattern Fragment. + * @param fragmentURL + * @param datasetURL + */ + public TriplePatternFragmentImpl( final String fragmentURL, + final String datasetURL ) { + this( null, 0L, fragmentURL, datasetURL, 1, true ); + } + + /** + * Creates an empty Triple Pattern Fragment page. + * @param fragmentURL + * @param datasetURL + * @param isLastPage + * @param pageNumber + */ + public TriplePatternFragmentImpl( final String fragmentURL, + final String datasetURL, + final long pageNumber, + final boolean isLastPage ) { + this( null, 0L, fragmentURL, datasetURL, pageNumber, isLastPage ); + } + + /** + * Creates a new Triple Pattern Fragment. + * @param triples the triples (possibly partial) + * @param totalSize the total size + * @param fragmentURL + * @param datasetURL + * @param isLastPage + * @param pageNumber + */ + public TriplePatternFragmentImpl( final Model triples, + long totalSize, + final String fragmentURL, + final String datasetURL, + final long pageNumber, + final boolean isLastPage ) { + super( totalSize, fragmentURL, datasetURL, pageNumber, isLastPage ); + this.triples = triples; + } + + /** + * + * @return + */ + @Override + protected StmtIterator getNonEmptyStmtIterator() { + return triples.listStatements(); + } + +} diff --git a/api/src/main/java/org/linkeddatafragments/fragments/tpf/TriplePatternFragmentRequestImpl.java b/api/src/main/java/org/linkeddatafragments/fragments/tpf/TriplePatternFragmentRequestImpl.java new file mode 100644 index 000000000..59424630b --- /dev/null +++ b/api/src/main/java/org/linkeddatafragments/fragments/tpf/TriplePatternFragmentRequestImpl.java @@ -0,0 +1,96 @@ +package org.linkeddatafragments.fragments.tpf; + +import org.linkeddatafragments.fragments.LinkedDataFragmentRequestBase; + +/** + * An implementation of {@link ITriplePatternFragmentRequest}. + * + * @author Olaf Hartig + * @param + * @param + * @param + */ +public class TriplePatternFragmentRequestImpl + extends LinkedDataFragmentRequestBase + implements ITriplePatternFragmentRequest +{ + + /** + * + */ + public final ITriplePatternElement subject; + + /** + * + */ + public final ITriplePatternElement predicate; + + /** + * + */ + public final ITriplePatternElement object; + + /** + * + * @param fragmentURL + * @param datasetURL + * @param pageNumberWasRequested + * @param pageNumber + * @param subject + * @param predicate + * @param object + */ + public TriplePatternFragmentRequestImpl( final String fragmentURL, + final String datasetURL, + final boolean pageNumberWasRequested, + final long pageNumber, + final ITriplePatternElement subject, + final ITriplePatternElement predicate, + final ITriplePatternElement object ) + { + super( fragmentURL, datasetURL, pageNumberWasRequested, pageNumber ); + + if ( subject == null ) + throw new IllegalArgumentException(); + + if ( predicate == null ) + throw new IllegalArgumentException(); + + if ( object == null ) + throw new IllegalArgumentException(); + + this.subject = subject; + this.predicate = predicate; + this.object = object; + } + + @Override + public ITriplePatternElement getSubject() { + return subject; + } + + @Override + public ITriplePatternElement getPredicate() { + return predicate; + } + + @Override + public ITriplePatternElement getObject() { + return object; + } + + @Override + public String toString() + { + return "TriplePatternFragmentRequest(" + + "class: " + getClass().getName() + + ", subject: " + subject.toString() + + ", predicate: " + predicate.toString() + + ", object: " + object.toString() + + ", fragmentURL: " + fragmentURL + + ", isPageRequest: " + pageNumberWasRequested + + ", pageNumber: " + pageNumber + + ")"; + } + +} diff --git a/api/src/main/java/org/linkeddatafragments/servlet/LinkedDataFragmentServlet.java b/api/src/main/java/org/linkeddatafragments/servlet/LinkedDataFragmentServlet.java new file mode 100644 index 000000000..881dd4fd5 --- /dev/null +++ b/api/src/main/java/org/linkeddatafragments/servlet/LinkedDataFragmentServlet.java @@ -0,0 +1,213 @@ +package org.linkeddatafragments.servlet; + +import com.google.gson.JsonObject; +import org.apache.jena.riot.Lang; +import org.linkeddatafragments.config.ConfigReader; +import org.linkeddatafragments.datasource.DataSourceFactory; +import org.linkeddatafragments.datasource.DataSourceTypesRegistry; +import org.linkeddatafragments.datasource.IDataSource; +import org.linkeddatafragments.datasource.IDataSourceType; +import org.linkeddatafragments.datasource.index.IndexDataSource; +import org.linkeddatafragments.exceptions.DataSourceNotFoundException; +import org.linkeddatafragments.fragments.FragmentRequestParserBase; +import org.linkeddatafragments.fragments.ILinkedDataFragment; +import org.linkeddatafragments.fragments.ILinkedDataFragmentRequest; +import org.linkeddatafragments.util.MIMEParse; +import org.linkeddatafragments.views.ILinkedDataFragmentWriter; +import org.linkeddatafragments.views.LinkedDataFragmentWriterFactory; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map.Entry; + +/** + * Servlet that responds with a Linked Data Fragment. + * + * @author Ruben Verborgh + * @author Bart Hanssens + * @author Olaf Hartig + */ +public class LinkedDataFragmentServlet extends HttpServlet { + + private final static long serialVersionUID = 1L; + + // Parameters + + /** + * + */ + public final static String CFGFILE = "configFile"; + + private ConfigReader config; + private final HashMap dataSources = new HashMap<>(); + private final Collection mimeTypes = new ArrayList<>(); + + private File getConfigFile(ServletConfig config) throws IOException { + String path = config.getServletContext().getRealPath("/"); + if (path == null) { + // this can happen when running standalone + path = System.getProperty("user.dir"); + } + File cfg = new File(path, "config-example.json"); + if (config.getInitParameter(CFGFILE) != null) { + cfg = new File(config.getInitParameter(CFGFILE)); + } + if (!cfg.exists()) { + throw new IOException("Configuration file " + cfg + " not found."); + } + if (!cfg.isFile()) { + throw new IOException("Configuration file " + cfg + " is not a file."); + } + return cfg; + } + + /** + * + * @param servletConfig + * @throws ServletException + */ + @Override + public void init(ServletConfig servletConfig) throws ServletException { + try { + // load the configuration + File configFile = getConfigFile(servletConfig); + config = new ConfigReader(new FileReader(configFile)); + + // register data source types + for ( Entry typeEntry : config.getDataSourceTypes().entrySet() ) { + DataSourceTypesRegistry.register( typeEntry.getKey(), + typeEntry.getValue() ); + } + + // register data sources + for (Entry dataSource : config.getDataSources().entrySet()) { + dataSources.put(dataSource.getKey(), DataSourceFactory.create(dataSource.getValue())); + } + + // register content types + MIMEParse.register("text/html"); + MIMEParse.register(Lang.TTL.getHeaderString()); + MIMEParse.register(Lang.JSONLD.getHeaderString()); + MIMEParse.register(Lang.NTRIPLES.getHeaderString()); + MIMEParse.register(Lang.RDFXML.getHeaderString()); + } catch (Exception e) { + throw new ServletException(e); + } + } + + /** + * + */ + @Override + public void destroy() + { + for ( IDataSource dataSource : dataSources.values() ) { + try { + dataSource.close(); + } + catch( Exception e ) { + // ignore + } + } + } + + /** + * Get the datasource + * + * @param request + * @return + * @throws IOException + */ + private IDataSource getDataSource(HttpServletRequest request) throws DataSourceNotFoundException { + String contextPath = request.getContextPath(); + String requestURI = request.getRequestURI(); + + String path = contextPath == null + ? requestURI + : requestURI.substring(contextPath.length()); + + if (path.equals("/") || path.isEmpty()) { + final String baseURL = FragmentRequestParserBase.extractBaseURL(request, config); + return new IndexDataSource(baseURL, dataSources); + } + + String dataSourceName = path.substring(1); + IDataSource dataSource = dataSources.get(dataSourceName); + if (dataSource == null) { + throw new DataSourceNotFoundException(dataSourceName); + } + return dataSource; + } + + /** + * + * @param request + * @param response + * @throws ServletException + */ + @Override + public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException { + ILinkedDataFragment fragment = null; + try { + // do conneg + String bestMatch = MIMEParse.bestMatch(request.getHeader("Accept")); + + // set additional response headers + response.setHeader("Server", "Linked Data Fragments Server"); + response.setContentType(bestMatch); + response.setCharacterEncoding("utf-8"); + + // create a writer depending on the best matching mimeType + ILinkedDataFragmentWriter writer = LinkedDataFragmentWriterFactory.create(config.getPrefixes(), dataSources, bestMatch); + + try { + + final IDataSource dataSource = getDataSource( request ); + + final ILinkedDataFragmentRequest ldfRequest = + dataSource.getRequestParser() + .parseIntoFragmentRequest( request, config ); + + fragment = dataSource.getRequestProcessor() + .createRequestedFragment( ldfRequest ); + + writer.writeFragment(response.getOutputStream(), dataSource, fragment, ldfRequest); + + } catch (DataSourceNotFoundException ex) { + try { + response.setStatus(404); + writer.writeNotFound(response.getOutputStream(), request); + } catch (Exception ex1) { + throw new ServletException(ex1); + } + } catch (Exception e) { + response.setStatus(500); + writer.writeError(response.getOutputStream(), e); + } + + } catch (Exception e) { + throw new ServletException(e); + } + finally { + // close the fragment + if ( fragment != null ) { + try { + fragment.close(); + } + catch ( Exception e ) { + // ignore + } + } + } + } + +} diff --git a/api/src/main/java/org/linkeddatafragments/util/CommonResources.java b/api/src/main/java/org/linkeddatafragments/util/CommonResources.java new file mode 100644 index 000000000..d5ca95f76 --- /dev/null +++ b/api/src/main/java/org/linkeddatafragments/util/CommonResources.java @@ -0,0 +1,139 @@ +package org.linkeddatafragments.util; + +import org.apache.jena.rdf.model.Property; +import org.apache.jena.rdf.model.ResourceFactory; + +/** + * + * @author mielvandersande + */ +@SuppressWarnings("javadoc") +/** + * All common URIs needed for parsing and serializations + */ +public class CommonResources { + + /** + * + */ + public final static String RDF = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"; + + /** + * + */ + public final static Property RDF_TYPE = createProperty(RDF + "type"); + + /** + * + */ + public final static Property RDF_SUBJECT = createProperty(RDF + "subject"); + + /** + * + */ + public final static Property RDF_PREDICATE = createProperty(RDF + "predicate"); + + /** + * + */ + public final static Property RDF_OBJECT = createProperty(RDF + "object"); + + /** + * + */ + public final static String VOID = "http://rdfs.org/ns/void#"; + + /** + * + */ + public final static Property VOID_TRIPLES = createProperty(VOID + "triples"); + + /** + * + */ + public final static Property VOID_SUBSET = createProperty(VOID + "subset"); + + /** + * + */ + public final static Property VOID_DATASET = createProperty(VOID + "Dataset"); + + /** + * + */ + public final static String HYDRA = "http://www.w3.org/ns/hydra/core#"; + + /** + * + */ + public final static Property HYDRA_TOTALITEMS = createProperty(HYDRA + "totalItems"); + + /** + * + */ + public final static Property HYDRA_ITEMSPERPAGE = createProperty(HYDRA + "itemsPerPage"); + + /** + * + */ + public final static Property HYDRA_SEARCH = createProperty(HYDRA + "search"); + + /** + * + */ + public final static Property HYDRA_TEMPLATE = createProperty(HYDRA + "template"); + + /** + * + */ + public final static Property HYDRA_MAPPING = createProperty(HYDRA + "mapping"); + + /** + * + */ + public final static Property HYDRA_VARIABLE = createProperty(HYDRA + "variable"); + + /** + * + */ + public final static Property HYDRA_PROPERTY = createProperty(HYDRA + "property"); + + /** + * + */ + public final static Property HYDRA_COLLECTION = createProperty(HYDRA + "Collection"); + + /** + * + */ + public final static Property HYDRA_PAGEDCOLLECTION = createProperty(HYDRA + "PagedCollection"); + + /** + * + */ + public final static Property HYDRA_FIRSTPAGE = createProperty(HYDRA + "firstPage"); + + /** + * + */ + public final static Property HYDRA_LASTPAGE = createProperty(HYDRA + "lastPage"); + + /** + * + */ + public final static Property HYDRA_NEXTPAGE = createProperty(HYDRA + "nextPage"); + + /** + * + */ + public final static Property HYDRA_PREVIOUSPAGE = createProperty(HYDRA + "previousPage"); + + /** + * + */ + public final static Property INVALID_URI = createProperty("urn:invalid"); + + private static Property createProperty(String uri) { + return ResourceFactory.createProperty(uri); + } +} diff --git a/api/src/main/java/org/linkeddatafragments/util/MIMEParse.java b/api/src/main/java/org/linkeddatafragments/util/MIMEParse.java new file mode 100644 index 000000000..c6c43f80b --- /dev/null +++ b/api/src/main/java/org/linkeddatafragments/util/MIMEParse.java @@ -0,0 +1,299 @@ +package org.linkeddatafragments.util; + +import org.apache.commons.lang.math.NumberUtils; +import org.apache.commons.lang3.StringUtils; +import org.linkeddatafragments.exceptions.NoRegisteredMimeTypesException; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +/** + * MIME-Type Parser + * + * This class provides basic functions for handling mime-types. It can handle + * matching mime-types against a list of media-ranges. See section 14.1 of the + * HTTP specification [RFC 2616] for a complete explanation. + * + * http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1 + * + * A port to Java of Joe Gregorio's MIME-Type Parser: + * + * http://code.google.com/p/mimeparse/ + * + * Ported by Tom Zellman. + * Extended by Miel Vander Sande + * + */ +public final class MIMEParse +{ + private final static List mimeTypes = new ArrayList<>(); + + /** + * Register mimeType in collection + * @param mimeType + */ + public static void register(String mimeType) { + mimeTypes.add(mimeType); + } + + + /** + * Parse results container + */ + protected static class ParseResults + { + String type; + + String subType; + + // !a dictionary of all the parameters for the media range + Map params; + + @Override + public String toString() + { + StringBuffer s = new StringBuffer("('" + type + "', '" + subType + + "', {"); + for (String k : params.keySet()) + s.append("'" + k + "':'" + params.get(k) + "',"); + return s.append("})").toString(); + } + } + + /** + * Carves up a mime-type and returns a ParseResults object + * + * For example, the media range 'application/xhtml;q=0.5' would get parsed + * into: + * + * ('application', 'xhtml', {'q', '0.5'}) + * @param mimeType + * @return + */ + protected static ParseResults parseMimeType(String mimeType) + { + String[] parts = StringUtils.split(mimeType, ";"); + ParseResults results = new ParseResults(); + results.params = new HashMap(); + + for (int i = 1; i < parts.length; ++i) + { + String p = parts[i]; + String[] subParts = StringUtils.split(p, '='); + if (subParts.length == 2) + results.params.put(subParts[0].trim(), subParts[1].trim()); + } + String fullType = parts[0].trim(); + + // Java URLConnection class sends an Accept header that includes a + // single "*" - Turn it into a legal wildcard. + if (fullType.equals("*")) + fullType = "*/*"; + String[] types = StringUtils.split(fullType, "/"); + results.type = types[0].trim(); + results.subType = types[1].trim(); + return results; + } + + /** + * Carves up a media range and returns a ParseResults. + * + * For example, the media range 'application/*;q=0.5' would get parsed into: + * + * ('application', '*', {'q', '0.5'}) + * + * In addition this function also guarantees that there is a value for 'q' + * in the params dictionary, filling it in with a proper default if + * necessary. + * + * @param range + * @return + */ + protected static ParseResults parseMediaRange(String range) + { + ParseResults results = parseMimeType(range); + String q = results.params.get("q"); + float f = NumberUtils.toFloat(q, 1); + if (StringUtils.isBlank(q) || f < 0 || f > 1) + results.params.put("q", "1"); + return results; + } + + /** + * Structure for holding a fitness/quality combo + */ + protected static class FitnessAndQuality implements + Comparable + { + int fitness; + + float quality; + + String mimeType; // optionally used + + /** + * + * @param fitness + * @param quality + */ + public FitnessAndQuality(int fitness, float quality) + { + this.fitness = fitness; + this.quality = quality; + } + + public int compareTo(FitnessAndQuality o) + { + if (fitness == o.fitness) + { + if (quality == o.quality) + return 0; + else + return quality < o.quality ? -1 : 1; + } + else + return fitness < o.fitness ? -1 : 1; + } + } + + /** + * Find the best match for a given mimeType against a list of media_ranges + * that have already been parsed by MimeParse.parseMediaRange(). Returns a + * tuple of the fitness value and the value of the 'q' quality parameter of + * the best match, or (-1, 0) if no match was found. Just as for + * quality_parsed(), 'parsed_ranges' must be a list of parsed media ranges. + * + * @param mimeType + * @param parsedRanges + * @return + */ + protected static FitnessAndQuality fitnessAndQualityParsed(String mimeType, + Collection parsedRanges) + { + int bestFitness = -1; + float bestFitQ = 0; + ParseResults target = parseMediaRange(mimeType); + + for (ParseResults range : parsedRanges) + { + if ((target.type.equals(range.type) || range.type.equals("*") || target.type + .equals("*")) + && (target.subType.equals(range.subType) + || range.subType.equals("*") || target.subType + .equals("*"))) + { + for (String k : target.params.keySet()) + { + int paramMatches = 0; + if (!k.equals("q") && range.params.containsKey(k) + && target.params.get(k).equals(range.params.get(k))) + { + paramMatches++; + } + int fitness = (range.type.equals(target.type)) ? 100 : 0; + fitness += (range.subType.equals(target.subType)) ? 10 : 0; + fitness += paramMatches; + if (fitness > bestFitness) + { + bestFitness = fitness; + bestFitQ = NumberUtils + .toFloat(range.params.get("q"), 0); + } + } + } + } + return new FitnessAndQuality(bestFitness, bestFitQ); + } + + /** + * Find the best match for a given mime-type against a list of ranges that + * have already been parsed by parseMediaRange(). Returns the 'q' quality + * parameter of the best match, 0 if no match was found. This function + * bahaves the same as quality() except that 'parsed_ranges' must be a list + * of parsed media ranges. + * + * @param mimeType + * @param parsedRanges + * @return + */ + protected static float qualityParsed(String mimeType, + Collection parsedRanges) + { + return fitnessAndQualityParsed(mimeType, parsedRanges).quality; + } + + /** + * Returns the quality 'q' of a mime-type when compared against the + * mediaRanges in ranges. For example: + * + * @param mimeType + * @param ranges + * @return + */ + public static float quality(String mimeType, String ranges) + { + List results = new LinkedList(); + for (String r : StringUtils.split(ranges, ',')) + results.add(parseMediaRange(r)); + return qualityParsed(mimeType, results); + } + + /** + * Takes a list of supported mime-types and finds the best match for all the + * media-ranges listed in header. The value of header must be a string that + * conforms to the format of the HTTP Accept: header. The value of + * 'supported' is a list of mime-types. + * + * MimeParse.bestMatch(Arrays.asList(new String[]{"application/xbel+xml", + * "text/xml"}), "text/*;q=0.5,*; q=0.1") 'text/xml' + * + * @param supported + * @param header + * @return + * @throws org.linkeddatafragments.exceptions.NoRegisteredMimeTypesException + */ + public static String bestMatch(List supported, String header) throws NoRegisteredMimeTypesException + { + if (supported.isEmpty()) + throw new NoRegisteredMimeTypesException(); + + List parseResults = new LinkedList(); + List weightedMatches = new LinkedList(); + for (String r : StringUtils.split(header, ',')) + parseResults.add(parseMediaRange(r)); + + for (String s : supported) + { + FitnessAndQuality fitnessAndQuality = fitnessAndQualityParsed(s, + parseResults); + fitnessAndQuality.mimeType = s; + weightedMatches.add(fitnessAndQuality); + } + Collections.sort(weightedMatches); + + FitnessAndQuality lastOne = weightedMatches + .get(weightedMatches.size() - 1); + return NumberUtils.compare(lastOne.quality, 0) != 0 ? lastOne.mimeType : supported.get(0); + } + + /** + * + * @param header + * @return + * @throws NoRegisteredMimeTypesException + */ + public static String bestMatch(String header) throws NoRegisteredMimeTypesException + { + return bestMatch(mimeTypes, header); + } + + // hidden + private MIMEParse() + { + } +} diff --git a/api/src/main/java/org/linkeddatafragments/util/RDFTermParser.java b/api/src/main/java/org/linkeddatafragments/util/RDFTermParser.java new file mode 100644 index 000000000..eafa401b5 --- /dev/null +++ b/api/src/main/java/org/linkeddatafragments/util/RDFTermParser.java @@ -0,0 +1,116 @@ +package org.linkeddatafragments.util; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Parses strings (as obtained from HTTP request parameters) into RDF terms. + * + * @param type for representing RDF terms + * + * @author Olaf Hartig + */ +abstract public class RDFTermParser +{ + + /** + * + */ + public static final Pattern STRINGPATTERN + = Pattern.compile("^\"(.*)\"(?:@(.*)|\\^\\^]*)>?)?$"); + + /** + * + * @param param + * @return + */ + public TermType parseIntoRDFNode( final String param ) + { + if ( param == null || param.isEmpty() ) + return handleUnparsableParameter( param ); + + // identify the kind of RDF term based on the first character + char firstChar = param.charAt(0); + switch ( firstChar ) + { + // blank node + case '_': + return createBlankNode( param ); + + // angular brackets indicate a URI + case '<': + return createURI( param.substring(1, param.length()-1) ); + + // quotes indicate a string + case '"': + Matcher matcher = STRINGPATTERN.matcher( param ); + if ( matcher.matches() ) { + String label = matcher.group(1); + String langTag = matcher.group(2); + String typeURI = matcher.group(3); + + if ( langTag != null ) + return createLanguageLiteral( label, langTag ); + + else if ( typeURI != null ) + return createTypedLiteral( label, typeURI ); + + else + return createPlainLiteral( label ); + } + else + return handleUnparsableParameter( param ); + + // assume it is a URI without angular brackets + default: + return createURI( param ); + } + } + + /** + * + * @param label + * @return + */ + abstract public TermType createBlankNode( final String label ); + + /** + * + * @param uri + * @return + */ + abstract public TermType createURI( final String uri ); + + /** + * + * @param label + * @param typeURI + * @return + */ + abstract public TermType createTypedLiteral( final String label, + final String typeURI ); + + /** + * + * @param label + * @param langTag + * @return + */ + abstract public TermType createLanguageLiteral( final String label, + final String langTag ); + + /** + * + * @param label + * @return + */ + abstract public TermType createPlainLiteral( final String label ); + + /** + * + * @param param + * @return + */ + abstract public TermType handleUnparsableParameter( final String param ); + +} diff --git a/api/src/main/java/org/linkeddatafragments/util/TriplePatternElementParser.java b/api/src/main/java/org/linkeddatafragments/util/TriplePatternElementParser.java new file mode 100644 index 000000000..9621bab09 --- /dev/null +++ b/api/src/main/java/org/linkeddatafragments/util/TriplePatternElementParser.java @@ -0,0 +1,80 @@ +package org.linkeddatafragments.util; + +import org.linkeddatafragments.fragments.tpf.ITriplePatternElement; +import org.linkeddatafragments.fragments.tpf.TriplePatternElementFactory; + +/** + * Parses strings (as obtained from HTTP request parameters) into + * {@link ITriplePatternElement}s. + * + * @param type for representing constants in triple patterns + * (i.e., URIs and literals) + * @param type for representing named variables in triple patterns + * @param type for representing anonymous variables in triple + * patterns (i.e., variables denoted by a blank node) + * + * @author Olaf Hartig + * @author Ruben Verborgh + */ +abstract public + class TriplePatternElementParser + extends RDFTermParser +{ + + /** + * + */ + public final TriplePatternElementFactory + factory = new TriplePatternElementFactory(); + + /** + * + * @param param + * @return + */ + public ITriplePatternElement + parseIntoTriplePatternElement( final String param ) + { + // nothing or empty indicates an unspecified variable + if ( param == null || param.isEmpty() ) + return factory.createUnspecifiedVariable(); + + // identify the kind of RDF term based on the first character + char firstChar = param.charAt(0); + switch ( firstChar ) + { + // specific variable that has a name + case '?': + { + final String varName = param.substring(1); + final NamedVarType var = createNamedVariable( varName ); + return factory.createNamedVariable( var ); + } + + // specific variable that is denoted by a blank node + case '_': + { + final AnonVarType var = createAnonymousVariable( param ); + return factory.createAnonymousVariable( var ); + } + + // assume it is an RDF term + default: + return factory.createConstantRDFTerm( parseIntoRDFNode(param) ); + } + } + + /** + * + * @param varName + * @return + */ + abstract public NamedVarType createNamedVariable( final String varName ); + + /** + * + * @param label + * @return + */ + abstract public AnonVarType createAnonymousVariable( final String label ); +} diff --git a/api/src/main/java/org/linkeddatafragments/util/TriplePatternElementParserForJena.java b/api/src/main/java/org/linkeddatafragments/util/TriplePatternElementParserForJena.java new file mode 100644 index 000000000..a54114d9b --- /dev/null +++ b/api/src/main/java/org/linkeddatafragments/util/TriplePatternElementParserForJena.java @@ -0,0 +1,128 @@ +package org.linkeddatafragments.util; + +import org.apache.jena.datatypes.RDFDatatype; +import org.apache.jena.datatypes.TypeMapper; +import org.apache.jena.rdf.model.RDFNode; +import org.apache.jena.rdf.model.ResourceFactory; + +/** + * A {@link TriplePatternElementParser} for Jena-based backends. + * + * @author Olaf Hartig + */ +public class TriplePatternElementParserForJena + extends TriplePatternElementParser +{ + private static TriplePatternElementParserForJena instance = null; + + /** + * + * @return + */ + public static TriplePatternElementParserForJena getInstance() + { + if ( instance == null ) { + instance = new TriplePatternElementParserForJena(); + } + return instance; + } + + /** + * + */ + protected TriplePatternElementParserForJena() {} + + /** + * + * @param varName + * @return + */ + @Override + public String createNamedVariable( final String varName ) + { + return varName; + } + + /** + * + * @param label + * @return + */ + @Override + public String createAnonymousVariable( final String label ) + { + return label; + } + + /** + * + * @param label + * @return + */ + @Override + public RDFNode createBlankNode(final String label ) + { + return ResourceFactory.createResource(); + } + + /** + * + * @param uri + * @return + */ + @Override + public RDFNode createURI(final String uri ) + { + return ResourceFactory.createResource( uri ); + } + + /** + * + * @param label + * @param typeURI + * @return + */ + @Override + public RDFNode createTypedLiteral(final String label, + final String typeURI ) + { + final RDFDatatype dt = TypeMapper.getInstance() + .getSafeTypeByName( typeURI ); + return ResourceFactory.createTypedLiteral( label, dt ); + } + + /** + * + * @param label + * @param languageTag + * @return + */ + @Override + public RDFNode createLanguageLiteral(final String label, + final String languageTag ) + { + return ResourceFactory.createLangLiteral( label, languageTag ); + } + + /** + * + * @param label + * @return + */ + @Override + public RDFNode createPlainLiteral(final String label ) + { + return ResourceFactory.createPlainLiteral( label ); + } + + /** + * + * @param parameter + * @return + */ + @Override + public RDFNode handleUnparsableParameter(final String parameter ) + { + return CommonResources.INVALID_URI; + } +} diff --git a/api/src/main/java/org/linkeddatafragments/views/HtmlTriplePatternFragmentWriterImpl.java b/api/src/main/java/org/linkeddatafragments/views/HtmlTriplePatternFragmentWriterImpl.java new file mode 100644 index 000000000..179c9744e --- /dev/null +++ b/api/src/main/java/org/linkeddatafragments/views/HtmlTriplePatternFragmentWriterImpl.java @@ -0,0 +1,145 @@ +package org.linkeddatafragments.views; + +import freemarker.template.Configuration; +import freemarker.template.Template; +import freemarker.template.TemplateException; +import freemarker.template.TemplateExceptionHandler; +import org.apache.jena.rdf.model.RDFNode; +import org.apache.jena.rdf.model.Statement; +import org.apache.jena.rdf.model.StmtIterator; +import org.linkeddatafragments.datasource.IDataSource; +import org.linkeddatafragments.datasource.index.IndexDataSource; +import org.linkeddatafragments.fragments.ILinkedDataFragment; +import org.linkeddatafragments.fragments.tpf.ITriplePatternFragment; +import org.linkeddatafragments.fragments.tpf.ITriplePatternFragmentRequest; + +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +//TODO: Refactor to a composable & flexible architecture using DataSource types, fragments types and request types + +/** + * Serializes an {@link ILinkedDataFragment} to the HTML format + * + * @author Miel Vander Sande + */ +public class HtmlTriplePatternFragmentWriterImpl extends TriplePatternFragmentWriterBase implements ILinkedDataFragmentWriter { + private final Configuration cfg; + + private final Template indexTemplate; + private final Template datasourceTemplate; + private final Template notfoundTemplate; + private final Template errorTemplate; + + private final String HYDRA = "http://www.w3.org/ns/hydra/core#"; + + /** + * + * @param prefixes + * @param datasources + * @throws IOException + */ + public HtmlTriplePatternFragmentWriterImpl(Map prefixes, HashMap datasources) throws IOException { + super(prefixes, datasources); + + cfg = new Configuration(Configuration.VERSION_2_3_22); + cfg.setClassForTemplateLoading(getClass(), "/views"); + cfg.setDefaultEncoding("UTF-8"); + cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER); + + indexTemplate = cfg.getTemplate("index.ftl.html"); + datasourceTemplate = cfg.getTemplate("datasource.ftl.html"); + notfoundTemplate = cfg.getTemplate("notfound.ftl.html"); + errorTemplate = cfg.getTemplate("error.ftl.html"); + } + + /** + * + * @param outputStream + * @param datasource + * @param fragment + * @param tpfRequest + * @throws IOException + * @throws TemplateException + */ + @Override + public void writeFragment(ServletOutputStream outputStream, IDataSource datasource, ITriplePatternFragment fragment, ITriplePatternFragmentRequest tpfRequest) throws IOException, TemplateException{ + Map data = new HashMap(); + + // base.ftl.html + data.put("assetsPath", "assets/"); + data.put("header", datasource.getTitle()); + data.put("date", new Date()); + + // fragment.ftl.html + data.put("datasourceUrl", tpfRequest.getDatasetURL()); + data.put("datasource", datasource); + + // Parse controls to template variables + StmtIterator controls = fragment.getControls(); + while (controls.hasNext()) { + Statement control = controls.next(); + + String predicate = control.getPredicate().getURI(); + RDFNode object = control.getObject(); + if (!object.isAnon()) { + String value = object.isURIResource() ? object.asResource().getURI() : object.asLiteral().getLexicalForm(); + data.put(predicate.replaceFirst(HYDRA, ""), value); + } + } + + // Add metadata + data.put("totalEstimate", fragment.getTotalSize()); + data.put("itemsPerPage", fragment.getMaxPageSize()); + + // Add triples and datasources + List triples = fragment.getTriples().toList(); + data.put("triples", triples); + data.put("datasources", getDatasources()); + + // Calculate start and end triple number + Long start = ((tpfRequest.getPageNumber() - 1) * fragment.getMaxPageSize()) + 1; + data.put("start", start); + data.put("end", start + (triples.size() < fragment.getMaxPageSize() ? triples.size() : fragment.getMaxPageSize())); + + // Compose query object + Map query = new HashMap(); + query.put("subject", !tpfRequest.getSubject().isVariable() ? tpfRequest.getSubject().asConstantTerm() : ""); + query.put("predicate", !tpfRequest.getPredicate().isVariable() ? tpfRequest.getPredicate().asConstantTerm() : ""); + query.put("object", !tpfRequest.getObject().isVariable() ? tpfRequest.getObject().asConstantTerm() : ""); + data.put("query", query); + + // Get the template (uses cache internally) + Template temp = datasource instanceof IndexDataSource ? indexTemplate : datasourceTemplate; + + // Merge data-model with template + temp.process(data, new OutputStreamWriter(outputStream)); + } + + @Override + public void writeNotFound(ServletOutputStream outputStream, HttpServletRequest request) throws Exception { + Map data = new HashMap(); + data.put("assetsPath", "assets/"); + data.put("datasources", getDatasources()); + data.put("date", new Date()); + data.put("url", request.getRequestURL().toString()); + + notfoundTemplate.process(data, new OutputStreamWriter(outputStream)); + } + + @Override + public void writeError(ServletOutputStream outputStream, Exception ex) throws Exception { + Map data = new HashMap(); + data.put("assetsPath", "assets/"); + data.put("date", new Date()); + data.put("error", ex); + + errorTemplate.process(data, new OutputStreamWriter(outputStream)); + } +} diff --git a/api/src/main/java/org/linkeddatafragments/views/ILinkedDataFragmentWriter.java b/api/src/main/java/org/linkeddatafragments/views/ILinkedDataFragmentWriter.java new file mode 100644 index 000000000..adaf9cbda --- /dev/null +++ b/api/src/main/java/org/linkeddatafragments/views/ILinkedDataFragmentWriter.java @@ -0,0 +1,44 @@ +package org.linkeddatafragments.views; + +import org.linkeddatafragments.datasource.IDataSource; +import org.linkeddatafragments.fragments.ILinkedDataFragment; +import org.linkeddatafragments.fragments.ILinkedDataFragmentRequest; + +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; + +/** + * Represents a possible writer to serialize an {@link ILinkedDataFragment} object + * + * @author Miel Vander Sande + */ +public interface ILinkedDataFragmentWriter { + /** + * Writes a 404 Not Found error + * + * @param outputStream The response stream to write to + * @param request Request that is unable to answer + * @throws Exception Error that occurs while serializing + */ + public void writeNotFound(ServletOutputStream outputStream, HttpServletRequest request) throws Exception; + + /** + * Writes a 5XX error + * + * @param outputStream The response stream to write to + * @param ex Exception that occurred + * @throws Exception Error that occurs while serializing + */ + public void writeError(ServletOutputStream outputStream, Exception ex) throws Exception; + + /** + * Serializes and writes a {@link ILinkedDataFragment} + * + * @param outputStream The response stream to write to + * @param datasource + * @param fragment + * @param ldfRequest Parsed request for fragment + * @throws Exception Error that occurs while serializing + */ + public void writeFragment(ServletOutputStream outputStream, IDataSource datasource, ILinkedDataFragment fragment, ILinkedDataFragmentRequest ldfRequest) throws Exception; +} diff --git a/api/src/main/java/org/linkeddatafragments/views/LinkedDataFragmentWriterBase.java b/api/src/main/java/org/linkeddatafragments/views/LinkedDataFragmentWriterBase.java new file mode 100644 index 000000000..0e7aed847 --- /dev/null +++ b/api/src/main/java/org/linkeddatafragments/views/LinkedDataFragmentWriterBase.java @@ -0,0 +1,42 @@ +package org.linkeddatafragments.views; + +import org.linkeddatafragments.datasource.IDataSource; + +import java.util.HashMap; +import java.util.Map; + +/** + * Base class of any implementation of {@link ILinkedDataFragmentWriter}. + * + * @author Miel Vander Sande + */ +public abstract class LinkedDataFragmentWriterBase implements ILinkedDataFragmentWriter { + private final Map prefixes; + private final HashMap datasources; + + /** + * + * @param prefixes + * @param datasources + */ + public LinkedDataFragmentWriterBase(Map prefixes, HashMap datasources) { + this.prefixes = prefixes; + this.datasources = datasources; + } + + /** + * + * @return + */ + public Map getPrefixes() { + return prefixes; + } + + /** + * + * @return + */ + public HashMap getDatasources() { + return datasources; + } +} diff --git a/api/src/main/java/org/linkeddatafragments/views/LinkedDataFragmentWriterFactory.java b/api/src/main/java/org/linkeddatafragments/views/LinkedDataFragmentWriterFactory.java new file mode 100644 index 000000000..efc868cc5 --- /dev/null +++ b/api/src/main/java/org/linkeddatafragments/views/LinkedDataFragmentWriterFactory.java @@ -0,0 +1,35 @@ +package org.linkeddatafragments.views; + +import org.linkeddatafragments.datasource.IDataSource; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +/** + * A factory for {@link ILinkedDataFragmentWriter}s. + * + * @author Miel Vander Sande + */ +public class LinkedDataFragmentWriterFactory { + + private final static String HTML = "text/html"; + + /** + * Creates {@link ILinkedDataFragmentWriter} for a given mimeType + * + * @param prefixes Configured prefixes to be used in serialization + * @param datasources Configured datasources + * @param mimeType mimeType to create writer for + * @return created writer + * @throws IOException + */ + public static ILinkedDataFragmentWriter create(Map prefixes, HashMap datasources, String mimeType) throws IOException { + switch (mimeType) { + case HTML: + return new HtmlTriplePatternFragmentWriterImpl(prefixes, datasources); + default: + return new RdfWriterImpl(prefixes, datasources, mimeType); + } + } +} diff --git a/api/src/main/java/org/linkeddatafragments/views/RdfWriterImpl.java b/api/src/main/java/org/linkeddatafragments/views/RdfWriterImpl.java new file mode 100644 index 000000000..f355fdb75 --- /dev/null +++ b/api/src/main/java/org/linkeddatafragments/views/RdfWriterImpl.java @@ -0,0 +1,55 @@ +package org.linkeddatafragments.views; + +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.ModelFactory; +import org.apache.jena.riot.Lang; +import org.apache.jena.riot.RDFDataMgr; +import org.apache.jena.riot.RDFLanguages; +import org.linkeddatafragments.datasource.IDataSource; +import org.linkeddatafragments.fragments.ILinkedDataFragment; +import org.linkeddatafragments.fragments.ILinkedDataFragmentRequest; + +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +/** + * Serializes an {@link ILinkedDataFragment} to an RDF format + * + * @author Miel Vander Sande + */ +public class RdfWriterImpl extends LinkedDataFragmentWriterBase implements ILinkedDataFragmentWriter { + + private final Lang contentType; + + public RdfWriterImpl(Map prefixes, HashMap datasources, String mimeType) { + super(prefixes, datasources); + this.contentType = RDFLanguages.contentTypeToLang(mimeType); + } + + @Override + public void writeNotFound(ServletOutputStream outputStream, HttpServletRequest request) throws IOException { + outputStream.println(request.getRequestURL().toString() + " not found!"); + outputStream.close(); + } + + @Override + public void writeError(ServletOutputStream outputStream, Exception ex) throws IOException { + outputStream.println(ex.getMessage()); + outputStream.close(); + } + + @Override + public void writeFragment(ServletOutputStream outputStream, IDataSource datasource, ILinkedDataFragment fragment, ILinkedDataFragmentRequest ldfRequest) throws Exception { + final Model output = ModelFactory.createDefaultModel(); + output.setNsPrefixes(getPrefixes()); + output.add(fragment.getMetadata()); + output.add(fragment.getTriples()); + output.add(fragment.getControls()); + + RDFDataMgr.write(outputStream, output, contentType); + } + +} diff --git a/api/src/main/java/org/linkeddatafragments/views/TriplePatternFragmentWriterBase.java b/api/src/main/java/org/linkeddatafragments/views/TriplePatternFragmentWriterBase.java new file mode 100644 index 000000000..43ebc3e3b --- /dev/null +++ b/api/src/main/java/org/linkeddatafragments/views/TriplePatternFragmentWriterBase.java @@ -0,0 +1,46 @@ +package org.linkeddatafragments.views; + +import freemarker.template.TemplateException; +import org.linkeddatafragments.datasource.IDataSource; +import org.linkeddatafragments.fragments.ILinkedDataFragment; +import org.linkeddatafragments.fragments.ILinkedDataFragmentRequest; +import org.linkeddatafragments.fragments.tpf.ITriplePatternFragment; +import org.linkeddatafragments.fragments.tpf.ITriplePatternFragmentRequest; + +import javax.servlet.ServletOutputStream; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +/** + * Base class of any implementation for ITriplePatternFragment. + * + * @author Miel Vander Sande + */ +public abstract class TriplePatternFragmentWriterBase extends LinkedDataFragmentWriterBase implements ILinkedDataFragmentWriter { + + /** + * + * @param prefixes + * @param datasources + */ + public TriplePatternFragmentWriterBase(Map prefixes, HashMap datasources) { + super(prefixes, datasources); + } + + @Override + public void writeFragment(ServletOutputStream outputStream, IDataSource datasource, ILinkedDataFragment fragment, ILinkedDataFragmentRequest ldfRequest) throws Exception { + writeFragment(outputStream, datasource, (ITriplePatternFragment) fragment, (ITriplePatternFragmentRequest) ldfRequest); + } + + /** + * + * @param outputStream + * @param datasource + * @param fragment + * @param tpfRequest + * @throws IOException + * @throws TemplateException + */ + abstract public void writeFragment(ServletOutputStream outputStream, IDataSource datasource, ITriplePatternFragment fragment, ITriplePatternFragmentRequest tpfRequest) throws IOException, TemplateException; +} diff --git a/api/src/main/java/org/vivoweb/linkeddatafragments/datasource/rdfservice/RDFServiceBasedRequestProcessorForTPFs.java b/api/src/main/java/org/vivoweb/linkeddatafragments/datasource/rdfservice/RDFServiceBasedRequestProcessorForTPFs.java new file mode 100644 index 000000000..ef17a21d8 --- /dev/null +++ b/api/src/main/java/org/vivoweb/linkeddatafragments/datasource/rdfservice/RDFServiceBasedRequestProcessorForTPFs.java @@ -0,0 +1,201 @@ +package org.vivoweb.linkeddatafragments.datasource.rdfservice; + +import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; +import edu.cornell.mannlib.vitro.webapp.dao.jena.QueryUtils; +import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService; +import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFServiceException; +import edu.cornell.mannlib.vitro.webapp.rdfservice.ResultSetConsumer; +import org.apache.jena.atlas.io.StringWriterI; +import org.apache.jena.query.Dataset; +import org.apache.jena.query.Query; +import org.apache.jena.query.QueryExecution; +import org.apache.jena.query.QueryExecutionFactory; +import org.apache.jena.query.QueryFactory; +import org.apache.jena.query.QuerySolution; +import org.apache.jena.query.QuerySolutionMap; +import org.apache.jena.query.ResultSet; +import org.apache.jena.query.Syntax; +import org.apache.jena.rdf.model.Literal; +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.ModelFactory; +import org.apache.jena.rdf.model.RDFNode; +import org.apache.jena.riot.out.NodeFormatter; +import org.apache.jena.riot.out.NodeFormatterTTL; +import org.apache.jena.tdb.TDBFactory; +import org.linkeddatafragments.datasource.AbstractRequestProcessorForTriplePatterns; +import org.linkeddatafragments.datasource.IFragmentRequestProcessor; +import org.linkeddatafragments.fragments.ILinkedDataFragment; +import org.linkeddatafragments.fragments.tpf.ITriplePatternElement; +import org.linkeddatafragments.fragments.tpf.ITriplePatternFragmentRequest; + +import java.io.File; + +public class RDFServiceBasedRequestProcessorForTPFs + extends AbstractRequestProcessorForTriplePatterns +{ + private static RDFService rdfService; + + public static void setRDFService(RDFService pRDFService) { + rdfService = pRDFService; + } + + @Override + protected Worker getTPFSpecificWorker( + final ITriplePatternFragmentRequest request ) + throws IllegalArgumentException + { + return new Worker( request ); + } + + /** + * + */ + protected class Worker + extends AbstractRequestProcessorForTriplePatterns.Worker + { + public Worker( + final ITriplePatternFragmentRequest req ) + { + super( req ); + } + + private void appendNode(StringBuilder builder, RDFNode node) { + if (node.isLiteral()) { + builder.append(literalToString(node.asLiteral())); + } else if (node.isURIResource()) { + builder.append('<' + node.asResource().getURI() + '>'); + } + } + + private String literalToString(Literal l) { + StringWriterI sw = new StringWriterI(); + NodeFormatter fmt = new NodeFormatterTTL(null, null); + fmt.formatLiteral(sw, l.asNode()); + return sw.toString(); + } + + @Override + protected ILinkedDataFragment createFragment( + final ITriplePatternElement subject, + final ITriplePatternElement predicate, + final ITriplePatternElement object, + final long offset, + final long limit ) + { + StringBuilder whereClause = new StringBuilder(); + StringBuilder filter = new StringBuilder(); + StringBuilder orderBy = new StringBuilder(); + + if ( ! subject.isVariable() ) { + appendNode(whereClause.append(' '), subject.asConstantTerm()); + } else { + whereClause.append(" ?s"); + if (filter.length() > 0) { filter.append(" && "); } + filter.append("!isBlank(?s)"); + orderBy.append(" ?s"); + } + + if ( ! predicate.isVariable() ) { + appendNode(whereClause.append(' '), predicate.asConstantTerm()); + } else { + whereClause.append(" ?p"); + if (filter.length() > 0) { filter.append(" && "); } + filter.append("!isBlank(?p)"); + orderBy.append(" ?p"); + } + + if ( ! object.isVariable() ) { + appendNode(whereClause.append(' '), object.asConstantTerm()); + } else { + whereClause.append(" ?o"); + if (filter.length() > 0) { filter.append(" && "); } + filter.append("!isBlank(?o)"); + orderBy.append(" ?o"); + } + + StringBuilder constructQuery = new StringBuilder(); + + constructQuery.append("CONSTRUCT { "); + constructQuery.append(whereClause.toString()); + constructQuery.append(" } WHERE { "); + constructQuery.append(whereClause.toString()).append(" . "); + if (filter.length() > 0) { + constructQuery.append(" FILTER(").append(filter.toString()).append(")"); + } + constructQuery.append(" }"); + + if (orderBy.length() > 0) { + constructQuery.append(" ORDER BY").append(orderBy.toString()); + } + + if (limit > 0) { + constructQuery.append(" LIMIT ").append(limit); + } + + if (offset > 0) { + constructQuery.append(" OFFSET ").append(offset); + } + + Model triples = ModelFactory.createDefaultModel(); + + try { + rdfService.sparqlConstructQuery(constructQuery.toString(), triples); + } catch (RDFServiceException e) { + return createEmptyTriplePatternFragment(); + } + + if (triples.isEmpty()) { + return createEmptyTriplePatternFragment(); + } + + // Try to get an estimate + long size = triples.size(); + long estimate = -1; + + StringBuilder count = new StringBuilder(); + count.append("SELECT (COUNT(*) AS ?count) WHERE { "); + count.append(whereClause.toString()); + count.append(" . "); + if (filter.length() > 0) { + count.append(" FILTER(").append(filter.toString()).append(") "); + } + count.append(" }"); + try { + CountConsumer countConsumer = new CountConsumer(); + rdfService.sparqlSelectQuery(count.toString(), countConsumer); + estimate = countConsumer.estimate; + } catch (RDFServiceException e) { + return createEmptyTriplePatternFragment(); + } + + // No estimate or incorrect + if (estimate < offset + size) { + estimate = (size == limit) ? offset + size + 1 : offset + size; + } + + // create the fragment + final boolean isLastPage = ( estimate < offset + limit ); + return createTriplePatternFragment( triples, estimate, isLastPage ); + } + + } // end of class Worker + + + /** + * Constructor + */ + public RDFServiceBasedRequestProcessorForTPFs() { + } + + class CountConsumer extends ResultSetConsumer { + public long estimate = -1; + + @Override + protected void processQuerySolution(QuerySolution qs) { + if (estimate == -1) { + Literal literal = qs.getLiteral("count"); + estimate = literal.getLong(); + } + } + } +} diff --git a/api/src/main/java/org/vivoweb/linkeddatafragments/datasource/rdfservice/RDFServiceDataSource.java b/api/src/main/java/org/vivoweb/linkeddatafragments/datasource/rdfservice/RDFServiceDataSource.java new file mode 100644 index 000000000..7511aad96 --- /dev/null +++ b/api/src/main/java/org/vivoweb/linkeddatafragments/datasource/rdfservice/RDFServiceDataSource.java @@ -0,0 +1,46 @@ +package org.vivoweb.linkeddatafragments.datasource.rdfservice; + +import org.linkeddatafragments.datasource.DataSourceBase; +import org.linkeddatafragments.datasource.IFragmentRequestProcessor; +import org.linkeddatafragments.fragments.IFragmentRequestParser; +import org.linkeddatafragments.fragments.tpf.TPFRequestParserForJenaBackends; + +import java.io.File; + +/** + * Experimental Jena TDB-backed data source of Basic Linked Data Fragments. + * + * @author Bart Hanssens + * @author Olaf Hartig + */ +public class RDFServiceDataSource extends DataSourceBase { + + /** + * The request processor + * + */ + protected final RDFServiceBasedRequestProcessorForTPFs requestProcessor; + + @Override + public IFragmentRequestParser getRequestParser() + { + return TPFRequestParserForJenaBackends.getInstance(); + } + + @Override + public IFragmentRequestProcessor getRequestProcessor() + { + return requestProcessor; + } + + /** + * Constructor + * + * @param title + * @param description + */ + public RDFServiceDataSource(String title, String description) { + super(title, description); + requestProcessor = new RDFServiceBasedRequestProcessorForTPFs(); + } +} diff --git a/api/src/main/java/org/vivoweb/linkeddatafragments/datasource/rdfservice/RDFServiceDataSourceType.java b/api/src/main/java/org/vivoweb/linkeddatafragments/datasource/rdfservice/RDFServiceDataSourceType.java new file mode 100644 index 000000000..417466dba --- /dev/null +++ b/api/src/main/java/org/vivoweb/linkeddatafragments/datasource/rdfservice/RDFServiceDataSourceType.java @@ -0,0 +1,31 @@ +package org.vivoweb.linkeddatafragments.datasource.rdfservice; + +import com.google.gson.JsonObject; +import org.linkeddatafragments.datasource.IDataSource; +import org.linkeddatafragments.datasource.IDataSourceType; +import org.linkeddatafragments.exceptions.DataSourceCreationException; + +import java.io.File; + +/** + * The type of Triple Pattern Fragment data sources that are backed by + * a Jena TDB instance. + * + * @author Olaf Hartig + */ +public class RDFServiceDataSourceType implements IDataSourceType +{ + @Override + public IDataSource createDataSource( final String title, + final String description, + final JsonObject settings ) + throws DataSourceCreationException + { + try { + return new RDFServiceDataSource(title, description); + } catch (Exception ex) { + throw new DataSourceCreationException(ex); + } + } + +} diff --git a/api/src/main/java/org/vivoweb/linkeddatafragments/servlet/VitroLinkedDataFragmentServlet.java b/api/src/main/java/org/vivoweb/linkeddatafragments/servlet/VitroLinkedDataFragmentServlet.java new file mode 100644 index 000000000..b43f80aab --- /dev/null +++ b/api/src/main/java/org/vivoweb/linkeddatafragments/servlet/VitroLinkedDataFragmentServlet.java @@ -0,0 +1,270 @@ +package org.vivoweb.linkeddatafragments.servlet; + +import com.google.gson.JsonObject; +import edu.cornell.mannlib.vitro.webapp.beans.Ontology; +import edu.cornell.mannlib.vitro.webapp.controller.VitroHttpServlet; +import edu.cornell.mannlib.vitro.webapp.dao.OntologyDao; +import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess; +import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService; +import org.apache.commons.io.IOUtils; +import org.apache.jena.riot.Lang; +import org.linkeddatafragments.config.ConfigReader; +import org.linkeddatafragments.datasource.DataSourceFactory; +import org.linkeddatafragments.datasource.DataSourceTypesRegistry; +import org.linkeddatafragments.datasource.IDataSource; +import org.linkeddatafragments.datasource.IDataSourceType; +import org.linkeddatafragments.datasource.index.IndexDataSource; +import org.linkeddatafragments.exceptions.DataSourceNotFoundException; +import org.linkeddatafragments.fragments.FragmentRequestParserBase; +import org.linkeddatafragments.fragments.ILinkedDataFragment; +import org.linkeddatafragments.fragments.ILinkedDataFragmentRequest; +import org.linkeddatafragments.util.MIMEParse; +import org.linkeddatafragments.views.ILinkedDataFragmentWriter; +import org.vivoweb.linkeddatafragments.views.HtmlTriplePatternFragmentWriterImpl; +import org.vivoweb.linkeddatafragments.views.LinkedDataFragmentWriterFactory; +import org.vivoweb.linkeddatafragments.datasource.rdfservice.RDFServiceBasedRequestProcessorForTPFs; +import org.vivoweb.linkeddatafragments.datasource.rdfservice.RDFServiceDataSource; +import org.vivoweb.linkeddatafragments.datasource.rdfservice.RDFServiceDataSourceType; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map.Entry; + +/** + * Servlet that responds with a Linked Data Fragment. + */ +public class VitroLinkedDataFragmentServlet extends VitroHttpServlet { + + private final static long serialVersionUID = 1L; + + private ConfigReader config; + private final HashMap dataSources = new HashMap<>(); + private final Collection mimeTypes = new ArrayList<>(); + + private File getConfigFile(ServletConfig config) throws IOException { + String path = config.getServletContext().getRealPath("/"); + if (path == null) { + // this can happen when running standalone + path = System.getProperty("user.dir"); + } + File cfg = new File(path, "config-example.json"); + if (!cfg.exists()) { + throw new IOException("Configuration file " + cfg + " not found."); + } + if (!cfg.isFile()) { + throw new IOException("Configuration file " + cfg + " is not a file."); + } + return cfg; + } + + @Override + public void init(ServletConfig servletConfig) throws ServletException { + try { + ServletContext ctx = servletConfig.getServletContext(); + RDFService rdfService = ModelAccess.on(ctx).getRDFService(); + RDFServiceBasedRequestProcessorForTPFs.setRDFService(rdfService); + + OntologyDao dao = ModelAccess.on(ctx).getWebappDaoFactory().getOntologyDao(); + + // load the configuration + config = new ConfigReader(new StringReader(getConfigJson(dao))); + + // register data source types + for ( Entry typeEntry : config.getDataSourceTypes().entrySet() ) { + if (!DataSourceTypesRegistry.isRegistered(typeEntry.getKey())) { + DataSourceTypesRegistry.register( typeEntry.getKey(), + typeEntry.getValue() ); + } + } + + // register data sources + for (Entry dataSource : config.getDataSources().entrySet()) { + dataSources.put(dataSource.getKey(), DataSourceFactory.create(dataSource.getValue())); + } + + // register content types + MIMEParse.register("text/html"); + MIMEParse.register(Lang.TTL.getHeaderString()); + MIMEParse.register(Lang.JSONLD.getHeaderString()); + MIMEParse.register(Lang.NTRIPLES.getHeaderString()); + MIMEParse.register(Lang.RDFXML.getHeaderString()); + + HtmlTriplePatternFragmentWriterImpl.setContextPath(servletConfig.getServletContext().getContextPath()); + } catch (Exception e) { + throw new ServletException(e); + } + } + + @Override + public void destroy() + { + for ( IDataSource dataSource : dataSources.values() ) { + try { + dataSource.close(); + } + catch( Exception e ) { + // ignore + } + } + } + + private IDataSource getDataSource(HttpServletRequest request) throws DataSourceNotFoundException { + String contextPath = request.getContextPath(); + String requestURI = request.getRequestURI(); + + String path = contextPath == null + ? requestURI + : requestURI.substring(contextPath.length()); + + if (path.startsWith("/tpf")) { + path = path.substring(4); + } + + if (path.equals("/") || path.isEmpty()) { + final String baseURL = FragmentRequestParserBase.extractBaseURL(request, config); + return new IndexDataSource(baseURL, dataSources); + } + + String dataSourceName = path.substring(1); + IDataSource dataSource = dataSources.get(dataSourceName); + if (dataSource == null) { + throw new DataSourceNotFoundException(dataSourceName); + } + + return dataSource; + } + + @Override + public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException { + int fileNamePos = request.getRequestURI().toLowerCase().lastIndexOf("/tpf/assets/"); + if (fileNamePos > 0) { + try { + String fileName = request.getRequestURI().substring(fileNamePos + 12); + InputStream in = VitroLinkedDataFragmentServlet.class.getResourceAsStream(fileName); + if (in != null) { + IOUtils.copy(in, response.getOutputStream()); + } + return; + } catch (IOException ioe) { + } + } + + ILinkedDataFragment fragment = null; + try { + // do conneg + String bestMatch = MIMEParse.bestMatch(request.getHeader("Accept")); + + // set additional response headers + response.setHeader("Server", "Linked Data Fragments Server"); + response.setContentType(bestMatch); + response.setCharacterEncoding("utf-8"); + + // create a writer depending on the best matching mimeType + ILinkedDataFragmentWriter writer = LinkedDataFragmentWriterFactory.create(config.getPrefixes(), dataSources, bestMatch); + + try { + + final IDataSource dataSource = getDataSource( request ); + + final ILinkedDataFragmentRequest ldfRequest = + dataSource.getRequestParser() + .parseIntoFragmentRequest( request, config ); + + fragment = dataSource.getRequestProcessor() + .createRequestedFragment( ldfRequest ); + + response.setHeader("Access-Control-Allow-Origin", "*"); + writer.writeFragment(response.getOutputStream(), dataSource, fragment, ldfRequest); + + } catch (DataSourceNotFoundException ex) { + try { + response.setStatus(404); + writer.writeNotFound(response.getOutputStream(), request); + } catch (Exception ex1) { + throw new ServletException(ex1); + } + } catch (Exception e) { + response.setStatus(500); + writer.writeError(response.getOutputStream(), e); + } + + } catch (Exception e) { + throw new ServletException(e); + } + finally { + // close the fragment + if ( fragment != null ) { + try { + fragment.close(); + } + catch ( Exception e ) { + // ignore + } + } + } + } + + private String getConfigJson(OntologyDao dao) { + StringBuilder configJson = new StringBuilder(); + configJson.append("{\n"); + configJson.append(" \"title\": \"Linked Data Fragments server\",\n"); + configJson.append("\n"); + configJson.append(" \"datasourcetypes\": {\n"); + configJson.append(" \"RDFServiceDatasource\": \"" + RDFServiceDataSourceType.class.getCanonicalName() + "\"\n"); + configJson.append(" },\n"); + configJson.append("\n"); + configJson.append(" \"datasources\": {\n"); + configJson.append(" \"core\": {\n"); + configJson.append(" \"title\": \"core\",\n"); + configJson.append(" \"type\": \"RDFServiceDatasource\",\n"); + configJson.append(" \"description\": \"All data\"\n"); + configJson.append(" }\n"); + configJson.append(" },\n"); + configJson.append("\n"); + configJson.append(" \"prefixes\": {\n"); + configJson.append(" \"rdf\": \"http://www.w3.org/1999/02/22-rdf-syntax-ns#\",\n"); + configJson.append(" \"rdfs\": \"http://www.w3.org/2000/01/rdf-schema#\",\n"); + configJson.append(" \"hydra\": \"http://www.w3.org/ns/hydra/core#\",\n"); + configJson.append(" \"void\": \"http://rdfs.org/ns/void#\""); + + List onts = dao.getAllOntologies(); + if (onts != null) { + for (Ontology ont : onts) { + switch (ont.getPrefix()) { + case "rdf": + case "rdfs": + case "hydra": + case "void": + break; + + default: + configJson.append(",\n"); + configJson.append(" \""); + configJson.append(ont.getPrefix()); + configJson.append("\": \""); + configJson.append(ont.getURI()); + configJson.append("\""); + break; + } + } + } + + configJson.append(" }\n"); + configJson.append("}\n"); + + return configJson.toString(); + } +} diff --git a/api/src/main/java/org/vivoweb/linkeddatafragments/views/HtmlTriplePatternFragmentWriterImpl.java b/api/src/main/java/org/vivoweb/linkeddatafragments/views/HtmlTriplePatternFragmentWriterImpl.java new file mode 100644 index 000000000..c58a0743d --- /dev/null +++ b/api/src/main/java/org/vivoweb/linkeddatafragments/views/HtmlTriplePatternFragmentWriterImpl.java @@ -0,0 +1,221 @@ +package org.vivoweb.linkeddatafragments.views; + +import freemarker.template.Configuration; +import freemarker.template.Template; +import freemarker.template.TemplateException; +import freemarker.template.TemplateExceptionHandler; +import org.apache.jena.atlas.io.StringWriterI; +import org.apache.jena.rdf.model.Literal; +import org.apache.jena.rdf.model.RDFNode; +import org.apache.jena.rdf.model.Statement; +import org.apache.jena.rdf.model.StmtIterator; +import org.apache.jena.rdf.model.impl.LiteralImpl; +import org.apache.jena.riot.out.NodeFormatter; +import org.apache.jena.riot.out.NodeFormatterTTL; +import org.linkeddatafragments.datasource.IDataSource; +import org.linkeddatafragments.datasource.index.IndexDataSource; +import org.linkeddatafragments.fragments.ILinkedDataFragment; +import org.linkeddatafragments.fragments.tpf.ITriplePatternElement; +import org.linkeddatafragments.fragments.tpf.ITriplePatternFragment; +import org.linkeddatafragments.fragments.tpf.ITriplePatternFragmentRequest; +import org.linkeddatafragments.views.ILinkedDataFragmentWriter; +import org.linkeddatafragments.views.TriplePatternFragmentWriterBase; + +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +//TODO: Refactor to a composable & flexible architecture using DataSource types, fragments types and request types + +/** + * Serializes an {@link ILinkedDataFragment} to the HTML format + * + * @author Miel Vander Sande + */ +public class HtmlTriplePatternFragmentWriterImpl extends TriplePatternFragmentWriterBase implements ILinkedDataFragmentWriter { + private final Configuration cfg; + + private final Template indexTemplate; + private final Template datasourceTemplate; + private final Template notfoundTemplate; + private final Template errorTemplate; + + private final String HYDRA = "http://www.w3.org/ns/hydra/core#"; + + private static String contextPath; + + public static void setContextPath(String path) { + contextPath = path; + if (!contextPath.endsWith("/")) { + contextPath += "/"; + } + } + + /** + * + * @param prefixes + * @param datasources + * @throws IOException + */ + public HtmlTriplePatternFragmentWriterImpl(Map prefixes, HashMap datasources) throws IOException { + super(prefixes, datasources); + + cfg = new Configuration(Configuration.VERSION_2_3_23); + cfg.setClassForTemplateLoading(getClass(), "/tpf"); + cfg.setDefaultEncoding("UTF-8"); + cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER); + + indexTemplate = cfg.getTemplate("index.ftl.html"); + datasourceTemplate = cfg.getTemplate("datasource.ftl.html"); + notfoundTemplate = cfg.getTemplate("notfound.ftl.html"); + errorTemplate = cfg.getTemplate("error.ftl.html"); + } + + /** + * + * @param outputStream + * @param datasource + * @param fragment + * @param tpfRequest + * @throws IOException + * @throws TemplateException + */ + @Override + public void writeFragment(ServletOutputStream outputStream, IDataSource datasource, ITriplePatternFragment fragment, ITriplePatternFragmentRequest tpfRequest) throws IOException, TemplateException{ + Map data = new HashMap(); + + // base.ftl.html + data.put("homePath", (contextPath != null ? contextPath : "") + "tpf"); + data.put("assetsPath", (contextPath != null ? contextPath : "") + "tpf/assets/"); + data.put("header", datasource.getTitle()); + data.put("date", new Date()); + + // fragment.ftl.html + data.put("datasourceUrl", tpfRequest.getDatasetURL()); + data.put("datasource", datasource); + + // Parse controls to template variables + StmtIterator controls = fragment.getControls(); + while (controls.hasNext()) { + Statement control = controls.next(); + + String predicate = control.getPredicate().getURI(); + RDFNode object = control.getObject(); + if (!object.isAnon()) { + String value = object.isURIResource() ? object.asResource().getURI() : object.asLiteral().getLexicalForm(); + data.put(predicate.replaceFirst(HYDRA, ""), value); + } + } + + // Add metadata + data.put("totalEstimate", fragment.getTotalSize()); + data.put("itemsPerPage", fragment.getMaxPageSize()); + + // Add triples and datasources + List triples = fragment.getTriples().toList(); + data.put("triples", triples); + data.put("datasources", getDatasources()); + + // Calculate start and end triple number + Long start = ((tpfRequest.getPageNumber() - 1) * fragment.getMaxPageSize()) + 1; + data.put("start", start); + data.put("end", start + (triples.size() < fragment.getMaxPageSize() ? triples.size() : fragment.getMaxPageSize())); + + // Compose query object + Map query = new HashMap(); + query.put("subject", !tpfRequest.getSubject().isVariable() ? handleCT(tpfRequest.getSubject().asConstantTerm()) : ""); + query.put("predicate", !tpfRequest.getPredicate().isVariable() ? handleCT(tpfRequest.getPredicate().asConstantTerm()) : ""); + query.put("object", !tpfRequest.getObject().isVariable() ? handleCT(tpfRequest.getObject().asConstantTerm()) : ""); + query.put("pattern", makeQueryPattern(tpfRequest)); + data.put("query", query); + + // Get the template (uses cache internally) + Template temp = datasource instanceof IndexDataSource ? indexTemplate : datasourceTemplate; + + // Merge data-model with template + temp.process(data, new OutputStreamWriter(outputStream)); + } + + private String makeQueryPattern(ITriplePatternFragmentRequest tpfRequest) { + StringBuilder pattern = new StringBuilder(); + + ITriplePatternElement subject = tpfRequest.getSubject(); + ITriplePatternElement predicate = tpfRequest.getPredicate(); + ITriplePatternElement object = tpfRequest.getObject(); + + pattern.append("{"); + + if ( ! subject.isVariable() ) { + appendNode(pattern.append(' '), subject.asConstantTerm()); + } else { + pattern.append(" ?s"); + } + + + if ( ! predicate.isVariable() ) { + appendNode(pattern.append(' '), predicate.asConstantTerm()); + } else { + pattern.append(" ?p"); + } + + if ( ! object.isVariable() ) { + appendNode(pattern.append(' '), object.asConstantTerm()); + } else { + pattern.append(" ?o"); + } + + pattern.append(" }"); + return pattern.toString(); + } + + private void appendNode(StringBuilder builder, RDFNode node) { + if (node.isLiteral()) { + builder.append(literalToString(node.asLiteral())); + } else if (node.isURIResource()) { + builder.append('<' + node.asResource().getURI() + '>'); + } + } + + private String literalToString(Literal l) { + StringWriterI sw = new StringWriterI(); + NodeFormatter fmt = new NodeFormatterTTL(null, null); + fmt.formatLiteral(sw, l.asNode()); + return sw.toString(); + } + + private Object handleCT(Object obj) { + if (obj instanceof LiteralImpl) { + return ((LiteralImpl)obj).asNode().toString(); + } + + return obj; + } + + @Override + public void writeNotFound(ServletOutputStream outputStream, HttpServletRequest request) throws Exception { + Map data = new HashMap(); + data.put("homePath", (contextPath != null ? contextPath : "") + "tpf"); + data.put("assetsPath", (contextPath != null ? contextPath : "") + "tpf/assets/"); + data.put("datasources", getDatasources()); + data.put("date", new Date()); + data.put("url", request.getRequestURL().toString()); + + notfoundTemplate.process(data, new OutputStreamWriter(outputStream)); + } + + @Override + public void writeError(ServletOutputStream outputStream, Exception ex) throws Exception { + Map data = new HashMap(); + data.put("homePath", (contextPath != null ? contextPath : "") + "tpf"); + data.put("assetsPath", (contextPath != null ? contextPath : "") + "tpf/assets/"); + data.put("date", new Date()); + data.put("error", ex); + + errorTemplate.process(data, new OutputStreamWriter(outputStream)); + } +} diff --git a/api/src/main/java/org/vivoweb/linkeddatafragments/views/LinkedDataFragmentWriterFactory.java b/api/src/main/java/org/vivoweb/linkeddatafragments/views/LinkedDataFragmentWriterFactory.java new file mode 100644 index 000000000..ebc933f9f --- /dev/null +++ b/api/src/main/java/org/vivoweb/linkeddatafragments/views/LinkedDataFragmentWriterFactory.java @@ -0,0 +1,36 @@ +package org.vivoweb.linkeddatafragments.views; + +import org.linkeddatafragments.datasource.IDataSource; +import org.linkeddatafragments.views.ILinkedDataFragmentWriter; +import org.linkeddatafragments.views.RdfWriterImpl; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +/** + * A factory for {@link ILinkedDataFragmentWriter}s. + * + * @author Miel Vander Sande + */ +public class LinkedDataFragmentWriterFactory { + + private final static String HTML = "text/html"; + + /** + * Creates {@link ILinkedDataFragmentWriter} for a given mimeType + * + * @param prefixes Configured prefixes to be used in serialization + * @param datasources Configured datasources + * @param mimeType mimeType to create writer for + * @return created writer + */ + public static ILinkedDataFragmentWriter create(Map prefixes, HashMap datasources, String mimeType) throws IOException { + switch (mimeType) { + case HTML: + return new HtmlTriplePatternFragmentWriterImpl(prefixes, datasources); + default: + return new RdfWriterImpl(prefixes, datasources, mimeType); + } + } +} diff --git a/api/src/main/resources/org/vivoweb/linkeddatafragments/servlet/favicon.ico b/api/src/main/resources/org/vivoweb/linkeddatafragments/servlet/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..65418193a24cd6f59b00198636351f7270b6dd41 GIT binary patch literal 318 zcmZQzU<5(|0RbS%!l1#(z#zuJz@P!d0zj+)#2|4HXaJKC0wf0l(z3D)k^bixltlM2 z{Qv(SB1i&h3~db%3#_M#y2to@)=;tsYa9FRIEw?&DS39 literal 0 HcmV?d00001 diff --git a/api/src/main/resources/org/vivoweb/linkeddatafragments/servlet/logo.svg b/api/src/main/resources/org/vivoweb/linkeddatafragments/servlet/logo.svg new file mode 100644 index 000000000..dce588f7e --- /dev/null +++ b/api/src/main/resources/org/vivoweb/linkeddatafragments/servlet/logo.svg @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/api/src/main/resources/org/vivoweb/linkeddatafragments/servlet/style.css b/api/src/main/resources/org/vivoweb/linkeddatafragments/servlet/style.css new file mode 100644 index 000000000..4728a61f4 --- /dev/null +++ b/api/src/main/resources/org/vivoweb/linkeddatafragments/servlet/style.css @@ -0,0 +1,247 @@ +/*! @license ©2013 Ruben Verborgh - Multimedia Lab / iMinds / Ghent University */ + +html, input, th, td { + font-family: "Open Sans", Verdana, Arial, sans-serif; + font-size: 11pt; +} + +html { + background: #f6f6f6; +} + +body { + max-width: 800px; + margin: 0 auto; + line-height: 1.3; + color: #333333; + background-color: white; + padding: 10px 40px; + box-shadow: 2px 2px 15px 0px rgba(50, 50, 50, 0.75); +} + +h1, h2, h3, legend { + margin: .4em 0 .2em; + overflow: hidden; +} +h1 { + margin-right: 180px; +} +h1 a { + color: black; +} +h2 { + color: #be1622; +} +h3 { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +p { + margin: 0; +} + +a { + color: #be1622; + text-decoration: none; + border-bottom: none 1px; +} +a:hover { + color: #be1622 !important; + border-bottom-style: solid; +} + +ul { + padding: 0; + margin: 0 0 .5em 1.5em; + list-style: none; +} + +pre { + margin: 0; +} + +form { + margin: 0 0 1.5em; +} + +fieldset { + border: none; + padding: .5em 0 0 20px; +} +fieldset ul { + margin-left: 0; +} +fieldset li { + line-height: 2em; +} + +legend { + font-size: 1.17em; + font-weight: bold; + padding: 0; + margin-left: -20px; +} + +label { + width: 100px; + display: block; + float: left; + clear: both; + font-weight: bold; +} +label:after { + content: ":"; +} + +input { + outline: none; + font-size: .95em; +} +fieldset input { + width: 500px; + color: #be1622; + background-color: transparent; + border: none; + border-bottom: 1px solid #bbbbbb; + cursor: pointer; +} +input[type=submit] { + font-weight: bold; + color: #be1622; + background-color: #f6f6f6; + border-radius: 3px; + padding: 5px 8px; + border: 1px solid #999999; + cursor: pointer; +} +input[type=submit]:hover { + border-color: #666666; +} +input[type=submit]:active { + padding: 6px 7px 4px 9px; +} +.uri { + font-family: "Droid Sans Mono", monospace; +} + +header .logo { + text-align: right; +} +header .logo a { + position: absolute; + top: 20px; + margin-left: -100px; + border-bottom-width: 0px; +} +header .logo img { + width: 160px; +} + +footer { + clear: both; + margin: 1.5em 0 .5em; + font-size: small; +} +footer * { + color: gray; + margin-right: 5px; +} + +.counts { + color: gray; +} +ul.links { + margin: 0; + padding: 0; + display: inline; +} +ul.links li { + display: inline; + padding-left: 20px; + font-weight: bold; +} + +ul.triples { + margin: .3em 0 1em 20px; + font-size: .95em; + line-height: 1.5; + font-family: "Droid Sans Mono", monospace; + overflow-x: hidden; +} +ul.triples li { + text-indent: -20px; + padding-left: 20px; + max-width: 100%; + max-height: 1.5em; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} +ul.triples li:hover { + max-height: 100em; + white-space: normal; + transition: max-height .5s ease-in; + transition-delay: .5s; +} +ul.triples li:not(:hover) a { + color: inherit; +} +ul.triples a:nth-child(2) { + margin: 0 1em; +} +abbr { + border: none; +} + +.index { + margin-bottom: 2em; +} +.datasets { + margin: .5em 20px; +} +dt { + font-weight: bold; + display: block; + float: left; + clear: left; +} +dd { + color: gray; + margin: .1em 0 0 12em; + font-size: .95em; +} + +#about { + margin-top: 1.5em; + font-size: .9em; +} + +@media screen and (max-width: 700px) { + html, input, th, td { + font-size: 10pt; + } + body { + padding: 15px; + } + header figure { + display: none; + } + h1, legend { + margin: 0; + } + fieldset, ul.triples { + padding: .5em 0; + margin: 0; + } + fieldset input { + width: 70%; + } + label { + width: 80px; + } + ul.triples li { + margin: 1em 0; + } +} diff --git a/api/src/main/resources/tpf/base.ftl.html b/api/src/main/resources/tpf/base.ftl.html new file mode 100644 index 000000000..8952ccf1c --- /dev/null +++ b/api/src/main/resources/tpf/base.ftl.html @@ -0,0 +1,30 @@ +<#-- @license ©2015 Miel Vander Sande - Multimedia Lab / iMinds / Ghent University --> +<#macro display_page> + + + + + Linked Data Fragments Server ${ (title!header)?ensure_starts_with("(")?ensure_ends_with(")") } + + + + + +
+

Linked Data Fragments Server

+ +
+
+ <@contents/> +
+ + + + \ No newline at end of file diff --git a/api/src/main/resources/tpf/datasource.ftl.html b/api/src/main/resources/tpf/datasource.ftl.html new file mode 100644 index 000000000..97cd09985 --- /dev/null +++ b/api/src/main/resources/tpf/datasource.ftl.html @@ -0,0 +1,7 @@ +<#-- @license ©2015 Miel Vander Sande - Multimedia Lab / iMinds / Ghent University --> +<#assign title = datasource.getTitle() + ' | ' + title!""> +<#include "base.ftl.html"> +<#macro contents> +<#include "fragment.ftl.html"> + +<@display_page/> diff --git a/api/src/main/resources/tpf/error.ftl.html b/api/src/main/resources/tpf/error.ftl.html new file mode 100644 index 000000000..84ce65876 --- /dev/null +++ b/api/src/main/resources/tpf/error.ftl.html @@ -0,0 +1,11 @@ +<#-- @license ©2015 Miel Vander Sande - Multimedia Lab / iMinds / Ghent University --> +<#include "base.ftl.html"> +<#macro contents> +

Error executing your request

+

Your request could not be executed due to an internal server error.

+

Please try reloading the page or return to the index page.

+ +

Error details

+

<#if error??>${(error.getMessage())!error!""}

+ +<@display_page/> \ No newline at end of file diff --git a/api/src/main/resources/tpf/fragment.ftl.html b/api/src/main/resources/tpf/fragment.ftl.html new file mode 100644 index 000000000..32ce716bf --- /dev/null +++ b/api/src/main/resources/tpf/fragment.ftl.html @@ -0,0 +1,83 @@ +<#-- @license ©2015 Miel Vander Sande - Multimedia Lab / iMinds / Ghent University --> +<#setting url_escaping_charset='UTF-8'> +

+

${datasource.getTitle()?cap_first}

+ +
+
+ Query ${datasource.getTitle()} by triple pattern +
    +<#list ['subject', 'predicate', 'object'] as component> +
  • + + +
  • + +
+
+

+ +

+
+
+ +

Matches in ${datasource.getTitle()} for ${ (query["pattern"]?html)!"" }

+ +
+<#if (triples?size > 0)> + Showing triples ${ start } to ${ end } of + <#if totalEstimate != end>± + ${ totalEstimate } + with ${ + itemsPerPage + } triples per page. + <@pageLinks/> +<#else> +

+ ${datasource.getTitle()} contains + + no <#if (totalEstimate > 0) >more + + triples that match this pattern. +

+ +
+ + + +<@pageLinks/> + +<#macro pageLinks> + + \ No newline at end of file diff --git a/api/src/main/resources/tpf/index.ftl.html b/api/src/main/resources/tpf/index.ftl.html new file mode 100644 index 000000000..568db4ab5 --- /dev/null +++ b/api/src/main/resources/tpf/index.ftl.html @@ -0,0 +1,21 @@ +<#-- @license ©2015 Miel Vander Sande - Multimedia Lab / iMinds / Ghent University --> +<#include "base.ftl.html"> +<#macro contents> +
+

Available datasets

+

Browse the following datasets as Triple Pattern Fragments:

+
+ <#if datasources??> + <#list datasources?keys as datasourceName> +
${datasources[datasourceName].getTitle() }
+
${ datasources[datasourceName].getDescription()!"" }
+ + +
+

The current dataset index contains metadata about these datasets.

+
+ +<#include "fragment.ftl.html"> + + +<@display_page/> \ No newline at end of file diff --git a/api/src/main/resources/tpf/notfound.ftl.html b/api/src/main/resources/tpf/notfound.ftl.html new file mode 100644 index 000000000..363b8abd9 --- /dev/null +++ b/api/src/main/resources/tpf/notfound.ftl.html @@ -0,0 +1,16 @@ +<#-- @license ©2015 Miel Vander Sande - Multimedia Lab / iMinds / Ghent University --> +<#include "base.ftl.html"> +<#macro contents> +

Resource not found

+

+ No resource with URL ${ url!"" } was found. +

+ +

Available datasets

+ + +<@display_page/> \ No newline at end of file diff --git a/dependencies/pom.xml b/dependencies/pom.xml index df30c3970..856f37d30 100644 --- a/dependencies/pom.xml +++ b/dependencies/pom.xml @@ -284,6 +284,11 @@ antisamy 1.5.3
+ + com.google.code.gson + gson + 2.5 + From be72c0d8b871da02effba0a3c85c4102d6261cb9 Mon Sep 17 00:00:00 2001 From: Graham Triggs Date: Sat, 24 Dec 2016 11:47:36 +0000 Subject: [PATCH 35/49] Remove COS dependency from JSP --- webapp/src/main/webapp/error.jsp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/webapp/src/main/webapp/error.jsp b/webapp/src/main/webapp/error.jsp index 566e53673..fb3368677 100755 --- a/webapp/src/main/webapp/error.jsp +++ b/webapp/src/main/webapp/error.jsp @@ -2,7 +2,7 @@ <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <%@ page isErrorPage="true" %> -<%@ page import="com.oreilly.servlet.ServletUtils,edu.cornell.mannlib.vitro.webapp.web.*" %> +<%@ page import="edu.cornell.mannlib.vitro.webapp.web.*" %> <%@page import="edu.cornell.mannlib.vitro.webapp.controller.VitroRequest"%> <%@page import="edu.cornell.mannlib.vitro.webapp.beans.ApplicationBean"%> <%@page import="org.apache.commons.logging.Log"%> @@ -46,7 +46,10 @@
<% try{ %> -

Trace:

<%= ServletUtils.getStackTraceAsString(exception) %>
+

Trace:

+

+                        exception.printStackTrace(new java.io.PrintWriter(out));
+                    
<% }catch (Exception e){ %> No trace is available. <% } %> From 88d4cec9cff1c4594b524ef14f1e8cfff03409b9 Mon Sep 17 00:00:00 2001 From: Graham Triggs Date: Sat, 24 Dec 2016 12:06:48 +0000 Subject: [PATCH 36/49] Move jaxrpc to VIVO --- dependencies/pom.xml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/dependencies/pom.xml b/dependencies/pom.xml index 856f37d30..1b4bbf68f 100644 --- a/dependencies/pom.xml +++ b/dependencies/pom.xml @@ -317,10 +317,5 @@ mail 1.4 - - javax.xml - jaxrpc - 1.1 - From 890d908a6a1da791aeccf7be059816a16e7d0d87 Mon Sep 17 00:00:00 2001 From: Graham Triggs Date: Sat, 24 Dec 2016 12:12:43 +0000 Subject: [PATCH 37/49] Allow owlapi to use transitive dependencies --- dependencies/pom.xml | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/dependencies/pom.xml b/dependencies/pom.xml index 1b4bbf68f..0493494c7 100644 --- a/dependencies/pom.xml +++ b/dependencies/pom.xml @@ -183,26 +183,6 @@ - - net.sourceforge.owlapi - owlapi-impl - 5.0.4 - - - net.sourceforge.owlapi - owlapi-oboformat - 5.0.4 - - - net.sourceforge.owlapi - owlapi-parsers - 5.0.4 - - - net.sourceforge.owlapi - owlapi-tools - 5.0.4 - org.semarglproject semargl-core From 49c5b561f91294304f24ac8660373e59cc2fe7b4 Mon Sep 17 00:00:00 2001 From: Graham Triggs Date: Sat, 24 Dec 2016 12:27:26 +0000 Subject: [PATCH 38/49] Migrate last dependencies on commons-lang 2.x --- .../vitro/webapp/edit/n3editing/VTwo/EditN3GeneratorVTwo.java | 4 ++-- api/src/main/java/org/linkeddatafragments/util/MIMEParse.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/EditN3GeneratorVTwo.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/EditN3GeneratorVTwo.java index ebcbf100d..7b1803f4f 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/EditN3GeneratorVTwo.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/EditN3GeneratorVTwo.java @@ -68,7 +68,7 @@ public class EditN3GeneratorVTwo { } log.debug("The original value String is " + values.toString()); - String valueString = org.apache.commons.lang.StringUtils.join(values, + String valueString = org.apache.commons.lang3.StringUtils.join(values, ">, <"); valueString = "<" + valueString + ">"; log.debug("The multiUri value String is " + valueString); @@ -233,7 +233,7 @@ public class EditN3GeneratorVTwo { log.debug("value of literal for " + var + " was null"); } } - String valueString = org.apache.commons.lang.StringUtils.join(n3Values, ","); + String valueString = org.apache.commons.lang3.StringUtils.join(n3Values, ","); //Substitute it in to n3 String varRegex = "\\?" + var + "(?=\\p{Punct}|\\p{Space}|$)"; diff --git a/api/src/main/java/org/linkeddatafragments/util/MIMEParse.java b/api/src/main/java/org/linkeddatafragments/util/MIMEParse.java index c6c43f80b..1bc679071 100644 --- a/api/src/main/java/org/linkeddatafragments/util/MIMEParse.java +++ b/api/src/main/java/org/linkeddatafragments/util/MIMEParse.java @@ -1,6 +1,6 @@ package org.linkeddatafragments.util; -import org.apache.commons.lang.math.NumberUtils; +import org.apache.commons.lang3.math.NumberUtils; import org.apache.commons.lang3.StringUtils; import org.linkeddatafragments.exceptions.NoRegisteredMimeTypesException; @@ -278,7 +278,7 @@ public final class MIMEParse FitnessAndQuality lastOne = weightedMatches .get(weightedMatches.size() - 1); - return NumberUtils.compare(lastOne.quality, 0) != 0 ? lastOne.mimeType : supported.get(0); + return Float.compare(lastOne.quality, 0.0f) != 0 ? lastOne.mimeType : supported.get(0); } /** From 4c952d01c64c47b1190b9be26f8ac77a74c16fc1 Mon Sep 17 00:00:00 2001 From: Graham Triggs Date: Sat, 24 Dec 2016 12:49:03 +0000 Subject: [PATCH 39/49] =?UTF-8?q?Doesn=E2=80=99t=20look=20like=20we=20need?= =?UTF-8?q?=20cxd=20or=20cos=20anymore,=20so=20commented=20out.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dependencies/pom.xml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/dependencies/pom.xml b/dependencies/pom.xml index 0493494c7..c710c8c2e 100644 --- a/dependencies/pom.xml +++ b/dependencies/pom.xml @@ -38,24 +38,24 @@ cglib 2.2 - + + + +
  • + +
    +
  • + + + + + + diff --git a/api/src/main/resources/tpf/examples.ftl.html b/api/src/main/resources/tpf/examples.ftl.html new file mode 100644 index 000000000..e7feccb52 --- /dev/null +++ b/api/src/main/resources/tpf/examples.ftl.html @@ -0,0 +1,122 @@ +
  • + + +
  • diff --git a/api/src/main/resources/tpf/index.ftl.html b/api/src/main/resources/tpf/index.ftl.html index 568db4ab5..3e8d1cac4 100644 --- a/api/src/main/resources/tpf/index.ftl.html +++ b/api/src/main/resources/tpf/index.ftl.html @@ -12,10 +12,9 @@ -

    The current dataset index contains metadata about these datasets.

    -<#include "fragment.ftl.html"> +<#include "client.ftl.html"> <@display_page/> \ No newline at end of file From 96b06fc9a50485975e4814a3c0abbd31bb1b1775 Mon Sep 17 00:00:00 2001 From: Graham Triggs Date: Tue, 31 Jan 2017 21:38:53 +0000 Subject: [PATCH 47/49] Add fluent dependency --- dependencies/pom.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/dependencies/pom.xml b/dependencies/pom.xml index 0ffe1e11c..75ee00f53 100644 --- a/dependencies/pom.xml +++ b/dependencies/pom.xml @@ -209,6 +209,12 @@ jackson-core 2.7.4
    + + + org.apache.httpcomponents + fluent-hc + 4.5.2 + org.apache.httpcomponents httpclient From ed2b570d3795998fa833732dfe79cf0fc2bbfcf9 Mon Sep 17 00:00:00 2001 From: Graham Triggs Date: Wed, 1 Feb 2017 14:39:13 +0000 Subject: [PATCH 48/49] [VIVO-1313] Swap javax JSON interface to Glassfish parser --- dependencies/pom.xml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/dependencies/pom.xml b/dependencies/pom.xml index 75ee00f53..3a00a9b8c 100644 --- a/dependencies/pom.xml +++ b/dependencies/pom.xml @@ -260,6 +260,11 @@ freemarker 2.3.23 + + org.glassfish + javax.json + 1.0.4 + org.hibernate jtidy @@ -298,11 +303,11 @@ 1.2.1 - + javax.mail mail From 1bc1f6854815093a4255f58c6ddc900dc54c65f2 Mon Sep 17 00:00:00 2001 From: hudajkhan Date: Fri, 10 Feb 2017 10:49:28 -0500 Subject: [PATCH 49/49] [VIVO-1316] moving base lookup architecture for vocabulary services to Vitro (#55) --- .../mannlib/semservices/bo/BaseObject.java | 25 ++ .../mannlib/semservices/bo/Concept.java | 163 ++++++++ .../mannlib/semservices/bo/ConceptInfo.java | 32 ++ .../semservices/bo/SemanticServicesError.java | 75 ++++ .../bo/SemanticServicesInfoBase.java | 29 ++ .../exceptions/ConceptsNotFoundException.java | 15 + .../service/ExternalConceptService.java | 27 ++ .../util/MetadataNamespaceContext.java | 26 ++ .../mannlib/semservices/util/SKOSUtils.java | 266 +++++++++++++ .../mannlib/semservices/util/XMLUtils.java | 361 ++++++++++++++++++ 10 files changed, 1019 insertions(+) create mode 100644 api/src/main/java/edu/cornell/mannlib/semservices/bo/BaseObject.java create mode 100644 api/src/main/java/edu/cornell/mannlib/semservices/bo/Concept.java create mode 100644 api/src/main/java/edu/cornell/mannlib/semservices/bo/ConceptInfo.java create mode 100644 api/src/main/java/edu/cornell/mannlib/semservices/bo/SemanticServicesError.java create mode 100644 api/src/main/java/edu/cornell/mannlib/semservices/bo/SemanticServicesInfoBase.java create mode 100644 api/src/main/java/edu/cornell/mannlib/semservices/exceptions/ConceptsNotFoundException.java create mode 100644 api/src/main/java/edu/cornell/mannlib/semservices/service/ExternalConceptService.java create mode 100644 api/src/main/java/edu/cornell/mannlib/semservices/util/MetadataNamespaceContext.java create mode 100644 api/src/main/java/edu/cornell/mannlib/semservices/util/SKOSUtils.java create mode 100644 api/src/main/java/edu/cornell/mannlib/semservices/util/XMLUtils.java diff --git a/api/src/main/java/edu/cornell/mannlib/semservices/bo/BaseObject.java b/api/src/main/java/edu/cornell/mannlib/semservices/bo/BaseObject.java new file mode 100644 index 000000000..ce4d8aa66 --- /dev/null +++ b/api/src/main/java/edu/cornell/mannlib/semservices/bo/BaseObject.java @@ -0,0 +1,25 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ +package edu.cornell.mannlib.semservices.bo; + +public class BaseObject { + /** + * Simple JavaBean domain object with an id property. + * Used as a base class for objects needing this property. + */ + private Integer id; + + public void setId(Integer id) { + this.id = id; + } + + public Integer getId() { + return id; + } + + public boolean isNew() { + return (this.id == null); + } + + + +} diff --git a/api/src/main/java/edu/cornell/mannlib/semservices/bo/Concept.java b/api/src/main/java/edu/cornell/mannlib/semservices/bo/Concept.java new file mode 100644 index 000000000..434f82ea4 --- /dev/null +++ b/api/src/main/java/edu/cornell/mannlib/semservices/bo/Concept.java @@ -0,0 +1,163 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.semservices.bo; + +import java.util.ArrayList; +import java.util.List; + +public class Concept { + + private String definedBy; + private String conceptId; + private String bestMatch; + private String label; + private String type; + private String definition; + private String uri; + private String schemeURI; + private List broaderURIList; + private List narrowerURIList; + private List exactMatchURIList; + private List closeMatchURIList; + private List altLabelList; + + /** + * default constructor + */ + public Concept() { + this.broaderURIList = new ArrayList(); + this.narrowerURIList = new ArrayList(); + this.exactMatchURIList = new ArrayList(); + this.closeMatchURIList = new ArrayList(); + } + + /** + * @return the conceptId + */ + public String getConceptId() { + return conceptId; + } + /** + * @param conceptId the conceptId to set + */ + public void setConceptId(String conceptId) { + this.conceptId = conceptId; + } + /** + * @return the label + */ + public String getLabel() { + return label; + } + /** + * @param label the label to set + */ + public void setLabel(String label) { + this.label = label; + } + /** + * @return the type + */ + public String getType() { + return type; + } + /** + * @param type the type to set + */ + public void setType(String type) { + this.type = type; + } + /** + * @return the definition + */ + public String getDefinition() { + return definition; + } + /** + * @param definition the definition to set + */ + public void setDefinition(String definition) { + this.definition = definition; + } + /** + * @return the uri + */ + public String getUri() { + return uri; + } + /** + * @param uri the uri to set + */ + public void setUri(String uri) { + this.uri = uri; + } + /** + * @return the definedBy + */ + public String getDefinedBy() { + return definedBy; + } + /** + * @param definedBy the definedBy to set + */ + public void setDefinedBy(String definedBy) { + this.definedBy = definedBy; + } + /** + * @return the schemeURI + */ + public String getSchemeURI() { + return schemeURI; + } + /** + * @param schemeURI the schemeURI to set + */ + public void setSchemeURI(String schemeURI) { + this.schemeURI = schemeURI; + } + /** + * @return the bestMatch + */ + public String getBestMatch() { + return bestMatch; + } + /** + * @param bestMatch the bestMatch to set + */ + public void setBestMatch(String bestMatch) { + this.bestMatch = bestMatch; + } +public List getBroaderURIList() { + return broaderURIList; +} +public void setBroaderURIList(List broaderURIList) { + this.broaderURIList = broaderURIList; +} +public List getNarrowerURIList() { + return narrowerURIList; +} +public void setNarrowerURIList(List narrowerURIList) { + this.narrowerURIList = narrowerURIList; +} +public List getExactMatchURIList() { + return exactMatchURIList; +} +public void setExactMatchURIList(List exactMatchURIList) { + this.exactMatchURIList = exactMatchURIList; +} +public List getCloseMatchURIList() { + return closeMatchURIList; +} +public void setCloseMatchURIList(List closeMatchURIList) { + this.closeMatchURIList = closeMatchURIList; +} + +public List getAltLabelList() { + return altLabelList; +} + +public void setAltLabelList(List altLabelList) { + this.altLabelList = altLabelList; +} + +} diff --git a/api/src/main/java/edu/cornell/mannlib/semservices/bo/ConceptInfo.java b/api/src/main/java/edu/cornell/mannlib/semservices/bo/ConceptInfo.java new file mode 100644 index 000000000..3ee08d520 --- /dev/null +++ b/api/src/main/java/edu/cornell/mannlib/semservices/bo/ConceptInfo.java @@ -0,0 +1,32 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.semservices.bo; + + +import java.util.List; + + +public class ConceptInfo extends SemanticServicesInfoBase { + + private List conceptList; + /** + * + */ + public ConceptInfo() { + super(); + } + + /** + * @return the conceptList + */ + public List getConceptList() { + return conceptList; + } + + /** + * @param conceptList the conceptList to set + */ + public void setConceptList(List conceptList) { + this.conceptList = conceptList; + } +} diff --git a/api/src/main/java/edu/cornell/mannlib/semservices/bo/SemanticServicesError.java b/api/src/main/java/edu/cornell/mannlib/semservices/bo/SemanticServicesError.java new file mode 100644 index 000000000..449f5c233 --- /dev/null +++ b/api/src/main/java/edu/cornell/mannlib/semservices/bo/SemanticServicesError.java @@ -0,0 +1,75 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.semservices.bo; + +public class SemanticServicesError { + private String message; + private String exception; + private String severity; + + /** + * + */ + public SemanticServicesError() { + super(); + } + + + + /** + * @param exception Exception description + * @param message Error message + * @param severity Severity + */ + public SemanticServicesError(String exception, String message, String severity) { + super(); + this.exception = exception; + this.message = message; + this.severity = severity; + } + + + + /** + * @return the message + */ + public String getMessage() { + return message; + } + + /** + * @param message the message to set + */ + public void setMessage(String message) { + this.message = message; + } + + /** + * @return the exception + */ + public String getException() { + return exception; + } + + /** + * @param exception the exception to set + */ + public void setException(String exception) { + this.exception = exception; + } + + /** + * @return the severity + */ + public String getSeverity() { + return severity; + } + + /** + * @param severity the severity to set + */ + public void setSeverity(String severity) { + this.severity = severity; + } + +} diff --git a/api/src/main/java/edu/cornell/mannlib/semservices/bo/SemanticServicesInfoBase.java b/api/src/main/java/edu/cornell/mannlib/semservices/bo/SemanticServicesInfoBase.java new file mode 100644 index 000000000..ac24a3ecc --- /dev/null +++ b/api/src/main/java/edu/cornell/mannlib/semservices/bo/SemanticServicesInfoBase.java @@ -0,0 +1,29 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.semservices.bo; + +public class SemanticServicesInfoBase { + + private SemanticServicesError semanticServicesError; + /** + * + */ + public SemanticServicesInfoBase() { + super(); + // TODO Auto-generated constructor stub + } + + /** + * @return the semanticServicesError + */ + public SemanticServicesError getSemanticServicesError() { + return semanticServicesError; + } + /** + * @param semanticServicesError the semanticServicesError to set + */ + public void setSemanticServicesError(SemanticServicesError semanticServicesError) { + this.semanticServicesError = semanticServicesError; + } + +} diff --git a/api/src/main/java/edu/cornell/mannlib/semservices/exceptions/ConceptsNotFoundException.java b/api/src/main/java/edu/cornell/mannlib/semservices/exceptions/ConceptsNotFoundException.java new file mode 100644 index 000000000..1264905eb --- /dev/null +++ b/api/src/main/java/edu/cornell/mannlib/semservices/exceptions/ConceptsNotFoundException.java @@ -0,0 +1,15 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.semservices.exceptions; + +public class ConceptsNotFoundException extends Exception { + /** + * An exception that indicates a service could not find a Concept + */ + private static final long serialVersionUID = -4729465393290022840L; + public ConceptsNotFoundException() { } + public ConceptsNotFoundException(String message) { super(message); } + public ConceptsNotFoundException(Throwable cause) { super(cause); } + public ConceptsNotFoundException(String message, Throwable cause) { super(message, cause); } + +} diff --git a/api/src/main/java/edu/cornell/mannlib/semservices/service/ExternalConceptService.java b/api/src/main/java/edu/cornell/mannlib/semservices/service/ExternalConceptService.java new file mode 100644 index 000000000..8a675a415 --- /dev/null +++ b/api/src/main/java/edu/cornell/mannlib/semservices/service/ExternalConceptService.java @@ -0,0 +1,27 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.semservices.service; + +import java.util.List; + +import edu.cornell.mannlib.semservices.bo.Concept; + +public interface ExternalConceptService { + + /** + * @param term Term + */ + List processResults(String term) throws Exception; + + /** + * @param term Term + * @throws Exception + */ + List getConcepts(String term) throws Exception; + + /** + * @param uri URI + */ + List getConceptsByURIWithSparql(String uri) throws Exception; + +} diff --git a/api/src/main/java/edu/cornell/mannlib/semservices/util/MetadataNamespaceContext.java b/api/src/main/java/edu/cornell/mannlib/semservices/util/MetadataNamespaceContext.java new file mode 100644 index 000000000..b9717e0c2 --- /dev/null +++ b/api/src/main/java/edu/cornell/mannlib/semservices/util/MetadataNamespaceContext.java @@ -0,0 +1,26 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.semservices.util; +import java.util.Iterator; +import javax.xml.XMLConstants; +import javax.xml.namespace.NamespaceContext; + +public class MetadataNamespaceContext implements NamespaceContext { + public String getNamespaceURI(String prefix) { + if (prefix == null) throw new NullPointerException("Null prefix"); + else if ("mix".equals(prefix)) return "http://www.loc.gov/mix/"; + else if ("xml".equals(prefix)) return XMLConstants.XML_NS_URI; + return XMLConstants.NULL_NS_URI; + } + + // This method isn't necessary for XPath processing. + public String getPrefix(String uri) { + throw new UnsupportedOperationException(); + } + + // This method isn't necessary for XPath processing either. + public Iterator getPrefixes(String uri) { + throw new UnsupportedOperationException(); + } + +} diff --git a/api/src/main/java/edu/cornell/mannlib/semservices/util/SKOSUtils.java b/api/src/main/java/edu/cornell/mannlib/semservices/util/SKOSUtils.java new file mode 100644 index 000000000..1afe48966 --- /dev/null +++ b/api/src/main/java/edu/cornell/mannlib/semservices/util/SKOSUtils.java @@ -0,0 +1,266 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +/* We are no longer using the SKOS API since Vitro has moved to V 4.0 of OWL API which does not appear to be compatible. + This file will contain methods used for reading SKOS as XML and parsing it for the properties + we want to extract*/ + +package edu.cornell.mannlib.semservices.util; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.io.StringReader; +import java.io.StringWriter; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.ModelFactory; +import org.apache.jena.rdf.model.NodeIterator; +import org.apache.jena.rdf.model.RDFNode; +import org.apache.jena.rdf.model.ResourceFactory; +import org.apache.jena.rdf.model.Statement; +import org.apache.jena.rdf.model.StmtIterator; + +import edu.cornell.mannlib.semservices.bo.Concept; + +public class SKOSUtils { + protected final static Log log = LogFactory.getLog(SKOSUtils.class); + + public static String getConceptXML(String conceptUriString) { + URL conceptURL = null; + try { + conceptURL = new URL(conceptUriString); + } catch (Exception e) { + log.error("Exception occurred in instantiating URL for " + + conceptUriString, e); + // If the url is having trouble, just return null for the concept + return null; + } + log.debug("loading concept uri " + conceptUriString); + + String results = null; + try { + + StringWriter sw = new StringWriter(); + + BufferedReader in = new BufferedReader(new InputStreamReader( + conceptURL.openStream())); + String inputLine; + while ((inputLine = in.readLine()) != null) { + sw.write(inputLine); + } + in.close(); + + results = sw.toString(); + log.debug(results); + } catch (Exception ex) { + log.error("Error occurred in getting concept from the URL " + + conceptUriString, ex); + return null; + } + return results; + } + + // Downloading the XML from the URI itself + // No language tag support here but can be specified if need be at this + // level as well + public static Concept createConceptUsingXMLFromURL(Concept concept, + String conceptURLString, String langTagValue, boolean addNotes) { + String results = getConceptXML(conceptURLString); + if (StringUtils.isEmpty(results)) { + return null; + } + + // return createConceptUsingXML(concept, results, langTagValue); + return createConceptUsingXMLModel(concept, results, langTagValue, + addNotes); + + } + + // Because of the fact the xml returns matches by tag name, and the XML may + // look like + // where conceptURI is the concept that is the subject of skos:narrower, we + // need to ensure we are not returning the same uri as that of the main + // concept + public static List removeConceptURIFromList(List uris, + String conceptURI) { + // remove will return a boolean if the value exists in the list and is + // removed + // if/when it returns false, the URI is not in the list + while (uris.remove(conceptURI)) { + } + ; + return uris; + } + + /** + * The above code, although functional, does not take advantage of the fact + * that we can actually read and query the RDF in precisely the manner we + * wish. + */ + + public static Concept createConceptUsingXMLModel(Concept concept, + String results, String langTagValue, boolean addNotes) { + + try { + String conceptURI = concept.getUri(); + + // Load Model from RDF + StringReader reader = new StringReader(results); + Model model = ModelFactory.createDefaultModel(); + model.read(reader, null, "RDF/XML"); + + // Execute the following query to get the information we want for + // this resource + + // Preferred label + List labelLiterals = getPrefLabelsFromModel(conceptURI, + model, langTagValue); + if (labelLiterals.size() > 0) { + concept.setLabel(labelLiterals.get(0)); + } else { + // This is an error because there should be at least one label + // returned + log.debug("The number of preferred labels is not greater than zero"); + } + + // Alternate label + + List altLabelList = getAltLabelsFromModel(conceptURI, + model, langTagValue); + concept.setAltLabelList(altLabelList); + + // Broder, narrower, exact match, and close match properties + + List broaderURIList = getBroaderURIsFromModel(conceptURI, + model); + // broaderURIList = removeConceptURIFromList(broaderURIList, + // conceptURI); + concept.setBroaderURIList(broaderURIList); + List narrowerURIList = getNarrowerURIsFromModel(conceptURI, + model); + // narrowerURIList = removeConceptURIFromList(narrowerURIList, + // conceptURI); + concept.setNarrowerURIList(narrowerURIList); + + List exactMatchURIList = getExactMatchURIsFromModel( + conceptURI, model); + // exactMatchURIList = removeConceptURIFromList(exactMatchURIList, + // conceptURI); + concept.setExactMatchURIList(exactMatchURIList); + List closeMatchURIList = getCloseMatchURIsFromModel( + conceptURI, model); + // closeMatchURIList = removeConceptURIFromList(closeMatchURIList, + // conceptURI); + concept.setCloseMatchURIList(closeMatchURIList); + + // Notes may exist, in which case they should be employed + if (addNotes) { + List notes = getNotesFromModel(conceptURI, model, + langTagValue); + if (notes.size() > 0) { + concept.setDefinition(notes.get(0)); + } + } + + } catch (Exception e) { + log.error("error occurred in parsing " + results, e); + } + + return concept; + + } + + private static List getPrefLabelsFromModel(String conceptURI, + Model model, String langTagValue) { + String propertyURI = "http://www.w3.org/2004/02/skos/core#prefLabel"; + return getLabelsFromModel(conceptURI, propertyURI, model, langTagValue); + } + + private static List getAltLabelsFromModel(String conceptURI, + Model model, String langTagValue) { + String propertyURI = "http://www.w3.org/2004/02/skos/core#altLabel"; + return getLabelsFromModel(conceptURI, propertyURI, model, langTagValue); + } + + private static List getLabelsFromModel(String conceptURI, + String propertyURI, Model model, String langTagValue) { + List labels = new ArrayList(); + StmtIterator statements = model.listStatements( + ResourceFactory.createResource(conceptURI), + ResourceFactory.createProperty(propertyURI), (RDFNode) null); + while (statements.hasNext()) { + Statement statement = statements.nextStatement(); + RDFNode node = statement.getObject(); + if (node != null && node.isLiteral()) { + String label = node.asLiteral().getString(); + if (StringUtils.isNotEmpty(langTagValue)) { + String language = node.asLiteral().getLanguage(); + if (language != null && language.equals(langTagValue)) { + labels.add(label); + } + } else { + labels.add(label); + } + } + + } + return labels; + } + + private static List getNotesFromModel(String conceptURI, + Model model, String langTagValue) { + String propertyURI = "http://www.w3.org/2004/02/skos/core#note"; + return getLabelsFromModel(conceptURI, propertyURI, model, langTagValue); + } + + private static List getCloseMatchURIsFromModel(String conceptURI, + Model model) { + String propertyURI = "http://www.w3.org/2004/02/skos/core#closeMatch"; + return getRelatedURIsFromModel(conceptURI, propertyURI, model); + + } + + private static List getExactMatchURIsFromModel(String conceptURI, + Model model) { + String propertyURI = "http://www.w3.org/2004/02/skos/core#exactMatch"; + return getRelatedURIsFromModel(conceptURI, propertyURI, model); + } + + private static List getNarrowerURIsFromModel(String conceptURI, + Model model) { + String propertyURI = "http://www.w3.org/2004/02/skos/core#narrower"; + return getRelatedURIsFromModel(conceptURI, propertyURI, model); + } + + private static List getBroaderURIsFromModel(String conceptURI, + Model model) { + String propertyURI = "http://www.w3.org/2004/02/skos/core#broader"; + return getRelatedURIsFromModel(conceptURI, propertyURI, model); + } + + private static List getRelatedURIsFromModel(String conceptURI, + String propertyURI, Model model) { + List URIs = new ArrayList(); + NodeIterator nodeIterator = model.listObjectsOfProperty( + ResourceFactory.createResource(conceptURI), + ResourceFactory.createProperty(propertyURI)); + + while (nodeIterator.hasNext()) { + RDFNode node = nodeIterator.nextNode(); + if (node.isResource() && node.asResource().getURI() != null) { + String URI = node.asResource().getURI(); + URIs.add(URI); + } + } + + return URIs; + } + +} \ No newline at end of file diff --git a/api/src/main/java/edu/cornell/mannlib/semservices/util/XMLUtils.java b/api/src/main/java/edu/cornell/mannlib/semservices/util/XMLUtils.java new file mode 100644 index 000000000..b5342c5c8 --- /dev/null +++ b/api/src/main/java/edu/cornell/mannlib/semservices/util/XMLUtils.java @@ -0,0 +1,361 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.semservices.util; + +import java.io.BufferedWriter; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStreamWriter; +import java.io.StringReader; +import java.io.StringWriter; +import java.io.Writer; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Source; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.TransformerFactoryConfigurationError; +import javax.xml.transform.stream.StreamResult; +import javax.xml.transform.stream.StreamSource; +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFactory; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.w3c.dom.Document; +import org.w3c.dom.DocumentType; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +/** + * Convenience Class to parse XML strings to DOM Document for XML contents + * retrieval. + */ +public class XMLUtils { + private static DocumentBuilder parser; + public static Writer writer; + static private String indent = ""; + protected static final Log logger = LogFactory.getLog(XMLUtils.class); + + + /** + * @throws ParserConfigurationException + */ + public static DocumentBuilder getDocumentBuilder() + throws ParserConfigurationException { + if (parser == null) { + // JPT: Remove xerces use + DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory + .newInstance(); + documentBuilderFactory.setNamespaceAware(true); + documentBuilderFactory.setValidating(false); + parser = documentBuilderFactory.newDocumentBuilder(); + } + + return parser; + } + + /** + * @param xmlString XML String + * @throws IOException + * @throws SAXException + * @throws ParserConfigurationException + */ + public synchronized static Document parse(String xmlString) + throws IOException, SAXException, ParserConfigurationException { + StringReader reader = new StringReader(xmlString); + InputSource inputSource = new InputSource(reader); + return getDocumentBuilder().parse(inputSource); + } + + /** + * @param stream Input stream + * @throws IOException + * @throws SAXException + * @throws ParserConfigurationException + */ + public synchronized static Document parse(InputStream stream) + throws IOException, SAXException, ParserConfigurationException { + return getDocumentBuilder().parse(stream); + } + + /** + * @param document DOM Document + * @param name Name + */ + public static String getElementByName(Document document, String name) { + NodeList nodes = document.getElementsByTagName(name); + String s = null; + for (int i=0; i < nodes.getLength() ; i++) { + Node node = nodes.item(i); + s = node.getTextContent().trim(); + } + return s; + } + + /** + * @param doc DOM Document + * @throws IOException + */ + @SuppressWarnings("deprecation") + public static void serializeDoc(Document doc) throws IOException { + org.apache.xml.serialize.XMLSerializer serializer = new org.apache.xml.serialize.XMLSerializer(); + serializer.setOutputByteStream(System.out); + serializer.serialize(doc); + } + + @SuppressWarnings("deprecation") + public static String serializeDoctoString(Document doc) throws IOException { + org.apache.xml.serialize.XMLSerializer serializer = new org.apache.xml.serialize.XMLSerializer(); + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + + serializer.setOutputByteStream(bout); + serializer.serialize(doc); + return bout.toString(); + } + + /** + * @param xml XML String + */ + public static void prettyPrint(String xml) { + Source xmlInput = new StreamSource(new StringReader(xml)); + StreamResult xmlOutput = new StreamResult(new StringWriter()); + Transformer transformer = null; + try { + transformer = TransformerFactory.newInstance().newTransformer(); + } catch (TransformerConfigurationException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (TransformerFactoryConfigurationError e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + //transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, "testing.dtd"); + transformer.setOutputProperty(OutputKeys.INDENT, "yes"); + transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); + try { + transformer.transform(xmlInput, xmlOutput); + } catch (TransformerException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + String formattedxml=xmlOutput.getWriter().toString(); + System.out.println(formattedxml); + + } + + /** + * @param xml XML String + */ + public static String prettyPrintToString(String xml) { + Source xmlInput = new StreamSource(new StringReader(xml)); + StreamResult xmlOutput = new StreamResult(new StringWriter()); + Transformer transformer = null; + try { + transformer = TransformerFactory.newInstance().newTransformer(); + } catch (TransformerConfigurationException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (TransformerFactoryConfigurationError e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + //transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, "testing.dtd"); + transformer.setOutputProperty(OutputKeys.INDENT, "yes"); + transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); + try { + transformer.transform(xmlInput, xmlOutput); + } catch (TransformerException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + String formattedxml=xmlOutput.getWriter().toString(); + return formattedxml; + + } + + /** + * @param node DOM Node + */ + public static void displayNodeInfo(Node node) { + switch (node.getNodeType()) { + case Node.DOCUMENT_NODE: + System.out.println("Document Node "); + break; + case Node.ELEMENT_NODE: + System.out.println("Element Node: "+ node.getNodeName()); + break; + case Node.TEXT_NODE: + System.out.println("Text Node: "+ node.getNodeName()); + break; + case Node.CDATA_SECTION_NODE: + System.out.println("CDATA Section Node: "); + break; + case Node.COMMENT_NODE: + System.out.println("Comment Node "); + break; + case Node.PROCESSING_INSTRUCTION_NODE: + System.out.println("Processing Instruction Node "); + break; + case Node.ENTITY_REFERENCE_NODE: + System.out.println("Entity Reference Node "); + break; + case Node.DOCUMENT_TYPE_NODE: + System.out.println("Document Type Node "); + break; + } + } + + /** + * @param node DOM Node + * @throws IOException + */ + public static void serializeNode(Node node) throws IOException { + if (writer == null) writer = new BufferedWriter(new OutputStreamWriter(System.out)); + + switch (node.getNodeType()) { + case Node.DOCUMENT_NODE: + Document doc = (Document) node; + writer.write("\n"); + + NodeList nodes = node.getChildNodes(); + if (nodes != null) + for (int i = 0; i < nodes.getLength(); i++) + serializeNode(nodes.item(i)); + break; + case Node.ELEMENT_NODE: + String name = node.getNodeName(); + writer.write("<" + name); + NamedNodeMap attributes = node.getAttributes(); + for (int i = 0; i < attributes.getLength(); i++) { + Node current = attributes.item(i); + writer.write(" " + current.getNodeName() + "=\""); + print(current.getNodeValue()); + writer.write("\""); + } + writer.write(">"); + + NodeList children = node.getChildNodes(); + if (children != null) { + //if ((children.item(0) != null) && (children.item(0).getNodeType() == Node.ELEMENT_NODE)) + // writer.write("\n"); + + for (int i = 0; i < children.getLength(); i++) + serializeNode(children.item(i)); + if ((children.item(0) != null) + && (children.item(children.getLength() - 1).getNodeType() == Node.ELEMENT_NODE)) + writer.write(""); + } + + writer.write(""); + break; + case Node.TEXT_NODE: + print(node.getNodeValue()); + break; + case Node.CDATA_SECTION_NODE: + writer.write("CDATA"); + print(node.getNodeValue()); + writer.write(""); + break; + case Node.COMMENT_NODE: + writer.write("\n"); + break; + case Node.PROCESSING_INSTRUCTION_NODE: + writer.write("\n"); + break; + case Node.ENTITY_REFERENCE_NODE: + writer.write("&" + node.getNodeName() + ";"); + break; + case Node.DOCUMENT_TYPE_NODE: + DocumentType docType = (DocumentType) node; + String publicId = docType.getPublicId(); + String systemId = docType.getSystemId(); + String internalSubset = docType.getInternalSubset(); + writer.write("\n"); + break; + } + writer.flush(); + } + + /** + * @param s String + * @throws IOException + */ + private static void print(String s) throws IOException { + if (s == null) + return; + for (int i = 0, len = s.length(); i < len; i++) { + char c = s.charAt(i); + switch (c) { + case '<': + writer.write("<"); + break; + case '>': + writer.write(">"); + break; + case '&': + writer.write("&"); + break; + case '\r': + writer.write(" "); + break; + default: + writer.write(c); + } + } + } + + /** + * @param obj (either a Document or a Node) + * @param expression Expression + * @return string contents + */ + public static Node getNodeWithXpath(Object obj, String expression) { + Object root = null; + if (obj instanceof Document) { + Document doc = (Document) obj; + root = doc.getDocumentElement(); + } else { + root = (Node) obj; + } + + XPath xpath = XPathFactory.newInstance().newXPath(); + xpath.setNamespaceContext(new MetadataNamespaceContext()); + Node result = null; + + try { + result = ((Node) xpath.evaluate(expression, root, XPathConstants.NODE)); + return result; + } catch (XPathExpressionException e) { + logger.error("XPathExpressionException ", e); + return null; + } + } + +}