Many changes to ProcessRdfForm.java

This commit is contained in:
briancaruso 2011-11-09 23:24:02 +00:00
parent de68feb180
commit bf940b59da
16 changed files with 942 additions and 642 deletions

View file

@ -0,0 +1,50 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.dao;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
import edu.cornell.mannlib.vitro.webapp.beans.Individual;
import edu.cornell.mannlib.vitro.webapp.beans.IndividualImpl;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.NewURIMaker;
public class NewURIMakerVitro implements NewURIMaker {
private static final int MAX_ATTEMPTS = 10;
WebappDaoFactory wdf;
Set<String> madeURIs = new HashSet<String>();
static Random random = new Random();
public NewURIMakerVitro( WebappDaoFactory wdf){
this.wdf = wdf;
}
@Override
public String getUnusedNewURI(String prefixURI) throws InsertException {
Individual ind = new IndividualImpl();
String newURI = null;
int attempts = 0;
boolean goodNewURI = false;
while( ! goodNewURI && attempts < MAX_ATTEMPTS ){
attempts++;
if( attempts > 2 && prefixURI != null && !prefixURI.isEmpty() )
ind.setURI(prefixURI + random.nextInt() );
else
ind.setURI( prefixURI );
newURI = wdf.getIndividualDao().getUnusedURI( ind );
if( newURI != null && ! newURI.isEmpty() && ! madeURIs.contains( newURI) ){
goodNewURI = true;
madeURIs.add( newURI );
}
}
if( newURI != null && !newURI.isEmpty())
return newURI;
else
throw new InsertException("Could not get a new URI for the prefix " + prefixURI );
}
}

View file

@ -2,8 +2,8 @@
package edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo;
import java.io.StringWriter;
import java.util.List;
import java.util.Map;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
@ -51,4 +51,27 @@ public class AdditionsAndRetractions {
this.retractions = retractions;
}
@Override
public String toString(){
String str = "{";
str += "\nadditions:[";
if( getAdditions() != null ) {
StringWriter writer = new StringWriter();
getAdditions().write(writer, "N3-PP");
str += "\n" + writer.toString() + "\n";
}
str += "],\n";
str += "\nretractions:[";
if( getRetractions() != null ) {
StringWriter writer = new StringWriter();
getRetractions().write(writer, "N3-PP");
str += "\n" + writer.toString() + "\n";
}
str += "],\n";
return str;
}
}

View file

@ -22,6 +22,10 @@ public abstract class BaseEditElementVTwo implements EditElementVTwo {
this.field = field;
}
public void setField(FieldVTwo field){
this.field = field;
}
/**
* Utility method for use in EditElements to merge a freemarker template.
*/

View file

@ -28,11 +28,7 @@ import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.EditConfigu
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.Field;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.processEdit.EditSubmission;
/**
* User: bdc34
* Date: Jan 24, 2008
* Time: 1:55:39 PM
*/
public class BasicValidationVTwo {
Map<String, List<String>> varsToValidations;
@ -253,6 +249,8 @@ public class BasicValidationVTwo {
private void checkValidations(){
List<String> unknown = new ArrayList<String>();
for( String key : varsToValidations.keySet()){
if( varsToValidations.get(key) == null )
continue;
for( String validator : varsToValidations.get(key)){
if( ! basicValidations.contains( validator)) {
if ( ! ( ( validator != null) &&

View file

@ -38,9 +38,7 @@ import freemarker.template.Configuration;
* $fieldname.value - DateTime literal
*
*/
public class DateTimeWithPrecisionVTwo extends BaseEditElementVTwo {
String fieldName;
public class DateTimeWithPrecisionVTwo extends BaseEditElementVTwo {
/**
* This is the minimum datetime precision that this element
@ -68,8 +66,7 @@ public class DateTimeWithPrecisionVTwo extends BaseEditElementVTwo {
protected static final String BLANK_SENTINEL = ">SUBMITTED VALUE WAS BLANK<";
public DateTimeWithPrecisionVTwo(FieldVTwo field) {
super(field);
fieldName = field.getName();
super(field);
minimumPrecision = DEFAULT_MIN_PRECISION;
displayRequiredLevel = DEFAULT_DISPLAY_LEVEL;
}
@ -104,6 +101,10 @@ public class DateTimeWithPrecisionVTwo extends BaseEditElementVTwo {
// }
}
private String getFieldName(){
return field.getName();
}
private static final Log log = LogFactory.getLog(DateTimeWithPrecisionVTwo.class);
protected String TEMPLATE_NAME = "dateTimeWithPrecision.ftl";
@ -121,7 +122,7 @@ public class DateTimeWithPrecisionVTwo extends BaseEditElementVTwo {
Map<String,Object>map = new HashMap<String,Object>();
//always need the fieldName, required precision, and constants
map.put("fieldName", fieldName);
map.put("fieldName", getFieldName());
addPrecisionConstants(map);
map.put("minimumPrecision", minimumPrecision.uri());
map.put("requiredLevel", displayRequiredLevel.uri());
@ -132,7 +133,7 @@ public class DateTimeWithPrecisionVTwo extends BaseEditElementVTwo {
VitroVocabulary.Precision existingPrec = toPrecision(precisionUri);
if( precisionUri != null && !"".equals(precisionUri) && existingPrec == null ){
log.error("field " + fieldName + ": existing precision uri was " +
log.error("field " + getFieldName() + ": existing precision uri was " +
"'" + precisionUri + "' but could not convert to Precision object");
}
@ -142,7 +143,7 @@ public class DateTimeWithPrecisionVTwo extends BaseEditElementVTwo {
/* no precision so there should also be no datetime */
DateTime value = getTimeValue(editConfig,editSub);
if( value != null )
log.info("Unexpected state: Precision for " + fieldName
log.info("Unexpected state: Precision for " + getFieldName()
+ " was '" + precisionUri + "' but date time was " + value);
map.put("year", "");
@ -167,7 +168,7 @@ public class DateTimeWithPrecisionVTwo extends BaseEditElementVTwo {
DateTime value = getTimeValue(editConfig,editSub);
/* This is the case where there is a precision so there should be a datetime */
if( value == null )
log.error("Field " + fieldName + " has precision " + precisionUri
log.error("Field " + getFieldName() + " has precision " + precisionUri
+ " but the date time is " + value);
/* only put the values in the map for ones which are significant based on the precision */
@ -288,25 +289,25 @@ public class DateTimeWithPrecisionVTwo extends BaseEditElementVTwo {
if( BLANK_SENTINEL.equals( submittedPrec ) )
return null;
Integer year = parseToInt(fieldName+"-year", queryParameters);
Integer year = parseToInt(getFieldName()+"-year", queryParameters);
//this is the case where date has not been filled out at all.
if( year == null )
return null;
Integer month = parseToInt(fieldName+"-month", queryParameters);
Integer month = parseToInt(getFieldName()+"-month", queryParameters);
if( month == null || month == 0 )
month = 1;
Integer day = parseToInt(fieldName+"-day", queryParameters);
Integer day = parseToInt(getFieldName()+"-day", queryParameters);
if( day == null || day == 0 )
day = 1;
Integer hour = parseToInt(fieldName+"-hour", queryParameters);
Integer hour = parseToInt(getFieldName()+"-hour", queryParameters);
if( hour == null )
hour = 0;
Integer minute = parseToInt(fieldName+"-minute", queryParameters);
Integer minute = parseToInt(getFieldName()+"-minute", queryParameters);
if( minute == null )
minute = 0;
Integer second = parseToInt(fieldName+"-second", queryParameters);
Integer second = parseToInt(getFieldName()+"-second", queryParameters);
if( second == null )
second = 0;
@ -350,12 +351,12 @@ public class DateTimeWithPrecisionVTwo extends BaseEditElementVTwo {
*/
protected String getSubmittedPrecision(Map<String, String[]> queryParameters) throws Exception {
Integer year = parseToInt(fieldName+"-year",queryParameters);
Integer month = parseToInt(fieldName+"-month",queryParameters);
Integer day = parseToInt(fieldName+"-day",queryParameters);
Integer hour = parseToInt(fieldName+"-hour",queryParameters);
Integer minute = parseToInt(fieldName+"-minute",queryParameters);
Integer second = parseToInt(fieldName+"-second",queryParameters);
Integer year = parseToInt(getFieldName()+"-year",queryParameters);
Integer month = parseToInt(getFieldName()+"-month",queryParameters);
Integer day = parseToInt(getFieldName()+"-day",queryParameters);
Integer hour = parseToInt(getFieldName()+"-hour",queryParameters);
Integer minute = parseToInt(getFieldName()+"-minute",queryParameters);
Integer second = parseToInt(getFieldName()+"-second",queryParameters);
Integer[] values = { year, month, day, hour, minute, second };
/* find the most significant date field that is null. */
@ -438,72 +439,72 @@ public class DateTimeWithPrecisionVTwo extends BaseEditElementVTwo {
//just check if the values for the precision parse to integers
if( precisionURI.equals(VitroVocabulary.Precision.YEAR.uri() ) ){
if( ! canParseToNumber(fieldName+"-year" ,qp))
errors.put(fieldName+"-year", NON_INTEGER_YEAR);
if( ! canParseToNumber(getFieldName()+"-year" ,qp))
errors.put(getFieldName()+"-year", NON_INTEGER_YEAR);
}else if( precisionURI.equals( VitroVocabulary.Precision.MONTH.uri() )){
if( ! canParseToNumber(fieldName+"-year" ,qp))
errors.put(fieldName+"-year", NON_INTEGER_YEAR);
if( ! canParseToNumber(fieldName+"-month" ,qp))
errors.put(fieldName+"-month", NON_INTEGER_MONTH);
if( ! canParseToNumber(getFieldName()+"-year" ,qp))
errors.put(getFieldName()+"-year", NON_INTEGER_YEAR);
if( ! canParseToNumber(getFieldName()+"-month" ,qp))
errors.put(getFieldName()+"-month", NON_INTEGER_MONTH);
}else if( precisionURI.equals( VitroVocabulary.Precision.DAY.uri() )){
if( ! canParseToNumber(fieldName+"-year" ,qp))
errors.put(fieldName+"-year", NON_INTEGER_YEAR);
if( ! canParseToNumber(fieldName+"-month" ,qp))
errors.put(fieldName+"-month", NON_INTEGER_MONTH);
if( ! canParseToNumber(fieldName+"-day" ,qp))
errors.put(fieldName+"-day", NON_INTEGER_DAY);
if( ! canParseToNumber(getFieldName()+"-year" ,qp))
errors.put(getFieldName()+"-year", NON_INTEGER_YEAR);
if( ! canParseToNumber(getFieldName()+"-month" ,qp))
errors.put(getFieldName()+"-month", NON_INTEGER_MONTH);
if( ! canParseToNumber(getFieldName()+"-day" ,qp))
errors.put(getFieldName()+"-day", NON_INTEGER_DAY);
}else if( precisionURI.equals( VitroVocabulary.Precision.HOUR.uri() )){
if( ! canParseToNumber(fieldName+"-year" ,qp))
errors.put(fieldName+"-year", NON_INTEGER_YEAR);
if( ! canParseToNumber(fieldName+"-month" ,qp))
errors.put(fieldName+"-month", NON_INTEGER_MONTH);
if( ! canParseToNumber(fieldName+"-day" ,qp))
errors.put(fieldName+"-day", NON_INTEGER_DAY);
if( ! canParseToNumber(fieldName+"-hour" ,qp))
errors.put(fieldName+"-hour", NON_INTEGER_HOUR);
if( ! canParseToNumber(getFieldName()+"-year" ,qp))
errors.put(getFieldName()+"-year", NON_INTEGER_YEAR);
if( ! canParseToNumber(getFieldName()+"-month" ,qp))
errors.put(getFieldName()+"-month", NON_INTEGER_MONTH);
if( ! canParseToNumber(getFieldName()+"-day" ,qp))
errors.put(getFieldName()+"-day", NON_INTEGER_DAY);
if( ! canParseToNumber(getFieldName()+"-hour" ,qp))
errors.put(getFieldName()+"-hour", NON_INTEGER_HOUR);
}else if( precisionURI.equals( VitroVocabulary.Precision.MINUTE.uri() )){
if( ! canParseToNumber(fieldName+"-year" ,qp))
errors.put(fieldName+"-year", NON_INTEGER_YEAR);
if( ! canParseToNumber(fieldName+"-month" ,qp))
errors.put(fieldName+"-month", NON_INTEGER_MONTH);
if( ! canParseToNumber(fieldName+"-day" ,qp))
errors.put(fieldName+"-day", NON_INTEGER_DAY);
if( ! canParseToNumber(fieldName+"-hour" ,qp))
errors.put(fieldName+"-hour", NON_INTEGER_HOUR);
if( ! canParseToNumber(fieldName+"-minute" ,qp))
errors.put(fieldName+"-minute", NON_INTEGER_HOUR);
if( ! canParseToNumber(getFieldName()+"-year" ,qp))
errors.put(getFieldName()+"-year", NON_INTEGER_YEAR);
if( ! canParseToNumber(getFieldName()+"-month" ,qp))
errors.put(getFieldName()+"-month", NON_INTEGER_MONTH);
if( ! canParseToNumber(getFieldName()+"-day" ,qp))
errors.put(getFieldName()+"-day", NON_INTEGER_DAY);
if( ! canParseToNumber(getFieldName()+"-hour" ,qp))
errors.put(getFieldName()+"-hour", NON_INTEGER_HOUR);
if( ! canParseToNumber(getFieldName()+"-minute" ,qp))
errors.put(getFieldName()+"-minute", NON_INTEGER_HOUR);
}else if( precisionURI.equals( VitroVocabulary.Precision.SECOND.uri() )){
if( ! canParseToNumber(fieldName+"-year" ,qp))
errors.put(fieldName+"-year", NON_INTEGER_YEAR);
if( ! canParseToNumber(fieldName+"-month" ,qp))
errors.put(fieldName+"-month", NON_INTEGER_MONTH);
if( ! canParseToNumber(fieldName+"-day" ,qp))
errors.put(fieldName+"-day", NON_INTEGER_DAY);
if( ! canParseToNumber(fieldName+"-hour" ,qp))
errors.put(fieldName+"-hour", NON_INTEGER_HOUR);
if( ! canParseToNumber(fieldName+"-minute" ,qp))
errors.put(fieldName+"-minute", NON_INTEGER_HOUR);
if( ! canParseToNumber(fieldName+"-second" ,qp))
errors.put(fieldName+"-second", NON_INTEGER_SECOND);
if( ! canParseToNumber(getFieldName()+"-year" ,qp))
errors.put(getFieldName()+"-year", NON_INTEGER_YEAR);
if( ! canParseToNumber(getFieldName()+"-month" ,qp))
errors.put(getFieldName()+"-month", NON_INTEGER_MONTH);
if( ! canParseToNumber(getFieldName()+"-day" ,qp))
errors.put(getFieldName()+"-day", NON_INTEGER_DAY);
if( ! canParseToNumber(getFieldName()+"-hour" ,qp))
errors.put(getFieldName()+"-hour", NON_INTEGER_HOUR);
if( ! canParseToNumber(getFieldName()+"-minute" ,qp))
errors.put(getFieldName()+"-minute", NON_INTEGER_HOUR);
if( ! canParseToNumber(getFieldName()+"-second" ,qp))
errors.put(getFieldName()+"-second", NON_INTEGER_SECOND);
}
//check if we can make a valid date with these integers
year = parseToInt(fieldName+"-year", qp);
year = parseToInt(getFieldName()+"-year", qp);
if( year == null )
year = 1999;
month= parseToInt(fieldName+"-month", qp);
month= parseToInt(getFieldName()+"-month", qp);
if(month == null )
month = 1;
day = parseToInt(fieldName+"-day", qp);
day = parseToInt(getFieldName()+"-day", qp);
if( day == null )
day = 1;
hour = parseToInt(fieldName+"-hour", qp);
hour = parseToInt(getFieldName()+"-hour", qp);
if( hour == null )
hour = 0;
minute = parseToInt(fieldName+"-minute",qp);
minute = parseToInt(getFieldName()+"-minute",qp);
if( minute == null )
minute = 0;
second = parseToInt(fieldName+"-second", qp);
second = parseToInt(getFieldName()+"-second", qp);
if( second == null )
second = 0;
@ -514,27 +515,27 @@ public class DateTimeWithPrecisionVTwo extends BaseEditElementVTwo {
try{
dateTime = dateTime.withYear(year);
}catch(IllegalArgumentException iae){
errors.put(fieldName+"-year", iae.getLocalizedMessage());
errors.put(getFieldName()+"-year", iae.getLocalizedMessage());
}
try{
dateTime = dateTime.withMonthOfYear(month);
}catch(IllegalArgumentException iae){
errors.put(fieldName+"-month", iae.getLocalizedMessage());
errors.put(getFieldName()+"-month", iae.getLocalizedMessage());
}
try{
dateTime = dateTime.withDayOfMonth(day);
}catch(IllegalArgumentException iae){
errors.put(fieldName+"-day", iae.getLocalizedMessage());
errors.put(getFieldName()+"-day", iae.getLocalizedMessage());
}
try{
dateTime = dateTime.withHourOfDay(hour);
}catch(IllegalArgumentException iae){
errors.put(fieldName+"-hour", iae.getLocalizedMessage());
errors.put(getFieldName()+"-hour", iae.getLocalizedMessage());
}
try{
dateTime = dateTime.withSecondOfMinute(second);
}catch(IllegalArgumentException iae){
errors.put(fieldName+"-second", iae.getLocalizedMessage());
errors.put(getFieldName()+"-second", iae.getLocalizedMessage());
}
return errors;
@ -613,8 +614,8 @@ public class DateTimeWithPrecisionVTwo extends BaseEditElementVTwo {
return null;
}
public String getValueVariableName(){ return fieldName + "-value" ; }
public String getPrecisionVariableName(){ return fieldName + "-precision" ; }
public String getValueVariableName(){ return getFieldName() + "-value" ; }
public String getPrecisionVariableName(){ return getFieldName() + "-precision" ; }
}

View file

@ -130,9 +130,9 @@ public class EditConfigurationUtils {
public static String getEditKey(VitroRequest vreq) {
HttpSession session = vreq.getSession();
String editKey =
(EditConfigurationVTwo.getEditKey(vreq) == null)
(EditConfigurationVTwo.getEditKeyFromRequest(vreq) == null)
? EditConfigurationVTwo.newEditKey(session)
: EditConfigurationVTwo.getEditKey(vreq);
: EditConfigurationVTwo.getEditKeyFromRequest(vreq);
return editKey;
}

View file

@ -4,35 +4,23 @@ package edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.servlet.ServletContext;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.joda.time.DateTime;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.FieldVTwo;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.EditConfiguration;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.ModelSelector;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.StandardModelSelector;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.StandardWDFSelector;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.WDFSelector;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.MultiValueEditSubmission;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditSubmissionVTwoPreprocessor;
import com.hp.hpl.jena.datatypes.xsd.XSDDatatype;
import com.hp.hpl.jena.rdf.model.Literal;
@ -40,9 +28,13 @@ import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ResourceFactory;
import edu.cornell.mannlib.vitro.webapp.beans.DataPropertyStatement;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.edit.EditLiteral;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.ModelSelector;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.StandardModelSelector;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.StandardWDFSelector;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.WDFSelector;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.preprocessors.ModelChangePreprocessor;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.validators.N3Validator;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.processEdit.EditN3Utils;
import edu.cornell.mannlib.vitro.webapp.search.beans.ProhibitedFromSearch;
@ -59,38 +51,38 @@ import edu.cornell.mannlib.vitro.webapp.search.beans.ProhibitedFromSearch;
public class EditConfigurationVTwo {
//Strings representing required n3 for RDF
List<String> n3Required = Collections.emptyList();
List<String> n3Required = new ArrayList<String>();
//String representing optional N3 for RDF
List<String> n3Optional = Collections.emptyList();
List<String> n3Optional = new ArrayList<String>();
//Names of variables of 'objects' i.e. URIs on form
List<String> urisOnform = Collections.emptyList();
List<String> urisOnform = new ArrayList<String>();
//Names of variables corresponding to data values i.e. literals on form
List<String> literalsOnForm = Collections.emptyList();
List<String> literalsOnForm = new ArrayList<String>();
//Names of variables corresponding to Files on form
List<String> filesOnForm = Collections.emptyList();
List<String> filesOnForm = new ArrayList<String>();
//Multi values now supported for uris and literals, so second parameter needs to be List<String>
//Mapping of variable name for object to values for object, i.e. URIs, e.g. "hasElement" = "<a.com>, <b.com>"
Map<String,List<String>> urisInScope = Collections.emptyMap();
Map<String,List<String>> urisInScope = new HashMap<String,List<String>>();
//Mapping from variable name to values for literals
Map<String, List<Literal>> literalsInScope = Collections.emptyMap();
Map<String, List<Literal>> literalsInScope = new HashMap<String,List<Literal>>();
//Map name of variable to sparql query which should return a one-column result set of URIs corresponding to variable
//E.g. sparql for inverse of object property
Map<String,String> sparqlForAdditionalUrisInScope = Collections.emptyMap();
Map<String,String> sparqlForAdditionalUrisInScope = new HashMap<String,String>();
//Mapping variable to sparql query returning literals
Map<String,String> sparqlForAdditionalLiteralsInScope = Collections.emptyMap();
Map<String,String> sparqlForAdditionalLiteralsInScope = new HashMap<String,String>();
//Variable names to URI prefixes for variables that are allowed to have new instances created
Map<String,String> newResources = Collections.emptyMap();
Map<String,String> newResources = new HashMap<String,String>();
//Variable names to fields, Field = additional configuration for variable
Map<String,FieldVTwo> fields = Collections.emptyMap();
Map<String,FieldVTwo> fields = new HashMap<String,FieldVTwo>();
//Mapping variable name to Sparql query to find existing literals corresponding to variable, result set should be one-column multi-row of literals
Map<String,String>sparqlForExistingLiterals = Collections.emptyMap();
Map<String,String>sparqlForExistingLiterals = new HashMap<String,String>();
//Mapping variable name to Sparql query to find existing URIs corresponding to variable, result set should be one-column multi-row of URIs/URI resources
Map<String,String>sparqlForExistingUris = Collections.emptyMap();
Map<String,String>sparqlForExistingUris = new HashMap<String,String>();
String subjectUri;
String varNameForSubject;
@ -636,7 +628,7 @@ public class EditConfigurationVTwo {
* there first since multipart parsing might have cleared them from the request.
*/
public static EditConfigurationVTwo getConfigFromSession( HttpSession sess, HttpServletRequest request ){
String key = getEditKey(request);
String key = getEditKeyFromRequest(request);
if( key == null )
return null;
@ -646,9 +638,11 @@ public class EditConfigurationVTwo {
/**
* The editKey can be a HTTP query parameter or it can be a request attribute.
*/
public static String getEditKey( ServletRequest request){
public static String getEditKeyFromRequest( ServletRequest request){
String key = null;
if( request instanceof HttpServletRequest ){
if( request instanceof VitroRequest ){
return request.getParameter("editKey");
}else if( request instanceof HttpServletRequest ){
HttpServletRequest hsreq = (HttpServletRequest)request;
boolean isMultipart = ServletFileUpload.isMultipartContent(hsreq);
if( isMultipart ) {
@ -677,9 +671,9 @@ public class EditConfigurationVTwo {
}
}
@SuppressWarnings("unchecked")
public static String newEditKey(HttpSession sess){
DateTime time = new DateTime();
int mills = time.getMillisOfDay();
int mills = new DateTime().getMillisOfDay();
Map<String,EditConfigurationVTwo> configs = (Map<String,EditConfigurationVTwo>)sess.getAttribute("EditConfigurations");
if( configs == null ){
@ -918,6 +912,10 @@ public class EditConfigurationVTwo {
this.submitToUrl = submitToUrl;
}
public boolean isUpdate(){
return isObjectPropertyUpdate() || isDataPropertyUpdate();
}
public boolean isObjectPropertyUpdate(){
return this.getObject() != null && this.getObject().trim().length() > 0;
}
@ -990,5 +988,9 @@ public class EditConfigurationVTwo {
map.put( field.getName(), field);
}
@Override
public String toString(){
return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
}
}

View file

@ -61,13 +61,33 @@ public class EditN3GeneratorVTwo {
valueString = org.apache.commons.lang.StringUtils.join(value, ">, <");
valueString = "<" + valueString + ">";
log.debug("Value string is " + valueString);
temp = subInUris( key, valueString, temp) ;
temp = subInNonBracketedURIS( key, valueString, temp) ;
}
outv.add(temp);
}
return outv;
}
//Already includes "<> for URIs so no need to add those here
private static String subInNonBracketedURIS(String var, String value, String target) {
//empty URIs get skipped
if( var == null || var.length() == 0 || value==null )
return target;
/* var followed by dot some whitespace or var followed by whitespace*/
String varRegex = "\\?" + var + "(?=\\.\\p{Space}|\\p{Space})";
String out = null;
if("".equals(value))
out = target.replaceAll(varRegex,">::" + var + " was BLANK::< ");
else {
String replaceWith = Matcher.quoteReplacement(value);
out = target.replaceAll(varRegex,replaceWith);
}
if( out != null && out.length() > 0 )
return out;
else
return target;
}
public static List<String> subInUris(Map<String,String> varsToVals, List<String> targets){
if( varsToVals == null || varsToVals.isEmpty() ) return targets;
ArrayList<String> outv = new ArrayList<String>();
@ -85,23 +105,11 @@ public class EditN3GeneratorVTwo {
//Already includes "<> for URIs so no need to add those here
public static String subInUris(String var, String value, String target) {
//empty URIs get skipped
if( var == null || var.length() == 0 || value==null )
return target;
/* var followed by dot some whitespace or var followed by whitespace*/
String varRegex = "\\?" + var + "(?=\\.\\p{Space}|\\p{Space})";
String out = null;
if("".equals(value))
out = target.replaceAll(varRegex,">::" + var + " was BLANK::< ");
else {
String replaceWith = Matcher.quoteReplacement(value);
out = target.replaceAll(varRegex,replaceWith);
}
if( out != null && out.length() > 0 )
return out;
else
if( var == null || var.isEmpty() || value == null )
return target;
return subInNonBracketedURIS(var, "<" + value + ">", target);
}
/*
//For cases where comma delimited URIs sent in already including <>
public static String subInMultipleUris(String var, List<String> values, String target){

View file

@ -10,6 +10,8 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.json.JSONArray;
@ -46,12 +48,12 @@ public class FieldVTwo {
/**
* List of basic validators. See BaiscValidation.
*/
private List <String> validators;
private List <String> validators = new ArrayList<String>();
/**
* What type of options is this?
*/
private OptionsType optionsType;
private OptionsType optionsType = OptionsType.UNDEFINED;
/**
* Special class to use for option type
@ -127,6 +129,10 @@ public class FieldVTwo {
public FieldVTwo setEditElement(EditElementVTwo editElement){
this.editElement = editElement;
if( editElement instanceof BaseEditElementVTwo)
((BaseEditElementVTwo) editElement).setField(this);
return this;
}
@ -274,4 +280,8 @@ public class FieldVTwo {
return this;
}
@Override
public String toString(){
return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
}
}

View file

@ -14,6 +14,8 @@ import javax.servlet.http.HttpSession;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.joda.time.DateTime;
@ -270,13 +272,8 @@ public class MultiValueEditSubmission {
this.urisFromForm = urisFromForm;
}
public String toString(){
String[] names ={
"literalsFromForm",
"urisFromForm","validationErrors","basicValidation"
};
JSONObject obj = new JSONObject(this,names);
return obj.toString();
public String toString(){
return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
}
private Log log = LogFactory.getLog(MultiValueEditSubmission.class);

View file

@ -117,8 +117,9 @@ public abstract class BaseEditConfigurationGenerator implements EditConfiguratio
*/
void initBasics(EditConfigurationVTwo editConf, VitroRequest vreq){
editConf.setN3Generator( new EditN3GeneratorVTwo(editConf) );
editConf.setEditKey( (String) vreq.getAttribute("editKey"));
String editKey = EditConfigurationUtils.getEditKey(vreq);
editConf.setEditKey(editKey);
String formUrl = EditConfigurationUtils.getFormUrl(vreq);
editConf.setFormUrl(formUrl);

View file

@ -47,6 +47,7 @@ import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditConfigurationVTw
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditSubmissionUtils;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.FieldVTwo;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.MultiValueEditSubmission;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.N3EditUtils;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.ProcessRdfForm;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.controller.ProcessRdfFormController.Utilities;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.processEdit.EditN3Utils;
@ -76,7 +77,7 @@ public class PostEditCleanupController extends FreemarkerHttpServlet{
//The submission for getting the entity to return to is not retrieved from the session but needs
//to be created - as it is in processRdfForm3.jsp
MultiValueEditSubmission submission = new MultiValueEditSubmission(vreq.getParameterMap(), configuration);
String entityToReturnTo = ProcessRdfForm.processEntityToReturnTo(configuration, submission, vreq);
String entityToReturnTo = N3EditUtils.processEntityToReturnTo(configuration, submission, vreq);
return doPostEdit(vreq, entityToReturnTo);
}

View file

@ -5,10 +5,8 @@ package edu.cornell.mannlib.vitro.webapp.edit.n3editing.controller;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Random;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
@ -17,56 +15,44 @@ import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditConfigurationUtils;
import com.hp.hpl.jena.ontology.OntModel;
import com.hp.hpl.jena.rdf.model.Literal;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.Property;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.rdf.model.ResourceFactory;
import com.hp.hpl.jena.rdf.model.Literal;
import edu.cornell.mannlib.vitro.webapp.beans.Individual;
import edu.cornell.mannlib.vitro.webapp.beans.IndividualImpl;
import edu.cornell.mannlib.vitro.webapp.beans.DataPropertyStatement;
import edu.cornell.mannlib.vitro.webapp.beans.DataProperty;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.processEdit.RdfLiteralHash;
import edu.cornell.mannlib.vitro.webapp.beans.DataPropertyStatement;
import edu.cornell.mannlib.vitro.webapp.beans.Individual;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerHttpServlet;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder.ParamMap;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder.Route;
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.InsertException;
import edu.cornell.mannlib.vitro.webapp.dao.NewURIMakerVitro;
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
import edu.cornell.mannlib.vitro.webapp.edit.EditLiteral;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.AdditionsAndRetractions;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditConfigurationUtils;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditConfigurationVTwo;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditSubmissionUtils;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditSubmissionVTwoPreprocessor;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.FieldVTwo;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.MultiValueEditSubmission;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.N3EditUtils;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.ProcessRdfForm;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.processEdit.EditN3Utils;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.processEdit.RdfLiteralHash;
import edu.cornell.mannlib.vitro.webapp.edit.EditLiteral;
/**
* This servlet will process EditConfigurations with query parameters
* to perform an edit.
*
* TODO: rename this class ProcessN3Edit
* This servlet will convert a request to an EditSubmission,
* find the EditConfiguration associated with the request,
* use ProcessRdfForm to process these to a set of RDF additions and retractions,
* the apply these to the models.
*/
public class ProcessRdfFormController extends FreemarkerHttpServlet{
private Log log = LogFactory.getLog(ProcessRdfFormController.class);
//bdc34: this is likely to become a servlet instead of a jsp.
// You can get a reference to the servlet from the context.
// this will need to be converted from a jsp to something else
@Override
protected ResponseValues processRequest(VitroRequest vreq) {
//get the EditConfiguration
@ -77,10 +63,7 @@ public class ProcessRdfFormController extends FreemarkerHttpServlet{
//get the EditSubmission
MultiValueEditSubmission submission = new MultiValueEditSubmission(vreq.getParameterMap(), configuration);
EditSubmissionUtils.putEditSubmissionInSession(vreq.getSession(), submission);
//utilize preprocessors for edit submission
applyEditSubmissionPreprocessors(configuration, submission);
//if errors, return error response
ResponseValues errorResponse = doValidationErrors(vreq, configuration, submission);
if( errorResponse != null )
@ -98,12 +81,18 @@ public class ProcessRdfFormController extends FreemarkerHttpServlet{
}
//Otherwise, process as usual
AdditionsAndRetractions changes = getAdditionsAndRetractions(configuration, submission, vreq);
AdditionsAndRetractions changes;
try {
changes = getAdditionsAndRetractions(configuration, submission, vreq);
} catch (Exception e) {
throw new Error(e);
}
if( configuration.isUseDependentResourceDelete() )
changes = ProcessRdfForm.addDependentDeletes(changes, queryModel);
ProcessRdfForm.preprocessModels(changes, configuration, vreq);
N3EditUtils.preprocessModels(changes, configuration, vreq);
ProcessRdfForm.applyChangesToWriteModel(changes, queryModel, writeModel, EditN3Utils.getEditorUri(vreq) );
@ -111,21 +100,13 @@ public class ProcessRdfFormController extends FreemarkerHttpServlet{
//More involved processing for data property apparently
//Also what do we actually DO with the vreq attribute: Answer: Use it for redirection
//And no where else so we could technically calculate and send that here
String entityToReturnTo = ProcessRdfForm.processEntityToReturnTo(configuration, submission, vreq);
String entityToReturnTo = N3EditUtils.processEntityToReturnTo(configuration, submission, vreq);
//For data property processing, need to update edit configuration for back button
ProcessRdfForm.updateEditConfigurationForBackButton(configuration, submission, vreq, writeModel);
N3EditUtils.updateEditConfigurationForBackButton(configuration, submission, vreq, writeModel);
return PostEditCleanupController.doPostEdit(vreq, entityToReturnTo);
}
private void applyEditSubmissionPreprocessors(
EditConfigurationVTwo configuration, MultiValueEditSubmission submission) {
List<EditSubmissionVTwoPreprocessor> preprocessors = configuration.getEditSubmissionPreprocessors();
if(preprocessors != null) {
for(EditSubmissionVTwoPreprocessor p: preprocessors) {
p.preprocess(submission);
}
}
}
//In case of back button confusion
//Currently returning an error message:
@ -175,17 +156,11 @@ public class ProcessRdfFormController extends FreemarkerHttpServlet{
private AdditionsAndRetractions getAdditionsAndRetractions(
EditConfigurationVTwo configuration,
MultiValueEditSubmission submission, VitroRequest vreq) {
MultiValueEditSubmission submission, VitroRequest vreq) throws Exception {
AdditionsAndRetractions changes = null;
//if editing existing resource or literal
if(configuration.isObjectPropertyUpdate() || configuration.isDataPropertyUpdate()) {
changes = ProcessRdfForm.editExistingStatement(configuration, submission, vreq);
} else {
changes = ProcessRdfForm.createNewStatement(configuration, submission, vreq);
}
return changes;
return ProcessRdfForm.process(configuration, submission,
new NewURIMakerVitro(vreq.getWebappDaoFactory()));
}
@ -227,7 +202,7 @@ public class ProcessRdfFormController extends FreemarkerHttpServlet{
public static class Utilities {
private static Log log = LogFactory.getLog(ProcessRdfFormController.class);
static Random random = new Random();
public static String assertionsType = "assertions";
public static String retractionsType = "retractions";
@ -273,87 +248,7 @@ public class ProcessRdfFormController extends FreemarkerHttpServlet{
public static Map<String,List<String>> fieldsToRetractionMap( Map<String,FieldVTwo> fields){
return fieldsToN3Map(fields, retractionsType);
}
//this works differently based on whether this is object property editing or data property editing
//Object prop version below
//Also updating to allow an array to be returned with the uri instead of a single uri
//Note this would require more analysis in context of multiple uris possible for a field
public static Map<String,List<String>> newToUriMap(Map<String,String> newResources, WebappDaoFactory wdf){
HashMap<String,List<String>> newVarsToUris = new HashMap<String,List<String>>();
HashSet<String> newUris = new HashSet<String>();
for( String key : newResources.keySet()){
String prefix = newResources.get(key);
String uri = makeNewUri(prefix, wdf);
while( newUris.contains(uri) ){
uri = makeNewUri(prefix,wdf);
}
List<String> urisList = new ArrayList<String>();
urisList.add(uri);
newVarsToUris.put(key,urisList);
newUris.add(uri);
}
return newVarsToUris;
}
public static String makeNewUri(String prefix, WebappDaoFactory wdf){
if( prefix == null || prefix.length() == 0 ){
String uri = null;
try{
uri = wdf.getIndividualDao().getUnusedURI(null);
}catch(InsertException ex){
log.error("could not create uri");
}
return uri;
}
String goodURI = null;
int attempts = 0;
while( goodURI == null && attempts < 30 ){
Individual ind = new IndividualImpl();
ind.setURI( prefix + random.nextInt() );
try{
goodURI = wdf.getIndividualDao().getUnusedURI(ind);
}catch(InsertException ex){
log.debug("could not create uri");
}
attempts++;
}
if( goodURI == null )
log.error("could not create uri for prefix " + prefix);
return goodURI;
}
//Data prop version, from processDatapropRdfForm.jsp
//TODO: Should this even be set this way as this needs to be changed somehow?
public static String defaultUriPrefix = "http://vivo.library.cornell.edu/ns/0.1#individual";
public static Map<String, List<String>> newToUriMap(Map<String, String> newResources,
Model model) {
HashMap<String, List<String>> newUris = new HashMap<String, List<String>>();
for (String key : newResources.keySet()) {
List<String> urisList = new ArrayList<String>();
urisList.add(makeNewUri(newResources.get(key), model));
newUris.put(key, urisList);
}
return newUris;
}
//This is the data property method, this is to be removed
//TODO: Remove this method and ensure this is not called
public static String makeNewUri(String prefix, Model model) {
if (prefix == null || prefix.length() == 0)
prefix = defaultUriPrefix;
String uri = prefix + random.nextInt();
Resource r = ResourceFactory.createResource(uri);
while (model.containsResource(r)) {
uri = prefix + random.nextInt();
r = ResourceFactory.createResource(uri);
}
return uri;
}
}
//TODO: Check if this would be correct with multiple values and uris being passed back
//First, need to order by uris in original and new values probably and
@ -404,6 +299,8 @@ public class ProcessRdfFormController extends FreemarkerHttpServlet{
+ (fieldChanged ? "did Change" : "did NOT change"));
return fieldChanged;
}
public static boolean checkForEmptyString(
MultiValueEditSubmission submission,
EditConfigurationVTwo configuration, VitroRequest vreq) {

View file

@ -94,17 +94,44 @@ public class EditConfigurationTemplateModel extends BaseTemplateModel {
//Based on certain pre-set fields/variables, look for what
//drop-downs need to be populated
private void populateDropdowns() {
String predicateUri = editConfig.getPredicateUri();
if(predicateUri != null) {
if(pageData.containsKey("objectSelect")) {
List<String> fieldNames = (List<String>)pageData.get("objectSelect");
for(String field:fieldNames) {
WebappDaoFactory wdf = vreq.getWebappDaoFactory();
Map<String,String> optionsMap = SelectListGeneratorVTwo.getOptions(editConfig, field , wdf);
pageData.put(field, optionsMap);
}
}
// String predicateUri = editConfig.getPredicateUri();
// if(predicateUri != null) {
// if(EditConfigurationUtils.isObjectProperty(editConfig.getPredicateUri(), vreq)) {
// setRangeOptions();
// }
// if(pageData.containsKey("objectSelect")) {
// List<String> fieldNames = (List<String>)pageData.get("objectSelect");
// for(String field:fieldNames) {
// WebappDaoFactory wdf = vreq.getWebappDaoFactory();
// Map<String,String> optionsMap = SelectListGeneratorVTwo.getOptions(editConfig, field , wdf);
// pageData.put(field, optionsMap);
// }
// }
// }
//For each field with an optionType defined, create the options
WebappDaoFactory wdf = vreq.getWebappDaoFactory();
for(String fieldName: editConfig.getFields().keySet()){
FieldVTwo field = editConfig.getField(fieldName);
if( field.getOptionsType() == FieldVTwo.OptionsType.UNDEFINED
|| field.getOptionsType() == null ){
continue;
}
pageData.put(fieldName, SelectListGeneratorVTwo.getOptions(editConfig, fieldName, wdf));
}
// String predicateUri = editConfig.getPredicateUri();
// if(predicateUri != null) {
// if(pageData.containsKey("objectSelect")) {
// List<String> fieldNames = (List<String>)pageData.get("objectSelect");
// for(String field:fieldNames) {
// WebappDaoFactory wdf = vreq.getWebappDaoFactory();
// Map<String,String> optionsMap = SelectListGeneratorVTwo.getOptions(editConfig, field , wdf);
// pageData.put(field, optionsMap);
// }
// }
// }
}
//TODO: Check if this should return a list instead

View file

@ -16,6 +16,79 @@ import com.hp.hpl.jena.rdf.model.ModelFactory;
public class EditN3GeneratorVTwoTest {
@Test
public void testSubInMultiUrisNull(){
String n3 = "?varXYZ" ;
List<String> targets = new ArrayList<String>();
targets.add(n3);
Map<String,List<String>> keyToValues = new HashMap<String,List<String>>();
List<String> targetValue = new ArrayList<String>();
targetValue.add(null);
keyToValues.put("varXYZ", targetValue);
List<String> result = EditN3GeneratorVTwo.subInMultiUris(keyToValues, targets);
Assert.assertNotNull(result);
Assert.assertEquals(1,result.size());
String resultN3 = result.get(0);
Assert.assertNotNull(resultN3);
Assert.assertTrue("String was empty", !resultN3.isEmpty());
String not_expected = "<null>";
Assert.assertTrue("must not sub in <null>", !not_expected.equals(resultN3));
}
@Test
public void testSubInUrisNull(){
String n3 = " ?varXYZ " ;
List<String> targets = new ArrayList<String>();
targets.add(n3);
Map<String,String> keyToValues = new HashMap<String,String>();
keyToValues.put("varXYZ", "xyzURI");
List<String> result = EditN3GeneratorVTwo.subInUris(keyToValues, targets);
Assert.assertNotNull(result);
Assert.assertEquals(1,result.size());
String resultN3 = result.get(0);
Assert.assertNotNull(resultN3);
Assert.assertTrue("String was empty", !resultN3.isEmpty());
Assert.assertEquals(" <xyzURI> ", resultN3);
keyToValues = new HashMap<String,String>();
keyToValues.put("varXYZ", null);
result = EditN3GeneratorVTwo.subInUris(keyToValues, targets);
Assert.assertNotNull(result);
Assert.assertEquals(1,result.size());
resultN3 = result.get(0);
resultN3 = result.get(0);
Assert.assertNotNull(resultN3);
Assert.assertTrue("String was empty", !resultN3.isEmpty());
Assert.assertEquals(" ?varXYZ ", resultN3);
}
/*
[@prefix core: <http://vivoweb.org/ontology/core#> .
?person core:educationalTraining ?edTraining .
?edTraining a core:EducationalTraining ;
core:educationalTrainingOf ?person ;
<http://vivoweb.org/ontology/core#trainingAtOrganization> ?org .
, ?org <http://www.w3.org/2000/01/rdf-schema#label> ?orgLabel ., ?org a ?orgType .]
*/
//{person=http://caruso-laptop.mannlib.cornell.edu:8090/vivo/individual/n2576, predicate=http://vivoweb.org/ontology/core#educationalTraining, edTraining=null}
@Test
public void testSubInMultiUris() {
String n3 = "?subject ?predicate ?multivalue ." ;