diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/VitroVocabulary.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/VitroVocabulary.java index 05e78bc4e..9749a0765 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/VitroVocabulary.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/VitroVocabulary.java @@ -2,6 +2,11 @@ package edu.cornell.mannlib.vitro.webapp.dao; +import java.util.Arrays; +import java.util.List; + +import com.hp.hpl.jena.rdf.model.Resource; +import com.hp.hpl.jena.vocabulary.XSD; import com.hp.hpl.jena.ontology.AnnotationProperty; public class VitroVocabulary { @@ -278,5 +283,28 @@ public class VitroVocabulary { public static final String NAMESPACE_ISCURRENTPREFIXMAPPING = vitroURI + "isCurrentPrefixMapping"; public static final String ONTOLOGY_PREFIX_ANNOT = vitroURI + "ontologyPrefixAnnot"; + + + public static final List VITRO_NS_PROPERTIES = Arrays.asList(BLURB, CITATION, DESCRIPTION, LABEL, LINK_ANCHOR, MONIKER, PRIMARY_LINK, RDF_TYPE, TIMEKEY); + + public static String getVitroNsPropDatatypeUri(String propName) { + Resource datatype = propName == TIMEKEY ? XSD.dateTime : XSD.xstring; + return datatype.getURI(); + } + +// public static final Map VITRO_NS_PROPERTIES = new HashMap() { +// { +// put(BLURB, XSD.xstring.getURI()); +// put(CITATION, XSD.xstring.getURI()); +// put(DESCRIPTION, XSD.xstring.getURI()); +// put(LABEL, XSD.xstring.getURI()); +// put(LINK_ANCHOR, XSD.xstring.getURI()); +// put(MONIKER, XSD.xstring.getURI()); +// put(PRIMARY_LINK, XSD.xstring.getURI()); +// put(RDF_TYPE, XSD.xstring.getURI()); +// put(TIMEKEY, XSD.dateTime.getURI()); +// } +// }; + } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/RdfLiteralHash.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/RdfLiteralHash.java index 8477fa3bb..b2829cb50 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/RdfLiteralHash.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/RdfLiteralHash.java @@ -86,11 +86,11 @@ public class RdfLiteralHash { // RY Instead of a code fork here, we should have a method of Individual getAllDataPropertyStatements() which // doesn't filter out the vitro ns property statements. This would also simplify the front end editing of the vitro ns // properties, because they wouldn't have to be a special case. - public static DataPropertyStatement getPropertyStmtByHash(Individual ind, int hash, Model model, boolean isVitroNsProp) { + public static DataPropertyStatement getPropertyStmtByHash(Individual ind, String predicateUri, int hash, Model model, boolean isVitroNsProp) { if (ind == null) return null; - DataPropertyStatement dps = isVitroNsProp ? RdfLiteralHash.getVitroNsPropertyStmtByHash(ind, model, hash) : + DataPropertyStatement dps = isVitroNsProp ? RdfLiteralHash.getVitroNsPropertyStmtByHash(ind, predicateUri, model, hash) : RdfLiteralHash.getDataPropertyStmtByHash(ind, hash); return dps; @@ -114,10 +114,12 @@ public class RdfLiteralHash { * @param hash * @return a DataPropertyStatement if found or null if not found */ - public static DataPropertyStatement getVitroNsPropertyStmtByHash(Individual ind, Model model, int hash) { + public static DataPropertyStatement getVitroNsPropertyStmtByHash(Individual ind, String predicateUri, Model model, int hash) { DataPropertyStatement dps = null; - StmtIterator stmts = model.listStatements(model.createResource(ind.getURI()), null, (RDFNode)null); + StmtIterator stmts = model.listStatements(model.createResource(ind.getURI()), + model.getProperty(predicateUri), + (RDFNode)null); try { while (stmts.hasNext()) { Statement stmt = stmts.nextStatement(); diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/jsptags/PropertyEditLinks.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/jsptags/PropertyEditLinks.java index 32c2179cd..b14a80ca4 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/jsptags/PropertyEditLinks.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/jsptags/PropertyEditLinks.java @@ -21,6 +21,8 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.hp.hpl.jena.rdf.model.Model; +import com.hp.hpl.jena.rdf.model.RDFNode; +import com.hp.hpl.jena.rdf.model.StmtIterator; import edu.cornell.mannlib.vitro.webapp.auth.identifier.IdentifierBundle; import edu.cornell.mannlib.vitro.webapp.auth.identifier.ServletIdentifierBundleFactory; @@ -133,9 +135,15 @@ public class PropertyEditLinks extends TagSupport{ } else if( item instanceof DataProperty ){ DataProperty prop = (DataProperty)item; // a DataProperty populated for this subject individual links = doDataProp( prop, entity, themeDir,policyToAccess(ids, policy, entity.getURI(), prop), contextPath ) ; - } else if (item instanceof String && data != null) { - DataPropertyStatement dps = (DataPropertyStatement) new DataPropertyStatementImpl(entity.getURI(), (String)item, data); - links = doVitroNamespaceProp( dps, entity, themeDir, policyToAccess(ids, policy, dps), contextPath ); + } else if (item instanceof String && isVitroNsProp((String) item)) { + String subjectUri = entity.getURI(); + if (data != null) { // links to edit or delete an existing value + DataPropertyStatement dps = (DataPropertyStatement) new DataPropertyStatementImpl(subjectUri, (String)item, data); + links = doVitroNamespacePropStmt( dps, entity, themeDir, policyToAccess(ids, policy, dps), contextPath ); + } else { // link to add a new value + + links = doVitroNsProp( subjectUri, (String)item, themeDir, policyToAccess(ids, policy, subjectUri, (String)item), contextPath ) ; + } } else { log.error("PropertyEditLinks cannot make links for an object of type "+item.getClass().getName()); return SKIP_BODY; @@ -160,6 +168,10 @@ public class PropertyEditLinks extends TagSupport{ return SKIP_BODY; } + + private boolean isVitroNsProp(String predicateUri) { + return VitroVocabulary.VITRO_NS_PROPERTIES.contains(predicateUri); + } protected LinkStruct[] doDataProp(DataProperty dprop, Individual entity, String themeDir, EditLinkAccess[] allowedAccessTypeArray, String contextPath) { if( allowedAccessTypeArray == null || dprop == null || allowedAccessTypeArray.length == 0 ) { @@ -188,6 +200,39 @@ public class PropertyEditLinks extends TagSupport{ return links; } + protected LinkStruct[] doVitroNsProp(String subjectUri, String propertyUri, String themeDir, EditLinkAccess[] allowedAccessTypeArray, String contextPath) { + if( allowedAccessTypeArray == null || subjectUri == null || allowedAccessTypeArray.length == 0 ) { + log.debug("null or empty access type array in doDataProp for vitro namespace property " + propertyUri + "; most likely just a property prohibited from editing"); + return empty_array; + } + LinkStruct[] links = new LinkStruct[1]; + + Model model = (Model)pageContext.getServletContext().getAttribute("jenaOntModel"); + StmtIterator stmts = model.listStatements(model.createResource(subjectUri), + model.getProperty(propertyUri), + (RDFNode) null); + + if (stmts.hasNext()) { + log.debug("not showing an \"add\" link for vitro namespace property " + propertyUri + " because it has a limit of 1"); + } else { + if( contains( allowedAccessTypeArray, EditLinkAccess.ADDNEW ) ){ + log.debug("vitro namespace property "+propertyUri+" gets an \"add\" link"); + String url = makeRelativeHref(contextPath + "edit/editDatapropStmtRequestDispatch.jsp", + "subjectUri", subjectUri, + "predicateUri", propertyUri, + "vitroNsProp", "true"); + LinkStruct ls = new LinkStruct(); + ls.setHref( url ); + ls.setType("add"); + ls.setMouseoverText("add a new entry"); + links[0] = ls; + } else { + log.debug("no add link generated for vitro namespace property "+propertyUri); + } + } + return links; + } + protected LinkStruct[] doObjProp(ObjectProperty oprop, Individual entity, String themeDir, EditLinkAccess[] allowedAccessTypeArray, String contextPath) { if( allowedAccessTypeArray == null || oprop == null || allowedAccessTypeArray.length == 0 ) { @@ -308,7 +353,7 @@ public class PropertyEditLinks extends TagSupport{ return links; } - protected LinkStruct[] doVitroNamespaceProp(DataPropertyStatement dpropStmt, Individual subject, String themeDir, EditLinkAccess[] allowedAccessTypeArray, String contextPath) { + protected LinkStruct[] doVitroNamespacePropStmt(DataPropertyStatement dpropStmt, Individual subject, String themeDir, EditLinkAccess[] allowedAccessTypeArray, String contextPath) { if( allowedAccessTypeArray == null || dpropStmt == null || allowedAccessTypeArray.length == 0 ) { log.debug("Null or empty access type array for vitro namespace property " + dpropStmt.getDatapropURI()); @@ -481,9 +526,16 @@ public class PropertyEditLinks extends TagSupport{ } protected EditLinkAccess[] policyToAccess( IdentifierBundle ids, PolicyIface policy, String subjectUri, DataProperty item) { + + String propertyUri = item.getURI(); + return policyToAccess(ids, policy, subjectUri, propertyUri); + } + + protected EditLinkAccess[] policyToAccess( IdentifierBundle ids, PolicyIface policy, String subjectUri, String propertyUri) { + EditLinkAccess[] access; - - RequestedAction action = new AddDataPropStmt(subjectUri, item.getURI(), RequestActionConstants.SOME_LITERAL, null, null); + + RequestedAction action = new AddDataPropStmt(subjectUri, propertyUri, RequestActionConstants.SOME_LITERAL, null, null); PolicyDecision dec = policy.isAuthorized(ids, action); if( dec != null && dec.getAuthorized() == Authorization.AUTHORIZED ){ @@ -494,7 +546,7 @@ public class PropertyEditLinks extends TagSupport{ return access; } - + public enum EditLinkAccess{ MODIFY, DELETE, ADDNEW, INFO, ADMIN }; public class LinkStruct { diff --git a/webapp/test/edu/cornell/mannlib/vitro/webapp/edit/n3editing/RdfLiteralHashTest.java b/webapp/test/edu/cornell/mannlib/vitro/webapp/edit/n3editing/RdfLiteralHashTest.java index 943877539..2be1dd331 100644 --- a/webapp/test/edu/cornell/mannlib/vitro/webapp/edit/n3editing/RdfLiteralHashTest.java +++ b/webapp/test/edu/cornell/mannlib/vitro/webapp/edit/n3editing/RdfLiteralHashTest.java @@ -201,9 +201,11 @@ public class RdfLiteralHashTest { Individual bob = new IndividualImpl(); bob.setURI("http://example.com/bob"); + + String propertyUri = VitroVocabulary.MONIKER; - int hash = RdfLiteralHash.makeVitroNsLiteralHash(bob,VitroVocabulary.MONIKER, "great", model); - DataPropertyStatement stmt = RdfLiteralHash.getVitroNsPropertyStmtByHash(bob, model, hash); + int hash = RdfLiteralHash.makeVitroNsLiteralHash(bob, propertyUri, "great", model); + DataPropertyStatement stmt = RdfLiteralHash.getVitroNsPropertyStmtByHash(bob, propertyUri, model, hash); String data = stmt.getData(); String datatypeUri = stmt.getDatatypeURI(); diff --git a/webapp/web/edit/editDatapropStmtRequestDispatch.jsp b/webapp/web/edit/editDatapropStmtRequestDispatch.jsp index 666fd1a3b..b3e4fae8a 100644 --- a/webapp/web/edit/editDatapropStmtRequestDispatch.jsp +++ b/webapp/web/edit/editDatapropStmtRequestDispatch.jsp @@ -113,7 +113,7 @@ DataPropertyStatement dps = null; if( dataHash != 0) { Model model = (Model)application.getAttribute("jenaOntModel"); - dps = RdfLiteralHash.getPropertyStmtByHash(subject, dataHash, model, isVitroNsProp); + dps = RdfLiteralHash.getPropertyStmtByHash(subject, predicateUri, dataHash, model, isVitroNsProp); if (dps==null) { log.error("No match to existing data property \""+predicateUri+"\" statement for subject \""+subjectUri+"\" via key "+datapropKeyStr); diff --git a/webapp/web/edit/forms/datapropStmtDelete.jsp b/webapp/web/edit/forms/datapropStmtDelete.jsp index 05540c90f..0339e60f5 100644 --- a/webapp/web/edit/forms/datapropStmtDelete.jsp +++ b/webapp/web/edit/forms/datapropStmtDelete.jsp @@ -65,7 +65,7 @@ String vitroNsProp = vreq.getParameter("vitroNsProp"); boolean isVitroNsProp = vitroNsProp != null && vitroNsProp.equals("true") ? true : false; - DataPropertyStatement dps = RdfLiteralHash.getPropertyStmtByHash(subject, dataHash, model, isVitroNsProp); + DataPropertyStatement dps = RdfLiteralHash.getPropertyStmtByHash(subject, predicateUri, dataHash, model, isVitroNsProp); if( log.isDebugEnabled() ){ log.debug("attempting to delete dataPropertyStatement: subjectURI <" + dps.getIndividualURI() +">"); diff --git a/webapp/web/edit/forms/defaultDatapropForm.jsp b/webapp/web/edit/forms/defaultDatapropForm.jsp index e0cc7fd9c..dc786a62f 100644 --- a/webapp/web/edit/forms/defaultDatapropForm.jsp +++ b/webapp/web/edit/forms/defaultDatapropForm.jsp @@ -68,7 +68,7 @@ vreq.setAttribute("rangeLangJson", rangeLang); } } else { - log.debug("No incoming dataproperty statement attribute for property "+prop.getPublicName()+", adding a new statement"); + log.debug("No incoming dataproperty statement attribute for property "+prop.getPublicName()+"; adding a new statement"); if(rangeDatatypeUri != null && rangeDatatypeUri.length() > 0) { String defaultVal = defaultsForXSDtypes.get(rangeDatatypeUri); if( defaultVal == null ) diff --git a/webapp/web/edit/forms/defaultVitroNsPropForm.jsp b/webapp/web/edit/forms/defaultVitroNsPropForm.jsp index 9562eef0d..d401afefd 100644 --- a/webapp/web/edit/forms/defaultVitroNsPropForm.jsp +++ b/webapp/web/edit/forms/defaultVitroNsPropForm.jsp @@ -2,6 +2,7 @@ <%@ page import="java.util.ArrayList"%> <%@ page import="java.util.Arrays"%> +<%@ page import="java.util.HashMap"%> <%@ page import="com.hp.hpl.jena.rdf.model.Literal"%> <%@ page import="com.hp.hpl.jena.rdf.model.Model"%> @@ -30,6 +31,8 @@ String subjectUri = vreq.getParameter("subjectUri"); String predicateUri = vreq.getParameter("predicateUri"); + String propertyName = predicateUri.substring(predicateUri.lastIndexOf("#")+1); + vreq.setAttribute("propertyName", propertyName); DataPropertyStatement dps = (DataPropertyStatement)vreq.getAttribute("dataprop"); @@ -42,16 +45,43 @@ Model model = (Model)application.getAttribute("jenaOntModel"); - String rangeDatatypeUri = dps.getDatatypeURI(); - String rangeDatatypeUriJson = MiscWebUtils.escape(rangeDatatypeUri); - vreq.setAttribute("rangeDatatypeUriJson", rangeDatatypeUriJson); + // Get datatype and language for the data property statement + String rangeDatatypeUri = null, + rangeLang = null; + if (dps != null) { + + rangeDatatypeUri = dps.getDatatypeURI(); + if (rangeDatatypeUri == null) { + log.debug("no range datatype uri set on vitro namespace property statement for property " + predicateUri + " in defaultVitroNsPropForm.jsp"); + } else { + log.debug("range datatype uri of [" + rangeDatatypeUri + "] on vitro namespace property statement for property " + predicateUri + " in defaultVitroNsPropForm.jsp"); + } + + rangeLang = dps.getLanguage(); + if( rangeLang == null ) { + log.debug("no language attribute on vitro namespace property statement for property " + predicateUri + " in defaultVitroNsPropForm.jsp"); + rangeLang = ""; + } else { + log.debug("language attribute of ["+rangeLang+"] on vitro namespace property statement for property " + predicateUri + " in defaultVitroNsPropForm.jsp"); + } + + } else { + log.debug("No incoming vitro namespace property statement for property "+predicateUri+"; adding a new statement"); + rangeDatatypeUri = VitroVocabulary.getVitroNsPropDatatypeUri(predicateUri); + } + + String rangeDatatypeUriJson = rangeDatatypeUri == null ? "" : MiscWebUtils.escape(rangeDatatypeUri); + + vreq.setAttribute("rangeDatatypeUriJson", rangeDatatypeUriJson); + vreq.setAttribute("rangeLangJson", rangeLang); + // Create list of validators ArrayList validatorList = new ArrayList(); if (predicateUri.equals(VitroVocabulary.LABEL) || predicateUri.equals(VitroVocabulary.RDF_TYPE)) { validatorList.add("nonempty"); } - if (!rangeDatatypeUriJson.isEmpty()) { + if (!StringUtils.isEmpty(rangeDatatypeUriJson)) { validatorList.add("datatype:" + rangeDatatypeUriJson); } vreq.setAttribute("validators", StringUtils.quotedList(validatorList, ",")); @@ -59,7 +89,6 @@ %> - <%-- Then enter a SPARQL query for the field, by convention concatenating the field id with "Existing" to convey that the expression is used to retrieve any existing value for the field in an existing individual. @@ -77,13 +106,6 @@ ?subject <${predicate}> ?${propertyName} . -<% - -%> - - - - { "formUrl" : "${formUrl}", @@ -116,15 +138,13 @@ "predicateUri" : "", "objectClassUri" : "", "rangeDatatypeUri" : "${rangeDatatypeUriJson}", - "rangeLang" : "", + "rangeLang" : "${rangeLangJson}", "assertions" : [ "${dataAssertion}" ] } } } - - <% if( log.isDebugEnabled()) log.debug(request.getAttribute("editjson")); @@ -141,19 +161,20 @@ editConfig.prepareForDataPropUpdate(model,dps); } + String propertyLabel = propertyName == "label" ? "name" : propertyName; + String actionText = dps == null ? "Add new " : "Edit "; + String submitLabel = actionText + propertyName; + String title = actionText + propertyName + " for " + subject.getName(); + %> - - - - -

${title}

+

<%= title %>

" > -

+

@@ -170,3 +191,4 @@ + diff --git a/webapp/web/edit/processDatapropRdfForm.jsp b/webapp/web/edit/processDatapropRdfForm.jsp index ab0d0f2c0..ee023951c 100644 --- a/webapp/web/edit/processDatapropRdfForm.jsp +++ b/webapp/web/edit/processDatapropRdfForm.jsp @@ -380,7 +380,7 @@ and set a flag in the request to indicate "back button confusion" int dpropHash = Integer.parseInt(editConfig.getDatapropKey()); String vitroNsProp = vreq.getParameter("vitroNsProp"); boolean isVitroNsProp = vitroNsProp != null && vitroNsProp.equals("true"); - DataPropertyStatement dps = RdfLiteralHash.getPropertyStmtByHash(subject, dpropHash, model, isVitroNsProp); + DataPropertyStatement dps = RdfLiteralHash.getPropertyStmtByHash(subject, editConfig.getPredicateUri(), dpropHash, model, isVitroNsProp); if (dps != null) return false; diff --git a/webapp/web/templates/entity/entityBasic.jsp b/webapp/web/templates/entity/entityBasic.jsp index 022806ec1..a289493a6 100644 --- a/webapp/web/templates/entity/entityBasic.jsp +++ b/webapp/web/templates/entity/entityBasic.jsp @@ -124,6 +124,7 @@ RY Description not working - FIX

moniker

+ <%-- Here's where we add the plus link, but only if there isn't already a moniker. --%> @@ -142,7 +143,7 @@ RY Description not working - FIX
- +