diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/NewURIMakerVitro.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/NewURIMakerVitro.java index f1297c04d..3abb6da4a 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/NewURIMakerVitro.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/NewURIMakerVitro.java @@ -5,13 +5,18 @@ import java.util.HashSet; import java.util.Random; import java.util.Set; +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.IndividualImpl; +import edu.cornell.mannlib.vitro.webapp.dao.jena.IndividualDaoJena; import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.NewURIMaker; public class NewURIMakerVitro implements NewURIMaker { + private static final Log log = LogFactory.getLog(NewURIMakerVitro.class.getName()); - private static final int MAX_ATTEMPTS = 10; + private static final int MAX_ATTEMPTS = 20; WebappDaoFactory wdf; Set madeURIs = new HashSet(); static Random random = new Random(); @@ -27,24 +32,38 @@ public class NewURIMakerVitro implements NewURIMaker { String newURI = null; int attempts = 0; boolean goodNewURI = false; + log.debug("Before starting : Made URIs contains " + madeURIs.toString()); + while( ! goodNewURI && attempts < MAX_ATTEMPTS ){ attempts++; - if( attempts > 2 && prefixURI != null && !prefixURI.isEmpty() ) + if( attempts > 2 && prefixURI != null && !prefixURI.isEmpty() ) + { + log.debug("Attempts: " + attempts + " and prefix not null and prefix not empty " + prefixURI); ind.setURI(prefixURI + random.nextInt() ); - else + } + else { + log.debug("Attempts:" + attempts + " and setting uri to " + prefixURI); ind.setURI( prefixURI ); - + } newURI = wdf.getIndividualDao().getUnusedURI( ind ); + log.debug("Created new uri " + newURI + " and does madeURIs contain it?" + madeURIs.contains(newURI)); if( newURI != null && ! newURI.isEmpty() && ! madeURIs.contains( newURI) ){ + log.debug("new URI is not null and new URI is empty and madeURIs does not containt new URI"); goodNewURI = true; madeURIs.add( newURI ); - } + } + log.debug("Made URIs contains " + madeURIs.toString()); } - if( newURI != null && !newURI.isEmpty()) + if(goodNewURI && newURI != null && !newURI.isEmpty()) { + log.debug("Decided on this URI " + newURI); + return newURI; - else - throw new InsertException("Could not get a new URI for the prefix " + prefixURI ); + } + else { + log.error("An error occurred and URI could not be created for prefix " + prefixURI); + throw new InsertException("Could not get a new URI for the prefix " + prefixURI ); + } } } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualDaoJena.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualDaoJena.java index c51db6f96..7293e0dda 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualDaoJena.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualDaoJena.java @@ -49,7 +49,9 @@ import edu.cornell.mannlib.vitro.webapp.dao.jena.event.IndividualUpdateEvent; import edu.cornell.mannlib.vitro.webapp.edit.EditLiteral; public class IndividualDaoJena extends JenaBaseDao implements IndividualDao { - + //For random number generation, creating it everytime the method is called lead to nextInt being about the same + //if calls were made close together in time + private Random random = new Random(System.currentTimeMillis()); public IndividualDaoJena(WebappDaoFactoryJena wadf) { super(wadf); } @@ -634,6 +636,9 @@ public class IndividualDaoJena extends JenaBaseDao implements IndividualDao { //we always want local names like n23423 for the default namespace namespace = DEFAULT_NAMESPACE; uri = null; + log.debug("Setting namespace to default namespace " + DEFAULT_NAMESPACE + " and uri is null"); + log.debug("Individual : " + individual + " - URI: " + individual.getURI() + " - namespace -" + + individual.getNamespace() + "- "); }else if( individual.getURI() != null ){ errMsg = getWebappDaoFactory().checkURI(individual.getURI()); if( errMsg == null){ @@ -642,14 +647,16 @@ public class IndividualDaoJena extends JenaBaseDao implements IndividualDao { }else{ throw new InsertException(errMsg); } + log.debug("Individual URI not null " + individual.getURI() + " and uriIsGood is true and uri set to individual uri"); }else{ namespace = individual.getNamespace(); if( namespace == null || namespace.length() == 0 ) namespace = DEFAULT_NAMESPACE; String localName = individual.getName(); - + log.debug("Namespace " + namespace + " -localname=" + localName); /* try to use the specified namespace and local name */ - if (localName != null) { + if (localName != null) { + log.debug("Local name not equal to null so replacing characters, etc."); localName = localName.replaceAll("\\W", ""); localName = localName.replaceAll(":", ""); if (localName.length() > 2) { @@ -661,29 +668,31 @@ public class IndividualDaoJena extends JenaBaseDao implements IndividualDao { if( errMsg == null) uriIsGood = true; else - throw new InsertException(errMsg); + throw new InsertException(errMsg); + log.debug("uriIsGood is true and uri is " + uri); } } /* else try namespace + n2343 */ } - Random random = new Random(System.currentTimeMillis()); int attempts = 0; - while( uriIsGood == false && attempts < 30 ){ + while( uriIsGood == false && attempts < 30 ){ + log.debug("While loop: Uri is good false, attempt=" + attempts); String localName = "n" + random.nextInt( Math.min(Integer.MAX_VALUE,(int)Math.pow(2,attempts + 13)) ); - uri = namespace + localName; + uri = namespace + localName; + log.debug("Trying URI " + uri); errMsg = getWebappDaoFactory().checkURI(uri); if( errMsg != null) uri = null; else - uriIsGood = true; + uriIsGood = true; attempts++; } if( uri == null ) throw new InsertException("Could not create URI for individual: " + errMsg); - + log.debug("Using URI" + uri); return uri; } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/ManagePageGenerator.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/ManagePageGenerator.java index 6e985d2ee..d23485c37 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/ManagePageGenerator.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/ManagePageGenerator.java @@ -307,6 +307,8 @@ public class ManagePageGenerator extends BaseEditConfigurationGenerator implemen //Takes data getter information, packs within JSON object to send back to the form private void addDataGetterSpecificFormData(String dataGetterURI, ProcessDataGetterN3 pn, OntModel queryModel, JSONArray jsonArray, ServletContext context) { JSONObject jo = pn.getExistingValuesJSON(dataGetterURI, queryModel, context); + //Add dataGetterURI to jsonObject + jo.element("URI", dataGetterURI); jsonArray.add(jo); } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/ManagePagePreprocessor.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/ManagePagePreprocessor.java index 112e24fc2..41520c592 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/ManagePagePreprocessor.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/ManagePagePreprocessor.java @@ -85,42 +85,45 @@ public class ManagePagePreprocessor extends private void processExistingValues() { //For all literals that were originally in scope that don't have values on the form - //anymore, replace with blank sentinel value + //anymore, replace with null value //For those literals, those values will be replaced with form values where overwritten //And will be deleted where not overwritten which is the behavior we desire - Map> literalsInScope = this.editConfiguration.getLiteralsInScope(); - Map> urisInScope = this.editConfiguration.getUrisInScope(); - List literalKeys = new ArrayList(literalsInScope.keySet()); - - - List uriKeys = new ArrayList(urisInScope.keySet()); - for(String literalName: literalKeys) { + if(this.editConfiguration.isParamUpdate()) { + Map> literalsInScope = this.editConfiguration.getLiteralsInScope(); + Map> urisInScope = this.editConfiguration.getUrisInScope(); + List literalKeys = new ArrayList(literalsInScope.keySet()); + - //if submission already has value for this, then leave be - //otherwise replace with null which will not be valid N3 - //TODO: Replace with better solution for forcing literal deletion - boolean haslv = submission.hasLiteralValue(literalName); - if(!submission.hasLiteralValue(literalName)) { - submission.addLiteralToForm(editConfiguration, - editConfiguration.getField(literalName), - literalName, - (new String[] {null})); + List uriKeys = new ArrayList(urisInScope.keySet()); + for(String literalName: literalKeys) { + + //if submission already has value for this, then leave be + //otherwise replace with null which will not be valid N3 + //TODO: Replace with better solution for forcing literal deletion + boolean haslv = submission.hasLiteralValue(literalName); + if(!submission.hasLiteralValue(literalName)) { + submission.addLiteralToForm(editConfiguration, + editConfiguration.getField(literalName), + literalName, + (new String[] {null})); + } + } + + + for(String uriName: uriKeys) { + //these values should never be overwritten or deleted + //if(uriName != "page" && uriName != "menuItem" && !uriName.startsWith("dataGetter")) { + if(uriName != "page") { + boolean hasuv = submission.hasUriValue(uriName); + if(!submission.hasUriValue(uriName)) { + submission.addUriToForm(editConfiguration, + uriName, + (new String[] {EditConfigurationConstants.BLANK_SENTINEL})); + } + } } } - for(String uriName: uriKeys) { - //these values should never be overwritten or deleted - if(uriName != "page" && uriName != "menuItem" && !uriName.startsWith("dataGetter")) { - boolean hasuv = submission.hasUriValue(uriName); - if(!submission.hasUriValue(uriName)) { - submission.addUriToForm(editConfiguration, - uriName, - (new String[] {EditConfigurationConstants.BLANK_SENTINEL})); - } - } - } - //Other than data getter itself, also get rid of any of the old URIs if any - } @@ -236,35 +239,15 @@ public class ManagePagePreprocessor extends submission.addUriToForm(editConfiguration, submissionUriName, uriValuesSubmission); } - //this needs to be different - //Get the literals directly from the processor - which you can get based on counter - //Problem then is we know what the connection is - some way to put that logic within the processor itself? - //It already knows the json object - - //--> Get field for this base label, with counter value - that you get from configuration -/* - while(jsonObject.keys().hasNext()) - { - //Other than class, all other variables considered a submission value corresponding to field - String key = (String) jsonObject.keys().next(); - if(key != "dataGetterClass") { - //not expecting multiple values, so will need to either make this array or - //think about this some more - //TODO: Consider multiple values here - Map submissionValues = new HashMap(); - submissionValues.put(key, new String[]{jsonObject.getString(key)} ); - - if(literalLabels.contains(key)) { - submission.addLiteralToForm(editConfiguration.getField(key), field, var, valuesArray) - } + + //To get data getter uris, check if editing an existing set and include those as form inputs + if(editConfiguration.isParamUpdate()) { + String URIValue = jsonObject.getString("URI"); + if(URIValue != null) { + String dataGetterURISubmissionName = pn.getDataGetterVarName(counter); + submission.addUriToForm(editConfiguration, dataGetterURISubmissionName, new String[]{URIValue}); } - } - List uris = pn.retrieveUrissOnForm(counter); - for(String l:literals) { - //json object should have - submissionValues.put(l, new String[]{jsonObject.getString(l)} ); - }*/ } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/utils/ProcessDataGetterAbstract.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/utils/ProcessDataGetterAbstract.java index 0f9b4a0a1..05743d168 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/utils/ProcessDataGetterAbstract.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/utils/ProcessDataGetterAbstract.java @@ -32,7 +32,12 @@ public abstract class ProcessDataGetterAbstract implements ProcessDataGetterN3 { //placeholder so need "?" in front of the variable public String getDataGetterVar(int counter) { - return "?dataGetter" + counter; + return "?" + getDataGetterVarName(counter); + } + + //Just the var name, no "?" + public String getDataGetterVarName(int counter) { + return "dataGetter" + counter; } public String getPrefixes() { diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/utils/ProcessDataGetterN3.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/utils/ProcessDataGetterN3.java index d14eafe90..1eef4e473 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/utils/ProcessDataGetterN3.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/utils/ProcessDataGetterN3.java @@ -28,6 +28,7 @@ public interface ProcessDataGetterN3 { public List getUriVarNamesBase(); public String getVarName(String base, int counter); public String getDataGetterVar(int counter); + public String getDataGetterVarName(int counter); public List getNewResources(int counter); //Get Existing values to put in scope diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/utils/ProcessSparqlDataGetterN3.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/utils/ProcessSparqlDataGetterN3.java index 3098cdb73..79136b506 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/utils/ProcessSparqlDataGetterN3.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/utils/ProcessSparqlDataGetterN3.java @@ -36,7 +36,6 @@ public class ProcessSparqlDataGetterN3 extends ProcessDataGetterAbstract { } //Pass in variable that represents the counter - //TODO: ensure correct model returned //We shouldn't use the ACTUAL values here but generate the n3 required public List retrieveN3Required(int counter) { String dataGetterVar = getDataGetterVar(counter); @@ -54,14 +53,6 @@ public class ProcessSparqlDataGetterN3 extends ProcessDataGetterAbstract { } - //Need to add method sfor returning the fields, literals on form, and all that - /* - * addLiteralsAndUrisOnForm(pn, counter); - // Add fields - addFields(pn, counter); - //Add input values to submission - addInputsToSubmission(pn, counter); - */ public List retrieveLiteralsOnForm(int counter) { List literalsOnForm = new ArrayList(); literalsOnForm.add(getVarName("saveToVar",counter)); @@ -81,16 +72,7 @@ public class ProcessSparqlDataGetterN3 extends ProcessDataGetterAbstract { public List retrieveFields(int counter) { List fields = new ArrayList(); - - //An alternative way of doing this - /* - List allFieldsBase = new ArrayList(); - allFieldsBase.addAll(getLiteralVarNamesBase()); - allFieldsBase.addAll(getUriVarNamesBase()); - - for(String varName: allFieldsBase) { - fields.add(new FieldVTwo().setName(getVarName(varName, counter))); - } */ + //For existing data getters //fields.add(new FieldVTwo().setName(getVarName("dataGetter", counter))); fields.add(new FieldVTwo().setName(getVarName("queryModel", counter))); diff --git a/webapp/test/edu/cornell/mannlib/vitro/webapp/dao/NewURIMakerVitroTest.java b/webapp/test/edu/cornell/mannlib/vitro/webapp/dao/NewURIMakerVitroTest.java new file mode 100644 index 000000000..4893d359c --- /dev/null +++ b/webapp/test/edu/cornell/mannlib/vitro/webapp/dao/NewURIMakerVitroTest.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.dao; + +import static org.junit.Assert.*; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.junit.Test; + +import com.hp.hpl.jena.ontology.OntModel; +import com.hp.hpl.jena.ontology.OntModelSpec; +import com.hp.hpl.jena.rdf.model.ModelFactory; +import com.hp.hpl.jena.vocabulary.OWL; +import com.hp.hpl.jena.vocabulary.RDF; + +import edu.cornell.mannlib.vitro.testing.AbstractTestClass; +import edu.cornell.mannlib.vitro.webapp.dao.jena.OntModelSelector; +import edu.cornell.mannlib.vitro.webapp.dao.jena.SimpleOntModelSelector; +import edu.cornell.mannlib.vitro.webapp.dao.jena.WebappDaoFactoryJena; + +public class NewURIMakerVitroTest extends AbstractTestClass{ + + @Test + public void testMultipleNewURIs() { + //Three items needs new URIs assigned in the default namespace + //Var name to namespace, in this case null to denote default namespace + Map newResources = new HashMap(); + newResources.put("page", null); + newResources.put("menuItem", null); + newResources.put("dataGetter", null); + + //Setup webappdaofactory + WebappDaoFactoryJena wadf = this.setupWebappDaoFactory(); + NewURIMakerVitro nv = new NewURIMakerVitro(wadf); + + //Now test for new URI + HashMap varToNewURIs = new HashMap(); + try { + for (String key : newResources.keySet()) { + String prefix = newResources.get(key); + String uri = nv.getUnusedNewURI(prefix); + varToNewURIs.put(key, uri); + } + } catch(Exception ex) { + System.out.println("Error occurred " + ex); + } + + //Ensure that URIs are not included more than once + List values = new ArrayList(varToNewURIs.values()); + Set valuesSet = new HashSet(varToNewURIs.values()); + assertTrue(valuesSet.size() == values.size()); + + } + + @Test + public void testNonNullNamespace() { + //Three items needs new URIs assigned in the default namespace + //Var name to namespace, in this case null to denote default namespace + Map newResources = new HashMap(); + newResources.put("page", "http://displayOntology/test/n12"); + + + //Setup webappdaofactory + WebappDaoFactoryJena wadf = this.setupWebappDaoFactory(); + NewURIMakerVitro nv = new NewURIMakerVitro(wadf); + + //Now test for new URI + HashMap varToNewURIs = new HashMap(); + try { + for (String key : newResources.keySet()) { + String prefix = newResources.get(key); + String uri = nv.getUnusedNewURI(prefix); + varToNewURIs.put(key, uri); + } + } catch(Exception ex) { + System.out.println("Error occurred " + ex); + } + + //Ensure that URIs are not included more than once + List values = new ArrayList(varToNewURIs.values()); + Set valuesSet = new HashSet(varToNewURIs.values()); + assertTrue(valuesSet.size() == values.size()); + } + + private WebappDaoFactoryJena setupWebappDaoFactory() { + String defaultNamespace= "http://vivo.mannlib.cornell.edu/individual/"; + String testNamespace = "http://displayOntology/test/"; + OntModel ontModel = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM); + ontModel.add( + ontModel.createResource(defaultNamespace + "n234"), + RDF.type, + OWL.Thing); + ontModel.add( + ontModel.createResource(testNamespace + "n234"), + RDF.type, + OWL.Thing); + OntModelSelector selector = new SimpleOntModelSelector(ontModel); + //Set up default namespace somewhere? + WebappDaoFactoryConfig config = new WebappDaoFactoryConfig(); + config.setDefaultNamespace(defaultNamespace); + //Set up some test uris + WebappDaoFactoryJena wadf = new WebappDaoFactoryJena(selector, config); + return wadf; + } + +} diff --git a/webapp/web/js/menupage/pageManagementUtils.js b/webapp/web/js/menupage/pageManagementUtils.js index 84bfa3b8c..4338799d5 100644 --- a/webapp/web/js/menupage/pageManagementUtils.js +++ b/webapp/web/js/menupage/pageManagementUtils.js @@ -547,6 +547,11 @@ var pageManagementUtils = { var dataGetterProcessor = pageManagementUtils.dataGetterProcessorMap[dataGetterType]; //the content type specific processor will create the json object to be returned var jsonObject = dataGetterProcessor.processPageContentSection(pageContentSection); + //if data getter uri included, include that as well + if(pageContentSection.find("input[name='URI']").length > 0) { + var uriValue = pageContentSection.find("input[name='URI']").val(); + jsonObject["URI"] = uriValue; + } return jsonObject; } else { //ERROR handling @@ -618,6 +623,8 @@ var pageManagementUtils = { var $newContentObj = pageManagementUtils.cloneContentAreaForEdit(contentType, contentTypeLabel, additionalLabelText); //Populate the section with the values dataGetterProcessorObject.populatePageContentSection(JSONContentObject, $newContentObj); + //Also include a hidden input with data getter URI + pageManagementUtils.includeDataGetterURI(JSONContentObject, $newContentObj); } else { //error condition } @@ -627,6 +634,12 @@ var pageManagementUtils = { } }, + includeDataGetterURI:function(JSONContentObject, $newContentObj) { + var uri = JSONContentObject["URI"]; + if(uri != null) { + $("").appendTo($newContentObj); + } + }, //Get the data getter processor getDataGetterProcessorObject:function(pageContentSection) { var dataGetterType = pageManagementUtils.processDataGetterUtils.selectDataGetterType(pageContentSection);