updates for freemarker conversion and related n3editing

This commit is contained in:
hjkhjk54 2011-10-28 15:39:24 +00:00
parent f5fc34628b
commit 202a657178
13 changed files with 2402 additions and 28 deletions

View file

@ -0,0 +1,75 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo;
import java.io.IOException;
import java.io.StringWriter;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
public abstract class BaseEditElementVTwo implements EditElementVTwo {
private static final Log log = LogFactory.getLog(BaseEditElementVTwo.class);
protected FieldVTwo field;
public BaseEditElementVTwo(FieldVTwo field){
this.field = field;
}
/**
* Utility method for use in EditElements to merge a freemarker template.
*/
protected String merge(Configuration fmConfig, String templateName, Map map){
Template template = null;
try {
template = fmConfig.getTemplate(templateName);
} catch (IOException e) {
log.error("Cannot get template " + templateName);
}
StringWriter writer = new StringWriter();
try {
template.process(map, writer);
} catch (TemplateException e) {
log.error(e,e);
} catch (IOException e) {
log.error(e,e);
}
return writer.toString();
}
/**
* Utility method to check if a value from the query parameters is none or a single value.
* This returns true if the key is there and the value is null.
* This does not check if the value is the empty string.
*/
protected boolean hasNoneOrSingle(String key, Map<String, String[]> queryParameters){
if( queryParameters != null ){
if( ! queryParameters.containsKey(key) )
return true; //none
String[] vt = queryParameters.get(key);
return vt == null || vt.length == 0 || vt.length==1;
}else{
log.error("passed null queryParameters");
return false;
}
}
protected boolean hasSingleNonNullNonEmptyValueForKey(String key, Map<String, String[]> queryParameters){
if( queryParameters != null ){
if( ! queryParameters.containsKey(key) )
return true; //none
String[] vt = queryParameters.get(key);
return vt != null && vt.length == 1 && vt[0] != null && ! vt[0].isEmpty() ;
}else{
log.error("passed null queryParameters");
return false;
}
}
}

View file

@ -0,0 +1,216 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.hp.hpl.jena.datatypes.xsd.XSDDateTime;
import com.hp.hpl.jena.rdf.model.Literal;
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary.Precision;
import edu.cornell.mannlib.vitro.webapp.edit.elements.DateTimeWithPrecision;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.EditConfiguration;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.processEdit.EditSubmission;
/*
* Assumption for date time interval validation: Only one start field/end field/and precision.
* We are currently not accepting multiple values for start time, end time, or precision.
*/
public class DateTimeIntervalValidationVTwo implements N3ValidatorVTwo {
private static Log log = LogFactory.getLog(DateTimeIntervalValidationVTwo.class);
private String startFieldName;
private String endFieldName;
private String startValueName;
private String endValueName;
private String startPrecisionName;
private String endPrecisionName;
public DateTimeIntervalValidationVTwo(String startFieldName, String endFieldName){
this.startFieldName = startFieldName;
this.endFieldName = endFieldName;
startValueName = startFieldName + "-value";
endValueName = endFieldName + "-value";
startPrecisionName = startFieldName + "-precision";
endPrecisionName = endFieldName + "-precision";
}
public Map<String, String> validate(EditConfigurationVTwo editConfig,
MultiValueEditSubmission editSub) {
Map<String, List<Literal>> existingLiterals = editConfig.getLiteralsInScope();
List<Literal> existingStartYear = existingLiterals.get(startValueName);
List<Literal> existingEndYear = existingLiterals.get(endValueName);
Map<String, List<Literal>> literalsFromForm = editSub.getLiteralsFromForm();
List<Literal> formStartYear = literalsFromForm.get(startValueName);
List<Literal> formEndYear = literalsFromForm.get(endValueName);
VitroVocabulary.Precision startPrecision = getPrecision(startPrecisionName, editConfig, editSub);
VitroVocabulary.Precision endPrecision = getPrecision(endPrecisionName, editConfig, editSub);
Map<String, String> errors = new HashMap<String, String>();
// NIHVIVO-2541 Commented out to allow end date with no start date
// if( formStartYear == null && formEndYear != null ){
// errors.put(startFieldName, "If there is an end date, there should be a start date");
// return errors;
// }
//Assuming form start year and form end year are working in conjunction with multiple values
int index;
if (formStartYear != null && formEndYear != null) {
int numberStartYears = formStartYear.size();
int numberEndYears = formEndYear.size();
if(numberStartYears > 1 && numberEndYears > 1) {
errors.put(startFieldName, "DateTimeIntervalValidationVTwo does not support multiple start years or end years");
return errors;
}
if(numberStartYears > 0 && numberEndYears > 0) {
errors.putAll(checkDateLiterals(formStartYear.get(0), formEndYear.get(0), startPrecision, endPrecision));
}
} else if (formStartYear != null && existingEndYear != null) {
int numberStartYears = formStartYear.size();
int numberEndYears = existingEndYear.size();
if(numberStartYears > 1 && numberEndYears > 1) {
errors.put(startFieldName, "DateTimeIntervalValidationVTwo does not support multiple start years or end years");
return errors;
}
if(numberStartYears > 0 && numberEndYears > 0) {
errors.putAll(checkDateLiterals(formStartYear.get(0), existingEndYear.get(0), startPrecision, endPrecision));
}
} else if (existingStartYear != null && formEndYear != null) {
int numberStartYears = existingStartYear.size();
int numberEndYears = formEndYear.size();
if(numberStartYears > 1 && numberEndYears > 1) {
errors.put(startFieldName, "DateTimeIntervalValidationVTwo does not support multiple start years or end years");
return errors;
}
if(numberStartYears > 0 && numberEndYears > 0) {
errors.putAll(checkDateLiterals(existingStartYear.get(0), formEndYear.get(0), startPrecision, endPrecision));
}
} else if (existingStartYear != null && existingEndYear != null) {
int numberStartYears = existingStartYear.size();
int numberEndYears = existingEndYear.size();
if(numberStartYears > 1 && numberEndYears > 1) {
errors.put(startFieldName, "DateTimeIntervalValidationVTwo does not support multiple start years or end years");
return errors;
}
if(numberStartYears > 0 && numberEndYears > 0) {
errors.putAll(checkDateLiterals(existingStartYear.get(0), existingEndYear.get(0), startPrecision, endPrecision));
}
}
if (errors.size() != 0)
return errors;
else
return null;
}
private Precision getPrecision(String precisionVarName,
EditConfigurationVTwo editConfig, MultiValueEditSubmission editSub) {
if( editSub != null
&& editSub.getUrisFromForm() != null
&& editSub.getUrisFromForm().containsKey(precisionVarName)){
List<String> precisionStr = editSub.getUrisFromForm().get(precisionVarName);
//TODO: Check if we need to handle multiple precision strings and what to do then
//Currently checks first precision str and then returns response
if(precisionStr.size() > 0) {
String precisionString = precisionStr.get(0);
VitroVocabulary.Precision precision = DateTimeWithPrecision.toPrecision( precisionString );
if( precision == null )
log.warn("cannot convert " + precisionStr + " to a precision");
else
return precision;
} else {
log.error("No precision strings returned");
}
}else if( editConfig != null
&& editConfig.getUrisInScope() != null
&& editConfig.getUrisInScope().containsKey(precisionVarName)){
List<String> precisionStr = editConfig.getUrisInScope().get(precisionVarName);
//TODO: Check if we need to handle multiple precision strings and what to do then
//Currently checks first precision str and then returns response
if(precisionStr.size() > 0) {
String precisionString = precisionStr.get(0);
VitroVocabulary.Precision precision = DateTimeWithPrecisionVTwo.toPrecision( precisionString );
if( precision == null )
log.warn("cannot convert " + precisionString + " to a precision");
else
return precision;
} else {
log.error("No precision strings returned");
}
}
//this is what is returned if a precision was not found in the config or submission
return null;
}
private Map<String, String> checkDateLiterals(
Literal startLit, Literal endLit,
VitroVocabulary.Precision startPrecision, VitroVocabulary.Precision endPrecision) {
Map<String, String> errors = new HashMap<String, String>();
if( endPrecision == null ){
//there is no end date, nothing to check
return errors;
}
try{
XSDDateTime startDate = (XSDDateTime)startLit.getValue();
XSDDateTime endDate = (XSDDateTime)endLit.getValue();
if( startDate != null && endDate!= null ){
Calendar startCal = startDate.asCalendar();
Calendar endCal = endDate.asCalendar();
if( endCal != null ){
if( !startCal.before( endCal ) ){
if( startPrecision == VitroVocabulary.Precision.YEAR
&& endPrecision == VitroVocabulary.Precision.YEAR ){
errors.putAll( checkYears(startCal,endCal));
}else{
errors.put(startFieldName, "Start must be before end");
errors.put(endFieldName, "End must be after start");
}
}
}
}
}catch(ClassCastException cce){
errors.put(startFieldName, "could not format start or end date");
errors.put(endFieldName, "could not format start or end date");
log.debug("could not format dates " + cce);
}
return errors;
}
private Map<? extends String, ? extends String> checkYears(
Calendar startCal, Calendar endCal) {
Map<String, String> errors = new HashMap<String, String>();
if( ! (endCal.get(Calendar.YEAR) >= startCal.get(Calendar.YEAR) )){
errors.put(startFieldName, "Start must be before end");
errors.put(endFieldName, "End must be after start");
}
return errors;
}
}

View file

@ -0,0 +1,620 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.List;
import java.util.ArrayList;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.joda.time.DateTime;
import org.joda.time.format.ISODateTimeFormat;
import com.hp.hpl.jena.datatypes.xsd.XSDDatatype;
import com.hp.hpl.jena.rdf.model.Literal;
import com.hp.hpl.jena.rdf.model.ResourceFactory;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerConfiguration;
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.EditConfiguration;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.Field;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.processEdit.EditSubmission;
import freemarker.template.Configuration;
/**
* This is intended to work in conjunction with a template to create the HTML for a
* datetime with precision and to convert the submitted parameters into
* varname -> Literal and varname -> URI maps.
*
* The variables that get passed to the template are defined in:
* DateTimeWithPrecision.getMapForTemplate()
*
* Two variables will be defined for the N3 edit graphs (These are NOT variables passed to FM templates):
* $fieldname.precision - URI of datetime precision
* $fieldname.value - DateTime literal
*
*/
public class DateTimeWithPrecisionVTwo extends BaseEditElementVTwo {
String fieldName;
/**
* This is the minimum datetime precision that this element
* will accept. If the parameters submitted do not meet this
* requirement, then a validation error will be created.
*/
VitroVocabulary.Precision minimumPrecision;
/**
* This is the maximum precision that the form should
* allow the user to enter. This value is not used by
* DateTimeWithPrecision for validation, it is only passed
* to the template. This should be removed when it can be
* specified in a ftl file.
*
* This could be thought of as the maximum precision to display.
*/
VitroVocabulary.Precision displayRequiredLevel;
VitroVocabulary.Precision DEFAULT_MIN_PRECISION = VitroVocabulary.Precision.DAY;
VitroVocabulary.Precision DEFAULT_DISPLAY_LEVEL = VitroVocabulary.Precision.DAY;
VitroVocabulary.Precision[] precisions = VitroVocabulary.Precision.values();
protected static final String BLANK_SENTINEL = ">SUBMITTED VALUE WAS BLANK<";
public DateTimeWithPrecisionVTwo(FieldVTwo field) {
super(field);
fieldName = field.getName();
minimumPrecision = DEFAULT_MIN_PRECISION;
displayRequiredLevel = DEFAULT_DISPLAY_LEVEL;
}
public DateTimeWithPrecisionVTwo(FieldVTwo field, VitroVocabulary.Precision minimumPrecision){
this(field);
if( minimumPrecision != null )
this.minimumPrecision = minimumPrecision;
else
this.minimumPrecision = DEFAULT_MIN_PRECISION;
this.displayRequiredLevel = this.minimumPrecision;
}
//it would be nice to have only the version of the constructor that takes the enum
//but this is to quickly get the JSP configuration working.
public DateTimeWithPrecisionVTwo(FieldVTwo field, String minimumPrecisionURI, String displayRequiredLevelUri){
this(field);
this.minimumPrecision = toPrecision( minimumPrecisionURI);
if( this.minimumPrecision == null )
throw new IllegalArgumentException(minimumPrecisionURI
+" is not a valid precision for minimumPrecision, see VitroVocabulary.Precision");
this.displayRequiredLevel = toPrecision( displayRequiredLevelUri );
if( this.displayRequiredLevel == null )
throw new IllegalArgumentException(displayRequiredLevelUri
+" is not a valid precision for displayRequiredLevel, see VitroVocabulary.Precision");
// if( this.displayRequiredLevel.ordinal() < this.minimumPrecision.ordinal() ){
// throw new IllegalArgumentException("the display precision level " + this.displayRequiredLevel
// + " is less precise than the required minimum precision of " + this.minimumPrecision);
// }
}
private static final Log log = LogFactory.getLog(DateTimeWithPrecisionVTwo.class);
protected String TEMPLATE_NAME = "dateTimeWithPrecision.ftl";
@Override
public String draw(String fieldName, EditConfigurationVTwo editConfig,
MultiValueEditSubmission editSub, Configuration fmConfig) {
Map map = getMapForTemplate( editConfig, editSub);
return merge( fmConfig, TEMPLATE_NAME, map);
}
/**
* This produces a map for use in the template. Will be using this b/c
*/
public Map getMapForTemplate(EditConfigurationVTwo editConfig, MultiValueEditSubmission editSub) {
Map<String,Object>map = new HashMap<String,Object>();
//always need the fieldName, required precision, and constants
map.put("fieldName", fieldName);
addPrecisionConstants(map);
map.put("minimumPrecision", minimumPrecision.uri());
map.put("requiredLevel", displayRequiredLevel.uri());
//Still expecting single precision uri not multiple
String precisionUri= getPrecision(editConfig,editSub);
VitroVocabulary.Precision existingPrec = toPrecision(precisionUri);
if( precisionUri != null && !"".equals(precisionUri) && existingPrec == null ){
log.error("field " + fieldName + ": existing precision uri was " +
"'" + precisionUri + "' but could not convert to Precision object");
}
if( precisionUri == null || precisionUri.isEmpty() || existingPrec == null){
map.put("existingPrecision", "");
/* no precision so there should also be no datetime */
DateTime value = getTimeValue(editConfig,editSub);
if( value != null )
log.info("Unexpected state: Precision for " + fieldName
+ " was '" + precisionUri + "' but date time was " + value);
map.put("year", "");
map.put("month", "");
map.put("day", "");
map.put("hour", "");
map.put("minute", "");
map.put("second", "") ;
} else if( VitroVocabulary.Precision.NONE.uri().equals(precisionUri) ){
//bdc34: not sure what to do with the NONE precision
map.put("existingPrecision", precisionUri);
map.put("year", "");
map.put("month", "");
map.put("day", "");
map.put("hour", "");
map.put("minute", "");
map.put("second", "") ;
}else{
map.put("existingPrecision", precisionUri);
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
+ " but the date time is " + value);
/* only put the values in the map for ones which are significant based on the precision */
if( existingPrec.ordinal() >= VitroVocabulary.Precision.SECOND.ordinal() )
map.put("second", Integer.toString(value.getSecondOfMinute() )) ;
else
map.put("second", "");
if( existingPrec.ordinal() >= VitroVocabulary.Precision.MINUTE.ordinal() )
map.put("minute", Integer.toString(value.getMinuteOfHour()) );
else
map.put("minute", "");
if( existingPrec.ordinal() >= VitroVocabulary.Precision.HOUR.ordinal() )
map.put("hour", Integer.toString(value.getHourOfDay()) );
else
map.put("hour", "");
if( existingPrec.ordinal() >= VitroVocabulary.Precision.DAY.ordinal() )
map.put("day", Integer.toString(value.getDayOfMonth()) );
else
map.put("day", "");
if( existingPrec.ordinal() >= VitroVocabulary.Precision.MONTH.ordinal() )
map.put("month", Integer.toString(value.getMonthOfYear()));
else
map.put("month", "");
if( existingPrec.ordinal() >= VitroVocabulary.Precision.YEAR.ordinal() )
map.put("year", Integer.toString(value.getYear()));
else
map.put("year", "");
}
return map;
}
/** Adds precisionURIs for use by the templates */
private void addPrecisionConstants(Map<String,Object> map){
Map<String,Object> constants = new HashMap<String,Object>();
for( VitroVocabulary.Precision pc: VitroVocabulary.Precision.values()){
constants.put(pc.name().toLowerCase(),pc.uri());
}
map.put("precisionConstants", constants);
}
/**
* Gets the currently set precision. May return null.
*/
private String getPrecision(EditConfigurationVTwo editConfig, MultiValueEditSubmission editSub) {
if( editSub != null ){
List<String> submittedPrecisionURI = editSub.getUrisFromForm().get( getPrecisionVariableName() );
if( submittedPrecisionURI != null
&& submittedPrecisionURI.size() > 0
&& submittedPrecisionURI.get(0) != null){
return submittedPrecisionURI.get(0);
}
}
List<String> existingPrecisionURI = editConfig.getUrisInScope().get( getPrecisionVariableName() );
if( existingPrecisionURI != null
&& existingPrecisionURI.size() > 0
&& existingPrecisionURI.get(0) != null){
//TODO: Check if relevant to return more than one element
return existingPrecisionURI.get(0);
}else{
return null;
}
}
private DateTime getTimeValue(EditConfigurationVTwo editConfig, MultiValueEditSubmission editSub) {
if( editSub != null ){
List<Literal> submittedValue = editSub.getLiteralsFromForm().get( getValueVariableName() );
if( submittedValue != null ) {
//TODO: Check what to do with multiple values, currently handling one value
if(submittedValue.size() > 0 && submittedValue.get(0) != null) {
return new DateTime( submittedValue.get(0).getLexicalForm() );
}
}
}
List<Literal> dtValue = editConfig.getLiteralsInScope().get( getValueVariableName() );
if( dtValue != null ){
if(dtValue.size() > 0 && dtValue.get(0) != null)
{
return new DateTime( dtValue.get(0).getLexicalForm() );
}
}
return null;
}
/**
* This gets the literals for a submitted form from the queryParmeters.
* It will only be called if getValidationErrors() doesn't return any errors.
*/
@Override
public Map<String, List<Literal>> getLiterals(String fieldName,
EditConfigurationVTwo editConfig, Map<String, String[]> queryParameters) {
Map<String,List<Literal>> literalMap = new HashMap<String,List<Literal>>();
Literal datetime =getDateTime( queryParameters);
List<Literal> literals = new ArrayList<Literal>();
literals.add(datetime);
literalMap.put(fieldName+"-value", literals);
return literalMap;
}
protected Literal getDateTime( Map<String, String[]> queryParameters ) {
String submittedPrec = BLANK_SENTINEL;
try {
submittedPrec = getSubmittedPrecision( queryParameters);
} catch (Exception e) {
log.error("could not get submitted precsion",e);
}
if( BLANK_SENTINEL.equals( submittedPrec ) )
return null;
Integer year = parseToInt(fieldName+"-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);
if( month == null || month == 0 )
month = 1;
Integer day = parseToInt(fieldName+"-day", queryParameters);
if( day == null || day == 0 )
day = 1;
Integer hour = parseToInt(fieldName+"-hour", queryParameters);
if( hour == null )
hour = 0;
Integer minute = parseToInt(fieldName+"-minute", queryParameters);
if( minute == null )
minute = 0;
Integer second = parseToInt(fieldName+"-second", queryParameters);
if( second == null )
second = 0;
DateTime value = new DateTime(
year.intValue(),month.intValue(),day.intValue(),
hour.intValue(),minute.intValue(),second.intValue(),0/*millis*/
);
return ResourceFactory.createTypedLiteral(
ISODateTimeFormat.dateHourMinuteSecond().print(value), /*does not include timezone*/
XSDDatatype.XSDdateTime);
}
/**
* This gets the URIs for a submitted form from the queryParmeters.
* It will only be called if getValidationErrors() doesn't return any errors.
*/
@Override
public Map<String, List<String>> getURIs(String fieldName,
EditConfigurationVTwo editConfig, Map<String, String[]> queryParameters) {
String precisionUri;
try {
precisionUri = getSubmittedPrecision( queryParameters);
} catch (Exception e) {
log.error("getURIs() should only be called on input that passed getValidationErrors()");
return Collections.emptyMap();
}
Map<String,List<String>> uriMap = new HashMap<String,List<String>>();
if( precisionUri != null ){
List<String> uris = new ArrayList<String>();
uris.add(precisionUri);
uriMap.put(fieldName+"-precision", uris);
}
return uriMap;
}
/**
* Precision is based on the values returned by the form. Throws an exception with
* the error message if the queryParameters cannot make a valid date/precision because
* there are values missing.
*/
protected String getSubmittedPrecision(Map<String, String[]> queryParameters) throws Exception {
Integer year = parseToInt(fieldName+"-year",queryParameters);
Integer month = parseToInt(fieldName+"-month",queryParameters);
Integer day = parseToInt(fieldName+"-day",queryParameters);
Integer hour = parseToInt(fieldName+"-hour",queryParameters);
Integer minute = parseToInt(fieldName+"-minute",queryParameters);
Integer second = parseToInt(fieldName+"-second",queryParameters);
Integer[] values = { year, month, day, hour, minute, second };
/* find the most significant date field that is null. */
int indexOfFirstNull= -1;
for(int i=0; i < values.length ; i++){
if( values[i] == null ){
indexOfFirstNull = i;
break;
}
}
/* the field wasn't filled out at all */
if( indexOfFirstNull == 0 )
//return VitroVocabulary.Precision.NONE.uri();
return BLANK_SENTINEL;
/* if they all had values then we have seconds precision */
if( indexOfFirstNull == -1 )
return VitroVocabulary.Precision.SECOND.uri();
/* check that there are no values after the most significant null field
* that are non-null. */
boolean nonNullAfterFirstNull=false;
for(int i=0; i < values.length ; i++){
if( i > indexOfFirstNull && values[i] != null ){
nonNullAfterFirstNull = true;
break;
}
}
if( nonNullAfterFirstNull )
throw new Exception("Invalid date-time value. When creating a date-time value, there cannot be gaps between any of the selected fields.");
else{
return precisions[ indexOfFirstNull ].uri();
}
}
@Override
public Map<String, String> getValidationMessages(String fieldName,
EditConfigurationVTwo editConfig, Map<String, String[]> queryParameters) {
Map<String,String> errorMsgMap = new HashMap<String,String>();
//check that any parameters we got are single values
String[] names = {"year","month","day","hour","minute","second", "precision"};
for( String name:names){
if ( !hasNoneOrSingle(fieldName+"-"+name, queryParameters))
errorMsgMap.put(fieldName+"-"+name, "must have only one value for " + name);
}
String precisionURI = null;
try{
precisionURI = getSubmittedPrecision( queryParameters);
}catch(Exception ex){
errorMsgMap.put(fieldName,ex.getMessage());
return errorMsgMap;
}
errorMsgMap.putAll(checkDate( precisionURI, queryParameters) );
return errorMsgMap;
}
/**
* This checks for invalid date times.
*/
final static String NON_INTEGER_YEAR = "must enter a valid year";
final static String NON_INTEGER_MONTH = "must enter a valid month";
final static String NON_INTEGER_DAY = "must enter a valid day";
final static String NON_INTEGER_HOUR = "must enter a valid hour";
final static String NON_INTEGER_MINUTE = "must enter a valid minute";
final static String NON_INTEGER_SECOND = "must enter a valid second";
private Map<String,String> checkDate( String precisionURI, Map<String, String[]> qp){
if( precisionURI == null )
return Collections.emptyMap();
Map<String,String> errors = new HashMap<String,String>();
Integer year,month,day,hour,minute,second;
//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);
}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);
}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);
}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);
}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);
}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);
}
//check if we can make a valid date with these integers
year = parseToInt(fieldName+"-year", qp);
if( year == null )
year = 1999;
month= parseToInt(fieldName+"-month", qp);
if(month == null )
month = 1;
day = parseToInt(fieldName+"-day", qp);
if( day == null )
day = 1;
hour = parseToInt(fieldName+"-hour", qp);
if( hour == null )
hour = 0;
minute = parseToInt(fieldName+"-minute",qp);
if( minute == null )
minute = 0;
second = parseToInt(fieldName+"-second", qp);
if( second == null )
second = 0;
//initialize to something so that we can be assured not to get
//system date dependent behavior
DateTime dateTime = new DateTime("1970-01-01T00:00:00Z");
try{
dateTime = dateTime.withYear(year);
}catch(IllegalArgumentException iae){
errors.put(fieldName+"-year", iae.getLocalizedMessage());
}
try{
dateTime = dateTime.withMonthOfYear(month);
}catch(IllegalArgumentException iae){
errors.put(fieldName+"-month", iae.getLocalizedMessage());
}
try{
dateTime = dateTime.withDayOfMonth(day);
}catch(IllegalArgumentException iae){
errors.put(fieldName+"-day", iae.getLocalizedMessage());
}
try{
dateTime = dateTime.withHourOfDay(hour);
}catch(IllegalArgumentException iae){
errors.put(fieldName+"-hour", iae.getLocalizedMessage());
}
try{
dateTime = dateTime.withSecondOfMinute(second);
}catch(IllegalArgumentException iae){
errors.put(fieldName+"-second", iae.getLocalizedMessage());
}
return errors;
}
private boolean fieldMatchesPattern( String fieldName, Map<String,String[]>queryParameters, Pattern pattern){
String[] varg = queryParameters.get(fieldName);
if( varg == null || varg.length != 1 || varg[0] == null)
return false;
String value = varg[0];
Matcher match = pattern.matcher(value);
return match.matches();
}
private boolean emptyOrBlank(String key,Map<String, String[]> queryParameters){
String[] vt = queryParameters.get(key);
return ( vt == null || vt.length ==0 || vt[0] == null || vt[0].length() == 0 );
}
private boolean canParseToNumber(String key,Map<String, String[]> queryParameters){
Integer out = null;
try{
String[] vt = queryParameters.get(key);
if( vt == null || vt.length ==0 || vt[0] == null)
return false;
else{
out = Integer.parseInt(vt[0]);
return true;
}
}catch(IndexOutOfBoundsException iex){
out = null;
}catch(NumberFormatException nfe){
out = null;
}catch(NullPointerException npe){
out = null;
}
return false;
}
private Integer parseToInt(String key,Map<String, String[]> queryParameters){
Integer out = null;
try{
String[] vt = queryParameters.get(key);
if( vt == null || vt.length ==0 || vt[0] == null)
out = null;
else
out = Integer.parseInt(vt[0]);
}catch(IndexOutOfBoundsException iex){
out = null;
}catch(NumberFormatException nfe){
out = null;
}catch(NullPointerException npe){
out = null;
}
return out;
}
public VitroVocabulary.Precision getRequiredMinimumPrecision() {
return minimumPrecision;
}
public void setRequiredMinimumPrecision(
VitroVocabulary.Precision requiredMinimumPrecision) {
this.minimumPrecision = requiredMinimumPrecision;
}
/* returns null if it cannot convert */
public static VitroVocabulary.Precision toPrecision(String precisionUri){
for( VitroVocabulary.Precision precision : VitroVocabulary.Precision.values()){
if( precision.uri().equals(precisionUri))
return precision;
}
return null;
}
public String getValueVariableName(){ return fieldName + "-value" ; }
public String getPrecisionVariableName(){ return fieldName + "-precision" ; }
}

View file

@ -2,6 +2,7 @@
package edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo; package edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -11,18 +12,23 @@ import javax.servlet.http.HttpSession;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import com.hp.hpl.jena.rdf.model.Literal;
import com.hp.hpl.jena.rdf.model.Model; import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.vocabulary.XSD;
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary; import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory; import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.EditConfiguration; import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.EditConfiguration;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.Field;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.processEdit.RdfLiteralHash; import edu.cornell.mannlib.vitro.webapp.edit.n3editing.processEdit.RdfLiteralHash;
import edu.cornell.mannlib.vitro.webapp.web.templatemodels.edit.EditConfigurationTemplateModel; import edu.cornell.mannlib.vitro.webapp.web.templatemodels.edit.EditConfigurationTemplateModel;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerConfigurationLoader;
import edu.cornell.mannlib.vitro.webapp.beans.DataProperty; import edu.cornell.mannlib.vitro.webapp.beans.DataProperty;
import edu.cornell.mannlib.vitro.webapp.beans.DataPropertyStatement; import edu.cornell.mannlib.vitro.webapp.beans.DataPropertyStatement;
import edu.cornell.mannlib.vitro.webapp.beans.Individual; import edu.cornell.mannlib.vitro.webapp.beans.Individual;
import edu.cornell.mannlib.vitro.webapp.beans.ObjectProperty; import edu.cornell.mannlib.vitro.webapp.beans.ObjectProperty;
import freemarker.template.Configuration;
public class EditConfigurationUtils { public class EditConfigurationUtils {
private static Log log = LogFactory.getLog(EditConfigurationUtils.class); private static Log log = LogFactory.getLog(EditConfigurationUtils.class);
@ -187,4 +193,48 @@ public class EditConfigurationUtils {
return dataHash; return dataHash;
} }
//Copied from the original input element formatting tag
//Allows the retrieval of the string values for the literals
//Useful for cases with date/time and other mechanisms
public static Map<String, List<String>> getExistingLiteralValues(VitroRequest vreq, EditConfigurationVTwo editConfig) {
Map<String, List<String>> literalsInScopeStringValues = new HashMap<String, List<String>>();
Map<String, List<Literal>> literalsInScope = editConfig.getLiteralsInScope();
for(String key: literalsInScope.keySet() ) {
List<String> stringValues = processLiteral(editConfig, key);
literalsInScopeStringValues.put(key, stringValues);
}
return literalsInScopeStringValues;
}
//Copied from input element formatting tag
private static List<String> processLiteral(EditConfigurationVTwo editConfig, String fieldName) {
Map<String, List<Literal>> literalsInScope = editConfig.getLiteralsInScope();
List<String> stringValues = new ArrayList<String>();
List<Literal> literalValues = literalsInScope.get(fieldName);
for(Literal l: literalValues) {
//Could do additional processing here if required, for example if date etc. if need be
stringValues.add(l.getValue().toString());
}
return stringValues;
}
public static Map<String, List<String>> getExistingUriValues(EditConfigurationVTwo editConfig) {
return editConfig.getUrisInScope();
}
//Generate HTML for a specific field name given
public static String generateHTMLForElement(VitroRequest vreq, String fieldName, EditConfigurationVTwo editConfig) {
String html = "";
Configuration fmConfig = FreemarkerConfigurationLoader.getConfig(vreq, vreq.getSession().getServletContext());
FieldVTwo field = editConfig == null ? null : editConfig.getField(fieldName);
MultiValueEditSubmission editSub = new MultiValueEditSubmission(vreq.getParameterMap(), editConfig);
if( field != null && field.getEditElement() != null ){
html = field.getEditElement().draw(fieldName, editConfig, editSub, fmConfig);
}
return html;
}
} }

View file

@ -114,16 +114,18 @@ public class EditConfigurationVTwo {
String formUrl; String formUrl;
String editKey; String editKey;
List<N3Validator> validators = Collections.emptyList(); List<N3ValidatorVTwo> validators;
EditN3GeneratorVTwo n3generator; EditN3GeneratorVTwo n3generator;
private List<ModelChangePreprocessor> modelChangePreprocessors; private List<ModelChangePreprocessor> modelChangePreprocessors;
private List<EditSubmissionVTwoPreprocessor> editSubmissionPreprocessors = Collections.emptyList(); private List<EditSubmissionVTwoPreprocessor> editSubmissionPreprocessors;
private ProhibitedFromSearch prohibitedFromSearch; private ProhibitedFromSearch prohibitedFromSearch;
private HashMap<String, Object> formSpecificData;
/** Name of freemarker template to generate form. */ /** Name of freemarker template to generate form. */
String template; String template;
@ -879,13 +881,13 @@ public class EditConfigurationVTwo {
this.resourceModelSelector = resourceModelSelector; this.resourceModelSelector = resourceModelSelector;
} }
public List<N3Validator> getValidators() { public List<N3ValidatorVTwo> getValidators() {
return validators; return validators;
} }
public void addValidator( N3Validator validator){ public void addValidator( N3ValidatorVTwo validator){
if( this.validators == null ) if( this.validators == null )
this.validators = new ArrayList<N3Validator>(); this.validators = new ArrayList<N3ValidatorVTwo>();
this.validators.add(validator); this.validators.add(validator);
} }
@ -922,4 +924,15 @@ public class EditConfigurationVTwo {
public boolean isDataPropertyUpdate() { public boolean isDataPropertyUpdate() {
return this.getDatapropKey() != null && this.getDatapropKey().length() > 0; return this.getDatapropKey() != null && this.getDatapropKey().length() > 0;
} }
//This is for specific data for a form that will be set by the generator
public void setFormSpecificData(HashMap<String, Object> formSpecificData) {
this.formSpecificData = formSpecificData;
}
public HashMap<String, Object> getFormSpecificData() {
// TODO Auto-generated method stub
return this.formSpecificData;
}
} }

View file

@ -39,6 +39,11 @@ public interface EditElementVTwo {
*/ */
public String draw(String fieldName, EditConfigurationVTwo editConfig, MultiValueEditSubmission editSub, Configuration fmConfig); public String draw(String fieldName, EditConfigurationVTwo editConfig, MultiValueEditSubmission editSub, Configuration fmConfig);
/**
* This method gets the map with the data that can then be passed to the template
*/
public Map getMapForTemplate(EditConfigurationVTwo editConfig, MultiValueEditSubmission editSub);
/* in the future, we may need to get existing values */ /* in the future, we may need to get existing values */
/* /*
public Map<String,Literal> getExistingLiterals(???) public Map<String,Literal> getExistingLiterals(???)

View file

@ -0,0 +1,12 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo;
import java.util.Map;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.EditConfiguration;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.processEdit.EditSubmission;
public interface N3ValidatorVTwo {
public Map<String,String> validate(EditConfigurationVTwo editConfig, MultiValueEditSubmission editSub);
}

View file

@ -0,0 +1,123 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.generators;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
import javax.servlet.http.HttpSession;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.DateTimeWithPrecisionVTwo;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditConfigurationUtils;
import edu.cornell.mannlib.vitro.webapp.dao.jena.QueryUtils;
import com.hp.hpl.jena.rdf.model.Literal;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.vocabulary.RDFS;
import com.hp.hpl.jena.vocabulary.RDF;
import com.hp.hpl.jena.vocabulary.XSD;
import com.hp.hpl.jena.ontology.OntModel;
import edu.cornell.mannlib.vitro.webapp.beans.DataProperty;
import edu.cornell.mannlib.vitro.webapp.beans.DataPropertyStatement;
import edu.cornell.mannlib.vitro.webapp.beans.Individual;
import edu.cornell.mannlib.vitro.webapp.beans.ObjectProperty;
import edu.cornell.mannlib.vitro.webapp.beans.VClass;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
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.DisplayVocabulary;
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditConfigurationVTwo;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.Field;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.processEdit.RdfLiteralHash;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditN3GeneratorVTwo;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.SelectListGeneratorVTwo;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.FieldVTwo;
import edu.cornell.mannlib.vitro.webapp.web.MiscWebUtils;
import edu.cornell.mannlib.vitro.webapp.search.beans.ProhibitedFromSearch;
import edu.cornell.mannlib.vitro.webapp.utils.FrontEndEditingUtils;
import edu.cornell.mannlib.vitro.webapp.utils.FrontEndEditingUtils.EditMode;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.validators.DateTimeIntervalValidation;
/**
* Generates the edit configuration for adding a Role to a Person.
Stage one is selecting the type of the non-person thing
associated with the Role with the intention of reducing the
number of Individuals that the user has to select from.
Stage two is selecting the non-person Individual to associate
with the Role.
This is intended to create a set of statements like:
?person core:hasResearchActivityRole ?newRole.
?newRole rdf:type core:ResearchActivityRole ;
roleToActivityPredicate ?someActivity .
?someActivity rdf:type core:ResearchActivity .
?someActivity rdfs:label "activity title" .
Each subclass of the abstract two stage Generator class will have the option of overriding certain
methods, and must always implement the following methods:
getRoleType
getRoleActivityTypeOptionsType
getRoleActivityTypeObjectClassUri
getRoleActivityTypeLiteralOptions
*
*/
public class AddClinicalRoleToPersonGenerator extends AddRoleToPersonTwoStageGenerator {
private Log log = LogFactory.getLog(AddClinicalRoleToPersonGenerator.class);
private static String template = "addClinicalRoleToPerson.ftl";
//Should this be overridden
@Override
protected void setTemplate(EditConfigurationVTwo editConfiguration,
VitroRequest vreq) {
editConfiguration.setTemplate(template);
}
//The default activityToRolePredicate and roleToActivityPredicates are
//correct for this subclass so they don't need to be overwritten
//role type will always be set based on particular form
public String getRoleType(VitroRequest vreq) {
//TODO: Get dynamic way of including vivoweb ontology
return "http://vivoweb.org/ontology/core#ClinicalRole";
}
//Each subclass generator will return its own type of option here:
//whether literal hardcoded, based on class group, or subclasses of a specific class
//The latter two will apparently lend some kind of uri to objectClassUri ?
public RoleActivityOptionTypes getRoleActivityTypeOptionsType(VitroRequest vreq) {
return RoleActivityOptionTypes.HARDCODED_LITERALS;
}
//This too will depend on the specific subclass of generator
public String getRoleActivityTypeObjectClassUri(VitroRequest vreq) {
return null;
}
//Clinical role involves hard-coded options for the "right side" of the role or activity
protected HashMap<String, String> getRoleActivityTypeLiteralOptions(VitroRequest vreq) {
HashMap<String, String> literalOptions = new HashMap<String, String>();
literalOptions.put("", "Select one");
literalOptions.put("http://vivoweb.org/ontology/core#Project", "Project");
literalOptions.put("http://vivoweb.org/ontology/core#Service","Service");
return literalOptions;
}
//isShowRoleLabelField remains true for this so doesn't need to be overwritten
}

View file

@ -0,0 +1,983 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.generators;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
import javax.servlet.http.HttpSession;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.DateTimeWithPrecisionVTwo;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.DateTimeIntervalValidationVTwo;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditConfigurationUtils;
import edu.cornell.mannlib.vitro.webapp.dao.jena.QueryUtils;
import com.hp.hpl.jena.rdf.model.Literal;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.vocabulary.RDFS;
import com.hp.hpl.jena.vocabulary.RDF;
import com.hp.hpl.jena.vocabulary.XSD;
import com.hp.hpl.jena.ontology.OntModel;
import edu.cornell.mannlib.vitro.webapp.beans.DataProperty;
import edu.cornell.mannlib.vitro.webapp.beans.DataPropertyStatement;
import edu.cornell.mannlib.vitro.webapp.beans.Individual;
import edu.cornell.mannlib.vitro.webapp.beans.ObjectProperty;
import edu.cornell.mannlib.vitro.webapp.beans.VClass;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
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.DisplayVocabulary;
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditConfigurationVTwo;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.Field;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.processEdit.RdfLiteralHash;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditN3GeneratorVTwo;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.SelectListGeneratorVTwo;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.FieldVTwo;
import edu.cornell.mannlib.vitro.webapp.web.MiscWebUtils;
import edu.cornell.mannlib.vitro.webapp.search.beans.ProhibitedFromSearch;
import edu.cornell.mannlib.vitro.webapp.utils.FrontEndEditingUtils;
import edu.cornell.mannlib.vitro.webapp.utils.FrontEndEditingUtils.EditMode;
/**
* Generates the edit configuration for adding a Role to a Person.
Stage one is selecting the type of the non-person thing
associated with the Role with the intention of reducing the
number of Individuals that the user has to select from.
Stage two is selecting the non-person Individual to associate
with the Role.
This is intended to create a set of statements like:
?person core:hasResearchActivityRole ?newRole.
?newRole rdf:type core:ResearchActivityRole ;
roleToActivityPredicate ?someActivity .
?someActivity rdf:type core:ResearchActivity .
?someActivity rdfs:label "activity title" .
Important: This form cannot be directly used as a custom form. It has parameters that must be set.
See addClinicalRoleToPerson.jsp for an example.
*
*/
public abstract class AddRoleToPersonTwoStageGenerator implements EditConfigurationGenerator {
private Log log = LogFactory.getLog(AddRoleToPersonTwoStageGenerator.class);
private boolean isObjectPropForm = false;
private String subjectUri = null;
private String predicateUri = null;
private String objectUri = null;
private String datapropKeyStr= null;
private int dataHash = 0;
private DataPropertyStatement dps = null;
private String dataLiteral = null;
private String template = "addRoleToPersonTwoStage.ftl";
private static HashMap<String,String> defaultsForXSDtypes ;
//Types of options to populate drop-down for types for the "right side" of the role
public static enum RoleActivityOptionTypes {
VCLASSGROUP,
CHILD_VCLASSES,
HARDCODED_LITERALS
};
@Override
public EditConfigurationVTwo getEditConfiguration(VitroRequest vreq, HttpSession session) {
EditConfigurationVTwo editConfiguration = new EditConfigurationVTwo();
//Set n3 generator
editConfiguration.setN3Generator(new EditN3GeneratorVTwo(editConfiguration));
//process subject, predicate, object parameters
this.initProcessParameters(vreq, session, editConfiguration);
//Assumes this is a simple case of subject predicate var
editConfiguration.setN3Required(this.generateN3Required(vreq));
//n3 optional
editConfiguration.setN3Optional(this.generateN3Optional());
//Todo: what do new resources depend on here?
//In original form, these variables start off empty
editConfiguration.setNewResources(generateNewResources(vreq));
//In scope
this.setUrisAndLiteralsInScope(editConfiguration, vreq);
//on Form
this.setUrisAndLiteralsOnForm(editConfiguration, vreq);
editConfiguration.setFilesOnForm(new ArrayList<String>());
//Sparql queries
this.setSparqlQueries(editConfiguration, vreq);
//set fields
setFields(editConfiguration, vreq, EditConfigurationUtils.getPredicateUri(vreq));
// No need to put in session here b/c put in session within edit request dispatch controller instead
//placing in session depends on having edit key which is handled in edit request dispatch controller
// editConfiguration.putConfigInSession(editConfiguration, session);
prepareForUpdate(vreq, session, editConfiguration);
//Form title and submit label now moved to edit configuration template
//TODO: check if edit configuration template correct place to set those or whether
//additional methods here should be used and reference instead, e.g. edit configuration template could call
//default obj property form.populateTemplate or some such method
//Select from existing also set within template itself
setTemplate(editConfiguration, vreq);
//Set edit key
setEditKey(editConfiguration, vreq);
//Add validator
editConfiguration.addValidator(new DateTimeIntervalValidationVTwo("startField","endField") );
//Adding additional data, specifically edit mode
addFormSpecificData(editConfiguration, vreq);
return editConfiguration;
}
private void setEditKey(EditConfigurationVTwo editConfiguration, VitroRequest vreq) {
String editKey = EditConfigurationUtils.getEditKey(vreq);
editConfiguration.setEditKey(editKey);
}
protected void setTemplate(EditConfigurationVTwo editConfiguration,
VitroRequest vreq) {
editConfiguration.setTemplate(template);
}
//Initialize setup: process parameters
//There will be specialized parameters as well, we may include them here or in a
//separate method
private void initProcessParameters(VitroRequest vreq, HttpSession session, EditConfigurationVTwo editConfiguration) {
String formUrl = EditConfigurationUtils.getFormUrl(vreq);
subjectUri = EditConfigurationUtils.getSubjectUri(vreq);
predicateUri = EditConfigurationUtils.getPredicateUri(vreq);
editConfiguration.setFormUrl(formUrl);
editConfiguration.setUrlPatternToReturnTo("/individual");
editConfiguration.setVarNameForSubject("person");
editConfiguration.setSubjectUri(subjectUri);
editConfiguration.setEntityToReturnTo(subjectUri);
editConfiguration.setVarNameForPredicate("rolePredicate");
editConfiguration.setPredicateUri(predicateUri);
//by definition, this is an object property
this.initObjectParameters(vreq);
this.processObjectPropForm(vreq, editConfiguration);
}
private void initObjectParameters(VitroRequest vreq) {
//in case of object property
objectUri = EditConfigurationUtils.getObjectUri(vreq);
}
private void processObjectPropForm(VitroRequest vreq, EditConfigurationVTwo editConfiguration) {
editConfiguration.setVarNameForObject("role");
editConfiguration.setObject(objectUri);
//this needs to be set for the editing to be triggered properly, otherwise the 'prepare' method
//pretends this is a data property editing statement and throws an error
//TODO: Check if null in case no object uri exists but this is still an object property
if(objectUri != null) {
editConfiguration.setObjectResource(true);
}
}
/*
* N3 Required and Optional Generators as well as supporting methods
*/
private String getPrefixesString() {
//TODO: Include dynamic way of including this
return "@prefix core: http://vivoweb.org/ontology/core# .";
}
//TODO: Check if single string or multiple strings - check rdfslabel form etc. for prefix
//processing
private List<String> generateN3Required(VitroRequest vreq) {
List<String> n3ForEdit = new ArrayList<String>();
String editString = getPrefixesString() + " /n";
editString += "?person ?rolePredicate ?role .";
editString += "?role a <" + getRoleType(vreq) + "> .";
editString += "?role <" + getRoleToActivityPredicate(vreq) + "> ?roleActivity .";
editString += "?roleActivity <" + getActivityToRolePredicate(vreq) + "> ?role .";
n3ForEdit.add(editString);
return n3ForEdit;
}
private List<String> generateN3Optional() {
List<String> n3Optional = new ArrayList<String>();
//n3 for activity label
n3Optional.add(getN3ForActivityLabel());
//n3 for activity type
n3Optional.add(getN3ForActivityType());
//n3 for inverse
n3Optional.add("?role ?inverseRolePredicate ?person .");
//N3ForStart
n3Optional.addAll(getN3ForStart());
//N3 For End
n3Optional.addAll(getN3ForEnd());
//role label assertion
n3Optional.add(getN3RoleLabelAssertion());
return n3Optional;
}
public String getN3ForActivityLabel() {
return "?roleActivity <" + RDFS.label.getURI() + "> ?activityLabel .";
}
public String getN3ForActivityType() {
return "?roleActivity a ?roleActivityType .";
}
public String getN3RoleLabelAssertion() {
return "?role <" + RDFS.label.getURI() + "> ?roleLabel .";
}
//Method b/c used in two locations, n3 optional and n3 assertions
private List<String> getN3ForStart() {
List<String> n3ForStart = new ArrayList<String>();
n3ForStart.add("?role <" + getRoleToIntervalURI() + "> ?intervalNode ." +
"?intervalNode <" + RDF.type.getURI() + "> <" + getIntervalTypeURI() + "> ." +
"?intervalNode <" + getIntervalToStartURI() + "> ?startNode ." +
"?startNode <" + RDF.type.getURI() + "> <" + getDateTimeValueTypeURI() + "> ." +
"?startNode <" + getDateTimeValueURI() + "> ?startField-value ." +
"?startNode <" + getDateTimePrecisionURI() + "> ?startField-precision .");
return n3ForStart;
}
private List<String> getN3ForEnd() {
List<String> n3ForEnd = new ArrayList<String>();
n3ForEnd.add("?role <" + getRoleToIntervalURI() + "> ?intervalNode . " +
"?intervalNode <" + RDF.type.getURI() + "> <" + getIntervalTypeURI() + "> ." +
"?intervalNode <" + getIntervalToEndURI() + "> ?endNode ." +
"?endNode <" + RDF.type.getURI() + "> <" + getDateTimeValueTypeURI() + "> ." +
"?endNode <" + getDateTimeValueURI() + "> ?endField-value ." +
"?endNode <" + getDateTimePrecisionURI() + "> ?endField-precision .");
return n3ForEnd;
}
/*
* Get new resources
*/
private Map<String, String> generateNewResources(VitroRequest vreq) {
HashMap<String, String> newResources = new HashMap<String, String>();
//TODO: Get default namespace
String defaultNamespace = vreq.getWebappDaoFactory().getDefaultNamespace();
newResources.put("role", defaultNamespace + "individual");
newResources.put("roleActivity", defaultNamespace + "individual");
newResources.put("intervalNode", defaultNamespace + "individual");
newResources.put("startNode", defaultNamespace + "individual");
newResources.put("endNode", defaultNamespace + "individual");
return newResources;
}
/*
* Set URIS and Literals In Scope and on form and supporting methods
*/
private void setUrisAndLiteralsInScope(EditConfigurationVTwo editConfiguration, VitroRequest vreq) {
HashMap<String, List<String>> urisInScope = new HashMap<String, List<String>>();
//note that at this point the subject, predicate, and object var parameters have already been processed
//these two were always set when instantiating an edit configuration object from json,
//although the json itself did not specify subject/predicate as part of uris in scope
urisInScope.put(editConfiguration.getVarNameForSubject(),
Arrays.asList(new String[]{editConfiguration.getSubjectUri()}));
urisInScope.put(editConfiguration.getVarNameForPredicate(),
Arrays.asList(new String[]{editConfiguration.getPredicateUri()}));
//Setting inverse role predicate
urisInScope.put("inverseRolePredicate", getInversePredicate(vreq));
editConfiguration.setUrisInScope(urisInScope);
//Uris in scope include subject, predicate, and object var
//literals in scope empty initially, usually populated by code in prepare for update
//with existing values for variables
editConfiguration.setLiteralsInScope(new HashMap<String, List<Literal>>());
}
private List<String> getInversePredicate(VitroRequest vreq) {
List<String> inversePredicateArray = new ArrayList<String>();
ObjectProperty op = EditConfigurationUtils.getObjectProperty(vreq);
if(op != null && op.getURIInverse() != null) {
inversePredicateArray.add(op.getURIInverse());
}
return inversePredicateArray;
}
//n3 should look as follows
//?subject ?predicate ?objectVar
private void setUrisAndLiteralsOnForm(EditConfigurationVTwo editConfiguration, VitroRequest vreq) {
List<String> urisOnForm = new ArrayList<String>();
List<String> literalsOnForm = new ArrayList<String>();
//add role activity and roleActivityType to uris on form
urisOnForm.add("roleActivity");
urisOnForm.add("roleActivityType");
editConfiguration.setUrisOnform(urisOnForm);
//activity label and role label are literals on form
literalsOnForm.add("activityLabel");
literalsOnForm.add("roleLabel");
editConfiguration.setLiteralsOnForm(literalsOnForm);
}
/**
* Set SPARQL Queries and supporting methods
*/
private void setSparqlQueries(EditConfigurationVTwo editConfiguration, VitroRequest vreq) {
//Sparql queries defining retrieval of literals etc.
editConfiguration.setSparqlForAdditionalLiteralsInScope(new HashMap<String, String>());
Map<String, String> urisInScope = new HashMap<String, String>();
editConfiguration.setSparqlForAdditionalUrisInScope(urisInScope);
editConfiguration.setSparqlForExistingLiterals(generateSparqlForExistingLiterals(vreq));
editConfiguration.setSparqlForExistingUris(generateSparqlForExistingUris(vreq));
}
//Get page uri for object
private HashMap<String, String> generateSparqlForExistingUris(VitroRequest vreq) {
HashMap<String, String> map = new HashMap<String, String>();
//Queries for role activity, activity type query, interval node, start node, end node, start field precision, endfield precision
map.put("roleActivity", getRoleActivityQuery(vreq));
map.put("roleActivityType", getActivityTypeQuery(vreq));
map.put("intervalNode", getIntervalNodeQuery(vreq));
map.put("startNode", getStartNodeQuery(vreq));
map.put("endNode", getEndNodeQuery(vreq));
map.put("startField-precision", getStartPrecisionQuery(vreq));
map.put("endField-precision", getEndPrecisionQuery(vreq));
return map;
}
private String getEndPrecisionQuery(VitroRequest vreq) {
String query = "SELECT ?existingEndPrecision WHERE {" +
"?role <" + getRoleToIntervalURI() + "> ?intervalNode ." +
"?intervalNode <" + VitroVocabulary.RDF_TYPE + "> <" + getIntervalTypeURI() + "> ." +
"?intervalNode <" + getIntervalToEndURI() + "> ?endNode ." +
"?endNode <" + VitroVocabulary.RDF_TYPE + "> <" + getDateTimeValueTypeURI() + "> . " +
"?endNode <" + getDateTimePrecisionURI() + "> ?existingEndPrecision . }";
return query;
}
private String getStartPrecisionQuery(VitroRequest vreq) {
String query = "SELECT ?existingStartPrecision WHERE {" +
"?role <" + getRoleToIntervalURI() + "> ?intervalNode ." +
"?intervalNode <" + VitroVocabulary.RDF_TYPE + "> <" + getIntervalTypeURI() + "> ." +
"?intervalNode <" + getIntervalToStartURI() + "> ?startNode ." +
"?startNode <" + VitroVocabulary.RDF_TYPE + "> <" + getDateTimeValueTypeURI() + "> . " +
"?startNode <" + getDateTimePrecisionURI() + "> ?existingStartPrecision . }";
return query;
}
private String getEndNodeQuery(VitroRequest vreq) {
String query = "SELECT ?existingEndNode WHERE {"+
"?role <" + getRoleToIntervalURI() + "> ?intervalNode ."+
"?intervalNode <" + VitroVocabulary.RDF_TYPE + "> <" + getIntervalTypeURI() + "> ."+
" ?intervalNode <" + getIntervalToEndURI() + "> ?existingEndNode . "+
"?existingEndNode <" + VitroVocabulary.RDF_TYPE + "> <" + getDateTimeValueTypeURI() + "> .}";
return query;
}
private String getStartNodeQuery(VitroRequest vreq) {
String query = "SELECT ?existingStartNode WHERE {"+
"?role <" + getRoleToIntervalURI() + "> ?intervalNode ."+
"?intervalNode <" + VitroVocabulary.RDF_TYPE + "> <" + getIntervalTypeURI() + "> ."+
"?intervalNode <" + getIntervalToStartURI() + "> ?existingStartNode . "+
"?existingStartNode <" + VitroVocabulary.RDF_TYPE + "> <" + getDateTimeValueTypeURI() + "> .}";
return query;
}
private String getIntervalNodeQuery(VitroRequest vreq) {
String query = "SELECT ?existingIntervalNode WHERE { " +
"?role <" + getRoleToIntervalURI() + "> ?existingIntervalNode . " +
" ?existingIntervalNode <" + VitroVocabulary.RDF_TYPE + "> <" + getIntervalTypeURI() + "> . }";
return query;
}
/*
* The activity type query results must be limited to the values in the activity type select element.
* Sometimes the query returns a superclass such as owl:Thing instead.
* Make use of vitro:mostSpecificType so that, for example, an individual is both a
* core:InvitedTalk and a core:Presentation, core:InvitedTalk is selected.
* vitro:mostSpecificType alone may not suffice, since it does not guarantee that the value returned
* is in the select list.
* We could still have problems if the value from the select list is not a vitro:mostSpecificType,
* but that is unlikely.
*/
//This method had some code already setup in the jsp file
private String getActivityTypeQuery(VitroRequest vreq) {
String activityTypeQuery = null;
//roleActivityType_optionsType: This gets you whether this is a literal
//
RoleActivityOptionTypes optionsType = getRoleActivityTypeOptionsType(vreq);
// Note that this value is overloaded to specify either object class uri or classgroup uri
String objectClassUri = getRoleActivityTypeObjectClassUri(vreq);
if (StringUtils.isNotBlank(objectClassUri)) {
log.debug("objectClassUri = " + objectClassUri);
if (RoleActivityOptionTypes.VCLASSGROUP.equals(optionsType)) {
activityTypeQuery = getClassgroupActivityTypeQuery(vreq);
activityTypeQuery = QueryUtils.subUriForQueryVar(activityTypeQuery, "classgroup", objectClassUri);
} else if (RoleActivityOptionTypes.CHILD_VCLASSES.equals(optionsType)) {
activityTypeQuery = getSubclassActivityTypeQuery(vreq);
activityTypeQuery = QueryUtils.subUriForQueryVar(activityTypeQuery, "objectClassUri", objectClassUri);
} else {
activityTypeQuery = getDefaultActivityTypeQuery(vreq);
}
// Select options are hardcoded
} else if (RoleActivityOptionTypes.HARDCODED_LITERALS.equals(optionsType)) {
//literal options
HashMap<String, String> typeLiteralOptions = getRoleActivityTypeLiteralOptions(vreq);
if (typeLiteralOptions.size() > 0) {
try {
List<String> typeUris = new ArrayList<String>();
Set<String> optionUris = typeLiteralOptions.keySet();
for(String uri: optionUris) {
typeUris.add("(?existingActivityType = <" + uri + ">)");
}
String typeFilters = "FILTER (" + StringUtils.join(typeUris, "||") + ")";
String defaultActivityTypeQuery = getDefaultActivityTypeQuery(vreq);
activityTypeQuery = defaultActivityTypeQuery.replaceAll("}$", "") + typeFilters + "}";
} catch (Exception e) {
activityTypeQuery = getDefaultActivityTypeQuery(vreq);
}
} else {
activityTypeQuery = getDefaultActivityTypeQuery(vreq);
}
} else {
activityTypeQuery = getDefaultActivityTypeQuery(vreq);
}
String roleToActivityPredicate = getRoleToActivityPredicate(vreq);
activityTypeQuery = QueryUtils.subUriForQueryVar(activityTypeQuery, "predicate", roleToActivityPredicate);
log.debug("Activity type query: " + activityTypeQuery);
return activityTypeQuery;
}
private String getDefaultActivityTypeQuery(VitroRequest vreq) {
String query = "PREFIX core: <" + getVivoCoreNamespace() + ">\n" +
"PREFIX vitro: <" + VitroVocabulary.vitroURI + "> \n" +
"SELECT ?existingActivityType WHERE { \n" +
" ?role ?predicate ?existingActivity . \n" +
" ?existingActivity vitro:mostSpecificType ?existingActivityType . \n" +
"}";
return query;
}
private String getSubclassActivityTypeQuery(VitroRequest vreq) {
String query = "PREFIX core: <" + getVivoCoreNamespace() + ">\n" +
"PREFIX rdfs: <" + VitroVocabulary.RDFS + ">\n" +
"PREFIX vitro: <" + VitroVocabulary.vitroURI + "> \n" +
"SELECT ?existingActivityType WHERE {\n" +
" ?role ?predicate ?existingActivity . \n" +
" ?existingActivity vitro:mostSpecificType ?existingActivityType . \n" +
" ?existingActivityType rdfs:subClassOf ?objectClassUri . \n" +
"}";
return query;
}
private String getClassgroupActivityTypeQuery(VitroRequest vreq) {
String query = "PREFIX core: <" + getVivoCoreNamespace() + ">\n" +
"PREFIX vitro: <" + VitroVocabulary.vitroURI + "> \n" +
"SELECT ?existingActivityType WHERE { \n" +
" ?role ?predicate ?existingActivity . \n" +
" ?existingActivity vitro:mostSpecificType ?existingActivityType . \n" +
" ?existingActivityType vitro:inClassGroup ?classgroup . \n" +
"}";
return query;
}
private String getRoleActivityQuery(VitroRequest vreq) {
String query = "PREFIX core: <" + getVivoCoreNamespace() + ">" +
"SELECT ?existingActivity WHERE { ?role <" + getRoleToActivityPredicate(vreq) + "> ?existingActivity . }";
return query;
}
private HashMap<String, String> generateSparqlForExistingLiterals(VitroRequest vreq) {
HashMap<String, String> map = new HashMap<String, String>();
//Queries for activity label, role label, start Field value, end Field value
map.put("activityLabel", getActivityLabelQuery(vreq));
map.put("roleLabel", getRoleLabelQuery(vreq));
map.put("startField-value", getExistingStartDateQuery(vreq));
map.put("endField-value", getExistingEndDateQuery(vreq));
return map;
}
private String getExistingEndDateQuery(VitroRequest vreq) {
String query = " SELECT ?existingEndDate WHERE {\n" +
"?role <" + getRoleToIntervalURI() + "> ?intervalNode .\n" +
"?intervalNode <" + VitroVocabulary.RDF_TYPE + "> <" + getIntervalTypeURI() + "> .\n" +
"?intervalNode <" + getIntervalToEndURI() + "> ?endNode .\n" +
"?endNode <" + VitroVocabulary.RDF_TYPE + "> <" + getDateTimeValueTypeURI() + "> .\n" +
"?endNode <" + getDateTimeValueURI() + "> ?existingEndDate . }";
return query;
}
private String getExistingStartDateQuery(VitroRequest vreq) {
String query = "SELECT ?existingDateStart WHERE {\n" +
"?role <" + getRoleToIntervalURI() + "> ?intervalNode .\n" +
"?intervalNode <" + VitroVocabulary.RDF_TYPE + "> <" + getIntervalTypeURI() + "> .\n" +
"?intervalNode <" + getIntervalToStartURI() + "> ?startNode .\n" +
"?startNode <" + VitroVocabulary.RDF_TYPE + "> <" + getDateTimeValueTypeURI() + "> .\n" +
"?startNode <" + getDateTimeValueURI() + "> ?existingDateStart . }";
return query;
}
private String getRoleLabelQuery(VitroRequest vreq) {
String query = "SELECT ?existingRoleLabel WHERE { ?role <" + VitroVocabulary.LABEL + "> ?existingRoleLabel . }";
return query;
}
private String getActivityLabelQuery(VitroRequest vreq) {
String query = "PREFIX core: <" + getVivoCoreNamespace() + "> \n" +
"PREFIX rdfs: <" + RDFS.getURI() + "> \n" +
"SELECT ?existingTitle WHERE { \n" +
"?role <" + getRoleToActivityPredicate(vreq) + "> ?existingActivity . \n" +
"?existingActivity rdfs:label ?existingTitle . }";
return query;
}
/**
*
* Set Fields and supporting methods
*/
private void setFields(EditConfigurationVTwo editConfiguration, VitroRequest vreq, String predicateUri) {
Map<String, FieldVTwo> fields = new HashMap<String, FieldVTwo>();
//Multiple fields
getActivityLabelField(editConfiguration, vreq, fields);
getRoleActivityTypeField(editConfiguration, vreq, fields);
getRoleActivityField(editConfiguration, vreq, fields);
getRoleLabelField(editConfiguration, vreq, fields);
getStartField(editConfiguration, vreq, fields);
getEndField(editConfiguration, vreq, fields);
editConfiguration.setFields(fields);
}
//Label of "right side" of role, i.e. label for role roleIn Activity
private void getActivityLabelField(EditConfigurationVTwo editConfiguration,
VitroRequest vreq, Map<String, FieldVTwo> fields) {
String fieldName = "activityLabel";
//get range data type uri and range language
String stringDatatypeUri = XSD.xstring.toString();
FieldVTwo field = new FieldVTwo();
field.setName(fieldName);
field.setNewResource(false);
//queryForExisting is not being used anywhere in Field
List<String> validators = new ArrayList<String>();
//If add mode or repair, etc. need to add label required validator
if(isAddMode(vreq) || isRepairMode(vreq)) {
validators.add("nonempty");
}
validators.add("datatype:" + stringDatatypeUri);
field.setValidators(validators);
//subjectUri and subjectClassUri are not being used in Field
field.setOptionsType("UNDEFINED");
//why isn't predicate uri set for data properties?
field.setPredicateUri(null);
field.setObjectClassUri(null);
field.setRangeDatatypeUri(stringDatatypeUri);
field.setLiteralOptions(new ArrayList<List<String>>());
//set assertions
List<String> assertions = new ArrayList<String>();
assertions.add(getN3ForActivityLabel());
field.setAssertions(assertions);
fields.put(field.getName(), field);
}
//type of "right side" of role, i.e. type of activity from role roleIn activity
private void getRoleActivityTypeField(
EditConfigurationVTwo editConfiguration, VitroRequest vreq,
Map<String, FieldVTwo> fields) {
String fieldName = "roleActivityType";
//get range data type uri and range language
FieldVTwo field = new FieldVTwo();
field.setName(fieldName);
field.setNewResource(true);
//queryForExisting is not being used anywhere in Field
List<String> validators = new ArrayList<String>();
if(isAddMode(vreq) || isRepairMode(vreq)) {
validators.add("nonempty");
}
field.setValidators(validators);
//subjectUri and subjectClassUri are not being used in Field
//TODO: Check if this is correct
field.setOptionsType(getRoleActivityTypeOptionsType(vreq).toString());
//why isn't predicate uri set for data properties?
field.setPredicateUri(null);
field.setObjectClassUri(getRoleActivityTypeObjectClassUri(vreq));
field.setRangeDatatypeUri(null);
HashMap<String, String> literalOptionsMap = getRoleActivityTypeLiteralOptions(vreq);
List<List<String>> fieldLiteralOptions = new ArrayList<List<String>>();
Set<String> optionUris = literalOptionsMap.keySet();
for(String optionUri: optionUris) {
List<String> uriLabelArray = new ArrayList<String>();
uriLabelArray.add(optionUri);
uriLabelArray.add(literalOptionsMap.get(optionUri));
fieldLiteralOptions.add(uriLabelArray);
}
field.setLiteralOptions(fieldLiteralOptions);
//set assertions
List<String> assertions = new ArrayList<String>();
assertions.add(getN3ForActivityType());
field.setAssertions(assertions);
fields.put(field.getName(), field);
}
//Assuming URI for activity for role?
private void getRoleActivityField(EditConfigurationVTwo editConfiguration,
VitroRequest vreq, Map<String, FieldVTwo> fields) {
String fieldName = "roleActivity";
//get range data type uri and range language
FieldVTwo field = new FieldVTwo();
field.setName(fieldName);
field.setNewResource(true);
List<String> validators = new ArrayList<String>();
field.setValidators(validators);
//subjectUri and subjectClassUri are not being used in Field
field.setOptionsType("UNDEFINED");
//why isn't predicate uri set for data properties?
field.setPredicateUri(null);
field.setObjectClassUri(null);
field.setRangeDatatypeUri(null);
//empty
field.setLiteralOptions(new ArrayList<List<String>>());
//set assertions
List<String> assertions = new ArrayList<String>();
//N3ForRoleToActivity
String n3ForRoleToActivity = "@prefix core: <" + getVivoCoreNamespace() + "> ." +
"?role <" + getRoleToActivityPredicate(vreq) + "> ?roleActivity ." +
"?roleActivity <" + getActivityToRolePredicate(vreq) + "> ?role .";
assertions.add(n3ForRoleToActivity);
field.setAssertions(assertions);
fields.put(field.getName(), field);
}
private void getRoleLabelField(EditConfigurationVTwo editConfiguration,
VitroRequest vreq, Map<String, FieldVTwo> fields) {
String fieldName = "roleLabel";
String stringDatatypeUri = XSD.xstring.toString();
FieldVTwo field = new FieldVTwo();
field.setName(fieldName);
field.setNewResource(false);
List<String> validators = new ArrayList<String>();
validators.add("datatype:" + stringDatatypeUri);
if(isShowRoleLabelField(vreq)) {
validators.add("nonempty");
}
field.setValidators(validators);
//subjectUri and subjectClassUri are not being used in Field
field.setOptionsType("UNDEFINED");
//why isn't predicate uri set for data properties?
field.setPredicateUri(null);
field.setObjectClassUri(null);
field.setRangeDatatypeUri(stringDatatypeUri);
//empty
field.setLiteralOptions(new ArrayList<List<String>>());
//set assertions
List<String> assertions = new ArrayList<String>();
assertions.add(getN3RoleLabelAssertion());
field.setAssertions(assertions);
fields.put(field.getName(), field);
}
private void getStartField(EditConfigurationVTwo editConfiguration,
VitroRequest vreq, Map<String, FieldVTwo> fields) {
String fieldName = "startField";
FieldVTwo field = new FieldVTwo();
field.setName(fieldName);
field.setNewResource(false);
List<String> validators = new ArrayList<String>();
field.setValidators(validators);
//subjectUri and subjectClassUri are not being used in Field
field.setOptionsType("UNDEFINED");
//why isn't predicate uri set for data properties?
field.setPredicateUri(null);
field.setObjectClassUri(null);
field.setRangeDatatypeUri(null);
//empty
field.setLiteralOptions(new ArrayList<List<String>>());
//set assertions
List<String> assertions = new ArrayList<String>();
assertions.addAll(getN3ForStart());
field.setAssertions(assertions);
//This logic was originally after edit configuration object created from json in original jsp
field.setEditElement(
new DateTimeWithPrecisionVTwo(field,
VitroVocabulary.Precision.YEAR.uri(),
VitroVocabulary.Precision.NONE.uri()));
fields.put(field.getName(), field);
}
private void getEndField(EditConfigurationVTwo editConfiguration,
VitroRequest vreq, Map<String, FieldVTwo> fields) {
String fieldName = "endField";
FieldVTwo field = new FieldVTwo();
field.setName(fieldName);
field.setNewResource(false);
List<String> validators = new ArrayList<String>();
field.setValidators(validators);
//subjectUri and subjectClassUri are not being used in Field
field.setOptionsType("UNDEFINED");
//why isn't predicate uri set for data properties?
field.setPredicateUri(null);
field.setObjectClassUri(null);
field.setRangeDatatypeUri(null);
//empty
field.setLiteralOptions(new ArrayList<List<String>>());
//set assertions
List<String> assertions = new ArrayList<String>();
assertions.addAll(getN3ForEnd());
field.setAssertions(assertions);
//Set edit element
field.setEditElement(
new DateTimeWithPrecisionVTwo(field,
VitroVocabulary.Precision.YEAR.uri(),
VitroVocabulary.Precision.NONE.uri()));
fields.put(field.getName(), field);
}
/**
* Prepare edit configuration for update
* @param vreq
* @param session
* @param editConfiguration
*/
private void prepareForUpdate(VitroRequest vreq, HttpSession session, EditConfigurationVTwo editConfiguration) {
//Here, retrieve model from
Model model = (Model) session.getServletContext().getAttribute("jenaOntModel");
//Object property by definition
String objectUri = EditConfigurationUtils.getObjectUri(vreq);
if(objectUri != null) {
//update existing object
editConfiguration.prepareForObjPropUpdate(model);
} else {
//new object to be created
editConfiguration.prepareForNonUpdate( model );
}
}
/**
* Methods that are REQUIRED to be implemented in subclasses
**/
//role type will always be set based on particular form
abstract public String getRoleType(VitroRequest vreq);
//In the case of literal options, subclass generator will set the options to be returned
abstract protected HashMap<String, String> getRoleActivityTypeLiteralOptions(VitroRequest vreq);
//Each subclass generator will return its own type of option here:
//whether literal hardcoded, based on class group, or subclasses of a specific class
//The latter two will apparently lend some kind of uri to objectClassUri ?
abstract public RoleActivityOptionTypes getRoleActivityTypeOptionsType(VitroRequest vreq);
//This too will depend on the specific subclass of generator
abstract public String getRoleActivityTypeObjectClassUri(VitroRequest vreq);
/**
* Methods with default values that may be overwritten when required by a subclass
* Both Default value and method that can be overwritten are included below
**/
public boolean isShowRoleLabelField(VitroRequest vreq) {
return true;
}
public String getActivityToRolePredicate(VitroRequest vreq) {
return getDefaultActivityToRolePredicate();
}
//This has a default value, but note that even that will not be used
//in the update with realized in or contributes to
//Overridden when need be in subclassed generator
public String getRoleToActivityPredicate(VitroRequest vreq) {
return getDefaultRoleToActivityPredicate();
}
//Some values will have a default value
//activityToRolePredicate
public String getDefaultActivityToRolePredicate() {
return "http://vivoweb.org/ontology/core#relatedRole";
}
//roleToActivityPredicate
public String getDefaultRoleToActivityPredicate() {
return "http://vivoweb.org/ontology/core#roleIn";
}
/**
* Methods that check edit mode
*/
//Get edit mode
private EditMode getEditMode(VitroRequest vreq) {
String roleToActivityPredicate = getRoleToActivityPredicate(vreq);
EditMode mode = FrontEndEditingUtils.getEditMode(vreq, roleToActivityPredicate);
return mode;
//(mode == EditMode.ADD || mode == EditMode.REPAIR) ? "\"nonempty\"
}
private boolean isAddMode(VitroRequest vreq) {
EditMode mode = getEditMode(vreq);
return (mode == EditMode.ADD);
}
private boolean isEditMode(VitroRequest vreq) {
EditMode mode = getEditMode(vreq);
return (mode == EditMode.EDIT);
}
private boolean isRepairMode(VitroRequest vreq) {
EditMode mode = getEditMode(vreq);
return (mode == EditMode.REPAIR);
}
/**
* Methods to return URIS for various predicates
**/
public String getVivoCoreNamespace() {
return "http://vivoweb.org/ontology/core#";
}
public String getRoleToIntervalURI() {
return getVivoCoreNamespace() + "dateTimeInterval";
}
public String getIntervalTypeURI() {
return getVivoCoreNamespace() + "DateTimeInterval";
}
public String getIntervalToStartURI() {
return getVivoCoreNamespace() + "start";
}
public String getIntervalToEndURI() {
return getVivoCoreNamespace() + "end";
}
public String getStartYearPredURI() {
return getVivoCoreNamespace() + "startYear";
}
public String getEndYearPredURI() {
return getVivoCoreNamespace() + "endYear";
}
public String getDateTimeValueTypeURI() {
return getVivoCoreNamespace() + "DateTimeValue";
}
public String getDateTimePrecisionURI() {
return getVivoCoreNamespace() + "dateTimePrecision";
}
public String getDateTimeValueURI() {
return getVivoCoreNamespace() + "dateTime";
}
//Form specific data
public void addFormSpecificData(EditConfigurationVTwo editConfiguration, VitroRequest vreq) {
HashMap<String, Object> formSpecificData = new HashMap<String, Object>();
formSpecificData.put("editMode", getEditMode(vreq).name());
//Fields that will need select lists generated
//Store field names
List<String> objectSelect = new ArrayList<String>();
objectSelect.add("roleActivityType");
//TODO: Check if this is the proper way to do this?
formSpecificData.put("objectSelect", objectSelect);
//Put in the fact that we require field
editConfiguration.setFormSpecificData(formSpecificData);
}
}

View file

@ -141,7 +141,10 @@ public class EditRequestDispatchController extends FreemarkerHttpServlet {
editConfGeneratorName = DEFAULT_DELETE_FORM; editConfGeneratorName = DEFAULT_DELETE_FORM;
} }
// *** handle the case where the form is specified as a request parameter *** // *** handle the case where the form is specified as a request parameter ***
else if( predicateUri == null && ( formParam != null && !formParam.isEmpty()) ){ //TODO: Substitute the original line in again which checks for null predicate, currently overriding
//in order to test
//else if( predicateUri == null && ( formParam != null && !formParam.isEmpty()) ){
else if( formParam != null && !formParam.isEmpty() ){
//form parameter must be a fully qualified java class name of a EditConfigurationVTwoGenerator implementation. //form parameter must be a fully qualified java class name of a EditConfigurationVTwoGenerator implementation.
editConfGeneratorName = formParam; editConfGeneratorName = formParam;
} else if(isVitroLabel(predicateUri)) { //in case of data property } else if(isVitroLabel(predicateUri)) { //in case of data property
@ -212,7 +215,7 @@ public class EditRequestDispatchController extends FreemarkerHttpServlet {
String subjectUri = EditConfigurationUtils.getSubjectUri(vreq); String subjectUri = EditConfigurationUtils.getSubjectUri(vreq);
String predicateUri = EditConfigurationUtils.getPredicateUri(vreq); String predicateUri = EditConfigurationUtils.getPredicateUri(vreq);
String formParam = getFormParam(vreq); String formParam = getFormParam(vreq);
//if no form parameter, then predicate uri and subject uri must both be populated
if (formParam == null || "".equals(formParam)) { if (formParam == null || "".equals(formParam)) {
if ((predicateUri == null || predicateUri.trim().length() == 0)) { if ((predicateUri == null || predicateUri.trim().length() == 0)) {
return true; return true;
@ -225,7 +228,11 @@ public class EditRequestDispatchController extends FreemarkerHttpServlet {
//Check predicate - if not vitro label and neither data prop nor object prop return error //Check predicate - if not vitro label and neither data prop nor object prop return error
WebappDaoFactory wdf = vreq.getWebappDaoFactory(); WebappDaoFactory wdf = vreq.getWebappDaoFactory();
if(!EditConfigurationUtils.isObjectProperty(predicateUri, vreq) //TODO: Check if any error conditions are not met here
//At this point, if there is a form paramter, we don't require a predicate uri
if(formParam == null
&& predicateUri != null
&& !EditConfigurationUtils.isObjectProperty(predicateUri, vreq)
&& !isVitroLabel(predicateUri) && !isVitroLabel(predicateUri)
&& !EditConfigurationUtils.isDataProperty(predicateUri, vreq)) && !EditConfigurationUtils.isDataProperty(predicateUri, vreq))
{ {
@ -255,7 +262,7 @@ public class EditRequestDispatchController extends FreemarkerHttpServlet {
//should return null //should return null
private String getFormParam(VitroRequest vreq) { private String getFormParam(VitroRequest vreq) {
String formParam = (String) vreq.getAttribute("editForm"); String formParam = (String) vreq.getParameter("editForm");
return formParam; return formParam;
} }

View file

@ -7,9 +7,13 @@ import edu.cornell.mannlib.vitro.webapp.beans.DataPropertyStatement;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditConfigurationUtils; 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.EditConfigurationVTwo;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.SelectListGeneratorVTwo; import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.SelectListGeneratorVTwo;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.EditConfiguration; import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.FieldVTwo;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditElementVTwo;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.generators.DefaultObjectPropertyFormGenerator; import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.generators.DefaultObjectPropertyFormGenerator;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.utils.FrontEndEditingUtils;
import edu.cornell.mannlib.vitro.webapp.utils.FrontEndEditingUtils.EditMode;
import edu.cornell.mannlib.vitro.webapp.web.templatemodels.BaseTemplateModel; import edu.cornell.mannlib.vitro.webapp.web.templatemodels.BaseTemplateModel;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
@ -22,6 +26,7 @@ import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
import java.util.List; import java.util.List;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Set;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
@ -64,28 +69,56 @@ public class EditConfigurationTemplateModel extends BaseTemplateModel {
public String getSubmitToUrl(){ public String getSubmitToUrl(){
return getUrl( editConfig.getSubmitToUrl() ); return getUrl( editConfig.getSubmitToUrl() );
} }
//TODO: Check whether to include additoinal data here or elsewhere
//For now, using attributes off of vitro request to add to template /*
//TODO: find better mechanism * Used to calculate/retrieve/extract additional form-specific data
//Calculate data here * Such as options for a drop-down etc.
*/
private void retrieveEditData() { private void retrieveEditData() {
//Get vitro request attributes for //Get vitro request attributes for
setFormTitle(); setFormTitle();
setSubmitLabel(); setSubmitLabel();
//this should only be called if this is an object property form
//how would we do this? //Get the form specific data
HashMap<String, Object> formSpecificData = editConfig.getFormSpecificData();
pageData.putAll(formSpecificData);
populateDropdowns();
//populate html with edit element where appropriate
populateGeneratedHtml();
}
//Based on certain pre-set fields/variables, look for what
//drop-downs need to be populated
private void populateDropdowns() {
if(EditConfigurationUtils.isObjectProperty(editConfig.getPredicateUri(), vreq)) { if(EditConfigurationUtils.isObjectProperty(editConfig.getPredicateUri(), vreq)) {
setRangeOptions(); setRangeOptions();
} }
//range data type probably not set here but for edit configuration's field if(pageData.containsKey("objectSelect")) {
/* List<String> fieldNames = (List<String>)pageData.get("objectSelect");
if(EditConfigurationUtils.isDataProperty(editConfig.getPredicateUri(), vreq)) { for(String field:fieldNames) {
setRangeDatatype(); WebappDaoFactory wdf = vreq.getWebappDaoFactory();
}*/ Map<String,String> optionsMap = SelectListGeneratorVTwo.getOptions(editConfig, field , wdf);
pageData.put(field, optionsMap);
}
}
} }
//TODO: Check if this should return a list instead
//Also check if better manipulated/handled within the freemarker form itself
private String getSelectedValue(String field) {
String selectedValue = null;
Map<String, List<String>> urisInScope = editConfig.getUrisInScope();
if(urisInScope.containsKey(field)) {
List<String> values = urisInScope.get(field);
//Unsure how to deal with multi-select drop-downs
//TODO: Handle multiple select dropdowns
selectedValue = StringUtils.join(values, ",");
}
return selectedValue;
}
private boolean isRangeOptionsExist() { private boolean isRangeOptionsExist() {
boolean rangeOptionsExist = (pageData.get("rangeOptionsExist") != null && (Boolean) pageData.get("rangeOptionsExist") == true); boolean rangeOptionsExist = (pageData.get("rangeOptionsExist") != null && (Boolean) pageData.get("rangeOptionsExist") == true);
@ -189,9 +222,10 @@ public class EditConfigurationTemplateModel extends BaseTemplateModel {
ObjectProperty prop = EditConfigurationUtils.getObjectProperty(vreq); ObjectProperty prop = EditConfigurationUtils.getObjectProperty(vreq);
if( prop.getSelectFromExisting() ){ if( prop.getSelectFromExisting() ){
WebappDaoFactory wdf = vreq.getWebappDaoFactory(); WebappDaoFactory wdf = vreq.getWebappDaoFactory();
//TODO: Change this to varname for object from object property?
String fieldName = editConfig.getVarNameForObject();
Map<String,String> rangeOptions = SelectListGeneratorVTwo.getOptions(editConfig, "objectVar" , wdf); //TODO: Check if this still works?
Map<String,String> rangeOptions = SelectListGeneratorVTwo.getOptions(editConfig, fieldName , wdf);
if( rangeOptions != null && rangeOptions.size() > 0 ) { if( rangeOptions != null && rangeOptions.size() > 0 ) {
pageData.put("rangeOptionsExist", true); pageData.put("rangeOptionsExist", true);
pageData.put("rangeOptions", rangeOptions); pageData.put("rangeOptions", rangeOptions);
@ -243,6 +277,7 @@ public class EditConfigurationTemplateModel extends BaseTemplateModel {
return literalValues; return literalValues;
} }
//Check if possible to send in particular parameter //Check if possible to send in particular parameter
public String dataLiteralValueFor(String dataLiteralName) { public String dataLiteralValueFor(String dataLiteralName) {
List<String> literalValues = getLiteralStringValue(dataLiteralName); List<String> literalValues = getLiteralStringValue(dataLiteralName);
@ -567,4 +602,40 @@ public class EditConfigurationTemplateModel extends BaseTemplateModel {
return vitroNsProp; return vitroNsProp;
} }
//Additional data to be returned
public HashMap<String, Object> getPageData() {
return pageData;
}
//Literals in scope and uris in scope are the values
//that currently exist for any of the fields/values
//Get literals in scope returned as string values
public Map<String, List<String>> getExistingLiteralValues() {
return EditConfigurationUtils.getExistingLiteralValues(vreq, editConfig);
}
public Map<String, List<String>> getExistingUriValues() {
return editConfig.getUrisInScope();
}
//Get editElements with html
public void populateGeneratedHtml() {
Map<String, String> generatedHtml = new HashMap<String, String>();
Map<String, FieldVTwo> fieldMap = editConfig.getFields();
//Check if any of the fields have edit elements and should be generated
Set<String> keySet = fieldMap.keySet();
for(String key: keySet) {
FieldVTwo field = fieldMap.get(key);
EditElementVTwo editElement = field.getEditElement();
String fieldName = field.getName();
if(editElement != null) {
generatedHtml.put(fieldName, EditConfigurationUtils.generateHTMLForElement(vreq, fieldName, editConfig));
}
}
//Put in pageData
pageData.put("htmlForElements", generatedHtml);
}
} }

View file

@ -0,0 +1,7 @@
<#--Assign property-specific variables here-->
<#assign roleDescriptor = "clinical activity" />
<#assign typeSelectorLabel = "clinical activity type" />
<#--Can Also set buttonText for a given form->
<#--Each of the two stage forms will include the form below-->
<#include "addRoleToPersonTwoStage.ftl">

View file

@ -0,0 +1,192 @@
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
<#--Retrieve certain edit configuration information-->
<#assign editMode = editConfiguration.pageData.editMode />
<#assign literalValues = editConfiguration.existingLiteralValues />
<#assign uriValues = editConfiguration.existingUriValues />
<#assign htmlForElements = editConfiguration.pageData.htmlForElements />
Edit Mode is ${editMode}
<#--Freemarker variables with default values that can be overridden by specific forms-->
<#--buttonText, typeSelectorLabel, numDateFields, showRoleLabelField, roleExamples-->
<#if !buttonText?has_content>
<#assign buttonText = roleDescriptor />
</#if>
<#if !typeSelectorLabel?has_content>
<#assign typeSelectorLabel = roleDescriptor />
</#if>
<#if !numDateFields?has_content>
<#assign numDateFields = 2 />
</#if>
<#if !showRoleLabelField?has_content>
<#assign showRoleLabelField = true />
</#if>
<#if !roleExamples?has_content>
<#assign roleExamples = "" />
</#if>
<#--Setting values for titleVerb, submitButonText, and disabled Value-->
<#if editConfiguration.objectUri?has_content>
<#assign titleVerb = "Edit"/>
<#assign submitButtonText>Edit ${buttonText}</#assign>
<#if editMode = "repair">
<#assign disabledVal = ""/>
<#else>
<#assign disabledVal = "disabled"/>
</#if>
<#else>
<#assign titleVerb = "Create"/>
<#assign submitButtonText>${buttonText}</#assign>
<#assign disabledVal = ""/>
<#--The original jsp sets editMode to add, why?-->
</#if>
<#--Get existing value for specific data literals and uris-->
<#--Get selected activity type value if it exists, this is alternative to below-->
<#assign activityTypeValue = ""/>
<#if uriValues?keys?seq_contains("activityType") && uriValues.activityType?size > 0>
<#assign activityTypeValue = uriValues.activityType[0] />
</#if>
<#--Get activity label value-->
<#assign activityLabelValue = "" />
<#if literalValues?keys?seq_contains("activityLabel") && literalValues.activityLabel?size > 0>
<#assign activityLabelValue = literalValues.activityLabel[0] />
</#if>
<#--Get role label-->
<#assign roleLabel = "" />
<#if literalValues?keys?seq_contains("roleLabel") && literalValues.roleLabel?size > 0 >
<#assign roleLabel = literalValues.roleLabel[0] />
</#if>
ActivityLabel:${activityLabelValue}
Activity type: ${activityTypeValue}
<h2>${titleVerb}&nbsp;${roleDescriptor} entry for ${editConfiguration.subjectName}</h2>
<#--Display error messages if any-->
<#if errorNameFieldIsEmpty??>
<#assign errorMessage = "Enter a name for the ." />
</#if>
<#if errorRoleFieldIsEmpty??>
<#assign errorMessage = "Specify a role for this ." />
</#if>
<#if errorMessage?has_content>
<section id="error-alert" role="alert">
<img src="${urls.images}/iconAlert.png" width="24" height="24" alert="Error alert icon" />
<p>${errorMessage}</p>
</section>
</#if>
<section id="add${roleDescriptor?capitalize}RoleToPersonTwoStage" role="region">
<form id="add${roleDescriptor?capitalize}RoleToPersonTwoStage" class="customForm noIE67" action="${submitUrl}" role="add/edit grant role">
<p class="inline"><label for="typeSelector">${roleDescriptor?capitalize} Type <span class='requiredHint'> *</span></label>
<select id="typeSelector" name="roleActivityType"
<#if disabledVal?has_content>
disabled = ${disabledVal}
</#if>
>
<#assign roleActivityTypeSelect = editConfiguration.pageData.roleActivityType />
<#assign roleActivityTypeKeys = roleActivityTypeSelect?keys />
<#list roleActivityTypeKeys as key>
<option value="${key}"
<#if activityTypeValue?has_content
&& activityTypeValue = key>selected</#if>
>
${roleActivityTypeSelect[key]}
</option>
</#list>
</select>
</p>
<div class="fullViewOnly">
<p>
<label for="relatedIndLabel">${roleDescriptor?capitalize} Name <span class='requiredHint'> *</span></label>
<input class="acSelector" size="50" type="text" id="relatedIndLabel" name="activityLabel" value="${activityLabelValue}"
<#if disabledVal?has_content>
disabled=${disabledVal}
</#if>
/>
</p>
<#if editMode = "edit">
<input type="hidden" id="roleActivityType" name="roleActivityType" value/>
<input type="hidden" id="activityLabel" name="activityLabel"/>
</#if>
<div class="acSelection">
<p class="inline">
<label>Selected ${roleDescriptor?capitalize}:</label>
<span class="acSelectionInfo"></span>
<a href="/vivo/individual?uri=" class="verifyMatch">(Verify this match)</a>
</p>
<input class="acUriReceiver" type="hidden" id="roleActivityUri" name="roleActivity" value="" />
<!-- Field value populated by JavaScript -->
</div>
<#if showRoleLabelField = true>
<p><label for="roleLabel">Role in ### <span class='requiredHint'> *</span> ${roleExamples}</label>
<input size="50" type="text" id="roleLabel" name="roleLabel" value="${roleLabel}" />
</p>
</#if>
<#if numDateFields == 1 >
<#--Generated html is a map with key name mapping to html string-->
<#if htmlForElements?keys?seq_contains("startField")>
<label for="startField">Start Year <span class='hint'>(YYYY)</span></label>
${htmlForElements["startField"]}
</#if>
<#else>
<h4>Years of Participation in ${roleDescriptor?capitalize}</h4>
<#if htmlForElements?keys?seq_contains("startField")>
<label for="startField">Start Year <span class='hint'>(YYYY)</span></label>
${htmlForElements["startField"]}
</#if>
<#if htmlForElements?keys?seq_contains("endField")>
<label for="endField">End Year <span class='hint'>(YYYY)</span></label>
${htmlForElements["endField"]}
</#if>
</#if>
</div>
<input type="hidden" id="editKey" name="editKey" value="${editKey} />
<p class="submit">
<input type="submit" id="submit" value="submitButtonText"/><span class="or"> or <a class="cancel" href="${cancelUrl}">Cancel</a>
</p>
<p id="requiredLegend" class="requiredHint">* required fields</p>
</form>
<#--Specifying form-specific script and adding stylesheets and scripts-->
<script type="text/javascript">
var customFormData = {
acUrl: '${urls.base}/autocomplete?tokenize=true',
editMode: '${editMode}',
submitButtonTextType: 'compound',
defaultTypeName: 'activity' // used in repair mode, to generate button text and org name field label
};
</script>
${stylesheets.add('<link rel="stylesheet" href="${urls.base}/js/jquery-ui/css/smoothness/jquery-ui-1.8.9.custom.css" />')}
${stylesheets.add('<link rel="stylesheet" href="${urls.base}/edit/forms/css/customForm.css" />')}
${stylesheets.add('<link rel="stylesheet" href="${urls.base}/edit/forms/css/customFormWithAutocomplete.cs" />')}
${scripts.add('<script type="text/javascript" src="${urls.base}/js/jquery-ui/js/jquery-ui-1.8.9.custom.min.js"></script>')}
${scripts.add('<script type="text/javascript" src="${urls.base}/js/customFormUtils.js"></script>')}
${scripts.add('<script type="text/javascript" src="${urls.base}/edit/forms/js/customFormWithAutocomplete.js"></script>')}
</section>