diff --git a/.gitignore b/.gitignore index ae5cbdb8..d5374069 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,5 @@ /deploy.properties /build.properties /runtime.properties +/ontology/public/catalog-v0001.xml + diff --git a/build.xml b/build.xml index ba031f79..c19a9b9a 100644 --- a/build.xml +++ b/build.xml @@ -69,8 +69,10 @@ + + diff --git a/config/licenser/licenser.properties b/config/licenser/licenser.properties index 237353ee..90b3ff73 100644 --- a/config/licenser/licenser.properties +++ b/config/licenser/licenser.properties @@ -32,6 +32,3 @@ license_file = doc/license.txt # Set to 'full' for a full report, 'short' for a brief statment, or to anything # else for a medium-length summary. report_level = short - -# if true, we are just scanning, not copying. -scan_only = true \ No newline at end of file diff --git a/doc/install.html b/doc/install.html index 33423d77..7740fd0f 100644 --- a/doc/install.html +++ b/doc/install.html @@ -316,18 +316,35 @@ /usr/local/vivo/home + + + Languages (in addition to American English) that will be built into your + VIVO site. The languages must be found in the + languages directory of the VIVO distribution. + See + the VIVO Wiki for more information. + + + + + languages.addToBuild + + + es_MX + +

5. Specify runtime properties

- In Step 4, you defined the location of the Vitro home directory, + In Step 4, you defined the location of the VIVO home directory, by specifying vitro.home in the build.properties file. Create that directory now.

At the top level of the VIVO distribution directory, you will find a file called - example.runtime.properties. Copy this to the Vitro home directory you have created, + example.runtime.properties. Copy this to the VIVO home directory you have created, renaming the copy to runtime.properties. Edit the file to suit your installation, as described in the following table.

diff --git a/doc/upgrade-1.6.html b/doc/upgrade-1.6.html index 0ee222ad..1e25bdfe 100644 --- a/doc/upgrade-1.6.html +++ b/doc/upgrade-1.6.html @@ -48,6 +48,8 @@
  • The foaf:Person template has been re-located.
  • Multiple foaf:Person Profile Pages
  • Home Page Re-design
  • +
  • Auto-loaded RDF files move to the Home directory
  • +
  • Support for additional languages
  • ANYTHING ELSE?
  • @@ -228,6 +230,163 @@ areas of geographic focus.

    +

    Auto-loaded RDF files move to the Home directory

    +

    + The RDF files that initialize the data model have moved, in both the distribution and + the runtime locations. + In the distribution, they have been collected in one place, and reorganized to use + a more consistent naming scheme. During the build process, they are copied to a + location within the VIVO home directory, instead of residing in the webapp itself. +

    +

    + If you have modified these RDF files, or added files of your own, you must adjust to + the new locations accordingly. + +

    +
    Old locations of RDF files
    +
    /WEB-INF/ontologies/app/application.owl
    +/WEB-INF/ontologies/app/aboutPage.n3
    +/WEB-INF/ontologies/app/menu.n3
    +/WEB-INF/ontologies/app/profilePageType.n3
    +/WEB-INF/ontologies/app/loadedAtStartup/displayModelListViews.rdf
    +/WEB-INF/ontologies/app/loadedAtStartup/homePageDataGetters.n3
    +/WEB-INF/ontologies/app/loadedAtStartup/localeSelectionGUI.n3
    +/WEB-INF/ontologies/app/loadedAtStartup/vivoListViewConfig.rdf
    +/WEB-INF/ontologies/app/loadedAtStartup/vivoOrganizationDataGetters.n3
    +/WEB-INF/ontologies/app/loadedAtStartup/vivoSearchProhibited.n3
    +/WEB-INF/ontologies/app/menuload/displayTBOX.n3
    +/WEB-INF/ontologies/app/menuload/displayDisplay.n3
    +/WEB-INF/init-data/initialSiteConfig.rdf
    +/WEB-INF/ontologies/user/abox/geopolitical.ver1.1-11-18-11-individual-labels.rdf
    +/WEB-INF/ontologies/user/abox/vocabularySource-labels.n3
    +/WEB-INF/ontologies/user/tbox/vitro-0.7-annotations.rdf
    +/WEB-INF/ontologies/user/tbox/geopolitical-ver1.1-11-18-11-annotations.rdf
    +/WEB-INF/ontologies/user/tbox/scires-1.5-annotations.rdf
    +/WEB-INF/ontologies/user/tbox/vivo-core-1.5-annotations.rdf
    +/WEB-INF/ontologies/user/tbox/isDefinedBy-1.5-annotations.rdf
    +/WEB-INF/ontologies/user/applicationMetadata/propertygroups.rdf
    +/WEB-INF/ontologies/user/applicationMetadata/classgroups.rdf
    +/WEB-INF/filegraph/abox/us-states.rdf
    +/WEB-INF/filegraph/abox/geopolitical.abox.ver1.1-11-18-11.owl
    +/WEB-INF/filegraph/abox/academicDegree.rdf
    +/WEB-INF/filegraph/abox/documentStatus.owl
    +/WEB-INF/filegraph/abox/continents.n3
    +/WEB-INF/filegraph/abox/vocabularySource.n3
    +/WEB-INF/filegraph/abox/dateTimeValuePrecision.owl
    +/WEB-INF/filegraph/tbox/vitroPublic.owl
    +/WEB-INF/filegraph/tbox/vivo-dcterms-1.5.owl
    +/WEB-INF/filegraph/tbox/scires-1.5.owl
    +/WEB-INF/filegraph/tbox/vivo-core-1.5.owl
    +/WEB-INF/filegraph/tbox/vivo-c4o-1.5.owl
    +/WEB-INF/filegraph/tbox/geopolitical.tbox.ver1.1-11-18-11.owl
    +/WEB-INF/filegraph/tbox/vivo-fabio-1.5.owl
    +/WEB-INF/filegraph/tbox/vivo-skos-1.5.owl
    +/WEB-INF/filegraph/tbox/vivo-event-1.5.owl
    +/WEB-INF/filegraph/tbox/vivo-foaf-1.5.owl
    +/WEB-INF/filegraph/tbox/vitro-0.7.owl
    +/WEB-INF/filegraph/tbox/vivo-pws-1.5.owl
    +/WEB-INF/filegraph/tbox/isDefinedBy-1.5.owl
    +/WEB-INF/filegraph/tbox/vivo-dcelements-1.5.owl
    +/WEB-INF/filegraph/tbox/vivo-bibo-1.5.owl
    + +
    New locations of RDF files
    +
    rdf/display/firsttime/aboutPage.n3
    +rdf/display/firsttime/application.owl
    +rdf/display/firsttime/menu.n3
    +rdf/display/firsttime/profilePageType.n3
    +rdf/display/everytime/displayModelListViews.rdf
    +rdf/display/everytime/homePageDataGetters.n3
    +rdf/display/everytime/localeSelectionGUI.n3
    +rdf/display/everytime/vivoListViewConfig.rdf
    +rdf/display/everytime/vivoOrganizationDataGetters.n3
    +rdf/display/everytime/vivoSearchProhibited.n3
    +rdf/displayTbox/everytime/displayTBOX.n3
    +rdf/displayDisplay/everytime/displayDisplay.n3
    +rdf/applicationMetadata/firsttime/classgroups.rdf
    +rdf/applicationMetadata/firsttime/initialSiteConfig.rdf
    +rdf/applicationMetadata/firsttime/propertygroups.rdf
    +rdf/abox/firsttime/geopolitical.ver1.1-11-18-11-individual-labels.rdf
    +rdf/abox/firsttime/vocabularySource-labels.n3
    +rdf/abox/filegraph/abox/academicDegree.rdf
    +rdf/abox/filegraph/abox/continents.n3
    +rdf/abox/filegraph/abox/dateTimeValuePrecision.owl
    +rdf/abox/filegraph/abox/documentStatus.owl
    +rdf/abox/filegraph/abox/geopolitical.abox.ver1.1-11-18-11.owl
    +rdf/abox/filegraph/abox/us-states.rdf
    +rdf/abox/filegraph/abox/vocabularySource.n3
    +rdf/tbox/firsttime/geopolitical-ver1.1-11-18-11-annotations.rdf
    +rdf/tbox/firsttime/isDefinedBy-1.5-annotations.rdf
    +rdf/tbox/firsttime/scires-1.5-annotations.rdf
    +rdf/tbox/firsttime/vitro-0.7-annotations.rdf
    +rdf/tbox/firsttime/vivo-core-1.5-annotations.rdf
    +rdf/tbox/filegraph/tbox/geopolitical.tbox.ver1.1-11-18-11.owl
    +rdf/tbox/filegraph/tbox/isDefinedBy-1.5.owl
    +rdf/tbox/filegraph/tbox/scires-1.5.owl
    +rdf/tbox/filegraph/tbox/vitro-0.7.owl
    +rdf/tbox/filegraph/tbox/vitroPublic.owl
    +rdf/tbox/filegraph/tbox/vivo-bibo-1.5.owl
    +rdf/tbox/filegraph/tbox/vivo-c4o-1.5.owl
    +rdf/tbox/filegraph/tbox/vivo-core-1.5.owl
    +rdf/tbox/filegraph/tbox/vivo-dcelements-1.5.owl
    +rdf/tbox/filegraph/tbox/vivo-dcterms-1.5.owl
    +rdf/tbox/filegraph/tbox/vivo-event-1.5.owl
    +rdf/tbox/filegraph/tbox/vivo-fabio-1.5.owl
    +rdf/tbox/filegraph/tbox/vivo-foaf-1.5.owl
    +rdf/tbox/filegraph/tbox/vivo-pws-1.5.owl
    +rdf/tbox/filegraph/tbox/vivo-skos-1.5.owl
    +

    + If you are using a three-tier build process, you will need to add a single line + to the build script so the RDF files will be merged properly across the tiers. So this: +

    <patternset id="appbase.patterns">
    +<include name="src/**/*" />
    +<include name="lib/**/*" />
    +<include name="test/**/*" />
    +<include name="themes/**/*" />
    +<include name="config/*.properties" />
    +<include name="config/*.txt" />
    +<include name="config/jarlist/*.txt" />
    +<include name="config/solr/*" />
    +<include name="context.xml" />
    +</patternset>
    + becomes this: +
    <patternset id="appbase.patterns">
    +<include name="src/**/*" />
    +<include name="lib/**/*" />
    +<include name="rdf/**/*" />
    +<include name="test/**/*" />
    +<include name="themes/**/*" />
    +<include name="config/*.properties" />
    +<include name="config/*.txt" />
    +<include name="config/jarlist/*.txt" />
    +<include name="config/solr/*" />
    +<include name="context.xml" />
    +</patternset>
    +

    + +

    Support for additional languages

    +

    + VIVO 1.6 includes limited support for other languages, in addition to American English. + This limited support is described as read-only support on public-facing + pages. +

    +

    + Read-only means that there is no provision for editing multi-language + data or displays. Property values, ontology labels, etc. must all be provided in RDF files + and ingested or otherwise inserted into the data model. The Page Management user interface + does not support maintaining pages in multiple languages. +

    +

    + Public-facing means that most of the pages used for site adminstration + are only presented in American English. +

    +

    + These two pages in the VIVO Wiki describe how to + + Build VIVO with multiple languages and how to + + Add a new language to VIVO. +

    +

    ANYTHING ELSE?

    @@ -260,7 +419,7 @@ -

    III. Upgrade Instructions

    +

    III. Upgrade Instructions

    1. Download the new distribution file and unpack it into a new @@ -268,9 +427,9 @@

    2. Separate your existing deploy.properties file into two files, - as described below. The new build.properties file is stored in - the top level of the VIVO distribution directory. The new runtime.properties - file is stored in your Vitro home directory. + as described below. Store the new build.properties file in + the top level of the VIVO distribution directory. Store the new runtime.properties + file in your VIVO home directory.

    @@ -307,9 +466,48 @@

    If you prefer, you may start with example.build.properties and example.runtime.properties, make copies, - and edit them to suit your installation. + and edit them to suit your installation. Remember, the runtime.properties file + goes into your VIVO home directory.

    +

    + The properties below are new to build.properties. They are optional, + so you need not add them unless you want a value other than the default. +

    +

    + +

    +
    + + + + + + + + + + + + + + +
    + Property Name + + Example Value +
    + Languages (in addition to American English) that will be built into your + VIVO site. The languages must be found in the + languages directory of the VIVO distribution. + See + the VIVO Wiki for more information. +
    + languages.addToBuild + + es_MX +
    +

    The properties below are new to runtime.properties. They are optional, so you need not add them, unless you want a value other than the default. @@ -514,6 +712,11 @@ +

    + 4. Apply any previous changes you have made to the RDF initialization files. + See the section on the Auto-loaded RDF files + above for more details. +

    5. Stop Apache Tomcat and from your VIVO source directory, run ant diff --git a/example.build.properties b/example.build.properties index 16c2b598..64fb99f2 100644 --- a/example.build.properties +++ b/example.build.properties @@ -37,3 +37,10 @@ webapp.name = vivo # This includes uploaded files (usually images) and the search index. # vitro.home = /usr/local/vivo/home + +# +# Additional languages to be built into your VIVO site. The locales specified +# here must appear as sub-directories of [vivo]/languages in the distribution. +# Find more information on the VIVO Wiki (https://wiki.duraspace.org/display/VIVO). +# +#languages.addToBuild = diff --git a/productMods/WEB-INF/ontologies/user/applicationMetadata/classgroups_labels_es.n3 b/languages/example/rdf/applicationMetadata/firsttime/classgroups_labels_es.n3 similarity index 100% rename from productMods/WEB-INF/ontologies/user/applicationMetadata/classgroups_labels_es.n3 rename to languages/example/rdf/applicationMetadata/firsttime/classgroups_labels_es.n3 diff --git a/productMods/WEB-INF/ontologies/user/applicationMetadata/propertygroups_labels_es.n3 b/languages/example/rdf/applicationMetadata/firsttime/propertygroups_labels_es.n3 similarity index 100% rename from productMods/WEB-INF/ontologies/user/applicationMetadata/propertygroups_labels_es.n3 rename to languages/example/rdf/applicationMetadata/firsttime/propertygroups_labels_es.n3 diff --git a/productMods/WEB-INF/ontologies/app/loadedAtStartup/aboutPage_es.n3 b/languages/example/rdf/display/firsttime/aboutPage_es.n3 similarity index 95% rename from productMods/WEB-INF/ontologies/app/loadedAtStartup/aboutPage_es.n3 rename to languages/example/rdf/display/firsttime/aboutPage_es.n3 index 8d8ddd69..74f7a3c4 100644 --- a/productMods/WEB-INF/ontologies/app/loadedAtStartup/aboutPage_es.n3 +++ b/languages/example/rdf/display/firsttime/aboutPage_es.n3 @@ -7,7 +7,7 @@ about:ABOUTDG """

    Acerca VIVO

    La aplicación VIVO permite el descubrimiento de los investigadores a través de las instituciones. Los participantes en la red se encuentran instituciones con instalaciones locales de VIVO o con la investigación y el descubrimiento de aplicaciones de perfiles que pueden proporcionar datos web compatibles semánticas. Por tanto, la información accesible a través de la búsqueda de VIVO y capacidad de exploración se residir y ser controlado a nivel local, dentro de vivos institucionales o de otras aplicaciones web compatibles con semánticos.

    -

    VIVO es una aplicación web semántica código abierto originalmente desarrollado e implementado en Cornell. Cuando se instala y se rellena con el contenido en una institución, que permite el descubrimiento de la investigación y de becas en todas las disciplinas de esta institución. VIVO compatible con la navegación y una función de búsqueda que devuelve resultados facetas para una rápida recuperación de la información deseada. Contenido en cualquier instalación VIVO local puede mantenerse manualmente o puesto en la base de datos de forma automática de los sistemas locales de registro, tales como recursos humanos, carreras impulsadas, becas, cursos, y bases de datos de la actividad docente.

    +

    VIVO es una aplicación web semántica código abierto originalmente desarrollado e implementado en Cornell. Cuando se instala y se rellena con el contenido en una institución, que permite el descubrimiento de la investigación y de becas en todas las disciplinas de esta institución. VIVO compatible con la navegación y una función de búsqueda que devuelve resultados facetas para una rápida recuperación de la información deseada. Contenido en cualquier instalación VIVO local puede mantenerse manualmente o puesto en la base de datos de forma automática de los sistemas locales de registro, tales como recursos humanos, becas, cursos, y bases de datos de la actividad docente.

    Ver más información sobre el Proyecto VIVO.

    """@es . \ No newline at end of file diff --git a/productMods/WEB-INF/ontologies/app/loadedAtStartup/menu_es.n3 b/languages/example/rdf/display/firsttime/menu_es.n3 similarity index 100% rename from productMods/WEB-INF/ontologies/app/loadedAtStartup/menu_es.n3 rename to languages/example/rdf/display/firsttime/menu_es.n3 diff --git a/productMods/WEB-INF/ontologies/user/tbox/vivo-core-1.5-labels_es.n3 b/languages/example/rdf/tbox/firsttime/vivo-core-1.5-labels_es.n3 similarity index 100% rename from productMods/WEB-INF/ontologies/user/tbox/vivo-core-1.5-labels_es.n3 rename to languages/example/rdf/tbox/firsttime/vivo-core-1.5-labels_es.n3 diff --git a/productMods/templates/freemarker/visualization/mapOfScience/aboutMapOfScience_es.ftl b/languages/example/templates/freemarker/aboutMapOfScience_es.ftl similarity index 100% rename from productMods/templates/freemarker/visualization/mapOfScience/aboutMapOfScience_es.ftl rename to languages/example/templates/freemarker/aboutMapOfScience_es.ftl diff --git a/productMods/templates/freemarker/body/aboutQrCodes_es.ftl b/languages/example/templates/freemarker/aboutQrCodes_es.ftl similarity index 100% rename from productMods/templates/freemarker/body/aboutQrCodes_es.ftl rename to languages/example/templates/freemarker/aboutQrCodes_es.ftl diff --git a/productMods/templates/freemarker/visualization/mapOfScience/mapOfScienceTooltips_es.ftl b/languages/example/templates/freemarker/mapOfScienceTooltips_es.ftl similarity index 100% rename from productMods/templates/freemarker/visualization/mapOfScience/mapOfScienceTooltips_es.ftl rename to languages/example/templates/freemarker/mapOfScienceTooltips_es.ftl diff --git a/themes/wilma/i18n/all_es.properties b/languages/example/themes/wilma/i18n/all_es.properties similarity index 100% rename from themes/wilma/i18n/all_es.properties rename to languages/example/themes/wilma/i18n/all_es.properties diff --git a/themes/wilma/i18n/images/select_locale_es_ES.GIF b/languages/example/themes/wilma/i18n/images/select_locale_es_ES.GIF similarity index 100% rename from themes/wilma/i18n/images/select_locale_es_ES.GIF rename to languages/example/themes/wilma/i18n/images/select_locale_es_ES.GIF diff --git a/lib/agrovoc_ws.jar b/lib/agrovoc_ws.jar deleted file mode 100644 index d8eb97b0..00000000 Binary files a/lib/agrovoc_ws.jar and /dev/null differ diff --git a/lib/agrovocws-3.0.jar b/lib/agrovocws-3.0.jar new file mode 100644 index 00000000..5581be71 Binary files /dev/null and b/lib/agrovocws-3.0.jar differ diff --git a/lib/commons-beanutils.jar b/lib/commons-beanutils.jar deleted file mode 100644 index b1b89c9c..00000000 Binary files a/lib/commons-beanutils.jar and /dev/null differ diff --git a/lib/ehcache-spring-annotations-1.1.3.jar b/lib/ehcache-spring-annotations-1.1.3.jar new file mode 100644 index 00000000..be81cf7f Binary files /dev/null and b/lib/ehcache-spring-annotations-1.1.3.jar differ diff --git a/lib/ezmorph-1.0.4.jar b/lib/ezmorph-1.0.4.jar deleted file mode 100644 index 7625af67..00000000 Binary files a/lib/ezmorph-1.0.4.jar and /dev/null differ diff --git a/lib/htmlparser.jar b/lib/htmlparser.jar new file mode 100644 index 00000000..fad7a207 Binary files /dev/null and b/lib/htmlparser.jar differ diff --git a/lib/json-lib-2.2.2-jdk15.jar b/lib/json-lib-2.2.2-jdk15.jar deleted file mode 100644 index 27e7c7cc..00000000 Binary files a/lib/json-lib-2.2.2-jdk15.jar and /dev/null differ diff --git a/lib/owlapi-bin.jar b/lib/owlapi-bin.jar new file mode 100644 index 00000000..17ce372e Binary files /dev/null and b/lib/owlapi-bin.jar differ diff --git a/lib/skosapi-3-bin.jar b/lib/skosapi-3-bin.jar new file mode 100644 index 00000000..8a484059 Binary files /dev/null and b/lib/skosapi-3-bin.jar differ diff --git a/olddeploy.properties b/olddeploy.properties new file mode 100644 index 00000000..f4c7ed7d --- /dev/null +++ b/olddeploy.properties @@ -0,0 +1,162 @@ +# ----------------------------------------------------------------------------- +# +# VIVO deployment properties +# +# This file is provided as example.deploy.properties. +# +# Save a copy of this file as deploy.properties, and edit the properties as +# needed for your deployment. +# +# ----------------------------------------------------------------------------- + +# +# This namespace will be used when generating URIs for objects created in the +# editor. Change it to reflect your own domain. For example, Cornell's +# namespace is http://vivo.cornell.edu/individual/ +# +# Note: it is essential that this namespace end with a trailing slash. +# +Vitro.defaultNamespace = http://vivo.mannlib.cornell.edu/individual/ + +# +# Where is the Vitro core directory? +# In most deployments, this is set to ./vitro-core (It is not uncommon for this +# setting to point elsewhere in development environments). +# Examples: +# vitro.core.dir = ./vitro-core +# vitro.core.dir = ../vitro +# vitro.core.dir = /usr/local/vitro/trunk +vitro.core.dir = ../vivovitro + +# +# The base install directory for your Tomcat server. The VIVO application +# will be deployed in the /webapps directory below this base. +# +tomcat.home = C:/apache/apache-tomcat-7.0.40 + +# +# The name of the VIVO application. This will be used as the name of the +# subdirectory within your Tomcat server's /webapps directory. It also appears +# in the URL for the application. For example, http://my.vivo.server/vivo +# +webapp.name = vivo + +# +# The location where the VIVO application will store the data that it creates. +# This includes uploaded files (usually images) and the Lucene search index. +# +vitro.home.directory = C:/Users/hjk54/vivodata + +# +# SMTP host which the "Contact Us" form can use to send mail. If this is left +# empty, the "Contact Us" form will be disabled. +# +Vitro.smtpHost =appsmtp.mail.cornell.edu +#Added these per Jim's instructions, TO DO: try without smtpHost line +email.smtpHost = appsmtp.mail.cornell.edu +email.replyTo = hjk54@cornell.edu + +# +# The basic parameters for a database connection. Change the end of the +# URL to reflect your database name (if it is not "vitro"). Change the username +# and password to match the authorized database user you created. Increase the +# maximum size of the database connection pool if you need to serve a greater +# number of concurrent page requests. +# +#Test Empty database +#VitroConnection.DataSource.url = jdbc:mysql://localhost/testvivo + +VitroConnection.DataSource.url = jdbc:mysql://localhost/vivodb +VitroConnection.DataSource.username = vivouser +VitroConnection.DataSource.password = vivopass +#test migration +#VitroConnection.DataSource.url = jdbc:mysql://localhost/migratetest +#VitroConnection.DataSource.username = migrateuser +#VitroConnection.DataSource.password = migratepassword + +# +# The Jena triple store technology to use. SDB is Jena's SPARQL database; +# this setting allows RDF data to scale beyond the limits of the JVM heap. +# Set to RDB to use the older Jena RDB store with in-memory caching. +# +VitroConnection.DataSource.tripleStoreType = SDB + +# +# The maximum number of active connections in the database connection pool. +# Increase this value to support a greater number of concurrent page requests +# with SDB. It is not necessary to adjust this value when using the +# RDB configuration. +# +VitroConnection.DataSource.pool.maxActive = 40 + +# +# The maximum number of database connections that will be allowed +# to remain idle in the connection pool. Default is 25% +# of the maximum number of active connections. +# +VitroConnection.DataSource.pool.maxIdle = 10 + +# +# Parameters to change in order to use VIVO with a database other than +# MySQL. +# +VitroConnection.DataSource.dbtype = MySQL +VitroConnection.DataSource.driver = com.mysql.jdbc.Driver +VitroConnection.DataSource.validationQuery = SELECT 1 + +# +# The name of your first admin user for the VIVO application. The password +# for this user is initially set to "defaultAdmin", but you will be asked to +# change the password the first time you log in. +# +initialAdminUser = defaultAdmin +rootUser.emailAddress = hjk54@cornell.edu +# +# How is a logged-in user associated with a particular Individual? One way is +# for the Individual to have a property whose value is the username of the user. +# This value should be the URI for that property. +# +selfEditing.idMatchingProperty = http://vivo.mannlib.cornell.edu/ns#networkId + +# +# If an external authentication system like Shibboleth or CUWebAuth is to be +# used, these properties say how the login button should be labeled, and which +# HTTP header will contain the user ID from the authentication system. If such +# a system is not to be used, leave these commented out. Consult the +# installation instructions for more details. +# +#externalAuth.buttonText = Log in using BearCat Shibboleth +#externalAuth.netIdHeaderName = remote_userID + +# +# The temporal graph visualization can require extensive machine resources. +# This can have a particularly noticable impact on memory usage if +# - VIVO is configured to use Jena SDB, +# - The organization tree is deep, +# - The number of grants and publications is large. +# VIVO release 1.2 guards against this impact by disabling the temporal graph +# visualization unless the "visualization.temporal" flag is set to "enabled". +# +# visualization.temporal = enabled + +# +# The temporal graph visualization is used to compare different organizations/people +# within an organization on parameters like number of publications or grants. +# By default, the app will attempt to make its best guess at the top level +# organization in your instance. If you're unhappy with this selection, uncomment out +# the property below and set it to the URI of the organization individual you want to +# identify as the top level organization. It will be used as the default whenever the +# temporal graph visualization is rendered without being passed an explicit org. +# For example, to use "Ponce School of Medicine" as the top organization: +# visualization.topLevelOrg = http://vivo.psm.edu/individual/n2862 +# +# visualization.topLevelOrg = http://vivo.mydomain.edu/individual/topLevelOrgURI + +# +# Default type(s) for Google Refine Reconciliation Service +# The format for this property is id, name; id1, name1; id2, name2 etc. +# See Service Metadata from this page http://code.google.com/p/google-refine/wiki/ReconciliationServiceApi +# for more information. +Vitro.reconcile.defaultTypeList = http://vivoweb.org/ontology/core#Course, Course; http://vivoweb.org/ontology/core#Grant, Grant; http://aims.fao.org/aos/geopolitical.owl, Location; http://xmlns.com/foaf/0.1/Organization, Organization; http://xmlns.com/foaf/0.1/Person, Person; http://purl.org/ontology/bibo/Article, Publication +#solr +vitro.local.solr.url = http://localhost:8080/vivosolr \ No newline at end of file diff --git a/productMods/WEB-INF/filegraph/abox/vocabularySource.n3 b/productMods/WEB-INF/filegraph/abox/vocabularySource.n3 deleted file mode 100644 index 97690dd7..00000000 --- a/productMods/WEB-INF/filegraph/abox/vocabularySource.n3 +++ /dev/null @@ -1,3 +0,0 @@ - . - . - . \ No newline at end of file diff --git a/productMods/WEB-INF/resources/startup_listeners.txt b/productMods/WEB-INF/resources/startup_listeners.txt index 0399eacc..93794994 100644 --- a/productMods/WEB-INF/resources/startup_listeners.txt +++ b/productMods/WEB-INF/resources/startup_listeners.txt @@ -45,7 +45,7 @@ edu.cornell.mannlib.vitro.webapp.servlet.setup.ThemeInfoSetup edu.cornell.mannlib.vitro.webapp.auth.permissions.PermissionRegistry$Setup -edu.cornell.mannlib.vitro.webapp.auth.permissions.PermissionSetsLoader +edu.cornell.mannlib.vitro.webapp.auth.permissions.PermissionSetsSmokeTest edu.cornell.mannlib.vitro.webapp.auth.policy.bean.PropertyRestrictionPolicyHelper$Setup @@ -72,6 +72,7 @@ edu.cornell.mannlib.vitro.webapp.search.solr.VivoDocumentModifiers edu.cornell.mannlib.vitro.webapp.search.solr.SolrSetup edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerSetup +edu.cornell.mannlib.vitro.webapp.freemarker.config.FreemarkerConfiguration$Setup # On shutdown, this will kill the background thread started by Apache Commons File Upload org.apache.commons.fileupload.servlet.FileCleanerCleanup diff --git a/productMods/images/individual/manage-icon.png b/productMods/images/individual/manage-icon.png deleted file mode 100644 index 18ab5756..00000000 Binary files a/productMods/images/individual/manage-icon.png and /dev/null differ diff --git a/productMods/js/homePageMaps.js b/productMods/js/homePageMaps.js index 01cb4058..f39f3ab6 100644 --- a/productMods/js/homePageMaps.js +++ b/productMods/js/homePageMaps.js @@ -9,6 +9,7 @@ $(document).ready(function(){ $.extend(this, urlsBase); $.extend(this, i18nStrings); + $.extend(this, geoResearcherCount); getGeoJsonForMaps(); @@ -368,7 +369,7 @@ $(document).ready(function(){ function getResearcherCount(area) { - var researcherCount = 0; + var researcherCount = this.geoResearcherCount; var areaCount = 0; var text = ""; if ( area == "global" ) { @@ -383,7 +384,6 @@ $(document).ready(function(){ $.each(researchAreas.features, function() { if ( this.properties.mapType == area ) { - researcherCount = researcherCount + this.properties.html ; areaCount = areaCount + 1; } }); @@ -391,10 +391,16 @@ $(document).ready(function(){ if ( areaCount == 1 && text == " states.") { text = " " + i18nStrings.stateString; } + if ( researcherCount == 1 ) { + researcherText = " " + i18nStrings.researcherString + " " + i18nStrings.inString; + } + else { + researcherText = " " + i18nStrings.researcherInString + } $('div#researcherTotal').html("" - + researcherCount.toString().replace(/(\d+)(\d{3})/, '$1'+','+'$2') - + " " + i18nStrings.researchersInString + " " + + researcherCount + + " " + researcherText + " " + areaCount + "" + text); } function appendLegendToLeafletContainer() { diff --git a/productMods/js/individual/propertyGroupControls.js b/productMods/js/individual/propertyGroupControls.js index 70cb4c99..c4386256 100644 --- a/productMods/js/individual/propertyGroupControls.js +++ b/productMods/js/individual/propertyGroupControls.js @@ -69,22 +69,25 @@ $(document).ready(function(){ location.hash = location.hash.replace(/\s+/g, ''); if ( location.hash.indexOf("map") >= 0 ) { // get the name of the group that contains the geographicFocusOf property. - var tabName = $('h3#geographicFocusOf').parent('article').parent('div').attr("id"); - tabName = tabName.replace("Group",""); - tabNameCapped = tabName.charAt(0).toUpperCase() + tabName.slice(1); - // if the name of the first tab section = tabName we don't have to do anything; - // otherwise, select the correct tab and deselect the first one - var $firstTab = $('li.clickable').first(); - if ( $firstTab.text() != tabNameCapped ) { - // select the correct tab - $('li[groupName="' + tabName + '"]').removeClass("nonSelectedGroupTab clickable"); - $('li[groupName="' + tabName + '"]').addClass("selectedGroupTab clickable"); - // deselect the first tab - $firstTab.removeClass("selectedGroupTab clickable"); - $firstTab.addClass("nonSelectedGroupTab clickable"); - $('section.property-group:visible').hide(); - // show the selected tab section - $('section#' + tabName).show(); + // if it doesn't exist, don't do anything. + if ( $('h3#geographicFocusOf').length ) { + var tabName = $('h3#geographicFocusOf').parent('article').parent('div').attr("id"); + tabName = tabName.replace("Group",""); + tabNameCapped = tabName.charAt(0).toUpperCase() + tabName.slice(1); + // if the name of the first tab section = tabName we don't have to do anything; + // otherwise, select the correct tab and deselect the first one + var $firstTab = $('li.clickable').first(); + if ( $firstTab.text() != tabNameCapped ) { + // select the correct tab + $('li[groupName="' + tabName + '"]').removeClass("nonSelectedGroupTab clickable"); + $('li[groupName="' + tabName + '"]').addClass("selectedGroupTab clickable"); + // deselect the first tab + $firstTab.removeClass("selectedGroupTab clickable"); + $firstTab.addClass("nonSelectedGroupTab clickable"); + $('section.property-group:visible').hide(); + // show the selected tab section + $('section#' + tabName).show(); + } } // if there is a more link, "click" more to show all the researchers // we need the timeout delay so that the more link can get rendered diff --git a/productMods/js/latLongJson.js b/productMods/js/latLongJson.js index 417e815f..9dcc4643 100644 --- a/productMods/js/latLongJson.js +++ b/productMods/js/latLongJson.js @@ -7,4 +7,4 @@ // IMPLEMENT A STATE MAP, YOU WILL NEED TO ADD THE GEOJSON DATA FOR THAT STATE'S COUNTIES AND OTHER // RELEVANT GEOGRAPHIC AREAS. -var latLongJson = [{"name": "Afghanistan", "data": {"mapType": "global", "geoClass": "country", "latitude": "33.0", "longitude": "65.0"}},{"name": "Albania", "data": {"mapType": "global", "geoClass": "country", "latitude": "41.0", "longitude": "20.0"}},{"name": "Algeria", "data": {"mapType": "global", "geoClass": "country", "latitude": "28.0", "longitude": "3.0"}},{"name": "American Samoa", "data": {"mapType": "global", "geoClass": "country", "latitude": "-14.3333", "longitude": "-170.0"}},{"name": "Andorra", "data": {"mapType": "global", "geoClass": "country", "latitude": "42.5", "longitude": "1.5"}},{"name": "Angola", "data": {"mapType": "global", "geoClass": "country", "latitude": "-12.5", "longitude": "18.5"}},{"name": "Anguilla", "data": {"mapType": "global", "geoClass": "country", "latitude": "18.25", "longitude": "-63.1667"}},{"name": "Antarctica", "data": {"mapType": "global", "geoClass": "country", "latitude": "-90.0", "longitude": "0.0"}},{"name": "Antigua and Barbuda", "data": {"mapType": "global", "geoClass": "country", "latitude": "17.05", "longitude": "-61.8"}},{"name": "Argentina", "data": {"mapType": "global", "geoClass": "country", "latitude": "-34.0", "longitude": "-64.0"}},{"name": "Armenia", "data": {"mapType": "global", "geoClass": "country", "latitude": "40.0", "longitude": "45.0"}},{"name": "Aruba", "data": {"mapType": "global", "geoClass": "country", "latitude": "12.5", "longitude": "-69.9667"}},{"name": "Australia", "data": {"mapType": "global", "geoClass": "country", "latitude": "-27.0", "longitude": "133.0"}},{"name": "Austria", "data": {"mapType": "global", "geoClass": "country", "latitude": "47.3333", "longitude": "13.3333"}},{"name": "Azerbaijan", "data": {"mapType": "global", "geoClass": "country", "latitude": "40.5", "longitude": "47.5"}},{"name": "Bahamas", "data": {"mapType": "global", "geoClass": "country", "latitude": "24.25", "longitude": "-76.0"}},{"name": "Bahrain", "data": {"mapType": "global", "geoClass": "country", "latitude": "26.0", "longitude": "50.55"}},{"name": "Bangladesh", "data": {"mapType": "global", "geoClass": "country", "latitude": "24.0", "longitude": "90.0"}},{"name": "Barbados", "data": {"mapType": "global", "geoClass": "country", "latitude": "13.1667", "longitude": "-59.5333"}},{"name": "Belarus", "data": {"mapType": "global", "geoClass": "country", "latitude": "53.0", "longitude": "28.0"}},{"name": "Belgium", "data": {"mapType": "global", "geoClass": "country", "latitude": "50.8333", "longitude": "4.0"}},{"name": "Belize", "data": {"mapType": "global", "geoClass": "country", "latitude": "17.25", "longitude": "-88.75"}},{"name": "Benin", "data": {"mapType": "global", "geoClass": "country", "latitude": "9.5", "longitude": "2.25"}},{"name": "Bermuda", "data": {"mapType": "global", "geoClass": "country", "latitude": "32.3333", "longitude": "-64.75"}},{"name": "Bhutan", "data": {"mapType": "global", "geoClass": "country", "latitude": "27.5", "longitude": "", "longitude": "90.5"}},{"name": "Bolivia", "data": {"mapType": "global", "geoClass": "country", "latitude": "-17.0", "longitude": "-65.0"}},{"name": "Bosnia and Herzegovina", "data": {"mapType": "global", "geoClass": "country", "latitude": "44.0", "longitude": "18.0"}},{"name": "Botswana", "data": {"mapType": "global", "geoClass": "country", "latitude": "-22.0", "longitude": "24.0"}},{"name": "Bouvet Island", "data": {"mapType": "global", "geoClass": "country", "latitude": "-54.4333", "longitude": "3.4"}},{"name": "Brazil", "data": {"mapType": "global", "geoClass": "country", "latitude": "-10.0", "longitude": "-55.0"}},{"name": "British Indian Ocean Territory", "data": {"mapType": "global", "geoClass": "country", "latitude": "-6.0", "longitude": "71.5"}},{"name": "Brunei", "data": {"mapType": "global", "geoClass": "country", "latitude": "4.5", "longitude": "114.6667"}},{"name": "Bulgaria", "data": {"mapType": "global", "geoClass": "country", "latitude": "43.0", "longitude": "25.0"}},{"name": "Burkina Faso", "data": {"mapType": "global", "geoClass": "country", "latitude": "13.0", "longitude": "-2.0"}},{"name": "Burundi", "data": {"mapType": "global", "geoClass": "country", "latitude": "-3.5", "longitude": "30.0"}},{"name": "Cambodia", "data": {"mapType": "global", "geoClass": "country", "latitude": "13.0", "longitude": "105.0"}},{"name": "Cameroon", "data": {"mapType": "global", "geoClass": "country", "latitude": "6.0", "longitude": "12.0"}},{"name": "Canada", "data": {"mapType": "global", "geoClass": "country", "latitude": "60.0", "longitude": "-95.0"}},{"name": "Cape Verde", "data": {"mapType": "global", "geoClass": "country", "latitude": "16.0", "longitude": "-24.0"}},{"name": "Cayman Islands", "data": {"mapType": "global", "geoClass": "country", "latitude": "19.5", "longitude": "-80.5"}},{"name": "Central African Republic", "data": {"mapType": "global", "geoClass": "country", "latitude": "7.0", "longitude": "21.0"}},{"name": "Chad", "data": {"mapType": "global", "geoClass": "country", "latitude": "15.0", "longitude": "19.0"}},{"name": "Chile", "data": {"mapType": "global", "geoClass": "country", "latitude": "-30.0", "longitude": "-71.0"}},{"name": "China", "data": {"mapType": "global", "geoClass": "country", "latitude": "35.0", "longitude": "105.0"}},{"name": "Christmas Island", "data": {"mapType": "global", "geoClass": "country", "latitude": "-10.5", "longitude": "105.6667"}},{"name": "Cocos (Keeling) Islands", "data": {"mapType": "global", "geoClass": "country", "latitude": "-12.5", "longitude": "96.8333"}},{"name": "Colombia", "data": {"mapType": "global", "geoClass": "country", "latitude": "4.0", "longitude": "-72.0"}},{"name": "Comoros", "data": {"mapType": "global", "geoClass": "country", "latitude": "-12.1667", "longitude": "44.25"}},{"name": "Congo", "data": {"mapType": "global", "geoClass": "country", "latitude": "-1.0", "longitude": "15.0"}},{"name": "Cook Islands", "data": {"mapType": "global", "geoClass": "country", "latitude": "-21.2333", "longitude": "-159.7667"}},{"name": "Costa Rica", "data": {"mapType": "global", "geoClass": "country", "latitude": "10.0", "longitude": "-84.0"}},{"name": "Ivory Coast", "data": {"mapType": "global", "geoClass": "country", "latitude": "8.0", "longitude": "-5.0"}},{"name": "Croatia", "data": {"mapType": "global", "geoClass": "country", "latitude": "45.1667", "longitude": "15.5"}},{"name": "Cuba", "data": {"mapType": "global", "geoClass": "country", "latitude": "21.5", "longitude": "-80.0"}},{"name": "Cyprus", "data": {"mapType": "global", "geoClass": "country", "latitude": "35.0", "longitude": "33.0"}},{"name": "Czech Republic", "data": {"mapType": "global", "geoClass": "country", "latitude": "49.75", "longitude": "15.5"}},{"name": "Denmark", "data": {"mapType": "global", "geoClass": "country", "latitude": "56.0", "longitude": "10.0"}},{"name": "Czechoslovakia", "data": {"mapType": "global", "geoClass": "country", "latitude": "49.75", "longitude": "15.5"}},{"name": "Denmark", "data": {"mapType": "global", "geoClass": "country", "latitude": "56.0", "longitude": "10.0"}},{"name": "Djibouti", "data": {"mapType": "global", "geoClass": "country", "latitude": "11.5", "longitude": "43.0"}},{"name": "Dominica", "data": {"mapType": "global", "geoClass": "country", "latitude": "15.4167", "longitude": "-61.3333"}},{"name": "Dominican Republic", "data": {"mapType": "global", "geoClass": "country", "latitude": "19.0", "longitude": "-70.6667"}},{"name": "Ecuador", "data": {"mapType": "global", "geoClass": "country", "latitude": "-2.0", "longitude": "-77.5"}},{"name": "Egypt", "data": {"mapType": "global", "geoClass": "country", "latitude": "27.0", "longitude": "30.0"}},{"name": "El Salvador", "data": {"mapType": "global", "geoClass": "country", "latitude": "13.8333", "longitude": "-88.9167"}},{"name": "Equatorial Guinea", "data": {"mapType": "global", "geoClass": "country", "latitude": "2.0", "longitude": "10.0"}},{"name": "Eritrea", "data": {"mapType": "global", "geoClass": "country", "latitude": "15.0", "longitude": "39.0"}},{"name": "Estonia", "data": {"mapType": "global", "geoClass": "country", "latitude": "59.0", "longitude": "26.0"}},{"name": "Ethiopia", "data": {"mapType": "global", "geoClass": "country", "latitude": "8.0", "longitude": "38.0"}},{"name": "Falkland Islands", "data": {"mapType": "global", "geoClass": "country", "latitude": "-51.75", "longitude": "-59.0"}},{"name": "Faroe Islands", "data": {"mapType": "global", "geoClass": "country", "latitude": "62.0", "longitude": "-7.0"}},{"name": "Fiji", "data": {"mapType": "global", "geoClass": "country", "latitude": "-18.0", "longitude": "175.0"}},{"name": "Finland", "data": {"mapType": "global", "geoClass": "country", "latitude": "64.0", "longitude": "26.0"}},{"name": "France", "data": {"mapType": "global", "geoClass": "country", "latitude": "46.0", "longitude": "2.0"}},{"name": "French Guiana", "data": {"mapType": "global", "geoClass": "country", "latitude": "4.0", "longitude": "-53.0"}},{"name": "French Polynesia", "data": {"mapType": "global", "geoClass": "country", "latitude": "-15.0", "longitude": "-140.0"}},{"name": "French Southern Territories", "data": {"mapType": "global", "geoClass": "country", "latitude": "-43.0", "longitude": "67.0"}},{"name": "Gabon", "data": {"mapType": "global", "geoClass": "country", "latitude": "-1.0", "longitude": "11.75"}},{"name": "Gambia", "data": {"mapType": "global", "geoClass": "country", "latitude": "13.4667", "longitude": "-16.5667"}},{"name": "Georgia", "data": {"mapType": "global", "geoClass": "country", "latitude": "42.0", "longitude": "43.5"}},{"name": "Germany", "data": {"mapType": "global", "geoClass": "country", "latitude": "51.0", "longitude": "9.0"}},{"name": "Ghana", "data": {"mapType": "global", "geoClass": "country", "latitude": "8.0", "longitude": "-2.0"}},{"name": "Greece", "data": {"mapType": "global", "geoClass": "country", "latitude": "39.0", "longitude": "22.0"}},{"name": "Greenland", "data": {"mapType": "global", "geoClass": "country", "latitude": "72.0", "longitude": "-40.0"}},{"name": "Grenada", "data": {"mapType": "global", "geoClass": "country", "latitude": "12.1167", "longitude": "-61.6667"}},{"name": "Guadeloupe", "data": {"mapType": "global", "geoClass": "country", "latitude": "16.25", "longitude": "-61.5833"}},{"name": "Guam", "data": {"mapType": "global", "geoClass": "country", "latitude": "13.4667", "longitude": "144.7833"}},{"name": "Guatemala", "data": {"mapType": "global", "geoClass": "country", "latitude": "15.5", "longitude": "-90.25"}},{"name": "Guinea", "data": {"mapType": "global", "geoClass": "country", "latitude": "11.0", "longitude": "-10.0"}},{"name": "Guinea-Bissau", "data": {"mapType": "global", "geoClass": "country", "latitude": "12.0", "longitude": "-15.0"}},{"name": "Guyana", "data": {"mapType": "global", "geoClass": "country", "latitude": "5.0", "longitude": "-59.0"}},{"name": "Haiti", "data": {"mapType": "global", "geoClass": "country", "latitude": "19.0", "longitude": "-72.4167"}},{"name": "Heard and McDonald Islands", "data": {"mapType": "global", "geoClass": "country", "latitude": "-53.1", "longitude": "72.5167"}},{"name": "Honduras", "data": {"mapType": "global", "geoClass": "country", "latitude": "15.0", "longitude": "-86.5"}},{"name": "Hong Kong", "data": {"mapType": "global", "geoClass": "country", "latitude": "22.25", "longitude": "114.1667"}},{"name": "Hungary", "data": {"mapType": "global", "geoClass": "country", "latitude": "47.0", "longitude": "20.0"}},{"name": "Iceland", "data": {"mapType": "global", "geoClass": "country", "latitude": "65.0", "longitude": "-18.0"}},{"name": "India", "data": {"mapType": "global", "geoClass": "country", "latitude": "20.0", "longitude": "77.0"}},{"name": "Indonesia", "data": {"mapType": "global", "geoClass": "country", "latitude": "-5.0", "longitude": "120.0"}},{"name": "Iran", "data": {"mapType": "global", "geoClass": "country", "latitude": "32.0", "longitude": "53.0"}},{"name": "Iraq", "data": {"mapType": "global", "geoClass": "country", "latitude": "33.0", "longitude": "44.0"}},{"name": "Ireland", "data": {"mapType": "global", "geoClass": "country", "latitude": "53.0", "longitude": "-8.0"}},{"name": "Israel", "data": {"mapType": "global", "geoClass": "country", "latitude": "31.5", "longitude": "34.75"}},{"name": "Italy", "data": {"mapType": "global", "geoClass": "country", "latitude": "42.8333", "longitude": "12.8333"}},{"name": "Jamaica", "data": {"mapType": "global", "geoClass": "country", "latitude": "18.25", "longitude": "-77.5"}},{"name": "Japan", "data": {"mapType": "global", "geoClass": "country", "latitude": "36.0", "longitude": "138.0"}},{"name": "Jordan", "data": {"mapType": "global", "geoClass": "country", "latitude": "31.0", "longitude": "36.0"}},{"name": "Kazakhstan", "data": {"mapType": "global", "geoClass": "country", "latitude": "48.0", "longitude": "68.0"}},{"name": "Kenya", "data": {"mapType": "global", "geoClass": "country", "latitude": "1.0", "longitude": "38.0"}},{"name": "Kiribati", "data": {"mapType": "global", "geoClass": "country", "latitude": "1.4167", "longitude": "173.0"}},{"name": "North Korea", "data": {"mapType": "global", "geoClass": "country", "latitude": "40.0", "longitude": "127.0"}},{"name": "Republic of Korea", "data": {"mapType": "global", "geoClass": "country", "latitude": "37.0", "longitude": "127.5"}},{"name": "Kuwait", "data": {"mapType": "global", "geoClass": "country", "latitude": "29.3375", "longitude": "47.6581"}},{"name": "Kyrgyzstan", "data": {"mapType": "global", "geoClass": "country", "latitude": "41.0", "longitude": "75.0"}},{"name": "Laos", "data": {"mapType": "global", "geoClass": "country", "latitude": "18.0", "longitude": "105.0"}},{"name": "Latvia", "data": {"mapType": "global", "geoClass": "country", "latitude": "57.0", "longitude": "25.0"}},{"name": "Lebanon", "data": {"mapType": "global", "geoClass": "country", "latitude": "33.8333", "longitude": "35.8333"}},{"name": "Lesotho", "data": {"mapType": "global", "geoClass": "country", "latitude": "-29.5", "longitude": "28.5"}},{"name": "Liberia", "data": {"mapType": "global", "geoClass": "country", "latitude": "6.5", "longitude": "-9.5"}},{"name": "Liechtenstein", "data": {"mapType": "global", "geoClass": "country", "latitude": "47.1667", "longitude": "9.5333"}},{"name": "Lithuania", "data": {"mapType": "global", "geoClass": "country", "latitude": "56.0", "longitude": "24.0"}},{"name": "Luxembourg", "data": {"mapType": "global", "geoClass": "country", "latitude": "49.75", "longitude": "6.1667"}},{"name": "Macau", "data": {"mapType": "global", "geoClass": "country", "latitude": "22.1667", "longitude": "113.55"}},{"name": "Macedonia", "data": {"mapType": "global", "geoClass": "country", "latitude": "41.8333", "longitude": "22.0"}},{"name": "Madagascar", "data": {"mapType": "global", "geoClass": "country", "latitude": "-20.0", "longitude": "47.0"}},{"name": "Malawi", "data": {"mapType": "global", "geoClass": "country", "latitude": "-13.5", "longitude": "34.0"}},{"name": "Malaysia", "data": {"mapType": "global", "geoClass": "country", "latitude": "2.5", "longitude": "112.5"}},{"name": "Maldives", "data": {"mapType": "global", "geoClass": "country", "latitude": "3.25", "longitude": "73.0"}},{"name": "Mali", "data": {"mapType": "global", "geoClass": "country", "latitude": "17.0", "longitude": "-4.0"}},{"name": "Malta", "data": {"mapType": "global", "geoClass": "country", "latitude": "35.8333", "longitude": "14.5833"}},{"name": "Marshal Islands", "data": {"mapType": "global", "geoClass": "country", "latitude": "9.0", "longitude": "168.0"}},{"name": "Martinique", "data": {"mapType": "global", "geoClass": "country", "latitude": "14.6667", "longitude": "-61.0"}},{"name": "Mauritania", "data": {"mapType": "global", "geoClass": "country", "latitude": "20.0", "longitude": "-12.0"}},{"name": "Mauritius", "data": {"mapType": "global", "geoClass": "country", "latitude": "-20.2833", "longitude": "57.55"}},{"name": "Mayotte", "data": {"mapType": "global", "geoClass": "country", "latitude": "-12.8333", "longitude": "45.1667"}},{"name": "Mexico", "data": {"mapType": "global", "geoClass": "country", "latitude": "23.0", "longitude": "-102.0"}},{"name": "Micronesia", "data": {"mapType": "global", "geoClass": "country", "latitude": "6.9167", "longitude": "158.25"}},{"name": "Moldova", "data": {"mapType": "global", "geoClass": "country", "latitude": "47.0", "longitude": "29.0"}},{"name": "Monaco", "data": {"mapType": "global", "geoClass": "country", "latitude": "43.7333", "longitude": "7.4"}},{"name": "Mongolia", "data": {"mapType": "global", "geoClass": "country", "latitude": "46.0", "longitude": "105.0"}},{"name": "Montserrat", "data": {"mapType": "global", "geoClass": "country", "latitude": "16.75", "longitude": "-62.2"}},{"name": "Morocco", "data": {"mapType": "global", "geoClass": "country", "latitude": "32.0", "longitude": "-5.0"}},{"name": "Mozambique", "data": {"mapType": "global", "geoClass": "country", "latitude": "-18.25", "longitude": "35.0"}},{"name": "Myanmar", "data": {"mapType": "global", "geoClass": "country", "latitude": "22.0", "longitude": "98.0"}},{"name": "Namibia", "data": {"mapType": "global", "geoClass": "country", "latitude": "-22.0", "longitude": "17.0"}},{"name": "Nauru", "data": {"mapType": "global", "geoClass": "country", "latitude": "-0.5333", "longitude": "166.9167"}},{"name": "Nepal", "data": {"mapType": "global", "geoClass": "country", "latitude": "28.0", "longitude": "84.0"}},{"name": "Netherlands Antilles", "data": {"mapType": "global", "geoClass": "country", "latitude": "12.25", "longitude": "-68.75"}},{"name": "Netherlands", "data": {"mapType": "global", "geoClass": "country", "latitude": "52.5", "longitude": "5.75"}},{"name": "New Caledonia", "data": {"mapType": "global", "geoClass": "country", "latitude": "-21.5", "longitude": "165.5"}},{"name": "New Zealand", "data": {"mapType": "global", "geoClass": "country", "latitude": "-41.0", "longitude": "174.0"}},{"name": "Nicaragua", "data": {"mapType": "global", "geoClass": "country", "latitude": "13.0", "longitude": "-85.0"}},{"name": "Niger", "data": {"mapType": "global", "geoClass": "country", "latitude": "16.0", "longitude": "8.0"}},{"name": "Nigeria", "data": {"mapType": "global", "geoClass": "country", "latitude": "10.0", "longitude": "8.0"}},{"name": "Niue", "data": {"mapType": "global", "geoClass": "country", "latitude": "-19.0333", "longitude": "-169.8667"}},{"name": "Norfolk Island", "data": {"mapType": "global", "geoClass": "country", "latitude": "-29.0333", "longitude": "167.95"}},{"name": "Northern Marianas Islands", "data": {"mapType": "global", "geoClass": "country", "latitude": "15.2", "longitude": "145.75"}},{"name": "Norway", "data": {"mapType": "global", "geoClass": "country", "latitude": "62.0", "longitude": "10.0"}},{"name": "Oman", "data": {"mapType": "global", "geoClass": "country", "latitude": "21.0", "longitude": "57.0"}},{"name": "Pakistan", "data": {"mapType": "global", "geoClass": "country", "latitude": "30.0", "longitude": "70.0"}},{"name": "Palau", "data": {"mapType": "global", "geoClass": "country", "latitude": "7.5", "longitude": "134.5"}},{"name": "Panama", "data": {"mapType": "global", "geoClass": "country", "latitude": "9.0", "longitude": "-80.0"}},{"name": "Papua New Guinea", "data": {"mapType": "global", "geoClass": "country", "latitude": "-6.0", "longitude": "147.0"}},{"name": "Paraguay", "data": {"mapType": "global", "geoClass": "country", "latitude": "-23.0", "longitude": "-58.0"}},{"name": "Peru", "data": {"mapType": "global", "geoClass": "country", "latitude": "-10.0", "longitude": "-76.0"}},{"name": "Philippines", "data": {"mapType": "global", "geoClass": "country", "latitude": "13.0", "longitude": "122.0"}},{"name": "Pitcairn", "data": {"mapType": "global", "geoClass": "country", "latitude": "-24.7", "longitude": "-127.4"}},{"name": "Poland", "data": {"mapType": "global", "geoClass": "country", "latitude": "52.0", "longitude": "20.0"}},{"name": "Portugal", "data": {"mapType": "global", "geoClass": "country", "latitude": "39.5", "longitude": "-8.0"}},{"name": "Puerto Rico", "data": {"mapType": "global", "geoClass": "country", "latitude": "18.25", "longitude": "-66.5"}},{"name": "Qatar", "data": {"mapType": "global", "geoClass": "country", "latitude": "25.5", "longitude": "51.25"}},{"name": "Reunion", "data": {"mapType": "global", "geoClass": "country", "latitude": "-21.1", "longitude": "55.6"}},{"name": "Romania", "data": {"mapType": "global", "geoClass": "country", "latitude": "46.0", "longitude": "25.0"}},{"name": "Russia", "data": {"mapType": "global", "geoClass": "country", "latitude": "60.0", "longitude": "100.0"}},{"name": "Russian Federation", "data": {"mapType": "global", "geoClass": "country", "latitude": "60.0", "longitude": "100.0"}},{"name": "Rwanda", "data": {"longitude": "-2.0", "longitude": "30.0"}},{"name": "Saint Helena", "data": {"mapType": "global", "geoClass": "country", "latitude": "-15.9333", "longitude": "-5.7"}},{"name": "Saint Kitts and Nevis", "data": {"mapType": "global", "geoClass": "country", "latitude": "17.3333", "longitude": "-62.75"}},{"name": "Saint Lucia", "data": {"mapType": "global", "geoClass": "country", "latitude": "13.8833", "longitude": "-61.1333"}},{"name": "Saint Pierre and Miquelon", "data": {"mapType": "global", "geoClass": "country", "latitude": "46.8333", "longitude": "-56.3333"}},{"name": "Saint Vincent and the Grenadines", "data": {"mapType": "global", "geoClass": "country", "latitude": "13.25", "longitude": "-61.2"}},{"name": "Samoa", "data": {"mapType": "global", "geoClass": "country", "latitude": "-13.5833", "longitude": "-172.3333"}},{"name": "San Marino", "data": {"mapType": "global", "geoClass": "country", "latitude": "43.7667", "longitude": "12.4167"}},{"name": "Sao Tome and Principe", "data": {"mapType": "global", "geoClass": "country", "latitude": "1.0", "longitude": "7.0"}},{"name": "Saudi Arabia", "data": {"mapType": "global", "geoClass": "country", "latitude": "25.0", "longitude": "45.0"}},{"name": "Senegal", "data": {"mapType": "global", "geoClass": "country", "latitude": "14.0", "longitude": "-14.0"}},{"name": "Seychelles", "data": {"mapType": "global", "geoClass": "country", "latitude": "-4.5833", "longitude": "55.6667"}},{"name": "Sierra Leone", "data": {"mapType": "global", "geoClass": "country", "latitude": "8.5", "longitude": "-11.5"}},{"name": "Singapore", "data": {"mapType": "global", "geoClass": "country", "latitude": "1.3667", "longitude": "103.8"}},{"name": "Slovak Republic", "data": {"mapType": "global", "geoClass": "country", "latitude": "48.6667", "longitude": "19.5"}},{"name": "Slovenia", "data": {"mapType": "global", "geoClass": "country", "latitude": "46.0", "longitude": "15.0"}},{"name": "Solomon Islands", "data": {"mapType": "global", "geoClass": "country", "latitude": "-8.0", "longitude": "159.0"}},{"name": "Somalia", "data": {"mapType": "global", "geoClass": "country", "latitude": "10.0", "longitude": "49.0"}},{"name": "South Africa", "data": {"mapType": "global", "geoClass": "country", "latitude": "-29.0", "longitude": "24.0"}},{"name": "South Georgia and the South Sandwich Islands", "data": {"mapType": "global", "geoClass": "country", "latitude": "-54.5", "longitude": "-37.0"}},{"name": "Spain", "data": {"mapType": "global", "geoClass": "country", "latitude": "40.0", "longitude": "-4.0"}},{"name": "Sri Lanka", "data": {"mapType": "global", "geoClass": "country", "latitude": "7.0", "longitude": "81.0"}},{"name": "Sudan", "data": {"mapType": "global", "geoClass": "country", "latitude": "15.0", "longitude": "30.0"}},{"name": "Suriname", "data": {"mapType": "global", "geoClass": "country", "latitude": "4.0", "longitude": "-56.0"}},{"name": "Svalbard and Jan Mayen Islands", "data": {"mapType": "global", "geoClass": "country", "latitude": "78.0", "longitude": "20.0"}},{"name": "Swaziland", "data": {"mapType": "global", "geoClass": "country", "latitude": "-26.5", "longitude": "31.5"}},{"name": "Sweden", "data": {"mapType": "global", "geoClass": "country", "latitude": "62.0", "longitude": "15.0"}},{"name": "Switzerland", "data": {"mapType": "global", "geoClass": "country", "latitude": "47.0", "longitude": "8.0"}},{"name": "Syria", "data": {"mapType": "global", "geoClass": "country", "latitude": "35.0", "longitude": "38.0"}},{"name": "Taiwan", "data": {"mapType": "global", "geoClass": "country", "latitude": "23.5", "longitude": "121.0"}},{"name": "Tajikistan", "data": {"mapType": "global", "geoClass": "country", "latitude": "39.0", "longitude": "71.0"}},{"name": "Tanzania", "data": {"mapType": "global", "geoClass": "country", "latitude": "-6.0", "longitude": "35.0"}},{"name": "Thailand", "data": {"mapType": "global", "geoClass": "country", "latitude": "15.0", "longitude": "100.0"}},{"name": "Togo", "data": {"mapType": "global", "geoClass": "country", "latitude": "8.0", "longitude": "1.1667"}},{"name": "Tokelau", "data": {"mapType": "global", "geoClass": "country", "latitude": "-9.0", "longitude": "-172.0"}},{"name": "Tonga", "data": {"mapType": "global", "geoClass": "country", "latitude": "-20.0", "longitude": "-175.0"}},{"name": "Trinidad and Tobago", "data": {"mapType": "global", "geoClass": "country", "latitude": "11.0", "longitude": "-61.0"}},{"name": "Tunisia", "data": {"mapType": "global", "geoClass": "country", "latitude": "34.0", "longitude": "9.0"}},{"name": "Turkey", "data": {"mapType": "global", "geoClass": "country", "latitude": "39.0", "longitude": "35.0"}},{"name": "Turkmenistan", "data": {"mapType": "global", "geoClass": "country", "latitude": "40.0", "longitude": "60.0"}},{"name": "Turks and Caicos Islands", "data": {"mapType": "global", "geoClass": "country", "latitude": "21.75", "longitude": "-71.5833"}},{"name": "Tuvalu", "data": {"mapType": "global", "geoClass": "country", "latitude": "-8.0", "longitude": "178.0"}},{"name": "Uganda", "data": {"mapType": "global", "geoClass": "country", "latitude": "1.0", "longitude": "32.0"}},{"name": "Ukraine", "data": {"mapType": "global", "geoClass": "country", "latitude": "49.0", "longitude": "32.0"}},{"name": "United Arab Emirates", "data": {"mapType": "global", "geoClass": "country", "latitude": "24.0", "longitude": "54.0"}},{"name": "United Kingdom", "data": {"mapType": "global", "geoClass": "country", "latitude": "54.0", "longitude": "-2.0"}},{"name": "United States of America", "data": {"mapType": "global", "geoClass": "country", "latitude": "38.0", "longitude": "-97.0"}},{"name": "Uruguay", "data": {"mapType": "global", "geoClass": "country", "latitude": "-33.0", "longitude": "-56.0"}},{"name": "Uzbekistan", "data": {"mapType": "global", "geoClass": "country", "latitude": "41.0", "longitude": "64.0"}},{"name": "Vanuatu", "data": {"mapType": "global", "geoClass": "country", "latitude": "-16.0", "longitude": "167.0"}},{"name": "Vatican City", "data": {"mapType": "global", "geoClass": "country", "latitude": "41.9", "longitude": "12.45"}},{"name": "Venezuela", "data": {"mapType": "global", "geoClass": "country", "latitude": "8.0", "longitude": "-66.0"}},{"name": "Vietnam", "data": {"mapType": "global", "geoClass": "country", "latitude": "16.0", "longitude": "106.0"}},{"name": "British Virgin Islands", "data": {"mapType": "global", "geoClass": "country", "latitude": "18.3333", "longitude": "-64.8333"}},{"name": "US Virgin Islands", "data": {"mapType": "global", "geoClass": "country", "latitude": "18.3333", "longitude": "-64.8333"}},{"name": "Wallis and Futuna Islands", "data": {"mapType": "global", "geoClass": "country", "latitude": "-13.3", "longitude": "-176.2"}},{"name": "Western Sahara", "data": {"mapType": "global", "geoClass": "country", "latitude": "24.5", "longitude": "-13.0"}},{"name": "Yemen", "data": {"mapType": "global", "geoClass": "country", "latitude": "15.0", "longitude": "48.0"}},{"name": "Zaire", "data": {"mapType": "global", "geoClass": "country", "latitude": "-20.0", "longitude": "30.0"}},{"name": "Zambia", "data": {"mapType": "global", "geoClass": "country", "latitude": "-15.0", "longitude": "30.0"}},{"name": "Zimbabwe", "data": {"mapType": "global", "geoClass": "country", "latitude": "-20.0", "longitude": "30.0"}},{"name": "Central Africa", "data": {"mapType": "global", "geoClass": "region", "latitude": "", "longitude": ""}},{"name": "Central Europe", "data": {"mapType": "global", "geoClass": "region", "latitude": "48.9225", "longitude": "9.22852"}},{"name": "East Asia", "data": {"mapType": "global", "geoClass": "region", "latitude": "31.95216", "longitude": "120.41016"}},{"name": "Eastern North America", "data": {"mapType": "global", "geoClass": "region", "latitude": "45.213", "longitude": "-66.44531"}},{"name": "European Union (EU)", "data": {"mapType": "global", "geoClass": "region", "latitude": "48.86471", "longitude": "11.68945"}},{"name": "Central Asia", "data": {"mapType": "global", "geoClass": "region", "latitude": "36.73888", "longitude": "93.16406"}},{"name": "Former Soviet bloc countries", "data": {"mapType": "global", "geoClass": "region", "latitude": "49.72448", "longitude": "24.43359"}},{"name": "French North Africa", "data": {"mapType": "global", "geoClass": "region", "latitude": "34.45222", "longitude": "0.52734"}},{"name": "Gibraltar", "data": {"mapType": "global", "geoClass": "region", "latitude": "36.1430", "longitude": "5.3530"}},{"name": "Latin America", "data": {"mapType": "global", "geoClass": "region", "latitude": "21.69827", "longitude": "-84.50684"}},{"name": "Oceania", "data": {"mapType": "global", "geoClass": "region", "latitude": "-20.63278", "longitude": "-195.99609"}},{"name": "North Africa", "data": {"mapType": "global", "geoClass": "region", "latitude": "26.43123", "longitude": "13.35938"}},{"name": "South America", "data": {"mapType": "global", "geoClass": "region", "latitude": "-21.28937", "longitude": "-58.00781"}},{"name": "South Asia", "data": {"mapType": "global", "geoClass": "region", "latitude": "22.91792", "longitude": "82.26563"}},{"name": "Southeast Asia", "data": {"mapType": "global", "geoClass": "region", "latitude": "9.1021", "longitude": "111.79688"}},{"name": "Sub-Saharan Africa", "data": {"mapType": "global", "geoClass": "region", "latitude": "2.46018", "longitude": "21.97266"}},{"name": "Tibet", "data": {"mapType": "global", "geoClass": "region", "latitude": "29.53523", "longitude": "87.89063"}},{"name": "central America", "data": {"mapType": "global", "geoClass": "region", "latitude": "16.29905", "longitude": "-92.98828"}},{"name": "eastern Africa", "data": {"mapType": "global", "geoClass": "region", "latitude": "-7.36247", "longitude": "39.19922"}},{"name": "eastern Europe", "data": {"mapType": "global", "geoClass": "region", "latitude": "47.7541", "longitude": "22.59789"}},{"name": "middle Africa", "data": {"mapType": "global", "geoClass": "region", "latitude": "5.70345", "longitude": "22.5"}},{"name": "northern Europe", "data": {"mapType": "global", "geoClass": "region", "latitude": "57.563", "longitude": "12.56836"}},{"name": "southern Africa", "data": {"mapType": "global", "geoClass": "region", "latitude": "-22.35008", "longitude": "25.04883"}},{"name": "southern Europe", "data": {"mapType": "global", "geoClass": "region", "latitude": "40.04444", "longitude": "9.14063"}},{"name": "western Africa", "data": {"mapType": "global", "geoClass": "region", "latitude": "4.65308", "longitude": "6.32813"}},{"name": "western Europe", "data": {"mapType": "global", "geoClass": "region", "latitude": "48.69096", "longitude": "3.51563"}},{"name": "Africa", "data": {"mapType": "global", "geoClass": "region", "latitude": "8.58102", "longitude": "21.97266"}},{"name": "Americas", "data": {"mapType": "global", "geoClass": "region", "latitude": "13.23995", "longitude": "-78.39844"}},{"name": "Caribbean", "data": {"mapType": "global", "geoClass": "region", "latitude": "19.64259", "longitude": "-79.10156"}},{"name": "Europe", "data": {"mapType": "global", "geoClass": "region", "latitude": "50.84757", "longitude": "19.33594"}},{"name": "Melanesia", "data": {"mapType": "global", "geoClass": "region", "latitude": "-11.3508", "longitude": "165.9375"}},{"name": "Asia", "data": {"mapType": "global", "geoClass": "region", "latitude": "40.31304", "longitude": "90.78906"}},{"name": "North America", "data": {"mapType": "global", "geoClass": "region", "latitude": "46.43786", "longitude": "-97.73437"}},{"name": "northern America", "data": {"mapType": "global", "geoClass": "region", "latitude": "45.58329", "longitude": "-91.75781"}},{"name": "western Asia", "data": {"mapType": "global", "geoClass": "region", "latitude": "36.45664", "longitude": "57.12891"}},{"name": "Polynesia", "data": {"mapType": "global", "geoClass": "region", "latitude": "1.75754", "longitude": "-156.09375"}},{"name": "eastern Asia", "data": {"mapType": "global", "geoClass": "region", "latitude": "30.75128", "longitude": "126.38672"}},{"name": "northern Africa", "data": {"mapType": "global", "geoClass": "region", "latitude": "29.53523", "longitude": "14.23828"}},{"name": "south-eastern Asia", "data": {"mapType": "global", "geoClass": "region", "latitude": "6.3153", "longitude": "129.375"}},{"name": "southern Asia", "data": {"mapType": "global", "geoClass": "region", "latitude": "-1.05463", "longitude": "108.63281"}},{"name": "Alaska", "data": {"mapType": "country", "geoClass": "state", "latitude": "64.3850", "longitude": "-154.2683"}},{"name": "Alabama", "data": {"mapType": "country", "geoClass": "state", "latitude": "32.7990", "longitude": "-86.8073"}},{"name": "Arkansas", "data": {"mapType": "country", "geoClass": "state", "latitude": "34.9513", "longitude": "-92.3809"}},{"name": "Arizona", "data": {"mapType": "country", "geoClass": "state", "latitude": "33.7712", "longitude": "-111.3877"}},{"name": "California", "data": {"mapType": "country", "geoClass": "state", "latitude": "36.1700", "longitude": "-119.7462"}},{"name": "Colorado", "data": {"mapType": "country", "geoClass": "state", "latitude": "39.0646", "longitude": "-105.3272"}},{"name": "Connecticut", "data": {"mapType": "country", "geoClass": "state", "latitude": "41.5834", "longitude": "-72.7622"}},{"name": "District of Columbia", "data": {"mapType": "country", "geoClass": "state", "latitude": "38.8964", "longitude": "-77.0262"}},{"name": "Delaware", "data": {"mapType": "country", "geoClass": "state", "latitude": "39.3498", "longitude": "-75.5148"}},{"name": "Florida", "data": {"mapType": "country", "geoClass": "state", "latitude": "27.8333", "longitude": "-81.7170"}},{"name": "Georgia", "data": {"mapType": "country", "geoClass": "state", "latitude": "32.9866", "longitude": "-83.6487"}},{"name": "Hawaii", "data": {"mapType": "country", "geoClass": "state", "latitude": "21.1098", "longitude": "-157.5311"}},{"name": "Iowa", "data": {"mapType": "country", "geoClass": "state", "latitude": "42.0046", "longitude": "-93.2140"}},{"name": "Idaho", "data": {"mapType": "country", "geoClass": "state", "latitude": "44.2394", "longitude": "-114.5103"}},{"name": "Illinois", "data": {"mapType": "country", "geoClass": "state", "latitude": "40.3363", "longitude": "-89.0022"}},{"name": "Indiana", "data": {"mapType": "country", "geoClass": "state", "latitude": "39.8647", "longitude": "-86.2604"}},{"name": "Kansas", "data": {"mapType": "country", "geoClass": "state", "latitude": "38.5111", "longitude": "-96.8005"}},{"name": "Kentucky", "data": {"mapType": "country", "geoClass": "state", "latitude": "37.6690", "longitude": "-84.6514"}},{"name": "Louisiana", "data": {"mapType": "country", "geoClass": "state", "latitude": "31.1801", "longitude": "-91.8749"}},{"name": "Massachusetts", "data": {"mapType": "country", "geoClass": "state", "latitude": "42.2373", "longitude": "-71.5314"}},{"name": "Maryland", "data": {"mapType": "country", "geoClass": "state", "latitude": "39.0724", "longitude": "-76.7902"}},{"name": "Maine", "data": {"mapType": "country", "geoClass": "state", "latitude": "44.6074", "longitude": "-69.3977"}},{"name": "Michigan", "data": {"mapType": "country", "geoClass": "state", "latitude": "43.3504", "longitude": "-84.5603"}},{"name": "Minnesota", "data": {"mapType": "country", "geoClass": "state", "latitude": "", "longitude": ""}},{"name": "Missouri", "data": {"mapType": "country", "geoClass": "state", "latitude": "38.4623", "longitude": "-92.3020"}},{"name": "Mississippi", "data": {"mapType": "country", "geoClass": "state", "latitude": "32.7673", "longitude": "-89.6812"}},{"name": "Montana", "data": {"mapType": "country", "geoClass": "state", "latitude": "46.9048", "longitude": "-110.3261"}},{"name": "North Carolina", "data": {"mapType": "country", "geoClass": "state", "latitude": "35.6411", "longitude": "-79.8431"}},{"name": "North Dakota", "data": {"mapType": "country", "geoClass": "state", "latitude": "47.5362", "longitude": "-99.7930"}},{"name": "Nebraska", "data": {"mapType": "country", "geoClass": "state", "latitude": "41.1289", "longitude": "-98.2883"}},{"name": "New Hampshire", "data": {"mapType": "country", "geoClass": "state", "latitude": "43.4108", "longitude": "-71.5653"}},{"name": "New Jersey", "data": {"mapType": "country", "geoClass": "state", "latitude": "40.3140", "longitude": "-74.5089"}},{"name": "New Mexico", "data": {"mapType": "country", "geoClass": "state", "latitude": "34.8375", "longitude": "-106.2371"}},{"name": "Nevada", "data": {"mapType": "country", "geoClass": "state", "latitude": "38.4199", "longitude": "-117.1219"}},{"name": "New York", "data": {"mapType": "country", "geoClass": "state", "latitude": "42.1497", "longitude": "-74.9384"}},{"name": "Ohio", "data": {"mapType": "country", "geoClass": "state", "latitude": "40.3736", "longitude": "-82.7755"}},{"name": "Oklahoma", "data": {"mapType": "country", "geoClass": "state", "latitude": "35.5376", "longitude": "-96.9247"}},{"name": "Oregon", "data": {"mapType": "country", "geoClass": "state", "latitude": "44.5672", "longitude": "-122.1269"}},{"name": "Pennsylvania", "data": {"mapType": "country", "geoClass": "state", "latitude": "40.5773", "longitude": "-77.2640"}},{"name": "Rhode Island", "data": {"mapType": "country", "geoClass": "state", "latitude": "41.6772", "longitude": "-71.5101"}},{"name": "South Carolina", "data": {"mapType": "country", "geoClass": "state", "latitude": "33.8191", "longitude": "-80.9066"}},{"name": "Tennessee", "data": {"mapType": "country", "geoClass": "state", "latitude": "35.7449", "longitude": "-86.7489"}},{"name": "South Dakota", "data": {"mapType": "country", "geoClass": "state", "latitude": "44.2853", "longitude": "-99.4632"}},{"name": "Texas", "data": {"mapType": "country", "geoClass": "state", "latitude": "31.1060", "longitude": "-97.6475"}},{"name": "Utah", "data": {"mapType": "country", "geoClass": "state", "latitude": "40.1135", "longitude": "-111.8535"}},{"name": "Virginia", "data": {"mapType": "country", "geoClass": "state", "latitude": "37.7680", "longitude": "-78.2057"}},{"name": "Vermont", "data": {"mapType": "country", "geoClass": "state", "latitude": "44.0407", "longitude": "-72.7093"}},{"name": "Washington", "data": {"mapType": "country", "geoClass": "state", "latitude": "47.3917", "longitude": "-121.5708"}},{"name": "Wisconsin", "data": {"mapType": "country", "geoClass": "state", "latitude": "44.2563", "longitude": "-89.6385"}},{"name": "West Virginia", "data": {"mapType": "country", "geoClass": "state", "latitude": "38.4680", "longitude": "-80.9696"}},{"name": "Wyoming", "data": {"mapType": "country", "geoClass": "state", "latitude": "42.7475", "longitude": "-107.2085"}}]; +var latLongJson = [{"name": "Afghanistan", "data": {"mapType": "global", "geoClass": "country", "latitude": "33.0", "longitude": "65.0"}},{"name": "Albania", "data": {"mapType": "global", "geoClass": "country", "latitude": "41.0", "longitude": "20.0"}},{"name": "Algeria", "data": {"mapType": "global", "geoClass": "country", "latitude": "28.0", "longitude": "3.0"}},{"name": "American Samoa", "data": {"mapType": "global", "geoClass": "country", "latitude": "-14.3333", "longitude": "-170.0"}},{"name": "Andorra", "data": {"mapType": "global", "geoClass": "country", "latitude": "42.5", "longitude": "1.5"}},{"name": "Angola", "data": {"mapType": "global", "geoClass": "country", "latitude": "-12.5", "longitude": "18.5"}},{"name": "Anguilla", "data": {"mapType": "global", "geoClass": "country", "latitude": "18.25", "longitude": "-63.1667"}},{"name": "Antarctica", "data": {"mapType": "global", "geoClass": "country", "latitude": "-90.0", "longitude": "0.0"}},{"name": "Antigua and Barbuda", "data": {"mapType": "global", "geoClass": "country", "latitude": "17.05", "longitude": "-61.8"}},{"name": "Argentina", "data": {"mapType": "global", "geoClass": "country", "latitude": "-34.0", "longitude": "-64.0"}},{"name": "Armenia", "data": {"mapType": "global", "geoClass": "country", "latitude": "40.0", "longitude": "45.0"}},{"name": "Aruba", "data": {"mapType": "global", "geoClass": "country", "latitude": "12.5", "longitude": "-69.9667"}},{"name": "Australia", "data": {"mapType": "global", "geoClass": "country", "latitude": "-27.0", "longitude": "133.0"}},{"name": "Austria", "data": {"mapType": "global", "geoClass": "country", "latitude": "47.3333", "longitude": "13.3333"}},{"name": "Azerbaijan", "data": {"mapType": "global", "geoClass": "country", "latitude": "40.5", "longitude": "47.5"}},{"name": "Bahamas", "data": {"mapType": "global", "geoClass": "country", "latitude": "24.25", "longitude": "-76.0"}},{"name": "Bahrain", "data": {"mapType": "global", "geoClass": "country", "latitude": "26.0", "longitude": "50.55"}},{"name": "Bangladesh", "data": {"mapType": "global", "geoClass": "country", "latitude": "24.0", "longitude": "90.0"}},{"name": "Barbados", "data": {"mapType": "global", "geoClass": "country", "latitude": "13.1667", "longitude": "-59.5333"}},{"name": "Belarus", "data": {"mapType": "global", "geoClass": "country", "latitude": "53.0", "longitude": "28.0"}},{"name": "Belgium", "data": {"mapType": "global", "geoClass": "country", "latitude": "50.8333", "longitude": "4.0"}},{"name": "Belize", "data": {"mapType": "global", "geoClass": "country", "latitude": "17.25", "longitude": "-88.75"}},{"name": "Benin", "data": {"mapType": "global", "geoClass": "country", "latitude": "9.5", "longitude": "2.25"}},{"name": "Bermuda", "data": {"mapType": "global", "geoClass": "country", "latitude": "32.3333", "longitude": "-64.75"}},{"name": "Bhutan", "data": {"mapType": "global", "geoClass": "country", "latitude": "27.5", "longitude": "", "longitude": "90.5"}},{"name": "Bolivia", "data": {"mapType": "global", "geoClass": "country", "latitude": "-17.0", "longitude": "-65.0"}},{"name": "Bosnia and Herzegovina", "data": {"mapType": "global", "geoClass": "country", "latitude": "44.0", "longitude": "18.0"}},{"name": "Botswana", "data": {"mapType": "global", "geoClass": "country", "latitude": "-22.0", "longitude": "24.0"}},{"name": "Bouvet Island", "data": {"mapType": "global", "geoClass": "country", "latitude": "-54.4333", "longitude": "3.4"}},{"name": "Brazil", "data": {"mapType": "global", "geoClass": "country", "latitude": "-10.0", "longitude": "-55.0"}},{"name": "British Indian Ocean Territory", "data": {"mapType": "global", "geoClass": "country", "latitude": "-6.0", "longitude": "71.5"}},{"name": "Brunei", "data": {"mapType": "global", "geoClass": "country", "latitude": "4.5", "longitude": "114.6667"}},{"name": "Bulgaria", "data": {"mapType": "global", "geoClass": "country", "latitude": "43.0", "longitude": "25.0"}},{"name": "Burkina Faso", "data": {"mapType": "global", "geoClass": "country", "latitude": "13.0", "longitude": "-2.0"}},{"name": "Burundi", "data": {"mapType": "global", "geoClass": "country", "latitude": "-3.5", "longitude": "30.0"}},{"name": "Cambodia", "data": {"mapType": "global", "geoClass": "country", "latitude": "13.0", "longitude": "105.0"}},{"name": "Cameroon", "data": {"mapType": "global", "geoClass": "country", "latitude": "6.0", "longitude": "12.0"}},{"name": "Canada", "data": {"mapType": "global", "geoClass": "country", "latitude": "60.0", "longitude": "-95.0"}},{"name": "Cape Verde", "data": {"mapType": "global", "geoClass": "country", "latitude": "16.0", "longitude": "-24.0"}},{"name": "Cayman Islands", "data": {"mapType": "global", "geoClass": "country", "latitude": "19.5", "longitude": "-80.5"}},{"name": "Central African Republic", "data": {"mapType": "global", "geoClass": "country", "latitude": "7.0", "longitude": "21.0"}},{"name": "Chad", "data": {"mapType": "global", "geoClass": "country", "latitude": "15.0", "longitude": "19.0"}},{"name": "Chile", "data": {"mapType": "global", "geoClass": "country", "latitude": "-30.0", "longitude": "-71.0"}},{"name": "China", "data": {"mapType": "global", "geoClass": "country", "latitude": "35.0", "longitude": "105.0"}},{"name": "Christmas Island", "data": {"mapType": "global", "geoClass": "country", "latitude": "-10.5", "longitude": "105.6667"}},{"name": "Cocos (Keeling) Islands", "data": {"mapType": "global", "geoClass": "country", "latitude": "-12.5", "longitude": "96.8333"}},{"name": "Colombia", "data": {"mapType": "global", "geoClass": "country", "latitude": "4.0", "longitude": "-72.0"}},{"name": "Comoros", "data": {"mapType": "global", "geoClass": "country", "latitude": "-12.1667", "longitude": "44.25"}},{"name": "Congo", "data": {"mapType": "global", "geoClass": "country", "latitude": "-1.0", "longitude": "15.0"}},{"name": "Cook Islands", "data": {"mapType": "global", "geoClass": "country", "latitude": "-21.2333", "longitude": "-159.7667"}},{"name": "Costa Rica", "data": {"mapType": "global", "geoClass": "country", "latitude": "10.0", "longitude": "-84.0"}},{"name": "Ivory Coast", "data": {"mapType": "global", "geoClass": "country", "latitude": "8.0", "longitude": "-5.0"}},{"name": "Croatia", "data": {"mapType": "global", "geoClass": "country", "latitude": "45.1667", "longitude": "15.5"}},{"name": "Cuba", "data": {"mapType": "global", "geoClass": "country", "latitude": "21.5", "longitude": "-80.0"}},{"name": "Cyprus", "data": {"mapType": "global", "geoClass": "country", "latitude": "35.0", "longitude": "33.0"}},{"name": "Czech Republic", "data": {"mapType": "global", "geoClass": "country", "latitude": "49.75", "longitude": "15.5"}},{"name": "Denmark", "data": {"mapType": "global", "geoClass": "country", "latitude": "56.0", "longitude": "10.0"}},{"name": "Czechoslovakia", "data": {"mapType": "global", "geoClass": "country", "latitude": "49.75", "longitude": "15.5"}},{"name": "Denmark", "data": {"mapType": "global", "geoClass": "country", "latitude": "56.0", "longitude": "10.0"}},{"name": "Djibouti", "data": {"mapType": "global", "geoClass": "country", "latitude": "11.5", "longitude": "43.0"}},{"name": "Dominica", "data": {"mapType": "global", "geoClass": "country", "latitude": "15.4167", "longitude": "-61.3333"}},{"name": "Dominican Republic", "data": {"mapType": "global", "geoClass": "country", "latitude": "19.0", "longitude": "-70.6667"}},{"name": "Ecuador", "data": {"mapType": "global", "geoClass": "country", "latitude": "-2.0", "longitude": "-77.5"}},{"name": "Egypt", "data": {"mapType": "global", "geoClass": "country", "latitude": "27.0", "longitude": "30.0"}},{"name": "El Salvador", "data": {"mapType": "global", "geoClass": "country", "latitude": "13.8333", "longitude": "-88.9167"}},{"name": "Equatorial Guinea", "data": {"mapType": "global", "geoClass": "country", "latitude": "2.0", "longitude": "10.0"}},{"name": "Eritrea", "data": {"mapType": "global", "geoClass": "country", "latitude": "15.0", "longitude": "39.0"}},{"name": "Estonia", "data": {"mapType": "global", "geoClass": "country", "latitude": "59.0", "longitude": "26.0"}},{"name": "Ethiopia", "data": {"mapType": "global", "geoClass": "country", "latitude": "8.0", "longitude": "38.0"}},{"name": "Falkland Islands", "data": {"mapType": "global", "geoClass": "country", "latitude": "-51.75", "longitude": "-59.0"}},{"name": "Faroe Islands", "data": {"mapType": "global", "geoClass": "country", "latitude": "62.0", "longitude": "-7.0"}},{"name": "Fiji", "data": {"mapType": "global", "geoClass": "country", "latitude": "-18.0", "longitude": "175.0"}},{"name": "Finland", "data": {"mapType": "global", "geoClass": "country", "latitude": "64.0", "longitude": "26.0"}},{"name": "France", "data": {"mapType": "global", "geoClass": "country", "latitude": "46.0", "longitude": "2.0"}},{"name": "French Guiana", "data": {"mapType": "global", "geoClass": "country", "latitude": "4.0", "longitude": "-53.0"}},{"name": "French Polynesia", "data": {"mapType": "global", "geoClass": "country", "latitude": "-15.0", "longitude": "-140.0"}},{"name": "French Southern Territories", "data": {"mapType": "global", "geoClass": "country", "latitude": "-43.0", "longitude": "67.0"}},{"name": "Gabon", "data": {"mapType": "global", "geoClass": "country", "latitude": "-1.0", "longitude": "11.75"}},{"name": "Gambia", "data": {"mapType": "global", "geoClass": "country", "latitude": "13.4667", "longitude": "-16.5667"}},{"name": "Georgia", "data": {"mapType": "global", "geoClass": "country", "latitude": "42.0", "longitude": "43.5"}},{"name": "Germany", "data": {"mapType": "global", "geoClass": "country", "latitude": "51.0", "longitude": "9.0"}},{"name": "Ghana", "data": {"mapType": "global", "geoClass": "country", "latitude": "8.0", "longitude": "-2.0"}},{"name": "Greece", "data": {"mapType": "global", "geoClass": "country", "latitude": "39.0", "longitude": "22.0"}},{"name": "Greenland", "data": {"mapType": "global", "geoClass": "country", "latitude": "72.0", "longitude": "-40.0"}},{"name": "Grenada", "data": {"mapType": "global", "geoClass": "country", "latitude": "12.1167", "longitude": "-61.6667"}},{"name": "Guadeloupe", "data": {"mapType": "global", "geoClass": "country", "latitude": "16.25", "longitude": "-61.5833"}},{"name": "Guam", "data": {"mapType": "global", "geoClass": "country", "latitude": "13.4667", "longitude": "144.7833"}},{"name": "Guatemala", "data": {"mapType": "global", "geoClass": "country", "latitude": "15.5", "longitude": "-90.25"}},{"name": "Guinea", "data": {"mapType": "global", "geoClass": "country", "latitude": "11.0", "longitude": "-10.0"}},{"name": "Guinea-Bissau", "data": {"mapType": "global", "geoClass": "country", "latitude": "12.0", "longitude": "-15.0"}},{"name": "Guyana", "data": {"mapType": "global", "geoClass": "country", "latitude": "5.0", "longitude": "-59.0"}},{"name": "Haiti", "data": {"mapType": "global", "geoClass": "country", "latitude": "19.0", "longitude": "-72.4167"}},{"name": "Heard and McDonald Islands", "data": {"mapType": "global", "geoClass": "country", "latitude": "-53.1", "longitude": "72.5167"}},{"name": "Honduras", "data": {"mapType": "global", "geoClass": "country", "latitude": "15.0", "longitude": "-86.5"}},{"name": "Hong Kong", "data": {"mapType": "global", "geoClass": "country", "latitude": "22.25", "longitude": "114.1667"}},{"name": "Hungary", "data": {"mapType": "global", "geoClass": "country", "latitude": "47.0", "longitude": "20.0"}},{"name": "Iceland", "data": {"mapType": "global", "geoClass": "country", "latitude": "65.0", "longitude": "-18.0"}},{"name": "India", "data": {"mapType": "global", "geoClass": "country", "latitude": "20.0", "longitude": "77.0"}},{"name": "Indonesia", "data": {"mapType": "global", "geoClass": "country", "latitude": "-5.0", "longitude": "120.0"}},{"name": "Iran", "data": {"mapType": "global", "geoClass": "country", "latitude": "32.0", "longitude": "53.0"}},{"name": "Iraq", "data": {"mapType": "global", "geoClass": "country", "latitude": "33.0", "longitude": "44.0"}},{"name": "Ireland", "data": {"mapType": "global", "geoClass": "country", "latitude": "53.0", "longitude": "-8.0"}},{"name": "Israel", "data": {"mapType": "global", "geoClass": "country", "latitude": "31.5", "longitude": "34.75"}},{"name": "Italy", "data": {"mapType": "global", "geoClass": "country", "latitude": "42.8333", "longitude": "12.8333"}},{"name": "Jamaica", "data": {"mapType": "global", "geoClass": "country", "latitude": "18.25", "longitude": "-77.5"}},{"name": "Japan", "data": {"mapType": "global", "geoClass": "country", "latitude": "36.0", "longitude": "138.0"}},{"name": "Jordan", "data": {"mapType": "global", "geoClass": "country", "latitude": "31.0", "longitude": "36.0"}},{"name": "Kazakhstan", "data": {"mapType": "global", "geoClass": "country", "latitude": "48.0", "longitude": "68.0"}},{"name": "Kenya", "data": {"mapType": "global", "geoClass": "country", "latitude": "1.0", "longitude": "38.0"}},{"name": "Kiribati", "data": {"mapType": "global", "geoClass": "country", "latitude": "1.4167", "longitude": "173.0"}},{"name": "North Korea", "data": {"mapType": "global", "geoClass": "country", "latitude": "40.0", "longitude": "127.0"}},{"name": "Republic of Korea", "data": {"mapType": "global", "geoClass": "country", "latitude": "37.0", "longitude": "127.5"}},{"name": "Kuwait", "data": {"mapType": "global", "geoClass": "country", "latitude": "29.3375", "longitude": "47.6581"}},{"name": "Kyrgyzstan", "data": {"mapType": "global", "geoClass": "country", "latitude": "41.0", "longitude": "75.0"}},{"name": "Laos", "data": {"mapType": "global", "geoClass": "country", "latitude": "18.0", "longitude": "105.0"}},{"name": "Latvia", "data": {"mapType": "global", "geoClass": "country", "latitude": "57.0", "longitude": "25.0"}},{"name": "Lebanon", "data": {"mapType": "global", "geoClass": "country", "latitude": "33.8333", "longitude": "35.8333"}},{"name": "Lesotho", "data": {"mapType": "global", "geoClass": "country", "latitude": "-29.5", "longitude": "28.5"}},{"name": "Liberia", "data": {"mapType": "global", "geoClass": "country", "latitude": "6.5", "longitude": "-9.5"}},{"name": "Liechtenstein", "data": {"mapType": "global", "geoClass": "country", "latitude": "47.1667", "longitude": "9.5333"}},{"name": "Lithuania", "data": {"mapType": "global", "geoClass": "country", "latitude": "56.0", "longitude": "24.0"}},{"name": "Luxembourg", "data": {"mapType": "global", "geoClass": "country", "latitude": "49.75", "longitude": "6.1667"}},{"name": "Macau", "data": {"mapType": "global", "geoClass": "country", "latitude": "22.1667", "longitude": "113.55"}},{"name": "Macedonia", "data": {"mapType": "global", "geoClass": "country", "latitude": "41.8333", "longitude": "22.0"}},{"name": "Madagascar", "data": {"mapType": "global", "geoClass": "country", "latitude": "-20.0", "longitude": "47.0"}},{"name": "Malawi", "data": {"mapType": "global", "geoClass": "country", "latitude": "-13.5", "longitude": "34.0"}},{"name": "Malaysia", "data": {"mapType": "global", "geoClass": "country", "latitude": "2.5", "longitude": "112.5"}},{"name": "Maldives", "data": {"mapType": "global", "geoClass": "country", "latitude": "3.25", "longitude": "73.0"}},{"name": "Mali", "data": {"mapType": "global", "geoClass": "country", "latitude": "17.0", "longitude": "-4.0"}},{"name": "Malta", "data": {"mapType": "global", "geoClass": "country", "latitude": "35.8333", "longitude": "14.5833"}},{"name": "Marshal Islands", "data": {"mapType": "global", "geoClass": "country", "latitude": "9.0", "longitude": "168.0"}},{"name": "Martinique", "data": {"mapType": "global", "geoClass": "country", "latitude": "14.6667", "longitude": "-61.0"}},{"name": "Mauritania", "data": {"mapType": "global", "geoClass": "country", "latitude": "20.0", "longitude": "-12.0"}},{"name": "Mauritius", "data": {"mapType": "global", "geoClass": "country", "latitude": "-20.2833", "longitude": "57.55"}},{"name": "Mayotte", "data": {"mapType": "global", "geoClass": "country", "latitude": "-12.8333", "longitude": "45.1667"}},{"name": "Mexico", "data": {"mapType": "global", "geoClass": "country", "latitude": "23.0", "longitude": "-102.0"}},{"name": "Micronesia", "data": {"mapType": "global", "geoClass": "country", "latitude": "6.9167", "longitude": "158.25"}},{"name": "Moldova", "data": {"mapType": "global", "geoClass": "country", "latitude": "47.0", "longitude": "29.0"}},{"name": "Monaco", "data": {"mapType": "global", "geoClass": "country", "latitude": "43.7333", "longitude": "7.4"}},{"name": "Mongolia", "data": {"mapType": "global", "geoClass": "country", "latitude": "46.0", "longitude": "105.0"}},{"name": "Montserrat", "data": {"mapType": "global", "geoClass": "country", "latitude": "16.75", "longitude": "-62.2"}},{"name": "Morocco", "data": {"mapType": "global", "geoClass": "country", "latitude": "32.0", "longitude": "-5.0"}},{"name": "Mozambique", "data": {"mapType": "global", "geoClass": "country", "latitude": "-18.25", "longitude": "35.0"}},{"name": "Myanmar", "data": {"mapType": "global", "geoClass": "country", "latitude": "22.0", "longitude": "98.0"}},{"name": "Namibia", "data": {"mapType": "global", "geoClass": "country", "latitude": "-22.0", "longitude": "17.0"}},{"name": "Nauru", "data": {"mapType": "global", "geoClass": "country", "latitude": "-0.5333", "longitude": "166.9167"}},{"name": "Nepal", "data": {"mapType": "global", "geoClass": "country", "latitude": "28.0", "longitude": "84.0"}},{"name": "Netherlands Antilles", "data": {"mapType": "global", "geoClass": "country", "latitude": "12.25", "longitude": "-68.75"}},{"name": "Netherlands", "data": {"mapType": "global", "geoClass": "country", "latitude": "52.5", "longitude": "5.75"}},{"name": "New Caledonia", "data": {"mapType": "global", "geoClass": "country", "latitude": "-21.5", "longitude": "165.5"}},{"name": "New Zealand", "data": {"mapType": "global", "geoClass": "country", "latitude": "-41.0", "longitude": "174.0"}},{"name": "Nicaragua", "data": {"mapType": "global", "geoClass": "country", "latitude": "13.0", "longitude": "-85.0"}},{"name": "Niger", "data": {"mapType": "global", "geoClass": "country", "latitude": "16.0", "longitude": "8.0"}},{"name": "Nigeria", "data": {"mapType": "global", "geoClass": "country", "latitude": "10.0", "longitude": "8.0"}},{"name": "Niue", "data": {"mapType": "global", "geoClass": "country", "latitude": "-19.0333", "longitude": "-169.8667"}},{"name": "Norfolk Island", "data": {"mapType": "global", "geoClass": "country", "latitude": "-29.0333", "longitude": "167.95"}},{"name": "Northern Marianas Islands", "data": {"mapType": "global", "geoClass": "country", "latitude": "15.2", "longitude": "145.75"}},{"name": "Norway", "data": {"mapType": "global", "geoClass": "country", "latitude": "62.0", "longitude": "10.0"}},{"name": "Oman", "data": {"mapType": "global", "geoClass": "country", "latitude": "21.0", "longitude": "57.0"}},{"name": "Pakistan", "data": {"mapType": "global", "geoClass": "country", "latitude": "30.0", "longitude": "70.0"}},{"name": "Palau", "data": {"mapType": "global", "geoClass": "country", "latitude": "7.5", "longitude": "134.5"}},{"name": "Panama", "data": {"mapType": "global", "geoClass": "country", "latitude": "9.0", "longitude": "-80.0"}},{"name": "Papua New Guinea", "data": {"mapType": "global", "geoClass": "country", "latitude": "-6.0", "longitude": "147.0"}},{"name": "Paraguay", "data": {"mapType": "global", "geoClass": "country", "latitude": "-23.0", "longitude": "-58.0"}},{"name": "Peru", "data": {"mapType": "global", "geoClass": "country", "latitude": "-10.0", "longitude": "-76.0"}},{"name": "Philippines", "data": {"mapType": "global", "geoClass": "country", "latitude": "13.0", "longitude": "122.0"}},{"name": "Pitcairn", "data": {"mapType": "global", "geoClass": "country", "latitude": "-24.7", "longitude": "-127.4"}},{"name": "Poland", "data": {"mapType": "global", "geoClass": "country", "latitude": "52.0", "longitude": "20.0"}},{"name": "Portugal", "data": {"mapType": "global", "geoClass": "country", "latitude": "39.5", "longitude": "-8.0"}},{"name": "Puerto Rico", "data": {"mapType": "global", "geoClass": "country", "latitude": "18.25", "longitude": "-66.5"}},{"name": "Qatar", "data": {"mapType": "global", "geoClass": "country", "latitude": "25.5", "longitude": "51.25"}},{"name": "Reunion", "data": {"mapType": "global", "geoClass": "country", "latitude": "-21.1", "longitude": "55.6"}},{"name": "Romania", "data": {"mapType": "global", "geoClass": "country", "latitude": "46.0", "longitude": "25.0"}},{"name": "Russia", "data": {"mapType": "global", "geoClass": "country", "latitude": "60.0", "longitude": "100.0"}},{"name": "Russian Federation", "data": {"mapType": "global", "geoClass": "country", "latitude": "60.0", "longitude": "100.0"}},{"name": "Rwanda", "data": {"longitude": "-2.0", "longitude": "30.0"}},{"name": "Saint Helena", "data": {"mapType": "global", "geoClass": "country", "latitude": "-15.9333", "longitude": "-5.7"}},{"name": "Saint Kitts and Nevis", "data": {"mapType": "global", "geoClass": "country", "latitude": "17.3333", "longitude": "-62.75"}},{"name": "Saint Lucia", "data": {"mapType": "global", "geoClass": "country", "latitude": "13.8833", "longitude": "-61.1333"}},{"name": "Saint Pierre and Miquelon", "data": {"mapType": "global", "geoClass": "country", "latitude": "46.8333", "longitude": "-56.3333"}},{"name": "Saint Vincent and the Grenadines", "data": {"mapType": "global", "geoClass": "country", "latitude": "13.25", "longitude": "-61.2"}},{"name": "Samoa", "data": {"mapType": "global", "geoClass": "country", "latitude": "-13.5833", "longitude": "-172.3333"}},{"name": "San Marino", "data": {"mapType": "global", "geoClass": "country", "latitude": "43.7667", "longitude": "12.4167"}},{"name": "Sao Tome and Principe", "data": {"mapType": "global", "geoClass": "country", "latitude": "1.0", "longitude": "7.0"}},{"name": "Saudi Arabia", "data": {"mapType": "global", "geoClass": "country", "latitude": "25.0", "longitude": "45.0"}},{"name": "Senegal", "data": {"mapType": "global", "geoClass": "country", "latitude": "14.0", "longitude": "-14.0"}},{"name": "Seychelles", "data": {"mapType": "global", "geoClass": "country", "latitude": "-4.5833", "longitude": "55.6667"}},{"name": "Sierra Leone", "data": {"mapType": "global", "geoClass": "country", "latitude": "8.5", "longitude": "-11.5"}},{"name": "Singapore", "data": {"mapType": "global", "geoClass": "country", "latitude": "1.3667", "longitude": "103.8"}},{"name": "Slovak Republic", "data": {"mapType": "global", "geoClass": "country", "latitude": "48.6667", "longitude": "19.5"}},{"name": "Slovenia", "data": {"mapType": "global", "geoClass": "country", "latitude": "46.0", "longitude": "15.0"}},{"name": "Solomon Islands", "data": {"mapType": "global", "geoClass": "country", "latitude": "-8.0", "longitude": "159.0"}},{"name": "Somalia", "data": {"mapType": "global", "geoClass": "country", "latitude": "10.0", "longitude": "49.0"}},{"name": "South Africa", "data": {"mapType": "global", "geoClass": "country", "latitude": "-29.0", "longitude": "24.0"}},{"name": "South Georgia and the South Sandwich Islands", "data": {"mapType": "global", "geoClass": "country", "latitude": "-54.5", "longitude": "-37.0"}},{"name": "Spain", "data": {"mapType": "global", "geoClass": "country", "latitude": "40.0", "longitude": "-4.0"}},{"name": "Sri Lanka", "data": {"mapType": "global", "geoClass": "country", "latitude": "7.0", "longitude": "81.0"}},{"name": "Sudan", "data": {"mapType": "global", "geoClass": "country", "latitude": "15.0", "longitude": "30.0"}},{"name": "Suriname", "data": {"mapType": "global", "geoClass": "country", "latitude": "4.0", "longitude": "-56.0"}},{"name": "Svalbard and Jan Mayen Islands", "data": {"mapType": "global", "geoClass": "country", "latitude": "78.0", "longitude": "20.0"}},{"name": "Swaziland", "data": {"mapType": "global", "geoClass": "country", "latitude": "-26.5", "longitude": "31.5"}},{"name": "Sweden", "data": {"mapType": "global", "geoClass": "country", "latitude": "62.0", "longitude": "15.0"}},{"name": "Switzerland", "data": {"mapType": "global", "geoClass": "country", "latitude": "47.0", "longitude": "8.0"}},{"name": "Syria", "data": {"mapType": "global", "geoClass": "country", "latitude": "35.0", "longitude": "38.0"}},{"name": "Taiwan", "data": {"mapType": "global", "geoClass": "country", "latitude": "23.5", "longitude": "121.0"}},{"name": "Tajikistan", "data": {"mapType": "global", "geoClass": "country", "latitude": "39.0", "longitude": "71.0"}},{"name": "Tanzania", "data": {"mapType": "global", "geoClass": "country", "latitude": "-6.0", "longitude": "35.0"}},{"name": "Thailand", "data": {"mapType": "global", "geoClass": "country", "latitude": "15.0", "longitude": "100.0"}},{"name": "Togo", "data": {"mapType": "global", "geoClass": "country", "latitude": "8.0", "longitude": "1.1667"}},{"name": "Tokelau", "data": {"mapType": "global", "geoClass": "country", "latitude": "-9.0", "longitude": "-172.0"}},{"name": "Tonga", "data": {"mapType": "global", "geoClass": "country", "latitude": "-20.0", "longitude": "-175.0"}},{"name": "Trinidad and Tobago", "data": {"mapType": "global", "geoClass": "country", "latitude": "11.0", "longitude": "-61.0"}},{"name": "Tunisia", "data": {"mapType": "global", "geoClass": "country", "latitude": "34.0", "longitude": "9.0"}},{"name": "Turkey", "data": {"mapType": "global", "geoClass": "country", "latitude": "39.0", "longitude": "35.0"}},{"name": "Turkmenistan", "data": {"mapType": "global", "geoClass": "country", "latitude": "40.0", "longitude": "60.0"}},{"name": "Turks and Caicos Islands", "data": {"mapType": "global", "geoClass": "country", "latitude": "21.75", "longitude": "-71.5833"}},{"name": "Tuvalu", "data": {"mapType": "global", "geoClass": "country", "latitude": "-8.0", "longitude": "178.0"}},{"name": "Uganda", "data": {"mapType": "global", "geoClass": "country", "latitude": "1.0", "longitude": "32.0"}},{"name": "Ukraine", "data": {"mapType": "global", "geoClass": "country", "latitude": "49.0", "longitude": "32.0"}},{"name": "United Arab Emirates", "data": {"mapType": "global", "geoClass": "country", "latitude": "24.0", "longitude": "54.0"}},{"name": "United Kingdom", "data": {"mapType": "global", "geoClass": "country", "latitude": "54.0", "longitude": "-2.0"}},{"name": "United States of America", "data": {"mapType": "global", "geoClass": "country", "latitude": "38.0", "longitude": "-97.0"}},{"name": "Uruguay", "data": {"mapType": "global", "geoClass": "country", "latitude": "-33.0", "longitude": "-56.0"}},{"name": "Uzbekistan", "data": {"mapType": "global", "geoClass": "country", "latitude": "41.0", "longitude": "64.0"}},{"name": "Vanuatu", "data": {"mapType": "global", "geoClass": "country", "latitude": "-16.0", "longitude": "167.0"}},{"name": "Vatican City", "data": {"mapType": "global", "geoClass": "country", "latitude": "41.9", "longitude": "12.45"}},{"name": "Venezuela", "data": {"mapType": "global", "geoClass": "country", "latitude": "8.0", "longitude": "-66.0"}},{"name": "Vietnam", "data": {"mapType": "global", "geoClass": "country", "latitude": "16.0", "longitude": "106.0"}},{"name": "British Virgin Islands", "data": {"mapType": "global", "geoClass": "country", "latitude": "18.3333", "longitude": "-64.8333"}},{"name": "US Virgin Islands", "data": {"mapType": "global", "geoClass": "country", "latitude": "18.3333", "longitude": "-64.8333"}},{"name": "Wallis and Futuna Islands", "data": {"mapType": "global", "geoClass": "country", "latitude": "-13.3", "longitude": "-176.2"}},{"name": "Western Sahara", "data": {"mapType": "global", "geoClass": "country", "latitude": "24.5", "longitude": "-13.0"}},{"name": "Yemen", "data": {"mapType": "global", "geoClass": "country", "latitude": "15.0", "longitude": "48.0"}},{"name": "Zaire", "data": {"mapType": "global", "geoClass": "country", "latitude": "-20.0", "longitude": "30.0"}},{"name": "Zambia", "data": {"mapType": "global", "geoClass": "country", "latitude": "-15.0", "longitude": "30.0"}},{"name": "Zimbabwe", "data": {"mapType": "global", "geoClass": "country", "latitude": "-20.0", "longitude": "30.0"}},{"name": "Central Africa", "data": {"mapType": "global", "geoClass": "region", "latitude": "", "longitude": ""}},{"name": "Central Europe", "data": {"mapType": "global", "geoClass": "region", "latitude": "48.9225", "longitude": "9.22852"}},{"name": "East Asia", "data": {"mapType": "global", "geoClass": "region", "latitude": "31.95216", "longitude": "120.41016"}},{"name": "Eastern North America", "data": {"mapType": "global", "geoClass": "region", "latitude": "45.213", "longitude": "-66.44531"}},{"name": "European Union (EU)", "data": {"mapType": "global", "geoClass": "region", "latitude": "48.86471", "longitude": "11.68945"}},{"name": "Central Asia", "data": {"mapType": "global", "geoClass": "region", "latitude": "36.73888", "longitude": "93.16406"}},{"name": "Former Soviet bloc countries", "data": {"mapType": "global", "geoClass": "region", "latitude": "49.72448", "longitude": "24.43359"}},{"name": "French North Africa", "data": {"mapType": "global", "geoClass": "region", "latitude": "34.45222", "longitude": "0.52734"}},{"name": "Gibraltar", "data": {"mapType": "global", "geoClass": "region", "latitude": "36.1430", "longitude": "5.3530"}},{"name": "Latin America", "data": {"mapType": "global", "geoClass": "region", "latitude": "21.69827", "longitude": "-84.50684"}},{"name": "Oceania", "data": {"mapType": "global", "geoClass": "region", "latitude": "-18.312777", "longitude": "138.51555"}},{"name": "North Africa", "data": {"mapType": "global", "geoClass": "region", "latitude": "26.43123", "longitude": "13.35938"}},{"name": "South America", "data": {"mapType": "global", "geoClass": "region", "latitude": "-21.28937", "longitude": "-58.00781"}},{"name": "South Asia", "data": {"mapType": "global", "geoClass": "region", "latitude": "22.91792", "longitude": "82.26563"}},{"name": "Southeast Asia", "data": {"mapType": "global", "geoClass": "region", "latitude": "9.1021", "longitude": "111.79688"}},{"name": "Sub-Saharan Africa", "data": {"mapType": "global", "geoClass": "region", "latitude": "2.46018", "longitude": "21.97266"}},{"name": "Tibet", "data": {"mapType": "global", "geoClass": "region", "latitude": "29.53523", "longitude": "87.89063"}},{"name": "central America", "data": {"mapType": "global", "geoClass": "region", "latitude": "16.29905", "longitude": "-92.98828"}},{"name": "eastern Africa", "data": {"mapType": "global", "geoClass": "region", "latitude": "-7.36247", "longitude": "39.19922"}},{"name": "eastern Europe", "data": {"mapType": "global", "geoClass": "region", "latitude": "47.7541", "longitude": "22.59789"}},{"name": "middle Africa", "data": {"mapType": "global", "geoClass": "region", "latitude": "5.70345", "longitude": "22.5"}},{"name": "northern Europe", "data": {"mapType": "global", "geoClass": "region", "latitude": "57.563", "longitude": "12.56836"}},{"name": "southern Africa", "data": {"mapType": "global", "geoClass": "region", "latitude": "-22.35008", "longitude": "25.04883"}},{"name": "southern Europe", "data": {"mapType": "global", "geoClass": "region", "latitude": "40.04444", "longitude": "9.14063"}},{"name": "western Africa", "data": {"mapType": "global", "geoClass": "region", "latitude": "4.65308", "longitude": "6.32813"}},{"name": "western Europe", "data": {"mapType": "global", "geoClass": "region", "latitude": "48.69096", "longitude": "3.51563"}},{"name": "Africa", "data": {"mapType": "global", "geoClass": "region", "latitude": "8.58102", "longitude": "21.97266"}},{"name": "Americas", "data": {"mapType": "global", "geoClass": "region", "latitude": "13.23995", "longitude": "-78.39844"}},{"name": "Caribbean", "data": {"mapType": "global", "geoClass": "region", "latitude": "19.64259", "longitude": "-79.10156"}},{"name": "Europe", "data": {"mapType": "global", "geoClass": "region", "latitude": "50.84757", "longitude": "19.33594"}},{"name": "Melanesia", "data": {"mapType": "global", "geoClass": "region", "latitude": "-11.3508", "longitude": "165.9375"}},{"name": "Asia", "data": {"mapType": "global", "geoClass": "region", "latitude": "40.31304", "longitude": "90.78906"}},{"name": "North America", "data": {"mapType": "global", "geoClass": "region", "latitude": "46.43786", "longitude": "-97.73437"}},{"name": "northern America", "data": {"mapType": "global", "geoClass": "region", "latitude": "45.58329", "longitude": "-91.75781"}},{"name": "western Asia", "data": {"mapType": "global", "geoClass": "region", "latitude": "36.45664", "longitude": "57.12891"}},{"name": "Polynesia", "data": {"mapType": "global", "geoClass": "region", "latitude": "1.75754", "longitude": "-156.09375"}},{"name": "eastern Asia", "data": {"mapType": "global", "geoClass": "region", "latitude": "30.75128", "longitude": "126.38672"}},{"name": "northern Africa", "data": {"mapType": "global", "geoClass": "region", "latitude": "29.53523", "longitude": "14.23828"}},{"name": "south-eastern Asia", "data": {"mapType": "global", "geoClass": "region", "latitude": "6.3153", "longitude": "129.375"}},{"name": "southern Asia", "data": {"mapType": "global", "geoClass": "region", "latitude": "-1.05463", "longitude": "108.63281"}},{"name": "Alaska", "data": {"mapType": "country", "geoClass": "state", "latitude": "64.3850", "longitude": "-154.2683"}},{"name": "Alabama", "data": {"mapType": "country", "geoClass": "state", "latitude": "32.7990", "longitude": "-86.8073"}},{"name": "Arkansas", "data": {"mapType": "country", "geoClass": "state", "latitude": "34.9513", "longitude": "-92.3809"}},{"name": "Arizona", "data": {"mapType": "country", "geoClass": "state", "latitude": "33.7712", "longitude": "-111.3877"}},{"name": "California", "data": {"mapType": "country", "geoClass": "state", "latitude": "36.1700", "longitude": "-119.7462"}},{"name": "Colorado", "data": {"mapType": "country", "geoClass": "state", "latitude": "39.0646", "longitude": "-105.3272"}},{"name": "Connecticut", "data": {"mapType": "country", "geoClass": "state", "latitude": "41.5834", "longitude": "-72.7622"}},{"name": "District of Columbia", "data": {"mapType": "country", "geoClass": "state", "latitude": "38.8964", "longitude": "-77.0262"}},{"name": "Delaware", "data": {"mapType": "country", "geoClass": "state", "latitude": "39.3498", "longitude": "-75.5148"}},{"name": "Florida", "data": {"mapType": "country", "geoClass": "state", "latitude": "27.8333", "longitude": "-81.7170"}},{"name": "Georgia", "data": {"mapType": "country", "geoClass": "state", "latitude": "32.9866", "longitude": "-83.6487"}},{"name": "Hawaii", "data": {"mapType": "country", "geoClass": "state", "latitude": "21.1098", "longitude": "-157.5311"}},{"name": "Iowa", "data": {"mapType": "country", "geoClass": "state", "latitude": "42.0046", "longitude": "-93.2140"}},{"name": "Idaho", "data": {"mapType": "country", "geoClass": "state", "latitude": "44.2394", "longitude": "-114.5103"}},{"name": "Illinois", "data": {"mapType": "country", "geoClass": "state", "latitude": "40.3363", "longitude": "-89.0022"}},{"name": "Indiana", "data": {"mapType": "country", "geoClass": "state", "latitude": "39.8647", "longitude": "-86.2604"}},{"name": "Kansas", "data": {"mapType": "country", "geoClass": "state", "latitude": "38.5111", "longitude": "-96.8005"}},{"name": "Kentucky", "data": {"mapType": "country", "geoClass": "state", "latitude": "37.6690", "longitude": "-84.6514"}},{"name": "Louisiana", "data": {"mapType": "country", "geoClass": "state", "latitude": "31.1801", "longitude": "-91.8749"}},{"name": "Massachusetts", "data": {"mapType": "country", "geoClass": "state", "latitude": "42.2373", "longitude": "-71.5314"}},{"name": "Maryland", "data": {"mapType": "country", "geoClass": "state", "latitude": "39.0724", "longitude": "-76.7902"}},{"name": "Maine", "data": {"mapType": "country", "geoClass": "state", "latitude": "44.6074", "longitude": "-69.3977"}},{"name": "Michigan", "data": {"mapType": "country", "geoClass": "state", "latitude": "43.3504", "longitude": "-84.5603"}},{"name": "Minnesota", "data": {"mapType": "country", "geoClass": "state", "latitude": "", "longitude": ""}},{"name": "Missouri", "data": {"mapType": "country", "geoClass": "state", "latitude": "38.4623", "longitude": "-92.3020"}},{"name": "Mississippi", "data": {"mapType": "country", "geoClass": "state", "latitude": "32.7673", "longitude": "-89.6812"}},{"name": "Montana", "data": {"mapType": "country", "geoClass": "state", "latitude": "46.9048", "longitude": "-110.3261"}},{"name": "North Carolina", "data": {"mapType": "country", "geoClass": "state", "latitude": "35.6411", "longitude": "-79.8431"}},{"name": "North Dakota", "data": {"mapType": "country", "geoClass": "state", "latitude": "47.5362", "longitude": "-99.7930"}},{"name": "Nebraska", "data": {"mapType": "country", "geoClass": "state", "latitude": "41.1289", "longitude": "-98.2883"}},{"name": "New Hampshire", "data": {"mapType": "country", "geoClass": "state", "latitude": "43.4108", "longitude": "-71.5653"}},{"name": "New Jersey", "data": {"mapType": "country", "geoClass": "state", "latitude": "40.3140", "longitude": "-74.5089"}},{"name": "New Mexico", "data": {"mapType": "country", "geoClass": "state", "latitude": "34.8375", "longitude": "-106.2371"}},{"name": "Nevada", "data": {"mapType": "country", "geoClass": "state", "latitude": "38.4199", "longitude": "-117.1219"}},{"name": "New York", "data": {"mapType": "country", "geoClass": "state", "latitude": "42.1497", "longitude": "-74.9384"}},{"name": "Ohio", "data": {"mapType": "country", "geoClass": "state", "latitude": "40.3736", "longitude": "-82.7755"}},{"name": "Oklahoma", "data": {"mapType": "country", "geoClass": "state", "latitude": "35.5376", "longitude": "-96.9247"}},{"name": "Oregon", "data": {"mapType": "country", "geoClass": "state", "latitude": "44.5672", "longitude": "-122.1269"}},{"name": "Pennsylvania", "data": {"mapType": "country", "geoClass": "state", "latitude": "40.5773", "longitude": "-77.2640"}},{"name": "Rhode Island", "data": {"mapType": "country", "geoClass": "state", "latitude": "41.6772", "longitude": "-71.5101"}},{"name": "South Carolina", "data": {"mapType": "country", "geoClass": "state", "latitude": "33.8191", "longitude": "-80.9066"}},{"name": "Tennessee", "data": {"mapType": "country", "geoClass": "state", "latitude": "35.7449", "longitude": "-86.7489"}},{"name": "South Dakota", "data": {"mapType": "country", "geoClass": "state", "latitude": "44.2853", "longitude": "-99.4632"}},{"name": "Texas", "data": {"mapType": "country", "geoClass": "state", "latitude": "31.1060", "longitude": "-97.6475"}},{"name": "Utah", "data": {"mapType": "country", "geoClass": "state", "latitude": "40.1135", "longitude": "-111.8535"}},{"name": "Virginia", "data": {"mapType": "country", "geoClass": "state", "latitude": "37.7680", "longitude": "-78.2057"}},{"name": "Vermont", "data": {"mapType": "country", "geoClass": "state", "latitude": "44.0407", "longitude": "-72.7093"}},{"name": "Washington", "data": {"mapType": "country", "geoClass": "state", "latitude": "47.3917", "longitude": "-121.5708"}},{"name": "Wisconsin", "data": {"mapType": "country", "geoClass": "state", "latitude": "44.2563", "longitude": "-89.6385"}},{"name": "West Virginia", "data": {"mapType": "country", "geoClass": "state", "latitude": "38.4680", "longitude": "-80.9696"}},{"name": "Wyoming", "data": {"mapType": "country", "geoClass": "state", "latitude": "42.7475", "longitude": "-107.2085"}}]; diff --git a/productMods/templates/freemarker/body/individual/individual--foaf-person-2column.ftl b/productMods/templates/freemarker/body/individual/individual--foaf-person-2column.ftl index d3a63df8..b50f47af 100644 --- a/productMods/templates/freemarker/body/individual/individual--foaf-person-2column.ftl +++ b/productMods/templates/freemarker/body/individual/individual--foaf-person-2column.ftl @@ -10,6 +10,9 @@ <#if !labelCount??> <#assign labelCount = 0 > +<#if !localesCount??> + <#assign localesCount = 1> + <#assign qrCodeIcon = "qr-code-icon.png"> <#assign visRequestingTemplate = "foaf-person-2column">
    @@ -40,7 +43,7 @@ <#else>

    style="float:left;border-right:1px solid #A6B1B0;"> <#-- Label --> - <@p.label individual editable labelCount/> + <@p.label individual editable labelCount localesCount/>

    <#-- Display preferredTitle if it exists; otherwise mostSpecificTypes --> <#assign title = propertyGroups.pullProperty("${core}preferredTitle")!> diff --git a/productMods/templates/freemarker/body/individual/individual--foaf-person-quickview.ftl b/productMods/templates/freemarker/body/individual/individual--foaf-person-quickview.ftl index 810250b5..006f1f8e 100644 --- a/productMods/templates/freemarker/body/individual/individual--foaf-person-quickview.ftl +++ b/productMods/templates/freemarker/body/individual/individual--foaf-person-quickview.ftl @@ -12,6 +12,9 @@ <#if !labelCount??> <#assign labelCount = 0 > +<#if !localesCount??> + <#assign localesCount = 1> + <#assign qrCodeIcon = "qr-code-icon.png"> <#assign individualImage> <@p.image individual=individual @@ -52,7 +55,7 @@
    ${individualImage}

    style="float:left;border-right:1px solid #A6B1B0;"> <#-- Label --> - <@p.label individual editable labelCount/> + <@p.label individual editable labelCount localesCount/>

    <#-- Display preferredTitle if it exists; otherwise mostSpecificTypes --> <#assign title = propertyGroups.pullProperty("${core}preferredTitle")!> diff --git a/productMods/templates/freemarker/body/individual/individual--skos-concept.ftl b/productMods/templates/freemarker/body/individual/individual--skos-concept.ftl new file mode 100644 index 00000000..628b1780 --- /dev/null +++ b/productMods/templates/freemarker/body/individual/individual--skos-concept.ftl @@ -0,0 +1,12 @@ +<#-- $This file is distributed under the terms of the license in /doc/license.txt$ --> + +<#-- Individual profile page template for skos:Concept individuals (extends individual.ftl in vivo)--> + +<#-- Do not show the link for temporal visualization unless it's enabled --> + +<#assign affiliatedResearchAreas> + <#include "individual-affiliated-departments.ftl"> + + +<#include "individual.ftl"> + diff --git a/productMods/templates/freemarker/body/individual/manageLabelsForIndividualAddForm.ftl b/productMods/templates/freemarker/body/individual/manageLabelsForIndividualAddForm.ftl new file mode 100644 index 00000000..9c0985ed --- /dev/null +++ b/productMods/templates/freemarker/body/individual/manageLabelsForIndividualAddForm.ftl @@ -0,0 +1,40 @@ +<#-- $This file is distributed under the terms of the license in /doc/license.txt$ --> +<#-- Custom form for managing labels for individuals - specific to VIVO which handles people as well --> +<#assign isPersonType = editConfiguration.pageData.isPersonType /> +
    +

    ${i18n().add_label}

    + <#if isPersonType = "true"> +

    + + +

    + +

    + + +

    + <#else> +

    + + +

    + + + + + + + + ${i18n().or} + ${i18n().cancel_link} + +

    * ${i18n().required_fields}

    +
    \ No newline at end of file diff --git a/productMods/templates/freemarker/body/individual/manageLabelsForIndividualSubmissionErrors.ftl b/productMods/templates/freemarker/body/individual/manageLabelsForIndividualSubmissionErrors.ftl new file mode 100644 index 00000000..c5b8b144 --- /dev/null +++ b/productMods/templates/freemarker/body/individual/manageLabelsForIndividualSubmissionErrors.ftl @@ -0,0 +1,27 @@ +<#-- $This file is distributed under the terms of the license in /doc/license.txt$ --> +<#--VIVO specific errors for person--> +<#import "lib-vivo-form.ftl" as lvf> + +<#--Get existing value for specific data literals and uris, in case the form is returned because of an error--> +<#assign firstNameValue = lvf.getFormFieldValue(editSubmission, editConfiguration, "firstName")/> +<#assign lastNameValue = lvf.getFormFieldValue(editSubmission, editConfiguration, "lastName")/> +<#assign labelValue = lvf.getFormFieldValue(editSubmission, editConfiguration, "label")/> +<#assign newLabelLanguageValue = lvf.getFormFieldValue(editSubmission, editConfiguration, "newLabelLanguage")/> + +<#if submissionErrors?has_content > + + \ No newline at end of file diff --git a/productMods/templates/freemarker/body/individual/manageLabelsForIndividualTerms.ftl b/productMods/templates/freemarker/body/individual/manageLabelsForIndividualTerms.ftl new file mode 100644 index 00000000..cca1dcb6 --- /dev/null +++ b/productMods/templates/freemarker/body/individual/manageLabelsForIndividualTerms.ftl @@ -0,0 +1,4 @@ +<#-- $This file is distributed under the terms of the license in /doc/license.txt$ --> + +<#--Some values for labels etc. may be different between vitro and other systems --> +<#assign returnText = "${i18n().return_to_profile}" /> \ No newline at end of file diff --git a/productMods/templates/freemarker/body/partials/individual/individual-affiliated-departments.ftl b/productMods/templates/freemarker/body/partials/individual/individual-affiliated-departments.ftl new file mode 100644 index 00000000..59a6f9b8 --- /dev/null +++ b/productMods/templates/freemarker/body/partials/individual/individual-affiliated-departments.ftl @@ -0,0 +1,35 @@ +<#-- $This file is distributed under the terms of the license in /doc/license.txt$ --> +<#if departmentsResults?has_content> + <#-- is strictly a usability issue so we can refer accurately to "faculty members" within the dept. --> + <#assign urlForDetailsPage = "affiliatedDepartments" /> + <#assign headingText = "${i18n().affiliated_departments}" /> +

    + ${headingText} +

    + + + diff --git a/productMods/templates/freemarker/body/partials/individual/individual-affiliated-dept-details.ftl b/productMods/templates/freemarker/body/partials/individual/individual-affiliated-dept-details.ftl new file mode 100644 index 00000000..3cb68d26 --- /dev/null +++ b/productMods/templates/freemarker/body/partials/individual/individual-affiliated-dept-details.ftl @@ -0,0 +1,25 @@ +<#-- $This file is distributed under the terms of the license in /doc/license.txt$ --> +<#if deptResearchAreas?has_content> +
    + <#list deptResearchAreas as firstRow> + <#assign raLink = "${urls.base}/individual?uri=${firstRow['raURI']}" /> +
    +

    ${firstRow["orgLabel"]}

    +

    ${i18n().individuals_with_dept(firstRow['raLabel'],raLink)} ${i18n().view_all_individuals_in_dept}

    +
    + <#break> + +
    + +
    + + +
    + + diff --git a/productMods/templates/freemarker/body/partials/individual/individual-affiliated-res-area-details.ftl b/productMods/templates/freemarker/body/partials/individual/individual-affiliated-res-area-details.ftl index bf62c621..f3c6e1d9 100644 --- a/productMods/templates/freemarker/body/partials/individual/individual-affiliated-res-area-details.ftl +++ b/productMods/templates/freemarker/body/partials/individual/individual-affiliated-res-area-details.ftl @@ -3,11 +3,12 @@
    <#list affiliatedResearchAreas as firstRow> <#assign firstOrgLabel = firstRow["orgLabel"]?upper_case /> + <#assign deptLink = "${urls.base}/individual?uri=${firstRow['orgURI']}" /> <#assign i18TextString1 = "" /> <#if ( firstOrgLabel?index_of("THE") == 0 ) > - <#assign i18TextString1 = "${i18n().individuals_with_researh_area_one(firstRow['orgLabel'])}" /> + <#assign i18TextString1 = "${i18n().individuals_with_researh_area_one(firstRow['orgLabel'],deptLink)}" /> <#else> - <#assign i18TextString1 = "${i18n().individuals_with_researh_area_two(firstRow['orgLabel'])}" /> + <#assign i18TextString1 = "${i18n().individuals_with_researh_area_two(firstRow['orgLabel'],deptLink)}" />

    ${firstRow["raLabel"]}

    diff --git a/productMods/templates/freemarker/body/partials/individual/individual-researchAreas.ftl b/productMods/templates/freemarker/body/partials/individual/individual-researchAreas.ftl index a2c9dc9b..aaabeb05 100644 --- a/productMods/templates/freemarker/body/partials/individual/individual-researchAreas.ftl +++ b/productMods/templates/freemarker/body/partials/individual/individual-researchAreas.ftl @@ -2,6 +2,7 @@ <#-- List of research areas for the individual --> <#assign researchAreas = propertyGroups.pullProperty("${core}hasResearchArea")!> +<#assign concepts = propertyGroups.pullProperty("${core}hasAssociatedConcept")!> <#if researchAreas?has_content> <#-- true when the property is in the list, even if not populated (when editing) --> <#assign localName = researchAreas.localName>

    @@ -11,5 +12,5 @@

      <@p.objectProperty researchAreas editable /> -
    + diff --git a/productMods/templates/freemarker/edit/forms/addAssociatedConcept.ftl b/productMods/templates/freemarker/edit/forms/addAssociatedConcept.ftl index 4e40f816..bacdf43f 100644 --- a/productMods/templates/freemarker/edit/forms/addAssociatedConcept.ftl +++ b/productMods/templates/freemarker/edit/forms/addAssociatedConcept.ftl @@ -51,6 +51,9 @@ <#if existingConcept.vocabURI?has_content && existingConcept.vocabLabel?has_content> (${existingConcept.vocabLabel}) + <#if existingConcept.conceptSemanticTypeLabel?has_content> + ${existingConcept.conceptSemanticTypeLabel} +  ${i18n().remove_capitalized} @@ -95,7 +98,10 @@

    ${i18n().or}  ${i18n().create_own_concept}  - + + + +

    diff --git a/productMods/templates/freemarker/edit/forms/js/addConcept.js b/productMods/templates/freemarker/edit/forms/js/addConcept.js index 5eb9318c..d650d349 100644 --- a/productMods/templates/freemarker/edit/forms/js/addConcept.js +++ b/productMods/templates/freemarker/edit/forms/js/addConcept.js @@ -54,6 +54,7 @@ var addConceptForm = { this.externalConceptURI = $('#conceptNode'); this.externalConceptLabel = $('#conceptLabel'); this.externalConceptSource = $('#conceptSource'); + this.externalConceptSemanticTypeLabel = $("#conceptSemanticTypeLabel"); //remove links this.removeConceptLinks = $('a.remove'); this.errors = $('#errors'); @@ -202,7 +203,9 @@ var addConceptForm = { var definedBy = conceptResult.definedBy; var type = conceptResult.type; var uri = conceptResult.uri; - return addConceptForm.generateIndividualConceptDisplay(uri, label, definition, type, definedBy, isBestMatch); + //this will be null if there are no alternate labels + var altLabels = conceptResult.altLabelList; + return addConceptForm.generateIndividualConceptDisplay(uri, label, altLabels, definition, type, definedBy, isBestMatch); }, //This should now return all best matches in one array and other results in another parseResults:function(resultsArray) { @@ -236,31 +239,35 @@ var addConceptForm = { } var i; var len = checkedElements.length; - var checkedConcept, checkedConceptElement, conceptLabel, conceptSource; + var checkedConcept, checkedConceptElement, conceptLabel, conceptSource, conceptSemanticType; var conceptNodes = []; var conceptLabels = []; var conceptSources = []; + var conceptSemanticTypes = []; checkedElements.each(function() { checkedConceptElement = $(this); checkedConcept = checkedConceptElement.val(); conceptLabel = checkedConceptElement.attr("label"); conceptSource = checkedConceptElement.attr("conceptDefinedBy"); + conceptSemanticType = checkedConceptElement.attr("conceptType"); conceptNodes.push(checkedConcept); conceptLabels.push(conceptLabel); conceptSources.push(conceptSource); + conceptSemanticTypes.push(conceptSemanticType); }); this.externalConceptURI.val(conceptNodes); this.externalConceptLabel.val(conceptLabels); this.externalConceptSource.val(conceptSources); + this.externalConceptSemanticTypeLabel.val(conceptSemanticTypes); return true; }, - generateIndividualConceptDisplay: function(cuiURI, label, definition, type, definedBy, isBestMatch) { + generateIndividualConceptDisplay: function(cuiURI, label, altLabels, definition, type, definedBy, isBestMatch) { var htmlAdd = "
  • " + "
    " + "
    " + addConceptForm.generateIndividualCUIInput(cuiURI, label, type, definedBy) + - label + addConceptForm.generateIndividualTypeDisplay(type) + "
    " + + addConceptForm.generateIndividualLabelsDisplay(label, altLabels) + addConceptForm.generateIndividualTypeDisplay(type) + "
    " + addConceptForm.generateIndividualDefinitionDisplay(definition) + addConceptForm.generateBestOrAlternate(isBestMatch) + "
  • " + @@ -270,6 +277,14 @@ var addConceptForm = { generateIndividualCUIInput:function(cuiURI, label, type, definedBy) { return ""; }, + //In case there are multiple labels display those + generateIndividualLabelsDisplay:function(label, altLabels) { + var labelDisplay = label; + if(altLabels != null && altLabels.length > 0) { + labelDisplay += "
    [" + altLabels + "]"; + } + return labelDisplay; + }, generateIndividualTypeDisplay:function(type) { if(type != null && type.length > 0) { return " (" + type + ")"; diff --git a/productMods/templates/freemarker/lib/lib-home-page.ftl b/productMods/templates/freemarker/lib/lib-home-page.ftl index 45baa28e..d3850f68 100644 --- a/productMods/templates/freemarker/lib/lib-home-page.ftl +++ b/productMods/templates/freemarker/lib/lib-home-page.ftl @@ -205,3 +205,16 @@ var urlsBase = "${urls.base}";
    +<#-- retrieves a count, the number of researchers with a geographic focus, --> +<#-- and saves it as a js variable to be used by the homePageMaps.js file --> +<#macro getGeoResearcherCount> + + diff --git a/productMods/WEB-INF/filegraph/abox/academicDegree.rdf b/rdf/abox/filegraph/academicDegree.rdf similarity index 100% rename from productMods/WEB-INF/filegraph/abox/academicDegree.rdf rename to rdf/abox/filegraph/academicDegree.rdf diff --git a/productMods/WEB-INF/filegraph/abox/continents.n3 b/rdf/abox/filegraph/continents.n3 similarity index 100% rename from productMods/WEB-INF/filegraph/abox/continents.n3 rename to rdf/abox/filegraph/continents.n3 diff --git a/productMods/WEB-INF/filegraph/abox/dateTimeValuePrecision.owl b/rdf/abox/filegraph/dateTimeValuePrecision.owl similarity index 100% rename from productMods/WEB-INF/filegraph/abox/dateTimeValuePrecision.owl rename to rdf/abox/filegraph/dateTimeValuePrecision.owl diff --git a/productMods/WEB-INF/filegraph/abox/documentStatus.owl b/rdf/abox/filegraph/documentStatus.owl similarity index 100% rename from productMods/WEB-INF/filegraph/abox/documentStatus.owl rename to rdf/abox/filegraph/documentStatus.owl diff --git a/productMods/WEB-INF/filegraph/abox/geopolitical.abox.ver1.1-11-18-11.owl b/rdf/abox/filegraph/geopolitical.abox.ver1.1-11-18-11.owl similarity index 100% rename from productMods/WEB-INF/filegraph/abox/geopolitical.abox.ver1.1-11-18-11.owl rename to rdf/abox/filegraph/geopolitical.abox.ver1.1-11-18-11.owl diff --git a/productMods/WEB-INF/filegraph/abox/us-states.rdf b/rdf/abox/filegraph/us-states.rdf similarity index 100% rename from productMods/WEB-INF/filegraph/abox/us-states.rdf rename to rdf/abox/filegraph/us-states.rdf diff --git a/productMods/WEB-INF/ontologies/user/abox/vocabularySource-labels.n3 b/rdf/abox/filegraph/vocabularySource.n3 similarity index 51% rename from productMods/WEB-INF/ontologies/user/abox/vocabularySource-labels.n3 rename to rdf/abox/filegraph/vocabularySource.n3 index a0a7966e..a111d896 100644 --- a/productMods/WEB-INF/ontologies/user/abox/vocabularySource-labels.n3 +++ b/rdf/abox/filegraph/vocabularySource.n3 @@ -1,3 +1,6 @@ + . + . + . "UMLS"^^ . "AGROVOC"^^ . "GEMET"^^ . \ No newline at end of file diff --git a/productMods/WEB-INF/ontologies/user/abox/geopolitical.ver1.1-11-18-11-individual-labels.rdf b/rdf/abox/firsttime/geopolitical.ver1.1-11-18-11-individual-labels.rdf similarity index 100% rename from productMods/WEB-INF/ontologies/user/abox/geopolitical.ver1.1-11-18-11-individual-labels.rdf rename to rdf/abox/firsttime/geopolitical.ver1.1-11-18-11-individual-labels.rdf diff --git a/productMods/WEB-INF/ontologies/user/applicationMetadata/classgroups.rdf b/rdf/applicationMetadata/firsttime/classgroups.rdf similarity index 100% rename from productMods/WEB-INF/ontologies/user/applicationMetadata/classgroups.rdf rename to rdf/applicationMetadata/firsttime/classgroups.rdf diff --git a/productMods/WEB-INF/init-data/initialSiteConfig.rdf b/rdf/applicationMetadata/firsttime/initialSiteConfig.rdf similarity index 100% rename from productMods/WEB-INF/init-data/initialSiteConfig.rdf rename to rdf/applicationMetadata/firsttime/initialSiteConfig.rdf diff --git a/productMods/WEB-INF/ontologies/user/applicationMetadata/propertygroups.rdf b/rdf/applicationMetadata/firsttime/propertygroups.rdf similarity index 100% rename from productMods/WEB-INF/ontologies/user/applicationMetadata/propertygroups.rdf rename to rdf/applicationMetadata/firsttime/propertygroups.rdf diff --git a/productMods/WEB-INF/ontologies/app/loadedAtStartup/PropertyConfig.n3 b/rdf/display/everytime/PropertyConfig.n3 similarity index 100% rename from productMods/WEB-INF/ontologies/app/loadedAtStartup/PropertyConfig.n3 rename to rdf/display/everytime/PropertyConfig.n3 diff --git a/productMods/WEB-INF/ontologies/app/loadedAtStartup/homePageDataGetters.n3 b/rdf/display/everytime/homePageDataGetters.n3 similarity index 58% rename from productMods/WEB-INF/ontologies/app/loadedAtStartup/homePageDataGetters.n3 rename to rdf/display/everytime/homePageDataGetters.n3 index 40a566b8..da71cc26 100644 --- a/productMods/WEB-INF/ontologies/app/loadedAtStartup/homePageDataGetters.n3 +++ b/rdf/display/everytime/homePageDataGetters.n3 @@ -29,3 +29,23 @@ display:academicDeptsDataGetter """ . + display:hasDataGetter display:researcherCountDataGetter . + +display:researcherCountDataGetter + a ; + display:saveToVar "researcherCountDG" ; + display:query """ + PREFIX geo: + PREFIX rdfs: + PREFIX rdf: + PREFIX core: + PREFIX foaf: + PREFIX vivoc: + + SELECT DISTINCT (COUNT(?person) AS ?count) + WHERE { + ?person rdf:type foaf:Person . + FILTER (EXISTS {?person core:geographicFocus ?focus}) + } + + """ . diff --git a/productMods/WEB-INF/ontologies/app/loadedAtStartup/localeSelectionGUI.n3 b/rdf/display/everytime/localeSelectionGUI.n3 similarity index 100% rename from productMods/WEB-INF/ontologies/app/loadedAtStartup/localeSelectionGUI.n3 rename to rdf/display/everytime/localeSelectionGUI.n3 diff --git a/rdf/display/everytime/vivoConceptDataGetters.n3 b/rdf/display/everytime/vivoConceptDataGetters.n3 new file mode 100644 index 00000000..47157443 --- /dev/null +++ b/rdf/display/everytime/vivoConceptDataGetters.n3 @@ -0,0 +1,82 @@ +# $This file is distributed under the terms of the license in /doc/license.txt$ + +@prefix owl: . +@prefix display: . +@prefix rdf: . +@prefix rdfs: . +@prefix core: . +@prefix vivoweb: . +@prefix afn: . + + +#### n3 for research areas #### + +## associate the classes with the datagetter ## + + display:hasDataGetter display:getDepartmentDataGetter . + +## define the datagetter ## + +display:getDepartmentDataGetter + a ; + display:saveToVar "departmentsResults"; + display:query + """ + PREFIX rdfs: + PREFIX vivo: + PREFIX afn: + SELECT DISTINCT (str(?departmentLabel) AS ?deptLabel) ?dept + WHERE { + ?individualURI vivo:researchAreaOf ?person . + ?person vivo:personInPosition ?posn . + ?posn vivo:positionInOrganization ?dept . + ?dept rdfs:label ?departmentLabel + OPTIONAL { ?posn vivo:dateTimeInterval ?dti + OPTIONAL { ?dti vivo:end ?end . + ?end vivo:dateTime ?endDate + } + } + FILTER ( !bound(?endDate) || + afn:substring(str(?endDate), 0, 4) >= afn:substring(str(afn:now()), 0, 4) ) + } + ORDER BY ?deptLabel + """ . + +## detail page for dept research areas ## + + + a ; + ; + "individual-affiliated-dept-details.ftl" ; + "Affiliated Departments" ; + "/affiliatedDepartments" . + + + a ; + + """ + PREFIX rdfs: + PREFIX vivo: + SELECT DISTINCT (str (?prsnLabel) AS ?personLabel) + ?person + (Str(?researchAreaLabel) AS ?raLabel) + (str(?departmentLabel) AS ?orgLabel) + ?raURI + ?orgURI + WHERE { + ?orgURI vivo:organizationForPosition ?posn . + ?orgURI rdfs:label ?orgLabel . + ?posn vivo:positionForPerson ?person . + ?person rdfs:label ?prsnLabel . + ?person vivo:hasResearchArea ?raURI . + ?raURI rdfs:label ?researchAreaLabel + + } + ORDER BY ?personLabel + """ ; + + "deptResearchAreas" . + + + + diff --git a/productMods/WEB-INF/ontologies/app/loadedAtStartup/vivoListViewConfig.rdf b/rdf/display/everytime/vivoListViewConfig.rdf similarity index 100% rename from productMods/WEB-INF/ontologies/app/loadedAtStartup/vivoListViewConfig.rdf rename to rdf/display/everytime/vivoListViewConfig.rdf diff --git a/productMods/WEB-INF/ontologies/app/loadedAtStartup/vivoOrganizationDataGetters.n3 b/rdf/display/everytime/vivoOrganizationDataGetters.n3 similarity index 99% rename from productMods/WEB-INF/ontologies/app/loadedAtStartup/vivoOrganizationDataGetters.n3 rename to rdf/display/everytime/vivoOrganizationDataGetters.n3 index b1ece312..7e3c301f 100644 --- a/productMods/WEB-INF/ontologies/app/loadedAtStartup/vivoOrganizationDataGetters.n3 +++ b/rdf/display/everytime/vivoOrganizationDataGetters.n3 @@ -69,6 +69,7 @@ display:getResearchAreaDataGetter (str(?researchAreaLabel) AS ?raLabel) (str(?organizationLabel) AS ?orgLabel) ?raURI + ?orgURI WHERE { ?orgURI vivo:organizationForPosition ?posn . ?orgURI rdfs:label ?organizationLabel . @@ -101,6 +102,7 @@ display:getResearchAreaDataGetter (Str(?researchAreaLabel) AS ?raLabel) (str(?departmentLabel) AS ?orgLabel) ?raURI + ?orgURI WHERE { ?orgURI vivo:organizationForPosition ?posn . ?orgURI rdfs:label ?orgLabel . diff --git a/productMods/WEB-INF/ontologies/app/loadedAtStartup/vivoSearchProhibited.n3 b/rdf/display/everytime/vivoSearchProhibited.n3 similarity index 100% rename from productMods/WEB-INF/ontologies/app/loadedAtStartup/vivoSearchProhibited.n3 rename to rdf/display/everytime/vivoSearchProhibited.n3 diff --git a/productMods/WEB-INF/ontologies/app/aboutPage.n3 b/rdf/display/firsttime/aboutPage.n3 similarity index 95% rename from productMods/WEB-INF/ontologies/app/aboutPage.n3 rename to rdf/display/firsttime/aboutPage.n3 index b52685bb..c606c2d5 100644 --- a/productMods/WEB-INF/ontologies/app/aboutPage.n3 +++ b/rdf/display/firsttime/aboutPage.n3 @@ -8,7 +8,7 @@ about:ABOUTDG """

    About VIVO

    The VIVO application enables the discovery of researchers across institutions. Participants in the network include institutions with local installations of VIVO or those with research discovery and profiling applications that can provide semantic web-compliant data. The information accessible through VIVO's search and browse capability will therefore reside and be controlled locally, within institutional VIVOs or other semantic web-compliant applications.

    -

    VIVO is an open source semantic web application originally developed and implemented at Cornell. When installed and populated with content at an institution, it enables the discovery of research and scholarship across disciplines at that institution. VIVO supports browsing and a search function which returns faceted results for rapid retrieval of desired information. Content in any local VIVO installation may be maintained manually or brought into the database in automated ways from local systems of record, such as HR, RBIs, grants, course, and faculty activity databases.

    +

    VIVO is an open source semantic web application originally developed and implemented at Cornell. When installed and populated with content at an institution, it enables the discovery of research and scholarship across disciplines at that institution. VIVO supports browsing and a search function which returns faceted results for rapid retrieval of desired information. Content in any local VIVO installation may be maintained manually or brought into the database in automated ways from local systems of record, such as human resources, scholarships, grants, course, and faculty activity databases.

    See more information on the VIVO Project.

    """@en ; diff --git a/productMods/WEB-INF/ontologies/app/menu.n3 b/rdf/display/firsttime/menu.n3 similarity index 100% rename from productMods/WEB-INF/ontologies/app/menu.n3 rename to rdf/display/firsttime/menu.n3 diff --git a/productMods/WEB-INF/filegraph/tbox/agent.owl b/rdf/tbox/filegraph/agent.owl similarity index 100% rename from productMods/WEB-INF/filegraph/tbox/agent.owl rename to rdf/tbox/filegraph/agent.owl diff --git a/productMods/WEB-INF/filegraph/tbox/appControls-temp.n3 b/rdf/tbox/filegraph/appControls-temp.n3 similarity index 100% rename from productMods/WEB-INF/filegraph/tbox/appControls-temp.n3 rename to rdf/tbox/filegraph/appControls-temp.n3 diff --git a/productMods/WEB-INF/filegraph/tbox/bfo-bridge.owl b/rdf/tbox/filegraph/bfo-bridge.owl similarity index 100% rename from productMods/WEB-INF/filegraph/tbox/bfo-bridge.owl rename to rdf/tbox/filegraph/bfo-bridge.owl diff --git a/productMods/WEB-INF/filegraph/tbox/bfo.owl b/rdf/tbox/filegraph/bfo.owl similarity index 100% rename from productMods/WEB-INF/filegraph/tbox/bfo.owl rename to rdf/tbox/filegraph/bfo.owl diff --git a/productMods/WEB-INF/filegraph/tbox/clinical.owl b/rdf/tbox/filegraph/clinical.owl similarity index 100% rename from productMods/WEB-INF/filegraph/tbox/clinical.owl rename to rdf/tbox/filegraph/clinical.owl diff --git a/productMods/WEB-INF/filegraph/tbox/contact-vcard.owl b/rdf/tbox/filegraph/contact-vcard.owl similarity index 100% rename from productMods/WEB-INF/filegraph/tbox/contact-vcard.owl rename to rdf/tbox/filegraph/contact-vcard.owl diff --git a/productMods/WEB-INF/filegraph/tbox/contact.owl b/rdf/tbox/filegraph/contact.owl similarity index 100% rename from productMods/WEB-INF/filegraph/tbox/contact.owl rename to rdf/tbox/filegraph/contact.owl diff --git a/productMods/WEB-INF/filegraph/tbox/data-properties.owl b/rdf/tbox/filegraph/data-properties.owl similarity index 100% rename from productMods/WEB-INF/filegraph/tbox/data-properties.owl rename to rdf/tbox/filegraph/data-properties.owl diff --git a/productMods/WEB-INF/filegraph/tbox/date-time.owl b/rdf/tbox/filegraph/date-time.owl similarity index 100% rename from productMods/WEB-INF/filegraph/tbox/date-time.owl rename to rdf/tbox/filegraph/date-time.owl diff --git a/productMods/WEB-INF/filegraph/tbox/dateTimeValuePrecision.owl b/rdf/tbox/filegraph/dateTimeValuePrecision.owl similarity index 100% rename from productMods/WEB-INF/filegraph/tbox/dateTimeValuePrecision.owl rename to rdf/tbox/filegraph/dateTimeValuePrecision.owl diff --git a/productMods/WEB-INF/filegraph/tbox/documentStatus.owl b/rdf/tbox/filegraph/documentStatus.owl similarity index 100% rename from productMods/WEB-INF/filegraph/tbox/documentStatus.owl rename to rdf/tbox/filegraph/documentStatus.owl diff --git a/productMods/WEB-INF/filegraph/tbox/education.owl b/rdf/tbox/filegraph/education.owl similarity index 100% rename from productMods/WEB-INF/filegraph/tbox/education.owl rename to rdf/tbox/filegraph/education.owl diff --git a/productMods/WEB-INF/filegraph/tbox/event.owl b/rdf/tbox/filegraph/event.owl similarity index 100% rename from productMods/WEB-INF/filegraph/tbox/event.owl rename to rdf/tbox/filegraph/event.owl diff --git a/productMods/WEB-INF/filegraph/tbox/geo-political.owl b/rdf/tbox/filegraph/geo-political.owl similarity index 100% rename from productMods/WEB-INF/filegraph/tbox/geo-political.owl rename to rdf/tbox/filegraph/geo-political.owl diff --git a/productMods/WEB-INF/filegraph/tbox/grant.owl b/rdf/tbox/filegraph/grant.owl similarity index 100% rename from productMods/WEB-INF/filegraph/tbox/grant.owl rename to rdf/tbox/filegraph/grant.owl diff --git a/productMods/WEB-INF/filegraph/tbox/linkSuppression.n3 b/rdf/tbox/filegraph/linkSuppression.n3 similarity index 100% rename from productMods/WEB-INF/filegraph/tbox/linkSuppression.n3 rename to rdf/tbox/filegraph/linkSuppression.n3 diff --git a/productMods/WEB-INF/filegraph/tbox/location.owl b/rdf/tbox/filegraph/location.owl similarity index 100% rename from productMods/WEB-INF/filegraph/tbox/location.owl rename to rdf/tbox/filegraph/location.owl diff --git a/productMods/WEB-INF/filegraph/tbox/object-properties.owl b/rdf/tbox/filegraph/object-properties.owl similarity index 100% rename from productMods/WEB-INF/filegraph/tbox/object-properties.owl rename to rdf/tbox/filegraph/object-properties.owl diff --git a/productMods/WEB-INF/filegraph/tbox/object-properties2.owl b/rdf/tbox/filegraph/object-properties2.owl similarity index 100% rename from productMods/WEB-INF/filegraph/tbox/object-properties2.owl rename to rdf/tbox/filegraph/object-properties2.owl diff --git a/productMods/WEB-INF/filegraph/tbox/other.owl b/rdf/tbox/filegraph/other.owl similarity index 100% rename from productMods/WEB-INF/filegraph/tbox/other.owl rename to rdf/tbox/filegraph/other.owl diff --git a/productMods/WEB-INF/filegraph/tbox/outreach.owl b/rdf/tbox/filegraph/outreach.owl similarity index 100% rename from productMods/WEB-INF/filegraph/tbox/outreach.owl rename to rdf/tbox/filegraph/outreach.owl diff --git a/productMods/WEB-INF/filegraph/tbox/personTypes.n3 b/rdf/tbox/filegraph/personTypes.n3 similarity index 100% rename from productMods/WEB-INF/filegraph/tbox/personTypes.n3 rename to rdf/tbox/filegraph/personTypes.n3 diff --git a/productMods/WEB-INF/filegraph/tbox/process.owl b/rdf/tbox/filegraph/process.owl similarity index 100% rename from productMods/WEB-INF/filegraph/tbox/process.owl rename to rdf/tbox/filegraph/process.owl diff --git a/productMods/WEB-INF/filegraph/tbox/publication.owl b/rdf/tbox/filegraph/publication.owl similarity index 100% rename from productMods/WEB-INF/filegraph/tbox/publication.owl rename to rdf/tbox/filegraph/publication.owl diff --git a/productMods/WEB-INF/filegraph/tbox/relationship.owl b/rdf/tbox/filegraph/relationship.owl similarity index 100% rename from productMods/WEB-INF/filegraph/tbox/relationship.owl rename to rdf/tbox/filegraph/relationship.owl diff --git a/productMods/WEB-INF/filegraph/tbox/research-resource-iao.owl b/rdf/tbox/filegraph/research-resource-iao.owl similarity index 100% rename from productMods/WEB-INF/filegraph/tbox/research-resource-iao.owl rename to rdf/tbox/filegraph/research-resource-iao.owl diff --git a/productMods/WEB-INF/filegraph/tbox/research-resource.owl b/rdf/tbox/filegraph/research-resource.owl similarity index 100% rename from productMods/WEB-INF/filegraph/tbox/research-resource.owl rename to rdf/tbox/filegraph/research-resource.owl diff --git a/productMods/WEB-INF/filegraph/tbox/research.owl b/rdf/tbox/filegraph/research.owl similarity index 100% rename from productMods/WEB-INF/filegraph/tbox/research.owl rename to rdf/tbox/filegraph/research.owl diff --git a/productMods/WEB-INF/filegraph/tbox/role.owl b/rdf/tbox/filegraph/role.owl similarity index 100% rename from productMods/WEB-INF/filegraph/tbox/role.owl rename to rdf/tbox/filegraph/role.owl diff --git a/productMods/WEB-INF/filegraph/tbox/service.owl b/rdf/tbox/filegraph/service.owl similarity index 100% rename from productMods/WEB-INF/filegraph/tbox/service.owl rename to rdf/tbox/filegraph/service.owl diff --git a/productMods/WEB-INF/filegraph/tbox/skos-vivo.owl b/rdf/tbox/filegraph/skos-vivo.owl similarity index 100% rename from productMods/WEB-INF/filegraph/tbox/skos-vivo.owl rename to rdf/tbox/filegraph/skos-vivo.owl diff --git a/productMods/WEB-INF/filegraph/tbox/teaching.owl b/rdf/tbox/filegraph/teaching.owl similarity index 100% rename from productMods/WEB-INF/filegraph/tbox/teaching.owl rename to rdf/tbox/filegraph/teaching.owl diff --git a/productMods/WEB-INF/filegraph/tbox/vitroPublic.owl b/rdf/tbox/filegraph/vitroPublic.owl similarity index 100% rename from productMods/WEB-INF/filegraph/tbox/vitroPublic.owl rename to rdf/tbox/filegraph/vitroPublic.owl diff --git a/productMods/WEB-INF/ontologies/user/tbox/geopolitical-ver1.1-11-18-11-annotations.rdf b/rdf/tbox/firsttime/geopolitical-ver1.1-11-18-11-annotations.rdf similarity index 100% rename from productMods/WEB-INF/ontologies/user/tbox/geopolitical-ver1.1-11-18-11-annotations.rdf rename to rdf/tbox/firsttime/geopolitical-ver1.1-11-18-11-annotations.rdf diff --git a/productMods/WEB-INF/ontologies/user/tbox/isDefinedBy-1.5-annotations.rdf b/rdf/tbox/firsttime/isDefinedBy-1.5-annotations.rdf similarity index 100% rename from productMods/WEB-INF/ontologies/user/tbox/isDefinedBy-1.5-annotations.rdf rename to rdf/tbox/firsttime/isDefinedBy-1.5-annotations.rdf diff --git a/productMods/WEB-INF/ontologies/user/tbox/scires-1.5-annotations.rdf b/rdf/tbox/firsttime/scires-1.5-annotations.rdf similarity index 100% rename from productMods/WEB-INF/ontologies/user/tbox/scires-1.5-annotations.rdf rename to rdf/tbox/firsttime/scires-1.5-annotations.rdf diff --git a/productMods/WEB-INF/ontologies/user/tbox/vitro-0.7-annotations.rdf b/rdf/tbox/firsttime/vitro-0.7-annotations.rdf similarity index 100% rename from productMods/WEB-INF/ontologies/user/tbox/vitro-0.7-annotations.rdf rename to rdf/tbox/firsttime/vitro-0.7-annotations.rdf diff --git a/productMods/WEB-INF/ontologies/user/tbox/vivo-core-1.5-annotations.rdf b/rdf/tbox/firsttime/vivo-core-1.5-annotations.rdf similarity index 99% rename from productMods/WEB-INF/ontologies/user/tbox/vivo-core-1.5-annotations.rdf rename to rdf/tbox/firsttime/vivo-core-1.5-annotations.rdf index 88df4862..d203cf88 100644 --- a/productMods/WEB-INF/ontologies/user/tbox/vivo-core-1.5-annotations.rdf +++ b/rdf/tbox/firsttime/vivo-core-1.5-annotations.rdf @@ -2953,6 +2953,7 @@ + individual--skos-concept.ftl -1 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 */ @@ -90,6 +103,18 @@ public class Concept { 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 */ @@ -102,5 +127,37 @@ public class Concept { 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/src/edu/cornell/mannlib/semservices/bo/ConceptInfo.java b/src/edu/cornell/mannlib/semservices/bo/ConceptInfo.java index 14aa22e0..af3cb0a1 100644 --- a/src/edu/cornell/mannlib/semservices/bo/ConceptInfo.java +++ b/src/edu/cornell/mannlib/semservices/bo/ConceptInfo.java @@ -8,8 +8,7 @@ import java.util.List; public class ConceptInfo extends SemanticServicesInfoBase { - private List conceptList; - + private List conceptList; /** * */ @@ -18,17 +17,16 @@ public class ConceptInfo extends SemanticServicesInfoBase { } /** - * @return the vivoDepartmentList + * @return the conceptList */ - public List getConceptList() { + public List getConceptList() { return conceptList; } /** - * @param vivoDepartmentList the vivoDepartmentList to set + * @param conceptList the conceptList to set */ - public void setConceptList(List inputConceptList) { - this.conceptList = inputConceptList; + public void setConceptList(List conceptList) { + this.conceptList = conceptList; } - } diff --git a/src/edu/cornell/mannlib/semservices/exceptions/ConceptsNotFoundException.java b/src/edu/cornell/mannlib/semservices/exceptions/ConceptsNotFoundException.java new file mode 100644 index 00000000..1264905e --- /dev/null +++ b/src/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/src/edu/cornell/mannlib/semservices/service/ExternalConceptService.java b/src/edu/cornell/mannlib/semservices/service/ExternalConceptService.java index 891ee322..034df4e3 100644 --- a/src/edu/cornell/mannlib/semservices/service/ExternalConceptService.java +++ b/src/edu/cornell/mannlib/semservices/service/ExternalConceptService.java @@ -7,7 +7,24 @@ import java.util.List; import edu.cornell.mannlib.semservices.bo.Concept; public interface ExternalConceptService { - // this is the only method that needs to be exposed - List processResults(String term) throws Exception; + + /** + * @param term + * @return + */ + List processResults(String term) throws Exception; + + /** + * @param term + * @return + * @throws Exception + */ + List getConcepts(String term) throws Exception; + + /** + * @param uri + * @return + */ + List getConceptsByURIWithSparql(String uri) throws Exception; } diff --git a/src/edu/cornell/mannlib/semservices/service/impl/AgrovocService.java b/src/edu/cornell/mannlib/semservices/service/impl/AgrovocService.java index 50ac9092..003aa26b 100644 --- a/src/edu/cornell/mannlib/semservices/service/impl/AgrovocService.java +++ b/src/edu/cornell/mannlib/semservices/service/impl/AgrovocService.java @@ -8,18 +8,30 @@ import java.io.IOException; import java.io.InputStreamReader; import java.io.StringWriter; import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; import java.net.URL; import java.rmi.RemoteException; import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; import java.util.List; - import javax.xml.parsers.ParserConfigurationException; import javax.xml.rpc.ServiceException; + +import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.fao.gilw.aims.webservices.AgrovocWS; -import org.fao.gilw.aims.webservices.AgrovocWSServiceLocator; +import org.fao.www.webservices.AgrovocWS.ACSWWebService; +import org.fao.www.webservices.AgrovocWS.ACSWWebServiceServiceLocator; +import org.semanticweb.skos.SKOSAnnotation; +import org.semanticweb.skos.SKOSConcept; +import org.semanticweb.skos.SKOSDataset; +import org.semanticweb.skos.SKOSEntity; +import org.semanticweb.skos.SKOSLiteral; +import org.semanticweb.skos.SKOSUntypedLiteral; +import org.semanticweb.skosapibinding.SKOSManager; import org.w3c.dom.Attr; import org.w3c.dom.Document; import org.w3c.dom.NamedNodeMap; @@ -27,95 +39,215 @@ import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; +import com.hp.hpl.jena.query.Query; +import com.hp.hpl.jena.query.QueryExecution; +import com.hp.hpl.jena.query.QueryExecutionFactory; +import com.hp.hpl.jena.query.QueryFactory; +import com.hp.hpl.jena.query.QuerySolution; +import com.hp.hpl.jena.query.ResultSet; +import com.hp.hpl.jena.rdf.model.Literal; +import com.hp.hpl.jena.rdf.model.RDFNode; +import com.hp.hpl.jena.rdf.model.Resource; + import edu.cornell.mannlib.semservices.bo.Concept; import edu.cornell.mannlib.semservices.service.ExternalConceptService; import edu.cornell.mannlib.semservices.util.XMLUtils; public class AgrovocService implements ExternalConceptService { + protected final Log logger = LogFactory.getLog(getClass()); - private java.lang.String AgrovocWS_address = "http://www.fao.org/webservices/AgrovocWS"; + private java.lang.String AgrovocWS_address = "http://agrovoc.fao.org/axis/services/SKOSWS"; + private final String schemeUri = "http://aims.fao.org/aos/agrovoc/agrovocScheme"; + private final String baseUri = "http://aims.fao.org/aos/agrovoc/"; + private final String ontologyName = "agrovoc"; + private final String format = "SKOS"; + private final String lang = "en"; + private final String codeName = "hasCodeAgrovoc"; + private final String searchMode = "Exact Match"; + protected final String dbpedia_endpoint = " http://dbpedia.org/sparql"; + + + @Override + public List getConcepts(String term) throws Exception { + List conceptList = new ArrayList(); + //System.out.println("Searching for term: "+ term); + String result = getURIByTermAndLangXML(this.ontologyName, term, this.searchMode, this.format, this.lang); + // return empty conceptList if conceptUri is empty + if (StringUtils.isEmpty(result)) { + return conceptList; + } + + // First create a new SKOSManager + String conceptUri = getConceptURIFromRDF(result); + SKOSManager manager = new SKOSManager(); + + // return empty conceptList if conceptUri is empty + if (StringUtils.isEmpty(conceptUri)) { + return conceptList; + } + URI uri = null; + try { + uri = new URI(conceptUri); + } catch (URISyntaxException e) { + e.printStackTrace(); + return conceptList; + } + + //System.out.println("uri: "+uri); + SKOSDataset dataset = manager.loadDataset(uri); + + for (SKOSConcept skosConcept : dataset.getSKOSConcepts()) { + Concept concept = new Concept(); + //System.out.println("Concept: " + skosConcept.getURI()); + concept.setUri(skosConcept.getURI().toString()); + concept.setConceptId(stripConceptId(skosConcept.getURI().toString())); + concept.setBestMatch("true"); + concept.setDefinedBy(schemeUri); + concept.setSchemeURI(this.schemeUri); + concept.setType(""); + String lang = ""; + + for (SKOSLiteral literal : skosConcept.getSKOSRelatedConstantByProperty(dataset, manager.getSKOSDataFactory().getSKOSPrefLabelProperty())) { + + if (!literal.isTyped()) { + // if it has language + SKOSUntypedLiteral untypedLiteral = literal.getAsSKOSUntypedLiteral(); + if (untypedLiteral.hasLang()) { + lang = untypedLiteral.getLang(); + } else { + lang = ""; + } + } + if (lang.equals("en")) { + //System.out.println("prefLabel: " + literal.getLiteral()); + + concept.setLabel(literal.getLiteral()); + } + } + + // get altLabels + List altLabelList = new ArrayList(); + for (SKOSLiteral literal : skosConcept + .getSKOSRelatedConstantByProperty(dataset, manager + .getSKOSDataFactory().getSKOSAltLabelProperty())) { + + if (!literal.isTyped()) { + // if it has language + SKOSUntypedLiteral untypedLiteral = literal + .getAsSKOSUntypedLiteral(); + if (untypedLiteral.hasLang()) { + lang = untypedLiteral.getLang(); + } else { + lang = ""; + } + } + //System.out.println("literal: "+ literal.getLiteral()); + if (lang.equals("en")) { + //System.out.println("altLabel: " + literal.getLiteral()); + altLabelList.add(literal.getLiteral()); + } + } + concept.setAltLabelList(altLabelList); + + + + // get the broader property URI + List broaderURIList = new ArrayList(); + for (SKOSAnnotation annotation: skosConcept.getSKOSAnnotationsByURI(dataset, manager.getSKOSDataFactory().getSKOSBroaderProperty().getURI())) { + String value = new String(); + if (annotation.isAnnotationByConstant()) { + SKOSLiteral literal = annotation.getAnnotationValueAsConstant(); + value = literal.getLiteral(); + //System.out.println("broder uri: "+ value); + } else { + // annotation is some resource + SKOSEntity entity = annotation.getAnnotationValue(); + value = entity.getURI().toString(); + } + //System.out.println("broader uri: "+value); + broaderURIList.add(value); + } + concept.setBroaderURIList(broaderURIList); + + // get the narrower property URI + List narrowerURIList = new ArrayList(); + for (SKOSAnnotation annotation: skosConcept.getSKOSAnnotationsByURI(dataset, manager.getSKOSDataFactory().getSKOSNarrowerProperty().getURI())) { + String value = new String(); + if (annotation.isAnnotationByConstant()) { + SKOSLiteral literal = annotation.getAnnotationValueAsConstant(); + value = literal.getLiteral(); + //System.out.println("narrower uri: "+ value); + } else { + // annotation is some resource + SKOSEntity entity = annotation.getAnnotationValue(); + value = entity.getURI().toString(); + } + //System.out.println("narrower uri: "+value); + narrowerURIList.add(value); + } + concept.setNarrowerURIList(narrowerURIList); + + // exact match + List exactMatchURIList = new ArrayList(); + for (SKOSAnnotation annotation: skosConcept.getSKOSAnnotationsByURI(dataset, manager.getSKOSDataFactory().getSKOSExactMatchProperty().getURI())) { + String value = new String(); + if (annotation.isAnnotationByConstant()) { + SKOSLiteral literal = annotation.getAnnotationValueAsConstant(); + value = literal.getLiteral(); + //System.out.println("exact match: "+ value); + } else { + // annotation is some resource + SKOSEntity entity = annotation.getAnnotationValue(); + value = entity.getURI().toString(); + } + //System.out.println("exact match: "+value); + exactMatchURIList.add(value); + } + concept.setExactMatchURIList(exactMatchURIList); + + // close match + List closeMatchURIList = new ArrayList(); + for (SKOSAnnotation annotation: skosConcept.getSKOSAnnotationsByURI(dataset, manager.getSKOSDataFactory().getSKOSCloseMatchProperty().getURI())) { + String value = new String(); + if (annotation.isAnnotationByConstant()) { + SKOSLiteral literal = annotation.getAnnotationValueAsConstant(); + value = literal.getLiteral(); + //System.out.println("close match: "+ value); + } else { + // annotation is some resource + SKOSEntity entity = annotation.getAnnotationValue(); + value = entity.getURI().toString(); + } + //System.out.println("close match: "+value); + closeMatchURIList.add(value); + if (value.startsWith("http://dbpedia.org")) { + String description = getDbpediaDescription(value); + //System.out.println("description: "+ description); + concept.setDefinition(description); + } + } + concept.setCloseMatchURIList(closeMatchURIList); + + conceptList.add(concept); + + + } + return conceptList; + } public List processResults(String term) throws Exception { - List conceptList = new ArrayList(); - - String termcode; - try { - termcode = getTermcodeByTerm(term); - } catch (Exception e1) { - logger.error("Could not get termcode from service", e1); - throw e1; - } - - String format = "SKOS"; - // if the termcode is null it means that either the service is not responding - // or there was not a match for the string - //System.out.println("Got termcode: "+termcode); - - String results = getConceptInfoByTermcodeXML(termcode, format); - - //XMLUtils.prettyPrint(results); - - try { - Document doc = XMLUtils.parse(results); - String prefLabelQuery = "child::*[@xml:lang='EN']"; - NodeList nodes = doc.getElementsByTagName("skos:Concept"); - //System.out.println("Found this many nodes: "+ nodes.getLength()); - for (int i=0; i < nodes.getLength(); i++) { - - Node node = nodes.item(i); - //XMLUtils.serializeNode(node); System.out.println(); - - Concept concept = new Concept(); - concept.setDefinedBy("http://aims.fao.org/aos/agrovoc/agrovocScheme"); - concept.setConceptId(termcode); - - NamedNodeMap attrs = node.getAttributes(); - Attr idAttr = (Attr) attrs.getNamedItem("rdf:about"); - String conceptUri = idAttr.getTextContent(); - concept.setUri(conceptUri); - - Node prefLabelNode = XMLUtils.getNodeWithXpath(node, prefLabelQuery); - if (prefLabelNode != null) { - String prefLabel = prefLabelNode.getTextContent(); - concept.setLabel(prefLabel); - } - conceptList.add(concept); - } - } catch (IOException e) { - e.printStackTrace(); - } catch (SAXException e) { - e.printStackTrace(); - } catch (ParserConfigurationException e) { - e.printStackTrace(); - } - return conceptList; + return getConcepts(term); } - - - protected String getAgrovocLanguages() { - String result = new String(); - AgrovocWSServiceLocator locator = new AgrovocWSServiceLocator(); - try { - URL url = new URL(AgrovocWS_address); - AgrovocWS agrovoc_service = locator.getAgrovocWS(url); - result = agrovoc_service.getAgrovocLanguages(); - } catch (ServiceException e) { - e.printStackTrace(); - } catch (RemoteException e) { - e.printStackTrace(); - } catch (MalformedURLException e) { - e.printStackTrace(); - } - - return result; - } - + + + + @Deprecated protected String getTermcodeByTerm(String term) throws Exception { String result = new String(); - AgrovocWSServiceLocator locator = new AgrovocWSServiceLocator(); + ACSWWebServiceServiceLocator locator = new ACSWWebServiceServiceLocator(); try { URL url = new URL(AgrovocWS_address); - AgrovocWS agrovoc_service = locator.getAgrovocWS(url); + ACSWWebService agrovoc_service = locator.getACSWWebService(url); result = agrovoc_service.getTermcodeByTerm(term); } catch (ServiceException e) { logger.error("service exception", e); @@ -130,275 +262,58 @@ public class AgrovocService implements ExternalConceptService { return result; } - protected String getTermcodeByTermXML(String term, String format) { - String result = new String(); - AgrovocWSServiceLocator locator = new AgrovocWSServiceLocator(); - try { - URL url = new URL(AgrovocWS_address); - AgrovocWS agrovoc_service = locator.getAgrovocWS(url); - result = agrovoc_service.getTermcodeByTermXML(term, format); - } catch (ServiceException e) { - logger.error("service exception", e); - e.printStackTrace(); - } catch (RemoteException e) { - e.printStackTrace(); - } catch (MalformedURLException e) { - e.printStackTrace(); - } - return result; - } + + + protected String getTermCodeByTermAndLangXML(String ontologyName, String searchString, String lang, String codeName, String format) { + String result = new String(); + ACSWWebServiceServiceLocator locator = new ACSWWebServiceServiceLocator(); + try { + URL url = new URL(AgrovocWS_address); + ACSWWebService agrovoc_service = locator.getACSWWebService(url); + result = agrovoc_service.getTermCodeByTermAndLangXML(ontologyName, searchString, lang, codeName, format); + } catch (ServiceException e) { + logger.error("service exception", e); + e.printStackTrace(); + } catch (RemoteException e) { + e.printStackTrace(); + } catch (MalformedURLException e) { + e.printStackTrace(); + } + return result; + } - protected String getTermByLanguage(int termcode, String language) { - String result = new String(); - AgrovocWSServiceLocator locator = new AgrovocWSServiceLocator(); - try { - URL url = new URL(AgrovocWS_address); - AgrovocWS agrovoc_service = locator.getAgrovocWS(url); - result = agrovoc_service.getTermByLanguage(termcode, language); - } catch (ServiceException e) { - logger.error("service exception", e); - e.printStackTrace(); - } catch (RemoteException e) { - e.printStackTrace(); - } catch (MalformedURLException e) { - e.printStackTrace(); - } - return result; - } + - protected String getTermByLanguageXML(int termcode, String language, String format) { - String result = new String(); - AgrovocWSServiceLocator locator = new AgrovocWSServiceLocator(); - try { - URL url = new URL(AgrovocWS_address); - AgrovocWS agrovoc_service = locator.getAgrovocWS(url); - result = agrovoc_service.getTermByLanguageXML(termcode, language, format); - } catch (ServiceException e) { - logger.error("service exception", e); - e.printStackTrace(); - } catch (RemoteException e) { - e.printStackTrace(); - } catch (MalformedURLException e) { - e.printStackTrace(); - } + protected String getURIByTermAndLangXML(String ontologyName, String term, + String searchMode, String format, String lang) { + String result = new String(); + ACSWWebServiceServiceLocator locator = new ACSWWebServiceServiceLocator(); + try { + URL url = new URL(AgrovocWS_address); + ACSWWebService agrovoc_service = locator.getACSWWebService(url); + result = agrovoc_service.getURIByTermAndLangXML(ontologyName, term, + searchMode, format, lang); + } catch (ServiceException e) { + e.printStackTrace(); + } catch (RemoteException e) { + e.printStackTrace(); + } catch (MalformedURLException e) { + e.printStackTrace(); + } - return result; - } + return result; + } - protected String getTermsListByLanguage2(String termcodes, String language, String sep) { - String result = new String(); - AgrovocWSServiceLocator locator = new AgrovocWSServiceLocator(); - try { - URL url = new URL(AgrovocWS_address); - AgrovocWS agrovoc_service = locator.getAgrovocWS(url); - result = agrovoc_service.getTermsListByLanguage2(termcodes, language, sep); - } catch (ServiceException e) { - logger.error("service exception", e); - e.printStackTrace(); - } catch (RemoteException e) { - e.printStackTrace(); - } catch (MalformedURLException e) { - e.printStackTrace(); - } - return result; - } - - protected String getTermsListByLanguageXML(String termcodes, String language, String format) { - String result = new String(); - AgrovocWSServiceLocator locator = new AgrovocWSServiceLocator(); - try { - URL url = new URL(AgrovocWS_address); - AgrovocWS agrovoc_service = locator.getAgrovocWS(url); - result = agrovoc_service.getTermsListByLanguageXML(termcodes, language, format); - } catch (ServiceException e) { - logger.error("service exception", e); - e.printStackTrace(); - } catch (RemoteException e) { - e.printStackTrace(); - } catch (MalformedURLException e) { - e.printStackTrace(); - } - - return result; - } - - protected String getAllLabelsByTermcode2(int termcode, String sep) { - String result = new String(); - AgrovocWSServiceLocator locator = new AgrovocWSServiceLocator(); - try { - URL url = new URL(AgrovocWS_address); - AgrovocWS agrovoc_service = locator.getAgrovocWS(url); - result = agrovoc_service.getAllLabelsByTermcode2(termcode, sep); - } catch (ServiceException e) { - logger.error("service exception", e); - e.printStackTrace(); - } catch (RemoteException e) { - e.printStackTrace(); - } catch (MalformedURLException e) { - e.printStackTrace(); - } - - return result; - } - - protected String getAllLabelsByTermcodeXML(int termcode, String format) { - String result = new String(); - AgrovocWSServiceLocator locator = new AgrovocWSServiceLocator(); - try { - URL url = new URL(AgrovocWS_address); - AgrovocWS agrovoc_service = locator.getAgrovocWS(url); - result = agrovoc_service.getAllLabelsByTermcodeXML(termcode, format); - } catch (ServiceException e) { - logger.error("service exception", e); - e.printStackTrace(); - } catch (RemoteException e) { - e.printStackTrace(); - } catch (MalformedURLException e) { - e.printStackTrace(); - } - - return result; - } - - protected String simpleSearchByMode2(String term, String mode, String sep ) { - String result = new String(); - AgrovocWSServiceLocator locator = new AgrovocWSServiceLocator(); - try { - URL url = new URL(AgrovocWS_address); - AgrovocWS agrovoc_service = locator.getAgrovocWS(url); - result = agrovoc_service.simpleSearchByMode2(term, mode, sep); - } catch (ServiceException e) { - logger.error("service exception", e); - e.printStackTrace(); - } catch (RemoteException e) { - e.printStackTrace(); - } catch (MalformedURLException e) { - e.printStackTrace(); - } - - return result; - } - - protected String simpleSearchByModeXML(String term, String mode, String format) { - String result = new String(); - AgrovocWSServiceLocator locator = new AgrovocWSServiceLocator(); - try { - URL url = new URL(AgrovocWS_address); - AgrovocWS agrovoc_service = locator.getAgrovocWS(url); - result = agrovoc_service.simpleSearchByModeXML(term, mode, format); - } catch (ServiceException e) { - logger.error("service exception", e); - e.printStackTrace(); - } catch (RemoteException e) { - e.printStackTrace(); - } catch (MalformedURLException e) { - e.printStackTrace(); - } - - return result; - } - - protected String searchByTerm2(String term, String sep) { - String result = new String(); - AgrovocWSServiceLocator locator = new AgrovocWSServiceLocator(); - try { - URL url = new URL(AgrovocWS_address); - AgrovocWS agrovoc_service = locator.getAgrovocWS(url); - result = agrovoc_service.searchByTerm2(term, sep); - } catch (ServiceException e) { - logger.error("service exception", e); - e.printStackTrace(); - } catch (RemoteException e) { - e.printStackTrace(); - } catch (MalformedURLException e) { - e.printStackTrace(); - } - - return result; - } - - protected String searchByTermXML(String term, String format) { - String result = new String(); - AgrovocWSServiceLocator locator = new AgrovocWSServiceLocator(); - try { - URL url = new URL(AgrovocWS_address); - AgrovocWS agrovoc_service = locator.getAgrovocWS(url); - result = agrovoc_service.searchByTermXML(term, format); - } catch (ServiceException e) { - logger.error("service exception", e); - e.printStackTrace(); - } catch (RemoteException e) { - e.printStackTrace(); - } catch (MalformedURLException e) { - e.printStackTrace(); - } - - return result; - } - - protected String searchCategoryByMode(String term, String lang, String schemeid, String mode, String sep) { - String result = new String(); - AgrovocWSServiceLocator locator = new AgrovocWSServiceLocator(); - try { - URL url = new URL(AgrovocWS_address); - AgrovocWS agrovoc_service = locator.getAgrovocWS(url); - result = agrovoc_service.searchCategoryByMode(term, lang, schemeid, mode, sep); - } catch (ServiceException e) { - logger.error("service exception", e); - e.printStackTrace(); - } catch (RemoteException e) { - e.printStackTrace(); - } catch (MalformedURLException e) { - e.printStackTrace(); - } - - return result; - } - - protected String searchCategoryByModeXML(String term, String mode, String schemeid, String lang, String format) { - String result = new String(); - AgrovocWSServiceLocator locator = new AgrovocWSServiceLocator(); - try { - URL url = new URL(AgrovocWS_address); - AgrovocWS agrovoc_service = locator.getAgrovocWS(url); - result = agrovoc_service.searchCategoryByModeXML(term, mode, schemeid, lang, format); - } catch (ServiceException e) { - logger.error("service exception", e); - e.printStackTrace(); - } catch (RemoteException e) { - e.printStackTrace(); - } catch (MalformedURLException e) { - e.printStackTrace(); - } - - return result; - } - - protected String[] getConceptInfoByTermcode(String termcode) { - String result[] = null; - AgrovocWSServiceLocator locator = new AgrovocWSServiceLocator(); - try { - URL url = new URL(AgrovocWS_address); - AgrovocWS agrovoc_service = locator.getAgrovocWS(url); - result = agrovoc_service.getConceptInfoByTermcode(termcode); - } catch (ServiceException e) { - logger.error("service exception", e); - e.printStackTrace(); - } catch (RemoteException e) { - e.printStackTrace(); - } catch (MalformedURLException e) { - e.printStackTrace(); - } - - return result; - } + + + protected String getConceptInfoByTermcodeXML(String termcode, String format) { String result = new String(); - AgrovocWSServiceLocator locator = new AgrovocWSServiceLocator(); + ACSWWebServiceServiceLocator locator = new ACSWWebServiceServiceLocator(); try { URL url = new URL(AgrovocWS_address); - AgrovocWS agrovoc_service = locator.getAgrovocWS(url); + ACSWWebService agrovoc_service = locator.getACSWWebService(url); result = agrovoc_service.getConceptInfoByTermcodeXML(termcode, format); } catch (ServiceException e) { logger.error("service exception", e); @@ -411,70 +326,34 @@ public class AgrovocService implements ExternalConceptService { return result; } + + protected String getConceptByKeyword(String ontologyName, String searchString, String format, String searchMode, String lang) { + String result = new String(); + ACSWWebServiceServiceLocator locator = new ACSWWebServiceServiceLocator(); + try { + URL url = new URL(AgrovocWS_address); + ACSWWebService agrovoc_service = locator.getACSWWebService(url); + result = agrovoc_service.getConceptByKeyword(ontologyName, searchString, format, searchMode, lang); + } catch (ServiceException e) { + logger.error("service exception", e); + e.printStackTrace(); + } catch (RemoteException e) { + e.printStackTrace(); + } catch (MalformedURLException e) { + e.printStackTrace(); + } - protected String[] getDefinitions(int termcode, String lang) { - String[] result = null; - AgrovocWSServiceLocator locator = new AgrovocWSServiceLocator(); - try { - URL url = new URL(AgrovocWS_address); - AgrovocWS agrovoc_service = locator.getAgrovocWS(url); - result = agrovoc_service.getDefinitions(termcode, lang); - } catch (ServiceException e) { - logger.error("service exception", e); - e.printStackTrace(); - } catch (RemoteException e) { - e.printStackTrace(); - } catch (MalformedURLException e) { - e.printStackTrace(); - } - - return result; - } - - protected String getDefinitionsXML(int termcode, String lang, String format) { - String result = null; - AgrovocWSServiceLocator locator = new AgrovocWSServiceLocator(); - try { - URL url = new URL(AgrovocWS_address); - AgrovocWS agrovoc_service = locator.getAgrovocWS(url); - result = agrovoc_service.getDefinitionsXML(termcode, lang, format); - } catch (ServiceException e) { - logger.error("service exception", e); - e.printStackTrace(); - } catch (RemoteException e) { - e.printStackTrace(); - } catch (MalformedURLException e) { - e.printStackTrace(); - } - - return result; - } - - protected String getTermExpansion(String aQuery, String langugage) { - String result = new String(); - AgrovocWSServiceLocator locator = new AgrovocWSServiceLocator(); - try { - URL url = new URL(AgrovocWS_address); - AgrovocWS agrovoc_service = locator.getAgrovocWS(url); - result = agrovoc_service.getTermExpansion(aQuery, langugage); - } catch (ServiceException e) { - logger.error("service exception", e); - e.printStackTrace(); - } catch (RemoteException e) { - e.printStackTrace(); - } catch (MalformedURLException e) { - e.printStackTrace(); - } - - return result; - } + return result; + } + + protected String getWsdl() { String result = new String(); try { StringWriter sw = new StringWriter(); - URL rss = new URL(AgrovocWS_address + "?wsdl"); + URL rss = new URL(this.AgrovocWS_address + "?wsdl"); BufferedReader in = new BufferedReader(new InputStreamReader(rss.openStream())); String inputLine; @@ -490,4 +369,141 @@ public class AgrovocService implements ExternalConceptService { } return result; } + + + public List getConceptsByURIWithSparql(String uri) throws Exception { + // deprecating this method...just return an empty list + List conceptList = new ArrayList(); + return conceptList; + } + + protected String getAgrovocTermCode(String rdf) throws Exception { + String termcode = new String(); + try { + Document doc = XMLUtils.parse(rdf); + NodeList nodes = doc.getElementsByTagName("hasCodeAgrovoc"); + if (nodes.item(0) != null) { + Node node = nodes.item(0); + termcode = node.getTextContent(); + } + + } catch (SAXException e) { + //e.printStackTrace(); + throw e; + } catch (ParserConfigurationException e) { + //e.printStackTrace(); + throw e; + } catch (IOException e) { + //e.printStackTrace(); + throw e; + } + return termcode; + } + + protected String getConceptURIFromRDF(String rdf) { + String conceptUri = new String(); + try { + Document doc = XMLUtils.parse(rdf); + NodeList nodes = doc.getElementsByTagName("skos:Concept"); + Node node = nodes.item(0); + + NamedNodeMap attrs = node.getAttributes(); + Attr idAttr = (Attr) attrs.getNamedItem("rdf:about"); + conceptUri = idAttr.getTextContent(); + } catch (IOException e) { + e.printStackTrace(); + System.err.println("rdf: "+rdf); + } catch (SAXException e) { + e.printStackTrace(); + System.err.println("rdf: "+rdf); + } catch (ParserConfigurationException e) { + e.printStackTrace(); + System.err.println("rdf: "+rdf); + } + return conceptUri; + + } + + protected String getDbpediaDescription(String uri) throws Exception{ + String descriptionSource = " (Source: DBpedia)"; + String description = new String(); + String qs = "" + + "PREFIX rdfs: \n" + + "PREFIX rdf: \n" + + "PREFIX foaf: \n" + + "PREFIX dbpedia-owl: \n" + + "SELECT DISTINCT ?description WHERE { \n" + "<" + uri + + "> rdfs:comment ?description . \n" + + "FILTER (LANG(?description)='en' ) \n" + "}"; + //System.out.println(qs); + List resultList = new ArrayList(); + QueryExecution qexec = null; + try { + + Query query = QueryFactory.create(qs); + qexec = QueryExecutionFactory.sparqlService(this.dbpedia_endpoint, + query); + resultList = new ArrayList(); + ResultSet resultSet = qexec.execSelect(); + int resultSetSize = 0; + while (resultSet.hasNext()) { + resultSetSize++; + QuerySolution solution = resultSet.nextSolution(); + Iterator varnames = solution.varNames(); + HashMap hm = new HashMap(); + while (varnames.hasNext()) { + String name = (String) varnames.next(); + RDFNode rdfnode = solution.get(name); + // logger.info("rdf node name, type: "+ name + // +", "+getRDFNodeType(rdfnode)); + if (rdfnode.isLiteral()) { + Literal literal = rdfnode.asLiteral(); + String nodeval = literal.getString(); + hm.put(name, nodeval); + } else if (rdfnode.isResource()) { + Resource resource = rdfnode.asResource(); + String nodeval = resource.toString(); + hm.put(name, nodeval); + } + } + resultList.add(hm); + } + description = ""; + for (HashMap map : resultList) { + if (map.containsKey("description")) { + description = (String) map.get("description"); + } + } + } catch (Exception ex) { + throw ex; + } + //Adding source so it is clear that this description comes from DBPedia + return description + descriptionSource; + } + + /** + * @param uri + * @return + */ + protected String stripConceptId(String uri) { + String conceptId = new String(); + int lastslash = uri.lastIndexOf('/'); + conceptId = uri.substring(lastslash + 1, uri.length()); + return conceptId; + } + + /** + * @param str + * @return + */ + protected String extractConceptId(String str) { + try { + return str.substring(1, str.length() - 1); + } catch (Exception ex) { + return ""; + } + } + + + } diff --git a/src/edu/cornell/mannlib/semservices/service/impl/GemetService.java b/src/edu/cornell/mannlib/semservices/service/impl/GemetService.java index e71b6a0d..1fe52b2f 100644 --- a/src/edu/cornell/mannlib/semservices/service/impl/GemetService.java +++ b/src/edu/cornell/mannlib/semservices/service/impl/GemetService.java @@ -4,38 +4,22 @@ package edu.cornell.mannlib.semservices.service.impl; import java.io.BufferedReader; -import java.io.IOException; import java.io.InputStreamReader; import java.io.StringWriter; -import java.net.MalformedURLException; import java.net.URL; -import java.rmi.RemoteException; import java.util.ArrayList; import java.util.List; - -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.rpc.ServiceException; - import net.sf.json.JSONArray; import net.sf.json.JSONObject; import net.sf.json.JSONSerializer; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.fao.gilw.aims.webservices.AgrovocWS; -import org.fao.gilw.aims.webservices.AgrovocWSServiceLocator; -import org.w3c.dom.Attr; -import org.w3c.dom.Document; -import org.w3c.dom.NamedNodeMap; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.xml.sax.SAXException; import edu.cornell.mannlib.semservices.bo.Concept; +import edu.cornell.mannlib.semservices.exceptions.ConceptsNotFoundException; import edu.cornell.mannlib.semservices.service.ExternalConceptService; -import edu.cornell.mannlib.semservices.util.XMLUtils; -import edu.cornell.mannlib.vitro.webapp.web.URLEncoder; public class GemetService implements ExternalConceptService { protected final Log logger = LogFactory.getLog(getClass()); @@ -49,63 +33,112 @@ public class GemetService implements ExternalConceptService { private final String altLabelUri = "http://www.w3.org/2004/02/skos/core%23altLabel"; private final String exampleUri = "http://www.w3.org/2004/02/skos/core%23example"; private final String acronymLabelUri = "http://www.w3.org/2004/02/skos/core%23acronymLabel"; + private final String endpoint = "http://cr.eionet.europa.eu/sparql"; + private final String schemeURI = "http://www.eionet.europa.eu/gemet/gemetThesaurus"; + + + @Override + public List getConcepts(String term) throws Exception { + List conceptList = new ArrayList(); + try { + String results = getConceptsMatchingKeyword(term); + //System.out.println(results); + conceptList = processOutput(results); + + } catch (Exception ex) { + return new ArrayList(); + //ex.printStackTrace(); + //throw ex; + } + return conceptList; + } public List processResults(String term) throws Exception { - List conceptList = processConceptsAndRelatedMatchingKeyword(term); + List conceptList = new ArrayList(); + try { + String results = getConceptsMatchingKeyword(term); + conceptList = processOutput(results); + } catch (Exception ex) { + //ex.printStackTrace(); + throw ex; + } return conceptList; } + public List getConceptsByURIWithSparql(String uri) + throws Exception { + // deprecating this method...just return an empty list + List conceptList = new ArrayList(); + return conceptList; + } + /** * @param results * @return - * By default, concepts set with best match = true */ - private List processOutput(String results) { - return processOutput(results, "true"); + private List processOutput(String results) throws Exception { + + List conceptList = new ArrayList(); - } - - private List processOutput(String results, String bestMatch) { - List conceptList = new ArrayList(); try { JSONArray jsonArray = (JSONArray) JSONSerializer.toJSON( results ); - - for (int i = 0; i < jsonArray.size(); i++) { - Concept concept = new Concept(); - concept - .setDefinedBy("http://www.eionet.europa.eu/gemet/gemetThesaurus"); - concept.setBestMatch(bestMatch); - JSONObject json = jsonArray.getJSONObject(i); - String uri = getJsonValue(json, "uri"); + if (jsonArray.size() == 0) { + throw new ConceptsNotFoundException(); + } - concept.setUri(uri); - concept.setConceptId(uri); - if (json.has("preferredLabel")) { - JSONObject preferredLabelObj = json - .getJSONObject("preferredLabel"); - if (preferredLabelObj.has("string")) { - concept.setLabel(getJsonValue(preferredLabelObj, - "string")); - } - } - if (json.has("definition")) { - JSONObject definitionObj = json.getJSONObject("definition"); - if (definitionObj.has("string")) { - concept.setDefinition(getJsonValue(definitionObj, - "string")); - } - } - conceptList.add(concept); + for (int i = 0; i < jsonArray.size(); i++) { + Concept concept = new Concept(); + concept.setDefinedBy(schemeURI); + concept.setBestMatch("true"); + JSONObject json = jsonArray.getJSONObject(i); + String uri = getJsonValue(json, "uri"); - } - + concept.setUri(uri); + concept.setConceptId(stripConceptId(uri)); + concept.setSchemeURI(schemeURI); + if (json.has("preferredLabel")) { + JSONObject preferredLabelObj = json + .getJSONObject("preferredLabel"); + if (preferredLabelObj.has("string")) { + concept.setLabel(getJsonValue(preferredLabelObj, + "string")); + } + } + if (json.has("definition")) { + JSONObject definitionObj = json.getJSONObject("definition"); + if (definitionObj.has("string")) { + concept.setDefinition(getJsonValue(definitionObj, + "string")); + } + } + + String narrower = getRelatedConcepts(uri, "narrower"); + List narrowerURIList = getRelatedUris(narrower); + concept.setNarrowerURIList(narrowerURIList); + + String broader = getRelatedConcepts(uri, "broader"); + List broaderURIList = getRelatedUris(broader); + concept.setBroaderURIList(broaderURIList); + + /*String related = getRelatedConcepts(uri, "related"); + List relatedURIList = getRelatedUris(related); + for (String s: relatedURIList) { + System.out.println("related uri: "+s); + }*/ + //String altLabels = getAllTranslationsForConcept(uri, "nonPreferredLabels"); + + conceptList.add(concept); + + } } catch (Exception ex ) { - ex.printStackTrace(); + //ex.printStackTrace(); logger.error("Could not get concepts", ex); + throw ex; } return conceptList; + } /** @@ -123,23 +156,50 @@ public class GemetService implements ExternalConceptService { } + /** + * @param concept_uri + * @return + * @throws Exception + */ protected String getAvailableLangs(String concept_uri) throws Exception { String result = new String(); String serviceUrl = GemetWS_address + "getAvailableLanguages" + "?concept_uri=" + concept_uri; - result = getGemetResults(serviceUrl); + try { + result = getGemetResults(serviceUrl); + } catch (Exception e) { + e.printStackTrace(); + throw e; + } return result; } + /** + * @param concept_uri + * @return + * @throws Exception + */ protected String getConcept(String concept_uri) throws Exception { String result = new String(); String serviceUrl = GemetWS_address + "getConcept" + "?concept_uri=" + concept_uri + "&language=en"; - result = getGemetResults(serviceUrl); + try { + result = getGemetResults(serviceUrl); + } catch (Exception e) { + e.printStackTrace(); + throw e; + } return result; } - protected String getAllTranslationsForConcept(String concept_uri, String property) throws Exception { + + /** + * @param concept_uri + * @param property + * @return + * @throws Exception + */ + protected String getAllTranslationsForConcept(String concept_uri, String property) throws Exception { String result = new String(); String property_uri = new String(); if (property.equals("definition")) { @@ -160,11 +220,24 @@ public class GemetService implements ExternalConceptService { "?concept_uri=" + concept_uri + "&property_uri=" + property_uri + "&language=en"; - result = getGemetResults(serviceUrl); + try { + result = getGemetResults(serviceUrl); + List props = getPropertyFromJson(result); + + } catch (Exception e) { + e.printStackTrace(); + throw e; + } return result; } + /** + * @param concept_uri + * @param relation + * @return + * @throws Exception + */ protected String getRelatedConcepts(String concept_uri, String relation) throws Exception { String result = new String(); String relation_uri = new String(); @@ -179,41 +252,43 @@ public class GemetService implements ExternalConceptService { "?concept_uri=" + concept_uri + "&relation_uri=" + relation_uri + "&language=en"; - result = getGemetResults(serviceUrl); + try { + result = getGemetResults(serviceUrl); + } catch (Exception e) { + e.printStackTrace(); + throw e; + } return result; } + /** + * @param keyword + * @return + * @throws Exception + */ protected String getConceptsMatchingKeyword(String keyword) throws Exception { String result = new String(); String serviceUrl = GemetWS_address + "getConceptsMatchingKeyword" + - "?keyword=" + URLEncoder.encode(keyword) + + "?keyword=" + keyword + "&search_mode=0" + "&thesaurus_uri=http://www.eionet.europa.eu/gemet/concept/" + "&language=en"; - - result = getGemetResults(serviceUrl); + try { + result = getGemetResults(serviceUrl); + } catch (Exception ex) { + throw ex; + } return result; } - - //Get concepts matching keyword plus any related concepts - protected List processConceptsAndRelatedMatchingKeyword(String keyword) throws Exception { - String result = getConceptsMatchingKeyword(keyword); - //iterate through each of the concepts and add related concepts a well - List bestMatchConceptList = processOutput(result); - List relatedConceptList = new ArrayList(); - for(Concept c: bestMatchConceptList) { - String conceptUri = c.getUri(); - String resultsRelated = getRelatedConcepts(conceptUri, "related"); - relatedConceptList.addAll(processOutput(resultsRelated, "false")); - } - bestMatchConceptList.addAll(relatedConceptList); - return bestMatchConceptList; - } - protected String getGemetResults(String url) throws Exception { + /** + * @param url + * @return + */ + protected String getGemetResults(String url) throws Exception { String results = new String(); //System.out.println("url: "+url); try { @@ -232,9 +307,50 @@ public class GemetService implements ExternalConceptService { } catch (Exception ex) { logger.error("error occurred in servlet", ex); + ex.printStackTrace(); throw ex; } return results; } + + + protected List getRelatedUris(String json) { + List uriList = new ArrayList(); + String uri = new String(); + JSONArray jsonArray = (JSONArray) JSONSerializer.toJSON( json ); + if (jsonArray.size() == 0) { + return new ArrayList(); + } + for (int i = 0; i < jsonArray.size(); i++) { + JSONObject jsonObj = jsonArray.getJSONObject(i); + uri = getJsonValue(jsonObj, "uri"); + uriList.add(uri); + } + + return uriList; + + } + + protected List getPropertyFromJson(String json) { + List props = new ArrayList(); + JSONArray jsonArray = (JSONArray) JSONSerializer.toJSON(json); + if (jsonArray.size() == 0) { + return new ArrayList(); + } + for (int i = 0; i < jsonArray.size(); i++) { + JSONObject jsonObj = jsonArray.getJSONObject(i); + System.out.println(jsonObj.toString()); + } + return props; + } + + protected String stripConceptId(String uri) { + String conceptId = new String(); + int lastslash = uri.lastIndexOf('/'); + conceptId = uri.substring(lastslash + 1, uri.length()); + return conceptId; + } + + } diff --git a/src/edu/cornell/mannlib/semservices/service/impl/UMLSService.java b/src/edu/cornell/mannlib/semservices/service/impl/UMLSService.java index b39b094c..ef930223 100644 --- a/src/edu/cornell/mannlib/semservices/service/impl/UMLSService.java +++ b/src/edu/cornell/mannlib/semservices/service/impl/UMLSService.java @@ -6,6 +6,7 @@ import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.StringWriter; import java.net.URL; +import java.net.URLEncoder; import java.util.ArrayList; import java.util.List; @@ -17,8 +18,8 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import edu.cornell.mannlib.semservices.bo.Concept; +import edu.cornell.mannlib.semservices.exceptions.ConceptsNotFoundException; import edu.cornell.mannlib.semservices.service.ExternalConceptService; -import edu.cornell.mannlib.vitro.webapp.web.URLEncoder; /** * @author jaf30 @@ -28,11 +29,48 @@ public class UMLSService implements ExternalConceptService { protected final Log logger = LogFactory.getLog(getClass()); private static final String submissionUrl = "http://link.informatics.stonybrook.edu/MeaningLookup/MlServiceServlet?"; private static final String baseUri = "http://link.informatics.stonybrook.edu/umls/CUI/"; + private static final String endpoint = "http://link.informatics.stonybrook.edu/sparql/"; + private static final String schemeURI = "http://link.informatics.stonybrook.edu/umls"; + + + + @Override + public List getConcepts(String term) throws Exception { + List conceptList = new ArrayList(); - public List processResults(String term) throws Exception{ + String results = null; + String dataUrl = submissionUrl + "textToProcess=" + + URLEncoder.encode(term, "UTF-8") + + "&format=json"; + + try { + + StringWriter sw = new StringWriter(); + URL rss = new URL(dataUrl); + + BufferedReader in = new BufferedReader(new InputStreamReader( + rss.openStream())); + String inputLine; + while ((inputLine = in.readLine()) != null) { + sw.write(inputLine); + } + in.close(); + + results = sw.toString(); + //System.out.println("results before processing: "+results); + conceptList = processOutput(results); + return conceptList; + + } catch (Exception ex) { + logger.error("error occurred in servlet", ex); + return null; + } + } + + public List processResults(String term) throws Exception { String results = null; String dataUrl = submissionUrl + "textToProcess=" - + URLEncoder.encode(term) + "&format=json"; + + URLEncoder.encode(term, "UTF-8") + "&format=json"; try { @@ -47,41 +85,58 @@ public class UMLSService implements ExternalConceptService { in.close(); results = sw.toString(); + //System.out.println("results before processing: "+results); + List conceptList = processOutput(results); + return conceptList; } catch (Exception ex) { logger.error("error occurred in servlet", ex); - throw ex; + return null; } - List conceptList = processOutput(results); - return conceptList; + } + /** + * @param uri + * @return + */ + public List getConceptsByURIWithSparql(String uri) + throws Exception { + // deprecating this method...just return an empty list + List conceptList = new ArrayList(); + return conceptList; + } + /** * @param results * @return */ - private List processOutput(String results) { + private List processOutput(String results) throws Exception { List conceptList = new ArrayList(); List bestMatchIdList = new ArrayList(); String bestMatchId = new String(); + boolean bestMatchFound = false; + boolean allFound = false; + try { JSONObject json = (JSONObject) JSONSerializer.toJSON( results ); - + //System.out.println(json.toString()); if (json.has("Best Match")) { + bestMatchFound = true; //System.out.println("Best Match"); JSONArray bestMatchArray = json.getJSONArray("Best Match"); int len = bestMatchArray.size(); if (len > 1) { - System.out.println("Found this many best matches: "+ len); + logger.debug("Found this many best matches: "+ len); } int i; for (i = 0; i < len; i++) { JSONObject o = bestMatchArray.getJSONObject(i); //System.out.println(o.toString()); Concept concept = new Concept(); - concept.setDefinedBy("http://link.informatics.stonybrook.edu/umls"); + concept.setDefinedBy(schemeURI); concept.setBestMatch("true"); String cui = getJsonValue(o, "CUI"); bestMatchIdList.add(cui); @@ -91,11 +146,12 @@ public class UMLSService implements ExternalConceptService { concept.setType(getJsonValue(o, "type")); concept.setDefinition(getJsonValue(o, "definition")); concept.setUri(baseUri + cui); + concept.setSchemeURI(schemeURI); conceptList.add(concept); } } if (json.has("All")) { - + allFound = true; JSONArray allArray = json.getJSONArray("All"); int len = allArray.size(); //System.out.println("size of best match array: "+ len); @@ -104,7 +160,7 @@ public class UMLSService implements ExternalConceptService { JSONObject o = allArray.getJSONObject(i); //System.out.println(o.toString()); Concept concept = new Concept(); - concept.setDefinedBy("http://link.informatics.stonybrook.edu/umls"); + concept.setDefinedBy(schemeURI); String cui = getJsonValue(o, "CUI"); concept.setConceptId(cui); @@ -112,6 +168,7 @@ public class UMLSService implements ExternalConceptService { concept.setType(getJsonValue(o, "type")); concept.setDefinition(getJsonValue(o, "definition")); concept.setUri(baseUri + cui); + concept.setSchemeURI(schemeURI); // prevent duplicate concepts in list if (! bestMatchIdList.contains(cui)) { concept.setBestMatch("false"); @@ -122,20 +179,18 @@ public class UMLSService implements ExternalConceptService { } catch (Exception ex ) { ex.printStackTrace(); logger.error("Could not get concepts", ex); + throw ex; } + if (! bestMatchFound && !allFound) { + // we did not get a bestMatch or All element + throw new ConceptsNotFoundException(); + } + + // return conceptList; - // - // now serialize the list of Concepts to a JSON String - // - //JSONObject jsonObject = null; - //jsonObject = BeanToJsonSerializer.serializeToJsonObject(conceptList); - //System.out.println(jsonObject.toString()); - //return jsonObject.toString(); - } - /** * Get a string from a json object or an empty string if there is no value for the given key * @param obj @@ -150,4 +205,13 @@ public class UMLSService implements ExternalConceptService { } } + + + protected String stripConceptId(String uri) { + String conceptId = new String(); + int lastslash = uri.lastIndexOf('/'); + conceptId = uri.substring(lastslash + 1, uri.length()); + return conceptId; + } + } diff --git a/src/edu/cornell/mannlib/semservices/util/ClassUtils.java b/src/edu/cornell/mannlib/semservices/util/ClassUtils.java index c71e3d22..1c1c5ca0 100644 --- a/src/edu/cornell/mannlib/semservices/util/ClassUtils.java +++ b/src/edu/cornell/mannlib/semservices/util/ClassUtils.java @@ -1,7 +1,6 @@ /* $This file is distributed under the terms of the license in /doc/license.txt$ */ /* - * $Id$ * CONFIDENTIAL AND PROPRIETARY. ? 2007 Revolution Health Group LLC. All rights reserved. * This source code may not be disclosed to others, used or reproduced without the written permission of Revolution Health Group. diff --git a/src/edu/cornell/mannlib/semservices/util/DateConverter.java b/src/edu/cornell/mannlib/semservices/util/DateConverter.java index d91d371a..02ddc491 100644 --- a/src/edu/cornell/mannlib/semservices/util/DateConverter.java +++ b/src/edu/cornell/mannlib/semservices/util/DateConverter.java @@ -1,7 +1,6 @@ /* $This file is distributed under the terms of the license in /doc/license.txt$ */ /* - * $Id: DateConverter.java 50408 2007-03-28 19:14:46Z jdamick $ * * Copyright 2006- Revolution Health Group. All rights reserved. diff --git a/src/edu/cornell/mannlib/semservices/util/ObjectUtils.java b/src/edu/cornell/mannlib/semservices/util/ObjectUtils.java index 9cea3a73..c146ede7 100644 --- a/src/edu/cornell/mannlib/semservices/util/ObjectUtils.java +++ b/src/edu/cornell/mannlib/semservices/util/ObjectUtils.java @@ -1,4 +1,7 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + /* + * $Id$ * CONFIDENTIAL AND PROPRIETARY. © 2007 Revolution Health Group LLC. All rights reserved. * This source code may not be disclosed to others, used or reproduced without the written permission of Revolution Health Group. @@ -264,5 +267,10 @@ public class ObjectUtils { } } + public static String nl2br(String text) { + return text.replaceAll("\n\n", "

    ").replaceAll("\n", "
    "); + } + + } diff --git a/src/edu/cornell/mannlib/semservices/util/XMLGregorianCalendarConverter.java b/src/edu/cornell/mannlib/semservices/util/XMLGregorianCalendarConverter.java index 180bd4f9..2caaf4ce 100644 --- a/src/edu/cornell/mannlib/semservices/util/XMLGregorianCalendarConverter.java +++ b/src/edu/cornell/mannlib/semservices/util/XMLGregorianCalendarConverter.java @@ -1,3 +1,5 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + /* * $Id: XMLGregorianCalendarConverter.java 28642 2006-10-25 13:41:54Z jdamick $ diff --git a/src/edu/cornell/mannlib/semservices/util/XMLUtils.java b/src/edu/cornell/mannlib/semservices/util/XMLUtils.java index 82fafd9c..f4735ea4 100644 --- a/src/edu/cornell/mannlib/semservices/util/XMLUtils.java +++ b/src/edu/cornell/mannlib/semservices/util/XMLUtils.java @@ -3,6 +3,7 @@ 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; @@ -81,7 +82,7 @@ public class XMLUtils { public synchronized static Document parse(String xmlString) throws IOException, SAXException, ParserConfigurationException { StringReader reader = new StringReader(xmlString); - InputSource inputSource = new InputSource(reader); + InputSource inputSource = new InputSource(reader); return getDocumentBuilder().parse(inputSource); } @@ -122,6 +123,15 @@ public class XMLUtils { serializer.serialize(doc); } + public static String serializeDoctoString(Document doc) throws IOException { + XMLSerializer serializer = new XMLSerializer(); + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + + serializer.setOutputByteStream(bout); + serializer.serialize(doc); + return bout.toString(); + } + /** * @param xml */ @@ -152,6 +162,36 @@ public class XMLUtils { } + /** + * @param xml + */ + 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 */ diff --git a/src/edu/cornell/mannlib/vitro/webapp/utils/ConceptSearchService/BeanToJsonSerializer.java b/src/edu/cornell/mannlib/semservices/view/BeanToJsonSerializer.java similarity index 92% rename from src/edu/cornell/mannlib/vitro/webapp/utils/ConceptSearchService/BeanToJsonSerializer.java rename to src/edu/cornell/mannlib/semservices/view/BeanToJsonSerializer.java index 8c26e5d4..13d4d859 100644 --- a/src/edu/cornell/mannlib/vitro/webapp/utils/ConceptSearchService/BeanToJsonSerializer.java +++ b/src/edu/cornell/mannlib/semservices/view/BeanToJsonSerializer.java @@ -1,4 +1,18 @@ -package edu.cornell.mannlib.vitro.webapp.utils.ConceptSearchService; +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +/* + * $Id: BeanToJsonSerializer.java 66350 2007-08-20 21:11:41Z xluan $ + * + * Copyright 2006- Revolution Health Group. All rights reserved. + * + * This software is the confidential and proprietary information + * of Revolution Health Group. (Confidential Information). + * You shall not disclose such Confidential Information and shall + * use it only in accordance with the terms of the license + * agreement you entered into with Revolution Health Group. + * + */ +package edu.cornell.mannlib.semservices.view; import java.beans.PropertyDescriptor; import java.lang.reflect.InvocationTargetException; diff --git a/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/AddAssociatedConceptGenerator.java b/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/AddAssociatedConceptGenerator.java index a51c32f9..23f4e1bf 100644 --- a/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/AddAssociatedConceptGenerator.java +++ b/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/AddAssociatedConceptGenerator.java @@ -16,8 +16,17 @@ import javax.servlet.http.HttpSession; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import com.hp.hpl.jena.ontology.OntModel; +import com.hp.hpl.jena.query.Query; +import com.hp.hpl.jena.query.QueryExecution; +import com.hp.hpl.jena.query.QueryExecutionFactory; +import com.hp.hpl.jena.query.QueryFactory; +import com.hp.hpl.jena.query.QuerySolution; +import com.hp.hpl.jena.query.ResultSet; import com.hp.hpl.jena.rdf.model.Literal; import com.hp.hpl.jena.rdf.model.Model; +import com.hp.hpl.jena.rdf.model.Resource; +import com.hp.hpl.jena.vocabulary.OWL; import com.hp.hpl.jena.vocabulary.RDF; import com.hp.hpl.jena.vocabulary.RDFS; import com.hp.hpl.jena.vocabulary.XSD; @@ -27,11 +36,13 @@ import edu.cornell.mannlib.vitro.webapp.beans.ObjectProperty; import edu.cornell.mannlib.vitro.webapp.beans.ObjectPropertyStatement; import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder; +import edu.cornell.mannlib.vitro.webapp.dao.ModelAccess; import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory; import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditConfigurationUtils; import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditConfigurationVTwo; import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.fields.FieldVTwo; import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.preprocessors.AddAssociatedConceptsPreprocessor; +import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.preprocessors.ConceptSemanticTypesPreprocessor; import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.validators.AntiXssValidation; import edu.cornell.mannlib.vitro.webapp.utils.ConceptSearchService.ConceptSearchServiceUtils; /** @@ -45,9 +56,9 @@ public class AddAssociatedConceptGenerator extends VivoBaseGenerator implements private Log log = LogFactory.getLog(AddAssociatedConceptGenerator.class); private String template = "addAssociatedConcept.ftl"; - private static String SKOSConceptType = "http://www.w3.org/2004/02/skos/core#Concept"; - - + //TODO: Set this to a dynamic mechanism + private static String VIVOCore = "http://vivoweb.org/ontology/core#"; + private static String SKOSConceptType = "http://www.w3.org/2004/02/skos/core#Concept"; @Override public EditConfigurationVTwo getEditConfiguration(VitroRequest vreq, HttpSession session) { EditConfigurationVTwo editConfiguration = new EditConfigurationVTwo(); @@ -84,7 +95,9 @@ public class AddAssociatedConceptGenerator extends VivoBaseGenerator implements setTemplate(editConfiguration, vreq); // No validators required here // Add preprocessors - addPreprocessors(editConfiguration, vreq.getWebappDaoFactory()); + addPreprocessors(editConfiguration, + ModelAccess.on(vreq).getJenaOntModel(), + ModelAccess.on(vreq).getOntModelSelector().getTBoxModel()); // Adding additional data, specifically edit mode addFormSpecificData(editConfiguration, vreq); // One override for basic functionality, changing url pattern @@ -168,10 +181,15 @@ public class AddAssociatedConceptGenerator extends VivoBaseGenerator implements return n3Required; } - //Don't think there's any n3 optional here + //Optional N3, includes possibility of semantic type which may or may not be included + //label and source are independent of semantic type + //concept semantic type uri is a placeholder which is actually processed in the sparql update preprocessor private List generateN3Optional() { return list("?conceptNode <" + RDFS.label.getURI() + "> ?conceptLabel .\n" + - "?conceptNode <" + RDFS.isDefinedBy.getURI() + "> ?conceptSource ." + "?conceptNode <" + RDFS.isDefinedBy.getURI() + "> ?conceptSource .", + "?conceptNode <" + RDF.type + "> ?conceptSemanticTypeURI ." + + "?conceptSemanticTypeURI <" + RDFS.label.getURI() + "> ?conceptSemanticTypeLabel ." + + "?conceptSemanticTypeURI <" + RDFS.subClassOf + "> <" + SKOSConceptType + "> ." ); } @@ -185,6 +203,8 @@ public class AddAssociatedConceptGenerator extends VivoBaseGenerator implements HashMap newResources = new HashMap(); //There are no new resources here, the concept node uri doesn't //get created but already exists, and vocab uri should already exist as well + //Adding concept semantic type uri just to test - note this isn't really on the form at all + newResources.put("conceptSemanticTypeURI", null); return newResources; } @@ -233,9 +253,12 @@ public class AddAssociatedConceptGenerator extends VivoBaseGenerator implements //The URI of the node that defines the concept urisOnForm.add("conceptNode"); urisOnForm.add("conceptSource"); + urisOnForm.add("conceptSemanticTypeURI"); editConfiguration.setUrisOnform(urisOnForm); //Also need to add the label of the concept literalsOnForm.add("conceptLabel"); + literalsOnForm.add("conceptSemanticTypeLabel"); + editConfiguration.setLiteralsOnForm(literalsOnForm); } @@ -263,6 +286,8 @@ public class AddAssociatedConceptGenerator extends VivoBaseGenerator implements setConceptNodeField(editConfiguration, vreq); setConceptLabelField(editConfiguration, vreq); setVocabURIField(editConfiguration, vreq); + setConceptSemanticTypeURIField(editConfiguration,vreq); + setConceptSemanticTypeLabelField(editConfiguration,vreq); } //this field will be hidden and include the concept node URI @@ -290,15 +315,36 @@ public class AddAssociatedConceptGenerator extends VivoBaseGenerator implements setRangeDatatypeUri(XSD.xstring.toString()) ); } + + //This will also be a URI + private void setConceptSemanticTypeURIField(EditConfigurationVTwo editConfiguration, + VitroRequest vreq) { + editConfiguration.addField(new FieldVTwo(). + setName("conceptSemanticTypeURI") + ); + } + + private void setConceptSemanticTypeLabelField(EditConfigurationVTwo editConfiguration, + VitroRequest vreq) { + editConfiguration.addField(new FieldVTwo(). + setName("conceptSemanticTypeLabel"). + setRangeDatatypeUri(XSD.xstring.toString()) + ); + } //Add preprocessor - private void addPreprocessors(EditConfigurationVTwo editConfiguration, WebappDaoFactory wadf) { + private void addPreprocessors(EditConfigurationVTwo editConfiguration, OntModel ontModel, OntModel modelChangeModel) { //An Edit submission preprocessor for enabling addition of multiple terms for a single search - + //TODO: Check if this is the appropriate way of getting model + + //Passing model to check for any URIs that are present + editConfiguration.addEditSubmissionPreprocessor( - new AddAssociatedConceptsPreprocessor(editConfiguration)); + new AddAssociatedConceptsPreprocessor(editConfiguration, ontModel)); + editConfiguration.addModelChangePreprocessor(new ConceptSemanticTypesPreprocessor( + modelChangeModel)); } @@ -350,54 +396,112 @@ public class AddAssociatedConceptGenerator extends VivoBaseGenerator implements } + //To determine whether or not a concept is a user generated or one from an external vocab source. + //we cannot rely on whether or not it is a skos concept because incorporating UMLS semantic network classes as + //SKOS concept subclasses means that even concepts from an external vocab source might be considered SKOS concepts + //Instead, we will simply determine whether a concept is defined by an external vocabulary source and use that + //as the primary indicator of whether a concept is from an external vocabulary source or a user generated concept private List getAssociatedConceptInfo( List concepts, VitroRequest vreq) { List info = new ArrayList(); for ( Individual conceptIndividual : concepts ) { - boolean isSKOSConcept = false; + boolean userGenerated = true; + //Note that this isn't technically String conceptUri = conceptIndividual.getURI(); String conceptLabel = conceptIndividual.getName(); - //Check if SKOS Concept type - List osl = conceptIndividual.getObjectPropertyStatements(RDF.type.getURI()); - for(ObjectPropertyStatement os: osl) { - if(os.getObjectURI().equals(SKOSConceptType)) { - isSKOSConcept = true; - break; - } - } + + //Check if defined by an external vocabulary source + List vocabList = conceptIndividual.getObjectPropertyStatements(RDFS.isDefinedBy.getURI()); + String vocabSource = null; + String vocabLabel = null; + if(vocabList != null && vocabList.size() > 0) { + userGenerated = false; + vocabSource = vocabList.get(0).getObjectURI(); + Individual sourceIndividual = EditConfigurationUtils.getIndividual(vreq, vocabSource); + //Assuming name will get label + vocabLabel = sourceIndividual.getName(); + } + - if(isSKOSConcept) { - info.add(new AssociatedConceptInfo(conceptLabel, conceptUri, null, null, SKOSConceptType)); + + if(userGenerated) { + //if the concept in question is skos - which would imply a user generated concept + info.add(new AssociatedConceptInfo(conceptLabel, conceptUri, null, null, SKOSConceptType, null, null)); } else { - //Get the vocab source and vocab label - List vocabList = conceptIndividual.getObjectPropertyStatements(RDFS.isDefinedBy.getURI()); - String vocabSource = null; - String vocabLabel = null; - if(vocabList != null && vocabList.size() > 0) { - vocabSource = vocabList.get(0).getObjectURI(); - Individual sourceIndividual = EditConfigurationUtils.getIndividual(vreq, vocabSource); - //Assuming name will get label - vocabLabel = sourceIndividual.getName(); + String conceptSemanticTypeURI = null; + String conceptSemanticTypeLabel = null; + //Can a concept have multiple semantic types? Currently we are only returning the first one + //TODO: Change this into a sparql query that returns all types for the concept that are subclasses of SKOS concepts + HashMap typeAndLabel = this.getConceptSemanticTypeQueryResults(conceptIndividual.getURI(), ModelAccess.on(vreq).getJenaOntModel()); + if(typeAndLabel.containsKey("semanticTypeURI")) { + conceptSemanticTypeURI = typeAndLabel.get("semanticTypeURI"); } - info.add(new AssociatedConceptInfo(conceptLabel, conceptUri, vocabSource, vocabLabel, null)); + if(typeAndLabel.containsKey("semanticTypeLabel")) { + conceptSemanticTypeLabel = typeAndLabel.get("semanticTypeLabel"); + } + + //Assuming this is from an external vocabulary source + info.add(new AssociatedConceptInfo(conceptLabel, conceptUri, vocabSource, vocabLabel, null, conceptSemanticTypeURI, conceptSemanticTypeLabel)); } } return info; } + private HashMap getConceptSemanticTypeQueryResults(String conceptURI, OntModel ontModel) { + HashMap typeAndLabel = new HashMap(); + String queryStr = "SELECT ?semanticTypeURI ?semanticTypeLabel WHERE { " + + "<" + conceptURI + "> <" + RDF.type.getURI() + "> ?semanticTypeURI . " + + "?semanticTypeURI <" + RDFS.subClassOf.getURI() + "> <" + this.SKOSConceptType + ">. " + + "?semanticTypeURI <" + RDFS.label.getURI() + "> ?semanticTypeLabel ." + + "}"; + QueryExecution qe = null; + try{ + Query query = QueryFactory.create(queryStr); + qe = QueryExecutionFactory.create(query, ontModel); + ResultSet results = null; + results = qe.execSelect(); + + while( results.hasNext()){ + QuerySolution qs = results.nextSolution(); + if(qs.get("semanticTypeURI") != null) { + Resource semanticTypeURI = qs.getResource("semanticTypeURI"); + log.debug("Semantic Type URI returned " + semanticTypeURI.getURI()); + typeAndLabel.put("semanticTypeURI", semanticTypeURI.getURI()); + } + if(qs.get("semanticTypeLabel") != null) { + Literal semanticTypeLabel = qs.getLiteral("semanticTypeLabel"); + log.debug("Semantic Type label returned " + semanticTypeLabel.getString()); + typeAndLabel.put("semanticTypeLabel", semanticTypeLabel.getString()); + } + + + } + }catch(Exception ex){ + throw new Error("Error in executing query string: \n" + queryStr + '\n' + ex.getMessage()); + }finally{ + if( qe != null) + qe.close(); + } + return typeAndLabel; + } + public class AssociatedConceptInfo { private String conceptLabel; private String conceptURI; private String vocabURI; private String vocabLabel; private String type; //In case of SKOS concept, will have skos concept type - public AssociatedConceptInfo(String inputLabel, String inputURI, String inputVocabURI, String inputVocabLabel, String inputType) { + private String conceptSemanticTypeURI; //For some services, such as UMLS, we have a semantic type associated + private String conceptSemanticTypeLabel; + public AssociatedConceptInfo(String inputLabel, String inputURI, String inputVocabURI, String inputVocabLabel, String inputType, String inputConceptSemanticTypeURI, String inputConceptSemanticTypeLabel) { this.conceptLabel = inputLabel; this.conceptURI = inputURI; this.vocabURI = inputVocabURI; this.vocabLabel = inputVocabLabel; this.type = inputType; + this.conceptSemanticTypeURI = inputConceptSemanticTypeURI; + this.conceptSemanticTypeLabel = inputConceptSemanticTypeLabel; } //Getters @@ -421,6 +525,14 @@ public class AddAssociatedConceptGenerator extends VivoBaseGenerator implements return type; } + public String getConceptSemanticTypeURI(){ + return conceptSemanticTypeURI; + } + + public String getConceptSemanticTypeLabel(){ + return conceptSemanticTypeLabel; + } + } public class AssociatedConceptInfoComparator implements Comparator{ diff --git a/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/AddAssociatedConceptsPreprocessor.java b/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/AddAssociatedConceptsPreprocessor.java index ec24711a..1b81dbf1 100644 --- a/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/AddAssociatedConceptsPreprocessor.java +++ b/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/AddAssociatedConceptsPreprocessor.java @@ -3,16 +3,30 @@ package edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.preprocessors; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import com.hp.hpl.jena.ontology.OntModel; +import com.hp.hpl.jena.query.Query; +import com.hp.hpl.jena.query.QueryExecution; +import com.hp.hpl.jena.query.QueryExecutionFactory; +import com.hp.hpl.jena.query.QueryFactory; +import com.hp.hpl.jena.query.QuerySolution; +import com.hp.hpl.jena.query.ResultSet; import com.hp.hpl.jena.rdf.model.Literal; +import com.hp.hpl.jena.rdf.model.Resource; +import com.hp.hpl.jena.vocabulary.OWL; +import com.hp.hpl.jena.vocabulary.RDF; import com.hp.hpl.jena.vocabulary.RDFS; import com.hp.hpl.jena.vocabulary.XSD; + + import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.BaseEditSubmissionPreprocessorVTwo; import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditConfigurationUtils; import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditConfigurationVTwo; @@ -24,24 +38,36 @@ public class AddAssociatedConceptsPreprocessor extends protected static final Log log = LogFactory .getLog(AddAssociatedConceptsPreprocessor.class.getName()); - + //TODO: Check if better way to do this? + protected OntModel ontModel = null; // Field names/variables names for n3 - these will have numbers added as // suffix if more than one term private static String conceptNodeBase = "conceptNode"; private static String sourceBase = "conceptSource"; private static String labelBase = "conceptLabel"; + private static String conceptSemanticTypeLabelBase = "conceptSemanticTypeLabel"; + private static String conceptSemanticTypeURIBase = "conceptSemanticTypeURI"; + //keyed off label variable, specifies which uri variable should be used, useful if same label repeated twice + private HashMap labelVarToUriVarHash = null; + private HashMap> conceptSemanticTypeURIVarToValueMap = null; //Also storing submission values private static String conceptNodeValues = null; private static String conceptLabelValues = null; private static String conceptSourceValues = null; + private static String conceptSemanticTypeLabelValues = null; + private static String conceptSemanticTypeURIValues = null; private static MultiValueEditSubmission submission = null; // String datatype // Will be editing the edit configuration as well as edit submission here - public AddAssociatedConceptsPreprocessor(EditConfigurationVTwo editConfig) { + public AddAssociatedConceptsPreprocessor(EditConfigurationVTwo editConfig, OntModel ontModel) { super(editConfig); + this.ontModel = ontModel; + this.labelVarToUriVarHash = new HashMap(); + //Saves values of concept type uris + this.conceptSemanticTypeURIVarToValueMap = new HashMap>(); } public void preprocess(MultiValueEditSubmission inputSubmission) { @@ -50,10 +76,16 @@ public class AddAssociatedConceptsPreprocessor extends // as vocab uri (which is based on thge // For query parameters, check whether CUI copySubmissionValues(); - + + if (conceptNodeValues != null) { String[] conceptNodes = convertDelimitedStringToArray(conceptNodeValues); int numberConcepts = conceptNodes.length; + //This will put the URI value in scope for the first semantic type label + //and generate the rest if need be + processConceptSemanticValues(); + //Also need to see if any broader or narrower uris for the concepts that already exist in the system + //and set up the appropriate relationships between this concept and the broader/narrower uri if (numberConcepts > 1) { processConceptNodes(numberConcepts); } @@ -71,10 +103,26 @@ public class AddAssociatedConceptsPreprocessor extends conceptLabelValues = getConceptLabelValues(); conceptNodeValues = getConceptNodeValues(); conceptSourceValues = getConceptSourceValues(); + log.debug("concept label values are " + conceptLabelValues); + + } + + // + private void processConceptSemanticValues() { + conceptSemanticTypeLabelValues = getConceptSemanticTypeLabelValues(); + conceptSemanticTypeURIValues = getConceptSemanticTypeURIValues(); + + //We are first going to handle the single value case and then handle additional values + //where the rest of the additional values are handled + } + + //This is for additional concept nodes (i.e. if user selects more than one concept) private void processConceptNodes(int numberConcepts) { //There are no "new" resources b/c the concept nodes are URIs from external vocabularies + //New resources for concept semantic type uris + addNewResources(numberConcepts); // Add N3Required addN3Required(numberConcepts); //Add N3 Optional as well @@ -88,6 +136,42 @@ public class AddAssociatedConceptsPreprocessor extends } + //This is specifically for concept semantic type URIs which may need to be generated + private void addNewResources(int numberConcepts) { + // TODO Auto-generated method stub + addConceptSemanticTypeURIResources(numberConcepts); + } + + private void addConceptSemanticTypeURIResources(int numberConcepts) { + //Iterate through the labels and get the corresponding uris + HashSet urisToAdd = new HashSet(); + String[] conceptSemanticTypeLabels= convertDelimitedStringToArray(conceptSemanticTypeLabelValues); + //the number of existing values may not match up, or at least existing populated ones + //Now we can't determine whether all concepts will have semantic types - at some point what if + //we ran a search across all external vocabularies? So we can't compare labels to number of concepts + //but we can ensure that it isn't greater than then number of concepts + if(conceptSemanticTypeLabels != null && conceptSemanticTypeLabels.length <= numberConcepts) { + int i; + for(i = 0; i < numberConcepts; i++) { + int suffix = i + 1; + String conceptSemanticTypeLabelVar = conceptSemanticTypeLabelBase + suffix; + if(this.labelVarToUriVarHash.containsKey(conceptSemanticTypeLabelVar)) { + String newResourceName = this.labelVarToUriVarHash.get(conceptSemanticTypeLabelVar); + if(!urisToAdd.contains(newResourceName)) { + urisToAdd.add(newResourceName); + editConfiguration.addNewResource(newResourceName, null); + } + } + + } + } else if(conceptSemanticTypeLabels != null && conceptSemanticTypeLabels.length > numberConcepts){ + log.error("Number of concept semantic type labels is greater than number of concepts"); + } else{ + log.error("Concept semantic type labels returned are null"); + } + + } + //This is where the actual values will be submitted as if they were separate input fields //Each field name will correspond to the names of the fileds/uris on form/literals on form //generated here @@ -98,6 +182,10 @@ public class AddAssociatedConceptsPreprocessor extends addConceptNodeInputs(numberConcepts); addConceptSourceInputs(numberConcepts); addConceptLabelInputs(numberConcepts); + //for concept semantic type labels and uris where they exist + //TODO: Make into single method as URIs depend on labels + addConceptSemanticTypeLabelAndURIInputs(numberConcepts); + //addConceptSemanticTypeURIInputs(numberConcepts); } @@ -167,22 +255,102 @@ public class AddAssociatedConceptsPreprocessor extends log.error("Concept labels returned were null"); } } + + private void addConceptSemanticTypeLabelAndURIInputs(int numberConcepts) { + String[] labels = convertDelimitedStringToArray(conceptSemanticTypeLabelValues); + HashSet uniqueLabelValues = new HashSet(); + if(labels != null && labels.length == numberConcepts) { + int i; + for(i = 0; i < numberConcepts; i++) { + String thisLabel = labels[i]; + int suffix = i + 1; + String labelInputName = conceptSemanticTypeLabelBase + suffix; + String[] labelValues = new String[1]; + labelValues[0] = thisLabel; + //TODO: Check if there are no funky typed information also stored + //At this point the field should already have been added to edit configuration + FieldVTwo labelField = editConfiguration.getField(labelInputName); + //TODO: Also check to see whether the label is actually populate or will n3 editing take care of that? + if(labelField != null) { + submission.addLiteralToForm(editConfiguration, labelField, labelInputName, labelValues); + //Associate URI + if(!uniqueLabelValues.contains(thisLabel)) { + uniqueLabelValues.add(thisLabel); + this.addConceptSemanticTypeURIInputForLabel(labelInputName, suffix); + } + } else { + log.error("Corresponding field for " + labelInputName + " was not added to edit configuration"); + } + + } + } else if(labels != null && labels.length != numberConcepts){ + log.error("Number of concept semantic type labels did not match the number of concepts to be added"); + } else{ + log.error("Concept labels returned were null"); + } + } + + private void addConceptSemanticTypeURIInputForLabel(String conceptSemanticTypeLabel, int suffix) { + //String[] conceptSemanticTypeURIs= convertDelimitedStringToArray(conceptSemanticTypeURIValues); + + //Get the semantic type URI variable name associated with this label + String uriInputName = this.getConceptSemanticTypeURIFieldName(conceptSemanticTypeLabel, suffix); + //List<> + if(this.conceptSemanticTypeURIVarToValueMap.containsKey(uriInputName)) { + List uriVals = this.conceptSemanticTypeURIVarToValueMap.get(uriInputName); + String[] uriValuesArray = uriVals.toArray(new String[uriVals.size()]); + submission.addUriToForm(editConfiguration, uriInputName, uriValuesArray); + } + + //the number of existing values may not match up, or at least existing populated ones + /* + if(conceptSemanticTypeURIs != null && conceptSemanticTypeURIs.length == numberConcepts) { + int i; + for(i = 0; i < numberConcepts; i++) { + int suffix = i + 1; + String conceptInputName = conceptSemanticTypeURIBase + suffix; + String[] uriValues = new String[1]; + uriValues[0] = conceptSemanticTypeURIs[i]; + //Add value for uri to form + //TODO: Check if value is empty in which case don't add to submission + submission.addUriToForm(editConfiguration, conceptInputName, uriValues); + } + } else if(conceptSemanticTypeURIs != null && conceptSemanticTypeURIs.length != numberConcepts){ + log.error("Number of concept nodes did not match the number of concepts to be added"); + } else{ + log.error("Concept nodes returned were null"); + } + + */ + } + //Fields + private void addFields(int numberConcepts) { //Clear out all fields in edit configuration first editConfiguration.setFields(new HashMap()); int index; + HashSet conceptSemanticTypeUris = new HashSet(); // First one already included in generator so add additional ones here for (index = 1; index <= numberConcepts; index++) { int suffix = index; String conceptNode = conceptNodeBase + suffix; String label = labelBase + suffix; String source = sourceBase + suffix; + String conceptSemanticTypeLabel = conceptSemanticTypeLabelBase + suffix; + String conceptSemanticTypeURI = this.getConceptSemanticTypeURIFieldName(conceptSemanticTypeLabel, suffix); addConceptNodeField(conceptNode); addLabelField(label); addSourceField(source); + //Also add fields for concept semantic type label + addConceptSemanticTypeLabelField(conceptSemanticTypeLabel); + //and concept semantic type URI + if(!conceptSemanticTypeUris.contains(conceptSemanticTypeURI)) { + conceptSemanticTypeUris.add(conceptSemanticTypeURI); + addConceptSemanticTypeURIField(conceptSemanticTypeURI); + } } } @@ -207,6 +375,25 @@ public class AddAssociatedConceptsPreprocessor extends setName(source)); } + + //TODO: Do we need to check if label is empty string? + private void addConceptSemanticTypeLabelField(String label) { + if(label != null) { + editConfiguration.addField(new FieldVTwo(). + setName(label). + setRangeDatatypeUri(XSD.xstring.toString()) + ); + } + + } + + private void addConceptSemanticTypeURIField(String conceptSemanticTypeURI) { + if(conceptSemanticTypeURI != null) { + editConfiguration.addField(new FieldVTwo(). + setName(conceptSemanticTypeURI)); + } + } + //original literals on form: label, uris on form: conceptNode and conceptSource //This will overwrite the original values in the edit configuration @@ -215,16 +402,24 @@ public class AddAssociatedConceptsPreprocessor extends List literalsOnForm = new ArrayList(); int index; - + HashSet conceptSemanticTypeURIs = new HashSet(); // First one already included so add new ones here for (index = 1; index <= numberTerms; index++) { int suffix = index; String conceptNode = conceptNodeBase + suffix; String label = labelBase + suffix; String source = sourceBase + suffix; + String conceptSemanticTypeLabel = conceptSemanticTypeLabelBase + suffix; + //String conceptSemanticTypeURI = conceptSemanticTypeURIBase + suffix; + String conceptSemanticTypeURI = this.getConceptSemanticTypeURIFieldName(conceptSemanticTypeLabel, suffix); urisOnForm.add(conceptNode); - urisOnForm.add(source); + urisOnForm.add(source); + if(!conceptSemanticTypeURIs.contains(conceptSemanticTypeURI)) { + conceptSemanticTypeURIs.add(conceptSemanticTypeURI); + urisOnForm.add(conceptSemanticTypeURI); + } literalsOnForm.add(label); + literalsOnForm.add(conceptSemanticTypeLabel); } editConfiguration.setUrisOnform(urisOnForm); editConfiguration.setLiteralsOnForm(literalsOnForm); @@ -240,8 +435,7 @@ public class AddAssociatedConceptsPreprocessor extends List n3Required = new ArrayList(); int index; String nodeBase = "?" + conceptNodeBase; - String labelVar = "?" + labelBase; - String sourceVar = "?" + sourceBase; + String prefixStr = "@prefix core: ."; // First one already included so add new ones here for (index = 1; index <= numberConcepts; index++) { @@ -254,30 +448,60 @@ public class AddAssociatedConceptsPreprocessor extends editConfiguration.setN3Required(n3Required); } //Add n3 optional - + //TODO: Rewrite optional N3 private void addN3Optional(int numberConcepts) { List n3Optional = new ArrayList(); int index; String nodeBase = "?" + conceptNodeBase; String labelVar = "?" + labelBase; String sourceVar = "?" + sourceBase; + String conceptSemanticTypeLabelVar = "?" + conceptSemanticTypeLabelBase; String prefixStr = "@prefix core: ."; // First one already included so add new ones here + //We already have a label var to uri var setup for (index = 1; index <= numberConcepts; index++) { int suffix = index; String node = nodeBase + suffix; String label = labelVar + suffix; String source = sourceVar + suffix; + String conceptSemanticTypeLabel = conceptSemanticTypeLabelVar + suffix; + //get the URI appropriate for the concept semantic type label var + String conceptSemanticTypeURI = getConceptSemanticTypeURIVar(conceptSemanticTypeLabelBase + suffix, suffix); + //onceptSemanticTypeURIVar + suffix; String n3String = prefixStr; n3String += node + " <" + RDFS.label.getURI() + "> " + label + " .\n" + - node + " <" + RDFS.isDefinedBy.getURI() + "> " + source + " ."; + node + " <" + RDFS.isDefinedBy.getURI() + "> " + source + " ."; + String n3ConceptTypeString = prefixStr; + n3ConceptTypeString += node + " <" + RDF.type.getURI() + "> " + conceptSemanticTypeURI + " ." + + conceptSemanticTypeURI + " <" + RDFS.label.getURI() + "> " + conceptSemanticTypeLabel + " .\n" + + conceptSemanticTypeURI + " <" + RDFS.subClassOf.getURI() + "> .\n" ; + n3Optional.add(n3String); + //adding separately so their resolution does not depend on each other + n3Optional.add(n3ConceptTypeString); + } //Already have n3 required so need to add to that editConfiguration.setN3Optional(n3Optional); } + //get the URI variable that is associated with this concept type URI, which might not be + //the same suffix because the same label value might be repeated and we need to use the same URI + //representing that concept semantic type + private String getConceptSemanticTypeURIVar(String labelVar, int suffix) { + // TODO Auto-generated method stub + return "?" + this.getConceptSemanticTypeURIFieldName(labelVar, suffix); + } + + private String getConceptSemanticTypeURIFieldName(String labelVar, int suffix) { + // TODO Auto-generated method stub + if(this.labelVarToUriVarHash.containsKey(labelVar)) { + return this.labelVarToUriVarHash.get(labelVar); + } + return this.conceptSemanticTypeURIBase + suffix; + } + private String[] convertDelimitedStringToArray(String inputString) { String[] inputArray = new String[1]; if (inputString.indexOf(",") != -1) { @@ -290,6 +514,7 @@ public class AddAssociatedConceptsPreprocessor extends } + //Get values from submission private String getConceptNodeValues() { Map> urisFromForm = submission.getUrisFromForm(); List conceptNodes = urisFromForm.get("conceptNode"); @@ -308,6 +533,131 @@ public class AddAssociatedConceptsPreprocessor extends } + private String getConceptSemanticTypeLabelValues() { + Map> literalsFromForm = submission.getLiteralsFromForm(); + Map> transformed = EditConfigurationUtils.transformLiteralMap(literalsFromForm); + return (String) getFirstElement(transformed.get("conceptSemanticTypeLabel")); + } + + //This will either generate or retrieve URIs for the concept semantic type labels if they exist + //We will then update the submission to include this + private String getConceptSemanticTypeURIValues() { + String[] conceptSemanticTypeLabels = convertDelimitedStringToArray(conceptSemanticTypeLabelValues); + //keep track of what label values already exist and to which label variables they map + HashMap> labelValueToVarSuffix = new HashMap>(); + int numberLabels = conceptSemanticTypeLabels.length; + String pseudoInputString = ""; + + //The rest of this code is really only relevant for multiple values, so we could break out the old code above + //as we don't need to set up hashes etc. if there is only one concept node being added + if(numberLabels == 1) { + String label = conceptSemanticTypeLabels[0]; + String uri = getURIForSemanticTypeLabel(label); + if(uri != "") { + String[] urisToAdd = new String[1]; + urisToAdd[0] = uri; + pseudoInputString = uri; + log.debug("uris to add" + uri); + submission.addUriToForm(this.editConfiguration, "conceptSemanticTypeURI", urisToAdd); + } + + } + //if there is more than one concept node, we may have duplicate semantic types + //which will need to be referred to by the same semantic type uri + else if (numberLabels > 1){ + + for(int i = 0; i < numberLabels; i++) { + int suffix = i + 1; + String label = conceptSemanticTypeLabels[i]; + String labelVar = this.conceptSemanticTypeLabelBase + suffix; + //if label has not already been encountered, create entry for label value + //and list with the label variables that would refer to it + //for unique values, the uri variable will be the same as label + Integer thisSuffix = new Integer(suffix); + if(!labelValueToVarSuffix.containsKey(label)) { + labelValueToVarSuffix.put(label, new ArrayList()); + //Add suffix to list if not already there + labelValueToVarSuffix.get(label).add(thisSuffix); + } else { + //in this case, the label already exists, get the very first element in the list + //and use that as the uri variable + List suffixList = labelValueToVarSuffix.get(label); + if(suffixList != null && suffixList.size() > 0) { + thisSuffix = suffixList.get(0); + } + + } + + //Now add the uri var to the hash mapping label variable to uri variable + String uriVar = this.conceptSemanticTypeURIBase + thisSuffix.intValue(); + this.labelVarToUriVarHash.put(labelVar, uriVar); + + + //Make or retrieve URI for this label + //TODO: Do we create this string with empty inputs ? + String uri = getURIForSemanticTypeLabel(label); + if(uri != "") { + //uri var shouldn't be repeated? + if(!this.conceptSemanticTypeURIVarToValueMap.containsKey(uriVar)) { + this.conceptSemanticTypeURIVarToValueMap.put(uriVar, new ArrayList()); + this.conceptSemanticTypeURIVarToValueMap.get(uriVar).add(uri); + } + } + if(i != 0) { + pseudoInputString += ","; + } + pseudoInputString += uri; + + } + + //Add this string to the uris for the form + String[] urisToAdd = new String[1]; + urisToAdd[0] = pseudoInputString; + log.debug("uris to add" + pseudoInputString); + submission.addUriToForm(this.editConfiguration, "conceptSemanticTypeURI", urisToAdd); + + } + return pseudoInputString; + } + + private String getURIForSemanticTypeLabel(String label) { + String existingURI = this.getExistingSemanticTypeURI(label); + if(existingURI != null) { + return existingURI; + } + //if we leave this as null, we should be able to generate a new resource + //empty string because there may be more than one value returned for labels + else return ""; + + } + + private String getExistingSemanticTypeURI(String label) { + String queryStr = "SELECT ?semanticType WHERE { ?semanticType <" + RDF.type.getURI() + "> <" + OWL.Class.getURI() + "> . " + + "?semanticType <" + RDFS.label.getURI() + "> \"" + label + "\"^^ . }"; + QueryExecution qe = null; + try{ + Query query = QueryFactory.create(queryStr); + qe = QueryExecutionFactory.create(query, this.ontModel); + ResultSet results = null; + results = qe.execSelect(); + + while( results.hasNext()){ + QuerySolution qs = results.nextSolution(); + if(qs.get("semanticType") != null) { + Resource semanticTypeURI = qs.getResource("semanticType"); + log.debug("Semantic Type URI returned " + semanticTypeURI.getURI()); + return semanticTypeURI.getURI(); + } + } + }catch(Exception ex){ + throw new Error("Error in executing query string: \n" + queryStr + '\n' + ex.getMessage()); + }finally{ + if( qe != null) + qe.close(); + } + return null; + } + private Object getFirstElement(List inputList) { if(inputList == null || inputList.size() == 0) return null; diff --git a/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/ConceptSemanticTypesPreprocessor.java b/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/ConceptSemanticTypesPreprocessor.java new file mode 100644 index 00000000..b95733b4 --- /dev/null +++ b/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/ConceptSemanticTypesPreprocessor.java @@ -0,0 +1,125 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.preprocessors; + +import javax.servlet.http.HttpServletRequest; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import com.hp.hpl.jena.ontology.OntModel; +import com.hp.hpl.jena.query.Dataset; +import com.hp.hpl.jena.query.Query; +import com.hp.hpl.jena.query.QueryExecution; +import com.hp.hpl.jena.query.QueryExecutionFactory; +import com.hp.hpl.jena.query.QueryFactory; +import com.hp.hpl.jena.query.QuerySolutionMap; +import com.hp.hpl.jena.query.Syntax; +import com.hp.hpl.jena.rdf.model.Literal; +import com.hp.hpl.jena.rdf.model.Model; +import com.hp.hpl.jena.rdf.model.ModelFactory; +import com.hp.hpl.jena.rdf.model.Property; +import com.hp.hpl.jena.rdf.model.ResIterator; +import com.hp.hpl.jena.rdf.model.Resource; +import com.hp.hpl.jena.rdf.model.ResourceFactory; +import com.hp.hpl.jena.rdf.model.Statement; +import com.hp.hpl.jena.shared.Lock; +import com.hp.hpl.jena.vocabulary.RDF; +import com.hp.hpl.jena.vocabulary.RDFS; + +import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary; +import edu.cornell.mannlib.vitro.webapp.dao.jena.DatasetWrapper; +import edu.cornell.mannlib.vitro.webapp.dao.jena.DatasetWrapperFactory; + +//We are representing semantic types from the UMLS Semantic Network as OWL Classes +//and this preprocessor will add the appropriate class information to the TBox + +public class ConceptSemanticTypesPreprocessor implements ModelChangePreprocessor { + + private static String VIVOCore = "http://vivoweb.org/ontology/core#"; + private static String SKOSConceptType = "http://www.w3.org/2004/02/skos/core#Concept"; + private Log log = LogFactory.getLog(ConceptSemanticTypesPreprocessor.class); + + private OntModel toUpdateModel = null; + + //Custom constructor + public ConceptSemanticTypesPreprocessor(OntModel updateModel) { + this.toUpdateModel = updateModel; + } + + @Override + public void preprocess(Model retractionsModel, Model additionsModel, + HttpServletRequest request) { + //Run a construct query against the additions model + String prefixes = "PREFIX rdfs:<" + RDFS.getURI() + "> " + + "PREFIX owl: " + + "PREFIX rdf:<" + RDF.getURI() + ">" + + "PREFIX skos:"; + String constructQuery = prefixes + " CONSTRUCT { " + + "?semanticType rdf:type owl:Class. " + + "?semanticType rdfs:subClassOf skos:Concept . " + + "?semanticType rdfs:label ?label. " + + "} WHERE { " + + "?concept rdf:type ?semanticType. " + + "?semanticType rdfs:label ?label . " + + "?semanticType rdfs:subClassOf skos:Concept . " + + "}"; + + //Execute construct query + Model constructedModel = ModelFactory.createDefaultModel(); + + + log.debug("CONSTRUCT query string " + constructQuery); + + Query query = null; + try { + query = QueryFactory.create(constructQuery, Syntax.syntaxARQ); + } catch(Throwable th){ + log.error("Could not create CONSTRUCT SPARQL query for query " + + "string. " + th.getMessage()); + log.error(constructQuery); + return; + } + + + + additionsModel.getLock().enterCriticalSection(Lock.READ); + QueryExecution qe = null; + try { + qe = QueryExecutionFactory.create( + query, additionsModel); + qe.execConstruct(constructedModel); + } catch (Exception e) { + log.error("Error getting constructed model for query string " + constructQuery); + } finally { + if (qe != null) { + qe.close(); + } + additionsModel.getLock().leaveCriticalSection(); + } + + //Add constructed model to the designated update model + toUpdateModel.enterCriticalSection(Lock.WRITE); + try { + toUpdateModel.add(constructedModel); + } catch (Exception e) { + log.error("Error adding statements to update model for " + constructQuery); + } finally { + toUpdateModel.leaveCriticalSection(); + } + + //Take this constructed model and remove from the additions model + additionsModel.enterCriticalSection(Lock.WRITE); + try { + additionsModel.remove(constructedModel.listStatements().toList()); + } catch (Exception e) { + log.error("Error removing statements from additions model for " + constructQuery); + } finally { + additionsModel.leaveCriticalSection(); + } + + } + + + +} diff --git a/src/edu/cornell/mannlib/vitro/webapp/servlet/ConceptSearchServlet.java b/src/edu/cornell/mannlib/vitro/webapp/servlet/ConceptSearchServlet.java index deca950d..9d47efb2 100644 --- a/src/edu/cornell/mannlib/vitro/webapp/servlet/ConceptSearchServlet.java +++ b/src/edu/cornell/mannlib/vitro/webapp/servlet/ConceptSearchServlet.java @@ -20,9 +20,9 @@ import org.apache.commons.logging.LogFactory; import edu.cornell.mannlib.semservices.bo.Concept; import edu.cornell.mannlib.semservices.bo.ConceptInfo; import edu.cornell.mannlib.semservices.bo.SemanticServicesError; +import edu.cornell.mannlib.semservices.view.BeanToJsonSerializer; import edu.cornell.mannlib.vitro.webapp.controller.VitroHttpServlet; import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; -import edu.cornell.mannlib.vitro.webapp.utils.ConceptSearchService.BeanToJsonSerializer; import edu.cornell.mannlib.vitro.webapp.utils.ConceptSearchService.ConceptSearchServiceUtils; public class ConceptSearchServlet extends VitroHttpServlet { diff --git a/src/edu/cornell/mannlib/vitro/webapp/utils/ConceptSearchService/ConceptSearchServiceUtils.java b/src/edu/cornell/mannlib/vitro/webapp/utils/ConceptSearchService/ConceptSearchServiceUtils.java index c0521e0b..d232e875 100644 --- a/src/edu/cornell/mannlib/vitro/webapp/utils/ConceptSearchService/ConceptSearchServiceUtils.java +++ b/src/edu/cornell/mannlib/vitro/webapp/utils/ConceptSearchService/ConceptSearchServiceUtils.java @@ -39,7 +39,7 @@ public class ConceptSearchServiceUtils { HashMap map = new HashMap(); map.put(UMLSVocabSource, new VocabSourceDescription("UMLS", UMLSVocabSource, "http://www.nlm.nih.gov/research/umls/", "Unified Medical Language System")); //Commenting out agrovoc for now until implementation is updated - // map.put(AgrovocVocabSource, new VocabSourceDescription("AGROVOC", AgrovocVocabSource, "http://www.fao.org/agrovoc/", "Agricultural Vocabulary")); + map.put(AgrovocVocabSource, new VocabSourceDescription("AGROVOC", AgrovocVocabSource, "http://www.fao.org/agrovoc/", "Agricultural Vocabulary")); map.put(GemetVocabSource, new VocabSourceDescription("GEMET", GemetVocabSource, "http://www.eionet.europa.eu/gemet", "GEneral Multilingual Environmental Thesaurus")); return map; } @@ -82,7 +82,7 @@ public class ConceptSearchServiceUtils { //Get search String searchTerm = getSearchTerm(vreq); - List conceptResults = conceptServiceClass.processResults(searchTerm); + List conceptResults = conceptServiceClass.getConcepts(searchTerm); return conceptResults; } diff --git a/themes/wilma/i18n/all.properties b/themes/wilma/i18n/all.properties index 48f72df7..a0f2585f 100644 --- a/themes/wilma/i18n/all.properties +++ b/themes/wilma/i18n/all.properties @@ -61,14 +61,18 @@ view_all_faculty = view all faculty view_all_members_of_org = View all the members of this organization. faculty_memberships = Faculty Memberships -individuals_with_researh_area_one = Here are the individuals in {0} who have an interest in this research area. -individuals_with_researh_area_two = Here are the individuals in the {0} who have an interest in this research area. +individuals_with_researh_area_one = Here are the individuals in {0} who have an interest in this research area. +individuals_with_researh_area_two = Here are the individuals in the {0} who have an interest in this research area. +individuals_with_dept = Here are the individuals with an interest in {0} who are in this organization. faculty_with_researh_area = Here are the faculty members in the {0} department who have an interest in this research area. view_all_individuals_in_area = View all individuals with an interest in this area. +view_all_individuals_in_dept = View all individuals in this organization. view_all_faculty_in_area = View all faculty with an interest in this area. faculty_research_areas = Faculty Research Areas affiliated_research_areas = Affiliated Research Areas -research_area = research area +affiliated_departments = Associated Departments +research_area = individuals in the department with this research area +organization = individuals with the research area in this organization display_more = more display_less = less @@ -276,7 +280,6 @@ change_selection = change selection # custom form templates ( /templates/freemarker/edit/forms ) # manage_concepts = Manage Concepts -remove_capitalized = Remove no_concepts_specified = There are currently no concepts specified. return_to_profile = Return to Profile Page external_vocabulary_services = External Vocabulary Services diff --git a/themes/wilma/i18n/images/select_locale_en_AU.GIF b/themes/wilma/i18n/images/select_locale_en_AU.GIF deleted file mode 100644 index e4c2274c..00000000 Binary files a/themes/wilma/i18n/images/select_locale_en_AU.GIF and /dev/null differ diff --git a/themes/wilma/i18n/images/select_locale_es_MX.GIF b/themes/wilma/i18n/images/select_locale_es_MX.GIF deleted file mode 100644 index 11c25782..00000000 Binary files a/themes/wilma/i18n/images/select_locale_es_MX.GIF and /dev/null differ diff --git a/themes/wilma/templates/individual--foaf-person.ftl b/themes/wilma/templates/individual--foaf-person.ftl index 6e2161fb..761333be 100644 --- a/themes/wilma/templates/individual--foaf-person.ftl +++ b/themes/wilma/templates/individual--foaf-person.ftl @@ -11,6 +11,9 @@ <#if !labelCount??> <#assign labelCount = 0 > +<#if !localesCount??> + <#assign localesCount = 1> + <#assign visRequestingTemplate = "foaf-person-wilma">

    @@ -55,7 +58,7 @@ <#else>

    <#-- Label --> - <@p.label individual editable labelCount/> + <@p.label individual editable labelCount localesCount/> <#-- Display preferredTitle if it exists; otherwise mostSpecificTypes --> <#assign title = propertyGroups.pullProperty("${core}preferredTitle")!> diff --git a/themes/wilma/templates/page-home.ftl b/themes/wilma/templates/page-home.ftl index 5a02ac10..8547e0b8 100644 --- a/themes/wilma/templates/page-home.ftl +++ b/themes/wilma/templates/page-home.ftl @@ -97,6 +97,7 @@ stateString: '${i18n().map_state_string}', statewideLocations: '${i18n().statewide_locations}', researchersInString: '${i18n().researchers_in}', + inString: '${i18n().in}', noFacultyFound: '${i18n().no_faculty_found}', placeholderImage: '${i18n().placeholder_image}', viewAllFaculty: '${i18n().view_all_faculty}', @@ -108,7 +109,7 @@ if ( $('input.search-homepage').css('text-align') == "right" ) { $('input.search-homepage').attr("value","${i18n().limit_search} \u2192"); } - + <@lh.getGeoResearcherCount/> \ No newline at end of file diff --git a/utilities/releaseScripts/1_setup.rb b/utilities/releaseScripts/1_setup.rb new file mode 100644 index 00000000..90194d85 --- /dev/null +++ b/utilities/releaseScripts/1_setup.rb @@ -0,0 +1,141 @@ +=begin +-------------------------------------------------------------------------------- + +Check for the required parameters of base directory, username, email address, +revision label and candidate label. + +Offer to run the licenser to be sure that we are ready to go. + +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +=end + +$: << File.dirname(File.expand_path(__FILE__)) +require '_common' + +# +# ------------------------------------------------------------------------------------ +# Runs the licenser against both VIVO and Vitro, and shows the results. +# ------------------------------------------------------------------------------------ +# + +class LicenserCaller + def call_licenser(property_file) + properties = PropertyFileReader.read(property_file) + l = Licenser.new(properties) + l.process + l.report(properties) + return l.success? + end + + def initialize() + require "#{Settings.vitro_path}/utilities/licenser/licenser" + require "#{Settings.vitro_path}/utilities/licenser/property_file_reader" + + puts "Scanning VIVO..." + vivo_success = call_licenser("#{Settings.vivo_path}/config/licenser/licenser.properties") + puts "Scanning Vitro..." + vitro_success = call_licenser("#{Settings.vitro_path}/webapp/config/licenser/licenser.properties") + if vivo_success && vitro_success + puts "Licenser was successful" + else + puts "Licenser found problems" + end + end +end + +# +# Show the current value of the setting, ask for a replacement value, validate it, and set it. +# +def do_setting(getter, validator, setter, label, format="a string") + v1 = getter.call + currently = v1.empty? ? "Currently not set" : "Currently '#{v1}'" + v2 = prompt "#{label}?\n(#{format})\n(#{currently})" + + v2 = v1 if v2.empty? + v2 = validator.call(v2) + + if v2.empty? + raise InputException.new("Can't run without #{label}") + elsif v1 == v2 + puts "Keeping #{label} as '#{v2}'" + puts + else + puts "Setting #{label} to '#{v2}'" + setter.call(v2) + puts + end + v2 +end + +def get_base_directory() + do_setting( + Settings.method(:base_directory), + Settings.method(:confirm_base_directory), + Settings.method(:base_directory=), + "Git base directory", + "holds Vitro and VIVO repositories") +end + +def get_user_name() + do_setting( + Settings.method(:username), + Settings.method(:confirm_username), + Settings.method(:username=), + "Git user.name") +end + +def get_email() + do_setting( + Settings.method(:email), + Settings.method(:confirm_email), + Settings.method(:email=), + "Git user.email") +end + +def get_release_label() + do_setting( + Settings.method(:release_label), + Settings.method(:confirm_release_label), + Settings.method(:release_label=), + "Release label", + "like '3.2' or '3.2.1'") +end + +def get_candidate_label() + do_setting( + Settings.method(:candidate_label), + Settings.method(:confirm_candidate_label), + Settings.method(:candidate_label=), + "Release candidate label", + "like 'rc1' or 'tc3' or 'final'") +end + +def run_licenser() + puts "It's a good idea to check the licenses before proceeding." + yn = prompt "Ready to run the licenser? (y/n)" + if (yn.downcase == 'y') + LicenserCaller.new() + else + puts "OK - forget it." + end +end + +# +# ------------------------------------------------------------------------------------ +# Main method +# ------------------------------------------------------------------------------------ +# + +begin + get_base_directory() + get_user_name() + get_email() + get_release_label() + get_candidate_label() + run_licenser() +rescue BadState + puts + puts "#{$!.message} - Aborting." + puts +end diff --git a/utilities/releaseScripts/2_create_branches.rb b/utilities/releaseScripts/2_create_branches.rb new file mode 100644 index 00000000..b5eb1215 --- /dev/null +++ b/utilities/releaseScripts/2_create_branches.rb @@ -0,0 +1,52 @@ +=begin +-------------------------------------------------------------------------------- + +Get the branch name. + +If either repository already contains the branch, complain. + +Otherwise, pull develop to the latest commit and create the branches. Don't push. + +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +=end + +$: << File.dirname(File.expand_path(__FILE__)) +require '_common' + +# +# Create a branch by this name in this repository. +# +def create_branch(dir, branch) + Dir.chdir(dir) do |path| + approve_and_execute([ + "git checkout develop", + "git pull", + "git checkout -b #{branch}" + ], "in #{path}") + end +end + +# +# ------------------------------------------------------------------------------------ +# Main method +# ------------------------------------------------------------------------------------ +# + +begin + branch = Settings.branch_name + vivo_path = Settings.vivo_path + vitro_path = Settings.vitro_path + + raise BadState.new("Branches are not created for test candidates.") if is_test_candidate?() + raise BadState.new("Branch #{branch} already exists in VIVO.") if branch_exists?(vivo_path, branch) + raise BadState.new("Branch #{branch} already exists in Vitro.") if branch_exists?(vitro_path, branch) + + get_permission_and_go("OK to create branches named '#{branch}'?") do + puts "Creating branches" + create_branch(vivo_path, branch) + create_branch(vitro_path, branch) + end +rescue BadState + puts "#{$!.message} - Aborting." +end diff --git a/utilities/releaseScripts/3_create_tags.rb b/utilities/releaseScripts/3_create_tags.rb new file mode 100644 index 00000000..f20cf77e --- /dev/null +++ b/utilities/releaseScripts/3_create_tags.rb @@ -0,0 +1,62 @@ +=begin +-------------------------------------------------------------------------------- + +Get the branch name and the tag name. + +If either repository doesn't contain the branch, complain. +If either repository already contains the tag, complain. + +Otherwise, Checkout the branch, pull the branch to the latest commit (if it is +tracking a remote branch) and create the tag. Don't push. + +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +=end + +$: << File.dirname(File.expand_path(__FILE__)) +require '_common' + +# +# Create a tag by this name in this repository. +# +def create_tag(dir, branch, tag, message) + Dir.chdir(dir) do |path| + cmds = ["git checkout #{branch}", + "git pull", + "git tag -a #{tag} -m '#{message}'" + ] + cmds.delete_at(1) unless is_remote_branch?(branch) + approve_and_execute(cmds, "in #{path}") + end +end + +def is_remote_branch?(branch) + ! `git branch --list -a origin/#{branch}`.strip.empty? +end + +# +# ------------------------------------------------------------------------------------ +# Main method +# ------------------------------------------------------------------------------------ +# + +begin + branch = Settings.branch_name + tag = Settings.tag_name + message = Settings.tag_message + vivo_path = Settings.vivo_path + vitro_path = Settings.vitro_path + + raise BadState.new("Branch #{branch} doesn't exist in VIVO.") unless branch_exists?(vivo_path, branch) + raise BadState.new("Branch #{branch} doesn't exist in Vitro.") unless branch_exists?(vitro_path, branch) + raise BadState.new("Tag #{tag} already exists in VIVO.") if tag_exists?(vivo_path, tag) + raise BadState.new("Tag #{tag} already exists in Vitro.") if tag_exists?(vitro_path, tag) + + get_permission_and_go("OK to create tags named '#{tag}' '#{message}'?") do + puts "Creating tags" + create_tag(vivo_path, branch, tag, message) + create_tag(vitro_path, branch, tag, message) + end +rescue BadState + puts "#{$!.message} - Aborting." +end diff --git a/utilities/releaseScripts/4_extract_files.rb b/utilities/releaseScripts/4_extract_files.rb new file mode 100644 index 00000000..6b480338 --- /dev/null +++ b/utilities/releaseScripts/4_extract_files.rb @@ -0,0 +1,61 @@ +=begin +-------------------------------------------------------------------------------- + +Get the tag name. + +If either repository doesn't contain the tag, complain. + +Otherwise, checkout the tag, copy the files to an appropriate area. + +The files are specified so hidden files will not be copied, but this only works +at the top levels. So the .git directories are omitted, as well as some Eclipse +artifacts and Mac OS artifacts. However, this only works at the top levels. + +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +=end + +$: << File.dirname(File.expand_path(__FILE__)) +require '_common' + +# +# Get the VIVO files and the Vitro files, and remove the .git directories. +# +def export_files(vivo_path, vitro_path, tag, export_dir) + approve_and_execute([ + "rm -Rf #{File.expand_path("..", export_dir)}", + "mkdir -pv #{export_dir}", + "cp -R #{vivo_path}/* #{export_dir}", + "mkdir -pv #{export_dir}/vitro-core", + "cp -R #{vitro_path}/* #{export_dir}/vitro-core", + ]) +end + +# +# ------------------------------------------------------------------------------------ +# Main method +# ------------------------------------------------------------------------------------ +# + +begin + tag = Settings.tag_name + vivo_path = Settings.vivo_path + vitro_path = Settings.vitro_path + export_dir = Settings.export_dir + + raise BadState.new("Tag #{tag} doesn't exist in VIVO.") unless tag_exists?(vivo_path, tag) + raise BadState.new("Tag #{tag} doesn't exist in Vitro.") unless tag_exists?(vitro_path, tag) + + if File.directory?(export_dir) + p = "OK to overwrite export area at #{export_dir} ?" + else + p = "OK to create export area at #{export_dir} ?" + end + + get_permission_and_go(p) do + puts "Building export area" + export_files(vivo_path, vitro_path, tag, export_dir) + end +rescue BadState + puts "#{$!.message} - Aborting." +end diff --git a/utilities/releaseScripts/5_insert_revision_info.rb b/utilities/releaseScripts/5_insert_revision_info.rb new file mode 100644 index 00000000..ada08700 --- /dev/null +++ b/utilities/releaseScripts/5_insert_revision_info.rb @@ -0,0 +1,62 @@ +=begin +-------------------------------------------------------------------------------- + +Figure the revision info and store it in the export directory, for both VIVO +and Vitro. + +If the tags don't exist in either repository, or if the export directory is not +populated, complain. + +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +=end + +$: << File.dirname(File.expand_path(__FILE__)) +require '_common' + +# +# Get the revision information from Git and store it in the export directory. +# +def create_revision_info(git_path, info_file_path, tag) + Dir.chdir(git_path) do |path| + commit = `git show-ref --tags --hash=7 #{tag}`.strip + puts "Writing '#{tag} ~ #{commit}' to #{info_file_path}" + File.open(info_file_path, "w") do |f| + f.puts tag + f.puts commit + end + end +end + +# +# ------------------------------------------------------------------------------------ +# Main method +# ------------------------------------------------------------------------------------ +# + +begin + tag = Settings.tag_name + vivo_path = Settings.vivo_path + vitro_path = Settings.vitro_path + export_dir = Settings.export_dir + vivo_revision_info_path = Settings.vivo_revision_info_path + vitro_revision_info_path = Settings.vitro_revision_info_path + + raise BadState.new("Tag #{tag} doesn't exist in VIVO.") unless tag_exists?(vivo_path, tag) + raise BadState.new("Tag #{tag} doesn't exist in Vitro.") unless tag_exists?(vitro_path, tag) + raise BadState.new("Files have not been exported to #{export_dir}") unless File.directory?(export_dir) + + if File.exist?(vivo_revision_info_path) || File.exist?(vitro_revision_info_path) + p = "OK to overwrite revision_info at these paths? \n #{vivo_revision_info_path} \n #{vitro_revision_info_path} ?" + else + p = "OK to write revision_info at these paths? \n #{vivo_revision_info_path} \n #{vitro_revision_info_path} ?" + end + + get_permission_and_go(p) do + puts "Building revision info" + create_revision_info(vivo_path, vivo_revision_info_path, tag) + create_revision_info(vitro_path, vitro_revision_info_path, tag) + end +rescue BadState + puts "#{$!.message} - Aborting." +end diff --git a/utilities/releaseScripts/6_create_distribution_files.rb b/utilities/releaseScripts/6_create_distribution_files.rb new file mode 100644 index 00000000..8c4e9013 --- /dev/null +++ b/utilities/releaseScripts/6_create_distribution_files.rb @@ -0,0 +1,60 @@ +=begin +-------------------------------------------------------------------------------- + +Create TAR and ZIP files for both VIVO and Vitro. + +Complain if the files have not been exported, or the revision info doesn't exist. + +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +=end + +$: << File.dirname(File.expand_path(__FILE__)) +require '_common' + +# +# Zip up the VIVO distribution. Extract the Vitro distribution and zip that. +# +def create_distribution_files(export_dir, vivo_filename, vitro_filename) + export_parent_dir = File.dirname(export_dir) + Dir.chdir(export_parent_dir) do |path| + cmds = [ + "cp -r #{vivo_filename}/vitro-core #{vitro_filename}", + "zip -rq #{vivo_filename}.zip #{vivo_filename}", + "tar -czf #{vivo_filename}.tar.gz #{vivo_filename}", + "zip -rq #{vitro_filename}.zip #{vitro_filename}", + "tar -czf #{vitro_filename}.tar.gz #{vitro_filename}" + ] + cmds.insert(0, "rm -r #{vitro_filename}") if File.exist?(vitro_filename) + approve_and_execute(cmds) + end +end + +# +# ------------------------------------------------------------------------------------ +# Main method +# ------------------------------------------------------------------------------------ +# + +begin + tag = Settings.tag_name + vivo_path = Settings.vivo_path + vitro_path = Settings.vitro_path + export_dir = Settings.export_dir + vivo_revision_info_path = Settings.vivo_revision_info_path + vitro_revision_info_path = Settings.vitro_revision_info_path + vivo_filename = Settings.vivo_distribution_filename + vitro_filename = Settings.vitro_distribution_filename + + raise BadState.new("Files have not been exported to #{export_dir}") unless File.directory?(export_dir) + raise BadState.new("Revision information file does not exist at #{vivo_revision_info_path}") unless File.exist?(vivo_revision_info_path) + raise BadState.new("Revision information file does not exist at #{vitro_revision_info_path}") unless File.exist?(vitro_revision_info_path) + + + get_permission_and_go("OK to create distribution files in #{export_dir} ?") do + puts "Creating distribution files" + create_distribution_files(export_dir, vivo_filename, vitro_filename) + end +rescue BadState + puts "#{$!.message} - Aborting." +end diff --git a/utilities/releaseScripts/7_merge_to_master.rb b/utilities/releaseScripts/7_merge_to_master.rb new file mode 100644 index 00000000..674013f0 --- /dev/null +++ b/utilities/releaseScripts/7_merge_to_master.rb @@ -0,0 +1,57 @@ +=begin +-------------------------------------------------------------------------------- + +Merge the maintenance branches into the master branchs, and create the final +release tags. + +This will only work if the release candidate is "final", and if the maintenance +branches already exist. + +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +=end + +$: << File.dirname(File.expand_path(__FILE__)) +require '_common' + +# +# Merge the maintenance branch to the master branch and create the tag. +# +def merge_branch_to_master(branch, tag, message, repo_path) + Dir.chdir(repo_path) do |path| + cmds = [ + "git checkout master", + "git merge --no-ff -Xtheirs #{branch}", + "git tag -a -f #{tag} -m '#{message}'" + ] + cmds.insert(0, "git branch master origin/master") if `git branch --list master`.strip.empty? + approve_and_execute(cmds, "in #{path}") + end +end + +# +# ------------------------------------------------------------------------------------ +# Main method +# ------------------------------------------------------------------------------------ +# + +begin + branch = Settings.branch_name + candidate_label = Settings.confirm_candidate_label(Settings.candidate_label) + tag = Settings.tag_name + message = Settings.tag_message + vivo_path = Settings.vivo_path + vitro_path = Settings.vitro_path + + raise BadState.new("Only the final release gets merged to the master branch.") unless candidate_label == "final" + raise BadState.new("Branch #{branch} doesn't exist in VIVO.") unless branch_exists?(vivo_path, branch) + raise BadState.new("Branch #{branch} doesn't exist in Vitro.") unless branch_exists?(vitro_path, branch) + + get_permission_and_go("OK to merge the #{tag} tags to the master branches?") do + puts "Merging tags" + merge_branch_to_master(branch, tag, message, vivo_path) + merge_branch_to_master(branch, tag, message, vitro_path) + end +rescue BadState + puts "#{$!.message} - Aborting." +end diff --git a/utilities/releaseScripts/_common.rb b/utilities/releaseScripts/_common.rb new file mode 100644 index 00000000..b175b3e1 --- /dev/null +++ b/utilities/releaseScripts/_common.rb @@ -0,0 +1,251 @@ +=begin +-------------------------------------------------------------------------------- + +Methods and classes used by the scripts. + +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +=end + +# +# ------------------------------------------------------------------------------------ +# This exception class says that we aren't happy with the state of things. +# ------------------------------------------------------------------------------------ +# + +class BadState < Exception +end + +# +# ------------------------------------------------------------------------------------ +# A class with methods for handling the settings. +# ------------------------------------------------------------------------------------ +# + +class Settings + # + # The settings themselves: getters, setters, and validators. + # + + def self.base_directory + `git config --get --global vivo.release.basedirectory`.strip + end + + def self.base_directory=(dir) + `git config --global vivo.release.basedirectory #{dir}` + end + + def self.confirm_base_directory(path) + expanded = File.expand_path(path) + vivo_git = File.expand_path("VIVO/.git", expanded) + vitro_git = File.expand_path("Vitro/.git", expanded) + raise BadState.new("#{expanded} is not a directory") unless File.directory?(expanded) + raise BadState.new("#{expanded} doesn't contain a VIVO repository") unless File.directory?(vivo_git) + raise BadState.new("#{expanded} doesn't contain a Vitro repository") unless File.directory?(vitro_git) + expanded + end + + + def self.username + `git config --get --global user.name`.strip + end + + def self.username=(name) + `git config --global user.name #{name}` + end + + def self.confirm_username(name) + # any string will do. + name + end + + + def self.email + `git config --get --global user.email`.strip + end + + def self.email=(address) + `git config --global user.email #{address}` + end + + def self.confirm_email(address) + # any string will do. + address + end + + + def self.release_label + `git config --get --global vivo.releaselabel`.strip + end + + def self.release_label=(label) + `git config --global vivo.releaselabel #{label}` + end + + def self.confirm_release_label(label) + raise BadState.new("Incorrect format for release label - '#{label}'") unless label =~ /^\d\.\d(\.\d)?$/ + label + end + + + def self.candidate_label + `git config --get --global vivo.candidatelabel`.strip + end + + def self.candidate_label=(label) + `git config --global vivo.candidatelabel #{label}` + end + + def self.confirm_candidate_label(label) + raise BadState.new("Incorrect format for candidate label - '#{label}'") unless label =~ /^(rc\d+|tc\d+|final)$/ + label + end + + # + # Values derived from the settings. + # + + # The name of the maintenance branch. Looks like "maint-rel-4.2" even for releases like "4.2.1" + # Test candidates for major releases are built on the develop branch. + def self.branch_name + if is_test_candidate?() + "develop" + else + release_label = Settings.confirm_release_label(Settings.release_label) + major_release = release_label[0..2] + "maint-rel-#{major_release}" + end + end + + # The name of the Git tag. Looks like "rel-1.9-tc2" or "rel-1.9" (for final) + def self.tag_name + release_label = Settings.confirm_release_label(Settings.release_label) + label = Settings.confirm_candidate_label(Settings.candidate_label) + suffix = label == "final" ? "" : "-#{label}" + "rel-#{release_label}#{suffix}" + end + + # The message for the Git tag. Looks like "Release 1.9 rc5 tag" + def self.tag_message + release_label = Settings.confirm_release_label(Settings.release_label) + candidate_label = Settings.confirm_candidate_label(Settings.candidate_label) + "Release #{release_label} #{candidate_label} tag" + end + + # Where is the local VIVO repository? Looks like "/Users/jeb228/git/VIVO" + def self.vivo_path + base_directory = Settings.confirm_base_directory(Settings.base_directory) + File.expand_path("VIVO", base_directory) + end + + # Where is the local Vitro repository? Looks like "/Users/jeb228/git/Vitro" + def self.vitro_path + base_directory = Settings.confirm_base_directory(Settings.base_directory) + File.expand_path("Vitro", base_directory) + end + + # Where will the distribution files be created? Looks like "/Users/jeb228/git/release_4.9/tc5/vivo-rel-4.9-tc5" + def self.export_dir + base_directory = Settings.confirm_base_directory(Settings.base_directory) + release_label = Settings.confirm_release_label(Settings.release_label) + candidate_label = Settings.confirm_candidate_label(Settings.candidate_label) + tag_name = Settings.tag_name + File.expand_path("release_#{release_label}/#{candidate_label}/vivo-#{tag_name}", base_directory) + end + + # Where to store the file for revision info in VIVO + def self.vivo_revision_info_path + File.expand_path("revisionInfo", Settings.export_dir) + end + + # Where to store the file for revision info in VIVO + def self.vitro_revision_info_path + File.expand_path("vitro-core/revisionInfo", Settings.export_dir) + end + + # Looks like "vivo-rel-4.9-tc3" or "vivo-rel-4.9" for final + def self.vivo_distribution_filename + "vivo-#{Settings.tag_name}" + end + + # Looks like "vitro-rel-4.9-tc3" or "vitro-rel-4.9" for final + def self.vitro_distribution_filename + "vitro-#{Settings.tag_name}" + end +end + +# +# ------------------------------------------------------------------------------------ +# Confirmation methods. +# ------------------------------------------------------------------------------------ +# + +def is_test_candidate?() + Settings.confirm_candidate_label(Settings.candidate_label)[0..0] == 't' +end + +def is_final_release?() + Settings.confirm_candidate_label(Settings.candidate_label) == 'final' +end + +# +# ------------------------------------------------------------------------------------ +# General-purpose methods. +# ------------------------------------------------------------------------------------ +# + +def prompt(p) + print("#{p} ") + gets.strip +end + +def echo_command(c) + puts ">>>>>> #{c}" + `#{c}` +end + +def get_permission_and_go(p) + puts + yn = prompt("#{p} (y/n)") + if yn.downcase == 'y' + puts + yield + puts + else + puts + puts "OK - forget it." + puts + end +end + +def approve_and_execute(cmds, prompt="") + if prompt.empty? + puts "Execute these commands?" + else + puts "Execute these commands? (#{prompt})" + end + + puts ">>>>> #{cmds.join("\n>>>>> ")}" + yn = prompt "(y/n)" + raise BadState.new("OK") if (yn.downcase != 'y') + + cmds.each do |cmd| + puts ">>>>> #{cmd}" + puts `#{cmd}` + raise BadState.new("Command failed: code #{$?.exitstatus}") unless $?.success? + end + puts +end + +def branch_exists?(dir, branch) + Dir.chdir(dir) do |path| + ! `git branch --list #{branch}`.strip.empty? + end +end + +def tag_exists?(dir, tag) + Dir.chdir(dir) do |path| + !`git tag --list #{tag}`.strip.empty? + end +end +