Compare commits

..

7 commits

Author SHA1 Message Date
cac6c55923 Added code for deleting individuals 2021-02-18 19:34:27 +01:00
Andrew Woods
eb949919b5
Sprint i18n with main (#209)
* Layer uqam updates onto master (minus trailing whitespace)

* Update RDFServiceFactorySingle.java

* Sprint i18n whitespace (#143)

* Removed extraneous whitespace
   - modified:   api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/BaseEditElementVTwo.java

* move RootUserPolicy.java from VIVO to Vitro repo.

* Remove blank line

* Fixed indentations

* Update whitespace for: TemplateProcessingHelper.java

* Update whitespace for: RDFServiceModel.java

* Removed extraneous whitespaces.

* Tagging UQAM Comments with following tags

-Add-Feature
-Optimization
-Linguistic-Management
-Bug-Correction

* Resolve compilation failures in Vitro tests

* Remove whitespace changes from SelectListGeneratorVTwo.java

* Add null check on field values of RDF Form (#158)

Resolves: https://jira.lyrasis.org/browse/VIVO-1800

Co-authored-by: Andrew Woods <awoods@duraspace.org>

* Fix incorrect tool-tip in language selection dropdown (#156)

Resolves: https://jira.lyrasis.org/browse/VIVO-1783

Co-authored-by: Andrew Woods <awoods@duraspace.org>

* Sprint i18n/lang filtering model (#159)

* Add language-aware graph filtering instead of layering on additional RDFService

Resolves: https://jira.lyrasis.org/browse/VIVO-1771

* Remove hardcoded link label (#161)

Resolves: https://jira.lyrasis.org/browse/VIVO-1779

* Enable filtering of non-enabled i18n language files from being loaded into triple store (#160)

Define name of available language listing file (found in Vitro-languages)
Update RDFFilesLoader method interfaces to include ServletContext

Part of resolution to: https://jira.lyrasis.org/browse/VIVO-1836

Co-authored-by: Andrew Woods <awoods@duraspace.org>

* Add i18n version of Edit page title (#157)

Related to: https://jira.lyrasis.org/browse/VIVO-1779

Co-authored-by: Andrew Woods <awoods@duraspace.org>

* Changing ontology extensions for n3 & assigning a base IRI to each (#163)

ontology

Co-authored-by: michelheon <heon@videotorn.ca>
Co-authored-by: Andrew Woods <awoods@duraspace.org>

https://jira.lyrasis.org/browse/VIVO-1862

* Update sprint-i18n with master branch (#166)

* Make data property richtext editor option selectable from UI

* [VIVO-1755] - Better error handling when reasoner disabled (#137)

* Better error handling when reasoner disabled

* Change reasoner error log message to debug

* Extend reasoner status error handling

* Improve reasoner error log message and extend to JenaAdminActions

* Bump up log level for admin action to 'warn' and edit admin panel error message

* Change Model writer lang from "N3-PP" to "N3" (#149)

Resolves: https://jira.lyrasis.org/browse/VIVO-1761

Co-authored-by: Andrew Woods <awoods@duraspace.org>

* [VIVO-1851] - Add 'remove' option to named graph management page (#162)

* Add 'remove' option to named graph management page

Resolves: https://jira.lyrasis.org/browse/VIVO-1851

* [VIVO-1872] - Add download option to SPARQL Query page (#164)

* Add download option to SPARQL Query page

* Set SPARQL query results content type even if downloading

* Address pull request comments

Co-authored-by: gneissone <mbgross@wustl.edu>
Co-authored-by: Ralph O'Flinn <roflinn@users.noreply.github.com>
Co-authored-by: Andrew Woods <awoods@duraspace.org>

* [VIVO-1839] - Use language name for selector instead of flags (#165)

* Use language name for selector instead of flags
* Add country name to language selector
* Increase min-width of language dropdown
* Update data tree comment in languageSelector.ftl
* Min-width for language dropdown
* Language dropdown css adjustment
* Capitalize locale label
* Indent on languageSelector.ftl

Resolves: https://jira.lyrasis.org/browse/VIVO-1839

* Adds internationalization to the admin/sparql-query page (#167)

* Adds internationalization to the admin/sparql-query page

Partial resolution of: https://jira.lyrasis.org/browse/VIVO-1873

* Add i18n for 'save query result'

Related to: https://jira.lyrasis.org/browse/VIVO-1873

* code review

Co-authored-by: Andrew Woods <awoods@duraspace.org>

* removed redundat files which are now available via Vitro- and VIVO-languages

* Making UQAM-optimization aware of https://

* Add parent reference to installer/pom.xml (#174)

Resolves: https://jira.lyrasis.org/browse/VIVO-1903

Co-authored-by: Andrew Woods <awoods@duraspace.org>

* Revert non-function RDF changes (#177)

Related to: https://jira.lyrasis.org/browse/VIVO-1905

Co-authored-by: Andrew Woods <awoods@duraspace.org>

* Ensure 'other' in Individual->Teaching->advisees->type is translated

Partial resolution to: https://jira.lyrasis.org/browse/VIVO-1881

* Re-add logic from commit 7420957

* [VIVO-1812] use i18n translation for validation messages (#179)

* replace constants with i18n text in BasicValidationVTwo
* use constants for i18n template key

Partial resolution of: https://jira.lyrasis.org/browse/VIVO-1812

* added js_string at i18n strings to handle quotes properly, ticket vivo-1842 (#180)

Partial resolution for: https://jira.lyrasis.org/browse/VIVO-1842

* [VIVO-1870] simplify and concat translation for browse by vclass (#182)

* simplify and concat translation for browse by vclass

Partial resolution of: https://jira.lyrasis.org/browse/VIVO-1870

* [VIVO-1900] i18n: added empty check for getCountry, fixing bug with spanish label (es) (#181)

* added empty check for getCountry, fixing bug with spanish label (es), ticket vivo-1900

Partial resolution to: https://jira.lyrasis.org/browse/VIVO-1900

* [VIVO 1870] update i18n key to JavaScript mapping (#183)

* update menupage-script i18n key to JavaScript mapping

Follow-on to resolution of: https://jira.lyrasis.org/browse/VIVO-1870

* [VIVO-1837] get i18n bundle from WebappDaoFactoryConfig preferred locales (#178)

* apply i18n text to VClassDaoJena.getLabelForClass
* expose i18n bundle through webapp dao factory interface
* use whole messages for i18n
* if request available use request bundle else use context bundle
* clear cache when context theme directory changes
* make getOverridingLocale from context private
* select locale based on preferred locale from webapp dao factory
* use first preferred local even when no selectable locales available on context
* build default preferred locales from default preferred languages

Resolves: https://jira.lyrasis.org/browse/VIVO-1837

* Ensure that "available langs" include base langs (#185)

Resolves: https://jira.lyrasis.org/browse/VIVO-1922

Co-authored-by: Andrew Woods <awoods@duraspace.org>

* Ensure I18nStub is initialized before pertinent tests (#186)

Resolves: https://jira.lyrasis.org/browse/VIVO-1923

Co-authored-by: Andrew Woods <awoods@duraspace.org>

* add additional null checks to ensure context is ready for theme change (#187)

* [VIVO-1915] i18n - Adding a label with language tag through the "new" manageLabelsForindividualAddForm.ftl does not take the setting for language tag (#184)

* Fixed bug when addng a label with language tag through managLabelsForindividualAddForm, re ticket VIVO-1915

* removed the language select for managing multi language labels, ticket vivo-1915

* readded the fix for language selection because of the fr-CA version of the manageLabelsForIndividualftl, ticket vivo-1915

* removed earlier fix, removed comments, modified ManageLabelGenrator, ticket vivo-1915

Partial resolution to: https://jira.lyrasis.org/browse/VIVO-1915

* - replaced hard coded "or"s with i18n().or

* [VIVO-1925] i18n: Editing labels results in new label (#188)

* fixed bug: Editing language labels results in new label, ticket vivo-1925

Resolves: https://jira.lyrasis.org/browse/VIVO-1925

* Enable lang selection without need for 'available-langs.properties' (#169)

* Enable lang selection without need for 'available-langs.properties'
Co-authored-by: Andrew Woods <awoods@duraspace.org>

* Reduce number of times QuerySolutions are looped in LanguageFilteringRDFService (#194)

- No functional change in this update

Resolves: https://jira.lyrasis.org/browse/VIVO-1931

Co-authored-by: Andrew Woods <awoods@duraspace.org>

* Prevent 'ProcessRdfForm.parseN3ToRDF' from using null linguisticContext (#197)

Resolves: https://jira.lyrasis.org/browse/VIVO-1944

Co-authored-by: Andrew Woods <awoods@duraspace.org>

* [Vivo 1918] i18n: Reload firsttime files on start-up if changed (#195)

Co-authored-by: Andrew Woods <awoods@lyrasis.org>

* [VIVO-1936] i18n: updated the language comment in runtime.properties

* ftl function to capitalize group name affording override

* Further i18n for BasicValidationVTwo.java

* Fixed DeletePropertyController.java - getting localname of property properly (#200)

* Fixed DeletePropertyController.java - getting localname of property properly

Resolves: https://jira.lyrasis.org/browse/VIVO-1816

* Removed hardcoded time units by properties calls in dateTimeWithPrecision.ftl

* Use i18n values for date time form (#204)

Resolves: https://jira.lyrasis.org/browse/VIVO-1953

* VIVO-1929: patch authorizing create individual form (#206)

* patch authorizing create individual form

Resolves: https://jira.lyrasis.org/browse/VIVO-1929

* Issue/vivo 1947 (#205)

* Make data property richtext editor option selectable from UI
* Better error handling when reasoner disabled
* Change reasoner error log message to debug
* Extend reasoner status error handling
* Improve reasoner error log message and extend to JenaAdminActions
* Bump up log level for admin action to 'warn' and edit admin panel error message
* Change Model writer lang from "N3-PP" to "N3" (#149)
* Prevent ontology editor and N3 editing from deleting property values in languages other than the one associated with the editing request. [https://jira.lyrasis.org/browse/VIVO-1947]

Resolves: https://jira.lyrasis.org/browse/VIVO-1947

Co-authored-by: gneissone <mbgross@wustl.edu>
Co-authored-by: Ralph O'Flinn <roflinn@users.noreply.github.com>
Co-authored-by: Andrew Woods <awoods@lyrasis.org>
Co-authored-by: Andrew Woods <awoods@duraspace.org>

* Remove comments

Co-authored-by: Andrew Woods <awoods@duraspace.org>
Co-authored-by: Nicolas D <46490666+nicalico@users.noreply.github.com>
Co-authored-by: VIVO UQAM <62542918+UQAM-VIVO@users.noreply.github.com>
Co-authored-by: Matthias Luehr <luehr@hs-mittweida.de>
Co-authored-by: michelheonuqam <heon.michel@uqam.ca>
Co-authored-by: Brian Lowe <brianjlowe@gmail.com>
Co-authored-by: j-dornbusch <joachim.dornbusch@ehess.fr>
Co-authored-by: Michel Heon <heon@videotron.ca>
Co-authored-by: gneissone <mbgross@wustl.edu>
Co-authored-by: Ralph O'Flinn <roflinn@users.noreply.github.com>
Co-authored-by: dofeldsc <dofeldsc@uos.de>
Co-authored-by: root <root@vivo-development.hs-mittweida.de>
Co-authored-by: gneissone <mbgross@unavco.org>
Co-authored-by: William Welling <wwelling@library.tamu.edu>
Co-authored-by: Kampe <Benjamin.Kampe@tib.eu>
Co-authored-by: Gross, Benjamin <benjamin.gross@clarivate.com>
Co-authored-by: matthiasluehr <60263380+matthiasluehr@users.noreply.github.com>
Co-authored-by: nicolasdickner <dickner.nicolas@uqam.ca>
2021-02-10 11:04:01 -06:00
William Welling
28188e9719
VIVO-1960: GitHub Actions Continued (#211)
* run tests during CI build
* build CI use java 11

Follow-on to: https://jira.lyrasis.org/browse/VIVO-1960
2021-02-09 17:45:53 -05:00
William Welling
06d9f5d333
VIVO-1960: GitHub Build Action (#210)
* add build workflow
* remove travis
* update readme badge

Partially resolves: https://jira.lyrasis.org/browse/VIVO-1960
2021-02-09 15:01:47 -05:00
Andrew Woods
8b9a7484b3
Create vivo/home on application start-up (#192)
* Create vivo/home on application start-up

- Add logic for untarring vivo-home

Related to: https://jira.lyrasis.org/browse/VIVO-1443

* Require runtime.properties and applicationSetup.n3 be in 'config/' dir

Related to: https://jira.lyrasis.org/browse/VIVO-1443

* Support loading config files with or without 'default' prefix
* Prioritize without the prefix

Related to: https://jira.lyrasis.org/browse/VIVO-1443

* Add leading slash to location of vivo-home.tar resource path
* This allows for deployment in both Tomcat and Jetty

Related to: https://jira.lyrasis.org/browse/VIVO-1443

* Ensure VIVO_HOME is populated whether it is empty or not

Related to: https://jira.lyrasis.org/browse/VIVO-1443

* Require common properties to be in JNDI

Properties include:
- vitro/home
- vitro/appName
- vitro/rootUserAddress
- vitro/defaultNamespace

Related to: https://jira.lyrasis.org/browse/VIVO-1443

* VIVO-1443: non destructive vivo home untarring (#2)

* Upgrade Jena version to 3.16.0 (#196)

Related to: https://jira.lyrasis.org/browse/VIVO-1943

* remove example-settings.xml
* update home directory untar non-destructive
* checksum digest to retain modified files
* compare checksum from digest with existing file
* overwrite files that have not changed
* add command to manually generate checksum digest
* simplify parsing checksum digest using pattern

Co-authored-by: Andrew Woods <awoods@lyrasis.org>
Co-authored-by: Andrew Woods <awoods@duraspace.org>

* not overwrite existing file if same as tar entry (#3)

* Upgrade Jena version to 3.16.0 (#196)

Related to: https://jira.lyrasis.org/browse/VIVO-1943

* remove example-settings.xml
* update home directory untar non-destructive
* checksum digest to retain modified files
* compare checksum from digest with existing file
* overwrite files that have not changed
* add command to manually generate checksum digest
* simplify parsing checksum digest using pattern
* do not overwrite file if same as already exists

Co-authored-by: Andrew Woods <awoods@lyrasis.org>
Co-authored-by: Andrew Woods <awoods@duraspace.org>

* Update log messages for clarity

Co-authored-by: Andrew Woods <awoods@duraspace.org>
Co-authored-by: William Welling <wwelling@library.tamu.edu>
Co-authored-by: Gross, Benjamin <benjamin.gross@clarivate.com>
2021-02-05 10:58:37 -06:00
Andrew Woods
936305be2a
Upgrade Jena version to 3.16.0 (#196)
Related to: https://jira.lyrasis.org/browse/VIVO-1943

Co-authored-by: Andrew Woods <awoods@duraspace.org>
2020-12-03 07:56:29 -06:00
Ben
119413413a
Adjust SPARQL node logic to add datatypes to literals only if lacking a language tag (#175) 2020-07-21 17:01:39 +03:00
224 changed files with 3432 additions and 3494 deletions

28
.github/workflows/build.yml vendored Normal file
View file

@ -0,0 +1,28 @@
name: Build
on: [ push, pull_request, workflow_dispatch ]
jobs:
build:
runs-on: ubuntu-latest
env:
MAVEN_OPTS: -Xmx1024M
steps:
- uses: actions/checkout@v2
- name: Maven Cache
uses: actions/cache@v2
with:
path: ~/.m2/repository
key: ${{ runner.os }}-cache-m2-${{ hashFiles('**/pom.xml') }}
restore-keys: ${{ runner.os }}-cache-m2-
- name: Setup Java
uses: actions/setup-java@v1
with:
java-version: 11
- name: Maven Build
run: mvn clean install

View file

@ -1,22 +0,0 @@
language: java
dist: trusty
sudo: false
jdk:
- openjdk8
- oraclejdk8
env:
# Give Maven 1GB of memory to work with
- MAVEN_OPTS=-Xmx1024M
cache:
directories:
- .autoconf
- $HOME/.m2
install:
- "echo 'Skipping install stage, dependencies will be downloaded during build and test stages.'"
script:
- "mvn clean package -Dmaven.test.skip=false"

View file

@ -1,6 +1,6 @@
# What is Vitro? # What is Vitro?
[![Build Status](https://travis-ci.org/vivo-project/Vitro.png?branch=develop)](https://travis-ci.org/vivo-project/Vitro) [![Build](https://github.com/vivo-project/Vitro/workflows/Build/badge.svg)](https://github.com/vivo-project/Vitro/actions?query=workflow%3ABuild)
Vitro is a general-purpose web-based ontology and instance editor with customizable public browsing. Vitro is a general-purpose web-based ontology and instance editor with customizable public browsing.

View file

@ -24,6 +24,7 @@ import edu.cornell.mannlib.vitro.webapp.utils.jena.criticalsection.LockableModel
*/ */
public class ApplicationSetup implements ServletContextListener { public class ApplicationSetup implements ServletContextListener {
private static final String APPLICATION_SETUP_PATH = "config/applicationSetup.n3"; private static final String APPLICATION_SETUP_PATH = "config/applicationSetup.n3";
private static final String APPLICATION_SETUP_DEFAULT_PATH = "config/default.applicationSetup.n3";
private ServletContext ctx; private ServletContext ctx;
private StartupStatus ss; private StartupStatus ss;
@ -45,6 +46,8 @@ public class ApplicationSetup implements ServletContextListener {
this.vitroHomeDir = VitroHomeDirectory.find(ctx); this.vitroHomeDir = VitroHomeDirectory.find(ctx);
ss.info(this, vitroHomeDir.getDiscoveryMessage()); ss.info(this, vitroHomeDir.getDiscoveryMessage());
this.vitroHomeDir.populate();
locateApplicationConfigFile(); locateApplicationConfigFile();
loadApplicationConfigFile(); loadApplicationConfigFile();
createConfigurationBeanLoader(); createConfigurationBeanLoader();
@ -62,11 +65,20 @@ public class ApplicationSetup implements ServletContextListener {
private void locateApplicationConfigFile() { private void locateApplicationConfigFile() {
Path path = this.vitroHomeDir.getPath().resolve(APPLICATION_SETUP_PATH); Path path = this.vitroHomeDir.getPath().resolve(APPLICATION_SETUP_PATH);
if (!Files.exists(path) || !Files.isReadable(path)) {
path = this.vitroHomeDir.getPath().resolve(APPLICATION_SETUP_DEFAULT_PATH);
}
if (!Files.exists(path)) { if (!Files.exists(path)) {
throw new IllegalStateException("'" + path + "' does not exist."); throw new IllegalStateException("Neither '" + APPLICATION_SETUP_PATH + "' nor '" +
APPLICATION_SETUP_DEFAULT_PATH + "' were found in " +
this.vitroHomeDir.getPath());
} }
if (!Files.isReadable(path)) { if (!Files.isReadable(path)) {
throw new IllegalStateException("Can't read '" + path + "'"); throw new IllegalStateException("No readable '" + APPLICATION_SETUP_PATH + "' nor '" +
APPLICATION_SETUP_DEFAULT_PATH + "' files were found in " +
this.vitroHomeDir.getPath());
} }
this.configFile = path; this.configFile = path;
} }

View file

@ -4,25 +4,46 @@ package edu.cornell.mannlib.vitro.webapp.application;
import static edu.cornell.mannlib.vitro.webapp.application.BuildProperties.WEBAPP_PATH_BUILD_PROPERTIES; import static edu.cornell.mannlib.vitro.webapp.application.BuildProperties.WEBAPP_PATH_BUILD_PROPERTIES;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import javax.naming.InitialContext;
import javax.servlet.ServletContext; import javax.servlet.ServletContext;
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vitro.webapp.config.ContextProperties;
/** /**
* Encapsulates some of the info relating to the Vitro home directory. * Encapsulates some of the info relating to and initializes the Vitro home directory.
*/ */
public class VitroHomeDirectory { public class VitroHomeDirectory {
private static final Log log = LogFactory.getLog(VitroHomeDirectory.class); private static final Log log = LogFactory.getLog(VitroHomeDirectory.class);
private static final String DIGEST_FILE_NAME = "digest.md5";
private static final Pattern CHECKSUM_PATTERN = Pattern.compile("^[a-f0-9]{32} \\*.+$");
public static VitroHomeDirectory find(ServletContext ctx) { public static VitroHomeDirectory find(ServletContext ctx) {
HomeDirectoryFinder finder = new HomeDirectoryFinder(ctx); HomeDirectoryFinder finder = new HomeDirectoryFinder(ctx);
return new VitroHomeDirectory(ctx, finder.getPath(), return new VitroHomeDirectory(ctx, finder.getPath(),
@ -52,6 +73,219 @@ public class VitroHomeDirectory {
return discoveryMessage; return discoveryMessage;
} }
/**
* Populates VIVO home directory with files required to run.
*
* NOTE: Will not overwrite any modified files on redeploy.
*/
public void populate() {
File vhdDir = getPath().toFile();
if (!vhdDir.isDirectory() || vhdDir.list() == null) {
throw new RuntimeException("Application home dir is not a directory! " + vhdDir);
}
Map<String, String> digest = untar(vhdDir);
writeDigest(digest);
}
/**
* A non-destructive untar process that returns checksum digest of tarred files.
*
* Checksum digest can be manually created with the following command.
*
* `find /vivo/home -type f | cut -c3- | grep -E '^bin/|^config/|^rdf/' | xargs md5sum > /vivo/home/digest.md5`
*
* @param destination VIVO home directory
* @return digest of each files checksum
*/
private Map<String, String> untar(File destination) {
log.info("Syncing VIVO home at: " + destination.getPath());
Map<String, String> digest = new HashMap<>();
Map<String, String> storedDigest = loadDigest();
TarArchiveEntry tarEntry;
try (
InputStream homeDirTar = getHomeDirTar();
TarArchiveInputStream tarInput = new TarArchiveInputStream(homeDirTar);
) {
while ((tarEntry = tarInput.getNextTarEntry()) != null) {
// Use the example configurations
String outFilename = tarEntry.getName().replace("example.", "");
File outFile = new File(destination, outFilename);
// Is the entry a directory?
if (tarEntry.isDirectory()) {
if (!outFile.exists()) {
outFile.mkdirs();
}
} else {
// Entry is a File
boolean write = true;
// reading bytes into memory to avoid having to unreliably reset stream
byte[] bytes = IOUtils.toByteArray(tarInput);
String newFileChecksum = checksum(bytes);
digest.put(outFilename, newFileChecksum);
// if file already exists and stored digest contains the file,
// check to determine if it has changed
if (outFile.exists() && storedDigest.containsKey(outFilename)) {
String existingFileChecksum = checksum(outFile);
// if file has not changed in home and is not the same as new file, overwrite
write = storedDigest.get(outFilename).equals(existingFileChecksum)
&& !existingFileChecksum.equals(newFileChecksum);
}
if (write) {
outFile.getParentFile().mkdirs();
try (
InputStream is = new ByteArrayInputStream(bytes);
FileOutputStream fos = new FileOutputStream(outFile);
) {
IOUtils.copy(is, fos);
log.info(outFile.getAbsolutePath() + " source has changed and has not been "
+ "edited in home, updated file has been copied to home directory.");
}
} else {
log.debug(outFile.getAbsolutePath() + " has been preserved.");
}
}
}
} catch (IOException | NoSuchAlgorithmException e) {
throw new RuntimeException("Error creating home directory!", e);
}
return digest;
}
/**
* Load checksum digest of VIVO home directory.
*
* @return checksum digest
*/
private Map<String, String> loadDigest() {
File storedDigest = new File(getPath().toFile(), DIGEST_FILE_NAME);
if (storedDigest.exists() && storedDigest.isFile()) {
log.info("Reading VIVO home digest: " + storedDigest.getPath());
try {
return FileUtils
.readLines(storedDigest, StandardCharsets.UTF_8)
.stream()
.filter(CHECKSUM_PATTERN.asPredicate())
.map(this::split)
.collect(Collectors.toMap(this::checksumFile, this::checksumValue));
} catch (IOException e) {
throw new RuntimeException("Error reading VIVO home checksum digest!", e);
}
}
log.info("VIVO home digest not found: " + storedDigest.getPath());
return new HashMap<>();
}
/**
* Write VIVO home checksum digest following md5 format; `<checksum> *<file>`.
*
* @param digest checksum digest to write
*/
private void writeDigest(Map<String, String> digest) {
File storedDigest = new File(getPath().toFile(), DIGEST_FILE_NAME);
try (
FileOutputStream fos = new FileOutputStream(storedDigest);
OutputStreamWriter osw = new OutputStreamWriter(fos);
) {
for (Map.Entry<String, String> entry : digest.entrySet()) {
String filename = entry.getKey();
String checksum = entry.getValue();
osw.write(String.format("%s *%s\n", checksum, filename));
}
} catch (IOException e) {
throw new RuntimeException("Error writing home directory checksum digest!", e);
}
log.info("VIVO home digest created: " + storedDigest.getPath());
}
/**
* Split checksum.
*
* @param checksum checksum delimited by space and asterisks `<checksum> *<file>`
* @return split checksum
*/
private String[] split(String checksum) {
return checksum.split("\\s+");
}
/**
* Get value from split checksum.
*
* @param checksum split checksum
* @return checksum value
*/
private String checksumValue(String[] checksum) {
return checksum[0];
}
/**
* Return file from split checksum.
*
* @param checksum split checksum
* @return filename
*/
private String checksumFile(String[] checksum) {
return checksum[1].substring(1);
}
/**
* Get md5 checksum from file.
*
* @param file file
* @return md5 checksum as string
* @throws IOException
* @throws NoSuchAlgorithmException
*/
private String checksum(File file) throws IOException, NoSuchAlgorithmException {
return checksum(FileUtils.readFileToByteArray(file));
}
/**
* Get md5 checksum from bytes.
*
* @param bytes bytes from file
* @return md5 checksum as string
* @throws NoSuchAlgorithmException
*/
private String checksum(byte[] bytes) throws NoSuchAlgorithmException {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(bytes);
// bytes to hex
StringBuilder result = new StringBuilder();
for (byte b : md.digest()) {
result.append(String.format("%02x", b));
}
return result.toString();
}
/**
* Get prepacked VIVO home tar file as input stream.
*
* @return input stream of VIVO home tar file
*/
private InputStream getHomeDirTar() {
String tarLocation = "/WEB-INF/resources/home-files/vivo-home.tar";
InputStream tar = ctx.getResourceAsStream(tarLocation);
if (tar == null) {
log.error("Application home tar not found in: " + tarLocation);
throw new RuntimeException("Application home tar not found in: " + tarLocation);
}
return tar;
}
/** /**
* Find something that specifies the location of the Vitro home directory. * Find something that specifies the location of the Vitro home directory.
* Look in the JDNI environment, the system properties, and the * Look in the JDNI environment, the system properties, and the
@ -92,24 +326,13 @@ public class VitroHomeDirectory {
} }
public void getVhdFromJndi() { public void getVhdFromJndi() {
try { String vhdPath = ContextProperties.findJndiProperty(VHD_JNDI_PATH);
String vhdPath = (String) new InitialContext() log.debug("'" + VHD_JNDI_PATH + "' as specified by JNDI: " + vhdPath);
.lookup(VHD_JNDI_PATH);
if (vhdPath == null) {
log.debug("Didn't find a JNDI value at '" + VHD_JNDI_PATH
+ "'.");
} else {
log.debug("'" + VHD_JNDI_PATH + "' as specified by JNDI: "
+ vhdPath);
String message = String.format( String message = String.format(
"JNDI environment '%s' was set to '%s'", "JNDI environment '%s' was set to '%s'",
VHD_JNDI_PATH, vhdPath); VHD_JNDI_PATH, vhdPath);
foundLocations.add(new Found(Paths.get(vhdPath), message)); foundLocations.add(new Found(Paths.get(vhdPath), message));
} }
} catch (Exception e) {
log.debug("JNDI lookup failed. " + e);
}
}
private void getVhdFromSystemProperties() { private void getVhdFromSystemProperties() {
String vhdPath = System.getProperty(VHD_SYSTEM_PROPERTY); String vhdPath = System.getProperty(VHD_SYSTEM_PROPERTY);

View file

@ -37,7 +37,14 @@ public class RootUserPolicy implements PolicyIface {
private static final Log log = LogFactory.getLog(RootUserPolicy.class); private static final Log log = LogFactory.getLog(RootUserPolicy.class);
private static final String PROPERTY_ROOT_USER_EMAIL = "rootUser.emailAddress"; private static final String PROPERTY_ROOT_USER_EMAIL = "rootUser.emailAddress";
/*
* UQAM Add-Feature For parameterization of rootUser
*/
private static final String PROPERTY_ROOT_USER_PASSWORD = "rootUser.password";
private static final String PROPERTY_ROOT_USER_PASSWORD_CHANGE_REQUIRED = "rootUser.passwordChangeRequired";
private static final String ROOT_USER_INITIAL_PASSWORD = "rootPassword"; private static final String ROOT_USER_INITIAL_PASSWORD = "rootPassword";
private static final String ROOT_USER_INITIAL_PASSWORD_CHANGE_REQUIRED = "true";
/** /**
* This is the entire policy. If you are a root user, you are authorized. * This is the entire policy. If you are a root user, you are authorized.
@ -150,10 +157,12 @@ public class RootUserPolicy implements PolicyIface {
ua.setEmailAddress(configuredRootUser); ua.setEmailAddress(configuredRootUser);
ua.setFirstName("root"); ua.setFirstName("root");
ua.setLastName("user"); ua.setLastName("user");
// UQAM Add-Feature using getRootPasswordFromConfig()
ua.setArgon2Password(Authenticator.applyArgon2iEncoding( ua.setArgon2Password(Authenticator.applyArgon2iEncoding(
ROOT_USER_INITIAL_PASSWORD)); getRootPasswordFromConfig()));
ua.setMd5Password(""); ua.setMd5Password("");
ua.setPasswordChangeRequired(true); // UQAM Add-Feature using getRootPasswdChangeRequiredFromConfig()
ua.setPasswordChangeRequired(getRootPasswdChangeRequiredFromConfig().booleanValue());
ua.setStatus(Status.ACTIVE); ua.setStatus(Status.ACTIVE);
ua.setRootUser(true); ua.setRootUser(true);
@ -191,7 +200,31 @@ public class RootUserPolicy implements PolicyIface {
ss.warning(this, "For security, " ss.warning(this, "For security, "
+ "it is best to delete unneeded root user accounts."); + "it is best to delete unneeded root user accounts.");
} }
/*
* UQAM Add-Feature
* Add for getting rootUser.password property value from runtime.properties
*/
private String getRootPasswordFromConfig() {
String passwd = ConfigurationProperties.getBean(ctx).getProperty(
PROPERTY_ROOT_USER_PASSWORD);
if (passwd == null) {
passwd = ROOT_USER_INITIAL_PASSWORD;
}
return passwd;
}
/*
* UQAM Add-Feature
* Add for getting rootUser.passwordChangeRequired property value from runtime.properties
*/
private Boolean getRootPasswdChangeRequiredFromConfig() {
String passwdCR = ConfigurationProperties.getBean(ctx).getProperty(
PROPERTY_ROOT_USER_PASSWORD_CHANGE_REQUIRED);
if (passwdCR == null) {
passwdCR = ROOT_USER_INITIAL_PASSWORD_CHANGE_REQUIRED;
}
return new Boolean(passwdCR);
}
@Override @Override
public void contextDestroyed(ServletContextEvent sce) { public void contextDestroyed(ServletContextEvent sce) {
// Nothing to destroy // Nothing to destroy

View file

@ -20,6 +20,7 @@ public class ApplicationBean {
public final static int VIVO_SEARCHBOX_SIZE = 20; public final static int VIVO_SEARCHBOX_SIZE = 20;
private final static String DEFAULT_APPLICATION_NAME = "Vitro"; private final static String DEFAULT_APPLICATION_NAME = "Vitro";
private final static String DEFAULT_APPLICATION_AVAILABLE_LANGS_FILE = "available-langs";
private final static String DEFAULT_ROOT_LOGOTYPE_IMAGE = ""; private final static String DEFAULT_ROOT_LOGOTYPE_IMAGE = "";
private final static int DEFAULT_ROOT_LOGOTYPE_WIDTH = 0; private final static int DEFAULT_ROOT_LOGOTYPE_WIDTH = 0;
private final static int DEFAULT_ROOT_LOGOTYPE_HEIGHT = 0; private final static int DEFAULT_ROOT_LOGOTYPE_HEIGHT = 0;
@ -33,6 +34,7 @@ public class ApplicationBean {
private boolean initialized = false; private boolean initialized = false;
private String sessionIdStr = null; private String sessionIdStr = null;
private String applicationName = DEFAULT_APPLICATION_NAME; private String applicationName = DEFAULT_APPLICATION_NAME;
private String availableLangsFile = DEFAULT_APPLICATION_AVAILABLE_LANGS_FILE;
private String rootLogotypeImage = DEFAULT_ROOT_LOGOTYPE_IMAGE; private String rootLogotypeImage = DEFAULT_ROOT_LOGOTYPE_IMAGE;
private int rootLogotypeWidth = DEFAULT_ROOT_LOGOTYPE_WIDTH; private int rootLogotypeWidth = DEFAULT_ROOT_LOGOTYPE_WIDTH;
@ -52,6 +54,7 @@ public class ApplicationBean {
output += " initialized from DB: [" + initialized + "]\n"; output += " initialized from DB: [" + initialized + "]\n";
output += " session id: [" + sessionIdStr + "]\n"; output += " session id: [" + sessionIdStr + "]\n";
output += " application name: [" + applicationName + "]\n"; output += " application name: [" + applicationName + "]\n";
output += " available langs file: [" + availableLangsFile + "]\n";
output += " root logotype image: [" + rootLogotypeImage + "]\n"; output += " root logotype image: [" + rootLogotypeImage + "]\n";
output += " root logotype width: [" + rootLogotypeWidth + "]\n"; output += " root logotype width: [" + rootLogotypeWidth + "]\n";
output += " root logotype height: [" + rootLogotypeHeight + "]\n"; output += " root logotype height: [" + rootLogotypeHeight + "]\n";
@ -177,6 +180,10 @@ public class ApplicationBean {
return ""; return "";
} }
public String getAvailableLangsFile() {
return availableLangsFile;
}
/** /**
* Directory to find the images. Subdirectories include css, jsp and site_icons. * Directory to find the images. Subdirectories include css, jsp and site_icons.
* Example: "themes/enhanced/" * Example: "themes/enhanced/"

View file

@ -7,11 +7,17 @@ import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import org.apache.commons.lang3.RandomStringUtils; import edu.cornell.mannlib.vitro.webapp.controller.authenticate.Authenticator;
/** /**
* Information about the account of a user. URI, email, password, etc. * Information about the account of a user. URI, email, password, etc.
* *
* The "password link expires hash" is just a string that is derived from the
* value in the passwordLinkExpires field. It doesn't have to be a hash, and
* there is no need for it to be cryptographic, but it seems embarrassing to
* just send the value as a clear string. There is no real need for security
* here, except that a brute force attack would allow someone to change the
* password on an account that they know has a password change pending.
*/ */
public class UserAccount { public class UserAccount {
public static final int MIN_PASSWORD_LENGTH = 6; public static final int MIN_PASSWORD_LENGTH = 6;
@ -46,7 +52,6 @@ public class UserAccount {
private String md5Password = ""; // Never null. private String md5Password = ""; // Never null.
private String oldPassword = ""; // Never null. private String oldPassword = ""; // Never null.
private long passwordLinkExpires = 0L; // Never negative. private long passwordLinkExpires = 0L; // Never negative.
private String emailKey = "";
private boolean passwordChangeRequired = false; private boolean passwordChangeRequired = false;
private int loginCount = 0; // Never negative. private int loginCount = 0; // Never negative.
@ -128,27 +133,15 @@ public class UserAccount {
return passwordLinkExpires; return passwordLinkExpires;
} }
public String getPasswordLinkExpiresHash() {
return limitStringLength(8, Authenticator.applyArgon2iEncoding(String
.valueOf(passwordLinkExpires)));
}
public void setPasswordLinkExpires(long passwordLinkExpires) { public void setPasswordLinkExpires(long passwordLinkExpires) {
this.passwordLinkExpires = Math.max(0, passwordLinkExpires); this.passwordLinkExpires = Math.max(0, passwordLinkExpires);
} }
public void generateEmailKey() {
boolean useLetters = true;
boolean useNumbers = true;
int length = 64;
emailKey = RandomStringUtils.random(length, useLetters, useNumbers);
}
public void setEmailKey(String emailKey) {
if (emailKey != null) {
this.emailKey = emailKey;
}
}
public String getEmailKey() {
return emailKey;
}
public boolean isPasswordChangeRequired() { public boolean isPasswordChangeRequired() {
return passwordChangeRequired; return passwordChangeRequired;
} }
@ -254,7 +247,6 @@ public class UserAccount {
+ (", oldPassword=" + oldPassword) + (", oldPassword=" + oldPassword)
+ (", argon2password=" + argon2Password) + (", argon2password=" + argon2Password)
+ (", passwordLinkExpires=" + passwordLinkExpires) + (", passwordLinkExpires=" + passwordLinkExpires)
+ (", emailKey =" + emailKey)
+ (", passwordChangeRequired=" + passwordChangeRequired) + (", passwordChangeRequired=" + passwordChangeRequired)
+ (", externalAuthOnly=" + externalAuthOnly) + (", externalAuthOnly=" + externalAuthOnly)
+ (", loginCount=" + loginCount) + (", status=" + status) + (", loginCount=" + loginCount) + (", status=" + status)

View file

@ -32,8 +32,10 @@ public class ConfigurationPropertiesImpl extends ConfigurationProperties {
public ConfigurationPropertiesImpl(InputStream stream, public ConfigurationPropertiesImpl(InputStream stream,
Map<String, String> preemptiveProperties, Map<String, String> preemptiveProperties,
Map<String, String> buildProperties) throws IOException { Map<String, String> buildProperties,
Map<String, String> contextProperties) throws IOException {
Map<String, String> map = new HashMap<>(buildProperties); Map<String, String> map = new HashMap<>(buildProperties);
map.putAll(contextProperties);
Properties props = loadFromPropertiesFile(stream); Properties props = loadFromPropertiesFile(stream);
for (String key: props.stringPropertyNames()) { for (String key: props.stringPropertyNames()) {

View file

@ -49,12 +49,12 @@ public class ConfigurationPropertiesSetup implements ServletContextListener {
/** Name of the file that contains runtime properties. */ /** Name of the file that contains runtime properties. */
private static final String FILE_RUNTIME_PROPERTIES = "runtime.properties"; private static final String FILE_RUNTIME_PROPERTIES = "runtime.properties";
/** Fall-back name of the file that contains runtime properties. */
private static final String FILE_DEFAULT_RUNTIME_PROPERTIES = "default.runtime.properties";
/** Configuration property to store the Vitro home directory */ /** Configuration property to store the Vitro home directory */
private static final String VHD_CONFIGURATION_PROPERTY = "vitro.home"; private static final String VHD_CONFIGURATION_PROPERTY = "vitro.home";
/** Configuration property used to determine if there are runtime.properties files in multiple locations **/
static final String RP_MULTIPLE = "rp.multiple";
@Override @Override
public void contextInitialized(ServletContextEvent sce) { public void contextInitialized(ServletContextEvent sce) {
ServletContext ctx = sce.getServletContext(); ServletContext ctx = sce.getServletContext();
@ -69,18 +69,17 @@ public class ConfigurationPropertiesSetup implements ServletContextListener {
File vitroHomeDirConfig = new File(vitroHomeDir.getPath() File vitroHomeDirConfig = new File(vitroHomeDir.getPath()
.concat(File.separator).concat("config")); .concat(File.separator).concat("config"));
String rpfLocation = findMultipleRuntimePropertiesFiles(
vitroHomeDir, vitroHomeDirConfig);
File runtimePropertiesFile = locateRuntimePropertiesFile( File runtimePropertiesFile = locateRuntimePropertiesFile(
vitroHomeDir, vitroHomeDirConfig, ss); vitroHomeDirConfig, ss);
stream = new FileInputStream(runtimePropertiesFile); stream = new FileInputStream(runtimePropertiesFile);
Map<String, String> preempts = createPreemptiveProperties( Map<String, String> preempts = createPreemptiveProperties(
VHD_CONFIGURATION_PROPERTY, vitroHomeDir, RP_MULTIPLE, rpfLocation); VHD_CONFIGURATION_PROPERTY, vitroHomeDir);
ConfigurationPropertiesImpl bean = new ConfigurationPropertiesImpl( ConfigurationPropertiesImpl bean = new ConfigurationPropertiesImpl(
stream, preempts, new BuildProperties(ctx).getMap()); stream, preempts,
new BuildProperties(ctx).getMap(),
new ContextProperties().getMap());
ConfigurationProperties.setBean(ctx, bean); ConfigurationProperties.setBean(ctx, bean);
ss.info(this, "Loaded " + bean.getPropertyMap().size() ss.info(this, "Loaded " + bean.getPropertyMap().size()
@ -99,54 +98,36 @@ public class ConfigurationPropertiesSetup implements ServletContextListener {
} }
} }
private String findMultipleRuntimePropertiesFiles(File vitroHomeDir, private File locateRuntimePropertiesFile(File vitroHomeDirConfig, StartupStatus ss) {
File vitroHomeDirConfig) {
File rpf = new File(vitroHomeDir, FILE_RUNTIME_PROPERTIES); // First look for the user-customized runtime.properties
File rpfc = new File(vitroHomeDirConfig, FILE_RUNTIME_PROPERTIES); File rpf = new File(vitroHomeDirConfig, FILE_RUNTIME_PROPERTIES);
if (rpf.exists() && !rpfc.exists()) { // Have we found a suitable runtime.properties file?
return "home"; if (!rpf.exists() || !rpf.isFile() || !rpf.canRead()) {
} else if (rpf.exists() && rpfc.exists()) {
return "both"; // If not... look for the default runtime.properties
} else if (rpfc.exists()) { rpf = new File(vitroHomeDirConfig, FILE_DEFAULT_RUNTIME_PROPERTIES);
return "config";
} else {
throw new IllegalStateException("Did not find '"
+ FILE_RUNTIME_PROPERTIES + "' in vitro home directory '"
+ vitroHomeDir + "' or config directory '" + vitroHomeDirConfig + "'");
}
} }
if (!rpf.exists() || !rpf.isFile()) {
private File locateRuntimePropertiesFile(File vitroHomeDir, throw new IllegalStateException("Neither '" + FILE_RUNTIME_PROPERTIES + "' nor '" +
File vitroHomeDirConfig, StartupStatus ss) { FILE_DEFAULT_RUNTIME_PROPERTIES + "' were found in " +
vitroHomeDirConfig.getAbsolutePath());
File rpf = new File(vitroHomeDir, FILE_RUNTIME_PROPERTIES);
File rpfc = new File(vitroHomeDirConfig, FILE_RUNTIME_PROPERTIES);
if (!rpf.exists()) {
rpf = rpfc;
}
if (!rpf.isFile()) {
throw new IllegalStateException("'" + rpf.getPath()
+ "' is not a file.");
} }
if (!rpf.canRead()) { if (!rpf.canRead()) {
throw new IllegalStateException("Cannot read '" + rpf.getPath() throw new IllegalStateException("No readable '" + FILE_RUNTIME_PROPERTIES + "' nor '" +
+ "'."); FILE_DEFAULT_RUNTIME_PROPERTIES + "' files were found in " +
vitroHomeDirConfig.getAbsolutePath());
} }
ss.info(this, "Loading runtime properties from '" + rpf.getPath() + "'"); ss.info(this, "Loading runtime properties from '" + rpf.getPath() + "'");
return rpf; return rpf;
} }
private Map<String, String> createPreemptiveProperties( private Map<String, String> createPreemptiveProperties(
String propertyVitroHome, File vitroHomeDir, String propertyRpfMultiple, String propertyVitroHome, File vitroHomeDir) {
String rpfLocation) {
Map<String, String> map = new HashMap<String, String>(); Map<String, String> map = new HashMap<String, String>();
map.put(propertyVitroHome, vitroHomeDir.getAbsolutePath()); map.put(propertyVitroHome, vitroHomeDir.getAbsolutePath());
map.put(propertyRpfMultiple, rpfLocation);
return map; return map;
} }

View file

@ -48,7 +48,6 @@ public class ConfigurationPropertiesSmokeTests implements
StartupStatus ss = StartupStatus.getBean(ctx); StartupStatus ss = StartupStatus.getBean(ctx);
checkDefaultNamespace(ctx, props, ss); checkDefaultNamespace(ctx, props, ss);
checkMultipleRPFs(ctx, props, ss);
checkLanguages(ctx, props, ss); checkLanguages(ctx, props, ss);
checkEncryptionParameters(props, ss); checkEncryptionParameters(props, ss);
@ -86,32 +85,6 @@ public class ConfigurationPropertiesSmokeTests implements
} }
} }
/**
* Warn if runtime.properties exists in multiple locations
* or is located vivo.home instead of vivo.home/config
*/
private void checkMultipleRPFs(ServletContext ctx,
ConfigurationProperties props, StartupStatus ss) {
String rpfStatus = props.getProperty(ConfigurationPropertiesSetup.RP_MULTIPLE);
if (rpfStatus.equals("both")) {
ss.warning(this,
"Deprecation warning: Files matching the name 'runtime.properties' "
+ "were found in both vivo.home and vivo.home/config. Using "
+ "the file in vivo.home. Future releases may require "
+ "runtime.properties be placed in vivo.home/config.");
}
if (rpfStatus.equals("home")) {
ss.warning(this,
"Deprecation warning: runtime.properties was found in the "
+ "vivo.home directory. The recommended directory for "
+ "runtime.properties is now vivo.home/config. Future releases "
+ "may require runtime.properties be placed in "
+ "vivo.home/config.");
}
}
/** /**
* Warn if we set up the languages incorrectly: * Warn if we set up the languages incorrectly:
* *

View file

@ -0,0 +1,76 @@
/* $This file is distributed under the terms of the license in LICENSE$ */
package edu.cornell.mannlib.vitro.webapp.config;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Obtains and provides the properties from the web application's context.xml
*
* @author awoods
* @since 2020-10-23
*/
public class ContextProperties {
private static final Log log = LogFactory.getLog(ContextProperties.class);
private static final String DEFAULT_NAMESPACE_JNDI_PATH = "java:comp/env/vitro/defaultNamespace";
private static final String ROOT_USER_ADDRESS_JNDI_PATH = "java:comp/env/vitro/rootUserAddress";
private static final String APP_NAME_JNDI_PATH = "java:comp/env/vitro/appName";
private static final String DEFAULT_NAMESPACE_KEY = "Vitro.defaultNamespace";
private static final String ROOT_USER_ADDRESS_KEY = "rootUser.emailAddress";
private static final String APP_NAME_KEY = "app-name";
private final Map<String, String> propertyMap;
public ContextProperties() {
Map<String, String> map = new HashMap<>();
// Find default namespace
map.put(DEFAULT_NAMESPACE_KEY, findJndiProperty(DEFAULT_NAMESPACE_JNDI_PATH));
// Find root user email address
map.put(ROOT_USER_ADDRESS_KEY, findJndiProperty(ROOT_USER_ADDRESS_JNDI_PATH));
// Find application name
map.put(APP_NAME_KEY, findJndiProperty(APP_NAME_JNDI_PATH));
propertyMap = Collections.unmodifiableMap(map);
}
public static String findJndiProperty(String jndiProperty) {
try {
return (String) new InitialContext().lookup(jndiProperty);
} catch (NamingException e) {
log.error("Unable to find name in JNDI: " + jndiProperty, e);
StringBuilder msg = new StringBuilder("\n====================\n");
msg.append("Error loading JNDI property: ");
msg.append(jndiProperty);
msg.append("\n");
msg.append("\tAn application context XML file (named after deployed war file, e.g. vivo.xml) ");
msg.append("must be placed in servlet container.\n");
msg.append("\tFor Tomcat, see documentation for location of file: \n");
msg.append("\t\thttps://tomcat.apache.org/tomcat-9.0-doc/config/context.html#Defining_a_context \n");
msg.append("\tThe common location on the server is: $CATALINA_BASE/conf/[enginename]/[hostname]/ \n");
msg.append("\t\te.g. /var/lib/tomcat9/conf/Catalina/localhost/vivo.xml\n");
msg.append("\tAn example 'context.xml' file is in the META-INF directory of this project.\n");
msg.append("====================\n");
throw new RuntimeException(msg.toString(), e);
}
}
public Map<String, String> getMap() {
return this.propertyMap;
}
}

View file

@ -249,7 +249,6 @@ public class UserAccountsSelector {
user.setMd5Password(ifLiteralPresent(solution, "md5pwd", "")); user.setMd5Password(ifLiteralPresent(solution, "md5pwd", ""));
user.setArgon2Password(ifLiteralPresent(solution, "a2pwd", "")); user.setArgon2Password(ifLiteralPresent(solution, "a2pwd", ""));
user.setPasswordLinkExpires(ifLongPresent(solution, "expire", 0L)); user.setPasswordLinkExpires(ifLongPresent(solution, "expire", 0L));
user.setEmailKey(ifLiteralPresent(solution, "emailKey", ""));
user.setLoginCount(ifIntPresent(solution, "count", 0)); user.setLoginCount(ifIntPresent(solution, "count", 0));
user.setLastLoginTime(ifLongPresent(solution, "lastLogin", 0)); user.setLastLoginTime(ifLongPresent(solution, "lastLogin", 0));
user.setStatus(parseStatus(solution, "status", null)); user.setStatus(parseStatus(solution, "status", null));

View file

@ -156,7 +156,6 @@ public class UserAccountsAddPage extends UserAccountsPage {
u.setOldPassword(""); u.setOldPassword("");
u.setPasswordChangeRequired(false); u.setPasswordChangeRequired(false);
u.setPasswordLinkExpires(0); u.setPasswordLinkExpires(0);
u.setEmailKey("");
u.setLoginCount(0); u.setLoginCount(0);
u.setLastLoginTime(0L); u.setLastLoginTime(0L);
u.setStatus(Status.INACTIVE); u.setStatus(Status.INACTIVE);

View file

@ -84,7 +84,6 @@ public abstract class UserAccountsAddPageStrategy extends UserAccountsPage {
u.setStatus(Status.ACTIVE); u.setStatus(Status.ACTIVE);
} else { } else {
u.setPasswordLinkExpires(figureExpirationDate().getTime()); u.setPasswordLinkExpires(figureExpirationDate().getTime());
u.generateEmailKey();
u.setStatus(Status.INACTIVE); u.setStatus(Status.INACTIVE);
} }
} }
@ -120,8 +119,10 @@ public abstract class UserAccountsAddPageStrategy extends UserAccountsPage {
private String buildCreatePasswordLink() { private String buildCreatePasswordLink() {
try { try {
String email = page.getAddedAccount().getEmailAddress(); String email = page.getAddedAccount().getEmailAddress();
String key = page.getAddedAccount().getEmailKey(); String hash = page.getAddedAccount()
String relativeUrl = UrlBuilder.getUrl(CREATE_PASSWORD_URL, "user", email, "key", key); .getPasswordLinkExpiresHash();
String relativeUrl = UrlBuilder.getUrl(CREATE_PASSWORD_URL,
"user", email, "key", hash);
URL context = new URL(vreq.getRequestURL().toString()); URL context = new URL(vreq.getRequestURL().toString());
URL url = new URL(context, relativeUrl); URL url = new URL(context, relativeUrl);

View file

@ -274,7 +274,6 @@ public class UserAccountsEditPage extends UserAccountsPage {
userAccount.setOldPassword(""); userAccount.setOldPassword("");
userAccount.setPasswordChangeRequired(false); userAccount.setPasswordChangeRequired(false);
userAccount.setPasswordLinkExpires(0L); userAccount.setPasswordLinkExpires(0L);
userAccount.setEmailKey("");
} }
if (isRootUser()) { if (isRootUser()) {

View file

@ -82,7 +82,6 @@ public abstract class UserAccountsEditPageStrategy extends UserAccountsPage {
protected void setAdditionalProperties(UserAccount u) { protected void setAdditionalProperties(UserAccount u) {
if (resetPassword && !page.isExternalAuthOnly()) { if (resetPassword && !page.isExternalAuthOnly()) {
u.setPasswordLinkExpires(figureExpirationDate().getTime()); u.setPasswordLinkExpires(figureExpirationDate().getTime());
u.generateEmailKey();
} }
} }
@ -122,8 +121,10 @@ public abstract class UserAccountsEditPageStrategy extends UserAccountsPage {
private String buildResetPasswordLink() { private String buildResetPasswordLink() {
try { try {
String email = page.getUpdatedAccount().getEmailAddress(); String email = page.getUpdatedAccount().getEmailAddress();
String key = page.getUpdatedAccount().getEmailKey(); String hash = page.getUpdatedAccount()
String relativeUrl = UrlBuilder.getUrl(RESET_PASSWORD_URL, "user", email, "key", key); .getPasswordLinkExpiresHash();
String relativeUrl = UrlBuilder.getUrl(RESET_PASSWORD_URL,
"user", email, "key", hash);
URL context = new URL(vreq.getRequestURL().toString()); URL context = new URL(vreq.getRequestURL().toString());
URL url = new URL(context, relativeUrl); URL url = new URL(context, relativeUrl);

View file

@ -36,7 +36,6 @@ public class UserAccountsCreatePasswordPage extends
userAccount.setArgon2Password(Authenticator.applyArgon2iEncoding(newPassword)); userAccount.setArgon2Password(Authenticator.applyArgon2iEncoding(newPassword));
userAccount.setMd5Password(""); userAccount.setMd5Password("");
userAccount.setPasswordLinkExpires(0L); userAccount.setPasswordLinkExpires(0L);
userAccount.setEmailKey("");
userAccount.setPasswordChangeRequired(false); userAccount.setPasswordChangeRequired(false);
userAccount.setStatus(Status.ACTIVE); userAccount.setStatus(Status.ACTIVE);
userAccountsDao.updateUserAccount(userAccount); userAccountsDao.updateUserAccount(userAccount);
@ -55,11 +54,6 @@ public class UserAccountsCreatePasswordPage extends
return i18n.text("account_already_activated", userEmail); return i18n.text("account_already_activated", userEmail);
} }
@Override
protected String passwordChangeInavlidKeyMessage() {
return i18n.text("password_change_invalid_key", userEmail);
}
@Override @Override
protected String templateName() { protected String templateName() {
return TEMPLATE_NAME; return TEMPLATE_NAME;

View file

@ -195,7 +195,6 @@ public class UserAccountsFirstTimeExternalPage extends UserAccountsPage {
u.setExternalAuthId(externalAuthId); u.setExternalAuthId(externalAuthId);
u.setPasswordChangeRequired(false); u.setPasswordChangeRequired(false);
u.setPasswordLinkExpires(0); u.setPasswordLinkExpires(0);
u.setEmailKey("");
u.setExternalAuthOnly(true); u.setExternalAuthOnly(true);
u.setLoginCount(0); u.setLoginCount(0);
u.setStatus(Status.ACTIVE); u.setStatus(Status.ACTIVE);

View file

@ -159,7 +159,6 @@ public abstract class UserAccountsMyAccountPageStrategy extends
userAccount.setMd5Password(""); userAccount.setMd5Password("");
userAccount.setPasswordChangeRequired(false); userAccount.setPasswordChangeRequired(false);
userAccount.setPasswordLinkExpires(0L); userAccount.setPasswordLinkExpires(0L);
userAccount.setEmailKey("");
} }
} }

View file

@ -103,12 +103,12 @@ public abstract class UserAccountsPasswordBasePage extends UserAccountsPage {
return; return;
} }
String expectedKey = userAccount.getEmailKey(); String expectedKey = userAccount.getPasswordLinkExpiresHash();
if (key.isEmpty() || !key.equals(expectedKey)) { if (!key.equals(expectedKey)) {
log.warn("Password request for '" + userEmail + "' is bogus: key (" log.warn("Password request for '" + userEmail + "' is bogus: key ("
+ key + ") doesn't match expected key (" + expectedKey + key + ") doesn't match expected key (" + expectedKey
+ ")"); + ")");
bogusMessage = passwordChangeInavlidKeyMessage(); bogusMessage = passwordChangeNotPendingMessage();
return; return;
} }
@ -153,7 +153,7 @@ public abstract class UserAccountsPasswordBasePage extends UserAccountsPage {
body.put("minimumLength", UserAccount.MIN_PASSWORD_LENGTH); body.put("minimumLength", UserAccount.MIN_PASSWORD_LENGTH);
body.put("maximumLength", UserAccount.MAX_PASSWORD_LENGTH); body.put("maximumLength", UserAccount.MAX_PASSWORD_LENGTH);
body.put("userAccount", userAccount); body.put("userAccount", userAccount);
body.put("key", userAccount.getEmailKey()); body.put("key", userAccount.getPasswordLinkExpiresHash());
body.put("newPassword", newPassword); body.put("newPassword", newPassword);
body.put("confirmPassword", confirmPassword); body.put("confirmPassword", confirmPassword);
body.put("formUrls", buildUrlsMap()); body.put("formUrls", buildUrlsMap());
@ -177,7 +177,5 @@ public abstract class UserAccountsPasswordBasePage extends UserAccountsPage {
protected abstract String passwordChangeNotPendingMessage(); protected abstract String passwordChangeNotPendingMessage();
protected abstract String passwordChangeInavlidKeyMessage();
protected abstract String templateName(); protected abstract String templateName();
} }

View file

@ -56,11 +56,6 @@ public class UserAccountsResetPasswordPage extends UserAccountsPasswordBasePage
return i18n.text("password_change_not_pending", userEmail); return i18n.text("password_change_not_pending", userEmail);
} }
@Override
protected String passwordChangeInavlidKeyMessage() {
return i18n.text("password_change_invalid_key", userEmail);
}
@Override @Override
protected String templateName() { protected String templateName() {
return TEMPLATE_NAME; return TEMPLATE_NAME;

View file

@ -17,6 +17,8 @@ import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import edu.cornell.mannlib.vitro.webapp.i18n.I18n;
import edu.cornell.mannlib.vitro.webapp.i18n.I18nBundle;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
@ -75,8 +77,8 @@ public class SparqlQueryController extends FreemarkerHttpServlet {
private static final String[] SAMPLE_QUERY = { // private static final String[] SAMPLE_QUERY = { //
"", // "", //
"#", // "#", //
"# This example query gets 20 geographic locations", // "i18n:sparql_query_description_0", //
"# and (if available) their labels", // "i18n:sparql_query_description_1", //
"#", // "#", //
"SELECT ?geoLocation ?label", // "SELECT ?geoLocation ?label", //
"WHERE", // "WHERE", //
@ -193,9 +195,11 @@ public class SparqlQueryController extends FreemarkerHttpServlet {
@Override @Override
protected ResponseValues processRequest(VitroRequest vreq) throws Exception { protected ResponseValues processRequest(VitroRequest vreq) throws Exception {
I18nBundle i18n = I18n.bundle(vreq);
Map<String, Object> bodyMap = new HashMap<>(); Map<String, Object> bodyMap = new HashMap<>();
bodyMap.put("sampleQuery", buildSampleQuery(buildPrefixList(vreq))); bodyMap.put("sampleQuery", buildSampleQuery(i18n, buildPrefixList(vreq)));
bodyMap.put("title", "SPARQL Query"); bodyMap.put("title", i18n.text("sparql_query_title"));
bodyMap.put("submitUrl", UrlBuilder.getUrl("admin/sparqlquery")); bodyMap.put("submitUrl", UrlBuilder.getUrl("admin/sparqlquery"));
return new TemplateResponseValues(TEMPLATE_NAME, bodyMap); return new TemplateResponseValues(TEMPLATE_NAME, bodyMap);
} }
@ -222,7 +226,7 @@ public class SparqlQueryController extends FreemarkerHttpServlet {
return prefixList; return prefixList;
} }
private String buildSampleQuery(List<Prefix> prefixList) { private String buildSampleQuery(I18nBundle i18n, List<Prefix> prefixList) {
StringWriter sw = new StringWriter(); StringWriter sw = new StringWriter();
PrintWriter writer = new PrintWriter(sw); PrintWriter writer = new PrintWriter(sw);
@ -230,6 +234,10 @@ public class SparqlQueryController extends FreemarkerHttpServlet {
writer.println(p); writer.println(p);
} }
for (String line : SAMPLE_QUERY) { for (String line : SAMPLE_QUERY) {
if (line.startsWith("i18n:")) {
// Get i18n translation
line = i18n.text(line.substring("i18n:".length()));
}
writer.println(line); writer.println(line);
} }

View file

@ -134,7 +134,6 @@ public class BasicAuthenticator extends Authenticator {
userAccount.setMd5Password(""); userAccount.setMd5Password("");
userAccount.setPasswordChangeRequired(false); userAccount.setPasswordChangeRequired(false);
userAccount.setPasswordLinkExpires(0L); userAccount.setPasswordLinkExpires(0L);
userAccount.setEmailKey("");
getUserAccountsDao().updateUserAccount(userAccount); getUserAccountsDao().updateUserAccount(userAccount);
} }

View file

@ -43,7 +43,7 @@ public class Classes2ClassesRetryController extends BaseEditController {
action = epo.getAction(); action = epo.getAction();
} }
VClassDao vcDao = ModelAccess.on(getServletContext()).getWebappDaoFactory().getVClassDao(); VClassDao vcDao = ModelAccess.on(request).getWebappDaoFactory().getVClassDao();
epo.setDataAccessObject(vcDao); epo.setDataAccessObject(vcDao);
Classes2Classes objectForEditing = new Classes2Classes(); Classes2Classes objectForEditing = new Classes2Classes();

View file

@ -51,8 +51,7 @@ public class ClassgroupRetryController extends BaseEditController {
action = epo.getAction(); action = epo.getAction();
} }
VClassGroupDao cgDao = ModelAccess.on( VClassGroupDao cgDao = ModelAccess.on(request).getWebappDaoFactory().getVClassGroupDao();
getServletContext()).getWebappDaoFactory().getVClassGroupDao();
epo.setDataAccessObject(cgDao); epo.setDataAccessObject(cgDao);

View file

@ -50,11 +50,12 @@ public class DatapropRetryController extends BaseEditController {
//create an EditProcessObject for this and put it in the session //create an EditProcessObject for this and put it in the session
EditProcessObject epo = super.createEpo(request); EditProcessObject epo = super.createEpo(request);
epo.setImplementationClass(DataProperty.class);
epo.setBeanClass(DataProperty.class); epo.setBeanClass(DataProperty.class);
VitroRequest vreq = new VitroRequest(request); VitroRequest vreq = new VitroRequest(request);
WebappDaoFactory wadf = ModelAccess.on(getServletContext()).getWebappDaoFactory(); WebappDaoFactory wadf = ModelAccess.on(vreq).getWebappDaoFactory();
DatatypeDao dDao = wadf.getDatatypeDao(); DatatypeDao dDao = wadf.getDatatypeDao();
DataPropertyDao dpDao = wadf.getDataPropertyDao(); DataPropertyDao dpDao = wadf.getDataPropertyDao();

View file

@ -106,7 +106,7 @@ public class FauxPropertyRetryController extends BaseEditController {
this.epo = epo; this.epo = epo;
this.fpDao = ModelAccess.on(ctx).getWebappDaoFactory() this.fpDao = ModelAccess.on(req).getWebappDaoFactory()
.getFauxPropertyDao(); .getFauxPropertyDao();
} }
@ -114,6 +114,8 @@ public class FauxPropertyRetryController extends BaseEditController {
void populate() { void populate() {
epo.setDataAccessObject(fpDao); epo.setDataAccessObject(fpDao);
epo.setAction(determineAction()); epo.setAction(determineAction());
epo.setImplementationClass(FauxProperty.class);
epo.setBeanClass(FauxProperty.class);
if (epo.getUseRecycledBean()) { if (epo.getUseRecycledBean()) {
beanForEditing = (FauxProperty) epo.getNewBean(); beanForEditing = (FauxProperty) epo.getNewBean();

View file

@ -71,7 +71,7 @@ public class NamespacePrefixOperationController extends BaseEditController {
if (request.getParameter("_cancel") == null) { if (request.getParameter("_cancel") == null) {
OntModel ontModel = ModelAccess.on(getServletContext()).getOntModel(); OntModel ontModel = ModelAccess.on(req).getOntModel();
String namespaceStr = request.getParameter("namespace"); String namespaceStr = request.getParameter("namespace");
String prefixStr = request.getParameter("prefix"); String prefixStr = request.getParameter("prefix");

View file

@ -51,7 +51,7 @@ public class PropertyGroupRetryController extends BaseEditController {
} }
PropertyGroupDao pgDao = ModelAccess.on( PropertyGroupDao pgDao = ModelAccess.on(
getServletContext()).getWebappDaoFactory().getPropertyGroupDao(); req).getWebappDaoFactory().getPropertyGroupDao();
epo.setDataAccessObject(pgDao); epo.setDataAccessObject(pgDao);

View file

@ -53,6 +53,7 @@ public class PropertyRetryController extends BaseEditController {
/*for testing*/ /*for testing*/
ObjectProperty testMask = new ObjectProperty(); ObjectProperty testMask = new ObjectProperty();
epo.setImplementationClass(ObjectProperty.class);
epo.setBeanClass(ObjectProperty.class); epo.setBeanClass(ObjectProperty.class);
epo.setBeanMask(testMask); epo.setBeanMask(testMask);
@ -64,7 +65,7 @@ public class PropertyRetryController extends BaseEditController {
action = epo.getAction(); action = epo.getAction();
} }
ObjectPropertyDao propDao = ModelAccess.on(getServletContext()).getWebappDaoFactory().getObjectPropertyDao(); ObjectPropertyDao propDao = ModelAccess.on(req).getWebappDaoFactory().getObjectPropertyDao();
epo.setDataAccessObject(propDao); epo.setDataAccessObject(propDao);
OntologyDao ontDao = request.getUnfilteredWebappDaoFactory().getOntologyDao(); OntologyDao ontDao = request.getUnfilteredWebappDaoFactory().getOntologyDao();

View file

@ -48,7 +48,7 @@ public class RestrictionOperationController extends BaseEditController {
String defaultLandingPage = getDefaultLandingPage(request); String defaultLandingPage = getDefaultLandingPage(request);
try { try {
OntModel ontModel = ModelAccess.on(getServletContext()) OntModel ontModel = ModelAccess.on(req)
.getOntModel(TBOX_ASSERTIONS); .getOntModel(TBOX_ASSERTIONS);
HashMap epoHash = null; HashMap epoHash = null;

View file

@ -48,7 +48,7 @@ public class VclassEditController extends BaseEditController {
EditProcessObject epo = super.createEpo(request, FORCE_NEW); EditProcessObject epo = super.createEpo(request, FORCE_NEW);
request.setAttribute("epoKey", epo.getKey()); request.setAttribute("epoKey", epo.getKey());
VClassDao vcwDao = ModelAccess.on(getServletContext()).getWebappDaoFactory(ASSERTIONS_ONLY).getVClassDao(); VClassDao vcwDao = ModelAccess.on(req).getWebappDaoFactory(ASSERTIONS_ONLY).getVClassDao();
VClass vcl = (VClass)vcwDao.getVClassByURI(request.getParameter("uri")); VClass vcl = (VClass)vcwDao.getVClassByURI(request.getParameter("uri"));
if (vcl == null) { if (vcl == null) {
@ -152,8 +152,8 @@ public class VclassEditController extends BaseEditController {
request.setAttribute("formSelect",formSelect); request.setAttribute("formSelect",formSelect);
// if supported, we want to show only the asserted superclasses and subclasses. // if supported, we want to show only the asserted superclasses and subclasses.
VClassDao vcDao = ModelAccess.on(getServletContext()).getWebappDaoFactory(ASSERTIONS_ONLY).getVClassDao(); VClassDao vcDao = ModelAccess.on(req).getWebappDaoFactory(ASSERTIONS_ONLY).getVClassDao();
VClassDao displayVcDao = ModelAccess.on(getServletContext()).getWebappDaoFactory().getVClassDao(); VClassDao displayVcDao = ModelAccess.on(req).getWebappDaoFactory().getVClassDao();
List<VClass> superVClasses = getVClassesForURIList( List<VClass> superVClasses = getVClassesForURIList(
vcDao.getSuperClassURIs(vcl.getURI(),false), displayVcDao); vcDao.getSuperClassURIs(vcl.getURI(),false), displayVcDao);

View file

@ -66,11 +66,10 @@ public class VclassRetryController extends BaseEditController {
action = epo.getAction(); action = epo.getAction();
} }
WebappDaoFactory wadf = ModelAccess.on(getServletContext()).getWebappDaoFactory(); WebappDaoFactory wadf = ModelAccess.on(req).getWebappDaoFactory();
VClassDao vcwDao = wadf.getVClassDao(); VClassDao vcwDao = wadf.getVClassDao();
epo.setDataAccessObject(vcwDao); epo.setDataAccessObject(vcwDao);
VClassGroupDao cgDao = wadf.getVClassGroupDao();
OntologyDao oDao = wadf.getOntologyDao(); OntologyDao oDao = wadf.getOntologyDao();
VClass vclassForEditing = null; VClass vclassForEditing = null;

View file

@ -37,7 +37,7 @@ public class NamespacesListingController extends BaseEditController {
VitroRequest vrequest = new VitroRequest(request); VitroRequest vrequest = new VitroRequest(request);
OntModel ontModel = ModelAccess.on(getServletContext()).getOntModel(); OntModel ontModel = ModelAccess.on(vrequest).getOntModel();
ArrayList results = new ArrayList(); ArrayList results = new ArrayList();
request.setAttribute("results",results); request.setAttribute("results",results);

View file

@ -54,7 +54,7 @@ public class RestrictionsListingController extends BaseEditController {
epo = super.createEpo(request); epo = super.createEpo(request);
OntModel ontModel = ModelAccess.on(getServletContext()).getOntModel(); OntModel ontModel = ModelAccess.on(vrequest).getOntModel();
ObjectPropertyDao opDao = vrequest.getUnfilteredWebappDaoFactory().getObjectPropertyDao(); ObjectPropertyDao opDao = vrequest.getUnfilteredWebappDaoFactory().getObjectPropertyDao();
VClassDao vcDao = vrequest.getUnfilteredWebappDaoFactory().getVClassDao(); VClassDao vcDao = vrequest.getUnfilteredWebappDaoFactory().getVClassDao();

View file

@ -3,6 +3,8 @@
package edu.cornell.mannlib.vitro.webapp.controller.freemarker; package edu.cornell.mannlib.vitro.webapp.controller.freemarker;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -42,6 +44,8 @@ public class BrowseController extends FreemarkerHttpServlet {
List<VClassGroup> groups = null; List<VClassGroup> groups = null;
VClassGroupsForRequest vcgc = VClassGroupCache.getVClassGroups(vreq); VClassGroupsForRequest vcgc = VClassGroupCache.getVClassGroups(vreq);
groups =vcgc.getGroups(); groups =vcgc.getGroups();
Collections.sort(groups, publicNameComparator);
// sortGroupListByPublicName(groups);
List<VClassGroupTemplateModel> vcgroups = new ArrayList<VClassGroupTemplateModel>(groups.size()); List<VClassGroupTemplateModel> vcgroups = new ArrayList<VClassGroupTemplateModel>(groups.size());
for (VClassGroup group : groups) { for (VClassGroup group : groups) {
vcgroups.add(new VClassGroupTemplateModel(group)); vcgroups.add(new VClassGroupTemplateModel(group));
@ -50,4 +54,35 @@ public class BrowseController extends FreemarkerHttpServlet {
return new TemplateResponseValues(templateName, body); return new TemplateResponseValues(templateName, body);
} }
public Comparator<VClassGroup> publicNameComparator = new Comparator<VClassGroup>() {
public int compare(VClassGroup s1, VClassGroup s2) {
String groupName1 = s1.getPublicName().toUpperCase();
String groupName2 = s2.getPublicName().toUpperCase();
//ascending order
return groupName1.compareTo(groupName2);
//descending order
//return groupName2.compareTo(groupName1);
}};
//
// public void sortGroupListByPublicName(List<VClassGroup> groupList) {
// groupList.sort(new Comparator<VClassGroup>() {
// public int compare(VClassGroup first, VClassGroup second) {
// if (first != null) {
// if (second != null) {
// return (first.getDisplayRank() - second.getDisplayRank());
// } else {
// log.error("error--2nd VClassGroup is null in VClassGroupDao.getGroupList().compare()");
// }
// } else {
// log.error("error--1st VClassGroup is null in VClassGroupDao.getGroupList().compare()");
// }
// return 0;
// }
// });
// }
} }

View file

@ -74,7 +74,7 @@ public class DeleteIndividualController extends FreemarkerHttpServlet{
String delteQueryText = getDeleteQueryForType(type, displayModel); String delteQueryText = getDeleteQueryForType(type, displayModel);
byte[] toRemove = getIndividualsToDelete(individualUri, delteQueryText, vreq); byte[] toRemove = getIndividualsToDelete(individualUri, delteQueryText, vreq);
if (toRemove.length > 0) { if (toRemove.length > 0) {
deleteIndividuals(toRemove,vreq); deleteIndividuals(toRemove, vreq);
} }
String redirectUrl = getRedirectUrl(vreq); String redirectUrl = getRedirectUrl(vreq);
@ -91,14 +91,14 @@ public class DeleteIndividualController extends FreemarkerHttpServlet{
private TemplateResponseValues prepareErrorMessage(String errorMessage) { private TemplateResponseValues prepareErrorMessage(String errorMessage) {
HashMap<String,Object> map = new HashMap<String,Object>(); HashMap<String, Object> map = new HashMap<String, Object>();
map.put("errorMessage", errorMessage); map.put("errorMessage", errorMessage);
return new TemplateResponseValues("error-message.ftl", map); return new TemplateResponseValues("error-message.ftl", map);
} }
private String handleErrors(VitroRequest vreq) { private String handleErrors(VitroRequest vreq) {
String uri = vreq.getParameter("individualUri"); String uri = vreq.getParameter("individualUri");
if ( uri == null) { if (uri == null) {
return "Individual uri is null. No object to delete."; return "Individual uri is null. No object to delete.";
} }
if (uri.contains(">")) { if (uri.contains(">")) {
@ -107,26 +107,26 @@ public class DeleteIndividualController extends FreemarkerHttpServlet{
return ""; return "";
} }
private static String getDeleteQueryForType(String typeURI,Model displayModel) { private static String getDeleteQueryForType(String typeURI, Model displayModel) {
String deleteQueryText = DEFAULT_DELETE_QUERY_TEXT; String deleteQueryText = DEFAULT_DELETE_QUERY_TEXT;
Query queryForTypeSpecificDeleteQuery = QueryFactory.create(queryForDeleteQuery); Query queryForTypeSpecificDeleteQuery = QueryFactory.create(queryForDeleteQuery);
QuerySolutionMap initialBindings = new QuerySolutionMap(); QuerySolutionMap initialBindings = new QuerySolutionMap();
initialBindings.add("associatedURI", ResourceFactory.createResource( typeURI )); initialBindings.add("associatedURI", ResourceFactory.createResource(typeURI));
displayModel.enterCriticalSection(Lock.READ); displayModel.enterCriticalSection(Lock.READ);
try{ try {
QueryExecution qexec = QueryExecutionFactory.create(queryForTypeSpecificDeleteQuery,displayModel,initialBindings ); QueryExecution qexec = QueryExecutionFactory.create(queryForTypeSpecificDeleteQuery, displayModel, initialBindings);
try{ try {
ResultSet results = qexec.execSelect(); ResultSet results = qexec.execSelect();
while (results.hasNext()) { while (results.hasNext()) {
QuerySolution solution = results.nextSolution(); QuerySolution solution = results.nextSolution();
deleteQueryText = solution.get("deleteQueryText").toString(); deleteQueryText = solution.get("deleteQueryText").toString();
} }
}finally{ qexec.close(); } } finally {
}finally{ displayModel.leaveCriticalSection(); } qexec.close();
}
} finally {
displayModel.leaveCriticalSection();
}
if (!deleteQueryText.equals(DEFAULT_DELETE_QUERY_TEXT)) { if (!deleteQueryText.equals(DEFAULT_DELETE_QUERY_TEXT)) {
log.debug("For " + typeURI + " found delete query \n" + deleteQueryText); log.debug("For " + typeURI + " found delete query \n" + deleteQueryText);
@ -152,16 +152,16 @@ public class DeleteIndividualController extends FreemarkerHttpServlet{
return type; return type;
} }
private byte[] getIndividualsToDelete(String targetIndividual, String deleteQuery,VitroRequest vreq) { private byte[] getIndividualsToDelete(String targetIndividual, String deleteQuery, VitroRequest vreq) {
ByteArrayOutputStream out = new ByteArrayOutputStream(); ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
Query queryForTypeSpecificDeleteQuery = QueryFactory.create(deleteQuery); Query queryForTypeSpecificDeleteQuery = QueryFactory.create(deleteQuery);
QuerySolutionMap initialBindings = new QuerySolutionMap(); QuerySolutionMap initialBindings = new QuerySolutionMap();
initialBindings.add("individualURI", ResourceFactory.createResource( targetIndividual )); initialBindings.add("individualURI", ResourceFactory.createResource(targetIndividual));
Model ontModel = vreq.getJenaOntModel(); Model ontModel = vreq.getJenaOntModel();
QueryExecution qexec = QueryExecutionFactory.create(queryForTypeSpecificDeleteQuery,ontModel,initialBindings ); try {
QueryExecution qexec = QueryExecutionFactory.create(queryForTypeSpecificDeleteQuery, ontModel, initialBindings);
Model results = qexec.execDescribe(); Model results = qexec.execDescribe();
results.write(out,"N3"); results.write(out, "N3");
} catch (Exception e) { } catch (Exception e) {
log.error("Query raised an error \n" + deleteQuery); log.error("Query raised an error \n" + deleteQuery);
@ -193,8 +193,7 @@ public class DeleteIndividualController extends FreemarkerHttpServlet{
cs.addPreChangeEvent(new BulkUpdateEvent(null, BEGIN)); cs.addPreChangeEvent(new BulkUpdateEvent(null, BEGIN));
cs.addPostChangeEvent(new BulkUpdateEvent(null, END)); cs.addPostChangeEvent(new BulkUpdateEvent(null, END));
return cs; return cs;
} }

View file

@ -10,6 +10,9 @@ import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.apache.jena.rdf.model.Property;
import org.apache.jena.rdf.model.ResourceFactory;
import edu.cornell.mannlib.vitro.webapp.auth.permissions.SimplePermission; import edu.cornell.mannlib.vitro.webapp.auth.permissions.SimplePermission;
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.AuthorizationRequest; import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.AuthorizationRequest;
import edu.cornell.mannlib.vitro.webapp.beans.DataProperty; import edu.cornell.mannlib.vitro.webapp.beans.DataProperty;
@ -25,6 +28,8 @@ import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditConfigurationUti
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.N3EditUtils; import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.N3EditUtils;
import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess; import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess;
import edu.cornell.mannlib.vitro.webapp.web.URLEncoder; import edu.cornell.mannlib.vitro.webapp.web.URLEncoder;
/* /*
* Custom deletion controller to which deletion requests from default property form are sent. May be replaced * Custom deletion controller to which deletion requests from default property form are sent. May be replaced
* later with additional features in process rdf form controller or alternative location. * later with additional features in process rdf form controller or alternative location.
@ -64,8 +69,8 @@ public class DeletePropertyController extends FreemarkerHttpServlet {
// TODO Auto-generated method stub // TODO Auto-generated method stub
String subjectUri = EditConfigurationUtils.getSubjectUri(vreq); String subjectUri = EditConfigurationUtils.getSubjectUri(vreq);
String predicateUri = EditConfigurationUtils.getPredicateUri(vreq); String predicateUri = EditConfigurationUtils.getPredicateUri(vreq);
int hashIndex = predicateUri.lastIndexOf("#"); Property prop = ResourceFactory.createProperty(predicateUri);
String localName = predicateUri.substring(hashIndex + 1); String localName = prop.getLocalName();
String redirectUrl = "/entity?uri=" + URLEncoder.encode(subjectUri); String redirectUrl = "/entity?uri=" + URLEncoder.encode(subjectUri);
return redirectUrl + "#" + URLEncoder.encode(localName); return redirectUrl + "#" + URLEncoder.encode(localName);
} }

View file

@ -8,6 +8,7 @@ import static javax.mail.Message.RecipientType.TO;
import java.io.IOException; import java.io.IOException;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.io.StringWriter; import java.io.StringWriter;
import java.nio.charset.Charset;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
@ -17,7 +18,6 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import edu.cornell.mannlib.vitro.webapp.dao.jena.MenuDaoJena;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
@ -93,6 +93,8 @@ public class FreemarkerHttpServlet extends VitroHttpServlet {
throws IOException, ServletException { throws IOException, ServletException {
super.doGet(request,response); super.doGet(request,response);
//UQAM-Optimization set for UTF-8
response.setCharacterEncoding("UTF-8");
VitroRequest vreq = new VitroRequest(request); VitroRequest vreq = new VitroRequest(request);
ResponseValues responseValues = null; ResponseValues responseValues = null;
@ -103,8 +105,8 @@ public class FreemarkerHttpServlet extends VitroHttpServlet {
if (!isAuthorizedToDisplayPage(request, response, requiredActions(vreq))) { if (!isAuthorizedToDisplayPage(request, response, requiredActions(vreq))) {
return; return;
} }
responseValues = processRequest(vreq); responseValues = processRequest(vreq);
doResponse(vreq, response, responseValues); doResponse(vreq, response, responseValues);
} catch (Throwable e) { } catch (Throwable e) {
@ -276,8 +278,15 @@ public class FreemarkerHttpServlet extends VitroHttpServlet {
// is specified in the main page template. // is specified in the main page template.
bodyString = ""; bodyString = "";
} }
templateDataModel.put("body", bodyString); templateDataModel.put("body", bodyString);
String lang = vreq.getLocale().getLanguage();
if (!vreq.getLocale().getCountry().isEmpty()) {
lang += "-" + vreq.getLocale().getCountry();
}
templateDataModel.put("country", lang);
// Tell the template and any directives it uses that we're processing a page template. // Tell the template and any directives it uses that we're processing a page template.
templateDataModel.put("templateType", PAGE_TEMPLATE_TYPE); templateDataModel.put("templateType", PAGE_TEMPLATE_TYPE);
@ -462,7 +471,7 @@ public class FreemarkerHttpServlet extends VitroHttpServlet {
protected MainMenu getDisplayModelMenu(VitroRequest vreq){ protected MainMenu getDisplayModelMenu(VitroRequest vreq){
String url = vreq.getRequestURI().substring(vreq.getContextPath().length()); String url = vreq.getRequestURI().substring(vreq.getContextPath().length());
return vreq.getWebappDaoFactory().getMenuDao().getMainMenu(vreq, url); return vreq.getWebappDaoFactory().getMenuDao().getMainMenu(url);
} }
// NIHVIVO-3307: we need this here instead of FreemarkerConfiguration.java so that updates to // NIHVIVO-3307: we need this here instead of FreemarkerConfiguration.java so that updates to

View file

@ -37,7 +37,6 @@ public class UrlBuilder {
LOGIN("/login"), LOGIN("/login"),
LOGOUT("/logout"), LOGOUT("/logout"),
OBJECT_PROPERTY_EDIT("/propertyEdit"), OBJECT_PROPERTY_EDIT("/propertyEdit"),
CUSTOMSEARCH("/customsearch"),
SEARCH("/search"), SEARCH("/search"),
SITE_ADMIN("/siteAdmin"), SITE_ADMIN("/siteAdmin"),
TERMS_OF_USE("/termsOfUse"), TERMS_OF_USE("/termsOfUse"),

View file

@ -4,6 +4,7 @@ package edu.cornell.mannlib.vitro.webapp.controller.json;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ArrayNode;
@ -15,6 +16,7 @@ import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vitro.webapp.beans.Individual; import edu.cornell.mannlib.vitro.webapp.beans.Individual;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.dao.IndividualDao; import edu.cornell.mannlib.vitro.webapp.dao.IndividualDao;
import edu.cornell.mannlib.vitro.webapp.i18n.selection.SelectedLocale;
import edu.cornell.mannlib.vitro.webapp.services.shortview.ShortViewService; import edu.cornell.mannlib.vitro.webapp.services.shortview.ShortViewService;
import edu.cornell.mannlib.vitro.webapp.services.shortview.ShortViewService.ShortViewContext; import edu.cornell.mannlib.vitro.webapp.services.shortview.ShortViewService.ShortViewContext;
import edu.cornell.mannlib.vitro.webapp.services.shortview.ShortViewServiceSetup; import edu.cornell.mannlib.vitro.webapp.services.shortview.ShortViewServiceSetup;
@ -73,7 +75,11 @@ public class GetRandomSearchIndividualsByVClass extends GetSearchIndividualsByVC
modelMap.put("individual", modelMap.put("individual",
IndividualTemplateModelBuilder.build(individual, vreq)); IndividualTemplateModelBuilder.build(individual, vreq));
modelMap.put("vclass", vclassName); modelMap.put("vclass", vclassName);
String langCtx = vreq.getLocale().getLanguage(); //UQAM-Linguistic-Management build the linguistic context
if (!vreq.getLocale().getCountry().isEmpty()) {
langCtx += "-" + vreq.getLocale().getCountry();
}
modelMap.put("langCtx", langCtx); // UQAM-Linguistic-Management add the linguistic context to map
ShortViewService svs = ShortViewServiceSetup.getService(ctx); ShortViewService svs = ShortViewServiceSetup.getService(ctx);
return svs.renderShortView(individual, ShortViewContext.BROWSE, return svs.renderShortView(individual, ShortViewContext.BROWSE,
modelMap, vreq); modelMap, vreq);

View file

@ -155,7 +155,6 @@ public class VitroVocabulary {
public static final String USERACCOUNT_LAST_LOGIN_TIME = VITRO_AUTH + "lastLoginTime"; public static final String USERACCOUNT_LAST_LOGIN_TIME = VITRO_AUTH + "lastLoginTime";
public static final String USERACCOUNT_STATUS = VITRO_AUTH + "status"; public static final String USERACCOUNT_STATUS = VITRO_AUTH + "status";
public static final String USERACCOUNT_PASSWORD_LINK_EXPIRES = VITRO_AUTH + "passwordLinkExpires"; public static final String USERACCOUNT_PASSWORD_LINK_EXPIRES = VITRO_AUTH + "passwordLinkExpires";
public static final String USERACCOUNT_EMAIL_KEY = VITRO_AUTH + "emailKey";
public static final String USERACCOUNT_PASSWORD_CHANGE_REQUIRED = VITRO_AUTH + "passwordChangeRequired"; public static final String USERACCOUNT_PASSWORD_CHANGE_REQUIRED = VITRO_AUTH + "passwordChangeRequired";
public static final String USERACCOUNT_EXTERNAL_AUTH_ID = VITRO_AUTH + "externalAuthId"; public static final String USERACCOUNT_EXTERNAL_AUTH_ID = VITRO_AUTH + "externalAuthId";
public static final String USERACCOUNT_EXTERNAL_AUTH_ONLY = VITRO_AUTH + "externalAuthOnly"; public static final String USERACCOUNT_EXTERNAL_AUTH_ONLY = VITRO_AUTH + "externalAuthOnly";

View file

@ -5,6 +5,8 @@ package edu.cornell.mannlib.vitro.webapp.dao;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import edu.cornell.mannlib.vitro.webapp.i18n.I18nBundle;
public interface WebappDaoFactory { public interface WebappDaoFactory {
/** /**
@ -132,4 +134,6 @@ public interface WebappDaoFactory {
public MenuDao getMenuDao(); public MenuDao getMenuDao();
public I18nBundle getI18nBundle();
} }

View file

@ -5,14 +5,17 @@ package edu.cornell.mannlib.vitro.webapp.dao;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import edu.cornell.mannlib.vitro.webapp.dao.PropertyDao.FullPropertyKey; import edu.cornell.mannlib.vitro.webapp.dao.PropertyDao.FullPropertyKey;
import edu.cornell.mannlib.vitro.webapp.rdfservice.filter.LanguageFilteringUtils;
public class WebappDaoFactoryConfig { public class WebappDaoFactoryConfig {
private List<String> preferredLanguages; private List<String> preferredLanguages;
private List<Locale> preferredLocales;
private String defaultNamespace; private String defaultNamespace;
private Set<String> nonUserNamespaces; private Set<String> nonUserNamespaces;
private boolean isUnderlyingStoreReasoned = false; private boolean isUnderlyingStoreReasoned = false;
@ -20,6 +23,7 @@ public class WebappDaoFactoryConfig {
public WebappDaoFactoryConfig() { public WebappDaoFactoryConfig() {
preferredLanguages = Arrays.asList("en-US", "en", "EN"); preferredLanguages = Arrays.asList("en-US", "en", "EN");
preferredLocales = LanguageFilteringUtils.languagesToLocales(preferredLanguages);
defaultNamespace = "http://vitro.mannlib.cornell.edu/ns/default#"; defaultNamespace = "http://vitro.mannlib.cornell.edu/ns/default#";
nonUserNamespaces = new HashSet<String>(); nonUserNamespaces = new HashSet<String>();
nonUserNamespaces.add(VitroVocabulary.vitroURI); nonUserNamespaces.add(VitroVocabulary.vitroURI);
@ -33,6 +37,14 @@ public class WebappDaoFactoryConfig {
this.preferredLanguages = pl; this.preferredLanguages = pl;
} }
public List<Locale> getPreferredLocales() {
return this.preferredLocales;
}
public void setPreferredLocales(List<Locale> pl) {
this.preferredLocales = pl;
}
public String getDefaultNamespace() { public String getDefaultNamespace() {
return defaultNamespace; return defaultNamespace;
} }

View file

@ -17,7 +17,7 @@ import edu.cornell.mannlib.vitro.webapp.dao.DataPropertyDao;
import edu.cornell.mannlib.vitro.webapp.dao.InsertException; import edu.cornell.mannlib.vitro.webapp.dao.InsertException;
import edu.cornell.mannlib.vitro.webapp.dao.filtering.filters.VitroFilters; import edu.cornell.mannlib.vitro.webapp.dao.filtering.filters.VitroFilters;
class DataPropertyDaoFiltering extends BaseFiltering implements DataPropertyDao{ public class DataPropertyDaoFiltering extends BaseFiltering implements DataPropertyDao{
final DataPropertyDao innerDataPropertyDao; final DataPropertyDao innerDataPropertyDao;
final VitroFilters filters; final VitroFilters filters;

View file

@ -18,7 +18,7 @@ import edu.cornell.mannlib.vitro.webapp.beans.Individual;
import edu.cornell.mannlib.vitro.webapp.dao.DataPropertyStatementDao; import edu.cornell.mannlib.vitro.webapp.dao.DataPropertyStatementDao;
import edu.cornell.mannlib.vitro.webapp.dao.filtering.filters.VitroFilters; import edu.cornell.mannlib.vitro.webapp.dao.filtering.filters.VitroFilters;
class DataPropertyStatementDaoFiltering extends BaseFiltering implements DataPropertyStatementDao{ public class DataPropertyStatementDaoFiltering extends BaseFiltering implements DataPropertyStatementDao{
final DataPropertyStatementDao innerDataPropertyStatementDao; final DataPropertyStatementDao innerDataPropertyStatementDao;
final VitroFilters filters; final VitroFilters filters;

View file

@ -26,47 +26,34 @@ public class FauxPropertyDaoFiltering extends BaseFiltering implements FauxPrope
@Override @Override
public List<FauxProperty> getFauxPropertiesForBaseUri(String uri) { public List<FauxProperty> getFauxPropertiesForBaseUri(String uri) {
// TODO Auto-generated method stub return innerFauxPropertyDao.getFauxPropertiesForBaseUri(uri);
throw new RuntimeException(
"FauxPropertyDao.getFauxPropertiesForBaseUri() not implemented.");
} }
@Override @Override
public FauxProperty getFauxPropertyFromContextUri(String contextUri) { public FauxProperty getFauxPropertyFromContextUri(String contextUri) {
// TODO Auto-generated method stub return innerFauxPropertyDao.getFauxPropertyFromContextUri(contextUri);
throw new RuntimeException(
"FauxPropertyDaoFiltering.getFauxPropertyFromConfigContextUri() not implemented.");
} }
@Override @Override
public FauxProperty getFauxPropertyByUris(String domainUri, String baseUri, public FauxProperty getFauxPropertyByUris(String domainUri, String baseUri,
String rangeUri) { String rangeUri) {
// TODO Auto-generated method stub return innerFauxPropertyDao.getFauxPropertyByUris(domainUri, baseUri,
throw new RuntimeException( rangeUri);
"FauxPropertyDaoFiltering.getFauxPropertyByUris() not implemented.");
} }
@Override @Override
public void updateFauxProperty(FauxProperty fp) { public void updateFauxProperty(FauxProperty fp) {
// TODO Auto-generated method stub innerFauxPropertyDao.updateFauxProperty(fp);
throw new RuntimeException("FauxPropertyDaoFiltering.updateFauxProperty() not implemented.");
} }
@Override @Override
public void deleteFauxProperty(FauxProperty fp) { public void deleteFauxProperty(FauxProperty fp) {
// TODO Auto-generated method stub innerFauxPropertyDao.deleteFauxProperty(fp);
throw new RuntimeException("FauxPropertyDao.deleteFauxProperty() not implemented.");
} }
@Override @Override
public void insertFauxProperty(FauxProperty fp) { public void insertFauxProperty(FauxProperty fp) {
// TODO Auto-generated method stub innerFauxPropertyDao.insertFauxProperty(fp);
throw new RuntimeException("FauxPropertyDao.insertFauxProperty() not implemented.");
} }
} }

View file

@ -20,7 +20,7 @@ import edu.cornell.mannlib.vitro.webapp.dao.filtering.filters.VitroFilters;
import edu.cornell.mannlib.vitro.webapp.edit.EditLiteral; import edu.cornell.mannlib.vitro.webapp.edit.EditLiteral;
class IndividualDaoFiltering extends BaseFiltering implements IndividualDao{ public class IndividualDaoFiltering extends BaseFiltering implements IndividualDao{
IndividualDao innerIndividualDao; IndividualDao innerIndividualDao;
VitroFilters filters; VitroFilters filters;

View file

@ -17,7 +17,7 @@ import edu.cornell.mannlib.vitro.webapp.dao.InsertException;
import edu.cornell.mannlib.vitro.webapp.dao.ObjectPropertyDao; import edu.cornell.mannlib.vitro.webapp.dao.ObjectPropertyDao;
import edu.cornell.mannlib.vitro.webapp.dao.filtering.filters.VitroFilters; import edu.cornell.mannlib.vitro.webapp.dao.filtering.filters.VitroFilters;
class ObjectPropertyDaoFiltering extends BaseFiltering implements ObjectPropertyDao{ public class ObjectPropertyDaoFiltering extends BaseFiltering implements ObjectPropertyDao{
final ObjectPropertyDao innerObjectPropertyDao; final ObjectPropertyDao innerObjectPropertyDao;
final VitroFilters filters; final VitroFilters filters;

View file

@ -16,7 +16,7 @@ import edu.cornell.mannlib.vitro.webapp.beans.ObjectPropertyStatementImpl;
import edu.cornell.mannlib.vitro.webapp.dao.ObjectPropertyStatementDao; import edu.cornell.mannlib.vitro.webapp.dao.ObjectPropertyStatementDao;
import edu.cornell.mannlib.vitro.webapp.dao.filtering.filters.VitroFilters; import edu.cornell.mannlib.vitro.webapp.dao.filtering.filters.VitroFilters;
class ObjectPropertyStatementDaoFiltering extends BaseFiltering implements ObjectPropertyStatementDao{ public class ObjectPropertyStatementDaoFiltering extends BaseFiltering implements ObjectPropertyStatementDao{
final ObjectPropertyStatementDao innerObjectPropertyStatementDao; final ObjectPropertyStatementDao innerObjectPropertyStatementDao;
final VitroFilters filters; final VitroFilters filters;

View file

@ -24,6 +24,7 @@ import edu.cornell.mannlib.vitro.webapp.dao.VClassDao;
import edu.cornell.mannlib.vitro.webapp.dao.VClassGroupDao; import edu.cornell.mannlib.vitro.webapp.dao.VClassGroupDao;
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory; import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
import edu.cornell.mannlib.vitro.webapp.dao.filtering.filters.VitroFilters; import edu.cornell.mannlib.vitro.webapp.dao.filtering.filters.VitroFilters;
import edu.cornell.mannlib.vitro.webapp.i18n.I18nBundle;
/** /**
* This wraps a WebappDaoFactory and applies filtering. * This wraps a WebappDaoFactory and applies filtering.
@ -67,7 +68,7 @@ public class WebappDaoFactoryFiltering implements WebappDaoFactory {
transient private PropertyGroupDao filteringPropertyGroupDao=null; transient private PropertyGroupDao filteringPropertyGroupDao=null;
transient private PropertyInstanceDao filteringPropertyInstanceDao=null; transient private PropertyInstanceDao filteringPropertyInstanceDao=null;
public WebappDaoFactoryFiltering( WebappDaoFactory innerDao, VitroFilters filters){ public WebappDaoFactoryFiltering(WebappDaoFactory innerDao, VitroFilters filters){
if( innerDao == null ) if( innerDao == null )
throw new Error("innerWebappDaoFactory must be non-null"); throw new Error("innerWebappDaoFactory must be non-null");
this.filters = filters; this.filters = filters;
@ -276,4 +277,9 @@ public class WebappDaoFactoryFiltering implements WebappDaoFactory {
public void close() { public void close() {
innerWebappDaoFactory.close(); innerWebappDaoFactory.close();
} }
@Override
public I18nBundle getI18nBundle() {
return innerWebappDaoFactory.getI18nBundle();
}
} }

View file

@ -83,22 +83,21 @@ public class ApplicationDaoJena extends JenaBaseDao implements ApplicationDao {
} }
ontModel.enterCriticalSection(Lock.WRITE); ontModel.enterCriticalSection(Lock.WRITE);
try { try {
appInd.setLabel(application.getApplicationName(), null); updateRDFSLabel(appInd, application.getApplicationName());
updatePropertyStringValue( updatePlainLiteralValue(
appInd, APPLICATION_ABOUTTEXT, application.getAboutText(), appInd, APPLICATION_ABOUTTEXT, application.getAboutText());
ontModel); updatePlainLiteralValue(
updatePropertyStringValue(
appInd, APPLICATION_ACKNOWLEGETEXT, appInd, APPLICATION_ACKNOWLEGETEXT,
application.getAcknowledgeText(), ontModel); application.getAcknowledgeText());
updatePropertyStringValue( updatePropertyStringValue(
appInd, APPLICATION_CONTACTMAIL, appInd, APPLICATION_CONTACTMAIL,
application.getContactMail(), ontModel); application.getContactMail(), ontModel);
updatePropertyStringValue( updatePropertyStringValue(
appInd, APPLICATION_CORRECTIONMAIL, appInd, APPLICATION_CORRECTIONMAIL,
application.getCorrectionMail(), ontModel); application.getCorrectionMail(), ontModel);
updatePropertyStringValue( updatePlainLiteralValue(
appInd, APPLICATION_COPYRIGHTANCHOR, appInd, APPLICATION_COPYRIGHTANCHOR,
application.getCopyrightAnchor(), ontModel); application.getCopyrightAnchor());
updatePropertyStringValue( updatePropertyStringValue(
appInd, APPLICATION_COPYRIGHTURL, appInd, APPLICATION_COPYRIGHTURL,
application.getCopyrightURL(), ontModel); application.getCopyrightURL(), ontModel);

View file

@ -516,9 +516,9 @@ public class DataPropertyDaoJena extends PropertyDaoJena implements
if (dtp.getFunctional()) { if (dtp.getFunctional()) {
ontModel.add(jDataprop,RDF.type,OWL.FunctionalProperty); ontModel.add(jDataprop,RDF.type,OWL.FunctionalProperty);
} }
addPropertyStringValue(jDataprop, EXAMPLE, dtp.getExample(), ontModel); updatePlainLiteralValue(jDataprop, EXAMPLE, dtp.getExample());
addPropertyStringValue(jDataprop, DESCRIPTION_ANNOT, dtp.getDescription(), ontModel); updatePlainLiteralValue(jDataprop, DESCRIPTION_ANNOT, dtp.getDescription());
addPropertyStringValue(jDataprop, PUBLIC_DESCRIPTION_ANNOT, dtp.getPublicDescription(), ontModel); updatePlainLiteralValue(jDataprop, PUBLIC_DESCRIPTION_ANNOT, dtp.getPublicDescription());
addPropertyStringValue(jDataprop, EDITING, dtp.getEditing(), ontModel); addPropertyStringValue(jDataprop, EDITING, dtp.getEditing(), ontModel);
addPropertyNonNegativeIntValue(jDataprop, DISPLAY_RANK_ANNOT, dtp.getDisplayTier(), ontModel); addPropertyNonNegativeIntValue(jDataprop, DISPLAY_RANK_ANNOT, dtp.getDisplayTier(), ontModel);
addPropertyNonNegativeIntValue(jDataprop, DISPLAY_LIMIT, dtp.getDisplayLimit(), ontModel); addPropertyNonNegativeIntValue(jDataprop, DISPLAY_LIMIT, dtp.getDisplayLimit(), ontModel);
@ -587,9 +587,9 @@ public class DataPropertyDaoJena extends PropertyDaoJena implements
} }
} }
updatePropertyStringValue(jDataprop, EXAMPLE, dtp.getExample(), ontModel); updatePlainLiteralValue(jDataprop, EXAMPLE, dtp.getExample());
updatePropertyStringValue(jDataprop, DESCRIPTION_ANNOT, dtp.getDescription(), ontModel); updatePlainLiteralValue(jDataprop, DESCRIPTION_ANNOT, dtp.getDescription());
updatePropertyStringValue(jDataprop, PUBLIC_DESCRIPTION_ANNOT, dtp.getPublicDescription(), ontModel); updatePlainLiteralValue(jDataprop, PUBLIC_DESCRIPTION_ANNOT, dtp.getPublicDescription());
updatePropertyStringValue(jDataprop, EDITING, dtp.getEditing(), ontModel); updatePropertyStringValue(jDataprop, EDITING, dtp.getEditing(), ontModel);
updatePropertyNonNegativeIntValue(jDataprop, DISPLAY_RANK_ANNOT, dtp.getDisplayTier(), ontModel); updatePropertyNonNegativeIntValue(jDataprop, DISPLAY_RANK_ANNOT, dtp.getDisplayTier(), ontModel);
updatePropertyNonNegativeIntValue(jDataprop, DISPLAY_LIMIT, dtp.getDisplayLimit(), ontModel); updatePropertyNonNegativeIntValue(jDataprop, DISPLAY_LIMIT, dtp.getDisplayLimit(), ontModel);

View file

@ -230,10 +230,9 @@ public class FauxPropertyDaoJena extends JenaBaseDao implements FauxPropertyDao
OBJECT_PROPERTY_DISPLAY_CONFIG); OBJECT_PROPERTY_DISPLAY_CONFIG);
addPropertyResourceURINotEmpty(config, PROPERTY_GROUP, addPropertyResourceURINotEmpty(config, PROPERTY_GROUP,
fp.getGroupURI()); fp.getGroupURI());
addPropertyStringValue(config, DISPLAY_NAME, fp.getDisplayName(), updatePlainLiteralValue(config, DISPLAY_NAME, fp.getDisplayName());
displayModel); updatePlainLiteralValue(config, PUBLIC_DESCRIPTION_ANNOT,
addPropertyStringValue(config, PUBLIC_DESCRIPTION_ANNOT, fp.getPublicDescription());
fp.getPublicDescription(), displayModel);
addPropertyIntValue(config, DISPLAY_RANK_ANNOT, addPropertyIntValue(config, DISPLAY_RANK_ANNOT,
fp.getDisplayTier(), displayModel); fp.getDisplayTier(), displayModel);
addPropertyIntValue(config, DISPLAY_LIMIT, fp.getDisplayLimit(), addPropertyIntValue(config, DISPLAY_LIMIT, fp.getDisplayLimit(),
@ -328,10 +327,10 @@ public class FauxPropertyDaoJena extends JenaBaseDao implements FauxPropertyDao
.getConfigUri()); .getConfigUri());
updatePropertyResourceURIValue(config, PROPERTY_GROUP, updatePropertyResourceURIValue(config, PROPERTY_GROUP,
fp.getGroupURI()); fp.getGroupURI());
updatePropertyStringValue(config, DISPLAY_NAME, updatePlainLiteralValue(config, DISPLAY_NAME,
fp.getDisplayName(), displayModel); fp.getDisplayName());
updatePropertyStringValue(config, PUBLIC_DESCRIPTION_ANNOT, updatePlainLiteralValue(config, PUBLIC_DESCRIPTION_ANNOT,
fp.getPublicDescription(), displayModel); fp.getPublicDescription());
updatePropertyIntValue(config, DISPLAY_RANK_ANNOT, updatePropertyIntValue(config, DISPLAY_RANK_ANNOT,
fp.getDisplayTier(), displayModel); fp.getDisplayTier(), displayModel);
updatePropertyIntValue(config, DISPLAY_LIMIT, fp.getDisplayLimit(), updatePropertyIntValue(config, DISPLAY_LIMIT, fp.getDisplayLimit(),

View file

@ -5,8 +5,8 @@ package edu.cornell.mannlib.vitro.webapp.dao.jena;
import java.text.DateFormat; import java.text.DateFormat;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.Date; import java.util.Date;
import java.util.HashSet; import java.util.HashSet;
@ -14,14 +14,14 @@ import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.apache.jena.iri.IRI;
import org.apache.jena.iri.IRIFactory;
import org.apache.jena.datatypes.xsd.XSDDatatype; import org.apache.jena.datatypes.xsd.XSDDatatype;
import org.apache.jena.graph.Node; import org.apache.jena.graph.Node;
import org.apache.jena.graph.NodeFactory; import org.apache.jena.graph.NodeFactory;
import org.apache.jena.iri.IRI;
import org.apache.jena.iri.IRIFactory;
import org.apache.jena.ontology.DatatypeProperty; import org.apache.jena.ontology.DatatypeProperty;
import org.apache.jena.ontology.ObjectProperty; import org.apache.jena.ontology.ObjectProperty;
import org.apache.jena.ontology.OntClass; import org.apache.jena.ontology.OntClass;
@ -39,6 +39,7 @@ import org.apache.jena.rdf.model.NodeIterator;
import org.apache.jena.rdf.model.Property; import org.apache.jena.rdf.model.Property;
import org.apache.jena.rdf.model.RDFNode; import org.apache.jena.rdf.model.RDFNode;
import org.apache.jena.rdf.model.Resource; import org.apache.jena.rdf.model.Resource;
import org.apache.jena.rdf.model.ResourceFactory;
import org.apache.jena.rdf.model.Statement; import org.apache.jena.rdf.model.Statement;
import org.apache.jena.rdf.model.StmtIterator; import org.apache.jena.rdf.model.StmtIterator;
import org.apache.jena.shared.Lock; import org.apache.jena.shared.Lock;
@ -754,21 +755,110 @@ public class JenaBaseDao extends JenaBaseDaoCon {
} }
/** /**
* convenience method for updating the RDFS label * Add to an OntResource an rdfs:label value with lexical form and default
* language tag. Remove any other existing values in default language.
* If lexicalForm parameter is null, remove all plain literal values of
* Property in default language.
* @param ontRes may not be null
* @param lexicalForm may be null. If null, existing values will be deleted
* but none will be added.
*/ */
protected void updateRDFSLabel(OntResource ontRes, String label) { protected void updateRDFSLabel(OntResource ontRes, String lexicalForm) {
updatePlainLiteralValue(ontRes, RDFS.label, lexicalForm);
if (label != null && label.length() > 0) {
String existingValue = ontRes.getLabel(getDefaultLanguage());
if (existingValue == null || !existingValue.equals(label)) {
ontRes.setLabel(label, getDefaultLanguage());
} }
/**
* Add to an OntResource an rdfs:label value with lexical form and optional
* language tag. Remove any other existing plain literal values that match
* specified language or lack language tags if no language is supplied.
* If lexicalForm parameter is null, remove all plain literal labels in
* specified language, or all existing language-less labels
* if no language is specified.
* @param ontRes may not be null
* @param lexicalForm may be null. If null, existing values will be deleted
* but none will be added.
* @param lang may be null. If null, method acts on language-less plain
* literal labels and ignores those with language tags.
*/
protected void updateRDFSLabel(OntResource ontRes, String lexicalForm, String lang) {
updatePlainLiteralValue(ontRes, RDFS.label, lexicalForm, lang);
}
/**
* Add to an OntResource a Property value with lexical form and default
* language tag. Remove any other existing values in default language.
* If lexicalForm parameter is null, remove all plain literal values of
* Property in default language.
* @param ontRes may not be null
* @param lexicalForm may be null. If null, existing values will be deleted
* but none will be added.
*/
protected void updatePlainLiteralValue(OntResource ontRes, Property property,
String lexicalForm) {
updatePlainLiteralValue(ontRes, property, lexicalForm, getDefaultLanguage());
}
/**
* Add to an OntResource a Property value with lexical form and optional
* language tag. Remove any other existing plain literal values that match
* specified language or lack language tags if no language is supplied.
* If lexicalForm parameter is null, remove all plain literal values of
* Property in specified language, or all existing language-less literals
* if no language is specified.
* @param ontRes may not be null
* @param lexicalForm may be null. If null, existing values will be deleted
* but none will be added.
* @param lang may be null. If null, method acts on language-less
* plain literal values and ignores those with language tags.
*/
protected void updatePlainLiteralValue(OntResource ontRes, Property property,
String lexicalForm, String lang) {
if(ontRes == null) {
throw new IllegalArgumentException("ontRes may not be null.");
}
boolean addNew = true;
List<Statement> toRemove = new ArrayList<Statement>();
StmtIterator existingStmts = ontRes.listProperties(property);
while(existingStmts.hasNext()) {
Statement stmt = existingStmts.next();
if(stmt.getObject().isLiteral()) {
Literal lit = stmt.getObject().asLiteral();
if( (lang == null && isLanguageLessPlainLiteral(lit))
|| (lang != null && lang.equals(lit.getLanguage())) ) {
if(!lit.getLexicalForm().equals(lexicalForm)) {
toRemove.add(stmt);
} else { } else {
ontRes.removeAll(RDFS.label); // New literal already exists in the model.
// Do not add it again.
addNew = false;
} }
} }
}
}
if(!toRemove.isEmpty()) {
ontRes.getModel().remove(toRemove);
}
if (addNew && (lexicalForm != null)) {
if(!StringUtils.isEmpty(lang)) {
ontRes.addProperty(property, ResourceFactory.createLangLiteral(
lexicalForm, lang));
} else {
ontRes.addProperty(property, ResourceFactory.createPlainLiteral(
lexicalForm));
}
}
}
private boolean isLanguageLessPlainLiteral(Literal lit) {
// In RDF 1.1 all the language-less literals get datatype xsd:string.
// The null datatype check is here just in case this gets run on an older
// version of Jena. rdf:PlainLiteral is also a datatype, but doesn't
// (yet) seem to be used by Jena.
return StringUtils.isEmpty(lit.getLanguage())
&& ((lit.getDatatype() == null)
|| XSDDatatype.XSDstring.equals(lit.getDatatype()) ||
(RDF.getURI() + "PlainLiteral").equals(lit.getDatatypeURI()));
}
private Literal getLabel(String lang, List<RDFNode>labelList) { private Literal getLabel(String lang, List<RDFNode>labelList) {
for (RDFNode label : labelList) { for (RDFNode label : labelList) {
@ -780,6 +870,13 @@ public class JenaBaseDao extends JenaBaseDaoCon {
} }
if ((lang != null) && (lang.equals(labelLanguage))) { if ((lang != null) && (lang.equals(labelLanguage))) {
return labelLit; return labelLit;
} else
/*
* UQAM-Linguistic-Management
* Check for country-part of lang (ex: 'en' for default consideration of labelLanguage in english but not encoded by 'en-US' most case of labels in vivo.owl)
*/
if ((lang != null) && (Arrays.asList(lang.split("-")).get(0).equals(labelLanguage))) {
return labelLit;
} }
} }
} }

View file

@ -121,7 +121,6 @@ public class JenaBaseDaoCon {
protected DatatypeProperty USERACCOUNT_LAST_LOGIN_TIME = _constModel.createDatatypeProperty(VitroVocabulary.USERACCOUNT_LAST_LOGIN_TIME); protected DatatypeProperty USERACCOUNT_LAST_LOGIN_TIME = _constModel.createDatatypeProperty(VitroVocabulary.USERACCOUNT_LAST_LOGIN_TIME);
protected DatatypeProperty USERACCOUNT_STATUS = _constModel.createDatatypeProperty(VitroVocabulary.USERACCOUNT_STATUS); protected DatatypeProperty USERACCOUNT_STATUS = _constModel.createDatatypeProperty(VitroVocabulary.USERACCOUNT_STATUS);
protected DatatypeProperty USERACCOUNT_PASSWORD_LINK_EXPIRES = _constModel.createDatatypeProperty(VitroVocabulary.USERACCOUNT_PASSWORD_LINK_EXPIRES); protected DatatypeProperty USERACCOUNT_PASSWORD_LINK_EXPIRES = _constModel.createDatatypeProperty(VitroVocabulary.USERACCOUNT_PASSWORD_LINK_EXPIRES);
protected DatatypeProperty USERACCOUNT_EMAIL_KEY = _constModel.createDatatypeProperty(VitroVocabulary.USERACCOUNT_EMAIL_KEY);
protected DatatypeProperty USERACCOUNT_PASSWORD_CHANGE_REQUIRED = _constModel.createDatatypeProperty(VitroVocabulary.USERACCOUNT_PASSWORD_CHANGE_REQUIRED); protected DatatypeProperty USERACCOUNT_PASSWORD_CHANGE_REQUIRED = _constModel.createDatatypeProperty(VitroVocabulary.USERACCOUNT_PASSWORD_CHANGE_REQUIRED);
protected DatatypeProperty USERACCOUNT_EXTERNAL_AUTH_ID = _constModel.createDatatypeProperty(VitroVocabulary.USERACCOUNT_EXTERNAL_AUTH_ID); protected DatatypeProperty USERACCOUNT_EXTERNAL_AUTH_ID = _constModel.createDatatypeProperty(VitroVocabulary.USERACCOUNT_EXTERNAL_AUTH_ID);
protected DatatypeProperty USERACCOUNT_EXTERNAL_AUTH_ONLY = _constModel.createDatatypeProperty(VitroVocabulary.USERACCOUNT_EXTERNAL_AUTH_ONLY); protected DatatypeProperty USERACCOUNT_EXTERNAL_AUTH_ONLY = _constModel.createDatatypeProperty(VitroVocabulary.USERACCOUNT_EXTERNAL_AUTH_ONLY);

View file

@ -72,6 +72,7 @@ public class MenuDaoJena extends JenaBaseDao implements MenuDao {
return getMenu( getOntModelSelector().getDisplayModel(), url ); return getMenu( getOntModelSelector().getDisplayModel(), url );
} }
@Override
public MainMenu getMainMenu( ServletRequest req, String url ) { public MainMenu getMainMenu( ServletRequest req, String url ) {
OntModel displayModel = LanguageFilteringUtils.wrapOntModelInALanguageFilter(getOntModelSelector().getDisplayModel(), req ); OntModel displayModel = LanguageFilteringUtils.wrapOntModelInALanguageFilter(getOntModelSelector().getDisplayModel(), req );
return getMenu(displayModel, url) ; return getMenu(displayModel, url) ;

View file

@ -714,14 +714,14 @@ public class ObjectPropertyDaoJena extends PropertyDaoJena implements ObjectProp
} }
} }
updatePropertyStringValue(p,EXAMPLE_ANNOT,prop.getExample(),getOntModel()); updatePlainLiteralValue(p, EXAMPLE_ANNOT, prop.getExample());
updatePropertyStringValue(p,DESCRIPTION_ANNOT,prop.getDescription(),getOntModel()); updatePlainLiteralValue(p, DESCRIPTION_ANNOT, prop.getDescription());
updatePropertyStringValue(p,PUBLIC_DESCRIPTION_ANNOT,prop.getPublicDescription(),getOntModel()); updatePlainLiteralValue(p, PUBLIC_DESCRIPTION_ANNOT, prop.getPublicDescription());
updatePropertyNonNegativeIntegerValue(p,DISPLAY_LIMIT,prop.getDomainDisplayLimitInteger(),getOntModel()); updatePropertyNonNegativeIntegerValue(p,DISPLAY_LIMIT,prop.getDomainDisplayLimitInteger(),getOntModel());
updatePropertyStringValue(p,PROPERTY_ENTITYSORTDIRECTION,prop.getDomainEntitySortDirection(),getOntModel()); updatePropertyStringValue(p,PROPERTY_ENTITYSORTDIRECTION,prop.getDomainEntitySortDirection(),getOntModel());
if (inv != null) { if (inv != null) {
updatePropertyStringValue(inv,EXAMPLE_ANNOT,prop.getExample(),getOntModel()); updatePlainLiteralValue(inv, EXAMPLE_ANNOT, prop.getExample());
updatePropertyStringValue(inv,DESCRIPTION_ANNOT,prop.getDescription(),getOntModel()); updatePlainLiteralValue(inv, DESCRIPTION_ANNOT, prop.getDescription());
updatePropertyNonNegativeIntegerValue(inv,DISPLAY_LIMIT,prop.getRangeDisplayLimitInteger(),getOntModel()); updatePropertyNonNegativeIntegerValue(inv,DISPLAY_LIMIT,prop.getRangeDisplayLimitInteger(),getOntModel());
updatePropertyStringValue(inv,PROPERTY_ENTITYSORTDIRECTION,prop.getRangeEntitySortDirection(),getOntModel()); updatePropertyStringValue(inv,PROPERTY_ENTITYSORTDIRECTION,prop.getRangeEntitySortDirection(),getOntModel());
} }

View file

@ -12,10 +12,10 @@ import java.util.function.Supplier;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.apache.jena.graph.Capabilities; import org.apache.jena.graph.Capabilities;
import org.apache.jena.graph.Graph; import org.apache.jena.graph.Graph;
import org.apache.jena.graph.GraphEventManager; import org.apache.jena.graph.GraphEventManager;
import org.apache.jena.graph.GraphListener;
import org.apache.jena.graph.GraphStatisticsHandler; import org.apache.jena.graph.GraphStatisticsHandler;
import org.apache.jena.graph.Node; import org.apache.jena.graph.Node;
import org.apache.jena.graph.TransactionHandler; import org.apache.jena.graph.TransactionHandler;
@ -23,6 +23,7 @@ import org.apache.jena.graph.Triple;
import org.apache.jena.graph.impl.GraphWithPerform; import org.apache.jena.graph.impl.GraphWithPerform;
import org.apache.jena.graph.impl.SimpleEventManager; import org.apache.jena.graph.impl.SimpleEventManager;
import org.apache.jena.query.QuerySolution; import org.apache.jena.query.QuerySolution;
import org.apache.jena.rdf.listeners.StatementListener;
import org.apache.jena.rdf.model.Model; import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ModelFactory; import org.apache.jena.rdf.model.ModelFactory;
import org.apache.jena.rdf.model.StmtIterator; import org.apache.jena.rdf.model.StmtIterator;
@ -289,10 +290,15 @@ public class RDFServiceGraph implements GraphWithPerform {
literalBuff.append("\""); literalBuff.append("\"");
pyString(literalBuff, node.getLiteralLexicalForm()); pyString(literalBuff, node.getLiteralLexicalForm());
literalBuff.append("\""); literalBuff.append("\"");
if (node.getLiteralDatatypeURI() != null) { /*
literalBuff.append("^^<").append(node.getLiteralDatatypeURI()).append(">"); * UQAM-Bug-Correction
} else if (!StringUtils.isEmpty(node.getLiteralLanguage())) { * reversing the condition tests.
* It is important to prioritize the language typology test in order to exploit the linguistic context in testing the type of data
*/
if (!StringUtils.isEmpty(node.getLiteralLanguage())) {
literalBuff.append("@").append(node.getLiteralLanguage()); literalBuff.append("@").append(node.getLiteralLanguage());
} else if (node.getLiteralDatatypeURI() != null) {
literalBuff.append("^^<").append(node.getLiteralDatatypeURI()).append(">");
} }
return literalBuff.toString(); return literalBuff.toString();
} else { } else {
@ -403,18 +409,7 @@ public class RDFServiceGraph implements GraphWithPerform {
@Override @Override
public GraphEventManager getEventManager() { public GraphEventManager getEventManager() {
if (eventManager == null) { if (eventManager == null) {
eventManager = new SimpleEventManager() { eventManager = new SimpleEventManager(this);
@Override
public void notifyEvent(Graph g, Object event) {
ChangeSet changeSet = rdfService.manufactureChangeSet();
changeSet.addPreChangeEvent(event);
try {
rdfService.changeSetUpdate(changeSet);
} catch (RDFServiceException e) {
throw new RuntimeException(e);
}
}
};
} }
return eventManager; return eventManager;
} }
@ -600,7 +595,21 @@ public class RDFServiceGraph implements GraphWithPerform {
} }
public static Model createRDFServiceModel(final RDFServiceGraph g) { public static Model createRDFServiceModel(final RDFServiceGraph g) {
return VitroModelFactory.createModelForGraph(g); Model m = VitroModelFactory.createModelForGraph(g);
m.register(new StatementListener() {
@Override
public void notifyEvent(Model m, Object event) {
ChangeSet changeSet = g.getRDFService().manufactureChangeSet();
changeSet.addPreChangeEvent(event);
try {
g.getRDFService().changeSetUpdate(changeSet);
} catch (RDFServiceException e) {
throw new RuntimeException(e);
}
}
});
return m;
} }
@Override @Override

View file

@ -232,10 +232,10 @@ public class SparqlGraph implements GraphWithPerform {
literalBuff.append("\""); literalBuff.append("\"");
pyString(literalBuff, node.getLiteralLexicalForm()); pyString(literalBuff, node.getLiteralLexicalForm());
literalBuff.append("\""); literalBuff.append("\"");
if (node.getLiteralDatatypeURI() != null) { if (!StringUtils.isEmpty(node.getLiteralLanguage())) {
literalBuff.append("^^<").append(node.getLiteralDatatypeURI()).append(">");
} else if (!StringUtils.isEmpty(node.getLiteralLanguage())) {
literalBuff.append("@").append(node.getLiteralLanguage()); literalBuff.append("@").append(node.getLiteralLanguage());
} else if (node.getLiteralDatatypeURI() != null) {
literalBuff.append("^^<").append(node.getLiteralDatatypeURI()).append(">");
} }
return literalBuff.toString(); return literalBuff.toString();
} else { } else {

View file

@ -4,6 +4,7 @@ package edu.cornell.mannlib.vitro.webapp.dao.jena;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.Random;
@ -97,8 +98,6 @@ public class UserAccountsDaoJena extends JenaBaseDao implements UserAccountsDao
u.setOldPassword(getPropertyStringValue(r, USERACCOUNT_OLD_PASSWORD)); u.setOldPassword(getPropertyStringValue(r, USERACCOUNT_OLD_PASSWORD));
u.setPasswordLinkExpires(getPropertyLongValue(r, u.setPasswordLinkExpires(getPropertyLongValue(r,
USERACCOUNT_PASSWORD_LINK_EXPIRES)); USERACCOUNT_PASSWORD_LINK_EXPIRES));
u.setEmailKey(getPropertyStringValue(r,USERACCOUNT_EMAIL_KEY));
u.setPasswordChangeRequired(getPropertyBooleanValue(r, u.setPasswordChangeRequired(getPropertyBooleanValue(r,
USERACCOUNT_PASSWORD_CHANGE_REQUIRED)); USERACCOUNT_PASSWORD_CHANGE_REQUIRED));
u.setExternalAuthOnly(getPropertyBooleanValue(r, u.setExternalAuthOnly(getPropertyBooleanValue(r,
@ -241,8 +240,6 @@ public class UserAccountsDaoJena extends JenaBaseDao implements UserAccountsDao
userAccount.getLoginCount(), model); userAccount.getLoginCount(), model);
addPropertyLongValue(res, USERACCOUNT_LAST_LOGIN_TIME, addPropertyLongValue(res, USERACCOUNT_LAST_LOGIN_TIME,
userAccount.getLastLoginTime(), model); userAccount.getLastLoginTime(), model);
addPropertyStringValue(res, USERACCOUNT_EMAIL_KEY,
userAccount.getEmailKey(), model);
if (userAccount.getStatus() != null) { if (userAccount.getStatus() != null) {
addPropertyStringValue(res, USERACCOUNT_STATUS, userAccount addPropertyStringValue(res, USERACCOUNT_STATUS, userAccount
.getStatus().toString(), model); .getStatus().toString(), model);
@ -309,8 +306,6 @@ public class UserAccountsDaoJena extends JenaBaseDao implements UserAccountsDao
userAccount.getLoginCount(), model); userAccount.getLoginCount(), model);
updatePropertyLongValue(res, USERACCOUNT_LAST_LOGIN_TIME, updatePropertyLongValue(res, USERACCOUNT_LAST_LOGIN_TIME,
userAccount.getLastLoginTime(), model); userAccount.getLastLoginTime(), model);
updatePropertyStringValue(res, USERACCOUNT_EMAIL_KEY,
userAccount.getEmailKey(), model);
if (userAccount.getStatus() == null) { if (userAccount.getStatus() == null) {
updatePropertyStringValue(res, USERACCOUNT_STATUS, null, model); updatePropertyStringValue(res, USERACCOUNT_STATUS, null, model);
} else { } else {

View file

@ -2,6 +2,8 @@
package edu.cornell.mannlib.vitro.webapp.dao.jena; package edu.cornell.mannlib.vitro.webapp.dao.jena;
import static java.lang.String.format;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
@ -60,15 +62,18 @@ import edu.cornell.mannlib.vitro.webapp.dao.OntologyDao;
import edu.cornell.mannlib.vitro.webapp.dao.VClassDao; import edu.cornell.mannlib.vitro.webapp.dao.VClassDao;
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary; import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
import edu.cornell.mannlib.vitro.webapp.dao.jena.event.EditEvent; import edu.cornell.mannlib.vitro.webapp.dao.jena.event.EditEvent;
import edu.cornell.mannlib.vitro.webapp.i18n.I18nBundle;
import edu.cornell.mannlib.vitro.webapp.web.URLEncoder; import edu.cornell.mannlib.vitro.webapp.web.URLEncoder;
public class VClassDaoJena extends JenaBaseDao implements VClassDao { public class VClassDaoJena extends JenaBaseDao implements VClassDao {
protected static final Log log = LogFactory.getLog(VClassDaoJena.class); protected static final Log log = LogFactory.getLog(VClassDaoJena.class);
private final I18nBundle i18n;
private boolean isUnderlyingStoreReasoned = false; private boolean isUnderlyingStoreReasoned = false;
public VClassDaoJena(WebappDaoFactoryJena wadf, boolean isUnderlyingStoreReasoned) { public VClassDaoJena(WebappDaoFactoryJena wadf, boolean isUnderlyingStoreReasoned) {
super(wadf); super(wadf);
this.i18n = wadf.getI18nBundle();
this.isUnderlyingStoreReasoned = isUnderlyingStoreReasoned; this.isUnderlyingStoreReasoned = isUnderlyingStoreReasoned;
} }
@ -91,17 +96,19 @@ public class VClassDaoJena extends JenaBaseDao implements VClassDao {
Restriction rest = cls.asRestriction(); Restriction rest = cls.asRestriction();
OntProperty onProperty = rest.getOnProperty(); OntProperty onProperty = rest.getOnProperty();
StringBuilder labelStr = new StringBuilder(); StringBuilder labelStr = new StringBuilder();
labelStr.append("restriction on ").append(getLabelOrId(onProperty)).append(": "); labelStr.append(format("%s ", i18n.text("restriction_on")))
.append(getLabelOrId(onProperty))
.append(": ");
if (rest.isAllValuesFromRestriction() || rest.isSomeValuesFromRestriction()) { if (rest.isAllValuesFromRestriction() || rest.isSomeValuesFromRestriction()) {
Resource fillerRes = null; Resource fillerRes = null;
if (rest.isAllValuesFromRestriction()) { if (rest.isAllValuesFromRestriction()) {
AllValuesFromRestriction avfRest = rest.asAllValuesFromRestriction(); AllValuesFromRestriction avfRest = rest.asAllValuesFromRestriction();
fillerRes = avfRest.getAllValuesFrom(); fillerRes = avfRest.getAllValuesFrom();
labelStr.append("all values from "); labelStr.append(format("%s ", i18n.text("all_values_from")));
} else { } else {
SomeValuesFromRestriction svfRest = rest.asSomeValuesFromRestriction(); SomeValuesFromRestriction svfRest = rest.asSomeValuesFromRestriction();
fillerRes = svfRest.getSomeValuesFrom(); fillerRes = svfRest.getSomeValuesFrom();
labelStr.append("some values from "); labelStr.append(format("%s ", i18n.text("some_values_from")));
} }
if (fillerRes.canAs(OntClass.class)) { if (fillerRes.canAs(OntClass.class)) {
OntClass avf = fillerRes.as(OntClass.class); OntClass avf = fillerRes.as(OntClass.class);
@ -115,7 +122,7 @@ public class VClassDaoJena extends JenaBaseDao implements VClassDao {
} }
} else if (rest.isHasValueRestriction()) { } else if (rest.isHasValueRestriction()) {
HasValueRestriction hvRest = rest.asHasValueRestriction(); HasValueRestriction hvRest = rest.asHasValueRestriction();
labelStr.append("has value "); labelStr.append(format("%s ", i18n.text("has_value")));
RDFNode fillerNode = hvRest.getHasValue(); RDFNode fillerNode = hvRest.getHasValue();
try { try {
if (fillerNode.isResource()) { if (fillerNode.isResource()) {
@ -128,22 +135,22 @@ public class VClassDaoJena extends JenaBaseDao implements VClassDao {
} }
} else if (rest.isMinCardinalityRestriction()) { } else if (rest.isMinCardinalityRestriction()) {
MinCardinalityRestriction mcRest = rest.asMinCardinalityRestriction(); MinCardinalityRestriction mcRest = rest.asMinCardinalityRestriction();
labelStr.append("minimum cardinality "); labelStr.append(format("%s ", i18n.text("minimum_cardinality")));
labelStr.append(mcRest.getMinCardinality()); labelStr.append(mcRest.getMinCardinality());
} else if (rest.isMaxCardinalityRestriction()) { } else if (rest.isMaxCardinalityRestriction()) {
MaxCardinalityRestriction mcRest = rest.asMaxCardinalityRestriction(); MaxCardinalityRestriction mcRest = rest.asMaxCardinalityRestriction();
labelStr.append("maximum cardinality "); labelStr.append(format("%s ", i18n.text("maximum_cardinality")));
labelStr.append(mcRest.getMaxCardinality()); labelStr.append(mcRest.getMaxCardinality());
} else if (rest.isCardinalityRestriction()) { } else if (rest.isCardinalityRestriction()) {
CardinalityRestriction cRest = rest.asCardinalityRestriction(); CardinalityRestriction cRest = rest.asCardinalityRestriction();
labelStr.append("cardinality "); labelStr.append(format("%s ", i18n.text("cardinality")));
labelStr.append(cRest.getCardinality()); labelStr.append(cRest.getCardinality());
} }
return labelStr.toString(); return labelStr.toString();
} else if (isBooleanClassExpression(cls)) { } else if (isBooleanClassExpression(cls)) {
StringBuilder labelStr = new StringBuilder("("); StringBuilder labelStr = new StringBuilder("(");
if (cls.isComplementClass()) { if (cls.isComplementClass()) {
labelStr.append("not "); labelStr.append(format("%s ", i18n.text("not")));
ComplementClass ccls = cls.as(ComplementClass.class); ComplementClass ccls = cls.as(ComplementClass.class);
labelStr.append(getLabelForClass(ccls.getOperand(), withPrefix, forPickList)); labelStr.append(getLabelForClass(ccls.getOperand(), withPrefix, forPickList));
} else if (cls.isIntersectionClass()) { } else if (cls.isIntersectionClass()) {
@ -153,7 +160,7 @@ public class VClassDaoJena extends JenaBaseDao implements VClassDao {
OntClass operand = operandIt.next(); OntClass operand = operandIt.next();
labelStr.append(getLabelForClass(operand, withPrefix, forPickList)); labelStr.append(getLabelForClass(operand, withPrefix, forPickList));
if (operandIt.hasNext()) { if (operandIt.hasNext()) {
labelStr.append(" and "); labelStr.append(format(" %s ", i18n.text("and")));
} }
} }
} else if (cls.isUnionClass()) { } else if (cls.isUnionClass()) {
@ -163,7 +170,7 @@ public class VClassDaoJena extends JenaBaseDao implements VClassDao {
OntClass operand = operandIt.next(); OntClass operand = operandIt.next();
labelStr.append(getLabelForClass(operand, withPrefix, forPickList)); labelStr.append(getLabelForClass(operand, withPrefix, forPickList));
if (operandIt.hasNext()) { if (operandIt.hasNext()) {
labelStr.append(" or "); labelStr.append(format(" %s ", i18n.text("or")));
} }
} }
} }
@ -952,9 +959,9 @@ public class VClassDaoJena extends JenaBaseDao implements VClassDao {
} catch (Exception e) { } catch (Exception e) {
log.error("error linking class "+cls.getURI()+" to class group"); log.error("error linking class "+cls.getURI()+" to class group");
} }
addPropertyStringValue(ontCls,SHORTDEF,cls.getShortDef(),ontModel); updatePlainLiteralValue(ontCls, SHORTDEF, cls.getShortDef());
addPropertyStringValue(ontCls,EXAMPLE_ANNOT,cls.getExample(),ontModel); updatePlainLiteralValue(ontCls, EXAMPLE_ANNOT, cls.getExample());
addPropertyStringValue(ontCls,DESCRIPTION_ANNOT,cls.getDescription(),ontModel); updatePlainLiteralValue(ontCls, DESCRIPTION_ANNOT, cls.getDescription());
addPropertyIntValue(ontCls,DISPLAY_LIMIT,cls.getDisplayLimit(),ontModel); addPropertyIntValue(ontCls,DISPLAY_LIMIT,cls.getDisplayLimit(),ontModel);
addPropertyIntValue(ontCls,DISPLAY_RANK_ANNOT,cls.getDisplayRank(),ontModel); addPropertyIntValue(ontCls,DISPLAY_RANK_ANNOT,cls.getDisplayRank(),ontModel);
@ -1011,9 +1018,9 @@ public class VClassDaoJena extends JenaBaseDao implements VClassDao {
if (ontCls != null) { if (ontCls != null) {
updateRDFSLabel(ontCls, cls.getName()); updateRDFSLabel(ontCls, cls.getName());
updatePropertyResourceURIValue(ontCls,IN_CLASSGROUP,cls.getGroupURI(),ontModel); updatePropertyResourceURIValue(ontCls,IN_CLASSGROUP,cls.getGroupURI(),ontModel);
updatePropertyStringValue(ontCls,SHORTDEF,cls.getShortDef(),ontModel); updatePlainLiteralValue(ontCls, SHORTDEF, cls.getShortDef());
updatePropertyStringValue(ontCls,EXAMPLE_ANNOT,cls.getExample(),ontModel); updatePlainLiteralValue(ontCls, EXAMPLE_ANNOT, cls.getExample());
updatePropertyStringValue(ontCls,DESCRIPTION_ANNOT,cls.getDescription(),ontModel); updatePlainLiteralValue(ontCls, DESCRIPTION_ANNOT, cls.getDescription());
updatePropertyNonNegativeIntValue(ontCls,DISPLAY_LIMIT,cls.getDisplayLimit(),ontModel); updatePropertyNonNegativeIntValue(ontCls,DISPLAY_LIMIT,cls.getDisplayLimit(),ontModel);
updatePropertyNonNegativeIntValue(ontCls,DISPLAY_RANK_ANNOT,cls.getDisplayRank(),ontModel); updatePropertyNonNegativeIntValue(ontCls,DISPLAY_RANK_ANNOT,cls.getDisplayRank(),ontModel);
updatePropertyFloatValue(ontCls, SEARCH_BOOST_ANNOT, cls.getSearchBoost(), ontModel); updatePropertyFloatValue(ontCls, SEARCH_BOOST_ANNOT, cls.getSearchBoost(), ontModel);

View file

@ -276,7 +276,7 @@ public class VClassGroupDaoJena extends JenaBaseDao implements VClassGroupDao {
try { try {
Individual groupInd = ontModel.getIndividual(vcg.getURI()); Individual groupInd = ontModel.getIndividual(vcg.getURI());
try { try {
groupInd.setLabel(vcg.getPublicName(), getDefaultLanguage()); updateRDFSLabel(groupInd, vcg.getPublicName(), getDefaultLanguage());
} catch (Exception e) { } catch (Exception e) {
log.error("error updating name for "+groupInd.getURI()); log.error("error updating name for "+groupInd.getURI());
} }

View file

@ -50,6 +50,8 @@ import edu.cornell.mannlib.vitro.webapp.dao.VClassGroupDao;
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary; import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory; import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactoryConfig; import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactoryConfig;
import edu.cornell.mannlib.vitro.webapp.i18n.I18n;
import edu.cornell.mannlib.vitro.webapp.i18n.I18nBundle;
import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelNames; import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelNames;
import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService; import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService;
import edu.cornell.mannlib.vitro.webapp.rdfservice.impl.jena.model.RDFServiceModel; import edu.cornell.mannlib.vitro.webapp.rdfservice.impl.jena.model.RDFServiceModel;
@ -611,5 +613,10 @@ public class WebappDaoFactoryJena implements WebappDaoFactory {
} }
} }
@Override
public I18nBundle getI18nBundle() {
// return context based bundle for preferred locales
return I18n.bundle(config.getPreferredLocales());
}
} }

View file

@ -132,6 +132,11 @@ public class EditLiteral implements Literal {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@Override
public boolean isStmtResource() {
throw new UnsupportedOperationException();
}
public Literal inModel(Model model) { public Literal inModel(Model model) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }

View file

@ -4,7 +4,6 @@ package edu.cornell.mannlib.vitro.webapp.edit.listener.impl;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator;
import java.util.Map; import java.util.Map;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;

View file

@ -24,15 +24,25 @@ import edu.cornell.mannlib.vitro.webapp.beans.Datatype;
import edu.cornell.mannlib.vitro.webapp.dao.jena.DatatypeDaoJena; import edu.cornell.mannlib.vitro.webapp.dao.jena.DatatypeDaoJena;
import edu.cornell.mannlib.vitro.webapp.dao.jena.WebappDaoFactoryJena; import edu.cornell.mannlib.vitro.webapp.dao.jena.WebappDaoFactoryJena;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.fields.FieldVTwo; import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.fields.FieldVTwo;
import edu.cornell.mannlib.vitro.webapp.i18n.I18nBundle;
public class BasicValidationVTwo { public class BasicValidationVTwo {
public final static String REQUIRED_FIELD_EMPTY_MSG = "required_field_empty_msg";
public final static String DATA_NOT_PAST_MSG = "data_not_past_msg";
public final static String INVALID_DATE_FORM_MSG = "invalid_date_form_msg";
public final static String FILE_MUST_BE_ENTERED_MSG = "file_must_be_entered_msg";
public final static String INVALID_URL_MSG = "invalid_url_msg";
private I18nBundle i18n;
Map<String, List<String>> varsToValidations; Map<String, List<String>> varsToValidations;
EditConfigurationVTwo editConfig; EditConfigurationVTwo editConfig;
public BasicValidationVTwo(EditConfigurationVTwo editConfig, MultiValueEditSubmission editSub){ public BasicValidationVTwo(EditConfigurationVTwo editConfig, I18nBundle i18n){
this.editConfig = editConfig; this.editConfig = editConfig;
this.i18n = i18n;
Map<String,List<String>> validatorsForFields = new HashMap<String,List<String>>(); Map<String,List<String>> validatorsForFields = new HashMap<String,List<String>>();
for(String fieldName: editConfig.getFields().keySet()){ for(String fieldName: editConfig.getFields().keySet()){
FieldVTwo field = editConfig.getField(fieldName); FieldVTwo field = editConfig.getField(fieldName);
@ -42,8 +52,9 @@ public class BasicValidationVTwo {
checkValidations(); checkValidations();
} }
public BasicValidationVTwo(Map<String, List<String>> varsToValidations){ public BasicValidationVTwo(Map<String, List<String>> varsToValidations, I18nBundle i18n){
this.varsToValidations = varsToValidations; this.varsToValidations = varsToValidations;
this.i18n = i18n;
checkValidations(); checkValidations();
} }
@ -94,7 +105,7 @@ public class BasicValidationVTwo {
//If no literals and this field was required, this is an error message //If no literals and this field was required, this is an error message
//and can return //and can return
if((literals == null || literals.size() == 0) && isRequiredField) { if((literals == null || literals.size() == 0) && isRequiredField) {
errors.put(name, REQUIRED_FIELD_EMPTY_MSG); errors.put(name, i18n.text(REQUIRED_FIELD_EMPTY_MSG));
break; break;
} }
//Loop through literals if literals exist //Loop through literals if literals exist
@ -113,7 +124,7 @@ public class BasicValidationVTwo {
// incorrectly generate errors. // incorrectly generate errors.
if (isEmpty(value)) { if (isEmpty(value)) {
if (isRequiredField) { if (isRequiredField) {
errors.put(name, REQUIRED_FIELD_EMPTY_MSG); errors.put(name, i18n.text(REQUIRED_FIELD_EMPTY_MSG));
} }
break; break;
} }
@ -154,11 +165,11 @@ public class BasicValidationVTwo {
private String validate(String validationType, List<FileItem> fileItems) { private String validate(String validationType, List<FileItem> fileItems) {
if( "nonempty".equalsIgnoreCase(validationType)){ if( "nonempty".equalsIgnoreCase(validationType)){
if( fileItems == null || fileItems.size() == 0 ){ if( fileItems == null || fileItems.size() == 0 ){
return "a file must be entered for this field."; return i18n.text(FILE_MUST_BE_ENTERED_MSG);
}else{ }else{
FileItem fileItem = fileItems.get(0); FileItem fileItem = fileItems.get(0);
if( fileItem == null || fileItem.getName() == null || fileItem.getName().length() < 1 || fileItem.getSize() < 0){ if( fileItem == null || fileItem.getName() == null || fileItem.getName().length() < 1 || fileItem.getSize() < 0){
return "a file must be entered for this field."; return i18n.text(FILE_MUST_BE_ENTERED_MSG);
} }
} }
} }
@ -174,14 +185,14 @@ public class BasicValidationVTwo {
// This case may be needed for validation of other field types. // This case may be needed for validation of other field types.
if( "nonempty".equalsIgnoreCase(validationType)){ if( "nonempty".equalsIgnoreCase(validationType)){
if( isEmpty(value) ) if( isEmpty(value) )
return REQUIRED_FIELD_EMPTY_MSG; return i18n.text(REQUIRED_FIELD_EMPTY_MSG);
} }
// Format validation // Format validation
else if("isDate".equalsIgnoreCase(validationType)){ else if("isDate".equalsIgnoreCase(validationType)){
if( isDate( value)) if( isDate( value))
return SUCCESS; return SUCCESS;
else else
return "must be in valid date format mm/dd/yyyy."; return i18n.text(INVALID_DATE_FORM_MSG);
} }
else if( validationType.indexOf("datatype:") == 0 ) { else if( validationType.indexOf("datatype:") == 0 ) {
String datatypeURI = validationType.substring(9); String datatypeURI = validationType.substring(9);
@ -194,7 +205,7 @@ public class BasicValidationVTwo {
} else if ("httpUrl".equalsIgnoreCase(validationType)){ } else if ("httpUrl".equalsIgnoreCase(validationType)){
//check if it has http or https, we could do more but for now this is all. //check if it has http or https, we could do more but for now this is all.
if(! value.startsWith("http://") && ! value.startsWith("https://") ){ if(! value.startsWith("http://") && ! value.startsWith("https://") ){
return "This URL must start with http:// or https://"; return i18n.text(INVALID_URL_MSG);
}else{ }else{
return SUCCESS; return SUCCESS;
} }
@ -216,7 +227,7 @@ public class BasicValidationVTwo {
dayParamStr = value.substring(monthDash + 1, value.length()); dayParamStr = value.substring(monthDash + 1, value.length());
inputC.set(Integer.parseInt(yearParamStr), Integer.parseInt(monthParamStr) - 1, Integer.parseInt(dayParamStr)); inputC.set(Integer.parseInt(yearParamStr), Integer.parseInt(monthParamStr) - 1, Integer.parseInt(dayParamStr));
if(inputC.before(c)) { if(inputC.before(c)) {
return this.DATE_NOT_PAST_MSG; return i18n.text(DATA_NOT_PAST_MSG);
//Returning null makes the error message "field is empty" display instead //Returning null makes the error message "field is empty" display instead
//return null; //return null;
} else { } else {
@ -278,14 +289,9 @@ public class BasicValidationVTwo {
return (value == null || value.trim().length() == 0); return (value == null || value.trim().length() == 0);
} }
private static Pattern urlRX = Pattern.compile("(([a-zA-Z][0-9a-zA-Z+\\-\\.]*:)/{0,2}[0-9a-zA-Z;/?:@&=+$\\.\\-_!~*'()%]+)(#[0-9a-zA-Z;/?:@&=+$\\.\\-_!~*'()%]+)?");
/** we use null to indicate success */ /** we use null to indicate success */
public final static String SUCCESS = null; public final static String SUCCESS = null;
public final static String REQUIRED_FIELD_EMPTY_MSG = "This field must not be empty.";
public final static String DATE_NOT_PAST_MSG = "Please enter a future target date for publication (past dates are invalid).";
//public final static String MIN_FIELDS_NOT_POPULATED = "Please enter values for at least "; //public final static String MIN_FIELDS_NOT_POPULATED = "Please enter values for at least ";
//public final static String FORM_ERROR_FIELD_ID = "formannotationerrors"; //public final static String FORM_ERROR_FIELD_ID = "formannotationerrors";
/** regex for strings like "12/31/2004" */ /** regex for strings like "12/31/2004" */

View file

@ -28,6 +28,7 @@ import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.fields.FieldVTwo; import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.fields.FieldVTwo;
import edu.cornell.mannlib.vitro.webapp.freemarker.config.FreemarkerConfiguration; import edu.cornell.mannlib.vitro.webapp.freemarker.config.FreemarkerConfiguration;
import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess; import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess;
import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess.LanguageOption;
import freemarker.template.Configuration; import freemarker.template.Configuration;
public class EditConfigurationUtils { public class EditConfigurationUtils {
@ -66,17 +67,19 @@ public class EditConfigurationUtils {
} }
public static VClass getRangeVClass(VitroRequest vreq) { public static VClass getRangeVClass(VitroRequest vreq) {
// This needs a WebappDaoFactory with no filtering/RDFService
// funny business because it needs to be able to retrieve anonymous union
// classes by their "pseudo-bnode URIs".
// Someday we'll need to figure out a different way of doing this.
WebappDaoFactory ctxDaoFact = ModelAccess.on( WebappDaoFactory ctxDaoFact = ModelAccess.on(
vreq.getSession().getServletContext()).getWebappDaoFactory(); vreq.getSession().getServletContext()).getWebappDaoFactory();
return ctxDaoFact.getVClassDao().getVClassByURI(getRangeUri(vreq)); return ctxDaoFact.getVClassDao().getVClassByURI(getRangeUri(vreq));
} }
//get individual public static VClass getLangAwardRangeVClass(VitroRequest vreq) {
// UQAM-Linguistic-Management
WebappDaoFactory vreqDaoFact = ModelAccess.on(vreq).getWebappDaoFactory(
LanguageOption.LANGUAGE_AWARE);
return vreqDaoFact.getVClassDao().getVClassByURI(getRangeUri(vreq));
}
//get individual
public static Individual getSubjectIndividual(VitroRequest vreq) { public static Individual getSubjectIndividual(VitroRequest vreq) {
Individual subject = null; Individual subject = null;
String subjectUri = getSubjectUri(vreq); String subjectUri = getSubjectUri(vreq);
@ -126,12 +129,24 @@ public class EditConfigurationUtils {
public static ObjectProperty getObjectPropertyForPredicate(VitroRequest vreq, public static ObjectProperty getObjectPropertyForPredicate(VitroRequest vreq,
String predicateUri, String domainUri, String rangeUri) { String predicateUri, String domainUri, String rangeUri) {
WebappDaoFactory wdf = vreq.getWebappDaoFactory(); // WebappDaoFactory wdf = vreq.getWebappDaoFactory();
// UQAM-Linguistic-Management Use linguistic context
WebappDaoFactory wdf = ModelAccess.on(vreq).getWebappDaoFactory(LanguageOption.LANGUAGE_AWARE);
ObjectProperty objectProp = wdf.getObjectPropertyDao().getObjectPropertyByURIs( ObjectProperty objectProp = wdf.getObjectPropertyDao().getObjectPropertyByURIs(
predicateUri, domainUri, rangeUri); predicateUri, domainUri, rangeUri);
return objectProp; return objectProp;
} }
// UQAM Use linguistic context
public static ObjectProperty getObjectPropertyForPredicateLangAware(VitroRequest vreq,
String predicateUri, String domainUri, String rangeUri) {
// WebappDaoFactory wdf = vreq.getWebappDaoFactory();
// UQAM Use linguistic context
WebappDaoFactory wdf = ModelAccess.on(vreq).getWebappDaoFactory(LanguageOption.LANGUAGE_AWARE);
ObjectProperty objectProp = wdf.getObjectPropertyDao().getObjectPropertyByURIs(
predicateUri, domainUri, rangeUri);
return objectProp;
}
public static DataProperty getDataPropertyForPredicate(VitroRequest vreq, String predicateUri) { public static DataProperty getDataPropertyForPredicate(VitroRequest vreq, String predicateUri) {
WebappDaoFactory wdf = vreq.getWebappDaoFactory(); WebappDaoFactory wdf = vreq.getWebappDaoFactory();
//TODO: Check reason for employing unfiltered webapp dao factory and note if using a different version //TODO: Check reason for employing unfiltered webapp dao factory and note if using a different version
@ -209,6 +224,7 @@ public class EditConfigurationUtils {
return (op != null && dp == null); return (op != null && dp == null);
} }
private static boolean isVitroLabel(String predicateUri) { private static boolean isVitroLabel(String predicateUri) {
return predicateUri.equals(VitroVocabulary.LABEL); return predicateUri.equals(VitroVocabulary.LABEL);
} }

View file

@ -366,6 +366,8 @@ public class EditN3GeneratorVTwo {
{ {
sbuff.append("@") ; sbuff.append("@") ;
sbuff.append(lang) ; sbuff.append(lang) ;
// added by UQAM to exit at this point without adding datatype
return sbuff.toString() ;
} }
// Format the datatype // Format the datatype

View file

@ -10,23 +10,23 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle; import org.apache.commons.lang3.builder.ToStringStyle;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.apache.jena.rdf.model.Literal; import org.apache.jena.rdf.model.Literal;
import org.apache.jena.rdf.model.Model; import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ModelFactory; import org.apache.jena.rdf.model.ModelFactory;
import org.apache.jena.rdf.model.ResourceFactory; import org.apache.jena.rdf.model.ResourceFactory;
import org.apache.jena.vocabulary.XSD; import org.apache.jena.vocabulary.XSD;
import org.apache.jena.vocabulary.RDF;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.edit.EditLiteral; import edu.cornell.mannlib.vitro.webapp.edit.EditLiteral;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.fields.FieldVTwo; import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.fields.FieldVTwo;
import edu.cornell.mannlib.vitro.webapp.i18n.I18n;
public class MultiValueEditSubmission { public class MultiValueEditSubmission {
@ -34,21 +34,31 @@ public class MultiValueEditSubmission {
private Map<String,List<Literal>> literalsFromForm ; private Map<String,List<Literal>> literalsFromForm ;
private Map<String,List<String>> urisFromForm ; private Map<String,List<String>> urisFromForm ;
private Map<String,String> validationErrors; private Map<String,String> validationErrors;
private BasicValidationVTwo basicValidation; private BasicValidationVTwo basicValidation;
private Map<String, List<FileItem>> filesFromForm;
private static Model literalCreationModel; private static Model literalCreationModel;
private String entityToReturnTo; private String entityToReturnTo;
private VitroRequest _vreq;
private static final String TIME_URI = XSD.time.getURI();
static{ static{
literalCreationModel = ModelFactory.createDefaultModel(); literalCreationModel = ModelFactory.createDefaultModel();
} }
/*
public MultiValueEditSubmission(Map<String,String[]> queryParameters, EditConfigurationVTwo editConfig){ * UQAM
* replace
* public MultiValueEditSubmission(Map<String,String[]> queryParameters, EditConfigurationVTwo editConfig)
* by this new signature
* This affect PostEditCleanupController and ProcessRdfFormController classes.
* This replacement is justified by the fact that we need a linguistic context in this class.
*/
public MultiValueEditSubmission(VitroRequest vreq, EditConfigurationVTwo editConfig){
// UQAM add this both lines
_vreq = vreq;
Map<String,String[]> queryParameters = vreq.getParameterMap();
if( editConfig == null ) if( editConfig == null )
throw new Error("EditSubmission needs an EditConfiguration"); throw new Error("EditSubmission needs an EditConfiguration");
this.editKey = editConfig.getEditKey(); this.editKey = editConfig.getEditKey();
@ -92,11 +102,12 @@ public class MultiValueEditSubmission {
processEditElementFields(editConfig,queryParameters); processEditElementFields(editConfig,queryParameters);
//Incorporating basic validation //Incorporating basic validation
//Validate URIS //Validate URIS
this.basicValidation = new BasicValidationVTwo(editConfig, this); this.basicValidation = new BasicValidationVTwo(editConfig, I18n.bundle(vreq));
Map<String,String> errors = basicValidation.validateUris( urisFromForm ); Map<String,String> errors = basicValidation.validateUris( urisFromForm );
//Validate literals and add errors to the list of existing errors //Validate literals and add errors to the list of existing errors
errors.putAll(basicValidation.validateLiterals( literalsFromForm )); errors.putAll(basicValidation.validateLiterals( literalsFromForm ));
if( errors != null ) { // UQAM Add empty contition
if( errors != null && !errors.isEmpty()) {
validationErrors.putAll( errors); validationErrors.putAll( errors);
} }
@ -141,9 +152,8 @@ public class MultiValueEditSubmission {
} }
} }
} }
/* maybe this could be static */ /* maybe this could be static */
public Literal createLiteral(String value, String datatypeUri, String lang) { public Literal createLiteral_ORIG(String value, String datatypeUri, String lang) {
if( datatypeUri != null ){ if( datatypeUri != null ){
if( "http://www.w3.org/2001/XMLSchema:anyURI".equals(datatypeUri) ){ if( "http://www.w3.org/2001/XMLSchema:anyURI".equals(datatypeUri) ){
try { try {
@ -159,12 +169,27 @@ public class MultiValueEditSubmission {
return ResourceFactory.createPlainLiteral(value); return ResourceFactory.createPlainLiteral(value);
} }
private static final String DATE_TIME_URI = XSD.dateTime.getURI(); /* maybe this could be static */
private static final String DATE_URI = XSD.date.getURI(); public Literal createLiteral(String value, String datatypeUri, String lang) {
private static final String TIME_URI = XSD.time.getURI(); if( datatypeUri != null && !datatypeUri.isEmpty() ){
// UQAM Original code contained tow-dots ':' in place of '#'
private static DateTimeFormatter dformater = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:00"); // if( "http://www.w3.org/2001/XMLSchema:anyURI".equals(datatypeUri) ){
private static DateTimeFormatter dateFormater = DateTimeFormat.forPattern("yyyy-MM-dd"); if( XSD.anyURI.getURI().equals(datatypeUri) ){
// try {
// return literalCreationModel.createTypedLiteral( URLEncoder.encode(value, "UTF8"), datatypeUri);
return literalCreationModel.createTypedLiteral( value, datatypeUri);
// } catch (UnsupportedEncodingException e) {
// log.error(e, e);
// }
} else if ( XSD.xstring.getURI().equals(datatypeUri) || RDF.dtLangString.getURI().equals(datatypeUri) ){
if( lang != null && lang.length() > 0 ) return ResourceFactory.createLangLiteral(value, lang);
}
return literalCreationModel.createTypedLiteral(value, datatypeUri);
// UQAM take into account the linguistic context
} else if( lang != null && lang.length() > 0 )
return ResourceFactory.createLangLiteral(value, lang);
return ResourceFactory.createPlainLiteral(value);
}
public Map<String,String> getValidationErrors(){ public Map<String,String> getValidationErrors(){
return validationErrors; return validationErrors;
@ -264,12 +289,46 @@ public class MultiValueEditSubmission {
for(String value:valueList) { for(String value:valueList) {
value = N3EditUtils.stripInvalidXMLChars(value); value = N3EditUtils.stripInvalidXMLChars(value);
//Add to array of literals corresponding to this variable //Add to array of literals corresponding to this variable
/* UQAM OLD
if (!StringUtils.isEmpty(value)) { if (!StringUtils.isEmpty(value)) {
literalsArray.add(createLiteral( literalsArray.add(createLiteral(
value, value,
field.getRangeDatatypeUri(), field.getRangeDatatypeUri(),
field.getRangeLang())); field.getRangeLang()));
} }
*/
/*
* UQAM Replaced by this to take the linguistic context into consideration.
*/
if (!StringUtils.isEmpty(value)) {
String rangeLang = field.getRangeLang(); //UQAM Default value
try {
if (_vreq != null ) {
// only if the request comes from the rdfsLabelGenerator the language should be used
Boolean getLabelLanguage = false;
if (!StringUtils.isBlank(editConfig.formUrl) && editConfig.formUrl.contains("RDFSLabelGenerator")) {
getLabelLanguage = true;
}
// if the language is set in the given Literal, this language-tag should be used and remain the same
// for example when you edit an label with an langauge-tag (no matter which language is selected globally)
if (!StringUtils.isBlank(editConfig.getLiteralsInScope().get("label").get(0).getLanguage()) && getLabelLanguage)
{
rangeLang = editConfig.getLiteralsInScope().get("label").get(0).getLanguage();
} else { // if the literal has no langauge-tag, use the language which is globally selected
rangeLang = _vreq.getLocale().getLanguage();
if (!_vreq.getLocale().getCountry().isEmpty()) {
rangeLang += "-" + _vreq.getLocale().getCountry();
}
}
}
} catch (Exception e) {
}
literalsArray.add(createLiteral(
value,
field.getRangeDatatypeUri(),
rangeLang));
}
} }
literalsFromForm.put(var, literalsArray); literalsFromForm.put(var, literalsArray);

View file

@ -9,15 +9,24 @@ import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.apache.jena.datatypes.xsd.XSDDatatype;
import org.apache.jena.ontology.OntModel; import org.apache.jena.ontology.OntModel;
import org.apache.jena.rdf.model.Literal; import org.apache.jena.rdf.model.Literal;
import org.apache.jena.rdf.model.Model; import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ModelFactory; import org.apache.jena.rdf.model.ModelFactory;
import org.apache.jena.rdf.model.Property;
import org.apache.jena.rdf.model.RDFNode;
import org.apache.jena.rdf.model.Resource;
import org.apache.jena.rdf.model.ResourceFactory;
import org.apache.jena.rdf.model.Statement;
import org.apache.jena.shared.Lock; import org.apache.jena.shared.Lock;
import org.apache.jena.vocabulary.RDF;
import org.apache.jena.vocabulary.XSD;
import org.apache.commons.lang3.StringUtils;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.dao.InsertException; import edu.cornell.mannlib.vitro.webapp.dao.InsertException;
@ -41,6 +50,7 @@ public class ProcessRdfForm {
private EditN3GeneratorVTwo populator; private EditN3GeneratorVTwo populator;
private Map<String,String> urisForNewResources = null; private Map<String,String> urisForNewResources = null;
// private VitroRequest _vreq;
/** /**
* Construct the ProcessRdfForm object. * Construct the ProcessRdfForm object.
*/ */
@ -76,9 +86,9 @@ public class ProcessRdfForm {
AdditionsAndRetractions changes; AdditionsAndRetractions changes;
if( configuration.isUpdate() ){ if( configuration.isUpdate() ){
changes = editExistingStatements(configuration, submission); changes = editExistingStatements(configuration, submission, vreq); //UQAM vreq for getting linguistic context
} else { } else {
changes = createNewStatements(configuration, submission ); changes = createNewStatements(configuration, submission, vreq ); //UQAM vreq for getting linguistic context
} }
changes = getMinimalChanges(changes); changes = getMinimalChanges(changes);
@ -99,12 +109,15 @@ public class ProcessRdfForm {
* any optional N3 is to originally configure the * any optional N3 is to originally configure the
* configuration.setN3Optional() to be empty. * configuration.setN3Optional() to be empty.
* *
* UQAM add vreq for linguistic context managing
*
* @throws Exception May throw an exception if the required N3 * @throws Exception May throw an exception if the required N3
* does not parse. * does not parse.
*
*/ */
private AdditionsAndRetractions createNewStatements( private AdditionsAndRetractions createNewStatements(
EditConfigurationVTwo configuration, EditConfigurationVTwo configuration,
MultiValueEditSubmission submission) throws Exception { MultiValueEditSubmission submission, VitroRequest vreq) throws Exception {
log.debug("in createNewStatements()" ); log.debug("in createNewStatements()" );
//getN3Required and getN3Optional will return copies of the //getN3Required and getN3Optional will return copies of the
@ -113,10 +126,10 @@ public class ProcessRdfForm {
List<String> optionalN3 = configuration.getN3Optional(); List<String> optionalN3 = configuration.getN3Optional();
/* substitute in the form values and existing values */ /* substitute in the form values and existing values */
subInValuesToN3( configuration, submission, requiredN3, optionalN3, null , null); subInValuesToN3( configuration, submission, requiredN3, optionalN3, null , null, vreq);
/* parse N3 to RDF Models, No retractions since all of the statements are new. */ /* parse N3 to RDF Models, No retractions since all of the statements are new. */
return parseN3ToChange(requiredN3, optionalN3, null, null); return parseN3ToChange(requiredN3, optionalN3, null, null, vreq, null);
} }
/* for a list of N3 strings, substitute in the subject, predicate and object URIs /* for a list of N3 strings, substitute in the subject, predicate and object URIs
@ -140,10 +153,12 @@ public class ProcessRdfForm {
* retractions are mutually diff'ed before statements are added to or * retractions are mutually diff'ed before statements are added to or
* removed from the model. The explicit change check can cause problems in * removed from the model. The explicit change check can cause problems in
* more complex setups, like the automatic form building in DataStaR. * more complex setups, like the automatic form building in DataStaR.
* @param vreq For getting linguistic context
*/ */
protected AdditionsAndRetractions editExistingStatements( protected AdditionsAndRetractions editExistingStatements(
EditConfigurationVTwo editConfig, EditConfigurationVTwo editConfig,
MultiValueEditSubmission submission) throws Exception { MultiValueEditSubmission submission, VitroRequest vreq) throws Exception {
log.debug("editing an existing resource: " + editConfig.getObject() ); log.debug("editing an existing resource: " + editConfig.getObject() );
@ -156,18 +171,18 @@ public class ProcessRdfForm {
subInValuesToN3(editConfig, submission, subInValuesToN3(editConfig, submission,
N3RequiredAssert, N3OptionalAssert, N3RequiredAssert, N3OptionalAssert,
N3RequiredRetract, N3OptionalRetract); N3RequiredRetract, N3OptionalRetract, vreq);
return parseN3ToChange( return parseN3ToChange(
N3RequiredAssert,N3OptionalAssert, N3RequiredAssert,N3OptionalAssert,
N3RequiredRetract, N3OptionalRetract); N3RequiredRetract, N3OptionalRetract, vreq, editConfig);
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
protected void subInValuesToN3( protected void subInValuesToN3(
EditConfigurationVTwo editConfig, MultiValueEditSubmission submission, EditConfigurationVTwo editConfig, MultiValueEditSubmission submission,
List<String> requiredAsserts, List<String> optionalAsserts, List<String> requiredAsserts, List<String> optionalAsserts,
List<String> requiredRetracts, List<String> optionalRetracts ) throws InsertException{ List<String> requiredRetracts, List<String> optionalRetracts, VitroRequest vreq ) throws InsertException{
//need to substitute into the return to URL becase it may need new resource URIs //need to substitute into the return to URL becase it may need new resource URIs
List<String> URLToReturnTo = Arrays.asList(submission.getEntityToReturnTo()); List<String> URLToReturnTo = Arrays.asList(submission.getEntityToReturnTo());
@ -184,7 +199,41 @@ public class ProcessRdfForm {
//Retractions does NOT get values from form. //Retractions does NOT get values from form.
/* ******** Form submission Literals *********** */ /* ******** Form submission Literals *********** */
substituteInMultiLiterals( submission.getLiteralsFromForm(), requiredAsserts, optionalAsserts, URLToReturnTo); /*
* UQAM Set all literals in the linguistic context
*/
Map<String, List<Literal>> literalsFromForm = submission.getLiteralsFromForm();
Set<String> keys = literalsFromForm.keySet();
for (String aKey : keys) {
List<Literal> literalFromForm = literalsFromForm.get(aKey);
List<Literal> newLiteralFromForm = new ArrayList<>();
for (Literal aLiteral : literalFromForm) {
if (aLiteral != null) {
String aLiteratDT = aLiteral.getDatatype().getURI();
Literal newLiteral = null;
String aText = aLiteral.getLexicalForm();
/*
* do it only if aLiteral are xstring datatype
*/
if (RDF.dtLangString.getURI().equals(aLiteratDT) && !aLiteral.getLanguage().isEmpty()) {
newLiteral = aLiteral;
}
else if (XSD.xstring.getURI().equals(aLiteratDT) || RDF.dtLangString.getURI().equals(aLiteratDT)) {
String lang = vreq.getLocale().getLanguage();
if (!vreq.getLocale().getCountry().isEmpty()) {
lang += "-" + vreq.getLocale().getCountry();
}
newLiteral = ResourceFactory.createLangLiteral(aText, lang);
} else {
newLiteral = ResourceFactory.createTypedLiteral(aText, aLiteral.getDatatype());
}
newLiteralFromForm.add(newLiteral);
}
}
literalsFromForm.replace(aKey, newLiteralFromForm);
}
substituteInMultiLiterals( literalsFromForm, requiredAsserts, optionalAsserts, URLToReturnTo);
logSubstitue( "Added form Literals", requiredAsserts, optionalAsserts, requiredRetracts, optionalRetracts); logSubstitue( "Added form Literals", requiredAsserts, optionalAsserts, requiredRetracts, optionalRetracts);
//Retractions does NOT get values from form. //Retractions does NOT get values from form.
@ -254,20 +303,106 @@ public class ProcessRdfForm {
protected AdditionsAndRetractions parseN3ToChange( protected AdditionsAndRetractions parseN3ToChange(
List<String> requiredAdds, List<String> optionalAdds, List<String> requiredAdds, List<String> optionalAdds,
List<String> requiredDels, List<String> optionalDels) throws Exception{ List<String> requiredDels, List<String> optionalDels, VitroRequest vreq, EditConfigurationVTwo editConfig) throws Exception{
List<Model> adds = parseN3ToRDF(requiredAdds, REQUIRED); List<Model> adds = parseN3ToRDF(requiredAdds, REQUIRED);
adds.addAll( parseN3ToRDF(optionalAdds, OPTIONAL)); adds.addAll( parseN3ToRDF(optionalAdds, OPTIONAL));
List<Model> retracts = new ArrayList<Model>(); List<Model> retracts = new ArrayList<Model>();
if( requiredDels != null && optionalDels != null ){ if( requiredDels != null && optionalDels != null ){
retracts.addAll( parseN3ToRDF(requiredDels, REQUIRED) ); String lingCxt=null;
retracts.addAll( parseN3ToRDF(optionalDels, OPTIONAL) ); //UQAM Taking into account the linguistic context in retract
try {
// only if the request comes from the rdfsLabelGenerator the language should be used
Boolean getLabelLanguage = false;
if (!StringUtils.isBlank(editConfig.formUrl) && editConfig.formUrl.contains("RDFSLabelGenerator")) {
getLabelLanguage = true;
}
// if the language is set in the given Literal, this language-tag should be used and remain the same
// for example when you edit an label with an langauge-tag (no matter which language is selected globally)
if (editConfig != null && !StringUtils.isBlank(editConfig.getLiteralsInScope().get("label").get(0).getLanguage()) && getLabelLanguage) {
lingCxt = editConfig.getLiteralsInScope().get("label").get(0).getLanguage();
} else { // if the literal has no langauge-tag, use the language which is globally selected
lingCxt = vreq.getLocale().getLanguage();
if (!vreq.getLocale().getCountry().isEmpty()) {
lingCxt += "-" + vreq.getLocale().getCountry();
}
}
} catch (Exception e) {
}
retracts.addAll( parseN3ToRDF(requiredDels, REQUIRED, lingCxt) );
retracts.addAll( parseN3ToRDF(optionalDels, OPTIONAL, lingCxt) );
} }
return new AdditionsAndRetractions(adds,retracts); return new AdditionsAndRetractions(adds,retracts);
} }
/**
* Parse the n3Strings to a List of RDF Model objects.
*
* @param n3Strings N3 Strings to parse
* @param parseType if OPTIONAL, then don't throw exceptions on errors
* @param linguisticContext For Literals, Making parse only if the literal linguisticContext are same than linguisticContext parameter //UQAM
* If REQUIRED, then throw exceptions on errors.
* @throws Exception
*/
protected static List<Model> parseN3ToRDF(
List<String> n3Strings, N3ParseType parseType, String linguisticContext ) throws Exception {
// Use non-linguistic version of this method if no linguisticContext is provided
if (linguisticContext == null) {
return parseN3ToRDF(n3Strings, parseType);
}
List<String> errorMessages = new ArrayList<String>();
List<Model> rdfModels = new ArrayList<Model>();
for(String n3 : n3Strings){
try{
Model model = ModelFactory.createDefaultModel();
StringReader reader = new StringReader(n3);
model.read(reader, "", "N3");
List<Statement> stmts = model.listStatements().toList();
for (Iterator iterator = stmts.iterator(); iterator.hasNext();) {
Statement stmt = (Statement) iterator.next();
Resource subj = stmt.getSubject();
Property pred = stmt.getPredicate();
RDFNode obj = stmt.getObject();
if (obj.isLiteral()) {
Literal lit = obj.asLiteral();
String lang = lit.getLanguage();
if (! linguisticContext.equals(lang)) {
//UQAM Remove if linguisticContext != lang of the Literal
model.remove(subj, pred, obj);
}
}
}
rdfModels.add( model );
}catch(Throwable t){
errorMessages.add(t.getMessage() + "\nN3: \n" + n3 + "\n");
}
}
StringBuilder errors = new StringBuilder();
for( String errorMsg : errorMessages){
errors.append(errorMsg).append('\n');
}
if( !errorMessages.isEmpty() ){
if( REQUIRED.equals(parseType) ){
throw new Exception("Errors processing required N3. The EditConfiguration should " +
"be setup so that if a submission passes validation, there will not be errors " +
"in the required N3.\n" + errors );
}else if( OPTIONAL.equals(parseType) ){
log.debug("Some Optional N3 did not parse, if a optional N3 does not parse it " +
"will be ignored. This allows optional parts of a form submission to " +
"remain unfilled out and then the optional N3 does not get values subsituted in from" +
"the form submission values. It may also be the case that there are unintentional " +
"syntax errors the optional N3." );
log.debug(errors.toString());
}
}
return rdfModels;
}
/** /**
* Parse the n3Strings to a List of RDF Model objects. * Parse the n3Strings to a List of RDF Model objects.
* *

View file

@ -7,6 +7,7 @@ import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import edu.cornell.mannlib.vitro.webapp.i18n.I18nBundle;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
@ -40,7 +41,8 @@ public class ChildVClassesOptions implements FieldOptions {
public Map<String, String> getOptions( public Map<String, String> getOptions(
EditConfigurationVTwo editConfig, EditConfigurationVTwo editConfig,
String fieldName, String fieldName,
WebappDaoFactory wDaoFact) throws Exception{ WebappDaoFactory wDaoFact,
I18nBundle i18n) throws Exception{
// now create an empty HashMap to populate and return // now create an empty HashMap to populate and return
HashMap <String,String> optionsMap = new LinkedHashMap<String,String>(); HashMap <String,String> optionsMap = new LinkedHashMap<String,String>();

View file

@ -1,6 +1,6 @@
/* $This file is distributed under the terms of the license in LICENSE$ */ /* $This file is distributed under the terms of the license in LICENSE$ */
package edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.fields;
package edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.fields;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
@ -15,6 +15,7 @@ import edu.cornell.mannlib.vitro.webapp.beans.VClass;
import edu.cornell.mannlib.vitro.webapp.dao.VClassDao; import edu.cornell.mannlib.vitro.webapp.dao.VClassDao;
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory; import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditConfigurationVTwo; import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditConfigurationVTwo;
import edu.cornell.mannlib.vitro.webapp.i18n.I18nBundle;
public class ChildVClassesWithParent implements FieldOptions { public class ChildVClassesWithParent implements FieldOptions {
@ -37,20 +38,24 @@ public class ChildVClassesWithParent implements FieldOptions {
return this; return this;
} }
@Override /*
* UQAM-Linguistic-Management
* This method is polymorphism of getOptions(EditConfigurationVTwo editConfig,String fieldName, WebappDaoFactory wDaoFact)
* for the internationalization of word "other" in the scroling list of personHasAdvisorRelationship.ftl
*/
public Map<String, String> getOptions( public Map<String, String> getOptions(
EditConfigurationVTwo editConfig, EditConfigurationVTwo editConfig,
String fieldName, String fieldName,
WebappDaoFactory wDaoFact) throws Exception { WebappDaoFactory wDaoFact,
I18nBundle i18n) throws Exception {
HashMap <String,String> optionsMap = new LinkedHashMap<String,String>(); HashMap <String,String> optionsMap = new LinkedHashMap<String,String>();
// first test to see whether there's a default "leave blank" value specified with the literal options // first test to see whether there's a default "leave blank" value specified with the literal options
if ( ! StringUtils.isEmpty( defaultOptionLabel ) ){ if ( ! StringUtils.isEmpty( defaultOptionLabel ) ){
optionsMap.put(LEFT_BLANK, defaultOptionLabel); optionsMap.put(LEFT_BLANK, defaultOptionLabel);
} }
String other_i18n = i18n.text("other");
optionsMap.put(classUri, "Other"); // first character in capital
optionsMap.put(classUri, other_i18n.substring(0, 1).toUpperCase() + other_i18n.substring(1));
VClassDao vclassDao = wDaoFact.getVClassDao(); VClassDao vclassDao = wDaoFact.getVClassDao();
List<String> subClassList = vclassDao.getAllSubClassURIs(classUri); List<String> subClassList = vclassDao.getAllSubClassURIs(classUri);
if (subClassList != null && subClassList.size() > 0) { if (subClassList != null && subClassList.size() > 0) {

View file

@ -10,6 +10,7 @@ import java.util.Map;
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory; import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditConfigurationVTwo; import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditConfigurationVTwo;
import edu.cornell.mannlib.vitro.webapp.i18n.I18nBundle;
public class ConstantFieldOptions implements FieldOptions { public class ConstantFieldOptions implements FieldOptions {
@ -54,7 +55,8 @@ public class ConstantFieldOptions implements FieldOptions {
public Map<String, String> getOptions( public Map<String, String> getOptions(
EditConfigurationVTwo editConfig, EditConfigurationVTwo editConfig,
String fieldName, String fieldName,
WebappDaoFactory wDaoFact) throws Exception { WebappDaoFactory wDaoFact,
I18nBundle i18n) throws Exception {
// originally not auto-sorted but sorted now, and empty values not removed or replaced // originally not auto-sorted but sorted now, and empty values not removed or replaced
HashMap <String,String> optionsMap = new LinkedHashMap<String,String>(); HashMap <String,String> optionsMap = new LinkedHashMap<String,String>();

View file

@ -6,6 +6,7 @@ import java.util.Map;
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory; import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditConfigurationVTwo; import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditConfigurationVTwo;
import edu.cornell.mannlib.vitro.webapp.i18n.I18nBundle;
/** /**
* Represents an object that can return a list of options * Represents an object that can return a list of options
@ -28,7 +29,8 @@ public interface FieldOptions {
public Map<String,String> getOptions( public Map<String,String> getOptions(
EditConfigurationVTwo editConfig, EditConfigurationVTwo editConfig,
String fieldName, String fieldName,
WebappDaoFactory wDaoFact) throws Exception; WebappDaoFactory wDaoFact,
I18nBundle i18n) throws Exception;
/* /*
* Certain field options may have custom sorting requirements. If no sorting requirements exist, * Certain field options may have custom sorting requirements. If no sorting requirements exist,

View file

@ -6,6 +6,7 @@ import java.util.Map;
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory; import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditConfigurationVTwo; import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditConfigurationVTwo;
import edu.cornell.mannlib.vitro.webapp.i18n.I18nBundle;
public class IndividualsViaClassGroupOptions implements FieldOptions { public class IndividualsViaClassGroupOptions implements FieldOptions {
@ -27,7 +28,8 @@ public class IndividualsViaClassGroupOptions implements FieldOptions {
public Map<String, String> getOptions( public Map<String, String> getOptions(
EditConfigurationVTwo editConfig, EditConfigurationVTwo editConfig,
String fieldName, String fieldName,
WebappDaoFactory wDaoFact) throws Exception { WebappDaoFactory wDaoFact,
I18nBundle i18n) throws Exception {
throw new Error("not implemented"); throw new Error("not implemented");
} }

View file

@ -11,6 +11,7 @@ import java.util.Map;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import edu.cornell.mannlib.vitro.webapp.i18n.I18nBundle;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
@ -77,7 +78,8 @@ public class IndividualsViaObjectPropetyOptions implements FieldOptions {
public Map<String, String> getOptions( public Map<String, String> getOptions(
EditConfigurationVTwo editConfig, EditConfigurationVTwo editConfig,
String fieldName, String fieldName,
WebappDaoFactory wDaoFact) { WebappDaoFactory wDaoFact,
I18nBundle i18n) {
HashMap<String, String> optionsMap = new LinkedHashMap<String, String>(); HashMap<String, String> optionsMap = new LinkedHashMap<String, String>();
int optionsCount = 0; int optionsCount = 0;

View file

@ -8,6 +8,7 @@ import java.util.List;
import java.util.ListIterator; import java.util.ListIterator;
import java.util.Map; import java.util.Map;
import edu.cornell.mannlib.vitro.webapp.i18n.I18nBundle;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
@ -90,7 +91,8 @@ public class IndividualsViaSearchQueryOptions extends IndividualsViaVClassOption
public Map<String, String> getOptions( public Map<String, String> getOptions(
EditConfigurationVTwo editConfig, EditConfigurationVTwo editConfig,
String fieldName, String fieldName,
WebappDaoFactory wDaoFact) throws Exception { WebappDaoFactory wDaoFact,
I18nBundle i18n) throws Exception {
Map<String, Individual> individualMap = new HashMap<String, Individual>(); Map<String, Individual> individualMap = new HashMap<String, Individual>();

View file

@ -8,6 +8,7 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import edu.cornell.mannlib.vitro.webapp.i18n.I18nBundle;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
@ -48,7 +49,8 @@ public class IndividualsViaVClassOptions implements FieldOptions {
public Map<String, String> getOptions( public Map<String, String> getOptions(
EditConfigurationVTwo editConfig, EditConfigurationVTwo editConfig,
String fieldName, String fieldName,
WebappDaoFactory wDaoFact) throws Exception { WebappDaoFactory wDaoFact,
I18nBundle i18n) throws Exception {
Map<String, Individual> individualMap = new HashMap<String, Individual>(); Map<String, Individual> individualMap = new HashMap<String, Individual>();

View file

@ -9,6 +9,7 @@ import java.util.Map;
import edu.cornell.mannlib.vitro.webapp.beans.VClass; import edu.cornell.mannlib.vitro.webapp.beans.VClass;
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory; import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditConfigurationVTwo; import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditConfigurationVTwo;
import edu.cornell.mannlib.vitro.webapp.i18n.I18nBundle;
public class RdfTypeOptions implements FieldOptions { public class RdfTypeOptions implements FieldOptions {
@ -29,7 +30,8 @@ public class RdfTypeOptions implements FieldOptions {
public Map<String, String> getOptions( public Map<String, String> getOptions(
EditConfigurationVTwo editConfig, EditConfigurationVTwo editConfig,
String fieldName, String fieldName,
WebappDaoFactory wdf) { WebappDaoFactory wdf,
I18nBundle i18n) {
Map<String,String> uriToLabel = new HashMap<String,String>(); Map<String,String> uriToLabel = new HashMap<String,String>();
for (String uri : typeURIs) { for (String uri : typeURIs) {

View file

@ -11,6 +11,8 @@ import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import edu.cornell.mannlib.vitro.webapp.i18n.I18n;
import edu.cornell.mannlib.vitro.webapp.i18n.I18nBundle;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
@ -25,7 +27,8 @@ public class SelectListGeneratorVTwo {
public static Map<String,String> getOptions( public static Map<String,String> getOptions(
EditConfigurationVTwo editConfig, EditConfigurationVTwo editConfig,
String fieldName, String fieldName,
WebappDaoFactory wDaoFact){ WebappDaoFactory wDaoFact,
I18nBundle i18n){
if( editConfig == null ){ if( editConfig == null ){
@ -48,7 +51,45 @@ public class SelectListGeneratorVTwo {
} }
try { try {
return field.getFieldOptions().getOptions(editConfig,fieldName,wDaoFact); return field.getFieldOptions().getOptions(editConfig,fieldName,wDaoFact,i18n);
} catch (Exception e) {
log.error("Error runing getFieldOptionis()",e);
return Collections.emptyMap();
}
}
// UQAM Overcharge method for linguistic contexte processisng
// AWoods: This method appears to never be invoked.
public static Map<String,String> getOptions(
EditConfigurationVTwo editConfig,
String fieldName,
VitroRequest vreq){
if( editConfig == null ){
log.error( "fieldToSelectItemList() must be called with a non-null EditConfigurationVTwo ");
return Collections.emptyMap();
}
if( fieldName == null ){
log.error( "fieldToSelectItemList() must be called with a non-null fieldName");
return Collections.emptyMap();
}
FieldVTwo field = editConfig.getField(fieldName);
if (field==null) {
log.error("no field \""+fieldName+"\" found from editConfig.");
return Collections.emptyMap();
}
if( field.getFieldOptions() == null ){
return Collections.emptyMap();
}
try {
//UQAM need vreq instead of WebappDaoFactory
Map<String, String> parentClass = Collections.emptyMap();
FieldOptions fieldOptions = field.getFieldOptions();
return fieldOptions.getOptions(editConfig,fieldName,vreq.getWebappDaoFactory(), I18n.bundle(vreq));
} catch (Exception e) { } catch (Exception e) {
log.error("Error runing getFieldOptionis()",e); log.error("Error runing getFieldOptionis()",e);
return Collections.emptyMap(); return Collections.emptyMap();

View file

@ -350,7 +350,7 @@ public class DefaultAddMissingIndividualFormGenerator implements EditConfigurati
private void prepareForUpdate(VitroRequest vreq, HttpSession session, EditConfigurationVTwo editConfiguration) { private void prepareForUpdate(VitroRequest vreq, HttpSession session, EditConfigurationVTwo editConfiguration) {
//Here, retrieve model from //Here, retrieve model from
OntModel model = ModelAccess.on(session.getServletContext()).getOntModel(); OntModel model = ModelAccess.on(vreq).getOntModel();
//if object property //if object property
if(EditConfigurationUtils.isObjectProperty(EditConfigurationUtils.getPredicateUri(vreq), vreq)){ if(EditConfigurationUtils.isObjectProperty(EditConfigurationUtils.getPredicateUri(vreq), vreq)){
Individual objectIndividual = EditConfigurationUtils.getObjectIndividual(vreq); Individual objectIndividual = EditConfigurationUtils.getObjectIndividual(vreq);

View file

@ -49,26 +49,18 @@ public class DefaultDeleteGenerator extends BaseEditConfigurationGenerator imple
prepare(vreq, editConfiguration); prepare(vreq, editConfiguration);
if (editConfiguration.getPredicateUri() == null && editConfiguration.getSubjectUri() == null) { if (editConfiguration.getPredicateUri() == null && editConfiguration.getSubjectUri() == null) {
editConfiguration.setTemplate(individualTemplate); editConfiguration.setTemplate(individualTemplate);
addDeleteParams(vreq, editConfiguration); addRedirectUrl(vreq, editConfiguration);
}else { } else {
editConfiguration.setTemplate(propertyTemplate); editConfiguration.setTemplate(propertyTemplate);
} }
return editConfiguration; return editConfiguration;
} }
private void addDeleteParams(VitroRequest vreq, EditConfigurationVTwo editConfiguration) { private void addRedirectUrl(VitroRequest vreq, EditConfigurationVTwo editConfiguration) {
String redirectUrl = vreq.getParameter("redirectUrl"); String redirectUrl = vreq.getParameter("redirectUrl");
if (redirectUrl != null) { if (redirectUrl != null) {
editConfiguration.addFormSpecificData("redirectUrl", redirectUrl); editConfiguration.addFormSpecificData("redirectUrl", redirectUrl);
} }
String individualName = vreq.getParameter("individualName");
if (redirectUrl != null) {
editConfiguration.addFormSpecificData("individualName", individualName);
}
String individualType = vreq.getParameter("individualType");
if (redirectUrl != null) {
editConfiguration.addFormSpecificData("individualType", individualType);
}
} }
private EditConfigurationVTwo setupEditConfiguration(VitroRequest vreq, HttpSession session) { private EditConfigurationVTwo setupEditConfiguration(VitroRequest vreq, HttpSession session) {

View file

@ -2,6 +2,8 @@
package edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.generators; package edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.generators;
import static edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess.LANGUAGE_NEUTRAL;
import static edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess.POLICY_NEUTRAL;
import static edu.cornell.mannlib.vitro.webapp.modelaccess.ModelNames.DISPLAY; import static edu.cornell.mannlib.vitro.webapp.modelaccess.ModelNames.DISPLAY;
import java.util.ArrayList; import java.util.ArrayList;
@ -35,6 +37,8 @@ import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.fields.IndividualsVi
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.validators.AntiXssValidation; import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.validators.AntiXssValidation;
import edu.cornell.mannlib.vitro.webapp.i18n.I18n; import edu.cornell.mannlib.vitro.webapp.i18n.I18n;
import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess; import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess;
import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess.LanguageOption;
import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess.PolicyOption;
import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchEngine; import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchEngine;
import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchEngineException; import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchEngineException;
import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchQuery; import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchQuery;
@ -125,7 +129,10 @@ public class DefaultObjectPropertyFormGenerator implements EditConfigurationGene
// Someday we'll need to figure out a different way of doing this. // Someday we'll need to figure out a different way of doing this.
//WebappDaoFactory ctxDaoFact = ModelAccess.on( //WebappDaoFactory ctxDaoFact = ModelAccess.on(
// vreq.getSession().getServletContext()).getWebappDaoFactory(); // vreq.getSession().getServletContext()).getWebappDaoFactory();
WebappDaoFactory ctxDaoFact = vreq.getLanguageNeutralWebappDaoFactory(); // WebappDaoFactory ctxDaoFact = vreq.getLanguageNeutralWebappDaoFactory();
//UQAM Linguistic-Management Manage linguistic context
WebappDaoFactory ctxDaoFact = ModelAccess.on(vreq).getWebappDaoFactory(LanguageOption.LANGUAGE_AWARE, PolicyOption.POLICY_NEUTRAL);
List<VClass> types = new ArrayList<VClass>(); List<VClass> types = new ArrayList<VClass>();
Individual subject = EditConfigurationUtils.getSubjectIndividual(vreq); Individual subject = EditConfigurationUtils.getSubjectIndividual(vreq);
@ -460,7 +467,7 @@ public class DefaultObjectPropertyFormGenerator implements EditConfigurationGene
private void prepareForUpdate(VitroRequest vreq, HttpSession session, EditConfigurationVTwo editConfiguration) { private void prepareForUpdate(VitroRequest vreq, HttpSession session, EditConfigurationVTwo editConfiguration) {
//Here, retrieve model from //Here, retrieve model from
OntModel model = ModelAccess.on(session.getServletContext()).getOntModel(); OntModel model = ModelAccess.on(vreq).getOntModel();
//if object property //if object property
if(EditConfigurationUtils.isObjectProperty(EditConfigurationUtils.getPredicateUri(vreq), vreq)){ if(EditConfigurationUtils.isObjectProperty(EditConfigurationUtils.getPredicateUri(vreq), vreq)){
Individual objectIndividual = EditConfigurationUtils.getObjectIndividual(vreq); Individual objectIndividual = EditConfigurationUtils.getObjectIndividual(vreq);

View file

@ -224,6 +224,20 @@ public class ManageLabelsForIndividualGenerator extends BaseEditConfigurationGen
config.addFormSpecificData("displayRemoveLink", (numberExistingLabels > 1)); config.addFormSpecificData("displayRemoveLink", (numberExistingLabels > 1));
// get current selected locale
String rangeLang = vreq.getLocale().getLanguage();
if (!vreq.getLocale().getCountry().isEmpty()) {
rangeLang += "-" + vreq.getLocale().getCountry();
}
// check if locale already has an entry (label)
boolean localeEntryExisting = true;
for (HashMap<String, String> tmp : availableLocalesForAdd) {
if (tmp.get("code").equals(rangeLang)) localeEntryExisting = false;
}
config.addFormSpecificData("localeEntryExisting", localeEntryExisting);
config.addFormSpecificData("currentSelectedLocale", rangeLang);
//How do we edit? Will need to see //How do we edit? Will need to see
config.addFormSpecificData("deleteWebpageUrl", "/edit/primitiveDelete"); config.addFormSpecificData("deleteWebpageUrl", "/edit/primitiveDelete");

View file

@ -233,7 +233,7 @@ public class NewIndividualFormGenerator implements EditConfigurationGenerator {
private void prepareForUpdate(VitroRequest vreq, HttpSession session, EditConfigurationVTwo editConfiguration) { private void prepareForUpdate(VitroRequest vreq, HttpSession session, EditConfigurationVTwo editConfiguration) {
//Here, retrieve model from //Here, retrieve model from
OntModel model = ModelAccess.on(session.getServletContext()).getOntModel(); OntModel model = ModelAccess.on(vreq).getOntModel();
//This form is always doing a non-update //This form is always doing a non-update
editConfiguration.prepareForNonUpdate( model ); editConfiguration.prepareForNonUpdate( model );

View file

@ -298,7 +298,7 @@ public class RDFSLabelGenerator implements EditConfigurationGenerator {
private void prepareForUpdate(VitroRequest vreq, HttpSession session, EditConfigurationVTwo editConfiguration) { private void prepareForUpdate(VitroRequest vreq, HttpSession session, EditConfigurationVTwo editConfiguration) {
//Here, retrieve model from //Here, retrieve model from
OntModel model = ModelAccess.on(session.getServletContext()).getOntModel(); OntModel model = ModelAccess.on(vreq).getOntModel();
if( editConfiguration.isDataPropertyUpdate() ){ if( editConfiguration.isDataPropertyUpdate() ){
editConfiguration.prepareForDataPropUpdate(model, vreq.getWebappDaoFactory().getDataPropertyDao()); editConfiguration.prepareForDataPropUpdate(model, vreq.getWebappDaoFactory().getDataPropertyDao());
} }

View file

@ -0,0 +1,92 @@
package edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.preprocessors;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.jena.rdf.model.Literal;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.RDFNode;
import org.apache.jena.rdf.model.Statement;
import org.apache.jena.rdf.model.StmtIterator;
import edu.cornell.mannlib.vitro.webapp.rdfservice.filter.LanguageFilteringUtils;
/**
* A model change preprocessor that discards triples with language tags
* in the retractionsModel that do not match the specified language, unless
* the additionsModel also contains a new value for the same subject and
* predicate in that language, or no values in any language are added for the
* same subject and predicate (such as when an entire resource is deleted) .
*/
public class LimitRemovalsToLanguage implements ModelChangePreprocessor {
private static final Log log = LogFactory.getLog(LimitRemovalsToLanguage.class);
private String language;
/**
* @param locale the Java locale object representing the language
* to which edits should be limited. May not be null.
*/
public LimitRemovalsToLanguage(Locale locale) {
if(locale == null) {
throw new IllegalArgumentException("Locale may not be null.");
}
this.language = LanguageFilteringUtils.localeToLanguage(locale);
}
/**
* @param language string representing the RDF language tag to which
* edits should be limited. May not be null.
*/
public LimitRemovalsToLanguage(String language) {
if(language == null) {
throw new IllegalArgumentException("Language may not be null.");
}
this.language = language;
}
@Override
public void preprocess(Model retractionsModel, Model additionsModel,
HttpServletRequest request) {
log.debug("limiting changes to " + language);
List<Statement> eliminatedRetractions = new ArrayList<Statement>();
StmtIterator sit = retractionsModel.listStatements();
while(sit.hasNext()) {
Statement stmt = sit.next();
if(stmt.getObject().isLiteral()) {
Literal lit = stmt.getObject().asLiteral();
if(!StringUtils.isEmpty(lit.getLanguage())
&& !lit.getLanguage().equals(language)) {
boolean eliminateRetraction = true;
StmtIterator replacements = additionsModel
.listStatements(stmt.getSubject(),
stmt.getPredicate(), (RDFNode) null);
if(!replacements.hasNext()) {
eliminateRetraction = false;
} else {
while(replacements.hasNext()) {
Statement replacement = replacements.next();
if(replacement.getObject().isLiteral()
&& lit.getLanguage().equals(replacement
.getObject().asLiteral()
.getLanguage())) {
eliminateRetraction = false;
}
}
}
if(eliminateRetraction) {
eliminatedRetractions.add(stmt);
}
}
}
}
retractionsModel.remove(eliminatedRetractions);
}
}

View file

@ -68,18 +68,12 @@ public class EditRequestDispatchController extends FreemarkerHttpServlet {
//TODO: Create this generator //TODO: Create this generator
final String RDFS_LABEL_FORM = "edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.generators.RDFSLabelGenerator"; final String RDFS_LABEL_FORM = "edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.generators.RDFSLabelGenerator";
final String DEFAULT_DELETE_FORM = "edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.generators.DefaultDeleteGenerator"; final String DEFAULT_DELETE_FORM = "edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.generators.DefaultDeleteGenerator";
final String MANAGE_MENUS_FORM = "edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.generators.ManagePageGenerator";
@Override @Override
protected AuthorizationRequest requiredActions(VitroRequest vreq) { protected AuthorizationRequest requiredActions(VitroRequest vreq) {
// If request is for new individual, return simple do back end editing action permission // If request is for new individual, return simple do back end editing action permission
if (StringUtils.isNotEmpty(EditConfigurationUtils.getTypeOfNew(vreq))) { if (StringUtils.isNotEmpty(EditConfigurationUtils.getTypeOfNew(vreq))) {
return SimplePermission.DO_BACK_END_EDITING.ACTION; return SimplePermission.DO_BACK_END_EDITING.ACTION;
} else if(MANAGE_MENUS_FORM.equals(vreq.getParameter("editForm"))) {
return SimplePermission.MANAGE_MENUS.ACTION;
}
if (isIndividualDeletion(vreq)) {
return SimplePermission.DO_BACK_END_EDITING.ACTION;
} }
// Check if this statement can be edited here and return unauthorized if not // Check if this statement can be edited here and return unauthorized if not
String subjectUri = EditConfigurationUtils.getSubjectUri(vreq); String subjectUri = EditConfigurationUtils.getSubjectUri(vreq);
@ -109,16 +103,6 @@ public class EditRequestDispatchController extends FreemarkerHttpServlet {
return isAuthorized? SimplePermission.DO_FRONT_END_EDITING.ACTION: AuthorizationRequest.UNAUTHORIZED; return isAuthorized? SimplePermission.DO_FRONT_END_EDITING.ACTION: AuthorizationRequest.UNAUTHORIZED;
} }
private boolean isIndividualDeletion(VitroRequest vreq) {
String subjectUri = EditConfigurationUtils.getSubjectUri(vreq);
String predicateUri = EditConfigurationUtils.getPredicateUri(vreq);
String objectUri = EditConfigurationUtils.getObjectUri(vreq);
if (objectUri != null && subjectUri == null && predicateUri == null && isDeleteForm(vreq)) {
return true;
}
return false;
}
@Override @Override
protected ResponseValues processRequest(VitroRequest vreq) { protected ResponseValues processRequest(VitroRequest vreq) {
@ -169,7 +153,7 @@ public class EditRequestDispatchController extends FreemarkerHttpServlet {
templateData.put("editConfiguration", etm); templateData.put("editConfiguration", etm);
templateData.put("editSubmission", submissionTemplateModel); templateData.put("editSubmission", submissionTemplateModel);
//Corresponding to original note for consistency with selenium tests and 1.1.1 //Corresponding to original note for consistency with selenium tests and 1.1.1
templateData.put("title", "Edit"); templateData.put("title", etm.getPageTitle());
templateData.put("submitUrl", getSubmissionUrl(vreq)); templateData.put("submitUrl", getSubmissionUrl(vreq));
templateData.put("cancelUrl", etm.getCancelUrl()); templateData.put("cancelUrl", etm.getCancelUrl());
templateData.put("editKey", editConfig.getEditKey()); templateData.put("editKey", editConfig.getEditKey());

View file

@ -74,9 +74,11 @@ public class PostEditCleanupController extends FreemarkerHttpServlet{
//The submission for getting the entity to return to is not retrieved from the session but needs //The submission for getting the entity to return to is not retrieved from the session but needs
//to be created - as it is in processRdfForm3.jsp //to be created - as it is in processRdfForm3.jsp
if( entityToReturnTo == null ){ if( entityToReturnTo == null ){
//this will not work if there entityToReturnTo has a new resource URI, // this will not work if there entityToReturnTo has a new resource URI,
//in that case entityToReturnTo should not have been passed to this method as null // in that case entityToReturnTo should not have been passed to this method as null
MultiValueEditSubmission submission = new MultiValueEditSubmission(vreq.getParameterMap(), editConfig); // UQAM-Linguistic-Management
// MultiValueEditSubmission submission = new MultiValueEditSubmission(vreq.getParameterMap(), editConfig);
MultiValueEditSubmission submission = new MultiValueEditSubmission(vreq, editConfig);
entityToReturnTo = N3EditUtils.processEntityToReturnTo(editConfig, submission, vreq); entityToReturnTo = N3EditUtils.processEntityToReturnTo(editConfig, submission, vreq);
} }

View file

@ -8,10 +8,11 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import javax.servlet.annotation.WebServlet;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.apache.jena.rdf.model.Literal; import org.apache.jena.rdf.model.Literal;
import org.apache.jena.rdf.model.Model; import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.Property; import org.apache.jena.rdf.model.Property;
@ -37,8 +38,7 @@ import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.MultiValueEditSubmis
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.N3EditUtils; import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.N3EditUtils;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.ProcessRdfForm; import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.ProcessRdfForm;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.RdfLiteralHash; import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.RdfLiteralHash;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.preprocessors.LimitRemovalsToLanguage;
import javax.servlet.annotation.WebServlet;
/** /**
* This servlet will convert a request to an EditSubmission, * This servlet will convert a request to an EditSubmission,
@ -66,7 +66,9 @@ public class ProcessRdfFormController extends FreemarkerHttpServlet{
return handleMissingConfiguration(vreq); return handleMissingConfiguration(vreq);
//get the EditSubmission //get the EditSubmission
MultiValueEditSubmission submission = new MultiValueEditSubmission(vreq.getParameterMap(), configuration); // MultiValueEditSubmission submission = new MultiValueEditSubmission(vreq.getParameterMap(), configuration);
// Modified by UQAM-Linguistic-Management
MultiValueEditSubmission submission = new MultiValueEditSubmission(vreq, configuration);
EditSubmissionUtils.putEditSubmissionInSession(vreq.getSession(), submission); EditSubmissionUtils.putEditSubmissionInSession(vreq.getSession(), submission);
//if errors, return error response //if errors, return error response
@ -101,6 +103,9 @@ public class ProcessRdfFormController extends FreemarkerHttpServlet{
if( configuration.isUseDependentResourceDelete() ) if( configuration.isUseDependentResourceDelete() )
changes = ProcessRdfForm.addDependentDeletes(changes, queryModel); changes = ProcessRdfForm.addDependentDeletes(changes, queryModel);
// prevent form from removing literals in languages other than the one
// associated with the current request
configuration.addModelChangePreprocessor(new LimitRemovalsToLanguage(vreq.getLocale()));
N3EditUtils.preprocessModels(changes, configuration, vreq); N3EditUtils.preprocessModels(changes, configuration, vreq);
ProcessRdfForm.applyChangesToWriteModel(changes, queryModel, writeModel, N3EditUtils.getEditorUri(vreq) ); ProcessRdfForm.applyChangesToWriteModel(changes, queryModel, writeModel, N3EditUtils.getEditorUri(vreq) );

View file

@ -35,6 +35,7 @@ import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess;
import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess.WhichService; import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess.WhichService;
import edu.cornell.mannlib.vitro.webapp.modelaccess.impl.RequestModelAccessImpl; import edu.cornell.mannlib.vitro.webapp.modelaccess.impl.RequestModelAccessImpl;
import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService; import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService;
import edu.cornell.mannlib.vitro.webapp.rdfservice.filter.LanguageFilteringUtils;
import edu.cornell.mannlib.vitro.webapp.rdfservice.impl.RDFServiceUtils; import edu.cornell.mannlib.vitro.webapp.rdfservice.impl.RDFServiceUtils;
/** /**
@ -88,8 +89,10 @@ public class ModelSwitcher {
// If they asked for the display model, give it to them. // If they asked for the display model, give it to them.
if (isParameterPresent(vreq, SWITCH_TO_DISPLAY_MODEL)) { if (isParameterPresent(vreq, SWITCH_TO_DISPLAY_MODEL)) {
OntModel mainOntModel = ModelAccess.on(_context).getOntModel(DISPLAY); OntModel mainOntModel = LanguageFilteringUtils.wrapOntModelInALanguageFilter(
OntModel tboxOntModel = ModelAccess.on(_context).getOntModel(DISPLAY_TBOX); ModelAccess.on(vreq).getOntModel(DISPLAY), vreq);
OntModel tboxOntModel = LanguageFilteringUtils.wrapOntModelInALanguageFilter(
ModelAccess.on(vreq).getOntModel(DISPLAY_TBOX), vreq);
setSpecialWriteModel(vreq, mainOntModel); setSpecialWriteModel(vreq, mainOntModel);
vreq.setAttribute(VitroRequest.ID_FOR_ABOX_MODEL, VitroModelSource.ModelName.DISPLAY.toString()); vreq.setAttribute(VitroRequest.ID_FOR_ABOX_MODEL, VitroModelSource.ModelName.DISPLAY.toString());

View file

@ -63,6 +63,7 @@ public class PageRoutingFilter implements Filter{
// get URL without hostname or servlet context // get URL without hostname or servlet context
HttpServletResponse response = (HttpServletResponse) arg1; HttpServletResponse response = (HttpServletResponse) arg1;
HttpServletRequest req = (HttpServletRequest) arg0; HttpServletRequest req = (HttpServletRequest) arg0;
String path = req.getRequestURI().substring(req.getContextPath().length()); String path = req.getRequestURI().substring(req.getContextPath().length());
// check for first part of path // check for first part of path

View file

@ -6,6 +6,7 @@ import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import javax.servlet.ServletContext; import javax.servlet.ServletContext;

View file

@ -304,7 +304,6 @@ public class FreemarkerConfigurationImpl extends Configuration {
urls.put("home", UrlBuilder.getHomeUrl()); urls.put("home", UrlBuilder.getHomeUrl());
urls.put("about", UrlBuilder.getUrl(Route.ABOUT)); urls.put("about", UrlBuilder.getUrl(Route.ABOUT));
urls.put("search", UrlBuilder.getUrl(Route.SEARCH)); urls.put("search", UrlBuilder.getUrl(Route.SEARCH));
urls.put("customsearch", UrlBuilder.getUrl(Route.CUSTOMSEARCH));
urls.put("termsOfUse", UrlBuilder.getUrl(Route.TERMS_OF_USE)); urls.put("termsOfUse", UrlBuilder.getUrl(Route.TERMS_OF_USE));
urls.put("login", UrlBuilder.getLoginUrl()); urls.put("login", UrlBuilder.getLoginUrl());
urls.put("logout", UrlBuilder.getLogoutUrl()); urls.put("logout", UrlBuilder.getLogoutUrl());

View file

@ -8,6 +8,7 @@ import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.MissingResourceException; import java.util.MissingResourceException;
import java.util.Objects;
import java.util.ResourceBundle; import java.util.ResourceBundle;
import java.util.SortedSet; import java.util.SortedSet;
import java.util.TreeSet; import java.util.TreeSet;
@ -20,7 +21,9 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
import edu.cornell.mannlib.vitro.webapp.i18n.selection.SelectedLocale; import edu.cornell.mannlib.vitro.webapp.i18n.selection.SelectedLocale;
import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess;
import edu.cornell.mannlib.vitro.webapp.utils.developer.DeveloperSettings; import edu.cornell.mannlib.vitro.webapp.utils.developer.DeveloperSettings;
import edu.cornell.mannlib.vitro.webapp.utils.developer.Key; import edu.cornell.mannlib.vitro.webapp.utils.developer.Key;
@ -49,12 +52,27 @@ public class I18n {
* This is where the work gets done. Not declared final, so it can be * This is where the work gets done. Not declared final, so it can be
* modified in unit tests. * modified in unit tests.
*/ */
private static I18n instance = new I18n(); private static I18n instance;
private final ServletContext ctx;
protected I18n(ServletContext ctx) {
this.ctx = ctx;
}
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
// Static methods // Static methods
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
/**
* This setup method must be called before I18n static methods can be used.
* It is currently called from LocaleSelectionSetup.contextInitialized, which
* should ensure it is called when the context is initialized.
*/
public static void setup(ServletContext ctx) {
I18n.instance = new I18n(ctx);
}
/** /**
* A convenience method to get a bundle and format the text. * A convenience method to get a bundle and format the text.
*/ */
@ -72,19 +90,26 @@ public class I18n {
} }
/** /**
* Get a I18nBundle by this name. * Get a request I18nBundle by this name.
*/ */
public static I18nBundle bundle(String bundleName, HttpServletRequest req) { public static I18nBundle bundle(String bundleName, HttpServletRequest req) {
return instance.getBundle(bundleName, req); return instance.getBundle(bundleName, req);
} }
/** /**
* Get the default I18nBundle. * Get the default request I18nBundle.
*/ */
public static I18nBundle bundle(HttpServletRequest req) { public static I18nBundle bundle(HttpServletRequest req) {
return instance.getBundle(DEFAULT_BUNDLE_NAME, req); return instance.getBundle(DEFAULT_BUNDLE_NAME, req);
} }
/**
* Get the default context I18nBundle for preferred locales.
*/
public static I18nBundle bundle(List<Locale> preferredLocales) {
return instance.getBundle(DEFAULT_BUNDLE_NAME, preferredLocales);
}
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
// The instance // The instance
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
@ -106,25 +131,59 @@ public class I18n {
* Declared 'protected' so it can be overridden in unit tests. * Declared 'protected' so it can be overridden in unit tests.
*/ */
protected I18nBundle getBundle(String bundleName, HttpServletRequest req) { protected I18nBundle getBundle(String bundleName, HttpServletRequest req) {
log.debug("Getting bundle '" + bundleName + "'"); log.debug("Getting request bundle '" + bundleName + "'");
I18nLogger i18nLogger = new I18nLogger();
try {
checkDevelopmentMode(req); checkDevelopmentMode(req);
checkForChangeInThemeDirectory(req); checkForChangeInThemeDirectory(req);
String dir = themeDirectory.get(); Locale locale = req.getLocale();
ServletContext ctx = req.getSession().getServletContext();
return getBundle(bundleName, locale);
}
/**
* Get an I18nBundle by this name. The context provides the selectable
* Locale, the application directory, the theme directory and the
* development mode flag. Choosing matching locale from context by
* provided preferred locales.
*
* If the context indicates that the system is in development mode, then the
* cache is cleared on each request.
*
* If the theme directory has changed, the cache is cleared.
*
* Declared 'protected' so it can be overridden in unit tests.
*/
protected I18nBundle getBundle(String bundleName, List<Locale> preferredLocales) {
log.debug("Getting context bundle '" + bundleName + "'");
checkDevelopmentMode();
checkForChangeInThemeDirectory(ctx);
Locale locale = SelectedLocale.getPreferredLocale(ctx, preferredLocales);
return getBundle(bundleName, locale);
}
/**
* Get an I18nBundle by this name, context, and locale.
*/
private I18nBundle getBundle(String bundleName, Locale locale) {
I18nLogger i18nLogger = new I18nLogger();
try {
String dir = themeDirectory.get();
ResourceBundle.Control control = new ThemeBasedControl(ctx, dir); ResourceBundle.Control control = new ThemeBasedControl(ctx, dir);
ResourceBundle rb = ResourceBundle.getBundle(bundleName, ResourceBundle rb = ResourceBundle.getBundle(bundleName,
req.getLocale(), control); locale, control);
return new I18nBundle(bundleName, rb, i18nLogger); return new I18nBundle(bundleName, rb, i18nLogger);
} catch (MissingResourceException e) { } catch (MissingResourceException e) {
log.warn("Didn't find text bundle '" + bundleName + "'"); log.warn("Didn't find text bundle '" + bundleName + "'");
return I18nBundle.emptyBundle(bundleName, i18nLogger); return I18nBundle.emptyBundle(bundleName, i18nLogger);
} catch (Exception e) { } catch (Exception e) {
log.error("Failed to create text bundle '" + bundleName + "'", e); log.error("Failed to create text bundle '" + bundleName + "'", e);
return I18nBundle.emptyBundle(bundleName, i18nLogger); return I18nBundle.emptyBundle(bundleName, i18nLogger);
} }
} }
@ -139,6 +198,16 @@ public class I18n {
} }
} }
/**
* If we are in development mode, clear the cache.
*/
private void checkDevelopmentMode() {
if (DeveloperSettings.getInstance().getBoolean(Key.I18N_DEFEAT_CACHE)) {
log.debug("In development mode - clearing the cache.");
ResourceBundle.clearCache();
}
}
/** /**
* If the theme directory has changed from before, clear the cache of all * If the theme directory has changed from before, clear the cache of all
* ResourceBundles. * ResourceBundles.
@ -153,6 +222,30 @@ public class I18n {
} }
} }
/**
* If we have a complete model access and the theme directory has changed
* from before, clear the cache of all ResourceBundles.
*/
private void checkForChangeInThemeDirectory(ServletContext ctx) {
WebappDaoFactory wdf = ModelAccess.on(ctx)
.getWebappDaoFactory();
// Only applicable if context has a complete model access
if (Objects.nonNull(wdf)
&& Objects.nonNull(wdf.getApplicationDao())
&& Objects.nonNull(wdf.getApplicationDao().getApplicationBean())) {
String currentDir = wdf
.getApplicationDao()
.getApplicationBean()
.getThemeDir();
String previousDir = themeDirectory.getAndSet(currentDir);
if (!currentDir.equals(previousDir)) {
log.debug("Theme directory changed from '" + previousDir + "' to '"
+ currentDir + "' - clearing the cache.");
ResourceBundle.clearCache();
}
}
}
/** Only clear the cache one time per request. */ /** Only clear the cache one time per request. */
private void clearCacheOnRequest(HttpServletRequest req) { private void clearCacheOnRequest(HttpServletRequest req) {
if (req.getAttribute(ATTRIBUTE_CACHE_CLEARED) != null) { if (req.getAttribute(ATTRIBUTE_CACHE_CLEARED) != null) {

View file

@ -89,8 +89,8 @@ public class LocaleSelectionDataGetter implements DataGetter {
Locale currentLocale) throws FileNotFoundException { Locale currentLocale) throws FileNotFoundException {
Map<String, Object> map = new HashMap<>(); Map<String, Object> map = new HashMap<>();
map.put("code", locale.toString()); map.put("code", locale.toString());
map.put("label", locale.getDisplayName(currentLocale)); map.put("label", locale.getDisplayLanguage(locale));
map.put("imageUrl", LocaleSelectorUtilities.getImageUrl(vreq, locale)); map.put("country", locale.getDisplayCountry(locale));
map.put("selected", currentLocale.equals(locale)); map.put("selected", currentLocale.equals(locale));
return map; return map;
} }

View file

@ -14,6 +14,7 @@ import org.apache.commons.lang3.LocaleUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import edu.cornell.mannlib.vitro.webapp.config.ConfigurationProperties; import edu.cornell.mannlib.vitro.webapp.config.ConfigurationProperties;
import edu.cornell.mannlib.vitro.webapp.i18n.I18n;
import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus; import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus;
/** /**
@ -48,6 +49,10 @@ public class LocaleSelectionSetup implements ServletContextListener {
ss = StartupStatus.getBean(ctx); ss = StartupStatus.getBean(ctx);
props = ConfigurationProperties.getBean(sce); props = ConfigurationProperties.getBean(sce);
// Instantiate I18n instance to afford access to ServletContext
// when requesting a bundle with or without a VitroRequest
I18n.setup(ctx);
readProperties(); readProperties();
if (isForcing() && hasSelectables()) { if (isForcing() && hasSelectables()) {

View file

@ -1,58 +0,0 @@
/* $This file is distributed under the terms of the license in LICENSE$ */
package edu.cornell.mannlib.vitro.webapp.i18n.selection;
import java.io.FileNotFoundException;
import java.util.Locale;
import java.util.Set;
import javax.servlet.ServletContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
/**
* Some static methods for the GUI aspects of selecting a Locale.
*/
public class LocaleSelectorUtilities {
private static final Log log = LogFactory
.getLog(LocaleSelectorUtilities.class);
/**
* Look in the current theme directory to find a selection image for this
* Locale.
*
* Images are expected at a resource path like
* /[themeDir]/i18n/images/select_locale_[locale_code].*
*
* For example, /themes/wilma/i18n/images/select_locale_en.png
* /themes/wilma/i18n/images/select_locale_en.JPEG
* /themes/wilma/i18n/images/select_locale_en.gif
*
* To create a proper URL, prepend the context path.
*/
public static String getImageUrl(VitroRequest vreq, Locale locale)
throws FileNotFoundException {
String filename = "select_locale_" + locale + ".";
String themeDir = vreq.getAppBean().getThemeDir();
String imageDirPath = "/" + themeDir + "i18n/images/";
ServletContext ctx = vreq.getSession().getServletContext();
@SuppressWarnings("unchecked")
Set<String> resourcePaths = ctx.getResourcePaths(imageDirPath);
if (resourcePaths != null) {
for (String resourcePath : resourcePaths) {
if (resourcePath.contains(filename)) {
String fullPath = vreq.getContextPath() + resourcePath;
log.debug("Found image for " + locale + " at '" + fullPath
+ "'");
return fullPath;
}
}
}
throw new FileNotFoundException("Can't find an image for " + locale);
}
}

Some files were not shown because too many files have changed in this diff Show more