diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/BasicSmokeTests.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/config/ConfigurationPropertiesSmokeTests.java similarity index 94% rename from webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/BasicSmokeTests.java rename to webapp/src/edu/cornell/mannlib/vitro/webapp/config/ConfigurationPropertiesSmokeTests.java index 3bb00239c..ecf362d41 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/BasicSmokeTests.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/config/ConfigurationPropertiesSmokeTests.java @@ -1,6 +1,6 @@ /* $This file is distributed under the terms of the license in /doc/license.txt$ */ -package edu.cornell.mannlib.vitro.webapp.servlet.setup; +package edu.cornell.mannlib.vitro.webapp.config; import java.io.File; import java.sql.Connection; @@ -12,10 +12,13 @@ import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; -import edu.cornell.mannlib.vitro.webapp.config.ConfigurationProperties; import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus; -public class BasicSmokeTests implements ServletContextListener { +/** + * Test that gets run at servlet context startup to check for the existence and + * validity of properties in the configuration. + */ +public class ConfigurationPropertiesSmokeTests implements ServletContextListener { private static final String PROPERTY_HOME_DIRECTORY = "vitro.home.directory"; private static final String PROPERTY_DB_URL = "VitroConnection.DataSource.url"; diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/jena/JenaIngestController.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/jena/JenaIngestController.java index c7eab56a5..7d2fb6434 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/jena/JenaIngestController.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/jena/JenaIngestController.java @@ -73,7 +73,7 @@ import edu.cornell.mannlib.vitro.webapp.dao.jena.VitroJenaModelMaker; import edu.cornell.mannlib.vitro.webapp.dao.jena.VitroJenaSDBModelMaker; import edu.cornell.mannlib.vitro.webapp.dao.jena.VitroJenaSpecialModelMaker; import edu.cornell.mannlib.vitro.webapp.dao.jena.event.EditEvent; -import edu.cornell.mannlib.vitro.webapp.servlet.setup.JenaDataSourceSetup; +import edu.cornell.mannlib.vitro.webapp.servlet.setup.WebappDaoSDBSetup; import edu.cornell.mannlib.vitro.webapp.utils.SparqlQueryUtils; import edu.cornell.mannlib.vitro.webapp.utils.jena.JenaIngestUtils; import edu.cornell.mannlib.vitro.webapp.utils.jena.JenaIngestUtils.MergeResult; @@ -942,7 +942,7 @@ public class JenaIngestController extends BaseEditController { log.debug("Connecting to DB at "+jdbcUrl); StoreDesc storeDesc = new StoreDesc(LayoutType.LayoutTripleNodesHash,dbTypeObj) ; ServletContext ctx = vreq.getSession().getServletContext(); - BasicDataSource bds = JenaDataSourceSetup.makeBasicDataSource( + BasicDataSource bds = WebappDaoSDBSetup.makeBasicDataSource( driver, jdbcUrl, username, password, ctx); try { VitroJenaSDBModelMaker vsmm = new VitroJenaSDBModelMaker(storeDesc, bds); diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/elements/DateTimeWithPrecision.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/elements/DateTimeWithPrecision.java deleted file mode 100644 index 7254e3c41..000000000 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/elements/DateTimeWithPrecision.java +++ /dev/null @@ -1,600 +0,0 @@ -/* $This file is distributed under the terms of the license in /doc/license.txt$ */ - -package edu.cornell.mannlib.vitro.webapp.edit.elements; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -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 DateTimeWithPrecision extends BaseEditElement { - - 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 DateTimeWithPrecision(Field field) { - super(field); - fieldName = field.getName(); - minimumPrecision = DEFAULT_MIN_PRECISION; - displayRequiredLevel = DEFAULT_DISPLAY_LEVEL; - } - - public DateTimeWithPrecision(Field 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 DateTimeWithPrecision(Field 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(DateTimeWithPrecision.class); - protected String TEMPLATE_NAME = "dateTimeWithPrecision.ftl"; - - @Override - public String draw(String fieldName, EditConfiguration editConfig, - EditSubmission editSub, Configuration fmConfig) { - Map map = getMapForTemplate( editConfig, editSub); - return merge( fmConfig, TEMPLATE_NAME, map); - } - - /** - * This produces a map for use in the template. - */ - protected Map getMapForTemplate(EditConfiguration editConfig, EditSubmission editSub) { - Mapmap = new HashMap(); - - //always need the fieldName, required precision, and constants - map.put("fieldName", fieldName); - addPrecisionConstants(map); - map.put("minimumPrecision", minimumPrecision.uri()); - map.put("requiredLevel", displayRequiredLevel.uri()); - - 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 map){ - Map constants = new HashMap(); - 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(EditConfiguration editConfig, EditSubmission editSub) { - if( editSub != null ){ - String submittedPrecisionURI = editSub.getUrisFromForm().get( getPrecisionVariableName() ); - if( submittedPrecisionURI != null ){ - return submittedPrecisionURI; - } - } - - String existingPrecisionURI = editConfig.getUrisInScope().get( getPrecisionVariableName() ); - if( existingPrecisionURI != null ){ - return existingPrecisionURI; - }else{ - return null; - } - } - - private DateTime getTimeValue(EditConfiguration editConfig, EditSubmission editSub) { - if( editSub != null ){ - Literal submittedValue = editSub.getLiteralsFromForm().get( getValueVariableName() ); - if( submittedValue != null ) - return new DateTime( submittedValue.getLexicalForm() ); - } - - Literal dtValue = editConfig.getLiteralsInScope().get( getValueVariableName() ); - if( dtValue != null ){ - return new DateTime( dtValue.getLexicalForm() ); - }else{ - 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 getLiterals(String fieldName, - EditConfiguration editConfig, Map queryParameters) { - Map literalMap = new HashMap(); - - Literal datetime =getDateTime( queryParameters); - literalMap.put(fieldName+"-value", datetime); - - return literalMap; - } - - protected Literal getDateTime( Map 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 getURIs(String fieldName, - EditConfiguration editConfig, Map 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 uriMap = new HashMap(); - if( precisionUri != null ) - uriMap.put(fieldName+"-precision", precisionUri); - 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 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 getValidationMessages(String fieldName, - EditConfiguration editConfig, Map queryParameters) { - Map errorMsgMap = new HashMap(); - - //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 checkDate( String precisionURI, Map qp){ - if( precisionURI == null ) - return Collections.emptyMap(); - - Map errors = new HashMap(); - - 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, MapqueryParameters, 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 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 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 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" ; } -} - - diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/DateTimeIntervalValidationVTwo.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/DateTimeIntervalValidationVTwo.java index 98c162f9c..aa3ca0ed6 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/DateTimeIntervalValidationVTwo.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/DateTimeIntervalValidationVTwo.java @@ -4,8 +4,8 @@ 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 java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -15,9 +15,6 @@ 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. @@ -133,7 +130,7 @@ public class DateTimeIntervalValidationVTwo implements N3ValidatorVTwo { //Currently checks first precision str and then returns response if(precisionStr.size() > 0) { String precisionString = precisionStr.get(0); - VitroVocabulary.Precision precision = DateTimeWithPrecision.toPrecision( precisionString ); + VitroVocabulary.Precision precision = DateTimeWithPrecisionVTwo.toPrecision( precisionString ); if( precision == null ) log.debug("cannot convert " + precisionStr + " to a precision"); else diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/validators/DateTimeIntervalValidation.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/validators/DateTimeIntervalValidation.java deleted file mode 100644 index 3954a6356..000000000 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/validators/DateTimeIntervalValidation.java +++ /dev/null @@ -1,154 +0,0 @@ -/* $This file is distributed under the terms of the license in /doc/license.txt$ */ - -package edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.validators; - -import java.util.Calendar; -import java.util.HashMap; -import java.util.Map; - -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; - -public class DateTimeIntervalValidation implements N3Validator { - private static Log log = LogFactory.getLog(DateTimeIntervalValidation.class); - - private String startFieldName; - private String endFieldName; - - private String startValueName; - private String endValueName; - - private String startPrecisionName; - private String endPrecisionName; - - public DateTimeIntervalValidation(String startFieldName, String endFieldName){ - this.startFieldName = startFieldName; - this.endFieldName = endFieldName; - startValueName = startFieldName + "-value"; - endValueName = endFieldName + "-value"; - startPrecisionName = startFieldName + "-precision"; - endPrecisionName = endFieldName + "-precision"; - } - - public Map validate(EditConfiguration editConfig, - EditSubmission editSub) { - Map existingLiterals = editConfig.getLiteralsInScope(); - Literal existingStartYear = existingLiterals.get(startValueName); - Literal existingEndYear = existingLiterals.get(endValueName); - - Map literalsFromForm = editSub.getLiteralsFromForm(); - Literal formStartYear = literalsFromForm.get(startValueName); - Literal formEndYear = literalsFromForm.get(endValueName); - - VitroVocabulary.Precision startPrecision = getPrecision(startPrecisionName, editConfig, editSub); - VitroVocabulary.Precision endPrecision = getPrecision(endPrecisionName, editConfig, editSub); - - Map errors = new HashMap(); - - // 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; -// } - - if (formStartYear != null && formEndYear != null) { - errors.putAll(checkDateLiterals(formStartYear, formEndYear, startPrecision, endPrecision)); - } else if (formStartYear != null && existingEndYear != null) { - errors.putAll(checkDateLiterals(formStartYear, existingEndYear, startPrecision, endPrecision)); - } else if (existingStartYear != null && formEndYear != null) { - errors.putAll(checkDateLiterals(existingStartYear, formEndYear, startPrecision, endPrecision)); - } else if (existingStartYear != null && existingEndYear != null) { - errors.putAll(checkDateLiterals(existingStartYear, existingEndYear, startPrecision, endPrecision)); - } - - if (errors.size() != 0) - return errors; - else - return null; - } - - private Precision getPrecision(String precisionVarName, - EditConfiguration editConfig, EditSubmission editSub) { - if( editSub != null - && editSub.getUrisFromForm() != null - && editSub.getUrisFromForm().containsKey(precisionVarName)){ - String precisionStr = editSub.getUrisFromForm().get(precisionVarName); - VitroVocabulary.Precision precision = DateTimeWithPrecision.toPrecision( precisionStr ); - if( precision == null ) - log.warn("cannot convert " + precisionStr + " to a precision"); - else - return precision; - }else if( editConfig != null - && editConfig.getUrisInScope() != null - && editConfig.getUrisInScope().containsKey(precisionVarName)){ - String precisionStr = editConfig.getUrisInScope().get(precisionVarName); - VitroVocabulary.Precision precision = DateTimeWithPrecision.toPrecision( precisionStr ); - if( precision == null ) - log.warn("cannot convert " + precisionStr + " to a precision"); - else - return precision; - } - //this is what is returned if a precision was not found in the config or submission - return null; - } - - private Map checkDateLiterals( - Literal startLit, Literal endLit, - VitroVocabulary.Precision startPrecision, VitroVocabulary.Precision endPrecision) { - Map errors = new HashMap(); - - 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 checkYears( - Calendar startCal, Calendar endCal) { - - Map errors = new HashMap(); - - 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; - } -} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/ApplicationModelSetup.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/ApplicationModelSetup.java new file mode 100644 index 000000000..9f81e8c2d --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/ApplicationModelSetup.java @@ -0,0 +1,251 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ +package edu.cornell.mannlib.vitro.webapp.servlet.setup; + +import static edu.cornell.mannlib.vitro.webapp.dao.DisplayVocabulary.DISPLAY_ONT_MODEL; + +import java.io.File; +import java.io.FileOutputStream; + +import javax.servlet.ServletContext; +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; + +import org.apache.commons.dbcp.BasicDataSource; +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.ontology.OntDocumentManager; +import com.hp.hpl.jena.ontology.OntModel; +import com.hp.hpl.jena.query.Query; +import com.hp.hpl.jena.query.QueryExecution; +import com.hp.hpl.jena.query.QueryExecutionFactory; +import com.hp.hpl.jena.query.QueryFactory; +import com.hp.hpl.jena.rdf.model.Model; +import com.hp.hpl.jena.rdf.model.ModelFactory; + +import edu.cornell.mannlib.vitro.webapp.dao.jena.ModelSynchronizer; +import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus; + +/** + * Setups the Application Configuration TBox and ABox. This is sometimes + * called the display model. + * + * @author bdc34 + */ + +public class ApplicationModelSetup extends JenaDataSourceSetupBase +implements ServletContextListener { + + private static final Log log = LogFactory.getLog( + ApplicationModelSetup.class.getName()); + + /** + * Setup the application configuration model. It is frequently called the + * display model. If this is a new DB, populate the display model with the + * initial data. + * + * Also load any files that get loaded to the display model at each tomcat + * startup. + * + * Also, at each start of tomcat, load The display TBox and the + * display/display model. + */ + private void setupDisplayModel(BasicDataSource bds, ServletContext ctx, + StartupStatus ss) { + + // display, editing and navigation Model + try { + Model displayDbModel = makeDBModel(bds, + JENA_DISPLAY_METADATA_MODEL, DB_ONT_MODEL_SPEC, ctx); + if (displayDbModel.size() == 0) { + readOntologyFilesInPathSet(APPPATH, ctx,displayDbModel); + } + OntModel displayModel = ModelFactory.createOntologyModel(MEM_ONT_MODEL_SPEC); + displayModel.add(displayDbModel); + displayModel.getBaseModel().register(new ModelSynchronizer(displayDbModel)); + ctx.setAttribute(DISPLAY_ONT_MODEL, displayModel); + + //at each startup load all RDF files from directory to sub-models of display model + initializeDisplayLoadedAtStartup(ctx, displayModel); + } catch (Throwable t) { + log.error("Unable to load user application configuration model", t); + ss.fatal(this, "Unable to load user application configuration model", t); + } + + //display tbox - currently reading in every time + try { + Model displayTboxModel = makeDBModel(bds, + JENA_DISPLAY_TBOX_MODEL, DB_ONT_MODEL_SPEC, ctx); + + //Reading in single file every time, needs to be cleared/removed every time + readOntologyFileFromPath(APPPATH_LOAD + "displayTBOX.n3", displayTboxModel, ctx); + OntModel appTBOXModel = ModelFactory.createOntologyModel( + MEM_ONT_MODEL_SPEC); + appTBOXModel.add(displayTboxModel); + appTBOXModel.getBaseModel().register(new ModelSynchronizer(displayTboxModel)); + ctx.setAttribute("displayOntModelTBOX", appTBOXModel); + log.debug("Loaded file " + APPPATH_LOAD + "displayTBOX.n3 into display tbox model"); + } catch (Throwable t) { + log.error("Unable to load user application configuration model TBOX", t); + ss.fatal(this, "Unable to load user application configuration model TBOX", t); + } + + //Display Display model, currently empty, create if doesn't exist but no files to load + try { + Model displayDisplayModel = makeDBModel(bds, + JENA_DISPLAY_DISPLAY_MODEL, DB_ONT_MODEL_SPEC, ctx); + + //Reading in single file every time, needs to be cleared/removed every + readOntologyFileFromPath(APPPATH_LOAD + "displayDisplay.n3", displayDisplayModel, ctx); + OntModel appDisplayDisplayModel = ModelFactory.createOntologyModel( + MEM_ONT_MODEL_SPEC); + appDisplayDisplayModel.add(displayDisplayModel); + appDisplayDisplayModel.getBaseModel().register(new ModelSynchronizer(displayDisplayModel)); + ctx.setAttribute("displayOntModelDisplayModel", appDisplayDisplayModel); + log.debug("Loaded file " + APPPATH_LOAD + "displayDisplay.n3 into display display model"); + } catch (Throwable t) { + log.error("Unable to load user application configuration model Display Model", t); + ss.fatal(this, "Unable to load user application configuration model Display Model", t); + } + } + + /** + * Load the RDF found in the directory DISPLAY_MODEL_LOAD_AT_STARTUP_DIR + * a sub-models of displayModel. The RDF from thes files will not be saved + * in the database and it will be reloaded each time the system starts up. + */ + private void initializeDisplayLoadedAtStartup(ServletContext ctx, OntModel displayModel){ + log.info("loading display model from files in " + ctx.getRealPath(DISPLAY_MODEL_LOAD_AT_STARTUP_DIR) ); + Model displayLoadAtStartup = readInDisplayModelLoadAtStartup(ctx); + + if( log.isDebugEnabled() ){ + log.debug("loaded display model from files in " + ctx.getRealPath(DISPLAY_MODEL_LOAD_AT_STARTUP_DIR) ); + displayLoadAtStartup.write(System.out, "N3-PP"); + } + + checkForOldListViews(ctx,displayModel,displayLoadAtStartup); + displayModel.addSubModel( displayLoadAtStartup ); + } + + protected Model readInDisplayModelLoadAtStartup( ServletContext ctx ){ + return getModelFromDir( new File( ctx.getRealPath( DISPLAY_MODEL_LOAD_AT_STARTUP_DIR ))); + } + + /** + * All of the list views should now reside in files in DISPLAY_MODEL_LOAD_AT_STARTUP_DIR. + * This will check for custom list view annotation statements in the displayModel, check + * if they exist in the files in DISPLAY_MODEL_LOAD_AT_STARTUP_DIR, and write any that don't + * exist there to a file in DISPLAY_MODEL_LOAD_AT_STARTUP_DIR. After that the statements + * will be removed from the displayDBModel. + * + * returns true if there were old list view statements in the DB, returns false + * if there were none. displayLoadAlways should be reloaded from the file system + * if this returns true as this method may have changed the files. + * + * displayLoadAtStartup and displayModel may be modified. + */ + private void checkForOldListViews( ServletContext ctx, OntModel displayModel, Model displayLoadAtStartup){ + // run construct for old custom list view statements from displayModel + Model oldListViewModel = getOldListViewStatements( displayModel ); + if( log.isDebugEnabled() ){ + log.debug("Printing the old list view statements from the display model to System.out."); + oldListViewModel.write(System.out,"N3-PP"); + } + + // find statements in old stmts that are not in loadedAtStartup and + // save them in a new file in DISPLAY_MODEL_LOAD_AT_STARTUP_DIR + // so that in the future they will be in loadedAtStartup + Model stmtsInOldAndFiles = displayLoadAtStartup.intersection( displayModel ); + Model unhandledOldListViewStmts = oldListViewModel.difference( stmtsInOldAndFiles ); + + boolean saved = false; + boolean neededSave = false; + + if( unhandledOldListViewStmts != null && !unhandledOldListViewStmts.isEmpty() ){ + log.debug("need to deal with old list view statements from the display model"); + neededSave = true; + try{ + //create a file for the old statements in the loadAtStartup directory + String newFileName = ctx.getRealPath( + DISPLAY_MODEL_LOAD_AT_STARTUP_DIR + File.separator + + new DateTime().toString(ISODateTimeFormat.basicDateTime()) + ".n3" ); + File file = new File( newFileName ); + file.createNewFile(); + + log.info("Relocating " + unhandledOldListViewStmts.size() + " custom list view statements from DB and saving to " + + file.getAbsolutePath()+ File.separator + file.getName() + + ". These will be loaded from this file when the system starts up."); + + FileOutputStream fileOut = new FileOutputStream(file); + unhandledOldListViewStmts.write(fileOut, "N3-PP"); + fileOut.close(); + saved = true; + }catch(Throwable th){ + log.warn("Could not save old list view statements. Leaving them in the DB",th); + } + + //need to reload displayLoadAlways because DISPLAY_MODEL_LOAD_AT_STARTUP_DIR may have changed + displayLoadAtStartup.removeAll().add(readInDisplayModelLoadAtStartup(ctx)); + } + + + if( oldListViewModel != null && ! oldListViewModel.isEmpty() ){ + //At this point, there are old list view statements in the DB but they + //should are all redundant with ones in DISPLAY_MODEL_LOAD_AT_STARTUP_DIR + if( (neededSave && saved) || (!neededSave) ){ + //if there was nothing to save, just remove the old stuff + //if there was stuff to save, only remove if it was saved. + log.debug("removing old statements from displayModel"); + displayModel.remove(oldListViewModel); + } + } + + } + + private Model getOldListViewStatements(OntModel displayModel) { + //run a construct on displayModel to get all list view statements + Query query = QueryFactory.create ( listViewQuery ); + QueryExecution qexec = QueryExecutionFactory.create(query, displayModel) ; + Model oldModel = null; + + try { + oldModel = qexec.execConstruct(); + } catch( Throwable th ){ + log.error("could not check for old custom list views, query exception",th); + }finally { + qexec.close() ; + } + + if( oldModel != null) + return oldModel; + else + return ModelFactory.createDefaultModel(); + } + + private static final String listViewQuery = "" + + "PREFIX d: \n" + + "CONSTRUCT { \n" + + " ?a d:listViewConfigFile ?b . \n" + + "} WHERE {\n" + + " ?a d:listViewConfigFile ?b . \n" + + "} "; + + @Override + public void contextDestroyed(ServletContextEvent arg0) { + // does nothing. + } + + @Override + public void contextInitialized(ServletContextEvent sce) { + ServletContext ctx = sce.getServletContext(); + StartupStatus ss = StartupStatus.getBean(ctx); + BasicDataSource bds = getApplicationDataSource(ctx); + + setupDisplayModel(bds, ctx, ss); + } + + + +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/JenaDataSourceSetup.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/JenaDataSourceSetup.java deleted file mode 100644 index e89770f1e..000000000 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/JenaDataSourceSetup.java +++ /dev/null @@ -1,674 +0,0 @@ -/* $This file is distributed under the terms of the license in /doc/license.txt$ */ - -package edu.cornell.mannlib.vitro.webapp.servlet.setup; - -import static edu.cornell.mannlib.vitro.webapp.dao.DisplayVocabulary.DISPLAY_ONT_MODEL; - -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.List; - -import javax.servlet.ServletContext; -import javax.servlet.ServletContextEvent; - -import org.apache.commons.dbcp.BasicDataSource; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import com.hp.hpl.jena.ontology.OntModel; -import com.hp.hpl.jena.ontology.OntModelSpec; -import com.hp.hpl.jena.query.Query; -import com.hp.hpl.jena.query.QueryExecution; -import com.hp.hpl.jena.query.QueryExecutionFactory; -import com.hp.hpl.jena.query.QueryFactory; -import com.hp.hpl.jena.query.Syntax; -import com.hp.hpl.jena.rdf.model.Model; -import com.hp.hpl.jena.rdf.model.ModelFactory; -import com.hp.hpl.jena.rdf.model.ResIterator; -import com.hp.hpl.jena.rdf.model.Resource; -import com.hp.hpl.jena.rdf.model.ResourceFactory; -import com.hp.hpl.jena.rdf.model.Statement; -import com.hp.hpl.jena.rdf.model.StmtIterator; -import com.hp.hpl.jena.sdb.SDB; -import com.hp.hpl.jena.sdb.SDBFactory; -import com.hp.hpl.jena.sdb.Store; -import com.hp.hpl.jena.sdb.StoreDesc; -import com.hp.hpl.jena.sdb.sql.SDBConnection; -import com.hp.hpl.jena.sdb.store.DatabaseType; -import com.hp.hpl.jena.sdb.store.LayoutType; -import com.hp.hpl.jena.sdb.util.StoreUtils; -import com.hp.hpl.jena.shared.Lock; -import com.hp.hpl.jena.util.ResourceUtils; -import com.hp.hpl.jena.util.iterator.ClosableIterator; -import com.hp.hpl.jena.vocabulary.RDF; - -import edu.cornell.mannlib.vitro.webapp.config.ConfigurationProperties; -import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary; -import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory; -import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactoryConfig; -import edu.cornell.mannlib.vitro.webapp.dao.jena.JenaModelUtils; -import edu.cornell.mannlib.vitro.webapp.dao.jena.ModelContext; -import edu.cornell.mannlib.vitro.webapp.dao.jena.ModelSynchronizer; -import edu.cornell.mannlib.vitro.webapp.dao.jena.OntModelSelector; -import edu.cornell.mannlib.vitro.webapp.dao.jena.OntModelSelectorImpl; -import edu.cornell.mannlib.vitro.webapp.dao.jena.VitroJenaModelMaker; -import edu.cornell.mannlib.vitro.webapp.dao.jena.VitroJenaSDBModelMaker; -import edu.cornell.mannlib.vitro.webapp.dao.jena.VitroModelSource; -import edu.cornell.mannlib.vitro.webapp.dao.jena.WebappDaoFactorySDB; -import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus; -import edu.cornell.mannlib.vitro.webapp.utils.jena.InitialJenaModelUtils; - -public class JenaDataSourceSetup extends JenaDataSourceSetupBase - implements javax.servlet.ServletContextListener { - - private static final Log log = LogFactory.getLog(JenaDataSourceSetup.class); - - @Override - public void contextInitialized(ServletContextEvent sce) { - ServletContext ctx = sce.getServletContext(); - StartupStatus ss = StartupStatus.getBean(ctx); - - try { - long startTime = System.currentTimeMillis(); - setUpJenaDataSource(ctx); - log.info((System.currentTimeMillis() - startTime) / 1000 + - " seconds to set up SDB store"); - } catch (SQLException sqle) { - // SQL exceptions are fatal and should halt startup - log.error("Error using SQL database; startup aborted.", sqle); - ss.fatal(this, "Error using SQL database; startup aborted.", sqle); - } catch (Throwable t) { - log.error("Throwable in " + this.getClass().getName(), t); - ss.fatal(this, "Throwable in " + this.getClass().getName(), t); - } - - } - - private void setUpJenaDataSource(ServletContext ctx) throws SQLException { - - OntModelSelectorImpl baseOms = new OntModelSelectorImpl(); - OntModelSelectorImpl inferenceOms = new OntModelSelectorImpl(); - OntModelSelectorImpl unionOms = new OntModelSelectorImpl(); - - OntModel userAccountsModel = ontModelFromContextAttribute( - ctx, "userAccountsOntModel"); - baseOms.setUserAccountsModel(userAccountsModel); - inferenceOms.setUserAccountsModel(userAccountsModel); - unionOms.setUserAccountsModel(userAccountsModel); - - OntModel displayModel = ontModelFromContextAttribute( - ctx,DISPLAY_ONT_MODEL); - baseOms.setDisplayModel(displayModel); - inferenceOms.setDisplayModel(displayModel); - unionOms.setDisplayModel(displayModel); - - // SDB setup - - // union default graph - SDB.getContext().set(SDB.unionDefaultGraph, true) ; - - StoreDesc storeDesc = makeStoreDesc(ctx); - setApplicationStoreDesc(storeDesc, ctx); - - BasicDataSource bds = getApplicationDataSource(ctx); - if (bds == null) { - bds = makeDataSourceFromConfigurationProperties(ctx); - setApplicationDataSource(bds, ctx); - } - - Store store = connectStore(bds, storeDesc); - setApplicationStore(store, ctx); - - if (!isSetUp(store)) { - log.info("Initializing SDB store"); - if (isFirstStartup()) { - setupSDB(ctx, store); - } else { - migrateToSDBFromExistingRDBStore(ctx, store); - } - } - - // The code below, which sets up the OntModelSelectors, controls whether - // each model is maintained in memory, in the DB, or both while the - // application is running. - - // Populate the three OntModelSelectors (BaseOntModel = assertions, - // InferenceOntModel = inferences and JenaOntModel = union of assertions - // and inferences) with the post-SDB-conversion models. - - // ABox assertions - Model aboxAssertions = makeDBModel( - bds, JenaDataSourceSetupBase.JENA_DB_MODEL, DB_ONT_MODEL_SPEC, - TripleStoreType.SDB, ctx); - Model listenableAboxAssertions = ModelFactory.createUnion( - aboxAssertions, ModelFactory.createDefaultModel()); - baseOms.setABoxModel( - ModelFactory.createOntologyModel( - OntModelSpec.OWL_MEM, listenableAboxAssertions)); - - // ABox inferences - Model aboxInferences = makeDBModel( - bds, JenaDataSourceSetupBase.JENA_INF_MODEL, DB_ONT_MODEL_SPEC, - TripleStoreType.SDB, ctx); - Model listenableAboxInferences = ModelFactory.createUnion( - aboxInferences, ModelFactory.createDefaultModel()); - inferenceOms.setABoxModel(ModelFactory.createOntologyModel( - OntModelSpec.OWL_MEM, listenableAboxInferences)); - - - // Since the TBox models are in memory, they do not have timeout issues - // like the like the ABox models do (and so don't need the extra step - // to make them listenable.) - - // TBox assertions - try { - Model tboxAssertionsDB = makeDBModel( - bds, JENA_TBOX_ASSERTIONS_MODEL, DB_ONT_MODEL_SPEC, - TripleStoreType.SDB, ctx); - OntModel tboxAssertions = ModelFactory.createOntologyModel( - MEM_ONT_MODEL_SPEC); - - if (tboxAssertionsDB != null) { - long startTime = System.currentTimeMillis(); - System.out.println( - "Copying cached tbox assertions into memory"); - tboxAssertions.add(tboxAssertionsDB); - System.out.println((System.currentTimeMillis() - startTime) - / 1000 + " seconds to load tbox assertions"); - } - - tboxAssertions.getBaseModel().register(new ModelSynchronizer( - tboxAssertionsDB)); - baseOms.setTBoxModel(tboxAssertions); - } catch (Throwable e) { - log.error("Unable to load tbox assertion cache from DB", e); - } - - // TBox inferences - try { - Model tboxInferencesDB = makeDBModel( - bds, JENA_TBOX_INF_MODEL, DB_ONT_MODEL_SPEC, - TripleStoreType.SDB, ctx); - OntModel tboxInferences = ModelFactory.createOntologyModel( - MEM_ONT_MODEL_SPEC); - - if (tboxInferencesDB != null) { - long startTime = System.currentTimeMillis(); - System.out.println( - "Copying cached tbox inferences into memory"); - tboxInferences.add(tboxInferencesDB); - System.out.println((System.currentTimeMillis() - startTime) - / 1000 + " seconds to load tbox inferences"); - } - - tboxInferences.getBaseModel().register(new ModelSynchronizer( - tboxInferencesDB)); - inferenceOms.setTBoxModel(tboxInferences); - } catch (Throwable e) { - log.error("Unable to load tbox inference cache from DB", e); - } - - // union ABox - OntModel unionABoxModel = ModelFactory.createOntologyModel( - MEM_ONT_MODEL_SPEC,ModelFactory.createUnion( - baseOms.getABoxModel(), inferenceOms.getABoxModel())); - unionOms.setABoxModel(unionABoxModel); - - // union TBox - OntModel unionTBoxModel = ModelFactory.createOntologyModel( - MEM_ONT_MODEL_SPEC,ModelFactory.createUnion( - baseOms.getTBoxModel(), inferenceOms.getTBoxModel())); - unionOms.setTBoxModel(unionTBoxModel); - - - // Application metadata model is cached in memory. - try { - - Model applicationMetadataModelDB = makeDBModel( - bds, JENA_APPLICATION_METADATA_MODEL, DB_ONT_MODEL_SPEC, - TripleStoreType.SDB, ctx); - OntModel applicationMetadataModel = - ModelFactory.createOntologyModel(MEM_ONT_MODEL_SPEC); - - long startTime = System.currentTimeMillis(); - System.out.println( - "Copying cached application metadata model into memory"); - applicationMetadataModel.add(applicationMetadataModelDB); - System.out.println((System.currentTimeMillis() - startTime) - / 1000 + " seconds to load application metadata model " + - "assertions of size " + applicationMetadataModel.size()); - applicationMetadataModel.getBaseModel().register( - new ModelSynchronizer(applicationMetadataModelDB)); - - if (isFirstStartup()) { - applicationMetadataModel.add( - InitialJenaModelUtils.loadInitialModel( - ctx, getDefaultNamespace(ctx))); - - } else if (applicationMetadataModelDB.size() == 0) { - repairAppMetadataModel( - applicationMetadataModel, aboxAssertions, - aboxInferences); - } - - baseOms.setApplicationMetadataModel(applicationMetadataModel); - inferenceOms.setApplicationMetadataModel( - baseOms.getApplicationMetadataModel()); - unionOms.setApplicationMetadataModel( - baseOms.getApplicationMetadataModel()); - - } catch (Throwable e) { - log.error("Unable to load application metadata model cache from DB" - , e); - } - - checkForNamespaceMismatch( baseOms.getApplicationMetadataModel(), ctx ); - - if (isFirstStartup()) { - loadDataFromFilesystem(baseOms, ctx); - } - - log.info("Setting up union models and DAO factories"); - - // create TBox + ABox union models and set up webapp DAO factories - OntModel baseUnion = ModelFactory.createOntologyModel( - OntModelSpec.OWL_MEM, - ModelFactory.createUnion(baseOms.getABoxModel(), - baseOms.getTBoxModel())); - baseOms.setFullModel(baseUnion); - ModelContext.setBaseOntModel(baseOms.getFullModel(), ctx); - WebappDaoFactoryConfig config = new WebappDaoFactoryConfig(); - config.setDefaultNamespace(getDefaultNamespace(ctx)); - WebappDaoFactory baseWadf = new WebappDaoFactorySDB( - baseOms, bds, storeDesc, config, - WebappDaoFactorySDB.SDBDatasetMode.ASSERTIONS_ONLY); - ctx.setAttribute("assertionsWebappDaoFactory",baseWadf); - - OntModel inferenceUnion = ModelFactory.createOntologyModel( - OntModelSpec.OWL_MEM, - ModelFactory.createUnion( - inferenceOms.getABoxModel(), - inferenceOms.getTBoxModel())); - inferenceOms.setFullModel(inferenceUnion); - ModelContext.setInferenceOntModel(inferenceOms.getFullModel(), ctx); - WebappDaoFactory infWadf = new WebappDaoFactorySDB( - inferenceOms, bds, storeDesc, config, - WebappDaoFactorySDB.SDBDatasetMode.INFERENCES_ONLY); - ctx.setAttribute("deductionsWebappDaoFactory", infWadf); - - OntModel masterUnion = ModelFactory.createOntologyModel( - DB_ONT_MODEL_SPEC, makeDBModel( - bds, WebappDaoFactorySDB.UNION_GRAPH, - DB_ONT_MODEL_SPEC, TripleStoreType.SDB, ctx)); - unionOms.setFullModel(masterUnion); - ctx.setAttribute("jenaOntModel", masterUnion); - WebappDaoFactory wadf = new WebappDaoFactorySDB( - unionOms, bds, storeDesc, config); - ctx.setAttribute("webappDaoFactory",wadf); - - ModelContext.setOntModelSelector(unionOms, ctx); - ModelContext.setUnionOntModelSelector(unionOms, ctx); - // assertions and inferences - ModelContext.setBaseOntModelSelector(baseOms, ctx); - // assertions - ModelContext.setInferenceOntModelSelector(inferenceOms, ctx); - // inferences - - ctx.setAttribute("defaultNamespace", getDefaultNamespace(ctx)); - - log.info("SDB store ready for use"); - - makeModelMakerFromConnectionProperties(TripleStoreType.RDB, ctx); - VitroJenaModelMaker vjmm = getVitroJenaModelMaker(); - setVitroJenaModelMaker(vjmm, ctx); - makeModelMakerFromConnectionProperties(TripleStoreType.SDB, ctx); - VitroJenaSDBModelMaker vsmm = getVitroJenaSDBModelMaker(); - setVitroJenaSDBModelMaker(vsmm, ctx); - - //bdc34: I have no reason for vsmm vs vjmm. - //I don't know what are the implications of this choice. - setVitroModelSource( new VitroModelSource(vsmm,ctx), ctx); - - log.info("Model makers set up"); - } - - - /** - * If we find a "portal1" portal (and we should), its URI should use the - * default namespace. - */ - private void checkForNamespaceMismatch(OntModel model, ServletContext ctx) { - String expectedNamespace = getDefaultNamespace(ctx); - - List portals = getPortal1s(model); - - if(!portals.isEmpty() && noPortalForNamespace( - portals, expectedNamespace)) { - // There really should be only one portal 1, but if there happen to - // be multiple, just arbitrarily pick the first in the list. - Resource portal = portals.get(0); - String oldNamespace = portal.getNameSpace(); - renamePortal(portal, expectedNamespace, model); - StartupStatus ss = StartupStatus.getBean(ctx); - ss.warning(this, "\nThe default namespace has been changed \n" + - "from " + oldNamespace + - "\nto " + expectedNamespace + ".\n" + - "The application will function normally, but " + - "any individuals in the \n" + oldNamespace + " " + - "namespace will need to have their URIs \n" + - "changed in order to be served as linked data. " + - "You can use the Ingest Tools \nto change the " + - "URIs for a batch of resources."); - } - } - - private List getPortal1s(Model model) { - List portals = new ArrayList(); - try { - model.enterCriticalSection(Lock.READ); - ResIterator portalIt = model.listResourcesWithProperty( - RDF.type, PORTAL); - while (portalIt.hasNext()) { - Resource portal = portalIt.nextResource(); - if ("portal1".equals(portal.getLocalName())) { - portals.add(portal); - } - } - } finally { - model.leaveCriticalSection(); - } - return portals; - } - - private boolean noPortalForNamespace(List portals, - String expectedNamespace) { - for (Resource portal : portals) { - if(expectedNamespace.equals(portal.getNameSpace())) { - return false; - } - } - return true; - } - - private void renamePortal(Resource portal, String namespace, Model model) { - model.enterCriticalSection(Lock.WRITE); - try { - ResourceUtils.renameResource( - portal, namespace + portal.getLocalName()); - } finally { - model.leaveCriticalSection(); - } - } - - - /* ===================================================================== */ - - - @Override - public void contextDestroyed(ServletContextEvent sce) { - // Nothing to do. - } - - private OntModel ontModelFromContextAttribute(ServletContext ctx, - String attribute) { - OntModel ontModel; - Object attributeValue = ctx.getAttribute(attribute); - if (attributeValue != null && attributeValue instanceof OntModel) { - ontModel = (OntModel) attributeValue; - } else { - ontModel = ModelFactory.createOntologyModel(MEM_ONT_MODEL_SPEC); - ctx.setAttribute(attribute, ontModel); - } - return ontModel; - } - - private boolean isEmpty(Model model) { - ClosableIterator closeIt = model.listStatements( - null, RDF.type, ResourceFactory.createResource( - VitroVocabulary.PORTAL)); - try { - if (closeIt.hasNext()) { - return false; - } else { - return true; - } - } finally { - closeIt.close(); - } - } - - private void loadDataFromFilesystem(OntModelSelector baseOms, - ServletContext ctx) { - Long startTime = System.currentTimeMillis(); - log.debug("Initializing models from RDF files"); - readOntologyFilesInPathSet(USER_ABOX_PATH, ctx, baseOms.getABoxModel()); - readOntologyFilesInPathSet(USER_TBOX_PATH, ctx, baseOms.getTBoxModel()); - readOntologyFilesInPathSet( - USER_APPMETA_PATH, ctx, baseOms.getApplicationMetadataModel()); - log.debug(((System.currentTimeMillis() - startTime) / 1000) - + " seconds to read RDF files "); - } - - private static void getTBoxModel(Model fullModel, - Model submodels, - Model tboxModel) { - - JenaModelUtils modelUtils = new JenaModelUtils(); - - Model tempModel = ModelFactory.createUnion(fullModel, submodels); - Model tempTBoxModel = modelUtils.extractTBox(tempModel); - - // copy intersection of tempTBoxModel and fullModel to tboxModel. - StmtIterator iter = tempTBoxModel.listStatements(); - - while (iter.hasNext()) { - Statement stmt = iter.next(); - if (fullModel.contains(stmt)) { - tboxModel.add(stmt); - } - } - - return; - } - - /* - * Copy all statements from model 1 that are not in model 2 to model 3. - */ - private static void copyDifference(Model model1, - Model model2, - Model model3) { - - StmtIterator iter = model1.listStatements(); - - while (iter.hasNext()) { - Statement stmt = iter.next(); - if (!model2.contains(stmt)) { - model3.add(stmt); - } - } - - return; - } - - private static void getAppMetadata(Model source, Model target) { - - String amdQuery = "DESCRIBE ?x WHERE { " + - "{?x a <" + VitroVocabulary.PORTAL +"> } UNION " + - "{?x a <" + VitroVocabulary.PROPERTYGROUP +"> } UNION " + - "{?x a <" + VitroVocabulary.CLASSGROUP +"> } } "; - - try { - Query q = QueryFactory.create(amdQuery, Syntax.syntaxARQ); - QueryExecution qe = QueryExecutionFactory.create(q, source); - qe.execDescribe(target); - } catch (Exception e) { - log.error("unable to create the application metadata model",e); - } - - return; - } - - private static void repairAppMetadataModel(Model applicationMetadataModel, - Model aboxAssertions, - Model aboxInferences) { - - log.info("Moving application metadata from ABox to dedicated model"); - getAppMetadata(aboxAssertions, applicationMetadataModel); - getAppMetadata(aboxInferences, applicationMetadataModel); - aboxAssertions.remove(applicationMetadataModel); - aboxInferences.remove(applicationMetadataModel); - - return; - } - - public static StoreDesc makeStoreDesc(ServletContext ctx) { - String layoutStr = ConfigurationProperties.getBean(ctx).getProperty( - "VitroConnection.DataSource.sdb.layout", "layout2/hash"); - String dbtypeStr = ConfigurationProperties.getBean(ctx).getProperty( - "VitroConnection.DataSource.dbtype", "MySQL"); - return new StoreDesc( - LayoutType.fetch(layoutStr), - DatabaseType.fetch(dbtypeStr) ); - } - - public static Store connectStore(BasicDataSource bds, StoreDesc storeDesc) - throws SQLException { - SDBConnection conn = new SDBConnection(bds.getConnection()) ; - return SDBFactory.connectStore(conn, storeDesc); - } - - public static void setupSDB(ServletContext ctx, Store store) { - setupSDB(ctx, - store, - ModelFactory.createDefaultModel(), - ModelFactory.createDefaultModel()); - } - - public static void setupSDB(ServletContext ctx, - Store store, - Model memModel, - Model inferenceModel) { - - store.getTableFormatter().create(); - store.getTableFormatter().truncate(); - - store.getTableFormatter().dropIndexes(); // improve load performance - - try { - - // This is a one-time copy of stored KB data - from a Jena RDB store - // to a Jena SDB store. In the process, we will also separate out - // the TBox from the Abox; these are in the same graph in pre-1.2 - // VIVO versions and will now be stored and maintained in separate - // models. Access to the Jena RDB data is through the - // OntModelSelectors that have been set up earlier in the current - // session by JenaPersistentDataSourceSetup.java. In the code - // below, note that the current getABoxModel() methods on the - // OntModelSelectors return a graph with both ABox and TBox data. - - OntModel submodels = ModelFactory.createOntologyModel( - MEM_ONT_MODEL_SPEC); - readOntologyFilesInPathSet(SUBMODELS, ctx, submodels); - - Model tboxAssertions = SDBFactory.connectNamedModel( - store, JenaDataSourceSetupBase.JENA_TBOX_ASSERTIONS_MODEL); - // initially putting the results in memory so we have a - // cheaper way of computing the difference when we copy the ABox - Model memTboxAssertions = ModelFactory.createDefaultModel(); - getTBoxModel(memModel, submodels, memTboxAssertions); - tboxAssertions.add(memTboxAssertions); - - Model tboxInferences = SDBFactory.connectNamedModel( - store, JenaDataSourceSetupBase.JENA_TBOX_INF_MODEL); - // initially putting the results in memory so we have a - // cheaper way of computing the difference when we copy the ABox - Model memTboxInferences = ModelFactory.createDefaultModel(); - getTBoxModel(inferenceModel, submodels, memTboxInferences); - tboxInferences.add(memTboxInferences); - - Model aboxAssertions = SDBFactory.connectNamedModel( - store, JenaDataSourceSetupBase.JENA_DB_MODEL); - copyDifference(memModel, memTboxAssertions, aboxAssertions); - - Model aboxInferences = SDBFactory.connectNamedModel( - store, JenaDataSourceSetupBase.JENA_INF_MODEL); - copyDifference(inferenceModel, memTboxInferences, aboxInferences); - - // Set up the application metadata model - Model applicationMetadataModel = SDBFactory.connectNamedModel( - store, - JenaDataSourceSetupBase.JENA_APPLICATION_METADATA_MODEL); - getAppMetadata(memModel, applicationMetadataModel); - log.info("During initial SDB setup, created an application " + - "metadata model of size " + - applicationMetadataModel.size()); - - // remove application metadata from ABox model - aboxAssertions.remove(applicationMetadataModel); - aboxInferences.remove(applicationMetadataModel); - - // Make sure the reasoner takes into account the newly-set-up data. - SimpleReasonerSetup.setRecomputeRequired(ctx); - - } finally { - log.info("Adding indexes to SDB database tables."); - store.getTableFormatter().addIndexes(); - log.info("Indexes created."); - } - } - - private void migrateToSDBFromExistingRDBStore(ServletContext ctx, - Store store) { - Model rdbAssertionsModel = makeDBModelFromConfigurationProperties( - JENA_DB_MODEL, DB_ONT_MODEL_SPEC, ctx); - Model rdbInferencesModel = makeDBModelFromConfigurationProperties( - JENA_INF_MODEL, DB_ONT_MODEL_SPEC, ctx); - setupSDB(ctx, store, rdbAssertionsModel, rdbInferencesModel); - } - - - - /** - * Tests whether an SDB store has been formatted and populated for use. - * @param store - * @return - */ - private boolean isSetUp(Store store) throws SQLException { - if (!(StoreUtils.isFormatted(store))) { - return false; - } - - // even if the store exists, it may be empty - - try { - return (SDBFactory.connectNamedModel( - store, - JenaDataSourceSetupBase.JENA_TBOX_ASSERTIONS_MODEL)) - .size() > 0; - } catch (Exception e) { - return false; - } - } - - private static final String STOREDESC_ATTR = "storeDesc"; - private static final String STORE_ATTR = "kbStore"; - - public static void setApplicationStoreDesc(StoreDesc storeDesc, - ServletContext ctx) { - ctx.setAttribute(STOREDESC_ATTR, storeDesc); - } - - public static StoreDesc getApplicationStoreDesc(ServletContext ctx) { - return (StoreDesc) ctx.getAttribute(STOREDESC_ATTR); - } - - public static void setApplicationStore(Store store, - ServletContext ctx) { - ctx.setAttribute(STORE_ATTR, store); - } - - public static Store getApplicationStore(ServletContext ctx) { - return (Store) ctx.getAttribute(STORE_ATTR); - } - } - diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/JenaDataSourceSetupBase.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/JenaDataSourceSetupBase.java index 0f02dd12c..17cf07994 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/JenaDataSourceSetupBase.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/JenaDataSourceSetupBase.java @@ -18,14 +18,21 @@ import org.apache.commons.logging.LogFactory; import com.hp.hpl.jena.graph.Graph; import com.hp.hpl.jena.ontology.OntModel; import com.hp.hpl.jena.ontology.OntModelSpec; +import com.hp.hpl.jena.query.Query; +import com.hp.hpl.jena.query.QueryExecution; +import com.hp.hpl.jena.query.QueryExecutionFactory; +import com.hp.hpl.jena.query.QueryFactory; +import com.hp.hpl.jena.query.Syntax; import com.hp.hpl.jena.rdf.model.Model; import com.hp.hpl.jena.rdf.model.ModelFactory; +import com.hp.hpl.jena.sdb.Store; import com.hp.hpl.jena.sdb.StoreDesc; import com.hp.hpl.jena.sdb.store.DatabaseType; import com.hp.hpl.jena.sdb.store.LayoutType; import edu.cornell.mannlib.vitro.webapp.config.ConfigurationProperties; import edu.cornell.mannlib.vitro.webapp.dao.DisplayVocabulary; +import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary; import edu.cornell.mannlib.vitro.webapp.dao.jena.JenaBaseDaoCon; import edu.cornell.mannlib.vitro.webapp.dao.jena.RDBGraphGenerator; import edu.cornell.mannlib.vitro.webapp.dao.jena.RegeneratingGraph; @@ -62,8 +69,7 @@ public class JenaDataSourceSetupBase extends JenaBaseDaoCon { protected static String USER_ABOX_PATH = BASE+"user/abox"; protected static String USER_TBOX_PATH = BASE+"user/tbox"; protected static String USER_APPMETA_PATH = BASE+"user/applicationMetadata"; - protected static String SYSTEMPATH = BASE+"system/"; - protected static String AUTHPATH = BASE+"auth/"; + protected static String SYSTEMPATH = BASE+"system/"; public static String APPPATH = BASE+"app/"; //these files are loaded everytime the system starts up public static String APPPATH_LOAD = APPPATH + "menuload/"; @@ -418,7 +424,7 @@ public class JenaDataSourceSetupBase extends JenaBaseDaoCon { } else if (TripleStoreType.SDB.equals(type)) { StoreDesc storeDesc = new StoreDesc( LayoutType.LayoutTripleNodesHash, DatabaseType.fetch(dbtypeStr)); - BasicDataSource bds = JenaDataSourceSetup.makeBasicDataSource( + BasicDataSource bds = WebappDaoSDBSetup.makeBasicDataSource( getDbDriverClassName(ctx), jdbcUrl, username, password, ctx); bds.setMaxActive(4); // for now, the SDB model makers should not use more // than a small handful of connections @@ -524,4 +530,68 @@ public class JenaDataSourceSetupBase extends JenaBaseDaoCon { "VitroConnection.DataSource.validationQuery", "SELECT 1"); } + protected OntModel ontModelFromContextAttribute(ServletContext ctx, + String attribute) { + OntModel ontModel; + Object attributeValue = ctx.getAttribute(attribute); + if (attributeValue != null && attributeValue instanceof OntModel) { + ontModel = (OntModel) attributeValue; + } else { + ontModel = ModelFactory.createOntologyModel(MEM_ONT_MODEL_SPEC); + ctx.setAttribute(attribute, ontModel); + } + return ontModel; + } + + protected static void repairAppMetadataModel(Model applicationMetadataModel, + Model aboxAssertions, + Model aboxInferences) { + + log.info("Moving application metadata from ABox to dedicated model"); + getAppMetadata(aboxAssertions, applicationMetadataModel); + getAppMetadata(aboxInferences, applicationMetadataModel); + aboxAssertions.remove(applicationMetadataModel); + aboxInferences.remove(applicationMetadataModel); + + return; + } + + protected static void getAppMetadata(Model source, Model target) { + + String amdQuery = "DESCRIBE ?x WHERE { " + + "{?x a <" + VitroVocabulary.PORTAL +"> } UNION " + + "{?x a <" + VitroVocabulary.PROPERTYGROUP +"> } UNION " + + "{?x a <" + VitroVocabulary.CLASSGROUP +"> } } "; + + try { + Query q = QueryFactory.create(amdQuery, Syntax.syntaxARQ); + QueryExecution qe = QueryExecutionFactory.create(q, source); + qe.execDescribe(target); + } catch (Exception e) { + log.error("unable to create the application metadata model",e); + } + + return; + } + + private static final String STOREDESC_ATTR = "storeDesc"; + private static final String STORE_ATTR = "kbStore"; + + public static void setApplicationStoreDesc(StoreDesc storeDesc, + ServletContext ctx) { + ctx.setAttribute(STOREDESC_ATTR, storeDesc); + } + + public static StoreDesc getApplicationStoreDesc(ServletContext ctx) { + return (StoreDesc) ctx.getAttribute(STOREDESC_ATTR); + } + + public static void setApplicationStore(Store store, + ServletContext ctx) { + ctx.setAttribute(STORE_ATTR, store); + } + + public static Store getApplicationStore(ServletContext ctx) { + return (Store) ctx.getAttribute(STORE_ATTR); + } } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/JenaPersistentDataSourceSetup.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/JenaPersistentDataSourceSetup.java index 40f3ed503..c0b5d3320 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/JenaPersistentDataSourceSetup.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/JenaPersistentDataSourceSetup.java @@ -2,11 +2,6 @@ package edu.cornell.mannlib.vitro.webapp.servlet.setup; -import static edu.cornell.mannlib.vitro.webapp.dao.DisplayVocabulary.DISPLAY_ONT_MODEL; - -import java.io.File; -import java.io.FileOutputStream; - import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; @@ -14,21 +9,18 @@ import javax.servlet.ServletContextListener; import org.apache.commons.dbcp.BasicDataSource; 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.ontology.OntDocumentManager; import com.hp.hpl.jena.ontology.OntModel; -import com.hp.hpl.jena.query.Query; -import com.hp.hpl.jena.query.QueryExecution; -import com.hp.hpl.jena.query.QueryExecutionFactory; -import com.hp.hpl.jena.query.QueryFactory; import com.hp.hpl.jena.rdf.model.Model; import com.hp.hpl.jena.rdf.model.ModelFactory; import edu.cornell.mannlib.vitro.webapp.dao.jena.ModelSynchronizer; import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus; +/** + * Create connection to DB and DataSource, put them in the context. + */ public class JenaPersistentDataSourceSetup extends JenaDataSourceSetupBase implements ServletContextListener { @@ -44,217 +36,13 @@ public class JenaPersistentDataSourceSetup extends JenaDataSourceSetupBase OntDocumentManager.getInstance().setProcessImports(false); BasicDataSource bds = makeDataSourceFromConfigurationProperties(ctx); - setApplicationDataSource(bds, ctx); - - // user accounts Model - try { - Model userAccountsDbModel = makeDBModel(bds, - JENA_USER_ACCOUNTS_MODEL, DB_ONT_MODEL_SPEC, ctx); - if (userAccountsDbModel.size() == 0) { - firstStartup = true; - readOntologyFilesInPathSet(AUTHPATH, ctx, - userAccountsDbModel); - } - OntModel userAccountsModel = ModelFactory.createOntologyModel( - MEM_ONT_MODEL_SPEC); - userAccountsModel.add(userAccountsDbModel); - userAccountsModel.getBaseModel().register( - new ModelSynchronizer(userAccountsDbModel)); - ctx.setAttribute("userAccountsOntModel", userAccountsModel); - - if (userAccountsModel.isEmpty()) { - initializeUserAccounts(ctx, userAccountsModel); - } - } catch (Throwable t) { - log.error("Unable to load user accounts model from DB", t); - ss.fatal(this, "Unable to load user accounts model from DB", t); - } - - // display, editing and navigation Model - try { - Model displayDbModel = makeDBModel(bds, - JENA_DISPLAY_METADATA_MODEL, DB_ONT_MODEL_SPEC, ctx); - if (displayDbModel.size() == 0) { - readOntologyFilesInPathSet(APPPATH, ctx,displayDbModel); - } - OntModel displayModel = ModelFactory.createOntologyModel(MEM_ONT_MODEL_SPEC); - displayModel.add(displayDbModel); - displayModel.getBaseModel().register(new ModelSynchronizer(displayDbModel)); - ctx.setAttribute(DISPLAY_ONT_MODEL, displayModel); - - //at each startup load all RDF files from directory to sub-models of display model - initializeDisplayLoadedAtStartup(ctx, displayModel); - } catch (Throwable t) { - log.error("Unable to load user application configuration model", t); - ss.fatal(this, "Unable to load user application configuration model", t); - } - - //display tbox - currently reading in every time - try { - Model displayTboxModel = makeDBModel(bds, - JENA_DISPLAY_TBOX_MODEL, DB_ONT_MODEL_SPEC, ctx); - //Reading in single file every time - //TODO: Check if original needs to be cleared/removed every time? - readOntologyFileFromPath(APPPATH_LOAD + "displayTBOX.n3", displayTboxModel, ctx); - OntModel appTBOXModel = ModelFactory.createOntologyModel( - MEM_ONT_MODEL_SPEC); - appTBOXModel.add(displayTboxModel); - appTBOXModel.getBaseModel().register(new ModelSynchronizer(displayTboxModel)); - ctx.setAttribute("displayOntModelTBOX", appTBOXModel); - log.debug("Loaded file " + APPPATH_LOAD + "displayTBOX.n3 into display tbox model"); - } catch (Throwable t) { - log.error("Unable to load user application configuration model TBOX", t); - ss.fatal(this, "Unable to load user application configuration model TBOX", t); - } - - //Display Display model, currently empty, create if doesn't exist but no files to load - try { - Model displayDisplayModel = makeDBModel(bds, - JENA_DISPLAY_DISPLAY_MODEL, DB_ONT_MODEL_SPEC, ctx); - //Reading in single file every time - //TODO: Check if original needs to be cleared/removed every time? - readOntologyFileFromPath(APPPATH_LOAD + "displayDisplay.n3", displayDisplayModel, ctx); - - OntModel appDisplayDisplayModel = ModelFactory.createOntologyModel( - MEM_ONT_MODEL_SPEC); - appDisplayDisplayModel.add(displayDisplayModel); - appDisplayDisplayModel.getBaseModel().register(new ModelSynchronizer(displayDisplayModel)); - ctx.setAttribute("displayOntModelDisplayModel", appDisplayDisplayModel); - log.debug("Loaded file " + APPPATH_LOAD + "displayDisplay.n3 into display display model"); - } catch (Throwable t) { - log.error("Unable to load user application configuration model Display Model", t); - ss.fatal(this, "Unable to load user application configuration model Display Model", t); - } + setApplicationDataSource(bds, ctx); } - @Override + + @Override public void contextDestroyed(ServletContextEvent sce) { // Nothing to do. - } - - private void initializeUserAccounts(ServletContext ctx, - Model userAccountsModel) { - readOntologyFilesInPathSet(AUTHPATH, ctx, userAccountsModel); - } - - /** - * Load the RDF found in the directory DISPLAY_MODEL_LOAD_AT_STARTUP_DIR - * a sub-models of displayModel. The RDF from thes files will not be saved - * in the database and it will be reloaded each time the system starts up. - */ - private void initializeDisplayLoadedAtStartup(ServletContext ctx, OntModel displayModel){ - log.info("loading display model from files in " + ctx.getRealPath(DISPLAY_MODEL_LOAD_AT_STARTUP_DIR) ); - Model displayLoadAtStartup = readInDisplayModelLoadAtStartup(ctx); - - if( log.isDebugEnabled() ){ - log.debug("loaded display model from files in " + ctx.getRealPath(DISPLAY_MODEL_LOAD_AT_STARTUP_DIR) ); - displayLoadAtStartup.write(System.out, "N3-PP"); - } - - checkForOldListViews(ctx,displayModel,displayLoadAtStartup); - displayModel.addSubModel( displayLoadAtStartup ); - } - - /** - * All of the list views should now reside in files in DISPLAY_MODEL_LOAD_AT_STARTUP_DIR. - * This will check for custom list view annotation statements in the displayModel, check - * if they exist in the files in DISPLAY_MODEL_LOAD_AT_STARTUP_DIR, and write any that don't - * exist there to a file in DISPLAY_MODEL_LOAD_AT_STARTUP_DIR. After that the statements - * will be removed from the displayDBModel. - * - * returns true if there were old list view statements in the DB, returns false - * if there were none. displayLoadAlways should be reloaded from the file system - * if this returns true as this method may have changed the files. - * - * displayLoadAtStartup and displayModel may be modified. - */ - private void checkForOldListViews( ServletContext ctx, OntModel displayModel, Model displayLoadAtStartup){ - // run construct for old custom list view statements from displayModel - Model oldListViewModel = getOldListViewStatements( displayModel ); - if( log.isDebugEnabled() ){ - log.debug("Printing the old list view statements from the display model to System.out."); - oldListViewModel.write(System.out,"N3-PP"); - } - - // find statements in old stmts that are not in loadedAtStartup and - // save them in a new file in DISPLAY_MODEL_LOAD_AT_STARTUP_DIR - // so that in the future they will be in loadedAtStartup - Model stmtsInOldAndFiles = displayLoadAtStartup.intersection( displayModel ); - Model unhandledOldListViewStmts = oldListViewModel.difference( stmtsInOldAndFiles ); - - boolean saved = false; - boolean neededSave = false; - - if( unhandledOldListViewStmts != null && !unhandledOldListViewStmts.isEmpty() ){ - log.debug("need to deal with old list view statements from the display model"); - neededSave = true; - try{ - //create a file for the old statements in the loadAtStartup directory - String newFileName = ctx.getRealPath( - DISPLAY_MODEL_LOAD_AT_STARTUP_DIR + File.separator - + new DateTime().toString(ISODateTimeFormat.basicDateTime()) + ".n3" ); - File file = new File( newFileName ); - file.createNewFile(); - - log.info("Relocating " + unhandledOldListViewStmts.size() + " custom list view statements from DB and saving to " - + file.getAbsolutePath()+ File.separator + file.getName() - + ". These will be loaded from this file when the system starts up."); - - FileOutputStream fileOut = new FileOutputStream(file); - unhandledOldListViewStmts.write(fileOut, "N3-PP"); - fileOut.close(); - saved = true; - }catch(Throwable th){ - log.warn("Could not save old list view statements. Leaving them in the DB",th); - } - - //need to reload displayLoadAlways because DISPLAY_MODEL_LOAD_AT_STARTUP_DIR may have changed - displayLoadAtStartup.removeAll().add(readInDisplayModelLoadAtStartup(ctx)); - } - - - if( oldListViewModel != null && ! oldListViewModel.isEmpty() ){ - //At this point, there are old list view statements in the DB but they - //should are all redundant with ones in DISPLAY_MODEL_LOAD_AT_STARTUP_DIR - if( (neededSave && saved) || (!neededSave) ){ - //if there was nothing to save, just remove the old stuff - //if there was stuff to save, only remove if it was saved. - log.debug("removing old statements from displayModel"); - displayModel.remove(oldListViewModel); - } - } - - } - - private Model getOldListViewStatements(OntModel displayModel) { - //run a construct on displayModel to get all list view statements - Query query = QueryFactory.create ( listViewQuery ); - QueryExecution qexec = QueryExecutionFactory.create(query, displayModel) ; - Model oldModel = null; - - try { - oldModel = qexec.execConstruct(); - } catch( Throwable th ){ - log.error("could not check for old custom list views, query exception",th); - }finally { - qexec.close() ; - } - - if( oldModel != null) - return oldModel; - else - return ModelFactory.createDefaultModel(); - } + } - private static final String listViewQuery = "" + - "PREFIX d: \n" + - "CONSTRUCT { \n" + - " ?a d:listViewConfigFile ?b . \n" + - "} WHERE {\n" + - " ?a d:listViewConfigFile ?b . \n" + - "} "; - - protected Model readInDisplayModelLoadAtStartup( ServletContext ctx ){ - return getModelFromDir( new File( ctx.getRealPath( DISPLAY_MODEL_LOAD_AT_STARTUP_DIR ))); - } } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/ModelSetup.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/ModelSetup.java new file mode 100644 index 000000000..7de262fc4 --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/ModelSetup.java @@ -0,0 +1,239 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ +package edu.cornell.mannlib.vitro.webapp.servlet.setup; + +import static edu.cornell.mannlib.vitro.webapp.dao.DisplayVocabulary.DISPLAY_ONT_MODEL; + +import javax.servlet.ServletContext; +import javax.servlet.ServletContextEvent; + +import org.apache.commons.dbcp.BasicDataSource; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import com.hp.hpl.jena.ontology.OntModel; +import com.hp.hpl.jena.ontology.OntModelSpec; +import com.hp.hpl.jena.query.Query; +import com.hp.hpl.jena.query.QueryExecution; +import com.hp.hpl.jena.query.QueryExecutionFactory; +import com.hp.hpl.jena.query.QueryFactory; +import com.hp.hpl.jena.query.Syntax; +import com.hp.hpl.jena.rdf.model.Model; +import com.hp.hpl.jena.rdf.model.ModelFactory; + +import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary; +import edu.cornell.mannlib.vitro.webapp.dao.jena.ModelContext; +import edu.cornell.mannlib.vitro.webapp.dao.jena.ModelSynchronizer; +import edu.cornell.mannlib.vitro.webapp.dao.jena.OntModelSelectorImpl; +import edu.cornell.mannlib.vitro.webapp.servlet.setup.JenaDataSourceSetupBase.TripleStoreType; +import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus; +import edu.cornell.mannlib.vitro.webapp.utils.jena.InitialJenaModelUtils; + +/** + * Setup the ABox, TBox, inference and Union models. + * Also setup the OntModelSelectors. + */ +public class ModelSetup extends JenaDataSourceSetupBase +implements javax.servlet.ServletContextListener { + private static final Log log = LogFactory.getLog(ModelSetup.class); + + @Override + public void contextInitialized(ServletContextEvent sce) { + ServletContext ctx = sce.getServletContext(); + StartupStatus ss = StartupStatus.getBean(ctx); + + BasicDataSource bds = getApplicationDataSource(ctx); + if( bds == null ){ + ss.fatal(this, "A DataSource must be setup before ModelSetup "+ + "is run. Make sure that JenaPersistentDataSourceSetup runs before "+ + "ModelSetup."); + return; + } + + setupModels(ctx,ss,bds); + } + + private void setupModels(ServletContext ctx, StartupStatus ss, BasicDataSource bds){ + log.info("Setting up model makers and union models"); + + /////////////////////////////////////////////////////////////// + //set up the OntModelSelectors + + OntModelSelectorImpl baseOms = new OntModelSelectorImpl(); + OntModelSelectorImpl inferenceOms = new OntModelSelectorImpl(); + OntModelSelectorImpl unionOms = new OntModelSelectorImpl(); + + //Put OntModelSelectorImpl objs into the context + ModelContext.setOntModelSelector(unionOms, ctx); + ModelContext.setUnionOntModelSelector(unionOms, ctx); + // assertions and inferences + ModelContext.setBaseOntModelSelector(baseOms, ctx); + // assertions + ModelContext.setInferenceOntModelSelector(inferenceOms, ctx); + // inferences + + //add userAccountsModel to OntModelSelectors + OntModel userAccountsModel = ontModelFromContextAttribute( + ctx, "userAccountsOntModel"); + baseOms.setUserAccountsModel(userAccountsModel); + inferenceOms.setUserAccountsModel(userAccountsModel); + unionOms.setUserAccountsModel(userAccountsModel); + + //add display to OntModelSelectors + OntModel displayModel = ontModelFromContextAttribute( + ctx,DISPLAY_ONT_MODEL); + baseOms.setDisplayModel(displayModel); + inferenceOms.setDisplayModel(displayModel); + unionOms.setDisplayModel(displayModel); + + // The code below, which sets up the OntModelSelectors, controls whether + // each model is maintained in memory, in the DB, or both while the + // application is running. + + // Populate the three OntModelSelectors (BaseOntModel = assertions, + // InferenceOntModel = inferences and JenaOntModel = union of assertions + // and inferences) with the post-SDB-conversion models. + + // ABox assertions + Model aboxAssertions = makeDBModel( + bds, JenaDataSourceSetupBase.JENA_DB_MODEL, DB_ONT_MODEL_SPEC, + TripleStoreType.SDB, ctx); + Model listenableAboxAssertions = ModelFactory.createUnion( + aboxAssertions, ModelFactory.createDefaultModel()); + baseOms.setABoxModel( + ModelFactory.createOntologyModel( + OntModelSpec.OWL_MEM, listenableAboxAssertions)); + + // ABox inferences + Model aboxInferences = makeDBModel( + bds, JenaDataSourceSetupBase.JENA_INF_MODEL, DB_ONT_MODEL_SPEC, + TripleStoreType.SDB, ctx); + Model listenableAboxInferences = ModelFactory.createUnion( + aboxInferences, ModelFactory.createDefaultModel()); + inferenceOms.setABoxModel(ModelFactory.createOntologyModel( + OntModelSpec.OWL_MEM, listenableAboxInferences)); + + + // Since the TBox models are in memory, they do not have timeout issues + // like the like the ABox models do (and so don't need the extra step + // to make them listenable.) + + // TBox assertions + try { + Model tboxAssertionsDB = makeDBModel( + bds, JENA_TBOX_ASSERTIONS_MODEL, DB_ONT_MODEL_SPEC, + TripleStoreType.SDB, ctx); + OntModel tboxAssertions = ModelFactory.createOntologyModel( + MEM_ONT_MODEL_SPEC); + + if (tboxAssertionsDB != null) { + long startTime = System.currentTimeMillis(); + System.out.println( + "Copying cached tbox assertions into memory"); + tboxAssertions.add(tboxAssertionsDB); + System.out.println((System.currentTimeMillis() - startTime) + / 1000 + " seconds to load tbox assertions"); + } + + tboxAssertions.getBaseModel().register(new ModelSynchronizer( + tboxAssertionsDB)); + baseOms.setTBoxModel(tboxAssertions); + } catch (Throwable e) { + log.error("Unable to load tbox assertion cache from DB", e); + } + + // TBox inferences + try { + Model tboxInferencesDB = makeDBModel( + bds, JENA_TBOX_INF_MODEL, DB_ONT_MODEL_SPEC, + TripleStoreType.SDB, ctx); + OntModel tboxInferences = ModelFactory.createOntologyModel( + MEM_ONT_MODEL_SPEC); + + if (tboxInferencesDB != null) { + long startTime = System.currentTimeMillis(); + System.out.println( + "Copying cached tbox inferences into memory"); + tboxInferences.add(tboxInferencesDB); + System.out.println((System.currentTimeMillis() - startTime) + / 1000 + " seconds to load tbox inferences"); + } + + tboxInferences.getBaseModel().register(new ModelSynchronizer( + tboxInferencesDB)); + inferenceOms.setTBoxModel(tboxInferences); + } catch (Throwable e) { + log.error("Unable to load tbox inference cache from DB", e); + } + + // union ABox + OntModel unionABoxModel = ModelFactory.createOntologyModel( + MEM_ONT_MODEL_SPEC,ModelFactory.createUnion( + baseOms.getABoxModel(), inferenceOms.getABoxModel())); + unionOms.setABoxModel(unionABoxModel); + + // union TBox + OntModel unionTBoxModel = ModelFactory.createOntologyModel( + MEM_ONT_MODEL_SPEC,ModelFactory.createUnion( + baseOms.getTBoxModel(), inferenceOms.getTBoxModel())); + unionOms.setTBoxModel(unionTBoxModel); + + + // Application metadata model is cached in memory. + try { + + Model applicationMetadataModelDB = makeDBModel( + bds, JENA_APPLICATION_METADATA_MODEL, DB_ONT_MODEL_SPEC, + TripleStoreType.SDB, ctx); + OntModel applicationMetadataModel = + ModelFactory.createOntologyModel(MEM_ONT_MODEL_SPEC); + + long startTime = System.currentTimeMillis(); + System.out.println( + "Copying cached application metadata model into memory"); + applicationMetadataModel.add(applicationMetadataModelDB); + System.out.println((System.currentTimeMillis() - startTime) + / 1000 + " seconds to load application metadata model " + + "assertions of size " + applicationMetadataModel.size()); + applicationMetadataModel.getBaseModel().register( + new ModelSynchronizer(applicationMetadataModelDB)); + + if (isFirstStartup()) { + applicationMetadataModel.add( + InitialJenaModelUtils.loadInitialModel( + ctx, getDefaultNamespace(ctx))); + + } else if (applicationMetadataModelDB.size() == 0) { + repairAppMetadataModel( + applicationMetadataModel, aboxAssertions, + aboxInferences); + } + + baseOms.setApplicationMetadataModel(applicationMetadataModel); + inferenceOms.setApplicationMetadataModel( + baseOms.getApplicationMetadataModel()); + unionOms.setApplicationMetadataModel( + baseOms.getApplicationMetadataModel()); + + } catch (Throwable e) { + log.error("Unable to load application metadata model cache from DB" + , e); + } + + // create TBox + ABox union models + OntModel baseUnion = ModelFactory.createOntologyModel( + OntModelSpec.OWL_MEM, + ModelFactory.createUnion(baseOms.getABoxModel(), + baseOms.getTBoxModel())); + baseOms.setFullModel(baseUnion); + ModelContext.setBaseOntModel(baseOms.getFullModel(), ctx); + + log.info("Model makers and union set up"); + } + + @Override + public void contextDestroyed(ServletContextEvent arg0) { + // nothing to do. + + } + +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/SDBSetup.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/SDBSetup.java new file mode 100644 index 000000000..1e958e0aa --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/SDBSetup.java @@ -0,0 +1,243 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ +package edu.cornell.mannlib.vitro.webapp.servlet.setup; + +import java.sql.SQLException; + +import javax.servlet.ServletContext; +import javax.servlet.ServletContextEvent; + +import org.apache.commons.dbcp.BasicDataSource; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import com.hp.hpl.jena.ontology.OntModel; +import com.hp.hpl.jena.rdf.model.Model; +import com.hp.hpl.jena.rdf.model.ModelFactory; +import com.hp.hpl.jena.rdf.model.Statement; +import com.hp.hpl.jena.rdf.model.StmtIterator; +import com.hp.hpl.jena.sdb.SDB; +import com.hp.hpl.jena.sdb.SDBFactory; +import com.hp.hpl.jena.sdb.Store; +import com.hp.hpl.jena.sdb.StoreDesc; +import com.hp.hpl.jena.sdb.sql.SDBConnection; +import com.hp.hpl.jena.sdb.store.DatabaseType; +import com.hp.hpl.jena.sdb.store.LayoutType; +import com.hp.hpl.jena.sdb.util.StoreUtils; + +import edu.cornell.mannlib.vitro.webapp.config.ConfigurationProperties; +import edu.cornell.mannlib.vitro.webapp.dao.jena.JenaModelUtils; +import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus; + +public class SDBSetup extends JenaDataSourceSetupBase +implements javax.servlet.ServletContextListener { + private static final Log log = LogFactory.getLog(SDBSetup.class); + + @Override + public void contextDestroyed(ServletContextEvent arg0) { + // nothing to do + + } + + @Override + public void contextInitialized(ServletContextEvent sce) { + ServletContext ctx = sce.getServletContext(); + StartupStatus ss = StartupStatus.getBean(ctx); + try { + setupSDB(ctx, ss); + log.info("SDB store ready for use"); + } catch (SQLException e) { + ss.fatal(this, "Exception in setupSDB", e); + } + } + + private void setupSDB(ServletContext ctx, StartupStatus ss) throws SQLException { + BasicDataSource bds = getApplicationDataSource(ctx); + if( bds == null ){ + ss.fatal(this, "A DataSource must be setup before SDBSetup "+ + "is run. Make sure that JenaPersistentDataSourceSetup runs before "+ + "SDBSetup."); + return; + } + + // union default graph + SDB.getContext().set(SDB.unionDefaultGraph, true) ; + + StoreDesc storeDesc = makeStoreDesc(ctx); + setApplicationStoreDesc(storeDesc, ctx); + + Store store = connectStore(bds, storeDesc); + setApplicationStore(store, ctx); + + if (!isSetUp(store)) { + log.info("Initializing SDB store"); + if (isFirstStartup()) { + setupSDB(ctx, store); + } else { + migrateToSDBFromExistingRDBStore(ctx, store); + } + } + } + + + /** + * Tests whether an SDB store has been formatted and populated for use. + * @param store + * @return + */ + private boolean isSetUp(Store store) throws SQLException { + if (!(StoreUtils.isFormatted(store))) { + return false; + } + + // even if the store exists, it may be empty + + try { + return (SDBFactory.connectNamedModel( + store, + JenaDataSourceSetupBase.JENA_TBOX_ASSERTIONS_MODEL)) + .size() > 0; + } catch (Exception e) { + return false; + } + } + + public static StoreDesc makeStoreDesc(ServletContext ctx) { + String layoutStr = ConfigurationProperties.getBean(ctx).getProperty( + "VitroConnection.DataSource.sdb.layout", "layout2/hash"); + String dbtypeStr = ConfigurationProperties.getBean(ctx).getProperty( + "VitroConnection.DataSource.dbtype", "MySQL"); + return new StoreDesc( + LayoutType.fetch(layoutStr), + DatabaseType.fetch(dbtypeStr) ); + } + + public static Store connectStore(BasicDataSource bds, StoreDesc storeDesc) + throws SQLException { + SDBConnection conn = new SDBConnection(bds.getConnection()); + return SDBFactory.connectStore(conn, storeDesc); + } + + protected static void setupSDB(ServletContext ctx, Store store) { + setupSDB(ctx, store, ModelFactory.createDefaultModel(), + ModelFactory.createDefaultModel()); + } + + protected static void setupSDB(ServletContext ctx, Store store, + Model memModel, Model inferenceModel) { + + store.getTableFormatter().create(); + store.getTableFormatter().truncate(); + + store.getTableFormatter().dropIndexes(); // improve load performance + + try { + + // This is a one-time copy of stored KB data - from a Jena RDB store + // to a Jena SDB store. In the process, we will also separate out + // the TBox from the Abox; these are in the same graph in pre-1.2 + // VIVO versions and will now be stored and maintained in separate + // models. Access to the Jena RDB data is through the + // OntModelSelectors that have been set up earlier in the current + // session by JenaPersistentDataSourceSetup.java. In the code + // below, note that the current getABoxModel() methods on the + // OntModelSelectors return a graph with both ABox and TBox data. + + OntModel submodels = ModelFactory + .createOntologyModel(MEM_ONT_MODEL_SPEC); + readOntologyFilesInPathSet(SUBMODELS, ctx, submodels); + + Model tboxAssertions = SDBFactory.connectNamedModel(store, + JenaDataSourceSetupBase.JENA_TBOX_ASSERTIONS_MODEL); + // initially putting the results in memory so we have a + // cheaper way of computing the difference when we copy the ABox + Model memTboxAssertions = ModelFactory.createDefaultModel(); + getTBoxModel(memModel, submodels, memTboxAssertions); + tboxAssertions.add(memTboxAssertions); + + Model tboxInferences = SDBFactory.connectNamedModel(store, + JenaDataSourceSetupBase.JENA_TBOX_INF_MODEL); + // initially putting the results in memory so we have a + // cheaper way of computing the difference when we copy the ABox + Model memTboxInferences = ModelFactory.createDefaultModel(); + getTBoxModel(inferenceModel, submodels, memTboxInferences); + tboxInferences.add(memTboxInferences); + + Model aboxAssertions = SDBFactory.connectNamedModel(store, + JenaDataSourceSetupBase.JENA_DB_MODEL); + copyDifference(memModel, memTboxAssertions, aboxAssertions); + + Model aboxInferences = SDBFactory.connectNamedModel(store, + JenaDataSourceSetupBase.JENA_INF_MODEL); + copyDifference(inferenceModel, memTboxInferences, aboxInferences); + + // Set up the application metadata model + Model applicationMetadataModel = SDBFactory.connectNamedModel( + store, + JenaDataSourceSetupBase.JENA_APPLICATION_METADATA_MODEL); + getAppMetadata(memModel, applicationMetadataModel); + log.info("During initial SDB setup, created an application " + + "metadata model of size " + + applicationMetadataModel.size()); + + // remove application metadata from ABox model + aboxAssertions.remove(applicationMetadataModel); + aboxInferences.remove(applicationMetadataModel); + + // Make sure the reasoner takes into account the newly-set-up data. + SimpleReasonerSetup.setRecomputeRequired(ctx); + + } finally { + log.info("Adding indexes to SDB database tables."); + store.getTableFormatter().addIndexes(); + log.info("Indexes created."); + } + } + + private void migrateToSDBFromExistingRDBStore(ServletContext ctx, + Store store) { + Model rdbAssertionsModel = makeDBModelFromConfigurationProperties( + JENA_DB_MODEL, DB_ONT_MODEL_SPEC, ctx); + Model rdbInferencesModel = makeDBModelFromConfigurationProperties( + JENA_INF_MODEL, DB_ONT_MODEL_SPEC, ctx); + setupSDB(ctx, store, rdbAssertionsModel, rdbInferencesModel); + } + + /* + * Copy all statements from model 1 that are not in model 2 to model 3. + */ + private static void copyDifference(Model model1, Model model2, Model model3) { + + StmtIterator iter = model1.listStatements(); + + while (iter.hasNext()) { + Statement stmt = iter.next(); + if (!model2.contains(stmt)) { + model3.add(stmt); + } + } + + return; + } + + private static void getTBoxModel(Model fullModel, Model submodels, + Model tboxModel) { + + JenaModelUtils modelUtils = new JenaModelUtils(); + + Model tempModel = ModelFactory.createUnion(fullModel, submodels); + Model tempTBoxModel = modelUtils.extractTBox(tempModel); + + // copy intersection of tempTBoxModel and fullModel to tboxModel. + StmtIterator iter = tempTBoxModel.listStatements(); + + while (iter.hasNext()) { + Statement stmt = iter.next(); + if (fullModel.contains(stmt)) { + tboxModel.add(stmt); + } + } + + return; + } + +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/UserModelSetup.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/UserModelSetup.java new file mode 100644 index 000000000..8f0f25621 --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/UserModelSetup.java @@ -0,0 +1,69 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ +package edu.cornell.mannlib.vitro.webapp.servlet.setup; + +import javax.servlet.ServletContext; +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; + +import org.apache.commons.dbcp.BasicDataSource; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import com.hp.hpl.jena.ontology.OntModel; +import com.hp.hpl.jena.rdf.model.Model; +import com.hp.hpl.jena.rdf.model.ModelFactory; + +import edu.cornell.mannlib.vitro.webapp.dao.jena.ModelSynchronizer; +import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus; + + +/** + * Setup the user account model. If it does not exist in the + * database, create and populate it. + */ +public class UserModelSetup extends JenaDataSourceSetupBase + implements ServletContextListener { + + private static final Log log = LogFactory.getLog( + UserModelSetup.class.getName()); + + @Override + public void contextInitialized(ServletContextEvent sce) { + ServletContext ctx = sce.getServletContext(); + StartupStatus ss = StartupStatus.getBean(ctx); + + BasicDataSource bds = getApplicationDataSource(ctx); + if( bds == null ){ + ss.fatal(this, "A DataSource must be setup before ModelSetup "+ + "is run. Make sure that JenaPersistentDataSourceSetup runs before "+ + "ModelSetup."); + return; + } + + setupUserAccountModel(bds, ctx, ss); + } + + @Override + public void contextDestroyed(ServletContextEvent arg0) { + // Does nothing. + } + + private void setupUserAccountModel (BasicDataSource bds, ServletContext ctx ,StartupStatus ss){ + try { + Model userAccountsDbModel = makeDBModel(bds, + JENA_USER_ACCOUNTS_MODEL, DB_ONT_MODEL_SPEC, ctx); + OntModel userAccountsModel = + ModelFactory.createOntologyModel( MEM_ONT_MODEL_SPEC); + + userAccountsModel.add(userAccountsDbModel); + userAccountsModel.getBaseModel().register( + new ModelSynchronizer(userAccountsDbModel)); + ctx.setAttribute("userAccountsOntModel", userAccountsModel); + + } catch (Throwable t) { + log.error("Unable to load user accounts model from DB", t); + ss.fatal(this, "Unable to load user accounts model from DB", t); + } + } + +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/WebappDaoSDBSetup.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/WebappDaoSDBSetup.java new file mode 100644 index 000000000..dfd27f819 --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/WebappDaoSDBSetup.java @@ -0,0 +1,265 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.vitro.webapp.servlet.setup; + +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +import javax.servlet.ServletContext; +import javax.servlet.ServletContextEvent; + +import org.apache.commons.dbcp.BasicDataSource; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import com.hp.hpl.jena.ontology.OntModel; +import com.hp.hpl.jena.ontology.OntModelSpec; +import com.hp.hpl.jena.rdf.model.Model; +import com.hp.hpl.jena.rdf.model.ModelFactory; +import com.hp.hpl.jena.rdf.model.ResIterator; +import com.hp.hpl.jena.rdf.model.Resource; +import com.hp.hpl.jena.rdf.model.ResourceFactory; +import com.hp.hpl.jena.rdf.model.Statement; +import com.hp.hpl.jena.sdb.StoreDesc; +import com.hp.hpl.jena.shared.Lock; +import com.hp.hpl.jena.util.ResourceUtils; +import com.hp.hpl.jena.util.iterator.ClosableIterator; +import com.hp.hpl.jena.vocabulary.RDF; + +import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary; +import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory; +import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactoryConfig; +import edu.cornell.mannlib.vitro.webapp.dao.jena.ModelContext; +import edu.cornell.mannlib.vitro.webapp.dao.jena.OntModelSelector; +import edu.cornell.mannlib.vitro.webapp.dao.jena.OntModelSelectorImpl; +import edu.cornell.mannlib.vitro.webapp.dao.jena.VitroJenaModelMaker; +import edu.cornell.mannlib.vitro.webapp.dao.jena.VitroJenaSDBModelMaker; +import edu.cornell.mannlib.vitro.webapp.dao.jena.VitroModelSource; +import edu.cornell.mannlib.vitro.webapp.dao.jena.WebappDaoFactorySDB; +import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus; + +/** + * Primarily sets up webapp DAO factories. + */ +public class WebappDaoSDBSetup extends JenaDataSourceSetupBase + implements javax.servlet.ServletContextListener { + + private static final Log log = LogFactory.getLog(WebappDaoSDBSetup.class); + + @Override + public void contextInitialized(ServletContextEvent sce) { + ServletContext ctx = sce.getServletContext(); + StartupStatus ss = StartupStatus.getBean(ctx); + + try { + long startTime = System.currentTimeMillis(); + setUpJenaDataSource(ctx, ss); + log.info((System.currentTimeMillis() - startTime) / 1000 + + " seconds to set up SDB store"); + } catch (SQLException sqle) { + // SQL exceptions are fatal and should halt startup + log.error("Error using SQL database; startup aborted.", sqle); + ss.fatal(this, "Error using SQL database; startup aborted.", sqle); + } catch (Throwable t) { + log.error("Throwable in " + this.getClass().getName(), t); + ss.fatal(this, "Throwable in " + this.getClass().getName(), t); + } + + } + + private void setUpJenaDataSource(ServletContext ctx, StartupStatus ss) throws SQLException { + + BasicDataSource bds = getApplicationDataSource(ctx); + if( bds == null ){ + ss.fatal(this, "A DataSource must be setup before "+ WebappDaoSDBSetup.class.getName() + + "is run. Make sure that JenaPersistentDataSourceSetup runs before "+ + WebappDaoSDBSetup.class.getName() ); + return; + } + + //Get the OntModelSelectors + OntModelSelectorImpl baseOms = + (OntModelSelectorImpl) ModelContext.getBaseOntModelSelector(ctx); + OntModelSelectorImpl inferenceOms = + (OntModelSelectorImpl) ModelContext.getInferenceOntModelSelector(ctx); + OntModelSelectorImpl unionOms = + (OntModelSelectorImpl) ModelContext.getUnionOntModelSelector(ctx); + + /////////////////////////////////////////////////////////////// + // Check for namespace mismatch + + checkForNamespaceMismatch( baseOms.getApplicationMetadataModel(), ctx ); + ctx.setAttribute("defaultNamespace", getDefaultNamespace(ctx)); + + /////////////////////////////////////////////////////////////// + // first startup? + + if (isFirstStartup()) { + loadDataFromFilesystem(baseOms, ctx); + } + + log.info("Setting up DAO factories"); + + /////////////////////////////////////////////////////////////// + //create assertions webapp DAO factory + + StoreDesc storeDesc = getApplicationStoreDesc(ctx); + WebappDaoFactoryConfig config = new WebappDaoFactoryConfig(); + config.setDefaultNamespace(getDefaultNamespace(ctx)); + WebappDaoFactory baseWadf = new WebappDaoFactorySDB( + baseOms, bds, storeDesc, config, + WebappDaoFactorySDB.SDBDatasetMode.ASSERTIONS_ONLY); + ctx.setAttribute("assertionsWebappDaoFactory",baseWadf); + + /////////////////////////////////////////////////////////////// + //create inference webapp DAO factory + + OntModel inferenceUnion = ModelFactory.createOntologyModel( + OntModelSpec.OWL_MEM, + ModelFactory.createUnion( + inferenceOms.getABoxModel(), + inferenceOms.getTBoxModel())); + inferenceOms.setFullModel(inferenceUnion); + ModelContext.setInferenceOntModel(inferenceOms.getFullModel(), ctx); + WebappDaoFactory infWadf = new WebappDaoFactorySDB( + inferenceOms, bds, storeDesc, config, + WebappDaoFactorySDB.SDBDatasetMode.INFERENCES_ONLY); + ctx.setAttribute("deductionsWebappDaoFactory", infWadf); + + /////////////////////////////////////////////////////////////// + //create default union webapp DAO factory + + OntModel masterUnion = ModelFactory.createOntologyModel( + DB_ONT_MODEL_SPEC, makeDBModel( + bds, WebappDaoFactorySDB.UNION_GRAPH, + DB_ONT_MODEL_SPEC, TripleStoreType.SDB, ctx)); + unionOms.setFullModel(masterUnion); + ctx.setAttribute("jenaOntModel", masterUnion); + WebappDaoFactory wadf = new WebappDaoFactorySDB( + unionOms, bds, storeDesc, config); + ctx.setAttribute("webappDaoFactory",wadf); + + makeModelMakerFromConnectionProperties(TripleStoreType.RDB, ctx); + VitroJenaModelMaker vjmm = getVitroJenaModelMaker(); + setVitroJenaModelMaker(vjmm, ctx); + makeModelMakerFromConnectionProperties(TripleStoreType.SDB, ctx); + VitroJenaSDBModelMaker vsmm = getVitroJenaSDBModelMaker(); + setVitroJenaSDBModelMaker(vsmm, ctx); + + //bdc34: I have no reason for vsmm vs vjmm. + //I don't know what are the implications of this choice. + setVitroModelSource( new VitroModelSource(vsmm,ctx), ctx); + + log.info("DAOs set up"); + } + + + /** + * If we find a "portal1" portal (and we should), its URI should use the + * default namespace. + */ + private void checkForNamespaceMismatch(OntModel model, ServletContext ctx) { + String expectedNamespace = getDefaultNamespace(ctx); + + List portals = getPortal1s(model); + + if(!portals.isEmpty() && noPortalForNamespace( + portals, expectedNamespace)) { + // There really should be only one portal 1, but if there happen to + // be multiple, just arbitrarily pick the first in the list. + Resource portal = portals.get(0); + String oldNamespace = portal.getNameSpace(); + renamePortal(portal, expectedNamespace, model); + StartupStatus ss = StartupStatus.getBean(ctx); + ss.warning(this, "\nThe default namespace has been changed \n" + + "from " + oldNamespace + + "\nto " + expectedNamespace + ".\n" + + "The application will function normally, but " + + "any individuals in the \n" + oldNamespace + " " + + "namespace will need to have their URIs \n" + + "changed in order to be served as linked data. " + + "You can use the Ingest Tools \nto change the " + + "URIs for a batch of resources."); + } + } + + private List getPortal1s(Model model) { + List portals = new ArrayList(); + try { + model.enterCriticalSection(Lock.READ); + ResIterator portalIt = model.listResourcesWithProperty( + RDF.type, PORTAL); + while (portalIt.hasNext()) { + Resource portal = portalIt.nextResource(); + if ("portal1".equals(portal.getLocalName())) { + portals.add(portal); + } + } + } finally { + model.leaveCriticalSection(); + } + return portals; + } + + private boolean noPortalForNamespace(List portals, + String expectedNamespace) { + for (Resource portal : portals) { + if(expectedNamespace.equals(portal.getNameSpace())) { + return false; + } + } + return true; + } + + private void renamePortal(Resource portal, String namespace, Model model) { + model.enterCriticalSection(Lock.WRITE); + try { + ResourceUtils.renameResource( + portal, namespace + portal.getLocalName()); + } finally { + model.leaveCriticalSection(); + } + } + + + /* ===================================================================== */ + + + @Override + public void contextDestroyed(ServletContextEvent sce) { + // Nothing to do. + } + + private boolean isEmpty(Model model) { + ClosableIterator closeIt = model.listStatements( + null, RDF.type, ResourceFactory.createResource( + VitroVocabulary.PORTAL)); + try { + if (closeIt.hasNext()) { + return false; + } else { + return true; + } + } finally { + closeIt.close(); + } + } + + private void loadDataFromFilesystem(OntModelSelector baseOms, + ServletContext ctx) { + Long startTime = System.currentTimeMillis(); + log.debug("Initializing models from RDF files"); + readOntologyFilesInPathSet(USER_ABOX_PATH, ctx, baseOms.getABoxModel()); + readOntologyFilesInPathSet(USER_TBOX_PATH, ctx, baseOms.getTBoxModel()); + readOntologyFilesInPathSet( + USER_APPMETA_PATH, ctx, baseOms.getApplicationMetadataModel()); + log.debug(((System.currentTimeMillis() - startTime) / 1000) + + " seconds to read RDF files "); + } + + + + + } + diff --git a/webapp/test/edu/cornell/mannlib/vitro/webapp/edit/elements/DateTimeWithPrecisionTest.java b/webapp/test/edu/cornell/mannlib/vitro/webapp/edit/elements/DateTimeWithPrecisionTest.java deleted file mode 100644 index 925eb78b5..000000000 --- a/webapp/test/edu/cornell/mannlib/vitro/webapp/edit/elements/DateTimeWithPrecisionTest.java +++ /dev/null @@ -1,423 +0,0 @@ -/* $This file is distributed under the terms of the license in /doc/license.txt$ */ - -package edu.cornell.mannlib.vitro.webapp.edit.elements; - -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.TimeZone; - -import org.joda.time.DateTime; -import org.joda.time.DateTimeZone; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import org.junit.runners.Parameterized.Parameters; - -import com.hp.hpl.jena.datatypes.xsd.XSDDatatype; -import com.hp.hpl.jena.datatypes.xsd.XSDDateTime; -import com.hp.hpl.jena.rdf.model.Literal; -import com.hp.hpl.jena.rdf.model.ResourceFactory; - -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; - - -@RunWith(value= Parameterized.class) -public class DateTimeWithPrecisionTest { - - TimeZone orginalTimeZone; - TimeZone testZone; - - public DateTimeWithPrecisionTest(TimeZone tz){ - orginalTimeZone = TimeZone.getDefault(); - testZone = tz; - } - - @Parameters - public static Collection data(){ - String allZones[] = TimeZone.getAvailableIDs(); - ArrayList data = new ArrayList( allZones.length ); - for( String zoneId : allZones ){ - Object v[] = new Object[1]; - v[0] = TimeZone.getTimeZone(zoneId); - try{ - DateTimeZone dtz = DateTimeZone.forID(zoneId); - if( dtz != null ){ - data.add(v); - } - }catch(IllegalArgumentException ex){ - //cannot convert to joda datetimezone. - } - } - return data; - } - - @Before - public void beforeTest(){ - TimeZone.setDefault( testZone ); - } - - @After - public void after(){ - if( orginalTimeZone != null){ - TimeZone.setDefault(orginalTimeZone); - } - } - - @Test - public void fieldNameTemplateVariableTest() throws Exception{ - String FIELDNAME = "testfield"; - Field field = new Field(); - field.setName(FIELDNAME); - DateTimeWithPrecision dtwp = new DateTimeWithPrecision(field); - - EditSubmission editSub = null; - EditConfiguration editConfig = new EditConfiguration(); - editConfig.setUrisInScope(Collections.EMPTY_MAP); - editConfig.setLiteralsInScope(Collections.EMPTY_MAP); - - Map templateVars = dtwp.getMapForTemplate(editConfig, editSub); - Assert.assertNotNull(templateVars); - - Assert.assertTrue( templateVars.containsKey("fieldName") ); - Assert.assertEquals(templateVars.get("fieldName"), "testfield"); - } - - @Test - public void precisionSecondsValidationTest() throws Exception{ - String FIELDNAME = "testfield"; - Field field = new Field(); - field.setName(FIELDNAME); - DateTimeWithPrecision dtwp = new DateTimeWithPrecision(field); - - Map queryParameters = new HashMap(); - queryParameters.put(FIELDNAME+"-year", new String[]{"1999" }); - queryParameters.put(FIELDNAME+"-month", new String[]{"12"}); - queryParameters.put(FIELDNAME+"-day", new String[]{"01"}); - queryParameters.put(FIELDNAME+"-hour", new String[]{"12"}); - queryParameters.put(FIELDNAME+"-minute", new String[]{"00"}); - queryParameters.put(FIELDNAME+"-second", new String[]{"00"}); - EditConfiguration editConfig=null; - Map validationMsgs = dtwp.getValidationMessages("testfield", editConfig, queryParameters); - Assert.assertNotNull(validationMsgs); - Assert.assertTrue(validationMsgs.size() == 0 ); - - String precisionURI = null; - precisionURI = dtwp.getSubmittedPrecision( queryParameters); - - Assert.assertNotNull(precisionURI); - Assert.assertEquals(VitroVocabulary.Precision.SECOND.uri(), precisionURI); - } - - @Test - public void precisionMinutesValidationTest() throws Exception{ - String FIELDNAME = "testfield"; - Field field = new Field(); - field.setName(FIELDNAME); - DateTimeWithPrecision dtwp = new DateTimeWithPrecision(field); - - Map queryParameters = new HashMap(); - queryParameters.put(FIELDNAME+"-year", new String[]{"1999" }); - queryParameters.put(FIELDNAME+"-month", new String[]{"12"}); - queryParameters.put(FIELDNAME+"-day", new String[]{"01"}); - queryParameters.put(FIELDNAME+"-hour", new String[]{"12"}); - queryParameters.put(FIELDNAME+"-minute", new String[]{"00"}); - //no seconds - - EditConfiguration editConfig=null; - Map validationMsgs = dtwp.getValidationMessages("testfield", editConfig, queryParameters); - Assert.assertNotNull(validationMsgs); - Assert.assertTrue(validationMsgs.size() == 0 ); - - String precisionURI = null; - precisionURI = dtwp.getSubmittedPrecision( queryParameters); - - Assert.assertNotNull(precisionURI); - Assert.assertEquals(VitroVocabulary.Precision.MINUTE.uri(), precisionURI); - } - - @Test - public void precisionHoursValidationTest() throws Exception{ - String FIELDNAME = "testfield"; - Field field = new Field(); - field.setName(FIELDNAME); - DateTimeWithPrecision dtwp = new DateTimeWithPrecision(field); - - Map queryParameters = new HashMap(); - queryParameters.put(FIELDNAME+"-year", new String[]{"1999" }); - queryParameters.put(FIELDNAME+"-month", new String[]{"12"}); - queryParameters.put(FIELDNAME+"-day", new String[]{"01"}); - queryParameters.put(FIELDNAME+"-hour", new String[]{"12"}); - //no minutes - //no seconds - - EditConfiguration editConfig=null; - Map validationMsgs = dtwp.getValidationMessages("testfield", editConfig, queryParameters); - Assert.assertNotNull(validationMsgs); - Assert.assertTrue(validationMsgs.size() == 0 ); - - String precisionURI = null; - precisionURI = dtwp.getSubmittedPrecision( queryParameters); - - Assert.assertNotNull(precisionURI); - Assert.assertEquals(VitroVocabulary.Precision.HOUR.uri(), precisionURI); - } - - @Test - public void precisionDaysValidationTest() throws Exception{ - String FIELDNAME = "testfield"; - Field field = new Field(); - field.setName(FIELDNAME); - DateTimeWithPrecision dtwp = new DateTimeWithPrecision(field); - - Map queryParameters = new HashMap(); - queryParameters.put(FIELDNAME+"-year", new String[]{"1999" }); - queryParameters.put(FIELDNAME+"-month", new String[]{"12"}); - queryParameters.put(FIELDNAME+"-day", new String[]{"01"}); - //no hours - //no minutes - //no seconds - - EditConfiguration editConfig=null; - Map validationMsgs = dtwp.getValidationMessages("testfield", editConfig, queryParameters); - Assert.assertNotNull(validationMsgs); - Assert.assertTrue(validationMsgs.size() == 0 ); - - String precisionURI = null; - precisionURI = dtwp.getSubmittedPrecision( queryParameters); - - Assert.assertNotNull(precisionURI); - Assert.assertEquals(VitroVocabulary.Precision.DAY.uri(), precisionURI); - } - - @Test - public void precisionMonthsValidationTest()throws Exception{ - String FIELDNAME = "testfield"; - Field field = new Field(); - field.setName(FIELDNAME); - DateTimeWithPrecision dtwp = new DateTimeWithPrecision(field); - - Map queryParameters = new HashMap(); - queryParameters.put(FIELDNAME+"-year", new String[]{"1999" }); - queryParameters.put(FIELDNAME+"-month", new String[]{"12"}); - //no days - //no hours - //no minutes - //no seconds - - EditConfiguration editConfig=null; - Map validationMsgs = dtwp.getValidationMessages("testfield", editConfig, queryParameters); - Assert.assertNotNull(validationMsgs); - Assert.assertTrue(validationMsgs.size() == 0 ); - - String precisionURI = null; - precisionURI = dtwp.getSubmittedPrecision( queryParameters); - - Assert.assertNotNull(precisionURI); - Assert.assertEquals(VitroVocabulary.Precision.MONTH.uri(), precisionURI); - } - - @Test - public void precisionYearValidationTest() throws Exception{ - String FIELDNAME = "testfield"; - Field field = new Field(); - field.setName(FIELDNAME); - DateTimeWithPrecision dtwp = new DateTimeWithPrecision(field); - - Map queryParameters = new HashMap(); - queryParameters.put(FIELDNAME+"-year", new String[]{"1999" }); - //no months - //no days - //no hours - //no minutes - //no seconds - - EditConfiguration editConfig=null; - Map validationMsgs = dtwp.getValidationMessages("testfield", editConfig, queryParameters); - Assert.assertNotNull(validationMsgs); - Assert.assertTrue(validationMsgs.size() == 0 ); - - String precisionURI = null; - precisionURI = dtwp.getSubmittedPrecision( queryParameters); - - Assert.assertNotNull(precisionURI); - Assert.assertEquals(VitroVocabulary.Precision.YEAR.uri(), precisionURI); - } - - @Test - public void precisionNoValueTest() throws Exception{ - String FIELDNAME = "testfield"; - Field field = new Field(); - field.setName(FIELDNAME); - DateTimeWithPrecision dtwp = new DateTimeWithPrecision(field); - - Map queryParameters = new HashMap(); - //field is not filled out at all - //no year - //no months - //no days - //no hours - //no minutes - //no seconds - - EditConfiguration editConfig=null; - Map validationMsgs = dtwp.getValidationMessages("testfield", editConfig, queryParameters); - Assert.assertNotNull(validationMsgs); - Assert.assertTrue(validationMsgs.size() == 0 ); - - String precisionURI = null; - - precisionURI = dtwp.getSubmittedPrecision( queryParameters ); - - Assert.assertNotNull(precisionURI); - Assert.assertEquals(dtwp.BLANK_SENTINEL, precisionURI); - - Literal date = dtwp.getDateTime( queryParameters); - Assert.assertNull(date); - } - - @Test - public void getDateLiteralTest(){ - String FIELDNAME = "testfield"; - Field field = new Field(); - field.setName(FIELDNAME); - DateTimeWithPrecision dtwp = new DateTimeWithPrecision(field); - - Map queryParameters = new HashMap(); - queryParameters.put(FIELDNAME+"-year", new String[]{"1999" }); - //no months - //no days - //no hours - //no minutes - //no seconds - - EditConfiguration editConfig=null; - Map validationMsgs = dtwp.getValidationMessages("testfield", editConfig, queryParameters); - Assert.assertNotNull(validationMsgs); - Assert.assertTrue(validationMsgs.size() == 0 ); - - Literal date = dtwp.getDateTime( queryParameters); - Assert.assertNotNull(date); - Assert.assertEquals( XSDDatatype.XSDdateTime.getURI() ,date.getDatatypeURI() ); - - Object obj = date.getValue(); - Assert.assertNotNull(obj); - Assert.assertEquals(XSDDateTime.class, obj.getClass()); - - DateTime result = new DateTime( date.getLexicalForm()); - DateTime expected = new DateTime(1999,1,1,0,0,0,0 ); - Assert.assertEquals(expected.toInstant() , result.toInstant()); - - Assert.assertEquals("1999-01-01T00:00:00" , date.getLexicalForm() ); - } - - - @Test - public void day30Test() throws Exception{ - String FIELDNAME = "testfield"; - Field field = new Field(); - field.setName(FIELDNAME); - DateTimeWithPrecision dtwp = new DateTimeWithPrecision(field); - - - /* Check if it works with day number under 29 */ - Map queryParameters = new HashMap(); - queryParameters.put(FIELDNAME+"-year", new String[]{"1999" }); - queryParameters.put(FIELDNAME+"-month", new String[]{"12"}); - queryParameters.put(FIELDNAME+"-day", new String[]{"28"}); - - Map validationMsgs = dtwp.getValidationMessages("testfield", (EditConfiguration)null, queryParameters); - Assert.assertNotNull(validationMsgs); - Assert.assertTrue(validationMsgs.size() == 0 ); - - String precisionURI = dtwp.getSubmittedPrecision( queryParameters); - Assert.assertNotNull(precisionURI); - Assert.assertEquals(VitroVocabulary.Precision.DAY.uri(), precisionURI); - - /* Check for days greater than 28 */ - queryParameters = new HashMap(); - queryParameters.put(FIELDNAME+"-year", new String[]{"1999" }); - queryParameters.put(FIELDNAME+"-month", new String[]{"12"}); - queryParameters.put(FIELDNAME+"-day", new String[]{"30"}); - - validationMsgs = dtwp.getValidationMessages("testfield", (EditConfiguration)null, queryParameters); - Assert.assertNotNull(validationMsgs); - Assert.assertTrue(validationMsgs.size() == 0 ); - - precisionURI = dtwp.getSubmittedPrecision( queryParameters); - Assert.assertNotNull(precisionURI); - Assert.assertEquals(VitroVocabulary.Precision.DAY.uri(), precisionURI); - - /* Check for leap year */ - queryParameters = new HashMap(); - queryParameters.put(FIELDNAME+"-year", new String[]{"2000" }); - queryParameters.put(FIELDNAME+"-month", new String[]{"2"}); - queryParameters.put(FIELDNAME+"-day", new String[]{"29"}); - - validationMsgs = dtwp.getValidationMessages("testfield", (EditConfiguration)null, queryParameters); - Assert.assertNotNull(validationMsgs); - Assert.assertTrue(validationMsgs.size() == 0 ); - - precisionURI = dtwp.getSubmittedPrecision( queryParameters); - Assert.assertNotNull(precisionURI); - Assert.assertEquals(VitroVocabulary.Precision.DAY.uri(), precisionURI); - - /* check for non leap year */ - queryParameters = new HashMap(); - queryParameters.put(FIELDNAME+"-year", new String[]{"1999" }); - queryParameters.put(FIELDNAME+"-month", new String[]{"2"}); - queryParameters.put(FIELDNAME+"-day", new String[]{"29"}); - - validationMsgs = dtwp.getValidationMessages("testfield", (EditConfiguration)null, queryParameters); - Assert.assertNotNull(validationMsgs); - Assert.assertTrue(validationMsgs.size() > 0 ); - - precisionURI = dtwp.getSubmittedPrecision( queryParameters); - Assert.assertNotNull(precisionURI); - Assert.assertEquals(VitroVocabulary.Precision.DAY.uri(), precisionURI); - } - - - @Test - public void basicGetMapForTemplateTest() throws Exception{ - String FIELDNAME = "testfield"; - Field field = new Field(); - field.setName(FIELDNAME); - DateTimeWithPrecision dtwp = new DateTimeWithPrecision(field); - - EditConfiguration config = new EditConfiguration(); - EditSubmission sub = null; - - Map urisInScope = new HashMap(); - urisInScope.put(dtwp.getPrecisionVariableName(), - VitroVocabulary.Precision.MINUTE.uri()); - config.setUrisInScope(urisInScope); - - Map literalsInScope = new HashMap(); - literalsInScope.put(dtwp.getValueVariableName(), - ResourceFactory.createTypedLiteral("1999-02-15T10:00",XSDDatatype.XSDdateTime) ); - config.setLiteralsInScope(literalsInScope); - - Map map = dtwp.getMapForTemplate(config,sub); - Assert.assertEquals("year wrong", "1999", map.get("year")); - Assert.assertEquals("month wrong", "2", map.get("month")); - Assert.assertEquals("day wrong", "15", map.get("day")); - Assert.assertEquals("hour wrong", "10", map.get("hour")); - Assert.assertEquals("minute wrong", "0", map.get("minute")); - Assert.assertEquals("second wrong", "", map.get("second")); - - Assert.assertEquals("precision wrong", VitroVocabulary.Precision.MINUTE.uri(), map.get("existingPrecision")); - - Assert.assertEquals("fieldname wrong", FIELDNAME, map.get("fieldName")); - } - -} diff --git a/webapp/web/WEB-INF/resources/startup_listeners.txt b/webapp/web/WEB-INF/resources/startup_listeners.txt index 7396c2ea7..03d60bdf9 100644 --- a/webapp/web/WEB-INF/resources/startup_listeners.txt +++ b/webapp/web/WEB-INF/resources/startup_listeners.txt @@ -7,18 +7,22 @@ edu.cornell.mannlib.vitro.webapp.config.ConfigurationPropertiesSetup -edu.cornell.mannlib.vitro.webapp.servlet.setup.BasicSmokeTests +edu.cornell.mannlib.vitro.webapp.config.ConfigurationPropertiesSmokeTests edu.cornell.mannlib.vitro.webapp.config.RevisionInfoSetup edu.cornell.mannlib.vitro.webapp.email.FreemarkerEmailFactory$Setup -# Comment out this listener to run Vitro without a database -# If used, this listener must be run before JenaDataSourceSetup +### this listener must be run before SDBSetup, all models setups and WebappDaoSetup ### edu.cornell.mannlib.vitro.webapp.servlet.setup.JenaPersistentDataSourceSetup + +edu.cornell.mannlib.vitro.webapp.servlet.setup.SDBSetup -# This listener is required in order to use a Jena triple store (currently the only option) -edu.cornell.mannlib.vitro.webapp.servlet.setup.JenaDataSourceSetup +edu.cornell.mannlib.vitro.webapp.servlet.setup.ApplicationModelSetup +edu.cornell.mannlib.vitro.webapp.servlet.setup.UserModelSetup +edu.cornell.mannlib.vitro.webapp.servlet.setup.ModelSetup + +edu.cornell.mannlib.vitro.webapp.servlet.setup.WebappDaoSDBSetup edu.cornell.mannlib.vitro.webapp.servlet.setup.UpdateKnowledgeBase