various dev work on language filtering and querying from a generic endpoint
This commit is contained in:
commit
376c7be7c3
110 changed files with 2372 additions and 3963 deletions
|
@ -116,6 +116,16 @@ deploy - Deploy the application directly into the Tomcat webapps directory.
|
|||
</condition>
|
||||
</fail>
|
||||
|
||||
<fail message="The vitro.home.directory "${vitro.home.directory}" is not writable.">
|
||||
<condition>
|
||||
<not>
|
||||
<isfileselected file="${vitro.home.directory}" >
|
||||
<writable/>
|
||||
</isfileselected>
|
||||
</not>
|
||||
</condition>
|
||||
</fail>
|
||||
|
||||
<property name="solr.home.dir" location="${vitro.home.directory}/solr" />
|
||||
</target>
|
||||
|
||||
|
|
|
@ -133,6 +133,9 @@ webapp/web/WEB-INF/tlds/taglibs-string.tld
|
|||
webapp/web/themes/enhanced/css/blueprint/grid.css
|
||||
webapp/web/themes/enhanced/css/blueprint/ie.css
|
||||
|
||||
# See /doc/3rd-party-licenses.txt for LICENSE file
|
||||
webapp/web/css/jquery_plugins/jquery.realperson.css
|
||||
|
||||
# PROBLEM: Can't find any info on licensing.
|
||||
webapp/web/themes/enhanced/css/blueprint/liquid.css
|
||||
|
||||
|
|
|
@ -441,14 +441,14 @@ public class OperationController extends BaseEditController {
|
|||
} catch (InvocationTargetException e) {
|
||||
log.error(this.getClass().getName()+" encountered exception performing two-stage update");
|
||||
Throwable innerE = e.getTargetException();
|
||||
log.error(innerE);
|
||||
log.error(innerE, innerE);
|
||||
if (innerE.getMessage()!=null) {
|
||||
log.error(innerE.getMessage());
|
||||
//log.error(innerE.getMessage());
|
||||
epo.setAttribute("globalErrorMsg",innerE.getMessage());
|
||||
}
|
||||
return FAILURE;
|
||||
} catch (IllegalAccessException iae) {
|
||||
log.error(iae);
|
||||
log.error(iae, iae);
|
||||
epo.setAttribute("globalErrorMessage", "Illegal access - see error logs.");
|
||||
return FAILURE;
|
||||
}
|
||||
|
@ -459,15 +459,15 @@ public class OperationController extends BaseEditController {
|
|||
log.error(this.getClass().getName()+" encountered exception performing edit action");
|
||||
Throwable innerE = e.getTargetException();
|
||||
//innerE.printStackTrace();
|
||||
log.error(innerE);
|
||||
log.error(innerE, innerE);
|
||||
if (innerE.getMessage()!=null) {
|
||||
//System.out.println(innerE.getMessage());
|
||||
log.error(innerE.getMessage());
|
||||
//log.error(innerE.getMessage());
|
||||
epo.setAttribute("globalErrorMsg",innerE.getMessage());
|
||||
}
|
||||
return FAILURE;
|
||||
} catch (IllegalAccessException iae) {
|
||||
log.error(iae);
|
||||
log.error(iae, iae);
|
||||
epo.setAttribute("globalErrorMessage", "Illegal access - see error logs.");
|
||||
return FAILURE;
|
||||
}
|
||||
|
|
|
@ -84,6 +84,8 @@ public class SimplePermission extends Permission {
|
|||
"UseMiscellaneousEditorPages");
|
||||
public static final SimplePermission USE_MISCELLANEOUS_PAGES = new SimplePermission(
|
||||
"UseMiscellaneousPages");
|
||||
public static final SimplePermission USE_SPARQL_QUERY_PAGE = new SimplePermission(
|
||||
"UseSparqlQueryPage");
|
||||
|
||||
public static List<SimplePermission> getAllInstances() {
|
||||
return new ArrayList<SimplePermission>(allInstances.values());
|
||||
|
|
|
@ -7,10 +7,6 @@ public interface ObjectPropertyStatement {
|
|||
|
||||
public String toString();
|
||||
|
||||
public boolean isSubjectOriented();
|
||||
|
||||
public void setSubjectOriented(boolean subjectOriented);
|
||||
|
||||
public String getSubjectURI();
|
||||
|
||||
public void setSubjectURI(String subjectURI);
|
||||
|
|
|
@ -18,9 +18,7 @@ public class ObjectPropertyStatementImpl implements ObjectPropertyStatement
|
|||
|
||||
private String propertyURI = null;
|
||||
private ObjectProperty property = null;
|
||||
private String qualifier = null;
|
||||
private boolean subjectOriented = true; //is the range the item of interest?
|
||||
private String description = null; //generated desc based on subjectOriented during sql query.
|
||||
|
||||
public ObjectPropertyStatementImpl() { }
|
||||
|
||||
|
@ -37,23 +35,7 @@ public class ObjectPropertyStatementImpl implements ObjectPropertyStatement
|
|||
String prop = (getProperty()!=null)?getProperty().getDomainPublic():"by propURI"+getPropertyURI();
|
||||
String ran = (getObject()!= null)?getObject().getName():"objectURI:"+getObjectURI();
|
||||
String dom = (getSubject()!= null)?getSubject().getName():"subjectURI:"+getSubjectURI();
|
||||
String orent = (isSubjectOriented() )?"subject oriented":"object oriented";
|
||||
return "Object Property Statements: "+dom+" "+prop+" to "+ran+" "+orent;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see edu.cornell.mannlib.vitro.webapp.beans.ObjectPropertyStatement#isSubjectOriented()
|
||||
*/
|
||||
public boolean isSubjectOriented() {
|
||||
return subjectOriented;
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see edu.cornell.mannlib.vitro.webapp.beans.ObjectPropertyStatement#setSubjectOriented(boolean)
|
||||
*/
|
||||
public void setSubjectOriented(boolean subjectOriented) {
|
||||
this.subjectOriented = subjectOriented;
|
||||
return "Object Property Statements: "+dom+" "+prop+" to "+ran+" ";
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
@ -100,6 +82,11 @@ public class ObjectPropertyStatementImpl implements ObjectPropertyStatement
|
|||
*/
|
||||
public void setSubject(Individual subject) {
|
||||
this.subject = subject;
|
||||
if (subject == null || subject.isAnonymous()) {
|
||||
setSubjectURI(null);
|
||||
} else {
|
||||
setSubjectURI(subject.getURI());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -136,6 +123,11 @@ public class ObjectPropertyStatementImpl implements ObjectPropertyStatement
|
|||
*/
|
||||
public void setObject(Individual object) {
|
||||
this.object = object;
|
||||
if (object == null || object.isAnonymous()) {
|
||||
setObjectURI(null);
|
||||
} else {
|
||||
setObjectURI(object.getURI());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -133,9 +133,15 @@ public class VClass extends BaseResourceBean implements Comparable<VClass>
|
|||
* Sorts alphabetically by name
|
||||
*/
|
||||
public int compareTo (VClass o1) {
|
||||
if (this.getName() == null) {
|
||||
return 1;
|
||||
} else if (o1.getName() == null) {
|
||||
return -1;
|
||||
} else {
|
||||
Collator collator = Collator.getInstance();
|
||||
return collator.compare(this.getName(),o1.getName());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the VClass to a string
|
||||
|
|
|
@ -128,8 +128,6 @@ public class MailUsersServlet extends VitroHttpServlet {
|
|||
msgBuf.append("</html>" + lineSeparator );
|
||||
|
||||
String msgText = msgBuf.toString();
|
||||
// debugging
|
||||
//PrintWriter outFile = new PrintWriter (new FileWriter(request.getSession().getServletContext().getRealPath("/WEB-INF/LatestMessage.html"),true)); //autoflush
|
||||
|
||||
Calendar cal = Calendar.getInstance();
|
||||
|
||||
|
|
|
@ -101,7 +101,7 @@ public class SparqlQueryServlet extends BaseEditController {
|
|||
throws ServletException, IOException
|
||||
{
|
||||
if (!isAuthorizedToDisplayPage(request, response,
|
||||
SimplePermission.USE_ADVANCED_DATA_TOOLS_PAGES.ACTIONS)) {
|
||||
SimplePermission.USE_SPARQL_QUERY_PAGE.ACTIONS)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ import com.hp.hpl.jena.query.Dataset;
|
|||
import edu.cornell.mannlib.vitro.webapp.beans.ApplicationBean;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.jena.JenaBaseDao;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.jena.OntModelSelector;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.jena.VitroModelSource.ModelName;
|
||||
|
||||
public class VitroRequest extends HttpServletRequestWrapper {
|
||||
|
@ -78,6 +79,10 @@ public class VitroRequest extends HttpServletRequestWrapper {
|
|||
setAttribute("jenaOntModel", ontModel);
|
||||
}
|
||||
|
||||
public void setOntModelSelector(OntModelSelector oms) {
|
||||
setAttribute("ontModelSelector", oms);
|
||||
}
|
||||
|
||||
/** gets assertions + inferences WebappDaoFactory with no filtering **/
|
||||
public WebappDaoFactory getFullWebappDaoFactory() {
|
||||
Object webappDaoFactoryAttr = _req.getAttribute("fullWebappDaoFactory");
|
||||
|
@ -97,10 +102,24 @@ public class VitroRequest extends HttpServletRequestWrapper {
|
|||
public WebappDaoFactory getAssertionsWebappDaoFactory() {
|
||||
Object webappDaoFactoryAttr = _req.getSession().getAttribute("assertionsWebappDaoFactory");
|
||||
if (webappDaoFactoryAttr instanceof WebappDaoFactory) {
|
||||
log.info("Returning assertionsWebappDaoFactory from session");
|
||||
return (WebappDaoFactory) webappDaoFactoryAttr;
|
||||
} else {
|
||||
webappDaoFactoryAttr = getAttribute("assertionsWebappDaoFactory");
|
||||
if (webappDaoFactoryAttr instanceof WebappDaoFactory) {
|
||||
log.info("returning assertionsWebappDaoFactory from request attribute");
|
||||
return (WebappDaoFactory) webappDaoFactoryAttr;
|
||||
} else {
|
||||
log.info("Returning assertionsWebappDaoFactory from context");
|
||||
return (WebappDaoFactory) _req.getSession().getServletContext().getAttribute("assertionsWebappDaoFactory");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/** gets assertions-only WebappDaoFactory with no filtering */
|
||||
public void setAssertionsWebappDaoFactory(WebappDaoFactory wadf) {
|
||||
setAttribute("assertionsWebappDaoFactory", wadf);
|
||||
}
|
||||
|
||||
/** gets inferences-only WebappDaoFactory with no filtering */
|
||||
|
@ -137,6 +156,16 @@ public class VitroRequest extends HttpServletRequestWrapper {
|
|||
return jenaOntModel;
|
||||
}
|
||||
|
||||
public OntModelSelector getOntModelSelector() {
|
||||
Object o = this.getAttribute("ontModelSelector");
|
||||
if (o instanceof OntModelSelector) {
|
||||
return (OntModelSelector) o;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public OntModel getAssertionsOntModel() {
|
||||
OntModel jenaOntModel = (OntModel)_req.getSession().getAttribute( JenaBaseDao.ASSERTIONS_ONT_MODEL_ATTRIBUTE_NAME );
|
||||
if ( jenaOntModel == null ) {
|
||||
|
|
|
@ -35,9 +35,6 @@ public abstract class UserAccountsPage extends AbstractPageHandler {
|
|||
|
||||
private static final String PERSON_CLASS_URI = "http://xmlns.com/foaf/0.1/Person";
|
||||
|
||||
private static final String DEFAULT_IMAGE_URL = UrlBuilder
|
||||
.getUrl("/images/placeholders/person.thumbnail.jpg");
|
||||
|
||||
/**
|
||||
* After the account is created, or the password is reset, the user has this
|
||||
* many days to repond to the email.
|
||||
|
@ -109,7 +106,6 @@ public abstract class UserAccountsPage extends AbstractPageHandler {
|
|||
UrlBuilder.getUrl("/accounts/firstTimeExternal"));
|
||||
map.put("accountsAjax", UrlBuilder.getUrl("/accountsAjax"));
|
||||
map.put("proxyAjax", UrlBuilder.getUrl("/proxiesAjax"));
|
||||
map.put("defaultImageUrl", DEFAULT_IMAGE_URL);
|
||||
|
||||
return map;
|
||||
}
|
||||
|
|
|
@ -237,6 +237,7 @@ public class UserAccountsEditPage extends UserAccountsPage {
|
|||
|
||||
if (!isRootUser()) {
|
||||
body.put("roles", buildListOfSelectableRoles());
|
||||
body.put("externalAuthPermitted", Boolean.TRUE);
|
||||
}
|
||||
|
||||
body.put("profileTypes", buildProfileTypesList());
|
||||
|
|
|
@ -24,7 +24,7 @@ import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder;
|
|||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
|
||||
import edu.cornell.mannlib.vitro.webapp.utils.ImageUtil;
|
||||
import edu.cornell.mannlib.vitro.webapp.web.images.PlaceholderUtil;
|
||||
|
||||
/**
|
||||
* TODO
|
||||
|
@ -134,8 +134,8 @@ public class ManageProxiesListPage extends AbstractPageHandler {
|
|||
private ProxyItemInfo wrapProxyItem(ProxyItemInfo item) {
|
||||
String imagePath = item.getImageUrl();
|
||||
if (imagePath.isEmpty()) {
|
||||
imagePath = ImageUtil
|
||||
.getPlaceholderImagePathForType(VitroVocabulary.USERACCOUNT);
|
||||
imagePath = PlaceholderUtil.getPlaceholderImagePathForType(vreq,
|
||||
VitroVocabulary.USERACCOUNT);
|
||||
}
|
||||
|
||||
UserAccount ua = userAccountsDao.getUserAccountByUri(item.getUri());
|
||||
|
@ -151,8 +151,8 @@ public class ManageProxiesListPage extends AbstractPageHandler {
|
|||
private ProxyItemInfo wrapProfileItem(ProxyItemInfo item) {
|
||||
String imagePath = item.getImageUrl();
|
||||
if (imagePath.isEmpty()) {
|
||||
imagePath = ImageUtil.getPlaceholderImagePathForIndividual(vreq,
|
||||
item.getUri());
|
||||
imagePath = PlaceholderUtil.getPlaceholderImagePathForIndividual(
|
||||
vreq, item.getUri());
|
||||
}
|
||||
|
||||
return new ProfileItemWrapper(item.getUri(), item.getLabel(),
|
||||
|
|
|
@ -24,9 +24,9 @@ import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder;
|
|||
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.OntModelSelector;
|
||||
import edu.cornell.mannlib.vitro.webapp.utils.ImageUtil;
|
||||
import edu.cornell.mannlib.vitro.webapp.utils.SparqlQueryRunner;
|
||||
import edu.cornell.mannlib.vitro.webapp.utils.SparqlQueryUtils;
|
||||
import edu.cornell.mannlib.vitro.webapp.web.images.PlaceholderUtil;
|
||||
|
||||
/**
|
||||
* Get the basic auto-complete info for the proxy selection.
|
||||
|
@ -64,8 +64,9 @@ public class BasicProxiesGetter extends AbstractAjaxResponder {
|
|||
OntModelSelector oms = ModelContext.getUnionOntModelSelector(ctx);
|
||||
userAccountsModel = oms.getUserAccountsModel();
|
||||
|
||||
placeholderImageUrl = UrlBuilder.getUrl(ImageUtil
|
||||
.getPlaceholderImagePathForType(VitroVocabulary.USERACCOUNT));
|
||||
placeholderImageUrl = UrlBuilder.getUrl(PlaceholderUtil
|
||||
.getPlaceholderImagePathForType(vreq,
|
||||
VitroVocabulary.USERACCOUNT));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -19,7 +19,7 @@ import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
|||
import edu.cornell.mannlib.vitro.webapp.controller.ajax.AbstractAjaxResponder;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.ObjectPropertyStatementDao;
|
||||
import edu.cornell.mannlib.vitro.webapp.utils.ImageUtil;
|
||||
import edu.cornell.mannlib.vitro.webapp.web.images.PlaceholderUtil;
|
||||
|
||||
/**
|
||||
* Get more information (class label and image URL) about a selected proxy.
|
||||
|
@ -79,7 +79,7 @@ public class MoreProfileInfo extends AbstractAjaxResponder {
|
|||
private String getFullImageUrl(Individual ind) {
|
||||
String path = ind.getThumbUrl();
|
||||
if ((path == null) || path.isEmpty()) {
|
||||
path = ImageUtil.getPlaceholderImagePathForIndividual(vreq,
|
||||
path = PlaceholderUtil.getPlaceholderImagePathForIndividual(vreq,
|
||||
ind.getURI());
|
||||
}
|
||||
return UrlBuilder.getUrl(path);
|
||||
|
|
|
@ -26,6 +26,8 @@ import edu.cornell.mannlib.vitro.webapp.controller.authenticate.Authenticator;
|
|||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
|
||||
import edu.cornell.mannlib.vitro.webapp.web.images.PlaceholderUtil;
|
||||
|
||||
/**
|
||||
* Handle the "My Account" form display and submission.
|
||||
|
@ -268,7 +270,9 @@ public class UserAccountsMyAccountPage extends UserAccountsPage {
|
|||
String userUri = proxyUser.getUri();
|
||||
String label = assembleUserAccountLabel(proxyUser);
|
||||
String classLabel = "";
|
||||
String imageUrl = "";
|
||||
String imageUrl = UrlBuilder.getUrl(PlaceholderUtil
|
||||
.getPlaceholderImagePathForType(vreq,
|
||||
VitroVocabulary.USERACCOUNT));
|
||||
|
||||
// Does this user have a profile? Can we get better info?
|
||||
Individual proxyProfilePage = getProfilePage(proxyUser);
|
||||
|
|
|
@ -16,7 +16,6 @@ import edu.cornell.mannlib.vedit.controller.BaseEditController;
|
|||
import edu.cornell.mannlib.vitro.webapp.auth.permissions.SimplePermission;
|
||||
import edu.cornell.mannlib.vitro.webapp.beans.Classes2Classes;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.Classes2ClassesDao;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.VClassDao;
|
||||
|
||||
public class Classes2ClassesOperationController extends BaseEditController {
|
||||
|
@ -58,7 +57,6 @@ public class Classes2ClassesOperationController extends BaseEditController {
|
|||
return;
|
||||
}
|
||||
|
||||
Classes2ClassesDao dao = request.getFullWebappDaoFactory().getClasses2ClassesDao();
|
||||
VClassDao vcDao = request.getFullWebappDaoFactory().getVClassDao();
|
||||
|
||||
String modeStr = request.getParameter("opMode");
|
||||
|
@ -81,7 +79,7 @@ public class Classes2ClassesOperationController extends BaseEditController {
|
|||
Classes2Classes c2c = new Classes2Classes();
|
||||
c2c.setSubclassURI(subclassURIstrs[i]);
|
||||
c2c.setSuperclassURI(superclassURIstr);
|
||||
dao.deleteClasses2Classes(c2c);
|
||||
vcDao.deleteClasses2Classes(c2c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -98,7 +96,7 @@ public class Classes2ClassesOperationController extends BaseEditController {
|
|||
Classes2Classes c2c = new Classes2Classes();
|
||||
c2c.setSuperclassURI(superclassURIstrs[i]);
|
||||
c2c.setSubclassURI(subclassURIstr);
|
||||
dao.deleteClasses2Classes(c2c);
|
||||
vcDao.deleteClasses2Classes(c2c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -112,7 +110,7 @@ public class Classes2ClassesOperationController extends BaseEditController {
|
|||
Classes2Classes c2c = new Classes2Classes();
|
||||
c2c.setSuperclassURI(request.getParameter("SuperclassURI"));
|
||||
c2c.setSubclassURI(request.getParameter("SubclassURI"));
|
||||
dao.insertNewClasses2Classes(c2c);
|
||||
vcDao.insertNewClasses2Classes(c2c);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
|
|
@ -19,7 +19,6 @@ import edu.cornell.mannlib.vitro.webapp.auth.permissions.SimplePermission;
|
|||
import edu.cornell.mannlib.vitro.webapp.beans.Classes2Classes;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.Controllers;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.Classes2ClassesDao;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.VClassDao;
|
||||
|
||||
public class Classes2ClassesRetryController extends BaseEditController {
|
||||
|
@ -44,9 +43,8 @@ public class Classes2ClassesRetryController extends BaseEditController {
|
|||
action = epo.getAction();
|
||||
}
|
||||
|
||||
Classes2ClassesDao c2cDao = request.getFullWebappDaoFactory().getClasses2ClassesDao();
|
||||
VClassDao vcDao = request.getFullWebappDaoFactory().getVClassDao();
|
||||
epo.setDataAccessObject(c2cDao);
|
||||
epo.setDataAccessObject(vcDao);
|
||||
Classes2Classes objectForEditing = new Classes2Classes();
|
||||
|
||||
String superclassURIstr = request.getParameter("SuperclassURI");
|
||||
|
|
|
@ -48,6 +48,7 @@ public class EntityEditController extends BaseEditController {
|
|||
VitroRequest vreq = (new VitroRequest(request));
|
||||
ApplicationBean application = vreq.getAppBean();
|
||||
|
||||
//Individual ent = vreq.getWebappDaoFactory().getIndividualDao().getIndividualByURI(entURI);
|
||||
Individual ent = vreq.getAssertionsWebappDaoFactory().getIndividualDao().getIndividualByURI(entURI);
|
||||
if (ent == null) {
|
||||
try {
|
||||
|
|
|
@ -78,7 +78,11 @@ public class EntityRetryController extends BaseEditController {
|
|||
action = epo.getAction();
|
||||
}
|
||||
|
||||
WebappDaoFactory wadf = (vreq.getAssertionsWebappDaoFactory()!=null) ? vreq.getAssertionsWebappDaoFactory() : vreq.getFullWebappDaoFactory();
|
||||
WebappDaoFactory wadf = vreq.getAssertionsWebappDaoFactory();
|
||||
if (wadf == null) {
|
||||
log.info("Using vreq.getFullWebappDaoFactory()");
|
||||
vreq.getFullWebappDaoFactory();
|
||||
}
|
||||
|
||||
LoginStatusBean loginBean = LoginStatusBean.getBean(request);
|
||||
WebappDaoFactory myWebappDaoFactory = wadf.getUserAwareDaoFactory(loginBean.getUserURI());
|
||||
|
|
|
@ -197,7 +197,7 @@ public class VclassRetryController extends BaseEditController {
|
|||
Classes2Classes c2c = new Classes2Classes();
|
||||
c2c.setSubclassURI(((VClass)newObj).getURI());
|
||||
c2c.setSuperclassURI(superclassURI);
|
||||
daoFactory.getClasses2ClassesDao().insertNewClasses2Classes(c2c);
|
||||
daoFactory.getVClassDao().insertNewClasses2Classes(c2c);
|
||||
}
|
||||
public void doUpdated(Object oldObj, Object newObj, EditProcessObject epo) {
|
||||
// nothing to do
|
||||
|
|
|
@ -198,9 +198,11 @@ public class BaseSiteAdminController extends FreemarkerHttpServlet {
|
|||
urls.put("ingest", UrlBuilder.getUrl("/ingest"));
|
||||
urls.put("rdfData", UrlBuilder.getUrl("/uploadRDFForm"));
|
||||
urls.put("rdfExport", UrlBuilder.getUrl("/export"));
|
||||
urls.put("sparqlQuery", UrlBuilder.getUrl("/admin/sparqlquery"));
|
||||
urls.put("sparqlQueryBuilder", UrlBuilder.getUrl("/admin/sparqlquerybuilder"));
|
||||
}
|
||||
if (PolicyHelper.isAuthorizedForActions(vreq, SimplePermission.USE_SPARQL_QUERY_PAGE.ACTIONS)) {
|
||||
urls.put("sparqlQuery", UrlBuilder.getUrl("/admin/sparqlquery"));
|
||||
}
|
||||
|
||||
return urls;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
package edu.cornell.mannlib.vitro.webapp.controller.freemarker;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
|
@ -25,6 +26,7 @@ import org.apache.commons.logging.Log;
|
|||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.beans.ApplicationBean;
|
||||
import edu.cornell.mannlib.vitro.webapp.config.ConfigurationProperties;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.TemplateProcessingHelper.TemplateProcessingException;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues;
|
||||
|
@ -38,7 +40,6 @@ public class ContactMailController extends FreemarkerHttpServlet {
|
|||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final static String SPAM_MESSAGE = "Your message was flagged as spam.";
|
||||
private final static String EMAIL_BACKUP_FILE_PATH = "/WEB-INF/LatestMessage.html";
|
||||
|
||||
private final static String WEB_USERNAME_PARAM = "webusername";
|
||||
private final static String WEB_USEREMAIL_PARAM = "webuseremail";
|
||||
|
@ -48,6 +49,11 @@ public class ContactMailController extends FreemarkerHttpServlet {
|
|||
private final static String TEMPLATE_EMAIL = "contactForm-email.ftl";
|
||||
private final static String TEMPLATE_BACKUP = "contactForm-backup.ftl";
|
||||
private final static String TEMPLATE_ERROR = "contactForm-error.ftl";
|
||||
private final static String TEMPLATE_FORM = "contactForm-form.ftl";
|
||||
|
||||
private static final String PROPERTY_VITRO_HOME_DIR = "vitro.home.directory";
|
||||
private static final String EMAIL_JOURNAL_FILE_DIR = "emailJournal";
|
||||
private static final String EMAIL_JOURNAL_FILE_NAME = "contactFormEmails.html";
|
||||
|
||||
@Override
|
||||
protected String getTitle(String siteName, VitroRequest vreq) {
|
||||
|
@ -70,9 +76,13 @@ public class ContactMailController extends FreemarkerHttpServlet {
|
|||
String webuseremail = nonNullAndTrim(vreq, WEB_USEREMAIL_PARAM);
|
||||
String comments = nonNullAndTrim(vreq, COMMENTS_PARAM);
|
||||
String formType = nonNullAndTrim(vreq, "DeliveryType");
|
||||
String captchaInput = nonNullAndTrim(vreq, "defaultReal");
|
||||
String captchaDisplay = nonNullAndTrim(vreq, "defaultRealHash");
|
||||
|
||||
if (validateInput(webusername, webuseremail, comments) != null) {
|
||||
return errorParametersNotValid();
|
||||
String errorMsg = validateInput(webusername, webuseremail, comments, captchaInput, captchaDisplay);
|
||||
|
||||
if ( errorMsg != null) {
|
||||
return errorParametersNotValid(errorMsg, webusername, webuseremail, comments);
|
||||
}
|
||||
|
||||
String spamReason = checkForSpam(comments, formType);
|
||||
|
@ -107,14 +117,14 @@ public class ContactMailController extends FreemarkerHttpServlet {
|
|||
deliveryfrom, originalReferer, vreq.getRemoteAddr(), config, vreq);
|
||||
|
||||
try {
|
||||
// Write the email to a backup file
|
||||
FileWriter fw = new FileWriter(getServletContext().getRealPath(EMAIL_BACKUP_FILE_PATH),true);
|
||||
// Write the message to the journal file
|
||||
FileWriter fw = new FileWriter(locateTheJournalFile(vreq),true);
|
||||
PrintWriter outFile = new PrintWriter(fw);
|
||||
writeBackupCopy(outFile, msgText, config, vreq);
|
||||
|
||||
Session s = FreemarkerEmailFactory.getEmailSession(vreq);
|
||||
|
||||
try {
|
||||
// Send the message
|
||||
Session s = FreemarkerEmailFactory.getEmailSession(vreq);
|
||||
sendMessage(s, webuseremail, webusername, recipients, deliveryfrom, msgText);
|
||||
} catch (AddressException e) {
|
||||
statusMsg = "Please supply a valid email address.";
|
||||
|
@ -147,6 +157,40 @@ public class ContactMailController extends FreemarkerHttpServlet {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The journal file belongs in a sub-directory of the Vitro home directory.
|
||||
* If the sub-directory doesn't exist, create it.
|
||||
*/
|
||||
private File locateTheJournalFile(VitroRequest vreq) {
|
||||
String homeDirPath = ConfigurationProperties.getBean(vreq).getProperty(
|
||||
PROPERTY_VITRO_HOME_DIR);
|
||||
if (homeDirPath == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"Configuration properties must contain a value for '"
|
||||
+ PROPERTY_VITRO_HOME_DIR + "'");
|
||||
}
|
||||
|
||||
File homeDir = new File(homeDirPath);
|
||||
if (!homeDir.exists()) {
|
||||
throw new IllegalStateException("Vitro home directory '"
|
||||
+ homeDir.getAbsolutePath() + "' does not exist.");
|
||||
}
|
||||
|
||||
File journalDir = new File(homeDir, EMAIL_JOURNAL_FILE_DIR);
|
||||
if (!journalDir.exists()) {
|
||||
boolean created = journalDir.mkdir();
|
||||
if (!created) {
|
||||
throw new IllegalStateException(
|
||||
"Unable to create email journal directory at '"
|
||||
+ journalDir + "'");
|
||||
}
|
||||
}
|
||||
|
||||
File journalFile = new File(journalDir, EMAIL_JOURNAL_FILE_NAME);
|
||||
return journalFile;
|
||||
}
|
||||
|
||||
|
||||
private String getOriginalRefererFromSession(VitroRequest vreq) {
|
||||
String originalReferer = (String) vreq.getSession().getAttribute("contactFormReferer");
|
||||
if (originalReferer != null) {
|
||||
|
@ -263,18 +307,26 @@ public class ContactMailController extends FreemarkerHttpServlet {
|
|||
}
|
||||
|
||||
private String validateInput(String webusername, String webuseremail,
|
||||
String comments) {
|
||||
String comments, String captchaInput, String captchaDisplay) {
|
||||
|
||||
if( webusername.isEmpty() ){
|
||||
return "A proper webusername field was not found in the form submitted.";
|
||||
return "Please enter a value in the Full name field.";
|
||||
}
|
||||
|
||||
if( webuseremail.isEmpty() ){
|
||||
return "A proper webuser email field was not found in the form submitted.";
|
||||
return "Please enter a valid email address.";
|
||||
}
|
||||
|
||||
if (comments.isEmpty()) {
|
||||
return "The proper comments field was not found in the form submitted.";
|
||||
return "Please enter your comments or questions in the space provided.";
|
||||
}
|
||||
|
||||
if (captchaInput.isEmpty()) {
|
||||
return "Please enter the contents of the gray box in the security field provided.";
|
||||
}
|
||||
|
||||
if ( !captchaHash(captchaInput).equals(captchaDisplay) ) {
|
||||
return "The value you entered in the security field did not match the letters displayed in the gray box.";
|
||||
}
|
||||
|
||||
return null;
|
||||
|
@ -308,6 +360,15 @@ public class ContactMailController extends FreemarkerHttpServlet {
|
|||
|
||||
}
|
||||
|
||||
private String captchaHash(String value) {
|
||||
int hash = 5381;
|
||||
value = value.toUpperCase();
|
||||
for(int i = 0; i < value.length(); i++) {
|
||||
hash = ((hash << 5) + hash) + value.charAt(i);
|
||||
}
|
||||
return String.valueOf(hash);
|
||||
}
|
||||
|
||||
private ResponseValues errorNoSmtpServer() {
|
||||
Map<String, Object> body = new HashMap<String, Object>();
|
||||
body.put("errorMessage",
|
||||
|
@ -324,11 +385,14 @@ public class ContactMailController extends FreemarkerHttpServlet {
|
|||
return new TemplateResponseValues(TEMPLATE_ERROR, body);
|
||||
}
|
||||
|
||||
private ResponseValues errorParametersNotValid() {
|
||||
// rjy7 We should reload the form, not go to the error page!
|
||||
private ResponseValues errorParametersNotValid(String errorMsg, String webusername, String webuseremail, String comments) {
|
||||
Map<String, Object> body = new HashMap<String, Object>();
|
||||
body.put("errorMessage", "Invalid submission");
|
||||
return new TemplateResponseValues(TEMPLATE_ERROR, body);
|
||||
body.put("errorMessage", errorMsg);
|
||||
body.put("formAction", "submitFeedback");
|
||||
body.put("webusername", webusername);
|
||||
body.put("webuseremail", webuseremail);
|
||||
body.put("comments", comments);
|
||||
return new TemplateResponseValues(TEMPLATE_FORM, body);
|
||||
}
|
||||
|
||||
private ResponseValues errorSpam() {
|
||||
|
|
|
@ -19,6 +19,10 @@ import edu.cornell.mannlib.vitro.webapp.config.ConfigurationProperties;
|
|||
import edu.cornell.mannlib.vitro.webapp.config.RevisionInfoBean;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder.Route;
|
||||
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.EditConfigurationConstants;
|
||||
import edu.cornell.mannlib.vitro.webapp.web.methods.IndividualLocalNameMethod;
|
||||
import edu.cornell.mannlib.vitro.webapp.web.methods.IndividualPlaceholderImageUrlMethod;
|
||||
import edu.cornell.mannlib.vitro.webapp.web.methods.IndividualProfileUrlMethod;
|
||||
import freemarker.cache.ClassTemplateLoader;
|
||||
import freemarker.cache.FileTemplateLoader;
|
||||
import freemarker.cache.MultiTemplateLoader;
|
||||
|
@ -108,6 +112,9 @@ public class FreemarkerConfiguration extends Configuration {
|
|||
sharedVariables.putAll(getMethods());
|
||||
sharedVariables.put("siteTagline", appBean.getShortHand());
|
||||
|
||||
//Put in edit configuration constants - useful for freemarker templates/editing
|
||||
sharedVariables.put("editConfigurationConstants", EditConfigurationConstants.exportConstants());
|
||||
|
||||
for ( Map.Entry<String, Object> variable : sharedVariables.entrySet() ) {
|
||||
try {
|
||||
setSharedVariable(variable.getKey(), variable.getValue());
|
||||
|
@ -156,8 +163,9 @@ public class FreemarkerConfiguration extends Configuration {
|
|||
|
||||
public static Map<String, Object> getMethods() {
|
||||
Map<String, Object> map = new HashMap<String, Object>();
|
||||
map.put("profileUrl", new edu.cornell.mannlib.vitro.webapp.web.methods.IndividualProfileUrlMethod());
|
||||
map.put("localName", new edu.cornell.mannlib.vitro.webapp.web.methods.IndividualLocalNameMethod());
|
||||
map.put("profileUrl", new IndividualProfileUrlMethod());
|
||||
map.put("localName", new IndividualLocalNameMethod());
|
||||
map.put("placeholderImageUrl", new IndividualPlaceholderImageUrlMethod());
|
||||
return map;
|
||||
}
|
||||
|
||||
|
|
|
@ -340,40 +340,36 @@ public class FreemarkerHttpServlet extends VitroHttpServlet {
|
|||
|
||||
/**
|
||||
* Define the request-specific URLs that are accessible to the templates.
|
||||
* @param VitroRequest vreq
|
||||
* Merge it with the context-specific URLs from the configuration, because
|
||||
* this map will mask that one.
|
||||
*/
|
||||
private void setRequestUrls(VitroRequest vreq) {
|
||||
private Map<String, Object> buildRequestUrls(VitroRequest vreq) {
|
||||
Map<String, Object> requestUrls = new HashMap<String, Object>();
|
||||
|
||||
FreemarkerConfiguration config = (FreemarkerConfiguration)vreq.getAttribute("freemarkerConfig");
|
||||
TemplateModel urlModel = config.getSharedVariable("urls");
|
||||
|
||||
try {
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> urls = (Map<String, Object>) DeepUnwrap.permissiveUnwrap(urlModel);
|
||||
Map<String, Object> configUrls = (Map<String, Object>) DeepUnwrap.permissiveUnwrap(urlModel);
|
||||
requestUrls.putAll(configUrls);
|
||||
|
||||
// This is request-specific because email can be configured
|
||||
// and de-configured in the application interface.
|
||||
if (FreemarkerEmailFactory.isConfigured(vreq)) {
|
||||
urls.put("contact", UrlBuilder.getUrl(Route.CONTACT));
|
||||
} else {
|
||||
urls.remove("contact"); // clear value from a previous request
|
||||
requestUrls.put("contact", UrlBuilder.getUrl(Route.CONTACT));
|
||||
}
|
||||
|
||||
urls.put("currentPage", getCurrentPageUrl(vreq));
|
||||
urls.put("referringPage", getReferringPageUrl(vreq));
|
||||
requestUrls.put("currentPage", getCurrentPageUrl(vreq));
|
||||
requestUrls.put("referringPage", getReferringPageUrl(vreq));
|
||||
|
||||
if (PolicyHelper.isAuthorizedForActions(vreq, SimplePermission.EDIT_OWN_ACCOUNT.ACTIONS)) {
|
||||
urls.put("myAccount", UrlBuilder.getUrl("/accounts/myAccount"));
|
||||
} else {
|
||||
urls.remove("myAccount"); // clear value from a previous request
|
||||
requestUrls.put("myAccount", UrlBuilder.getUrl("/accounts/myAccount"));
|
||||
}
|
||||
|
||||
config.setSharedVariable("urls", urls);
|
||||
|
||||
} catch (TemplateModelException e) {
|
||||
log.error(e, e);
|
||||
}
|
||||
|
||||
return requestUrls;
|
||||
}
|
||||
|
||||
private String getCurrentPageUrl(HttpServletRequest request) {
|
||||
|
@ -424,7 +420,7 @@ public class FreemarkerHttpServlet extends VitroHttpServlet {
|
|||
// This may be overridden by the body data model received from the subcontroller.
|
||||
map.put("title", getTitle(vreq.getAppBean().getApplicationName(), vreq));
|
||||
|
||||
setRequestUrls(vreq);
|
||||
map.put("urls", buildRequestUrls(vreq));
|
||||
|
||||
map.put("menu", getDisplayModelMenu(vreq));
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ import edu.cornell.mannlib.vitro.webapp.filestorage.backend.FileStorageSetup;
|
|||
import edu.cornell.mannlib.vitro.webapp.filestorage.model.FileInfo;
|
||||
import edu.cornell.mannlib.vitro.webapp.filestorage.model.ImageInfo;
|
||||
import edu.cornell.mannlib.vitro.webapp.filestorage.uploadrequest.FileUploadServletRequest;
|
||||
import edu.cornell.mannlib.vitro.webapp.web.images.PlaceholderUtil;
|
||||
|
||||
/**
|
||||
* Handle adding, replacing or deleting the main image on an Individual.
|
||||
|
@ -63,12 +64,6 @@ public class ImageUploadController extends FreemarkerHttpServlet {
|
|||
/** The form field of the uploaded file; use as a key to the FileItem map. */
|
||||
public static final String PARAMETER_UPLOADED_FILE = "datafile";
|
||||
|
||||
/**
|
||||
* The image to use as a placeholder when the individual has no image.
|
||||
* Determined by the template.
|
||||
*/
|
||||
public static final String PARAMETER_PLACEHOLDER_URL = "placeholder";
|
||||
|
||||
/** Here is the main image file. Hold on to it. */
|
||||
public static final String ACTION_UPLOAD = "upload";
|
||||
|
||||
|
@ -141,7 +136,8 @@ public class ImageUploadController extends FreemarkerHttpServlet {
|
|||
String imageUri = entity.getMainImageUri();
|
||||
|
||||
RequestedAction ra;
|
||||
if (ACTION_DELETE.equals(action) || ACTION_DELETE_EDIT.equals(action)) {
|
||||
if (ACTION_DELETE.equals(action)
|
||||
|| ACTION_DELETE_EDIT.equals(action)) {
|
||||
ra = new DropObjectPropStmt(entity.getURI(),
|
||||
VitroVocabulary.IND_MAIN_IMAGE, imageUri);
|
||||
} else if (imageUri != null) {
|
||||
|
@ -405,12 +401,13 @@ public class ImageUploadController extends FreemarkerHttpServlet {
|
|||
private TemplateResponseValues showAddImagePage(VitroRequest vreq,
|
||||
Individual entity) {
|
||||
|
||||
String placeholderUrl = vreq.getParameter(PARAMETER_PLACEHOLDER_URL);
|
||||
|
||||
String formAction = (entity == null) ? "" : formAction(entity.getURI(),
|
||||
ACTION_UPLOAD, placeholderUrl);
|
||||
ACTION_UPLOAD);
|
||||
String cancelUrl = (entity == null) ? "" : exitPageUrl(vreq,
|
||||
entity.getURI());
|
||||
String placeholderUrl = (entity == null) ? "" : UrlBuilder
|
||||
.getUrl(PlaceholderUtil.getPlaceholderImagePathForIndividual(
|
||||
vreq, entity.getURI()));
|
||||
|
||||
TemplateResponseValues rv = new TemplateResponseValues(TEMPLATE_NEW);
|
||||
|
||||
|
@ -437,12 +434,11 @@ public class ImageUploadController extends FreemarkerHttpServlet {
|
|||
*/
|
||||
private TemplateResponseValues showReplaceImagePage(VitroRequest vreq,
|
||||
Individual entity, ImageInfo imageInfo) {
|
||||
String placeholderUrl = vreq.getParameter(PARAMETER_PLACEHOLDER_URL);
|
||||
TemplateResponseValues rv = new TemplateResponseValues(TEMPLATE_REPLACE);
|
||||
rv.put(BODY_THUMBNAIL_URL, UrlBuilder.getUrl(imageInfo.getThumbnail()
|
||||
.getBytestreamAliasUrl()));
|
||||
rv.put(BODY_DELETE_URL, formAction(entity.getURI(), ACTION_DELETE_EDIT, placeholderUrl));
|
||||
rv.put(BODY_FORM_ACTION, formAction(entity.getURI(), ACTION_UPLOAD, placeholderUrl));
|
||||
rv.put(BODY_DELETE_URL, formAction(entity.getURI(), ACTION_DELETE_EDIT));
|
||||
rv.put(BODY_FORM_ACTION, formAction(entity.getURI(), ACTION_UPLOAD));
|
||||
rv.put(BODY_CANCEL_URL, exitPageUrl(vreq, entity.getURI()));
|
||||
rv.put(BODY_TITLE, "Replace image" + forName(entity));
|
||||
rv.put(BODY_MAX_FILE_SIZE, MAXIMUM_FILE_SIZE / (1024 * 1024));
|
||||
|
@ -468,12 +464,11 @@ public class ImageUploadController extends FreemarkerHttpServlet {
|
|||
*/
|
||||
private TemplateResponseValues showCropImagePage(VitroRequest vreq,
|
||||
Individual entity, String imageUrl, Dimensions dimensions) {
|
||||
String placeholderUrl = vreq.getParameter(PARAMETER_PLACEHOLDER_URL);
|
||||
TemplateResponseValues rv = new TemplateResponseValues(TEMPLATE_CROP);
|
||||
rv.put(BODY_MAIN_IMAGE_URL, UrlBuilder.getUrl(imageUrl));
|
||||
rv.put(BODY_MAIN_IMAGE_HEIGHT, dimensions.height);
|
||||
rv.put(BODY_MAIN_IMAGE_WIDTH, dimensions.width);
|
||||
rv.put(BODY_FORM_ACTION, formAction(entity.getURI(), ACTION_SAVE, placeholderUrl));
|
||||
rv.put(BODY_FORM_ACTION, formAction(entity.getURI(), ACTION_SAVE));
|
||||
rv.put(BODY_CANCEL_URL, exitPageUrl(vreq, entity.getURI()));
|
||||
rv.put(BODY_TITLE, "Crop Photo" + forName(entity));
|
||||
return rv;
|
||||
|
@ -518,11 +513,9 @@ public class ImageUploadController extends FreemarkerHttpServlet {
|
|||
* back to this controller, along with the desired action and the Entity
|
||||
* URI.
|
||||
*/
|
||||
private String formAction(String entityUri, String action,
|
||||
String placeholderUrl) {
|
||||
ParamMap params = new ParamMap(
|
||||
PARAMETER_ENTITY_URI, entityUri, PARAMETER_ACTION, action,
|
||||
PARAMETER_PLACEHOLDER_URL, placeholderUrl);
|
||||
private String formAction(String entityUri, String action) {
|
||||
ParamMap params = new ParamMap(PARAMETER_ENTITY_URI, entityUri,
|
||||
PARAMETER_ACTION, action);
|
||||
return UrlBuilder.getPath(URL_HERE, params);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.dao;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.beans.Classes2Classes;
|
||||
|
||||
public interface Classes2ClassesDao {
|
||||
|
||||
public abstract void deleteClasses2Classes(Classes2Classes c2c);
|
||||
|
||||
public abstract void insertNewClasses2Classes(Classes2Classes c2c);
|
||||
|
||||
}
|
|
@ -4,6 +4,7 @@ package edu.cornell.mannlib.vitro.webapp.dao;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.beans.Classes2Classes;
|
||||
import edu.cornell.mannlib.vitro.webapp.beans.VClass;
|
||||
import edu.cornell.mannlib.vitro.webapp.beans.VClassGroup;
|
||||
|
||||
|
@ -67,6 +68,10 @@ public interface VClassDao {
|
|||
|
||||
void addVClassesToGroup(VClassGroup group);
|
||||
|
||||
void insertNewClasses2Classes(Classes2Classes c2c);
|
||||
|
||||
void deleteClasses2Classes(Classes2Classes c2c);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
void addVClassesToGroup(VClassGroup group, boolean includeUninstantiatedClasses);/* (non-Javadoc)
|
||||
* @see edu.cornell.mannlib.vitro.webapp.dao.db.VClassDao#addVClassesToGroups(java.util.List)
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
package edu.cornell.mannlib.vitro.webapp.dao;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public interface WebappDaoFactory {
|
||||
|
@ -13,12 +12,6 @@ public interface WebappDaoFactory {
|
|||
*/
|
||||
public void close();
|
||||
|
||||
/**
|
||||
* Retrieves a map containing arbitrary key-value pairs describing this
|
||||
* WebappDaoFactory
|
||||
*/
|
||||
public Map<String,String> getProperties();
|
||||
|
||||
/**
|
||||
* Checks a URI String for two things: well-formedness and uniqueness in the
|
||||
* model. Ill-formed strings or those matching URIs already in use will
|
||||
|
@ -39,7 +32,7 @@ public interface WebappDaoFactory {
|
|||
|
||||
public Set<String> getNonuserNamespaces();
|
||||
|
||||
public String[] getPreferredLanguages();
|
||||
public List<String> getPreferredLanguages();
|
||||
|
||||
/**
|
||||
* BJL23 2008-05-20: Putting this here for lack of a more logical place.
|
||||
|
@ -66,11 +59,6 @@ public interface WebappDaoFactory {
|
|||
|
||||
/* =============== DAOs for ontology (TBox) manipulation =============== */
|
||||
|
||||
/**
|
||||
* returns a Data Access Object for working with class subsumption axioms
|
||||
*/
|
||||
public Classes2ClassesDao getClasses2ClassesDao();
|
||||
|
||||
/**
|
||||
* returns a Data Access Object for working with DataProperties
|
||||
*/
|
||||
|
|
|
@ -2,30 +2,29 @@
|
|||
|
||||
package edu.cornell.mannlib.vitro.webapp.dao;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class WebappDaoFactoryConfig {
|
||||
|
||||
private String[] preferredLanguages;
|
||||
private List<String> preferredLanguages;
|
||||
private String defaultNamespace;
|
||||
private Set<String> nonUserNamespaces;
|
||||
|
||||
public WebappDaoFactoryConfig() {
|
||||
preferredLanguages = new String[3];
|
||||
preferredLanguages[0] = "en-US";
|
||||
preferredLanguages[1] = "en";
|
||||
preferredLanguages[2] = "EN";
|
||||
preferredLanguages = Arrays.asList("en-US", "en", "EN");
|
||||
defaultNamespace = "http://vitro.mannlib.cornell.edu/ns/default#";
|
||||
nonUserNamespaces = new HashSet<String>();
|
||||
nonUserNamespaces.add(VitroVocabulary.vitroURI);
|
||||
}
|
||||
|
||||
public String[] getPreferredLanguages() {
|
||||
public List<String> getPreferredLanguages() {
|
||||
return this.preferredLanguages;
|
||||
}
|
||||
|
||||
public void setPreferredLanguages(String[] pl) {
|
||||
public void setPreferredLanguages(List<String> pl) {
|
||||
this.preferredLanguages = pl;
|
||||
}
|
||||
|
||||
|
|
|
@ -56,10 +56,6 @@ public class ObjectPropertyStatementFiltering implements ObjectPropertyStatement
|
|||
return innerStmt.getSubjectURI();
|
||||
}
|
||||
|
||||
public boolean isSubjectOriented() {
|
||||
return innerStmt.isSubjectOriented();
|
||||
}
|
||||
|
||||
public void setObject(Individual object) {
|
||||
innerStmt.setObject(object);
|
||||
}
|
||||
|
@ -80,10 +76,6 @@ public class ObjectPropertyStatementFiltering implements ObjectPropertyStatement
|
|||
innerStmt.setSubject(subject);
|
||||
}
|
||||
|
||||
public void setSubjectOriented(boolean subjectOriented) {
|
||||
innerStmt.setSubjectOriented(subjectOriented);
|
||||
}
|
||||
|
||||
public void setSubjectURI(String subjectURI) {
|
||||
innerStmt.setSubjectURI(subjectURI);
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import java.util.List;
|
|||
import net.sf.jga.algorithms.Filter;
|
||||
import net.sf.jga.fn.UnaryFunctor;
|
||||
import net.sf.jga.fn.property.GetProperty;
|
||||
import edu.cornell.mannlib.vitro.webapp.beans.Classes2Classes;
|
||||
import edu.cornell.mannlib.vitro.webapp.beans.Individual;
|
||||
import edu.cornell.mannlib.vitro.webapp.beans.VClass;
|
||||
import edu.cornell.mannlib.vitro.webapp.beans.VClassGroup;
|
||||
|
@ -240,6 +241,14 @@ public class VClassDaoFiltering extends BaseFiltering implements VClassDao{
|
|||
return innerVClassDao.getBottomConcept();
|
||||
}
|
||||
|
||||
public void insertNewClasses2Classes(Classes2Classes c2c) {
|
||||
innerVClassDao.insertNewClasses2Classes(c2c);
|
||||
}
|
||||
|
||||
public void deleteClasses2Classes(Classes2Classes c2c) {
|
||||
innerVClassDao.deleteClasses2Classes(c2c);
|
||||
}
|
||||
|
||||
public boolean isSubClassOf(VClass vc1, VClass vc2) {
|
||||
return innerVClassDao.isSubClassOf(vc1, vc2);
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@ import java.util.Map;
|
|||
import java.util.Set;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.ApplicationDao;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.Classes2ClassesDao;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.DataPropertyDao;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.DataPropertyStatementDao;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.DatatypeDao;
|
||||
|
@ -76,10 +75,6 @@ public class WebappDaoFactoryFiltering implements WebappDaoFactory {
|
|||
|
||||
/* ******************* filtering *********************** */
|
||||
|
||||
public Map<String,String> getProperties() {
|
||||
return innerWebappDaoFactory.getProperties();
|
||||
}
|
||||
|
||||
public String checkURI(String uriStr) {
|
||||
return innerWebappDaoFactory.checkURI(uriStr);
|
||||
}
|
||||
|
@ -101,7 +96,7 @@ public class WebappDaoFactoryFiltering implements WebappDaoFactory {
|
|||
return innerWebappDaoFactory.getNonuserNamespaces();
|
||||
}
|
||||
|
||||
public String[] getPreferredLanguages() {
|
||||
public List<String> getPreferredLanguages() {
|
||||
return innerWebappDaoFactory.getPreferredLanguages();
|
||||
}
|
||||
|
||||
|
@ -168,10 +163,6 @@ public class WebappDaoFactoryFiltering implements WebappDaoFactory {
|
|||
|
||||
/* ******************* non-filtering DAOs *************************** */
|
||||
|
||||
public Classes2ClassesDao getClasses2ClassesDao() {
|
||||
return innerWebappDaoFactory.getClasses2ClassesDao();
|
||||
}
|
||||
|
||||
public DatatypeDao getDatatypeDao() {
|
||||
return innerWebappDaoFactory.getDatatypeDao();
|
||||
}
|
||||
|
|
|
@ -1,69 +0,0 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.dao.jena;
|
||||
|
||||
import com.hp.hpl.jena.ontology.OntModel;
|
||||
import com.hp.hpl.jena.ontology.OntResource;
|
||||
import com.hp.hpl.jena.rdf.model.Resource;
|
||||
import com.hp.hpl.jena.shared.Lock;
|
||||
import com.hp.hpl.jena.vocabulary.RDFS;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.beans.Classes2Classes;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.Classes2ClassesDao;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.jena.event.EditEvent;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class Classes2ClassesDaoJena extends JenaBaseDao implements Classes2ClassesDao {
|
||||
|
||||
public Classes2ClassesDaoJena(WebappDaoFactoryJena wadf) {
|
||||
super(wadf);
|
||||
}
|
||||
|
||||
public void deleteClasses2Classes( Classes2Classes c2c ) {
|
||||
deleteClasses2Classes(c2c, getOntModelSelector().getTBoxModel());
|
||||
}
|
||||
|
||||
public void deleteClasses2Classes( Classes2Classes c2c, OntModel ontModel )
|
||||
{
|
||||
ontModel.enterCriticalSection(Lock.WRITE);
|
||||
ontModel.getBaseModel().notifyEvent(new EditEvent(getWebappDaoFactory().getUserURI(),true));
|
||||
try {
|
||||
OntResource subclass = getOntClass(ontModel,c2c.getSubclassURI());
|
||||
OntResource superclass = getOntClass(ontModel,c2c.getSuperclassURI());
|
||||
if ((subclass != null) && (superclass != null)) {
|
||||
ontModel.removeAll(subclass, RDFS.subClassOf, superclass);
|
||||
}
|
||||
if (subclass.isAnon()) {
|
||||
smartRemove(subclass, getOntModel());
|
||||
}
|
||||
if (superclass.isAnon()) {
|
||||
smartRemove(superclass, getOntModel());
|
||||
}
|
||||
} finally {
|
||||
ontModel.getBaseModel().notifyEvent(new EditEvent(getWebappDaoFactory().getUserURI(),false));
|
||||
ontModel.leaveCriticalSection();
|
||||
}
|
||||
}
|
||||
|
||||
public void insertNewClasses2Classes( Classes2Classes c2c ) {
|
||||
insertNewClasses2Classes(c2c, getOntModelSelector().getTBoxModel());
|
||||
}
|
||||
|
||||
public void insertNewClasses2Classes( Classes2Classes c2c, OntModel ontModel )
|
||||
{
|
||||
ontModel.enterCriticalSection(Lock.WRITE);
|
||||
ontModel.getBaseModel().notifyEvent(new EditEvent(getWebappDaoFactory().getUserURI(),true));
|
||||
try {
|
||||
Resource subclass = ontModel.getResource(c2c.getSubclassURI());
|
||||
Resource superclass = ontModel.getResource(c2c.getSuperclassURI());
|
||||
if ((subclass != null) && (superclass != null)) {
|
||||
ontModel.add(subclass, RDFS.subClassOf, superclass);
|
||||
}
|
||||
} finally {
|
||||
ontModel.getBaseModel().notifyEvent(new EditEvent(getWebappDaoFactory().getUserURI(),false));
|
||||
ontModel.leaveCriticalSection();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -43,17 +43,17 @@ public class EmptyReifier implements Reifier {
|
|||
|
||||
@Override
|
||||
public ExtendedIterator<Triple> find(TripleMatch arg0) {
|
||||
return WrappedIterator.create(Collections.EMPTY_LIST.iterator());
|
||||
return g.find(arg0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExtendedIterator<Triple> findEither(TripleMatch arg0, boolean arg1) {
|
||||
return WrappedIterator.create(Collections.EMPTY_LIST.iterator());
|
||||
return find(arg0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExtendedIterator<Triple> findExposed(TripleMatch arg0) {
|
||||
return WrappedIterator.create(Collections.EMPTY_LIST.iterator());
|
||||
return find(arg0);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -68,14 +68,14 @@ public class EmptyReifier implements Reifier {
|
|||
|
||||
@Override
|
||||
public boolean handledAdd(Triple arg0) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
g.add(arg0);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handledRemove(Triple arg0) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
g.delete(arg0);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -98,20 +98,17 @@ public class EmptyReifier implements Reifier {
|
|||
|
||||
@Override
|
||||
public void remove(Triple arg0) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
g.delete(arg0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(Node arg0, Triple arg1) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
g.delete(arg1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
// TODO Auto-generated method stub
|
||||
return 0;
|
||||
return g.size();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -187,9 +187,10 @@ public class IndividualDaoSDB extends IndividualDaoJena {
|
|||
continue;
|
||||
}
|
||||
if (uri != null && !uri.equals(currRes.getURI())) {
|
||||
Individual ent = makeIndividual(uri, label);
|
||||
if (ent != null) {
|
||||
ents.add(ent);
|
||||
try {
|
||||
ents.add(makeIndividual(uri, label));
|
||||
} catch (IndividualNotFoundException e) {
|
||||
// don't add
|
||||
}
|
||||
uri = currRes.getURI();
|
||||
label = null;
|
||||
|
@ -201,9 +202,10 @@ public class IndividualDaoSDB extends IndividualDaoJena {
|
|||
label = labelLit.getLexicalForm();
|
||||
}
|
||||
if (!rs.hasNext()) {
|
||||
Individual ent = makeIndividual(uri, label);
|
||||
if (ent != null) {
|
||||
ents.add(ent);
|
||||
try {
|
||||
ents.add(makeIndividual(uri, label));
|
||||
} catch (IndividualNotFoundException e) {
|
||||
// don't add
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -237,8 +239,12 @@ public class IndividualDaoSDB extends IndividualDaoJena {
|
|||
if (currRes.isAnon()) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
filteredIndividualList.add(
|
||||
makeIndividual(currRes.getURI(), null));
|
||||
} catch (IndividualNotFoundException e) {
|
||||
// don't add
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
dataset.getLock().leaveCriticalSection();
|
||||
|
@ -247,7 +253,7 @@ public class IndividualDaoSDB extends IndividualDaoJena {
|
|||
return filteredIndividualList;
|
||||
}
|
||||
|
||||
private Individual makeIndividual(String uri, String label) {
|
||||
private Individual makeIndividual(String uri, String label) throws IndividualNotFoundException {
|
||||
Individual ent = new IndividualSDB(uri,
|
||||
this.dwf, datasetMode, getWebappDaoFactory(),
|
||||
SKIP_INITIALIZATION);
|
||||
|
|
|
@ -109,7 +109,7 @@ public class IndividualSDB extends IndividualImpl implements Individual {
|
|||
DatasetWrapperFactory datasetWrapperFactory,
|
||||
SDBDatasetMode datasetMode,
|
||||
WebappDaoFactoryJena wadf,
|
||||
boolean skipInitialization) {
|
||||
boolean skipInitialization) throws IndividualNotFoundException {
|
||||
this.individualURI = individualURI;
|
||||
this.datasetMode = datasetMode;
|
||||
this.dwf = datasetWrapperFactory;
|
||||
|
@ -176,7 +176,7 @@ public class IndividualSDB extends IndividualImpl implements Individual {
|
|||
public IndividualSDB(String individualURI,
|
||||
DatasetWrapperFactory datasetWrapperFactory,
|
||||
SDBDatasetMode datasetMode,
|
||||
WebappDaoFactoryJena wadf) {
|
||||
WebappDaoFactoryJena wadf) throws IndividualNotFoundException {
|
||||
this(individualURI,
|
||||
datasetWrapperFactory,
|
||||
datasetMode,
|
||||
|
@ -184,7 +184,7 @@ public class IndividualSDB extends IndividualImpl implements Individual {
|
|||
!SKIP_INITIALIZATION);
|
||||
}
|
||||
|
||||
public class IndividualNotFoundException extends RuntimeException {}
|
||||
public class IndividualNotFoundException extends Exception {}
|
||||
|
||||
private void setUpURIParts(OntResource ind) {
|
||||
if (ind != null) {
|
||||
|
@ -464,8 +464,24 @@ public class IndividualSDB extends IndividualImpl implements Individual {
|
|||
if (!s.getSubject().canAs(OntResource.class) || !s.getObject().canAs(OntResource.class)) {
|
||||
continue;
|
||||
}
|
||||
Individual subj = new IndividualSDB(((OntResource) s.getSubject().as(OntResource.class)).getURI(), this.dwf, datasetMode, webappDaoFactory);
|
||||
Individual obj = new IndividualSDB(((OntResource) s.getObject().as(OntResource.class)).getURI(), this.dwf, datasetMode, webappDaoFactory);
|
||||
Individual subj = null;
|
||||
try {
|
||||
subj = new IndividualSDB(
|
||||
((OntResource) s.getSubject().as(OntResource.class))
|
||||
.getURI(),
|
||||
this.dwf, datasetMode, webappDaoFactory);
|
||||
} catch (IndividualNotFoundException e) {
|
||||
// leave null subject
|
||||
}
|
||||
Individual obj = null;
|
||||
try {
|
||||
obj = new IndividualSDB(
|
||||
((OntResource) s.getObject().as(OntResource.class))
|
||||
.getURI(),
|
||||
this.dwf, datasetMode, webappDaoFactory);
|
||||
} catch (IndividualNotFoundException e) {
|
||||
// leave null object
|
||||
}
|
||||
ObjectProperty op = webappDaoFactory.getObjectPropertyDao().getObjectPropertyByURI(s.getPredicate().getURI());
|
||||
// We don't want to filter out statements simply because we
|
||||
// can't find a type for the property, so we'll just make a
|
||||
|
@ -517,6 +533,7 @@ public class IndividualSDB extends IndividualImpl implements Individual {
|
|||
while (values.hasNext()) {
|
||||
result = values.next();
|
||||
RDFNode value = result.get("object");
|
||||
try {
|
||||
if (value.canAs(OntResource.class)) {
|
||||
relatedIndividuals.add(
|
||||
new IndividualSDB(
|
||||
|
@ -526,6 +543,9 @@ public class IndividualSDB extends IndividualImpl implements Individual {
|
|||
datasetMode,
|
||||
webappDaoFactory) );
|
||||
}
|
||||
} catch (IndividualNotFoundException e) {
|
||||
// don't add to the list
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
dataset.getLock().leaveCriticalSection();
|
||||
|
@ -555,9 +575,13 @@ public class IndividualSDB extends IndividualImpl implements Individual {
|
|||
QuerySolution result = results.next();
|
||||
RDFNode value = result.get("object");
|
||||
if (value != null && value.canAs(OntResource.class)) {
|
||||
try {
|
||||
return new IndividualSDB(
|
||||
((OntResource) value.as(OntResource.class)).getURI(),
|
||||
dwf, datasetMode, webappDaoFactory);
|
||||
} catch (IndividualNotFoundException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
|
|
@ -80,7 +80,7 @@ public class JenaBaseDao extends JenaBaseDaoCon {
|
|||
|
||||
protected String DEFAULT_NAMESPACE;
|
||||
protected Set<String> NONUSER_NAMESPACES;
|
||||
protected String[] PREFERRED_LANGUAGES;
|
||||
protected List<String> PREFERRED_LANGUAGES;
|
||||
|
||||
/* ******************* constructor ************************* */
|
||||
|
||||
|
@ -501,7 +501,7 @@ public class JenaBaseDao extends JenaBaseDaoCon {
|
|||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("Error in updatePropertyDateValue");
|
||||
log.error("Error in updatePropertyDateValue", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -552,8 +552,7 @@ public class JenaBaseDao extends JenaBaseDaoCon {
|
|||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("Error in updatePropertyDateTimeValue");
|
||||
log.error(e, e);
|
||||
log.error("Error in updatePropertyDateTimeValue", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -767,7 +766,7 @@ public class JenaBaseDao extends JenaBaseDaoCon {
|
|||
if (label.isLiteral()) {
|
||||
Literal labelLit = ((Literal)label);
|
||||
String labelLanguage = labelLit.getLanguage();
|
||||
if ( (labelLanguage==null) && (lang==null) ) {
|
||||
if ( (labelLanguage == null) && (lang == null || lang.isEmpty()) ) {
|
||||
return labelLit;
|
||||
}
|
||||
if ( (lang != null) && (lang.equals(labelLanguage)) ) {
|
||||
|
@ -857,6 +856,10 @@ public class JenaBaseDao extends JenaBaseDaoCon {
|
|||
Literal label = null;
|
||||
List<RDFNode> labels = r.listPropertyValues(p).toList();
|
||||
|
||||
if (labels.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Sort by lexical value to guarantee consistent results
|
||||
Collections.sort(labels, new Comparator<RDFNode>() {
|
||||
public int compare(RDFNode left, RDFNode right) {
|
||||
|
@ -871,8 +874,7 @@ public class JenaBaseDao extends JenaBaseDaoCon {
|
|||
}
|
||||
});
|
||||
|
||||
for (int i=0; i<PREFERRED_LANGUAGES.length; i++) {
|
||||
String lang = PREFERRED_LANGUAGES[i];
|
||||
for (String lang : PREFERRED_LANGUAGES) {
|
||||
label = getLabel(lang,labels);
|
||||
if (label != null) {
|
||||
break;
|
||||
|
@ -880,12 +882,21 @@ public class JenaBaseDao extends JenaBaseDaoCon {
|
|||
}
|
||||
if ( label == null && alsoTryNoLang ) {
|
||||
label = getLabel("", labels);
|
||||
// accept any label as a last resort
|
||||
if (label == null) {
|
||||
for (RDFNode labelNode : labels) {
|
||||
if (labelNode instanceof Literal) {
|
||||
label = ((Literal) labelNode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return label;
|
||||
}
|
||||
|
||||
protected String getDefaultLanguage() {
|
||||
return PREFERRED_LANGUAGES[0];
|
||||
return PREFERRED_LANGUAGES.get(0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -404,6 +404,17 @@ public class ObjectPropertyStatementDaoJena extends JenaBaseDao implements Objec
|
|||
/**
|
||||
* Finds all mostSpecificTypes of an individual that are members of a classgroup.
|
||||
* Returns a list of type labels.
|
||||
*
|
||||
* Note that the Map returned is a LinkedHashMap, which means that an iterator
|
||||
* will return the entries in the order in which the keys were inserted in the map.
|
||||
* Since the SPARQL query included an "ORDER BY ?label" clause, and since an
|
||||
* iterator through that ResultSet was used to add entries to the map, an iterator
|
||||
* on the map will return entries that are sorted by label (value, not key).
|
||||
*
|
||||
* While this sorting order is not specified as a requirement (maybe it should be?),
|
||||
* it is certainly useful that the types are returned in some order that is
|
||||
* replicable, so an individual with multiple mostSpecificTypes, will always see
|
||||
* the same list in the same order. (See https://issues.library.cornell.edu/browse/NIHVIVO-568)
|
||||
* **/
|
||||
public Map<String, String> getMostSpecificTypesInClassgroupsForIndividual(String subjectUri) {
|
||||
|
||||
|
|
|
@ -132,7 +132,7 @@ public class OntologyDaoJena extends JenaBaseDao implements OntologyDao {
|
|||
try {
|
||||
com.hp.hpl.jena.ontology.Ontology o = ontModel.createOntology(adjustOntologyURI(ontology.getURI()));
|
||||
if (ontology.getName() != null && ontology.getName().length()>0) {
|
||||
o.setLabel(ontology.getName(), PREFERRED_LANGUAGES[0]);
|
||||
o.setLabel(ontology.getName(), getDefaultLanguage());
|
||||
}
|
||||
if (ontology.getPrefix() != null && ontology.getPrefix().length()>0) {
|
||||
addPropertyStringValue(o,ONTOLOGY_PREFIX_ANNOT,ontology.getPrefix(),ontModel);
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
package edu.cornell.mannlib.vitro.webapp.dao.jena;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
|
@ -35,6 +34,7 @@ import com.hp.hpl.jena.rdf.model.Statement;
|
|||
import com.hp.hpl.jena.rdf.model.StmtIterator;
|
||||
import com.hp.hpl.jena.shared.Lock;
|
||||
import com.hp.hpl.jena.sparql.resultset.ResultSetMem;
|
||||
import com.hp.hpl.jena.util.iterator.ClosableIterator;
|
||||
import com.hp.hpl.jena.vocabulary.OWL;
|
||||
import com.hp.hpl.jena.vocabulary.RDFS;
|
||||
|
||||
|
@ -596,6 +596,31 @@ public class PropertyDaoJena extends JenaBaseDao implements PropertyDao {
|
|||
}
|
||||
}
|
||||
|
||||
private List<OntClass> listSuperClasses(OntClass ontClass) {
|
||||
return relatedClasses(ontClass, RDFS.subClassOf);
|
||||
}
|
||||
|
||||
private List<OntClass> listEquivalentClasses(OntClass ontClass) {
|
||||
return relatedClasses(ontClass, OWL.equivalentClass);
|
||||
}
|
||||
|
||||
private List<OntClass> relatedClasses(OntClass ontClass,
|
||||
com.hp.hpl.jena.rdf.model.Property property) {
|
||||
List<OntClass> classes = new ArrayList<OntClass>();
|
||||
StmtIterator closeIt = ontClass.listProperties(property);
|
||||
try {
|
||||
while (closeIt.hasNext()) {
|
||||
Statement stmt = closeIt.nextStatement();
|
||||
if (stmt.getObject().canAs(OntClass.class)) {
|
||||
classes.add(stmt.getObject().as(OntClass.class));
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
closeIt.close();
|
||||
}
|
||||
return classes;
|
||||
}
|
||||
|
||||
public List<PropertyInstance> getAllPropInstByVClasses(List<VClass> vclasses) {
|
||||
|
||||
List<PropertyInstance> propInsts = new ArrayList<PropertyInstance>();
|
||||
|
@ -628,8 +653,8 @@ public class PropertyDaoJena extends JenaBaseDao implements PropertyDao {
|
|||
OntClass ontClass = getOntClass(ontModel,VClassURI);
|
||||
if (ontClass != null) {
|
||||
List<OntClass> relatedClasses = new ArrayList<OntClass>();
|
||||
relatedClasses.addAll(ontClass.listEquivalentClasses().toList());
|
||||
relatedClasses.addAll(ontClass.listSuperClasses().toList());
|
||||
relatedClasses.addAll(listEquivalentClasses(ontClass));
|
||||
relatedClasses.addAll(listSuperClasses(ontClass));
|
||||
for (OntClass relatedClass : relatedClasses) {
|
||||
// find properties in restrictions
|
||||
if (relatedClass.isRestriction()) {
|
||||
|
|
|
@ -14,14 +14,14 @@ import com.hp.hpl.jena.shared.Lock;
|
|||
*/
|
||||
public class SimpleOntModelSelector implements OntModelSelector {
|
||||
|
||||
private OntModel fullModel;
|
||||
private OntModel aboxModel;
|
||||
private OntModel applicationMetadataModel;
|
||||
private OntModel tboxModel;
|
||||
private OntModel userAccountsModel;
|
||||
protected OntModel fullModel;
|
||||
protected OntModel aboxModel;
|
||||
protected OntModel applicationMetadataModel;
|
||||
protected OntModel tboxModel;
|
||||
protected OntModel userAccountsModel;
|
||||
|
||||
private OntModelSpec DEFAULT_ONT_MODEL_SPEC = OntModelSpec.OWL_MEM;
|
||||
private OntModel displayModel;
|
||||
protected OntModelSpec DEFAULT_ONT_MODEL_SPEC = OntModelSpec.OWL_MEM;
|
||||
protected OntModel displayModel;
|
||||
|
||||
/**
|
||||
* Construct an OntModelSelector with a bunch of empty models
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
package edu.cornell.mannlib.vitro.webapp.dao.jena;
|
||||
|
||||
import com.hp.hpl.jena.ontology.OntModel;
|
||||
|
||||
public class SingleContentOntModelSelector extends SimpleOntModelSelector {
|
||||
|
||||
public SingleContentOntModelSelector(OntModel contentModel,
|
||||
OntModel displayModel,
|
||||
OntModel userAccountsModel) {
|
||||
super(contentModel);
|
||||
super.displayModel = displayModel;
|
||||
super.userAccountsModel = userAccountsModel;
|
||||
}
|
||||
|
||||
}
|
|
@ -82,11 +82,25 @@ public class SparqlGraph implements GraphWithPerform {
|
|||
@Override
|
||||
public void performAdd(Triple t) {
|
||||
|
||||
String updateString = "INSERT DATA { "
|
||||
//log.info("adding " + t);
|
||||
|
||||
String updateString = "INSERT DATA { GRAPH <junk:junk> { "
|
||||
+ sparqlNode(t.getSubject(), "") + " "
|
||||
+ sparqlNode(t.getPredicate(), "") + " "
|
||||
+ sparqlNode(t.getObject(), "") +
|
||||
"}";
|
||||
" } }";
|
||||
|
||||
if (false) {
|
||||
try {
|
||||
|
||||
throw new RuntimeException("Breakpoint");
|
||||
} catch (RuntimeException e) {
|
||||
log.error(e, e);
|
||||
//throw(e);
|
||||
}
|
||||
}
|
||||
|
||||
//log.info(updateString);
|
||||
|
||||
try {
|
||||
RepositoryConnection conn = getConnection();
|
||||
|
@ -108,11 +122,15 @@ public class SparqlGraph implements GraphWithPerform {
|
|||
|
||||
@Override
|
||||
public void performDelete(Triple t) {
|
||||
String updateString = "DELETE DATA { "
|
||||
log.info ("************** DELETE!!!!! ********************");
|
||||
|
||||
String updateString = "DELETE DATA { GRAPH <junk:junk> { "
|
||||
+ sparqlNode(t.getSubject(), "") + " "
|
||||
+ sparqlNode(t.getPredicate(), "") + " "
|
||||
+ sparqlNode(t.getObject(), "") +
|
||||
"}";
|
||||
" } }";
|
||||
|
||||
log.info(updateString);
|
||||
|
||||
try {
|
||||
RepositoryConnection conn = getConnection();
|
||||
|
@ -158,6 +176,7 @@ public class SparqlGraph implements GraphWithPerform {
|
|||
|
||||
@Override
|
||||
public void delete(Triple arg0) throws DeleteDeniedException {
|
||||
log.info("********************** DELETE!!!!!! ************************");
|
||||
performDelete(arg0);
|
||||
}
|
||||
|
||||
|
@ -212,7 +231,7 @@ public class SparqlGraph implements GraphWithPerform {
|
|||
.append(sparqlNode(object, "?o"))
|
||||
.append("\n}");
|
||||
|
||||
log.info(findQuery.toString());
|
||||
//log.info(findQuery.toString());
|
||||
ResultSet rs = execSelect(findQuery.toString());
|
||||
//rs = execSelect(findQuery.toString());
|
||||
//rs = execSelect(findQuery.toString());
|
||||
|
@ -226,6 +245,7 @@ public class SparqlGraph implements GraphWithPerform {
|
|||
//log.info(t);
|
||||
triplist.add(t);
|
||||
}
|
||||
//log.info(triplist.size() + " results");
|
||||
return WrappedIterator.create(triplist.iterator());
|
||||
}
|
||||
|
||||
|
@ -236,7 +256,7 @@ public class SparqlGraph implements GraphWithPerform {
|
|||
@Override
|
||||
public BulkUpdateHandler getBulkUpdateHandler() {
|
||||
if (this.bulkUpdateHandler == null) {
|
||||
this.bulkUpdateHandler = new SimpleBulkUpdateHandler(this);
|
||||
this.bulkUpdateHandler = new SparqlGraphBulkUpdater(this);
|
||||
}
|
||||
return this.bulkUpdateHandler;
|
||||
}
|
||||
|
@ -383,7 +403,7 @@ public class SparqlGraph implements GraphWithPerform {
|
|||
try {
|
||||
return new ResultSetMem(qe.execSelect());
|
||||
} finally {
|
||||
log.info((System.currentTimeMillis() - startTime) + " to execute via Jena");
|
||||
//log.info((System.currentTimeMillis() - startTime) + " to execute via Jena");
|
||||
qe.close();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,148 @@
|
|||
package edu.cornell.mannlib.vitro.webapp.dao.jena;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import com.hp.hpl.jena.graph.Node;
|
||||
import com.hp.hpl.jena.graph.Triple;
|
||||
import com.hp.hpl.jena.graph.TripleMatch;
|
||||
import com.hp.hpl.jena.graph.impl.GraphWithPerform;
|
||||
import com.hp.hpl.jena.shared.AddDeniedException;
|
||||
import com.hp.hpl.jena.sparql.util.NodeFactory;
|
||||
import com.hp.hpl.jena.util.iterator.ExtendedIterator;
|
||||
import com.hp.hpl.jena.util.iterator.WrappedIterator;
|
||||
|
||||
public class SparqlGraphMultilingual extends SparqlGraph implements GraphWithPerform {
|
||||
|
||||
private static final Log log = LogFactory.getLog(SparqlGraphMultilingual.class);
|
||||
|
||||
protected List<String> langs;
|
||||
|
||||
|
||||
public SparqlGraphMultilingual(String endpointURI, List<String> languages) {
|
||||
super(endpointURI);
|
||||
this.langs = languages;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(Triple arg0) throws AddDeniedException {
|
||||
performAdd(arg0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void performAdd(Triple t) {
|
||||
if (true) {
|
||||
super.performAdd(t);
|
||||
return;
|
||||
}
|
||||
if (langs == null || langs.size() == 0) {
|
||||
log.info("No language configured - adding original triple " + t);
|
||||
super.performAdd(t);
|
||||
} else if (t.getObject().isLiteral()
|
||||
&& t.getObject().getLiteral().getDatatypeURI() == null) {
|
||||
log.info("adding language tag");
|
||||
super.performAdd(Triple.create(t.getSubject(),
|
||||
t.getPredicate(), NodeFactory.createLiteralNode(
|
||||
t.getObject().getLiteralLexicalForm(), langs.get(0), null)));
|
||||
} else {
|
||||
log.info("adding original triple " + t);
|
||||
super.performAdd(t);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExtendedIterator<Triple> find(TripleMatch arg0) {
|
||||
//log.info("find(TripleMatch) " + arg0);
|
||||
Triple t = arg0.asTriple();
|
||||
return find(t.getSubject(), t.getPredicate(), t.getObject());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExtendedIterator<Triple> find(Node subject, Node predicate, Node object) {
|
||||
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
ExtendedIterator<Triple> rawResults = super.find(subject, predicate, object);
|
||||
long rawTime = System.currentTimeMillis() - startTime;
|
||||
|
||||
List<Triple> tripList = new ArrayList<Triple>();
|
||||
while (rawResults.hasNext()) {
|
||||
tripList.add(rawResults.next());
|
||||
}
|
||||
if (tripList.size() == 0) {
|
||||
return WrappedIterator.create(tripList.iterator());
|
||||
}
|
||||
if (subject.isConcrete() && predicate.isConcrete() && !object.isConcrete()) {
|
||||
Collections.sort(tripList, new TripleSortByLang());
|
||||
LinkedList<Triple> tripl = new LinkedList<Triple>();
|
||||
if (!tripList.get(0).getObject().isLiteral()) {
|
||||
tripl.addAll(tripList);
|
||||
} else if (StringUtils.isEmpty(tripList.get(0).getObject().getLiteralLanguage())) {
|
||||
tripl.addAll(tripList); // is this right?
|
||||
} else {
|
||||
String lang = tripList.get(0).getObject().getLiteralLanguage();
|
||||
for (Triple t : tripList) {
|
||||
if (lang.equals(t.getObject().getLiteralLanguage())) {
|
||||
tripl.add(t);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
long filterTime = System.currentTimeMillis() - rawTime - startTime;
|
||||
if (filterTime > 1) {
|
||||
log.info("raw time " + rawTime + " ; filter time " + filterTime);
|
||||
}
|
||||
return WrappedIterator.create(tripl.iterator());
|
||||
} else {
|
||||
long filterTime = System.currentTimeMillis() - rawTime - startTime;
|
||||
if (rawTime > 9) {
|
||||
log.info("raw time " + rawTime + " ; filter time " + filterTime);
|
||||
log.info("^ " + subject + " : " + predicate + " : " + object);
|
||||
}
|
||||
return WrappedIterator.create(tripList.iterator());
|
||||
}
|
||||
}
|
||||
|
||||
private class TripleSortByLang implements Comparator<Triple> {
|
||||
|
||||
public int compare(Triple t1, Triple t2) {
|
||||
if (t1 == null || t2 == null) {
|
||||
return 0;
|
||||
} else if (!t1.getObject().isLiteral() || !t2.getObject().isLiteral()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
String t1lang = t1.getObject().getLiteral().language();
|
||||
String t2lang = t2.getObject().getLiteral().language();
|
||||
|
||||
if ( t1lang == null && t2lang == null) {
|
||||
return 0;
|
||||
} else if (t1lang == null) {
|
||||
return 1;
|
||||
} else if (t2lang == null) {
|
||||
return -1;
|
||||
} else {
|
||||
int t1langPref = langs.indexOf(t1.getObject().getLiteral().language());
|
||||
if (t1langPref == -1) {
|
||||
t1langPref = Integer.MAX_VALUE;
|
||||
}
|
||||
int t2langPref = langs.indexOf(t2.getObject().getLiteral().language());
|
||||
if (t2langPref == -1) {
|
||||
t2langPref = Integer.MAX_VALUE;
|
||||
}
|
||||
return t1langPref - t2langPref;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -9,6 +9,9 @@ import java.util.HashSet;
|
|||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import com.hp.hpl.jena.ontology.AllValuesFromRestriction;
|
||||
import com.hp.hpl.jena.ontology.AnnotationProperty;
|
||||
import com.hp.hpl.jena.ontology.CardinalityRestriction;
|
||||
|
@ -59,6 +62,8 @@ import edu.cornell.mannlib.vitro.webapp.dao.jena.pellet.PelletListener;
|
|||
|
||||
public class VClassDaoJena extends JenaBaseDao implements VClassDao {
|
||||
|
||||
protected static final Log log = LogFactory.getLog(VClassDaoJena.class);
|
||||
|
||||
public VClassDaoJena(WebappDaoFactoryJena wadf) {
|
||||
super(wadf);
|
||||
}
|
||||
|
@ -308,7 +313,7 @@ public class VClassDaoJena extends JenaBaseDao implements VClassDao {
|
|||
Classes2Classes c2c = new Classes2Classes();
|
||||
c2c.setSubclassURI(vclassURI);
|
||||
c2c.setSuperclassURI(superclassURI);
|
||||
getWebappDaoFactory().getClasses2ClassesDao().insertNewClasses2Classes(c2c);
|
||||
insertNewClasses2Classes(c2c);
|
||||
}
|
||||
|
||||
public void removeSuperclass(VClass vclass, VClass superclass) {
|
||||
|
@ -319,7 +324,7 @@ public class VClassDaoJena extends JenaBaseDao implements VClassDao {
|
|||
Classes2Classes c2c = new Classes2Classes();
|
||||
c2c.setSubclassURI(vclassURI);
|
||||
c2c.setSuperclassURI(superclassURI);
|
||||
getWebappDaoFactory().getClasses2ClassesDao().deleteClasses2Classes(c2c);
|
||||
deleteClasses2Classes(c2c);
|
||||
}
|
||||
|
||||
public void addSubclass(VClass vclass, VClass subclass) {
|
||||
|
@ -330,7 +335,7 @@ public class VClassDaoJena extends JenaBaseDao implements VClassDao {
|
|||
Classes2Classes c2c = new Classes2Classes();
|
||||
c2c.setSubclassURI(subclassURI);
|
||||
c2c.setSuperclassURI(vclassURI);
|
||||
getWebappDaoFactory().getClasses2ClassesDao().insertNewClasses2Classes(c2c);
|
||||
insertNewClasses2Classes(c2c);
|
||||
}
|
||||
|
||||
public void removeSubclass(VClass vclass, VClass subclass) {
|
||||
|
@ -341,7 +346,7 @@ public class VClassDaoJena extends JenaBaseDao implements VClassDao {
|
|||
Classes2Classes c2c = new Classes2Classes();
|
||||
c2c.setSubclassURI(subclassURI);
|
||||
c2c.setSuperclassURI(vclassURI);
|
||||
getWebappDaoFactory().getClasses2ClassesDao().deleteClasses2Classes(c2c);
|
||||
deleteClasses2Classes(c2c);
|
||||
}
|
||||
|
||||
public void addEquivalentClass(String classURI, String equivalentClassURI) {
|
||||
|
@ -446,11 +451,12 @@ public class VClassDaoJena extends JenaBaseDao implements VClassDao {
|
|||
List<VClass> classes = new ArrayList<VClass>();
|
||||
getOntModel().enterCriticalSection(Lock.READ);
|
||||
try {
|
||||
ClosableIterator<OntClass> classIt = getOntModel().listClasses();
|
||||
ClosableIterator<Individual> classIt = getOntModel().listIndividuals(OWL.Class);
|
||||
try {
|
||||
while (classIt.hasNext()) {
|
||||
try {
|
||||
OntClass cls = classIt.next();
|
||||
Individual classInd = classIt.next();
|
||||
OntClass cls = (OntClass) classInd.as(OntClass.class);
|
||||
if (!cls.isAnon() && !(NONUSER_NAMESPACES.contains(cls.getNameSpace()))) {
|
||||
classes.add(new VClassJena(cls,getWebappDaoFactory()));
|
||||
}
|
||||
|
@ -481,11 +487,15 @@ public class VClassDaoJena extends JenaBaseDao implements VClassDao {
|
|||
*/
|
||||
private Iterator<OntClass> smarterListHierarchyRootClasses(OntModel ontModel, String ontologyURI) {
|
||||
List<OntClass> rootClassList = new ArrayList<OntClass>();
|
||||
ClosableIterator ci = ontModel.listClasses();
|
||||
ClosableIterator<Individual> ci = ontModel.listIndividuals(OWL.Class);
|
||||
try {
|
||||
for (ClosableIterator i = ci ; i.hasNext(); ) {
|
||||
for (ClosableIterator<Individual> i = ci ; i.hasNext(); ) {
|
||||
try {
|
||||
OntClass ontClass = (OntClass) i.next();
|
||||
Individual classInd = i.next();
|
||||
// if (!classInd.canAs(OntClass.class)) {
|
||||
// continue;
|
||||
// }
|
||||
OntClass ontClass = (OntClass) classInd.as(OntClass.class);
|
||||
boolean isRoot = true;
|
||||
for (Iterator<RDFNode> j = ontClass.listPropertyValues(RDFS.subClassOf); j.hasNext(); ) {
|
||||
Resource res = (Resource) j.next();
|
||||
|
@ -510,7 +520,7 @@ public class VClassDaoJena extends JenaBaseDao implements VClassDao {
|
|||
rootClassList.add(ontClass);
|
||||
}
|
||||
} catch (ClassCastException cce) {
|
||||
log.error(cce);
|
||||
log.error(cce, cce);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
|
@ -989,6 +999,52 @@ public class VClassDaoJena extends JenaBaseDao implements VClassDao {
|
|||
}
|
||||
}
|
||||
|
||||
public void deleteClasses2Classes( Classes2Classes c2c ) {
|
||||
deleteClasses2Classes(c2c, getOntModelSelector().getTBoxModel());
|
||||
}
|
||||
|
||||
public void deleteClasses2Classes( Classes2Classes c2c, OntModel ontModel )
|
||||
{
|
||||
ontModel.enterCriticalSection(Lock.WRITE);
|
||||
ontModel.getBaseModel().notifyEvent(new EditEvent(getWebappDaoFactory().getUserURI(),true));
|
||||
try {
|
||||
OntResource subclass = getOntClass(ontModel,c2c.getSubclassURI());
|
||||
OntResource superclass = getOntClass(ontModel,c2c.getSuperclassURI());
|
||||
if ((subclass != null) && (superclass != null)) {
|
||||
ontModel.removeAll(subclass, RDFS.subClassOf, superclass);
|
||||
}
|
||||
if (subclass.isAnon()) {
|
||||
smartRemove(subclass, getOntModel());
|
||||
}
|
||||
if (superclass.isAnon()) {
|
||||
smartRemove(superclass, getOntModel());
|
||||
}
|
||||
} finally {
|
||||
ontModel.getBaseModel().notifyEvent(new EditEvent(getWebappDaoFactory().getUserURI(),false));
|
||||
ontModel.leaveCriticalSection();
|
||||
}
|
||||
}
|
||||
|
||||
public void insertNewClasses2Classes( Classes2Classes c2c ) {
|
||||
insertNewClasses2Classes(c2c, getOntModelSelector().getTBoxModel());
|
||||
}
|
||||
|
||||
public void insertNewClasses2Classes( Classes2Classes c2c, OntModel ontModel )
|
||||
{
|
||||
ontModel.enterCriticalSection(Lock.WRITE);
|
||||
ontModel.getBaseModel().notifyEvent(new EditEvent(getWebappDaoFactory().getUserURI(),true));
|
||||
try {
|
||||
Resource subclass = ontModel.getResource(c2c.getSubclassURI());
|
||||
Resource superclass = ontModel.getResource(c2c.getSuperclassURI());
|
||||
if ((subclass != null) && (superclass != null)) {
|
||||
ontModel.add(subclass, RDFS.subClassOf, superclass);
|
||||
}
|
||||
} finally {
|
||||
ontModel.getBaseModel().notifyEvent(new EditEvent(getWebappDaoFactory().getUserURI(),false));
|
||||
ontModel.leaveCriticalSection();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isSubClassOf(VClass vc1, VClass vc2) {
|
||||
if (vc1 == null || vc2 == null) {
|
||||
return false;
|
||||
|
|
|
@ -30,7 +30,6 @@ import com.hp.hpl.jena.shared.Lock;
|
|||
import com.hp.hpl.jena.util.iterator.ClosableIterator;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.ApplicationDao;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.Classes2ClassesDao;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.DataPropertyDao;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.DataPropertyStatementDao;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.DatatypeDao;
|
||||
|
@ -233,7 +232,7 @@ public class WebappDaoFactoryJena implements WebappDaoFactory {
|
|||
return config.getDefaultNamespace();
|
||||
}
|
||||
|
||||
public String[] getPreferredLanguages() {
|
||||
public List<String> getPreferredLanguages() {
|
||||
return config.getPreferredLanguages();
|
||||
}
|
||||
|
||||
|
@ -312,13 +311,6 @@ public class WebappDaoFactoryJena implements WebappDaoFactory {
|
|||
return userAccountsDao = new UserAccountsDaoJena(this);
|
||||
}
|
||||
|
||||
Classes2ClassesDao classes2ClassesDao = null;
|
||||
public Classes2ClassesDao getClasses2ClassesDao() {
|
||||
if(classes2ClassesDao == null )
|
||||
classes2ClassesDao = new Classes2ClassesDaoJena(this);
|
||||
return classes2ClassesDao;
|
||||
}
|
||||
|
||||
DataPropertyStatementDao dataPropertyStatementDao = null;
|
||||
public DataPropertyStatementDao getDataPropertyStatementDao() {
|
||||
if( dataPropertyStatementDao == null )
|
||||
|
|
|
@ -163,7 +163,9 @@ public class PelletListener implements ModelChangedListener {
|
|||
this.deletedDataProperties = ModelFactory.createDefaultModel();
|
||||
this.mainModel.enterCriticalSection(Lock.READ);
|
||||
try {
|
||||
addedStatements(mainModel);
|
||||
for (ObjectPropertyStatementPattern pat : this.inferenceDrivingPatternAllowSet) {
|
||||
addedStatements(mainModel.listStatements((Resource) null, pat.getPredicate(), (RDFNode) null));
|
||||
}
|
||||
if (!skipReasoningUponInitialization) {
|
||||
this.foreground = foreground;
|
||||
notifyEvent(null,new EditEvent(null,false));
|
||||
|
|
|
@ -7,6 +7,7 @@ import java.util.ArrayList;
|
|||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
@ -23,6 +24,7 @@ import com.hp.hpl.jena.shared.Lock;
|
|||
import edu.cornell.mannlib.vitro.webapp.dao.InsertException;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.jena.DependentResourceDeleteJena;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.jena.event.EditEvent;
|
||||
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.EditConfigurationConstants;
|
||||
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.controller.ProcessRdfFormController.Utilities;
|
||||
|
||||
/**
|
||||
|
@ -41,7 +43,6 @@ public class ProcessRdfForm {
|
|||
private EditN3GeneratorVTwo populator;
|
||||
|
||||
private Map<String,String> urisForNewResources = null;
|
||||
|
||||
/**
|
||||
* Construct the ProcessRdfForm object.
|
||||
*/
|
||||
|
@ -172,6 +173,12 @@ public class ProcessRdfForm {
|
|||
//need to substitute into the return to URL becase it may need new resource URIs
|
||||
List<String> URLToReturnTo = Arrays.asList(submission.getEntityToReturnTo());
|
||||
|
||||
/* *********** Check if new resource needs to be forcibly created ******** */
|
||||
urisForNewResources = URIsForNewRsources(editConfig, newURIMaker);
|
||||
substituteInForcedNewURIs(urisForNewResources, submission.getUrisFromForm(), requiredAsserts, optionalAsserts, URLToReturnTo);
|
||||
logSubstitue( "Added form URIs that required new URIs", requiredAsserts, optionalAsserts, requiredRetracts, optionalRetracts);
|
||||
|
||||
|
||||
/* ********** Form submission URIs ********* */
|
||||
substituteInMultiURIs(submission.getUrisFromForm(), requiredAsserts, optionalAsserts, URLToReturnTo);
|
||||
logSubstitue( "Added form URIs", requiredAsserts, optionalAsserts, requiredRetracts, optionalRetracts);
|
||||
|
@ -182,10 +189,13 @@ public class ProcessRdfForm {
|
|||
logSubstitue( "Added form Literals", requiredAsserts, optionalAsserts, requiredRetracts, optionalRetracts);
|
||||
//Retractions does NOT get values from form.
|
||||
|
||||
|
||||
|
||||
/* *********** Add subject, object and predicate ******** */
|
||||
substituteInSubPredObjURIs(editConfig, requiredAsserts, optionalAsserts, requiredRetracts, optionalRetracts, URLToReturnTo);
|
||||
logSubstitue( "Added sub, pred and obj URIs", requiredAsserts, optionalAsserts, requiredRetracts, optionalRetracts);
|
||||
|
||||
|
||||
/* ********* Existing URIs and Literals ********** */
|
||||
substituteInMultiURIs(editConfig.getUrisInScope(),
|
||||
requiredAsserts, optionalAsserts, requiredRetracts, optionalRetracts, URLToReturnTo);
|
||||
|
@ -197,7 +207,8 @@ public class ProcessRdfForm {
|
|||
//Both Assertions and Retractions get existing values.
|
||||
|
||||
/* ************ Edits may need new resources *********** */
|
||||
urisForNewResources = URIsForNewRsources(editConfig, newURIMaker);
|
||||
//moved this up?
|
||||
//urisForNewResources = URIsForNewRsources(editConfig, newURIMaker);
|
||||
substituteInURIs( urisForNewResources, requiredAsserts, optionalAsserts, URLToReturnTo);
|
||||
logSubstitue( "Added URIs for new Resources", requiredAsserts, optionalAsserts, requiredRetracts, optionalRetracts);
|
||||
// Only Assertions get new resources.
|
||||
|
@ -205,6 +216,8 @@ public class ProcessRdfForm {
|
|||
submission.setEntityToReturnTo(URLToReturnTo.get(0));
|
||||
}
|
||||
|
||||
|
||||
|
||||
//TODO: maybe move this to utils or contorller?
|
||||
public static AdditionsAndRetractions addDependentDeletes( AdditionsAndRetractions changes, Model queryModel){
|
||||
//Add retractions for dependent resource delete if that is configured and
|
||||
|
@ -455,5 +468,35 @@ public class ProcessRdfForm {
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* In some situations, an object may have an existing URI but be left blank
|
||||
* when the desired behavior is that a new object be created to replace the existing URI
|
||||
* E.g. autocomplete forms that allow editing of autocomplete fields
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private void substituteInForcedNewURIs(
|
||||
Map<String, String> urisForNewResources, Map<String, List<String>> urisFromForm,
|
||||
List<String> requiredAsserts, List<String> optionalAsserts,
|
||||
List<String> uRLToReturnTo) {
|
||||
Map<String, List<String>> newUris = new HashMap<String, List<String>>();
|
||||
//Check if any values from the submission have the "force new uri" value
|
||||
//TODO: Check how to handle multiple new resource values
|
||||
Iterator<String> keyIterator = urisFromForm.keySet().iterator();
|
||||
while(keyIterator.hasNext()) {
|
||||
String key = keyIterator.next().toString();
|
||||
if(urisFromForm.get(key).contains(EditConfigurationConstants.NEW_URI_SENTINEL)) {
|
||||
String newUri = urisForNewResources.get(key);
|
||||
List<String> newUrisForKey = new ArrayList<String>();
|
||||
newUrisForKey.add(newUri);
|
||||
newUris.put(key, newUrisForKey);
|
||||
}
|
||||
}
|
||||
if(newUris.size() > 0) {
|
||||
substituteInMultiURIs(newUris, requiredAsserts, optionalAsserts, uRLToReturnTo);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private static Log log = LogFactory.getLog(ProcessRdfForm.class);
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration;
|
||||
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.ProcessRdfForm;
|
||||
|
||||
|
||||
public class EditConfigurationConstants {
|
||||
/** Constants used by edit configuration */
|
||||
//forces creation of new uri if present
|
||||
public static final String NEW_URI_SENTINEL = ">NEW URI REQUIRED<";
|
||||
public static final String BLANK_SENTINEL = ">SUBMITTED VALUE WAS BLANK<";
|
||||
|
||||
//For freemarker configuration
|
||||
public static Map<String, String> exportConstants() {
|
||||
Map<String, String> constants = new HashMap<String, String>();
|
||||
java.lang.reflect.Field[] fields = EditConfigurationConstants.class.getDeclaredFields();
|
||||
for(java.lang.reflect.Field f: fields) {
|
||||
if(Modifier.isStatic(f.getModifiers()) &&
|
||||
Modifier.isPublic(f.getModifiers())) {
|
||||
try {
|
||||
constants.put(f.getName(), f.get(null).toString());
|
||||
} catch(Exception ex) {
|
||||
log.error("An exception occurred in trying to retrieve this field ", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
return constants;
|
||||
}
|
||||
private static Log log = LogFactory.getLog(EditConfigurationConstants.class);
|
||||
|
||||
}
|
|
@ -5,6 +5,9 @@ package edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration;
|
|||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import com.hp.hpl.jena.ontology.OntModel;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||
|
@ -12,6 +15,8 @@ import edu.cornell.mannlib.vitro.webapp.dao.jena.OntModelSelector;
|
|||
|
||||
public class StandardModelSelector implements ModelSelector {
|
||||
|
||||
private static final Log log = LogFactory.getLog(StandardModelSelector.class);
|
||||
|
||||
public OntModel getModel(HttpServletRequest request, ServletContext context) {
|
||||
VitroRequest vreq = new VitroRequest( request );
|
||||
|
||||
|
@ -23,12 +28,18 @@ public class StandardModelSelector implements ModelSelector {
|
|||
sessionOntModel = oms.getABoxModel();
|
||||
}
|
||||
}
|
||||
if(sessionOntModel != null && sessionOntModel instanceof OntModel )
|
||||
if(sessionOntModel != null && sessionOntModel instanceof OntModel ) {
|
||||
log.info("++++++++++ using OntModelSelector from session");
|
||||
return (OntModel)sessionOntModel;
|
||||
else
|
||||
} else if (vreq.getOntModelSelector() != null) {
|
||||
log.info("++++++++++ using OntModelSelector from request");
|
||||
return vreq.getOntModelSelector().getABoxModel();
|
||||
} else {
|
||||
log.info("++++++++++ using OntModelSelector from context");
|
||||
return ((OntModelSelector) context
|
||||
.getAttribute("unionOntModelSelector")).getABoxModel();
|
||||
}
|
||||
}
|
||||
|
||||
public static final ModelSelector selector = new StandardModelSelector();
|
||||
|
||||
|
|
|
@ -66,7 +66,7 @@ public abstract class BaseEditConfigurationGenerator implements EditConfiguratio
|
|||
//setup the model selectors for query, write and display models on editConfig
|
||||
setupModelSelectorsFromVitroRequest(vreq, editConfig);
|
||||
|
||||
OntModel queryModel = (OntModel)vreq.getAttribute("jenaOntModel");
|
||||
OntModel queryModel = vreq.getJenaOntModel(); // (OntModel)vreq.getAttribute("jenaOntModel");
|
||||
|
||||
if( editConfig.getSubjectUri() == null)
|
||||
editConfig.setSubjectUri( EditConfigurationUtils.getSubjectUri(vreq));
|
||||
|
|
|
@ -50,6 +50,8 @@ public class ProcessRdfFormController extends FreemarkerHttpServlet{
|
|||
|
||||
private Log log = LogFactory.getLog(ProcessRdfFormController.class);
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
protected Actions requiredActions(VitroRequest vreq) {
|
||||
return SimplePermission.DO_FRONT_END_EDITING.ACTIONS;
|
||||
|
|
|
@ -1,64 +0,0 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.filestorage.updater;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import com.hp.hpl.jena.rdf.model.Resource;
|
||||
|
||||
/**
|
||||
* Adjust any individual that has a thumbnail with no main image.
|
||||
*/
|
||||
public class AllThumbsAdjuster extends FsuScanner {
|
||||
private ImageDirectoryWithBackup imageDirectoryWithBackup;
|
||||
|
||||
public AllThumbsAdjuster(FSUController controller) {
|
||||
super(controller);
|
||||
this.imageDirectoryWithBackup = controller
|
||||
.getImageDirectoryWithBackup();
|
||||
}
|
||||
|
||||
/**
|
||||
* For every individual with thumbnails but no main images, create a main
|
||||
* image from the first thumbnail.
|
||||
*/
|
||||
public void adjust() {
|
||||
updateLog.section("Creating main images for thumbnails "
|
||||
+ "that have none.");
|
||||
|
||||
for (Resource resource : ModelWrapper.listResourcesWithProperty(model,
|
||||
thumbProperty)) {
|
||||
if (ResourceWrapper.getProperty(resource, imageProperty) == null) {
|
||||
createMainImageFromThumbnail(resource);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This individual has a thumbnail but no main image. Create one.
|
||||
* <ul>
|
||||
* <li>Figure a name for the main image.</li>
|
||||
* <li>Copy the thumbnail image file into the main image file.</li>
|
||||
* <li>Set that file as an image (old-style) on the individual.</li>
|
||||
* </ul>
|
||||
*/
|
||||
private void createMainImageFromThumbnail(Resource resource) {
|
||||
String thumbFilename = getValues(resource, thumbProperty).get(0);
|
||||
String mainFilename = addFilenamePrefix("_main_image_", thumbFilename);
|
||||
updateLog.log(resource, "creating a main file at '" + mainFilename
|
||||
+ "' to match the thumbnail at '" + thumbFilename + "'");
|
||||
|
||||
try {
|
||||
File thumbFile = imageDirectoryWithBackup
|
||||
.getExistingFile(thumbFilename);
|
||||
File mainFile = imageDirectoryWithBackup.getNewfile(mainFilename);
|
||||
mainFile = checkNameConflicts(mainFile);
|
||||
FileUtil.copyFile(thumbFile, mainFile);
|
||||
ResourceWrapper.addProperty(resource, imageProperty, mainFilename);
|
||||
} catch (IOException e) {
|
||||
updateLog.error(resource, "failed to create main file '"
|
||||
+ mainFilename + "'", e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,71 +0,0 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.filestorage.updater;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import com.hp.hpl.jena.rdf.model.Literal;
|
||||
import com.hp.hpl.jena.rdf.model.Property;
|
||||
import com.hp.hpl.jena.rdf.model.RDFNode;
|
||||
import com.hp.hpl.jena.rdf.model.Resource;
|
||||
import com.hp.hpl.jena.rdf.model.Statement;
|
||||
|
||||
/**
|
||||
* Removes any image properties (main or thumbnail) that point to files that
|
||||
* don't actually exist.
|
||||
*/
|
||||
public class DeadEndPropertyRemover extends FsuScanner {
|
||||
private ImageDirectoryWithBackup imageDirectoryWithBackup;
|
||||
|
||||
public DeadEndPropertyRemover(FSUController controller) {
|
||||
super(controller);
|
||||
this.imageDirectoryWithBackup = controller
|
||||
.getImageDirectoryWithBackup();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove dead end properties for both main images and thumbnails.
|
||||
*/
|
||||
public void remove() {
|
||||
updateLog.section("Removing image properties whose "
|
||||
+ "referenced files do not exist.");
|
||||
|
||||
removeDeadEndProperties(imageProperty, "main image");
|
||||
removeDeadEndProperties(thumbProperty, "thumbnail");
|
||||
}
|
||||
|
||||
/**
|
||||
* Check all of the individuals that possess this property.
|
||||
*/
|
||||
private void removeDeadEndProperties(Property prop, String label) {
|
||||
for (Resource resource : ModelWrapper.listResourcesWithProperty(model,
|
||||
prop)) {
|
||||
removeDeadEndPropertiesFromResource(resource, prop, label);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check these statments on this resource. If any of them does not point to
|
||||
* an existing file, remove the statement.
|
||||
*/
|
||||
private void removeDeadEndPropertiesFromResource(Resource resource,
|
||||
Property prop, String label) {
|
||||
for (Statement stmt : getStatements(resource, prop)) {
|
||||
RDFNode node = stmt.getObject();
|
||||
if (node.isLiteral()) {
|
||||
String filename = ((Literal) node).getString();
|
||||
File file = imageDirectoryWithBackup.getExistingFile(filename);
|
||||
if (!file.exists()) {
|
||||
updateLog.warn(
|
||||
resource,
|
||||
"removing link to " + label + " '" + filename
|
||||
+ "': file does not exist at '"
|
||||
+ file.getAbsolutePath() + "'.");
|
||||
|
||||
ModelWrapper.removeStatement(model, stmt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.filestorage.updater;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import com.hp.hpl.jena.rdf.model.Model;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.filestorage.UploadedFileHelper;
|
||||
import edu.cornell.mannlib.vitro.webapp.filestorage.backend.FileStorage;
|
||||
|
||||
/**
|
||||
* An object that can initialize one of the {@link FsuScanner}s.
|
||||
*/
|
||||
public interface FSUController {
|
||||
|
||||
/** The Jena model. */
|
||||
Model getModel();
|
||||
|
||||
/** The update log. */
|
||||
FSULog getUpdateLog();
|
||||
|
||||
/** The place to find or to create image files. */
|
||||
ImageDirectoryWithBackup getImageDirectoryWithBackup();
|
||||
|
||||
/** A helper with access to the DAO layer and the file storage system. */
|
||||
UploadedFileHelper getUploadedFileHelper();
|
||||
|
||||
/** The file storage system. */
|
||||
FileStorage getFileStorage();
|
||||
|
||||
/** Where to store the files that were translated. */
|
||||
File getTranslatedDirectory();
|
||||
|
||||
/** Where to store the files that weren't in use anyway. */
|
||||
File getUnreferencedDirectory();
|
||||
|
||||
}
|
|
@ -1,181 +0,0 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.filestorage.updater;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
import com.hp.hpl.jena.rdf.model.Literal;
|
||||
import com.hp.hpl.jena.rdf.model.Model;
|
||||
import com.hp.hpl.jena.rdf.model.Property;
|
||||
import com.hp.hpl.jena.rdf.model.RDFNode;
|
||||
import com.hp.hpl.jena.rdf.model.Resource;
|
||||
import com.hp.hpl.jena.rdf.model.Statement;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
|
||||
|
||||
/**
|
||||
* Writes the log file for the {@link FileStorageUpdater}. Be sure to call
|
||||
* {@link #close()} when finished.
|
||||
*/
|
||||
public class FSULog {
|
||||
private final SimpleDateFormat timeStamper = new SimpleDateFormat(
|
||||
"yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
private final File logFile;
|
||||
private final PrintWriter writer;
|
||||
private boolean open;
|
||||
|
||||
FSULog(File logDirectory, String prefix) throws IOException {
|
||||
this.logFile = generateTimestampedFilename(logDirectory, prefix);
|
||||
this.writer = new PrintWriter(this.logFile);
|
||||
open = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a filename for the log file that contains a timestamp, so if we
|
||||
* run the process more than once, we will see multiple files.
|
||||
*/
|
||||
private File generateTimestampedFilename(File upgradeDirectory,
|
||||
String prefix) {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH-mm-sss");
|
||||
String filename = prefix + "." + sdf.format(new Date()) + ".txt";
|
||||
return new File(upgradeDirectory, filename);
|
||||
}
|
||||
|
||||
/**
|
||||
* Where are we writing the output?
|
||||
*/
|
||||
String getFilename() {
|
||||
return this.logFile.getAbsolutePath();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write this message.
|
||||
*/
|
||||
void log(String message) {
|
||||
writer.println(timeStamper.format(new Date()) + " INFO " + message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write this message about this resource.
|
||||
*/
|
||||
void log(Resource resource, String message) {
|
||||
log(showResource(resource) + message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write this warning message.
|
||||
*/
|
||||
public void warn(String message) {
|
||||
writer.println(timeStamper.format(new Date()) + " WARN " + message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write this warning message about this resource.
|
||||
*/
|
||||
public void warn(Resource resource, String message) {
|
||||
warn(showResource(resource) + message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write this error message.
|
||||
*/
|
||||
void error(String message) {
|
||||
writer.println(timeStamper.format(new Date()) + " ERROR " + message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write this exception as an error message..
|
||||
*/
|
||||
void error(Exception e) {
|
||||
error(e.toString());
|
||||
e.printStackTrace(writer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write an error message with this exception.
|
||||
*/
|
||||
public void error(String message, Exception e) {
|
||||
error(message);
|
||||
e.printStackTrace(writer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write an error message about this resource and with this exception.
|
||||
*/
|
||||
public void error(Resource resource, String message) {
|
||||
error(showResource(resource) + message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write an error message about this resource and with this exception.
|
||||
*/
|
||||
public void error(Resource resource, String message, Exception e) {
|
||||
error(showResource(resource) + message, e);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a section heading.
|
||||
*/
|
||||
public void section(String message) {
|
||||
log(">>>>>>>>>> ");
|
||||
log(">>>>>>>>>> " + message);
|
||||
log(">>>>>>>>>> ");
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the writer, if not already closed.
|
||||
*/
|
||||
public void close() {
|
||||
if (open) {
|
||||
writer.close();
|
||||
open = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the resource label and URI for output in a message.
|
||||
*/
|
||||
private String showResource(Resource resource) {
|
||||
return "On resource '" + getLabel(resource) + "' (" + getUri(resource)
|
||||
+ "), ";
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the URI for this resource, if there is one.
|
||||
*/
|
||||
private String getUri(Resource resource) {
|
||||
if (resource != null) {
|
||||
String uri = resource.getURI();
|
||||
if (uri != null) {
|
||||
return uri;
|
||||
}
|
||||
}
|
||||
return "no URI";
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the label for this resource, if there is one.
|
||||
*/
|
||||
private String getLabel(Resource resource) {
|
||||
if (resource != null) {
|
||||
Model model = resource.getModel();
|
||||
if (model != null) {
|
||||
Property prop = model.createProperty(VitroVocabulary.LABEL);
|
||||
Statement stmt = resource.getProperty(prop);
|
||||
if (stmt != null) {
|
||||
RDFNode node = stmt.getObject();
|
||||
if (node.isLiteral()) {
|
||||
return ((Literal) node).getString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return "no label";
|
||||
}
|
||||
|
||||
}
|
|
@ -1,352 +0,0 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.filestorage.updater;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
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.QuerySolution;
|
||||
import com.hp.hpl.jena.query.ResultSet;
|
||||
import com.hp.hpl.jena.rdf.model.Literal;
|
||||
import com.hp.hpl.jena.rdf.model.Model;
|
||||
import com.hp.hpl.jena.rdf.model.Property;
|
||||
import com.hp.hpl.jena.rdf.model.RDFNode;
|
||||
import com.hp.hpl.jena.rdf.model.Resource;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
|
||||
|
||||
/**
|
||||
* Check all of the FileByteStream objects. If there are any that don't have
|
||||
* alias URLs, fix them.
|
||||
*/
|
||||
public class FileStorageAliasAdder {
|
||||
private static final Log log = LogFactory
|
||||
.getLog(FileStorageAliasAdder.class);
|
||||
|
||||
private static final String FILE_PATH = "/file/";
|
||||
|
||||
/**
|
||||
* Query: get all bytestream resources that do not have alias URLs.
|
||||
*/
|
||||
private static final String QUERY_BYTESTREAMS_WITHOUT_ALIASES = ""
|
||||
+ "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>\n"
|
||||
+ "PREFIX public: <http://vitro.mannlib.cornell.edu/ns/vitro/public#>\n"
|
||||
+ "SELECT ?bs\n" + "WHERE {\n"
|
||||
+ " ?bs rdf:type public:FileByteStream\n"
|
||||
+ " OPTIONAL { ?bs public:directDownloadUrl ?alias }\n"
|
||||
+ " FILTER ( !BOUND(?alias) )\n" + "}\n";
|
||||
|
||||
/**
|
||||
* Query: get the filenames for all bytestream resources that do not have
|
||||
* alias URLs.
|
||||
*/
|
||||
private static final String QUERY_FILENAMES_FOR_BYTESTREAMS = ""
|
||||
+ "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>\n"
|
||||
+ "PREFIX public: <http://vitro.mannlib.cornell.edu/ns/vitro/public#>\n"
|
||||
+ "SELECT ?bs ?fn\n" + "WHERE {\n"
|
||||
+ " ?bs rdf:type public:FileByteStream . \n"
|
||||
+ " ?f public:downloadLocation ?bs . \n"
|
||||
+ " ?f public:filename ?fn . \n"
|
||||
+ " OPTIONAL { ?bs public:directDownloadUrl ?alias . }\n"
|
||||
+ " FILTER ( !BOUND(?alias) )\n" + "}\n";
|
||||
|
||||
private final Model model;
|
||||
private final File upgradeDirectory;
|
||||
private final String vivoDefaultNamespace;
|
||||
|
||||
private FSULog updateLog;
|
||||
|
||||
private Set<String> bytestreamUrisWithoutAliases;
|
||||
private Map<String, String> bytestreamUrisAndFilenames;
|
||||
|
||||
public FileStorageAliasAdder(Model model, File uploadDirectory,
|
||||
String vivoDefaultNamespace) {
|
||||
this.model = model;
|
||||
this.upgradeDirectory = new File(uploadDirectory, "upgrade");
|
||||
this.vivoDefaultNamespace = vivoDefaultNamespace;
|
||||
}
|
||||
|
||||
/**
|
||||
* Go through all of the FileByteStream objects in the model, creating Alias
|
||||
* URLs for any objects that don't have them.
|
||||
*
|
||||
* If there is nothing to do, don't even create a log file, just exit.
|
||||
*
|
||||
* If there is something to do, go through the whole process.
|
||||
*
|
||||
* At the end, there should be nothing to do.
|
||||
*/
|
||||
public void update() {
|
||||
// If there is nothing to do, we're done: don't even create a log file.
|
||||
if (!isThereAnythingToDo()) {
|
||||
log.debug("Found no FileByteStreams without alias URLs.");
|
||||
return;
|
||||
}
|
||||
|
||||
setup();
|
||||
|
||||
try {
|
||||
findAndAddMissingAliasUrls();
|
||||
|
||||
if (isThereAnythingToDo()) {
|
||||
throw new IllegalStateException("FileStorageAliasAdder "
|
||||
+ "was unsuccessful -- model still contains "
|
||||
+ "FileByteStreams without alias URLs.");
|
||||
}
|
||||
|
||||
updateLog.section("Finished adding alias URLs to FileByteStreams.");
|
||||
} finally {
|
||||
updateLog.close();
|
||||
}
|
||||
|
||||
log.info("Finished adding alias URLs to FileByteStreams.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Query the model. If there are any FileByteStream objects with no Alias
|
||||
* URL, we have work to do.
|
||||
*/
|
||||
private boolean isThereAnythingToDo() {
|
||||
String queryString = QUERY_BYTESTREAMS_WITHOUT_ALIASES;
|
||||
log.debug("query: " + queryString);
|
||||
|
||||
QueryExecution qexec = null;
|
||||
try {
|
||||
qexec = createQueryExecutor(queryString);
|
||||
ResultSet results = qexec.execSelect();
|
||||
|
||||
boolean foundSome = results.hasNext();
|
||||
log.debug("any work to do? " + foundSome);
|
||||
|
||||
return foundSome;
|
||||
} catch (Exception e) {
|
||||
log.error(e, e);
|
||||
return false;
|
||||
} finally {
|
||||
if (qexec != null) {
|
||||
qexec.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the upgrade directory. Create the log file. If we fail, drop dead.
|
||||
*/
|
||||
private void setup() {
|
||||
try {
|
||||
this.upgradeDirectory.mkdirs();
|
||||
updateLog = new FSULog(this.upgradeDirectory,
|
||||
"FileStorageAliasAdder-log");
|
||||
log.info("Updating pre-1.1 file references. Log file is "
|
||||
+ updateLog.getFilename());
|
||||
} catch (IOException e) {
|
||||
if (updateLog != null) {
|
||||
updateLog.close();
|
||||
}
|
||||
throw new IllegalStateException("can't create log file: '"
|
||||
+ updateLog.getFilename() + "'", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an alias URL to any FileByteStream object that doesn't have one.
|
||||
*/
|
||||
private void findAndAddMissingAliasUrls() {
|
||||
findBytestreamsWithoutAliasUrls();
|
||||
findFilenamesForBytestreams();
|
||||
addAliasUrlsToModel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find every bytestream that doesn't have an alias URL.
|
||||
*/
|
||||
private void findBytestreamsWithoutAliasUrls() {
|
||||
BytestreamUriUnpacker unpacker = new BytestreamUriUnpacker();
|
||||
|
||||
runQuery(QUERY_BYTESTREAMS_WITHOUT_ALIASES, unpacker);
|
||||
this.bytestreamUrisWithoutAliases = unpacker.getUris();
|
||||
|
||||
log.debug("Found " + unpacker.getUris().size()
|
||||
+ " bytestreams without alias URLs");
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the filename for every bytestream that doesn't have an alias URL.
|
||||
*/
|
||||
private void findFilenamesForBytestreams() {
|
||||
FilenameUnpacker unpacker = new FilenameUnpacker();
|
||||
|
||||
runQuery(QUERY_FILENAMES_FOR_BYTESTREAMS, unpacker);
|
||||
this.bytestreamUrisAndFilenames = unpacker.getFilenameMap();
|
||||
|
||||
log.debug("Found " + unpacker.getFilenameMap().size()
|
||||
+ " bytestreams with filenames but no alias URLs");
|
||||
}
|
||||
|
||||
/** Add an alias URL to each resource in the list. */
|
||||
private void addAliasUrlsToModel() {
|
||||
if (this.bytestreamUrisWithoutAliases.isEmpty()) {
|
||||
updateLog.warn("Found no bytestreams without aliases. "
|
||||
+ "Why am I here?");
|
||||
return;
|
||||
}
|
||||
|
||||
Property aliasProperty = model
|
||||
.createProperty(VitroVocabulary.FS_ALIAS_URL);
|
||||
|
||||
for (String bytestreamUri : this.bytestreamUrisWithoutAliases) {
|
||||
String aliasUrl = figureAliasUrl(bytestreamUri);
|
||||
Resource resource = model.getResource(bytestreamUri);
|
||||
|
||||
ModelWrapper.add(model, resource, aliasProperty, aliasUrl);
|
||||
updateLog.log(resource, "added alias URL: '" + aliasUrl + "'");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the bytestream URI and the filename into an alias URL.
|
||||
*
|
||||
* If they aren't in our default namespace, or they don't have a filename,
|
||||
* then their URI is the best we can do for an alias URL.
|
||||
*/
|
||||
private String figureAliasUrl(String bytestreamUri) {
|
||||
if (!bytestreamUri.startsWith(vivoDefaultNamespace)) {
|
||||
updateLog.warn("bytestream uri does not start "
|
||||
+ "with the default namespace: '" + bytestreamUri + "'");
|
||||
return bytestreamUri;
|
||||
}
|
||||
|
||||
String filename = this.bytestreamUrisAndFilenames.get(bytestreamUri);
|
||||
if (filename == null) {
|
||||
updateLog.warn("bytestream has no surrogate or no filename: '"
|
||||
+ bytestreamUri + "'");
|
||||
return "filename_not_found";
|
||||
}
|
||||
|
||||
try {
|
||||
String remainder = bytestreamUri.substring(vivoDefaultNamespace
|
||||
.length());
|
||||
String encodedFilename = URLEncoder.encode(filename, "UTF-8");
|
||||
String separator = remainder.endsWith("/") ? "" : "/";
|
||||
|
||||
return FILE_PATH + remainder + separator + encodedFilename;
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new IllegalStateException(e); // No UTF-8? Can't happen.
|
||||
}
|
||||
}
|
||||
|
||||
private void runQuery(String queryString, QueryResultUnpacker unpacker) {
|
||||
log.debug("query: " + queryString);
|
||||
|
||||
QueryExecution qexec = null;
|
||||
try {
|
||||
qexec = createQueryExecutor(queryString);
|
||||
|
||||
Iterator<QuerySolution> results = qexec.execSelect();
|
||||
while (results.hasNext()) {
|
||||
QuerySolution result = results.next();
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Query result variables: "
|
||||
+ listVariables(result));
|
||||
}
|
||||
unpacker.unpack(result);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error(e, e);
|
||||
} finally {
|
||||
if (qexec != null) {
|
||||
qexec.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private QueryExecution createQueryExecutor(String queryString) {
|
||||
Query query = QueryFactory.create(queryString);
|
||||
return QueryExecutionFactory.create(query, model);
|
||||
}
|
||||
|
||||
/** For debug logging. */
|
||||
private List<String> listVariables(QuerySolution result) {
|
||||
List<String> list = new ArrayList<String>();
|
||||
for (Iterator<String> names = result.varNames(); names.hasNext();) {
|
||||
String name = names.next();
|
||||
RDFNode value = result.get(name);
|
||||
list.add(name + "=" + value);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Helper classes
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
private interface QueryResultUnpacker {
|
||||
public abstract void unpack(QuerySolution result);
|
||||
}
|
||||
|
||||
private class BytestreamUriUnpacker implements QueryResultUnpacker {
|
||||
private final Set<String> uris = new HashSet<String>();
|
||||
|
||||
@Override
|
||||
public void unpack(QuerySolution result) {
|
||||
Resource bytestream = result.getResource("bs");
|
||||
if (bytestream == null) {
|
||||
updateLog.error("Query result contains no "
|
||||
+ "bytestream resource: " + result);
|
||||
return;
|
||||
}
|
||||
|
||||
uris.add(bytestream.getURI());
|
||||
}
|
||||
|
||||
public Set<String> getUris() {
|
||||
return uris;
|
||||
}
|
||||
}
|
||||
|
||||
private class FilenameUnpacker implements QueryResultUnpacker {
|
||||
private final Map<String, String> filenameMap = new HashMap<String, String>();
|
||||
|
||||
@Override
|
||||
public void unpack(QuerySolution result) {
|
||||
Resource bytestream = result.getResource("bs");
|
||||
if (bytestream == null) {
|
||||
updateLog.error("Query result contains no "
|
||||
+ "bytestream resource: " + result);
|
||||
return;
|
||||
}
|
||||
String bytestreamUri = bytestream.getURI();
|
||||
|
||||
Literal filenameLiteral = result.getLiteral("fn");
|
||||
if (filenameLiteral == null) {
|
||||
updateLog.error("Query result for '" + bytestreamUri
|
||||
+ "' contains no filename.");
|
||||
return;
|
||||
}
|
||||
String filename = filenameLiteral.getString();
|
||||
|
||||
filenameMap.put(bytestreamUri, filename);
|
||||
}
|
||||
|
||||
public Map<String, String> getFilenameMap() {
|
||||
return filenameMap;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,268 +0,0 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.filestorage.updater;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import com.hp.hpl.jena.rdf.model.Model;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
|
||||
import edu.cornell.mannlib.vitro.webapp.filestorage.UploadedFileHelper;
|
||||
import edu.cornell.mannlib.vitro.webapp.filestorage.backend.FileStorage;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Clean up any files that are stored in the old directory structure and
|
||||
* referenced by old-style image properties.
|
||||
* </p>
|
||||
* <p>
|
||||
* Besides converting the files to the new framework, this process will produce
|
||||
* these artifacts:
|
||||
* <ul>
|
||||
* <li>A log file in the uploaded files directory, with a timestamped name, such
|
||||
* as <code>upgrade/upgradeLog2010-06-20T14-55-00.txt</code>, for example. If
|
||||
* for any reason, the upgrade process must run again, the log will not be
|
||||
* overwritten.</li>
|
||||
* <li>A directory of "deleted" files - these were extra thumbnail files or
|
||||
* extra main image files -- see the details below.</li>
|
||||
* <li>A directory of "unreferenced" files - these were in the image directory,
|
||||
* but not connected to any entity.</li>
|
||||
* </ul>
|
||||
* </p>
|
||||
* <p>
|
||||
* We consider some special cases:
|
||||
* <ul>
|
||||
* <li>An individual may refer to an image file that does not actually exist. If
|
||||
* so, that reference will be deleted.</li>
|
||||
* <li>There may be more than one reference to the same image file. If so, all
|
||||
* but the first such reference will be deleted.</li>
|
||||
* <li>
|
||||
* In the old style, it was possible to have a main image without a thumbnail.
|
||||
* If we find that, we will generate a scaled down copy of the main image, store
|
||||
* that as a thumbnail image file, and then proceed.</li>
|
||||
* <li>
|
||||
* In the old style, it was possible to have a thumbnail without a main image.
|
||||
* If we find that, we will make a copy of the thumbnail image file, declare
|
||||
* that copy to be the main image, and then proceed.</li>
|
||||
* <li>
|
||||
* We may find individuals with more than one main image, or more than one
|
||||
* thumbnail. If so, we will discard all but the first one (move them to the
|
||||
* "deleted" directory).</li>
|
||||
* </ul>
|
||||
* </p>
|
||||
* <p>
|
||||
* Aside from these special cases, we will:
|
||||
* <ul>
|
||||
* <li>Translate the main image.
|
||||
* <ul>
|
||||
* <li>Store the image in the new file system.</li>
|
||||
* <li>Delete the image from the old images directory.</li>
|
||||
* <li>Create a ByteStream individual for the main image.</li>
|
||||
* <li>Create a Surrogate individual for the main image.</li>
|
||||
* <li>Tie these together and attach to the entity that owns the image.</li>
|
||||
* </ul>
|
||||
* </li>
|
||||
* <li>Translate the thumbnail.
|
||||
* <ul>
|
||||
* <li>Store the thumbnail in the new file system.</li>
|
||||
* <li>Create a ByteStream individual for the thumbnail.</li>
|
||||
* <li>Create a Surrogate individual for the thumbnail.</li>
|
||||
* <li>Tie these together and attach to the Surrogate for the main image.</li>
|
||||
* </ul>
|
||||
* </li>
|
||||
* </ul>
|
||||
* </p>
|
||||
* <p>
|
||||
* After processing all of these cases, there may be some images remaining in
|
||||
* the "images" directory. These will be moved to the "unreferenced" directory,
|
||||
* while preserving any internal tree structure.
|
||||
* </p>
|
||||
*/
|
||||
public class FileStorageUpdater implements FSUController {
|
||||
private static final Log log = LogFactory.getLog(FileStorageUpdater.class);
|
||||
|
||||
/** How wide should a generated thumbnail image be (in pixels)? */
|
||||
public static final int THUMBNAIL_WIDTH = 200;
|
||||
|
||||
/** How high should a generated thumbnail image be (in pixels)? */
|
||||
public static final int THUMBNAIL_HEIGHT = 200;
|
||||
|
||||
/** How is the main image referenced in the old scheme? */
|
||||
public static final String IMAGEFILE = VitroVocabulary.vitroURI
|
||||
+ "imageFile";
|
||||
|
||||
/** How is the thumbnail referenced in the old scheme? */
|
||||
public static final String IMAGETHUMB = VitroVocabulary.vitroURI
|
||||
+ "imageThumb";
|
||||
|
||||
private final Model model;
|
||||
|
||||
private final FileStorage fileStorage;
|
||||
private final UploadedFileHelper uploadedFileHelper;
|
||||
private final ImageDirectoryWithBackup imageDirectoryWithBackup;
|
||||
private final File upgradeDirectory;
|
||||
|
||||
private FSULog updateLog;
|
||||
|
||||
public FileStorageUpdater(WebappDaoFactory wadf, Model model,
|
||||
FileStorage fileStorage, File uploadDirectory,
|
||||
File webappImageDirectory, ServletContext ctx) {
|
||||
this.model = model;
|
||||
this.fileStorage = fileStorage;
|
||||
this.uploadedFileHelper = new UploadedFileHelper(fileStorage, wadf, ctx);
|
||||
this.upgradeDirectory = new File(uploadDirectory, "upgrade");
|
||||
|
||||
this.imageDirectoryWithBackup = new ImageDirectoryWithBackup(new File(
|
||||
uploadDirectory, "images"), webappImageDirectory);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Go through all of the individuals who have image files or thumbnail
|
||||
* files, adjusting them to the new way.
|
||||
* </p>
|
||||
* <p>
|
||||
* If there is nothing to do, don't even create a log file, just exit.
|
||||
* </p>
|
||||
* <p>
|
||||
* If there is something to do, go through the whole process.
|
||||
* </p>
|
||||
* <p>
|
||||
* At the end, there should be nothing to do. If that's true, clean out the
|
||||
* old images directory.
|
||||
* </p>
|
||||
*/
|
||||
public void update() {
|
||||
// If there is nothing to do, we're done: don't even create a log file.
|
||||
if (!isThereAnythingToDo()) {
|
||||
log.debug("Found no pre-1.1 file references.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the upgrade directory and the log file.
|
||||
setup();
|
||||
|
||||
try {
|
||||
// Remove any image properties that don't point to literals.
|
||||
new NonLiteralPropertyRemover(this).remove();
|
||||
|
||||
// Remove any image properties that point to files that don't exist.
|
||||
new DeadEndPropertyRemover(this).remove();
|
||||
|
||||
// No resource may have multiple main images or multiple thumbnails.
|
||||
new MultiplePropertyRemover(this).remove();
|
||||
|
||||
// Create a main image for any thumbnail that doesn't have one.
|
||||
new AllThumbsAdjuster(this).adjust();
|
||||
|
||||
// Create a thumbnail for any main image that doesn't have one.
|
||||
new NoThumbsAdjuster(this).adjust();
|
||||
|
||||
// Copy all images into the new file storage system, translating
|
||||
// into the new schema. Get a list of all the images we translated.
|
||||
ImageSchemaTranslater translater = new ImageSchemaTranslater(this);
|
||||
Collection<String> translatedFiles = translater.translate();
|
||||
|
||||
if (isThereAnythingToDo()) {
|
||||
throw new IllegalStateException(
|
||||
"FileStorageUpdate was unsuccessful -- "
|
||||
+ "model still contains pre-1.1 file references.");
|
||||
}
|
||||
|
||||
// Clean out the old image directory, separating into files which
|
||||
// were translated, and files for which we found no reference.
|
||||
new ImageDirectoryCleaner(this).clean(translatedFiles);
|
||||
|
||||
updateLog.section("File Storage update is complete.");
|
||||
} finally {
|
||||
updateLog.close();
|
||||
}
|
||||
|
||||
log.info("Finished updating pre-1.1 file references.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Query the model. If there are any resources with old-style image
|
||||
* properties, we have work to do.
|
||||
*/
|
||||
private boolean isThereAnythingToDo() {
|
||||
if (!ModelWrapper.listResourcesWithProperty(model,
|
||||
model.createProperty(IMAGEFILE)).isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!ModelWrapper.listResourcesWithProperty(model,
|
||||
model.createProperty(IMAGETHUMB)).isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the upgrade directory. Create the log file. If we fail, drop dead.
|
||||
*/
|
||||
private void setup() {
|
||||
try {
|
||||
this.upgradeDirectory.mkdirs();
|
||||
updateLog = new FSULog(this.upgradeDirectory,
|
||||
"FileStorageUpdater-log");
|
||||
log.info("Updating pre-1.1 file references. Log file is "
|
||||
+ updateLog.getFilename());
|
||||
} catch (IOException e) {
|
||||
if (updateLog != null) {
|
||||
updateLog.close();
|
||||
}
|
||||
throw new IllegalStateException("can't create log file: '"
|
||||
+ updateLog.getFilename() + "'", e);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Methods to set up the individual scanners.
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public Model getModel() {
|
||||
return this.model;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FSULog getUpdateLog() {
|
||||
return this.updateLog;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UploadedFileHelper getUploadedFileHelper() {
|
||||
return this.uploadedFileHelper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileStorage getFileStorage() {
|
||||
return this.fileStorage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImageDirectoryWithBackup getImageDirectoryWithBackup() {
|
||||
return this.imageDirectoryWithBackup;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getTranslatedDirectory() {
|
||||
return new File(this.upgradeDirectory, "translatedImages");
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getUnreferencedDirectory() {
|
||||
return new File(this.upgradeDirectory, "unreferencedImages");
|
||||
}
|
||||
|
||||
}
|
|
@ -1,107 +0,0 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.filestorage.updater;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* A collection of static routines for moving, copying and deleting files.
|
||||
*/
|
||||
public class FileUtil {
|
||||
/**
|
||||
* Copy a file from one location to another, and remove it from the original
|
||||
* location.
|
||||
*/
|
||||
public static void moveFile(File from, File to) throws IOException {
|
||||
copyFile(from, to);
|
||||
deleteFile(from);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy a file from one location to another.
|
||||
*/
|
||||
public static void copyFile(File from, File to) throws IOException {
|
||||
if (!from.exists()) {
|
||||
throw new FileNotFoundException("File '" + from.getAbsolutePath()
|
||||
+ "' does not exist.");
|
||||
}
|
||||
|
||||
InputStream in = null;
|
||||
try {
|
||||
in = new FileInputStream(from);
|
||||
writeFile(in, to);
|
||||
} finally {
|
||||
if (in != null) {
|
||||
try {
|
||||
in.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a file with the contents of this data stream.
|
||||
*
|
||||
* @param stream
|
||||
* the data stream. You must close it afterward.
|
||||
*/
|
||||
public static void writeFile(InputStream stream, File to)
|
||||
throws IOException {
|
||||
if (to.exists()) {
|
||||
throw new IOException("File '" + to.getAbsolutePath()
|
||||
+ "' already exists.");
|
||||
}
|
||||
|
||||
File parent = to.getParentFile();
|
||||
if (!parent.exists()) {
|
||||
parent.mkdirs();
|
||||
if (!parent.exists()) {
|
||||
throw new IOException("Can't create parent directory for '"
|
||||
+ to.getAbsolutePath() + "'");
|
||||
}
|
||||
}
|
||||
|
||||
OutputStream out = null;
|
||||
try {
|
||||
out = new FileOutputStream(to);
|
||||
byte[] buffer = new byte[8192];
|
||||
int howMany;
|
||||
while (-1 != (howMany = stream.read(buffer))) {
|
||||
out.write(buffer, 0, howMany);
|
||||
}
|
||||
} finally {
|
||||
if (out != null) {
|
||||
try {
|
||||
out.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete this file, and make sure that it's gone.
|
||||
*/
|
||||
public static void deleteFile(File file) throws IOException {
|
||||
file.delete();
|
||||
if (file.exists()) {
|
||||
throw new IOException("Failed to delete file '"
|
||||
+ file.getAbsolutePath() + "'");
|
||||
}
|
||||
}
|
||||
|
||||
/** No need to instantiate it -- all methods are static. */
|
||||
private FileUtil() {
|
||||
// Nothing to instantiate.
|
||||
}
|
||||
|
||||
}
|
|
@ -1,126 +0,0 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.filestorage.updater;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.hp.hpl.jena.rdf.model.Literal;
|
||||
import com.hp.hpl.jena.rdf.model.Model;
|
||||
import com.hp.hpl.jena.rdf.model.Property;
|
||||
import com.hp.hpl.jena.rdf.model.RDFNode;
|
||||
import com.hp.hpl.jena.rdf.model.Resource;
|
||||
import com.hp.hpl.jena.rdf.model.Statement;
|
||||
import com.hp.hpl.jena.rdf.model.StmtIterator;
|
||||
import com.hp.hpl.jena.shared.Lock;
|
||||
|
||||
/**
|
||||
* Base class for the tools that scan the model. Holds some useful fields and
|
||||
* some utility methods.
|
||||
*/
|
||||
public abstract class FsuScanner {
|
||||
protected final Model model;
|
||||
protected final FSULog updateLog;
|
||||
|
||||
protected final Property imageProperty;
|
||||
protected final Property thumbProperty;
|
||||
|
||||
public FsuScanner(FSUController controller) {
|
||||
this.model = controller.getModel();
|
||||
this.updateLog = controller.getUpdateLog();
|
||||
|
||||
this.imageProperty = model.createProperty(FileStorageUpdater.IMAGEFILE);
|
||||
this.thumbProperty = model
|
||||
.createProperty(FileStorageUpdater.IMAGETHUMB);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read all of the specified properties on a resource, and return a
|
||||
* {@link List} of the {@link String} values.
|
||||
*/
|
||||
protected List<String> getValues(Resource resource, Property property) {
|
||||
List<String> list = new ArrayList<String>();
|
||||
StmtIterator stmts = resource.listProperties(property);
|
||||
try {
|
||||
while (stmts.hasNext()) {
|
||||
Statement stmt = stmts.next();
|
||||
RDFNode object = stmt.getObject();
|
||||
if (object.isLiteral()) {
|
||||
list.add(((Literal) object).getString());
|
||||
} else {
|
||||
updateLog.error(resource,
|
||||
"property value was not a literal: "
|
||||
+ "property is '" + property.getURI()
|
||||
+ "', value is '" + object + "'");
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
stmts.close();
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read all of the specified properties on a resource, and return a
|
||||
* {@link List} of the {@link Statement}s.
|
||||
*/
|
||||
protected List<Statement> getStatements(Resource resource, Property property) {
|
||||
List<Statement> list = new ArrayList<Statement>();
|
||||
|
||||
resource.getModel().enterCriticalSection(Lock.READ);
|
||||
StmtIterator stmts = resource.listProperties(property);
|
||||
try {
|
||||
while (stmts.hasNext()) {
|
||||
list.add(stmts.next());
|
||||
}
|
||||
} finally {
|
||||
stmts.close();
|
||||
resource.getModel().leaveCriticalSection();
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the filename within a path so we can add this prefix to it, while
|
||||
* retaining the path.
|
||||
*/
|
||||
protected String addFilenamePrefix(String prefix, String path) {
|
||||
int slashHere = Math.max(path.lastIndexOf('/'), path.lastIndexOf('\\'));
|
||||
if (slashHere == -1) {
|
||||
return prefix + path;
|
||||
} else {
|
||||
String dirs = path.substring(0, slashHere + 1);
|
||||
String filename = path.substring(slashHere + 1);
|
||||
return dirs + prefix + filename;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* We are about to create a file - if a file of this name already exists,
|
||||
* increment the name until we have no collision.
|
||||
*
|
||||
* @return the original file, or the file with the incremented name.
|
||||
*/
|
||||
protected File checkNameConflicts(final File file) {
|
||||
if (!file.exists()) {
|
||||
// No conflict.
|
||||
return file;
|
||||
}
|
||||
|
||||
File parent = file.getParentFile();
|
||||
String filename = file.getName();
|
||||
for (int i = 0; i < 100; i++) {
|
||||
File newFile = new File(parent, i + filename);
|
||||
if (!newFile.exists()) {
|
||||
updateLog.log("File '" + file + "' already exists, using '"
|
||||
+ newFile + "' to avoid conflict.");
|
||||
return newFile;
|
||||
}
|
||||
}
|
||||
|
||||
updateLog.error("File '" + file
|
||||
+ "' already exists. Unable to avoid conflict.");
|
||||
return file;
|
||||
}
|
||||
}
|
|
@ -1,134 +0,0 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.filestorage.updater;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Clean out the old image directory. Copy the files into the upgrade directory,
|
||||
* separating into the ones that we translated, and the ones that weren't
|
||||
* referenced.
|
||||
*/
|
||||
public class ImageDirectoryCleaner extends FsuScanner {
|
||||
private final ImageDirectoryWithBackup imageDirectoryWithBackup;
|
||||
protected final File translatedDirectory;
|
||||
protected final File unreferencedDirectory;
|
||||
|
||||
public ImageDirectoryCleaner(FSUController controller) {
|
||||
super(controller);
|
||||
this.imageDirectoryWithBackup = controller
|
||||
.getImageDirectoryWithBackup();
|
||||
|
||||
this.translatedDirectory = controller.getTranslatedDirectory();
|
||||
this.unreferencedDirectory = controller.getUnreferencedDirectory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all of the files from the old image directory.
|
||||
*/
|
||||
public void clean(Collection<String> translatedFiles) {
|
||||
updateLog.section("Cleaning the old image directory of "
|
||||
+ "files that were translated.");
|
||||
removeTranslatedFiles(translatedFiles);
|
||||
|
||||
updateLog.section("Cleaning the old image directory of "
|
||||
+ "files that were not referenced.");
|
||||
removeRemainingFiles(imageDirectoryWithBackup
|
||||
.getPrimaryImageDirectory());
|
||||
}
|
||||
|
||||
/**
|
||||
* Move all of the files that we translated into the new system.
|
||||
*/
|
||||
private void removeTranslatedFiles(Collection<String> translatedFiles) {
|
||||
for (String path : translatedFiles) {
|
||||
File oldFile = new File(
|
||||
imageDirectoryWithBackup.getPrimaryImageDirectory(), path);
|
||||
if (oldFile.exists()) {
|
||||
updateLog.log("moving image file '" + path
|
||||
+ "' to the 'translated' directory.");
|
||||
File deletedFile = new File(translatedDirectory, path);
|
||||
try {
|
||||
FileUtil.moveFile(oldFile, deletedFile);
|
||||
} catch (IOException e) {
|
||||
updateLog.error("Failed to move translated file '"
|
||||
+ oldFile.getAbsolutePath() + "'");
|
||||
}
|
||||
} else {
|
||||
updateLog.log("Not moving image file '" + path
|
||||
+ "' to the 'translated' directory -- "
|
||||
+ "found it in the backup directory.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Go through the images directory, and discard any that remain. They must
|
||||
* not have been referenced by any existing individuals.
|
||||
*/
|
||||
private void removeRemainingFiles(File directory) {
|
||||
updateLog.log("Cleaning image directory '" + directory + "'");
|
||||
try {
|
||||
File targetDirectory = makeCorrespondingDirectory(directory);
|
||||
File[] children = directory.listFiles();
|
||||
if (children != null) {
|
||||
for (File child : children) {
|
||||
if (child.isDirectory()) {
|
||||
removeRemainingFiles(child);
|
||||
} else {
|
||||
moveUnreferencedFile(targetDirectory, child);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
updateLog.error(
|
||||
"Failed to clean images directory '"
|
||||
+ directory.getAbsolutePath() + "'", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Move this file from its current location to its new home in the
|
||||
* "unreferenced" directory. Log it.
|
||||
*/
|
||||
private void moveUnreferencedFile(File targetDirectory, File file) {
|
||||
updateLog.log("Moving image file '" + file.getPath()
|
||||
+ "' to the 'unreferenced' directory");
|
||||
try {
|
||||
File newFile = new File(targetDirectory, file.getName());
|
||||
FileUtil.moveFile(file, newFile);
|
||||
} catch (IOException e) {
|
||||
updateLog.error(
|
||||
"Can't move unreferenced file '" + file.getAbsolutePath()
|
||||
+ "'", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Figure out the path from the "images" directory to this one, and create a
|
||||
* corresponding directory in the "unreferenced" area.
|
||||
*/
|
||||
private File makeCorrespondingDirectory(File directory) throws IOException {
|
||||
String imagesPath = imageDirectoryWithBackup.getPrimaryImageDirectory()
|
||||
.getAbsolutePath();
|
||||
String thisPath = directory.getAbsolutePath();
|
||||
|
||||
if (!thisPath.startsWith(imagesPath)) {
|
||||
throw new IOException("Can't make a corresponding directory for '"
|
||||
+ thisPath + "'");
|
||||
}
|
||||
|
||||
String suffix = thisPath.substring(imagesPath.length());
|
||||
|
||||
File corresponding = new File(unreferencedDirectory, suffix);
|
||||
corresponding.mkdirs();
|
||||
if (!corresponding.exists()) {
|
||||
throw new IOException("Failed to create corresponding directory '"
|
||||
+ corresponding.getAbsolutePath() + "'");
|
||||
}
|
||||
|
||||
return corresponding;
|
||||
}
|
||||
}
|
|
@ -1,77 +0,0 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.filestorage.updater;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* A way to look for files in TOMCAT_WEBAPP/vivo/images, if they are not found
|
||||
* in upload.directory/images.
|
||||
*/
|
||||
public class ImageDirectoryWithBackup {
|
||||
private static final Log log = LogFactory
|
||||
.getLog(ImageDirectoryWithBackup.class);
|
||||
|
||||
/** The primary image directory, where we do most of the manipulation. */
|
||||
private final File uploadImageDirectory;
|
||||
|
||||
/**
|
||||
* If we are looking for a file and don't find it in the primary directory,
|
||||
* look for it here.
|
||||
*/
|
||||
private final File webappImageDirectory;
|
||||
|
||||
/**
|
||||
* Be careful! webappImageDirectory may be null.
|
||||
*/
|
||||
public ImageDirectoryWithBackup(File uploadImageDirectory,
|
||||
File webappImageDirectory) {
|
||||
this.uploadImageDirectory = uploadImageDirectory;
|
||||
this.webappImageDirectory = webappImageDirectory;
|
||||
}
|
||||
|
||||
/**
|
||||
* When looking to read a file, start by looking in the
|
||||
* {@link #uploadImageDirectory}.
|
||||
*
|
||||
* If the file isn't found there, look in the {@link #webappImageDirectory}
|
||||
* as a fallback.
|
||||
*
|
||||
* If not there either, return the pointer to the nonexistent file in the
|
||||
* {@link #uploadImageDirectory}.
|
||||
*/
|
||||
File getExistingFile(String relativePath) {
|
||||
File file1 = new File(uploadImageDirectory, relativePath);
|
||||
if (file1.exists()) {
|
||||
log.trace("Found file: " + file1.getAbsolutePath());
|
||||
return file1;
|
||||
}
|
||||
if (webappImageDirectory != null) {
|
||||
File file2 = new File(webappImageDirectory, relativePath);
|
||||
if (file2.exists()) {
|
||||
log.trace("Found file: " + file2.getAbsolutePath());
|
||||
return file2;
|
||||
}
|
||||
}
|
||||
log.trace("Didn't find file: " + file1.getAbsolutePath());
|
||||
return file1;
|
||||
}
|
||||
|
||||
/**
|
||||
* New files will always be created in the primary directory.
|
||||
*/
|
||||
File getNewfile(String relativePath) {
|
||||
return new File(uploadImageDirectory, relativePath);
|
||||
}
|
||||
|
||||
/**
|
||||
* You can get a direct reference to the primary image directory, but it
|
||||
* should only be used for directory-base operations, like final cleanup.
|
||||
*/
|
||||
public File getPrimaryImageDirectory() {
|
||||
return uploadImageDirectory;
|
||||
}
|
||||
}
|
|
@ -1,170 +0,0 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.filestorage.updater;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
|
||||
import com.hp.hpl.jena.rdf.model.ResIterator;
|
||||
import com.hp.hpl.jena.rdf.model.Resource;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.filestorage.UploadedFileHelper;
|
||||
import edu.cornell.mannlib.vitro.webapp.filestorage.backend.FileStorage;
|
||||
import edu.cornell.mannlib.vitro.webapp.filestorage.model.FileInfo;
|
||||
|
||||
/**
|
||||
* Make copies of the main image and thumbnail in the new file storage system,
|
||||
* and in the model. Remove the old properties, but don't remove the old files
|
||||
* yet, in case someone else is referring to them also.
|
||||
*/
|
||||
public class ImageSchemaTranslater extends FsuScanner {
|
||||
private final ImageDirectoryWithBackup imageDirectoryWithBackup;
|
||||
protected final FileStorage fileStorage;
|
||||
protected final UploadedFileHelper uploadedFileHelper;
|
||||
|
||||
public ImageSchemaTranslater(FSUController controller) {
|
||||
super(controller);
|
||||
this.imageDirectoryWithBackup = controller
|
||||
.getImageDirectoryWithBackup();
|
||||
this.fileStorage = controller.getFileStorage();
|
||||
this.uploadedFileHelper = controller.getUploadedFileHelper();
|
||||
}
|
||||
|
||||
/**
|
||||
* By the time we get here, any individual with a main image also has a
|
||||
* thumbnail, and vice versa, and exactly one of each. For each one,
|
||||
* translate the main image and the thumbnail into the new system.
|
||||
*/
|
||||
public Collection<String> translate() {
|
||||
updateLog.section("Copying images into the new file storage, "
|
||||
+ "and adding them to the new model.");
|
||||
|
||||
SortedSet<String> translated = new TreeSet<String>();
|
||||
ResIterator haveImage = model.listResourcesWithProperty(imageProperty);
|
||||
try {
|
||||
while (haveImage.hasNext()) {
|
||||
Resource resource = haveImage.next();
|
||||
translateImages(resource, translated);
|
||||
}
|
||||
} finally {
|
||||
haveImage.close();
|
||||
}
|
||||
return translated;
|
||||
}
|
||||
|
||||
/**
|
||||
* This individual should have exactly one main image and exactly one
|
||||
* thumbnail.
|
||||
* <ul>
|
||||
* <li>Translate the first main image into the new system.</li>
|
||||
* <li>Translate the first thumbnail into the new system.</li>
|
||||
* <li>Remove all old-style main image properties.</li>
|
||||
* <li>Remove all old-style thumbnail properties.</li>
|
||||
* </ul>
|
||||
*/
|
||||
private void translateImages(Resource resource,
|
||||
Collection<String> translated) {
|
||||
List<String> mainImages = getValues(resource, imageProperty);
|
||||
if (mainImages.size() != 1) {
|
||||
updateLog.error(resource, "has " + mainImages.size()
|
||||
+ " main images: " + mainImages);
|
||||
return;
|
||||
}
|
||||
|
||||
List<String> thumbnails = getValues(resource, thumbProperty);
|
||||
if (thumbnails.size() != 1) {
|
||||
updateLog.error(resource, "has " + thumbnails.size()
|
||||
+ " thumbnails: " + thumbnails);
|
||||
return;
|
||||
}
|
||||
|
||||
FileInfo main = translateFile(resource, mainImages.get(0), "main image");
|
||||
FileInfo thumb = translateFile(resource, thumbnails.get(0), "thumbnail");
|
||||
if ((main == null) || (thumb == null)) {
|
||||
return;
|
||||
}
|
||||
uploadedFileHelper.setImagesOnEntity(resource.getURI(), main, thumb);
|
||||
|
||||
translated.add(mainImages.get(0));
|
||||
ResourceWrapper.removeAll(resource, imageProperty);
|
||||
|
||||
translated.add(thumbnails.get(0));
|
||||
ResourceWrapper.removeAll(resource, thumbProperty);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate an image file into the new system
|
||||
* <ul>
|
||||
* <li>Attempt to infer MIME type.</li>
|
||||
* <li>Copy into the File system.</li>
|
||||
* <li>Create the File and Bytestream individuals in the model.</li>
|
||||
* </ul>
|
||||
*/
|
||||
private FileInfo translateFile(Resource resource, String path, String label) {
|
||||
File oldFile = imageDirectoryWithBackup.getExistingFile(path);
|
||||
String filename = getSimpleFilename(path);
|
||||
String mimeType = guessMimeType(resource, filename);
|
||||
|
||||
InputStream inputStream = null;
|
||||
try {
|
||||
inputStream = new FileInputStream(oldFile);
|
||||
// Create the file individuals in the model
|
||||
FileInfo fileInfo = uploadedFileHelper.createFile(filename,
|
||||
mimeType, inputStream);
|
||||
updateLog.log(resource, "translating " + label + " '" + path
|
||||
+ "' into the file storage as '" + fileInfo.getUri() + "'");
|
||||
return fileInfo;
|
||||
} catch (IOException e) {
|
||||
updateLog.error(resource, "Can't create the " + label + " file. ",
|
||||
e);
|
||||
return null;
|
||||
} finally {
|
||||
if (inputStream != null) {
|
||||
try {
|
||||
inputStream.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove any path parts, and just get the filename and extension.
|
||||
*/
|
||||
private String getSimpleFilename(String path) {
|
||||
return FilenameUtils.getName(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Guess what the MIME type might be.
|
||||
*/
|
||||
private String guessMimeType(Resource resource, String filename) {
|
||||
if (filename.endsWith(".gif") || filename.endsWith(".GIF")) {
|
||||
return "image/gif";
|
||||
} else if (filename.endsWith(".png") || filename.endsWith(".PNG")) {
|
||||
return "image/png";
|
||||
} else if (filename.endsWith(".jpg") || filename.endsWith(".JPG")) {
|
||||
return "image/jpeg";
|
||||
} else if (filename.endsWith(".jpeg") || filename.endsWith(".JPEG")) {
|
||||
return "image/jpeg";
|
||||
} else if (filename.endsWith(".jpe") || filename.endsWith(".JPE")) {
|
||||
return "image/jpeg";
|
||||
} else {
|
||||
updateLog.warn(resource,
|
||||
"can't recognize the MIME type of this image file: '"
|
||||
+ filename + "'");
|
||||
return "image";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.filestorage.updater;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import com.hp.hpl.jena.rdf.model.Model;
|
||||
import com.hp.hpl.jena.rdf.model.Property;
|
||||
import com.hp.hpl.jena.rdf.model.ResIterator;
|
||||
import com.hp.hpl.jena.rdf.model.Resource;
|
||||
import com.hp.hpl.jena.rdf.model.Statement;
|
||||
import com.hp.hpl.jena.shared.Lock;
|
||||
|
||||
/**
|
||||
* Utility methods that operate against the Model with proper locks.
|
||||
*/
|
||||
public class ModelWrapper {
|
||||
|
||||
public static Collection<Resource> listResourcesWithProperty(Model model,
|
||||
Property property) {
|
||||
List<Resource> list = new ArrayList<Resource>();
|
||||
ResIterator iterator = model.listResourcesWithProperty(property);
|
||||
try {
|
||||
while (iterator.hasNext()) {
|
||||
Resource resource = iterator.next();
|
||||
list.add(resource);
|
||||
}
|
||||
} finally {
|
||||
iterator.close();
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public static void removeStatement(Model model, Statement stmt) {
|
||||
model.enterCriticalSection(Lock.WRITE);
|
||||
try {
|
||||
model.remove(stmt);
|
||||
} finally {
|
||||
model.leaveCriticalSection();
|
||||
}
|
||||
}
|
||||
|
||||
public static void add(Model model, Resource subject, Property predicate,
|
||||
String value) {
|
||||
model.enterCriticalSection(Lock.WRITE);
|
||||
try {
|
||||
model.add(subject, predicate, value);
|
||||
} finally {
|
||||
model.leaveCriticalSection();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,65 +0,0 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.filestorage.updater;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.hp.hpl.jena.rdf.model.Literal;
|
||||
import com.hp.hpl.jena.rdf.model.Property;
|
||||
import com.hp.hpl.jena.rdf.model.RDFNode;
|
||||
import com.hp.hpl.jena.rdf.model.Resource;
|
||||
import com.hp.hpl.jena.rdf.model.Statement;
|
||||
|
||||
/**
|
||||
* If a resource has more than one image or more than one thumbnail, this
|
||||
* discards the extras.
|
||||
*/
|
||||
public class MultiplePropertyRemover extends FsuScanner {
|
||||
|
||||
public MultiplePropertyRemover(FSUController controller) {
|
||||
super(controller);
|
||||
}
|
||||
|
||||
/**
|
||||
* By now, we have removed any non-literals or dead ends, so keep the first
|
||||
* one and discard any extras.
|
||||
*/
|
||||
public void remove() {
|
||||
updateLog.section("Checking for resources with more "
|
||||
+ "than one main image, or more than one thumbnail.");
|
||||
|
||||
removeExtraProperties(imageProperty, "main image");
|
||||
removeExtraProperties(thumbProperty, "thumbnail");
|
||||
}
|
||||
|
||||
/**
|
||||
* Check each resource that has this property.
|
||||
*/
|
||||
public void removeExtraProperties(Property prop, String label) {
|
||||
for (Resource resource : ModelWrapper.listResourcesWithProperty(model,
|
||||
prop)) {
|
||||
removeExtraProperties(resource, prop, label);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If this resource has more than one of this property, delete the extras.
|
||||
*/
|
||||
private void removeExtraProperties(Resource resource, Property prop,
|
||||
String label) {
|
||||
List<Statement> stmts = getStatements(resource, prop);
|
||||
for (int i = 1; i < stmts.size(); i++) {
|
||||
Statement stmt = stmts.get(i);
|
||||
RDFNode node = stmt.getObject();
|
||||
if (node.isLiteral()) {
|
||||
String value = ((Literal) node).getString();
|
||||
updateLog.warn(resource, "removing extra " + label
|
||||
+ " property: '" + value + "'");
|
||||
} else {
|
||||
updateLog.warn(resource, "removing extra " + label
|
||||
+ " property: '" + node + "'");
|
||||
}
|
||||
ModelWrapper.removeStatement(model, stmt);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,173 +0,0 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.filestorage.updater;
|
||||
|
||||
import static edu.cornell.mannlib.vitro.webapp.controller.freemarker.ImageUploadController.THUMBNAIL_HEIGHT;
|
||||
import static edu.cornell.mannlib.vitro.webapp.controller.freemarker.ImageUploadController.THUMBNAIL_WIDTH;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import javax.media.jai.JAI;
|
||||
import javax.media.jai.RenderedOp;
|
||||
|
||||
import com.hp.hpl.jena.rdf.model.Resource;
|
||||
import com.sun.media.jai.codec.MemoryCacheSeekableStream;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.ImageUploadController.CropRectangle;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.ImageUploadThumbnailer;
|
||||
|
||||
/**
|
||||
* Adjust any individual that has a main image but no thumbnail.
|
||||
*/
|
||||
public class NoThumbsAdjuster extends FsuScanner {
|
||||
private ImageDirectoryWithBackup imageDirectoryWithBackup;
|
||||
|
||||
public NoThumbsAdjuster(FSUController controller) {
|
||||
super(controller);
|
||||
this.imageDirectoryWithBackup = controller
|
||||
.getImageDirectoryWithBackup();
|
||||
}
|
||||
|
||||
/**
|
||||
* For every individual with main images but no thumbnails, create a
|
||||
* thumbnail from the first main image.
|
||||
*/
|
||||
public void adjust() {
|
||||
updateLog.section("Creating thumbnails to match main images.");
|
||||
|
||||
for (Resource resource : ModelWrapper.listResourcesWithProperty(model,
|
||||
imageProperty)) {
|
||||
if (resource.getProperty(thumbProperty) == null) {
|
||||
createThumbnailFromMainImage(resource);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This individual has a main image but no thumbnail. Create one.
|
||||
* <ul>
|
||||
* <li>Figure a name for the thumbnail image.</li>
|
||||
* <li>Make a scaled copy of the main image into the thumbnail.</li>
|
||||
* <li>Set that file as a thumbnail (old-style) on the individual.</li>
|
||||
* </ul>
|
||||
*/
|
||||
private void createThumbnailFromMainImage(Resource resource) {
|
||||
String mainFilename = getValues(resource, imageProperty).get(0);
|
||||
String thumbFilename = addFilenamePrefix("_thumbnail_", mainFilename);
|
||||
updateLog.log(resource, "creating a thumbnail at '" + thumbFilename
|
||||
+ "' from the main image at '" + mainFilename + "'");
|
||||
|
||||
File mainFile = imageDirectoryWithBackup.getExistingFile(mainFilename);
|
||||
File thumbFile = imageDirectoryWithBackup.getNewfile(thumbFilename);
|
||||
thumbFile = checkNameConflicts(thumbFile);
|
||||
|
||||
try {
|
||||
CropRectangle crop = getImageSize(mainFile);
|
||||
if (imageIsSmallEnoughAlready(crop)) {
|
||||
copyMainImageToThumbnail(mainFile, thumbFile);
|
||||
} else {
|
||||
cropScaleAndStore(crop, mainFile, thumbFile);
|
||||
}
|
||||
|
||||
ResourceWrapper.addProperty(resource, thumbProperty, thumbFilename);
|
||||
} catch (IOException e) {
|
||||
updateLog.error(resource, "failed to create thumbnail file '"
|
||||
+ thumbFilename + "'", e);
|
||||
}
|
||||
}
|
||||
|
||||
private CropRectangle getImageSize(File file) throws IOException {
|
||||
InputStream imageSource = null;
|
||||
try {
|
||||
imageSource = new FileInputStream(file);
|
||||
MemoryCacheSeekableStream stream = new MemoryCacheSeekableStream(
|
||||
imageSource);
|
||||
RenderedOp image = JAI.create("stream", stream);
|
||||
return new CropRectangle(0, 0, image.getHeight(), image.getWidth());
|
||||
} finally {
|
||||
if (imageSource != null) {
|
||||
try {
|
||||
imageSource.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean imageIsSmallEnoughAlready(CropRectangle crop) {
|
||||
return (crop.height <= THUMBNAIL_HEIGHT)
|
||||
&& (crop.width <= THUMBNAIL_WIDTH);
|
||||
}
|
||||
|
||||
private void copyMainImageToThumbnail(File mainFile, File thumbFile)
|
||||
throws IOException {
|
||||
InputStream imageSource = null;
|
||||
try {
|
||||
imageSource = new FileInputStream(mainFile);
|
||||
storeImage(imageSource, thumbFile);
|
||||
} finally {
|
||||
if (imageSource != null) {
|
||||
try {
|
||||
imageSource.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void cropScaleAndStore(CropRectangle crop, File mainFile,
|
||||
File thumbFile) throws IOException {
|
||||
InputStream mainImageStream = null;
|
||||
InputStream imageSource = null;
|
||||
try {
|
||||
mainImageStream = new FileInputStream(mainFile);
|
||||
ImageUploadThumbnailer iut = new ImageUploadThumbnailer(
|
||||
THUMBNAIL_HEIGHT, THUMBNAIL_WIDTH);
|
||||
imageSource = iut.cropAndScale(mainImageStream, crop);
|
||||
storeImage(imageSource, thumbFile);
|
||||
} finally {
|
||||
if (mainImageStream != null) {
|
||||
try {
|
||||
mainImageStream.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (imageSource != null) {
|
||||
try {
|
||||
imageSource.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void storeImage(InputStream source, File file) throws IOException {
|
||||
OutputStream sink = null;
|
||||
try {
|
||||
sink = new FileOutputStream(file);
|
||||
|
||||
byte[] buffer = new byte[8192];
|
||||
int howMany;
|
||||
while (-1 != (howMany = source.read(buffer))) {
|
||||
sink.write(buffer, 0, howMany);
|
||||
}
|
||||
} finally {
|
||||
if (sink != null) {
|
||||
try {
|
||||
sink.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,71 +0,0 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.filestorage.updater;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.hp.hpl.jena.rdf.model.Literal;
|
||||
import com.hp.hpl.jena.rdf.model.Property;
|
||||
import com.hp.hpl.jena.rdf.model.RDFNode;
|
||||
import com.hp.hpl.jena.rdf.model.Resource;
|
||||
import com.hp.hpl.jena.rdf.model.Statement;
|
||||
import com.hp.hpl.jena.shared.Lock;
|
||||
|
||||
/**
|
||||
* All image properties should have literal values. Burn any that don't.
|
||||
*/
|
||||
public class NonLiteralPropertyRemover extends FsuScanner {
|
||||
|
||||
public NonLiteralPropertyRemover(FSUController controller) {
|
||||
super(controller);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove any image properties whose objects are not {@link Literal}s.
|
||||
*/
|
||||
public void remove() {
|
||||
updateLog.section("Checking for image properties whose objects "
|
||||
+ "are not literals.");
|
||||
|
||||
removeNonLiterals(imageProperty, "image file");
|
||||
removeNonLiterals(thumbProperty, "thumbnail");
|
||||
}
|
||||
|
||||
/**
|
||||
* Check all resources for bogus values on this property.
|
||||
*/
|
||||
private void removeNonLiterals(Property prop, String label) {
|
||||
for (Resource resource : ModelWrapper.listResourcesWithProperty(model,
|
||||
prop)) {
|
||||
removeNonLiterals(resource, prop, label);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check this resource for bogus values onthis property.
|
||||
*/
|
||||
private void removeNonLiterals(Resource resource, Property prop,
|
||||
String label) {
|
||||
List<RDFNode> bogusValues = new ArrayList<RDFNode>();
|
||||
for (Statement stmt : ResourceWrapper.listProperties(resource, prop)) {
|
||||
RDFNode object = stmt.getObject();
|
||||
if (!object.isLiteral()) {
|
||||
bogusValues.add(object);
|
||||
}
|
||||
}
|
||||
|
||||
for (RDFNode bogusValue : bogusValues) {
|
||||
updateLog.warn(resource, "discarding " + label
|
||||
+ " property with non-literal as object: '" + bogusValue
|
||||
+ "'");
|
||||
model.enterCriticalSection(Lock.WRITE);
|
||||
try {
|
||||
model.createStatement(resource, prop, bogusValue).remove();
|
||||
} finally {
|
||||
model.leaveCriticalSection();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.filestorage.updater;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import com.hp.hpl.jena.rdf.model.Property;
|
||||
import com.hp.hpl.jena.rdf.model.Resource;
|
||||
import com.hp.hpl.jena.rdf.model.Statement;
|
||||
import com.hp.hpl.jena.rdf.model.StmtIterator;
|
||||
import com.hp.hpl.jena.shared.Lock;
|
||||
|
||||
/**
|
||||
* Utility methods that get the appropriate model locks before manipluating
|
||||
* resources.
|
||||
*/
|
||||
public class ResourceWrapper {
|
||||
|
||||
public static Statement getProperty(Resource resource, Property property) {
|
||||
resource.getModel().enterCriticalSection(Lock.READ);
|
||||
try {
|
||||
return resource.getProperty(property);
|
||||
} finally {
|
||||
resource.getModel().leaveCriticalSection();
|
||||
}
|
||||
}
|
||||
|
||||
public static void addProperty(Resource resource, Property property,
|
||||
String value) {
|
||||
resource.getModel().enterCriticalSection(Lock.WRITE);
|
||||
try {
|
||||
resource.addProperty(property, value);
|
||||
} finally {
|
||||
resource.getModel().leaveCriticalSection();
|
||||
}
|
||||
}
|
||||
|
||||
public static void removeAll(Resource resource, Property property) {
|
||||
resource.getModel().enterCriticalSection(Lock.WRITE);
|
||||
try {
|
||||
resource.removeAll(property);
|
||||
} finally {
|
||||
resource.getModel().leaveCriticalSection();
|
||||
}
|
||||
}
|
||||
|
||||
public static Collection<Statement> listProperties(Resource resource,
|
||||
Property prop) {
|
||||
List<Statement> list = new ArrayList<Statement>();
|
||||
StmtIterator stmts = resource.listProperties(prop);
|
||||
try {
|
||||
while (stmts.hasNext()) {
|
||||
list.add(stmts.next());
|
||||
}
|
||||
return list;
|
||||
} finally {
|
||||
stmts.close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -5,6 +5,10 @@ package edu.cornell.mannlib.vitro.webapp.filters;
|
|||
import java.io.IOException;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
|
@ -21,18 +25,27 @@ import org.apache.commons.dbcp.BasicDataSource;
|
|||
import org.apache.commons.logging.Log;
|
||||
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.DataSource;
|
||||
import com.hp.hpl.jena.query.Dataset;
|
||||
import com.hp.hpl.jena.query.DatasetFactory;
|
||||
import com.hp.hpl.jena.rdf.model.Model;
|
||||
import com.hp.hpl.jena.rdf.model.ModelFactory;
|
||||
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 edu.cornell.mannlib.vitro.webapp.config.ConfigurationProperties;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactoryConfig;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.jena.OntModelSelector;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.jena.SingleContentOntModelSelector;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.jena.SparqlGraphMultilingual;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.jena.WebappDaoFactoryJena;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.jena.WebappDaoFactorySDB;
|
||||
import edu.cornell.mannlib.vitro.webapp.servlet.setup.JenaDataSourceSetupBase;
|
||||
|
||||
|
@ -89,6 +102,15 @@ public class WebappDaoFactorySDBPrep implements Filter {
|
|||
Dataset dataset = null;
|
||||
WebappDaoFactory wadf = null;
|
||||
|
||||
// temporary scaffolding in the rdfapi dev branch
|
||||
// TODO remove me
|
||||
if (ConfigurationProperties.getBean(request).getProperty(
|
||||
"VitroConnection.DataSource.endpointURI") != null) {
|
||||
filterSparql(request, oms, defaultNamespace);
|
||||
filterChain.doFilter(request, response);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (bds == null || storeDesc == null || oms == null) {
|
||||
throw new RuntimeException("SDB store not property set up");
|
||||
|
@ -140,6 +162,56 @@ public class WebappDaoFactorySDBPrep implements Filter {
|
|||
|
||||
}
|
||||
|
||||
private void filterSparql(ServletRequest request, OntModelSelector oms, String defaultNamespace) {
|
||||
log.info("---------");
|
||||
|
||||
VitroRequest vreq = new VitroRequest((HttpServletRequest) request);
|
||||
|
||||
Enumeration<String> headStrs = vreq.getHeaderNames();
|
||||
while (headStrs.hasMoreElements()) {
|
||||
String head = headStrs.nextElement();
|
||||
log.info(head + " : " + vreq.getHeader(head));
|
||||
}
|
||||
|
||||
List<String> langs = new ArrayList<String>();
|
||||
|
||||
log.info("Accept-Language: " + vreq.getHeader("Accept-Language"));
|
||||
Enumeration<Locale> locs = vreq.getLocales();
|
||||
while (locs.hasMoreElements()) {
|
||||
Locale locale = locs.nextElement();
|
||||
langs.add(locale.toString().replace("_", "-"));
|
||||
log.info(locale.toString() + " / " + locale.getLanguage() + " + " + locale.getCountry() + " : " + locale.getDisplayCountry() + " | " + locale.getLanguage() + " : " + locale.getDisplayLanguage());
|
||||
}
|
||||
WebappDaoFactoryConfig config = new WebappDaoFactoryConfig();
|
||||
config.setDefaultNamespace(defaultNamespace);
|
||||
config.setPreferredLanguages(langs);
|
||||
|
||||
//okay let's make a graph-backed model
|
||||
String endpointURI = ConfigurationProperties.getBean(
|
||||
request).getProperty("VitroConnection.DataSource.endpointURI");
|
||||
|
||||
Graph g = new SparqlGraphMultilingual(endpointURI, langs);
|
||||
//Graph g = new SparqlGraph(endpointURI);
|
||||
|
||||
Model m = ModelFactory.createModelForGraph(g);
|
||||
OntModel om = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM, m);
|
||||
oms = new SingleContentOntModelSelector(om, oms.getDisplayModel(), oms.getUserAccountsModel());
|
||||
|
||||
DataSource dataset = DatasetFactory.create();
|
||||
dataset.addNamedModel("fake:fake", m);
|
||||
|
||||
WebappDaoFactory wadf = new WebappDaoFactoryJena(oms, config);
|
||||
//wadf = new WebappDaoFactorySDB(oms, dataset, config);
|
||||
vreq.setWebappDaoFactory(wadf);
|
||||
vreq.setFullWebappDaoFactory(wadf);
|
||||
vreq.setUnfilteredWebappDaoFactory(wadf);
|
||||
vreq.setWebappDaoFactory(wadf);
|
||||
vreq.setAssertionsWebappDaoFactory(wadf);
|
||||
vreq.setDataset(dataset);
|
||||
vreq.setJenaOntModel(om);
|
||||
vreq.setOntModelSelector(oms);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(FilterConfig filterConfig) throws ServletException {
|
||||
try {
|
||||
|
|
|
@ -43,12 +43,12 @@ import edu.cornell.mannlib.vitro.webapp.dao.jena.event.BulkUpdateEvent;
|
|||
* Allows for real-time incremental materialization or retraction of RDFS-
|
||||
* style class and property subsumption based ABox inferences as statements
|
||||
* are added to or removed from the (ABox or TBox) knowledge base.
|
||||
* @author sjm222
|
||||
*/
|
||||
|
||||
public class SimpleReasoner extends StatementListener {
|
||||
|
||||
private static final Log log = LogFactory.getLog(SimpleReasoner.class);
|
||||
//private static final MyTempLogger log = new MyTempLogger();
|
||||
|
||||
private OntModel tboxModel; // asserted and inferred TBox axioms
|
||||
private OntModel aboxModel; // ABox assertions
|
||||
|
@ -120,9 +120,9 @@ public class SimpleReasoner extends StatementListener {
|
|||
}
|
||||
|
||||
/*
|
||||
* Performs selected incremental ABox reasoning based
|
||||
* on the addition of a new statement (aka assertion)
|
||||
* to the ABox.
|
||||
* Performs incremental ABox reasoning based
|
||||
* on the addition of a new statement
|
||||
* (aka assertion) to the ABox.
|
||||
*/
|
||||
@Override
|
||||
public void addedStatement(Statement stmt) {
|
||||
|
@ -142,7 +142,7 @@ public class SimpleReasoner extends StatementListener {
|
|||
}
|
||||
|
||||
/*
|
||||
* Performs selected incremental ABox reasoning based
|
||||
* Performs incremental ABox reasoning based
|
||||
* on the retraction of a statement (aka assertion)
|
||||
* from the ABox.
|
||||
*/
|
||||
|
@ -160,7 +160,12 @@ public class SimpleReasoner extends StatementListener {
|
|||
}
|
||||
}
|
||||
|
||||
public synchronized void handleRemovedStatement(Statement stmt) {
|
||||
|
||||
/*
|
||||
* Synchronized part of removedStatement. Interacts
|
||||
* with DeltaComputer.
|
||||
*/
|
||||
protected synchronized void handleRemovedStatement(Statement stmt) {
|
||||
|
||||
if (batchMode1) {
|
||||
aBoxDeltaModeler1.removedStatement(stmt);
|
||||
|
@ -176,7 +181,7 @@ public class SimpleReasoner extends StatementListener {
|
|||
}
|
||||
|
||||
/*
|
||||
* Performs incremental selected ABox reasoning based
|
||||
* Performs incremental ABox reasoning based
|
||||
* on changes to the class hierarchy.
|
||||
*
|
||||
* Handles rdfs:subclassOf, owl:equivalentClass,
|
||||
|
@ -229,7 +234,7 @@ public class SimpleReasoner extends StatementListener {
|
|||
}
|
||||
|
||||
/*
|
||||
* Performs incremental selected ABox reasoning based
|
||||
* Performs incremental ABox reasoning based
|
||||
* on changes to the class hierarchy.
|
||||
*
|
||||
* Handles rdfs:subclassOf, owl:equivalentClass,
|
||||
|
@ -282,9 +287,9 @@ public class SimpleReasoner extends StatementListener {
|
|||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* This signature used when recomputing the whole ABox
|
||||
*/
|
||||
public void addedABoxTypeAssertion(Resource individual, Model inferenceModel, HashSet<String> unknownTypes) {
|
||||
protected void addedABoxTypeAssertion(Resource individual, Model inferenceModel, HashSet<String> unknownTypes) {
|
||||
|
||||
StmtIterator iter = null;
|
||||
|
||||
|
@ -302,6 +307,7 @@ public class SimpleReasoner extends StatementListener {
|
|||
aboxModel.leaveCriticalSection();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Performs incremental reasoning based on a new type assertion
|
||||
* added to the ABox (assertion that an individual is of a certain
|
||||
|
@ -309,9 +315,8 @@ public class SimpleReasoner extends StatementListener {
|
|||
*
|
||||
* If it is added that B is of type A, then for each superclass of
|
||||
* A assert that B is of that type.
|
||||
*
|
||||
*/
|
||||
public void addedABoxTypeAssertion(Statement stmt, Model inferenceModel, HashSet<String> unknownTypes) {
|
||||
protected void addedABoxTypeAssertion(Statement stmt, Model inferenceModel, HashSet<String> unknownTypes) {
|
||||
|
||||
tboxModel.enterCriticalSection(Lock.READ);
|
||||
|
||||
|
@ -377,13 +382,10 @@ public class SimpleReasoner extends StatementListener {
|
|||
* that B is of that type.
|
||||
*
|
||||
*/
|
||||
public void removedABoxTypeAssertion(Statement stmt, Model inferenceModel) {
|
||||
protected void removedABoxTypeAssertion(Statement stmt, Model inferenceModel) {
|
||||
|
||||
tboxModel.enterCriticalSection(Lock.READ);
|
||||
|
||||
// convert this method to use generic resources - not get ontclass, not cls.listSuperClasses...
|
||||
// use model contains if want to log warning about type owl class
|
||||
|
||||
try {
|
||||
|
||||
OntClass cls = null;
|
||||
|
@ -431,7 +433,6 @@ public class SimpleReasoner extends StatementListener {
|
|||
inferenceModel.enterCriticalSection(Lock.WRITE);
|
||||
try {
|
||||
if (inferenceModel.contains(infStmt)) {
|
||||
//log.debug("Removing this inferred statement: " + infStmt.toString() + " - " + infStmt.getSubject().toString() + " - " + infStmt.getPredicate().toString() + " - " + infStmt.getObject().toString());
|
||||
inferenceModel.remove(infStmt);
|
||||
}
|
||||
} finally {
|
||||
|
@ -454,7 +455,7 @@ public class SimpleReasoner extends StatementListener {
|
|||
|
||||
// Returns true if it is entailed by class subsumption that
|
||||
// subject is of type cls; otherwise returns false.
|
||||
public boolean entailedType(Resource subject, OntClass cls) {
|
||||
protected boolean entailedType(Resource subject, OntClass cls) {
|
||||
aboxModel.enterCriticalSection(Lock.READ);
|
||||
tboxModel.enterCriticalSection(Lock.READ);
|
||||
|
||||
|
@ -485,9 +486,9 @@ public class SimpleReasoner extends StatementListener {
|
|||
/*
|
||||
* If it is added that B is a subClass of A, then for each
|
||||
* individual that is typed as B, either in the ABox or in the
|
||||
* inferred model, assert that it is of type A.
|
||||
* inferred model, infer that it is of type A.
|
||||
*/
|
||||
public void addedSubClass(OntClass subClass, OntClass superClass, Model inferenceModel) {
|
||||
protected void addedSubClass(OntClass subClass, OntClass superClass, Model inferenceModel) {
|
||||
log.debug("subClass = " + subClass.getURI() + " superClass = " + superClass.getURI());
|
||||
OntModel unionModel = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM);
|
||||
unionModel.addSubModel(aboxModel);
|
||||
|
@ -530,7 +531,7 @@ public class SimpleReasoner extends StatementListener {
|
|||
* UNLESS the individual is of some type C that is a subClass
|
||||
* of A (including A itself)
|
||||
*/
|
||||
public void removedSubClass(OntClass subClass, OntClass superClass, Model inferenceModel) {
|
||||
protected void removedSubClass(OntClass subClass, OntClass superClass, Model inferenceModel) {
|
||||
OntModel unionModel = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM);
|
||||
unionModel.addSubModel(aboxModel);
|
||||
unionModel.addSubModel(inferenceModel);
|
||||
|
@ -567,10 +568,10 @@ public class SimpleReasoner extends StatementListener {
|
|||
|
||||
/*
|
||||
* Find the most specific types (classes) of an individual and
|
||||
* indicate them for the individual with the core:mostSpecificType
|
||||
* indicate them for the individual with the mostSpecificType
|
||||
* annotation.
|
||||
*/
|
||||
public void setMostSpecificTypes(Resource individual, Model inferenceModel, HashSet<String> unknownTypes) {
|
||||
protected void setMostSpecificTypes(Resource individual, Model inferenceModel, HashSet<String> unknownTypes) {
|
||||
|
||||
tboxModel.enterCriticalSection(Lock.READ);
|
||||
aboxModel.enterCriticalSection(Lock.READ);
|
||||
|
@ -665,13 +666,13 @@ public class SimpleReasoner extends StatementListener {
|
|||
return;
|
||||
}
|
||||
|
||||
public void setMostSpecificTypes(Resource individual, HashSet<String> typeURIs, Model inferenceModel) {
|
||||
protected void setMostSpecificTypes(Resource individual, HashSet<String> typeURIs, Model inferenceModel) {
|
||||
|
||||
inferenceModel.enterCriticalSection(Lock.WRITE);
|
||||
|
||||
try {
|
||||
Model retractions = ModelFactory.createDefaultModel();
|
||||
// remove obsolete most-specific-type assertions
|
||||
// remove obsolete mostSpecificType assertions
|
||||
StmtIterator iter = inferenceModel.listStatements(individual, mostSpecificType, (RDFNode) null);
|
||||
|
||||
while (iter.hasNext()) {
|
||||
|
@ -689,7 +690,7 @@ public class SimpleReasoner extends StatementListener {
|
|||
|
||||
inferenceModel.remove(retractions);
|
||||
|
||||
// add new most-specific-type assertions
|
||||
// add new mostSpecificType assertions
|
||||
Iterator<String> typeIter = typeURIs.iterator();
|
||||
|
||||
while (typeIter.hasNext()) {
|
||||
|
@ -707,12 +708,12 @@ public class SimpleReasoner extends StatementListener {
|
|||
return;
|
||||
}
|
||||
|
||||
private boolean recomputing = false;
|
||||
|
||||
/**
|
||||
* Returns true if the reasoner is in the process of recomputing all
|
||||
* inferences.
|
||||
*/
|
||||
private boolean recomputing = false;
|
||||
|
||||
public boolean isRecomputing() {
|
||||
return recomputing;
|
||||
}
|
||||
|
@ -731,14 +732,14 @@ public class SimpleReasoner extends StatementListener {
|
|||
|
||||
/*
|
||||
* Recompute the entire ABox inference graph. The new
|
||||
* inference graph is built up in a separate model and
|
||||
* then reconciled with the inference graph used by the
|
||||
* application. The model reconciliation must be done
|
||||
* inference graph is built in a separate model and
|
||||
* then reconciled with the inference graph in active
|
||||
* use. The model reconciliation must be done
|
||||
* without reading the whole inference models into
|
||||
* memory in order to support very large ABox
|
||||
* inference models.
|
||||
*/
|
||||
public synchronized void recomputeABox() {
|
||||
protected synchronized void recomputeABox() {
|
||||
|
||||
HashSet<String> unknownTypes = new HashSet<String>();
|
||||
|
||||
|
@ -799,8 +800,8 @@ public class SimpleReasoner extends StatementListener {
|
|||
|
||||
log.info("Finished computing class-based ABox inferences");
|
||||
|
||||
// reflect the recomputed inferences into the application inference
|
||||
// model.
|
||||
// reflect the recomputed inferences into the application
|
||||
// inference model.
|
||||
log.info("Updating ABox inference model");
|
||||
StmtIterator iter = null;
|
||||
|
||||
|
@ -913,23 +914,16 @@ public class SimpleReasoner extends StatementListener {
|
|||
log.info("ABox inference model updated");
|
||||
}
|
||||
|
||||
public synchronized boolean isABoxReasoningAsynchronous() {
|
||||
if (batchMode1 || batchMode2) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public ArrayList<String> getAllIndividualURIs() {
|
||||
/*
|
||||
* Get the URIs for all individuals in the system
|
||||
*/
|
||||
protected ArrayList<String> getAllIndividualURIs() {
|
||||
|
||||
String queryString = "select distinct ?subject where {?subject <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> ?type}";
|
||||
return getIndividualURIs(queryString);
|
||||
}
|
||||
|
||||
public ArrayList<String> getIndividualURIs(String queryString) {
|
||||
protected ArrayList<String> getIndividualURIs(String queryString) {
|
||||
|
||||
ArrayList<String> individuals = new ArrayList<String>();
|
||||
aboxModel.enterCriticalSection(Lock.READ);
|
||||
|
@ -960,6 +954,19 @@ public class SimpleReasoner extends StatementListener {
|
|||
return individuals;
|
||||
}
|
||||
|
||||
|
||||
// system-configured reasoning modules (plugins)
|
||||
public boolean isInterestedInRemovedStatement(Statement stmt) {
|
||||
|
||||
if (stmt.getPredicate().equals(RDF.type)) return true;
|
||||
|
||||
for (ReasonerPlugin plugin : getPluginList()) {
|
||||
if (plugin.isInterestedInRemovedStatement(stmt)) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void doPlugins(ModelUpdate.Operation op, Statement stmt) {
|
||||
|
||||
for (ReasonerPlugin plugin : getPluginList()) {
|
||||
|
@ -983,29 +990,16 @@ public class SimpleReasoner extends StatementListener {
|
|||
}
|
||||
}
|
||||
|
||||
public boolean isInterestedInRemovedStatement(Statement stmt) {
|
||||
|
||||
if (stmt.getPredicate().equals(RDF.type)) return true;
|
||||
|
||||
for (ReasonerPlugin plugin : getPluginList()) {
|
||||
if (plugin.isInterestedInRemovedStatement(stmt)) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//TODO remove this for 1.5
|
||||
public synchronized void computeMostSpecificType() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called when the system shuts down.
|
||||
* This is called when the application shuts down.
|
||||
*/
|
||||
public void setStopRequested() {
|
||||
this.stopRequested = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Utility method for logging
|
||||
*/
|
||||
public static String stmtString(Statement statement) {
|
||||
return " [subject = " + statement.getSubject().getURI() +
|
||||
"] [property = " + statement.getPredicate().getURI() +
|
||||
|
@ -1013,6 +1007,20 @@ public class SimpleReasoner extends StatementListener {
|
|||
: ((Resource)statement.getObject()).getURI() + " (Resource)") + "]";
|
||||
}
|
||||
|
||||
|
||||
// DeltaComputer
|
||||
|
||||
/*
|
||||
* Asynchronous reasoning mode (DeltaComputer) is used in the case of batch removals.
|
||||
*/
|
||||
public synchronized boolean isABoxReasoningAsynchronous() {
|
||||
if (batchMode1 || batchMode2) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private volatile boolean deltaComputerProcessing = false;
|
||||
private int eventCount = 0;
|
||||
|
||||
|
@ -1083,7 +1091,7 @@ public class SimpleReasoner extends StatementListener {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
log.warn("unexpected condition, invoked when batchMode1 and batchMode2 were both false");
|
||||
log.warn("unexpected condition, invoked when batchMode1 and batchMode2 are both false");
|
||||
deltaComputerProcessing = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -13,12 +13,11 @@ import com.hp.hpl.jena.rdf.model.Statement;
|
|||
import edu.cornell.mannlib.vitro.webapp.servlet.setup.JenaDataSourceSetupBase;
|
||||
import edu.cornell.mannlib.vitro.webapp.utils.threads.VitroBackgroundThread;
|
||||
|
||||
|
||||
/**
|
||||
* Route notification of changes to TBox to the incremental ABox reasoner.
|
||||
* The incremental ABox reasoner handles only subclass, superclass
|
||||
* and equivalent class axioms.
|
||||
*
|
||||
* The incremental ABox reasoner handles only subClass and
|
||||
* equivalentClass class axioms. Reasoning dones as a result of TBox
|
||||
* changes is always done in a separate thread.
|
||||
*/
|
||||
|
||||
public class SimpleReasonerTBoxListener extends StatementListener {
|
||||
|
|
|
@ -20,7 +20,9 @@ import org.apache.commons.logging.Log;
|
|||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import com.hp.hpl.jena.graph.Node;
|
||||
import com.hp.hpl.jena.ontology.OntDocumentManager;
|
||||
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.sdb.SDBFactory;
|
||||
|
@ -48,6 +50,8 @@ public class FileGraphSetup implements ServletContextListener {
|
|||
OntModelSelector baseOms = null;
|
||||
|
||||
try {
|
||||
|
||||
OntDocumentManager.getInstance().setProcessImports(true);
|
||||
baseOms = ModelContext.getBaseOntModelSelector(sce.getServletContext());
|
||||
Store kbStore = (Store) sce.getServletContext().getAttribute("kbStore");
|
||||
|
||||
|
@ -78,6 +82,8 @@ public class FileGraphSetup implements ServletContextListener {
|
|||
System.out.println("Throwable in listener " + this.getClass().getName());
|
||||
log.error(t);
|
||||
t.printStackTrace();
|
||||
} finally {
|
||||
OntDocumentManager.getInstance().setProcessImports(false);
|
||||
}
|
||||
|
||||
if (isUpdateRequired(sce.getServletContext())) {
|
||||
|
@ -114,7 +120,7 @@ public class FileGraphSetup implements ServletContextListener {
|
|||
try {
|
||||
FileInputStream fis = new FileInputStream( file );
|
||||
try {
|
||||
Model model = ModelFactory.createDefaultModel();
|
||||
OntModel model = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM);
|
||||
if ( p.endsWith(".n3") || p.endsWith(".N3") || p.endsWith(".ttl") || p.endsWith(".TTL") ) {
|
||||
model.read( fis, null, "N3" );
|
||||
} else if ( p.endsWith(".owl") || p.endsWith(".OWL") || p.endsWith(".rdf") || p.endsWith(".RDF") || p.endsWith(".xml") || p.endsWith(".XML") ) {
|
||||
|
|
|
@ -68,6 +68,14 @@ public class JenaDataSourceSetup extends JenaDataSourceSetupBase
|
|||
ServletContext ctx = sce.getServletContext();
|
||||
StartupStatus ss = StartupStatus.getBean(ctx);
|
||||
|
||||
// temporary scaffolding in the rdfapi dev branch
|
||||
// TODO remove me
|
||||
if (ConfigurationProperties.getBean(ctx).getProperty(
|
||||
"VitroConnection.DataSource.endpointURI") != null) {
|
||||
(new JenaDataSourceSetupSparql()).contextInitialized(sce);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
long startTime = System.currentTimeMillis();
|
||||
setUpJenaDataSource(ctx);
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
package edu.cornell.mannlib.vitro.webapp.servlet.setup;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.File;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Set;
|
||||
|
||||
|
|
|
@ -2,10 +2,7 @@
|
|||
|
||||
package edu.cornell.mannlib.vitro.webapp.servlet.setup;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletContextEvent;
|
||||
|
|
|
@ -16,7 +16,6 @@ import javax.servlet.ServletContextListener;
|
|||
import org.apache.commons.dbcp.BasicDataSource;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.mindswap.pellet.PelletOptions;
|
||||
|
||||
import com.hp.hpl.jena.rdf.model.Model;
|
||||
import com.hp.hpl.jena.vocabulary.OWL;
|
||||
|
@ -45,6 +44,14 @@ public class SimpleReasonerSetup implements ServletContextListener {
|
|||
|
||||
@Override
|
||||
public void contextInitialized(ServletContextEvent sce) {
|
||||
|
||||
// temporary scaffolding in the rdfapi dev branch
|
||||
// TODO remove me
|
||||
if (ConfigurationProperties.getBean(sce).getProperty(
|
||||
"VitroConnection.DataSource.endpointURI") != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// set up Pellet reasoning for the TBox
|
||||
|
||||
|
@ -60,12 +67,12 @@ public class SimpleReasonerSetup implements ServletContextListener {
|
|||
}
|
||||
|
||||
// Set various Pellet options for incremental consistency checking, etc.
|
||||
PelletOptions.DL_SAFE_RULES = true;
|
||||
PelletOptions.USE_COMPLETION_QUEUE = true;
|
||||
PelletOptions.USE_TRACING = true;
|
||||
PelletOptions.TRACK_BRANCH_EFFECTS = true;
|
||||
PelletOptions.USE_INCREMENTAL_CONSISTENCY = true;
|
||||
PelletOptions.USE_INCREMENTAL_DELETION = true;
|
||||
//PelletOptions.DL_SAFE_RULES = true;
|
||||
//PelletOptions.USE_COMPLETION_QUEUE = true;
|
||||
//PelletOptions.USE_TRACING = true;
|
||||
//PelletOptions.TRACK_BRANCH_EFFECTS = true;
|
||||
//PelletOptions.USE_INCREMENTAL_CONSISTENCY = true;
|
||||
//PelletOptions.USE_INCREMENTAL_DELETION = true;
|
||||
|
||||
PelletListener pelletListener = new PelletListener(unionOms.getTBoxModel(),assertionsOms.getTBoxModel(),inferencesOms.getTBoxModel(),ReasonerConfiguration.DEFAULT);
|
||||
sce.getServletContext().setAttribute("pelletListener",pelletListener);
|
||||
|
|
|
@ -20,16 +20,8 @@ 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.Property;
|
||||
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.vocabulary.RDF;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.DisplayVocabulary;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.jena.ModelContext;
|
||||
import edu.cornell.mannlib.vitro.webapp.ontology.update.KnowledgeBaseUpdater;
|
||||
|
|
|
@ -1,144 +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 java.io.File;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletContextEvent;
|
||||
import javax.servlet.ServletContextListener;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import com.hp.hpl.jena.ontology.OntModel;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.config.ConfigurationProperties;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.jena.JenaBaseDao;
|
||||
import edu.cornell.mannlib.vitro.webapp.filestorage.backend.FileStorage;
|
||||
import edu.cornell.mannlib.vitro.webapp.filestorage.backend.FileStorageSetup;
|
||||
import edu.cornell.mannlib.vitro.webapp.filestorage.updater.FileStorageAliasAdder;
|
||||
import edu.cornell.mannlib.vitro.webapp.filestorage.updater.FileStorageUpdater;
|
||||
import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus;
|
||||
|
||||
/**
|
||||
* Check that the conditions are met for updating uploaded files. If everything
|
||||
* is in place, call the two updaters.
|
||||
*
|
||||
* The first updater converts from old-style (pre 1.0) to new-style (post 1.0)
|
||||
* file storage.
|
||||
*
|
||||
* The second updater insures that all bytestreams store their own alias URLs
|
||||
* (post 1.1.1).
|
||||
*/
|
||||
public class UpdateUploadedFiles implements ServletContextListener {
|
||||
private static final Log log = LogFactory.getLog(UpdateUploadedFiles.class);
|
||||
|
||||
/**
|
||||
* Nothing to do on teardown.
|
||||
*/
|
||||
@Override
|
||||
public void contextDestroyed(ServletContextEvent sce) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the ontology model, the old upload directory, and the file
|
||||
* storage system are all valid. Then do the update.
|
||||
*/
|
||||
@Override
|
||||
public void contextInitialized(ServletContextEvent sce) {
|
||||
ServletContext ctx = sce.getServletContext();
|
||||
|
||||
try {
|
||||
WebappDaoFactory wadf = (WebappDaoFactory) ctx
|
||||
.getAttribute("assertionsWebappDaoFactory");
|
||||
if (wadf == null) {
|
||||
throw new IllegalStateException("Webapp DAO Factory is null. "
|
||||
+ "The ServletContext does not contain an attribute "
|
||||
+ "for '" + "assertionsWebappDaoFactory" + "'. "
|
||||
+ "Does the log contain a previous exception from "
|
||||
+ "JenaDataSourceSetup? Is it possible that web.xml "
|
||||
+ "is not set up to run JenaDataSourceSetup before "
|
||||
+ "UpdateUploadedFiles?");
|
||||
}
|
||||
|
||||
OntModel jenaOntModel = (OntModel) ctx
|
||||
.getAttribute(JenaBaseDao.ASSERTIONS_ONT_MODEL_ATTRIBUTE_NAME);
|
||||
if (jenaOntModel == null) {
|
||||
throw new IllegalStateException("Ontology model is null. "
|
||||
+ "The ServletContext does not contain an attribute "
|
||||
+ "for '"
|
||||
+ JenaBaseDao.ASSERTIONS_ONT_MODEL_ATTRIBUTE_NAME
|
||||
+ "'. "
|
||||
+ "Does the log contain a previous exception from "
|
||||
+ "JenaDataSourceSetup? Is it possible that web.xml "
|
||||
+ "is not set up to run JenaDataSourceSetup before "
|
||||
+ "UpdateUploadedFiles?");
|
||||
}
|
||||
|
||||
FileStorage fileStorage = (FileStorage) ctx
|
||||
.getAttribute(FileStorageSetup.ATTRIBUTE_NAME);
|
||||
if (fileStorage == null) {
|
||||
throw new IllegalStateException("File storage system is null. "
|
||||
+ "The ServletContext does not contain an attribute "
|
||||
+ "for '" + FileStorageSetup.ATTRIBUTE_NAME + "'. "
|
||||
+ "Does the log contain a previous exception from "
|
||||
+ "FileStorageSetup? Is it possible that web.xml is "
|
||||
+ "not set up to run FileStorageSetup before "
|
||||
+ "UpdateUploadedFiles?");
|
||||
}
|
||||
|
||||
String vitroHomeDirectoryName = ConfigurationProperties
|
||||
.getBean(ctx).getProperty(
|
||||
FileStorageSetup.PROPERTY_VITRO_HOME_DIR);
|
||||
if (vitroHomeDirectoryName == null) {
|
||||
throw new IllegalStateException("Upload directory name is null");
|
||||
}
|
||||
File vitroHomeDirectory = new File(vitroHomeDirectoryName);
|
||||
if (!vitroHomeDirectory.exists()) {
|
||||
throw new IllegalStateException("Vitro home directory '"
|
||||
+ vitroHomeDirectory.getAbsolutePath()
|
||||
+ "' does not exist.");
|
||||
}
|
||||
File uploadDirectory = new File(vitroHomeDirectory,
|
||||
FileStorageSetup.FILE_STORAGE_SUBDIRECTORY);
|
||||
if (!uploadDirectory.exists()) {
|
||||
uploadDirectory.mkdir();
|
||||
if (!uploadDirectory.exists()) {
|
||||
throw new IllegalStateException(
|
||||
"Failed to create the file uploads directory: "
|
||||
+ uploadDirectory.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
String vivoDefaultNamespace = ConfigurationProperties.getBean(ctx)
|
||||
.getProperty(FileStorageSetup.PROPERTY_DEFAULT_NAMESPACE);
|
||||
if (vivoDefaultNamespace == null) {
|
||||
throw new IllegalStateException("Default namespace is null.");
|
||||
}
|
||||
|
||||
String webappImagePath = ctx.getRealPath("images");
|
||||
File webappImageDirectory = (webappImagePath == null) ? null
|
||||
: new File(webappImagePath);
|
||||
|
||||
/*
|
||||
* Update from old-style storage to new-style storage.
|
||||
*/
|
||||
FileStorageUpdater fsu = new FileStorageUpdater(wadf, jenaOntModel,
|
||||
fileStorage, uploadDirectory, webappImageDirectory, ctx);
|
||||
fsu.update();
|
||||
|
||||
/*
|
||||
* Insure that every FileByteStream object has an alias URL.
|
||||
*/
|
||||
FileStorageAliasAdder fsaa = new FileStorageAliasAdder(
|
||||
jenaOntModel, uploadDirectory, vivoDefaultNamespace);
|
||||
fsaa.update();
|
||||
} catch (Exception e) {
|
||||
log.fatal("Unknown problem", e);
|
||||
StartupStatus.getBean(ctx).fatal(this, "Unknown problem", e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,485 +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 java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletContextEvent;
|
||||
import javax.servlet.ServletContextListener;
|
||||
|
||||
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.OntResource;
|
||||
import com.hp.hpl.jena.rdf.model.Literal;
|
||||
import com.hp.hpl.jena.rdf.model.Property;
|
||||
import com.hp.hpl.jena.rdf.model.Resource;
|
||||
import com.hp.hpl.jena.rdf.model.Statement;
|
||||
import com.hp.hpl.jena.shared.Lock;
|
||||
import com.hp.hpl.jena.util.iterator.ClosableIterator;
|
||||
import com.hp.hpl.jena.vocabulary.RDF;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.auth.permissions.PermissionSetsLoader;
|
||||
import edu.cornell.mannlib.vitro.webapp.beans.UserAccount;
|
||||
import edu.cornell.mannlib.vitro.webapp.beans.UserAccount.Status;
|
||||
import edu.cornell.mannlib.vitro.webapp.config.ConfigurationProperties;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.UserAccountsDao;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.jena.ModelContext;
|
||||
import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus;
|
||||
|
||||
/**
|
||||
* Convert any existing User resources (up to rel 1.2) in the UserAccounts Model
|
||||
* to UserAccount resources (rel 1.3 and on).
|
||||
*/
|
||||
public class UpdateUserAccounts implements ServletContextListener {
|
||||
private static final Log log = LogFactory.getLog(UpdateUserAccounts.class);
|
||||
|
||||
public static final String NS = "http://vitro.mannlib.cornell.edu/ns/vitro/0.7#";
|
||||
public static final String USER = NS + "User";
|
||||
public static final String USER_USERNAME = NS + "username";
|
||||
public static final String USER_MD5PASSWORD = NS + "md5password";
|
||||
public static final String USER_OLDPASSWORD = NS + "oldpassword";
|
||||
public static final String USER_FIRSTTIME = NS + "firstTime";
|
||||
public static final String USER_LOGINCOUNT = NS + "loginCount";
|
||||
public static final String USER_ROLE = NS + "roleURI";
|
||||
public static final String USER_LASTNAME = NS + "lastName";
|
||||
public static final String USER_FIRSTNAME = NS + "firstName";
|
||||
public static final String MAY_EDIT_AS = NS + "mayEditAs";
|
||||
|
||||
@Override
|
||||
public void contextInitialized(ServletContextEvent sce) {
|
||||
ServletContext ctx = sce.getServletContext();
|
||||
StartupStatus ss = StartupStatus.getBean(ctx);
|
||||
|
||||
try {
|
||||
Updater updater = new Updater(ctx);
|
||||
if (updater.isThereAnythingToDo()) {
|
||||
updater.update();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.fatal("Failed to update user accounts information", e);
|
||||
ss.fatal(this, "Failed to update user accounts information", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void contextDestroyed(ServletContextEvent sce) {
|
||||
// Nothing to destroy.
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// The Updater class
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
private static class Updater {
|
||||
private final ServletContext ctx;
|
||||
private final MockUserDao userDao;
|
||||
private final UserAccountsDao userAccountsDao;
|
||||
|
||||
public Updater(ServletContext ctx) {
|
||||
this.ctx = ctx;
|
||||
|
||||
WebappDaoFactory wadf = (WebappDaoFactory) ctx
|
||||
.getAttribute("webappDaoFactory");
|
||||
userAccountsDao = wadf.getUserAccountsDao();
|
||||
|
||||
userDao = new MockUserDao(ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* If there is nothing to do, we shouldn't even create a Journal.
|
||||
*/
|
||||
public boolean isThereAnythingToDo() {
|
||||
return !userDao.getAllUsers().isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* We found some old User resources, so convert them.
|
||||
*/
|
||||
public void update() throws IOException {
|
||||
Journal journal = new Journal(ctx);
|
||||
log.info("Updating user accounts info. Journal is in '"
|
||||
+ journal.getPath() + "'");
|
||||
|
||||
try {
|
||||
for (MockUser user : userDao.getAllUsers()) {
|
||||
try {
|
||||
UserAccount ua = getConvertedUser(user);
|
||||
if (ua != null) {
|
||||
journal.noteAlreadyConverted(user, ua);
|
||||
} else {
|
||||
journal.writeUser(user);
|
||||
|
||||
ua = convertToUserAccount(user);
|
||||
userAccountsDao.insertUserAccount(ua);
|
||||
journal.noteUserAccount(ua);
|
||||
}
|
||||
|
||||
userDao.deleteUser(user);
|
||||
journal.noteDeletedUser(user);
|
||||
} catch (Exception e) {
|
||||
log.error(e, e);
|
||||
journal.noteException(e);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
journal.close();
|
||||
}
|
||||
}
|
||||
|
||||
private UserAccount getConvertedUser(MockUser user) {
|
||||
return userAccountsDao.getUserAccountByEmail(user.getUsername());
|
||||
}
|
||||
|
||||
private UserAccount convertToUserAccount(MockUser u) {
|
||||
UserAccount ua = new UserAccount();
|
||||
ua.setEmailAddress(nonNull(u.getUsername()));
|
||||
ua.setFirstName(nonNull(u.getFirstName()));
|
||||
ua.setLastName(nonNull(u.getLastName()));
|
||||
ua.setMd5Password(nonNull(u.getMd5password()));
|
||||
ua.setLoginCount(nonNegative(u.getLoginCount()));
|
||||
ua.setPasswordChangeRequired(u.getLoginCount() == 0);
|
||||
ua.setPasswordLinkExpires(0L);
|
||||
ua.setStatus(Status.ACTIVE);
|
||||
ua.setExternalAuthId(nonNull(u.getUsername()));
|
||||
ua.setPermissionSetUris(translateFromRoleUri(u.getRoleURI()));
|
||||
return ua;
|
||||
}
|
||||
|
||||
private String nonNull(String value) {
|
||||
return (value == null) ? "" : value;
|
||||
}
|
||||
|
||||
private int nonNegative(int value) {
|
||||
return Math.max(0, value);
|
||||
}
|
||||
|
||||
private Set<String> translateFromRoleUri(String roleUri) {
|
||||
String permissionSetUri = PermissionSetsLoader.URI_SELF_EDITOR;
|
||||
if ("role:/4".equals(roleUri)) {
|
||||
permissionSetUri = PermissionSetsLoader.URI_EDITOR;
|
||||
} else if ("role:/5".equals(roleUri)) {
|
||||
permissionSetUri = PermissionSetsLoader.URI_CURATOR;
|
||||
} else if ("role:/50".equals(roleUri)) {
|
||||
permissionSetUri = PermissionSetsLoader.URI_DBA;
|
||||
}
|
||||
return Collections.singleton(permissionSetUri);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// The Journal class
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
private static class Journal {
|
||||
private final File file;
|
||||
private final PrintWriter w;
|
||||
private int errorCount;
|
||||
|
||||
Journal(ServletContext ctx) throws IOException {
|
||||
String homeDirectoryPath = ConfigurationProperties.getBean(ctx)
|
||||
.getProperty("vitro.home.directory");
|
||||
if (homeDirectoryPath == null) {
|
||||
throw new IllegalStateException(
|
||||
"No value found for vitro.home.directory");
|
||||
}
|
||||
File homeDirectory = new File(homeDirectoryPath);
|
||||
confirmIsDirectory(homeDirectory);
|
||||
|
||||
File upgradeDirectory = createDirectory(homeDirectory, "upgrade");
|
||||
String filename = timestampedFilename("UpgradeUserAccounts", ".txt");
|
||||
this.file = new File(upgradeDirectory, filename);
|
||||
|
||||
this.w = new PrintWriter(this.file);
|
||||
|
||||
w.println("PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>");
|
||||
w.println("PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>");
|
||||
w.println("PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>");
|
||||
w.println("PREFIX vitro: <http://vitro.mannlib.cornell.edu/ns/vitro/0.7#>");
|
||||
w.println("");
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return file.getAbsolutePath();
|
||||
}
|
||||
|
||||
public void note(String... notes) {
|
||||
w.println();
|
||||
for (String note : notes) {
|
||||
w.println("# " + note);
|
||||
}
|
||||
}
|
||||
|
||||
public void noteAlreadyConverted(MockUser user, UserAccount ua) {
|
||||
note("UserAccount '" + ua.getUri() + "' already exists for User '"
|
||||
+ user.getURI() + "', " + user.getFirstName() + " "
|
||||
+ user.getLastName());
|
||||
}
|
||||
|
||||
public void writeUser(MockUser u) {
|
||||
w.println();
|
||||
w.println("# converting User: ");
|
||||
w.println(u.getURI());
|
||||
w.println(" a vitro:User ;");
|
||||
w.println(" vitro:username \"" + u.getUsername() + "\" ;");
|
||||
w.println(" vitro:firstName \"" + u.getFirstName() + "\" ;");
|
||||
w.println(" vitro:lastName \"" + u.getLastName() + "\" ;");
|
||||
w.println(" vitro:md5password \"" + u.getMd5password() + "\" ;");
|
||||
w.println(" vitro:loginCount " + u.getLoginCount() + " ;");
|
||||
w.println(" vitro:roleUri \"" + u.getRoleURI() + "\" ;");
|
||||
w.println(" .");
|
||||
}
|
||||
|
||||
public void noteUserAccount(UserAccount ua) {
|
||||
note("Created UserAccount '" + ua.getUri() + "' for "
|
||||
+ ua.getFirstName() + " " + ua.getLastName());
|
||||
}
|
||||
|
||||
public void noteDeletedUser(MockUser user) {
|
||||
note("Delete User: '" + user.getURI() + "'");
|
||||
}
|
||||
|
||||
public void noteException(Exception e) {
|
||||
errorCount++;
|
||||
note("Exception: " + e, " (full stack trace in Vitro log file)");
|
||||
}
|
||||
|
||||
public void close() {
|
||||
w.println("upgrade complete with " + errorCount + " errors.");
|
||||
w.close();
|
||||
}
|
||||
|
||||
private void confirmIsDirectory(File home) {
|
||||
if (!home.exists()) {
|
||||
throw new IllegalStateException("Vitro home directory '"
|
||||
+ home.getPath() + "' does not exist.");
|
||||
}
|
||||
if (!home.isDirectory()) {
|
||||
throw new IllegalStateException("Vitro home '" + home.getPath()
|
||||
+ "' is not a directory.");
|
||||
}
|
||||
if (!home.canWrite()) {
|
||||
throw new IllegalStateException(
|
||||
"Can't write to Vitro home directory '"
|
||||
+ home.getPath() + "'.");
|
||||
}
|
||||
}
|
||||
|
||||
private File createDirectory(File home, String name) {
|
||||
File upgradeDirectory = new File(home, name);
|
||||
if (!upgradeDirectory.exists()) {
|
||||
upgradeDirectory.mkdirs();
|
||||
if (!upgradeDirectory.exists()) {
|
||||
throw new IllegalStateException(
|
||||
"Failed to create the upgrade directory '"
|
||||
+ upgradeDirectory.getPath() + "'");
|
||||
}
|
||||
}
|
||||
|
||||
if (!upgradeDirectory.isDirectory()) {
|
||||
throw new IllegalStateException("Upgrade directory '"
|
||||
+ upgradeDirectory.getPath() + "' is not a directory.");
|
||||
}
|
||||
if (!upgradeDirectory.canWrite()) {
|
||||
throw new IllegalStateException(
|
||||
"Can't write to Upgrade directory '"
|
||||
+ upgradeDirectory.getPath() + "'.");
|
||||
}
|
||||
|
||||
return upgradeDirectory;
|
||||
}
|
||||
|
||||
private String timestampedFilename(String prefix, String suffix) {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat(
|
||||
"yyyy-MM-dd'T'HH-mm-sss");
|
||||
return prefix + "." + sdf.format(new Date()) + suffix;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Classes to replace the User and UserDao, just for the upgrade.
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
private static class MockUser {
|
||||
private String username;
|
||||
private String roleURI;
|
||||
private int loginCount;
|
||||
private String md5password;
|
||||
private String lastName;
|
||||
private String firstName;
|
||||
private String URI;
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public String getRoleURI() {
|
||||
return roleURI;
|
||||
}
|
||||
|
||||
public void setRoleURI(String roleURI) {
|
||||
this.roleURI = roleURI;
|
||||
}
|
||||
|
||||
public int getLoginCount() {
|
||||
return loginCount;
|
||||
}
|
||||
|
||||
public void setLoginCount(int loginCount) {
|
||||
this.loginCount = loginCount;
|
||||
}
|
||||
|
||||
public String getMd5password() {
|
||||
return md5password;
|
||||
}
|
||||
|
||||
public void setMd5password(String md5password) {
|
||||
this.md5password = md5password;
|
||||
}
|
||||
|
||||
public String getLastName() {
|
||||
return lastName;
|
||||
}
|
||||
|
||||
public void setLastName(String lastName) {
|
||||
this.lastName = lastName;
|
||||
}
|
||||
|
||||
public String getFirstName() {
|
||||
return firstName;
|
||||
}
|
||||
|
||||
public void setFirstName(String firstName) {
|
||||
this.firstName = firstName;
|
||||
}
|
||||
|
||||
public String getURI() {
|
||||
return URI;
|
||||
}
|
||||
|
||||
public void setURI(String uRI) {
|
||||
URI = uRI;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class MockUserDao {
|
||||
private final OntModel model;
|
||||
|
||||
public MockUserDao(ServletContext ctx) {
|
||||
this.model = ModelContext.getBaseOntModelSelector(ctx)
|
||||
.getUserAccountsModel();
|
||||
}
|
||||
|
||||
public Collection<MockUser> getAllUsers() {
|
||||
List<MockUser> allUsersList = new ArrayList<MockUser>();
|
||||
model.enterCriticalSection(Lock.READ);
|
||||
try {
|
||||
ClosableIterator<Statement> userStmtIt = model.listStatements(
|
||||
null, RDF.type, resource(USER));
|
||||
try {
|
||||
while (userStmtIt.hasNext()) {
|
||||
Statement stmt = userStmtIt.next();
|
||||
OntResource subjRes = stmt.getSubject().as(
|
||||
OntResource.class);
|
||||
allUsersList.add(userFromUserInd(subjRes));
|
||||
}
|
||||
} finally {
|
||||
userStmtIt.close();
|
||||
}
|
||||
} finally {
|
||||
model.leaveCriticalSection();
|
||||
}
|
||||
return allUsersList;
|
||||
}
|
||||
|
||||
private MockUser userFromUserInd(OntResource userInd) {
|
||||
MockUser user = new MockUser();
|
||||
user.setURI(userInd.getURI());
|
||||
|
||||
try {
|
||||
user.setUsername(getStringPropertyValue(userInd, USER_USERNAME));
|
||||
} catch (Exception e) {
|
||||
// ignore it.
|
||||
}
|
||||
|
||||
try {
|
||||
user.setMd5password(getStringPropertyValue(userInd,
|
||||
USER_MD5PASSWORD));
|
||||
} catch (Exception e) {
|
||||
// ignore it.
|
||||
}
|
||||
|
||||
try {
|
||||
user.setLoginCount(getIntegerPropertyValue(userInd,
|
||||
USER_LOGINCOUNT));
|
||||
} catch (Exception e) {
|
||||
user.setLoginCount(0);
|
||||
}
|
||||
|
||||
try {
|
||||
user.setRoleURI(getStringPropertyValue(userInd, USER_ROLE));
|
||||
} catch (Exception e) {
|
||||
log.error("Unable to set user role\n", e);
|
||||
e.printStackTrace();
|
||||
user.setRoleURI("1");
|
||||
}
|
||||
try {
|
||||
user.setLastName(getStringPropertyValue(userInd, USER_LASTNAME));
|
||||
} catch (Exception e) {
|
||||
// ignore it.
|
||||
}
|
||||
|
||||
try {
|
||||
user.setFirstName(getStringPropertyValue(userInd,
|
||||
USER_FIRSTNAME));
|
||||
} catch (Exception e) {
|
||||
// ignore it.
|
||||
}
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
private String getStringPropertyValue(OntResource userInd,
|
||||
String propertyUri) {
|
||||
Property property = model.getProperty(propertyUri);
|
||||
Literal object = (Literal) userInd.getProperty(property)
|
||||
.getObject();
|
||||
return object.getString();
|
||||
}
|
||||
|
||||
private int getIntegerPropertyValue(OntResource userInd,
|
||||
String propertyUri) {
|
||||
Property property = model.getProperty(propertyUri);
|
||||
Literal object = (Literal) userInd.getProperty(property)
|
||||
.getObject();
|
||||
return object.getInt();
|
||||
}
|
||||
|
||||
public void deleteUser(MockUser user) {
|
||||
model.removeAll(resource(user.getURI()), null, null);
|
||||
}
|
||||
|
||||
private Resource resource(String uri) {
|
||||
return model.getResource(uri);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,61 +0,0 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.utils;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.IndividualDao;
|
||||
|
||||
/**
|
||||
* Some static methods that help in dealing with image files.
|
||||
*/
|
||||
public class ImageUtil {
|
||||
private static final String DEFAULT_IMAGE_PATH = "/images/placeholders/thumbnail.jpg";
|
||||
|
||||
private static final Map<String, String> DEFAULT_IMAGE_PATHS_BY_TYPE = initImagePaths();
|
||||
|
||||
private static Map<String, String> initImagePaths() {
|
||||
Map<String, String> map = new HashMap<String, String>();
|
||||
// No images other than the default.
|
||||
return Collections.unmodifiableMap(map);
|
||||
}
|
||||
|
||||
/**
|
||||
* If we have a placeholder image for this exact type, return it. Otherwise,
|
||||
* return the default.
|
||||
*/
|
||||
public static String getPlaceholderImagePathForType(String typeUri) {
|
||||
for (Entry<String, String> entry : DEFAULT_IMAGE_PATHS_BY_TYPE
|
||||
.entrySet()) {
|
||||
if (typeUri.equals(entry.getKey())) {
|
||||
return entry.getValue();
|
||||
}
|
||||
}
|
||||
return DEFAULT_IMAGE_PATH;
|
||||
}
|
||||
|
||||
/**
|
||||
* If there is a placeholder image for any type that this Individual
|
||||
* instantiates, return that image. Otherwise, return the default.
|
||||
*/
|
||||
public static String getPlaceholderImagePathForIndividual(
|
||||
VitroRequest vreq, String individualUri) {
|
||||
IndividualDao indDao = vreq.getWebappDaoFactory().getIndividualDao();
|
||||
for (Entry<String, String> entry : DEFAULT_IMAGE_PATHS_BY_TYPE
|
||||
.entrySet()) {
|
||||
if (indDao.isIndividualOfClass(entry.getKey(), individualUri)) {
|
||||
return entry.getValue();
|
||||
}
|
||||
}
|
||||
return DEFAULT_IMAGE_PATH;
|
||||
}
|
||||
|
||||
/** Never need to instantiate this -- all methods are static. */
|
||||
private ImageUtil() {
|
||||
// Nothing to do
|
||||
}
|
||||
}
|
|
@ -97,7 +97,7 @@ public class ClassGroupPageData extends DataGetterBase implements DataGetter{
|
|||
setAllClassCountsToZero(group);
|
||||
}
|
||||
}else{
|
||||
log.error("classgroup " + classGroupUri + " does not exist in the system");
|
||||
throw new RuntimeException("classgroup " + classGroupUri + " does not exist in the system");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,238 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.web.images;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletContextEvent;
|
||||
import javax.servlet.ServletContextListener;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.IndividualDao;
|
||||
import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus;
|
||||
|
||||
/**
|
||||
* A utility for finding the URL of the correct Placeholder image.
|
||||
*
|
||||
* The mapping of image URLs to classes is created at startup, and stored in the
|
||||
* ServletContext.
|
||||
*/
|
||||
public class PlaceholderUtil {
|
||||
private static final Log log = LogFactory.getLog(PlaceholderUtil.class);
|
||||
|
||||
private static final String ATTRIBUTE_NAME = PlaceholderUtil.class
|
||||
.getName();
|
||||
private static final String PROPERTIES_FILE_PATH = "/images/placeholders/placeholders.properties";
|
||||
private static final String DEFAULT_IMAGE_PATH = "/images/placeholders/thumbnail.jpg";
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Static methods
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* If we have a placeholder image for this exact type, return it. Otherwise,
|
||||
* return the default.
|
||||
*/
|
||||
public static String getPlaceholderImagePathForType(VitroRequest vreq,
|
||||
String typeUri) {
|
||||
PlaceholderUtil pu = getPlaceholderUtil(vreq);
|
||||
if (pu == null) {
|
||||
return DEFAULT_IMAGE_PATH;
|
||||
} else {
|
||||
return pu.getPlaceholderImagePathForType(typeUri);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If there is a placeholder image for any type that this Individual
|
||||
* instantiates, return that image. Otherwise, return the default.
|
||||
*/
|
||||
public static String getPlaceholderImagePathForIndividual(
|
||||
VitroRequest vreq, String individualUri) {
|
||||
PlaceholderUtil pu = getPlaceholderUtil(vreq);
|
||||
if (pu == null) {
|
||||
return DEFAULT_IMAGE_PATH;
|
||||
} else {
|
||||
IndividualDao iDao = vreq.getWebappDaoFactory().getIndividualDao();
|
||||
return pu.getPlaceholderImagePathForIndividual(iDao, individualUri);
|
||||
}
|
||||
}
|
||||
|
||||
/** Get the PlaceholderUtil instance from the context, or null if none. */
|
||||
private static PlaceholderUtil getPlaceholderUtil(VitroRequest vreq) {
|
||||
if (vreq == null) {
|
||||
return null;
|
||||
}
|
||||
ServletContext ctx = vreq.getSession().getServletContext();
|
||||
Object attrib = ctx.getAttribute(ATTRIBUTE_NAME);
|
||||
if (attrib instanceof PlaceholderUtil) {
|
||||
return (PlaceholderUtil) attrib;
|
||||
} else {
|
||||
log.warn("Looked for a PlaceholerUtil, but found " + attrib);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// The object
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
private final Map<String, String> mapUrlsByClass;
|
||||
|
||||
private PlaceholderUtil(Map<String, String> map) {
|
||||
this.mapUrlsByClass = Collections
|
||||
.unmodifiableMap(new HashMap<String, String>(map));
|
||||
}
|
||||
|
||||
/**
|
||||
* If we have a placeholder image for this exact type, return it. Otherwise,
|
||||
* return the default.
|
||||
*/
|
||||
private String getPlaceholderImagePathForType(String typeUri) {
|
||||
if (typeUri == null) {
|
||||
log.debug("getPlaceholderImagePathForType: typeUri is null");
|
||||
return DEFAULT_IMAGE_PATH;
|
||||
}
|
||||
String url = mapUrlsByClass.get(typeUri);
|
||||
if (url == null) {
|
||||
log.debug("getPlaceholderImagePathForType: no value for '"
|
||||
+ typeUri + "'");
|
||||
return DEFAULT_IMAGE_PATH;
|
||||
}
|
||||
log.debug("getPlaceholderImagePathForType: value for '" + typeUri
|
||||
+ "' is '" + url + "'");
|
||||
return url;
|
||||
}
|
||||
|
||||
/**
|
||||
* If there is a placeholder image for any type that this Individual
|
||||
* instantiates, return that image. Otherwise, return the default.
|
||||
*/
|
||||
private String getPlaceholderImagePathForIndividual(IndividualDao iDao,
|
||||
String individualUri) {
|
||||
if (individualUri == null) {
|
||||
log.debug("getPlaceholderImagePathForIndividual: "
|
||||
+ "individualUri is null");
|
||||
return DEFAULT_IMAGE_PATH;
|
||||
}
|
||||
for (String classUri : mapUrlsByClass.keySet()) {
|
||||
String imageUrl = mapUrlsByClass.get(classUri);
|
||||
if (iDao.isIndividualOfClass(classUri, individualUri)) {
|
||||
log.debug("getPlaceholderImagePathForIndividual: individual '"
|
||||
+ individualUri + "' is of class '" + classUri
|
||||
+ "', value is '" + imageUrl + "'");
|
||||
return imageUrl;
|
||||
}
|
||||
}
|
||||
log.debug("getPlaceholderImagePathForIndividual: individual '"
|
||||
+ individualUri + "' is not of any recognized class");
|
||||
return DEFAULT_IMAGE_PATH;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Classes used for setup
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
public static class Setup implements ServletContextListener {
|
||||
@Override
|
||||
public void contextInitialized(ServletContextEvent sce) {
|
||||
ServletContext ctx = sce.getServletContext();
|
||||
StartupStatus ss = StartupStatus.getBean(ctx);
|
||||
|
||||
try {
|
||||
File propertiesFile = confirmRealPath(ctx, PROPERTIES_FILE_PATH);
|
||||
Map<String, String> map = loadPropertiesToMap(propertiesFile);
|
||||
confirmImagesArePresent(ctx, map);
|
||||
ctx.setAttribute(ATTRIBUTE_NAME, new PlaceholderUtil(map));
|
||||
} catch (SetupException e) {
|
||||
if (e.getCause() == null) {
|
||||
ss.warning(this, e.getMessage());
|
||||
} else {
|
||||
ss.warning(this, e.getMessage(), e.getCause());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, String> loadPropertiesToMap(File propertiesFile)
|
||||
throws SetupException {
|
||||
Properties props = new Properties();
|
||||
try {
|
||||
props.load(new FileReader(propertiesFile));
|
||||
} catch (IOException e) {
|
||||
throw new SetupException(
|
||||
"Can't load properties from the file at '"
|
||||
+ PROPERTIES_FILE_PATH
|
||||
+ "'. Is it in a valid format?", e);
|
||||
}
|
||||
|
||||
Map<String, String> map = new HashMap<String, String>();
|
||||
for (Enumeration<Object> keys = props.keys(); keys
|
||||
.hasMoreElements();) {
|
||||
String key = (String) keys.nextElement();
|
||||
String value = props.getProperty(key);
|
||||
map.put(key, value);
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
private void confirmImagesArePresent(ServletContext ctx,
|
||||
Map<String, String> map) throws SetupException {
|
||||
Set<String> imageUrls = new HashSet<String>();
|
||||
imageUrls.add(DEFAULT_IMAGE_PATH);
|
||||
imageUrls.addAll(map.values());
|
||||
for (String imageUrl : imageUrls) {
|
||||
confirmRealPath(ctx, imageUrl);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private File confirmRealPath(ServletContext ctx, String url)
|
||||
throws SetupException {
|
||||
String path = ctx.getRealPath(url);
|
||||
if (path == null) {
|
||||
throw new SetupException("Can't translate to real path: '"
|
||||
+ url + "'");
|
||||
}
|
||||
File file = new File(path);
|
||||
if (!file.exists()) {
|
||||
throw new SetupException("No file found at '" + url + "'.");
|
||||
}
|
||||
if (!file.canRead()) {
|
||||
throw new SetupException("Can't read the file at '" + url
|
||||
+ "'.");
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void contextDestroyed(ServletContextEvent sce) {
|
||||
sce.getServletContext().removeAttribute(ATTRIBUTE_NAME);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class SetupException extends Exception {
|
||||
public SetupException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public SetupException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.web.methods;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder;
|
||||
import edu.cornell.mannlib.vitro.webapp.web.images.PlaceholderUtil;
|
||||
import freemarker.core.Environment;
|
||||
import freemarker.template.TemplateModelException;
|
||||
|
||||
/**
|
||||
* Get a URL for the placeholder image for this Individual, based on the VClass
|
||||
* that the Individual belongs to.
|
||||
*/
|
||||
public class IndividualPlaceholderImageUrlMethod extends BaseTemplateMethodModel {
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
@Override
|
||||
public String exec(List args) throws TemplateModelException {
|
||||
if (args.size() != 1) {
|
||||
throw new TemplateModelException("Wrong number of arguments");
|
||||
}
|
||||
|
||||
String uri = (String) args.get(0);
|
||||
Environment env = Environment.getCurrentEnvironment();
|
||||
HttpServletRequest request = (HttpServletRequest) env.getCustomAttribute("request");
|
||||
VitroRequest vreq = new VitroRequest(request);
|
||||
String imageUrl = PlaceholderUtil.getPlaceholderImagePathForIndividual(vreq, uri);
|
||||
return UrlBuilder.getUrl(imageUrl);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> help(String name) {
|
||||
Map<String, Object> map = new LinkedHashMap<String, Object>();
|
||||
|
||||
map.put("return value", "The URL of the placeholder image for this individual, " +
|
||||
"based on the VClasses that the individual belongs to.");
|
||||
|
||||
List<String>params = new ArrayList<String>();
|
||||
params.add("Uri of individual");
|
||||
map.put("parameters", params);
|
||||
|
||||
List<String> examples = new ArrayList<String>();
|
||||
examples.add(name + "(individual.uri)");
|
||||
map.put("examples", examples);
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
}
|
|
@ -76,15 +76,11 @@ public abstract class BaseIndividualTemplateModel extends BaseTemplateModel {
|
|||
return UrlBuilder.getIndividualProfileUrl(individual, vreq);
|
||||
}
|
||||
|
||||
// For image, we use the default list view and Individual methods to reconstruct the image
|
||||
// url from various triples. A custom list view would require that logic to be duplicated here.
|
||||
public String getImageUrl() {
|
||||
String imageUrl = individual.getImageUrl();
|
||||
return imageUrl == null ? null : getUrl(imageUrl);
|
||||
}
|
||||
|
||||
// For image, we use the default list view and Individual methods to reconstruct the image
|
||||
// url from various triples. A custom list view would require that logic to be duplicated here.
|
||||
public String getThumbUrl() {
|
||||
String thumbUrl = individual.getThumbUrl();
|
||||
return thumbUrl == null ? null : getUrl(thumbUrl);
|
||||
|
|
|
@ -207,7 +207,7 @@ public class GroupedPropertyList extends BaseTemplateModel {
|
|||
ObjectPropertyDao opDao = wdf.getObjectPropertyDao();
|
||||
ObjectProperty op = opDao.getObjectPropertyByURI(propertyUri);
|
||||
if (op == null) {
|
||||
log.error("ObjectProperty op returned null from opDao.getObjectPropertyByURI()");
|
||||
log.error("ObjectProperty op returned null from opDao.getObjectPropertyByURI(" + propertyUri + ")");
|
||||
} else if (op.getURI() == null) {
|
||||
log.error("ObjectProperty op returned with null propertyURI from opDao.getObjectPropertyByURI()");
|
||||
} else {
|
||||
|
|
|
@ -111,7 +111,8 @@ public abstract class PropertyTemplateModel extends BaseTemplateModel {
|
|||
}
|
||||
|
||||
public String getAddUrl() {
|
||||
return addUrl;
|
||||
//log.info("addUrl=" + addUrl);
|
||||
return (addUrl != null) ? addUrl : "";
|
||||
}
|
||||
|
||||
public Map<String, Object> getVerboseDisplay() {
|
||||
|
|
|
@ -638,18 +638,6 @@ public class IndividualFilteringByStatementTest extends AbstractTestClass {
|
|||
// Un-implemented methods
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public boolean isSubjectOriented() {
|
||||
throw new RuntimeException(
|
||||
"ObjectPropertyStatement.isSubjectOriented() not implemented.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSubjectOriented(boolean subjectOriented) {
|
||||
throw new RuntimeException(
|
||||
"ObjectPropertyStatement.setSubjectOriented() not implemented.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSubjectURI(String subjectURI) {
|
||||
throw new RuntimeException(
|
||||
|
|
|
@ -9,12 +9,16 @@ import java.util.Map;
|
|||
import static org.junit.Assert.*;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.hp.hpl.jena.rdf.model.Literal;
|
||||
import com.hp.hpl.jena.rdf.model.Model;
|
||||
import com.hp.hpl.jena.rdf.model.ModelFactory;
|
||||
import com.hp.hpl.jena.rdf.model.ResourceFactory;
|
||||
import com.hp.hpl.jena.vocabulary.RDF;
|
||||
import com.hp.hpl.jena.vocabulary.RDFS;
|
||||
|
||||
import edu.cornell.mannlib.vitro.testing.AbstractTestClass;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.InsertException;
|
||||
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.EditConfigurationConstants;
|
||||
|
||||
public class ProcessRdfFormTest extends AbstractTestClass{
|
||||
|
||||
|
@ -243,6 +247,137 @@ public class ProcessRdfFormTest extends AbstractTestClass{
|
|||
ResourceFactory.createResource("http://test.com/uri3")));
|
||||
}
|
||||
|
||||
@Test
|
||||
//Edit existing statement
|
||||
public void forcedNewResourceTest() throws Exception{
|
||||
/* A very basic new statement edit. */
|
||||
EditConfigurationVTwo config = new EditConfigurationVTwo();
|
||||
config.setEditKey("mockEditKey");
|
||||
config.setN3Required(Arrays.asList("?newRes ?test2 ?test3 ." ));
|
||||
config.setUrisOnform(Arrays.asList( "newRes", "test2", "test3"));
|
||||
//set uris in scope to include an existing value for new resource
|
||||
config.addUrisInScope("newRes", Arrays.asList("<http://test.com/uri1>"));
|
||||
config.addNewResource("newRes", null);
|
||||
config.setEntityToReturnTo("?newRes");
|
||||
|
||||
Map<String,String[]> values = new HashMap<String, String[]>();
|
||||
//value from form should indicate that newRes should have new uri created
|
||||
values.put("newRes", (new String[] {EditConfigurationConstants.NEW_URI_SENTINEL}));
|
||||
values.put("test2", (new String[] {"http://test.com/uri2"}));
|
||||
values.put("test3", (new String[] {"http://test.com/uri3"}));
|
||||
values.put("editKey", (new String[] {"mockEditKey"}));
|
||||
|
||||
MultiValueEditSubmission submission = new MultiValueEditSubmission(values, config);
|
||||
|
||||
ProcessRdfForm processor = new ProcessRdfForm(config,getMockNewURIMaker());
|
||||
|
||||
/* test just the N3 substitution part */
|
||||
List<String>req = config.getN3Required();
|
||||
List<String>opt = config.getN3Optional();
|
||||
processor.subInValuesToN3( config , submission, req, opt, null , null);
|
||||
assertNotNull(req);
|
||||
assertTrue( req.size() > 0);
|
||||
assertNotNull(req.get(0));
|
||||
assertEquals("<"+NEWURI_STRING + "0> <http://test.com/uri2> <http://test.com/uri3> .", req.get(0));
|
||||
|
||||
assertEquals("<" + NEWURI_STRING + "0>", submission.getEntityToReturnTo());
|
||||
|
||||
/* test the N3 and parse RDF parts */
|
||||
AdditionsAndRetractions changes = processor.process( config, submission );
|
||||
|
||||
assertNotNull( changes );
|
||||
assertNotNull( changes.getAdditions() );
|
||||
assertNotNull( changes.getRetractions());
|
||||
assertTrue( changes.getAdditions().size() == 1 );
|
||||
//the old uri should be removed
|
||||
assertTrue( changes.getRetractions().size() == 0 );
|
||||
|
||||
assertTrue( changes.getAdditions().contains(
|
||||
ResourceFactory.createResource(NEWURI_STRING + "0"),
|
||||
ResourceFactory.createProperty("http://test.com/uri2"),
|
||||
ResourceFactory.createResource("http://test.com/uri3")));
|
||||
|
||||
|
||||
}
|
||||
|
||||
/* An edit of an existing statement set where some statements need to be replaced while
|
||||
* others must be retained. */
|
||||
@Test
|
||||
public void basicEditReplaceStatement() throws Exception{
|
||||
String testXURI = "http://test.com/uriX";
|
||||
String testYURI = "http://test.com/uriY";
|
||||
String testZURIOrginal = "http://test.com/uriZ";
|
||||
String testZURIChanged = "http://test.com/uriZChanged";
|
||||
String zType = "http://test.com/TestType";
|
||||
String rdfsLabel = "http://www.w3.org/2000/01/rdf-schema#label";
|
||||
/* set up model */
|
||||
Model model = ModelFactory.createDefaultModel();
|
||||
//?x ?y ?zOriginal.
|
||||
model.add(model.createResource(testXURI),
|
||||
model.createProperty(testYURI),
|
||||
model.createResource(testZURIOrginal));
|
||||
//?zOriginal a TestType.
|
||||
|
||||
model.add(model.createResource(testZURIOrginal),
|
||||
RDF.type,
|
||||
model.createResource(zType));
|
||||
//?zOriginal label "zLabel";
|
||||
|
||||
model.add(model.createResource(testZURIOrginal),
|
||||
RDFS.label,
|
||||
model.createLiteral("Z Original Label"));
|
||||
|
||||
/* set up EditConfiguration */
|
||||
EditConfigurationVTwo config = new EditConfigurationVTwo();
|
||||
config.setEditKey("mockEditKey");
|
||||
config.setLiteralsOnForm(Arrays.asList("zLabel"));
|
||||
config.setUrisOnform(Arrays.asList("testX", "testY", "testZ"));
|
||||
config.setN3Required( Arrays.asList("?testX ?testY ?testZ ." ));
|
||||
config.setN3Optional( Arrays.asList("?testZ a <" + zType + "> . \n" +
|
||||
"?testZ <" + rdfsLabel + "> ?zLabel ." ));
|
||||
//mimicking an existing value for the label
|
||||
config.addLiteralInScope("zLabel", model.createLiteral("Z Original Label"));
|
||||
|
||||
config.setVarNameForSubject("testX");
|
||||
config.setSubjectUri(testXURI);
|
||||
|
||||
config.setPredicateUri(testYURI);
|
||||
config.setVarNameForPredicate("testY");
|
||||
|
||||
config.setObject(testZURIOrginal);
|
||||
config.setVarNameForObject("testZ");
|
||||
|
||||
config.addField(new FieldVTwo().setName("zLabel"));
|
||||
config.prepareForObjPropUpdate(model);
|
||||
/* set up Submission */
|
||||
Map<String,String[]> values = new HashMap<String, String[]>();
|
||||
values.put("testZ", (new String[] {testZURIChanged}));
|
||||
values.put("zLabel", (new String[] {"New Z Label"}));
|
||||
values.put("editKey", (new String[] {"mockEditKey"}));
|
||||
MultiValueEditSubmission submission = new MultiValueEditSubmission(values, config);
|
||||
|
||||
ProcessRdfForm processor = new ProcessRdfForm(config,getMockNewURIMaker());
|
||||
AdditionsAndRetractions changes = processor.process( config, submission );
|
||||
|
||||
assertNotNull( changes );
|
||||
assertNotNull( changes.getAdditions() );
|
||||
assertNotNull( changes.getRetractions());
|
||||
|
||||
// assertTrue( changes.getAdditions().size() == 3 );
|
||||
//only one statement should be retracted
|
||||
// assertTrue( changes.getRetractions().size() == 1 );
|
||||
|
||||
assertTrue( changes.getAdditions().contains(
|
||||
ResourceFactory.createResource(testXURI),
|
||||
ResourceFactory.createProperty(testYURI),
|
||||
ResourceFactory.createResource(testZURIChanged)));
|
||||
|
||||
assertTrue( changes.getRetractions().contains(
|
||||
ResourceFactory.createResource(testXURI),
|
||||
ResourceFactory.createProperty(testYURI),
|
||||
ResourceFactory.createResource(testZURIOrginal)));
|
||||
}
|
||||
|
||||
|
||||
String NEWURI_STRING= "http://newURI/n";
|
||||
|
||||
|
|
|
@ -55,16 +55,6 @@ public class ObjectPropertyStatementDaoStub implements
|
|||
.getObjectURI());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSubjectOriented() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSubjectOriented(boolean subjectOriented) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSubjectURI() {
|
||||
return s;
|
||||
|
|
|
@ -7,7 +7,6 @@ import java.util.Map;
|
|||
import java.util.Set;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.ApplicationDao;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.Classes2ClassesDao;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.DataPropertyDao;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.DataPropertyStatementDao;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.DatatypeDao;
|
||||
|
@ -144,12 +143,6 @@ return this.objectPropertyStatementDao; }
|
|||
// Un-implemented methods
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public Map<String, String> getProperties() {
|
||||
throw new RuntimeException(
|
||||
"WebappDaoFactory.getProperties() not implemented.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String checkURI(String uriStr) {
|
||||
throw new RuntimeException(
|
||||
|
@ -169,7 +162,7 @@ return this.objectPropertyStatementDao; }
|
|||
}
|
||||
|
||||
@Override
|
||||
public String[] getPreferredLanguages() {
|
||||
public List<String> getPreferredLanguages() {
|
||||
throw new RuntimeException(
|
||||
"WebappDaoFactory.getPreferredLanguages() not implemented.");
|
||||
}
|
||||
|
@ -192,12 +185,6 @@ return this.objectPropertyStatementDao; }
|
|||
"WebappDaoFactory.getUserURI() not implemented.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Classes2ClassesDao getClasses2ClassesDao() {
|
||||
throw new RuntimeException(
|
||||
"WebappDaoFactory.getClasses2ClassesDao() not implemented.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatatypeDao getDatatypeDao() {
|
||||
throw new RuntimeException(
|
||||
|
|
|
@ -32,4 +32,4 @@ display:Home
|
|||
########## Data Getter ############
|
||||
|
||||
<http://vitro.mannlib.cornell.edu/ontologies/display/1.1#homeDataGetter>
|
||||
a <java:edu.cornell.mannlib.vitro.webapp.utils.pageDataGetter.BrowseDataGetter> .
|
||||
a <java:edu.cornell.mannlib.vitro.webapp.utils.dataGetter.BrowseDataGetter> .
|
|
@ -22,6 +22,7 @@ auth:ADMIN
|
|||
auth:hasPermission simplePermission:SeeStartupStatus ;
|
||||
auth:hasPermission simplePermission:UseAdvancedDataToolsPages ;
|
||||
auth:hasPermission simplePermission:UseMiscellaneousAdminPages ;
|
||||
auth:hasPermission simplePermission:UseSparqlQueryPage ;
|
||||
|
||||
# permissions for CURATOR and above.
|
||||
auth:hasPermission simplePermission:EditOntology ;
|
||||
|
|
|
@ -24,6 +24,8 @@ edu.cornell.mannlib.vitro.webapp.servlet.setup.UpdateKnowledgeBase
|
|||
|
||||
edu.cornell.mannlib.vitro.webapp.filestorage.backend.FileStorageSetup
|
||||
|
||||
edu.cornell.mannlib.vitro.webapp.web.images.PlaceholderUtil$Setup
|
||||
|
||||
# Update the URIs on Permission Sets on UserAccounts from model (1.4) to 1.5.
|
||||
edu.cornell.mannlib.vitro.webapp.servlet.setup.UpdatePermissionSetUris
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
<%@taglib prefix="vitro" uri="/WEB-INF/tlds/VitroUtils.tld" %>
|
||||
<%@page import="edu.cornell.mannlib.vitro.webapp.auth.permissions.SimplePermission" %>
|
||||
<% request.setAttribute("requestedActions", SimplePermission.MANAGE_PORTALS.ACTION); %>
|
||||
<% request.setAttribute("requestedActions", SimplePermission.USE_SPARQL_QUERY_PAGE.ACTION); %>
|
||||
<vitro:confirmAuthorization />
|
||||
|
||||
<body>
|
||||
|
|
38
webapp/web/css/jquery_plugins/jquery.realperson.css
Normal file
38
webapp/web/css/jquery_plugins/jquery.realperson.css
Normal file
|
@ -0,0 +1,38 @@
|
|||
/* http://keith-wood.name/realPerson.html
|
||||
Real Person Form Submission for jQuery v1.0.1.
|
||||
Written by Keith Wood (kwood{at}iinet.com.au) June 2009.
|
||||
Dual licensed under the GPL (http://dev.jquery.com/browser/trunk/jquery/GPL-LICENSE.txt) and
|
||||
MIT (http://dev.jquery.com/browser/trunk/jquery/MIT-LICENSE.txt) licenses.
|
||||
Please attribute the author if you use it. */
|
||||
|
||||
/* Real Person jQuery plugin styles v1.0.1. */
|
||||
.realperson-challenge {
|
||||
display: inline-block;
|
||||
background-color: #ddd;
|
||||
width: 150px;
|
||||
padding-top: 10px;
|
||||
padding-left: 12px;
|
||||
}
|
||||
.realperson-text {
|
||||
font-family: "Courier New",monospace;
|
||||
font-size: 6px;
|
||||
font-weight: bold;
|
||||
letter-spacing: -1px;
|
||||
line-height: 3px;
|
||||
color: #000;
|
||||
}
|
||||
.realperson-regen {
|
||||
padding-top: 4px;
|
||||
padding-right: 6px;
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
.realpersonLabel {
|
||||
display: block;
|
||||
}
|
||||
#defaultReal {
|
||||
margin-left: 20px;
|
||||
vertical-align: top;
|
||||
margin-top: 3px;
|
||||
}
|
Binary file not shown.
Before Width: | Height: | Size: 3.4 KiB |
17
webapp/web/images/placeholders/placeholders.properties
Normal file
17
webapp/web/images/placeholders/placeholders.properties
Normal file
|
@ -0,0 +1,17 @@
|
|||
#
|
||||
# Assign placeholder images to classes of individuals.
|
||||
#
|
||||
# If showing an individual that has no image, a placeholder image may be shown.
|
||||
# By default, the placeholder is /images/placeholders/thumbnail.jpg. However,
|
||||
# this file allows you to associate classes with special placeholder images, and
|
||||
# if the individual belongs to such a class, the special placeholder is shown
|
||||
# instead of the default.
|
||||
#
|
||||
# EXAMPLE:
|
||||
# http\://xmlns.com/foaf/0.1/Person = /images/placeholders/person.thumbnail.jpg
|
||||
# means that any individual of type foaf:Person will be represented by
|
||||
# person.thumbnail.jpg
|
||||
#
|
||||
# NOTE: a colon is a special character in a properties file, and must be escaped
|
||||
# by a backslash.
|
||||
|
|
@ -44,7 +44,7 @@ function itemElement(template, uri, label, classLabel, imageUrl, removeInfo) {
|
|||
this.uri = uri;
|
||||
this.label = label;
|
||||
this.classLabel = classLabel;
|
||||
this.imageUrl = (imageUrl) ? imageUrl : imageUrl="../images/placeholders/person.thumbnail.jpg";
|
||||
this.imageUrl = imageUrl;
|
||||
this.removeInfo = removeInfo;
|
||||
|
||||
this.toString = function() {
|
||||
|
|
|
@ -6,41 +6,9 @@ function ValidateForm(formName) {
|
|||
errors = false;
|
||||
var errorList;
|
||||
|
||||
if (document.forms[formName].RequiredFields) {
|
||||
errorList = 'Please fill out the following required fields:\n';
|
||||
// build array of required fields
|
||||
reqStr = document.forms[formName].RequiredFields.value;
|
||||
requiredFields = reqStr.split(',');
|
||||
// build array holding the names of required fields as
|
||||
// displayed in error box
|
||||
if (document.forms[formName].RequiredFieldsNames) {
|
||||
reqNameStr = document.forms[formName].RequiredFieldsNames.value;
|
||||
} else {
|
||||
reqNameStr = document.forms[formName].RequiredFields.value;
|
||||
}
|
||||
requiredNames = reqNameStr.split(',');
|
||||
// Loop through form elements, checking for required fields
|
||||
while ((x < document.forms[formName].elements.length)) {
|
||||
if (document.forms[formName].elements[x].name == requiredFields[y]) {
|
||||
if (document.forms[formName].elements[x].value == '') {
|
||||
errorList += requiredNames[y] + '\n';
|
||||
errors = true;
|
||||
}
|
||||
y++;
|
||||
}
|
||||
x++;
|
||||
}
|
||||
if (errors) {
|
||||
alert(errorList);
|
||||
return false;
|
||||
}
|
||||
x = 0;
|
||||
y = 0;
|
||||
}
|
||||
|
||||
// Check for Email formatting
|
||||
if (document.forms[formName].EmailFields) {
|
||||
errorList = 'Please format your e-mail address as: \"userid@institution.edu\" or enter another complete email address';
|
||||
errorList = '\nPlease format your e-mail address as:\n \"userid@institution.edu\" or enter another complete and valid email address';
|
||||
// build array of required fields
|
||||
emailStr = document.forms[formName].EmailFields.value;
|
||||
emailFields = emailStr.split(',');
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue