diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/NewURIMakerVitro.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/NewURIMakerVitro.java new file mode 100644 index 000000000..f1297c04d --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/NewURIMakerVitro.java @@ -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 madeURIs = new HashSet(); + 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 ); + } + +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/AdditionsAndRetractions.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/AdditionsAndRetractions.java index d3467dfe5..1025b2aa2 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/AdditionsAndRetractions.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/AdditionsAndRetractions.java @@ -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; + } + } \ No newline at end of file diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/BaseEditElementVTwo.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/BaseEditElementVTwo.java index d5e6a410e..a7c4c3738 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/BaseEditElementVTwo.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/BaseEditElementVTwo.java @@ -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. */ diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/BasicValidationVTwo.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/BasicValidationVTwo.java index 4807b3d31..9e72dbca6 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/BasicValidationVTwo.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/BasicValidationVTwo.java @@ -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> varsToValidations; @@ -253,6 +249,8 @@ public class BasicValidationVTwo { private void checkValidations(){ List unknown = new ArrayList(); for( String key : varsToValidations.keySet()){ + if( varsToValidations.get(key) == null ) + continue; for( String validator : varsToValidations.get(key)){ if( ! basicValidations.contains( validator)) { if ( ! ( ( validator != null) && diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/DateTimeWithPrecisionVTwo.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/DateTimeWithPrecisionVTwo.java index 728cd75b7..fb4491b4f 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/DateTimeWithPrecisionVTwo.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/DateTimeWithPrecisionVTwo.java @@ -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 { Mapmap = new HashMap(); //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 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" ; } } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/EditConfigurationUtils.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/EditConfigurationUtils.java index 6b2b8bbd6..a06f337a7 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/EditConfigurationUtils.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/EditConfigurationUtils.java @@ -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; } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/EditConfigurationVTwo.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/EditConfigurationVTwo.java index da35832ec..ab488a628 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/EditConfigurationVTwo.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/EditConfigurationVTwo.java @@ -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 n3Required = Collections.emptyList(); + List n3Required = new ArrayList(); //String representing optional N3 for RDF - List n3Optional = Collections.emptyList(); + List n3Optional = new ArrayList(); //Names of variables of 'objects' i.e. URIs on form - List urisOnform = Collections.emptyList(); + List urisOnform = new ArrayList(); //Names of variables corresponding to data values i.e. literals on form - List literalsOnForm = Collections.emptyList(); + List literalsOnForm = new ArrayList(); //Names of variables corresponding to Files on form - List filesOnForm = Collections.emptyList(); + List filesOnForm = new ArrayList(); //Multi values now supported for uris and literals, so second parameter needs to be List //Mapping of variable name for object to values for object, i.e. URIs, e.g. "hasElement" = ", " - Map> urisInScope = Collections.emptyMap(); + Map> urisInScope = new HashMap>(); //Mapping from variable name to values for literals - Map> literalsInScope = Collections.emptyMap(); + Map> literalsInScope = new HashMap>(); //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 sparqlForAdditionalUrisInScope = Collections.emptyMap(); + Map sparqlForAdditionalUrisInScope = new HashMap(); //Mapping variable to sparql query returning literals - Map sparqlForAdditionalLiteralsInScope = Collections.emptyMap(); + Map sparqlForAdditionalLiteralsInScope = new HashMap(); //Variable names to URI prefixes for variables that are allowed to have new instances created - Map newResources = Collections.emptyMap(); + Map newResources = new HashMap(); //Variable names to fields, Field = additional configuration for variable - Map fields = Collections.emptyMap(); + Map fields = new HashMap(); //Mapping variable name to Sparql query to find existing literals corresponding to variable, result set should be one-column multi-row of literals - MapsparqlForExistingLiterals = Collections.emptyMap(); + MapsparqlForExistingLiterals = new HashMap(); //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 - MapsparqlForExistingUris = Collections.emptyMap(); + MapsparqlForExistingUris = new HashMap(); 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 configs = (Map)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); + } } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/EditN3GeneratorVTwo.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/EditN3GeneratorVTwo.java index 6e97c5a75..dc320ae1a 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/EditN3GeneratorVTwo.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/EditN3GeneratorVTwo.java @@ -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 subInUris(Map varsToVals, List targets){ if( varsToVals == null || varsToVals.isEmpty() ) return targets; ArrayList outv = new ArrayList(); @@ -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 values, String target){ diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/FieldVTwo.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/FieldVTwo.java index b5fa2d5d6..c97538f64 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/FieldVTwo.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/FieldVTwo.java @@ -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 validators; + private List validators = new ArrayList(); /** * 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); + } } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/MultiValueEditSubmission.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/MultiValueEditSubmission.java index 4a9941df6..575eb3784 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/MultiValueEditSubmission.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/MultiValueEditSubmission.java @@ -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); diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/ProcessRdfForm.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/ProcessRdfForm.java index 0e6d2502e..ba34633d9 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/ProcessRdfForm.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/ProcessRdfForm.java @@ -4,10 +4,12 @@ package edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo; import java.io.StringReader; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.HashMap; +import java.util.Random; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -16,54 +18,153 @@ import com.hp.hpl.jena.ontology.OntModel; import com.hp.hpl.jena.rdf.model.Model; import com.hp.hpl.jena.rdf.model.ModelFactory; import com.hp.hpl.jena.shared.Lock; -import com.hp.hpl.jena.rdf.model.Literal; -import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; +import edu.cornell.mannlib.vitro.webapp.dao.InsertException; import edu.cornell.mannlib.vitro.webapp.dao.jena.DependentResourceDeleteJena; import edu.cornell.mannlib.vitro.webapp.dao.jena.event.EditEvent; -import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditConfigurationVTwo; -import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.preprocessors.ModelChangePreprocessor; import edu.cornell.mannlib.vitro.webapp.edit.n3editing.controller.ProcessRdfFormController.Utilities; -import edu.cornell.mannlib.vitro.webapp.beans.DataPropertyStatement; -import edu.cornell.mannlib.vitro.webapp.beans.DataPropertyStatementImpl; -import edu.cornell.mannlib.vitro.webapp.edit.n3editing.processEdit.RdfLiteralHash; -public class ProcessRdfForm { - - private static Log log = LogFactory.getLog(ProcessRdfForm.class); - //Making this a global variable because this may be referenced in multiple places - //Alternatively we could handle all new resource related information separately in its own method - private static Map> varToNewResource = null; - - - - - /** - * Execute any modelChangePreprocessors in the editConfiguration; - * - */ - public static void preprocessModels(AdditionsAndRetractions changes, EditConfigurationVTwo editConfiguration, VitroRequest request){ - List modelChangePreprocessors = editConfiguration.getModelChangePreprocessors(); - if ( modelChangePreprocessors != null ) { - for ( ModelChangePreprocessor pp : modelChangePreprocessors ) { - //these work by side effect - pp.preprocess( changes.getRetractions(), changes.getAdditions(), request ); - } - } - } +/** + * The goal of this class is to provide processing from + * an EditConfiguration and an EditSubmission to produce + * a set of additions and retractions. + * + * When working with the default object property form or the + * default data property from, the way to avoid having + * any optional N3 is to originally configure the + * configuration.setN3Optional() to be empty. + */ +public class ProcessRdfForm { - protected static AdditionsAndRetractions getMinimalChanges( AdditionsAndRetractions changes ){ - //make a model with all the assertions and a model with all the - //retractions, do a diff on those and then only add those to the jenaOntModel - Model allPossibleAssertions = changes.getAdditions(); - Model allPossibleRetractions = changes.getRetractions(); + /** + * This detects if this is an edit of an existing statement or an edit + * to create a new statement or set of statements. Then the correct + * method will be called to convert the EditConfiguration and EditSubmission + * into a set of additions and retractions. + * + * This will handle data property editing, object property editing + * and general editing. + * + * @throws Exception May throw an exception if Required N3 does not + * parse correctly. + */ + public static AdditionsAndRetractions process( + EditConfigurationVTwo configuration, + MultiValueEditSubmission submission, + NewURIMaker newURIMaker) + throws Exception{ + log.debug("configuration:\n" + configuration.toString()); + log.debug("submission:\n" + submission.toString()); - //find the minimal change set - Model assertions = allPossibleAssertions.difference( allPossibleRetractions ); - Model retractions = allPossibleRetractions.difference( allPossibleAssertions ); - return new AdditionsAndRetractions(assertions,retractions); + applyEditSubmissionPreprocessors( configuration, submission ); + + AdditionsAndRetractions changes; + if( configuration.isUpdate() ){ + changes = editExistingStatements(configuration, submission, newURIMaker); + } else { + changes = createNewStatements(configuration, submission, newURIMaker); + } + + changes = getMinimalChanges(changes); + logChanges( configuration, changes); + + return changes; } + + /** + * Processes an EditConfiguration for to create a new statement or a + * set of new statements. + * + * This will handle data property editing, object property editing + * and general editing. + * + * When working with the default object property form or the + * default data property from, the way to avoid having + * any optional N3 is to originally configure the + * configuration.setN3Optional() to be empty. + * + * @throws Exception May throw an exception if the required N3 + * does not parse. + */ + @SuppressWarnings("static-access") + private static AdditionsAndRetractions createNewStatements( + EditConfigurationVTwo configuration, + MultiValueEditSubmission submission, + NewURIMaker newURIMaker) throws Exception { + log.debug("in createNewStatements()" ); + + EditN3GeneratorVTwo n3Populator = configuration.getN3Generator(); + + List requiredN3 = configuration.getN3Required(); + List optionalN3 = configuration.getN3Optional(); + logRequiredOpt("Original valus for required and optional", requiredN3, optionalN3); + + /* add subject from configuration */ + requiredN3 = n3Populator.subInUris(getSubPedObjVarMap(configuration), requiredN3); + optionalN3 = n3Populator.subInUris(getSubPedObjVarMap(configuration), optionalN3); + logRequiredOpt("attempted to substitute in subject, predicate and object from configuration", requiredN3, optionalN3); + + /* add URIs from the form/EditSubmission */ + requiredN3 = n3Populator.subInMultiUris(submission.getUrisFromForm(), requiredN3); + optionalN3 = n3Populator.subInMultiUris(submission.getUrisFromForm(), optionalN3); + logRequiredOpt("substitued in URIs from submission", requiredN3, optionalN3); + + /* add Literals from the form/EditSubmission */ + requiredN3 = n3Populator.subInMultiLiterals(submission.getLiteralsFromForm(), requiredN3); + optionalN3 = n3Populator.subInMultiLiterals(submission.getLiteralsFromForm(), optionalN3); + logRequiredOpt("substitued in Literals from form", requiredN3, optionalN3); + + /* Add URIs in scope */ + requiredN3 = n3Populator.subInMultiUris(configuration.getUrisInScope(), requiredN3); + optionalN3 = n3Populator.subInMultiUris(configuration.getUrisInScope(), optionalN3); + logRequiredOpt("substitued in URIs from configuration scope", requiredN3, optionalN3); + + /* Add Literals in scope */ + requiredN3 = n3Populator.subInMultiLiterals(configuration.getLiteralsInScope(), requiredN3); + optionalN3 = n3Populator.subInMultiLiterals(configuration.getLiteralsInScope(), optionalN3); + logRequiredOpt("substitued in Literals from scope", requiredN3, optionalN3); + + /* add URIs for new resources */ + Map urisForNewResources = URIsForNewRsources(configuration, newURIMaker); + + requiredN3 = n3Populator.subInUris(urisForNewResources, requiredN3); + optionalN3 = n3Populator.subInUris(urisForNewResources, optionalN3); + logRequiredOpt("substitued in new resource URIs", requiredN3, optionalN3); + + /* parse N3 to RDF Models */ + List assertions = parseN3ToRDF( requiredN3 , REQUIRED ); + assertions.addAll( parseN3ToRDF( optionalN3, OPTIONAL )); + + /* No retractions since all of the statements are new. */ + List retractions = Collections.emptyList(); + return new AdditionsAndRetractions(assertions, retractions); + } + + + /** + * Process an EditConfiguration to edit a set of existing statements. + * + * In this method, the N3 associated with fields that changed be + * processed in two sets, one for the state before the edit and + * another for the state after the edit. + * + * This will handle data property editing, object property editing + * and general editing. + */ + private static AdditionsAndRetractions editExistingStatements( + EditConfigurationVTwo editConfiguration, + MultiValueEditSubmission submission, + NewURIMaker newURIMaker) { + + log.debug("in editExistingStatements()"); + + List fieldAssertions = populateAssertions(editConfiguration, submission, newURIMaker); + List fieldRetractions = populateRetractions(editConfiguration, submission, newURIMaker); + return new AdditionsAndRetractions(fieldAssertions, fieldRetractions); + } + + //TODO: maybe move this to utils or contorller? public static AdditionsAndRetractions addDependentDeletes( AdditionsAndRetractions changes, Model queryModel){ //Add retractions for dependent resource delete if that is configured and //if there are any dependent resources. @@ -74,9 +175,11 @@ public class ProcessRdfForm { changes.getRetractions().add(depResRetractions); return changes; } - - - public static void applyChangesToWriteModel(AdditionsAndRetractions changes, OntModel queryModel, OntModel writeModel, String editorUri) { + + //TODO: move this to utils or controller? + public static void applyChangesToWriteModel( + AdditionsAndRetractions changes, + OntModel queryModel, OntModel writeModel, String editorUri) { //side effect: modify the write model with the changes Lock lock = null; try{ @@ -92,144 +195,235 @@ public class ProcessRdfForm { lock.leaveCriticalSection(); } } - - //Create new resource - // - @SuppressWarnings("static-access") - public static AdditionsAndRetractions createNewStatement(EditConfigurationVTwo editConfiguration , MultiValueEditSubmission submission, VitroRequest vreq){ - varToNewResource = null; - //Get all assertions - List assertions = populateAssertions(editConfiguration, submission, vreq); - //Retractions should be empty anyway but the method should take care of that - List retractions = new ArrayList(); - return getMinimalChanges(new AdditionsAndRetractions(assertions, retractions)); - + + /** + * Parse the n3Strings to a List of RDF Model objects. + * + * @param n3Strings + * @param parseType if OPTIONAL, then don't throw exceptions on errors + * If REQUIRED, then throw exceptions on errors. + * @throws Exception + */ + private static List parseN3ToRDF( + List n3Strings, N3ParseType parseType ) throws Exception { + List errorMessages = new ArrayList(); + + List rdfModels = new ArrayList(); + for(String n3 : n3Strings){ + try{ + Model model = ModelFactory.createDefaultModel(); + StringReader reader = new StringReader(n3); + model.read(reader, "", "N3"); + rdfModels.add( model ); + }catch(Throwable t){ + errorMessages.add(t.getMessage() + "\nN3: \n" + n3 + "\n"); + } + } + + String errors = ""; + for( String errorMsg : errorMessages){ + errors += errorMsg + '\n'; + } + + if( !errorMessages.isEmpty() ){ + if( REQUIRED.equals(parseType) ){ + throw new Exception("Errors processing required N3. The EditConfiguration should " + + "be setup so that if a submission passes validation, there will not be errors " + + "in the required N3.\n" + errors ); + }else if( OPTIONAL.equals(parseType) ){ + log.debug("Some Optional N3 did not parse, if a optional N3 does not parse it " + + "will be ignored. This allows optional parts of a form submission to " + + "remain unfilled out and then the optional N3 does not get values subsituted in from" + + "the form submission values. It may also be the case that there are unintentional " + + "syntax errors the optional N3." ); + log.debug( errors ); + } + } + + return rdfModels; } + - public static AdditionsAndRetractions editExistingStatement(EditConfigurationVTwo editConfiguration, MultiValueEditSubmission submission, VitroRequest vreq) { - varToNewResource = null; - List fieldAssertions = populateAssertions(editConfiguration, submission, vreq); - List fieldRetractions = populateRetractions(editConfiguration, submission, vreq); - return getMinimalChanges(new AdditionsAndRetractions(fieldAssertions, fieldRetractions)); - } - /** + //optional field assertions + //if data property, then this would be empty + public static List getOptionalN3Assertions( + EditConfigurationVTwo configuration, MultiValueEditSubmission submission, + NewURIMaker newURIMaker) { + + //Default object property form and default data property form + // avoid having the optional N3 assertions worked with by + // not configuring anything in configuration.setN3Optional() + + List optionalN3Assertions = new ArrayList(); + List n3Optional = configuration.getN3Optional(); + //Substitute uris and literals, including for + n3Optional = subUrisAndLiteralsForN3(configuration, submission, newURIMaker, n3Optional); + optionalN3Assertions = processN3Assertions(configuration, submission, newURIMaker, n3Optional); + return optionalN3Assertions; + } + + + /** * Certain methods/mechanisms overlap across type of property (object or data) and whether or not * the updates are for existing or new resource or value */ - //This should be a separate method because varToNewResources is referred to in multiple places - + //get field assertions - so these appear to be employed when editing an EXISTING literal or resource //Also note this depends on field assertions - public static List getRequiredFieldAssertions(EditConfigurationVTwo configuration, MultiValueEditSubmission submission, VitroRequest vreq) { + public static List getRequiredFieldAssertions( + EditConfigurationVTwo configuration, + MultiValueEditSubmission submission, + NewURIMaker newURIMaker) { List requiredFieldAssertions = new ArrayList(); //Get the original assertions from the edit configuration field - Map> fieldAssertions = Utilities.fieldsToN3Map(configuration.getFields(), Utilities.assertionsType); - fieldAssertions = subUrisAndLiteralsInFieldAssertions(configuration, submission, vreq, fieldAssertions); + Map> fieldAssertions = + Utilities.fieldsToN3Map(configuration.getFields(), Utilities.assertionsType); + + fieldAssertions = subUrisAndLiteralsInFieldAssertions(configuration, submission, newURIMaker, fieldAssertions); //process assertions - requiredFieldAssertions = processFieldAssertions(configuration, submission, vreq, fieldAssertions); + requiredFieldAssertions = parseFieldAssertions( fieldAssertions ); return requiredFieldAssertions; } - - private static Map> subUrisAndLiteralsInFieldRetractions( - EditConfigurationVTwo configuration, - MultiValueEditSubmission submission, - VitroRequest vreq, Map> fieldRetractions) { - return subUrisAndLiteralsForField(configuration, submission, vreq, fieldRetractions); - } - - //substitute uris and literals and also handle new resource - private static Map> subUrisAndLiteralsInFieldAssertions( - EditConfigurationVTwo configuration, - MultiValueEditSubmission submission, - VitroRequest vreq, Map> fieldAssertions) { - //Substitute URIs and literals from form and from scope - fieldAssertions = subUrisAndLiteralsForField(configuration, submission, vreq, fieldAssertions); - fieldAssertions = subNewResourceForField(configuration, vreq, fieldAssertions); - return fieldAssertions; - } - - //For both new and existing statement, need to incorporate varToNewResource - //Check whether data or not, to be consistent - //Map varToNewResource = newToUriMap - //TODO: Check if this still needs to differentiate between object and data property - private static Map> subNewResourceForField( - EditConfigurationVTwo configuration, VitroRequest vreq, - Map> fieldAssertions) { - EditN3GeneratorVTwo n3Subber = configuration.getN3Generator(); - setVarToNewResource(configuration, vreq); - fieldAssertions = n3Subber.substituteIntoValues(varToNewResource, null, fieldAssertions ); - return fieldAssertions; - } - //Substitue for uris and literals from both form and scope for field - private static Map> subUrisAndLiteralsForField( - EditConfigurationVTwo configuration, - MultiValueEditSubmission submission, - VitroRequest vreq, Map> fieldN3) { - EditN3GeneratorVTwo n3Subber = configuration.getN3Generator(); - //Substitute URIs and literals from form - fieldN3 = n3Subber.substituteIntoValues(submission.getUrisFromForm(), submission.getLiteralsFromForm(), fieldN3); - //Substitute URIS and literals from scope - fieldN3 = n3Subber.substituteIntoValues(configuration.getUrisInScope(), configuration.getLiteralsInScope(), fieldN3 ); - return fieldN3; - } - - //Substitute for uris and literals for n3 required or n3Optional - private static List subUrisAndLiteralsForN3( - EditConfigurationVTwo configuration, - MultiValueEditSubmission submission, - VitroRequest vreq, List n3Statements) { - EditN3GeneratorVTwo n3Subber = configuration.getN3Generator(); + public static List getRequiredFieldRetractions( + EditConfigurationVTwo configuration, + MultiValueEditSubmission submission ) { - //Substitute URIs and literals from form - n3Statements = n3Subber.subInMultiUris(submission.getUrisFromForm(), n3Statements); - n3Statements = n3Subber.subInMultiLiterals(submission.getLiteralsFromForm(), n3Statements); - //Substitute URIS and literals in scope - n3Statements = n3Subber.subInMultiUris(configuration.getUrisInScope(), n3Statements); - n3Statements = n3Subber.subInMultiLiterals(configuration.getLiteralsInScope(), n3Statements); - //for new resource - setVarToNewResource(configuration, vreq); - n3Statements = n3Subber.subInMultiUris(varToNewResource, n3Statements); - return n3Statements; + List requiredFieldRetractions = new ArrayList(); + + //TODO: Huda: Check if need to check twice or if once is sufficient? + //if adding new object no retractions, although this should be empty if adding new literal too? + if(!configuration.isDataPropertyUpdate() && !configuration.isObjectPropertyUpdate()) { + return new ArrayList(); + } + + //else populate + //If data property, field retractions based on field alone and if object property additional + //retraction processing required + if(configuration.isObjectPropertyUpdate()){ + Map> fieldRetractions = Utilities.fieldsToN3Map(configuration.getFields(), Utilities.retractionsType); + //sub in uris and literals for field + //fieldRetractions = subUrisAndLiteralsInFieldRetractions(configuration, submission, fieldRetractions); + requiredFieldRetractions = processFieldRetractions(configuration, submission, fieldRetractions); + } + if(configuration.isDataPropertyUpdate()) { + //this simply goes through each field and checks if it has retractions + requiredFieldRetractions = processFieldRetractions(configuration, submission); + } + return requiredFieldRetractions; } - public static void setVarToNewResource(EditConfigurationVTwo configuration, VitroRequest vreq) { - if(varToNewResource == null) { - //No longer using the data poperty method but just using the object processing form version - // if(Utilities.isDataProperty(configuration, vreq)) { - // OntModel resourcesModel = configuration.getResourceModelSelector().getModel(vreq,vreq.getSession().getServletContext()); - // varToNewResource = Utilities.newToUriMap(configuration.getNewResources(),resourcesModel); - // } else { - varToNewResource = Utilities.newToUriMap(configuration.getNewResources(),vreq.getWebappDaoFactory()); - /* - if(log.isDebugEnabled()) { - Utilities.logAddRetract("substituted in URIs for new resources",fieldAssertions,fieldRetractions); - }*/ - // } + //required assertions based on N3 + public static List getRequiredN3Assertions( + EditConfigurationVTwo configuration, MultiValueEditSubmission submission, + NewURIMaker newURIMaker) { + + List n3Required = configuration.getN3Required(); + //Substitute uris and literals, including for + n3Required = subUrisAndLiteralsForN3(configuration, submission, newURIMaker, n3Required); + return processN3Assertions(configuration, submission, newURIMaker, n3Required); + } + + + /** + * TODO: bdc34: what does this check? Why? + */ + public static boolean isGenerateModelFromField( + String fieldName, + EditConfigurationVTwo configuration, MultiValueEditSubmission submission) { +// if(Utilities.isObjectProperty(configuration, vreq)) { +// return true; +// } +// if(Utilities.isDataProperty(configuration, vreq)) { +// if(Utilities.hasFieldChanged(fieldName, configuration, submission)) { +// return true; +// } +// } + return false; + } + + private static boolean logRequiredOpt(String msg, Listrequired, Listoptional){ + if( log.isDebugEnabled() ){ + String out = msg + "\n"; + + if( required != null ){ + out += "required:\n" ; + for( String str : required){ + out += " " + str + "\n"; + } + }else{ + out += " No required\n"; + } + + if( optional != null ){ + out += "optional:\n"; + for( String str : optional){ + out += " " + str + "\n"; + } + }else{ + out += " No Optional\n"; + } + + } + return true; + } + + //generally should always have assertions + private static List populateAssertions( + EditConfigurationVTwo configuration, MultiValueEditSubmission submission, + NewURIMaker newURIMaker) { + List assertions = new ArrayList(); + //if editing existing statement, then assertions based on field + if(configuration.isDataPropertyUpdate() || configuration.isObjectPropertyUpdate()) { + assertions = getRequiredFieldAssertions(configuration, submission, newURIMaker); + } + //otherwise, if new literal or value, assertions generated from n3 required or n3 optional statements + else { + } + return assertions; } + //"final" or general methods- get the assertions and retractions + private static List populateRetractions( + EditConfigurationVTwo configuration, MultiValueEditSubmission submission, + NewURIMaker newURIMaker) { + List retractions = new ArrayList(); + //if adding new object no retractions, although this should be empty if adding new literal too? + if(!configuration.isDataPropertyUpdate() && !configuration.isObjectPropertyUpdate()) { + return new ArrayList(); + } + + //retractions = getRequiredFieldRetractions(configuration, submission, newURIMaker); + + return retractions; + } + + //this occurs for edits of existing statements whether object resource or literal //In data form, not only is the condition for edit check but an additional check regarding //has field changed is included, whereas object form depends only on whether or not this is an edit //Here we take care of both conditions but including a method that checks whether or not to populate the assertions //model - private static List processFieldAssertions( - EditConfigurationVTwo configuration, - MultiValueEditSubmission submission, - VitroRequest vreq, + + /** Parse field assertion N3 to RDF Model objects */ + private static List parseFieldAssertions( +// EditConfigurationVTwo configuration, +// MultiValueEditSubmission submission, Map> fieldAssertions) { + List requiredFieldAssertions = new ArrayList(); + List errorMessages = new ArrayList(); //Loop through field assertions for(String fieldName : fieldAssertions.keySet()){ //this checks whether or not proceed with populating the model based on the field - if(isGenerateModelFromField(fieldName, configuration, submission, vreq)) { +// if(isGenerateModelFromField(fieldName, configuration, submission)) { List assertions = fieldAssertions.get(fieldName); for(String n3: assertions){ try{ @@ -240,116 +434,36 @@ public class ProcessRdfForm { }catch(Throwable t){ String errMsg = "error processing N3 assertion string from field " + fieldName + "\n" + t.getMessage() + '\n' + "n3: \n" + n3; - //errorMessages.add(errMsg); - log.error(errMsg); - //TODO:Check whether need to throw exception here + errorMessages.add(errMsg); } - } + //} } } + log.error("bdc34: is this code every used?"); + if( !errorMessages.isEmpty() ){ + String msg = "Error processing required N3.\n"; + for( String em : errorMessages){ + msg += em + '\n'; + } + throw new Error(msg); + } + //if data property - since only see that there - then check for empty string condition //which means only one value and it is an empty string - if(Utilities.checkForEmptyString(submission, configuration, vreq)) { - requiredFieldAssertions.clear(); - } + //TODO: bdc34 why is this happening here? Could this happen in a default data property form + // model processor? +// if(Utilities.checkForEmptyString(submission, configuration, vreq)) { +// requiredFieldAssertions.clear(); +// } return requiredFieldAssertions; } - - //Process Entity to Return to - substituting uris etc. - public static String processEntityToReturnTo(EditConfigurationVTwo configuration, MultiValueEditSubmission submission, VitroRequest vreq) { - List entityToReturnTo = new ArrayList(); - String entity = configuration.getEntityToReturnTo(); - entityToReturnTo.add(entity); - //Substitute uris and literals on form - //Substitute uris and literals in scope - //Substite var to new resource - EditN3GeneratorVTwo n3Subber = configuration.getN3Generator(); - - //Substitute URIs and literals from form - entityToReturnTo = n3Subber.subInMultiUris(submission.getUrisFromForm(), entityToReturnTo); - entityToReturnTo = n3Subber.subInMultiLiterals(submission.getLiteralsFromForm(), entityToReturnTo); - setVarToNewResource(configuration, vreq); - entityToReturnTo = n3Subber.subInMultiUris(varToNewResource, entityToReturnTo); - - String processedEntity = entityToReturnTo.get(0); - if(processedEntity != null) { - - processedEntity = processedEntity.trim().replaceAll("<","").replaceAll(">",""); - } - return processedEntity; - - } - - public static boolean isGenerateModelFromField(String fieldName, EditConfigurationVTwo configuration, MultiValueEditSubmission submission, VitroRequest vreq) { - if(Utilities.isObjectProperty(configuration, vreq)) { - return true; - } - if(Utilities.isDataProperty(configuration, vreq)) { - if(Utilities.hasFieldChanged(fieldName, configuration, submission)) { - return true; - } - } - return false; - } - - - public static List getRequiredFieldRetractions(EditConfigurationVTwo configuration, MultiValueEditSubmission submission, VitroRequest vreq) { - List requiredFieldRetractions = new ArrayList(); - //TODO: Check if need to check twice or if once is sufficient? - //if adding new object no retractions, although this should be empty if adding new literal too? - if(!configuration.isDataPropertyUpdate() && !configuration.isObjectPropertyUpdate()) { - return new ArrayList(); - } - //else populate - //If data property, field retractions based on field alone and if object property additional - //retraction processing required - if(configuration.isObjectPropertyUpdate()){ - Map> fieldRetractions = Utilities.fieldsToN3Map(configuration.getFields(), Utilities.retractionsType); - //sub in uris and literals for field - fieldRetractions = subUrisAndLiteralsInFieldRetractions(configuration, submission, vreq, fieldRetractions); - requiredFieldRetractions = processFieldRetractions(configuration, submission, vreq, fieldRetractions); - } - if(configuration.isDataPropertyUpdate()) { - //this simply goes through each field and checks if it has retractions - requiredFieldRetractions = processFieldRetractions(configuration, submission, vreq); - } - return requiredFieldRetractions; - } - - //this expects an input map with retractions populated and and with uris/literals subbed - private static List processFieldRetractions( - EditConfigurationVTwo configuration, - MultiValueEditSubmission submission, VitroRequest vreq, - Map> fieldRetractions) { - List requiredFieldRetractions = new ArrayList(); - //Get key set for fields - Map fields = configuration.getFields(); - for(String fieldName: fields.keySet()) { - //get retractions from field retractions for this field - post uri substitution etc. - List retractions = fieldRetractions.get(fieldName); - for( String n3 : retractions ){ - try{ - Model model = ModelFactory.createDefaultModel(); - StringReader reader = new StringReader(n3); - model.read(reader, "", "N3"); - requiredFieldRetractions.add(model); - }catch(Throwable t){ - String errMsg = "error processing N3 retraction string from field " + fieldName + "\n"+ - t.getMessage() + '\n' + - "n3: \n" + n3; - //errorMessages.add(errMsg); - log.error(errMsg); - } - } - } - return requiredFieldRetractions; - } //data property version , gets retractions from each field private static List processFieldRetractions( EditConfigurationVTwo configuration, - MultiValueEditSubmission submission, VitroRequest vreq) { + MultiValueEditSubmission submission) { + List requiredFieldRetractions = new ArrayList(); //Get key set for fields Map fields = configuration.getFields(); @@ -379,22 +493,44 @@ public class ProcessRdfForm { } return requiredFieldRetractions; } - - //required assertions based on N3 - public static List getRequiredN3Assertions(EditConfigurationVTwo configuration, MultiValueEditSubmission submission, VitroRequest vreq) { - List requiredN3Assertions = new ArrayList(); - List n3Required = configuration.getN3Required(); - //Substitute uris and literals, including for - n3Required = subUrisAndLiteralsForN3(configuration, submission, vreq, n3Required); - requiredN3Assertions = processN3Assertions(configuration, submission, vreq, n3Required); - return requiredN3Assertions; - } -private static List processN3Assertions( + //this expects an input map with retractions populated and and with uris/literals subbed + private static List processFieldRetractions( EditConfigurationVTwo configuration, - MultiValueEditSubmission submission, VitroRequest vreq, + MultiValueEditSubmission submission, + Map> fieldRetractions) { + List requiredFieldRetractions = new ArrayList(); + //Get key set for fields + Map fields = configuration.getFields(); + for(String fieldName: fields.keySet()) { + //get retractions from field retractions for this field - post uri substitution etc. + List retractions = fieldRetractions.get(fieldName); + for( String n3 : retractions ){ + try{ + Model model = ModelFactory.createDefaultModel(); + StringReader reader = new StringReader(n3); + model.read(reader, "", "N3"); + requiredFieldRetractions.add(model); + }catch(Throwable t){ + String errMsg = "error processing N3 retraction string from field " + fieldName + "\n"+ + t.getMessage() + '\n' + + "n3: \n" + n3; + //errorMessages.add(errMsg); + log.error(errMsg); + } + } + } + return requiredFieldRetractions; + } + + private static List processN3Assertions( + EditConfigurationVTwo configuration, MultiValueEditSubmission submission, + NewURIMaker newURIMaker, List n3Statements) { - //deal with required N3 + + //deal with required N3, any that cannot + //be parsed are serious configuration errors + List errorMessages = new ArrayList(); List n3Models = new ArrayList(); for(String n3 : n3Statements){ try{ @@ -403,115 +539,187 @@ private static List processN3Assertions( model.read(reader, "", "N3"); n3Models.add( model ); }catch(Throwable t){ - log.error("error processing required n3 string \n"+ - t.getMessage() + '\n' + - "n3: \n" + n3 ); + errorMessages.add( t.getMessage() + '\n' + + "Required N3: \n" + n3 ); } } + + if( !errorMessages.isEmpty() ){ + String msg = "Error processing required N3.\n"; + for( String em : errorMessages){ + msg += em + '\n'; + } + throw new Error(msg); + } + return n3Models; } + + private static void setVarToNewResource(EditConfigurationVTwo configuration, NewURIMaker newURIMaker) { +// if(varToNewResource == null) { +// varToNewResource = Utilities.newToUriMap(configuration.getNewResources(),newURIMaker); +// } + } //there are no retractions based on N3 since N3 is only employed when new literal or resource being processed - //optional field assertions - //if data property, then this would be empty - public static List getOptionalN3Assertions(EditConfigurationVTwo configuration, MultiValueEditSubmission submission, VitroRequest vreq) { - - if(Utilities.isDataProperty(configuration, vreq)) { - return new ArrayList(); - } - //if object property and existing prop update then return null - //otherwise this needs to be populated - if(Utilities.isObjectProperty(configuration, vreq) && configuration.isObjectPropertyUpdate()) { - return new ArrayList(); - } - - //populate - List optionalN3Assertions = new ArrayList(); - List n3Optional = configuration.getN3Optional(); - //Substitute uris and literals, including for - n3Optional = subUrisAndLiteralsForN3(configuration, submission, vreq, n3Optional); - optionalN3Assertions = processN3Assertions(configuration, submission, vreq, n3Optional); - return optionalN3Assertions; + //For both new and existing statement, need to incorporate varToNewResource + //Check whether data or not, to be consistent + //Map varToNewResource = newToUriMap + //TODO: Check if this still needs to differentiate between object and data property + private static Map> subNewResourceForField( + EditConfigurationVTwo configuration, NewURIMaker newURIMaker, + Map> fieldAssertions) { + + EditN3GeneratorVTwo n3Subber = configuration.getN3Generator(); + setVarToNewResource(configuration, newURIMaker); + //fieldAssertions = n3Subber.substituteIntoValues(varToNewResource, null, fieldAssertions ); + return fieldAssertions; } - //"final" or general methods- get the assertions and retractions - public static List populateRetractions(EditConfigurationVTwo configuration, MultiValueEditSubmission submission, VitroRequest vreq) { - List retractions = new ArrayList(); - //if adding new object no retractions, although this should be empty if adding new literal too? - if(!configuration.isDataPropertyUpdate() && !configuration.isObjectPropertyUpdate()) { - return new ArrayList(); - } - - retractions = getRequiredFieldRetractions(configuration, submission, vreq); - - return retractions; + //Substitue for uris and literals from both form and scope for field + private static Map> subUrisAndLiteralsForField( + EditConfigurationVTwo configuration, + MultiValueEditSubmission submission, + Map> fieldN3) { + EditN3GeneratorVTwo n3Subber = configuration.getN3Generator(); + //Substitute URIs and literals from form + fieldN3 = n3Subber.substituteIntoValues(submission.getUrisFromForm(), submission.getLiteralsFromForm(), fieldN3); + //Substitute URIS and literals from scope + fieldN3 = n3Subber.substituteIntoValues(configuration.getUrisInScope(), configuration.getLiteralsInScope(), fieldN3 ); + return fieldN3; } - //generally should always have assertions - public static List populateAssertions(EditConfigurationVTwo configuration, MultiValueEditSubmission submission, VitroRequest vreq) { - List assertions = new ArrayList(); - //if editing existing statement, then assertions based on field - if(configuration.isDataPropertyUpdate() || configuration.isObjectPropertyUpdate()) { - assertions = getRequiredFieldAssertions(configuration, submission, vreq); - } - //otherwise, if new literal or value, assertions generated from n3 required or n3 optional statements - else { - assertions = getRequiredN3Assertions(configuration, submission, vreq); - assertions.addAll(getOptionalN3Assertions(configuration, submission, vreq)); - } - return assertions; + //Substitute for uris and literals for n3 required or n3Optional + private static List subUrisAndLiteralsForN3( + EditConfigurationVTwo configuration, + MultiValueEditSubmission submission, + NewURIMaker newURIMaker, List n3Statements) { + EditN3GeneratorVTwo n3Subber = configuration.getN3Generator(); + + //Substitute URIs and literals from form + n3Statements = n3Subber.subInMultiUris(submission.getUrisFromForm(), n3Statements); + n3Statements = n3Subber.subInMultiLiterals(submission.getLiteralsFromForm(), n3Statements); + //Substitute URIS and literals in scope + n3Statements = n3Subber.subInMultiUris(configuration.getUrisInScope(), n3Statements); + n3Statements = n3Subber.subInMultiLiterals(configuration.getLiteralsInScope(), n3Statements); + //for new resource + setVarToNewResource(configuration, newURIMaker); + //n3Statements = n3Subber.subInMultiUris(varToNewResource, n3Statements); + return n3Statements; } - private static boolean logAddRetract(String msg, Map>add, Map>retract){ - log.debug(msg); - if( add != null ) log.debug( "assertions: " + add.toString() ); - if( retract != null ) log.debug( "retractions: " + retract.toString() ); - return true; - } + //substitute uris and literals and also handle new resource + private static Map> subUrisAndLiteralsInFieldAssertions( + EditConfigurationVTwo configuration, + MultiValueEditSubmission submission, + NewURIMaker newURIMaker, Map> fieldAssertions) { + //Substitute URIs and literals from form and from scope + //fieldAssertions = subUrisAndLiteralsForField(configuration, submission, newURIMaker, fieldAssertions); + fieldAssertions = subNewResourceForField(configuration, newURIMaker, fieldAssertions); + return fieldAssertions; + } - private static boolean logRequiredOpt(String msg, Listrequired, Listoptional){ - log.debug(msg); - if( required != null ) log.debug( "required: " + required.toString() ); - if( optional != null ) log.debug( "optional: " + optional.toString() ); - return true; - } - - public static void updateEditConfigurationForBackButton( - EditConfigurationVTwo editConfig, - MultiValueEditSubmission submission, VitroRequest vreq, OntModel writeModel) { - - //now setup an EditConfiguration so a single back button submissions can be handled - //Do this if data property - if(EditConfigurationUtils.isDataProperty(editConfig.getPredicateUri(), vreq)) { - EditConfigurationVTwo copy = editConfig.copy(); - - //need a new DataPropHash and a new editConfig that uses that, and replace - //the editConfig used for this submission in the session. The same thing - //is done for an update or a new insert since it will convert the insert - //EditConfig into an update EditConfig. - log.debug("attempting to make an updated copy of the editConfig for browser back button support"); - FieldVTwo dataField = copy.getField(copy.getVarNameForObject()); - - DataPropertyStatement dps = new DataPropertyStatementImpl(); - List submitted = submission.getLiteralsFromForm().get(copy.getVarNameForObject()); - if( submitted != null && submitted.size() > 0){ - for(Literal submittedLiteral: submitted) { - dps.setIndividualURI( copy.getSubjectUri() ); - dps.setDatapropURI( copy.getPredicateUri() ); - dps.setDatatypeURI( submittedLiteral.getDatatypeURI()); - dps.setLanguage( submittedLiteral.getLanguage() ); - dps.setData( submittedLiteral.getLexicalForm() ); - - copy.prepareForDataPropUpdate(writeModel, dps); - copy.setDatapropKey( Integer.toString(RdfLiteralHash.makeRdfLiteralHash(dps)) ); - } - EditConfigurationVTwo.putConfigInSession(copy,vreq.getSession()); - } - } - + //TODO: get rid of this as it does nothing new or interesting + private static Map> subUrisAndLiteralsInFieldRetractions( + EditConfigurationVTwo configuration, + MultiValueEditSubmission submission, + NewURIMaker newURIMaker, Map> fieldRetractions) { + return subUrisAndLiteralsForField(configuration, submission, fieldRetractions); } + private static Map getSubPedObjVarMap( + EditConfigurationVTwo configuration) + { + Map varToValue = new HashMap(); + + String varNameForSub = configuration.getVarNameForSubject(); + if( varNameForSub != null && ! varNameForSub.isEmpty()){ + varToValue.put( varNameForSub,configuration.getSubjectUri()); + }else{ + log.debug("no varNameForSubject found in configuration"); + } + + String varNameForPred = configuration.getVarNameForPredicate(); + if( varNameForPred != null && ! varNameForPred.isEmpty()){ + varToValue.put( varNameForPred,configuration.getPredicateUri()); + }else{ + log.debug("no varNameForPredicate found in configuration"); + } + + String varNameForObj = configuration.getVarNameForObject(); + if( varNameForObj != null && ! varNameForObj.isEmpty()){ + varToValue.put( varNameForObj, configuration.getObject()); + }else{ + log.debug("no varNameForObject found in configuration"); + } + + return varToValue; + } + + protected static AdditionsAndRetractions getMinimalChanges( AdditionsAndRetractions changes ){ + //make a model with all the assertions and a model with all the + //retractions, do a diff on those and then only add those to the jenaOntModel + Model allPossibleAssertions = changes.getAdditions(); + Model allPossibleRetractions = changes.getRetractions(); + + //find the minimal change set + Model assertions = allPossibleAssertions.difference( allPossibleRetractions ); + Model retractions = allPossibleRetractions.difference( allPossibleAssertions ); + return new AdditionsAndRetractions(assertions,retractions); + } + private static void applyEditSubmissionPreprocessors( + EditConfigurationVTwo configuration, MultiValueEditSubmission submission) { + List preprocessors = configuration.getEditSubmissionPreprocessors(); + if(preprocessors != null) { + for(EditSubmissionVTwoPreprocessor p: preprocessors) { + p.preprocess(submission); + } + } + } + + //this works differently based on whether this is object property editing or data property editing + //TODO: bdc34: Why would this work differently for data prop or obj prop? + + //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 URIsForNewRsources( + EditConfigurationVTwo configuration, NewURIMaker newURIMaker) + throws InsertException { + Map newResources = configuration.getNewResources(); + + HashMap varToNewURIs = new HashMap(); + for (String key : newResources.keySet()) { + String prefix = newResources.get(key); + String uri = newURIMaker.getUnusedNewURI(prefix); + varToNewURIs.put(key, uri); + } + log.debug( "URIs for new resources: " + varToNewURIs ); + return varToNewURIs; + } + + private static void logChanges(EditConfigurationVTwo configuration, + AdditionsAndRetractions changes) { + if( log.isDebugEnabled() ) + log.debug("Changes for edit " + configuration.getEditKey() + + "\n" + changes.toString()); + } + + private static N3ParseType OPTIONAL = N3ParseType.OPTIONAL; + private static N3ParseType REQUIRED = N3ParseType.REQUIRED; + + private enum N3ParseType { + /* indicates that the n3 is optional and that a parse error should not + * throw an exception */ + OPTIONAL, + /* indicates that the N3 is required and that a parse error should + * stop the processing and throw an exception. */ + REQUIRED + }; + + static Random random = new Random(); + private static Log log = LogFactory.getLog(ProcessRdfForm.class); } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/BaseEditConfigurationGenerator.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/BaseEditConfigurationGenerator.java index cb432158a..dc19514d1 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/BaseEditConfigurationGenerator.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/BaseEditConfigurationGenerator.java @@ -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); diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/controller/PostEditCleanupController.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/controller/PostEditCleanupController.java index 770863dd2..38e399f1a 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/controller/PostEditCleanupController.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/controller/PostEditCleanupController.java @@ -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); } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/controller/ProcessRdfFormController.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/controller/ProcessRdfFormController.java index b603a9cf2..c79d2063c 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/controller/ProcessRdfFormController.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/controller/ProcessRdfFormController.java @@ -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 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> fieldsToRetractionMap( Map 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> newToUriMap(Map newResources, WebappDaoFactory wdf){ - HashMap> newVarsToUris = new HashMap>(); - HashSet newUris = new HashSet(); - for( String key : newResources.keySet()){ - String prefix = newResources.get(key); - String uri = makeNewUri(prefix, wdf); - while( newUris.contains(uri) ){ - uri = makeNewUri(prefix,wdf); - } - List urisList = new ArrayList(); - 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> newToUriMap(Map newResources, - Model model) { - HashMap> newUris = new HashMap>(); - for (String key : newResources.keySet()) { - List urisList = new ArrayList(); - 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) { diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/edit/EditConfigurationTemplateModel.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/edit/EditConfigurationTemplateModel.java index 2e9ffa819..57acb91d5 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/edit/EditConfigurationTemplateModel.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/edit/EditConfigurationTemplateModel.java @@ -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 fieldNames = (List)pageData.get("objectSelect"); - for(String field:fieldNames) { - WebappDaoFactory wdf = vreq.getWebappDaoFactory(); - Map 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 fieldNames = (List)pageData.get("objectSelect"); +// for(String field:fieldNames) { +// WebappDaoFactory wdf = vreq.getWebappDaoFactory(); +// Map 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 fieldNames = (List)pageData.get("objectSelect"); +// for(String field:fieldNames) { +// WebappDaoFactory wdf = vreq.getWebappDaoFactory(); +// Map optionsMap = SelectListGeneratorVTwo.getOptions(editConfig, field , wdf); +// pageData.put(field, optionsMap); +// } +// } +// } } //TODO: Check if this should return a list instead diff --git a/webapp/test/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/EditN3GeneratorVTwoTest.java b/webapp/test/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/EditN3GeneratorVTwoTest.java index 114592583..e4447133c 100644 --- a/webapp/test/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/EditN3GeneratorVTwoTest.java +++ b/webapp/test/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/EditN3GeneratorVTwoTest.java @@ -16,6 +16,79 @@ import com.hp.hpl.jena.rdf.model.ModelFactory; public class EditN3GeneratorVTwoTest { + @Test + public void testSubInMultiUrisNull(){ + String n3 = "?varXYZ" ; + List targets = new ArrayList(); + targets.add(n3); + + Map> keyToValues = new HashMap>(); + List targetValue = new ArrayList(); + targetValue.add(null); + keyToValues.put("varXYZ", targetValue); + + List 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 = ""; + Assert.assertTrue("must not sub in ", !not_expected.equals(resultN3)); + } + + + @Test + public void testSubInUrisNull(){ + String n3 = " ?varXYZ " ; + List targets = new ArrayList(); + targets.add(n3); + + Map keyToValues = new HashMap(); + keyToValues.put("varXYZ", "xyzURI"); + + List 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(" ", resultN3); + + keyToValues = new HashMap(); + 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: . +?person core:educationalTraining ?edTraining . +?edTraining a core:EducationalTraining ; +core:educationalTrainingOf ?person ; + ?org . +, ?org ?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 ." ;