Merge pull request #355 from vivo-project/i18n-redesign

I18n redesign
This commit is contained in:
Dragan Ivanovic 2023-02-13 14:08:01 +01:00 committed by GitHub
commit 48c88d3d3e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
110 changed files with 52884 additions and 1421 deletions

View file

@ -14,12 +14,6 @@ jobs:
with:
path: Vitro
- name: Checkout vitro languages
uses: actions/checkout@v3
with:
repository: vivo-project/Vitro-languages
path: Vitro-languages
- name: Maven Cache
uses: actions/cache@v2
with:
@ -34,7 +28,5 @@ jobs:
- name: Maven Build
run: |
cd ./Vitro-languages
mvn clean install
cd ../Vitro
cd ./Vitro
mvn clean install

View file

@ -6,8 +6,6 @@ import java.lang.reflect.Method;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
@ -17,6 +15,7 @@ import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.logging.Log;
@ -272,6 +271,37 @@ public class FormUtils {
return options;
}
public static List<Option> makeOptionListOfNotDisjointClasses(WebappDaoFactory wadf, String baseVclassUri, String selectedUri) {
VClassDao vClassDao = wadf.getVClassDao();
Set<String> uris = getNotDisjointClassUris(wadf, baseVclassUri, vClassDao);
uris.add(baseVclassUri);
List<Option> options = new LinkedList<>();
for (String vclassUri : uris) {
VClass vclass = vClassDao.getVClassByURI(vclassUri);
Option option = new Option();
option.setValue(vclass.getURI());
option.setBody(vclass.getPickListName());
options.add(option);
if (Objects.equals(selectedUri, vclass.getURI())) {
option.setSelected(true);
}
}
options.sort((o1, o2) -> o1.getBody().compareTo(o2.getBody()));
return options;
}
private static Set<String> getNotDisjointClassUris(WebappDaoFactory wadf, String classUri, VClassDao vClassDao) {
Set<String> allClasses = wadf.getVClassDao()
.getAllVclasses()
.stream()
.map(vclass -> vclass.getURI())
.collect(Collectors.toSet());
Set<String> disjointClasses = new HashSet<>(vClassDao.getDisjointWithClassURIs(classUri));
allClasses.removeAll(disjointClasses);
return allClasses;
}
public static void beanSet(Object newObj, String field, String value) {
beanSet (newObj, field, value, null);
}

View file

@ -87,6 +87,11 @@ public class DataProperty extends Property implements Comparable<DataProperty>,
public String getRangeDatatypeURI() {
return rangeDatatypeURI;
}
@Override
public String getRangeVClassURI() {
return rangeDatatypeURI;
}
public void setRangeDatatypeURI(String rangeDatatypeURI) {
this.rangeDatatypeURI = rangeDatatypeURI;

View file

@ -6,6 +6,8 @@ import static org.apache.jena.rdf.model.ResourceFactory.createResource;
import java.util.Objects;
import org.apache.commons.lang3.StringUtils;
import edu.cornell.mannlib.vitro.webapp.auth.policy.bean.RoleRestrictedProperty;
/**
@ -20,7 +22,9 @@ public class FauxProperty extends BaseResourceBean implements ResourceBean,
private String configUri;
// Must not be null on insert or update. Partial identifier on delete.
private String rangeURI;
private String rangeURI = "";
private String rootRangeURI;
// May be null. Partial identifier on delete.
private String domainURI;
@ -55,7 +59,7 @@ public class FauxProperty extends BaseResourceBean implements ResourceBean,
*/
public FauxProperty(String domainURI, String baseURI, String rangeURI) {
super(Objects.requireNonNull(baseURI, "baseURI may not be null"));
this.rangeURI = rangeURI;
this.setRangeURI(rangeURI);
this.domainURI = domainURI;
}
@ -93,7 +97,11 @@ public class FauxProperty extends BaseResourceBean implements ResourceBean,
}
public void setRangeURI(String rangeURI) {
this.rangeURI = rangeURI;
if (StringUtils.isEmpty(rangeURI)) {
this.rangeURI = "";
} else {
this.rangeURI = rangeURI;
}
}
public String getBaseLabel() {
@ -105,7 +113,14 @@ public class FauxProperty extends BaseResourceBean implements ResourceBean,
}
public String getRangeLabel() {
return (rangeLabel == null) ? localName(rangeURI) : rangeLabel;
if (StringUtils.isEmpty(rangeLabel)) {
if (StringUtils.isEmpty(rangeURI)) {
return "untyped";
}
return localName(rangeURI);
} else {
return rangeLabel;
}
}
public void setRangeLabel(String rangeLabel) {
@ -247,4 +262,12 @@ public class FauxProperty extends BaseResourceBean implements ResourceBean,
public String getRangeVClassURI() {
return getRangeURI();
}
public void setRootRangeUri(String rootRangeUri) {
this.rootRangeURI = rootRangeUri;
}
public String getRootRangeUri() {
return rootRangeURI;
}
}

View file

@ -4,7 +4,6 @@ package edu.cornell.mannlib.vitro.webapp.beans;
import java.beans.XMLEncoder;
import java.text.Collator;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.Iterator;

View file

@ -160,7 +160,7 @@ public class ConfigurationPropertiesSmokeTests implements
String vivoBundle = VIVO_BUNDLE_PREFIX + language + ".properties";
String vitroBundle = VITRO_BUNDLE_PREFIX + language + ".properties";
if (!i18nNames.contains(vivoBundle) && !i18nNames.contains(vitroBundle)) {
ss.warning(this, language + " was found in the value for "
ss.info(this, language + " was found in the value for "
+ PROPERTY_LANGUAGE_SELECTABLE + " but no corresponding "
+ "language file was found.");
}

View file

@ -41,7 +41,7 @@ public class RevisionInfoBean {
new Date(0), Collections.singleton(LevelRevisionInfo.DUMMY_LEVEL));
/** The bean is attached to the session by this name. */
static final String ATTRIBUTE_NAME = RevisionInfoBean.class.getName();
public static final String ATTRIBUTE_NAME = RevisionInfoBean.class.getName();
// ----------------------------------------------------------------------
// static methods

View file

@ -21,7 +21,6 @@ public class Controllers {
public static final String ABOUT = "/about";
public static final String CONTACT_URL = "/comments";
public static final String TERMS_OF_USE_URL = "/termsOfUse";
public static final String SEARCH_URL = "/search";
public static final String ENTITY = "/entity";

View file

@ -57,8 +57,6 @@ public abstract class UserAccountsAddPageStrategy extends UserAccountsPage {
private static class EmailStrategy extends UserAccountsAddPageStrategy {
public static final String CREATE_PASSWORD_URL = "/accounts/createPassword";
private static final String EMAIL_TEMPLATE_WITH_PASSWORD = "userAccounts-acctCreatedEmail.ftl";
private static final String EMAIL_TEMPLATE_NO_PASSWORD = "userAccounts-acctCreatedExternalOnlyEmail.ftl";
private boolean sentEmail;
@ -100,15 +98,19 @@ public abstract class UserAccountsAddPageStrategy extends UserAccountsPage {
body.put("userAccount", page.getAddedAccount());
body.put("passwordLink", buildCreatePasswordLink());
body.put("siteName", getSiteName());
FreemarkerEmailMessage email = FreemarkerEmailFactory
.createNewMessage(vreq);
email.addRecipient(TO, page.getAddedAccount().getEmailAddress());
email.setSubject(i18n.text("account_created_subject", getSiteName()));
String subject = i18n.text("account_created_subject", getSiteName());
email.setSubject(subject);
if (page.isExternalAuthOnly()) {
email.setTemplate(EMAIL_TEMPLATE_NO_PASSWORD);
body.put("subject", subject);
body.put("textMessage", i18n.text("acct_created_external_only_email_plain_text"));
body.put("htmlMessage", i18n.text("acct_created_external_only_email_html_text"));
} else {
email.setTemplate(EMAIL_TEMPLATE_WITH_PASSWORD);
body.put("subject", subject);
body.put("textMessage", i18n.text("acct_created_email_plain_text"));
body.put("htmlMessage", i18n.text("acct_created_email_html_text"));
}
email.setBodyMap(body);
email.processTemplate();

View file

@ -56,8 +56,6 @@ public abstract class UserAccountsEditPageStrategy extends UserAccountsPage {
private static class EmailStrategy extends UserAccountsEditPageStrategy {
private static final String PARAMETER_RESET_PASSWORD = "resetPassword";
private static final String EMAIL_TEMPLATE = "userAccounts-passwordResetPendingEmail.ftl";
public static final String RESET_PASSWORD_URL = "/accounts/resetPassword";
private boolean resetPassword;
@ -107,11 +105,13 @@ public abstract class UserAccountsEditPageStrategy extends UserAccountsPage {
body.put("userAccount", page.getUpdatedAccount());
body.put("passwordLink", buildResetPasswordLink());
body.put("siteName", getSiteName());
body.put("subject", i18n.text("password_reset_pending_email_subject"));
body.put("textMessage",i18n.text("password_reset_pending_email_plain_text"));
body.put("htmlMessage", i18n.text("password_reset_pending_email_html_text"));
FreemarkerEmailMessage email = FreemarkerEmailFactory
.createNewMessage(vreq);
email.addRecipient(TO, page.getUpdatedAccount().getEmailAddress());
email.setTemplate(EMAIL_TEMPLATE);
email.setBodyMap(body);
email.processTemplate();
email.send();

View file

@ -26,8 +26,6 @@ public class UserAccountsCreatePasswordPage extends
.getLog(UserAccountsCreatePasswordPage.class);
private static final String TEMPLATE_NAME = "userAccounts-createPassword.ftl";
private static final String EMAIL_TEMPLATE = "userAccounts-passwordCreatedEmail.ftl";
public UserAccountsCreatePasswordPage(VitroRequest vreq) {
super(vreq);
}
@ -73,8 +71,11 @@ public class UserAccountsCreatePasswordPage extends
FreemarkerEmailMessage email = FreemarkerEmailFactory
.createNewMessage(vreq);
email.addRecipient(TO, userAccount.getEmailAddress());
email.setSubject(i18n.text("password_created_subject", getSiteName()));
email.setTemplate(EMAIL_TEMPLATE);
final String subject = i18n.text("password_created_subject", getSiteName());
email.setSubject(subject);
body.put("subject", subject);
body.put("textMessage", i18n.text("password_created_email_plain_text"));
body.put("htmlMessage", i18n.text("password_created_email_html_text"));
email.setBodyMap(body);
email.processTemplate();
email.send();

View file

@ -52,8 +52,6 @@ public abstract class UserAccountsFirstTimeExternalPageStrategy extends
public static class EmailStrategy extends
UserAccountsFirstTimeExternalPageStrategy {
private static final String EMAIL_TEMPLATE = "userAccounts-firstTimeExternalEmail.ftl";
public EmailStrategy(VitroRequest vreq,
UserAccountsFirstTimeExternalPage page) {
super(vreq, page);
@ -73,8 +71,11 @@ public abstract class UserAccountsFirstTimeExternalPageStrategy extends
FreemarkerEmailMessage email = FreemarkerEmailFactory
.createNewMessage(vreq);
email.addRecipient(TO, ua.getEmailAddress());
email.setSubject(i18n.text("account_created_subject", getSiteName()));
email.setTemplate(EMAIL_TEMPLATE);
final String subject = i18n.text("account_created_subject", getSiteName());
email.setSubject(subject);
body.put("subject", subject);
body.put("textMessage", i18n.text("first_time_external_email_plain_text"));
body.put("htmlMessage", i18n.text("first_time_external_email_html_text"));
email.setBodyMap(body);
email.processTemplate();
email.send();

View file

@ -108,8 +108,6 @@ public abstract class UserAccountsMyAccountPageStrategy extends
private static final String ERROR_WRONG_PASSWORD_LENGTH = "errorPasswordIsWrongLength";
private static final String ERROR_PASSWORDS_DONT_MATCH = "errorPasswordsDontMatch";
private static final String EMAIL_TEMPLATE = "userAccounts-confirmEmailChangedEmail.ftl";
private final String originalEmail;
private String newPassword;
@ -179,8 +177,11 @@ public abstract class UserAccountsMyAccountPageStrategy extends
FreemarkerEmailMessage email = FreemarkerEmailFactory
.createNewMessage(vreq);
email.addRecipient(TO, page.getUserAccount().getEmailAddress());
email.setSubject(i18n.text("email_changed_subject", getSiteName()));
email.setTemplate(EMAIL_TEMPLATE);
final String subject = i18n.text("email_changed_subject", getSiteName());
email.setSubject(subject);
body.put("subject", subject);
body.put("textMessage", i18n.text("confirm_email_changed_email_plain_text"));
body.put("htmlMessage", i18n.text("confirm_email_changed_email_html_text"));
email.setBodyMap(body);
email.processTemplate();
email.send();

View file

@ -26,8 +26,6 @@ public class UserAccountsResetPasswordPage extends UserAccountsPasswordBasePage
private static final String TEMPLATE_NAME = "userAccounts-resetPassword.ftl";
private static final String EMAIL_TEMPLATE = "userAccounts-passwordResetCompleteEmail.ftl";
protected UserAccountsResetPasswordPage(VitroRequest vreq) {
super(vreq);
}
@ -68,14 +66,16 @@ public class UserAccountsResetPasswordPage extends UserAccountsPasswordBasePage
private void notifyUser() {
Map<String, Object> body = new HashMap<String, Object>();
FreemarkerEmailMessage email = FreemarkerEmailFactory.createNewMessage(vreq);
final String subject = i18n.text("password_changed_subject");
email.setSubject(subject);
body.put("userAccount", userAccount);
body.put("siteName", getSiteName());
FreemarkerEmailMessage email = FreemarkerEmailFactory
.createNewMessage(vreq);
body.put("subject", subject);
body.put("textMessage", i18n.text("password_reset_complete_email_plain_text"));
body.put("htmlMessage", i18n.text("password_reset_complete_email_html_text"));
email.addRecipient(TO, userAccount.getEmailAddress());
email.setSubject(i18n.text("password_changed_subject"));
email.setTemplate(EMAIL_TEMPLATE);
email.setBodyMap(body);
email.processTemplate();
email.send();

View file

@ -22,6 +22,7 @@ import edu.cornell.mannlib.vedit.controller.BaseEditController;
import edu.cornell.mannlib.vitro.webapp.auth.permissions.SimplePermission;
import edu.cornell.mannlib.vitro.webapp.beans.ApplicationBean;
import edu.cornell.mannlib.vitro.webapp.beans.DataProperty;
import edu.cornell.mannlib.vitro.webapp.beans.FauxProperty;
import edu.cornell.mannlib.vitro.webapp.beans.Ontology;
import edu.cornell.mannlib.vitro.webapp.beans.PropertyGroup;
import edu.cornell.mannlib.vitro.webapp.beans.VClass;
@ -176,6 +177,11 @@ public class DatapropEditController extends BaseEditController {
assertionsDpDao.getEquivalentPropertyURIs(dp.getURI()), assertionsDpDao);
sortForPickList(eqProps, vreq);
request.setAttribute("equivalentProperties", eqProps);
List<FauxProperty> fauxProps = vreq.getUnfilteredAssertionsWebappDaoFactory().getFauxPropertyDao().
getFauxPropertiesForBaseUri(dp.getURI());
sortForPickList(fauxProps, vreq);
request.setAttribute("fauxproperties", fauxProps);
ApplicationBean appBean = vreq.getAppBean();

View file

@ -32,12 +32,14 @@ import edu.cornell.mannlib.vedit.validator.Validator;
import edu.cornell.mannlib.vedit.validator.impl.RequiredFieldValidator;
import edu.cornell.mannlib.vitro.webapp.auth.permissions.SimplePermission;
import edu.cornell.mannlib.vitro.webapp.auth.policy.bean.PropertyRestrictionListener;
import edu.cornell.mannlib.vitro.webapp.beans.Datatype;
import edu.cornell.mannlib.vitro.webapp.beans.FauxProperty;
import edu.cornell.mannlib.vitro.webapp.beans.ObjectProperty;
import edu.cornell.mannlib.vitro.webapp.beans.Property;
import edu.cornell.mannlib.vitro.webapp.beans.PropertyGroup;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.controller.edit.utils.RoleLevelOptionsSetup;
import edu.cornell.mannlib.vitro.webapp.dao.DataPropertyDao;
import edu.cornell.mannlib.vitro.webapp.dao.FauxPropertyDao;
import edu.cornell.mannlib.vitro.webapp.dao.ObjectPropertyDao;
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
@ -88,6 +90,8 @@ public class FauxPropertyRetryController extends BaseEditController {
}
private static class EpoPopulator {
private static final String LITERAL = "http://www.w3.org/2000/01/rdf-schema#Literal";
private static final String XML_LITERAL = "http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral";
private final VitroRequest req;
private final ServletContext ctx;
private final WebappDaoFactory wadf;
@ -98,6 +102,8 @@ public class FauxPropertyRetryController extends BaseEditController {
private FauxProperty beanForEditing;
private Property baseProperty;
private boolean isFauxDataProperty = false;
EpoPopulator(HttpServletRequest req, EditProcessObject epo) {
this.req = new VitroRequest(req);
@ -127,10 +133,19 @@ public class FauxPropertyRetryController extends BaseEditController {
this.baseProperty = req.getUnfilteredWebappDaoFactory()
.getObjectPropertyDao()
.getObjectPropertyByURI(beanForEditing.getURI());
if (this.baseProperty == null) {
this.baseProperty = req.getUnfilteredWebappDaoFactory()
.getDataPropertyDao()
.getDataPropertyByURI(beanForEditing.getURI());
isFauxDataProperty = true;
}
addCheckboxValuesToTheRequest();
setFieldValidators();
if (!isFauxDataProperty) {
setFieldValidators();
}
setListeners();
setForwarders();
@ -150,8 +165,7 @@ public class FauxPropertyRetryController extends BaseEditController {
return newFauxProperty(baseUri);
}
FauxProperty bean = fpDao.getFauxPropertyByUris(domainUri, baseUri,
rangeUri);
FauxProperty bean = fpDao.getFauxPropertyByUris(domainUri, baseUri, rangeUri);
if (bean == null) {
throw new IllegalArgumentException(
"FauxProperty does not exist for <" + domainUri
@ -168,7 +182,11 @@ public class FauxPropertyRetryController extends BaseEditController {
private FauxProperty newFauxProperty(String baseUri) {
FauxProperty fp = new FauxProperty(null, baseUri, null);
ObjectPropertyDao opDao = wadf.getObjectPropertyDao();
ObjectProperty base = opDao.getObjectPropertyByURI(baseUri);
DataPropertyDao dpDao = wadf.getDataPropertyDao();
Property base = opDao.getObjectPropertyByURI(baseUri);
if (base == null) {
base = dpDao.getDataPropertyByURI(baseUri);
}
fp.setGroupURI(base.getGroupURI());
fp.setRangeURI(base.getRangeVClassURI());
fp.setDomainURI(base.getDomainVClassURI());
@ -270,7 +288,7 @@ public class FauxPropertyRetryController extends BaseEditController {
list.addAll(FormUtils.makeVClassOptionList(wadf,
beanForEditing.getDomainURI()));
} else {
list.addAll(FormUtils.makeOptionListOfSubVClasses(wadf,
list.addAll(FormUtils.makeOptionListOfNotDisjointClasses(wadf,
baseProperty.getDomainVClassURI(),
beanForEditing.getDomainURI()));
}
@ -279,12 +297,20 @@ public class FauxPropertyRetryController extends BaseEditController {
}
private List<Option> buildRangeOptionList() {
if (isFauxDataProperty) {
return buildDataPropOptionList();
} else {
return buildObjectPropOptionList();
}
}
private List<Option> buildObjectPropOptionList() {
List<Option> list = new ArrayList<>();
if (baseProperty.getRangeVClassURI() == null) {
list.addAll(FormUtils.makeVClassOptionList(wadf,
beanForEditing.getRangeURI()));
} else {
list.addAll(FormUtils.makeOptionListOfSubVClasses(wadf,
list.addAll(FormUtils.makeOptionListOfNotDisjointClasses(wadf,
baseProperty.getRangeVClassURI(),
beanForEditing.getRangeURI()));
if (containsVCardKind(list)) {
@ -295,6 +321,43 @@ public class FauxPropertyRetryController extends BaseEditController {
return list;
}
private List<Option> buildDataPropOptionList() {
List<Option> list = new ArrayList<>();
String rangeUri = baseProperty.getRangeVClassURI();
if (rangeUri == null) {
Option option = new Option();
option.setValue("");
option.setBody("Untyped");
option.setSelected(true);
list.add(option);
} else if (rangeUri.equals(LITERAL)) {
Option option = new Option();
option.setValue(rangeUri);
option.setBody("Literal");
option.setSelected(true);
list.add(option);
} else if (rangeUri.equals(XML_LITERAL)) {
Option option = new Option();
option.setValue(rangeUri);
option.setBody("XML Literal");
option.setSelected(true);
list.add(option);
} else {
Datatype dataType = wadf.getDatatypeDao().getDatatypeByURI(rangeUri);
Option option = new Option();
if (dataType != null) {
option.setValue(dataType.getUri());
option.setBody(dataType.getName());
} else {
option.setValue(rangeUri);
option.setBody(rangeUri);
}
option.setSelected(true);
list.add(option);
}
return list;
}
private static final String VCARD_KIND_URI = "http://www.w3.org/2006/vcard/ns#Kind";
private static final String VCARD_NAMESPACE = "http://www.w3.org/2006/vcard/ns#";

View file

@ -8,7 +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.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
@ -41,6 +41,8 @@ import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.Tem
import edu.cornell.mannlib.vitro.webapp.email.FreemarkerEmailFactory;
import edu.cornell.mannlib.vitro.webapp.email.FreemarkerEmailMessage;
import edu.cornell.mannlib.vitro.webapp.freemarker.config.FreemarkerConfiguration;
import edu.cornell.mannlib.vitro.webapp.i18n.I18n;
import edu.cornell.mannlib.vitro.webapp.i18n.I18nBundle;
import edu.cornell.mannlib.vitro.webapp.web.templatemodels.Tags;
import edu.cornell.mannlib.vitro.webapp.web.templatemodels.User;
import edu.cornell.mannlib.vitro.webapp.web.templatemodels.menu.MainMenu;
@ -67,7 +69,6 @@ public class FreemarkerHttpServlet extends VitroHttpServlet {
// error templates
ERROR_DISPLAY("error-display.ftl"),
ERROR_EMAIL("error-email.ftl"),
ERROR_MESSAGE("error-message.ftl"),
STANDARD_ERROR("error-standard.ftl"),
TITLED_ERROR_MESSAGE("error-titled.ftl"),
@ -161,7 +162,8 @@ public class FreemarkerHttpServlet extends VitroHttpServlet {
}
adminErrorData.put("cause", cause);
adminErrorData.put("datetime", new Date());
SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
adminErrorData.put("datetime", dateformat.format(new Date()));
templateMap.put("errorOnHomePage", this instanceof HomePageController);
@ -175,7 +177,11 @@ public class FreemarkerHttpServlet extends VitroHttpServlet {
} else if (FreemarkerEmailFactory.isConfigured(vreq)) {
FreemarkerEmailMessage email = FreemarkerEmailFactory.createNewMessage(vreq);
email.addRecipient(TO, email.getReplyToAddress());
email.setTemplate(Template.ERROR_EMAIL.toString());
I18nBundle i18n = I18n.bundle(vreq);
addSiteName(vreq, adminErrorData);
adminErrorData.put("subject", i18n.text("application_error_email_subject"));
adminErrorData.put("textMessage", i18n.text("application_error_email_plain_text"));
adminErrorData.put("htmlMessage", i18n.text("application_error_email_html_text"));
email.setBodyMap(adminErrorData);
email.processTemplate();
sentEmail = email.send();
@ -193,6 +199,16 @@ public class FreemarkerHttpServlet extends VitroHttpServlet {
}
}
private void addSiteName(VitroRequest vreq, Map<String, Object> adminErrorData) {
try {
ApplicationBean appBean = vreq.getAppBean();
String appName = appBean.getApplicationName();
adminErrorData.put("siteName", appName);
} catch (Exception e) {
log.error(e,e);
}
}
@Override
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {

View file

@ -8,39 +8,40 @@ import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
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;
import edu.cornell.mannlib.vitro.webapp.beans.FauxProperty;
import edu.cornell.mannlib.vitro.webapp.beans.ObjectProperty;
import edu.cornell.mannlib.vitro.webapp.beans.Property;
import edu.cornell.mannlib.vitro.webapp.beans.PropertyGroup;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues;
import edu.cornell.mannlib.vitro.webapp.dao.DataPropertyDao;
import edu.cornell.mannlib.vitro.webapp.dao.FauxPropertyDao;
import edu.cornell.mannlib.vitro.webapp.dao.ObjectPropertyDao;
import edu.cornell.mannlib.vitro.webapp.dao.PropertyGroupDao;
import javax.servlet.annotation.WebServlet;
@WebServlet(name = "ListFauxPropertiesController", urlPatterns = {"/listFauxProperties"} )
@WebServlet(name = "ListFauxPropertiesController", urlPatterns = { "/listFauxProperties" })
public class ListFauxPropertiesController extends FreemarkerHttpServlet {
private static final Log log = LogFactory.getLog(ListFauxPropertiesController.class.getName());
private static final Log log = LogFactory.getLog(ListFauxPropertiesController.class.getName());
private static final String TEMPLATE_NAME = "siteAdmin-fauxPropertiesList.ftl";
private ObjectPropertyDao opDao = null;
private PropertyGroupDao pgDao = null;
private FauxPropertyDao fpDao = null;
private String notFoundMessage = "";
private String notFoundMessage = "";
@Override
protected AuthorizationRequest requiredActions(VitroRequest vreq) {
return SimplePermission.EDIT_ONTOLOGY.ACTION;
}
protected AuthorizationRequest requiredActions(VitroRequest vreq) {
return SimplePermission.EDIT_ONTOLOGY.ACTION;
}
@Override
protected ResponseValues processRequest(VitroRequest vreq) {
@ -50,176 +51,303 @@ public class ListFauxPropertiesController extends FreemarkerHttpServlet {
String displayOption = "";
if ( vreq.getParameter("displayOption") != null ) {
if (vreq.getParameter("displayOption") != null) {
displayOption = vreq.getParameter("displayOption");
}
else {
} else {
displayOption = "listing";
}
body.put("displayOption", displayOption);
if ( displayOption.equals("listing") ) {
if (displayOption.equals("listing")) {
body.put("pageTitle", "Faux Property Listing");
}
else {
} else {
body.put("pageTitle", "Faux Properties by Base Property");
}
List<ObjectProperty> objectProps = getOPDao(vreq).getRootObjectProperties();
List<DataProperty> dataProps = getDPDao(vreq).getRootDataProperties();
Map<String, Object> allFauxProps = new TreeMap<String, Object>();
opDao = vreq.getUnfilteredAssertionsWebappDaoFactory().getObjectPropertyDao();
fpDao = vreq.getUnfilteredAssertionsWebappDaoFactory().getFauxPropertyDao();
pgDao = vreq.getUnfilteredAssertionsWebappDaoFactory().getPropertyGroupDao();
List<ObjectProperty> objectProps = null;
objectProps = opDao.getRootObjectProperties();
Map<String, Object> allFauxProps = new TreeMap<String, Object>();
// get the faux depending on the display option
if ( displayOption.equals("listing") ) {
allFauxProps = getFauxPropertyList(objectProps);
// get the faux depending on the display option
if (displayOption.equals("listing")) {
allFauxProps.putAll(getFauxPropertyList(objectProps, vreq));
allFauxProps.putAll(getFauxDataPropertyList(dataProps, vreq));
} else {
allFauxProps.putAll(getFauxByBaseList(objectProps, vreq));
allFauxProps.putAll(getFauxDataPropsByBaseList(dataProps, vreq));
}
else {
allFauxProps = getFauxByBaseList(objectProps);
}
log.debug(allFauxProps.toString());
log.debug(allFauxProps.toString());
if ( notFoundMessage.length() == 0 ) {
body.put("message", notFoundMessage);
}
else {
body.put("fauxProps", allFauxProps);
}
if (notFoundMessage.length() == 0) {
body.put("message", notFoundMessage);
} else {
body.put("fauxProps", allFauxProps);
}
} catch (Throwable t) {
t.printStackTrace();
log.error(t, t);
}
return new TemplateResponseValues(TEMPLATE_NAME, body);
}
private TreeMap<String, Object> getFauxPropertyList(List<ObjectProperty> objectProps) {
List<FauxProperty> fauxProps = null;
TreeMap<String, Object> theFauxProps = new TreeMap<String, Object>();
if ( objectProps != null ) {
private PropertyGroupDao getPGDao(VitroRequest vreq) {
return vreq.getUnfilteredAssertionsWebappDaoFactory().getPropertyGroupDao();
}
private FauxPropertyDao getFPDao(VitroRequest vreq) {
return vreq.getUnfilteredAssertionsWebappDaoFactory().getFauxPropertyDao();
}
private DataPropertyDao getDPDao(VitroRequest vreq) {
return vreq.getUnfilteredAssertionsWebappDaoFactory().getDataPropertyDao();
}
private ObjectPropertyDao getOPDao(VitroRequest vreq) {
return vreq.getUnfilteredAssertionsWebappDaoFactory().getObjectPropertyDao();
}
private TreeMap<String, Object> getFauxPropertyList(List<ObjectProperty> objectProps, VitroRequest vreq) {
List<FauxProperty> fauxProps = null;
TreeMap<String, Object> theFauxProps = new TreeMap<String, Object>();
if (objectProps != null) {
Iterator<ObjectProperty> opIt = objectProps.iterator();
if ( !opIt.hasNext()) {
if (!opIt.hasNext()) {
notFoundMessage = "No object properties found.";
}
else {
} else {
while (opIt.hasNext()) {
ObjectProperty op = opIt.next();
String baseURI = op.getURI();
fauxProps = fpDao.getFauxPropertiesForBaseUri(baseURI);
if ( fauxProps != null ) {
Iterator<FauxProperty> fpIt = fauxProps.iterator();
if ( !fpIt.hasNext()) {
notFoundMessage = "No faux properties found.";
}
else {
while (fpIt.hasNext()) {
// No point in getting these unless we have a faux property
String baseLabel = getDisplayLabel(op) == null ? "(no name)" : getDisplayLabel(op);
String baseLocalName = op.getLocalNameWithPrefix();
baseLabel = baseLabel.substring(0,baseLabel.indexOf("("));
baseLabel += "(" + baseLocalName + ")";
// get the info we need from the faux property
FauxProperty fp = fpIt.next();
String fauxLabel = fp.getDisplayName();
String rangeLabel = fp.getRangeLabel();
String rangeURI = fp.getRangeURI();
String domainLabel = fp.getDomainLabel();
String domainURI = fp.getDomainURI();
String groupURI = fp.getGroupURI();
// FauxProperty only gets groupURI but we want the label
PropertyGroup pGroup = pgDao.getGroupByURI(groupURI);
String groupLabel = ( pGroup == null ) ? "unspecified" : pGroup.getName();
// store all the strings in a hash with the faux property label as the key
Map<String, Object> tmpHash = new HashMap<String, Object>();
tmpHash.put("base", baseLabel);
tmpHash.put("baseURI", baseURI);
tmpHash.put("group", groupLabel);
tmpHash.put("range", rangeLabel);
tmpHash.put("rangeURI", rangeURI);
tmpHash.put("domain", domainLabel);
tmpHash.put("domainURI", domainURI);
// add the faux and its details to the treemap
theFauxProps.put(fauxLabel + "@@" + domainLabel, tmpHash);
}
}
}
}
String baseURI = op.getURI();
fauxProps = getFPDao(vreq).getFauxPropertiesForBaseUri(baseURI);
if (fauxProps != null) {
Iterator<FauxProperty> fpIt = fauxProps.iterator();
if (!fpIt.hasNext()) {
notFoundMessage = "No faux properties found.";
} else {
while (fpIt.hasNext()) {
// No point in getting these unless we have a
// faux property
String baseLabel = getBaseLabel(op, false);
// get the info we need from the faux property
FauxProperty fp = fpIt.next();
String fauxLabel = fp.getDisplayName();
String rangeLabel = fp.getRangeLabel();
String rangeURI = fp.getRangeURI();
String domainLabel = fp.getDomainLabel();
String domainURI = fp.getDomainURI();
String groupURI = fp.getGroupURI();
// FauxProperty only gets groupURI but we want
// the label
PropertyGroup pGroup = getPGDao(vreq).getGroupByURI(groupURI);
String groupLabel = (pGroup == null) ? "unspecified" : pGroup.getName();
// store all the strings in a hash with the faux
// property label as the key
Map<String, Object> tmpHash = new HashMap<String, Object>();
tmpHash.put("base", baseLabel);
tmpHash.put("baseURI", baseURI);
tmpHash.put("group", groupLabel);
tmpHash.put("range", rangeLabel);
tmpHash.put("rangeURI", rangeURI);
tmpHash.put("domain", domainLabel);
tmpHash.put("domainURI", domainURI);
tmpHash.put("editUrl", "propertyEdit");
// add the faux and its details to the treemap
theFauxProps.put(fauxLabel + "@@" + domainLabel, tmpHash);
}
}
}
}
}
}
return theFauxProps;
}
}
private TreeMap<String, Object> getFauxByBaseList(List<ObjectProperty> objectProps) {
List<FauxProperty> fauxProps = null;
TreeMap<String, Object> fauxByBaseProps = new TreeMap<String, Object>();
if ( objectProps != null ) {
private TreeMap<String, Object> getFauxByBaseList(List<ObjectProperty> objectProps, VitroRequest vreq) {
List<FauxProperty> fauxProps = null;
TreeMap<String, Object> fauxByBaseProps = new TreeMap<String, Object>();
if (objectProps != null) {
Iterator<ObjectProperty> opIt = objectProps.iterator();
if ( !opIt.hasNext()) {
if (!opIt.hasNext()) {
notFoundMessage = "No object properties found.";
}
else {
} else {
while (opIt.hasNext()) {
TreeMap<String, Object> fauxForGivenBase = new TreeMap<String, Object>();
TreeMap<String, Object> fauxForGivenBase = new TreeMap<String, Object>();
ObjectProperty op = opIt.next();
String baseURI = op.getURI();
fauxProps = fpDao.getFauxPropertiesForBaseUri(baseURI);
String baseURI = op.getURI();
fauxProps = getFPDao(vreq).getFauxPropertiesForBaseUri(baseURI);
if ( fauxProps != null ) {
Iterator<FauxProperty> fpIt = fauxProps.iterator();
if ( !fpIt.hasNext()) {
notFoundMessage = "No faux properties found.";
}
else {
String baseLabel = getDisplayLabel(op) == null ? "(no name)" : getDisplayLabel(op);
String baseLocalName = op.getLocalNameWithPrefix();
baseLabel = baseLabel.substring(0,baseLabel.indexOf("("));
baseLabel += "(" + baseLocalName + ")" + "|" + baseURI;
while (fpIt.hasNext()) {
// get the info we need from the faux property
FauxProperty fp = fpIt.next();
String fauxLabel = fp.getDisplayName();
String rangeLabel = fp.getRangeLabel();
String rangeURI = fp.getRangeURI();
String domainLabel = fp.getDomainLabel();
String domainURI = fp.getDomainURI();
String groupURI = fp.getGroupURI();
// FauxProperty only gets groupURI but we want the label
PropertyGroup pGroup = pgDao.getGroupByURI(groupURI);
String groupLabel = ( pGroup == null ) ? "unspecified" : pGroup.getName();
// store all the strings in a hash with the faux property label as the key
Map<String, Object> tmpHash = new HashMap<String, Object>();
tmpHash.put("baseURI", baseURI);
tmpHash.put("group", groupLabel);
tmpHash.put("range", rangeLabel);
tmpHash.put("rangeURI", rangeURI);
tmpHash.put("domain", domainLabel);
tmpHash.put("domainURI", domainURI);
// add the faux and its details to the treemap
fauxForGivenBase.put(fauxLabel + "@@" + domainLabel, tmpHash);
}
fauxByBaseProps.put(baseLabel, fauxForGivenBase);
}
}
}
if (fauxProps != null) {
Iterator<FauxProperty> fpIt = fauxProps.iterator();
if (!fpIt.hasNext()) {
notFoundMessage = "No faux properties found.";
} else {
String baseLabel = getBaseLabel(op, true);
while (fpIt.hasNext()) {
// get the info we need from the faux property
FauxProperty fp = fpIt.next();
String fauxLabel = fp.getDisplayName();
String rangeLabel = fp.getRangeLabel();
String rangeURI = fp.getRangeURI();
String domainLabel = fp.getDomainLabel();
String domainURI = fp.getDomainURI();
String groupURI = fp.getGroupURI();
// FauxProperty only gets groupURI but we want
// the label
PropertyGroup pGroup = getPGDao(vreq).getGroupByURI(groupURI);
String groupLabel = (pGroup == null) ? "unspecified" : pGroup.getName();
// store all the strings in a hash with the faux
// property label as the key
Map<String, Object> tmpHash = new HashMap<String, Object>();
tmpHash.put("baseURI", baseURI);
tmpHash.put("group", groupLabel);
tmpHash.put("range", rangeLabel);
tmpHash.put("rangeURI", rangeURI);
tmpHash.put("domain", domainLabel);
tmpHash.put("domainURI", domainURI);
// add the faux and its details to the treemap
fauxForGivenBase.put(fauxLabel + "@@" + domainLabel, tmpHash);
fauxForGivenBase.put("editUrl", "propertyEdit");
}
fauxByBaseProps.put(baseLabel, fauxForGivenBase);
}
}
}
}
}
return fauxByBaseProps;
}
}
/*
* should never be null
*/
public static String getDisplayLabel(ObjectProperty op) {
String displayLabel = op.getPickListName();
displayLabel = (displayLabel != null && displayLabel.length() > 0)
? displayLabel
: op.getLocalName();
return (displayLabel != null) ? displayLabel : "[object property]" ;
private TreeMap<String, Object> getFauxDataPropertyList(List<DataProperty> dataProps, VitroRequest vreq) {
List<FauxProperty> fauxProps = null;
TreeMap<String, Object> theFauxProps = new TreeMap<String, Object>();
if (dataProps != null) {
Iterator<DataProperty> opIt = dataProps.iterator();
if (!opIt.hasNext()) {
notFoundMessage = "No data properties found.";
} else {
while (opIt.hasNext()) {
DataProperty dp = opIt.next();
String baseURI = dp.getURI();
fauxProps = getFPDao(vreq).getFauxPropertiesForBaseUri(baseURI);
if (fauxProps != null) {
Iterator<FauxProperty> fpIt = fauxProps.iterator();
if (!fpIt.hasNext()) {
notFoundMessage = "No faux properties found.";
} else {
while (fpIt.hasNext()) {
// No point in getting these unless we have a
// faux property
String baseLabel = getBaseLabel(dp, false);
// get the info we need from the faux property
FauxProperty fp = fpIt.next();
String fauxLabel = fp.getDisplayName();
String rangeLabel = fp.getRangeLabel();
String rangeURI = fp.getRangeURI();
String domainLabel = fp.getDomainLabel();
String domainURI = fp.getDomainURI();
String groupURI = fp.getGroupURI();
// FauxProperty only gets groupURI but we want
// the label
PropertyGroup pGroup = getPGDao(vreq).getGroupByURI(groupURI);
String groupLabel = (pGroup == null) ? "unspecified" : pGroup.getName();
// store all the strings in a hash with the faux
// property label as the key
Map<String, Object> tmpHash = new HashMap<String, Object>();
tmpHash.put("base", baseLabel);
tmpHash.put("baseURI", baseURI);
tmpHash.put("group", groupLabel);
tmpHash.put("range", rangeLabel);
tmpHash.put("rangeURI", rangeURI);
tmpHash.put("domain", domainLabel);
tmpHash.put("domainURI", domainURI);
tmpHash.put("editUrl", "datapropEdit");
// add the faux and its details to the treemap
theFauxProps.put(fauxLabel + "@@" + domainLabel, tmpHash);
}
}
}
}
}
}
return theFauxProps;
}
private TreeMap<String, Object> getFauxDataPropsByBaseList(List<DataProperty> dataProps, VitroRequest vreq) {
List<FauxProperty> fauxProps = null;
TreeMap<String, Object> fauxByBaseProps = new TreeMap<String, Object>();
if (dataProps != null) {
Iterator<DataProperty> opIt = dataProps.iterator();
if (!opIt.hasNext()) {
notFoundMessage = "No data properties found.";
} else {
while (opIt.hasNext()) {
TreeMap<String, Object> fauxForGivenBase = new TreeMap<String, Object>();
DataProperty dp = opIt.next();
String baseURI = dp.getURI();
fauxProps = getFPDao(vreq).getFauxPropertiesForBaseUri(baseURI);
if (fauxProps != null) {
Iterator<FauxProperty> fpIt = fauxProps.iterator();
if (!fpIt.hasNext()) {
notFoundMessage = "No faux properties found.";
} else {
String baseLabel = getBaseLabel(dp, true);
while (fpIt.hasNext()) {
// get the info we need from the faux property
FauxProperty fp = fpIt.next();
String fauxLabel = fp.getDisplayName();
String rangeLabel = fp.getRangeLabel();
String rangeURI = fp.getRangeURI();
String domainLabel = fp.getDomainLabel();
String domainURI = fp.getDomainURI();
String groupURI = fp.getGroupURI();
// FauxProperty only gets groupURI but we want
// the label
PropertyGroup pGroup = getPGDao(vreq).getGroupByURI(groupURI);
String groupLabel = (pGroup == null) ? "unspecified" : pGroup.getName();
// store all the strings in a hash with the faux
// property label as the key
Map<String, Object> tmpHash = new HashMap<String, Object>();
tmpHash.put("baseURI", baseURI);
tmpHash.put("group", groupLabel);
tmpHash.put("range", rangeLabel);
tmpHash.put("rangeURI", rangeURI);
tmpHash.put("domain", domainLabel);
tmpHash.put("domainURI", domainURI);
// add the faux and its details to the treemap
fauxForGivenBase.put(fauxLabel + "@@" + domainLabel, tmpHash);
fauxForGivenBase.put("editUrl", "datapropEdit");
}
fauxByBaseProps.put(baseLabel, fauxForGivenBase);
}
}
}
}
}
return fauxByBaseProps;
}
private String getBaseLabel(Property property, boolean addUri) {
String baseLabel = property.getPickListName();
if (StringUtils.isEmpty(baseLabel)) {
baseLabel = property.getLocalName();
}
if (StringUtils.isEmpty(baseLabel)) {
baseLabel = "[property]";
}
String baseLocalName = property.getLocalNameWithPrefix();
int indexOf = baseLabel.indexOf("(");
if (indexOf > 0) {
baseLabel = baseLabel.substring(0, indexOf);
}
baseLabel += "(" + baseLocalName + ")";
if (addUri) {
baseLabel += "|" + property.getURI();
}
return baseLabel;
}
}

View file

@ -1,49 +0,0 @@
/* $This file is distributed under the terms of the license in LICENSE$ */
package edu.cornell.mannlib.vitro.webapp.controller.freemarker;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vitro.webapp.beans.ApplicationBean;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues;
import javax.servlet.annotation.WebServlet;
@WebServlet(name = "TermsOfUseController", urlPatterns = {"/termsOfUse"} )
public class TermsOfUseController extends FreemarkerHttpServlet {
private static final long serialVersionUID = 1L;
private static final Log log = LogFactory.getLog(TermsOfUseController.class);
private static final String TEMPLATE_DEFAULT = "termsOfUse.ftl";
@Override
protected ResponseValues processRequest(VitroRequest vreq) {
Map<String, Object> map = new HashMap<String, Object>();
Map<String, String> termsOfUse = new HashMap<String, String>();
ApplicationBean appBean = vreq.getAppBean();
termsOfUse.put("siteName", appBean.getApplicationName());
String siteHost = appBean.getCopyrightAnchor();
if (siteHost == null) {
siteHost = "the hosting institution";
}
termsOfUse.put("siteHost", siteHost);
map.put("termsOfUse", termsOfUse);
return new TemplateResponseValues(TEMPLATE_DEFAULT, map);
}
@Override
protected String getTitle(String siteName, VitroRequest vreq) {
return siteName + " Terms of Use";
}
}

View file

@ -170,7 +170,7 @@ public class ViewLabelsServlet extends FreemarkerHttpServlet{
Locale currentLocale) throws FileNotFoundException {
HashMap<String, String> map = new HashMap<String, String>();
//Replacing the underscore with a hyphen because that is what is represented in the actual literals
map.put("code", locale.toString().replace("_", "-"));
map.put("code", locale.toLanguageTag().replace("_", "-"));
map.put("label", locale.getDisplayName(currentLocale));
return map;
}

View file

@ -14,6 +14,7 @@ import java.util.List;
import java.util.Random;
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.ontology.ObjectProperty;
@ -152,20 +153,22 @@ public class FauxPropertyDaoJena extends JenaBaseDao implements FauxPropertyDao
Collection<String> rangeUris = getPropertyResourceURIValues(
context, QUALIFIED_BY_RANGE);
if (rangeUris.isEmpty()) {
log.debug("'" + contextUri + "' has no value for '"
+ QUALIFIED_BY_RANGE + "'");
return null;
String rangeUri = null;
if (!rangeUris.isEmpty()) {
rangeUri = rangeUris.iterator().next();
}
String rangeUri = rangeUris.iterator().next();
// domainURI is optional.
Collection<String> domainUris = getPropertyResourceURIValues(
context, QUALIFIED_BY_DOMAIN);
String domainUri = domainUris.isEmpty() ? null : domainUris
.iterator().next();
Collection<String> rootRangeUris = getPropertyResourceURIValues(context, QUALIFIED_BY_ROOT);
FauxProperty fp = new FauxProperty(domainUri, baseUri, rangeUri);
if (!rootRangeUris.isEmpty()) {
fp.setRootRangeUri(rootRangeUris.iterator().next());
}
fp.setContextUri(contextUri);
populateInstance(fp);
log.debug("Loaded FauxProperty: " + fp);
@ -214,7 +217,7 @@ public class FauxPropertyDaoJena extends JenaBaseDao implements FauxPropertyDao
addPropertyResourceValue(context, RDF.type, CONFIG_CONTEXT);
addPropertyResourceURIValue(context, CONFIG_CONTEXT_FOR,
fp.getBaseURI());
addPropertyResourceURIValue(context, QUALIFIED_BY_RANGE,
addPropertyResourceURINotEmpty(context, QUALIFIED_BY_RANGE,
fp.getRangeURI());
addPropertyResourceURINotEmpty(context, QUALIFIED_BY_DOMAIN,
fp.getDomainURI());
@ -493,31 +496,22 @@ public class FauxPropertyDaoJena extends JenaBaseDao implements FauxPropertyDao
// ConfigContext
// ----------------------------------------------------------------------
private static final String QUERY_LOCATE_CONFIG_CONTEXT_WITH_DOMAIN = "" //
+ "PREFIX : <http://vitro.mannlib.cornell.edu/ns/vitro/ApplicationConfiguration#> \n" //
+ "\n" //
+ "SELECT DISTINCT ?context ?config \n" //
+ "WHERE { \n" //
+ " ?context a :ConfigContext ; \n" //
+ " :configContextFor ?baseUri ; \n" //
+ " :qualifiedByDomain ?domainUri ; \n" //
+ " :qualifiedBy ?rangeUri ; \n" //
+ " :hasConfiguration ?config . \n" //
+ "} \n"; //
private static String queryLocateConfigContext(boolean hasDomain, boolean hasRange) {
return "PREFIX : <http://vitro.mannlib.cornell.edu/ns/vitro/ApplicationConfiguration#> \n"
+ "SELECT DISTINCT ?context ?config \n"
+ "WHERE { \n"
+ " ?context a :ConfigContext . \n"
+ " ?context :configContextFor ?baseUri . \n"
+ ( hasDomain ? "" : " FILTER NOT EXISTS { \n " )
+ " ?context :qualifiedByDomain ?domainUri . \n"
+ ( hasDomain ? "" : "} \n" )
+ ( hasRange ? "" : " FILTER NOT EXISTS { \n " )
+ " ?context :qualifiedBy ?rangeUri . \n"
+ ( hasRange ? "" : "} \n" )
+ " ?context :hasConfiguration ?config . \n"
+ "} \n";
private static final String QUERY_LOCATE_CONFIG_CONTEXT_WITH_NO_DOMAIN = "" //
+ "PREFIX : <http://vitro.mannlib.cornell.edu/ns/vitro/ApplicationConfiguration#> \n" //
+ "\n" //
+ "SELECT DISTINCT ?context ?config \n" //
+ "WHERE { \n" //
+ " ?context a :ConfigContext ; \n" //
+ " :configContextFor ?baseUri ; \n" //
+ " :qualifiedBy ?rangeUri ; \n" //
+ " :hasConfiguration ?config . \n" //
+ " FILTER NOT EXISTS { \n" //
+ " ?context :qualifiedByDomain ?domainUri \n" //
+ " } \n" //
+ "} \n"; //
}
private static class ParserLocateConfigContext extends
ResultSetParser<Set<ConfigContext>> {
@ -556,22 +550,16 @@ public class FauxPropertyDaoJena extends JenaBaseDao implements FauxPropertyDao
private static class ConfigContext {
public static Set<ConfigContext> findByQualifiers(
LockableOntModel lockableDisplayModel, String domainUri,
String baseUri, String rangeUri) {
LockableOntModel lockableDisplayModel, String domainUri, String baseUri, String rangeUri) {
try (LockedOntModel displayModel = lockableDisplayModel.read()) {
QueryHolder qHolder;
if (domainUri == null || domainUri.trim().isEmpty()
|| domainUri.equals(OWL.Thing.getURI())) {
qHolder = queryHolder(
QUERY_LOCATE_CONFIG_CONTEXT_WITH_NO_DOMAIN)
.bindToUri("baseUri", baseUri).bindToUri(
"rangeUri", rangeUri);
} else {
qHolder = queryHolder(
QUERY_LOCATE_CONFIG_CONTEXT_WITH_DOMAIN)
.bindToUri("baseUri", baseUri)
.bindToUri("rangeUri", rangeUri)
.bindToUri("domainUri", domainUri);
boolean hasDomain = !StringUtils.isEmpty(domainUri) && !domainUri.equals(OWL.Thing.getURI());
boolean hasRange = !StringUtils.isEmpty(rangeUri);
QueryHolder qHolder = queryHolder(queryLocateConfigContext(hasDomain, hasRange)).bindToUri("baseUri", baseUri);
if (hasDomain) {
qHolder = qHolder.bindToUri("domainUri", domainUri);
}
if (hasRange) {
qHolder = qHolder.bindToUri("rangeUri", rangeUri);
}
if (log.isDebugEnabled()) {
log.debug("domainUri=" + domainUri + ", baseUri=" + baseUri

View file

@ -813,7 +813,9 @@ public class PropertyDaoJena extends JenaBaseDao implements PropertyDao {
List<ObjectProperty> stragglers = getAdditionalFauxSubpropertiesForVClasses(
vclasses, propInsts);
for (ObjectProperty op : stragglers) {
propInsts.add(makePropInst(op));
if (op != null) {
propInsts.add(makePropInst(op));
}
}
return propInsts;

View file

@ -264,6 +264,7 @@ public class VClassDaoJena extends JenaBaseDao implements VClassDao {
} catch (ProfileException pe) {
// Current language profile does not support disjointWith axioms.
// We'd prefer to return an empty list instead of throwing an exception.
log.error(pe, pe);
} finally {
getOntModel().leaveCriticalSection();
}

View file

@ -50,6 +50,7 @@ public class ProcessRdfForm {
private EditN3GeneratorVTwo populator;
private Map<String,String> urisForNewResources = null;
private static final String langStringDatatypeUri = RDF.dtLangString.getURI();
// private VitroRequest _vreq;
/**
* Construct the ProcessRdfForm object.
@ -368,7 +369,8 @@ public class ProcessRdfForm {
if (obj.isLiteral()) {
Literal lit = obj.asLiteral();
String lang = lit.getLanguage();
if (! linguisticContext.equals(lang)) {
if (langStringDatatypeUri.equals(lit.getDatatypeURI()) &&
! linguisticContext.equals(lang)) {
//UQAM Remove if linguisticContext != lang of the Literal
model.remove(subj, pred, obj);
}

View file

@ -38,11 +38,6 @@ public class ChildVClassesWithParent implements FieldOptions {
return this;
}
/*
* UQAM-Linguistic-Management
* This method is polymorphism of getOptions(EditConfigurationVTwo editConfig,String fieldName, WebappDaoFactory wDaoFact)
* for the internationalization of word "other" in the scroling list of personHasAdvisorRelationship.ftl
*/
public Map<String, String> getOptions(
EditConfigurationVTwo editConfig,
String fieldName,
@ -53,16 +48,17 @@ public class ChildVClassesWithParent implements FieldOptions {
if ( ! StringUtils.isEmpty( defaultOptionLabel ) ){
optionsMap.put(LEFT_BLANK, defaultOptionLabel);
}
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();
VClass rdfClass = vclassDao.getVClassByURI(classUri);
if (rdfClass != null && !OWL.Nothing.getURI().equals(classUri)) {
optionsMap.put(classUri, rdfClass.getName().trim());
}
List<String> subClassList = vclassDao.getAllSubClassURIs(classUri);
if (subClassList != null && subClassList.size() > 0) {
for (String subClassUri : subClassList) {
VClass subClass = vclassDao.getVClassByURI(subClassUri);
if (subClass != null && !OWL.Nothing.getURI().equals(subClassUri)) {
optionsMap.put(subClassUri, subClass.getName().trim());
rdfClass = vclassDao.getVClassByURI(subClassUri);
if (rdfClass != null && !OWL.Nothing.getURI().equals(subClassUri)) {
optionsMap.put(subClassUri, rdfClass.getName().trim());
}
}
}
@ -72,5 +68,5 @@ public class ChildVClassesWithParent implements FieldOptions {
public Comparator<String[]> getCustomComparator() {
return null;
}
}

View file

@ -464,7 +464,7 @@ public class ManageLabelsForIndividualGenerator extends BaseEditConfigurationGen
Locale currentLocale) throws FileNotFoundException {
HashMap<String, String> map = new HashMap<String, String>();
//Replacing the underscore with a hyphen because that is what is represented in the actual literals
map.put("code", locale.toString().replace("_", "-"));
map.put("code", locale.toLanguageTag().replace("_", "-"));
map.put("label", locale.getDisplayName(currentLocale));
return map;
}

View file

@ -24,24 +24,19 @@ import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.web.directives.EmailDirective;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
/**
* A framework that makes it simpler to send email messages with a body built
* from a Freemarker template.
*
* The template must call the @email directive, which may provide the subject
* line, the HTML content, and the plain text content. If these values are not
* provided by the directive, they default to empty strings, or to values that
* were set by the controller.
*
* @see EmailDirective
*/
public class FreemarkerEmailMessage {
private static final Log log = LogFactory
@ -56,7 +51,6 @@ public class FreemarkerEmailMessage {
private InternetAddress fromAddress = null;
private String subject = "";
private String templateName = "";
private String htmlContent = "";
private String textContent = "";
private Map<String, Object> bodyMap = Collections.emptyMap();
@ -124,10 +118,6 @@ public class FreemarkerEmailMessage {
this.textContent = nonNull(textContent, "");
}
public void setTemplate(String templateName) {
this.templateName = nonNull(templateName, "");
}
public void setBodyMap(Map<String, Object> body) {
if (body == null) {
this.bodyMap = Collections.emptyMap();
@ -137,16 +127,52 @@ public class FreemarkerEmailMessage {
}
public void processTemplate() {
bodyMap.put("email", new EmailDirective(this));
try {
config.getTemplate(templateName).process(bodyMap,
new StringWriter());
addDefaultBodyMapValues();
StringWriter writer = new StringWriter();
new Template(null, getInlineVariable("subject"), config).process(bodyMap, writer);
subject = writer.toString();
writer.getBuffer().setLength(0);
new Template(null, getEmailTemplate(), config).process(bodyMap, writer);
htmlContent = writer.toString();
writer.getBuffer().setLength(0);
new Template(null, getInlineVariable("textMessage"), config).process(bodyMap, writer);
textContent = writer.toString();
} catch (TemplateException | IOException e) {
log.error(e, e);
}
}
private void addDefaultBodyMapValues() {
if (!bodyMap.containsKey("subject")) {
if (StringUtils.isBlank(subject)) {
bodyMap.put("subject", "No subject defined");
}
bodyMap.put("subject", subject);
}
if (!bodyMap.containsKey("textMessage")) {
bodyMap.put("textMessage", "No text message defined");
}
if (!bodyMap.containsKey("htmlMessage")) {
bodyMap.put("htmlMessage", "No html message defined");
}
}
private String getInlineVariable(String name) {
return "<@" + name + "?interpret />";
}
private String getEmailTemplate() {
return "<html>\n"
+ " <head>\n"
+ " <title><@subject?interpret /></title>\n"
+ " </head>\n"
+ " <body>\n"
+ " <@htmlMessage?interpret />\n"
+ " </body>\n"
+ "</html>";
}
public boolean send() {
try {
MimeMessage msg = new MimeMessage(mailSession);
@ -182,8 +208,7 @@ public class FreemarkerEmailMessage {
}
msg.setSentDate(new Date());
Transport.send(msg);
sendMessage(msg);
return true;
} catch (MessagingException e) {
log.error("Failed to send message.", e);
@ -191,6 +216,19 @@ public class FreemarkerEmailMessage {
}
}
private void sendMessage(MimeMessage msg) {
Thread thread = new Thread() {
public void run() {
try {
Transport.send(msg);
} catch (MessagingException e) {
log.error(e, e);
}
}
};
thread.start();
}
private void addBodyPart(MimeMultipart content, String textBody, String type)
throws MessagingException {
MimeBodyPart bodyPart = new MimeBodyPart();

View file

@ -284,7 +284,7 @@ public class CachingResponseFilter implements Filter {
StringBuilder buffer = new StringBuilder("\"").append(rawEtag);
for (Locale locale : locales) {
buffer.append(locale.toString());
buffer.append(locale.toLanguageTag());
}
buffer.append("\"");

View file

@ -2,16 +2,10 @@
package edu.cornell.mannlib.vitro.webapp.i18n;
import java.io.IOException;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.Collections;
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;
import java.util.concurrent.atomic.AtomicReference;
import javax.servlet.ServletContext;
@ -39,8 +33,6 @@ import edu.cornell.mannlib.vitro.webapp.utils.developer.Key;
public class I18n {
private static final Log log = LogFactory.getLog(I18n.class);
public static final String DEFAULT_BUNDLE_NAME = "all";
/**
* If this attribute is present on the request, then the cache has already
* been cleared.
@ -73,14 +65,6 @@ public class I18n {
I18n.instance = new I18n(ctx);
}
/**
* A convenience method to get a bundle and format the text.
*/
public static String text(String bundleName, HttpServletRequest req,
String key, Object... parameters) {
return bundle(bundleName, req).text(key, parameters);
}
/**
* A convenience method to get the default bundle and format the text.
*/
@ -89,25 +73,18 @@ public class I18n {
return bundle(req).text(key, parameters);
}
/**
* Get a request I18nBundle by this name.
*/
public static I18nBundle bundle(String bundleName, HttpServletRequest req) {
return instance.getBundle(bundleName, req);
}
/**
* Get the default request I18nBundle.
*/
public static I18nBundle bundle(HttpServletRequest req) {
return instance.getBundle(DEFAULT_BUNDLE_NAME, req);
return instance.getBundle(req);
}
/**
* Get the default context I18nBundle for preferred locales.
*/
public static I18nBundle bundle(List<Locale> preferredLocales) {
return instance.getBundle(DEFAULT_BUNDLE_NAME, preferredLocales);
return instance.getBundle(preferredLocales);
}
// ----------------------------------------------------------------------
@ -130,15 +107,11 @@ public class I18n {
*
* Declared 'protected' so it can be overridden in unit tests.
*/
protected I18nBundle getBundle(String bundleName, HttpServletRequest req) {
log.debug("Getting request bundle '" + bundleName + "'");
protected I18nBundle getBundle(HttpServletRequest req) {
checkDevelopmentMode(req);
checkForChangeInThemeDirectory(req);
Locale locale = req.getLocale();
return getBundle(bundleName, locale);
return new I18nSemanticBundle(Collections.singletonList(locale));
}
/**
@ -154,38 +127,11 @@ public class I18n {
*
* Declared 'protected' so it can be overridden in unit tests.
*/
protected I18nBundle getBundle(String bundleName, List<Locale> preferredLocales) {
log.debug("Getting context bundle '" + bundleName + "'");
protected I18nBundle getBundle( List<Locale> preferredLocales) {
checkDevelopmentMode();
checkForChangeInThemeDirectory(ctx);
Locale locale = SelectedLocale.getPreferredLocale(ctx, preferredLocales);
return getBundle(bundleName, locale);
}
/**
* Get an I18nBundle by this name, context, and locale.
*/
private I18nBundle getBundle(String bundleName, Locale locale) {
I18nLogger i18nLogger = new I18nLogger();
try {
String dir = themeDirectory.get();
ResourceBundle.Control control = new ThemeBasedControl(ctx, dir);
ResourceBundle rb = ResourceBundle.getBundle(bundleName,
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);
}
return new I18nSemanticBundle(Collections.singletonList(locale));
}
/**
@ -204,7 +150,7 @@ public class I18n {
private void checkDevelopmentMode() {
if (DeveloperSettings.getInstance().getBoolean(Key.I18N_DEFEAT_CACHE)) {
log.debug("In development mode - clearing the cache.");
ResourceBundle.clearCache();
clearCache();
}
}
@ -241,158 +187,24 @@ public class I18n {
if (!currentDir.equals(previousDir)) {
log.debug("Theme directory changed from '" + previousDir + "' to '"
+ currentDir + "' - clearing the cache.");
ResourceBundle.clearCache();
clearCache();
}
}
}
private void clearCache() {
TranslationProvider.getInstance().clearCache();
}
/** Only clear the cache one time per request. */
private void clearCacheOnRequest(HttpServletRequest req) {
if (req.getAttribute(ATTRIBUTE_CACHE_CLEARED) != null) {
log.debug("Cache was already cleared on this request.");
} else {
ResourceBundle.clearCache();
clearCache();
log.debug("Cache cleared.");
req.setAttribute(ATTRIBUTE_CACHE_CLEARED, Boolean.TRUE);
}
}
// ----------------------------------------------------------------------
// Control classes for instantiating ResourceBundles
// ----------------------------------------------------------------------
/**
* Instead of looking in the classpath, look in the theme i18n directory and
* the application i18n directory.
*/
static class ThemeBasedControl extends ResourceBundle.Control {
private static final String BUNDLE_DIRECTORY = "i18n/";
private final ServletContext ctx;
private final String themeDirectory;
public ThemeBasedControl(ServletContext ctx, String themeDirectory) {
this.ctx = ctx;
this.themeDirectory = themeDirectory;
}
/**
* Don't look for classes to satisfy the request, just property files.
*/
@Override
public List<String> getFormats(String baseName) {
return FORMAT_PROPERTIES;
}
/**
* Don't look in the class path, look in the current servlet context, in
* the bundle directory under the theme directory and in the bundle
* directory under the application directory.
*/
@Override
public ResourceBundle newBundle(String baseName, Locale locale,
String format, ClassLoader loader, boolean reload)
throws IllegalAccessException, InstantiationException,
IOException {
checkArguments(baseName, locale, format);
log.debug("Creating bundle for '" + baseName + "', " + locale
+ ", '" + format + "', " + reload);
String bundleName = toBundleName(baseName, locale);
if (bundleName == null) {
throw new NullPointerException("bundleName may not be null.");
}
String themeI18nPath = "/" + themeDirectory + BUNDLE_DIRECTORY;
String appI18nPath = "/" + BUNDLE_DIRECTORY;
log.debug("Paths are '" + themeI18nPath + "' and '" + appI18nPath
+ "'");
return VitroResourceBundle.getBundle(bundleName, ctx, appI18nPath,
themeI18nPath, this);
}
/**
* When creating the chain of acceptable Locales, include approximate
* matches before giving up and using the root Locale.
*
* Check the list of supported Locales to see if any have the same
* language but different region. If we find any, sort them and insert
* them into the usual result list, just before the root Locale.
*/
@Override
public List<Locale> getCandidateLocales(String baseName, Locale locale) {
// Find the list of Locales that would normally be returned.
List<Locale> usualList = super
.getCandidateLocales(baseName, locale);
// If our "selectable locales" include no approximate matches that
// are not already in the list, we're done.
SortedSet<Locale> approximateMatches = findApproximateMatches(locale);
approximateMatches.removeAll(usualList);
if (approximateMatches.isEmpty()) {
return usualList;
}
// Otherwise, insert those approximate matches into the list just
// before the ROOT locale.
List<Locale> mergedList = new LinkedList<>(usualList);
int rootLocaleHere = mergedList.indexOf(Locale.ROOT);
if (rootLocaleHere == -1) {
mergedList.addAll(approximateMatches);
} else {
mergedList.addAll(rootLocaleHere, approximateMatches);
}
return mergedList;
}
private SortedSet<Locale> findApproximateMatches(Locale locale) {
SortedSet<Locale> set = new TreeSet<>(new LocaleComparator());
for (Locale l : SelectedLocale.getSelectableLocales(ctx)) {
if (locale.getLanguage().equals(l.getLanguage())) {
set.add(l);
}
}
return set;
}
/**
* The documentation for ResourceBundle.Control.newBundle() says I
* should throw these exceptions.
*/
private void checkArguments(String baseName, Locale locale,
String format) {
if (baseName == null) {
throw new NullPointerException("baseName may not be null.");
}
if (locale == null) {
throw new NullPointerException("locale may not be null.");
}
if (format == null) {
throw new NullPointerException("format may not be null.");
}
if (!FORMAT_DEFAULT.contains(format)) {
throw new IllegalArgumentException(
"format must be one of these: " + FORMAT_DEFAULT);
}
}
}
private static class LocaleComparator implements Comparator<Locale> {
@Override
public int compare(Locale o1, Locale o2) {
int c = o1.getLanguage().compareTo(o2.getLanguage());
if (c == 0) {
c = o1.getCountry().compareTo(o2.getCountry());
if (c == 0) {
c = o1.getVariant().compareTo(o2.getVariant());
}
}
return c;
}
}
}

View file

@ -1,133 +1,10 @@
/* $This file is distributed under the terms of the license in LICENSE$ */
package edu.cornell.mannlib.vitro.webapp.i18n;
import java.text.MessageFormat;
import java.util.Collections;
import java.util.Enumeration;
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.
*
* If the ResourceBundle was not found, or if it doesn't contain the requested
* key, an error message string is returned, to help the developer diagnose the
* problem.
*/
public class I18nBundle {
private static final Log log = LogFactory.getLog(I18nBundle.class);
private static final String START_SEP = "\u25a4";
private static final String END_SEP = "\u25a5";
public static final String INT_SEP = "\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}''";
public static I18nBundle emptyBundle(String bundleName,
I18nLogger i18nLogger) {
return new I18nBundle(bundleName, i18nLogger);
}
private final String bundleName;
private final ResourceBundle resources;
private final String notFoundMessage;
private final I18nLogger i18nLogger;
private I18nBundle(String bundleName, I18nLogger i18nLogger) {
this(bundleName, new EmptyResourceBundle(), MESSAGE_BUNDLE_NOT_FOUND,
i18nLogger);
}
public I18nBundle(String bundleName, ResourceBundle resources,
I18nLogger i18nLogger) {
this(bundleName, resources, MESSAGE_KEY_NOT_FOUND, i18nLogger);
}
private I18nBundle(String bundleName, ResourceBundle resources,
String notFoundMessage, I18nLogger i18nLogger) {
if (bundleName == null) {
throw new IllegalArgumentException("bundleName may not be null");
}
if (bundleName.isEmpty()) {
throw new IllegalArgumentException("bundleName may not be empty");
}
if (resources == null) {
throw new NullPointerException("resources may not be null.");
}
if (notFoundMessage == null) {
throw new NullPointerException("notFoundMessage may not be null.");
}
this.bundleName = bundleName;
this.resources = resources;
this.notFoundMessage = notFoundMessage;
this.i18nLogger = i18nLogger;
}
public String text(String key, Object... parameters) {
String textString;
if (resources.containsKey(key)) {
textString = resources.getString(key);
log.debug("In '" + bundleName + "', " + key + "='" + textString
+ "')");
} else {
String message = MessageFormat.format(notFoundMessage, bundleName,
key);
log.warn(message);
textString = "ERROR: " + message;
}
String message = formatString(textString, parameters);
if (i18nLogger != null) {
i18nLogger.log(bundleName, key, parameters, textString, message);
}
if (isNeedExportInfo()) {
String separatedArgs = "";
for (int i = 0; i < parameters.length; i++) {
separatedArgs += parameters[i] + INT_SEP;
}
return START_SEP + key + INT_SEP + textString + INT_SEP + separatedArgs + message + END_SEP;
} else {
return message;
}
}
public interface I18nBundle {
private static boolean isNeedExportInfo() {
return DeveloperSettings.getInstance().getBoolean(Key.I18N_ONLINE_TRANSLATION);
}
private static String formatString(String textString, Object... parameters) {
if (parameters.length == 0) {
return textString;
} else {
return MessageFormat.format(textString, parameters);
}
}
/**
* A resource bundle that contains no strings.
*/
public static class EmptyResourceBundle extends ResourceBundle {
@Override
public Enumeration<String> getKeys() {
return Collections.enumeration(Collections.<String> emptySet());
}
@Override
protected Object handleGetObject(String key) {
if (key == null) {
throw new NullPointerException("key may not be null.");
}
return null;
}
}
public static final String START_SEP = "\u25a4";
public static final String END_SEP = "\u25a5";
public static final String INT_SEP = "\u25a6";
public String text(String key, Object... parameters);
}

View file

@ -0,0 +1,30 @@
package edu.cornell.mannlib.vitro.webapp.i18n;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
public class I18nContextListener implements ServletContextListener{
@Override
public void contextInitialized(ServletContextEvent sce) {
initializeTranslationProvider(sce);
initializeTranslationConverter(sce);
}
private void initializeTranslationConverter(ServletContextEvent sce) {
ServletContext ctx = sce.getServletContext();
TranslationConverter.getInstance().initialize(ctx);
}
private void initializeTranslationProvider(ServletContextEvent sce) {
ServletContext ctx = sce.getServletContext();
TranslationProvider.getInstance().initialize(ctx);
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
}
}

View file

@ -13,32 +13,29 @@ import edu.cornell.mannlib.vitro.webapp.utils.developer.Key;
/**
* If enabled in developer mode, write a message to the log each time someone
* asks for a language string.
*
* The I18nBundle has a life span of one HTTP request, and so does this.
*/
public class I18nLogger {
private static final Log log = LogFactory.getLog(I18nLogger.class);
private final boolean isLogging;
private DeveloperSettings settings;
public I18nLogger() {
DeveloperSettings settings = DeveloperSettings.getInstance();
this.isLogging = settings.getBoolean(Key.I18N_LOG_STRINGS)
&& log.isInfoEnabled();
settings = DeveloperSettings.getInstance();
}
public void log(String bundleName, String key, Object[] parameters,
String rawText, String formattedText) {
if (isLogging) {
public void log(String key, Object[] parameters, String rawText, String formattedText) {
if (isI18nLoggingTurnedOn()) {
String message = String.format(
"Retrieved from %s.%s with %s: '%s'", bundleName, key,
"Retrieved from %s with %s: '%s'", key,
Arrays.toString(parameters), rawText);
if (!rawText.equals(formattedText)) {
message += String.format(" --> '%s'", formattedText);
}
log.info(message);
}
}
private boolean isI18nLoggingTurnedOn() {
return settings.getBoolean(Key.I18N_LOG_STRINGS) && log.isInfoEnabled();
}
}

View file

@ -0,0 +1,28 @@
package edu.cornell.mannlib.vitro.webapp.i18n;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.stream.Collectors;
public class I18nSemanticBundle implements I18nBundle {
private List<String> preferredLocales = Collections.emptyList();
public I18nSemanticBundle(List<Locale> preferredLocales){
this.preferredLocales = convertToStrings(preferredLocales);
}
private static List<String> convertToStrings(List<Locale> preferredLocales) {
return preferredLocales.stream().map(Locale::toLanguageTag).collect(Collectors.toList());
}
@Override
public String text(String key, Object... parameters) {
final TranslationProvider provider = TranslationProvider.getInstance();
return provider.getTranslation(preferredLocales, key, parameters);
}
}

View file

@ -0,0 +1,330 @@
package edu.cornell.mannlib.vitro.webapp.i18n;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
import java.util.UUID;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.DirectoryFileFilter;
import org.apache.commons.io.filefilter.RegexFileFilter;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.jena.ontology.OntModel;
import org.apache.jena.ontology.OntModelSpec;
import org.apache.jena.query.ParameterizedSparqlString;
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.ModelFactory;
import org.apache.jena.rdf.model.RDFNode;
import org.apache.jena.rdf.model.Literal;
import org.apache.jena.rdf.model.ResourceFactory;
import org.apache.jena.shared.Lock;
import javax.servlet.ServletContext;
import edu.cornell.mannlib.vitro.webapp.dao.jena.event.BulkUpdateEvent;
import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess;
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;
import static edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess.WhichService.CONFIGURATION;
public class TranslationConverter {
protected OntModel memModel = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM);
protected ServletContext ctx;
private static final boolean BEGIN = true;
private static final boolean END = !BEGIN;
private static final int SUFFIX_LENGTH = ".properties".length();
private static final Log log = LogFactory.getLog(TranslationConverter.class);
private static final TranslationConverter INSTANCE = new TranslationConverter();
private static final String THEMES = "themes";
private static final String ALL = "all";
protected static final String APP_I18N_PATH = "/i18n/";
protected static final String LOCAL_I18N_PATH = "/local/i18n/";
protected static final String THEMES_PATH = "/themes/";
private static final String TEMPLATE_BODY = ""
+ "?uri <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2002/07/owl#NamedIndividual> .\n"
+ "?uri <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://vivoweb.org/ontology/core/properties/vocabulary#PropertyKey> .\n"
+ "?uri <http://vivoweb.org/ontology/core/properties/vocabulary#hasApp> ?application .\n"
+ "?uri <http://vivoweb.org/ontology/core/properties/vocabulary#hasKey> ?key .\n";
private static final String TEMPLATE_LABEL = ""
+ "?uri <http://www.w3.org/2000/01/rdf-schema#label> ?label .\n";
private static final String TEMPLATE_THEME = ""
+ "?uri <http://vivoweb.org/ontology/core/properties/vocabulary#hasTheme> ?theme .\n";
private static final String queryWithTheme(String langTag) {
return
"SELECT ?uri ?label WHERE {"
+ TEMPLATE_BODY
+ optionalLabel(langTag)
+ TEMPLATE_THEME
+ "}";
}
private static final String queryNoTheme(String langTag) {
return
"SELECT ?uri ?label WHERE {"
+ TEMPLATE_BODY
+ optionalLabel(langTag)
+ "FILTER NOT EXISTS {"
+ TEMPLATE_THEME
+ "}"
+ "}";
}
private static final String optionalLabel(String langTag) {
return
"OPTIONAL {"
+ "?uri <http://www.w3.org/2000/01/rdf-schema#label> ?label .\n "
+ "FILTER (LANG(?label)=\"" + langTag + "\")"
+ "}";
}
public static TranslationConverter getInstance() {
return INSTANCE;
}
public void initialize(ServletContext ctx) {
this.ctx = ctx;
OntModel tdbModel = ModelAccess.on(ctx).getOntModel(ModelNames.INTERFACE_I18N);
RDFService rdfService = ModelAccess.on(ctx).getRDFService(CONFIGURATION);
memModel.add(tdbModel);
convertAll();
cleanTdbModel(tdbModel, rdfService);
updateTDBModel(rdfService);
}
private void cleanTdbModel(OntModel storedModel, RDFService rdfService) {
ChangeSet cs = makeChangeSet(rdfService);
ByteArrayOutputStream removeOS = new ByteArrayOutputStream();
storedModel.write(removeOS, "N3");
InputStream removeIS = new ByteArrayInputStream(removeOS.toByteArray());
cs.addRemoval(removeIS, RDFServiceUtils.getSerializationFormatFromJenaString("N3"), ModelNames.INTERFACE_I18N);
try {
rdfService.changeSetUpdate(cs);
} catch (RDFServiceException e) {
log.error(e,e);
}
}
private void updateTDBModel(RDFService rdfService) {
ChangeSet cs = makeChangeSet(rdfService);
ByteArrayOutputStream addOS = new ByteArrayOutputStream();
memModel.write(addOS, "N3");
InputStream addIS = new ByteArrayInputStream(addOS.toByteArray());
cs.addAddition(addIS, RDFServiceUtils.getSerializationFormatFromJenaString("N3"), ModelNames.INTERFACE_I18N);
try {
rdfService.changeSetUpdate(cs);
} catch (RDFServiceException e) {
log.error(e,e);
}
}
public void convertAll() {
List<String> i18nDirs = new LinkedList<>(Arrays.asList(APP_I18N_PATH, LOCAL_I18N_PATH, THEMES_PATH));
List<String> prefixes = VitroResourceBundle.getAppPrefixes();
prefixes.add("");
String prefixesRegex = "(" + StringUtils.join(prefixes, ALL + "|") + ALL + ")";
log.debug("prefixesRegex " + prefixesRegex);
for (String dir : i18nDirs) {
File realDir = new File(ctx.getRealPath(dir));
Collection<File> files = FileUtils.listFiles(realDir, new RegexFileFilter(prefixesRegex + ".*\\.properties"), DirectoryFileFilter.DIRECTORY);
for (File file : files) {
convert(file);
}
}
}
private void convert(File file) {
Properties props = new Properties();
try (Reader reader = new InputStreamReader( new FileInputStream(file), "UTF-8")) {
props.load(reader);
} catch (Exception e) {
log.error(e,e);
}
if (props == null || props.isEmpty()) {
return;
}
log.info("Converting properties " + file.getAbsolutePath());
String theme = getTheme(file);
String application = getApplication(file);
String language = getLanguage(file);
String langTag = getLanguageTag(language);
StringWriter additions = new StringWriter();
StringWriter retractionsN3 = new StringWriter();
for (Object key : props.keySet()) {
Object value = props.get(key);
QueryExecution queryExecution = getQueryExecution(key.toString(), theme, application, langTag);
ResultSet results = queryExecution.execSelect();
String uri = null;
if (results.hasNext()) {
QuerySolution solution = results.nextSolution();
uri = solution.get("uri").toString();
String label = getLabel(solution);
if (labelAreadyExists(value, label)) {
continue;
}
if (!StringUtils.isBlank(label)) {
String retraction = fillOutLabelTemplate(uri, label, langTag);
retractionsN3.append(retraction);
}
}
String addition = fillOutTemplate(uri, key.toString(), value.toString(), theme, application, langTag);
additions.append(addition);
}
log.debug("Remove from model" + retractionsN3.toString());
log.debug("Add to model" + additions.toString());
OntModel addModel = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM);
OntModel removeModel = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM);
addModel.read(new StringReader(additions.toString()), null, "n3");
removeModel.read(new StringReader(retractionsN3.toString()), null, "n3");
memModel.enterCriticalSection(Lock.WRITE);
try {
memModel.remove(removeModel);
memModel.add(addModel);
} finally {
memModel.leaveCriticalSection();
}
log.info("Conversion finished for properties " + file.getAbsolutePath());
}
private String getLanguageTag(String language) {
return language.replaceAll("_","-");
}
private String getLabel(QuerySolution solution) {
final RDFNode label = solution.get("label");
if (label == null) {
return "";
}
return ((Literal)label).getLexicalForm();
}
private boolean labelAreadyExists(Object value, String label) {
return label.equals(value.toString());
}
private String fillOutTemplate(String uri, String key, String newLabel, String theme, String application, String langTag) {
if (StringUtils.isBlank(uri)) {
return fillOutFullTemplate(key, newLabel, theme, application, langTag);
} else {
return fillOutLabelTemplate(uri, newLabel, langTag);
}
}
private String fillOutLabelTemplate(String uri, String label, String langTag) {
ParameterizedSparqlString pss = new ParameterizedSparqlString();
pss.setCommandText(TEMPLATE_LABEL);
pss.setIri("uri", uri);
pss.setLiteral("label", label, langTag);
return pss.toString();
}
private String fillOutFullTemplate(String key, String label, String theme, String application, String langTag) {
String template = getBodyTemplate(theme);
ParameterizedSparqlString pss = new ParameterizedSparqlString();
pss.setCommandText(template);
pss.setIri("uri", createUUID());
pss.setLiteral("label", label, langTag);
pss.setLiteral("key", key);
pss.setLiteral("application", application);
if (!StringUtils.isBlank(theme)) {
pss.setLiteral("theme", theme);
}
return pss.toString();
}
private QueryExecution getQueryExecution(String key, String theme, String application, String langTag) {
Query query;
QuerySolutionMap bindings = new QuerySolutionMap();
bindings.add("application", ResourceFactory.createStringLiteral(application));
bindings.add("key", ResourceFactory.createStringLiteral(key));
if (StringUtils.isBlank(theme)) {
query = QueryFactory.create(queryNoTheme(langTag));
} else {
query = QueryFactory.create(queryWithTheme(langTag));
bindings.add("theme", ResourceFactory.createStringLiteral(theme));
}
QueryExecution qexec = QueryExecutionFactory.create(query, memModel, bindings);
return qexec;
}
private String createUUID() {
return "urn:uuid:" + UUID.randomUUID();
}
private String getBodyTemplate(String theme) {
if (StringUtils.isBlank(theme)) {
return TEMPLATE_BODY + TEMPLATE_LABEL;
}
return TEMPLATE_BODY + TEMPLATE_LABEL + TEMPLATE_THEME;
}
private String getLanguage(File file) {
String name = file.getName();
if (!name.contains("_")) {
return "en_US";
}
int startIndex;
if (name.contains("_all")) {
startIndex = name.indexOf("_all_") + 5;
} else {
startIndex = name.indexOf("_") + 1;
}
int endIndex = name.length() - SUFFIX_LENGTH;
return name.substring(startIndex,endIndex);
}
private String getApplication(File file) {
String name = file.getName();
if (name.toLowerCase().contains("vivo")) {
return "VIVO";
}
return "Vitro";
}
private String getTheme(File file) {
File parent = file.getParentFile();
if (parent == null) {
return "";
}
if (THEMES.equals(parent.getName())) {
return file.getName();
}
return getTheme(parent);
}
private ChangeSet makeChangeSet(RDFService rdfService) {
ChangeSet cs = rdfService.manufactureChangeSet();
cs.addPreChangeEvent(new BulkUpdateEvent(null, BEGIN));
cs.addPostChangeEvent(new BulkUpdateEvent(null, END));
return cs;
}
}

View file

@ -0,0 +1,235 @@
package edu.cornell.mannlib.vitro.webapp.i18n;
import java.text.MessageFormat;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.servlet.ServletContext;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.jena.query.QuerySolution;
import org.apache.jena.rdf.model.Literal;
import static edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess.WhichService.CONFIGURATION;
import edu.cornell.mannlib.vitro.webapp.config.RevisionInfoBean;
import edu.cornell.mannlib.vitro.webapp.config.RevisionInfoBean.LevelRevisionInfo;
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess;
import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService;
import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFServiceException;
import edu.cornell.mannlib.vitro.webapp.rdfservice.ResultSetConsumer;
import edu.cornell.mannlib.vitro.webapp.rdfservice.filter.LanguageFilteringRDFService;
import edu.cornell.mannlib.vitro.webapp.utils.developer.DeveloperSettings;
import edu.cornell.mannlib.vitro.webapp.utils.developer.Key;
import edu.cornell.mannlib.vitro.webapp.utils.sparqlrunner.QueryHolder;
public class TranslationProvider {
private static final String MESSAGE_KEY_NOT_FOUND = "ERROR: Translation not found ''{0}''";
private static final TranslationProvider INSTANCE = new TranslationProvider();
private static final Log log = LogFactory.getLog(TranslationProvider.class);
private static final I18nLogger i18nLogger = new I18nLogger();
private static final String QUERY = ""
+ "PREFIX : <http://vivoweb.org/ontology/core/properties/vocabulary#>\n"
+ "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>\n"
+ "PREFIX vitro: <http://vitro.mannlib.cornell.edu/ns/vitro/0.7#> \n"
+ "PREFIX xsd: <http://www.w3.org/2001/XMLSchema#> \n"
+ "SELECT ?translation \n" + "WHERE {\n"
+ " GRAPH <http://vitro.mannlib.cornell.edu/default/interface-i18n> {\n"
+ " ?uri :hasKey ?key .\n"
+ " ?uri rdfs:label ?translation .\n"
+ " OPTIONAL { \n"
+ " ?uri :hasTheme ?found_theme .\n"
+ " }\n"
+ " OPTIONAL { \n"
+ " ?uri :hasApp ?found_application .\n"
+ " }\n"
+ " BIND(COALESCE(?found_theme, \"none\") as ?theme ) .\n"
+ " FILTER(?theme = \"none\" || ?theme = ?current_theme) . "
+ " BIND(COALESCE(?found_application, \"none\") as ?application ) .\n"
+ " BIND(IF(?current_application = ?application && ?current_theme = ?theme, 3, "
+ " IF(?current_theme = ?theme, 2, "
+ " IF(?current_application = ?application, 1, 0)) ) AS ?order ) .\n"
+ " }\n" + "} \n"
+ "ORDER by DESC(?order)";
protected RDFService rdfService;
protected String application = "Vitro";
private Map<TranslationKey, String> cache = new ConcurrentHashMap<>();
private String theme = "vitro";
private int prefixLen = "themes/".length();
private int suffixLen = "/".length();
private WebappDaoFactory wdf;
public static TranslationProvider getInstance() {
return INSTANCE;
}
public void initialize(ServletContext ctx) {
RevisionInfoBean info = (RevisionInfoBean) ctx.getAttribute(RevisionInfoBean.ATTRIBUTE_NAME);
List<LevelRevisionInfo> levelInfos = info.getLevelInfos();
setApplication(levelInfos);
rdfService = ModelAccess.on(ctx).getRDFService(CONFIGURATION);
wdf = ModelAccess.on(ctx).getWebappDaoFactory();
updateTheme();
}
private void updateTheme() {
final String themeDir = wdf.getApplicationDao().getApplicationBean().getThemeDir();
final int length = themeDir.length();
theme = themeDir.substring(prefixLen, length - suffixLen);
}
public void setTheme(String theme) {
this.theme = theme;
}
private void setApplication(List<LevelRevisionInfo> levelInfos) {
if (levelInfos.isEmpty()) {
return;
}
application = levelInfos.get(0).getName();
}
public String getTranslation(List<String> preferredLocales, String key, Object[] parameters) {
TranslationKey tk = new TranslationKey(preferredLocales, key, parameters);
if (cache.containsKey(tk) && !needExportInfo()) {
log.debug("Returned value from cache for " + key);
return cache.get(tk);
}
String text = getText(preferredLocales, key);
String formattedText = formatString(text, parameters);
i18nLogger.log(key, parameters, text, formattedText);
if (needExportInfo()) {
return prepareExportInfo(key, parameters, text, formattedText);
} else {
cache.put(tk, formattedText);
log.debug("Added to cache " + key);
log.debug("Returned value from request for " + key);
return formattedText;
}
}
private String prepareExportInfo(String key, Object[] parameters, String text, String message) {
String separatedArgs = "";
for (int i = 0; i < parameters.length; i++) {
separatedArgs += parameters[i] + I18nBundle.INT_SEP;
}
log.debug("Returned value with export info for " + key );
return I18nBundle.START_SEP + key + I18nBundle.INT_SEP + text + I18nBundle.INT_SEP + separatedArgs
+ message + I18nBundle.END_SEP;
}
private String getText(List<String> preferredLocales, String key) {
String textString;
QueryHolder queryHolder = new QueryHolder(QUERY)
.bindToPlainLiteral("current_application", application)
.bindToPlainLiteral("key", key)
.bindToPlainLiteral("current_theme", theme)
.bindToPlainLiteral("locale", preferredLocales.get(0));
LanguageFilteringRDFService lfrs = new LanguageFilteringRDFService(rdfService, preferredLocales);
List<String> list = new LinkedList<>();
try {
lfrs.sparqlSelectQuery(queryHolder.getQueryString(), new ResultSetConsumer() {
@Override
protected void processQuerySolution(QuerySolution qs) {
Literal translation = qs.getLiteral("translation");
if (translation != null) {
list.add(translation.getLexicalForm());
}
}
});
} catch (RDFServiceException e) {
log.error(e,e);
}
if (list.isEmpty()) {
textString = notFound(key);
} else {
textString = list.get(0);
}
return textString;
}
private static boolean needExportInfo() {
return DeveloperSettings.getInstance().getBoolean(Key.I18N_ONLINE_TRANSLATION);
}
private static String formatString(String textString, Object... parameters) {
if (parameters.length == 0) {
return textString;
} else {
return MessageFormat.format(TranslationProvider.preprocessForFormating(textString), parameters);
}
}
/**
* This method should prepare the inputText for MessageFormat.format method. At the moment it is replacing single
* apostrophe with double, it might be extented in the future with some additional preprocessing.
* @param inputText - string which should be preprocessed
* @return preprocessed input string, i.e. string with replaced single apostrophe with double
*/
public static String preprocessForFormating(String inputText){
if (inputText != null) {
return inputText.replace("''", "'").replace("'", "''");
} else {
return "";
}
}
private String notFound(String key) {
return MessageFormat.format(MESSAGE_KEY_NOT_FOUND, key);
}
public void clearCache() {
if (wdf != null) {
updateTheme();
}
cache.clear();
log.info("Translation cache cleared");
}
private class TranslationKey {
private List<String> preferredLocales;
private String key;
private Object[] parameters;
public TranslationKey(List<String> preferredLocales, String key, Object[] parameters) {
this.preferredLocales = preferredLocales;
this.key = key;
this.parameters = parameters;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (! (obj instanceof TranslationKey)) {
return false;
}
TranslationKey other = (TranslationKey) obj;
return new EqualsBuilder()
.append(preferredLocales, other.preferredLocales)
.append(key, other.key)
.append(parameters, other.parameters)
.isEquals();
}
@Override
public int hashCode(){
return new HashCodeBuilder()
.append(preferredLocales)
.append(key)
.append(parameters)
.toHashCode();
}
}
}

View file

@ -2,61 +2,26 @@
package edu.cornell.mannlib.vitro.webapp.i18n;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Properties;
import java.util.ResourceBundle;
import javax.servlet.ServletContext;
import org.apache.commons.io.FileUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Works like a PropertyResourceBundle with two exceptions:
*
* It looks for the file in both the i18n directory of the theme and in the i18n
* directory of the application. Properties found in the theme override those
* found in the application.
*
* It allows a property to take its contents from a file. File paths are
* relative to the i18n directory. Again, a file in the theme will override one
* in the application.
*
* If a property has a value (after overriding) of "@@file &lt;filepath&gt;", the
* bundle looks for the file relative to the i18n directory of the theme, then
* relative to the i18n directory of the application. If the file is not found
* in either location, a warning is written to the log and the property will
* contain an error message for displayed.
*
* Note that the filename is not manipulated for Locale, so the author of the
* properties files must do it explicitly. For example:
*
* In all.properties: account_email_html = @@file accountEmail.html
*
* In all_es.properties: account_email_html = @@file accountEmail_es.html
* If you use 3 tier architecture with custom prefix for properties files
* you can add it with {@link #addAppPrefix(String)}
*
*/
public class VitroResourceBundle extends ResourceBundle {
private static final Log log = LogFactory.getLog(VitroResourceBundle.class);
private static final String FILE_FLAG = "@@file ";
private static final String MESSAGE_FILE_NOT_FOUND = "File {1} not found for property {0}.";
public class VitroResourceBundle {
private static final List<String> appPrefixes = new ArrayList<>();
static {
addAppPrefix("vitro");
}
public static List<String> getAppPrefixes(){
return appPrefixes;
}
public static void addAppPrefix(String prefix) {
if (!prefix.endsWith("-") && !prefix.endsWith("_")) {
prefix = prefix + "_";
@ -67,188 +32,4 @@ public class VitroResourceBundle extends ResourceBundle {
}
}
// ----------------------------------------------------------------------
// Factory method
// ----------------------------------------------------------------------
/**
* Returns the bundle for the for foo_ba_RR, providing that
* foo_ba_RR.properties exists in the I18n area of either the theme or the
* application.
*
* If the desired file doesn't exist in either location, return null.
* Usually, this does not indicate a problem but only that we were looking
* for too specific a bundle. For example, if the base name of the bundle is
* "all" and the locale is "en_US", we will likely return null on the search
* for all_en_US.properties, and all_en.properties, but will return a full
* bundle for all.properties.
*
* Of course, if all.properties doesn't exist either, then we have a
* problem, but that will be reported elsewhere.
*
* @return the populated bundle or null.
*/
public static VitroResourceBundle getBundle(String bundleName,
ServletContext ctx, String appI18nPath, String themeI18nPath,
Control control) {
try {
return new VitroResourceBundle(bundleName, ctx, appI18nPath,
themeI18nPath, control);
} catch (FileNotFoundException e) {
log.debug(e.getMessage());
return null;
} catch (Exception e) {
log.warn(e, e);
return null;
}
}
// ----------------------------------------------------------------------
// The instance
// ----------------------------------------------------------------------
private final String bundleName;
private final ServletContext ctx;
private final String appI18nPath;
private final String themeI18nPath;
private final Control control;
private final Properties properties;
private VitroResourceBundle(String bundleName, ServletContext ctx,
String appI18nPath, String themeI18nPath, Control control)
throws IOException {
this.bundleName = bundleName;
this.ctx = ctx;
this.appI18nPath = appI18nPath;
this.themeI18nPath = themeI18nPath;
this.control = control;
this.properties = loadProperties();
loadReferencedFiles();
}
private Properties loadProperties() throws IOException {
String resourceName = control.toResourceName(bundleName, "properties");
Properties props = null;
File defaultsPath = locateFile(joinPath(appI18nPath, resourceName));
File propertiesPath = locateFile(joinPath(themeI18nPath, resourceName));
props = loadProperties(props, defaultsPath);
if (appPrefixes != null && appPrefixes.size() > 0) {
for (String appPrefix : appPrefixes) {
props = loadProperties(props, locateFile(joinPath(appI18nPath, (appPrefix + resourceName))));
}
}
props = loadProperties(props, propertiesPath);
if (props == null) {
throw new FileNotFoundException("Property file not found at '" + defaultsPath + "' or '" + propertiesPath + "'");
}
props = loadProperties(props, locateFile(joinPath("/local/i18n/", resourceName)));
return props;
}
private Properties loadProperties(Properties defProps, File file) throws IOException {
if (file == null || !file.isFile()) {
return defProps;
}
Properties props = null;
if (defProps != null) {
props = new Properties(defProps);
} else {
props = new Properties();
}
log.debug("Loading bundle '" + bundleName + "' defaults from '" + file + "'");
FileInputStream stream = new FileInputStream(file);
Reader reader = new InputStreamReader(stream, "UTF-8");
try {
props.load(reader);
} finally {
reader.close();
}
if (props.size() > 0) {
return props;
}
return defProps;
}
private void loadReferencedFiles() throws IOException {
for (String key : this.properties.stringPropertyNames()) {
String value = this.properties.getProperty(key);
if (value.startsWith(FILE_FLAG)) {
String filepath = value.substring(FILE_FLAG.length()).trim();
loadReferencedFile(key, filepath);
}
}
}
private void loadReferencedFile(String key, String filepath)
throws IOException {
String appFilePath = joinPath(appI18nPath, filepath);
String themeFilePath = joinPath(themeI18nPath, filepath);
File appFile = locateFile(appFilePath);
File themeFile = locateFile(themeFilePath);
if (themeFile != null) {
this.properties.setProperty(key,
FileUtils.readFileToString(themeFile, "UTF-8"));
} else if (appFile != null) {
this.properties.setProperty(key,
FileUtils.readFileToString(appFile, "UTF-8"));
} else {
String message = MessageFormat.format(MESSAGE_FILE_NOT_FOUND, key,
themeFilePath, appFilePath);
this.properties.setProperty(key, message);
log.warn(message);
}
}
private String joinPath(String root, String twig) {
if ((root.charAt(root.length() - 1) == File.separatorChar)
|| (twig.charAt(0) == File.separatorChar)) {
return root + twig;
} else {
return root + File.separatorChar + twig;
}
}
private File locateFile(String path) {
String realPath = ctx.getRealPath(path);
if (realPath == null) {
log.debug("No real path for '" + path + "'");
return null;
}
File f = new File(realPath);
if (!f.isFile()) {
log.debug("No file at '" + realPath + "'");
return null;
}
if (!f.canRead()) {
log.error("Can't read the file at '" + realPath + "'");
return null;
}
log.debug("Located file '" + path + "' at '" + realPath + "'");
return f;
}
@SuppressWarnings("unchecked")
@Override
public Enumeration<String> getKeys() {
return (Enumeration<String>) this.properties.propertyNames();
}
@Override
protected Object handleGetObject(String key) {
String value = this.properties.getProperty(key);
if (value == null) {
log.debug(bundleName + " has no value for '" + key + "'");
}
return value;
}
}

View file

@ -15,21 +15,17 @@ import freemarker.template.TemplateModelException;
* wrapper around an I18nBundle.
*/
public class I18nBundleTemplateModel implements TemplateHashModel {
private static final Log log = LogFactory
.getLog(I18nBundleTemplateModel.class);
private static final Log log = LogFactory.getLog(I18nBundleTemplateModel.class);
private final String bundleName;
private final I18nBundle textBundle;
public I18nBundleTemplateModel(String bundleName, I18nBundle textBundle) {
this.bundleName = bundleName;
public I18nBundleTemplateModel( I18nBundle textBundle) {
this.textBundle = textBundle;
}
@Override
public TemplateModel get(String key) throws TemplateModelException {
return new I18nStringTemplateModel(bundleName, key,
textBundle.text(key));
return new I18nStringTemplateModel(key, textBundle.text(key));
}
@Override

View file

@ -12,7 +12,7 @@ import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vitro.webapp.i18n.I18n;
import edu.cornell.mannlib.vitro.webapp.i18n.I18nBundle;
import freemarker.core.Environment;
import freemarker.template.TemplateMethodModel;
import freemarker.template.TemplateMethodModelEx;
import freemarker.template.TemplateModelException;
/**
@ -21,30 +21,15 @@ import freemarker.template.TemplateModelException;
*
* If the bundle name is not provided, the default bundle is assumed.
*/
public class I18nMethodModel implements TemplateMethodModel {
public class I18nMethodModel implements TemplateMethodModelEx {
private static final Log log = LogFactory.getLog(I18nMethodModel.class);
@SuppressWarnings("rawtypes")
@Override
public Object exec(List args) throws TemplateModelException {
if (args.size() > 1) {
throw new TemplateModelException("Too many arguments: "
+ "displayText method only requires a bundle name.");
}
Object arg = args.isEmpty() ? I18n.DEFAULT_BUNDLE_NAME : args.get(0);
if (!(arg instanceof String)) {
throw new IllegalArgumentException(
"Arguments to a TemplateMethodModel are supposed to be Strings!");
}
log.debug("Asking for this bundle: " + arg);
String bundleName = (String) arg;
Environment env = Environment.getCurrentEnvironment();
HttpServletRequest request = (HttpServletRequest) env
.getCustomAttribute("request");
I18nBundle tb = I18n.bundle(bundleName, request);
return new I18nBundleTemplateModel(bundleName, tb);
HttpServletRequest request = (HttpServletRequest) env.getCustomAttribute("request");
I18nBundle tb = I18n.bundle(request);
return new I18nBundleTemplateModel(tb);
}
}

View file

@ -5,6 +5,7 @@ package edu.cornell.mannlib.vitro.webapp.i18n.freemarker;
import java.text.MessageFormat;
import java.util.List;
import edu.cornell.mannlib.vitro.webapp.i18n.TranslationProvider;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@ -37,13 +38,10 @@ public class I18nStringTemplateModel implements TemplateMethodModelEx,
private static final Log log = LogFactory
.getLog(I18nStringTemplateModel.class);
private final String bundleName;
private final String key;
private final String textString;
public I18nStringTemplateModel(String bundleName, String key,
String textString) {
this.bundleName = bundleName;
public I18nStringTemplateModel( String key, String textString) {
this.key = key;
this.textString = textString;
}
@ -56,8 +54,7 @@ public class I18nStringTemplateModel implements TemplateMethodModelEx,
@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
public Object exec(List args) throws TemplateModelException {
log.debug("Formatting string '" + key + "' from bundle '" + bundleName
+ "' with these arguments: " + args);
log.debug("Formatting string '" + key + "' with these arguments: " + args);
if (args.isEmpty()) {
return textString;
@ -71,11 +68,10 @@ public class I18nStringTemplateModel implements TemplateMethodModelEx,
if(isOnlineTranslationsEnabled()) {
return getOnlineTranslationsFormattedMessage(textString, unwrappedArgs);
} else {
return MessageFormat.format(textString, unwrappedArgs);
return MessageFormat.format(TranslationProvider.preprocessForFormating(textString), unwrappedArgs);
}
} catch (Exception e) {
String message = "Can't format '" + key + "' from bundle '"
+ bundleName + "', wrong argument types: " + args
String message = "Can't format '" + key + "', wrong argument types: " + args
+ " for message format'" + textString + "'";
log.warn(message);
return message;
@ -88,13 +84,13 @@ public class I18nStringTemplateModel implements TemplateMethodModelEx,
* 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
* @param args 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.INT_SEP);
final int messageIndex = parts.length -1;
String message = MessageFormat.format(parts[messageIndex], args);
String message = MessageFormat.format(TranslationProvider.preprocessForFormating(parts[messageIndex]), args);
String[] arguments = convertToArrayOfStrings(args);
parts[messageIndex] = "";
String result = String.join(I18nBundle.INT_SEP, parts) +

View file

@ -88,7 +88,7 @@ public class LocaleSelectionController extends HttpServlet {
if (!selectables.contains(locale)) {
log.warn("User selected a locale '" + locale
+ "' that was not in the list: " + selectables);
} else if (!LocaleUtils.isAvailableLocale(locale)) {
} else if (!LocaleUtils.isAvailableLocale(locale.stripExtensions())) {
log.warn("User selected an unrecognized locale: '" + locale + "'");
}

View file

@ -3,12 +3,7 @@
package edu.cornell.mannlib.vitro.webapp.i18n.selection;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@ -36,7 +31,8 @@ import edu.cornell.mannlib.vitro.webapp.utils.dataGetter.DataGetter;
* { [a map for each Locale]
* code = [the code for the Locale, e.g. "en_US"]
* label = [the alt text for the Locale, e.g. "Spanish (Spain)"]
* imageUrl = [the URL of the image that represents the Locale]
* country = [the country for the Locale, e.g. "United States"]
* institution = [the abbreviation for institution, e.g. "UQAM"]
* selected = [true, if this locale is currently selected]
* }
* }
@ -50,6 +46,8 @@ public class LocaleSelectionDataGetter implements DataGetter {
private final VitroRequest vreq;
private static final char PRIVATE_USE_SUBTAG = 'x';
public LocaleSelectionDataGetter(VitroRequest vreq) {
this.vreq = vreq;
}
@ -73,10 +71,23 @@ public class LocaleSelectionDataGetter implements DataGetter {
private List<Map<String, Object>> buildLocalesList(List<Locale> selectables) {
Locale currentLocale = SelectedLocale.getCurrentLocale(vreq);
// The next couple of lines check whether there are locales in the list with the same root.
// If yes, the institution abbreviation (private tag) will be displayed in UI.
// For instance, if there are fr_CA_x_uqam and fr_CA in a VIVO instance runtime.properties,
// the institutional abbreviation (UQAM) will be displayed next to locale name
// in the dropdown menu for selection of a UI language.
boolean includeAbbreviation = false;
Set<String> setOfLocalesBase = new HashSet<>();
for(final Locale locale: selectables) {
setOfLocalesBase.add(locale.stripExtensions().toLanguageTag());
}
if (setOfLocalesBase.size() < selectables.size()) {
includeAbbreviation = true;
}
List<Map<String, Object>> list = new ArrayList<>();
for (Locale locale : selectables) {
try {
list.add(buildLocaleMap(locale, currentLocale));
list.add(buildLocaleMap(locale, currentLocale, includeAbbreviation));
} catch (FileNotFoundException e) {
log.warn("Can't show the Locale selector for '" + locale
+ "': " + e);
@ -86,12 +97,15 @@ public class LocaleSelectionDataGetter implements DataGetter {
}
private Map<String, Object> buildLocaleMap(Locale locale,
Locale currentLocale) throws FileNotFoundException {
Locale currentLocale, boolean includeAbbreviation) throws FileNotFoundException {
Map<String, Object> map = new HashMap<>();
map.put("code", locale.toLanguageTag().replace('-','_'));
map.put("label", locale.getDisplayLanguage(locale));
map.put("country", locale.getDisplayCountry(locale));
if (includeAbbreviation) {
map.put("institution", Optional.ofNullable(locale.getExtension(LocaleSelectionDataGetter.PRIVATE_USE_SUBTAG)).orElse("").toUpperCase());
}
map.put("selected", currentLocale.equals(locale));
return map;
}

View file

@ -154,7 +154,7 @@ public class LocaleSelectionSetup implements ServletContextListener {
Locale locale = LocaleUtility.languageStringToLocale(localeString);
if (!"es_GO".equals(localeString) && // No complaint about bogus locale
!LocaleUtils.isAvailableLocale(locale)) {
!LocaleUtils.isAvailableLocale(locale.stripExtensions())) {
ssWarning("'" + locale + "' is not a recognized locale.");
}

View file

@ -34,6 +34,10 @@ public class ModelNames {
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";
public static final String INTERFACE_I18N = "http://vitro.mannlib.cornell.edu/default/interface-i18n";
public static final String INTERFACE_I18N_FIRSTTIME_BACKUP = INTERFACE_I18N + "FirsttimeBackup";
/**
* A map of the URIS, keyed by their short names, intended only for display
@ -64,6 +68,9 @@ public class ModelNames {
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);
map.put("INTERFACE_I18N", INTERFACE_I18N);
map.put("INTERFACE_I18N_FIRSTTIME_BACKUP", INTERFACE_I18N_FIRSTTIME_BACKUP);
return Collections.unmodifiableMap(map);
}

View file

@ -13,6 +13,9 @@ import static edu.cornell.mannlib.vitro.webapp.modelaccess.ModelNames.USER_ACCOU
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 static edu.cornell.mannlib.vitro.webapp.modelaccess.ModelNames.INTERFACE_I18N ;
import static edu.cornell.mannlib.vitro.webapp.modelaccess.ModelNames.INTERFACE_I18N_FIRSTTIME_BACKUP;
import org.apache.jena.rdf.model.ModelMaker;
@ -25,11 +28,21 @@ public abstract class ConfigurationTripleSource implements TripleSource {
* A list of all Configuration models, in case the implementation wants to
* add memory-mapping.
*/
protected static final String[] CONFIGURATION_MODELS = { DISPLAY,
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 };
protected static final String[] CONFIGURATION_MODELS = {
DISPLAY,
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,
INTERFACE_I18N,
INTERFACE_I18N_FIRSTTIME_BACKUP,
};
/**
* These decorators are added to a Configuration ModelMaker, regardless of

View file

@ -33,7 +33,7 @@ public class LanguageFilteringUtils {
* (as in RDF language specifiers).
*/
public static String localeToLanguage(Locale locale) {
return locale.toString().replace(UNDERSCORE, HYPHEN);
return locale.toLanguageTag().replace(UNDERSCORE, HYPHEN);
}
/**
@ -69,9 +69,9 @@ public class LanguageFilteringUtils {
List<String> langs = new ArrayList<>();
while (locales.hasMoreElements()) {
Locale locale = (Locale) locales.nextElement();
langs.add(locale.toString().replace(UNDERSCORE, HYPHEN));
langs.add(locale.toLanguageTag().replace(UNDERSCORE, HYPHEN));
}
if (langs.isEmpty()) {
if (!langs.contains(DEFAULT_LANG_STRING)) {
langs.add(DEFAULT_LANG_STRING);
}

View file

@ -6,6 +6,7 @@ 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.INTERFACE_I18N;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
@ -13,17 +14,10 @@ import javax.servlet.ServletContextListener;
import org.apache.jena.ontology.OntModel;
import org.apache.jena.rdf.model.Model;
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.Statement;
import org.apache.jena.rdf.model.StmtIterator;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess;
import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus;
@ -46,6 +40,7 @@ public class ConfigurationModelsSetup implements ServletContextListener {
setupModel(ctx, DISPLAY_TBOX, "displayTbox");
setupModel(ctx, DISPLAY_DISPLAY, "displayDisplay");
setupModel(ctx, USER_ACCOUNTS, "auth");
setupModel(ctx, INTERFACE_I18N, "interface-i18n");
ss.info(this, "Set up the display models and the user accounts model.");
} catch (Exception e) {
ss.fatal(this, e.getMessage(), e.getCause());

View file

@ -137,7 +137,19 @@ public class RDFFilesLoader {
// Which locales are enabled in runtime.properties?
List<Locale> locales = SelectedLocale.getSelectableLocales(ctx);
for (Locale locale : locales) {
enabledLocales.add(locale.toLanguageTag().replace('-', '_'));
String localeString = locale.toLanguageTag().replace('-', '_');
if (! enabledLocales.contains(localeString)) {
enabledLocales.add(localeString);
}
// If a locale with fr_CA_x_uqam is used, the locale fr_CA should be also enabled for loading.
// Private tags (lang_CountryCode_x_InstitutionAbbreviation) are inteded to be just extension,
// therefore the basic locale (lang_CountryCode) should be loaded as well.
if(locale.hasExtensions()){
localeString = locale.stripExtensions().toLanguageTag().replace('-', '_');
if (! enabledLocales.contains(localeString)) {
enabledLocales.add(localeString);
}
}
}
// If no languages were enabled in runtime.properties, add a fallback as the default

View file

@ -4,6 +4,9 @@ package edu.cornell.mannlib.vitro.webapp.utils;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@ -18,112 +21,227 @@ import org.apache.jena.query.ResultSet;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ModelFactory;
import org.apache.jena.rdf.model.Resource;
import org.apache.jena.rdf.model.ResourceFactory;
import org.apache.jena.vocabulary.RDFS;
import edu.cornell.mannlib.vitro.webapp.beans.DataProperty;
import edu.cornell.mannlib.vitro.webapp.beans.FauxProperty;
import edu.cornell.mannlib.vitro.webapp.beans.Individual;
import edu.cornell.mannlib.vitro.webapp.beans.ObjectProperty;
import edu.cornell.mannlib.vitro.webapp.beans.VClass;
import edu.cornell.mannlib.vitro.webapp.beans.Property;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.dao.DataPropertyDao;
import edu.cornell.mannlib.vitro.webapp.dao.FauxPropertyDao;
import edu.cornell.mannlib.vitro.webapp.dao.ObjectPropertyDao;
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
import edu.cornell.mannlib.vitro.webapp.dao.jena.WebappDaoFactoryJena;
import edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual.FauxDataPropertyWrapper;
import edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual.FauxObjectPropertyWrapper;
import edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual.FauxPropertyWrapper;
public class ApplicationConfigurationOntologyUtils {
private static final Log log = LogFactory.getLog(ApplicationConfigurationOntologyUtils.class);
public static List<ObjectProperty> getAdditionalFauxSubpropertiesForList(List<ObjectProperty> propList, Individual subject, VitroRequest vreq) {
Model displayModel = vreq.getDisplayModel();
Model tboxModel = vreq.getOntModelSelector().getTBoxModel();
return getAdditionalFauxSubpropertiesForList(propList, subject, displayModel, tboxModel);
}
public static List<ObjectProperty> getAdditionalFauxSubproperties(ObjectProperty prop,
Individual subject,
Model tboxModel,
Model union) {
List<ObjectProperty> additionalProps = new ArrayList<ObjectProperty>();
String queryStr = "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n" +
private static final String getPossibleFauxQuery(boolean isData) {
return
"PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n" +
"PREFIX config: <http://vitro.mannlib.cornell.edu/ns/vitro/ApplicationConfiguration#> \n" +
"PREFIX vitro: <http://vitro.mannlib.cornell.edu/ns/vitro/0.7#> \n" +
"SELECT DISTINCT ?range ?domain ?property WHERE { \n" +
"SELECT DISTINCT ?domain ?property ?context ?isData WHERE { \n" +
" ?context config:configContextFor ?property . \n" +
" ?context config:qualifiedBy ?range . \n" +
(isData ?
"?property a <http://www.w3.org/2002/07/owl#DatatypeProperty> . \n"
:
"?property a <http://www.w3.org/2002/07/owl#ObjectProperty> . \n" ) +
" OPTIONAL { ?context config:qualifiedBy ?range . } \n " +
" ?context config:hasConfiguration ?configuration . \n" +
" ?configuration a config:ObjectPropertyDisplayConfig . \n" +
" OPTIONAL { ?context config:qualifiedByDomain ?domain } \n" +
" OPTIONAL { ?context config:qualifiedByDomain ?domain } . \n" +
"}";
}
private static String getFauxPropQuery(String baseUri, boolean optionalRange) {
return
"PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n" +
"PREFIX config: <http://vitro.mannlib.cornell.edu/ns/vitro/ApplicationConfiguration#> \n" +
"PREFIX vitro: <http://vitro.mannlib.cornell.edu/ns/vitro/0.7#> \n" +
"SELECT DISTINCT ?domain ?context WHERE { \n" +
" ?context config:configContextFor <" + baseUri + "> . \n" +
(optionalRange ? " OPTIONAL { " : "") +
" ?context config:qualifiedBy ?range . \n" +
(optionalRange ? " } " : "") +
" ?context config:hasConfiguration ?configuration . \n" +
" ?configuration a config:ObjectPropertyDisplayConfig . \n" +
" OPTIONAL { ?context config:qualifiedByDomain ?domain } \n" +
"}";
}
if(prop != null) {
log.debug("Checking " + prop.getURI() + " for additional properties");
queryStr = queryStr.replaceAll("For \\?property", "For <" + prop.getURI() + ">");
}
log.debug(queryStr);
Query q = QueryFactory.create(queryStr);
public static List<FauxObjectPropertyWrapper> getPopulatedFauxOPs(List<ObjectProperty> populatedObjectProperties, Individual subject, VitroRequest vreq) {
List<FauxObjectPropertyWrapper> fauxProperties = new ArrayList<FauxObjectPropertyWrapper>();
for (ObjectProperty op : populatedObjectProperties) {
fauxProperties.addAll(getPopulatedFauxObjectProperties(op, subject, vreq));
}
return fauxProperties;
}
public static List<FauxDataPropertyWrapper> getPopulatedFauxDPs(List<DataProperty> populatedDataProperties, Individual subject, VitroRequest vreq) {
List<FauxDataPropertyWrapper> fauxProperties = new ArrayList<FauxDataPropertyWrapper>();
for (DataProperty dp : populatedDataProperties) {
fauxProperties.addAll(getPopulatedFauxDataProperties(dp, subject, vreq));
}
return fauxProperties;
}
private static List<FauxObjectPropertyWrapper> getPopulatedFauxObjectProperties(ObjectProperty op, Individual subject, VitroRequest vreq) {
Model displayModel = vreq.getDisplayModel();
Model tboxModel = vreq.getOntModelSelector().getTBoxModel();
Model union = ModelFactory.createUnion(displayModel, tboxModel);
WebappDaoFactory wadf = new WebappDaoFactoryJena(ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM, union));
FauxPropertyDao fpDao = wadf.getFauxPropertyDao();
Query q = createQuery(op, false);
QueryExecution qe = QueryExecutionFactory.create(q, union);
WebappDaoFactory wadf = new WebappDaoFactoryJena(
ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM, union));
ObjectPropertyDao opDao = wadf.getObjectPropertyDao();
List<FauxObjectPropertyWrapper> fauxObjectProps = new ArrayList<FauxObjectPropertyWrapper>();
try {
ResultSet rs = qe.execSelect();
while (rs.hasNext()) {
QuerySolution qsoln = rs.nextSolution();
log.debug(qsoln);
String opURI = (prop != null) ? prop.getURI() : qsoln.getResource(
"property").getURI();
Resource domainRes = qsoln.getResource("domain");
String domainURI = (domainRes != null) ? domainRes.getURI() : null;
String rangeURI = qsoln.getResource("range").getURI();
if (appropriateDomain(domainRes, subject, tboxModel)) {
ObjectProperty faux = opDao.getObjectPropertyByURIs(
opURI, domainURI, rangeURI, (prop != null) ? prop.clone() : null);
if (faux != null) {
additionalProps.add(faux);
} else {
log.error("Could not retrieve " + opURI + " qualified by " +
" domain " + domainURI + " and range " + rangeURI);
String contextURI = qsoln.getResource("context").getURI();
if (isDomainMatchSubject(domainURI, subject)) {
try {
FauxProperty fp = fpDao.getFauxPropertyFromContextUri(contextURI);
if (fp != null) {
fauxObjectProps.add(new FauxObjectPropertyWrapper(op.clone(), fp));
}
} catch (Exception e) {
log.warn("Couldn't look up the faux property", e);
}
}
}
} finally {
qe.close();
}
return additionalProps;
return fauxObjectProps;
}
public static List<ObjectProperty> getAdditionalFauxSubpropertiesForList(List<ObjectProperty> propList,
Individual subject,
Model displayModel,
Model tboxModel) {
List<ObjectProperty> additionalProps = new ArrayList<ObjectProperty>();
private static List<FauxDataPropertyWrapper> getPopulatedFauxDataProperties(DataProperty dp, Individual subject, VitroRequest vreq) {
Model displayModel = vreq.getDisplayModel();
Model tboxModel = vreq.getOntModelSelector().getTBoxModel();
Model union = ModelFactory.createUnion(displayModel, tboxModel);
WebappDaoFactory wadf = new WebappDaoFactoryJena(ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM, union));
FauxPropertyDao fpDao = wadf.getFauxPropertyDao();
for (ObjectProperty op : propList) {
additionalProps.addAll(getAdditionalFauxSubproperties(op, subject, tboxModel, union));
Query q = createQuery(dp, true);
QueryExecution qe = QueryExecutionFactory.create(q, union);
List<FauxDataPropertyWrapper> fauxDataProps = new ArrayList<FauxDataPropertyWrapper>();
try {
ResultSet rs = qe.execSelect();
while (rs.hasNext()) {
QuerySolution qsoln = rs.nextSolution();
log.debug(qsoln);
Resource domainRes = qsoln.getResource("domain");
String domainURI = (domainRes != null) ? domainRes.getURI() : null;
String contextURI = qsoln.getResource("context").getURI();
if (isDomainMatchSubject(domainURI, subject)) {
try {
FauxProperty fp = fpDao.getFauxPropertyFromContextUri(contextURI);
if (fp != null) {
fauxDataProps.add(new FauxDataPropertyWrapper(dp, fp));
}
} catch (Exception e) {
log.warn("Couldn't look up the faux property", e);
}
}
}
} finally {
qe.close();
}
return additionalProps;
return fauxDataProps;
}
private static boolean appropriateDomain(Resource domainRes, Individual subject, Model tboxModel) {
if (subject == null || domainRes == null) {
private static Query createQuery(Property op, boolean optionalRange) {
String queryStr = getFauxPropQuery(op.getURI(), optionalRange);
log.debug(queryStr);
Query q = QueryFactory.create(queryStr);
return q;
}
private static boolean isDomainMatchSubject(String domainUri, Individual subject) {
if (subject == null || domainUri == null) {
return true;
}
for (VClass vclass : subject.getVClasses()) {
if ((vclass.getURI() != null) &&
((vclass.getURI().equals(domainRes.getURI()) ||
(tboxModel.contains(
ResourceFactory.createResource(
vclass.getURI()), RDFS.subClassOf, domainRes))))) {
Set<String> vClassUris = subject.getVClasses().stream().map(vclass -> vclass.getURI())
.collect(Collectors.toSet());
for (String vClassUri : vClassUris) {
if (vClassUri != null && vClassUri.equals(domainUri)) {
return true;
}
}
return false;
}
public static List<Property> getPossibleFauxProps(List<? extends FauxPropertyWrapper> curProps, Individual subject, VitroRequest vreq, boolean isData) {
Model displayModel = vreq.getDisplayModel();
Model tboxModel = vreq.getOntModelSelector().getTBoxModel();
Model union = ModelFactory.createUnion(displayModel, tboxModel);
Map<String, FauxProperty> curPropsMap = curProps.stream()
.collect(Collectors.toMap(FauxPropertyWrapper::getContextUri, FauxPropertyWrapper::getFauxProperty));
WebappDaoFactory wadf = new WebappDaoFactoryJena(ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM, union));
FauxPropertyDao fpDao = wadf.getFauxPropertyDao();
ObjectPropertyDao opDao = wadf.getObjectPropertyDao();
DataPropertyDao dpDao = wadf.getDataPropertyDao();
Query q = QueryFactory.create(getPossibleFauxQuery(isData));
QueryExecution qe = QueryExecutionFactory.create(q, union);
List<Property> fauxDataProps = new ArrayList<Property>();
try {
ResultSet rs = qe.execSelect();
while (rs.hasNext()) {
QuerySolution qsoln = rs.nextSolution();
Resource domainRes = qsoln.getResource("domain");
String domainURI = (domainRes != null) ? domainRes.getURI() : null;
String basePropertyUri = qsoln.getResource("property").getURI();
String contextURI = qsoln.getResource("context").getURI();
if (isDomainMatchSubject(domainURI, subject) && !curPropsMap.containsKey(contextURI)) {
if (isData) {
addDataProperty(fauxDataProps, basePropertyUri, contextURI, fpDao, dpDao);
} else {
addObjectProperty(fauxDataProps, basePropertyUri, contextURI, fpDao, opDao);
}
}
}
} finally {
qe.close();
}
return fauxDataProps;
}
private static void addObjectProperty(List<Property> fauxProps, String basePropertyUri, String contextURI,
FauxPropertyDao fpDao, ObjectPropertyDao opDao) {
try {
FauxProperty fp = fpDao.getFauxPropertyFromContextUri(contextURI);
ObjectProperty op = opDao.getObjectPropertyByURI(basePropertyUri);
if (fp != null && op != null) {
fauxProps.add(new FauxObjectPropertyWrapper(op, fp));
}
} catch (Exception e) {
log.warn("Couldn't look up the faux object property, contextUri " + contextURI, e);
}
}
private static void addDataProperty(List<Property> fauxProps, String basePropertyUri, String contextURI,
FauxPropertyDao fpDao, DataPropertyDao dpDao) {
try {
FauxProperty fp = fpDao.getFauxPropertyFromContextUri(contextURI);
DataProperty dp = dpDao.getDataPropertyByURI(basePropertyUri);
if (fp != null && dp != null) {
fauxProps.add(new FauxDataPropertyWrapper(dp, fp));
}
} catch (Exception e) {
log.warn("Couldn't look up the faux data property, contextUri " + contextURI, e);
}
}
}

View file

@ -10,10 +10,17 @@ public final class LocaleUtility {
public static Locale languageStringToLocale(String localeString){
String[] parsedLoc = localeString.trim().split("_", -1);
//regex pattern for locale tag with script specified
Locale locale = localeString.matches("^[a-z]{1,3}_[A-Z][a-z]{3}_[A-Z]{2}") ?
new Locale.Builder().setLanguage(parsedLoc[0]).setRegion(parsedLoc[2]).setScript(parsedLoc[1]).build() :
LocaleUtils.toLocale(localeString);
Locale locale = null;
if (localeString.matches("^[a-z]{1,3}_[A-Z][a-z]{3}_[A-Z]{2}_x_[a-z]{1,}")) { //regex pattern for locale tag with script and private-use subtag, e.g. sr_Latn_RS_x_uns
locale = new Locale.Builder().setLanguage(parsedLoc[0]).setRegion(parsedLoc[2]).setScript(parsedLoc[1]).setExtension('x', parsedLoc[4]).build();
} else if (localeString.matches("^[a-z]{1,3}_[A-Za-z]{2}_x_[a-z]{1,}")) { //regex pattern for locale tag with script and private-use subtag, e.g. fr_CA_x_uqam
locale = new Locale.Builder().setLanguage(parsedLoc[0]).setRegion(parsedLoc[1]).setExtension('x', parsedLoc[3]).build();
} else if (localeString.matches("^[a-z]{1,3}_[A-Z][a-z]{3}_[A-Z]{2}")) { //regex pattern for locale tag with script specified, e.g. sr_Latn_RS
locale = new Locale.Builder().setLanguage(parsedLoc[0]).setRegion(parsedLoc[2]).setScript(parsedLoc[1]).build();
} else { // other, just languge, e.g. es, or language + region, e.g. en_US, pt_BR, ru_RU, etc.
locale = LocaleUtils.toLocale(localeString);
}
String localeLang = locale.toLanguageTag();
return locale;
}
}

View file

@ -209,11 +209,11 @@ public class SearchQueryUtils {
}
public static String getSortFieldNameForLocale(Locale locale) {
return locale.toString().replace('_', '-') + VitroSearchTermNames.LABEL_SORT_SUFFIX;
return locale.toLanguageTag().replace('_', '-') + VitroSearchTermNames.LABEL_SORT_SUFFIX;
}
public static String getLabelFieldNameForLocale(Locale locale) {
return locale.toString().replace('_', '-') + VitroSearchTermNames.LABEL_DISPLAY_SUFFIX;
return locale.toLanguageTag().replace('_', '-') + VitroSearchTermNames.LABEL_DISPLAY_SUFFIX;
}
public static SearchQuery getRandomQuery(List<String> vclassUris, int page, int pageSize){

View file

@ -1,82 +0,0 @@
/* $This file is distributed under the terms of the license in LICENSE$ */
package edu.cornell.mannlib.vitro.webapp.web.directives;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vitro.webapp.email.FreemarkerEmailMessage;
import freemarker.core.Environment;
import freemarker.template.TemplateDirectiveBody;
import freemarker.template.TemplateException;
import freemarker.template.TemplateModel;
import freemarker.template.TemplateModelException;
/**
* Process the inputs for a FreemarkerEmailMessage.
*
* @see FreemarkerEmailMessage
*/
public class EmailDirective extends BaseTemplateDirectiveModel {
private static final Log log = LogFactory.getLog(EmailDirective.class);
private final FreemarkerEmailMessage message;
public EmailDirective(FreemarkerEmailMessage message) {
this.message = message;
}
@Override
public void execute(Environment env, Map params, TemplateModel[] loopVars,
TemplateDirectiveBody body) throws TemplateException, IOException {
String subject = getOptionalSimpleScalarParameter(params, "subject");
if (subject != null) {
message.setSubject(subject);
}
String htmlContent = getOptionalSimpleScalarParameter(params, "html");
if (htmlContent != null) {
message.setHtmlContent(htmlContent);
}
String textContent = getOptionalSimpleScalarParameter(params, "text");
if (textContent != null) {
message.setTextContent(textContent);
}
if ((htmlContent == null) && (textContent == null)) {
throw new TemplateModelException("The email directive must have "
+ "either a 'html' parameter or a 'text' parameter.");
}
}
@Override
public Map<String, Object> help(String name) {
Map<String, Object> map = new LinkedHashMap<String, Object>();
map.put("effect",
"Create an email message from the parameters set in the invoking template.");
Map<String, String> params = new HashMap<String, String>();
params.put("subject", "email subject (optional)");
params.put("html", "HTML version of email message (optional)");
params.put("text", "Plain text version of email message (optional)");
map.put("parameters", params);
List<String> examples = new ArrayList<String>();
examples.add("&lt;email subject=\"Password reset confirmation\" html=html text=text&gt;");
examples.add("&lt;email html=html text=text&gt;");
map.put("examples", examples);
return map;
}
}

View file

@ -0,0 +1,332 @@
/* $This file is distributed under the terms of the license in LICENSE$ */
package edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual;
import java.util.List;
import java.util.Objects;
import org.apache.jena.rdf.model.ResourceFactory;
import edu.cornell.mannlib.vitro.webapp.beans.DataProperty;
import edu.cornell.mannlib.vitro.webapp.beans.DataPropertyStatement;
import edu.cornell.mannlib.vitro.webapp.beans.FauxProperty;
import edu.cornell.mannlib.vitro.webapp.beans.ObjectPropertyStatement;
/**
* A DataProperty that has some of its values overridden by a FauxProperty.
*
* TODO This is a horrible kluge that should be discarded as soon as we can
* rewrite GroupedPropertyList.
*/
public class FauxDataPropertyWrapper extends DataProperty implements FauxPropertyWrapper{
private final DataProperty innerDP;
private final FauxProperty faux;
public FauxDataPropertyWrapper(DataProperty inner, FauxProperty faux) {
this.innerDP = inner;
this.faux = faux;
}
// ----------------------------------------------------------------------
// Methods where FauxProperty overrides.
// ----------------------------------------------------------------------
@Override
public String getGroupURI() {
String uri = faux.getGroupURI();
if (uri != null) {
return uri;
}
return innerDP.getGroupURI();
}
@Override
public void setGroupURI(String groupUri) {
faux.setGroupURI(groupUri);
innerDP.setGroupURI(groupUri);
}
// -------
@Override
public String getDomainVClassURI() {
String uri = faux.getDomainVClassURI();
if (uri != null) {
return uri;
}
return innerDP.getDomainVClassURI();
}
@Override
public void setDomainVClassURI(String domainClassURI) {
faux.setDomainURI(domainClassURI);
innerDP.setDomainVClassURI(domainClassURI);
}
// -------
@Override
public String getRangeVClassURI() {
String uri = faux.getRangeVClassURI();
if (uri != null) {
return uri;
}
return innerDP.getRangeVClassURI();
}
@Override
public void setRangeVClassURI(String rangeClassURI) {
faux.setRangeURI(rangeClassURI);
innerDP.setRangeVClassURI(rangeClassURI);
}
// -------
@Override
public String getCustomEntryForm() {
String s = faux.getCustomEntryForm();
if (s != null) {
return s;
}
return innerDP.getCustomEntryForm();
}
@Override
public void setCustomEntryForm(String s) {
faux.setCustomEntryForm(s);
innerDP.setCustomEntryForm(s);
}
// -------
@Override
public String getPublicDescription() {
String s = faux.getPublicDescription();
if (s != null) {
return s;
}
return innerDP.getPublicDescription();
}
@Override
public void setPublicDescription(String s) {
faux.setPublicDescription(s);
innerDP.setPublicDescription(s);
}
// -------
@Override
public String getPickListName() {
String name = faux.getDisplayName();
if (name != null) {
return name;
}
return innerDP.getPickListName();
}
@Override
public void setPickListName(String pickListName) {
faux.setDisplayName(pickListName);
innerDP.setPickListName(pickListName);
}
// ----------------------------------------------------------------------
// Methods from DataProperty
// ----------------------------------------------------------------------
@Override
public String getLabel() {
return innerDP.getLabel();
}
@Override
public String getDescription() {
return innerDP.getDescription();
}
@Override
public void setDescription(String description) {
innerDP.setDescription(description);
}
@Override
public String getExample() {
return innerDP.getExample();
}
@Override
public void setExample(String example) {
innerDP.setExample(example);
}
@Override
public int getDisplayTier() {
return faux.getDisplayTier();
}
@Override
public boolean getFunctional() {
return innerDP.getFunctional();
}
@Override
public void setFunctional(boolean functional) {
innerDP.setFunctional(functional);
}
@Override
public void setLabel(String label) {
innerDP.setLabel(label);
}
@Override
public boolean isSubjectSide() {
return innerDP.isSubjectSide();
}
@Override
public boolean isEditLinkSuppressed() {
return innerDP.isEditLinkSuppressed();
}
@Override
public boolean isAddLinkSuppressed() {
return innerDP.isAddLinkSuppressed();
}
@Override
public boolean isDeleteLinkSuppressed() {
return innerDP.isDeleteLinkSuppressed();
}
@Override
public void setEditLinkSuppressed(boolean editLinkSuppressed) {
innerDP.setEditLinkSuppressed(editLinkSuppressed);
}
@Override
public void setAddLinkSuppressed(boolean addLinkSuppressed) {
innerDP.setAddLinkSuppressed(addLinkSuppressed);
}
@Override
public void setDeleteLinkSuppressed(boolean deleteLinkSuppressed) {
innerDP.setDeleteLinkSuppressed(deleteLinkSuppressed);
}
@Override
public boolean isAnonymous() {
return innerDP.isAnonymous();
}
@Override
public String getURI() {
return innerDP.getURI();
}
@Override
public void setURI(String URI) {
innerDP.setURI(URI);
}
@Override
public String getNamespace() {
return innerDP.getNamespace();
}
@Override
public void setNamespace(String namespace) {
innerDP.setNamespace(namespace);
}
@Override
public String getLocalName() {
return innerDP.getLocalName();
}
@Override
public void setLocalName(String localName) {
innerDP.setLocalName(localName);
}
@Override
public String getLocalNameWithPrefix() {
return innerDP.getLocalNameWithPrefix();
}
@Override
public void setLocalNameWithPrefix(String prefixedLocalName) {
innerDP.setLocalNameWithPrefix(prefixedLocalName);
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + ((faux == null) ? 0 : faux.hashCode());
result = prime * result + ((innerDP == null) ? 0 : innerDP.hashCode());
return Objects.hash(innerDP, faux);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!super.equals(obj)) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
FauxDataPropertyWrapper that = (FauxDataPropertyWrapper) obj;
return Objects.equals(this.innerDP, that.innerDP)
&& Objects.equals(this.faux, that.faux);
}
@Override
public List<DataPropertyStatement> getDataPropertyStatements() {
return innerDP.getDataPropertyStatements();
}
@Override
public String toString() {
return String.format("FauxDataPropertyWrapper[ %s ==> %s ==> %s, statementCount=%d, group=%s, customEntryForm=%s ]",
localName(getDomainVClassURI()),
localName(getURI()),
localName(getRangeVClassURI()),
(getDataPropertyStatements() == null ? 0: getDataPropertyStatements().size()),
localName(getGroupURI()),
simpleName(getCustomEntryForm()));
}
private Object simpleName(String classname) {
if (classname == null) {
return null;
} else {
return classname.substring(classname.lastIndexOf(".") + 1);
}
}
private Object localName(String uri) {
if (uri == null) {
return null;
} else {
return ResourceFactory.createResource(uri).getLocalName();
}
}
@Override
public FauxProperty getFauxProperty() {
return faux;
}
@Override
public String getContextUri() {
return faux.getContextUri();
}
}

View file

@ -18,7 +18,7 @@ import edu.cornell.mannlib.vitro.webapp.beans.VClass;
* TODO This is a horrible kluge that should be discarded as soon as we can
* rewrite GroupedPropertyList.
*/
public class FauxObjectPropertyWrapper extends ObjectProperty {
public class FauxObjectPropertyWrapper extends ObjectProperty implements FauxPropertyWrapper{
private final ObjectProperty innerOP;
private final FauxProperty faux;
@ -226,6 +226,10 @@ public class FauxObjectPropertyWrapper extends ObjectProperty {
@Override
public String getRangeEntityURI() {
String uri = faux.getRootRangeUri();
if (uri != null) {
return uri;
}
return innerOP.getRangeEntityURI();
}
@ -372,7 +376,7 @@ public class FauxObjectPropertyWrapper extends ObjectProperty {
@Override
public int getDomainDisplayTier() {
return innerOP.getDomainDisplayTier();
return faux.getDisplayTier();
}
@Override
@ -624,8 +628,11 @@ public class FauxObjectPropertyWrapper extends ObjectProperty {
@Override
public String toString() {
return String.format("FauxObjectPropertyWrapper[ %s <==> %s | %s ==> %s ==> %s, statementCount=%d, group=%s, customEntryForm=%s ]",
getDomainPublic(), getRangePublic(),
localName(getDomainVClassURI()), localName(getURI()), localName(getRangeVClassURI()),
getDomainPublic(),
getRangePublic(),
localName(getDomainVClassURI()),
localName(getURI()),
localName(getRangeVClassURI()),
(getObjectPropertyStatements() == null ? 0: getObjectPropertyStatements().size()),
localName(getGroupURI()),
simpleName(getCustomEntryForm()));
@ -647,4 +654,14 @@ public class FauxObjectPropertyWrapper extends ObjectProperty {
}
}
@Override
public FauxProperty getFauxProperty() {
return faux;
}
@Override
public String getContextUri() {
return faux.getContextUri();
}
}

View file

@ -0,0 +1,10 @@
package edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual;
import edu.cornell.mannlib.vitro.webapp.beans.FauxProperty;
public interface FauxPropertyWrapper {
public FauxProperty getFauxProperty();
public String getContextUri();
}

View file

@ -10,6 +10,8 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@ -17,7 +19,6 @@ import org.apache.commons.logging.LogFactory;
import org.apache.jena.vocabulary.OWL;
import edu.cornell.mannlib.vitro.webapp.beans.DataProperty;
import edu.cornell.mannlib.vitro.webapp.beans.FauxProperty;
import edu.cornell.mannlib.vitro.webapp.beans.Individual;
import edu.cornell.mannlib.vitro.webapp.beans.ObjectProperty;
import edu.cornell.mannlib.vitro.webapp.beans.Property;
@ -25,7 +26,6 @@ import edu.cornell.mannlib.vitro.webapp.beans.PropertyGroup;
import edu.cornell.mannlib.vitro.webapp.beans.PropertyInstance;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.dao.DataPropertyDao;
import edu.cornell.mannlib.vitro.webapp.dao.FauxPropertyDao;
import edu.cornell.mannlib.vitro.webapp.dao.ObjectPropertyDao;
import edu.cornell.mannlib.vitro.webapp.dao.PropertyDao.FullPropertyKey;
import edu.cornell.mannlib.vitro.webapp.dao.PropertyGroupDao;
@ -63,53 +63,53 @@ public class GroupedPropertyList extends BaseTemplateModel {
private List<PropertyGroupTemplateModel> groups;
GroupedPropertyList(Individual subject, VitroRequest vreq,
boolean editing) {
GroupedPropertyList(Individual subject, VitroRequest vreq, boolean editing) {
this.vreq = vreq;
this.subject = subject;
this.wdf = vreq.getWebappDaoFactory();
// Create the property list for the subject. The properties will be put
// into groups later.
List<Property> propertyList = new ArrayList<Property>();
List<Property> allProperties = new ArrayList<Property>();
// First get all the object properties that occur in statements in the
// db with this subject as subject.
// This may include properties that are not defined as
// "possible properties" for a subject of this class,
// so we cannot just rely on getting that list.
List<ObjectProperty> populatedObjectPropertyList = subject
.getPopulatedObjectPropertyList();
List<ObjectProperty> populatedOPs = subject.getPopulatedObjectPropertyList();
Map<String, List<String>> populatedObjTypes = makePopulatedObjTypeMap(
populatedObjectPropertyList);
Map<String, List<String>> populatedObjTypes = makePopulatedObjTypeMap(populatedOPs);
// save applicable ranges before deduping to filter later
populatedObjectPropertyList = dedupe(populatedObjectPropertyList);
populatedOPs = dedupe(populatedOPs);
Collection<ObjectProperty> additions = ApplicationConfigurationOntologyUtils
.getAdditionalFauxSubpropertiesForList(
populatedObjectPropertyList, subject, vreq);
List<FauxObjectPropertyWrapper> populatedFauxOPs = ApplicationConfigurationOntologyUtils.getPopulatedFauxOPs(populatedOPs, subject, vreq);
additions = filterAdditions(additions, populatedObjTypes);
populatedFauxOPs = filterAdditions(populatedFauxOPs, populatedObjTypes);
if (log.isDebugEnabled()) {
for (ObjectProperty t : additions) {
log.debug("addition: " + t);
for (ObjectProperty fauxOP : populatedFauxOPs) {
log.debug("faux object property: " + fauxOP);
}
log.debug("Added " + additions.size() +
" properties due to application configuration ontology");
log.debug("Added " + populatedFauxOPs.size() + " faux object properties due to application configuration ontology");
}
populatedObjectPropertyList.addAll(additions);
if(editing) {
List<Property> possibleFauxProps = ApplicationConfigurationOntologyUtils.getPossibleFauxProps(populatedFauxOPs, subject, vreq, false);
allProperties.addAll(possibleFauxProps);
}
populatedOPs.addAll(populatedFauxOPs);
propertyList.addAll(populatedObjectPropertyList);
allProperties.addAll(populatedOPs);
// If editing this page, merge in object properties applicable to the individual that are currently
// unpopulated, so the properties are displayed to allow statements to be added to these properties.
// RY In future, we should limit this to properties that the user has permission to add properties to.
if (editing) {
propertyList = mergeAllPossibleObjectProperties(populatedObjectPropertyList, propertyList);
List<Property> possibleOPs = getPossibleOPs(populatedOPs, allProperties, subject);
allProperties.addAll(possibleOPs);
}
// Now do much the same with data properties: get the list of populated data properties, then add in placeholders for missing ones
@ -118,25 +118,36 @@ public class GroupedPropertyList extends BaseTemplateModel {
// DataPropertyStatements. Note that this does not apply to object properties, because the queries
// can be customized and thus differ from property to property. So it's easier for now to keep the
// two working in parallel.
List<DataProperty> populatedDataPropertyList = subject
.getPopulatedDataPropertyList();
propertyList.addAll(populatedDataPropertyList);
List<DataProperty> populatedDPs = subject.getPopulatedDataPropertyList();
if (editing) {
mergeAllPossibleDataProperties(propertyList);
List<Property> possibleDPs = getPossibleDPs(populatedDPs, allProperties);
allProperties.addAll(possibleDPs);
}
sort(propertyList);
List<FauxDataPropertyWrapper> populatedFauxDPs = ApplicationConfigurationOntologyUtils.getPopulatedFauxDPs(populatedDPs, subject, vreq);
if(editing) {
List<Property> possibleFauxProps = ApplicationConfigurationOntologyUtils.getPossibleFauxProps(populatedFauxDPs, subject, vreq, true);
allProperties.addAll(possibleFauxProps);
}
populatedDPs.addAll(populatedFauxDPs);
allProperties.addAll(populatedDPs);
sort(allProperties);
// Put the list into groups
List<PropertyGroup> propertyGroupList = addPropertiesToGroups(propertyList);
List<PropertyGroup> propertyGroups = addPropertiesToGroups(allProperties);
// Build the template data model from the groupList
groups = new ArrayList<PropertyGroupTemplateModel>(
propertyGroupList.size());
for (PropertyGroup propertyGroup : propertyGroupList) {
propertyGroups.size());
for (PropertyGroup propertyGroup : propertyGroups) {
groups.add(new PropertyGroupTemplateModel(vreq, propertyGroup,
subject, editing, populatedDataPropertyList,
populatedObjectPropertyList));
subject, editing, populatedDPs,
populatedOPs));
}
if (!editing) {
@ -160,14 +171,20 @@ public class GroupedPropertyList extends BaseTemplateModel {
return map;
}
private List<ObjectProperty> filterAdditions(Collection<ObjectProperty> additions,
private List<FauxObjectPropertyWrapper> filterAdditions(List<FauxObjectPropertyWrapper> populatedFauxOPs,
Map<String, List<String>> populatedObjTypes) {
List<ObjectProperty> filteredAdditions = new ArrayList<ObjectProperty>();
for (ObjectProperty prop : additions) {
List<FauxObjectPropertyWrapper> filteredAdditions = new ArrayList<FauxObjectPropertyWrapper>();
for (FauxObjectPropertyWrapper prop : populatedFauxOPs) {
List<String> allowedTypes = populatedObjTypes.get(prop.getURI());
if(allowedTypes != null && (allowedTypes.contains(prop.getRangeVClassURI())
|| allowedTypes.contains(prop.getRangeEntityURI()) ) ) {
if (allowedTypes == null) {
continue;
}
String rangeVClassURI = prop.getRangeVClassURI();
String rangeEntityURI = prop.getRangeEntityURI();
if(allowedTypes.contains(rangeVClassURI) ) {
filteredAdditions.add(prop);
} else if (allowedTypes.contains(rangeEntityURI)) {
filteredAdditions.add(prop);
}
}
return filteredAdditions;
@ -223,9 +240,7 @@ public class GroupedPropertyList extends BaseTemplateModel {
}
}
private List<Property> mergeAllPossibleObjectProperties(
List<ObjectProperty> populatedObjectPropertyList,
List<Property> propertyList) {
private List<Property> getPossibleOPs(List<ObjectProperty> populatedOPs, List<Property> allProperties, Individual subject) {
// There is no ObjectPropertyDao.getAllPossibleObjectPropertiesForIndividual() parallel to
// DataPropertyDao.getAllPossibleDatapropsForIndividual(). The comparable method for object properties
@ -235,27 +250,27 @@ public class GroupedPropertyList extends BaseTemplateModel {
// breaks blank node structures in the restrictions that determine applicable properties.
WebappDaoFactory wadf = vreq.getLanguageNeutralWebappDaoFactory();
PropertyInstanceDao piDao = wadf.getPropertyInstanceDao();
ObjectPropertyDao opDao = wadf.getObjectPropertyDao();
Set<String> vClassUris = subject.getVClasses().stream().map(vclass -> vclass.getURI()).collect(Collectors.toSet());
Map<String, Property> possiblePropertiesMap = new HashMap<String,Property>();
Collection<PropertyInstance> allPossiblePI = piDao
.getAllPossiblePropInstForIndividual(subject.getURI());
Collection<PropertyInstance> allPossiblePI = piDao.getAllPossiblePropInstForIndividual(subject.getURI());
if (allPossiblePI != null) {
for (PropertyInstance possiblePI : allPossiblePI) {
if (possiblePI != null) {
// use the language-aware wdf because redundancy check
// for display will depend on public label match
ObjectProperty possibleOP = assembleObjectProperty(possiblePI);
ObjectProperty possibleOP = opDao.getObjectPropertyByURI(possiblePI.getPropertyURI());
if (possibleOP == null) {
continue;
}
boolean addToList = true;
for(ObjectProperty populatedOP : populatedObjectPropertyList) {
if (redundant(populatedOP, possibleOP)) {
addToList = false;
}
if (isInPopulatedOPs(populatedOPs, possibleOP)) {
continue;
}
if(addToList) {
propertyList.add(possibleOP);
if (!vClassUris.contains(possibleOP.getDomainVClassURI())) {
continue;
}
possiblePropertiesMap.put(possibleOP.getURI(), possibleOP);
} else {
log.error("a property instance in the Collection created by PropertyInstanceDao.getAllPossiblePropInstForIndividual() is unexpectedly null");
}
@ -267,34 +282,23 @@ public class GroupedPropertyList extends BaseTemplateModel {
// These properties are outside the ontologies (in vitro and vitro public) but need to be added to the list.
// In future, vitro ns props will be phased out. Vitro public properties should be changed so they do not
// constitute a special case (i.e., included in piDao.getAllPossiblePropInstForIndividual()).
ArrayList<Property> possibleProperties = new ArrayList<>(possiblePropertiesMap.values());
for (String propertyUri : VITRO_PROPS_TO_ADD_TO_LIST) {
if (!alreadyOnPropertyList(propertyList, propertyUri)) {
addObjectPropertyToPropertyList(propertyUri, null, null, propertyList);
if (!alreadyOnPropertyList(possibleProperties, propertyUri) && !alreadyOnPropertyList(allProperties, propertyUri)) {
addObjectPropertyToPropertyList(propertyUri, null, null, possibleProperties);
}
}
return propertyList;
return possibleProperties;
}
private ObjectProperty assembleObjectProperty(PropertyInstance pi) {
WebappDaoFactory rawWadf = ModelAccess.on(vreq).getWebappDaoFactory();
ObjectPropertyDao opDao = rawWadf.getObjectPropertyDao();
FauxPropertyDao fpDao = rawWadf.getFauxPropertyDao();
String base = pi.getPropertyURI();
String domain = pi.getDomainClassURI();
String range = pi.getRangeClassURI();
ObjectProperty op = opDao.getObjectPropertyByURIs(base, domain, range);
try {
FauxProperty fp = fpDao.getFauxPropertyByUris(domain, base, range);
if (fp != null) {
return new FauxObjectPropertyWrapper(op, fp);
private boolean isInPopulatedOPs(List<ObjectProperty> populatedOPs, ObjectProperty possibleOP) {
for(ObjectProperty populatedOP : populatedOPs) {
if (redundant(populatedOP, possibleOP)) {
return true;
}
} catch (Exception e) {
log.warn("Couldn't look up the faux property", e);
}
return op;
return false;
}
/**
@ -367,19 +371,19 @@ public class GroupedPropertyList extends BaseTemplateModel {
}
}
protected void mergeAllPossibleDataProperties(List<Property> propertyList) {
protected List<Property> getPossibleDPs(List<DataProperty> populatedDPs, List<Property> allProperties) {
// see comments in mergeAllPossibleObjectProperties() for the reason
// that we need a neutral WebappDaoFactory here.
DataPropertyDao dpDao = vreq.getLanguageNeutralWebappDaoFactory().getDataPropertyDao();
Collection<DataProperty> allDatapropColl = dpDao
.getAllPossibleDatapropsForIndividual(subject.getURI());
List<Property> possibleProperties = new ArrayList<Property>();
Collection<DataProperty> allDatapropColl = dpDao.getAllPossibleDatapropsForIndividual(subject.getURI());
if (allDatapropColl != null) {
for (DataProperty dp : allDatapropColl) {
if (dp != null) {
if (dp.getURI() == null) {
log.error("DataProperty dp returned with null propertyURI from dpDao.getAllPossibleDatapropsForIndividual()");
} else if (!alreadyOnPropertyList(propertyList, dp)) {
propertyList.add(dp);
} else if (!alreadyOnPropertyList(allProperties, dp) && !alreadyOnPropertyList(populatedDPs, dp)) {
possibleProperties.add(dp);
}
} else {
log.error("a data property in the Collection created in DataPropertyDao.getAllPossibleDatapropsForIndividual() is unexpectedly null)");
@ -388,9 +392,10 @@ public class GroupedPropertyList extends BaseTemplateModel {
} else {
log.error("a null Collection is returned from DataPropertyDao.getAllPossibleDatapropsForIndividual())");
}
return possibleProperties;
}
private boolean alreadyOnPropertyList(List<Property> propertyList,
private boolean alreadyOnPropertyList(List<? extends Property> propertyList,
Property p) {
if (p.getURI() == null) {
log.error("Property p has no propertyURI in alreadyOnPropertyList()");
@ -399,8 +404,7 @@ public class GroupedPropertyList extends BaseTemplateModel {
return (alreadyOnPropertyList(propertyList, p.getURI()));
}
private boolean alreadyOnPropertyList(List<Property> propertyList,
String propertyUri) {
private boolean alreadyOnPropertyList(List<? extends Property> propertyList, String propertyUri) {
for (Property p : propertyList) {
String uri = p.getURI();
if (uri != null && uri.equals(propertyUri)) {

View file

@ -17,7 +17,6 @@ import edu.cornell.mannlib.vitro.webapp.beans.Property;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder.Route;
import edu.cornell.mannlib.vitro.webapp.dao.FauxPropertyDao;
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
import edu.cornell.mannlib.vitro.webapp.web.templatemodels.BaseTemplateModel;
@ -40,26 +39,30 @@ public abstract class PropertyTemplateModel extends BaseTemplateModel {
protected String addUrl;
private String name;
private FauxProperty fauxProperty;
private int displayLimit;
PropertyTemplateModel(Property property, Individual subject, VitroRequest vreq, String name) {
this.vreq = vreq;
subjectUri = subject.getURI();
this.property = property;
propertyUri = property.getURI();
localName = property.getLocalName();
this.name = name;
addUrl = "";
fauxProperty = isFauxProperty(property);
if (fauxProperty != null) {
this.name = fauxProperty.getDisplayName();
this.displayLimit = fauxProperty.getDisplayLimit();
if (isFauxProperty(property)) {
FauxProperty fauxProperty = getFauxProperty(property);
this.name = fauxProperty.getDisplayName();
this.displayLimit = fauxProperty.getDisplayLimit();
propertyUri = fauxProperty.getBaseURI();
} else {
propertyUri = property.getURI();
this.name = name;
}
localName = property.getLocalName();
addUrl = "";
setVerboseDisplayValues(property);
}
private FauxProperty getFauxProperty(Property property) {
return ((FauxPropertyWrapper) property).getFauxProperty();
}
protected void setVerboseDisplayValues(Property property) {
// No verbose display for vitro and vitro public properties.
@ -104,15 +107,17 @@ public abstract class PropertyTemplateModel extends BaseTemplateModel {
String editUrl = UrlBuilder.getUrl(getPropertyEditRoute(), "uri", property.getURI());
verboseDisplay.put("propertyEditUrl", editUrl);
if (fauxProperty != null) {
verboseDisplay.put("fauxProperty", assembleFauxPropertyValues(fauxProperty));
if (isFauxProperty(property)) {
verboseDisplay.put("fauxProperty", assembleFauxPropertyValues(getFauxProperty(property)));
}
}
private FauxProperty isFauxProperty(Property prop) {
FauxPropertyDao fpDao = vreq.getUnfilteredWebappDaoFactory().getFauxPropertyDao();
return fpDao.getFauxPropertyByUris(prop.getDomainVClassURI(), prop.getURI(), prop.getRangeVClassURI());
}
private boolean isFauxProperty(Property prop) {
if (prop instanceof FauxPropertyWrapper) {
return true;
}
return false;
}
private Map<String, Object> assembleFauxPropertyValues(FauxProperty fp) {
Map<String, Object> map = new HashMap<>();
@ -168,10 +173,6 @@ public abstract class PropertyTemplateModel extends BaseTemplateModel {
return (addUrl != null) ? addUrl : "";
}
//check to see whether or not this property represents a faux property
public boolean getIsFauxProperty() {
return (fauxProperty != null);
}
public Map<String, Object> getVerboseDisplay() {
return verboseDisplay;
}

View file

@ -1,93 +0,0 @@
package edu.cornell.mannlib.vitro.webapp.i18n;
import static org.junit.Assert.assertEquals;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import org.junit.Before;
import org.junit.Test;
import stubs.javax.servlet.ServletContextStub;
import edu.cornell.mannlib.vitro.testing.AbstractTestClass;
import edu.cornell.mannlib.vitro.webapp.i18n.selection.SelectedLocale;
/* $This file is distributed under the terms of the license in LICENSE$ */
/**
* Test the I18N functionality.
*
* Start by checking the logic that finds approximate matches for
* language-specific property files.
*/
public class I18nTest extends AbstractTestClass {
private static final List<Locale> SELECTABLE_LOCALES = locales("es_MX",
"en_US");
ServletContextStub ctx;
@Before
public void setup() {
ctx = new ServletContextStub();
}
@Test
public void noMatchOnLanguageRegion() {
assertLocales("fr_CA", SELECTABLE_LOCALES, "fr_CA", "fr", "");
}
@Test
public void noMatchOnLanguage() {
assertLocales("fr", SELECTABLE_LOCALES, "fr", "");
}
@Test
public void noMatchOnRoot() {
assertLocales("", SELECTABLE_LOCALES, "");
}
@Test
public void matchOnLanguageRegion() {
assertLocales("es_ES", SELECTABLE_LOCALES, "es_ES", "es", "es_MX", "");
}
@Test
public void matchOnLanguage() {
assertLocales("es", SELECTABLE_LOCALES, "es", "es_MX", "");
}
// ----------------------------------------------------------------------
// Helper methods
// ----------------------------------------------------------------------
private void assertLocales(String requested, List<Locale> selectable,
String... expected) {
SelectedLocale.setSelectableLocales(ctx, selectable);
List<Locale> expectedLocales = locales(expected);
I18n.ThemeBasedControl control = new I18n.ThemeBasedControl(ctx,
"bogusThemeDirectory");
List<Locale> actualLocales = control.getCandidateLocales(
"bogusBaseName", locale(requested));
assertEquals("Expected locales", expectedLocales, actualLocales);
}
private static List<Locale> locales(String... strings) {
List<Locale> locales = new ArrayList<>();
for (String s : strings) {
locales.add(locale(s));
}
return locales;
}
private static Locale locale(String s) {
String[] parts = s.split("_");
String language = (parts.length > 0) ? parts[0] : "";
String country = (parts.length > 1) ? parts[1] : "";
String variant = (parts.length > 2) ? parts[2] : "";
return new Locale(language, country, variant);
}
}

View file

@ -0,0 +1,92 @@
package edu.cornell.mannlib.vitro.webapp.i18n;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import org.apache.jena.graph.NodeFactory;
import org.apache.jena.ontology.OntModel;
import org.apache.jena.rdf.model.Selector;
import org.apache.jena.rdf.model.SimpleSelector;
import org.apache.jena.rdf.model.StmtIterator;
import org.apache.jena.rdf.model.impl.PropertyImpl;
import org.junit.Test;
import stubs.javax.servlet.ServletContextStub;
public class TranslationConverterTest {
private static final String WILMA = "wilma";
private static final String HAS_THEME = "http://vivoweb.org/ontology/core/properties/vocabulary#hasTheme";
private static final String VITRO = "Vitro";
private static final String VIVO = "VIVO";
private static final String HAS_APP = "http://vivoweb.org/ontology/core/properties/vocabulary#hasApp";
private static final String HAS_KEY = "http://vivoweb.org/ontology/core/properties/vocabulary#hasKey";
private static final String ROOT_PATH = "src/test/resources/edu/cornell/mannlib/vitro/webapp/i18n/TranslationConverterTest/root";
private static final String INIT_N3_FILE = "src/test/resources/edu/cornell/mannlib/vitro/webapp/i18n/TranslationConverterTest/modelInitContent.n3";
ServletContextStub ctx = new ServletContextStub();
private OntModel model;
@Test
public void testConversion() throws FileNotFoundException {
VitroResourceBundle.addAppPrefix("customprefix");
VitroResourceBundle.addAppPrefix("vivo");
TranslationConverter converter = TranslationConverter.getInstance();
model = converter.memModel;
File n3 = new File(INIT_N3_FILE);
assertTrue(model.isEmpty());
model.read(new FileReader(n3), null, "n3");
assertFalse(model.isEmpty());
File appI18n = new File(ROOT_PATH + TranslationConverter.APP_I18N_PATH);
File localI18n = new File(ROOT_PATH + TranslationConverter.LOCAL_I18N_PATH);
File themes = new File(ROOT_PATH + TranslationConverter.THEMES_PATH);
ctx.setRealPath(TranslationConverter.APP_I18N_PATH, appI18n.getAbsolutePath());
ctx.setRealPath(TranslationConverter.LOCAL_I18N_PATH, localI18n.getAbsolutePath());
ctx.setRealPath(TranslationConverter.THEMES_PATH, themes.getAbsolutePath());
converter.ctx = ctx;
converter.convertAll();
assertEquals(2, getCount(HAS_KEY, "test_key_all_en_US"));
assertEquals(2, getCount(HAS_KEY, "test_key_all_en_CA"));
assertEquals(2, getCount(HAS_KEY, "test_key_all"));
assertEquals(1, getCount(HAS_KEY, "property_to_overwrite"));
assertTrue(n3TranslationValueIsOverwrittenByProperty(model));
assertEquals(3, getCount(HAS_THEME, WILMA));
assertEquals(6, getCount(HAS_APP, VITRO));
assertEquals(3, getCount(HAS_APP, VIVO));
// printResultModel();
}
private void printResultModel() {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
model.write(baos, "N3");
System.out.println(baos.toString());
}
private int getCount(String hasTheme, String wilma) {
Selector selector = new SimpleSelector(null, new PropertyImpl(hasTheme), wilma);
StmtIterator it = model.listStatements(selector);
int count = 0;
while (it.hasNext()) {
count++;
it.next();
}
return count;
}
private boolean n3TranslationValueIsOverwrittenByProperty(OntModel model) {
return model.getGraph().contains(
NodeFactory.createURI("urn:uuid:8c80dbf5-adda-41d5-a6fe-d5efde663600"),
NodeFactory.createURI("http://www.w3.org/2000/01/rdf-schema#label"),
NodeFactory.createLiteral("value from properties file","en-US"));
}
}

View file

@ -0,0 +1,161 @@
package edu.cornell.mannlib.vitro.webapp.i18n;
import static org.junit.Assert.assertEquals;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.Collections;
import org.apache.jena.query.Dataset;
import org.apache.jena.query.DatasetFactory;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ModelFactory;
import org.junit.Test;
import edu.cornell.mannlib.vitro.webapp.rdfservice.impl.jena.model.RDFServiceModel;
public class TranslationProviderTest {
private static final String VITRO = "Vitro";
private static final String VIVO = "VIVO";
private static final String ROOT = "src/test/resources/edu/cornell/mannlib/vitro/webapp/i18n/TranslationProviderTest/";
private static final String TRANSLATIONS_N3_FILE = ROOT + "modelInitContent.n3";
private static final String WILMA = "wilma";
private static final String NEMO = "nemo";
private Model i18nModel;
private RDFServiceModel rdfService;
private TranslationProvider tp;
public void init(String i18nFile, String themeName, String appName) throws FileNotFoundException {
i18nModel = ModelFactory.createDefaultModel();
i18nModel.read(new FileReader(new File(i18nFile)), null, "n3");
Dataset ds = DatasetFactory.createTxnMem();
ds.addNamedModel("http://vitro.mannlib.cornell.edu/default/interface-i18n", i18nModel);
rdfService = new RDFServiceModel(ds);
tp = TranslationProvider.getInstance();
tp.rdfService = rdfService;
tp.setTheme(themeName);
tp.application = appName;
tp.clearCache();
}
@Test
public void testNotExistingKey() throws FileNotFoundException {
init(TRANSLATIONS_N3_FILE, WILMA, VITRO);
Object array[] = {};
String translation = tp.getTranslation(Collections.singletonList("en-US"), "non_existing_key", array);
assertEquals("ERROR: Translation not found 'non_existing_key'", translation);
}
@Test
public void testVitroWilmaEnUS() throws FileNotFoundException {
init(TRANSLATIONS_N3_FILE, WILMA, VITRO);
Object array[] = {};
String translation = tp.getTranslation(Collections.singletonList("en-US"), "testkey", array);
assertEquals("testkey Vitro wilma en-US", translation);
}
@Test
public void testVitroWilmaDeDE() throws FileNotFoundException {
init(TRANSLATIONS_N3_FILE, WILMA, VITRO);
Object array[] = {};
String translation = tp.getTranslation(Collections.singletonList("de-DE"), "testkey", array);
assertEquals("testkey Vitro wilma de-DE", translation);
}
@Test
public void testVIVOWilmaEnUS() throws FileNotFoundException {
init(TRANSLATIONS_N3_FILE, WILMA, VIVO);
Object array[] = {};
String translation = tp.getTranslation(Collections.singletonList("en-US"), "testkey", array);
assertEquals("testkey VIVO wilma en-US", translation);
}
@Test
public void testVIVOWilmaDeDE() throws FileNotFoundException {
init(TRANSLATIONS_N3_FILE, WILMA, VIVO);
Object array[] = {};
String translation = tp.getTranslation(Collections.singletonList("de-DE"), "testkey", array);
assertEquals("testkey VIVO wilma de-DE", translation);
}
@Test
public void testThemeFallbackVitroNemoEnUS() throws FileNotFoundException {
init(TRANSLATIONS_N3_FILE, NEMO, VITRO);
Object array[] = {};
String translation = tp.getTranslation(Collections.singletonList("en-US"), "testkey", array);
assertEquals("testkey Vitro no theme en-US", translation);
}
@Test
public void testThemeFallbackVitroNemoDeDE() throws FileNotFoundException {
init(TRANSLATIONS_N3_FILE, NEMO, VITRO);
Object array[] = {};
String translation = tp.getTranslation(Collections.singletonList("de-DE"), "testkey", array);
assertEquals("testkey Vitro no theme de-DE", translation);
}
@Test
public void testThemeFallbackVIVONemoEnUS() throws FileNotFoundException {
init(TRANSLATIONS_N3_FILE, NEMO, VIVO);
Object array[] = {};
String translation = tp.getTranslation(Collections.singletonList("en-US"), "testkey", array);
assertEquals("testkey VIVO no theme en-US", translation);
}
@Test
public void testThemeFallbackVIVONemoDeDE() throws FileNotFoundException {
init(TRANSLATIONS_N3_FILE, NEMO, VIVO);
Object array[] = {};
String translation = tp.getTranslation(Collections.singletonList("de-DE"), "testkey", array);
assertEquals("testkey VIVO no theme de-DE", translation);
}
@Test
public void testAppFallbackVIVONemoEnUS() throws FileNotFoundException {
init(TRANSLATIONS_N3_FILE, WILMA, VIVO);
Object array[] = {};
String translation = tp.getTranslation(Collections.singletonList("en-US"), "testkey_app_fallback", array);
assertEquals("testkey_app_fallback Vitro wilma en-US", translation);
}
@Test
public void testAppFallbackVIVONemoDeDE() throws FileNotFoundException {
init(TRANSLATIONS_N3_FILE, WILMA, VIVO);
Object array[] = {};
String translation = tp.getTranslation(Collections.singletonList("de-DE"), "testkey_app_fallback", array);
assertEquals("testkey_app_fallback Vitro wilma de-DE", translation);
}
@Test
public void testAppAndThemeFallbackVIVONemoEnUS() throws FileNotFoundException {
init(TRANSLATIONS_N3_FILE, NEMO, VIVO);
Object array[] = {};
String translation = tp.getTranslation(Collections.singletonList("en-US"), "testkey_app_fallback", array);
assertEquals("testkey_app_fallback Vitro no theme en-US", translation);
}
@Test
public void testAppAndThemeFallbackVIVONemoDeDE() throws FileNotFoundException {
init(TRANSLATIONS_N3_FILE, NEMO, VIVO);
Object array[] = {};
String translation = tp.getTranslation(Collections.singletonList("de-DE"), "testkey_app_fallback", array);
assertEquals("testkey_app_fallback Vitro no theme de-DE", translation);
}
@Test
public void testCache() throws FileNotFoundException {
init(TRANSLATIONS_N3_FILE, WILMA, VITRO);
Object array[] = {};
String translation = tp.getTranslation(Collections.singletonList("en-US"), "testkey", array);
assertEquals("testkey Vitro wilma en-US", translation);
tp.application = VIVO;
translation = tp.getTranslation(Collections.singletonList("en-US"), "testkey", array);
assertEquals("testkey Vitro wilma en-US", translation);
tp.clearCache();
translation = tp.getTranslation(Collections.singletonList("en-US"), "testkey", array);
assertEquals("testkey VIVO wilma en-US", translation);
}
}

View file

@ -51,14 +51,11 @@ public class I18nStub extends I18n {
}
@Override
protected I18nBundle getBundle(String bundleName, HttpServletRequest req) {
return new I18nBundleStub(bundleName);
protected I18nBundle getBundle( HttpServletRequest req) {
return new I18nBundleStub();
}
private class I18nBundleStub extends I18nBundle {
public I18nBundleStub(String bundleName) {
super(bundleName, new DummyResourceBundle(), null);
}
private class I18nBundleStub implements I18nBundle {
@Override
public String text(String key, Object... parameters) {

View file

@ -0,0 +1,12 @@
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
<urn:uuid:8c80dbf5-adda-41d5-a6fe-d5efde663600>
a owl:NamedIndividual , <http://vivoweb.org/ontology/core/properties/vocabulary#PropertyKey> ;
rdfs:label "value from n3 file"@en-US ;
<http://vivoweb.org/ontology/core/properties/vocabulary#hasApp>
"VIVO" ;
<http://vivoweb.org/ontology/core/properties/vocabulary#hasKey>
"property_to_overwrite" .

View file

@ -0,0 +1 @@
test_key_all_en_CA = test value all_en_CA

View file

@ -0,0 +1,2 @@
test_key = test value vivo_all_en_US
property_to_overwrite = value from properties file

View file

@ -0,0 +1 @@
test_key_all_en_US = test value customprefix_all_en_US

View file

@ -0,0 +1 @@
test_key_all_en_CA = test value all_en_CA wilma

View file

@ -0,0 +1 @@
test_key_all_en_US = test value vivo_all_en_US wilma

View file

@ -0,0 +1,77 @@
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
<urn:uuid:8c80dbf5-adda-41d5-a6fe-d5efde663600>
a owl:NamedIndividual , <http://vivoweb.org/ontology/core/properties/vocabulary#PropertyKey> ;
rdfs:label "testkey VIVO no theme en-US"@en-US ;
rdfs:label "testkey VIVO no theme de-DE"@de-DE ;
<http://vivoweb.org/ontology/core/properties/vocabulary#hasApp>
"VIVO" ;
<http://vivoweb.org/ontology/core/properties/vocabulary#hasKey>
"testkey" .
<urn:uuid:8c80dbf5-adda-41d5-a6fe-d5efde663601>
a owl:NamedIndividual , <http://vivoweb.org/ontology/core/properties/vocabulary#PropertyKey> ;
rdfs:label "testkey Vitro no theme en-US"@en-US ;
rdfs:label "testkey Vitro no theme de-DE"@de-DE ;
<http://vivoweb.org/ontology/core/properties/vocabulary#hasApp>
"Vitro" ;
<http://vivoweb.org/ontology/core/properties/vocabulary#hasKey>
"testkey" .
<urn:uuid:8c80dbf5-adda-41d5-a6fe-d5efde663602>
a owl:NamedIndividual , <http://vivoweb.org/ontology/core/properties/vocabulary#PropertyKey> ;
rdfs:label "testkey VIVO wilma en-US"@en-US ;
rdfs:label "testkey VIVO wilma de-DE"@de-DE ;
<http://vivoweb.org/ontology/core/properties/vocabulary#hasApp>
"VIVO" ;
<http://vivoweb.org/ontology/core/properties/vocabulary#hasTheme>
"wilma" ;
<http://vivoweb.org/ontology/core/properties/vocabulary#hasKey>
"testkey" .
<urn:uuid:8c80dbf5-adda-41d5-a6fe-d5efde663603>
a owl:NamedIndividual , <http://vivoweb.org/ontology/core/properties/vocabulary#PropertyKey> ;
rdfs:label "testkey Vitro wilma en-US"@en-US ;
rdfs:label "testkey Vitro wilma de-DE"@de-DE ;
<http://vivoweb.org/ontology/core/properties/vocabulary#hasApp>
"Vitro" ;
<http://vivoweb.org/ontology/core/properties/vocabulary#hasTheme>
"wilma" ;
<http://vivoweb.org/ontology/core/properties/vocabulary#hasKey>
"testkey" .
<urn:uuid:8c80dbf5-adda-41d5-a6fe-d5efde663604>
a owl:NamedIndividual , <http://vivoweb.org/ontology/core/properties/vocabulary#PropertyKey> ;
rdfs:label "testkey Vitro vitro en-US"@en-US ;
rdfs:label "testkey Vitro vitro de-DE"@de-DE ;
<http://vivoweb.org/ontology/core/properties/vocabulary#hasApp>
"Vitro" ;
<http://vivoweb.org/ontology/core/properties/vocabulary#hasTheme>
"vitro" ;
<http://vivoweb.org/ontology/core/properties/vocabulary#hasKey>
"testkey" .
<urn:uuid:8c80dbf5-adda-41d5-a6fe-d5efde663605>
a owl:NamedIndividual , <http://vivoweb.org/ontology/core/properties/vocabulary#PropertyKey> ;
rdfs:label "testkey_app_fallback Vitro wilma en-US"@en-US ;
rdfs:label "testkey_app_fallback Vitro wilma de-DE"@de-DE ;
<http://vivoweb.org/ontology/core/properties/vocabulary#hasApp>
"Vitro" ;
<http://vivoweb.org/ontology/core/properties/vocabulary#hasTheme>
"wilma" ;
<http://vivoweb.org/ontology/core/properties/vocabulary#hasKey>
"testkey_app_fallback" .
<urn:uuid:8c80dbf5-adda-41d5-a6fe-d5efde663606>
a owl:NamedIndividual , <http://vivoweb.org/ontology/core/properties/vocabulary#PropertyKey> ;
rdfs:label "testkey_app_fallback Vitro no theme en-US"@en-US ;
rdfs:label "testkey_app_fallback Vitro no theme de-DE"@de-DE ;
<http://vivoweb.org/ontology/core/properties/vocabulary#hasApp>
"Vitro" ;
<http://vivoweb.org/ontology/core/properties/vocabulary#hasKey>
"testkey_app_fallback" .

View file

@ -167,7 +167,8 @@ proxy.eligibleTypeList = http://www.w3.org/2002/07/owl#Thing
#
# A list of supported languages or Locales that the user may choose to
# use instead of the one specified by the browser. The selected language(s)
# must exist in the Vitro-languages repository. This affects RDF data
# must exist in the list of property files in webapps or in the list of ttl
# files in interface-i18n directories within Vitro home. This affects RDF data
# retrieved from the model, if RDFService.languageFilter is true.
# This also affects the text of pages that have been modified to support
# multiple languages.

View file

@ -0,0 +1,20 @@
# $This file is distributed under the terms of the license in LICENSE$
@prefix default: <http://vitro.mannlib.cornell.edu/ns/default/pages#> .
default:terms_of_use_dg
a <java:edu.cornell.mannlib.vitro.webapp.utils.dataGetter.FixedHTMLDataGetter> ;
<http://vitro.mannlib.cornell.edu/ontologies/display/1.1#htmlValue>
"""
<p>Die Nutzungsbedingungen sollten hier stehen</p>
"""@de-DE ;
<http://vitro.mannlib.cornell.edu/ontologies/display/1.1#saveToVar>
"termsOfUse" .
default:terms_of_use
a <http://vitro.mannlib.cornell.edu/ontologies/display/1.1#Page> ;
<http://vitro.mannlib.cornell.edu/ontologies/display/1.1#hasDataGetter>
default:terms_of_use_dg ;
<http://vitro.mannlib.cornell.edu/ontologies/display/1.1#title>
"Terms of use"@de-DE ;
<http://vitro.mannlib.cornell.edu/ontologies/display/1.1#urlMapping>
"/termsOfUse" .

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,20 @@
# $This file is distributed under the terms of the license in LICENSE$
@prefix default: <http://vitro.mannlib.cornell.edu/ns/default/pages#> .
default:terms_of_use_dg
a <java:edu.cornell.mannlib.vitro.webapp.utils.dataGetter.FixedHTMLDataGetter> ;
<http://vitro.mannlib.cornell.edu/ontologies/display/1.1#htmlValue>
"""
<p>Terms of use should be here</p>
"""@en-CA ;
<http://vitro.mannlib.cornell.edu/ontologies/display/1.1#saveToVar>
"termsOfUse" .
default:terms_of_use
a <http://vitro.mannlib.cornell.edu/ontologies/display/1.1#Page> ;
<http://vitro.mannlib.cornell.edu/ontologies/display/1.1#hasDataGetter>
default:terms_of_use_dg ;
<http://vitro.mannlib.cornell.edu/ontologies/display/1.1#title>
"Terms of use"@en-CA ;
<http://vitro.mannlib.cornell.edu/ontologies/display/1.1#urlMapping>
"/termsOfUse" .

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,20 @@
# $This file is distributed under the terms of the license in LICENSE$
@prefix default: <http://vitro.mannlib.cornell.edu/ns/default/pages#> .
default:terms_of_use_dg
a <java:edu.cornell.mannlib.vitro.webapp.utils.dataGetter.FixedHTMLDataGetter> ;
<http://vitro.mannlib.cornell.edu/ontologies/display/1.1#htmlValue>
"""
<p>Terms of use should be here</p>
"""@en-US ;
<http://vitro.mannlib.cornell.edu/ontologies/display/1.1#saveToVar>
"termsOfUse" .
default:terms_of_use
a <http://vitro.mannlib.cornell.edu/ontologies/display/1.1#Page> ;
<http://vitro.mannlib.cornell.edu/ontologies/display/1.1#hasDataGetter>
default:terms_of_use_dg ;
<http://vitro.mannlib.cornell.edu/ontologies/display/1.1#title>
"Terms of use"@en-US ;
<http://vitro.mannlib.cornell.edu/ontologies/display/1.1#urlMapping>
"/termsOfUse" .

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,4 @@
@prefix vitro-public: <http://vitro.mannlib.cornell.edu/ns/vitro/public#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
vitro-public:storedFile rdfs:label "stored file"@en-US .

View file

@ -0,0 +1,20 @@
# $This file is distributed under the terms of the license in LICENSE$
@prefix default: <http://vitro.mannlib.cornell.edu/ns/default/pages#> .
default:terms_of_use_dg
a <java:edu.cornell.mannlib.vitro.webapp.utils.dataGetter.FixedHTMLDataGetter> ;
<http://vitro.mannlib.cornell.edu/ontologies/display/1.1#htmlValue>
"""
<p>Las condiciones de uso deberían estar aquí</p>
"""@es ;
<http://vitro.mannlib.cornell.edu/ontologies/display/1.1#saveToVar>
"termsOfUse" .
default:terms_of_use
a <http://vitro.mannlib.cornell.edu/ontologies/display/1.1#Page> ;
<http://vitro.mannlib.cornell.edu/ontologies/display/1.1#hasDataGetter>
default:terms_of_use_dg ;
<http://vitro.mannlib.cornell.edu/ontologies/display/1.1#title>
"Terms of use"@es ;
<http://vitro.mannlib.cornell.edu/ontologies/display/1.1#urlMapping>
"/termsOfUse" .

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,20 @@
# $This file is distributed under the terms of the license in LICENSE$
@prefix default: <http://vitro.mannlib.cornell.edu/ns/default/pages#> .
default:terms_of_use_dg
a <java:edu.cornell.mannlib.vitro.webapp.utils.dataGetter.FixedHTMLDataGetter> ;
<http://vitro.mannlib.cornell.edu/ontologies/display/1.1#htmlValue>
"""
<p>Les conditions d'utilisation devraient être ici</p>
"""@fr-CA ;
<http://vitro.mannlib.cornell.edu/ontologies/display/1.1#saveToVar>
"termsOfUse" .
default:terms_of_use
a <http://vitro.mannlib.cornell.edu/ontologies/display/1.1#Page> ;
<http://vitro.mannlib.cornell.edu/ontologies/display/1.1#hasDataGetter>
default:terms_of_use_dg ;
<http://vitro.mannlib.cornell.edu/ontologies/display/1.1#title>
"Terms of use"@fr-CA ;
<http://vitro.mannlib.cornell.edu/ontologies/display/1.1#urlMapping>
"/termsOfUse" .

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,20 @@
# $This file is distributed under the terms of the license in LICENSE$
@prefix default: <http://vitro.mannlib.cornell.edu/ns/default/pages#> .
default:terms_of_use_dg
a <java:edu.cornell.mannlib.vitro.webapp.utils.dataGetter.FixedHTMLDataGetter> ;
<http://vitro.mannlib.cornell.edu/ontologies/display/1.1#htmlValue>
"""
<p>Os termos de uso devem estar aqui</p>
"""@pt-BR ;
<http://vitro.mannlib.cornell.edu/ontologies/display/1.1#saveToVar>
"termsOfUse" .
default:terms_of_use
a <http://vitro.mannlib.cornell.edu/ontologies/display/1.1#Page> ;
<http://vitro.mannlib.cornell.edu/ontologies/display/1.1#hasDataGetter>
default:terms_of_use_dg ;
<http://vitro.mannlib.cornell.edu/ontologies/display/1.1#title>
"Terms of use"@pt-BR ;
<http://vitro.mannlib.cornell.edu/ontologies/display/1.1#urlMapping>
"/termsOfUse" .

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,20 @@
# $This file is distributed under the terms of the license in LICENSE$
@prefix default: <http://vitro.mannlib.cornell.edu/ns/default/pages#> .
default:terms_of_use_dg
a <java:edu.cornell.mannlib.vitro.webapp.utils.dataGetter.FixedHTMLDataGetter> ;
<http://vitro.mannlib.cornell.edu/ontologies/display/1.1#htmlValue>
"""
<p>Условия использования должны находиться здесь</p>
"""@ru-RU ;
<http://vitro.mannlib.cornell.edu/ontologies/display/1.1#saveToVar>
"termsOfUse" .
default:terms_of_use
a <http://vitro.mannlib.cornell.edu/ontologies/display/1.1#Page> ;
<http://vitro.mannlib.cornell.edu/ontologies/display/1.1#hasDataGetter>
default:terms_of_use_dg ;
<http://vitro.mannlib.cornell.edu/ontologies/display/1.1#title>
"Terms of use"@ru-RU ;
<http://vitro.mannlib.cornell.edu/ontologies/display/1.1#urlMapping>
"/termsOfUse" .

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,20 @@
# $This file is distributed under the terms of the license in LICENSE$
@prefix default: <http://vitro.mannlib.cornell.edu/ns/default/pages#> .
default:terms_of_use_dg
a <java:edu.cornell.mannlib.vitro.webapp.utils.dataGetter.FixedHTMLDataGetter> ;
<http://vitro.mannlib.cornell.edu/ontologies/display/1.1#htmlValue>
"""
<p>Uslovi korišćenja bi trebalo da budu ovde</p>
"""@sr-Latn-RS ;
<http://vitro.mannlib.cornell.edu/ontologies/display/1.1#saveToVar>
"termsOfUse" .
default:terms_of_use
a <http://vitro.mannlib.cornell.edu/ontologies/display/1.1#Page> ;
<http://vitro.mannlib.cornell.edu/ontologies/display/1.1#hasDataGetter>
default:terms_of_use_dg ;
<http://vitro.mannlib.cornell.edu/ontologies/display/1.1#title>
"Terms of use"@sr-Latn-RS ;
<http://vitro.mannlib.cornell.edu/ontologies/display/1.1#urlMapping>
"/termsOfUse" .

View file

@ -0,0 +1,39 @@
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix prop-data: <http://vivoweb.org/ontology/core/properties/individual#> .
@prefix prop: <http://vivoweb.org/ontology/core/properties/vocabulary#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix skos: <http://www.w3.org/2004/02/skos/core#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
prop:hasPackage rdf:type owl:DatatypeProperty ;
rdfs:domain prop:PropertyKey ;
rdfs:label "has package" ;
rdfs:range xsd:string .
prop:hasKey rdf:type owl:DatatypeProperty ;
rdfs:comment "Value of the key" ;
rdfs:domain prop:PropertyKey ;
rdfs:label "Propertie file url " ;
rdfs:range xsd:string .
prop:hasTheme rdf:type owl:DatatypeProperty ;
rdfs:domain prop:PropertyKey ;
rdfs:label "has theme" ;
rdfs:range xsd:string .
prop:PropertyKey rdf:type owl:Class ;
rdfs:label skos:Concept ;
rdfs:subClassOf owl:Thing ;
rdfs:subClassOf skos:Concept .
prop:ftlUrl rdf:type owl:DatatypeProperty ;
rdfs:comment "Points to the FTL file containing the key" ;
rdfs:domain prop:PropertyKey ;
rdfs:label "ftl file url" ;
rdfs:range xsd:anyURI .
prop:hasApp rdf:type owl:DatatypeProperty ;
rdfs:domain prop:PropertyKey ;
rdfs:label "has application" ;
rdfs:range xsd:string .

View file

@ -107,11 +107,5 @@
<artifactId>vitro-home</artifactId>
<type>tar.gz</type>
</dependency>
<dependency>
<groupId>org.vivoweb</groupId>
<artifactId>vitro-languages-home-core</artifactId>
<version>${project.version}</version>
<type>tar.gz</type>
</dependency>
</dependencies>
</project>

View file

@ -44,12 +44,6 @@
<artifactId>vitro-webapp</artifactId>
<type>war</type>
</overlay>
<!-- Overlays for multilingual support -->
<overlay>
<groupId>org.vivoweb</groupId>
<artifactId>vitro-languages-webapp-core</artifactId>
<type>war</type>
</overlay>
</overlays>
<webResources>
<resource>
@ -147,14 +141,6 @@
<artifactId>vitro-webapp</artifactId>
<type>war</type>
</dependency>
<!-- Dependency for multilingual support -->
<dependency>
<groupId>org.vivoweb</groupId>
<artifactId>vitro-languages-webapp-core</artifactId>
<version>${project.version}</version>
<type>war</type>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>

View file

@ -21,6 +21,7 @@ edu.cornell.mannlib.vitro.webapp.config.RevisionInfoSetup
edu.cornell.mannlib.vitro.webapp.email.FreemarkerEmailFactory$Setup
edu.cornell.mannlib.vitro.webapp.i18n.selection.LocaleSelectionSetup
edu.cornell.mannlib.vitro.webapp.servlet.setup.ConfigurationModelsSetup
edu.cornell.mannlib.vitro.webapp.servlet.setup.ContentModelSetup
@ -51,7 +52,7 @@ edu.cornell.mannlib.vitro.webapp.services.shortview.ShortViewServiceSetup
edu.ucsf.vitro.opensocial.OpenSocialSmokeTests
# For multiple language support
edu.cornell.mannlib.vitro.webapp.i18n.selection.LocaleSelectionSetup
edu.cornell.mannlib.vitro.webapp.i18n.I18nContextListener
# The search indexer uses a "public" permission, so the PropertyRestrictionPolicyHelper
# and the PermissionRegistry must already be set up.

View file

@ -0,0 +1,8 @@
Please note that although usage of property files for translation of UI labels is supported at the moment,
it is deprecated and not recommended. Please, consider using ontology instead of property file located at:
Source code: [VIVO project]Vitro/home/src/main/resources/rdf/i18n/de_DE/interface-i18n/firsttime/vitro_UiLabel_de_DE.ttl
Deployment: [VIVO home]/rdf/i18n/de_DE/display/interface-i18n/vitro_UiLabel_de_DE.ttl
However, if you decide to use property files, please create and post the file in the same
directory as this Readme file.

View file

@ -0,0 +1,8 @@
Please note that although usage of property files for translation of UI labels is supported at the moment,
it is deprecated and not recommended. Please, consider using ontology instead of property file located at:
Source code: [VIVO project]Vitro/home/src/main/resources/rdf/i18n/en_CA/interface-i18n/firsttime/vitro_UiLabel_en_CA.ttl
Deployment: [VIVO home]/rdf/i18n/en_CA/display/interface-i18n/vitro_UiLabel_en_CA.ttl
However, if you decide to use property files, please create and post the file in the same
directory as this Readme file.

View file

@ -0,0 +1,8 @@
Please note that although usage of property files for translation of UI labels is supported at the moment,
it is deprecated and not recommended. Please, consider using ontology instead of property file located at:
Source code: [VIVO project]Vitro/home/src/main/resources/rdf/i18n/en_US/interface-i18n/firsttime/vitro_UiLabel_en_US.ttl
Deployment: [VIVO home]/rdf/i18n/en_US/display/interface-i18n/vitro_UiLabel_en_US.ttl
However, if you decide to use property files, please create and post the file in the same
directory as this Readme file.

View file

@ -0,0 +1,8 @@
Please note that although usage of property files for translation of UI labels is supported at the moment,
it is deprecated and not recommended. Please, consider using ontology instead of property file located at:
Source code: [VIVO project]Vitro/home/src/main/resources/rdf/i18n/es/interface-i18n/firsttime/vitro_UiLabel_es.ttl
Deployment: [VIVO home]/rdf/i18n/es/display/interface-i18n/vitro_UiLabel_es.ttl
However, if you decide to use property files, please create and post the file in the same
directory as this Readme file.

View file

@ -0,0 +1,8 @@
Please note that although usage of property files for translation of UI labels is supported at the moment,
it is deprecated and not recommended. Please, consider using ontology instead of property file located at:
Source code: [VIVO project]Vitro/home/src/main/resources/rdf/i18n/fr_CA/interface-i18n/firsttime/vitro_UiLabel_fr_CA.ttl
Deployment: [VIVO home]/rdf/i18n/fr_CA/display/interface-i18n/vitro_UiLabel_fr_CA.ttl
However, if you decide to use property files, please create and post the file in the same
directory as this Readme file.

View file

@ -0,0 +1,8 @@
Please note that although usage of property files for translation of UI labels is supported at the moment,
it is deprecated and not recommended. Please, consider using ontology instead of property file located at:
Source code: [VIVO project]Vitro/home/src/main/resources/rdf/i18n/pt_BR/interface-i18n/firsttime/vitro_UiLabel_pt_BR.ttl
Deployment: [VIVO home]/rdf/i18n/pt_BR/display/interface-i18n/vitro_UiLabel_pt_BR.ttl
However, if you decide to use property files, please create and post the file in the same
directory as this Readme file.

View file

@ -0,0 +1,8 @@
Please note that although usage of property files for translation of UI labels is supported at the moment,
it is deprecated and not recommended. Please, consider using ontology instead of property file located at:
Source code: [VIVO project]Vitro/home/src/main/resources/rdf/i18n/ru_RU/interface-i18n/firsttime/vitro_UiLabel_ru_RU.ttl
Deployment: [VIVO home]/rdf/i18n/ru_RU/display/interface-i18n/vitro_UiLabel_ru_RU.ttl
However, if you decide to use property files, please create and post the file in the same
directory as this Readme file.

View file

@ -0,0 +1,8 @@
Please note that although usage of property files for translation of UI labels is supported at the moment,
it is deprecated and not recommended. Please, consider using ontology instead of property file located at:
Source code: [VIVO project]Vitro/home/src/main/resources/rdf/i18n/sr_Latn_RS/interface-i18n/firsttime/vitro_UiLabel_sr_Latn_RS.ttl
Deployment: [VIVO home]/rdf/i18n/sr_Latn_RS/display/interface-i18n/vitro_UiLabel_sr_Latn_RS.ttl
However, if you decide to use property files, please create and post the file in the same
directory as this Readme file.

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