From 3314e5a4b09fe721400583d64416ac80eb9070f7 Mon Sep 17 00:00:00 2001
From: hudajkhan
Date: Tue, 3 Sep 2013 15:34:02 -0400
Subject: [PATCH 1/4] updates for label management
---
.../individual/IndividualResponseBuilder.java | 4 +-
.../ManageLabelsForIndividualGenerator.java | 574 ++++++++++++++++++
.../ConceptSparqlUpdatePreprocessor.java | 129 ++++
.../FoafNameToRdfsLabelPreprocessor.java | 17 +-
...ManageLabelsForIndividualPreprocessor.java | 111 ++++
webapp/web/i18n/all.properties | 3 +-
.../individual/manageLabelsForIndividual.js | 223 ++++++-
.../individual/manageLabelsForIndividual.ftl | 107 ++--
.../manageLabelsForIndividualAddForm.ftl | 29 +
.../manageLabelsForIndividualMacros.ftl | 79 +++
...ageLabelsForIndividualSubmissionErrors.ftl | 14 +
.../freemarker/lib/lib-properties.ftl | 11 +-
12 files changed, 1226 insertions(+), 75 deletions(-)
create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/ManageLabelsForIndividualGenerator.java
create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/ConceptSparqlUpdatePreprocessor.java
create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/ManageLabelsForIndividualPreprocessor.java
create mode 100644 webapp/web/templates/freemarker/body/individual/manageLabelsForIndividualAddForm.ftl
create mode 100644 webapp/web/templates/freemarker/body/individual/manageLabelsForIndividualMacros.ftl
create mode 100644 webapp/web/templates/freemarker/body/individual/manageLabelsForIndividualSubmissionErrors.ftl
diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/individual/IndividualResponseBuilder.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/individual/IndividualResponseBuilder.java
index e63791df5..2ddca87c2 100644
--- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/individual/IndividualResponseBuilder.java
+++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/individual/IndividualResponseBuilder.java
@@ -279,7 +279,9 @@ class IndividualResponseBuilder {
log.debug("queryStr = " + queryStr);
int theCount = 0;
try {
- ResultSet results = QueryUtils.getQueryResults(queryStr, vreq);
+ //ResultSet results = QueryUtils.getQueryResults(queryStr, vreq);
+ //Get query results across all languages in order for template to show manage labels link correctly
+ ResultSet results = QueryUtils.getLanguageNeutralQueryResults(queryStr, vreq);
if (results.hasNext()) {
QuerySolution soln = results.nextSolution();
String countStr = soln.get("labelCount").toString();
diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/ManageLabelsForIndividualGenerator.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/ManageLabelsForIndividualGenerator.java
new file mode 100644
index 000000000..a9cb131d7
--- /dev/null
+++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/ManageLabelsForIndividualGenerator.java
@@ -0,0 +1,574 @@
+/* $This file is distributed under the terms of the license in /doc/license.txt$ */
+package edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.generators;
+
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import javax.servlet.http.HttpSession;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import com.hp.hpl.jena.ontology.OntModel;
+import com.hp.hpl.jena.query.Dataset;
+import com.hp.hpl.jena.query.QueryExecution;
+import com.hp.hpl.jena.query.QueryExecutionFactory;
+import com.hp.hpl.jena.query.QuerySolution;
+import com.hp.hpl.jena.query.ResultSet;
+import com.hp.hpl.jena.rdf.model.Literal;
+import com.hp.hpl.jena.rdf.model.RDFNode;
+import com.hp.hpl.jena.shared.Lock;
+import com.hp.hpl.jena.sparql.resultset.ResultSetMem;
+import com.hp.hpl.jena.vocabulary.RDFS;
+import com.hp.hpl.jena.vocabulary.XSD;
+
+import edu.cornell.mannlib.vitro.webapp.auth.policy.PolicyHelper;
+import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.Actions;
+import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.ifaces.RequestActionConstants;
+import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.propstmt.AddDataPropertyStatement;
+import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.propstmt.AddObjectPropertyStatement;
+import edu.cornell.mannlib.vitro.webapp.beans.DataProperty;
+import edu.cornell.mannlib.vitro.webapp.beans.DataPropertyStatement;
+import edu.cornell.mannlib.vitro.webapp.beans.Individual;
+import edu.cornell.mannlib.vitro.webapp.beans.VClass;
+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.ParamMap;
+import edu.cornell.mannlib.vitro.webapp.dao.ModelAccess;
+import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
+import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
+import edu.cornell.mannlib.vitro.webapp.dao.jena.QueryUtils;
+import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditConfigurationUtils;
+import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditConfigurationVTwo;
+import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.fields.FieldVTwo;
+import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.preprocessors.FoafNameToRdfsLabelPreprocessor;
+import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.preprocessors.ManageLabelsForIndividualPreprocessor;
+import edu.cornell.mannlib.vitro.webapp.i18n.selection.LocaleSelectionDataGetter;
+import edu.cornell.mannlib.vitro.webapp.i18n.selection.LocaleSelectorUtilities;
+import edu.cornell.mannlib.vitro.webapp.i18n.selection.SelectedLocale;
+import edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual.DataPropertyStatementTemplateModel;
+
+/**
+ *This allows the page to show all the labels for a particular individual and sets up code
+ *enabling the addition of a new label. Links on the page will allow for removal or editing of a given label.
+ */
+public class ManageLabelsForIndividualGenerator extends BaseEditConfigurationGenerator implements EditConfigurationGenerator {
+ public static Log log = LogFactory.getLog(ManageLabelsForIndividualGenerator.class);
+ private static String template = "manageLabelsForIndividual.ftl";
+ private HashMap> labelsSortedByLanguage = null;
+ private List existingLabelLiterals = null;
+ //list of language names sorted alphabetically
+ private List existingSortedLanguageNameList = null;
+ //This would be for the full list and can be used for the existing labels list as well
+
+ private HashMap fullLanguageNameToCodeMap = null;
+ private static String predicateUri = RDFS.label.getURI();
+ @Override
+ public EditConfigurationVTwo getEditConfiguration(VitroRequest vreq, HttpSession session) {
+
+ EditConfigurationVTwo config = new EditConfigurationVTwo();
+ config.setTemplate(this.getTemplate());
+
+ initBasics(config, vreq);
+ initPropertyParameters(vreq, session, config);
+
+ //This form is technically not an object property form in the true sense
+ //or a data property form because it is used to list the various labels
+ //and allow for adding new labels
+ //URL to return to is the same page once addition is complete
+ this.setUrlToReturnTo(config, vreq);
+
+ config.setSubjectUri(EditConfigurationUtils.getSubjectUri(vreq));
+
+ setVarNames(config);
+ config.setDatapropKey( EditConfigurationUtils.getDataHash(vreq) );
+ //Add n3, fields, etc. in the case where the user wants to add a label
+ //N3 required should be empty since the addition of a label is optional in this case
+ config.setN3Required(this.generateN3Required(vreq));
+ config.setN3Optional(this.generateN3Optional(vreq));
+ this.setUrisAndLiteralsOnForm(config, vreq);
+ setUrisAndLiteralsInScope(config);
+ this.setFields(config, vreq, EditConfigurationUtils
+ .getPredicateUri(vreq));
+
+ //Get existing labels
+ //this.initExistingLabels(config, vreq);
+
+ //Add form specific data used to populate template
+ addFormSpecificData(config, vreq);
+ //This preprocessor handles getting the correct label language and putting the attribute on the label
+ config.addEditSubmissionPreprocessor(
+ new ManageLabelsForIndividualPreprocessor(config));
+ //This will handle generating the label from the first name and last name and also make sure to associate
+ //a language with that label
+ config.addModelChangePreprocessor(new FoafNameToRdfsLabelPreprocessor());
+
+ prepare(vreq, config);
+ return config;
+ }
+
+ private void setUrlToReturnTo(EditConfigurationVTwo editConfiguration, VitroRequest vreq) {
+ editConfiguration.setUrlPatternToReturnTo(EditConfigurationUtils.getFormUrlWithoutContext(vreq));
+ }
+
+ private void setVarNames(EditConfigurationVTwo editConfiguration) {
+ editConfiguration.setVarNameForSubject("subject");
+ editConfiguration.setVarNameForPredicate("predicate");
+
+ }
+
+
+ private List generateN3Required(VitroRequest vreq) {
+ List n3Required = new ArrayList();
+ return n3Required;
+ }
+
+ private List generateN3Optional(VitroRequest vreq) {
+ List n3Optional = new ArrayList();
+ String predicateUri = EditConfigurationUtils.getPredicateUri(vreq);
+ String n3 = "?subject <" + predicateUri + "> ?label ";
+ //n3 used if the subject is a person
+ String personN3 = this.N3_PREFIX + "?subject foaf:firstName ?firstName ; foaf:lastName ?lastName .";
+ n3Optional.add(n3);
+ n3Optional.add(personN3);
+ return n3Optional;
+ }
+
+
+
+ private void setFields(EditConfigurationVTwo editConfiguration, VitroRequest vreq, String predicateUri) {
+ Map fields = new HashMap();
+ editConfiguration.setFields(fields);
+ editConfiguration.addField(new FieldVTwo().
+ setName("label").
+ setValidators(getLabelValidators(vreq, editConfiguration)));
+ editConfiguration.addField(new FieldVTwo(
+ ).setName("newLabelLanguage"));
+ //no validators since all of this is optional
+ //there should be error-checking client side though
+ editConfiguration.addField(new FieldVTwo().
+ setName("firstName").
+ setValidators(getFirstNameValidators(vreq, editConfiguration)));
+
+ editConfiguration.addField(new FieldVTwo().
+ setName("lastName").
+ setValidators(getLastNameValidators(vreq, editConfiguration)));
+ }
+
+ //first and last name have validators if is person is true
+ private List getFirstNameValidators(VitroRequest vreq, EditConfigurationVTwo config) {
+ List validators = new ArrayList();
+ if(isPersonType(vreq, config)) {
+ validators.add("nonempty");
+ }
+ return validators;
+ }
+
+ private List getLastNameValidators(VitroRequest vreq, EditConfigurationVTwo config) {
+ List validators = new ArrayList();
+ if(isPersonType(vreq, config)) {
+ validators.add("nonempty");
+ }
+ return validators;
+ }
+
+ //validate label if person is not true
+ private List getLabelValidators(VitroRequest vreq, EditConfigurationVTwo config) {
+ List validators = new ArrayList();
+ if(!isPersonType(vreq, config)) {
+ validators.add("nonempty");
+ }
+ return validators;
+ }
+
+
+
+ private void setUrisAndLiteralsOnForm(EditConfigurationVTwo config,
+ VitroRequest vreq) {
+ List literalsOnForm = new ArrayList();
+ literalsOnForm.add("label");
+ literalsOnForm.add("newLabelLanguage");
+ //optional for person
+ literalsOnForm.add("firstName");
+ literalsOnForm.add("lastName");
+ config.setLiteralsOnForm(literalsOnForm);
+
+ }
+
+
+ private void setUrisAndLiteralsInScope(EditConfigurationVTwo editConfiguration) {
+ HashMap> urisInScope = new HashMap>();
+ //note that at this point the subject, predicate, and object var parameters have already been processed
+ urisInScope.put(editConfiguration.getVarNameForSubject(),
+ Arrays.asList(new String[]{editConfiguration.getSubjectUri()}));
+ urisInScope.put(editConfiguration.getVarNameForPredicate(),
+ Arrays.asList(new String[]{editConfiguration.getPredicateUri()}));
+ editConfiguration.setUrisInScope(urisInScope);
+ //Uris in scope include subject, predicate, and object var
+
+ editConfiguration.setLiteralsInScope(new HashMap>());
+ }
+
+ private void initExistingLabels(EditConfigurationVTwo config,
+ VitroRequest vreq) {
+ this.existingLabelLiterals = this.getExistingLabels(config.getSubjectUri(), vreq);
+ // this.labelsSortedByLanguage = this.getLabelsSortedByLanguage(config,vreq);
+ //language names sorted for the existing languages
+ // this.existingSortedLanguageNameList = getExistingSortedLanguageNamesList();
+
+ //Generate a label to language code hash map
+ //TODO:
+
+ //HashMap labelToLanguageCode = new HashMap();
+
+ //this.labels = getExistingLabels(config.getSubjectUri(), vreq);
+ //this.labelsSortedByLanguage = getLabelsSortedByLanguage(config.getSubjectUri(), vreq);
+
+ }
+
+
+ private List getExistingSortedLanguageNamesList() {
+ HashSet existingLanguages = new HashSet();
+ for(Literal l: this.existingLabelLiterals) {
+ String language = l.getLanguage();
+ if(!existingLanguages.contains(language)) {
+ existingLanguages.add(language);
+ }
+ }
+ List sortedNames = new ArrayList(existingLanguages);
+ //sort alphabetically
+ Collections.sort(sortedNames);
+ return sortedNames;
+ }
+
+
+ private void addFormSpecificData(EditConfigurationVTwo config,
+ VitroRequest vreq) {
+ //Get all language codes/labels in the system, and this list is sorted by language name
+ List> locales = this.getLocales(vreq);
+ //Get code to label hashmap - we use this to get the language name for the language code returned in the rdf literal
+ HashMap localeCodeToNameMap = this.getFullCodeToLanguageNameMap(locales);
+ //the labels already added by the user
+ ArrayList existingLabels = this.getExistingLabels(config.getSubjectUri(), vreq);
+ //existing labels keyed by language name and each of the list of labels is sorted by language name
+ HashMap> existingLabelsByLanguageName = this.getLabelsSortedByLanguageName(existingLabels, localeCodeToNameMap, config, vreq);
+ //Get available locales for the drop down for adding a new label, also sorted by language name
+ HashSet existingLanguageNames = new HashSet(existingLabelsByLanguageName.keySet());
+ List> availableLocalesForAdd = getAvailableLocales(locales, existingLanguageNames);
+
+
+ //Save all locales
+ config.addFormSpecificData("selectLocaleFullList", locales);
+ //Save labels sorted by language name, untyped have "untyped" as the language name value
+ config.addFormSpecificData("labelsSortedByLanguageName", existingLabelsByLanguageName);
+ config.addFormSpecificData("selectLocale",availableLocalesForAdd);
+
+
+ //How do we edit? Will need to see
+ config.addFormSpecificData("deleteWebpageUrl", "/edit/primitiveDelete");
+
+
+ Individual subject = vreq.getWebappDaoFactory().getIndividualDao().getIndividualByURI(config.getSubjectUri());
+ if( subject != null && subject.getName() != null ){
+ config.addFormSpecificData("subjectName", subject.getName());
+ }else{
+ config.addFormSpecificData("subjectName", null);
+ }
+
+ //Put in whether or not person type
+ if(isPersonType(vreq, config)) {
+ //Doing this b/c unsure how freemarker will handle boolean value from JAVA
+ config.addFormSpecificData("isPersonType", "true");
+ } else {
+ config.addFormSpecificData("isPersonType", "false");
+
+ }
+
+ //Include whether or not editable to enable edit/remove links and add to show up
+ config.addFormSpecificData("editable", isEditable(vreq, config));
+ }
+
+
+
+ //Based on what locales have already been selected for labels, return a list of
+ //locales for which new labels can be added and have these sorted by the name of the language
+ private List> getAvailableLocales(List> allLocales,
+ HashSet existingLabelsLanguageNames) {
+ List> availableLocales = new ArrayList>();
+ for(HashMap localeInfo: allLocales) {
+ String languageName = (String) localeInfo.get("label");
+ //If this language label is NOT in the labels sorted by language, then available
+ //for selection when creating a new label
+ //The assumption here is we don't want to allow the user to add a new label when a label
+ //already exists in that language
+ if(languageName != "untyped" && !existingLabelsLanguageNames.contains(languageName)) {
+ availableLocales.add(localeInfo);
+ }
+ }
+ //Sort list by language label and return
+ Collections.sort(availableLocales, new Comparator>() {
+ public int compare(HashMap h1, HashMap h2) {
+ String languageName1 = (String) h1.get("label");
+ String languageName2 = (String) h2.get("label");
+ return languageName1.compareTo(languageName2);
+ }
+ });
+
+ return availableLocales;
+ }
+
+
+ private Object isEditable(VitroRequest vreq, EditConfigurationVTwo config) {
+ Individual individual = EditConfigurationUtils.getIndividual(vreq, config.getSubjectUri());
+ AddDataPropertyStatement adps = new AddDataPropertyStatement(
+ vreq.getJenaOntModel(), individual.getURI(),
+ RequestActionConstants.SOME_URI);
+ AddObjectPropertyStatement aops = new AddObjectPropertyStatement(
+ vreq.getJenaOntModel(), individual.getURI(),
+ RequestActionConstants.SOME_URI,
+ RequestActionConstants.SOME_URI);
+ return PolicyHelper.isAuthorizedForActions(vreq, new Actions(adps).or(aops));
+ }
+
+
+ //Copied from NewIndividualFormGenerator
+ //TODO: Refactor so common code can be used by both generators
+ public String getFOAFPersonClassURI() {
+ return "http://xmlns.com/foaf/0.1/Person";
+ }
+
+ public boolean isPersonType(VitroRequest vreq, EditConfigurationVTwo config) {
+ WebappDaoFactory wdf = vreq.getWebappDaoFactory();
+ Boolean isPersonType = Boolean.FALSE;
+ String foafPersonType = getFOAFPersonClassURI();
+ List vclasses = this.getVClasses(config, vreq);
+ if( vclasses != null ){
+ for( VClass v: vclasses){
+ String typeUri = v.getURI();
+ if( foafPersonType.equals(typeUri)) {
+ isPersonType = Boolean.TRUE;
+ break;
+ }
+ }
+ }
+ return isPersonType;
+ }
+
+ //how to get the type of the individual in question
+ public List getVClasses(EditConfigurationVTwo config, VitroRequest vreq) {
+ Individual subject = EditConfigurationUtils.getIndividual(vreq, config.getSubjectUri());
+ //Get the vclasses appropriate for this subject
+ return subject.getVClasses();
+ }
+
+ //Languages sorted by language name
+ private HashMap> getLabelsSortedByLanguageName(List labels, Map localeCodeToNameMap, EditConfigurationVTwo config,
+ VitroRequest vreq) {
+ String subjectUri = config.getSubjectUri();
+ String propertyUri = config.getPredicateUri();
+
+
+ //Iterate through the labels and create a hashmap
+ HashMap> labelsHash= new HashMap>();
+
+ for(Literal l: labels) {
+ String languageTag = l.getLanguage();
+ String languageName = "";
+ if(languageTag == "") {
+ languageName = "untyped";
+ }
+ else if(localeCodeToNameMap.containsKey(languageTag)) {
+ languageName = localeCodeToNameMap.get(languageTag);
+ } else {
+ log.warn("This language tag " + languageTag + " does not have corresponding name in the system and was not processed");
+ }
+
+ if(languageName != "") {
+ if(!labelsHash.containsKey(languageName)) {
+ labelsHash.put(languageName, new ArrayList());
+ }
+ ArrayList labelsList = (ArrayList)labelsHash.get(languageName);
+ //This should put the label in the list
+ //Create label information instance with the required information
+ //To generate link
+ DataPropertyStatementTemplateModel dpstm = new DataPropertyStatementTemplateModel(subjectUri, propertyUri, l,
+ template, vreq);
+ labelsList.add(new LabelInformation(
+ l, dpstm.getEditUrl(), dpstm.getDeleteUrl(), languageTag, languageName));
+ }
+ }
+
+ //Sort each label list
+ LabelInformationComparator lic = new LabelInformationComparator();
+ for(String languageName: labelsHash.keySet()) {
+ List labelInfo = labelsHash.get(languageName);
+ Collections.sort(labelInfo, lic);
+ }
+ return labelsHash;
+
+ }
+
+
+ public static class LabelInformationComparator implements Comparator {
+
+ public int compare(LabelInformation l1, LabelInformation l2) {
+ return l1.getLabelStringValue().compareTo(l2.getLabelStringValue());
+ }
+ }
+
+
+ private static String LABEL_QUERY = ""
+ + "PREFIX rdfs: \n"
+ + "SELECT DISTINCT ?label WHERE { \n"
+ + " ?subject rdfs:label ?label \n"
+ + "} ORDER BY ?label";
+
+
+ private ArrayList getExistingLabels(String subjectUri, VitroRequest vreq) {
+ String queryStr = QueryUtils.subUriForQueryVar(LABEL_QUERY, "subject", subjectUri);
+ log.debug("queryStr = " + queryStr);
+
+ ArrayList labels = new ArrayList();
+ try {
+ //We want to get the labels for all the languages, not just the display language
+ ResultSet results = QueryUtils.getLanguageNeutralQueryResults(queryStr, vreq);
+ while (results.hasNext()) {
+ QuerySolution soln = results.nextSolution();
+ Literal nodeLiteral = soln.get("label").asLiteral();
+ labels.add(nodeLiteral);
+
+
+ }
+ } catch (Exception e) {
+ log.error(e, e);
+ }
+ return labels;
+}
+
+
+
+ //Putting this into a method allows overriding it in subclasses
+ protected String getEditForm() {
+ return null;
+ //return AddEditWebpageFormGenerator.class.getName();
+ }
+
+
+ protected String getTemplate() {
+ return template;
+ }
+
+
+
+ //get locales
+ public List> getLocales(VitroRequest vreq) {
+ List selectables = SelectedLocale.getSelectableLocales(vreq);
+ if (selectables.isEmpty()) {
+ return Collections.emptyList();
+ }
+ List> list = new ArrayList>();
+ Locale currentLocale = SelectedLocale.getCurrentLocale(vreq);
+ for (Locale locale : selectables) {
+ try {
+ list.add(buildLocaleMap(locale, currentLocale));
+ } catch (FileNotFoundException e) {
+ log.warn("Can't show the Locale selector for '" + locale
+ + "': " + e);
+ }
+ }
+
+ return list;
+ }
+
+
+
+ public HashMap getFullCodeToLanguageNameMap(List> localesList) {
+ HashMap codeToLanguageMap = new HashMap();
+ for(Map locale: localesList) {
+ String code = (String) locale.get("code");
+ String label = (String) locale.get("label");
+ if(!codeToLanguageMap.containsKey(code)) {
+ codeToLanguageMap.put(code, label);
+ }
+ else {
+ log.warn("Language code " + code + " for " + label + " was not associated in map becayse label already exists");
+ }
+ }
+ return codeToLanguageMap;
+ }
+
+ public List getFullLanguagesNamesSortedList(List> localesList) {
+ HashSet languageNamesSet = new HashSet();
+ for(Map locale: localesList) {
+ String label = (String) locale.get("label");
+ if(!languageNamesSet.contains(label)) {
+ languageNamesSet.add(label);
+ }
+
+ }
+ List languageNames = new ArrayList(languageNamesSet);
+ Collections.sort(languageNames);
+ return languageNames;
+ }
+
+ //copied from locale selection data getter but don't need all this information
+ private HashMap buildLocaleMap(Locale locale,
+ Locale currentLocale) throws FileNotFoundException {
+ HashMap map = new HashMap();
+ //Replacing the underscore with a hyphen because that is what is represented in the actual literals
+ map.put("code", locale.toString().replace("_", "-"));
+ map.put("label", locale.getDisplayName(currentLocale));
+ return map;
+ }
+
+ //Class used to store the information needed for the template, such as the labels, their languages, their edit links
+ public class LabelInformation {
+ private Literal labelLiteral = null;
+ private String editLinkURL;
+ private String deleteLinkURL;
+ private String languageCode; //languageCode
+ private String languageName;
+ public LabelInformation(Literal inputLiteral, String inputEditLinkURL, String inputDeleteLinkURL, String inputLanguageCode, String inputLanguageName) {
+ this.labelLiteral = inputLiteral;
+ this.editLinkURL = inputEditLinkURL;
+ this.deleteLinkURL = inputDeleteLinkURL;
+ this.languageCode = inputLanguageCode;
+ this.languageName = inputLanguageName;
+ }
+
+
+ public Literal getLabelLiteral() {
+ return this.labelLiteral;
+ }
+
+ public String getLabelStringValue() {
+ return this.labelLiteral.getString();
+ }
+
+ public String getEditLinkURL() {
+ return this.editLinkURL;
+ }
+
+ public String getDeleteLinkURL() {
+ return this.deleteLinkURL;
+ }
+ public String getLanguageCode() {
+ return this.languageCode;
+ }
+
+ public String getLanguageName() {
+ return this.languageName;
+ }
+ }
+
+ private String N3_PREFIX = "@prefix foaf: .\n";
+
+}
diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/ConceptSparqlUpdatePreprocessor.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/ConceptSparqlUpdatePreprocessor.java
new file mode 100644
index 000000000..04b2d3cad
--- /dev/null
+++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/ConceptSparqlUpdatePreprocessor.java
@@ -0,0 +1,129 @@
+/* $This file is distributed under the terms of the license in /doc/license.txt$ */
+
+package edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.preprocessors;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import com.hp.hpl.jena.ontology.OntModel;
+import com.hp.hpl.jena.query.Dataset;
+import com.hp.hpl.jena.query.Query;
+import com.hp.hpl.jena.query.QueryExecution;
+import com.hp.hpl.jena.query.QueryExecutionFactory;
+import com.hp.hpl.jena.query.QueryFactory;
+import com.hp.hpl.jena.query.QuerySolutionMap;
+import com.hp.hpl.jena.query.Syntax;
+import com.hp.hpl.jena.rdf.model.Literal;
+import com.hp.hpl.jena.rdf.model.Model;
+import com.hp.hpl.jena.rdf.model.ModelFactory;
+import com.hp.hpl.jena.rdf.model.Property;
+import com.hp.hpl.jena.rdf.model.ResIterator;
+import com.hp.hpl.jena.rdf.model.Resource;
+import com.hp.hpl.jena.rdf.model.ResourceFactory;
+import com.hp.hpl.jena.rdf.model.Statement;
+import com.hp.hpl.jena.shared.Lock;
+import com.hp.hpl.jena.vocabulary.RDF;
+import com.hp.hpl.jena.vocabulary.RDFS;
+
+import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
+import edu.cornell.mannlib.vitro.webapp.dao.jena.DatasetWrapper;
+import edu.cornell.mannlib.vitro.webapp.dao.jena.DatasetWrapperFactory;
+
+//We are representing semantic types from the UMLS Semantic Network as OWL Classes
+//and this preprocessor will add the appropriate class information to the TBox
+
+public class ConceptSparqlUpdatePreprocessor implements ModelChangePreprocessor {
+
+ private static String VIVOCore = "http://vivoweb.org/ontology/core#";
+ private static String SKOSConceptType = "http://www.w3.org/2004/02/skos/core#Concept";
+ private Log log = LogFactory.getLog(ConceptSparqlUpdatePreprocessor.class);
+
+ private OntModel toUpdateModel = null;
+ private DatasetWrapperFactory dwf = null;
+
+ //Custom constructor
+ public ConceptSparqlUpdatePreprocessor(OntModel updateModel, DatasetWrapperFactory inputDwf) {
+ this.toUpdateModel = updateModel;
+ this.dwf = inputDwf;
+ }
+
+ @Override
+ public void preprocess(Model retractionsModel, Model additionsModel,
+ HttpServletRequest request) {
+ //Run a construct query against the additions model
+ String prefixes = "PREFIX RDFS:<" + RDFS.getURI() + "> " +
+ "PREFIX OWL: " +
+ "PREFIX RDF:<" + RDF.getURI() + ">";
+ String constructQuery = prefixes + " CONSTRUCT { " +
+ "?semanticType rdf:type OWL:Class. { " +
+ "?semanticType rdfs:subClassOf SKOS:Concept . { " +
+ "?semanticType rdfs:label ?label. { " +
+ "} WHERE { " +
+ "?concept rdf:type ?semanticType. { " +
+ "?semanticType rdfs:label ?label .{ " +
+ "?semanticType rdfs:subClassOf SKOS:Concept .{ " +
+ "}";
+
+ //Execute construct query
+ Model constructedModel = ModelFactory.createDefaultModel();
+
+
+ log.debug("CONSTRUCT query string " + constructQuery);
+
+ Query query = null;
+ try {
+ query = QueryFactory.create(constructQuery, Syntax.syntaxARQ);
+ } catch(Throwable th){
+ log.error("Could not create CONSTRUCT SPARQL query for query " +
+ "string. " + th.getMessage());
+ log.error(constructQuery);
+ return;
+ }
+
+
+
+ DatasetWrapper w = dwf.getDatasetWrapper();
+ Dataset dataset = w.getDataset();
+ dataset.getLock().enterCriticalSection(Lock.READ);
+ QueryExecution qe = null;
+ try {
+ qe = QueryExecutionFactory.create(
+ query, dataset);
+ qe.execConstruct(constructedModel);
+ } catch (Exception e) {
+ log.error("Error getting constructed model for query string " + constructQuery);
+ } finally {
+ if (qe != null) {
+ qe.close();
+ }
+ dataset.getLock().leaveCriticalSection();
+ w.close();
+ }
+
+ //Add constructed model to the designated update model
+ toUpdateModel.enterCriticalSection(Lock.WRITE);
+ try {
+ toUpdateModel.add(constructedModel);
+ } catch (Exception e) {
+ log.error("Error adding statements to update model for " + constructQuery);
+ } finally {
+ toUpdateModel.leaveCriticalSection();
+ }
+
+ //Take this constructed model and remove from the additions model
+ additionsModel.enterCriticalSection(Lock.WRITE);
+ try {
+ additionsModel.remove(constructedModel.listStatements().toList());
+ } catch (Exception e) {
+ log.error("Error removing statements from additions model for " + constructQuery);
+ } finally {
+ additionsModel.leaveCriticalSection();
+ }
+
+ }
+
+
+
+}
diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/FoafNameToRdfsLabelPreprocessor.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/FoafNameToRdfsLabelPreprocessor.java
index 49e979740..bbb280f2a 100644
--- a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/FoafNameToRdfsLabelPreprocessor.java
+++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/FoafNameToRdfsLabelPreprocessor.java
@@ -4,6 +4,7 @@ package edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.preprocess
import javax.servlet.http.HttpServletRequest;
+import com.hp.hpl.jena.rdf.model.Literal;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.Property;
import com.hp.hpl.jena.rdf.model.ResIterator;
@@ -30,7 +31,21 @@ public class FoafNameToRdfsLabelPreprocessor implements ModelChangePreprocessor
Statement fname = sub.getProperty( firstNameP );
Statement lname = sub.getProperty( lastNameP );
if( fname != null && lname != null && fname.getString() != null && lname.getString() != null ){
- additionsModel.add(sub, rdfsLabelP, lname.getString() + ", " + fname.getString() );
+ //Check if there are languages associated with first name and last name and add the language
+ //attribute to the label
+ //This preprocessor is used in multiple places, including for managing labels
+ Literal firstNameLiteral = fname.getLiteral();
+ Literal lastNameLiteral = lname.getLiteral();
+ String firstNameLanguage = firstNameLiteral.getLanguage();
+ String lastNameLanguage = lastNameLiteral.getLanguage();
+ String newLabel = lname.getString() + ", " + fname.getString();
+ if(firstNameLanguage != null && lastNameLanguage != null && firstNameLanguage.equals(lastNameLanguage)) {
+ //create a literal with the appropriate value and the language
+ Literal labelWithLanguage = additionsModel.createLiteral(newLabel, firstNameLanguage);
+ additionsModel.add(sub, rdfsLabelP, labelWithLanguage);
+ } else {
+ additionsModel.add(sub, rdfsLabelP, newLabel );
+ }
}
}
diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/ManageLabelsForIndividualPreprocessor.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/ManageLabelsForIndividualPreprocessor.java
new file mode 100644
index 000000000..bb7967d64
--- /dev/null
+++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/ManageLabelsForIndividualPreprocessor.java
@@ -0,0 +1,111 @@
+/* $This file is distributed under the terms of the license in /doc/license.txt$ */
+
+package edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.preprocessors;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+
+import com.hp.hpl.jena.ontology.OntModel;
+import com.hp.hpl.jena.rdf.model.Literal;
+import com.hp.hpl.jena.rdf.model.Model;
+import com.hp.hpl.jena.rdf.model.Property;
+import com.hp.hpl.jena.rdf.model.ResIterator;
+import com.hp.hpl.jena.rdf.model.Resource;
+import com.hp.hpl.jena.rdf.model.Statement;
+
+import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
+/*
+ * This preprocessor is used to set the language attribute on the label based on the user selection
+ * on the manage labels page when adding a new label.
+ */
+import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.BaseEditSubmissionPreprocessorVTwo;
+import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditConfigurationVTwo;
+import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.MultiValueEditSubmission;
+
+public class ManageLabelsForIndividualPreprocessor extends BaseEditSubmissionPreprocessorVTwo {
+
+
+
+
+ public ManageLabelsForIndividualPreprocessor(EditConfigurationVTwo editConfig) {
+ super(editConfig);
+
+ }
+
+ @Override
+ public void preprocess(MultiValueEditSubmission inputSubmission) {
+ //Check and see if a language was selected by the user, and this is the regular label submission
+ //TODO: Check if firstname and lastname should be changed here or elsewhere
+ if(inputSubmission.hasLiteralValue("label") && inputSubmission.hasLiteralValue("newLabelLanguage")) {
+ Map> literalsFromForm = inputSubmission.getLiteralsFromForm();
+ List newLabelLanguages = literalsFromForm.get("newLabelLanguage");
+ List labels = literalsFromForm.get("label");
+
+ //Expecting only one language
+ if(labels.size() > 0 && newLabelLanguages.size() > 0) {
+ Literal newLabelLanguage = newLabelLanguages.get(0);
+ Literal labelLiteral = labels.get(0);
+ //Get the string
+ String lang = this.getLanguage(newLabelLanguage.getString());
+ String label = labelLiteral.getString();
+ //Now add the language category to the literal
+ Literal labelWithLanguage = inputSubmission.createLiteral(label,
+ newLabelLanguage.getDatatypeURI(),
+ lang);
+ labels = new ArrayList();
+ labels.add(labelWithLanguage);
+ //replace the label with one with language, again assuming only one label being returned
+ literalsFromForm.put("label", labels);
+ inputSubmission.setLiteralsFromForm(literalsFromForm);
+ }
+ }
+ //First name and last name would also have a language selected so make sure those literals are also
+ //correctly typed
+ if(inputSubmission.hasLiteralValue("firstName") && inputSubmission.hasLiteralValue("lastName") && inputSubmission.hasLiteralValue("newLabelLanguage")) {
+ Map> literalsFromForm = inputSubmission.getLiteralsFromForm();
+ List newLabelLanguages = literalsFromForm.get("newLabelLanguage");
+ List firstNames = literalsFromForm.get("firstName");
+ List lastNames = literalsFromForm.get("lastName");
+
+ //Expecting only one language
+ if(firstNames.size() > 0 && lastNames.size() > 0 && newLabelLanguages.size() > 0) {
+ Literal newLabelLanguage = newLabelLanguages.get(0);
+ Literal firstNameLiteral = firstNames.get(0);
+ Literal lastNameLiteral = lastNames.get(0);
+ //Get the string
+ String lang = this.getLanguage(newLabelLanguage.getString());
+ String firstNameValue = firstNameLiteral.getString();
+ String lastNameValue = lastNameLiteral.getString();
+ //Now add the language category to the literal
+ Literal firstNameWithLanguage = inputSubmission.createLiteral(firstNameValue,
+ null,
+ lang);
+ Literal lastNameWithLanguage = inputSubmission.createLiteral(lastNameValue,
+ null,
+ lang);
+ firstNames = new ArrayList();
+ lastNames = new ArrayList();
+ firstNames.add(firstNameWithLanguage);
+ lastNames.add(lastNameWithLanguage);
+ //replace the label with one with language, again assuming only one label being returned
+ literalsFromForm.put("firstName", firstNames);
+ literalsFromForm.put("lastName", lastNames);
+ inputSubmission.setLiteralsFromForm(literalsFromForm);
+ }
+ }
+
+ }
+
+ //The language code returned from JAVA locales has an underscore whereas we need a hyphen
+ private String getLanguage(String inputLanguageCode) {
+ if(inputLanguageCode.contains("_")) {
+ return inputLanguageCode.replace("_", "-");
+ }
+ return inputLanguageCode;
+ }
+
+}
diff --git a/webapp/web/i18n/all.properties b/webapp/web/i18n/all.properties
index 6fb58986b..7980d00a9 100644
--- a/webapp/web/i18n/all.properties
+++ b/webapp/web/i18n/all.properties
@@ -675,7 +675,8 @@ photo = Photo
no_image = no image
placeholder_image = placeholder image
manage_labels = manage labels
-
+add_label = Add Label
+add_label_for_language = Language
unsupported_ie_version = This form is not supported in versions of Internet Explorer below version 8. Please upgrade your browser, or switch to another browser, such as FireFox.
#
diff --git a/webapp/web/js/individual/manageLabelsForIndividual.js b/webapp/web/js/individual/manageLabelsForIndividual.js
index cd91e9033..7eb54c92e 100644
--- a/webapp/web/js/individual/manageLabelsForIndividual.js
+++ b/webapp/web/js/individual/manageLabelsForIndividual.js
@@ -6,9 +6,10 @@ var manageLabels = {
onLoad: function() {
- this.mixIn();
+ this.mixIn();
+ this.initObjects();
this.initPage();
-
+
var selectedRadio;
},
@@ -18,24 +19,86 @@ var manageLabels = {
$.extend(this, customFormData);
$.extend(this, i18nStrings);
},
+
+ initObjects:function() {
+ this.addLabelForm = $('#addLabelForm');
+ this.showFormButtonWrapper = $('#showAddForm');
+ this.showFormButton = $("#showAddFormButton");
+ this.addLabelCancel = this.addLabelForm.find(".cancel");
+ this.submit = this.addLabelForm.find('input#submit');
+ this.labelLanguage = this.addLabelForm.find("#newLabelLanguage");
+ this.existingLabelsList = $("#existingLabelsList");
+ },
// Initial page setup. Called only at page load.
initPage: function() {
+ //disable submit until user selects a language
+ this.submit.attr('disabled', 'disabled');
+ this.submit.addClass('disabledSubmit');
+ if(this.submissionErrorsExist == "false") {
+ //hide the form to add label
+ this.addLabelForm.hide();
+ //the cancel in add label can be unbound until the form is visible
+ //this.addLabelCancel.unbind("click");
+ } else {
+ //Display the form
+ this.onShowAddForm();
- $('input#submit').attr('disabled', 'disabled');
- $('input#submit').addClass('disabledSubmit');
+ }
+
+
this.bindEventListeners();
},
bindEventListeners: function() {
- $('input:radio').click( function() {
- manageLabels.selectedRadio = $(this);
- $('input#submit').attr('disabled', '');
- $('input#submit').removeClass('disabledSubmit');
+ this.labelLanguage.change( function() {
+ //if language selected, allow submission, otherwise disallow
+ var selectedLanguage = manageLabels.labelLanguage.val();
+ if(selectedLanguage != "") {
+ manageLabels.submit.attr('disabled', '');
+ manageLabels.submit.removeClass('disabledSubmit');
+ } else {
+ manageLabels.submit.attr('disabled', 'disabled');
+ manageLabels.submit.addClass('disabledSubmit');
+ }
+ });
+
+ //enable form to add label to be displayed or hidden
+ this.showFormButton.click(function() {
+ //clear the inputs for the label if the button is being clicked
+ manageLabels.clearAddForm();
+ manageLabels.onShowAddForm();
+ });
+
+ //Check for clicking on existing labels list remove links
+ //Note addition will refresh the page and removing will remove the item so adding event listeners
+ //to remove links should keep remove link events in synch with page
+
+ this.existingLabelsList.find("a.remove").click(function(event) {
+ var message = "Are you sure you wish to delete this label?"
+ if (!confirm(message)) {
+ return false;
+ }
+
+ //First check with confirmation whether or not they want to delete
+ manageLabels.processLabelDeletion(this);
+ return false;
+ });
+
+
+ this.addLabelForm.find("a.cancel").click(function(){
+ //clear the add form
+ manageLabels.clearAddForm();
+ //hide the add form
+ manageLabels.onHideAddForm();
+
});
+ //TODO: Add method to check that language is selected on submission
+
+ /*
$('input#submit').click( function() {
manageLabels.processLabel(manageLabels.selectedRadio);
$('span.or').hide();
@@ -43,24 +106,47 @@ var manageLabels = {
$('span#indicator').removeClass('hidden');
$('input.submit').addClass('disabledSubmit');
$('input.submit').attr('disabled', 'disabled');
- });
+ });*/
},
-
- processLabel: function(selectedRadio) {
-
+ clearAddForm:function() {
+ //clear inputs and select
+ manageLabels.addLabelForm.find("input[type='text'],select").val("");
+ //set the button for save to be disabled again
+ manageLabels.submit.attr('disabled', 'disabled');
+ manageLabels.submit.addClass('disabledSubmit');
+ },
+ onShowAddForm:function() {
+ manageLabels.addLabelForm.show();
+ manageLabels.showFormButtonWrapper.hide();
+ manageLabels.addLabelCancel.click(function(){
+ //Canceling the add label form will hide the form
+ manageLabels.addLabelForm.hide();
+ manageLabels.showFormButtonWrapper.show();
+ });
+ },
+
+ onHideAddForm:function() {
+ manageLabels.addLabelForm.hide();
+ manageLabels.showFormButtonWrapper.show();
+ //manageLabels.addLabelCancel.unbind("click");
+ },
+ //Remove label
+ processLabelDeletion: function(selectedLink) {
+
// PrimitiveDelete only handles one statement, so we have to use PrimitiveRdfEdit to handle multiple
// retractions if they exist. But PrimitiveRdfEdit also handles assertions, so pass an empty string
// for "additions"
var add = "";
- var retract = "";
-
- $('input:radio').each( function() {
- if ( !$(this).is(':checked') ) {
- retract += " <" + manageLabels.individualUri + "> "
- + "\"" + $(this).attr('id') + "\"" + $(this).attr('tagOrType') + " ." ;
- }
- });
+ var labelValue = $(selectedLink).attr('labelValue');
+ var tagOrTypeValue = $(selectedLink).attr('tagOrType');
+ if(tagOrTypeValue == "untyped") {
+ tagOrTypeValue = "";
+ }
+ var retract = "<" + manageLabels.individualUri + "> "
+ + "\"" + $(selectedLink).attr('labelValue') + "\"" + $(selectedLink).attr('tagOrType') + " ." ;
+
+
retract = retract.substring(0,retract.length -1);
@@ -72,28 +158,103 @@ var manageLabels = {
retractions: retract
},
dataType: 'json',
- context: selectedRadio, // context for callback
+ context: selectedLink, // context for callback
complete: function(request, status) {
if (status == 'success') {
- $('span.or').show();
- $('a.cancel').show();
- $('span#indicator').addClass('hidden');
- window.location = $('a.cancel').attr('href');
+ //Remove the label from the list
+ manageLabels.removeLabelFromList(selectedLink);
+ manageLabels.updateLocaleSelection();
}
else {
+ //Instead of alert, write error to template
alert(manageLabels.errorProcessingLabels);
- selectedRadio.removeAttr('checked');
- $('span.or').show();
- $('a.cancel').show();
- $('span#indicator').addClass('hidden');
- $('input.submit').removeClass('disabledSubmit');
- $('input.submit').attr('disabled', '');
+
}
}
});
},
+ removeLabelFromList:function(selectedLink) {
+ var languageName = $(selectedLink).attr("languageName");
+ $(selectedLink).parent().remove();
+ //See if there are any other remove link
+ if(languageCode != "untyped") {
+ //find if there are any other remove links for the same language
+ var removeLinks = manageLabels.existingLabelsList.find("a.remove[languageName='" + languageName + "']");
+ if(removeLinks.length == 0) {
+ //if there aren't any other labels for this language, also remove the heading
+ manageLabels.existingLabelsList.find("h3[languageName='" + langaugeName + "']").remove();
+
+ }
+ }
+
+ },
+ //Determine if there are new locales that can be added to the options once a delete has occurred
+ updateLocaleSelection:function() {
+ //Check what languages remain
+ var existingLanguages = {};
+ //Look at which languages are currently represented
+ manageLabels.existingLabelsList.find("a.remove").each(function(){
+ var languageCode = $(this).attr("languageCode");
+ if(!(languageCode in existingLanguages)) {
+ existingLanguages[languageCode] = true;
+ }
+ });
+
+ //Now check against full list, if any in full list not represented, will need to include in dropdown
+ //This is a list of
+ var availableLocalesList = [];
+ var listLen = selectLocalesFullList.length;
+ var i;
+ for(i = 0; i < listLen; i++) {
+ var possibleLanguageInfo = selectLocalesFullList[i];
+ var possibleLanguageCode = possibleLanguageInfo["code"];
+ var possibleLangaugeLabel = possibleLanguageInfo["label"];
+ if(!(possibleLanguageCode in existingLanguages)) {
+ //manageLabels.addLanguageCode(possibleLanguageCode, possibleLanguageLabel);
+ availableLocalesList.push(possibleLanguageInfo);
+ }
+ }
+
+ //Now sort this list by the label property on the object
+ availableLocalesList.sort(function(a, b) {
+ var compA = a["label"];
+ var compB = b["label"];
+ return compA < compB ? -1 : 1;
+ });
+ //Now replace dropdown with this new list
+ manageLabels.generateLocalesDropdown(availableLocalesList);
+
+ },
+ generateLocalesDropdown:function(availableLocalesList) {
+ //First check if there are any available locales left, if not then hide the entire add form
+ //technically, this first part should never be invoked client side because
+ //this can only happen on ADD not remove, and add will refresh the page
+ //On the other hand the show add button etc. can be displayed
+ if(availableLocalesList.length == 0) {
+ //Hide the add form if there are no locales left that can be added
+ manageLabels.addLabelForm.hide();
+ manageLabels.showFormButtonWrapper.hide();
+ } else {
+ //There are some locales so generate the dropdown accordingly, removing all elements but the first
+ $("#newLabelLanguage option:gt(0)").remove();
+ var i;
+ var len = availableLocalesList.length;
+ for(i = 0; i < len; i++) {
+ var localeInfo = availableLocalesList[i];
+ manageLabels.addLocaleInfo(localeInfo);
+ }
+ //Put some value in that shows whether neither add button nor add form were shown
+ //because the form thought there were no available locales
+ }
+ },
+
+ addLocaleInfo:function(localeInfo) {
+ //Add code to dropdown
+ //Would we need to regenerate alphabetically? Argh.
+ manageLabels.labelLanguage.append("" + localeInfo["label"] + " ");
+ }
};
diff --git a/webapp/web/templates/freemarker/body/individual/manageLabelsForIndividual.ftl b/webapp/web/templates/freemarker/body/individual/manageLabelsForIndividual.ftl
index bf5d84337..6c5492faa 100644
--- a/webapp/web/templates/freemarker/body/individual/manageLabelsForIndividual.ftl
+++ b/webapp/web/templates/freemarker/body/individual/manageLabelsForIndividual.ftl
@@ -1,62 +1,93 @@
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
<#-- Custom form for managing labels for individuals -->
+<#import "manageLabelsForIndividualMacros.ftl" as m >
+<#assign requiredHint = " * " />
+<#assign subjectUri = editConfiguration.subjectUri/>
<#assign labelStr = "" >
<#assign languageTag = "" >
<#assign labelSeq = [] >
-<#if subjectName?? >
-${i18n().manage_labels_for} ${subjectName}
+<#assign submissionErrorsExist = "false"/>
+<#assign selectLocalesFullList = {} />
+<#assign editable = false/>
+<#if editConfiguration.pageData.editable?has_content>
+ <#assign editable = editConfiguration.pageData.editable />
+#if>
+<#if editSubmission?has_content && editSubmission.submissionExists = true && editSubmission.validationErrors?has_content>
+ <#assign submissionErrors = editSubmission.validationErrors/>
+ <#assign submissionErrorsExist = "true" />
+#if>
+
+<#if editConfiguration.pageData.subjectName?? >
+${i18n().manage_labels_for} ${editConfiguration.pageData.subjectName}
<#else>
${i18n().manage_labels_capitalized}
#if>
+
+
+
${i18n().manage_labels_intro}
+
+
+
+ <#if editable>
+ <#include "manageLabelsForIndividualSubmissionErrors.ftl">
+
+
+ <#include "manageLabelsForIndividualAddForm.ftl" >
+ #if>
+
+
+
+
diff --git a/webapp/web/templates/freemarker/body/individual/manageLabelsForIndividualAddForm.ftl b/webapp/web/templates/freemarker/body/individual/manageLabelsForIndividualAddForm.ftl
new file mode 100644
index 000000000..e6d6714c3
--- /dev/null
+++ b/webapp/web/templates/freemarker/body/individual/manageLabelsForIndividualAddForm.ftl
@@ -0,0 +1,29 @@
+<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
+<#--The form for adding a new label-->
+
\ No newline at end of file
diff --git a/webapp/web/templates/freemarker/body/individual/manageLabelsForIndividualMacros.ftl b/webapp/web/templates/freemarker/body/individual/manageLabelsForIndividualMacros.ftl
new file mode 100644
index 000000000..35839dada
--- /dev/null
+++ b/webapp/web/templates/freemarker/body/individual/manageLabelsForIndividualMacros.ftl
@@ -0,0 +1,79 @@
+<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
+<#--LabelsSorted is a hash keyed by language name where the value is a list of LabelInformation class objects-->
+<#macro displayExistingLabelsForLanguage lang labelsSorted editable editGenerator>
+ <#--get label information for this language-->
+ <#assign labelList = labelsSorted[lang] />
+ <#--Reset for every language-->
+ <#assign labelSeq = []/>
+ <#list labelList as labelObject>
+ <#assign labelLiteral = labelObject.labelLiteral />
+ <#assign labelStringValue = labelObject.labelStringValue />
+ <#--Try label as label literal-->
+ <#assign label = labelLiteral />
+ <#assign labelLang = labelObject.languageName />
+ <#assign languageCode = labelObject.languageCode />
+ <#assign labelEditLink = labelObject.editLinkURL />
+ <#if label?? && ( label?index_of("@") > -1 ) >
+ <#assign labelStr = label?substring(0, label?index_of("@")) >
+ <#assign tagOrTypeStr = label?substring(label?index_of("@")) >
+ <#elseif label?? && ( label?index_of("^^") > -1 ) >
+ <#assign labelStr = label?substring(0, label?index_of("^^")) >
+ <#assign tagOrTypeStr = label?substring(label?index_of("^^")) >
+ <#assign tagOrTypeStr = tagOrTypeStr?replace("^^http","^^
+ <#assign tagOrTypeStr = tagOrTypeStr?replace("#string","#string>") >
+ <#else>
+ <#assign labelStr = label >
+ <#assign tagOrTypeStr = "" >
+ #if>
+ ${labelStr} <#if labelSeq?seq_contains(labelStr)> (duplicate value) #if>
+ <#if editable && labelEditLink?has_content> Edit
+ ${i18n().remove_capitalized}
+ #if>
+
+
+ <#assign labelSeq = labelSeq + [labelStr]>
+ #list>
+#macro>
+
+<#--ignore 'untyped' and display everything-->
+<#macro displayExistingTypedLabels langList labelsSorted editable editGenerator>
+ <#list langList as lang>
+ <#if lang != "untyped">
+ ${lang}
+ <#--get label information for this language-->
+ <#assign labelList = labelsSorted[lang] />
+ <#--Reset for every language-->
+ <#assign labelSeq = []/>
+ <#list labelList as labelObject>
+ <#assign labelLiteral = labelObject.labelLiteral />
+ <#assign labelStringValue = labelObject.labelStringValue />
+ <#--Try label as label literal-->
+ <#assign label = labelLiteral />
+ <#assign labelLang = labelObject.languageName />
+ <#assign languageCode = labelObject.languageCode />
+ <#assign labelEditLink = labelObject.editLinkURL />
+ <#if label?? && ( label?index_of("@") > -1 ) >
+ <#assign labelStr = label?substring(0, label?index_of("@")) >
+ <#assign tagOrTypeStr = label?substring(label?index_of("@")) >
+ <#elseif label?? && ( label?index_of("^^") > -1 ) >
+ <#assign labelStr = label?substring(0, label?index_of("^^")) >
+ <#assign tagOrTypeStr = label?substring(label?index_of("^^")) >
+ <#assign tagOrTypeStr = tagOrTypeStr?replace("^^http","^^
+ <#assign tagOrTypeStr = tagOrTypeStr?replace("#string","#string>") >
+ <#else>
+ <#assign labelStr = label >
+ <#assign tagOrTypeStr = "" >
+ #if>
+ ${labelStr} <#if labelSeq?seq_contains(labelStr)> (duplicate value) #if>
+ <#if editable && labelEditLink?has_content> Edit
+ ${i18n().remove_capitalized}
+ #if>
+
+
+ <#assign labelSeq = labelSeq + [labelStr]>
+ #list>
+ #if>
+ #list>
+#macro>
\ No newline at end of file
diff --git a/webapp/web/templates/freemarker/body/individual/manageLabelsForIndividualSubmissionErrors.ftl b/webapp/web/templates/freemarker/body/individual/manageLabelsForIndividualSubmissionErrors.ftl
new file mode 100644
index 000000000..ef4f8fe95
--- /dev/null
+++ b/webapp/web/templates/freemarker/body/individual/manageLabelsForIndividualSubmissionErrors.ftl
@@ -0,0 +1,14 @@
+<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
+<#if submissionErrors?has_content >
+
+
+
+ <#list submissionErrors?keys as errorFieldName>
+ <#if errorFieldName == "label">
+ ${i18n().enter_value_name_field}
+ #if>
+
+ #list>
+
+
+#if>
\ No newline at end of file
diff --git a/webapp/web/templates/freemarker/lib/lib-properties.ftl b/webapp/web/templates/freemarker/lib/lib-properties.ftl
index 7d360496a..f48adc194 100644
--- a/webapp/web/templates/freemarker/lib/lib-properties.ftl
+++ b/webapp/web/templates/freemarker/lib/lib-properties.ftl
@@ -209,13 +209,18 @@ name will be used as the label. -->
<#-- Label -->
<#macro label individual editable labelCount>
+ <#assign labelPropertyUri = ("http://www.w3.org/2000/01/rdf-schema#label"?url) />
+ <#-- Will need to deal with multiple languages as well-->
<#local label = individual.nameStatement>
${label.value}
<#if (labelCount > 1) && editable >
+ <#-- Changing this so that manage labels now goes to generator -->
-
- ${i18n().manage_labels}
-
+ <#--Previous link which went to manage labels controller-->
+ <#--a id="manageLabels" href="${urls.base}/manageLabels?subjectUri=${individual.uri!}"-->
+
+
<#else>
<@editingLinks "label" label editable />
From 9ec7d11cab04b67035986516134c612f2cb879a7 Mon Sep 17 00:00:00 2001
From: hudajkhan
Date: Wed, 4 Sep 2013 12:22:46 -0400
Subject: [PATCH 2/4] label management and concept semantic type
---
... => ConceptSemanticTypesPreprocessor.java} | 36 +++++++--------
webapp/web/i18n/all.properties | 3 +-
.../individual/manageLabelsForIndividual.js | 46 +++++++++++--------
.../individual/manageLabelsForIndividual.ftl | 10 ++--
.../freemarker/lib/lib-properties.ftl | 6 +--
5 files changed, 53 insertions(+), 48 deletions(-)
rename webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/{ConceptSparqlUpdatePreprocessor.java => ConceptSemanticTypesPreprocessor.java} (78%)
diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/ConceptSparqlUpdatePreprocessor.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/ConceptSemanticTypesPreprocessor.java
similarity index 78%
rename from webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/ConceptSparqlUpdatePreprocessor.java
rename to webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/ConceptSemanticTypesPreprocessor.java
index 04b2d3cad..b95733b4f 100644
--- a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/ConceptSparqlUpdatePreprocessor.java
+++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/ConceptSemanticTypesPreprocessor.java
@@ -34,36 +34,35 @@ import edu.cornell.mannlib.vitro.webapp.dao.jena.DatasetWrapperFactory;
//We are representing semantic types from the UMLS Semantic Network as OWL Classes
//and this preprocessor will add the appropriate class information to the TBox
-public class ConceptSparqlUpdatePreprocessor implements ModelChangePreprocessor {
+public class ConceptSemanticTypesPreprocessor implements ModelChangePreprocessor {
private static String VIVOCore = "http://vivoweb.org/ontology/core#";
private static String SKOSConceptType = "http://www.w3.org/2004/02/skos/core#Concept";
- private Log log = LogFactory.getLog(ConceptSparqlUpdatePreprocessor.class);
+ private Log log = LogFactory.getLog(ConceptSemanticTypesPreprocessor.class);
private OntModel toUpdateModel = null;
- private DatasetWrapperFactory dwf = null;
//Custom constructor
- public ConceptSparqlUpdatePreprocessor(OntModel updateModel, DatasetWrapperFactory inputDwf) {
+ public ConceptSemanticTypesPreprocessor(OntModel updateModel) {
this.toUpdateModel = updateModel;
- this.dwf = inputDwf;
}
@Override
public void preprocess(Model retractionsModel, Model additionsModel,
HttpServletRequest request) {
//Run a construct query against the additions model
- String prefixes = "PREFIX RDFS:<" + RDFS.getURI() + "> " +
- "PREFIX OWL: " +
- "PREFIX RDF:<" + RDF.getURI() + ">";
+ String prefixes = "PREFIX rdfs:<" + RDFS.getURI() + "> " +
+ "PREFIX owl: " +
+ "PREFIX rdf:<" + RDF.getURI() + ">" +
+ "PREFIX skos:";
String constructQuery = prefixes + " CONSTRUCT { " +
- "?semanticType rdf:type OWL:Class. { " +
- "?semanticType rdfs:subClassOf SKOS:Concept . { " +
- "?semanticType rdfs:label ?label. { " +
+ "?semanticType rdf:type owl:Class. " +
+ "?semanticType rdfs:subClassOf skos:Concept . " +
+ "?semanticType rdfs:label ?label. " +
"} WHERE { " +
- "?concept rdf:type ?semanticType. { " +
- "?semanticType rdfs:label ?label .{ " +
- "?semanticType rdfs:subClassOf SKOS:Concept .{ " +
+ "?concept rdf:type ?semanticType. " +
+ "?semanticType rdfs:label ?label . " +
+ "?semanticType rdfs:subClassOf skos:Concept . " +
"}";
//Execute construct query
@@ -84,13 +83,11 @@ public class ConceptSparqlUpdatePreprocessor implements ModelChangePreprocessor
- DatasetWrapper w = dwf.getDatasetWrapper();
- Dataset dataset = w.getDataset();
- dataset.getLock().enterCriticalSection(Lock.READ);
+ additionsModel.getLock().enterCriticalSection(Lock.READ);
QueryExecution qe = null;
try {
qe = QueryExecutionFactory.create(
- query, dataset);
+ query, additionsModel);
qe.execConstruct(constructedModel);
} catch (Exception e) {
log.error("Error getting constructed model for query string " + constructQuery);
@@ -98,8 +95,7 @@ public class ConceptSparqlUpdatePreprocessor implements ModelChangePreprocessor
if (qe != null) {
qe.close();
}
- dataset.getLock().leaveCriticalSection();
- w.close();
+ additionsModel.getLock().leaveCriticalSection();
}
//Add constructed model to the designated update model
diff --git a/webapp/web/i18n/all.properties b/webapp/web/i18n/all.properties
index 7980d00a9..b235c903c 100644
--- a/webapp/web/i18n/all.properties
+++ b/webapp/web/i18n/all.properties
@@ -675,6 +675,7 @@ photo = Photo
no_image = no image
placeholder_image = placeholder image
manage_labels = manage labels
+manage_list_of_labels = manage list of labels
add_label = Add Label
add_label_for_language = Language
unsupported_ie_version = This form is not supported in versions of Internet Explorer below version 8. Please upgrade your browser, or switch to another browser, such as FireFox.
@@ -858,6 +859,6 @@ subproperty = subproperty
manage_labels_for = Manage Labels for
manage_labels_capitalized = Manage Labels
-manage_labels_intro = Multiple labels exist for this profile but there should only be one. Select the label you want displayed on the profile page, and the others will be deleted.
+manage_labels_intro = In the case where multiple labels exist in the same language, please use the remove link to delete the labels you do not want displayed on the profile page for a given language.
processing_icon = processing
selection_in_process = Your selection is being processed.
diff --git a/webapp/web/js/individual/manageLabelsForIndividual.js b/webapp/web/js/individual/manageLabelsForIndividual.js
index 7eb54c92e..7e1c8128c 100644
--- a/webapp/web/js/individual/manageLabelsForIndividual.js
+++ b/webapp/web/js/individual/manageLabelsForIndividual.js
@@ -32,20 +32,31 @@ var manageLabels = {
// Initial page setup. Called only at page load.
initPage: function() {
- //disable submit until user selects a language
- this.submit.attr('disabled', 'disabled');
- this.submit.addClass('disabledSubmit');
+
+ var disableSubmit = true;
if(this.submissionErrorsExist == "false") {
//hide the form to add label
this.addLabelForm.hide();
- //the cancel in add label can be unbound until the form is visible
- //this.addLabelCancel.unbind("click");
+ //If the number of available locales is zero, then hide the ability to show the form as well
+ if(this.numberAvailableLocales == 0) {
+ manageLabels.showFormButtonWrapper.hide();
+ }
+
} else {
//Display the form
this.onShowAddForm();
+ //Also make sure the save button is enabled in case there is a value selected for the drop down
+ if(this.labelLanguage.val() != "") {
+ disableSubmit = false;
+ }
}
+ if(disableSubmit) {
+ //disable submit until user selects a language
+ this.submit.attr('disabled', 'disabled');
+ this.submit.addClass('disabledSubmit');
+ }
this.bindEventListeners();
@@ -88,25 +99,15 @@ var manageLabels = {
});
- this.addLabelForm.find("a.cancel").click(function(){
+ this.addLabelForm.find("a.cancel").click(function(event){
+ event.preventDefault();
//clear the add form
manageLabels.clearAddForm();
//hide the add form
manageLabels.onHideAddForm();
-
+ return false;
});
- //TODO: Add method to check that language is selected on submission
-
- /*
- $('input#submit').click( function() {
- manageLabels.processLabel(manageLabels.selectedRadio);
- $('span.or').hide();
- $('a.cancel').hide();
- $('span#indicator').removeClass('hidden');
- $('input.submit').addClass('disabledSubmit');
- $('input.submit').attr('disabled', 'disabled');
- });*/
},
clearAddForm:function() {
@@ -179,12 +180,12 @@ var manageLabels = {
var languageName = $(selectedLink).attr("languageName");
$(selectedLink).parent().remove();
//See if there are any other remove link
- if(languageCode != "untyped") {
+ if(languageName != "untyped") {
//find if there are any other remove links for the same language
var removeLinks = manageLabels.existingLabelsList.find("a.remove[languageName='" + languageName + "']");
if(removeLinks.length == 0) {
//if there aren't any other labels for this language, also remove the heading
- manageLabels.existingLabelsList.find("h3[languageName='" + langaugeName + "']").remove();
+ manageLabels.existingLabelsList.find("h3[languageName='" + languageName + "']").remove();
}
}
@@ -223,6 +224,11 @@ var manageLabels = {
var compB = b["label"];
return compA < compB ? -1 : 1;
});
+ //Re-show the add button and the form if they were hidden before
+ if(availableLocalesList.length > 0 && manageLabels.showFormButtonWrapper.is(":hidden")) {
+ manageLabels.showFormButtonWrapper.show();
+ }
+
//Now replace dropdown with this new list
manageLabels.generateLocalesDropdown(availableLocalesList);
diff --git a/webapp/web/templates/freemarker/body/individual/manageLabelsForIndividual.ftl b/webapp/web/templates/freemarker/body/individual/manageLabelsForIndividual.ftl
index 6c5492faa..dea117f5c 100644
--- a/webapp/web/templates/freemarker/body/individual/manageLabelsForIndividual.ftl
+++ b/webapp/web/templates/freemarker/body/individual/manageLabelsForIndividual.ftl
@@ -17,7 +17,10 @@
<#assign submissionErrors = editSubmission.validationErrors/>
<#assign submissionErrorsExist = "true" />
#if>
-
+<#assign availableLocalesNumber = 0/>
+<#if editConfiguration.pageData.selectLocale?has_content>
+ <#assign availableLocalesNumber = editConfiguration.pageData.selectLocale?size />
+#if>
<#if editConfiguration.pageData.subjectName?? >
${i18n().manage_labels_for} ${editConfiguration.pageData.subjectName}
<#else>
@@ -64,7 +67,7 @@
#if>
-
+