From f6b2387a3ecb5452dde86df09f4c834d609c687e Mon Sep 17 00:00:00 2001 From: hjkhjk54 Date: Thu, 21 Jun 2012 20:44:42 +0000 Subject: [PATCH] updates for page management as well as updates to new URI maker and individual dao jena to handle creation of new URI (old code was returning duplicate when maximum number of attempts was exhausted in NewURIMakerVitro b/c IndividualDaoJena kept returning the same URI since Random instance was set with system time seed and possibly the calls to the method were occurring close together in time and nextInt kept returning the same number). --- .../vitro/webapp/dao/NewURIMakerVitro.java | 35 ++++-- .../webapp/dao/jena/IndividualDaoJena.java | 27 +++-- .../generators/ManagePageGenerator.java | 2 + .../preprocessors/ManagePagePreprocessor.java | 97 +++++++-------- .../utils/ProcessDataGetterAbstract.java | 7 +- .../utils/ProcessDataGetterN3.java | 1 + .../utils/ProcessSparqlDataGetterN3.java | 20 +--- .../webapp/dao/NewURIMakerVitroTest.java | 111 ++++++++++++++++++ webapp/web/js/menupage/pageManagementUtils.js | 13 ++ 9 files changed, 219 insertions(+), 94 deletions(-) create mode 100644 webapp/test/edu/cornell/mannlib/vitro/webapp/dao/NewURIMakerVitroTest.java 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);