From 91fd8a4c1ba78721e693460e2e43c44c7d0fe554 Mon Sep 17 00:00:00 2001 From: hudajkhan Date: Tue, 24 Sep 2013 13:44:58 -0400 Subject: [PATCH] updates for concepts and labels --- .../manageLabelsForIndividualAddForm.ftl | 6 + ...ageLabelsForIndividualSubmissionErrors.ftl | 3 + .../edit/forms/addAssociatedConcept.ftl | 6 +- .../freemarker/edit/forms/js/addConcept.js | 7 +- .../service/impl/AgrovocService.java | 62 +- .../semservices/service/impl/LCSHService.java | 30 +- .../AddAssociatedConceptGenerator.java | 11 +- .../ManageLabelsForPersonGenerator.java | 606 ++++++++++++++++++ .../generators/ManageLabelsGenerator.java | 70 ++ .../AddAssociatedConceptsPreprocessor.java | 44 +- .../ConceptSemanticTypesPreprocessor.java | 8 +- 11 files changed, 792 insertions(+), 61 deletions(-) create mode 100644 src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/ManageLabelsForPersonGenerator.java create mode 100644 src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/ManageLabelsGenerator.java diff --git a/productMods/templates/freemarker/body/individual/manageLabelsForIndividualAddForm.ftl b/productMods/templates/freemarker/body/individual/manageLabelsForIndividualAddForm.ftl index 9c0985ed..aa3ea7f7 100644 --- a/productMods/templates/freemarker/body/individual/manageLabelsForIndividualAddForm.ftl +++ b/productMods/templates/freemarker/body/individual/manageLabelsForIndividualAddForm.ftl @@ -8,6 +8,12 @@

+ <#--TODO: With ISF changes, add middle name input--> + + +

diff --git a/productMods/templates/freemarker/body/individual/manageLabelsForIndividualSubmissionErrors.ftl b/productMods/templates/freemarker/body/individual/manageLabelsForIndividualSubmissionErrors.ftl index c5b8b144..833f5e99 100644 --- a/productMods/templates/freemarker/body/individual/manageLabelsForIndividualSubmissionErrors.ftl +++ b/productMods/templates/freemarker/body/individual/manageLabelsForIndividualSubmissionErrors.ftl @@ -5,6 +5,9 @@ <#--Get existing value for specific data literals and uris, in case the form is returned because of an error--> <#assign firstNameValue = lvf.getFormFieldValue(editSubmission, editConfiguration, "firstName")/> <#assign lastNameValue = lvf.getFormFieldValue(editSubmission, editConfiguration, "lastName")/> +<#--With ISF changes, we also have a niddle name value, also add error field below--> +<#--assign middleNameValue = lvf.getFormFieldValue(editSubmission, editConfiguration, "middleName") /--> + <#assign labelValue = lvf.getFormFieldValue(editSubmission, editConfiguration, "label")/> <#assign newLabelLanguageValue = lvf.getFormFieldValue(editSubmission, editConfiguration, "newLabelLanguage")/> diff --git a/productMods/templates/freemarker/edit/forms/addAssociatedConcept.ftl b/productMods/templates/freemarker/edit/forms/addAssociatedConcept.ftl index 0f7a2c1b..316683c6 100644 --- a/productMods/templates/freemarker/edit/forms/addAssociatedConcept.ftl +++ b/productMods/templates/freemarker/edit/forms/addAssociatedConcept.ftl @@ -101,9 +101,8 @@

<#assign checkedSource = false />

${i18n().external_vocabulary_services}

- <#list sources?keys?sort as sourceUri> - <#assign thisSource = sources[sourceUri]/> - <#assign checkedSource = true/>checked="checked"> + <#list sources?values?sort_by("label") as thisSource> + <#assign checkedSource = true/>checked="checked">
@@ -180,6 +179,7 @@ ${stylesheets.add('')} ${scripts.add('')} +${scripts.add('')} ${scripts.add('')} ${scripts.add('')} ${scripts.add('')} diff --git a/productMods/templates/freemarker/edit/forms/js/addConcept.js b/productMods/templates/freemarker/edit/forms/js/addConcept.js index ce9200a6..606a981b 100644 --- a/productMods/templates/freemarker/edit/forms/js/addConcept.js +++ b/productMods/templates/freemarker/edit/forms/js/addConcept.js @@ -321,8 +321,11 @@ var addConceptForm = { this.externalConceptLabel.val(conceptLabels); this.externalConceptSource.val(conceptSources); this.externalConceptSemanticTypeLabel.val(conceptSemanticTypes); - this.externalConceptBroaderUris.val(conceptBroaderUris); - this.externalConceptNarrowerUris.val(conceptNarrowerUris); + //Using JSON here because there may be multiple broader and narrower uris per concept + //and using a regular string representation does not differentiate between which set of uris + //would belong to which concept + this.externalConceptBroaderUris.val(JSON.stringify(conceptBroaderUris)); + this.externalConceptNarrowerUris.val(JSON.stringify(conceptNarrowerUris)); return true; }, diff --git a/src/edu/cornell/mannlib/semservices/service/impl/AgrovocService.java b/src/edu/cornell/mannlib/semservices/service/impl/AgrovocService.java index 003aa26b..eb25fcf6 100644 --- a/src/edu/cornell/mannlib/semservices/service/impl/AgrovocService.java +++ b/src/edu/cornell/mannlib/semservices/service/impl/AgrovocService.java @@ -108,20 +108,23 @@ public class AgrovocService implements ExternalConceptService { String lang = ""; for (SKOSLiteral literal : skosConcept.getSKOSRelatedConstantByProperty(dataset, manager.getSKOSDataFactory().getSKOSPrefLabelProperty())) { - - if (!literal.isTyped()) { - // if it has language - SKOSUntypedLiteral untypedLiteral = literal.getAsSKOSUntypedLiteral(); - if (untypedLiteral.hasLang()) { - lang = untypedLiteral.getLang(); - } else { - lang = ""; - } - } - if (lang.equals("en")) { - //System.out.println("prefLabel: " + literal.getLiteral()); - - concept.setLabel(literal.getLiteral()); + if(literal != null) { + if (!literal.isTyped()) { + // if it has language + SKOSUntypedLiteral untypedLiteral = literal.getAsSKOSUntypedLiteral(); + if (untypedLiteral.hasLang()) { + lang = untypedLiteral.getLang(); + } else { + lang = ""; + } + } + if (lang.equals("en")) { + //System.out.println("prefLabel: " + literal.getLiteral()); + + concept.setLabel(literal.getLiteral()); + } + } else { + logger.debug("Literal returned for preferred label was null and was ignored"); } } @@ -130,21 +133,24 @@ public class AgrovocService implements ExternalConceptService { for (SKOSLiteral literal : skosConcept .getSKOSRelatedConstantByProperty(dataset, manager .getSKOSDataFactory().getSKOSAltLabelProperty())) { - - if (!literal.isTyped()) { - // if it has language - SKOSUntypedLiteral untypedLiteral = literal - .getAsSKOSUntypedLiteral(); - if (untypedLiteral.hasLang()) { - lang = untypedLiteral.getLang(); - } else { - lang = ""; + if(literal != null) { + if (!literal.isTyped()) { + // if it has language + SKOSUntypedLiteral untypedLiteral = literal + .getAsSKOSUntypedLiteral(); + if (untypedLiteral.hasLang()) { + lang = untypedLiteral.getLang(); + } else { + lang = ""; + } } - } - //System.out.println("literal: "+ literal.getLiteral()); - if (lang.equals("en")) { - //System.out.println("altLabel: " + literal.getLiteral()); - altLabelList.add(literal.getLiteral()); + //System.out.println("literal: "+ literal.getLiteral()); + if (lang.equals("en")) { + //System.out.println("altLabel: " + literal.getLiteral()); + altLabelList.add(literal.getLiteral()); + } + } else { + logger.debug("Literal retrieved for altlabel was null and was ignored"); } } concept.setAltLabelList(altLabelList); diff --git a/src/edu/cornell/mannlib/semservices/service/impl/LCSHService.java b/src/edu/cornell/mannlib/semservices/service/impl/LCSHService.java index 14a59dd1..614bd356 100644 --- a/src/edu/cornell/mannlib/semservices/service/impl/LCSHService.java +++ b/src/edu/cornell/mannlib/semservices/service/impl/LCSHService.java @@ -269,20 +269,24 @@ public class LCSHService implements ExternalConceptService { String lang = ""; List literalValues = new ArrayList(); for (SKOSLiteral literal : skosLiterals) { - if (!literal.isTyped()) { - // if it has language - SKOSUntypedLiteral untypedLiteral = literal - .getAsSKOSUntypedLiteral(); - if (untypedLiteral.hasLang()) { - lang = untypedLiteral.getLang(); - } else { - lang = ""; + if(literal != null) { + if (!literal.isTyped()) { + // if it has language + SKOSUntypedLiteral untypedLiteral = literal + .getAsSKOSUntypedLiteral(); + if (untypedLiteral.hasLang()) { + lang = untypedLiteral.getLang(); + } else { + lang = ""; + } } - } - // log.debug("literal: "+ literal.getLiteral()); - if (lang.equals("en")) { - log.debug("literal value: " + literal.getLiteral()); - literalValues.add(literal.getLiteral()); + // log.debug("literal: "+ literal.getLiteral()); + if (lang.equals("en")) { + log.debug("literal value: " + literal.getLiteral()); + literalValues.add(literal.getLiteral()); + } + } else { + log.debug("Literal returned was null so was ignored"); } } return literalValues; diff --git a/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/AddAssociatedConceptGenerator.java b/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/AddAssociatedConceptGenerator.java index 98d38df6..a7f8773e 100644 --- a/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/AddAssociatedConceptGenerator.java +++ b/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/AddAssociatedConceptGenerator.java @@ -67,7 +67,6 @@ public class AddAssociatedConceptGenerator extends VivoBaseGenerator implements initBasics(editConfiguration, vreq); initPropertyParameters(vreq, session, editConfiguration); initObjectPropForm(editConfiguration, vreq); - editConfiguration.setTemplate(template); setVarNames(editConfiguration); @@ -97,10 +96,10 @@ public class AddAssociatedConceptGenerator extends VivoBaseGenerator implements setTemplate(editConfiguration, vreq); // No validators required here // Add preprocessors + //Passing from servlet context for now but will have to see if there's a way to pass vreq addPreprocessors(editConfiguration, - ModelAccess.on(vreq).getJenaOntModel(), - ModelAccess.on(vreq).getOntModelSelector().getTBoxModel(), - vreq.getWebappDaoFactory()); + ModelAccess.on(session.getServletContext()).getJenaOntModel(), + ModelAccess.on(session.getServletContext()).getWebappDaoFactory()); // Adding additional data, specifically edit mode addFormSpecificData(editConfiguration, vreq); // One override for basic functionality, changing url pattern @@ -361,7 +360,6 @@ public class AddAssociatedConceptGenerator extends VivoBaseGenerator implements private void addPreprocessors(EditConfigurationVTwo editConfiguration, OntModel ontModel, - OntModel modelChangeModel, WebappDaoFactory wdf) { //An Edit submission preprocessor for enabling addition of multiple terms for a single search //TODO: Check if this is the appropriate way of getting model @@ -370,8 +368,7 @@ public class AddAssociatedConceptGenerator extends VivoBaseGenerator implements editConfiguration.addEditSubmissionPreprocessor( new AddAssociatedConceptsPreprocessor(editConfiguration, ontModel, wdf)); - editConfiguration.addModelChangePreprocessor(new ConceptSemanticTypesPreprocessor( - modelChangeModel)); + editConfiguration.addModelChangePreprocessor(new ConceptSemanticTypesPreprocessor()); } diff --git a/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/ManageLabelsForPersonGenerator.java b/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/ManageLabelsForPersonGenerator.java new file mode 100644 index 00000000..bfc5a43e --- /dev/null +++ b/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/ManageLabelsForPersonGenerator.java @@ -0,0 +1,606 @@ +/* $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 generator is specifically for handling labels for a FOAF Person individual and is an object property form. + *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 ManageLabelsForPersonGenerator extends BaseEditConfigurationGenerator implements EditConfigurationGenerator { + public static Log log = LogFactory.getLog(ManageLabelsForIndividualGenerator.class); + private static String template = "manageLabelsForPerson.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, but since the generator will + //be employed when the 'add' button is used, we will set this is an object property form + //although label will mean we need to add a data property statement as well + //URL to return to is the same page once addition is complete + initObjectPropForm(config, vreq); + + + 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.addNewResources(config); + this.setUrisAndLiteralsOnForm(config, vreq); + this.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, middle, and last names and also make sure to associate + //a language with that label + config.addModelChangePreprocessor(new FoafNameToRdfsLabelPreprocessor()); + + prepare(vreq, config); + return config; + } + + /**With ISF Changes**/ + //For addition of a label, with ISF changes, the name is now linked to a vcard which in turn is linked to a "fullname" that then has first/middle/last names + + private void addNewResources(EditConfigurationVTwo config) { + config.addNewResource("fullName", DEFAULT_NS_FOR_NEW_RESOURCE); + config.addNewResource("individualVcard", DEFAULT_NS_FOR_NEW_RESOURCE); + } + + 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 ."; + //This n3 will be different with the ISF changes + String personN3 = this.N3_PREFIX + + "?subject ?individualVcard . \n" + + "?individualVcard a . \n" + + "?individualVcard ?subject . \n" + + "?individualVcard ?fullName . \n" + + "?fullName a . \n" + + "?fullName ?firstName . \n" + + "?fullName ?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("middleName"). + setValidators(getLastNameValidators(vreq, editConfiguration))); + + editConfiguration.addField(new FieldVTwo(). + setName("lastName"). + setValidators(getLastNameValidators(vreq, editConfiguration))); + + //With ISF Changes, also include middle name + + } + + //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); + int numberExistingLabels = existingLabels.size(); + //existing labels keyed by language name and each of the list of labels is sorted by language name + HashMap> existingLabelsByLanguageName = this.getLabelsSortedByLanguageName(existingLabels, localeCodeToNameMap, config, vreq); + //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); + config.addFormSpecificData("displayRemoveLink", (numberExistingLabels > 1)); + + + //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/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/ManageLabelsGenerator.java b/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/ManageLabelsGenerator.java new file mode 100644 index 00000000..3d97c02e --- /dev/null +++ b/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/ManageLabelsGenerator.java @@ -0,0 +1,70 @@ +/* $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.util.List; + +import javax.servlet.http.HttpSession; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +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.edit.n3editing.VTwo.EditConfigurationUtils; +import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditConfigurationVTwo; + +/** + *This generator selects the actual generator to be employed based on whether the individual is a Person + *or another individual. Adding a label for a person relies on first/name last name information i.e. object properties. + */ +public class ManageLabelsGenerator extends BaseEditConfigurationGenerator implements EditConfigurationGenerator { + public static Log log = LogFactory.getLog(ManageLabelsForIndividualGenerator.class); + @Override + public EditConfigurationVTwo getEditConfiguration(VitroRequest vreq, HttpSession session) { + EditConfigurationVTwo e = null; + String subjectUri = EditConfigurationUtils.getSubjectUri(vreq); + if(this.isPersonType(subjectUri, vreq)) { + //Generator for persons + e = new ManageLabelsForPersonGenerator().getEditConfiguration(vreq, session); + } else { + //Non-Person individuals + e = new ManageLabelsForIndividualGenerator().getEditConfiguration(vreq, session); + + } + + return e; + + } + + + public boolean isPersonType(String subjectUri, VitroRequest vreq) { + Boolean isPersonType = Boolean.FALSE; + String foafPersonType = getFOAFPersonClassURI(); + List vclasses = this.getVClasses(subjectUri, vreq); + if( vclasses != null ){ + for( VClass v: vclasses){ + String typeUri = v.getURI(); + if( foafPersonType.equals(typeUri)) { + isPersonType = Boolean.TRUE; + break; + } + } + } + return isPersonType; + } + + //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"; + } + + //how to get the type of the individual in question + public List getVClasses(String subjectUri, VitroRequest vreq) { + Individual subject = EditConfigurationUtils.getIndividual(vreq, subjectUri); + //Get the vclasses appropriate for this subject + return subject.getVClasses(); + } + +} diff --git a/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/AddAssociatedConceptsPreprocessor.java b/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/AddAssociatedConceptsPreprocessor.java index 87deceb4..c2687659 100644 --- a/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/AddAssociatedConceptsPreprocessor.java +++ b/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/AddAssociatedConceptsPreprocessor.java @@ -9,6 +9,11 @@ import java.util.HashSet; import java.util.List; import java.util.Map; +import net.sf.json.JSON; +import net.sf.json.JSONArray; +import net.sf.json.JSONObject; +import net.sf.json.JSONSerializer; + import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -140,26 +145,55 @@ public class AddAssociatedConceptsPreprocessor extends //The original code for submission wouldn't put in a key if the values were null or size 0 urisFromForm.remove("conceptNarrowerURI"); } + //Set the copied values to this value as well so when if there are multiple + //concepts, the inputs get copied correctly for each of them + this.conceptNarrowerURIValues = existingNarrowerURIs; if(existingBroaderURIs.size() > 0) { urisFromForm.put("conceptBroaderURI", existingBroaderURIs); } else { urisFromForm.remove("conceptBroaderURI"); } + this.conceptBroaderURIValues = existingBroaderURIs; } //get the broader and narrower uri values that already exist in the system from the ones returned in the search //and use those to populate relationships between the concept and other concepts already in the system //We should also make sure to use bidirectional n3 so the graph has both sets of relationships represented private List getConceptNarrowerURIValues() { - Map> urisFromForm = submission.getUrisFromForm(); - List narrowerURIs = urisFromForm.get("conceptNarrowerURI"); - return narrowerURIs; + return this.getJSONFormURIValues("conceptNarrowerURI"); } private List getConceptBroaderURIValues() { + return this.getJSONFormURIValues("conceptBroaderURI"); + } + + private List getJSONFormURIValues(String varName) { Map> urisFromForm = submission.getUrisFromForm(); - List broaderURIs = urisFromForm.get("conceptBroaderURI"); - return broaderURIs; + List uris = urisFromForm.get(varName); + //This should be a JSON object stringified + if(uris.size() > 0) { + String jsonString = uris.get(0); + if(jsonString != null && !jsonString.isEmpty()) { + JSON json = JSONSerializer.toJSON(jsonString); + //This should be an array + if(json.isArray()) { + JSONArray jsonArray = (JSONArray) JSONSerializer.toJSON(jsonString); + //Convert to list of strings + return convertJsonArrayToList(jsonArray); + } + } + } + return uris; + } + + private List convertJsonArrayToList(JSONArray jsonArray) { + List stringList = new ArrayList(); + int len = jsonArray.size(); + int i = 0; + for(i = 0; i < len; i++) { + stringList.add(jsonArray.getString(i)); + } + return stringList; } private List getExistingBroaderURIs(List broaderURIs) { diff --git a/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/ConceptSemanticTypesPreprocessor.java b/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/ConceptSemanticTypesPreprocessor.java index b95733b4..345aeeee 100644 --- a/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/ConceptSemanticTypesPreprocessor.java +++ b/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/ConceptSemanticTypesPreprocessor.java @@ -27,6 +27,8 @@ 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.controller.VitroRequest; +import edu.cornell.mannlib.vitro.webapp.dao.ModelAccess; 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; @@ -40,16 +42,15 @@ public class ConceptSemanticTypesPreprocessor implements ModelChangePreprocessor private static String SKOSConceptType = "http://www.w3.org/2004/02/skos/core#Concept"; private Log log = LogFactory.getLog(ConceptSemanticTypesPreprocessor.class); - private OntModel toUpdateModel = null; //Custom constructor - public ConceptSemanticTypesPreprocessor(OntModel updateModel) { - this.toUpdateModel = updateModel; + public ConceptSemanticTypesPreprocessor() { } @Override public void preprocess(Model retractionsModel, Model additionsModel, HttpServletRequest request) { + VitroRequest vreq = new VitroRequest(vreq); //Run a construct query against the additions model String prefixes = "PREFIX rdfs:<" + RDFS.getURI() + "> " + "PREFIX owl: " + @@ -99,6 +100,7 @@ public class ConceptSemanticTypesPreprocessor implements ModelChangePreprocessor } //Add constructed model to the designated update model + OntModel toUpdateModel = ModelAccess.on(vreq).getOntModelSelector().getTBoxModel(); toUpdateModel.enterCriticalSection(Lock.WRITE); try { toUpdateModel.add(constructedModel);