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).

This commit is contained in:
hjkhjk54 2012-06-21 20:44:42 +00:00
parent 98e5dc93f6
commit f6b2387a3e
9 changed files with 219 additions and 94 deletions

View file

@ -5,13 +5,18 @@ import java.util.HashSet;
import java.util.Random; import java.util.Random;
import java.util.Set; 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.Individual;
import edu.cornell.mannlib.vitro.webapp.beans.IndividualImpl; 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; import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.NewURIMaker;
public class NewURIMakerVitro implements 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; WebappDaoFactory wdf;
Set<String> madeURIs = new HashSet<String>(); Set<String> madeURIs = new HashSet<String>();
static Random random = new Random(); static Random random = new Random();
@ -27,24 +32,38 @@ public class NewURIMakerVitro implements NewURIMaker {
String newURI = null; String newURI = null;
int attempts = 0; int attempts = 0;
boolean goodNewURI = false; boolean goodNewURI = false;
log.debug("Before starting : Made URIs contains " + madeURIs.toString());
while( ! goodNewURI && attempts < MAX_ATTEMPTS ){ while( ! goodNewURI && attempts < MAX_ATTEMPTS ){
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() ); ind.setURI(prefixURI + random.nextInt() );
else }
else {
log.debug("Attempts:" + attempts + " and setting uri to " + prefixURI);
ind.setURI( prefixURI ); ind.setURI( prefixURI );
}
newURI = wdf.getIndividualDao().getUnusedURI( ind ); 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) ){ 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; goodNewURI = true;
madeURIs.add( newURI ); 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; return newURI;
else }
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 ); throw new InsertException("Could not get a new URI for the prefix " + prefixURI );
} }
}
} }

View file

@ -49,7 +49,9 @@ import edu.cornell.mannlib.vitro.webapp.dao.jena.event.IndividualUpdateEvent;
import edu.cornell.mannlib.vitro.webapp.edit.EditLiteral; import edu.cornell.mannlib.vitro.webapp.edit.EditLiteral;
public class IndividualDaoJena extends JenaBaseDao implements IndividualDao { 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) { public IndividualDaoJena(WebappDaoFactoryJena wadf) {
super(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 //we always want local names like n23423 for the default namespace
namespace = DEFAULT_NAMESPACE; namespace = DEFAULT_NAMESPACE;
uri = null; 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 ){ }else if( individual.getURI() != null ){
errMsg = getWebappDaoFactory().checkURI(individual.getURI()); errMsg = getWebappDaoFactory().checkURI(individual.getURI());
if( errMsg == null){ if( errMsg == null){
@ -642,14 +647,16 @@ public class IndividualDaoJena extends JenaBaseDao implements IndividualDao {
}else{ }else{
throw new InsertException(errMsg); throw new InsertException(errMsg);
} }
log.debug("Individual URI not null " + individual.getURI() + " and uriIsGood is true and uri set to individual uri");
}else{ }else{
namespace = individual.getNamespace(); namespace = individual.getNamespace();
if( namespace == null || namespace.length() == 0 ) if( namespace == null || namespace.length() == 0 )
namespace = DEFAULT_NAMESPACE; namespace = DEFAULT_NAMESPACE;
String localName = individual.getName(); String localName = individual.getName();
log.debug("Namespace " + namespace + " -localname=" + localName);
/* try to use the specified namespace and local name */ /* 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("\\W", "");
localName = localName.replaceAll(":", ""); localName = localName.replaceAll(":", "");
if (localName.length() > 2) { if (localName.length() > 2) {
@ -662,17 +669,19 @@ public class IndividualDaoJena extends JenaBaseDao implements IndividualDao {
uriIsGood = true; uriIsGood = true;
else else
throw new InsertException(errMsg); throw new InsertException(errMsg);
log.debug("uriIsGood is true and uri is " + uri);
} }
} }
/* else try namespace + n2343 */ /* else try namespace + n2343 */
} }
Random random = new Random(System.currentTimeMillis());
int attempts = 0; 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)) ); 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); errMsg = getWebappDaoFactory().checkURI(uri);
if( errMsg != null) if( errMsg != null)
uri = null; uri = null;
@ -683,7 +692,7 @@ public class IndividualDaoJena extends JenaBaseDao implements IndividualDao {
if( uri == null ) if( uri == null )
throw new InsertException("Could not create URI for individual: " + errMsg); throw new InsertException("Could not create URI for individual: " + errMsg);
log.debug("Using URI" + uri);
return uri; return uri;
} }

View file

@ -307,6 +307,8 @@ public class ManagePageGenerator extends BaseEditConfigurationGenerator implemen
//Takes data getter information, packs within JSON object to send back to the form //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) { private void addDataGetterSpecificFormData(String dataGetterURI, ProcessDataGetterN3 pn, OntModel queryModel, JSONArray jsonArray, ServletContext context) {
JSONObject jo = pn.getExistingValuesJSON(dataGetterURI, queryModel, context); JSONObject jo = pn.getExistingValuesJSON(dataGetterURI, queryModel, context);
//Add dataGetterURI to jsonObject
jo.element("URI", dataGetterURI);
jsonArray.add(jo); jsonArray.add(jo);
} }

View file

@ -85,9 +85,10 @@ public class ManagePagePreprocessor extends
private void processExistingValues() { private void processExistingValues() {
//For all literals that were originally in scope that don't have values on the form //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 //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 //And will be deleted where not overwritten which is the behavior we desire
if(this.editConfiguration.isParamUpdate()) {
Map<String, List<Literal>> literalsInScope = this.editConfiguration.getLiteralsInScope(); Map<String, List<Literal>> literalsInScope = this.editConfiguration.getLiteralsInScope();
Map<String, List<String>> urisInScope = this.editConfiguration.getUrisInScope(); Map<String, List<String>> urisInScope = this.editConfiguration.getUrisInScope();
List<String> literalKeys = new ArrayList<String>(literalsInScope.keySet()); List<String> literalKeys = new ArrayList<String>(literalsInScope.keySet());
@ -108,9 +109,11 @@ public class ManagePagePreprocessor extends
} }
} }
for(String uriName: uriKeys) { for(String uriName: uriKeys) {
//these values should never be overwritten or deleted //these values should never be overwritten or deleted
if(uriName != "page" && uriName != "menuItem" && !uriName.startsWith("dataGetter")) { //if(uriName != "page" && uriName != "menuItem" && !uriName.startsWith("dataGetter")) {
if(uriName != "page") {
boolean hasuv = submission.hasUriValue(uriName); boolean hasuv = submission.hasUriValue(uriName);
if(!submission.hasUriValue(uriName)) { if(!submission.hasUriValue(uriName)) {
submission.addUriToForm(editConfiguration, submission.addUriToForm(editConfiguration,
@ -119,7 +122,7 @@ public class ManagePagePreprocessor extends
} }
} }
} }
//Other than data getter itself, also get rid of any of the old URIs if any }
} }
@ -236,37 +239,17 @@ public class ManagePagePreprocessor extends
submission.addUriToForm(editConfiguration, submissionUriName, uriValuesSubmission); 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 //To get data getter uris, check if editing an existing set and include those as form inputs
/* if(editConfiguration.isParamUpdate()) {
while(jsonObject.keys().hasNext()) String URIValue = jsonObject.getString("URI");
{ if(URIValue != null) {
//Other than class, all other variables considered a submission value corresponding to field String dataGetterURISubmissionName = pn.getDataGetterVarName(counter);
String key = (String) jsonObject.keys().next(); submission.addUriToForm(editConfiguration, dataGetterURISubmissionName, new String[]{URIValue});
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<String, String[]> submissionValues = new HashMap<String, String[]>();
submissionValues.put(key, new String[]{jsonObject.getString(key)} );
if(literalLabels.contains(key)) {
submission.addLiteralToForm(editConfiguration.getField(key), field, var, valuesArray)
} }
} }
} }
List<String> uris = pn.retrieveUrissOnForm(counter);
for(String l:literals) {
//json object should have
submissionValues.put(l, new String[]{jsonObject.getString(l)} );
}*/
}

View file

@ -32,7 +32,12 @@ public abstract class ProcessDataGetterAbstract implements ProcessDataGetterN3 {
//placeholder so need "?" in front of the variable //placeholder so need "?" in front of the variable
public String getDataGetterVar(int counter) { 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() { public String getPrefixes() {

View file

@ -28,6 +28,7 @@ public interface ProcessDataGetterN3 {
public List<String> getUriVarNamesBase(); public List<String> getUriVarNamesBase();
public String getVarName(String base, int counter); public String getVarName(String base, int counter);
public String getDataGetterVar(int counter); public String getDataGetterVar(int counter);
public String getDataGetterVarName(int counter);
public List<String> getNewResources(int counter); public List<String> getNewResources(int counter);
//Get Existing values to put in scope //Get Existing values to put in scope

View file

@ -36,7 +36,6 @@ public class ProcessSparqlDataGetterN3 extends ProcessDataGetterAbstract {
} }
//Pass in variable that represents the counter //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 //We shouldn't use the ACTUAL values here but generate the n3 required
public List<String> retrieveN3Required(int counter) { public List<String> retrieveN3Required(int counter) {
String dataGetterVar = getDataGetterVar(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<String> retrieveLiteralsOnForm(int counter) { public List<String> retrieveLiteralsOnForm(int counter) {
List<String> literalsOnForm = new ArrayList<String>(); List<String> literalsOnForm = new ArrayList<String>();
literalsOnForm.add(getVarName("saveToVar",counter)); literalsOnForm.add(getVarName("saveToVar",counter));
@ -82,15 +73,6 @@ public class ProcessSparqlDataGetterN3 extends ProcessDataGetterAbstract {
public List<FieldVTwo> retrieveFields(int counter) { public List<FieldVTwo> retrieveFields(int counter) {
List<FieldVTwo> fields = new ArrayList<FieldVTwo>(); List<FieldVTwo> fields = new ArrayList<FieldVTwo>();
//An alternative way of doing this
/*
List<String> allFieldsBase = new ArrayList<String>();
allFieldsBase.addAll(getLiteralVarNamesBase());
allFieldsBase.addAll(getUriVarNamesBase());
for(String varName: allFieldsBase) {
fields.add(new FieldVTwo().setName(getVarName(varName, counter)));
} */
//For existing data getters //For existing data getters
//fields.add(new FieldVTwo().setName(getVarName("dataGetter", counter))); //fields.add(new FieldVTwo().setName(getVarName("dataGetter", counter)));
fields.add(new FieldVTwo().setName(getVarName("queryModel", counter))); fields.add(new FieldVTwo().setName(getVarName("queryModel", counter)));

View file

@ -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<String,String> newResources = new HashMap<String, String>();
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<String,String> varToNewURIs = new HashMap<String,String>();
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<String> values = new ArrayList<String>(varToNewURIs.values());
Set<String> valuesSet = new HashSet<String>(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<String,String> newResources = new HashMap<String, String>();
newResources.put("page", "http://displayOntology/test/n12");
//Setup webappdaofactory
WebappDaoFactoryJena wadf = this.setupWebappDaoFactory();
NewURIMakerVitro nv = new NewURIMakerVitro(wadf);
//Now test for new URI
HashMap<String,String> varToNewURIs = new HashMap<String,String>();
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<String> values = new ArrayList<String>(varToNewURIs.values());
Set<String> valuesSet = new HashSet<String>(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;
}
}

View file

@ -547,6 +547,11 @@ var pageManagementUtils = {
var dataGetterProcessor = pageManagementUtils.dataGetterProcessorMap[dataGetterType]; var dataGetterProcessor = pageManagementUtils.dataGetterProcessorMap[dataGetterType];
//the content type specific processor will create the json object to be returned //the content type specific processor will create the json object to be returned
var jsonObject = dataGetterProcessor.processPageContentSection(pageContentSection); 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; return jsonObject;
} else { } else {
//ERROR handling //ERROR handling
@ -618,6 +623,8 @@ var pageManagementUtils = {
var $newContentObj = pageManagementUtils.cloneContentAreaForEdit(contentType, contentTypeLabel, additionalLabelText); var $newContentObj = pageManagementUtils.cloneContentAreaForEdit(contentType, contentTypeLabel, additionalLabelText);
//Populate the section with the values //Populate the section with the values
dataGetterProcessorObject.populatePageContentSection(JSONContentObject, $newContentObj); dataGetterProcessorObject.populatePageContentSection(JSONContentObject, $newContentObj);
//Also include a hidden input with data getter URI
pageManagementUtils.includeDataGetterURI(JSONContentObject, $newContentObj);
} else { } else {
//error condition //error condition
} }
@ -627,6 +634,12 @@ var pageManagementUtils = {
} }
}, },
includeDataGetterURI:function(JSONContentObject, $newContentObj) {
var uri = JSONContentObject["URI"];
if(uri != null) {
$("<input type='hidden' name='URI' value='" + uri + "'>").appendTo($newContentObj);
}
},
//Get the data getter processor //Get the data getter processor
getDataGetterProcessorObject:function(pageContentSection) { getDataGetterProcessorObject:function(pageContentSection) {
var dataGetterType = pageManagementUtils.processDataGetterUtils.selectDataGetterType(pageContentSection); var dataGetterType = pageManagementUtils.processDataGetterUtils.selectDataGetterType(pageContentSection);