Added code for deleting individuals
This commit is contained in:
parent
2a56ec8c30
commit
4fdbb71fee
7 changed files with 252 additions and 2 deletions
|
@ -0,0 +1,201 @@
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.controller.freemarker;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
import javax.servlet.annotation.WebServlet;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.apache.jena.query.Query;
|
||||||
|
import org.apache.jena.query.QueryExecution;
|
||||||
|
import org.apache.jena.query.QueryExecutionFactory;
|
||||||
|
import org.apache.jena.query.QueryFactory;
|
||||||
|
import org.apache.jena.query.QuerySolution;
|
||||||
|
import org.apache.jena.query.QuerySolutionMap;
|
||||||
|
import org.apache.jena.query.ResultSet;
|
||||||
|
import org.apache.jena.rdf.model.Model;
|
||||||
|
import org.apache.jena.rdf.model.ResourceFactory;
|
||||||
|
import org.apache.jena.shared.Lock;
|
||||||
|
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.auth.permissions.SimplePermission;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.AuthorizationRequest;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.RedirectResponseValues;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.dao.DisplayVocabulary;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.dao.jena.QueryUtils;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.dao.jena.event.BulkUpdateEvent;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelNames;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.rdfservice.ChangeSet;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFServiceException;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.rdfservice.impl.RDFServiceUtils;
|
||||||
|
|
||||||
|
@WebServlet(name="DeleteIndividualController",urlPatterns="/deleteIndividualController")
|
||||||
|
public class DeleteIndividualController extends FreemarkerHttpServlet{
|
||||||
|
|
||||||
|
private static final Log log = LogFactory.getLog(DeleteIndividualController.class);
|
||||||
|
private static final boolean BEGIN = true;
|
||||||
|
private static final boolean END = !BEGIN;
|
||||||
|
|
||||||
|
private static String TYPE_QUERY_START = ""
|
||||||
|
+ "PREFIX vitro: <http://vitro.mannlib.cornell.edu/ns/vitro/0.7#>"
|
||||||
|
+ "SELECT ?type "
|
||||||
|
+ "WHERE"
|
||||||
|
+ "{ <";
|
||||||
|
private static String TYPE_QUERY_END = "> vitro:mostSpecificType ?type ."
|
||||||
|
+ "}";
|
||||||
|
private static String queryForDeleteQuery =
|
||||||
|
"PREFIX display: <" + DisplayVocabulary.DISPLAY_NS +"> \n" +
|
||||||
|
"SELECT ?deleteQueryText WHERE { ?associatedURI display:hasDeleteQuery ?deleteQueryText }";
|
||||||
|
|
||||||
|
private static final String DEFAULT_DELETE_QUERY_TEXT = "DESCRIBE ?associatedURI";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected AuthorizationRequest requiredActions(VitroRequest vreq) {
|
||||||
|
return SimplePermission.DO_FRONT_END_EDITING.ACTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ResponseValues processRequest(VitroRequest vreq) {
|
||||||
|
String errorMessage = handleErrors(vreq);
|
||||||
|
if (!errorMessage.isEmpty()) {
|
||||||
|
return prepareErrorMessage(errorMessage);
|
||||||
|
}
|
||||||
|
String individualUri = vreq.getParameter("individualUri");
|
||||||
|
String type = getObjectMostSpecificType(individualUri, vreq);
|
||||||
|
Model displayModel = vreq.getDisplayModel();
|
||||||
|
|
||||||
|
String delteQueryText = getDeleteQueryForType(type, displayModel);
|
||||||
|
byte[] toRemove = getIndividualsToDelete(individualUri, delteQueryText, vreq);
|
||||||
|
if (toRemove.length > 0) {
|
||||||
|
deleteIndividuals(toRemove,vreq);
|
||||||
|
}
|
||||||
|
String redirectUrl = getRedirectUrl(vreq);
|
||||||
|
|
||||||
|
return new RedirectResponseValues(redirectUrl, HttpServletResponse.SC_SEE_OTHER);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getRedirectUrl(VitroRequest vreq) {
|
||||||
|
String redirectUrl = vreq.getParameter("redirectUrl");
|
||||||
|
if (redirectUrl != null) {
|
||||||
|
return redirectUrl;
|
||||||
|
}
|
||||||
|
return "/";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private TemplateResponseValues prepareErrorMessage(String errorMessage) {
|
||||||
|
HashMap<String,Object> map = new HashMap<String,Object>();
|
||||||
|
map.put("errorMessage", errorMessage);
|
||||||
|
return new TemplateResponseValues("error-message.ftl", map);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String handleErrors(VitroRequest vreq) {
|
||||||
|
String uri = vreq.getParameter("individualUri");
|
||||||
|
if ( uri == null) {
|
||||||
|
return "Individual uri is null. No object to delete.";
|
||||||
|
}
|
||||||
|
if (uri.contains(">")) {
|
||||||
|
return "Individual uri shouldn't contain >";
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getDeleteQueryForType(String typeURI,Model displayModel) {
|
||||||
|
|
||||||
|
String deleteQueryText = DEFAULT_DELETE_QUERY_TEXT;
|
||||||
|
|
||||||
|
Query queryForTypeSpecificDeleteQuery = QueryFactory.create(queryForDeleteQuery);
|
||||||
|
|
||||||
|
QuerySolutionMap initialBindings = new QuerySolutionMap();
|
||||||
|
initialBindings.add("associatedURI", ResourceFactory.createResource( typeURI ));
|
||||||
|
|
||||||
|
displayModel.enterCriticalSection(Lock.READ);
|
||||||
|
try{
|
||||||
|
QueryExecution qexec = QueryExecutionFactory.create(queryForTypeSpecificDeleteQuery,displayModel,initialBindings );
|
||||||
|
try{
|
||||||
|
ResultSet results = qexec.execSelect();
|
||||||
|
while (results.hasNext()) {
|
||||||
|
QuerySolution solution = results.nextSolution();
|
||||||
|
deleteQueryText = solution.get("deleteQueryText").toString();
|
||||||
|
}
|
||||||
|
}finally{ qexec.close(); }
|
||||||
|
}finally{ displayModel.leaveCriticalSection(); }
|
||||||
|
|
||||||
|
if (!deleteQueryText.equals(DEFAULT_DELETE_QUERY_TEXT)) {
|
||||||
|
log.debug("For " + typeURI + " found delete query \n" + deleteQueryText);
|
||||||
|
} else {
|
||||||
|
log.debug("For " + typeURI + " delete query not found. Using defalut query \n" + deleteQueryText);
|
||||||
|
}
|
||||||
|
return deleteQueryText;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getObjectMostSpecificType(String individualURI, VitroRequest vreq) {
|
||||||
|
String type = "";
|
||||||
|
try {
|
||||||
|
ResultSet results = QueryUtils.getLanguageNeutralQueryResults(makeTypeQuery(individualURI), vreq);
|
||||||
|
while (results.hasNext()) {
|
||||||
|
QuerySolution solution = results.nextSolution();
|
||||||
|
type = solution.get("type").toString();
|
||||||
|
log.debug(type);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Failed to get type for individual URI " + individualURI);
|
||||||
|
log.error(e, e);
|
||||||
|
}
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] getIndividualsToDelete(String targetIndividual, String deleteQuery,VitroRequest vreq) {
|
||||||
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
|
Query queryForTypeSpecificDeleteQuery = QueryFactory.create(deleteQuery);
|
||||||
|
QuerySolutionMap initialBindings = new QuerySolutionMap();
|
||||||
|
initialBindings.add("individualURI", ResourceFactory.createResource( targetIndividual ));
|
||||||
|
Model ontModel = vreq.getJenaOntModel();
|
||||||
|
try {
|
||||||
|
QueryExecution qexec = QueryExecutionFactory.create(queryForTypeSpecificDeleteQuery,ontModel,initialBindings );
|
||||||
|
Model results = qexec.execDescribe();
|
||||||
|
results.write(out,"N3");
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Query raised an error \n" + deleteQuery);
|
||||||
|
log.error(e, e);
|
||||||
|
}
|
||||||
|
return out.toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String makeTypeQuery(String objectURI) {
|
||||||
|
return TYPE_QUERY_START + objectURI + TYPE_QUERY_END;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deleteIndividuals(byte[] toRemove, VitroRequest vreq) {
|
||||||
|
String removingString = new String(toRemove, StandardCharsets.UTF_8);
|
||||||
|
RDFService rdfService = vreq.getRDFService();
|
||||||
|
ChangeSet cs = makeChangeSet(rdfService);
|
||||||
|
InputStream in = new ByteArrayInputStream(toRemove);
|
||||||
|
cs.addRemoval(in, RDFServiceUtils.getSerializationFormatFromJenaString("N3"), ModelNames.ABOX_ASSERTIONS);
|
||||||
|
try {
|
||||||
|
rdfService.changeSetUpdate(cs);
|
||||||
|
} catch (RDFServiceException e) {
|
||||||
|
log.error("Got error while removing\n" + removingString);
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ChangeSet makeChangeSet(RDFService rdfService) {
|
||||||
|
ChangeSet cs = rdfService.manufactureChangeSet();
|
||||||
|
cs.addPreChangeEvent(new BulkUpdateEvent(null, BEGIN));
|
||||||
|
cs.addPostChangeEvent(new BulkUpdateEvent(null, END));
|
||||||
|
return cs;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -28,7 +28,9 @@ public class DefaultDeleteGenerator extends BaseEditConfigurationGenerator imple
|
||||||
private Integer dataHash = 0;
|
private Integer dataHash = 0;
|
||||||
private DataPropertyStatement dps = null;
|
private DataPropertyStatement dps = null;
|
||||||
private String dataLiteral = null;
|
private String dataLiteral = null;
|
||||||
private String template = "confirmDeletePropertyForm.ftl";
|
private String propertyTemplate = "confirmDeletePropertyForm.ftl";
|
||||||
|
private String individualTemplate = "confirmDeleteIndividualForm.ftl";
|
||||||
|
|
||||||
|
|
||||||
//In this case, simply return the edit configuration currently saved in session
|
//In this case, simply return the edit configuration currently saved in session
|
||||||
//Since this is forwarding from another form, an edit configuration should already exist in session
|
//Since this is forwarding from another form, an edit configuration should already exist in session
|
||||||
|
@ -43,12 +45,24 @@ public class DefaultDeleteGenerator extends BaseEditConfigurationGenerator imple
|
||||||
if(editConfiguration == null) {
|
if(editConfiguration == null) {
|
||||||
editConfiguration = setupEditConfiguration(vreq, session);
|
editConfiguration = setupEditConfiguration(vreq, session);
|
||||||
}
|
}
|
||||||
editConfiguration.setTemplate(template);
|
|
||||||
//prepare update?
|
//prepare update?
|
||||||
prepare(vreq, editConfiguration);
|
prepare(vreq, editConfiguration);
|
||||||
|
if (editConfiguration.getPredicateUri() == null && editConfiguration.getSubjectUri() == null) {
|
||||||
|
editConfiguration.setTemplate(individualTemplate);
|
||||||
|
addRedirectUrl(vreq, editConfiguration);
|
||||||
|
}else {
|
||||||
|
editConfiguration.setTemplate(propertyTemplate);
|
||||||
|
}
|
||||||
return editConfiguration;
|
return editConfiguration;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void addRedirectUrl(VitroRequest vreq, EditConfigurationVTwo editConfiguration) {
|
||||||
|
String redirectUrl = vreq.getParameter("redirectUrl");
|
||||||
|
if (redirectUrl != null) {
|
||||||
|
editConfiguration.addFormSpecificData("redirectUrl", redirectUrl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private EditConfigurationVTwo setupEditConfiguration(VitroRequest vreq, HttpSession session) {
|
private EditConfigurationVTwo setupEditConfiguration(VitroRequest vreq, HttpSession session) {
|
||||||
EditConfigurationVTwo editConfiguration = new EditConfigurationVTwo();
|
EditConfigurationVTwo editConfiguration = new EditConfigurationVTwo();
|
||||||
initProcessParameters(vreq, session, editConfiguration);
|
initProcessParameters(vreq, session, editConfiguration);
|
||||||
|
|
|
@ -705,6 +705,10 @@ public class EditConfigurationTemplateModel extends BaseTemplateModel {
|
||||||
public String getDeleteProcessingUrl() {
|
public String getDeleteProcessingUrl() {
|
||||||
return vreq.getContextPath() + "/deletePropertyController";
|
return vreq.getContextPath() + "/deletePropertyController";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getDeleteIndividualProcessingUrl() {
|
||||||
|
return vreq.getContextPath() + "/deleteIndividualController";
|
||||||
|
}
|
||||||
|
|
||||||
//TODO: Check if this logic is correct and delete prohibited does not expect a specific value
|
//TODO: Check if this logic is correct and delete prohibited does not expect a specific value
|
||||||
public boolean isDeleteProhibited() {
|
public boolean isDeleteProhibited() {
|
||||||
|
|
|
@ -128,6 +128,7 @@
|
||||||
<owl:ObjectProperty rdf:about="&display;restrictResultsByClass"/>
|
<owl:ObjectProperty rdf:about="&display;restrictResultsByClass"/>
|
||||||
<owl:ObjectProperty rdf:about="&display;getIndividualsForClass"/>
|
<owl:ObjectProperty rdf:about="&display;getIndividualsForClass"/>
|
||||||
<owl:ObjectProperty rdf:about="&display;hasDataGetter"/>
|
<owl:ObjectProperty rdf:about="&display;hasDataGetter"/>
|
||||||
|
<owl:DataProperty rdf:about="&display;hasDeleteQuery"/>
|
||||||
<owl:ObjectProperty rdf:about="&display;requiresAction">
|
<owl:ObjectProperty rdf:about="&display;requiresAction">
|
||||||
|
|
||||||
</owl:ObjectProperty>
|
</owl:ObjectProperty>
|
||||||
|
|
|
@ -204,6 +204,9 @@ vitro:additionalLink
|
||||||
display:hasElement
|
display:hasElement
|
||||||
a owl:ObjectProperty .
|
a owl:ObjectProperty .
|
||||||
|
|
||||||
|
display:hasDeleteQuery
|
||||||
|
a owl:DataProperty .
|
||||||
|
|
||||||
display:excludeClass
|
display:excludeClass
|
||||||
a owl:ObjectProperty .
|
a owl:ObjectProperty .
|
||||||
|
|
||||||
|
|
|
@ -720,6 +720,7 @@ there_are_no_entries_for_selection = There are no entries in the system from whi
|
||||||
the_range_class_does_not_exist= The range class for this property does not exist in the system.
|
the_range_class_does_not_exist= The range class for this property does not exist in the system.
|
||||||
editing_prohibited = This property is currently configured to prohibit editing.
|
editing_prohibited = This property is currently configured to prohibit editing.
|
||||||
confirm_entry_deletion_from = Are you sure you want to delete the following entry from
|
confirm_entry_deletion_from = Are you sure you want to delete the following entry from
|
||||||
|
confirm_individual_deletion = Are you sure you want to delete the following individual?
|
||||||
|
|
||||||
edit_date_time_value = Edit Date/Time Value
|
edit_date_time_value = Edit Date/Time Value
|
||||||
create_date_time_value = Create Date/Time Value
|
create_date_time_value = Create Date/Time Value
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
<#-- $This file is distributed under the terms of the license in LICENSE$ -->
|
||||||
|
<#if editConfiguration.pageData.redirectUrl??>
|
||||||
|
<#assign redirectUrl = editConfiguration.pageData.redirectUrl />
|
||||||
|
<#else>
|
||||||
|
<#assign redirectUrl = "/" />
|
||||||
|
</#if>
|
||||||
|
<#assign statement = editConfiguration.objectStatementDisplay />
|
||||||
|
<#assign deletionTemplateName = editConfiguration.deleteTemplate/>
|
||||||
|
|
||||||
|
<form action="${editConfiguration.deleteIndividualProcessingUrl}" method="get">
|
||||||
|
<h2>${i18n().confirm_individual_deletion} </h2>
|
||||||
|
|
||||||
|
<input type="hidden" name="individualUri" value="${editConfiguration.objectUri}" role="input" />
|
||||||
|
<input type="hidden" name="redirectUrl" value="${redirectUrl}" role="input" />
|
||||||
|
<#assign deletionTemplateName = editConfiguration.deleteTemplate/>
|
||||||
|
|
||||||
|
<#if statement?has_content>
|
||||||
|
<#include deletionTemplateName />
|
||||||
|
</#if>
|
||||||
|
<br />
|
||||||
|
<p class="submit">
|
||||||
|
<input type="submit" id="submit" value="${i18n().delete_button}" role="button"/>
|
||||||
|
or
|
||||||
|
<a class="cancel" title="${i18n().cancel_title}" href="${editConfiguration.cancelUrl}">${i18n().cancel_link}</a>
|
||||||
|
</p>
|
||||||
|
</form>
|
Loading…
Add table
Reference in a new issue