diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
new file mode 100644
index 000000000..e71b19cbd
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -0,0 +1,34 @@
+---
+name: Bug report
+about: Create a report to help us improve
+title: ''
+labels: ''
+assignees: ''
+
+---
+
+**Describe the bug**
+A clear and concise description of what the bug is.
+
+**To Reproduce**
+Steps to reproduce the behavior:
+1. Go to '...'
+2. Click on '....'
+3. Scroll down to '....'
+4. See error
+
+**Expected behavior**
+A clear and concise description of what you expected to happen.
+
+**Screenshots**
+If applicable, add screenshots to help explain your problem.
+
+**Desktop (please complete the following information):**
+ - OS: [e.g. Windows, Linux]
+ - Browser [e.g. chrome, safari]
+ - Tomcat version [e.g. 8, 9]
+ - VIVO version [e.g. 1.11.0, 1.12.0]
+ - Apache Solr or ElasticSearch version
+
+**Additional context**
+Add any other context about the problem here.
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
new file mode 100644
index 000000000..bbcbbe7d6
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -0,0 +1,20 @@
+---
+name: Feature request
+about: Suggest an idea for this project
+title: ''
+labels: ''
+assignees: ''
+
+---
+
+**Is your feature request related to a problem? Please describe.**
+A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
+
+**Describe the solution you'd like**
+A clear and concise description of what you want to happen.
+
+**Describe alternatives you've considered**
+A clear and concise description of any alternative solutions or features you've considered.
+
+**Additional context**
+Add any other context or screenshots about the feature request here.
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
new file mode 100644
index 000000000..aa9d3a4aa
--- /dev/null
+++ b/.github/workflows/build.yml
@@ -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
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index ce9b09b50..000000000
--- a/.travis.yml
+++ /dev/null
@@ -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"
diff --git a/README.md b/README.md
index 1125398ec..d65138c6a 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# What is Vitro?
-[](https://travis-ci.org/vivo-project/Vitro)
+[](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.
diff --git a/api/pom.xml b/api/pom.xml
index c486a2ee1..bf032b4e4 100644
--- a/api/pom.xml
+++ b/api/pom.xml
@@ -7,13 +7,13 @@
org.vivoweb
vitro-api
- 1.11.2-SNAPSHOT
+ 1.12.1-SNAPSHOT
jar
org.vivoweb
vitro-project
- 1.11.2-SNAPSHOT
+ 1.12.1-SNAPSHOT
..
@@ -66,7 +66,7 @@
org.vivoweb
vitro-dependencies
- 1.11.2-SNAPSHOT
+ 1.12.1-SNAPSHOT
pom
@@ -85,7 +85,7 @@
junit
junit
- 4.11
+ 4.13.1
test
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/application/ApplicationSetup.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/application/ApplicationSetup.java
index 03798f6c4..a8fd8aa2f 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/application/ApplicationSetup.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/application/ApplicationSetup.java
@@ -62,6 +62,7 @@ public class ApplicationSetup implements ServletContextListener {
private void locateApplicationConfigFile() {
Path path = this.vitroHomeDir.getPath().resolve(APPLICATION_SETUP_PATH);
+
if (!Files.exists(path)) {
throw new IllegalStateException("'" + path + "' does not exist.");
}
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/auth/policy/RootUserPolicy.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/auth/policy/RootUserPolicy.java
index e72436152..816bf7d51 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/auth/policy/RootUserPolicy.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/auth/policy/RootUserPolicy.java
@@ -37,7 +37,14 @@ public class RootUserPolicy implements PolicyIface {
private static final Log log = LogFactory.getLog(RootUserPolicy.class);
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_CHANGE_REQUIRED = "true";
/**
* 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.setFirstName("root");
ua.setLastName("user");
+ // UQAM Add-Feature using getRootPasswordFromConfig()
ua.setArgon2Password(Authenticator.applyArgon2iEncoding(
- ROOT_USER_INITIAL_PASSWORD));
+ getRootPasswordFromConfig()));
ua.setMd5Password("");
- ua.setPasswordChangeRequired(true);
+ // UQAM Add-Feature using getRootPasswdChangeRequiredFromConfig()
+ ua.setPasswordChangeRequired(getRootPasswdChangeRequiredFromConfig().booleanValue());
ua.setStatus(Status.ACTIVE);
ua.setRootUser(true);
@@ -191,7 +200,31 @@ public class RootUserPolicy implements PolicyIface {
ss.warning(this, "For security, "
+ "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
public void contextDestroyed(ServletContextEvent sce) {
// Nothing to destroy
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/beans/ApplicationBean.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/beans/ApplicationBean.java
index c083d44f3..563b1c9b4 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/beans/ApplicationBean.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/beans/ApplicationBean.java
@@ -20,6 +20,7 @@ public class ApplicationBean {
public final static int VIVO_SEARCHBOX_SIZE = 20;
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 int DEFAULT_ROOT_LOGOTYPE_WIDTH = 0;
private final static int DEFAULT_ROOT_LOGOTYPE_HEIGHT = 0;
@@ -33,6 +34,7 @@ public class ApplicationBean {
private boolean initialized = false;
private String sessionIdStr = null;
private String applicationName = DEFAULT_APPLICATION_NAME;
+ private String availableLangsFile = DEFAULT_APPLICATION_AVAILABLE_LANGS_FILE;
private String rootLogotypeImage = DEFAULT_ROOT_LOGOTYPE_IMAGE;
private int rootLogotypeWidth = DEFAULT_ROOT_LOGOTYPE_WIDTH;
@@ -52,6 +54,7 @@ public class ApplicationBean {
output += " initialized from DB: [" + initialized + "]\n";
output += " session id: [" + sessionIdStr + "]\n";
output += " application name: [" + applicationName + "]\n";
+ output += " available langs file: [" + availableLangsFile + "]\n";
output += " root logotype image: [" + rootLogotypeImage + "]\n";
output += " root logotype width: [" + rootLogotypeWidth + "]\n";
output += " root logotype height: [" + rootLogotypeHeight + "]\n";
@@ -177,6 +180,10 @@ public class ApplicationBean {
return "";
}
+ public String getAvailableLangsFile() {
+ return availableLangsFile;
+ }
+
/**
* Directory to find the images. Subdirectories include css, jsp and site_icons.
* Example: "themes/enhanced/"
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/beans/UserAccount.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/beans/UserAccount.java
index 7b9d49792..7b5581885 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/beans/UserAccount.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/beans/UserAccount.java
@@ -7,17 +7,11 @@ import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
-import edu.cornell.mannlib.vitro.webapp.controller.authenticate.Authenticator;
+import org.apache.commons.lang3.RandomStringUtils;
/**
* 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 static final int MIN_PASSWORD_LENGTH = 6;
@@ -52,6 +46,7 @@ public class UserAccount {
private String md5Password = ""; // Never null.
private String oldPassword = ""; // Never null.
private long passwordLinkExpires = 0L; // Never negative.
+ private String emailKey = "";
private boolean passwordChangeRequired = false;
private int loginCount = 0; // Never negative.
@@ -133,15 +128,27 @@ public class UserAccount {
return passwordLinkExpires;
}
- public String getPasswordLinkExpiresHash() {
- return limitStringLength(8, Authenticator.applyArgon2iEncoding(String
- .valueOf(passwordLinkExpires)));
- }
-
public void setPasswordLinkExpires(long 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() {
return passwordChangeRequired;
}
@@ -247,6 +254,7 @@ public class UserAccount {
+ (", oldPassword=" + oldPassword)
+ (", argon2password=" + argon2Password)
+ (", passwordLinkExpires=" + passwordLinkExpires)
+ + (", emailKey =" + emailKey)
+ (", passwordChangeRequired=" + passwordChangeRequired)
+ (", externalAuthOnly=" + externalAuthOnly)
+ (", loginCount=" + loginCount) + (", status=" + status)
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/config/ConfigurationProperties.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/config/ConfigurationProperties.java
index 49fe5e81d..ee27feef3 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/config/ConfigurationProperties.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/config/ConfigurationProperties.java
@@ -109,7 +109,7 @@ public abstract class ConfigurationProperties {
throw new NullPointerException("bean may not be null.");
}
context.setAttribute(ATTRIBUTE_NAME, bean);
- log.info(bean);
+ log.debug(bean);
}
/** Package access, so unit tests can call it. */
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/config/ConfigurationPropertiesSetup.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/config/ConfigurationPropertiesSetup.java
index 773f43e87..54d0ac90d 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/config/ConfigurationPropertiesSetup.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/config/ConfigurationPropertiesSetup.java
@@ -73,7 +73,7 @@ public class ConfigurationPropertiesSetup implements ServletContextListener {
vitroHomeDir, vitroHomeDirConfig);
File runtimePropertiesFile = locateRuntimePropertiesFile(
- vitroHomeDir, vitroHomeDirConfig, ss);
+ vitroHomeDir, vitroHomeDirConfig, ss);
stream = new FileInputStream(runtimePropertiesFile);
Map preempts = createPreemptiveProperties(
@@ -118,7 +118,6 @@ public class ConfigurationPropertiesSetup implements ServletContextListener {
}
}
-
private File locateRuntimePropertiesFile(File vitroHomeDir,
File vitroHomeDirConfig, StartupStatus ss) {
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsSelector.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsSelector.java
index 6caadf24c..d878ae315 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsSelector.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsSelector.java
@@ -249,6 +249,7 @@ public class UserAccountsSelector {
user.setMd5Password(ifLiteralPresent(solution, "md5pwd", ""));
user.setArgon2Password(ifLiteralPresent(solution, "a2pwd", ""));
user.setPasswordLinkExpires(ifLongPresent(solution, "expire", 0L));
+ user.setEmailKey(ifLiteralPresent(solution, "emailKey", ""));
user.setLoginCount(ifIntPresent(solution, "count", 0));
user.setLastLoginTime(ifLongPresent(solution, "lastLogin", 0));
user.setStatus(parseStatus(solution, "status", null));
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsAddPage.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsAddPage.java
index bdbc5dbce..7fc4181da 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsAddPage.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsAddPage.java
@@ -156,6 +156,7 @@ public class UserAccountsAddPage extends UserAccountsPage {
u.setOldPassword("");
u.setPasswordChangeRequired(false);
u.setPasswordLinkExpires(0);
+ u.setEmailKey("");
u.setLoginCount(0);
u.setLastLoginTime(0L);
u.setStatus(Status.INACTIVE);
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsAddPageStrategy.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsAddPageStrategy.java
index 307ccf9f6..036d314e2 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsAddPageStrategy.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsAddPageStrategy.java
@@ -84,6 +84,7 @@ public abstract class UserAccountsAddPageStrategy extends UserAccountsPage {
u.setStatus(Status.ACTIVE);
} else {
u.setPasswordLinkExpires(figureExpirationDate().getTime());
+ u.generateEmailKey();
u.setStatus(Status.INACTIVE);
}
}
@@ -119,10 +120,8 @@ public abstract class UserAccountsAddPageStrategy extends UserAccountsPage {
private String buildCreatePasswordLink() {
try {
String email = page.getAddedAccount().getEmailAddress();
- String hash = page.getAddedAccount()
- .getPasswordLinkExpiresHash();
- String relativeUrl = UrlBuilder.getUrl(CREATE_PASSWORD_URL,
- "user", email, "key", hash);
+ String key = page.getAddedAccount().getEmailKey();
+ String relativeUrl = UrlBuilder.getUrl(CREATE_PASSWORD_URL, "user", email, "key", key);
URL context = new URL(vreq.getRequestURL().toString());
URL url = new URL(context, relativeUrl);
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsEditPage.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsEditPage.java
index 42dd4102d..13e1ab0dd 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsEditPage.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsEditPage.java
@@ -274,6 +274,7 @@ public class UserAccountsEditPage extends UserAccountsPage {
userAccount.setOldPassword("");
userAccount.setPasswordChangeRequired(false);
userAccount.setPasswordLinkExpires(0L);
+ userAccount.setEmailKey("");
}
if (isRootUser()) {
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsEditPageStrategy.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsEditPageStrategy.java
index 708f11e66..d9ee8aa14 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsEditPageStrategy.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsEditPageStrategy.java
@@ -82,6 +82,7 @@ public abstract class UserAccountsEditPageStrategy extends UserAccountsPage {
protected void setAdditionalProperties(UserAccount u) {
if (resetPassword && !page.isExternalAuthOnly()) {
u.setPasswordLinkExpires(figureExpirationDate().getTime());
+ u.generateEmailKey();
}
}
@@ -121,10 +122,8 @@ public abstract class UserAccountsEditPageStrategy extends UserAccountsPage {
private String buildResetPasswordLink() {
try {
String email = page.getUpdatedAccount().getEmailAddress();
- String hash = page.getUpdatedAccount()
- .getPasswordLinkExpiresHash();
- String relativeUrl = UrlBuilder.getUrl(RESET_PASSWORD_URL,
- "user", email, "key", hash);
+ String key = page.getUpdatedAccount().getEmailKey();
+ String relativeUrl = UrlBuilder.getUrl(RESET_PASSWORD_URL, "user", email, "key", key);
URL context = new URL(vreq.getRequestURL().toString());
URL url = new URL(context, relativeUrl);
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsCreatePasswordPage.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsCreatePasswordPage.java
index b9515d4c7..68daa2d67 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsCreatePasswordPage.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsCreatePasswordPage.java
@@ -36,6 +36,7 @@ public class UserAccountsCreatePasswordPage extends
userAccount.setArgon2Password(Authenticator.applyArgon2iEncoding(newPassword));
userAccount.setMd5Password("");
userAccount.setPasswordLinkExpires(0L);
+ userAccount.setEmailKey("");
userAccount.setPasswordChangeRequired(false);
userAccount.setStatus(Status.ACTIVE);
userAccountsDao.updateUserAccount(userAccount);
@@ -53,6 +54,11 @@ public class UserAccountsCreatePasswordPage extends
protected String passwordChangeNotPendingMessage() {
return i18n.text("account_already_activated", userEmail);
}
+
+ @Override
+ protected String passwordChangeInavlidKeyMessage() {
+ return i18n.text("password_change_invalid_key", userEmail);
+ }
@Override
protected String templateName() {
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsFirstTimeExternalPage.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsFirstTimeExternalPage.java
index fc11f665d..ffb34c754 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsFirstTimeExternalPage.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsFirstTimeExternalPage.java
@@ -195,6 +195,7 @@ public class UserAccountsFirstTimeExternalPage extends UserAccountsPage {
u.setExternalAuthId(externalAuthId);
u.setPasswordChangeRequired(false);
u.setPasswordLinkExpires(0);
+ u.setEmailKey("");
u.setExternalAuthOnly(true);
u.setLoginCount(0);
u.setStatus(Status.ACTIVE);
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsMyAccountPageStrategy.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsMyAccountPageStrategy.java
index 057098eea..ca895cab8 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsMyAccountPageStrategy.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsMyAccountPageStrategy.java
@@ -159,6 +159,7 @@ public abstract class UserAccountsMyAccountPageStrategy extends
userAccount.setMd5Password("");
userAccount.setPasswordChangeRequired(false);
userAccount.setPasswordLinkExpires(0L);
+ userAccount.setEmailKey("");
}
}
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsPasswordBasePage.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsPasswordBasePage.java
index 3923c17b2..d4cc56f03 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsPasswordBasePage.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsPasswordBasePage.java
@@ -103,12 +103,12 @@ public abstract class UserAccountsPasswordBasePage extends UserAccountsPage {
return;
}
- String expectedKey = userAccount.getPasswordLinkExpiresHash();
- if (!key.equals(expectedKey)) {
+ String expectedKey = userAccount.getEmailKey();
+ if (key.isEmpty() || !key.equals(expectedKey)) {
log.warn("Password request for '" + userEmail + "' is bogus: key ("
+ key + ") doesn't match expected key (" + expectedKey
+ ")");
- bogusMessage = passwordChangeNotPendingMessage();
+ bogusMessage = passwordChangeInavlidKeyMessage();
return;
}
@@ -153,7 +153,7 @@ public abstract class UserAccountsPasswordBasePage extends UserAccountsPage {
body.put("minimumLength", UserAccount.MIN_PASSWORD_LENGTH);
body.put("maximumLength", UserAccount.MAX_PASSWORD_LENGTH);
body.put("userAccount", userAccount);
- body.put("key", userAccount.getPasswordLinkExpiresHash());
+ body.put("key", userAccount.getEmailKey());
body.put("newPassword", newPassword);
body.put("confirmPassword", confirmPassword);
body.put("formUrls", buildUrlsMap());
@@ -176,6 +176,8 @@ public abstract class UserAccountsPasswordBasePage extends UserAccountsPage {
protected abstract String alreadyLoggedInMessage(String currentUserEmail);
protected abstract String passwordChangeNotPendingMessage();
+
+ protected abstract String passwordChangeInavlidKeyMessage();
protected abstract String templateName();
}
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsResetPasswordPage.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsResetPasswordPage.java
index 712df1b40..f865cbe94 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsResetPasswordPage.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsResetPasswordPage.java
@@ -55,6 +55,11 @@ public class UserAccountsResetPasswordPage extends UserAccountsPasswordBasePage
protected String passwordChangeNotPendingMessage() {
return i18n.text("password_change_not_pending", userEmail);
}
+
+ @Override
+ protected String passwordChangeInavlidKeyMessage() {
+ return i18n.text("password_change_invalid_key", userEmail);
+ }
@Override
protected String templateName() {
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/admin/SparqlQueryController.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/admin/SparqlQueryController.java
index 096263dab..5369d2626 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/admin/SparqlQueryController.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/admin/SparqlQueryController.java
@@ -17,6 +17,8 @@ import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
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.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -75,8 +77,8 @@ public class SparqlQueryController extends FreemarkerHttpServlet {
private static final String[] SAMPLE_QUERY = { //
"", //
"#", //
- "# This example query gets 20 geographic locations", //
- "# and (if available) their labels", //
+ "i18n:sparql_query_description_0", //
+ "i18n:sparql_query_description_1", //
"#", //
"SELECT ?geoLocation ?label", //
"WHERE", //
@@ -193,9 +195,11 @@ public class SparqlQueryController extends FreemarkerHttpServlet {
@Override
protected ResponseValues processRequest(VitroRequest vreq) throws Exception {
+ I18nBundle i18n = I18n.bundle(vreq);
+
Map bodyMap = new HashMap<>();
- bodyMap.put("sampleQuery", buildSampleQuery(buildPrefixList(vreq)));
- bodyMap.put("title", "SPARQL Query");
+ bodyMap.put("sampleQuery", buildSampleQuery(i18n, buildPrefixList(vreq)));
+ bodyMap.put("title", i18n.text("sparql_query_title"));
bodyMap.put("submitUrl", UrlBuilder.getUrl("admin/sparqlquery"));
return new TemplateResponseValues(TEMPLATE_NAME, bodyMap);
}
@@ -222,7 +226,7 @@ public class SparqlQueryController extends FreemarkerHttpServlet {
return prefixList;
}
- private String buildSampleQuery(List prefixList) {
+ private String buildSampleQuery(I18nBundle i18n, List prefixList) {
StringWriter sw = new StringWriter();
PrintWriter writer = new PrintWriter(sw);
@@ -230,6 +234,10 @@ public class SparqlQueryController extends FreemarkerHttpServlet {
writer.println(p);
}
for (String line : SAMPLE_QUERY) {
+ if (line.startsWith("i18n:")) {
+ // Get i18n translation
+ line = i18n.text(line.substring("i18n:".length()));
+ }
writer.println(line);
}
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/BasicAuthenticator.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/BasicAuthenticator.java
index f6f95081b..34fc6a01d 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/BasicAuthenticator.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/BasicAuthenticator.java
@@ -134,6 +134,7 @@ public class BasicAuthenticator extends Authenticator {
userAccount.setMd5Password("");
userAccount.setPasswordChangeRequired(false);
userAccount.setPasswordLinkExpires(0L);
+ userAccount.setEmailKey("");
getUserAccountsDao().updateUserAccount(userAccount);
}
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/LoginRedirector.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/LoginRedirector.java
index ffc18f805..65b8a2310 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/LoginRedirector.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/LoginRedirector.java
@@ -108,7 +108,9 @@ public class LoginRedirector {
throws IOException {
try {
DisplayMessage.setMessage(request, assembleWelcomeMessage());
- response.sendRedirect(getRedirectionUriForLoggedInUser());
+ String redirectUrl = getRedirectionUriForLoggedInUser();
+ log.debug("Sending redirect to path: " + redirectUrl);
+ response.sendRedirect(redirectUrl);
} catch (IOException e) {
log.debug("Problem with re-direction", e);
response.sendRedirect(getApplicationHomePageUrl());
@@ -175,21 +177,13 @@ public class LoginRedirector {
}
}
- /**
- * The application home page can be overridden by an attribute in the
- * ServletContext. Further, it can either be an absolute URL, or it can be
- * relative to the application. Weird.
- */
private String getApplicationHomePageUrl() {
- String contextRedirect = (String) session.getServletContext()
- .getAttribute("postLoginRequest");
- if (contextRedirect != null) {
- if (contextRedirect.indexOf(":") == -1) {
- return request.getContextPath() + contextRedirect;
- } else {
- return contextRedirect;
- }
+ String contextPath = request.getContextPath();
+ if (contextPath.equals("")) {
+ return "/";
+ }
+ else {
+ return contextPath;
}
- return request.getContextPath();
}
}
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/Classes2ClassesRetryController.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/Classes2ClassesRetryController.java
index d4417e6a3..d51d90452 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/Classes2ClassesRetryController.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/Classes2ClassesRetryController.java
@@ -43,7 +43,7 @@ public class Classes2ClassesRetryController extends BaseEditController {
action = epo.getAction();
}
- VClassDao vcDao = ModelAccess.on(getServletContext()).getWebappDaoFactory().getVClassDao();
+ VClassDao vcDao = ModelAccess.on(request).getWebappDaoFactory().getVClassDao();
epo.setDataAccessObject(vcDao);
Classes2Classes objectForEditing = new Classes2Classes();
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/ClassgroupRetryController.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/ClassgroupRetryController.java
index 5c1535489..82b618665 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/ClassgroupRetryController.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/ClassgroupRetryController.java
@@ -51,8 +51,7 @@ public class ClassgroupRetryController extends BaseEditController {
action = epo.getAction();
}
- VClassGroupDao cgDao = ModelAccess.on(
- getServletContext()).getWebappDaoFactory().getVClassGroupDao();
+ VClassGroupDao cgDao = ModelAccess.on(request).getWebappDaoFactory().getVClassGroupDao();
epo.setDataAccessObject(cgDao);
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/DatapropRetryController.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/DatapropRetryController.java
index c4b04c08b..70d47a80a 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/DatapropRetryController.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/DatapropRetryController.java
@@ -50,11 +50,12 @@ public class DatapropRetryController extends BaseEditController {
//create an EditProcessObject for this and put it in the session
EditProcessObject epo = super.createEpo(request);
+ epo.setImplementationClass(DataProperty.class);
epo.setBeanClass(DataProperty.class);
VitroRequest vreq = new VitroRequest(request);
- WebappDaoFactory wadf = ModelAccess.on(getServletContext()).getWebappDaoFactory();
+ WebappDaoFactory wadf = ModelAccess.on(vreq).getWebappDaoFactory();
DatatypeDao dDao = wadf.getDatatypeDao();
DataPropertyDao dpDao = wadf.getDataPropertyDao();
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/FauxPropertyRetryController.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/FauxPropertyRetryController.java
index 941c6e7f6..9f4d27092 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/FauxPropertyRetryController.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/FauxPropertyRetryController.java
@@ -106,7 +106,7 @@ public class FauxPropertyRetryController extends BaseEditController {
this.epo = epo;
- this.fpDao = ModelAccess.on(ctx).getWebappDaoFactory()
+ this.fpDao = ModelAccess.on(req).getWebappDaoFactory()
.getFauxPropertyDao();
}
@@ -114,6 +114,8 @@ public class FauxPropertyRetryController extends BaseEditController {
void populate() {
epo.setDataAccessObject(fpDao);
epo.setAction(determineAction());
+ epo.setImplementationClass(FauxProperty.class);
+ epo.setBeanClass(FauxProperty.class);
if (epo.getUseRecycledBean()) {
beanForEditing = (FauxProperty) epo.getNewBean();
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/NamespacePrefixOperationController.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/NamespacePrefixOperationController.java
index 356569c54..2223c69e6 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/NamespacePrefixOperationController.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/NamespacePrefixOperationController.java
@@ -71,7 +71,7 @@ public class NamespacePrefixOperationController extends BaseEditController {
if (request.getParameter("_cancel") == null) {
- OntModel ontModel = ModelAccess.on(getServletContext()).getOntModel();
+ OntModel ontModel = ModelAccess.on(req).getOntModel();
String namespaceStr = request.getParameter("namespace");
String prefixStr = request.getParameter("prefix");
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/PropertyGroupRetryController.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/PropertyGroupRetryController.java
index d84b15db5..3ae22e5c1 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/PropertyGroupRetryController.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/PropertyGroupRetryController.java
@@ -51,7 +51,7 @@ public class PropertyGroupRetryController extends BaseEditController {
}
PropertyGroupDao pgDao = ModelAccess.on(
- getServletContext()).getWebappDaoFactory().getPropertyGroupDao();
+ req).getWebappDaoFactory().getPropertyGroupDao();
epo.setDataAccessObject(pgDao);
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/PropertyRetryController.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/PropertyRetryController.java
index 5e35fb369..909ebeff9 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/PropertyRetryController.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/PropertyRetryController.java
@@ -53,6 +53,7 @@ public class PropertyRetryController extends BaseEditController {
/*for testing*/
ObjectProperty testMask = new ObjectProperty();
+ epo.setImplementationClass(ObjectProperty.class);
epo.setBeanClass(ObjectProperty.class);
epo.setBeanMask(testMask);
@@ -64,7 +65,7 @@ public class PropertyRetryController extends BaseEditController {
action = epo.getAction();
}
- ObjectPropertyDao propDao = ModelAccess.on(getServletContext()).getWebappDaoFactory().getObjectPropertyDao();
+ ObjectPropertyDao propDao = ModelAccess.on(req).getWebappDaoFactory().getObjectPropertyDao();
epo.setDataAccessObject(propDao);
OntologyDao ontDao = request.getUnfilteredWebappDaoFactory().getOntologyDao();
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/RestrictionOperationController.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/RestrictionOperationController.java
index f704b5b39..26956be74 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/RestrictionOperationController.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/RestrictionOperationController.java
@@ -48,7 +48,7 @@ public class RestrictionOperationController extends BaseEditController {
String defaultLandingPage = getDefaultLandingPage(request);
try {
- OntModel ontModel = ModelAccess.on(getServletContext())
+ OntModel ontModel = ModelAccess.on(req)
.getOntModel(TBOX_ASSERTIONS);
HashMap epoHash = null;
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/VclassEditController.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/VclassEditController.java
index 340a846e4..a9b018670 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/VclassEditController.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/VclassEditController.java
@@ -48,7 +48,7 @@ public class VclassEditController extends BaseEditController {
EditProcessObject epo = super.createEpo(request, FORCE_NEW);
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"));
if (vcl == null) {
@@ -152,8 +152,8 @@ public class VclassEditController extends BaseEditController {
request.setAttribute("formSelect",formSelect);
// if supported, we want to show only the asserted superclasses and subclasses.
- VClassDao vcDao = ModelAccess.on(getServletContext()).getWebappDaoFactory(ASSERTIONS_ONLY).getVClassDao();
- VClassDao displayVcDao = ModelAccess.on(getServletContext()).getWebappDaoFactory().getVClassDao();
+ VClassDao vcDao = ModelAccess.on(req).getWebappDaoFactory(ASSERTIONS_ONLY).getVClassDao();
+ VClassDao displayVcDao = ModelAccess.on(req).getWebappDaoFactory().getVClassDao();
List superVClasses = getVClassesForURIList(
vcDao.getSuperClassURIs(vcl.getURI(),false), displayVcDao);
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/VclassRetryController.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/VclassRetryController.java
index ee00bc64e..326b4fb1d 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/VclassRetryController.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/VclassRetryController.java
@@ -66,11 +66,10 @@ public class VclassRetryController extends BaseEditController {
action = epo.getAction();
}
- WebappDaoFactory wadf = ModelAccess.on(getServletContext()).getWebappDaoFactory();
+ WebappDaoFactory wadf = ModelAccess.on(req).getWebappDaoFactory();
VClassDao vcwDao = wadf.getVClassDao();
epo.setDataAccessObject(vcwDao);
- VClassGroupDao cgDao = wadf.getVClassGroupDao();
OntologyDao oDao = wadf.getOntologyDao();
VClass vclassForEditing = null;
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/listing/jena/NamespacesListingController.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/listing/jena/NamespacesListingController.java
index 05acd18ad..79bc5f071 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/listing/jena/NamespacesListingController.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/listing/jena/NamespacesListingController.java
@@ -37,7 +37,7 @@ public class NamespacesListingController extends BaseEditController {
VitroRequest vrequest = new VitroRequest(request);
- OntModel ontModel = ModelAccess.on(getServletContext()).getOntModel();
+ OntModel ontModel = ModelAccess.on(vrequest).getOntModel();
ArrayList results = new ArrayList();
request.setAttribute("results",results);
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/listing/jena/RestrictionsListingController.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/listing/jena/RestrictionsListingController.java
index 02b176969..746185621 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/listing/jena/RestrictionsListingController.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/listing/jena/RestrictionsListingController.java
@@ -54,7 +54,7 @@ public class RestrictionsListingController extends BaseEditController {
epo = super.createEpo(request);
- OntModel ontModel = ModelAccess.on(getServletContext()).getOntModel();
+ OntModel ontModel = ModelAccess.on(vrequest).getOntModel();
ObjectPropertyDao opDao = vrequest.getUnfilteredWebappDaoFactory().getObjectPropertyDao();
VClassDao vcDao = vrequest.getUnfilteredWebappDaoFactory().getVClassDao();
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/BrowseController.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/BrowseController.java
index 0ee20f2fe..fcf655e36 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/BrowseController.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/BrowseController.java
@@ -3,6 +3,8 @@
package edu.cornell.mannlib.vitro.webapp.controller.freemarker;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -42,6 +44,8 @@ public class BrowseController extends FreemarkerHttpServlet {
List groups = null;
VClassGroupsForRequest vcgc = VClassGroupCache.getVClassGroups(vreq);
groups =vcgc.getGroups();
+ Collections.sort(groups, publicNameComparator);
+// sortGroupListByPublicName(groups);
List vcgroups = new ArrayList(groups.size());
for (VClassGroup group : groups) {
vcgroups.add(new VClassGroupTemplateModel(group));
@@ -50,4 +54,35 @@ public class BrowseController extends FreemarkerHttpServlet {
return new TemplateResponseValues(templateName, body);
}
+ public Comparator publicNameComparator = new Comparator() {
+
+ 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 groupList) {
+// groupList.sort(new Comparator() {
+// 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;
+// }
+// });
+// }
+
}
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/DeleteIndividualController.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/DeleteIndividualController.java
new file mode 100644
index 000000000..f107531dc
--- /dev/null
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/DeleteIndividualController.java
@@ -0,0 +1,200 @@
+package edu.cornell.mannlib.vitro.webapp.controller.freemarker;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.jena.query.Query;
+import org.apache.jena.query.QueryExecution;
+import org.apache.jena.query.QueryExecutionFactory;
+import org.apache.jena.query.QueryFactory;
+import org.apache.jena.query.QuerySolution;
+import org.apache.jena.query.QuerySolutionMap;
+import org.apache.jena.query.ResultSet;
+import org.apache.jena.rdf.model.Model;
+import org.apache.jena.rdf.model.ResourceFactory;
+import org.apache.jena.shared.Lock;
+
+import edu.cornell.mannlib.vitro.webapp.auth.permissions.SimplePermission;
+import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.AuthorizationRequest;
+import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
+import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.RedirectResponseValues;
+import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues;
+import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues;
+import edu.cornell.mannlib.vitro.webapp.dao.DisplayVocabulary;
+import edu.cornell.mannlib.vitro.webapp.dao.jena.QueryUtils;
+import edu.cornell.mannlib.vitro.webapp.dao.jena.event.BulkUpdateEvent;
+import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelNames;
+import edu.cornell.mannlib.vitro.webapp.rdfservice.ChangeSet;
+import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService;
+import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFServiceException;
+import edu.cornell.mannlib.vitro.webapp.rdfservice.impl.RDFServiceUtils;
+
+@WebServlet(name="DeleteIndividualController",urlPatterns="/deleteIndividualController")
+public class DeleteIndividualController extends FreemarkerHttpServlet{
+
+ private static final Log log = LogFactory.getLog(DeleteIndividualController.class);
+ private static final boolean BEGIN = true;
+ private static final boolean END = !BEGIN;
+
+ private static String TYPE_QUERY = ""
+ + "PREFIX vitro: "
+ + "SELECT ?type "
+ + "WHERE"
+ + "{ ?individualURI vitro:mostSpecificType ?type ."
+ + "}";
+ private static String queryForDeleteQuery =
+ "PREFIX display: <" + DisplayVocabulary.DISPLAY_NS +"> \n" +
+ "SELECT ?deleteQueryText WHERE { ?associatedURI display:hasDeleteQuery ?deleteQueryText }";
+
+ private static final String DEFAULT_DELETE_QUERY_TEXT = "DESCRIBE ?individualURI";
+
+ @Override
+ protected AuthorizationRequest requiredActions(VitroRequest vreq) {
+ return SimplePermission.DO_FRONT_END_EDITING.ACTION;
+ }
+
+ protected ResponseValues processRequest(VitroRequest vreq) {
+ String errorMessage = handleErrors(vreq);
+ if (!errorMessage.isEmpty()) {
+ return prepareErrorMessage(errorMessage);
+ }
+ String individualUri = vreq.getParameter("individualUri");
+ String type = getObjectMostSpecificType(individualUri, vreq);
+ Model displayModel = vreq.getDisplayModel();
+
+ String delteQueryText = getDeleteQueryForType(type, displayModel);
+ byte[] toRemove = getIndividualsToDelete(individualUri, delteQueryText, vreq);
+ if (toRemove.length > 0) {
+ deleteIndividuals(toRemove, vreq);
+ }
+ String redirectUrl = getRedirectUrl(vreq);
+
+ return new RedirectResponseValues(redirectUrl, HttpServletResponse.SC_SEE_OTHER);
+ }
+
+ private String getRedirectUrl(VitroRequest vreq) {
+ String redirectUrl = vreq.getParameter("redirectUrl");
+ if (redirectUrl != null) {
+ return redirectUrl;
+ }
+ return "/";
+ }
+
+
+ private TemplateResponseValues prepareErrorMessage(String errorMessage) {
+ HashMap map = new HashMap();
+ map.put("errorMessage", errorMessage);
+ return new TemplateResponseValues("error-message.ftl", map);
+ }
+
+ private String handleErrors(VitroRequest vreq) {
+ String uri = vreq.getParameter("individualUri");
+ if (uri == null) {
+ return "Individual uri is null. No object to delete.";
+ }
+ if (uri.contains(">")) {
+ return "Individual uri shouldn't contain >";
+ }
+ return "";
+ }
+
+ private static String getDeleteQueryForType(String typeURI, Model displayModel) {
+ String deleteQueryText = DEFAULT_DELETE_QUERY_TEXT;
+ Query queryForTypeSpecificDeleteQuery = QueryFactory.create(queryForDeleteQuery);
+ QuerySolutionMap initialBindings = new QuerySolutionMap();
+ initialBindings.add("associatedURI", ResourceFactory.createResource(typeURI));
+ displayModel.enterCriticalSection(Lock.READ);
+ try {
+ QueryExecution qexec = QueryExecutionFactory.create(queryForTypeSpecificDeleteQuery, displayModel, initialBindings);
+ try {
+ ResultSet results = qexec.execSelect();
+ while (results.hasNext()) {
+ QuerySolution solution = results.nextSolution();
+ deleteQueryText = solution.get("deleteQueryText").toString();
+ }
+ } finally {
+ qexec.close();
+ }
+ } finally {
+ displayModel.leaveCriticalSection();
+ }
+
+ if (!deleteQueryText.equals(DEFAULT_DELETE_QUERY_TEXT)) {
+ log.debug("For " + typeURI + " found delete query \n" + deleteQueryText);
+ } else {
+ log.debug("For " + typeURI + " delete query not found. Using defalut query \n" + deleteQueryText);
+ }
+ return deleteQueryText;
+ }
+
+ private String getObjectMostSpecificType(String individualURI, VitroRequest vreq) {
+ String type = "";
+ try {
+ Query typeQuery = QueryFactory.create(TYPE_QUERY);
+ QuerySolutionMap bindings = new QuerySolutionMap();
+ bindings.add("individualURI", ResourceFactory.createResource(individualURI));
+ Model ontModel = vreq.getJenaOntModel();
+ QueryExecution qexec = QueryExecutionFactory.create(typeQuery, ontModel, bindings);
+ ResultSet results = qexec.execSelect();
+ while (results.hasNext()) {
+ QuerySolution solution = results.nextSolution();
+ type = solution.get("type").toString();
+ log.debug(type);
+ }
+ } catch (Exception e) {
+ log.error("Failed to get type for individual URI " + individualURI);
+ log.error(e, e);
+ }
+ return type;
+ }
+
+ private byte[] getIndividualsToDelete(String targetIndividual, String deleteQuery, VitroRequest vreq) {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ try {
+ Query queryForTypeSpecificDeleteQuery = QueryFactory.create(deleteQuery);
+ QuerySolutionMap bindings = new QuerySolutionMap();
+ bindings.add("individualURI", ResourceFactory.createResource(targetIndividual));
+ Model ontModel = vreq.getJenaOntModel();
+ QueryExecution qexec = QueryExecutionFactory.create(queryForTypeSpecificDeleteQuery, ontModel, bindings);
+ Model results = qexec.execDescribe();
+ results.write(out, "N3");
+
+ } catch (Exception e) {
+ log.error("Query raised an error \n" + deleteQuery);
+ log.error(e, e);
+ }
+ return out.toByteArray();
+ }
+
+ private void deleteIndividuals(byte[] toRemove, VitroRequest vreq) {
+ String removingString = new String(toRemove, StandardCharsets.UTF_8);
+ RDFService rdfService = vreq.getRDFService();
+ ChangeSet cs = makeChangeSet(rdfService);
+ InputStream in = new ByteArrayInputStream(toRemove);
+ cs.addRemoval(in, RDFServiceUtils.getSerializationFormatFromJenaString("N3"), ModelNames.ABOX_ASSERTIONS);
+ try {
+ rdfService.changeSetUpdate(cs);
+ } catch (RDFServiceException e) {
+ log.error("Got error while removing\n" + removingString);
+ throw new RuntimeException(e);
+ }
+ }
+
+ private ChangeSet makeChangeSet(RDFService rdfService) {
+ ChangeSet cs = rdfService.manufactureChangeSet();
+ cs.addPreChangeEvent(new BulkUpdateEvent(null, BEGIN));
+ cs.addPostChangeEvent(new BulkUpdateEvent(null, END));
+ return cs;
+ }
+
+
+
+}
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/DeletePropertyController.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/DeletePropertyController.java
index c62a2c87a..18fb4f39f 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/DeletePropertyController.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/DeletePropertyController.java
@@ -10,6 +10,9 @@ import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
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.requestedAction.AuthorizationRequest;
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.modelaccess.ModelAccess;
import edu.cornell.mannlib.vitro.webapp.web.URLEncoder;
+
+
/*
* 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.
@@ -61,14 +66,14 @@ public class DeletePropertyController extends FreemarkerHttpServlet {
private String getRedirectUrl(VitroRequest vreq) {
- // TODO Auto-generated method stub
+ // TODO Auto-generated method stub
String subjectUri = EditConfigurationUtils.getSubjectUri(vreq);
String predicateUri = EditConfigurationUtils.getPredicateUri(vreq);
- int hashIndex = predicateUri.lastIndexOf("#");
- String localName = predicateUri.substring(hashIndex + 1);
+ Property prop = ResourceFactory.createProperty(predicateUri);
+ String localName = prop.getLocalName();
String redirectUrl = "/entity?uri=" + URLEncoder.encode(subjectUri);
- return redirectUrl + "#" + URLEncoder.encode(localName);
- }
+ return redirectUrl + "#" + URLEncoder.encode(localName);
+ }
private String handleErrors(VitroRequest vreq) {
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/FreemarkerHttpServlet.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/FreemarkerHttpServlet.java
index bc7766e83..50f54e2e0 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/FreemarkerHttpServlet.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/FreemarkerHttpServlet.java
@@ -8,6 +8,7 @@ import static javax.mail.Message.RecipientType.TO;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
+import java.nio.charset.Charset;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
@@ -17,7 +18,6 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import edu.cornell.mannlib.vitro.webapp.dao.jena.MenuDaoJena;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -93,6 +93,8 @@ public class FreemarkerHttpServlet extends VitroHttpServlet {
throws IOException, ServletException {
super.doGet(request,response);
+//UQAM-Optimization set for UTF-8
+ response.setCharacterEncoding("UTF-8");
VitroRequest vreq = new VitroRequest(request);
ResponseValues responseValues = null;
@@ -103,8 +105,8 @@ public class FreemarkerHttpServlet extends VitroHttpServlet {
if (!isAuthorizedToDisplayPage(request, response, requiredActions(vreq))) {
return;
}
-
responseValues = processRequest(vreq);
+
doResponse(vreq, response, responseValues);
} catch (Throwable e) {
@@ -256,7 +258,7 @@ public class FreemarkerHttpServlet extends VitroHttpServlet {
protected void doTemplate(VitroRequest vreq, HttpServletResponse response,
ResponseValues values) throws TemplateProcessingException {
- Map templateDataModel = new HashMap();
+ Map templateDataModel = new HashMap();
templateDataModel.putAll(getPageTemplateValues(vreq));
// Add the values that we got from the subcontroller processRequest() method, and merge to the template.
@@ -276,8 +278,15 @@ public class FreemarkerHttpServlet extends VitroHttpServlet {
// is specified in the main page template.
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.
templateDataModel.put("templateType", PAGE_TEMPLATE_TYPE);
@@ -462,7 +471,7 @@ public class FreemarkerHttpServlet extends VitroHttpServlet {
protected MainMenu getDisplayModelMenu(VitroRequest vreq){
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
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/TemplateProcessingHelper.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/TemplateProcessingHelper.java
index 85d648f6b..c5439d4a2 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/TemplateProcessingHelper.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/TemplateProcessingHelper.java
@@ -42,7 +42,7 @@ public class TemplateProcessingHelper {
try {
Environment env = template.createProcessingEnvironment(map, writer);
-
+
// Define a setup template to be included by every page template
String templateType = (String) map.get("templateType");
if (FreemarkerHttpServlet.PAGE_TEMPLATE_TYPE.equals(templateType)) {
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/UrlBuilder.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/UrlBuilder.java
index 8e4d4ae25..bb9d7428b 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/UrlBuilder.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/UrlBuilder.java
@@ -37,6 +37,7 @@ public class UrlBuilder {
LOGIN("/login"),
LOGOUT("/logout"),
OBJECT_PROPERTY_EDIT("/propertyEdit"),
+ EXTENDED_SEARCH("/extendedsearch"),
SEARCH("/search"),
SITE_ADMIN("/siteAdmin"),
TERMS_OF_USE("/termsOfUse"),
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/ViewLabelsServlet.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/ViewLabelsServlet.java
index 1425b10f7..f68db8d56 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/ViewLabelsServlet.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/ViewLabelsServlet.java
@@ -11,28 +11,29 @@ import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
+import java.util.Set;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import org.apache.commons.lang3.LocaleUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-
import org.apache.jena.query.QuerySolution;
import org.apache.jena.query.ResultSet;
import org.apache.jena.rdf.model.Literal;
import edu.cornell.mannlib.vitro.webapp.beans.Individual;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
-import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerHttpServlet;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ExceptionResponseValues;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues;
import edu.cornell.mannlib.vitro.webapp.dao.jena.QueryUtils;
import edu.cornell.mannlib.vitro.webapp.i18n.selection.SelectedLocale;
+import edu.cornell.mannlib.vitro.webapp.rdfservice.filter.LanguageFilteringUtils;
/*Servlet to view all labels in various languages for individual*/
@@ -47,12 +48,13 @@ public class ViewLabelsServlet extends FreemarkerHttpServlet{
String subjectUri = vreq.getParameter("subjectUri");
body.put("subjectUri", subjectUri);
try {
- //Get all language codes/labels in the system, and this list is sorted by language name
- List> locales = this.getLocales(vreq);
+ //the labels already added by the user
+ ArrayList existingLabels = this.getExistingLabels(subjectUri, vreq);
+ //Get all language codes/labels used in the list of existing labels
+ List> locales = this.getLocales(vreq, existingLabels);
//Get code to label hashmap - we use this to get the language name for the language code returned in the rdf literal
HashMap localeCodeToNameMap = this.getFullCodeToLanguageNameMap(locales);
- //the labels already added by the user
- ArrayList existingLabels = this.getExistingLabels(subjectUri, vreq);
+
//existing labels keyed by language name and each of the list of labels is sorted by language name
HashMap> existingLabelsByLanguageName = this.getLabelsSortedByLanguageName(existingLabels, localeCodeToNameMap, vreq, subjectUri);
//Get available locales for the drop down for adding a new label, also sorted by language name
@@ -137,20 +139,26 @@ public class ViewLabelsServlet extends FreemarkerHttpServlet{
doGet(request, response);
}
- //get locales
- public List> getLocales(VitroRequest vreq) {
- List selectables = SelectedLocale.getSelectableLocales(vreq);
- if (selectables.isEmpty()) {
+ //get locales present in list of literals
+ public List> getLocales(VitroRequest vreq,
+ List existingLiterals) {
+ Set locales = new HashSet();
+ for(Literal literal : existingLiterals) {
+ String language = literal.getLanguage();
+ if(!StringUtils.isEmpty(language)) {
+ locales.add(LanguageFilteringUtils.languageToLocale(language));
+ }
+ }
+ if (locales.isEmpty()) {
return Collections.emptyList();
}
List> list = new ArrayList>();
Locale currentLocale = SelectedLocale.getCurrentLocale(vreq);
- for (Locale locale : selectables) {
+ for (Locale locale : locales) {
try {
list.add(buildLocaleMap(locale, currentLocale));
} catch (FileNotFoundException e) {
- log.warn("Can't show the Locale selector for '" + locale
- + "': " + e);
+ log.warn("Can't show locale '" + locale + "': " + e);
}
}
@@ -188,8 +196,8 @@ public class ViewLabelsServlet extends FreemarkerHttpServlet{
ArrayList labels = new ArrayList();
try {
- //We want to get the labels for all the languages, not just the display language
- ResultSet results = QueryUtils.getLanguageNeutralQueryResults(queryStr, vreq);
+ // Show only labels with current language filtering
+ ResultSet results = QueryUtils.getQueryResults(queryStr, vreq);
while (results.hasNext()) {
QuerySolution soln = results.nextSolution();
Literal nodeLiteral = soln.get("label").asLiteral();
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/individual/IndividualResponseBuilder.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/individual/IndividualResponseBuilder.java
index c89119f5a..0f7154c88 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/individual/IndividualResponseBuilder.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/individual/IndividualResponseBuilder.java
@@ -6,14 +6,13 @@ import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
-import org.apache.jena.rdf.model.RDFNode;
-import edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual.IndividualTemplateModelBuilder;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-
import org.apache.jena.query.QuerySolution;
import org.apache.jena.query.ResultSet;
@@ -36,6 +35,7 @@ import edu.cornell.mannlib.vitro.webapp.i18n.selection.SelectedLocale;
import edu.cornell.mannlib.vitro.webapp.utils.dataGetter.ExecuteDataRetrieval;
import edu.cornell.mannlib.vitro.webapp.web.beanswrappers.ReadOnlyBeansWrapper;
import edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual.IndividualTemplateModel;
+import edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual.IndividualTemplateModelBuilder;
import edu.ucsf.vitro.opensocial.OpenSocialManager;
import freemarker.ext.beans.BeansWrapper;
import freemarker.template.TemplateModel;
@@ -123,8 +123,10 @@ class IndividualResponseBuilder {
* into the data model: no real data can be modified.
*/
// body.put("individual", wrap(itm, BeansWrapper.EXPOSE_SAFE));
- body.put("labelCount", getLabelCount(itm.getUri(), vreq));
- body.put("languageCount", getLanguagesRepresentedCount(itm.getUri(), vreq));
+ LabelAndLanguageCount labelAndLanguageCount = getLabelAndLanguageCount(
+ itm.getUri(), vreq);
+ body.put("labelCount", labelAndLanguageCount.getLabelCount());
+ body.put("languageCount", labelAndLanguageCount.getLanguageCount());
//We also need to know the number of available locales
body.put("localesCount", SelectedLocale.getSelectableLocales(vreq).size());
body.put("profileType", getProfileType(itm.getUri(), vreq));
@@ -282,61 +284,103 @@ class IndividualResponseBuilder {
return map;
}
- private static String LABEL_COUNT_QUERY = ""
- + "PREFIX rdfs: \n"
- + "SELECT ( str(COUNT(?label)) AS ?labelCount ) WHERE { \n"
- + " ?subject rdfs:label ?label \n"
- + " FILTER isLiteral(?label) \n"
- + "}" ;
-
- private static String DISTINCT_LANGUAGE_QUERY = ""
+ private static String LABEL_QUERY = ""
+ "PREFIX rdfs: \n"
- + "SELECT ( str(COUNT(DISTINCT lang(?label))) AS ?languageCount ) WHERE { \n"
+ + "SELECT ?label WHERE { \n"
+ " ?subject rdfs:label ?label \n"
+ " FILTER isLiteral(?label) \n"
+ "}" ;
+
+// Queries that were previously used for counts via RDFService that didn't
+// filter results by language. With language filtering, aggregate
+// functions like COUNT() cannot be used.
+
+// private static String LABEL_COUNT_QUERY = ""
+// + "PREFIX rdfs: \n"
+// + "SELECT ( str(COUNT(?label)) AS ?labelCount ) WHERE { \n"
+// + " ?subject rdfs:label ?label \n"
+// + " FILTER isLiteral(?label) \n"
+// + "}" ;
- private static Integer getLabelCount(String subjectUri, VitroRequest vreq) {
- String queryStr = QueryUtils.subUriForQueryVar(LABEL_COUNT_QUERY, "subject", subjectUri);
+// private static String DISTINCT_LANGUAGE_QUERY = ""
+// + "PREFIX rdfs: \n"
+// + "SELECT ( str(COUNT(DISTINCT lang(?label))) AS ?languageCount ) WHERE { \n"
+// + " ?subject rdfs:label ?label \n"
+// + " FILTER isLiteral(?label) \n"
+// + "}" ;
+
+ private static LabelAndLanguageCount getLabelAndLanguageCount(
+ String subjectUri, VitroRequest vreq) {
+ // 1.12.0 Now filtering to only the labels for the current locale so as
+ // to be consistent with other editing forms. Because the language
+ // filter can only act on a result set containing actual literals,
+ // we can't do the counting with a COUNT() in the query itself. So
+ // we will now use the LABEL_QUERY instead of LABEL_COUNT_QUERY and
+ // count the rows and the number of distinct languages represented.
+ Set distinctLanguages = new HashSet();
+ String queryStr = QueryUtils.subUriForQueryVar(LABEL_QUERY, "subject", subjectUri);
log.debug("queryStr = " + queryStr);
- int theCount = 0;
- try {
- //ResultSet results = QueryUtils.getQueryResults(queryStr, vreq);
- //Get query results across all languages in order for template to show manage labels link correctly
- ResultSet results = QueryUtils.getLanguageNeutralQueryResults(queryStr, vreq);
- if (results.hasNext()) {
- QuerySolution soln = results.nextSolution();
- RDFNode labelCount = soln.get("labelCount");
- if (labelCount != null && labelCount.isLiteral()) {
- theCount = labelCount.asLiteral().getInt();
+ int labelCount = 0;
+ try {
+ ResultSet results = QueryUtils.getQueryResults(queryStr, vreq);
+ while(results.hasNext()) {
+ QuerySolution qsoln = results.next();
+ labelCount++;
+ String lang = qsoln.getLiteral("label").getLanguage();
+ if(lang == null) {
+ lang = "";
}
+ distinctLanguages.add(lang);
}
} catch (Exception e) {
log.error(e, e);
}
- return theCount;
+ return new LabelAndLanguageCount(labelCount, distinctLanguages.size());
+ }
+
+ private static class LabelAndLanguageCount {
+
+ private Integer labelCount;
+ private Integer languageCount;
+
+ public LabelAndLanguageCount(Integer labelCount, Integer languageCount) {
+ this.labelCount = labelCount;
+ this.languageCount = languageCount;
+ }
+
+ public Integer getLabelCount() {
+ return this.labelCount;
+ }
+
+ public Integer getLanguageCount() {
+ return this.languageCount;
+ }
+
}
//what is the number of languages represented across the labels
- private static Integer getLanguagesRepresentedCount(String subjectUri, VitroRequest vreq) {
- String queryStr = QueryUtils.subUriForQueryVar(DISTINCT_LANGUAGE_QUERY, "subject", subjectUri);
- log.debug("queryStr = " + queryStr);
- int theCount = 0;
- try {
-
- ResultSet results = QueryUtils.getLanguageNeutralQueryResults(queryStr, vreq);
- if (results.hasNext()) {
- QuerySolution soln = results.nextSolution();
- RDFNode languageCount = soln.get("languageCount");
- if (languageCount != null && languageCount.isLiteral()) {
- theCount = languageCount.asLiteral().getInt();
- }
- }
- } catch (Exception e) {
- log.error(e, e);
- }
- return theCount;
- }
+ // This version not compatible with language-filtering RDF services
+// private static Integer getLanguagesRepresentedCount(String subjectUri, VitroRequest vreq) {
+// String queryStr = QueryUtils.subUriForQueryVar(DISTINCT_LANGUAGE_QUERY, "subject", subjectUri);
+// log.debug("queryStr = " + queryStr);
+// int theCount = 0;
+// try {
+//
+// ResultSet results = QueryUtils.getLanguageNeutralQueryResults(queryStr, vreq);
+// if (results.hasNext()) {
+// QuerySolution soln = results.nextSolution();
+// RDFNode languageCount = soln.get("languageCount");
+// if (languageCount != null && languageCount.isLiteral()) {
+// theCount = languageCount.asLiteral().getInt();
+// log.info("Language count is " + theCount);
+// }
+// }
+// } catch (Exception e) {
+// log.error(e, e);
+// }
+// log.info("Returning language count " + theCount);
+// return theCount;
+// }
private static String PROFILE_TYPE_QUERY = ""
+ "PREFIX display: \n"
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/json/GetRandomSearchIndividualsByVClass.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/json/GetRandomSearchIndividualsByVClass.java
index 8f3aaa311..325683d54 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/json/GetRandomSearchIndividualsByVClass.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/json/GetRandomSearchIndividualsByVClass.java
@@ -4,6 +4,7 @@ package edu.cornell.mannlib.vitro.webapp.controller.json;
import java.util.HashMap;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
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.controller.VitroRequest;
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.ShortViewContext;
import edu.cornell.mannlib.vitro.webapp.services.shortview.ShortViewServiceSetup;
@@ -73,7 +75,11 @@ public class GetRandomSearchIndividualsByVClass extends GetSearchIndividualsByVC
modelMap.put("individual",
IndividualTemplateModelBuilder.build(individual, vreq));
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);
return svs.renderShortView(individual, ShortViewContext.BROWSE,
modelMap, vreq);
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/VitroVocabulary.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/VitroVocabulary.java
index fdd9387c0..fba900cad 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/VitroVocabulary.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/VitroVocabulary.java
@@ -155,6 +155,7 @@ public class VitroVocabulary {
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_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_EXTERNAL_AUTH_ID = VITRO_AUTH + "externalAuthId";
public static final String USERACCOUNT_EXTERNAL_AUTH_ONLY = VITRO_AUTH + "externalAuthOnly";
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/WebappDaoFactory.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/WebappDaoFactory.java
index 622367e23..7ebe8a209 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/WebappDaoFactory.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/WebappDaoFactory.java
@@ -5,6 +5,8 @@ package edu.cornell.mannlib.vitro.webapp.dao;
import java.util.List;
import java.util.Set;
+import edu.cornell.mannlib.vitro.webapp.i18n.I18nBundle;
+
public interface WebappDaoFactory {
/**
@@ -132,4 +134,6 @@ public interface WebappDaoFactory {
public MenuDao getMenuDao();
+ public I18nBundle getI18nBundle();
+
}
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/WebappDaoFactoryConfig.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/WebappDaoFactoryConfig.java
index 3d3dc4afd..9ab5563f5 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/WebappDaoFactoryConfig.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/WebappDaoFactoryConfig.java
@@ -5,21 +5,25 @@ package edu.cornell.mannlib.vitro.webapp.dao;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.Set;
import edu.cornell.mannlib.vitro.webapp.dao.PropertyDao.FullPropertyKey;
+import edu.cornell.mannlib.vitro.webapp.rdfservice.filter.LanguageFilteringUtils;
public class WebappDaoFactoryConfig {
private List preferredLanguages;
+ private List preferredLocales;
private String defaultNamespace;
private Set nonUserNamespaces;
private boolean isUnderlyingStoreReasoned = false;
public Map customListViewConfigFileMap;
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#";
nonUserNamespaces = new HashSet();
nonUserNamespaces.add(VitroVocabulary.vitroURI);
@@ -33,6 +37,14 @@ public class WebappDaoFactoryConfig {
this.preferredLanguages = pl;
}
+ public List getPreferredLocales() {
+ return this.preferredLocales;
+ }
+
+ public void setPreferredLocales(List pl) {
+ this.preferredLocales = pl;
+ }
+
public String getDefaultNamespace() {
return defaultNamespace;
}
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/filtering/DataPropertyDaoFiltering.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/filtering/DataPropertyDaoFiltering.java
index 85d21a14f..9028f3c93 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/filtering/DataPropertyDaoFiltering.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/filtering/DataPropertyDaoFiltering.java
@@ -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.filtering.filters.VitroFilters;
-class DataPropertyDaoFiltering extends BaseFiltering implements DataPropertyDao{
+public class DataPropertyDaoFiltering extends BaseFiltering implements DataPropertyDao{
final DataPropertyDao innerDataPropertyDao;
final VitroFilters filters;
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/filtering/DataPropertyStatementDaoFiltering.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/filtering/DataPropertyStatementDaoFiltering.java
index 5bcc78830..961763297 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/filtering/DataPropertyStatementDaoFiltering.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/filtering/DataPropertyStatementDaoFiltering.java
@@ -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.filtering.filters.VitroFilters;
-class DataPropertyStatementDaoFiltering extends BaseFiltering implements DataPropertyStatementDao{
+public class DataPropertyStatementDaoFiltering extends BaseFiltering implements DataPropertyStatementDao{
final DataPropertyStatementDao innerDataPropertyStatementDao;
final VitroFilters filters;
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/filtering/FauxPropertyDaoFiltering.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/filtering/FauxPropertyDaoFiltering.java
index bc79e1443..796bbc8df 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/filtering/FauxPropertyDaoFiltering.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/filtering/FauxPropertyDaoFiltering.java
@@ -26,47 +26,34 @@ public class FauxPropertyDaoFiltering extends BaseFiltering implements FauxPrope
@Override
public List getFauxPropertiesForBaseUri(String uri) {
- // TODO Auto-generated method stub
- throw new RuntimeException(
- "FauxPropertyDao.getFauxPropertiesForBaseUri() not implemented.");
+ return innerFauxPropertyDao.getFauxPropertiesForBaseUri(uri);
}
@Override
public FauxProperty getFauxPropertyFromContextUri(String contextUri) {
- // TODO Auto-generated method stub
- throw new RuntimeException(
- "FauxPropertyDaoFiltering.getFauxPropertyFromConfigContextUri() not implemented.");
-
+ return innerFauxPropertyDao.getFauxPropertyFromContextUri(contextUri);
}
@Override
public FauxProperty getFauxPropertyByUris(String domainUri, String baseUri,
String rangeUri) {
- // TODO Auto-generated method stub
- throw new RuntimeException(
- "FauxPropertyDaoFiltering.getFauxPropertyByUris() not implemented.");
-
+ return innerFauxPropertyDao.getFauxPropertyByUris(domainUri, baseUri,
+ rangeUri);
}
@Override
public void updateFauxProperty(FauxProperty fp) {
- // TODO Auto-generated method stub
- throw new RuntimeException("FauxPropertyDaoFiltering.updateFauxProperty() not implemented.");
-
+ innerFauxPropertyDao.updateFauxProperty(fp);
}
@Override
public void deleteFauxProperty(FauxProperty fp) {
- // TODO Auto-generated method stub
- throw new RuntimeException("FauxPropertyDao.deleteFauxProperty() not implemented.");
-
+ innerFauxPropertyDao.deleteFauxProperty(fp);
}
@Override
public void insertFauxProperty(FauxProperty fp) {
- // TODO Auto-generated method stub
- throw new RuntimeException("FauxPropertyDao.insertFauxProperty() not implemented.");
-
+ innerFauxPropertyDao.insertFauxProperty(fp);
}
}
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/filtering/IndividualDaoFiltering.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/filtering/IndividualDaoFiltering.java
index 74a275f8b..e9121cd7f 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/filtering/IndividualDaoFiltering.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/filtering/IndividualDaoFiltering.java
@@ -20,7 +20,7 @@ import edu.cornell.mannlib.vitro.webapp.dao.filtering.filters.VitroFilters;
import edu.cornell.mannlib.vitro.webapp.edit.EditLiteral;
-class IndividualDaoFiltering extends BaseFiltering implements IndividualDao{
+public class IndividualDaoFiltering extends BaseFiltering implements IndividualDao{
IndividualDao innerIndividualDao;
VitroFilters filters;
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/filtering/ObjectPropertyDaoFiltering.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/filtering/ObjectPropertyDaoFiltering.java
index c85ca36a5..30cd70521 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/filtering/ObjectPropertyDaoFiltering.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/filtering/ObjectPropertyDaoFiltering.java
@@ -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.filtering.filters.VitroFilters;
-class ObjectPropertyDaoFiltering extends BaseFiltering implements ObjectPropertyDao{
+public class ObjectPropertyDaoFiltering extends BaseFiltering implements ObjectPropertyDao{
final ObjectPropertyDao innerObjectPropertyDao;
final VitroFilters filters;
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/filtering/ObjectPropertyStatementDaoFiltering.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/filtering/ObjectPropertyStatementDaoFiltering.java
index 3aa4ea3ab..8ccc636cc 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/filtering/ObjectPropertyStatementDaoFiltering.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/filtering/ObjectPropertyStatementDaoFiltering.java
@@ -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.filtering.filters.VitroFilters;
-class ObjectPropertyStatementDaoFiltering extends BaseFiltering implements ObjectPropertyStatementDao{
+public class ObjectPropertyStatementDaoFiltering extends BaseFiltering implements ObjectPropertyStatementDao{
final ObjectPropertyStatementDao innerObjectPropertyStatementDao;
final VitroFilters filters;
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/filtering/WebappDaoFactoryFiltering.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/filtering/WebappDaoFactoryFiltering.java
index 84e2823d7..fdb386a12 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/filtering/WebappDaoFactoryFiltering.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/filtering/WebappDaoFactoryFiltering.java
@@ -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.WebappDaoFactory;
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.
@@ -67,7 +68,7 @@ public class WebappDaoFactoryFiltering implements WebappDaoFactory {
transient private PropertyGroupDao filteringPropertyGroupDao=null;
transient private PropertyInstanceDao filteringPropertyInstanceDao=null;
- public WebappDaoFactoryFiltering( WebappDaoFactory innerDao, VitroFilters filters){
+ public WebappDaoFactoryFiltering(WebappDaoFactory innerDao, VitroFilters filters){
if( innerDao == null )
throw new Error("innerWebappDaoFactory must be non-null");
this.filters = filters;
@@ -276,4 +277,9 @@ public class WebappDaoFactoryFiltering implements WebappDaoFactory {
public void close() {
innerWebappDaoFactory.close();
}
+
+ @Override
+ public I18nBundle getI18nBundle() {
+ return innerWebappDaoFactory.getI18nBundle();
+ }
}
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/ApplicationDaoJena.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/ApplicationDaoJena.java
index 884c5f964..9e1898020 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/ApplicationDaoJena.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/ApplicationDaoJena.java
@@ -83,22 +83,21 @@ public class ApplicationDaoJena extends JenaBaseDao implements ApplicationDao {
}
ontModel.enterCriticalSection(Lock.WRITE);
try {
- appInd.setLabel(application.getApplicationName(), null);
- updatePropertyStringValue(
- appInd, APPLICATION_ABOUTTEXT, application.getAboutText(),
- ontModel);
- updatePropertyStringValue(
+ updateRDFSLabel(appInd, application.getApplicationName());
+ updatePlainLiteralValue(
+ appInd, APPLICATION_ABOUTTEXT, application.getAboutText());
+ updatePlainLiteralValue(
appInd, APPLICATION_ACKNOWLEGETEXT,
- application.getAcknowledgeText(), ontModel);
+ application.getAcknowledgeText());
updatePropertyStringValue(
appInd, APPLICATION_CONTACTMAIL,
application.getContactMail(), ontModel);
updatePropertyStringValue(
appInd, APPLICATION_CORRECTIONMAIL,
application.getCorrectionMail(), ontModel);
- updatePropertyStringValue(
+ updatePlainLiteralValue(
appInd, APPLICATION_COPYRIGHTANCHOR,
- application.getCopyrightAnchor(), ontModel);
+ application.getCopyrightAnchor());
updatePropertyStringValue(
appInd, APPLICATION_COPYRIGHTURL,
application.getCopyrightURL(), ontModel);
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/DataPropertyDaoJena.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/DataPropertyDaoJena.java
index a17ef6ec1..5c836281d 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/DataPropertyDaoJena.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/DataPropertyDaoJena.java
@@ -516,9 +516,9 @@ public class DataPropertyDaoJena extends PropertyDaoJena implements
if (dtp.getFunctional()) {
ontModel.add(jDataprop,RDF.type,OWL.FunctionalProperty);
}
- addPropertyStringValue(jDataprop, EXAMPLE, dtp.getExample(), ontModel);
- addPropertyStringValue(jDataprop, DESCRIPTION_ANNOT, dtp.getDescription(), ontModel);
- addPropertyStringValue(jDataprop, PUBLIC_DESCRIPTION_ANNOT, dtp.getPublicDescription(), ontModel);
+ updatePlainLiteralValue(jDataprop, EXAMPLE, dtp.getExample());
+ updatePlainLiteralValue(jDataprop, DESCRIPTION_ANNOT, dtp.getDescription());
+ updatePlainLiteralValue(jDataprop, PUBLIC_DESCRIPTION_ANNOT, dtp.getPublicDescription());
addPropertyStringValue(jDataprop, EDITING, dtp.getEditing(), ontModel);
addPropertyNonNegativeIntValue(jDataprop, DISPLAY_RANK_ANNOT, dtp.getDisplayTier(), ontModel);
addPropertyNonNegativeIntValue(jDataprop, DISPLAY_LIMIT, dtp.getDisplayLimit(), ontModel);
@@ -587,9 +587,9 @@ public class DataPropertyDaoJena extends PropertyDaoJena implements
}
}
- updatePropertyStringValue(jDataprop, EXAMPLE, dtp.getExample(), ontModel);
- updatePropertyStringValue(jDataprop, DESCRIPTION_ANNOT, dtp.getDescription(), ontModel);
- updatePropertyStringValue(jDataprop, PUBLIC_DESCRIPTION_ANNOT, dtp.getPublicDescription(), ontModel);
+ updatePlainLiteralValue(jDataprop, EXAMPLE, dtp.getExample());
+ updatePlainLiteralValue(jDataprop, DESCRIPTION_ANNOT, dtp.getDescription());
+ updatePlainLiteralValue(jDataprop, PUBLIC_DESCRIPTION_ANNOT, dtp.getPublicDescription());
updatePropertyStringValue(jDataprop, EDITING, dtp.getEditing(), ontModel);
updatePropertyNonNegativeIntValue(jDataprop, DISPLAY_RANK_ANNOT, dtp.getDisplayTier(), ontModel);
updatePropertyNonNegativeIntValue(jDataprop, DISPLAY_LIMIT, dtp.getDisplayLimit(), ontModel);
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/FauxPropertyDaoJena.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/FauxPropertyDaoJena.java
index 744881f7f..a454e1d1e 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/FauxPropertyDaoJena.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/FauxPropertyDaoJena.java
@@ -230,10 +230,9 @@ public class FauxPropertyDaoJena extends JenaBaseDao implements FauxPropertyDao
OBJECT_PROPERTY_DISPLAY_CONFIG);
addPropertyResourceURINotEmpty(config, PROPERTY_GROUP,
fp.getGroupURI());
- addPropertyStringValue(config, DISPLAY_NAME, fp.getDisplayName(),
- displayModel);
- addPropertyStringValue(config, PUBLIC_DESCRIPTION_ANNOT,
- fp.getPublicDescription(), displayModel);
+ updatePlainLiteralValue(config, DISPLAY_NAME, fp.getDisplayName());
+ updatePlainLiteralValue(config, PUBLIC_DESCRIPTION_ANNOT,
+ fp.getPublicDescription());
addPropertyIntValue(config, DISPLAY_RANK_ANNOT,
fp.getDisplayTier(), displayModel);
addPropertyIntValue(config, DISPLAY_LIMIT, fp.getDisplayLimit(),
@@ -328,10 +327,10 @@ public class FauxPropertyDaoJena extends JenaBaseDao implements FauxPropertyDao
.getConfigUri());
updatePropertyResourceURIValue(config, PROPERTY_GROUP,
fp.getGroupURI());
- updatePropertyStringValue(config, DISPLAY_NAME,
- fp.getDisplayName(), displayModel);
- updatePropertyStringValue(config, PUBLIC_DESCRIPTION_ANNOT,
- fp.getPublicDescription(), displayModel);
+ updatePlainLiteralValue(config, DISPLAY_NAME,
+ fp.getDisplayName());
+ updatePlainLiteralValue(config, PUBLIC_DESCRIPTION_ANNOT,
+ fp.getPublicDescription());
updatePropertyIntValue(config, DISPLAY_RANK_ANNOT,
fp.getDisplayTier(), displayModel);
updatePropertyIntValue(config, DISPLAY_LIMIT, fp.getDisplayLimit(),
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/JenaBaseDao.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/JenaBaseDao.java
index f96349bcf..9b0458109 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/JenaBaseDao.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/JenaBaseDao.java
@@ -5,8 +5,8 @@ package edu.cornell.mannlib.vitro.webapp.dao.jena;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
-import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashSet;
@@ -14,14 +14,14 @@ import java.util.Iterator;
import java.util.List;
import java.util.Set;
+import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
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.graph.Node;
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.ObjectProperty;
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.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.rdf.model.StmtIterator;
import org.apache.jena.shared.Lock;
@@ -752,22 +753,111 @@ public class JenaBaseDao extends JenaBaseDaoCon {
}
}
}
+
+ /**
+ * 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 lexicalForm) {
+ updatePlainLiteralValue(ontRes, RDFS.label, lexicalForm);
+ }
+
+ /**
+ * 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);
+ }
/**
- * convenience method for updating the RDFS label
+ * 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 updateRDFSLabel(OntResource ontRes, String label) {
-
- if (label != null && label.length() > 0) {
-
- String existingValue = ontRes.getLabel(getDefaultLanguage());
-
- if (existingValue == null || !existingValue.equals(label)) {
- ontRes.setLabel(label, getDefaultLanguage());
- }
- } else {
- ontRes.removeAll(RDFS.label);
- }
+ 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 toRemove = new ArrayList();
+ 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 {
+ // 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, ListlabelList) {
@@ -780,6 +870,13 @@ public class JenaBaseDao extends JenaBaseDaoCon {
}
if ((lang != null) && (lang.equals(labelLanguage))) {
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;
}
}
}
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/JenaBaseDaoCon.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/JenaBaseDaoCon.java
index d618ac804..71fd6447a 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/JenaBaseDaoCon.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/JenaBaseDaoCon.java
@@ -121,6 +121,7 @@ public class JenaBaseDaoCon {
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_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_EXTERNAL_AUTH_ID = _constModel.createDatatypeProperty(VitroVocabulary.USERACCOUNT_EXTERNAL_AUTH_ID);
protected DatatypeProperty USERACCOUNT_EXTERNAL_AUTH_ONLY = _constModel.createDatatypeProperty(VitroVocabulary.USERACCOUNT_EXTERNAL_AUTH_ONLY);
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/MenuDaoJena.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/MenuDaoJena.java
index 73da8f76b..30dd022c9 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/MenuDaoJena.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/MenuDaoJena.java
@@ -72,6 +72,7 @@ public class MenuDaoJena extends JenaBaseDao implements MenuDao {
return getMenu( getOntModelSelector().getDisplayModel(), url );
}
+ @Override
public MainMenu getMainMenu( ServletRequest req, String url ) {
OntModel displayModel = LanguageFilteringUtils.wrapOntModelInALanguageFilter(getOntModelSelector().getDisplayModel(), req );
return getMenu(displayModel, url) ;
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/ObjectPropertyDaoJena.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/ObjectPropertyDaoJena.java
index ea4d5f041..9ae00d59e 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/ObjectPropertyDaoJena.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/ObjectPropertyDaoJena.java
@@ -714,14 +714,14 @@ public class ObjectPropertyDaoJena extends PropertyDaoJena implements ObjectProp
}
}
- updatePropertyStringValue(p,EXAMPLE_ANNOT,prop.getExample(),getOntModel());
- updatePropertyStringValue(p,DESCRIPTION_ANNOT,prop.getDescription(),getOntModel());
- updatePropertyStringValue(p,PUBLIC_DESCRIPTION_ANNOT,prop.getPublicDescription(),getOntModel());
+ updatePlainLiteralValue(p, EXAMPLE_ANNOT, prop.getExample());
+ updatePlainLiteralValue(p, DESCRIPTION_ANNOT, prop.getDescription());
+ updatePlainLiteralValue(p, PUBLIC_DESCRIPTION_ANNOT, prop.getPublicDescription());
updatePropertyNonNegativeIntegerValue(p,DISPLAY_LIMIT,prop.getDomainDisplayLimitInteger(),getOntModel());
updatePropertyStringValue(p,PROPERTY_ENTITYSORTDIRECTION,prop.getDomainEntitySortDirection(),getOntModel());
if (inv != null) {
- updatePropertyStringValue(inv,EXAMPLE_ANNOT,prop.getExample(),getOntModel());
- updatePropertyStringValue(inv,DESCRIPTION_ANNOT,prop.getDescription(),getOntModel());
+ updatePlainLiteralValue(inv, EXAMPLE_ANNOT, prop.getExample());
+ updatePlainLiteralValue(inv, DESCRIPTION_ANNOT, prop.getDescription());
updatePropertyNonNegativeIntegerValue(inv,DISPLAY_LIMIT,prop.getRangeDisplayLimitInteger(),getOntModel());
updatePropertyStringValue(inv,PROPERTY_ENTITYSORTDIRECTION,prop.getRangeEntitySortDirection(),getOntModel());
}
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/RDFServiceGraph.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/RDFServiceGraph.java
index 491858453..f6c3b4dec 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/RDFServiceGraph.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/RDFServiceGraph.java
@@ -12,10 +12,10 @@ import java.util.function.Supplier;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-
import org.apache.jena.graph.Capabilities;
import org.apache.jena.graph.Graph;
import org.apache.jena.graph.GraphEventManager;
+import org.apache.jena.graph.GraphListener;
import org.apache.jena.graph.GraphStatisticsHandler;
import org.apache.jena.graph.Node;
import org.apache.jena.graph.TransactionHandler;
@@ -23,7 +23,6 @@ import org.apache.jena.graph.Triple;
import org.apache.jena.graph.impl.GraphWithPerform;
import org.apache.jena.graph.impl.SimpleEventManager;
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.ModelFactory;
import org.apache.jena.rdf.model.StmtIterator;
@@ -290,10 +289,15 @@ public class RDFServiceGraph implements GraphWithPerform {
literalBuff.append("\"");
pyString(literalBuff, node.getLiteralLexicalForm());
literalBuff.append("\"");
- if (node.getLiteralDatatypeURI() != null) {
- literalBuff.append("^^<").append(node.getLiteralDatatypeURI()).append(">");
- } else if (!StringUtils.isEmpty(node.getLiteralLanguage())) {
+ /*
+ * UQAM-Bug-Correction
+ * 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());
+ } else if (node.getLiteralDatatypeURI() != null) {
+ literalBuff.append("^^<").append(node.getLiteralDatatypeURI()).append(">");
}
return literalBuff.toString();
} else {
@@ -404,7 +408,18 @@ public class RDFServiceGraph implements GraphWithPerform {
@Override
public GraphEventManager getEventManager() {
if (eventManager == null) {
- eventManager = new SimpleEventManager(this);
+ eventManager = new SimpleEventManager() {
+ @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;
}
@@ -590,21 +605,7 @@ public class RDFServiceGraph implements GraphWithPerform {
}
public static Model createRDFServiceModel(final RDFServiceGraph 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;
+ return VitroModelFactory.createModelForGraph(g);
}
@Override
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/SparqlGraph.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/SparqlGraph.java
index 8b2ed8668..f0e55e239 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/SparqlGraph.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/SparqlGraph.java
@@ -232,10 +232,10 @@ public class SparqlGraph implements GraphWithPerform {
literalBuff.append("\"");
pyString(literalBuff, node.getLiteralLexicalForm());
literalBuff.append("\"");
- if (node.getLiteralDatatypeURI() != null) {
- literalBuff.append("^^<").append(node.getLiteralDatatypeURI()).append(">");
- } else if (!StringUtils.isEmpty(node.getLiteralLanguage())) {
+ if (!StringUtils.isEmpty(node.getLiteralLanguage())) {
literalBuff.append("@").append(node.getLiteralLanguage());
+ } else if (node.getLiteralDatatypeURI() != null) {
+ literalBuff.append("^^<").append(node.getLiteralDatatypeURI()).append(">");
}
return literalBuff.toString();
} else {
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/UserAccountsDaoJena.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/UserAccountsDaoJena.java
index 73557fd5c..29c1d5a29 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/UserAccountsDaoJena.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/UserAccountsDaoJena.java
@@ -4,7 +4,6 @@ package edu.cornell.mannlib.vitro.webapp.dao.jena;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Random;
@@ -98,6 +97,8 @@ public class UserAccountsDaoJena extends JenaBaseDao implements UserAccountsDao
u.setOldPassword(getPropertyStringValue(r, USERACCOUNT_OLD_PASSWORD));
u.setPasswordLinkExpires(getPropertyLongValue(r,
USERACCOUNT_PASSWORD_LINK_EXPIRES));
+ u.setEmailKey(getPropertyStringValue(r,USERACCOUNT_EMAIL_KEY));
+
u.setPasswordChangeRequired(getPropertyBooleanValue(r,
USERACCOUNT_PASSWORD_CHANGE_REQUIRED));
u.setExternalAuthOnly(getPropertyBooleanValue(r,
@@ -240,6 +241,8 @@ public class UserAccountsDaoJena extends JenaBaseDao implements UserAccountsDao
userAccount.getLoginCount(), model);
addPropertyLongValue(res, USERACCOUNT_LAST_LOGIN_TIME,
userAccount.getLastLoginTime(), model);
+ addPropertyStringValue(res, USERACCOUNT_EMAIL_KEY,
+ userAccount.getEmailKey(), model);
if (userAccount.getStatus() != null) {
addPropertyStringValue(res, USERACCOUNT_STATUS, userAccount
.getStatus().toString(), model);
@@ -306,6 +309,8 @@ public class UserAccountsDaoJena extends JenaBaseDao implements UserAccountsDao
userAccount.getLoginCount(), model);
updatePropertyLongValue(res, USERACCOUNT_LAST_LOGIN_TIME,
userAccount.getLastLoginTime(), model);
+ updatePropertyStringValue(res, USERACCOUNT_EMAIL_KEY,
+ userAccount.getEmailKey(), model);
if (userAccount.getStatus() == null) {
updatePropertyStringValue(res, USERACCOUNT_STATUS, null, model);
} else {
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/VClassDaoJena.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/VClassDaoJena.java
index 8d79155b1..0c3183f50 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/VClassDaoJena.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/VClassDaoJena.java
@@ -2,6 +2,8 @@
package edu.cornell.mannlib.vitro.webapp.dao.jena;
+import static java.lang.String.format;
+
import java.util.ArrayList;
import java.util.Collections;
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.VitroVocabulary;
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;
public class VClassDaoJena extends JenaBaseDao implements VClassDao {
protected static final Log log = LogFactory.getLog(VClassDaoJena.class);
+ private final I18nBundle i18n;
private boolean isUnderlyingStoreReasoned = false;
public VClassDaoJena(WebappDaoFactoryJena wadf, boolean isUnderlyingStoreReasoned) {
super(wadf);
+ this.i18n = wadf.getI18nBundle();
this.isUnderlyingStoreReasoned = isUnderlyingStoreReasoned;
}
@@ -91,17 +96,19 @@ public class VClassDaoJena extends JenaBaseDao implements VClassDao {
Restriction rest = cls.asRestriction();
OntProperty onProperty = rest.getOnProperty();
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()) {
Resource fillerRes = null;
if (rest.isAllValuesFromRestriction()) {
AllValuesFromRestriction avfRest = rest.asAllValuesFromRestriction();
fillerRes = avfRest.getAllValuesFrom();
- labelStr.append("all values from ");
+ labelStr.append(format("%s ", i18n.text("all_values_from")));
} else {
SomeValuesFromRestriction svfRest = rest.asSomeValuesFromRestriction();
fillerRes = svfRest.getSomeValuesFrom();
- labelStr.append("some values from ");
+ labelStr.append(format("%s ", i18n.text("some_values_from")));
}
if (fillerRes.canAs(OntClass.class)) {
OntClass avf = fillerRes.as(OntClass.class);
@@ -115,7 +122,7 @@ public class VClassDaoJena extends JenaBaseDao implements VClassDao {
}
} else if (rest.isHasValueRestriction()) {
HasValueRestriction hvRest = rest.asHasValueRestriction();
- labelStr.append("has value ");
+ labelStr.append(format("%s ", i18n.text("has_value")));
RDFNode fillerNode = hvRest.getHasValue();
try {
if (fillerNode.isResource()) {
@@ -128,22 +135,22 @@ public class VClassDaoJena extends JenaBaseDao implements VClassDao {
}
} else if (rest.isMinCardinalityRestriction()) {
MinCardinalityRestriction mcRest = rest.asMinCardinalityRestriction();
- labelStr.append("minimum cardinality ");
+ labelStr.append(format("%s ", i18n.text("minimum_cardinality")));
labelStr.append(mcRest.getMinCardinality());
} else if (rest.isMaxCardinalityRestriction()) {
MaxCardinalityRestriction mcRest = rest.asMaxCardinalityRestriction();
- labelStr.append("maximum cardinality ");
+ labelStr.append(format("%s ", i18n.text("maximum_cardinality")));
labelStr.append(mcRest.getMaxCardinality());
} else if (rest.isCardinalityRestriction()) {
CardinalityRestriction cRest = rest.asCardinalityRestriction();
- labelStr.append("cardinality ");
+ labelStr.append(format("%s ", i18n.text("cardinality")));
labelStr.append(cRest.getCardinality());
}
return labelStr.toString();
} else if (isBooleanClassExpression(cls)) {
StringBuilder labelStr = new StringBuilder("(");
if (cls.isComplementClass()) {
- labelStr.append("not ");
+ labelStr.append(format("%s ", i18n.text("not")));
ComplementClass ccls = cls.as(ComplementClass.class);
labelStr.append(getLabelForClass(ccls.getOperand(), withPrefix, forPickList));
} else if (cls.isIntersectionClass()) {
@@ -153,7 +160,7 @@ public class VClassDaoJena extends JenaBaseDao implements VClassDao {
OntClass operand = operandIt.next();
labelStr.append(getLabelForClass(operand, withPrefix, forPickList));
if (operandIt.hasNext()) {
- labelStr.append(" and ");
+ labelStr.append(format(" %s ", i18n.text("and")));
}
}
} else if (cls.isUnionClass()) {
@@ -163,7 +170,7 @@ public class VClassDaoJena extends JenaBaseDao implements VClassDao {
OntClass operand = operandIt.next();
labelStr.append(getLabelForClass(operand, withPrefix, forPickList));
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) {
log.error("error linking class "+cls.getURI()+" to class group");
}
- addPropertyStringValue(ontCls,SHORTDEF,cls.getShortDef(),ontModel);
- addPropertyStringValue(ontCls,EXAMPLE_ANNOT,cls.getExample(),ontModel);
- addPropertyStringValue(ontCls,DESCRIPTION_ANNOT,cls.getDescription(),ontModel);
+ updatePlainLiteralValue(ontCls, SHORTDEF, cls.getShortDef());
+ updatePlainLiteralValue(ontCls, EXAMPLE_ANNOT, cls.getExample());
+ updatePlainLiteralValue(ontCls, DESCRIPTION_ANNOT, cls.getDescription());
addPropertyIntValue(ontCls,DISPLAY_LIMIT,cls.getDisplayLimit(),ontModel);
addPropertyIntValue(ontCls,DISPLAY_RANK_ANNOT,cls.getDisplayRank(),ontModel);
@@ -1011,9 +1018,9 @@ public class VClassDaoJena extends JenaBaseDao implements VClassDao {
if (ontCls != null) {
updateRDFSLabel(ontCls, cls.getName());
updatePropertyResourceURIValue(ontCls,IN_CLASSGROUP,cls.getGroupURI(),ontModel);
- updatePropertyStringValue(ontCls,SHORTDEF,cls.getShortDef(),ontModel);
- updatePropertyStringValue(ontCls,EXAMPLE_ANNOT,cls.getExample(),ontModel);
- updatePropertyStringValue(ontCls,DESCRIPTION_ANNOT,cls.getDescription(),ontModel);
+ updatePlainLiteralValue(ontCls, SHORTDEF, cls.getShortDef());
+ updatePlainLiteralValue(ontCls, EXAMPLE_ANNOT, cls.getExample());
+ updatePlainLiteralValue(ontCls, DESCRIPTION_ANNOT, cls.getDescription());
updatePropertyNonNegativeIntValue(ontCls,DISPLAY_LIMIT,cls.getDisplayLimit(),ontModel);
updatePropertyNonNegativeIntValue(ontCls,DISPLAY_RANK_ANNOT,cls.getDisplayRank(),ontModel);
updatePropertyFloatValue(ontCls, SEARCH_BOOST_ANNOT, cls.getSearchBoost(), ontModel);
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/VClassGroupDaoJena.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/VClassGroupDaoJena.java
index 3ba868de8..5a655660b 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/VClassGroupDaoJena.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/VClassGroupDaoJena.java
@@ -276,7 +276,7 @@ public class VClassGroupDaoJena extends JenaBaseDao implements VClassGroupDao {
try {
Individual groupInd = ontModel.getIndividual(vcg.getURI());
try {
- groupInd.setLabel(vcg.getPublicName(), getDefaultLanguage());
+ updateRDFSLabel(groupInd, vcg.getPublicName(), getDefaultLanguage());
} catch (Exception e) {
log.error("error updating name for "+groupInd.getURI());
}
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/WebappDaoFactoryJena.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/WebappDaoFactoryJena.java
index 26aabf0be..813cf27ad 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/WebappDaoFactoryJena.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/WebappDaoFactoryJena.java
@@ -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.WebappDaoFactory;
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.rdfservice.RDFService;
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());
+ }
}
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/EditLiteral.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/EditLiteral.java
index 95f2848b7..8ff13bfc0 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/EditLiteral.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/EditLiteral.java
@@ -132,6 +132,11 @@ public class EditLiteral implements Literal {
throw new UnsupportedOperationException();
}
+ @Override
+ public boolean isStmtResource() {
+ throw new UnsupportedOperationException();
+ }
+
public Literal inModel(Model model) {
throw new UnsupportedOperationException();
}
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/listener/impl/IndividualDataPropertyStatementProcessor.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/listener/impl/IndividualDataPropertyStatementProcessor.java
index f2b6cad4f..b2758c7fd 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/listener/impl/IndividualDataPropertyStatementProcessor.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/listener/impl/IndividualDataPropertyStatementProcessor.java
@@ -4,7 +4,6 @@ package edu.cornell.mannlib.vitro.webapp.edit.listener.impl;
import java.util.HashMap;
import java.util.HashSet;
-import java.util.Iterator;
import java.util.Map;
import org.apache.commons.logging.Log;
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/BasicValidationVTwo.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/BasicValidationVTwo.java
index c5eb8280f..1e942aa8e 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/BasicValidationVTwo.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/BasicValidationVTwo.java
@@ -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.WebappDaoFactoryJena;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.fields.FieldVTwo;
-
+import edu.cornell.mannlib.vitro.webapp.i18n.I18nBundle;
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> varsToValidations;
EditConfigurationVTwo editConfig;
- public BasicValidationVTwo(EditConfigurationVTwo editConfig, MultiValueEditSubmission editSub){
+ public BasicValidationVTwo(EditConfigurationVTwo editConfig, I18nBundle i18n){
this.editConfig = editConfig;
+ this.i18n = i18n;
Map> validatorsForFields = new HashMap>();
for(String fieldName: editConfig.getFields().keySet()){
FieldVTwo field = editConfig.getField(fieldName);
@@ -42,8 +52,9 @@ public class BasicValidationVTwo {
checkValidations();
}
- public BasicValidationVTwo(Map> varsToValidations){
+ public BasicValidationVTwo(Map> varsToValidations, I18nBundle i18n){
this.varsToValidations = varsToValidations;
+ this.i18n = i18n;
checkValidations();
}
@@ -94,7 +105,7 @@ public class BasicValidationVTwo {
//If no literals and this field was required, this is an error message
//and can return
if((literals == null || literals.size() == 0) && isRequiredField) {
- errors.put(name, REQUIRED_FIELD_EMPTY_MSG);
+ errors.put(name, i18n.text(REQUIRED_FIELD_EMPTY_MSG));
break;
}
//Loop through literals if literals exist
@@ -113,7 +124,7 @@ public class BasicValidationVTwo {
// incorrectly generate errors.
if (isEmpty(value)) {
if (isRequiredField) {
- errors.put(name, REQUIRED_FIELD_EMPTY_MSG);
+ errors.put(name, i18n.text(REQUIRED_FIELD_EMPTY_MSG));
}
break;
}
@@ -154,11 +165,11 @@ public class BasicValidationVTwo {
private String validate(String validationType, List fileItems) {
if( "nonempty".equalsIgnoreCase(validationType)){
if( fileItems == null || fileItems.size() == 0 ){
- return "a file must be entered for this field.";
+ return i18n.text(FILE_MUST_BE_ENTERED_MSG);
}else{
FileItem fileItem = fileItems.get(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.
if( "nonempty".equalsIgnoreCase(validationType)){
if( isEmpty(value) )
- return REQUIRED_FIELD_EMPTY_MSG;
+ return i18n.text(REQUIRED_FIELD_EMPTY_MSG);
}
// Format validation
else if("isDate".equalsIgnoreCase(validationType)){
if( isDate( value))
return SUCCESS;
else
- return "must be in valid date format mm/dd/yyyy.";
+ return i18n.text(INVALID_DATE_FORM_MSG);
}
else if( validationType.indexOf("datatype:") == 0 ) {
String datatypeURI = validationType.substring(9);
@@ -194,7 +205,7 @@ public class BasicValidationVTwo {
} else if ("httpUrl".equalsIgnoreCase(validationType)){
//check if it has http or https, we could do more but for now this is all.
if(! value.startsWith("http://") && ! value.startsWith("https://") ){
- return "This URL must start with http:// or https://";
+ return i18n.text(INVALID_URL_MSG);
}else{
return SUCCESS;
}
@@ -216,7 +227,7 @@ public class BasicValidationVTwo {
dayParamStr = value.substring(monthDash + 1, value.length());
inputC.set(Integer.parseInt(yearParamStr), Integer.parseInt(monthParamStr) - 1, Integer.parseInt(dayParamStr));
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
//return null;
} else {
@@ -278,14 +289,9 @@ public class BasicValidationVTwo {
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 */
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 FORM_ERROR_FIELD_ID = "formannotationerrors";
/** regex for strings like "12/31/2004" */
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/EditConfigurationUtils.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/EditConfigurationUtils.java
index e72e172c1..63164c0dd 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/EditConfigurationUtils.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/EditConfigurationUtils.java
@@ -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.freemarker.config.FreemarkerConfiguration;
import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess;
+import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess.LanguageOption;
import freemarker.template.Configuration;
public class EditConfigurationUtils {
@@ -61,18 +62,24 @@ public class EditConfigurationUtils {
return vreq.getParameter("rangeUri");
}
+ public static String getTypeOfNew(VitroRequest vreq) {
+ return vreq.getParameter("typeOfNew");
+ }
+
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(
vreq.getSession().getServletContext()).getWebappDaoFactory();
return ctxDaoFact.getVClassDao().getVClassByURI(getRangeUri(vreq));
}
+ 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) {
Individual subject = null;
String subjectUri = getSubjectUri(vreq);
@@ -122,12 +129,24 @@ public class EditConfigurationUtils {
public static ObjectProperty getObjectPropertyForPredicate(VitroRequest vreq,
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(
predicateUri, domainUri, rangeUri);
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) {
WebappDaoFactory wdf = vreq.getWebappDaoFactory();
//TODO: Check reason for employing unfiltered webapp dao factory and note if using a different version
@@ -205,6 +224,7 @@ public class EditConfigurationUtils {
return (op != null && dp == null);
}
+
private static boolean isVitroLabel(String predicateUri) {
return predicateUri.equals(VitroVocabulary.LABEL);
}
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/EditN3GeneratorVTwo.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/EditN3GeneratorVTwo.java
index 015652445..b81ce06d5 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/EditN3GeneratorVTwo.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/EditN3GeneratorVTwo.java
@@ -366,6 +366,8 @@ public class EditN3GeneratorVTwo {
{
sbuff.append("@") ;
sbuff.append(lang) ;
+ // added by UQAM to exit at this point without adding datatype
+ return sbuff.toString() ;
}
// Format the datatype
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/MultiValueEditSubmission.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/MultiValueEditSubmission.java
index 8f61f4870..306ebdce7 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/MultiValueEditSubmission.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/MultiValueEditSubmission.java
@@ -10,23 +10,23 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import org.apache.commons.fileupload.FileItem;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.joda.time.format.DateTimeFormat;
-import org.joda.time.format.DateTimeFormatter;
import org.apache.jena.rdf.model.Literal;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ModelFactory;
import org.apache.jena.rdf.model.ResourceFactory;
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.n3editing.VTwo.fields.FieldVTwo;
+import edu.cornell.mannlib.vitro.webapp.i18n.I18n;
public class MultiValueEditSubmission {
@@ -34,21 +34,31 @@ public class MultiValueEditSubmission {
private Map> literalsFromForm ;
private Map> urisFromForm ;
-
private Map validationErrors;
private BasicValidationVTwo basicValidation;
-
- private Map> filesFromForm;
-
+
private static Model literalCreationModel;
-
private String entityToReturnTo;
+ private VitroRequest _vreq;
+
+ private static final String TIME_URI = XSD.time.getURI();
+
static{
literalCreationModel = ModelFactory.createDefaultModel();
}
-
- public MultiValueEditSubmission(Map queryParameters, EditConfigurationVTwo editConfig){
+ /*
+ * UQAM
+ * replace
+ * public MultiValueEditSubmission(Map 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 queryParameters = vreq.getParameterMap();
if( editConfig == null )
throw new Error("EditSubmission needs an EditConfiguration");
this.editKey = editConfig.getEditKey();
@@ -92,11 +102,12 @@ public class MultiValueEditSubmission {
processEditElementFields(editConfig,queryParameters);
//Incorporating basic validation
//Validate URIS
- this.basicValidation = new BasicValidationVTwo(editConfig, this);
+ this.basicValidation = new BasicValidationVTwo(editConfig, I18n.bundle(vreq));
Map errors = basicValidation.validateUris( urisFromForm );
//Validate literals and add errors to the list of existing errors
errors.putAll(basicValidation.validateLiterals( literalsFromForm ));
- if( errors != null ) {
+ // UQAM Add empty contition
+ if( errors != null && !errors.isEmpty()) {
validationErrors.putAll( errors);
}
@@ -141,9 +152,8 @@ public class MultiValueEditSubmission {
}
}
}
-
/* 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( "http://www.w3.org/2001/XMLSchema:anyURI".equals(datatypeUri) ){
try {
@@ -159,12 +169,27 @@ public class MultiValueEditSubmission {
return ResourceFactory.createPlainLiteral(value);
}
- private static final String DATE_TIME_URI = XSD.dateTime.getURI();
- private static final String DATE_URI = XSD.date.getURI();
- private static final String TIME_URI = XSD.time.getURI();
-
- private static DateTimeFormatter dformater = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:00");
- private static DateTimeFormatter dateFormater = DateTimeFormat.forPattern("yyyy-MM-dd");
+ /* maybe this could be static */
+ public Literal createLiteral(String value, String datatypeUri, String lang) {
+ if( datatypeUri != null && !datatypeUri.isEmpty() ){
+ // UQAM Original code contained tow-dots ':' in place of '#'
+// if( "http://www.w3.org/2001/XMLSchema:anyURI".equals(datatypeUri) ){
+ 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 getValidationErrors(){
return validationErrors;
@@ -264,12 +289,46 @@ public class MultiValueEditSubmission {
for(String value:valueList) {
value = N3EditUtils.stripInvalidXMLChars(value);
//Add to array of literals corresponding to this variable
+ /* UQAM OLD
if (!StringUtils.isEmpty(value)) {
literalsArray.add(createLiteral(
value,
field.getRangeDatatypeUri(),
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);
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/ProcessRdfForm.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/ProcessRdfForm.java
index 54fd7fb1b..9652d72dc 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/ProcessRdfForm.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/ProcessRdfForm.java
@@ -9,15 +9,24 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-
+import org.apache.jena.datatypes.xsd.XSDDatatype;
import org.apache.jena.ontology.OntModel;
import org.apache.jena.rdf.model.Literal;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ModelFactory;
+import org.apache.jena.rdf.model.Property;
+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.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.dao.InsertException;
@@ -41,6 +50,7 @@ public class ProcessRdfForm {
private EditN3GeneratorVTwo populator;
private Map urisForNewResources = null;
+// private VitroRequest _vreq;
/**
* Construct the ProcessRdfForm object.
*/
@@ -76,9 +86,9 @@ public class ProcessRdfForm {
AdditionsAndRetractions changes;
if( configuration.isUpdate() ){
- changes = editExistingStatements(configuration, submission);
+ changes = editExistingStatements(configuration, submission, vreq); //UQAM vreq for getting linguistic context
} else {
- changes = createNewStatements(configuration, submission );
+ changes = createNewStatements(configuration, submission, vreq ); //UQAM vreq for getting linguistic context
}
changes = getMinimalChanges(changes);
@@ -99,12 +109,15 @@ public class ProcessRdfForm {
* any optional N3 is to originally configure the
* configuration.setN3Optional() to be empty.
*
+ * UQAM add vreq for linguistic context managing
+ *
* @throws Exception May throw an exception if the required N3
* does not parse.
+ *
*/
private AdditionsAndRetractions createNewStatements(
EditConfigurationVTwo configuration,
- MultiValueEditSubmission submission) throws Exception {
+ MultiValueEditSubmission submission, VitroRequest vreq) throws Exception {
log.debug("in createNewStatements()" );
//getN3Required and getN3Optional will return copies of the
@@ -113,10 +126,10 @@ public class ProcessRdfForm {
List optionalN3 = configuration.getN3Optional();
/* 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. */
- 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
@@ -140,10 +153,12 @@ public class ProcessRdfForm {
* retractions are mutually diff'ed before statements are added to or
* removed from the model. The explicit change check can cause problems in
* more complex setups, like the automatic form building in DataStaR.
+ * @param vreq For getting linguistic context
+
*/
protected AdditionsAndRetractions editExistingStatements(
EditConfigurationVTwo editConfig,
- MultiValueEditSubmission submission) throws Exception {
+ MultiValueEditSubmission submission, VitroRequest vreq) throws Exception {
log.debug("editing an existing resource: " + editConfig.getObject() );
@@ -156,18 +171,18 @@ public class ProcessRdfForm {
subInValuesToN3(editConfig, submission,
N3RequiredAssert, N3OptionalAssert,
- N3RequiredRetract, N3OptionalRetract);
+ N3RequiredRetract, N3OptionalRetract, vreq);
return parseN3ToChange(
N3RequiredAssert,N3OptionalAssert,
- N3RequiredRetract, N3OptionalRetract);
+ N3RequiredRetract, N3OptionalRetract, vreq, editConfig);
}
@SuppressWarnings("unchecked")
protected void subInValuesToN3(
EditConfigurationVTwo editConfig, MultiValueEditSubmission submission,
List requiredAsserts, List optionalAsserts,
- List requiredRetracts, List optionalRetracts ) throws InsertException{
+ List requiredRetracts, List optionalRetracts, VitroRequest vreq ) throws InsertException{
//need to substitute into the return to URL becase it may need new resource URIs
List URLToReturnTo = Arrays.asList(submission.getEntityToReturnTo());
@@ -184,7 +199,41 @@ public class ProcessRdfForm {
//Retractions does NOT get values from form.
/* ******** Form submission Literals *********** */
- substituteInMultiLiterals( submission.getLiteralsFromForm(), requiredAsserts, optionalAsserts, URLToReturnTo);
+ /*
+ * UQAM Set all literals in the linguistic context
+ */
+ Map> literalsFromForm = submission.getLiteralsFromForm();
+ Set keys = literalsFromForm.keySet();
+ for (String aKey : keys) {
+ List literalFromForm = literalsFromForm.get(aKey);
+ List 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);
//Retractions does NOT get values from form.
@@ -254,20 +303,106 @@ public class ProcessRdfForm {
protected AdditionsAndRetractions parseN3ToChange(
List requiredAdds, List optionalAdds,
- List requiredDels, List optionalDels) throws Exception{
+ List requiredDels, List optionalDels, VitroRequest vreq, EditConfigurationVTwo editConfig) throws Exception{
List adds = parseN3ToRDF(requiredAdds, REQUIRED);
adds.addAll( parseN3ToRDF(optionalAdds, OPTIONAL));
-
List retracts = new ArrayList();
if( requiredDels != null && optionalDels != null ){
- retracts.addAll( parseN3ToRDF(requiredDels, REQUIRED) );
- retracts.addAll( parseN3ToRDF(optionalDels, OPTIONAL) );
+ String lingCxt=null;
+ //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);
}
+ /**
+ * 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 parseN3ToRDF(
+ List 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 errorMessages = new ArrayList();
+
+ List rdfModels = new ArrayList();
+ for(String n3 : n3Strings){
+ try{
+ Model model = ModelFactory.createDefaultModel();
+ StringReader reader = new StringReader(n3);
+ model.read(reader, "", "N3");
+ List 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.
*
@@ -479,4 +614,4 @@ public class ProcessRdfForm {
private static Log log = LogFactory.getLog(ProcessRdfForm.class);
-}
+}
\ No newline at end of file
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/ChildVClassesOptions.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/ChildVClassesOptions.java
index f87dd8f48..0c7b44ef2 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/ChildVClassesOptions.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/ChildVClassesOptions.java
@@ -7,6 +7,7 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
+import edu.cornell.mannlib.vitro.webapp.i18n.I18nBundle;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -40,7 +41,8 @@ public class ChildVClassesOptions implements FieldOptions {
public Map getOptions(
EditConfigurationVTwo editConfig,
String fieldName,
- WebappDaoFactory wDaoFact) throws Exception{
+ WebappDaoFactory wDaoFact,
+ I18nBundle i18n) throws Exception{
// now create an empty HashMap to populate and return
HashMap optionsMap = new LinkedHashMap();
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/ChildVClassesWithParent.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/ChildVClassesWithParent.java
index 135b38474..22f5763a4 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/ChildVClassesWithParent.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/ChildVClassesWithParent.java
@@ -1,6 +1,6 @@
/* $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.HashMap;
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.WebappDaoFactory;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditConfigurationVTwo;
+import edu.cornell.mannlib.vitro.webapp.i18n.I18nBundle;
public class ChildVClassesWithParent implements FieldOptions {
@@ -37,20 +38,24 @@ public class ChildVClassesWithParent implements FieldOptions {
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 getOptions(
EditConfigurationVTwo editConfig,
String fieldName,
- WebappDaoFactory wDaoFact) throws Exception {
-
+ WebappDaoFactory wDaoFact,
+ I18nBundle i18n) throws Exception {
HashMap optionsMap = new LinkedHashMap();
// first test to see whether there's a default "leave blank" value specified with the literal options
if ( ! StringUtils.isEmpty( defaultOptionLabel ) ){
optionsMap.put(LEFT_BLANK, defaultOptionLabel);
}
-
- optionsMap.put(classUri, "Other");
-
+ String other_i18n = i18n.text("other");
+ // first character in capital
+ optionsMap.put(classUri, other_i18n.substring(0, 1).toUpperCase() + other_i18n.substring(1));
VClassDao vclassDao = wDaoFact.getVClassDao();
List subClassList = vclassDao.getAllSubClassURIs(classUri);
if (subClassList != null && subClassList.size() > 0) {
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/ConstantFieldOptions.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/ConstantFieldOptions.java
index 3c68ac14d..9fc7662d5 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/ConstantFieldOptions.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/ConstantFieldOptions.java
@@ -10,6 +10,7 @@ import java.util.Map;
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditConfigurationVTwo;
+import edu.cornell.mannlib.vitro.webapp.i18n.I18nBundle;
public class ConstantFieldOptions implements FieldOptions {
@@ -54,7 +55,8 @@ public class ConstantFieldOptions implements FieldOptions {
public Map getOptions(
EditConfigurationVTwo editConfig,
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
HashMap optionsMap = new LinkedHashMap();
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/FieldOptions.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/FieldOptions.java
index b2c67f549..772b22913 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/FieldOptions.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/FieldOptions.java
@@ -6,6 +6,7 @@ import java.util.Map;
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
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
@@ -28,7 +29,8 @@ public interface FieldOptions {
public Map getOptions(
EditConfigurationVTwo editConfig,
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,
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/IndividualsViaClassGroupOptions.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/IndividualsViaClassGroupOptions.java
index b0a499005..fa627a12e 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/IndividualsViaClassGroupOptions.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/IndividualsViaClassGroupOptions.java
@@ -6,6 +6,7 @@ import java.util.Map;
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditConfigurationVTwo;
+import edu.cornell.mannlib.vitro.webapp.i18n.I18nBundle;
public class IndividualsViaClassGroupOptions implements FieldOptions {
@@ -27,7 +28,8 @@ public class IndividualsViaClassGroupOptions implements FieldOptions {
public Map getOptions(
EditConfigurationVTwo editConfig,
String fieldName,
- WebappDaoFactory wDaoFact) throws Exception {
+ WebappDaoFactory wDaoFact,
+ I18nBundle i18n) throws Exception {
throw new Error("not implemented");
}
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/IndividualsViaObjectPropetyOptions.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/IndividualsViaObjectPropetyOptions.java
index 6a5d30be5..0cd216ef7 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/IndividualsViaObjectPropetyOptions.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/IndividualsViaObjectPropetyOptions.java
@@ -11,6 +11,7 @@ import java.util.Map;
import javax.servlet.http.HttpServletRequest;
+import edu.cornell.mannlib.vitro.webapp.i18n.I18nBundle;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -77,7 +78,8 @@ public class IndividualsViaObjectPropetyOptions implements FieldOptions {
public Map getOptions(
EditConfigurationVTwo editConfig,
String fieldName,
- WebappDaoFactory wDaoFact) {
+ WebappDaoFactory wDaoFact,
+ I18nBundle i18n) {
HashMap optionsMap = new LinkedHashMap();
int optionsCount = 0;
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/IndividualsViaSearchQueryOptions.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/IndividualsViaSearchQueryOptions.java
index ec7167c58..d752bfe28 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/IndividualsViaSearchQueryOptions.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/IndividualsViaSearchQueryOptions.java
@@ -8,6 +8,7 @@ import java.util.List;
import java.util.ListIterator;
import java.util.Map;
+import edu.cornell.mannlib.vitro.webapp.i18n.I18nBundle;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -90,7 +91,8 @@ public class IndividualsViaSearchQueryOptions extends IndividualsViaVClassOption
public Map getOptions(
EditConfigurationVTwo editConfig,
String fieldName,
- WebappDaoFactory wDaoFact) throws Exception {
+ WebappDaoFactory wDaoFact,
+ I18nBundle i18n) throws Exception {
Map individualMap = new HashMap();
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/IndividualsViaVClassOptions.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/IndividualsViaVClassOptions.java
index 80c9cf273..374d571ed 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/IndividualsViaVClassOptions.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/IndividualsViaVClassOptions.java
@@ -8,6 +8,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import edu.cornell.mannlib.vitro.webapp.i18n.I18nBundle;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -48,7 +49,8 @@ public class IndividualsViaVClassOptions implements FieldOptions {
public Map getOptions(
EditConfigurationVTwo editConfig,
String fieldName,
- WebappDaoFactory wDaoFact) throws Exception {
+ WebappDaoFactory wDaoFact,
+ I18nBundle i18n) throws Exception {
Map individualMap = new HashMap();
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/RdfTypeOptions.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/RdfTypeOptions.java
index 994385673..32c520fd3 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/RdfTypeOptions.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/RdfTypeOptions.java
@@ -9,6 +9,7 @@ import java.util.Map;
import edu.cornell.mannlib.vitro.webapp.beans.VClass;
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditConfigurationVTwo;
+import edu.cornell.mannlib.vitro.webapp.i18n.I18nBundle;
public class RdfTypeOptions implements FieldOptions {
@@ -29,7 +30,8 @@ public class RdfTypeOptions implements FieldOptions {
public Map getOptions(
EditConfigurationVTwo editConfig,
String fieldName,
- WebappDaoFactory wdf) {
+ WebappDaoFactory wdf,
+ I18nBundle i18n) {
Map uriToLabel = new HashMap();
for (String uri : typeURIs) {
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/SelectListGeneratorVTwo.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/SelectListGeneratorVTwo.java
index 3e732ce58..c554cf39e 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/SelectListGeneratorVTwo.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/SelectListGeneratorVTwo.java
@@ -11,6 +11,8 @@ import java.util.LinkedHashMap;
import java.util.List;
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.LogFactory;
@@ -25,7 +27,8 @@ public class SelectListGeneratorVTwo {
public static Map getOptions(
EditConfigurationVTwo editConfig,
String fieldName,
- WebappDaoFactory wDaoFact){
+ WebappDaoFactory wDaoFact,
+ I18nBundle i18n){
if( editConfig == null ){
@@ -48,13 +51,51 @@ public class SelectListGeneratorVTwo {
}
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 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 parentClass = Collections.emptyMap();
+ FieldOptions fieldOptions = field.getFieldOptions();
+ return fieldOptions.getOptions(editConfig,fieldName,vreq.getWebappDaoFactory(), I18n.bundle(vreq));
+ } catch (Exception e) {
+ log.error("Error runing getFieldOptionis()",e);
+ return Collections.emptyMap();
+ }
+ }
+
//Methods to sort the options map
// from http://forum.java.sun.com/thread.jspa?threadID=639077&messageID=4250708
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/BaseEditConfigurationGenerator.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/BaseEditConfigurationGenerator.java
index f5de55789..55cff7761 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/BaseEditConfigurationGenerator.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/BaseEditConfigurationGenerator.java
@@ -16,6 +16,7 @@ import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditConfigurationVTw
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.IdModelSelector;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.StandardModelSelector;
import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess;
+import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess.LanguageOption;
public abstract class BaseEditConfigurationGenerator implements EditConfigurationGenerator {
@@ -63,6 +64,7 @@ public abstract class BaseEditConfigurationGenerator implements EditConfiguratio
setupModelSelectorsFromVitroRequest(vreq, editConfig);
OntModel queryModel = ModelAccess.on(vreq).getOntModel();
+ OntModel languageNeutralModel = vreq.getLanguageNeutralUnionFullModel();
if( editConfig.getSubjectUri() == null)
editConfig.setSubjectUri( EditConfigurationUtils.getSubjectUri(vreq));
@@ -78,7 +80,10 @@ public abstract class BaseEditConfigurationGenerator implements EditConfiguratio
editConfig.prepareForObjPropUpdate(queryModel);
} else if( dataKey != null ) { // edit of a data prop statement
//do nothing since the data prop form generator must take care of it
- editConfig.prepareForDataPropUpdate(queryModel, vreq.getWebappDaoFactory().getDataPropertyDao());
+ // Use language-neutral model to ensure that a data property statement
+ // is found for any literal hash, even if the UI locale is changed.
+ editConfig.prepareForDataPropUpdate(languageNeutralModel,
+ vreq.getWebappDaoFactory().getDataPropertyDao());
} else{
//this might be a create new or a form
editConfig.prepareForNonUpdate(queryModel);
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/DefaultAddMissingIndividualFormGenerator.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/DefaultAddMissingIndividualFormGenerator.java
index 702474da2..5537cecac 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/DefaultAddMissingIndividualFormGenerator.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/DefaultAddMissingIndividualFormGenerator.java
@@ -350,7 +350,7 @@ public class DefaultAddMissingIndividualFormGenerator implements EditConfigurati
private void prepareForUpdate(VitroRequest vreq, HttpSession session, EditConfigurationVTwo editConfiguration) {
//Here, retrieve model from
- OntModel model = ModelAccess.on(session.getServletContext()).getOntModel();
+ OntModel model = ModelAccess.on(vreq).getOntModel();
//if object property
if(EditConfigurationUtils.isObjectProperty(EditConfigurationUtils.getPredicateUri(vreq), vreq)){
Individual objectIndividual = EditConfigurationUtils.getObjectIndividual(vreq);
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/DefaultDeleteGenerator.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/DefaultDeleteGenerator.java
index 7b77786d4..bb615c42c 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/DefaultDeleteGenerator.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/DefaultDeleteGenerator.java
@@ -28,7 +28,9 @@ public class DefaultDeleteGenerator extends BaseEditConfigurationGenerator imple
private Integer dataHash = 0;
private DataPropertyStatement dps = null;
private String dataLiteral = null;
- private String template = "confirmDeletePropertyForm.ftl";
+ private String propertyTemplate = "confirmDeletePropertyForm.ftl";
+ private String individualTemplate = "confirmDeleteIndividualForm.ftl";
+
//In this case, simply return the edit configuration currently saved in session
//Since this is forwarding from another form, an edit configuration should already exist in session
@@ -43,12 +45,32 @@ public class DefaultDeleteGenerator extends BaseEditConfigurationGenerator imple
if(editConfiguration == null) {
editConfiguration = setupEditConfiguration(vreq, session);
}
- editConfiguration.setTemplate(template);
//prepare update?
prepare(vreq, editConfiguration);
+ if (editConfiguration.getPredicateUri() == null && editConfiguration.getSubjectUri() == null) {
+ editConfiguration.setTemplate(individualTemplate);
+ addDeleteParams(vreq, editConfiguration);
+ }else {
+ editConfiguration.setTemplate(propertyTemplate);
+ }
return editConfiguration;
}
+ private void addDeleteParams(VitroRequest vreq, EditConfigurationVTwo editConfiguration) {
+ String redirectUrl = vreq.getParameter("redirectUrl");
+ if (redirectUrl != null) {
+ 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) {
EditConfigurationVTwo editConfiguration = new EditConfigurationVTwo();
initProcessParameters(vreq, session, editConfiguration);
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/DefaultObjectPropertyFormGenerator.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/DefaultObjectPropertyFormGenerator.java
index ce471ca98..adb7e8bb8 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/DefaultObjectPropertyFormGenerator.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/DefaultObjectPropertyFormGenerator.java
@@ -2,6 +2,8 @@
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 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.i18n.I18n;
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.SearchEngineException;
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.
//WebappDaoFactory ctxDaoFact = ModelAccess.on(
// 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 types = new ArrayList();
Individual subject = EditConfigurationUtils.getSubjectIndividual(vreq);
@@ -460,7 +467,7 @@ public class DefaultObjectPropertyFormGenerator implements EditConfigurationGene
private void prepareForUpdate(VitroRequest vreq, HttpSession session, EditConfigurationVTwo editConfiguration) {
//Here, retrieve model from
- OntModel model = ModelAccess.on(session.getServletContext()).getOntModel();
+ OntModel model = ModelAccess.on(vreq).getOntModel();
//if object property
if(EditConfigurationUtils.isObjectProperty(EditConfigurationUtils.getPredicateUri(vreq), vreq)){
Individual objectIndividual = EditConfigurationUtils.getObjectIndividual(vreq);
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/ManageLabelsForIndividualGenerator.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/ManageLabelsForIndividualGenerator.java
index 15782747b..3f7e912bb 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/ManageLabelsForIndividualGenerator.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/ManageLabelsForIndividualGenerator.java
@@ -15,6 +15,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
+import java.util.Set;
import javax.servlet.http.HttpSession;
@@ -41,6 +42,7 @@ import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.fields.FieldVTwo;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.preprocessors.FoafNameToRdfsLabelPreprocessor;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.preprocessors.ManageLabelsForIndividualPreprocessor;
import edu.cornell.mannlib.vitro.webapp.i18n.selection.SelectedLocale;
+import edu.cornell.mannlib.vitro.webapp.rdfservice.filter.LanguageFilteringUtils;
import edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual.DataPropertyStatementTemplateModel;
/**
@@ -202,12 +204,12 @@ public class ManageLabelsForIndividualGenerator extends BaseEditConfigurationGen
private void addFormSpecificData(EditConfigurationVTwo config,
VitroRequest vreq) {
- //Get all language codes/labels in the system, and this list is sorted by language name
- List> locales = this.getLocales(vreq);
+ //the labels already added by the user
+ ArrayList existingLabels = this.getExistingLabels(config.getSubjectUri(), vreq);
+ //Get language codes/labels for languages present in the existing labels
+ List> locales = this.getLocales(vreq, existingLabels);
//Get code to label hashmap - we use this to get the language name for the language code returned in the rdf literal
- HashMap localeCodeToNameMap = this.getFullCodeToLanguageNameMap(locales);
- //the labels already added by the user
- ArrayList existingLabels = this.getExistingLabels(config.getSubjectUri(), vreq);
+ HashMap localeCodeToNameMap = this.getFullCodeToLanguageNameMap(locales);
int numberExistingLabels = existingLabels.size();
//existing labels keyed by language name and each of the list of labels is sorted by language name
HashMap> existingLabelsByLanguageName = this.getLabelsSortedByLanguageName(existingLabels, localeCodeToNameMap, config, vreq);
@@ -224,6 +226,20 @@ public class ManageLabelsForIndividualGenerator extends BaseEditConfigurationGen
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 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
config.addFormSpecificData("deleteWebpageUrl", "/edit/primitiveDelete");
@@ -359,8 +375,9 @@ public class ManageLabelsForIndividualGenerator extends BaseEditConfigurationGen
ArrayList labels = new ArrayList();
try {
- //We want to get the labels for all the languages, not just the display language
- ResultSet results = QueryUtils.getLanguageNeutralQueryResults(queryStr, vreq);
+ // Get results filtered to current locale so as to be consistent
+ // with other editing forms.
+ ResultSet results = QueryUtils.getQueryResults(queryStr, vreq);
while (results.hasNext()) {
QuerySolution soln = results.nextSolution();
Literal nodeLiteral = soln.get("label").asLiteral();
@@ -387,30 +404,32 @@ public class ManageLabelsForIndividualGenerator extends BaseEditConfigurationGen
return template;
}
+ //get locales present in list of literals
+ public List> getLocales(VitroRequest vreq,
+ List existingLiterals) {
+ Set locales = new HashSet();
+ for(Literal literal : existingLiterals) {
+ String language = literal.getLanguage();
+ if(!StringUtils.isEmpty(language)) {
+ locales.add(LanguageFilteringUtils.languageToLocale(language));
+ }
+ }
+ if (locales.isEmpty()) {
+ return Collections.emptyList();
+ }
+ List> list = new ArrayList>();
+ Locale currentLocale = SelectedLocale.getCurrentLocale(vreq);
+ for (Locale locale : locales) {
+ try {
+ list.add(buildLocaleMap(locale, currentLocale));
+ } catch (FileNotFoundException e) {
+ log.warn("Can't show locale '" + locale + "': " + e);
+ }
+ }
-
- //get locales
- public List> getLocales(VitroRequest vreq) {
- List selectables = SelectedLocale.getSelectableLocales(vreq);
- if (selectables.isEmpty()) {
- return Collections.emptyList();
- }
- List> list = new ArrayList>();
- Locale currentLocale = SelectedLocale.getCurrentLocale(vreq);
- for (Locale locale : selectables) {
- try {
- list.add(buildLocaleMap(locale, currentLocale));
- } catch (FileNotFoundException e) {
- log.warn("Can't show the Locale selector for '" + locale
- + "': " + e);
- }
- }
-
- return list;
+ return list;
}
-
-
public HashMap getFullCodeToLanguageNameMap(List> localesList) {
HashMap codeToLanguageMap = new HashMap();
for(Map locale: localesList) {
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/NewIndividualFormGenerator.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/NewIndividualFormGenerator.java
index 8c251467b..fff4d6732 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/NewIndividualFormGenerator.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/NewIndividualFormGenerator.java
@@ -233,7 +233,7 @@ public class NewIndividualFormGenerator implements EditConfigurationGenerator {
private void prepareForUpdate(VitroRequest vreq, HttpSession session, EditConfigurationVTwo editConfiguration) {
//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
editConfiguration.prepareForNonUpdate( model );
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/RDFSLabelGenerator.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/RDFSLabelGenerator.java
index 3a3e7f371..13e845a86 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/RDFSLabelGenerator.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/RDFSLabelGenerator.java
@@ -298,7 +298,7 @@ public class RDFSLabelGenerator implements EditConfigurationGenerator {
private void prepareForUpdate(VitroRequest vreq, HttpSession session, EditConfigurationVTwo editConfiguration) {
//Here, retrieve model from
- OntModel model = ModelAccess.on(session.getServletContext()).getOntModel();
+ OntModel model = ModelAccess.on(vreq).getOntModel();
if( editConfiguration.isDataPropertyUpdate() ){
editConfiguration.prepareForDataPropUpdate(model, vreq.getWebappDaoFactory().getDataPropertyDao());
}
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/LimitRemovalsToLanguage.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/LimitRemovalsToLanguage.java
new file mode 100644
index 000000000..acd94dfae
--- /dev/null
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/LimitRemovalsToLanguage.java
@@ -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 eliminatedRetractions = new ArrayList();
+ 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);
+ }
+
+}
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/controller/EditRequestDispatchController.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/controller/EditRequestDispatchController.java
index 96d6556b8..c33b70279 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/controller/EditRequestDispatchController.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/controller/EditRequestDispatchController.java
@@ -11,6 +11,7 @@ import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
+import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.jena.ontology.OntModel;
@@ -67,10 +68,20 @@ public class EditRequestDispatchController extends FreemarkerHttpServlet {
//TODO: Create this generator
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";
-
- @Override
- protected AuthorizationRequest requiredActions(VitroRequest vreq) {
- //Check if this statement can be edited here and return unauthorized if not
+ final String MANAGE_MENUS_FORM = "edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.generators.ManagePageGenerator";
+
+ @Override
+ protected AuthorizationRequest requiredActions(VitroRequest vreq) {
+ // If request is for new individual, return simple do back end editing action permission
+ if (StringUtils.isNotEmpty(EditConfigurationUtils.getTypeOfNew(vreq))) {
+ 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
String subjectUri = EditConfigurationUtils.getSubjectUri(vreq);
String predicateUri = EditConfigurationUtils.getPredicateUri(vreq);
String objectUri = EditConfigurationUtils.getObjectUri(vreq);
@@ -98,6 +109,16 @@ public class EditRequestDispatchController extends FreemarkerHttpServlet {
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
protected ResponseValues processRequest(VitroRequest vreq) {
@@ -148,7 +169,7 @@ public class EditRequestDispatchController extends FreemarkerHttpServlet {
templateData.put("editConfiguration", etm);
templateData.put("editSubmission", submissionTemplateModel);
//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("cancelUrl", etm.getCancelUrl());
templateData.put("editKey", editConfig.getEditKey());
@@ -355,7 +376,7 @@ public class EditRequestDispatchController extends FreemarkerHttpServlet {
String predicateUri = EditConfigurationUtils.getPredicateUri(vreq);
String formParam = getFormParam(vreq);
//if no form parameter, then predicate uri and subject uri must both be populated
- if (formParam == null || "".equals(formParam)) {
+ if ((formParam == null || "".equals(formParam)) && !isDeleteForm(vreq)) {
if ((predicateUri == null || predicateUri.trim().length() == 0)) {
return true;
}
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/controller/PostEditCleanupController.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/controller/PostEditCleanupController.java
index 64f605103..b1336b50f 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/controller/PostEditCleanupController.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/controller/PostEditCleanupController.java
@@ -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
//to be created - as it is in processRdfForm3.jsp
if( entityToReturnTo == null ){
- //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
- MultiValueEditSubmission submission = new MultiValueEditSubmission(vreq.getParameterMap(), editConfig);
+ // 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
+ // UQAM-Linguistic-Management
+ // MultiValueEditSubmission submission = new MultiValueEditSubmission(vreq.getParameterMap(), editConfig);
+ MultiValueEditSubmission submission = new MultiValueEditSubmission(vreq, editConfig);
entityToReturnTo = N3EditUtils.processEntityToReturnTo(editConfig, submission, vreq);
}
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/controller/ProcessRdfFormController.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/controller/ProcessRdfFormController.java
index 790781a95..1c82b034b 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/controller/ProcessRdfFormController.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/controller/ProcessRdfFormController.java
@@ -8,10 +8,11 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import javax.servlet.annotation.WebServlet;
+
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.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.ProcessRdfForm;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.RdfLiteralHash;
-
-import javax.servlet.annotation.WebServlet;
+import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.preprocessors.LimitRemovalsToLanguage;
/**
* This servlet will convert a request to an EditSubmission,
@@ -66,7 +66,9 @@ public class ProcessRdfFormController extends FreemarkerHttpServlet{
return handleMissingConfiguration(vreq);
//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);
//if errors, return error response
@@ -101,8 +103,11 @@ public class ProcessRdfFormController extends FreemarkerHttpServlet{
if( configuration.isUseDependentResourceDelete() )
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);
-
+
ProcessRdfForm.applyChangesToWriteModel(changes, queryModel, writeModel, N3EditUtils.getEditorUri(vreq) );
//Here we are trying to get the entity to return to URL,
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/filters/ModelSwitcher.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/filters/ModelSwitcher.java
index 7c0813275..7e5f49a58 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/filters/ModelSwitcher.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/filters/ModelSwitcher.java
@@ -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.impl.RequestModelAccessImpl;
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;
/**
@@ -88,8 +89,10 @@ public class ModelSwitcher {
// If they asked for the display model, give it to them.
if (isParameterPresent(vreq, SWITCH_TO_DISPLAY_MODEL)) {
- OntModel mainOntModel = ModelAccess.on(_context).getOntModel(DISPLAY);
- OntModel tboxOntModel = ModelAccess.on(_context).getOntModel(DISPLAY_TBOX);
+ OntModel mainOntModel = LanguageFilteringUtils.wrapOntModelInALanguageFilter(
+ ModelAccess.on(vreq).getOntModel(DISPLAY), vreq);
+ OntModel tboxOntModel = LanguageFilteringUtils.wrapOntModelInALanguageFilter(
+ ModelAccess.on(vreq).getOntModel(DISPLAY_TBOX), vreq);
setSpecialWriteModel(vreq, mainOntModel);
vreq.setAttribute(VitroRequest.ID_FOR_ABOX_MODEL, VitroModelSource.ModelName.DISPLAY.toString());
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/filters/PageRoutingFilter.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/filters/PageRoutingFilter.java
index d956483f6..0f739361c 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/filters/PageRoutingFilter.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/filters/PageRoutingFilter.java
@@ -63,6 +63,7 @@ public class PageRoutingFilter implements Filter{
// get URL without hostname or servlet context
HttpServletResponse response = (HttpServletResponse) arg1;
HttpServletRequest req = (HttpServletRequest) arg0;
+
String path = req.getRequestURI().substring(req.getContextPath().length());
// check for first part of path
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/freemarker/config/FreemarkerConfiguration.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/freemarker/config/FreemarkerConfiguration.java
index c0ab92d25..719b041ab 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/freemarker/config/FreemarkerConfiguration.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/freemarker/config/FreemarkerConfiguration.java
@@ -6,6 +6,7 @@ import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import javax.servlet.ServletContext;
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/freemarker/config/FreemarkerConfigurationImpl.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/freemarker/config/FreemarkerConfigurationImpl.java
index 10e2d9926..d4899c19a 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/freemarker/config/FreemarkerConfigurationImpl.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/freemarker/config/FreemarkerConfigurationImpl.java
@@ -304,6 +304,7 @@ public class FreemarkerConfigurationImpl extends Configuration {
urls.put("home", UrlBuilder.getHomeUrl());
urls.put("about", UrlBuilder.getUrl(Route.ABOUT));
urls.put("search", UrlBuilder.getUrl(Route.SEARCH));
+ urls.put("extendedsearch", UrlBuilder.getUrl(Route.EXTENDED_SEARCH));
urls.put("termsOfUse", UrlBuilder.getUrl(Route.TERMS_OF_USE));
urls.put("login", UrlBuilder.getLoginUrl());
urls.put("logout", UrlBuilder.getLogoutUrl());
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/i18n/I18n.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/i18n/I18n.java
index 8f07f7301..85f58495d 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/i18n/I18n.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/i18n/I18n.java
@@ -8,6 +8,7 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.MissingResourceException;
+import java.util.Objects;
import java.util.ResourceBundle;
import java.util.SortedSet;
import java.util.TreeSet;
@@ -20,7 +21,9 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
+import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
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.Key;
@@ -49,12 +52,27 @@ public class I18n {
* This is where the work gets done. Not declared final, so it can be
* 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
// ----------------------------------------------------------------------
+ /**
+ * 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.
*/
@@ -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) {
return instance.getBundle(bundleName, req);
}
/**
- * Get the default I18nBundle.
+ * Get the default request I18nBundle.
*/
public static I18nBundle bundle(HttpServletRequest req) {
return instance.getBundle(DEFAULT_BUNDLE_NAME, req);
}
+ /**
+ * Get the default context I18nBundle for preferred locales.
+ */
+ public static I18nBundle bundle(List preferredLocales) {
+ return instance.getBundle(DEFAULT_BUNDLE_NAME, preferredLocales);
+ }
+
// ----------------------------------------------------------------------
// The instance
// ----------------------------------------------------------------------
@@ -106,25 +131,59 @@ public class I18n {
* Declared 'protected' so it can be overridden in unit tests.
*/
protected I18nBundle getBundle(String bundleName, HttpServletRequest req) {
- log.debug("Getting bundle '" + bundleName + "'");
+ log.debug("Getting request bundle '" + bundleName + "'");
+ checkDevelopmentMode(req);
+ checkForChangeInThemeDirectory(req);
+
+ Locale locale = req.getLocale();
+
+ 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 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 {
- checkDevelopmentMode(req);
- checkForChangeInThemeDirectory(req);
-
String dir = themeDirectory.get();
- ServletContext ctx = req.getSession().getServletContext();
-
ResourceBundle.Control control = new ThemeBasedControl(ctx, dir);
ResourceBundle rb = ResourceBundle.getBundle(bundleName,
- req.getLocale(), control);
+ locale, control);
+
return new I18nBundle(bundleName, rb, i18nLogger);
} catch (MissingResourceException e) {
log.warn("Didn't find text bundle '" + bundleName + "'");
+
return I18nBundle.emptyBundle(bundleName, i18nLogger);
} catch (Exception e) {
log.error("Failed to create text bundle '" + bundleName + "'", e);
+
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
* 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. */
private void clearCacheOnRequest(HttpServletRequest req) {
if (req.getAttribute(ATTRIBUTE_CACHE_CLEARED) != null) {
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/i18n/I18nBundle.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/i18n/I18nBundle.java
index 0d57cb8fd..030edaf84 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/i18n/I18nBundle.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/i18n/I18nBundle.java
@@ -10,6 +10,9 @@ import java.util.ResourceBundle;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import edu.cornell.mannlib.vitro.webapp.utils.developer.DeveloperSettings;
+import edu.cornell.mannlib.vitro.webapp.utils.developer.Key;
+
/**
* A wrapper for a ResourceBundle that will not throw an exception, no matter
* what string you request.
@@ -20,7 +23,9 @@ import org.apache.commons.logging.LogFactory;
*/
public class I18nBundle {
private static final Log log = LogFactory.getLog(I18nBundle.class);
-
+ private static final String startSep = "\u25a4";
+ private static final String endSep = "\u25a5";
+ public static final String intSep = "\u25a6";
private static final String MESSAGE_BUNDLE_NOT_FOUND = "Text bundle ''{0}'' not found.";
private static final String MESSAGE_KEY_NOT_FOUND = "Text bundle ''{0}'' has no text for ''{1}''";
@@ -75,13 +80,27 @@ public class I18nBundle {
key);
log.warn(message);
textString = "ERROR: " + message;
- }
- String result = formatString(textString, parameters);
+ }
+ String message = formatString(textString, parameters);
if (i18nLogger != null) {
- i18nLogger.log(bundleName, key, parameters, textString, result);
+ i18nLogger.log(bundleName, key, parameters, textString, message);
}
- return result;
+ if (isNeedExportInfo()) {
+ String separatedArgs = "";
+ for (int i = 0; i < parameters.length; i++) {
+ separatedArgs += parameters[i] + intSep;
+ }
+
+ return startSep + key + intSep + textString + intSep + separatedArgs + message + endSep;
+ } else {
+ return message;
+ }
+
+ }
+
+ private static boolean isNeedExportInfo() {
+ return DeveloperSettings.getInstance().getBoolean(Key.I18N_ONLINE_TRANSLATION);
}
private static String formatString(String textString, Object... parameters) {
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/i18n/freemarker/I18nStringTemplateModel.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/i18n/freemarker/I18nStringTemplateModel.java
index c7b129349..8d16f6c03 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/i18n/freemarker/I18nStringTemplateModel.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/i18n/freemarker/I18nStringTemplateModel.java
@@ -8,6 +8,9 @@ import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import edu.cornell.mannlib.vitro.webapp.i18n.I18nBundle;
+import edu.cornell.mannlib.vitro.webapp.utils.developer.DeveloperSettings;
+import edu.cornell.mannlib.vitro.webapp.utils.developer.Key;
import freemarker.template.TemplateMethodModelEx;
import freemarker.template.TemplateModel;
import freemarker.template.TemplateModelException;
@@ -65,7 +68,11 @@ public class I18nStringTemplateModel implements TemplateMethodModelEx,
.get(i));
}
try {
- return MessageFormat.format(textString, unwrappedArgs);
+ if(isOnlineTranslationsEnabled()) {
+ return getOnlineTranslationsFormattedMessage(textString, unwrappedArgs);
+ } else {
+ return MessageFormat.format(textString, unwrappedArgs);
+ }
} catch (Exception e) {
String message = "Can't format '" + key + "' from bundle '"
+ bundleName + "', wrong argument types: " + args
@@ -75,5 +82,40 @@ public class I18nStringTemplateModel implements TemplateMethodModelEx,
}
}
}
+
+ /**
+ * Splits preProcessed string, formats message with arguments, lists arguments before message
+ * and combines preProcessed string back to be used with online translations.
+ * Substitutes arguments in message which is a part of preProcessed string
+ * @param preProcessed String "startSep + key + intSep + textString + intSep + message + endSep"
+ * @param arguments that should be listed before message and substituted in the message itself
+ * @return
+ */
+ private String getOnlineTranslationsFormattedMessage(String preProcessed, Object[] args) {
+ String[] parts = preProcessed.split(I18nBundle.intSep);
+ final int messageIndex = parts.length -1;
+ String message = MessageFormat.format(parts[messageIndex], args);
+ String[] arguments = convertToArrayOfStrings(args);
+ parts[messageIndex] = "";
+ String result = String.join(I18nBundle.intSep, parts) +
+ String.join(I18nBundle.intSep, arguments) +
+ I18nBundle.intSep + message ;
+ return result;
+ }
+
+ private String[] convertToArrayOfStrings(Object[] args) {
+ String[] result = new String[args.length];
+ for (int i = 0; i < result.length; i++)
+ if (args[i] != null) {
+ result[i] = args[i].toString();
+ } else {
+ result[i] = "";
+ }
+ return result;
+ }
+
+ private static boolean isOnlineTranslationsEnabled() {
+ return DeveloperSettings.getInstance().getBoolean(Key.I18N_ONLINE_TRANSLATION);
+ }
}
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/i18n/selection/LocaleSelectionDataGetter.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/i18n/selection/LocaleSelectionDataGetter.java
index 3fd949e87..d0bff6349 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/i18n/selection/LocaleSelectionDataGetter.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/i18n/selection/LocaleSelectionDataGetter.java
@@ -89,8 +89,8 @@ public class LocaleSelectionDataGetter implements DataGetter {
Locale currentLocale) throws FileNotFoundException {
Map map = new HashMap<>();
map.put("code", locale.toString());
- map.put("label", locale.getDisplayName(currentLocale));
- map.put("imageUrl", LocaleSelectorUtilities.getImageUrl(vreq, locale));
+ map.put("label", locale.getDisplayLanguage(locale));
+ map.put("country", locale.getDisplayCountry(locale));
map.put("selected", currentLocale.equals(locale));
return map;
}
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/i18n/selection/LocaleSelectionSetup.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/i18n/selection/LocaleSelectionSetup.java
index 6530d8aff..596880edd 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/i18n/selection/LocaleSelectionSetup.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/i18n/selection/LocaleSelectionSetup.java
@@ -14,6 +14,7 @@ import org.apache.commons.lang3.LocaleUtils;
import org.apache.commons.lang3.StringUtils;
import edu.cornell.mannlib.vitro.webapp.config.ConfigurationProperties;
+import edu.cornell.mannlib.vitro.webapp.i18n.I18n;
import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus;
/**
@@ -48,6 +49,10 @@ public class LocaleSelectionSetup implements ServletContextListener {
ss = StartupStatus.getBean(ctx);
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();
if (isForcing() && hasSelectables()) {
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/i18n/selection/LocaleSelectorUtilities.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/i18n/selection/LocaleSelectorUtilities.java
deleted file mode 100644
index 111181574..000000000
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/i18n/selection/LocaleSelectorUtilities.java
+++ /dev/null
@@ -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 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);
- }
-}
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/i18n/selection/SelectedLocale.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/i18n/selection/SelectedLocale.java
index 4605436a4..f044546e0 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/i18n/selection/SelectedLocale.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/i18n/selection/SelectedLocale.java
@@ -6,6 +6,8 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
+import java.util.Objects;
+import java.util.Optional;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
@@ -61,13 +63,10 @@ public abstract class SelectedLocale {
ServletContext ctx = session.getServletContext();
Object ctxInfo = ctx.getAttribute(ATTRIBUTE_NAME);
- if (ctxInfo instanceof ContextSelectedLocale) {
- Locale forcedLocale = ((ContextSelectedLocale) ctxInfo)
- .getForcedLocale();
- if (forcedLocale != null) {
- log.debug("Found forced locale in the context: " + forcedLocale);
- return forcedLocale;
- }
+
+ Optional forcedLocale = getForcedLocale(ctxInfo);
+ if (forcedLocale.isPresent()) {
+ return forcedLocale.get();
}
Object sessionInfo = session.getAttribute(ATTRIBUTE_NAME);
@@ -92,7 +91,62 @@ public abstract class SelectedLocale {
}
}
- return null;
+ Locale fallbackLocale = getFallbackLocale();
+ log.debug("Using fallback locale as default: " + fallbackLocale);
+ return fallbackLocale;
+ }
+
+ /**
+ * Get the overriding Locale to use, which is the first of these to be found:
+ *
+ * - The forced Locale in the servlet context
+ * - The first selectable locale matching a preferred locale
+ * - The first of the preferred locale
+ * - null
+ *
+ */
+ public static Locale getOverridingLocale(ServletContext ctx, List preferredLocales) {
+ Object ctxInfo = ctx.getAttribute(ATTRIBUTE_NAME);
+ Optional forcedLocale = getForcedLocale(ctxInfo);
+ if (forcedLocale.isPresent()) {
+ return forcedLocale.get();
+ }
+
+ if (ctxInfo instanceof ContextSelectedLocale) {
+ List selectableLocales = ((ContextSelectedLocale) ctxInfo)
+ .getSelectableLocales();
+
+ if (Objects.nonNull(selectableLocales) && Objects.nonNull(preferredLocales)) {
+ for (Locale preferredLocal : preferredLocales) {
+ for (Locale selectableLocale : selectableLocales) {
+ if (selectableLocale.equals(preferredLocal)) {
+ log.debug("Using first matching selectable locale from context: "
+ + selectableLocale);
+ return selectableLocale;
+ }
+ }
+ }
+ }
+ }
+
+ if (Objects.nonNull(preferredLocales) && !preferredLocales.isEmpty()) {
+ Locale preferredLocal = preferredLocales.get(0);
+ log.debug("Using first preferred locale as default: "
+ + preferredLocal);
+ return preferredLocal;
+ }
+
+ Locale fallbackLocale = getFallbackLocale();
+ log.debug("Using fallback locale as default: " + fallbackLocale);
+ return fallbackLocale;
+ }
+
+ /**
+ * @return a default locale to use if no other criteria for selecting a
+ * different one exist.
+ */
+ public static Locale getFallbackLocale() {
+ return new Locale("en", "US");
}
/**
@@ -121,6 +175,42 @@ public abstract class SelectedLocale {
return Locale.getDefault();
}
+ /**
+ * Get the preferred Locale to use, which is the first of these to be found:
+ *
+ * - The forced Locale in the servlet context
+ * - The first selectable locale matching a preferred locale
+ * - The first of the preferred locale
+ * - The default Locale for the JVM
+ *
+ */
+ public static Locale getPreferredLocale(ServletContext ctx, List preferredLocales) {
+ Locale overridingLocale = getOverridingLocale(ctx, preferredLocales);
+
+ if (overridingLocale != null) {
+ return overridingLocale;
+ }
+
+ log.debug("Using default locale: " + Locale.getDefault());
+ return Locale.getDefault();
+ }
+
+ /**
+ * Check for forced locale on the context.
+ */
+ private static Optional getForcedLocale(Object ctxInfo) {
+ if (ctxInfo instanceof ContextSelectedLocale) {
+ Locale forcedLocale = ((ContextSelectedLocale) ctxInfo)
+ .getForcedLocale();
+ if (forcedLocale != null) {
+ log.debug("Found forced locale in the context: " + forcedLocale);
+ return Optional.of(forcedLocale);
+ }
+ }
+
+ return Optional.empty();
+ }
+
/**
* Store a list of selectable Locales in the servlet context, so we can
* easily build the selection panel in the GUI. Clears any forced locale.
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/modelaccess/ModelNames.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/modelaccess/ModelNames.java
index 245ca9908..10493a0c3 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/modelaccess/ModelNames.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/modelaccess/ModelNames.java
@@ -13,20 +13,27 @@ public class ModelNames {
public static final String ABOX_ASSERTIONS = "http://vitro.mannlib.cornell.edu/default/vitro-kb-2";
public static final String ABOX_INFERENCES = "http://vitro.mannlib.cornell.edu/default/vitro-kb-inf";
public static final String ABOX_UNION = "vitro:aboxOntModel";
+ public static final String ABOX_ASSERTIONS_FIRSTTIME_BACKUP = ABOX_ASSERTIONS + "FirsttimeBackup";
public static final String TBOX_ASSERTIONS = "http://vitro.mannlib.cornell.edu/default/asserted-tbox";
public static final String TBOX_INFERENCES = "http://vitro.mannlib.cornell.edu/default/inferred-tbox";
public static final String TBOX_UNION = "vitro:tboxOntModel";
+ public static final String TBOX_ASSERTIONS_FIRSTTIME_BACKUP = TBOX_ASSERTIONS + "FirsttimeBackup";
public static final String FULL_ASSERTIONS = "vitro:baseOntModel";
public static final String FULL_INFERENCES = "vitro:inferenceOntModel";
public static final String FULL_UNION = "vitro:jenaOntModel";
public static final String APPLICATION_METADATA = "http://vitro.mannlib.cornell.edu/default/vitro-kb-applicationMetadata";
+ public static final String APPLICATION_METADATA_FIRSTTIME_BACKUP = APPLICATION_METADATA + "FirsttimeBackup";
public static final String USER_ACCOUNTS = "http://vitro.mannlib.cornell.edu/default/vitro-kb-userAccounts";
+ public static final String USER_ACCOUNTS_FIRSTTIME_BACKUP = USER_ACCOUNTS + "FirsttimeBackup";
public static final String DISPLAY = "http://vitro.mannlib.cornell.edu/default/vitro-kb-displayMetadata";
+ public static final String DISPLAY_FIRSTTIME_BACKUP = DISPLAY + "FirsttimeBackup";
public static final String DISPLAY_TBOX = "http://vitro.mannlib.cornell.edu/default/vitro-kb-displayMetadataTBOX";
+ public static final String DISPLAY_TBOX_FIRSTTIME_BACKUP = DISPLAY_TBOX + "FirsttimeBackup";
public static final String DISPLAY_DISPLAY = "http://vitro.mannlib.cornell.edu/default/vitro-kb-displayMetadata-displayModel";
+ public static final String DISPLAY_DISPLAY_FIRSTTIME_BACKUP = DISPLAY_DISPLAY + "FirsttimeBackup";
/**
* A map of the URIS, keyed by their short names, intended only for display
@@ -39,17 +46,24 @@ public class ModelNames {
map.put("ABOX_ASSERTIONS", ABOX_ASSERTIONS);
map.put("ABOX_INFERENCES", ABOX_INFERENCES);
map.put("ABOX_UNION", ABOX_UNION);
+ map.put("ABOX_ASSERTIONS_FIRSTTIME_BACKUP", ABOX_ASSERTIONS_FIRSTTIME_BACKUP);
map.put("TBOX_ASSERTIONS", TBOX_ASSERTIONS);
map.put("TBOX_INFERENCES", TBOX_INFERENCES);
map.put("TBOX_UNION", TBOX_UNION);
+ map.put("TBOX_ASSERTIONS_FIRSTTIME_BACKUP", TBOX_ASSERTIONS_FIRSTTIME_BACKUP);
map.put("FULL_ASSERTIONS", FULL_ASSERTIONS);
map.put("FULL_INFERENCES", FULL_INFERENCES);
map.put("FULL_UNION", FULL_UNION);
map.put("APPLICATION_METADATA", APPLICATION_METADATA);
+ map.put("APPLICATION_METADATA_FIRSTTIME_BACKUP", APPLICATION_METADATA_FIRSTTIME_BACKUP);
map.put("USER_ACCOUNTS", USER_ACCOUNTS);
+ map.put("USER_ACCOUNTS_FIRSTTIME_BACKUP", USER_ACCOUNTS_FIRSTTIME_BACKUP);
map.put("DISPLAY", DISPLAY);
+ map.put("DISPLAY_FIRSTTIME_BACKUP", DISPLAY_FIRSTTIME_BACKUP);
map.put("DISPLAY_TBOX", DISPLAY_TBOX);
+ map.put("DISPLAY_TBOX_FIRSTTIME_BACKUP", DISPLAY_TBOX_FIRSTTIME_BACKUP);
map.put("DISPLAY_DISPLAY", DISPLAY_DISPLAY);
+ map.put("DISPLAY_DISPLAY_FIRSTTIME_BACKUP", DISPLAY_DISPLAY_FIRSTTIME_BACKUP);
return Collections.unmodifiableMap(map);
}
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/modules/tripleSource/ConfigurationTripleSource.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/modules/tripleSource/ConfigurationTripleSource.java
index fa1725af5..fe766329b 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/modules/tripleSource/ConfigurationTripleSource.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/modules/tripleSource/ConfigurationTripleSource.java
@@ -6,6 +6,14 @@ import static edu.cornell.mannlib.vitro.webapp.modelaccess.ModelNames.DISPLAY;
import static edu.cornell.mannlib.vitro.webapp.modelaccess.ModelNames.DISPLAY_DISPLAY;
import static edu.cornell.mannlib.vitro.webapp.modelaccess.ModelNames.DISPLAY_TBOX;
import static edu.cornell.mannlib.vitro.webapp.modelaccess.ModelNames.USER_ACCOUNTS;
+import static edu.cornell.mannlib.vitro.webapp.modelaccess.ModelNames.ABOX_ASSERTIONS_FIRSTTIME_BACKUP;
+import static edu.cornell.mannlib.vitro.webapp.modelaccess.ModelNames.TBOX_ASSERTIONS_FIRSTTIME_BACKUP;
+import static edu.cornell.mannlib.vitro.webapp.modelaccess.ModelNames.APPLICATION_METADATA_FIRSTTIME_BACKUP;
+import static edu.cornell.mannlib.vitro.webapp.modelaccess.ModelNames.USER_ACCOUNTS_FIRSTTIME_BACKUP;
+import static edu.cornell.mannlib.vitro.webapp.modelaccess.ModelNames.DISPLAY_FIRSTTIME_BACKUP;
+import static edu.cornell.mannlib.vitro.webapp.modelaccess.ModelNames.DISPLAY_TBOX_FIRSTTIME_BACKUP;
+import static edu.cornell.mannlib.vitro.webapp.modelaccess.ModelNames.DISPLAY_DISPLAY_FIRSTTIME_BACKUP;
+
import org.apache.jena.rdf.model.ModelMaker;
@@ -18,7 +26,10 @@ public abstract class ConfigurationTripleSource implements TripleSource {
* add memory-mapping.
*/
protected static final String[] CONFIGURATION_MODELS = { DISPLAY,
- DISPLAY_TBOX, DISPLAY_DISPLAY, USER_ACCOUNTS };
+ DISPLAY_TBOX, DISPLAY_DISPLAY, USER_ACCOUNTS, ABOX_ASSERTIONS_FIRSTTIME_BACKUP,
+ TBOX_ASSERTIONS_FIRSTTIME_BACKUP, APPLICATION_METADATA_FIRSTTIME_BACKUP,
+ USER_ACCOUNTS_FIRSTTIME_BACKUP, DISPLAY_FIRSTTIME_BACKUP,
+ DISPLAY_TBOX_FIRSTTIME_BACKUP, DISPLAY_DISPLAY_FIRSTTIME_BACKUP };
/**
* These decorators are added to a Configuration ModelMaker, regardless of
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/RDFService.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/RDFService.java
index babac6c52..06a17e4f4 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/RDFService.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/RDFService.java
@@ -10,6 +10,8 @@ import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ModelChangedListener;
import org.apache.jena.rdf.model.RDFNode;
+import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
+
/**
* Interface for API to write, read, and update Vitro's RDF store, with support
* to allow listening, logging and auditing.
@@ -263,4 +265,10 @@ public interface RDFService {
* multiple invocations do not cause an error.
*/
public void close();
+ /**
+ * UQAM-Bug-Correction Useful among other things to transport the linguistic context in the service
+ * @param vitroRequest
+ */
+ public void setVitroRequest(VitroRequest vitroRequest);
+ public VitroRequest getVitroRequest();
}
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/adapters/AbstractGraphDecorator.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/adapters/AbstractGraphDecorator.java
new file mode 100644
index 000000000..c2f9faa67
--- /dev/null
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/adapters/AbstractGraphDecorator.java
@@ -0,0 +1,136 @@
+package edu.cornell.mannlib.vitro.webapp.rdfservice.adapters;
+
+import org.apache.jena.graph.Capabilities;
+import org.apache.jena.graph.Graph;
+import org.apache.jena.graph.GraphEventManager;
+import org.apache.jena.graph.GraphStatisticsHandler;
+import org.apache.jena.graph.Node;
+import org.apache.jena.graph.TransactionHandler;
+import org.apache.jena.graph.Triple;
+import org.apache.jena.shared.AddDeniedException;
+import org.apache.jena.shared.DeleteDeniedException;
+import org.apache.jena.shared.PrefixMapping;
+import org.apache.jena.util.iterator.ExtendedIterator;
+
+import edu.cornell.mannlib.vitro.webapp.utils.logging.ToString;
+
+/**
+ * The base class for a delegating graph decorator.
+ *
+ * As implemented, all methods simply delegate to the inner graph. Subclasses
+ * should override selected methods to provide functionality.
+ */
+public abstract class AbstractGraphDecorator implements
+ Graph {
+
+ private final Graph inner;
+
+ protected AbstractGraphDecorator(Graph g) {
+ if (g == null) {
+ throw new IllegalArgumentException("g may not be null.");
+ }
+ this.inner = g;
+ }
+
+ @Override
+ public String toString() {
+ return ToString.simpleName(this) + "[" + ToString.hashHex(this)
+ + ", inner=" + ToString.graphToString(inner) + "]";
+ }
+
+ @Override
+ public void add(Triple arg0) throws AddDeniedException {
+ inner.add(arg0);
+ }
+
+ @Override
+ public void clear() {
+ inner.clear();
+ }
+
+ @Override
+ public void close() {
+ inner.close();
+ }
+
+ @Override
+ public boolean contains(Triple arg0) {
+ return inner.contains(arg0);
+ }
+
+ @Override
+ public boolean contains(Node arg0, Node arg1, Node arg2) {
+ return inner.contains(arg0, arg1, arg2);
+ }
+
+ @Override
+ public void delete(Triple arg0) throws DeleteDeniedException {
+ inner.delete(arg0);
+ }
+
+ @Override
+ public boolean dependsOn(Graph arg0) {
+ return inner.dependsOn(arg0);
+ }
+
+ @Override
+ public ExtendedIterator find(Triple arg0) {
+ return inner.find(arg0);
+ }
+
+ @Override
+ public ExtendedIterator find(Node arg0, Node arg1, Node arg2) {
+ return inner.find(arg0, arg1, arg2);
+ }
+
+ @Override
+ public Capabilities getCapabilities() {
+ return inner.getCapabilities();
+ }
+
+ @Override
+ public GraphEventManager getEventManager() {
+ return inner.getEventManager();
+ }
+
+ @Override
+ public PrefixMapping getPrefixMapping() {
+ return inner.getPrefixMapping();
+ }
+
+ @Override
+ public GraphStatisticsHandler getStatisticsHandler() {
+ return inner.getStatisticsHandler();
+ }
+
+ @Override
+ public TransactionHandler getTransactionHandler() {
+ return inner.getTransactionHandler();
+ }
+
+ @Override
+ public boolean isClosed() {
+ return inner.isClosed();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return inner.isEmpty();
+ }
+
+ @Override
+ public boolean isIsomorphicWith(Graph arg0) {
+ return inner.isIsomorphicWith(arg0);
+ }
+
+ @Override
+ public void remove(Node arg0, Node arg1, Node arg2) {
+ inner.remove(arg0, arg1, arg2);
+ }
+
+ @Override
+ public int size() {
+ return inner.size();
+ }
+
+}
\ No newline at end of file
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/adapters/AbstractModelDecorator.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/adapters/AbstractModelDecorator.java
index 052d1b8db..6a5fc0f90 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/adapters/AbstractModelDecorator.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/adapters/AbstractModelDecorator.java
@@ -54,7 +54,7 @@ public abstract class AbstractModelDecorator implements Model {
protected AbstractModelDecorator(Model m) {
if (m == null) {
- throw new NullPointerException("m may not be null.");
+ throw new IllegalArgumentException("m may not be null.");
}
this.inner = m;
}
@@ -325,6 +325,11 @@ public abstract class AbstractModelDecorator implements Model {
return inner.lock();
}
+ @Override
+ public boolean hasNoMappings() {
+ return inner.hasNoMappings();
+ }
+
@Override
public boolean samePrefixMappingAs(PrefixMapping other) {
return inner.samePrefixMappingAs(other);
@@ -684,6 +689,11 @@ public abstract class AbstractModelDecorator implements Model {
return inner.createResource(uri);
}
+ @Override
+ public Resource createResource(Statement statement) {
+ return inner.createResource(statement);
+ }
+
@Override
public Property createProperty(String nameSpace, String localName) {
return inner.createProperty(nameSpace, localName);
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/adapters/AbstractOntModelDecorator.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/adapters/AbstractOntModelDecorator.java
index 895928987..f9305d8f4 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/adapters/AbstractOntModelDecorator.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/adapters/AbstractOntModelDecorator.java
@@ -364,6 +364,11 @@ public abstract class AbstractOntModelDecorator implements OntModel {
return inner.lock();
}
+ @Override
+ public boolean hasNoMappings() {
+ return inner.hasNoMappings();
+ }
+
@Override
public boolean samePrefixMappingAs(PrefixMapping other) {
return inner.samePrefixMappingAs(other);
@@ -729,6 +734,11 @@ public abstract class AbstractOntModelDecorator implements OntModel {
return inner.createResource(uri);
}
+ @Override
+ public Resource createResource(Statement statement) {
+ return inner.createResource(statement);
+ }
+
@Override
public Property createProperty(String nameSpace, String localName) {
return inner.createProperty(nameSpace, localName);
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/filter/AcceptableLanguages.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/filter/AcceptableLanguages.java
new file mode 100644
index 000000000..01e96c9cc
--- /dev/null
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/filter/AcceptableLanguages.java
@@ -0,0 +1,36 @@
+package edu.cornell.mannlib.vitro.webapp.rdfservice.filter;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * A normalized list of languages/locales acceptable in results
+ * returned by language-filtering RDFServices, graphs, models, etc.
+ */
+public class AcceptableLanguages extends ArrayList{
+
+ private static final long serialVersionUID = 1L;
+ private static final Log log = LogFactory.getLog(AcceptableLanguages.class);
+
+ /**
+ * Construct a normalized list of acceptable language strings
+ * from a set of raw language strings. For any values of form 'aa-BB',
+ * the base language ('aa') will be also added to the list.
+ * @param rawLanguageStrs may not be null
+ */
+ public AcceptableLanguages(List rawLanguageStrs) {
+ log.debug("Raw language strings:" + rawLanguageStrs);
+ for (String lang : rawLanguageStrs) {
+ this.add(lang);
+ String baseLang = lang.split("-")[0];
+ if (!lang.equals(baseLang) && !this.contains(baseLang)) {
+ this.add(baseLang);
+ }
+ }
+ log.debug("Normalized language strings:" + this);
+ }
+
+}
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/filter/FilteredResultSet.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/filter/FilteredResultSet.java
index 230766d3e..e116caece 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/filter/FilteredResultSet.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/filter/FilteredResultSet.java
@@ -9,6 +9,7 @@ import org.apache.jena.query.QuerySolution;
import org.apache.jena.query.ResultSet;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.sparql.engine.binding.Binding;
+import org.apache.jena.sparql.engine.binding.BindingUtils;
public class FilteredResultSet implements ResultSet {
@@ -53,7 +54,7 @@ public class FilteredResultSet implements ResultSet {
@Override
public Binding nextBinding() {
- throw new UnsupportedOperationException("Can we ignore this?");
+ return BindingUtils.asBinding(nextSolution());
}
@Override
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/filter/LangSort.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/filter/LangSort.java
new file mode 100644
index 000000000..10007b119
--- /dev/null
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/filter/LangSort.java
@@ -0,0 +1,78 @@
+package edu.cornell.mannlib.vitro.webapp.rdfservice.filter;
+
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * A class for sorting language strings by acceptability according to a
+ * supplied list of language preferences.
+ * Refactored from LanguageFilteringRDFService for reuse by classes performing
+ * similar functions.
+ */
+public class LangSort {
+
+ private static final Log log = LogFactory.getLog(LangSort.class);
+
+ protected List langs;
+ private int inexactMatchPenalty;
+ private int noLanguage;
+ private int noMatch;
+
+ /**
+ * Construct a language string sorter with a supplied list of preferred
+ * language strings
+ * @param preferredLanguageStrings list of preferred languages of form
+ * 'en-US', 'es', 'fr-CA'. May not be null.
+ */
+ public LangSort(List preferredLanguageStrings) {
+ this.langs = preferredLanguageStrings;
+ this.inexactMatchPenalty = langs.size();
+ // no language is worse than any inexact match (if the preferred list does not include "").
+ this.noLanguage = 2 * inexactMatchPenalty;
+ // no match is worse than no language.
+ this.noMatch = noLanguage + 1;
+ }
+
+ protected int compareLangs(String t1lang, String t2lang) {
+ int index1 = languageIndex(t1lang);
+ int index2 = languageIndex(t2lang);
+ if(index1 == index2) {
+ return t1lang.compareTo(t2lang);
+ } else {
+ return languageIndex(t1lang) - languageIndex(t2lang);
+ }
+ }
+
+ /**
+ * Return index of exact match, or index of partial match, or
+ * language-free, or no match.
+ */
+ private int languageIndex(String lang) {
+ if (lang == null) {
+ lang = "";
+ }
+
+ int index = langs.indexOf(lang);
+ if (index >= 0) {
+ log.debug("languageIndex for '" + lang + "' is " + index);
+ return index;
+ }
+
+ if (lang.length() > 2) {
+ index = langs.indexOf(lang.substring(0, 2));
+ if (index >= 0) {
+ log.debug("languageIndex for '" + lang + "' is " + index + inexactMatchPenalty);
+ return index + inexactMatchPenalty;
+ }
+ }
+
+ if (lang.isEmpty()) {
+ log.debug("languageIndex for '" + lang + "' is " + noLanguage);
+ return noLanguage;
+ }
+
+ return noMatch;
+ }
+}
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/filter/LanguageFilterModel.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/filter/LanguageFilterModel.java
new file mode 100644
index 000000000..0b1e5ce2f
--- /dev/null
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/filter/LanguageFilterModel.java
@@ -0,0 +1,104 @@
+package edu.cornell.mannlib.vitro.webapp.rdfservice.filter;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.jena.rdf.model.Model;
+import org.apache.jena.rdf.model.RDFNode;
+import org.apache.jena.rdf.model.Statement;
+import org.apache.jena.rdf.model.StmtIterator;
+
+/**
+ * A filter of literal statements from Models according to language preferences.
+ */
+public class LanguageFilterModel {
+
+ private static final Log log = LogFactory.getLog(LanguageFilterModel.class);
+
+ /**
+ *
+ * @param m the model to filter. May not be null.
+ * @param langs list of strings of type 'en-US'. May not be null.
+ * @return model with language-inappropriate literal statements filtered out.
+ */
+ public Model filterModel(Model m, List langs) {
+ log.debug("filterModel");
+ List retractions = new ArrayList();
+ StmtIterator stmtIt = m.listStatements();
+ while (stmtIt.hasNext()) {
+ Statement stmt = stmtIt.nextStatement();
+ if (stmt.getObject().isLiteral()) {
+ List candidatesForRemoval = m.listStatements(
+ stmt.getSubject(), stmt.getPredicate(), (RDFNode) null).toList();
+ if (candidatesForRemoval.size() == 1) {
+ continue;
+ }
+ candidatesForRemoval.sort(new StatementSortByLang(langs));
+ log.debug("sorted statements: " + showSortedStatements(candidatesForRemoval));
+ Iterator candIt = candidatesForRemoval.iterator();
+ String langRegister = null;
+ boolean chuckRemaining = false;
+ while(candIt.hasNext()) {
+ Statement s = candIt.next();
+ if (!s.getObject().isLiteral()) {
+ continue;
+ } else if (chuckRemaining) {
+ retractions.add(s);
+ }
+ String lang = s.getObject().asLiteral().getLanguage();
+ if (langRegister == null) {
+ langRegister = lang;
+ } else if (!langRegister.equals(lang)) {
+ chuckRemaining = true;
+ retractions.add(s);
+ }
+ }
+ }
+
+ }
+ m.remove(retractions);
+ return m;
+ }
+
+ private String showSortedStatements(List candidatesForRemoval) {
+ List langStrings = new ArrayList();
+ for (Statement stmt: candidatesForRemoval) {
+ if (stmt == null) {
+ langStrings.add("null stmt");
+ } else {
+ RDFNode node = stmt.getObject();
+ if (!node.isLiteral()) {
+ langStrings.add("not literal");
+ } else {
+ langStrings.add(node.asLiteral().getLanguage());
+ }
+ }
+ }
+ return langStrings.toString();
+ }
+
+ private class StatementSortByLang extends LangSort implements Comparator {
+
+ public StatementSortByLang(List langs) {
+ super(langs);
+ }
+
+ public int compare(Statement s1, Statement s2) {
+ if (s1 == null || s2 == null) {
+ return 0;
+ } else if (!s1.getObject().isLiteral() || !s2.getObject().isLiteral()) {
+ return 0;
+ }
+
+ String s1lang = s1.getObject().asLiteral().getLanguage();
+ String s2lang = s2.getObject().asLiteral().getLanguage();
+
+ return compareLangs(s1lang, s2lang);
+ }
+ }
+
+}
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/filter/LanguageFilteringGraph.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/filter/LanguageFilteringGraph.java
new file mode 100644
index 000000000..b578fddeb
--- /dev/null
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/filter/LanguageFilteringGraph.java
@@ -0,0 +1,59 @@
+package edu.cornell.mannlib.vitro.webapp.rdfservice.filter;
+
+import java.util.List;
+
+import org.apache.jena.graph.Graph;
+import org.apache.jena.graph.Node;
+import org.apache.jena.graph.Triple;
+import org.apache.jena.mem.GraphMem;
+import org.apache.jena.rdf.model.Model;
+import org.apache.jena.rdf.model.ModelFactory;
+import org.apache.jena.util.iterator.ExtendedIterator;
+
+import edu.cornell.mannlib.vitro.webapp.rdfservice.adapters.AbstractGraphDecorator;
+
+/**
+ * A graph decorator that filters find() results according to a list of
+ * preferred language strings
+ */
+public class LanguageFilteringGraph extends AbstractGraphDecorator
+ implements Graph {
+
+ private List langs;
+ private LanguageFilterModel filterModel = new LanguageFilterModel();
+
+ /**
+ * Return a graph wrapped in a decorator that will filter find() results
+ * according to the supplied list of acceptable languages
+ * @param g the graph to wrap with language awareness. May not be null.
+ * @param preferredLanguages a list of preferred language strings. May not
+ * be null.
+ */
+ protected LanguageFilteringGraph(Graph g, List preferredLanguages) {
+ super(g);
+ this.langs = preferredLanguages;
+ }
+
+ @Override
+ public ExtendedIterator find(Triple arg0) {
+ return filter(super.find(arg0));
+
+ }
+
+ @Override
+ public ExtendedIterator find(Node arg0, Node arg1, Node arg2) {
+ return filter(super.find(arg0, arg1, arg2));
+ }
+
+ private ExtendedIterator filter(ExtendedIterator triples) {
+ Graph tmp = new GraphMem();
+ while(triples.hasNext()) {
+ Triple t = triples.next();
+ tmp.add(t);
+ }
+ Model filteredModel = filterModel.filterModel(
+ ModelFactory.createModelForGraph(tmp), langs);
+ return filteredModel.getGraph().find();
+ }
+
+}
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/filter/LanguageFilteringRDFService.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/filter/LanguageFilteringRDFService.java
index 903711e52..5e59118dd 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/filter/LanguageFilteringRDFService.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/filter/LanguageFilteringRDFService.java
@@ -7,14 +7,14 @@ import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.Comparator;
+import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-
import org.apache.jena.query.QuerySolution;
import org.apache.jena.query.ResultSet;
import org.apache.jena.query.ResultSetFactory;
@@ -22,11 +22,9 @@ import org.apache.jena.query.ResultSetFormatter;
import org.apache.jena.rdf.model.Literal;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ModelChangedListener;
-import org.apache.jena.rdf.model.ModelFactory;
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.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.rdfservice.ChangeListener;
import edu.cornell.mannlib.vitro.webapp.rdfservice.ChangeSet;
import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService;
@@ -39,27 +37,13 @@ public class LanguageFilteringRDFService implements RDFService {
private static final Log log = LogFactory.getLog(LanguageFilteringRDFService.class);
private RDFService s;
private List langs;
+ private LanguageFilterModel filterModel = new LanguageFilterModel();
public LanguageFilteringRDFService(RDFService service, List langs) {
this.s = service;
- this.langs = normalizeLangs(langs);
+ this.langs = new AcceptableLanguages(langs);
}
- private List normalizeLangs(List langs) {
- log.debug("Preferred languages:" + langs);
-
- List normalizedLangs = new ArrayList(langs);
- for (String lang : langs) {
- String baseLang = lang.split("-")[0];
- if (!normalizedLangs.contains(baseLang)) {
- normalizedLangs.add(baseLang);
- }
- }
-
- log.debug("Normalized languages:" + normalizedLangs);
- return normalizedLangs;
- }
-
@Override
public boolean changeSetUpdate(ChangeSet changeSet)
throws RDFServiceException {
@@ -83,23 +67,17 @@ public class LanguageFilteringRDFService implements RDFService {
public InputStream sparqlConstructQuery(String query,
ModelSerializationFormat resultFormat)
throws RDFServiceException {
- Model m = RDFServiceUtils.parseModel(s.sparqlConstructQuery(query, resultFormat), resultFormat);
- InputStream in = outputModel(filterModel(m), resultFormat);
+ Model m = RDFServiceUtils.parseModel(s.sparqlConstructQuery(
+ query, resultFormat), resultFormat);
+ InputStream in = outputModel(filterModel.filterModel(
+ m, langs), resultFormat);
return in;
}
@Override
public void sparqlConstructQuery(String query, Model model)
throws RDFServiceException {
- if (model.isEmpty()) {
- s.sparqlConstructQuery(query, model);
- filterModel(model);
- } else {
- Model constructedModel = ModelFactory.createDefaultModel();
- s.sparqlConstructQuery(query, constructedModel);
- filterModel(constructedModel);
- model.add(constructedModel);
- }
+ s.sparqlConstructQuery(query, model);
}
@Override
@@ -107,7 +85,7 @@ public class LanguageFilteringRDFService implements RDFService {
ModelSerializationFormat resultFormat)
throws RDFServiceException {
Model m = RDFServiceUtils.parseModel(s.sparqlDescribeQuery(query, resultFormat), resultFormat);
- return outputModel(filterModel(m), resultFormat);
+ return outputModel(filterModel.filterModel(m, langs), resultFormat);
}
private InputStream outputModel(Model m, ModelSerializationFormat resultFormat) {
@@ -116,62 +94,6 @@ public class LanguageFilteringRDFService implements RDFService {
return new ByteArrayInputStream(out.toByteArray());
}
- private Model filterModel(Model m) {
- log.debug("filterModel");
- List retractions = new ArrayList();
- StmtIterator stmtIt = m.listStatements();
- while (stmtIt.hasNext()) {
- Statement stmt = stmtIt.nextStatement();
- if (stmt.getObject().isLiteral()) {
- List candidatesForRemoval = m.listStatements(
- stmt.getSubject(), stmt.getPredicate(), (RDFNode) null).toList();
- if (candidatesForRemoval.size() == 1) {
- continue;
- }
- candidatesForRemoval.sort(new StatementSortByLang());
- log.debug("sorted statements: " + showSortedStatements(candidatesForRemoval));
- Iterator candIt = candidatesForRemoval.iterator();
- String langRegister = null;
- boolean chuckRemaining = false;
- while(candIt.hasNext()) {
- Statement s = candIt.next();
- if (!s.getObject().isLiteral()) {
- continue;
- } else if (chuckRemaining) {
- retractions.add(s);
- }
- String lang = s.getObject().asLiteral().getLanguage();
- if (langRegister == null) {
- langRegister = lang;
- } else if (!langRegister.equals(lang)) {
- chuckRemaining = true;
- retractions.add(s);
- }
- }
- }
-
- }
- m.remove(retractions);
- return m;
- }
-
- private String showSortedStatements(List candidatesForRemoval) {
- List langStrings = new ArrayList();
- for (Statement stmt: candidatesForRemoval) {
- if (stmt == null) {
- langStrings.add("null stmt");
- } else {
- RDFNode node = stmt.getObject();
- if (!node.isLiteral()) {
- langStrings.add("not literal");
- } else {
- langStrings.add(node.asLiteral().getLanguage());
- }
- }
- }
- return langStrings.toString();
- }
-
@Override
public InputStream sparqlSelectQuery(String query,
ResultFormat resultFormat) throws RDFServiceException {
@@ -180,7 +102,16 @@ public class LanguageFilteringRDFService implements RDFService {
s.sparqlSelectQuery(query, RDFService.ResultFormat.JSON));
List solnList = getSolutionList(resultSet);
List vars = resultSet.getResultVars();
+
+ // This block loops all of the Query variables;
+ // for each QuerySolution, creates a map of the values of the other variables than the current
+ // 'variable' --> a list of RowIndexedLiterals.
+ // In this way, all of the QuerySolutions with equal values of their other variables are grouped.
+ // This map is used subsequently to filter Literals based on lang
for (String var : vars) {
+ Map, List> nonVarToRowIndexedLiterals = new HashMap<>();
+
+ // First pass of solnList to populate map
for (int i = 0; i < solnList.size(); i++) {
QuerySolution s = solnList.get(i);
if (s == null) {
@@ -190,23 +121,32 @@ public class LanguageFilteringRDFService implements RDFService {
if (node == null || !node.isLiteral()) {
continue;
}
- List candidatesForRemoval =
- new ArrayList();
- candidatesForRemoval.add(new RowIndexedLiteral(node.asLiteral(), i));
- for (int j = i + 1; j < solnList.size(); j++) {
- QuerySolution t = solnList.get(j);
- if (t == null) {
- continue;
- }
- if (matchesExceptForVar(s, t, var, vars)) {
- candidatesForRemoval.add(
- new RowIndexedLiteral(t.getLiteral(var), j));
+
+ // Create entry representing values other than current 'var' for this QuerySolution
+ List nonVarList = new ArrayList(vars.size() - 1);
+ for (String v : vars) {
+ if (!v.equals(var)) {
+ nonVarList.add(s.get(v));
}
}
+
+ List rowIndexedLiterals = nonVarToRowIndexedLiterals.get(nonVarList);
+ if (rowIndexedLiterals == null) {
+ rowIndexedLiterals = new ArrayList();
+ }
+ rowIndexedLiterals.add(new RowIndexedLiteral(node.asLiteral(), i));
+
+ // Add RowIndexedLiterals to the map
+ nonVarToRowIndexedLiterals.put(nonVarList, rowIndexedLiterals);
+ }
+
+ // Second pass of solnList (via the map) to evaluate candidatesForRemoval
+ for (List key : nonVarToRowIndexedLiterals.keySet()) {
+ List candidatesForRemoval = nonVarToRowIndexedLiterals.get(key);
if (candidatesForRemoval.size() == 1) {
continue;
}
- candidatesForRemoval.sort(new RowIndexedLiteralSortByLang());
+ candidatesForRemoval.sort(new RowIndexedLiteralSortByLang(langs));
log.debug("sorted RowIndexedLiterals: " + showSortedRILs(candidatesForRemoval));
Iterator candIt = candidatesForRemoval.iterator();
String langRegister = null;
@@ -254,10 +194,9 @@ public class LanguageFilteringRDFService implements RDFService {
@Override
public void sparqlSelectQuery(String query, ResultSetConsumer consumer) throws RDFServiceException {
log.debug("sparqlSelectQuery: " + query.replaceAll("\\s+", " "));
-
s.sparqlSelectQuery(query, new ResultSetConsumer.Chaining(consumer) {
List vars;
- List solnList = new ArrayList();
+ List solnList = new ArrayList<>();
@Override
protected void processQuerySolution(QuerySolution qs) {
@@ -273,7 +212,15 @@ public class LanguageFilteringRDFService implements RDFService {
protected void endProcessing() {
chainStartProcessing();
+ // This block loops all of the Query variables;
+ // for each QuerySolution, creates a map of the values of the other variables than the current
+ // 'variable' --> a list of RowIndexedLiterals.
+ // In this way, all of the QuerySolutions with equal values of their other variables are grouped.
+ // This map is used subsequently to filter Literals based on lang
for (String var : vars) {
+ Map, List> nonVarToRowIndexedLiterals = new HashMap<>();
+
+ // First pass of solnList to populate map
for (int i = 0; i < solnList.size(); i++) {
QuerySolution s = solnList.get(i);
if (s == null) {
@@ -283,23 +230,32 @@ public class LanguageFilteringRDFService implements RDFService {
if (node == null || !node.isLiteral()) {
continue;
}
- List candidatesForRemoval =
- new ArrayList();
- candidatesForRemoval.add(new RowIndexedLiteral(node.asLiteral(), i));
- for (int j = i + 1; j < solnList.size(); j++) {
- QuerySolution t = solnList.get(j);
- if (t == null) {
- continue;
- }
- if (matchesExceptForVar(s, t, var, vars)) {
- candidatesForRemoval.add(
- new RowIndexedLiteral(t.getLiteral(var), j));
+
+ // Create entry representing values other than current 'var' for this QuerySolution
+ List nonVarList = new ArrayList(vars.size() - 1);
+ for (String v : vars) {
+ if (!v.equals(var)) {
+ nonVarList.add(s.get(v));
}
}
+
+ List rowIndexedLiterals = nonVarToRowIndexedLiterals.get(nonVarList);
+ if (rowIndexedLiterals == null) {
+ rowIndexedLiterals = new ArrayList();
+ }
+ rowIndexedLiterals.add(new RowIndexedLiteral(node.asLiteral(), i));
+
+ // Add RowIndexedLiterals to the map
+ nonVarToRowIndexedLiterals.put(nonVarList, rowIndexedLiterals);
+ }
+
+ // Second pass of solnList (via the map) to evaluate candidatesForRemoval
+ for (List key : nonVarToRowIndexedLiterals.keySet()) {
+ List candidatesForRemoval = nonVarToRowIndexedLiterals.get(key);
if (candidatesForRemoval.size() == 1) {
continue;
}
- candidatesForRemoval.sort(new RowIndexedLiteralSortByLang());
+ candidatesForRemoval.sort(new RowIndexedLiteralSortByLang(langs));
log.debug("sorted RowIndexedLiterals: " + showSortedRILs(candidatesForRemoval));
Iterator candIt = candidatesForRemoval.iterator();
String langRegister = null;
@@ -357,34 +313,6 @@ public class LanguageFilteringRDFService implements RDFService {
}
- private boolean matchesExceptForVar(QuerySolution a, QuerySolution b,
- String varName, List varList) {
- if (varName == null) {
- throw new RuntimeException("expected non-null variable nane");
- }
- for (String var : varList) {
- RDFNode nodea = a.get(var);
- RDFNode nodeb = b.get(var);
- if (var.equals(varName)) {
- if (nodea == null || !nodea.isLiteral() || nodeb == null || !nodeb.isLiteral()) {
- return false;
- }
- } else {
- if (nodea == null && nodeb == null) {
- continue;
- } else if (nodea == null && nodeb != null) {
- return false;
- } else if (nodeb == null && nodea != null) {
- return false;
- }
- if (!a.get(var).equals(b.get(var))) {
- return false;
- }
- }
- }
- return true;
- }
-
private List getSolutionList(ResultSet resultSet) {
List solnList = new ArrayList();
while (resultSet.hasNext()) {
@@ -489,52 +417,12 @@ public class LanguageFilteringRDFService implements RDFService {
s.close();
}
- private class LangSort {
- // any inexact match is worse than any exact match
- private int inexactMatchPenalty = langs.size();
- // no language is worse than any inexact match (if the preferred list does not include "").
- private int noLanguage = 2 * inexactMatchPenalty;
- // no match is worse than no language.
- private int noMatch = noLanguage + 1;
-
- protected int compareLangs(String t1lang, String t2lang) {
- return languageIndex(t1lang) - languageIndex(t2lang);
- }
-
- /**
- * Return index of exact match, or index of partial match, or
- * language-free, or no match.
- */
- private int languageIndex(String lang) {
- if (lang == null) {
- lang = "";
- }
-
- int index = langs.indexOf(lang);
- if (index >= 0) {
- log.debug("languageIndex for '" + lang + "' is " + index);
- return index;
- }
-
- if (lang.length() > 2) {
- index = langs.indexOf(lang.substring(0, 2));
- if (index >= 0) {
- log.debug("languageIndex for '" + lang + "' is " + index + inexactMatchPenalty);
- return index + inexactMatchPenalty;
- }
- }
-
- if (lang.isEmpty()) {
- log.debug("languageIndex for '" + lang + "' is " + noLanguage);
- return noLanguage;
- }
-
- return noMatch;
- }
- }
-
private class RowIndexedLiteralSortByLang extends LangSort implements Comparator {
+ public RowIndexedLiteralSortByLang(List langs) {
+ super(langs);
+ }
+
public int compare(RowIndexedLiteral rilit1, RowIndexedLiteral rilit2) {
if (rilit1 == null || rilit2 == null) {
return 0;
@@ -547,21 +435,20 @@ public class LanguageFilteringRDFService implements RDFService {
}
}
- private class StatementSortByLang extends LangSort implements Comparator {
+ /*
+ * UQAM-Linguistic-Management Useful among other things to transport the linguistic context in the service
+ * (non-Javadoc)
+ * @see edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService#setVitroRequest(edu.cornell.mannlib.vitro.webapp.controller.VitroRequest)
+ */
+ private VitroRequest vitroRequest;
- public int compare(Statement s1, Statement s2) {
- if (s1 == null || s2 == null) {
- return 0;
- } else if (!s1.getObject().isLiteral() || !s2.getObject().isLiteral()) {
- return 0;
- }
+ public void setVitroRequest(VitroRequest vitroRequest) {
+ this.vitroRequest = vitroRequest;
+ }
- String s1lang = s1.getObject().asLiteral().getLanguage();
- String s2lang = s2.getObject().asLiteral().getLanguage();
-
- return compareLangs(s1lang, s2lang);
- }
- }
+ public VitroRequest getVitroRequest() {
+ return vitroRequest;
+ }
}
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/filter/LanguageFilteringUtils.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/filter/LanguageFilteringUtils.java
index 5a0336462..720bcc148 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/filter/LanguageFilteringUtils.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/filter/LanguageFilteringUtils.java
@@ -4,26 +4,62 @@ package edu.cornell.mannlib.vitro.webapp.rdfservice.filter;
import java.util.ArrayList;
import java.util.Enumeration;
+import java.util.HashSet;
import java.util.List;
import java.util.Locale;
+import java.util.Set;
import javax.servlet.ServletRequest;
+import org.apache.commons.lang3.LocaleUtils;
import org.apache.jena.ontology.OntModel;
import org.apache.jena.ontology.OntModelSpec;
import org.apache.jena.rdf.model.ModelFactory;
-import edu.cornell.mannlib.vitro.webapp.dao.jena.RDFServiceGraph;
-import edu.cornell.mannlib.vitro.webapp.rdfservice.impl.jena.model.RDFServiceModel;
-
/**
* Some methods that will come in handy when dealing with Language Filtering
*/
public class LanguageFilteringUtils {
+ private static final String UNDERSCORE = "_";
+ private static final String HYPHEN = "-";
+ private static final String DEFAULT_LANG_STRING = "en";
+
+ /**
+ * Take a Locale object, such as we might get from a
+ * request, and convert to a language string used in RDF.
+ *
+ * While converting, change all underscores (as in Locale names) to hyphens
+ * (as in RDF language specifiers).
+ */
+ public static String localeToLanguage(Locale locale) {
+ return locale.toString().replace(UNDERSCORE, HYPHEN);
+ }
+
+ /**
+ * Take a language string and convert to a Locale.
+ *
+ * While converting, change all hyphens (as in RDF language specifiers) to
+ * underscores (as in Locale names). Ensure language string is lowercase
+ * and country abbreviation is uppercase.
+ */
+ public static Locale languageToLocale(String langStr) {
+ String[] langParts = langStr.split(HYPHEN);
+ if (langParts.length > 2) {
+ langStr = String.join(UNDERSCORE, langParts[0].toLowerCase(),
+ langParts[1].toUpperCase(), langParts[2]);
+ } else if (langParts.length > 1) {
+ langStr = String.join(UNDERSCORE, langParts[0].toLowerCase(),
+ langParts[1].toUpperCase());
+ } else {
+ langStr = langParts[0].toLowerCase();
+ }
+ return LocaleUtils.toLocale(langStr);
+ }
+
/**
* Take an Enumeration of Locale objects, such as we might get from a
- * request, and convert to a List of langauage strings, such as are needed
+ * request, and convert to a List of language strings, such as are needed
* by the LanguageFilteringRDFService.
*
* While converting, change all underscores (as in Locale names) to hyphens
@@ -33,27 +69,43 @@ public class LanguageFilteringUtils {
List langs = new ArrayList<>();
while (locales.hasMoreElements()) {
Locale locale = (Locale) locales.nextElement();
- langs.add(locale.toString().replace("_", "-"));
+ langs.add(locale.toString().replace(UNDERSCORE, HYPHEN));
}
if (langs.isEmpty()) {
- langs.add("en");
+ langs.add(DEFAULT_LANG_STRING);
}
- return langs;
+ return langs;
}
/**
- * Add a Language Filtering layer to an OntModel by treating it as an RDFService.
+ * Take a List of language strings and convert to a List of Locale.
+ *
+ * While converting, change all hyphens (as in RDF language specifiers) to
+ * under scores (as in Locale names). Ensure language string is lowercase
+ * and country abbreviation is uppercase.
+ */
+ public static List languagesToLocales(List langs) {
+ Set locales = new HashSet<>();
+ langs.forEach(langStr -> {
+ locales.add(languageToLocale(langStr));
+ });
+ if (locales.isEmpty()) {
+ locales.add(LocaleUtils.toLocale(DEFAULT_LANG_STRING));
+ }
+
+ return new ArrayList<>(locales);
+ }
+
+ /**
+ * Add a Language Filtering layer to an OntModel
*/
public static OntModel wrapOntModelInALanguageFilter(OntModel rawModel,
ServletRequest req) {
- /** This is some nasty layering. Could we do this more easily? */
- List languages = localesToLanguages(req.getLocales());
+ List languages = new AcceptableLanguages(localesToLanguages(req.getLocales()));
return ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM,
- RDFServiceGraph.createRDFServiceModel(
- new RDFServiceGraph(
- new LanguageFilteringRDFService(
- new RDFServiceModel(rawModel), languages))));
+ ModelFactory.createModelForGraph(new LanguageFilteringGraph(
+ rawModel.getGraph(), languages)));
}
private LanguageFilteringUtils() {
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/RDFServiceFactorySingle.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/RDFServiceFactorySingle.java
index f44d2b59f..44bd2aabb 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/RDFServiceFactorySingle.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/RDFServiceFactorySingle.java
@@ -9,6 +9,7 @@ import java.util.List;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ModelChangedListener;
+import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.rdfservice.ChangeListener;
import edu.cornell.mannlib.vitro.webapp.rdfservice.ChangeSet;
import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService;
@@ -218,7 +219,20 @@ public class RDFServiceFactorySingle implements RDFServiceFactory {
return ToString.simpleName(this) + "[" + ToString.hashHex(this)
+ ", inner=" + s + "]";
}
+ /*
+ * UQAM-Linguistic-Management Useful among other things to transport the linguistic context in the service
+ * (non-Javadoc)
+ * @see edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService#setVitroRequest(edu.cornell.mannlib.vitro.webapp.controller.VitroRequest)
+ */
+ private VitroRequest vitroRequest;
+ public void setVitroRequest(VitroRequest vitroRequest) {
+ this.vitroRequest = vitroRequest;
+ }
+
+ public VitroRequest getVitroRequest() {
+ return vitroRequest;
+ }
}
}
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/RDFServiceImpl.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/RDFServiceImpl.java
index 217149283..6ff961382 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/RDFServiceImpl.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/RDFServiceImpl.java
@@ -32,6 +32,7 @@ import org.apache.jena.riot.out.NodeFormatter;
import org.apache.jena.riot.out.NodeFormatterTTL;
import org.apache.jena.vocabulary.RDF;
+import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.rdfservice.ChangeListener;
import edu.cornell.mannlib.vitro.webapp.rdfservice.ChangeSet;
import edu.cornell.mannlib.vitro.webapp.rdfservice.ModelChange;
@@ -141,8 +142,8 @@ public abstract class RDFServiceImpl implements RDFService {
}
protected void notifyListeners(ModelChange modelChange) throws IOException {
+ modelChange.getSerializedModel().reset();
for (ChangeListener listener : registeredListeners) {
- modelChange.getSerializedModel().reset();
listener.notifyModelChange(modelChange);
}
log.debug(registeredJenaListeners.size() + " registered Jena listeners");
@@ -254,11 +255,12 @@ public abstract class RDFServiceImpl implements RDFService {
literalBuff.append("\"");
pyString(literalBuff, node.getLiteralLexicalForm());
literalBuff.append("\"");
- if (node.getLiteralDatatypeURI() != null) {
- literalBuff.append("^^<").append(node.getLiteralDatatypeURI()).append(">");
- } else if (node.getLiteralLanguage() != null && node.getLiteralLanguage().length() > 0) {
+ if (node.getLiteralLanguage() != null && node.getLiteralLanguage().length() > 0) {
literalBuff.append("@").append(node.getLiteralLanguage());
+ } else if (node.getLiteralDatatypeURI() != null) {
+ literalBuff.append("^^<").append(node.getLiteralDatatypeURI()).append(">");
}
+
return literalBuff.toString();
} else {
return varName;
@@ -453,4 +455,19 @@ public abstract class RDFServiceImpl implements RDFService {
}
}
}
+ /*
+ * UQAM Useful among other things to transport the linguistic context in the service
+ * (non-Javadoc)
+ * @see edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService#setVitroRequest(edu.cornell.mannlib.vitro.webapp.controller.VitroRequest)
+ */
+ private VitroRequest vitroRequest;
+
+ public void setVitroRequest(VitroRequest vitroRequest) {
+ this.vitroRequest = vitroRequest;
+ }
+
+ public VitroRequest getVitroRequest() {
+ return vitroRequest;
+ }
+
}
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/jena/RDFServiceJena.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/jena/RDFServiceJena.java
index dadccfed4..09a98a647 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/jena/RDFServiceJena.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/jena/RDFServiceJena.java
@@ -42,6 +42,7 @@ import org.apache.jena.sdb.SDB;
import org.apache.jena.shared.Lock;
import org.apache.jena.sparql.core.Quad;
+import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.dao.jena.DatasetWrapper;
import edu.cornell.mannlib.vitro.webapp.dao.jena.RDFServiceDataset;
import edu.cornell.mannlib.vitro.webapp.dao.jena.SparqlGraph;
@@ -200,8 +201,8 @@ public abstract class RDFServiceJena extends RDFServiceImpl implements RDFServic
log.debug("blank node model size " + blankNodeModel.size());
if (blankNodeModel.size() == 1) {
- log.warn("Deleting single triple with blank node: " + blankNodeModel);
- log.warn("This likely indicates a problem; excessive data may be deleted.");
+ log.debug("Deleting single triple with blank node: " + blankNodeModel);
+ log.debug("This could result in the deletion of multiple triples if multiple blank nodes match the same triple pattern.");
}
Query rootFinderQuery = QueryFactory.create(BNODE_ROOT_QUERY);
@@ -704,4 +705,19 @@ public abstract class RDFServiceJena extends RDFServiceImpl implements RDFServic
protected QueryExecution createQueryExecution(String queryString, Query q, Dataset d) {
return QueryExecutionFactory.create(q, d);
}
+ /*
+ * UQAM-Linguistic-Management Useful among other things to transport the linguistic context in the service
+ * (non-Javadoc)
+ * @see edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService#setVitroRequest(edu.cornell.mannlib.vitro.webapp.controller.VitroRequest)
+ */
+ private VitroRequest vitroRequest;
+
+ public void setVitroRequest(VitroRequest vitroRequest) {
+ this.vitroRequest = vitroRequest;
+ }
+
+ public VitroRequest getVitroRequest() {
+ return vitroRequest;
+ }
+
}
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/jena/model/RDFServiceModel.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/jena/model/RDFServiceModel.java
index 496928fbc..4b910b568 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/jena/model/RDFServiceModel.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/jena/model/RDFServiceModel.java
@@ -13,6 +13,7 @@ import org.apache.jena.query.Dataset;
import org.apache.jena.query.DatasetFactory;
import org.apache.jena.rdf.model.Model;
+import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.dao.jena.DatasetWrapper;
import edu.cornell.mannlib.vitro.webapp.rdfservice.ChangeSet;
import edu.cornell.mannlib.vitro.webapp.rdfservice.ModelChange;
@@ -119,4 +120,18 @@ public class RDFServiceModel extends RDFServiceJena implements RDFService {
return true;
}
+ /*
+ * UQAM-Linguistic-Management Useful among other things to transport the linguistic context in the service
+ * (non-Javadoc)
+ * @see edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService#setVitroRequest(edu.cornell.mannlib.vitro.webapp.controller.VitroRequest)
+ */
+ private VitroRequest vitroRequest;
+
+ public void setVitroRequest(VitroRequest vitroRequest) {
+ this.vitroRequest = vitroRequest;
+ }
+
+ public VitroRequest getVitroRequest() {
+ return vitroRequest;
+ }
}
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/jena/tdb/RDFServiceTDB.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/jena/tdb/RDFServiceTDB.java
index 6b5e4557a..adcb69826 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/jena/tdb/RDFServiceTDB.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/jena/tdb/RDFServiceTDB.java
@@ -13,6 +13,8 @@ import java.nio.file.Paths;
import java.util.List;
import org.apache.jena.rdf.model.Model;
+import org.apache.jena.rdf.model.RDFNode;
+
import edu.cornell.mannlib.vitro.webapp.rdfservice.ResultSetConsumer;
import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
@@ -74,11 +76,19 @@ public class RDFServiceTDB extends RDFServiceJena {
}
notifyListenersOfPreChangeEvents(changeSet);
- dataset.begin(ReadWrite.WRITE);
- try {
- applyChangeSetToModel(changeSet, dataset);
- dataset.commit();
- } finally {
+ dataset.begin(ReadWrite.WRITE);
+ try {
+ boolean committed = false;
+ try {
+ applyChangeSetToModel(changeSet, dataset);
+ dataset.commit();
+ committed = true;
+ } finally {
+ if(!committed) {
+ dataset.abort();
+ }
+ }
+ } finally {
dataset.end();
}
@@ -93,6 +103,10 @@ public class RDFServiceTDB extends RDFServiceJena {
}
}
+ @Override
+ public boolean preferPreciseOptionals() {
+ return true;
+ }
@Override
public void close() {
@@ -232,6 +246,28 @@ public class RDFServiceTDB extends RDFServiceJena {
return isEquivalentGraph(graphURI, inStream, ModelSerializationFormat.NTRIPLE);
}
+ @Override
+ public long countTriples(RDFNode subject, RDFNode predicate, RDFNode object)
+ throws RDFServiceException {
+ dataset.begin(ReadWrite.READ);
+ try {
+ return super.countTriples(subject, predicate, object);
+ } finally {
+ dataset.end();
+ }
+ }
+
+ @Override
+ public Model getTriples(RDFNode subject, RDFNode predicate, RDFNode object,
+ long limit, long offset) throws RDFServiceException {
+ dataset.begin(ReadWrite.READ);
+ try {
+ return super.getTriples(subject, predicate, object, limit, offset);
+ } finally {
+ dataset.end();
+ }
+ }
+
/**
* Convert all of the references to integer compatible type to "integer" in the serialized graph.
*
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/logging/LoggingRDFService.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/logging/LoggingRDFService.java
index 5a0189f41..abae2aeb9 100644
--- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/logging/LoggingRDFService.java
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/logging/LoggingRDFService.java
@@ -9,6 +9,7 @@ import java.util.List;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ModelChangedListener;
+import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.rdfservice.ChangeListener;
import edu.cornell.mannlib.vitro.webapp.rdfservice.ChangeSet;
import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService;
@@ -207,4 +208,19 @@ public class LoggingRDFService implements RDFService {
public String toString() {
return "LoggingRDFService[inner=" + innerService + "]";
}
+ /*
+ * UQAM-Linguistic-Management Useful among other things to transport the linguistic context in the service
+ * (non-Javadoc)
+ * @see edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService#setVitroRequest(edu.cornell.mannlib.vitro.webapp.controller.VitroRequest)
+ */
+ private VitroRequest vitroRequest;
+
+ public void setVitroRequest(VitroRequest vitroRequest) {
+ this.vitroRequest = vitroRequest;
+ }
+
+ public VitroRequest getVitroRequest() {
+ return vitroRequest;
+ }
+
}
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/search/controller/ExtendedSearchController.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/search/controller/ExtendedSearchController.java
new file mode 100644
index 000000000..9bc308db0
--- /dev/null
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/search/controller/ExtendedSearchController.java
@@ -0,0 +1,767 @@
+/* $This file is distributed under the terms of the license in LICENSE$ */
+
+package edu.cornell.mannlib.vitro.webapp.search.controller;
+
+import java.io.IOException;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Base64;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import edu.cornell.mannlib.vitro.webapp.application.ApplicationUtils;
+import edu.cornell.mannlib.vitro.webapp.beans.ApplicationBean;
+import edu.cornell.mannlib.vitro.webapp.beans.Individual;
+import edu.cornell.mannlib.vitro.webapp.beans.VClass;
+import edu.cornell.mannlib.vitro.webapp.beans.VClassGroup;
+import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
+import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerHttpServlet;
+import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder;
+import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder.ParamMap;
+import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ExceptionResponseValues;
+import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues;
+import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues;
+import edu.cornell.mannlib.vitro.webapp.dao.IndividualDao;
+import edu.cornell.mannlib.vitro.webapp.dao.VClassDao;
+import edu.cornell.mannlib.vitro.webapp.dao.VClassGroupDao;
+import edu.cornell.mannlib.vitro.webapp.dao.VClassGroupsForRequest;
+import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
+import edu.cornell.mannlib.vitro.webapp.dao.jena.VClassGroupCache;
+import edu.cornell.mannlib.vitro.webapp.i18n.I18n;
+import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchEngine;
+import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchFacetField;
+import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchFacetField.Count;
+import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchQuery;
+import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchResponse;
+import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchResultDocument;
+import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchResultDocumentList;
+import edu.cornell.mannlib.vitro.webapp.search.VitroSearchTermNames;
+import edu.cornell.mannlib.vitro.webapp.web.templatemodels.LinkTemplateModel;
+import edu.cornell.mannlib.vitro.webapp.web.templatemodels.searchresult.IndividualSearchResult;
+import edu.ucsf.vitro.opensocial.OpenSocialManager;
+
+/**
+ * Paged search controller that uses the search engine
+ */
+
+@WebServlet(name = "ExtendedSearchController", urlPatterns = {"/extendedsearch","/extendedsearch.jsp","/extendedfedsearch","/extendedsearchcontroller"} )
+public class ExtendedSearchController extends FreemarkerHttpServlet {
+
+ private static final long serialVersionUID = 1L;
+ private static final Log log = LogFactory.getLog(ExtendedSearchController.class);
+
+ protected static final int DEFAULT_HITS_PER_PAGE = 25;
+ protected static final int DEFAULT_MAX_HIT_COUNT = 1000;
+
+ private static final String PARAM_XML_REQUEST = "xml";
+ private static final String PARAM_CSV_REQUEST = "csv";
+ private static final String PARAM_START_INDEX = "startIndex";
+ private static final String PARAM_HITS_PER_PAGE = "hitsPerPage";
+ private static final String PARAM_CLASSGROUP = "classgroup";
+ private static final String PARAM_RDFTYPE = "type";
+ private static final String PARAM_QUERY_TEXT = "querytext";
+ private static final String EXTENDEDSEARCH = "/extendedsearch";
+
+ protected static final Map> templateTable;
+
+ protected enum Format {
+ HTML, XML, CSV;
+ }
+
+ protected enum Result {
+ PAGED, ERROR, BAD_QUERY
+ }
+
+ static{
+ templateTable = setupTemplateTable();
+ }
+
+ /**
+ * Overriding doGet from FreemarkerHttpController to do a page template (as
+ * opposed to body template) style output for XML requests.
+ *
+ * This follows the pattern in AutocompleteController.java.
+ */
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws IOException, ServletException {
+ VitroRequest vreq = new VitroRequest(request);
+ boolean wasXmlRequested = isRequestedFormatXml(vreq);
+ boolean wasCSVRequested = isRequestedFormatCSV(vreq);
+ if( !wasXmlRequested && !wasCSVRequested){
+ super.doGet(vreq,response);
+ }else if (wasXmlRequested){
+ try {
+ ResponseValues rvalues = processRequest(vreq);
+
+ response.setCharacterEncoding("UTF-8");
+ response.setContentType("text/xml;charset=UTF-8");
+ response.setHeader("Content-Disposition", "attachment; filename=search.xml");
+ writeTemplate(rvalues.getTemplateName(), rvalues.getMap(), request, response);
+ } catch (Exception e) {
+ log.error(e, e);
+ }
+ }else if (wasCSVRequested){
+ try {
+ ResponseValues rvalues = processRequest(vreq);
+
+ response.setCharacterEncoding("UTF-8");
+ response.setContentType("text/csv;charset=UTF-8");
+ response.setHeader("Content-Disposition", "attachment; filename=search.csv");
+ writeTemplate(rvalues.getTemplateName(), rvalues.getMap(), request, response);
+ } catch (Exception e) {
+ log.error(e, e);
+ }
+ }
+ }
+
+ @Override
+ public void doPost(HttpServletRequest request, HttpServletResponse response)
+ throws IOException, ServletException {
+ VitroRequest vreq = new VitroRequest(request);
+ boolean wasXmlRequested = isRequestedFormatXml(vreq);
+ boolean wasCSVRequested = isRequestedFormatCSV(vreq);
+ if( !wasXmlRequested && !wasCSVRequested){
+ super.doGet(vreq,response);
+ }else if (wasXmlRequested){
+ try {
+ ResponseValues rvalues = processRequest(vreq);
+
+ response.setCharacterEncoding("UTF-8");
+ response.setContentType("text/xml;charset=UTF-8");
+ response.setHeader("Content-Disposition", "attachment; filename=search.xml");
+ writeTemplate(rvalues.getTemplateName(), rvalues.getMap(), request, response);
+ } catch (Exception e) {
+ log.error(e, e);
+ }
+ }else if (wasCSVRequested){
+ try {
+ ResponseValues rvalues = processRequest(vreq);
+
+ response.setCharacterEncoding("UTF-8");
+ response.setContentType("text/csv;charset=UTF-8");
+ response.setHeader("Content-Disposition", "attachment; filename=search.csv");
+ writeTemplate(rvalues.getTemplateName(), rvalues.getMap(), request, response);
+ } catch (Exception e) {
+ log.error(e, e);
+ }
+ }
+ }
+
+ @Override
+ protected ResponseValues processRequest(VitroRequest vreq) {
+
+ //There may be other non-html formats in the future
+ Format format = getFormat(vreq);
+ boolean wasXmlRequested = Format.XML == format;
+ boolean wasCSVRequested = Format.CSV == format;
+ log.debug("Requested format was " + (wasXmlRequested ? "xml" : "html"));
+ boolean wasHtmlRequested = ! (wasXmlRequested || wasCSVRequested);
+
+ try {
+
+ //make sure an IndividualDao is available
+ if( vreq.getWebappDaoFactory() == null
+ || vreq.getWebappDaoFactory().getIndividualDao() == null ){
+ log.error("Could not get webappDaoFactory or IndividualDao");
+ throw new Exception("Could not access model.");
+ }
+ IndividualDao iDao = vreq.getWebappDaoFactory().getIndividualDao();
+ VClassGroupDao grpDao = vreq.getWebappDaoFactory().getVClassGroupDao();
+ VClassDao vclassDao = vreq.getWebappDaoFactory().getVClassDao();
+
+ ApplicationBean appBean = vreq.getAppBean();
+
+ log.debug("IndividualDao is " + iDao.toString() + " Public classes in the classgroup are " + grpDao.getPublicGroupsWithVClasses().toString());
+ log.debug("VClassDao is "+ vclassDao.toString() );
+
+ int startIndex = getStartIndex(vreq);
+ int hitsPerPage = getHitsPerPage( vreq );
+ String queryBuilderRules = getQueryBuilderRules(vreq);
+
+
+ String queryText = vreq.getParameter(PARAM_QUERY_TEXT);
+ log.debug("Query text is \""+ queryText + "\"");
+
+
+ String badQueryMsg = badQueryText( queryText, vreq );
+ if( badQueryMsg != null ){
+ return doFailedSearch(badQueryMsg, queryText, format, vreq);
+ }
+
+ SearchQuery query = getQuery(queryText, hitsPerPage, startIndex, vreq);
+ SearchEngine search = ApplicationUtils.instance().getSearchEngine();
+ SearchResponse response = null;
+
+ try {
+ response = search.query(query);
+ } catch (Exception ex) {
+ String msg = makeBadSearchMessage(queryText, ex.getMessage(), vreq);
+ log.error("could not run search query",ex);
+ return doFailedSearch(msg, queryText, format, vreq);
+ }
+
+ if (response == null) {
+ log.error("Search response was null");
+ return doFailedSearch(I18n.text(vreq, "error_in_search_request"), queryText, format, vreq);
+ }
+
+ SearchResultDocumentList docs = response.getResults();
+ if (docs == null) {
+ log.error("Document list for a search was null");
+ return doFailedSearch(I18n.text(vreq, "error_in_search_request"), queryText,format, vreq);
+ }
+
+ long hitCount = docs.getNumFound();
+ log.debug("Number of hits = " + hitCount);
+ if ( hitCount < 1 ) {
+ return doNoHits(queryText,format, vreq);
+ }
+
+ List individuals = new ArrayList(docs.size());
+ for (SearchResultDocument doc : docs) {
+ try {
+ String uri = doc.getStringValue(VitroSearchTermNames.URI);
+ Individual ind = iDao.getIndividualByURI(uri);
+ if (ind != null) {
+ ind.setSearchSnippet(getSnippet(doc, response));
+ individuals.add(ind);
+ }
+ } catch (Exception e) {
+ log.error("Problem getting usable individuals from search hits. ", e);
+ }
+ }
+
+ ParamMap pagingLinkParams = new ParamMap();
+ pagingLinkParams.put(PARAM_QUERY_TEXT, queryText);
+ pagingLinkParams.put(PARAM_HITS_PER_PAGE, String.valueOf(hitsPerPage));
+
+ if( wasXmlRequested ){
+ pagingLinkParams.put(PARAM_XML_REQUEST,"1");
+ }
+
+ /* Compile the data for the templates */
+
+ Map body = new HashMap();
+
+ String classGroupParam = vreq.getParameter(PARAM_CLASSGROUP);
+ log.debug("ClassGroupParam is \""+ classGroupParam + "\"");
+ boolean classGroupFilterRequested = false;
+ if (!StringUtils.isEmpty(classGroupParam)) {
+ VClassGroup grp = grpDao.getGroupByURI(classGroupParam);
+ classGroupFilterRequested = true;
+ if (grp != null && grp.getPublicName() != null)
+ body.put("classGroupName", grp.getPublicName());
+ }
+
+ String typeParam = vreq.getParameter(PARAM_RDFTYPE);
+ boolean typeFilterRequested = false;
+ if (!StringUtils.isEmpty(typeParam)) {
+ VClass type = vclassDao.getVClassByURI(typeParam);
+ typeFilterRequested = true;
+ if (type != null && type.getName() != null)
+ body.put("typeName", type.getName());
+ }
+
+ /* Add ClassGroup and type refinement links to body */
+ if( wasHtmlRequested ){
+ if ( !classGroupFilterRequested && !typeFilterRequested ) {
+ // Search request includes no ClassGroup and no type, so add ClassGroup search refinement links.
+ body.put("classGroupLinks", getClassGroupsLinks(vreq, grpDao, docs, response, queryText));
+ } else if ( classGroupFilterRequested && !typeFilterRequested ) {
+ // Search request is for a ClassGroup, so add rdf:type search refinement links
+ // but try to filter out classes that are subclasses
+ body.put("classLinks", getVClassLinks(vclassDao, docs, response, queryText));
+ pagingLinkParams.put(PARAM_CLASSGROUP, classGroupParam);
+
+ } else {
+ //search request is for a class so there are no more refinements
+ pagingLinkParams.put(PARAM_RDFTYPE, typeParam);
+ }
+ }
+
+ body.put("individuals", IndividualSearchResult
+ .getIndividualTemplateModels(individuals, vreq));
+
+ body.put("querytext", queryText);
+ body.put("title", new StringBuilder().append(appBean.getApplicationName()).append(" - ").
+ append(I18n.text(vreq, "search_results_for")).append(" '").append(queryText).append("'").toString());
+
+ body.put("hitCount", hitCount);
+ body.put("startIndex", startIndex);
+ body.put(PARAM_HITS_PER_PAGE, hitsPerPage);
+
+ body.put("pagingLinks",
+ getPagingLinks(startIndex, hitsPerPage, hitCount,
+ vreq.getServletPath(),
+ pagingLinkParams, vreq));
+
+ if (startIndex != 0) {
+ body.put("prevPage", getPreviousPageLink(startIndex,
+ hitsPerPage, vreq.getServletPath(), pagingLinkParams));
+ }
+ if (startIndex < (hitCount - hitsPerPage)) {
+ body.put("nextPage", getNextPageLink(startIndex, hitsPerPage,
+ vreq.getServletPath(), pagingLinkParams));
+ }
+ if (queryBuilderRules != null) {
+ body.put("queryBuilderRules", queryBuilderRules);
+ }
+ body.put(PARAM_HITS_PER_PAGE, hitsPerPage);
+
+ // VIVO OpenSocial Extension by UCSF
+ try {
+ OpenSocialManager openSocialManager = new OpenSocialManager(vreq, "search");
+ // put list of people found onto pubsub channel
+ // only turn this on for a people only search
+ if ("http://vivoweb.org/ontology#vitroClassGrouppeople".equals(vreq.getParameter(PARAM_CLASSGROUP))) {
+ List ids = OpenSocialManager.getOpenSocialId(individuals);
+ openSocialManager.setPubsubData(OpenSocialManager.JSON_PERSONID_CHANNEL,
+ OpenSocialManager.buildJSONPersonIds(ids, "" + ids.size() + " people found"));
+ }
+ // TODO put this in a better place to guarantee that it gets called at the proper time!
+ openSocialManager.removePubsubGadgetsWithoutData();
+ body.put("openSocial", openSocialManager);
+ if (openSocialManager.isVisible()) {
+ body.put("bodyOnload", "my.init();");
+ }
+ } catch (IOException e) {
+ log.error("IOException in doTemplate()", e);
+ } catch (SQLException e) {
+ log.error("SQLException in doTemplate()", e);
+ }
+
+ String template = templateTable.get(format).get(Result.PAGED);
+
+
+
+ return new TemplateResponseValues(template, body);
+ } catch (Throwable e) {
+ return doSearchError(e,format);
+ }
+ }
+
+ private String getQueryBuilderRules(VitroRequest vreq) {
+ String rules = null;
+ try {
+ rules = vreq.getParameter("queryBuilderRules");
+ } catch (Throwable e) {
+ log.error(e);
+ }
+ return rules;
+ }
+
+ private int getHitsPerPage(VitroRequest vreq) {
+ int hitsPerPage = DEFAULT_HITS_PER_PAGE;
+ try{
+ hitsPerPage = Integer.parseInt(vreq.getParameter(PARAM_HITS_PER_PAGE));
+ } catch (Throwable e) {
+ hitsPerPage = DEFAULT_HITS_PER_PAGE;
+ }
+ log.debug("hitsPerPage is " + hitsPerPage);
+ return hitsPerPage;
+ }
+
+ private int getStartIndex(VitroRequest vreq) {
+ int startIndex = 0;
+ try{
+ startIndex = Integer.parseInt(vreq.getParameter(PARAM_START_INDEX));
+ }catch (Throwable e) {
+ startIndex = 0;
+ }
+ log.debug("startIndex is " + startIndex);
+ return startIndex;
+ }
+
+ private String badQueryText(String qtxt, VitroRequest vreq) {
+ if( qtxt == null || "".equals( qtxt.trim() ) )
+ return I18n.text(vreq, "enter_search_term");
+
+ if( qtxt.equals("*:*") )
+ return I18n.text(vreq, "invalid_search_term") ;
+
+ return null;
+ }
+
+ /**
+ * Get the class groups represented for the individuals in the documents.
+ */
+ private List getClassGroupsLinks(VitroRequest vreq, VClassGroupDao grpDao, SearchResultDocumentList docs, SearchResponse rsp, String qtxt) {
+ Map cgURItoCount = new HashMap();
+
+ List classgroups = new ArrayList( );
+ List ffs = rsp.getFacetFields();
+ for(SearchFacetField ff : ffs){
+ if(VitroSearchTermNames.CLASSGROUP_URI.equals(ff.getName())){
+ List counts = ff.getValues();
+ for( Count ct: counts){
+ VClassGroup vcg = grpDao.getGroupByURI( ct.getName() );
+ if( vcg == null ){
+ log.debug("could not get classgroup for URI " + ct.getName());
+ }else{
+ classgroups.add(vcg);
+ cgURItoCount.put(vcg.getURI(), ct.getCount());
+ }
+ }
+ }
+ }
+
+ grpDao.sortGroupList(classgroups);
+
+ VClassGroupsForRequest vcgfr = VClassGroupCache.getVClassGroups(vreq);
+ List classGroupLinks = new ArrayList(classgroups.size());
+ for (VClassGroup vcg : classgroups) {
+ String groupURI = vcg.getURI();
+ VClassGroup localizedVcg = vcgfr.getGroup(groupURI);
+ long count = cgURItoCount.get( groupURI );
+ if (localizedVcg.getPublicName() != null && count > 0 ) {
+ classGroupLinks.add(new VClassGroupSearchLink(qtxt, localizedVcg, count));
+ }
+ }
+ return classGroupLinks;
+ }
+
+ private List getVClassLinks(VClassDao vclassDao, SearchResultDocumentList docs, SearchResponse rsp, String qtxt){
+ HashSet typesInHits = getVClassUrisForHits(docs);
+ List