diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/FreemarkerConfiguration.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/FreemarkerConfiguration.java index 5940db33e..de6fd454c 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/FreemarkerConfiguration.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/FreemarkerConfiguration.java @@ -28,6 +28,7 @@ import freemarker.template.Configuration; import freemarker.template.DefaultObjectWrapper; import freemarker.template.TemplateException; import freemarker.template.TemplateModelException; +import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.EditConfigurationConstants; public class FreemarkerConfiguration extends Configuration { @@ -108,6 +109,9 @@ public class FreemarkerConfiguration extends Configuration { sharedVariables.putAll(getMethods()); sharedVariables.put("siteTagline", appBean.getShortHand()); + //Put in edit configuration constants - useful for freemarker templates/editing + sharedVariables.put("editConfigurationConstants", EditConfigurationConstants.exportConstants()); + for ( Map.Entry variable : sharedVariables.entrySet() ) { try { setSharedVariable(variable.getKey(), variable.getValue()); diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/ProcessRdfForm.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/ProcessRdfForm.java index 079e19ef3..8d4f503b4 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/ProcessRdfForm.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/ProcessRdfForm.java @@ -7,6 +7,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Random; @@ -23,6 +24,7 @@ import com.hp.hpl.jena.shared.Lock; import edu.cornell.mannlib.vitro.webapp.dao.InsertException; import edu.cornell.mannlib.vitro.webapp.dao.jena.DependentResourceDeleteJena; import edu.cornell.mannlib.vitro.webapp.dao.jena.event.EditEvent; +import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.EditConfigurationConstants; import edu.cornell.mannlib.vitro.webapp.edit.n3editing.controller.ProcessRdfFormController.Utilities; /** @@ -41,8 +43,7 @@ public class ProcessRdfForm { private EditN3GeneratorVTwo populator; private Map urisForNewResources = null; - - /** + /** * Construct the ProcessRdfForm object. */ public ProcessRdfForm( EditConfigurationVTwo config, NewURIMaker newURIMaker){ @@ -171,7 +172,13 @@ public class ProcessRdfForm { //need to substitute into the return to URL becase it may need new resource URIs List URLToReturnTo = Arrays.asList(submission.getEntityToReturnTo()); - + + /* *********** Check if new resource needs to be forcibly created ******** */ + urisForNewResources = URIsForNewRsources(editConfig, newURIMaker); + substituteInForcedNewURIs(urisForNewResources, submission.getUrisFromForm(), requiredAsserts, optionalAsserts, URLToReturnTo); + logSubstitue( "Added form URIs that required new URIs", requiredAsserts, optionalAsserts, requiredRetracts, optionalRetracts); + + /* ********** Form submission URIs ********* */ substituteInMultiURIs(submission.getUrisFromForm(), requiredAsserts, optionalAsserts, URLToReturnTo); logSubstitue( "Added form URIs", requiredAsserts, optionalAsserts, requiredRetracts, optionalRetracts); @@ -182,10 +189,13 @@ public class ProcessRdfForm { logSubstitue( "Added form Literals", requiredAsserts, optionalAsserts, requiredRetracts, optionalRetracts); //Retractions does NOT get values from form. + + /* *********** Add subject, object and predicate ******** */ substituteInSubPredObjURIs(editConfig, requiredAsserts, optionalAsserts, requiredRetracts, optionalRetracts, URLToReturnTo); logSubstitue( "Added sub, pred and obj URIs", requiredAsserts, optionalAsserts, requiredRetracts, optionalRetracts); + /* ********* Existing URIs and Literals ********** */ substituteInMultiURIs(editConfig.getUrisInScope(), requiredAsserts, optionalAsserts, requiredRetracts, optionalRetracts, URLToReturnTo); @@ -197,7 +207,8 @@ public class ProcessRdfForm { //Both Assertions and Retractions get existing values. /* ************ Edits may need new resources *********** */ - urisForNewResources = URIsForNewRsources(editConfig, newURIMaker); + //moved this up? + //urisForNewResources = URIsForNewRsources(editConfig, newURIMaker); substituteInURIs( urisForNewResources, requiredAsserts, optionalAsserts, URLToReturnTo); logSubstitue( "Added URIs for new Resources", requiredAsserts, optionalAsserts, requiredRetracts, optionalRetracts); // Only Assertions get new resources. @@ -205,7 +216,9 @@ public class ProcessRdfForm { submission.setEntityToReturnTo(URLToReturnTo.get(0)); } - //TODO: maybe move this to utils or contorller? + + + //TODO: maybe move this to utils or contorller? public static AdditionsAndRetractions addDependentDeletes( AdditionsAndRetractions changes, Model queryModel){ //Add retractions for dependent resource delete if that is configured and //if there are any dependent resources. @@ -454,6 +467,36 @@ public class ProcessRdfForm { } } } + + /* + * In some situations, an object may have an existing URI but be left blank + * when the desired behavior is that a new object be created to replace the existing URI + * E.g. autocomplete forms that allow editing of autocomplete fields + */ + @SuppressWarnings("unchecked") + private void substituteInForcedNewURIs( + Map urisForNewResources, Map> urisFromForm, + List requiredAsserts, List optionalAsserts, + List uRLToReturnTo) { + Map> newUris = new HashMap>(); + //Check if any values from the submission have the "force new uri" value + //TODO: Check how to handle multiple new resource values + Iterator keyIterator = urisFromForm.keySet().iterator(); + while(keyIterator.hasNext()) { + String key = keyIterator.next().toString(); + if(urisFromForm.get(key).contains(EditConfigurationConstants.NEW_URI_SENTINEL)) { + String newUri = urisForNewResources.get(key); + List newUrisForKey = new ArrayList(); + newUrisForKey.add(newUri); + newUris.put(key, newUrisForKey); + } + } + if(newUris.size() > 0) { + substituteInMultiURIs(newUris, requiredAsserts, optionalAsserts, uRLToReturnTo); + } + + } + private static Log log = LogFactory.getLog(ProcessRdfForm.class); } \ No newline at end of file diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/EditConfigurationConstants.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/EditConfigurationConstants.java new file mode 100644 index 000000000..350a7be38 --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/EditConfigurationConstants.java @@ -0,0 +1,36 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration; + +import java.lang.reflect.Modifier; +import java.util.HashMap; +import java.util.Map; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.ProcessRdfForm; + + +public class EditConfigurationConstants { + /** Constants used by edit configuration */ + //forces creation of new uri if present + public static final String NEW_URI_SENTINEL = ">NEW URI REQUIRED<"; + //For freemarker configuration + public static Map exportConstants() { + Map constants = new HashMap(); + java.lang.reflect.Field[] fields = EditConfigurationConstants.class.getDeclaredFields(); + for(java.lang.reflect.Field f: fields) { + if(Modifier.isStatic(f.getModifiers()) && + Modifier.isPublic(f.getModifiers())) { + try { + constants.put(f.getName(), f.get(null).toString()); + } catch(Exception ex) { + log.error("An exception occurred in trying to retrieve this field ", ex); + } + } + } + return constants; + } + private static Log log = LogFactory.getLog(EditConfigurationConstants.class); + +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/controller/ProcessRdfFormController.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/controller/ProcessRdfFormController.java index 3aedff039..3c8c0a717 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/controller/ProcessRdfFormController.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/controller/ProcessRdfFormController.java @@ -49,6 +49,8 @@ import edu.cornell.mannlib.vitro.webapp.edit.n3editing.processEdit.RdfLiteralHas public class ProcessRdfFormController extends FreemarkerHttpServlet{ private Log log = LogFactory.getLog(ProcessRdfFormController.class); + + @Override protected Actions requiredActions(VitroRequest vreq) { diff --git a/webapp/test/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/ProcessRdfFormTest.java b/webapp/test/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/ProcessRdfFormTest.java index 7d992e620..b8bb06b55 100644 --- a/webapp/test/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/ProcessRdfFormTest.java +++ b/webapp/test/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/ProcessRdfFormTest.java @@ -15,6 +15,7 @@ import com.hp.hpl.jena.rdf.model.ResourceFactory; import edu.cornell.mannlib.vitro.testing.AbstractTestClass; import edu.cornell.mannlib.vitro.webapp.dao.InsertException; +import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.EditConfigurationConstants; public class ProcessRdfFormTest extends AbstractTestClass{ @@ -242,6 +243,59 @@ public class ProcessRdfFormTest extends AbstractTestClass{ ResourceFactory.createProperty("http://test.com/uri2"), ResourceFactory.createResource("http://test.com/uri3"))); } + + @Test + //Edit existing statement + public void forcedNewResourceTest() throws Exception{ + /* A very basic new statement edit. */ + EditConfigurationVTwo config = new EditConfigurationVTwo(); + config.setEditKey("mockEditKey"); + config.setN3Required(Arrays.asList("?newRes ?test2 ?test3 ." )); + config.setUrisOnform(Arrays.asList( "newRes", "test2", "test3")); + //set uris in scope to include an existing value for new resource + config.addUrisInScope("newRes", Arrays.asList("")); + config.addNewResource("newRes", null); + config.setEntityToReturnTo("?newRes"); + + Map values = new HashMap(); + //value from form should indicate that newRes should have new uri created + values.put("newRes", (new String[] {EditConfigurationConstants.NEW_URI_SENTINEL})); + values.put("test2", (new String[] {"http://test.com/uri2"})); + values.put("test3", (new String[] {"http://test.com/uri3"})); + values.put("editKey", (new String[] {"mockEditKey"})); + + MultiValueEditSubmission submission = new MultiValueEditSubmission(values, config); + + ProcessRdfForm processor = new ProcessRdfForm(config,getMockNewURIMaker()); + + /* test just the N3 substitution part */ + Listreq = config.getN3Required(); + Listopt = config.getN3Optional(); + processor.subInValuesToN3( config , submission, req, opt, null , null); + assertNotNull(req); + assertTrue( req.size() > 0); + assertNotNull(req.get(0)); + assertEquals("<"+NEWURI_STRING + "0> .", req.get(0)); + + assertEquals("<" + NEWURI_STRING + "0>", submission.getEntityToReturnTo()); + + /* test the N3 and parse RDF parts */ + AdditionsAndRetractions changes = processor.process( config, submission ); + + assertNotNull( changes ); + assertNotNull( changes.getAdditions() ); + assertNotNull( changes.getRetractions()); + assertTrue( changes.getAdditions().size() == 1 ); + //the old uri should be removed + assertTrue( changes.getRetractions().size() == 0 ); + + assertTrue( changes.getAdditions().contains( + ResourceFactory.createResource(NEWURI_STRING + "0"), + ResourceFactory.createProperty("http://test.com/uri2"), + ResourceFactory.createResource("http://test.com/uri3"))); + + + } String NEWURI_STRING= "http://newURI/n";