diff --git a/dspace-api/src/main/java/org/dspace/app/mediafilter/MediaFilterServiceImpl.java b/dspace-api/src/main/java/org/dspace/app/mediafilter/MediaFilterServiceImpl.java index 961cbaa7d0ee..974dc784bd4f 100644 --- a/dspace-api/src/main/java/org/dspace/app/mediafilter/MediaFilterServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/app/mediafilter/MediaFilterServiceImpl.java @@ -37,7 +37,6 @@ import org.dspace.core.Constants; import org.dspace.core.Context; import org.dspace.core.SelfNamedPlugin; -import org.dspace.core.UUIDIterator; import org.dspace.eperson.Group; import org.dspace.eperson.service.GroupService; import org.dspace.scripts.handler.DSpaceRunnableHandler; @@ -133,19 +132,21 @@ public void applyFiltersAllItems(Context context) throws Exception { @Override public void applyFiltersCommunity(Context context, Community community) throws Exception { //only apply filters if community not in skip-list + // ensure that the community is attached to the current hibernate session + // as we are committing after each item (handles, sub-communties and + // collections are lazy attributes) + community = context.reloadEntity(community); if (!inSkipList(community.getHandle())) { List subcommunities = community.getSubcommunities(); - List collections = community.getCollections(); - - UUIDIterator communityIterator = new UUIDIterator<>(context, subcommunities, Community.class); - UUIDIterator collectionIterator = new UUIDIterator<>(context, collections, Collection.class); - - while (communityIterator.hasNext()) { - applyFiltersCommunity(context, communityIterator.next()); + for (Community subcommunity : subcommunities) { + applyFiltersCommunity(context, subcommunity); } - - while (collectionIterator.hasNext()) { - applyFiltersCollection(context, collectionIterator.next()); + // ensure that the community is attached to the current hibernate session + // as we are committing after each item + community = context.reloadEntity(community); + List collections = community.getCollections(); + for (Collection collection : collections) { + applyFiltersCollection(context, collection); } } } @@ -153,6 +154,9 @@ public void applyFiltersCommunity(Context context, Community community) @Override public void applyFiltersCollection(Context context, Collection collection) throws Exception { + // ensure that the collection is attached to the current hibernate session + // as we are committing after each item (handles are lazy attributes) + collection = context.reloadEntity(collection); //only apply filters if collection not in skip-list if (!inSkipList(collection.getHandle())) { Iterator itemIterator = itemService.findAllByCollection(context, collection); diff --git a/dspace-api/src/main/java/org/dspace/app/requestitem/dao/impl/RequestItemDAOImpl.java b/dspace-api/src/main/java/org/dspace/app/requestitem/dao/impl/RequestItemDAOImpl.java index a09a2bf250e5..008174ded88c 100644 --- a/dspace-api/src/main/java/org/dspace/app/requestitem/dao/impl/RequestItemDAOImpl.java +++ b/dspace-api/src/main/java/org/dspace/app/requestitem/dao/impl/RequestItemDAOImpl.java @@ -46,6 +46,6 @@ public RequestItem findByToken(Context context, String token) throws SQLExceptio public Iterator findByItem(Context context, Item item) throws SQLException { Query query = createQuery(context, "FROM RequestItem WHERE item_id= :uuid"); query.setParameter("uuid", item.getID()); - return iterate(context, query, RequestItem.class); + return iterate(query); } } diff --git a/dspace-api/src/main/java/org/dspace/content/ItemServiceImpl.java b/dspace-api/src/main/java/org/dspace/content/ItemServiceImpl.java index c61d6e8c8c9f..6b3ef003edca 100644 --- a/dspace-api/src/main/java/org/dspace/content/ItemServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/ItemServiceImpl.java @@ -1844,7 +1844,7 @@ public boolean isItemListedForUser(Context context, Item item) { @Override public Iterator findByIds(Context context, List ids) throws SQLException { return itemDAO.findByIds(context, - ids.stream().map(uuid -> UUID.fromString(uuid)).collect(Collectors.toList())); + ids.stream().map(uuid -> UUID.fromString(uuid)).distinct().collect(Collectors.toList())); } @Override diff --git a/dspace-api/src/main/java/org/dspace/content/dao/impl/BitstreamDAOImpl.java b/dspace-api/src/main/java/org/dspace/content/dao/impl/BitstreamDAOImpl.java index a4f61f0c6435..a3347a40ab93 100644 --- a/dspace-api/src/main/java/org/dspace/content/dao/impl/BitstreamDAOImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/dao/impl/BitstreamDAOImpl.java @@ -27,6 +27,7 @@ import org.dspace.core.AbstractHibernateDSODAO; import org.dspace.core.Constants; import org.dspace.core.Context; +import org.dspace.core.UUIDIterator; /** * Hibernate implementation of the Database Access Object interface class for the Bitstream object. @@ -77,7 +78,7 @@ public List findBitstreamsWithNoRecentChecksum(Context context) throw @Override public Iterator findByCommunity(Context context, Community community) throws SQLException { - Query query = createQuery(context, "select b from Bitstream b " + + Query query = createQuery(context, "select b.id from Bitstream b " + "join b.bundles bitBundles " + "join bitBundles.items item " + "join item.collections itemColl " + @@ -85,40 +86,43 @@ public Iterator findByCommunity(Context context, Community community) "WHERE :community IN community"); query.setParameter("community", community); - - return iterate(context, query, Bitstream.class); + @SuppressWarnings("unchecked") + List uuids = query.getResultList(); + return new UUIDIterator(context, uuids, Bitstream.class, this); } @Override public Iterator findByCollection(Context context, Collection collection) throws SQLException { - Query query = createQuery(context, "select b from Bitstream b " + + Query query = createQuery(context, "select b.id from Bitstream b " + "join b.bundles bitBundles " + "join bitBundles.items item " + "join item.collections c " + "WHERE :collection IN c"); query.setParameter("collection", collection); - - return iterate(context, query, Bitstream.class); + @SuppressWarnings("unchecked") + List uuids = query.getResultList(); + return new UUIDIterator(context, uuids, Bitstream.class, this); } @Override public Iterator findByItem(Context context, Item item) throws SQLException { - Query query = createQuery(context, "select b from Bitstream b " + + Query query = createQuery(context, "select b.id from Bitstream b " + "join b.bundles bitBundles " + "join bitBundles.items item " + "WHERE :item IN item"); query.setParameter("item", item); - - return iterate(context, query, Bitstream.class); + @SuppressWarnings("unchecked") + List uuids = query.getResultList(); + return new UUIDIterator(context, uuids, Bitstream.class, this); } @Override public Iterator findShowableByItem(Context context, UUID itemId, String bundleName) throws SQLException { Query query = createQuery( context, - "select b from Bitstream b " + + "select b.id from Bitstream b " + "join b.bundles bitBundle " + "join bitBundle.items item " + "WHERE item.id = :itemId " + @@ -150,15 +154,18 @@ public Iterator findShowableByItem(Context context, UUID itemId, Stri query.setParameter("itemId", itemId); query.setParameter("bundleName", bundleName); - - return iterate(context, query, Bitstream.class); + @SuppressWarnings("unchecked") + List uuids = query.getResultList(); + return new UUIDIterator(context, uuids, Bitstream.class, this); } @Override public Iterator findByStoreNumber(Context context, Integer storeNumber) throws SQLException { - Query query = createQuery(context, "select b from Bitstream b where b.storeNumber = :storeNumber"); + Query query = createQuery(context, "select b.id from Bitstream b where b.storeNumber = :storeNumber"); query.setParameter("storeNumber", storeNumber); - return iterate(context, query, Bitstream.class); + @SuppressWarnings("unchecked") + List uuids = query.getResultList(); + return new UUIDIterator(context, uuids, Bitstream.class, this); } @Override diff --git a/dspace-api/src/main/java/org/dspace/content/dao/impl/ItemDAOImpl.java b/dspace-api/src/main/java/org/dspace/content/dao/impl/ItemDAOImpl.java index 443268cbbb7a..3b12c68dcedd 100644 --- a/dspace-api/src/main/java/org/dspace/content/dao/impl/ItemDAOImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/dao/impl/ItemDAOImpl.java @@ -29,6 +29,7 @@ import org.dspace.content.dao.ItemDAO; import org.dspace.core.AbstractHibernateDSODAO; import org.dspace.core.Context; +import org.dspace.core.UUIDIterator; import org.dspace.eperson.EPerson; import org.hibernate.Criteria; import org.hibernate.criterion.Criterion; @@ -56,28 +57,34 @@ protected ItemDAOImpl() { @Override public Iterator findAll(Context context, boolean archived) throws SQLException { - Query query = createQuery(context, "FROM Item WHERE inArchive=:in_archive ORDER BY id"); + Query query = createQuery(context, "SELECT i.id FROM Item i WHERE inArchive=:in_archive ORDER BY id"); query.setParameter("in_archive", archived); - return iterate(context, query, Item.class); + @SuppressWarnings("unchecked") + List uuids = query.getResultList(); + return new UUIDIterator(context, uuids, Item.class, this); } @Override public Iterator findAll(Context context, boolean archived, int limit, int offset) throws SQLException { - Query query = createQuery(context, "FROM Item WHERE inArchive=:in_archive ORDER BY id"); + Query query = createQuery(context, "SELECT i.id FROM Item i WHERE inArchive=:in_archive ORDER BY id"); query.setParameter("in_archive", archived); query.setFirstResult(offset); query.setMaxResults(limit); - return iterate(context, query, Item.class); + @SuppressWarnings("unchecked") + List uuids = query.getResultList(); + return new UUIDIterator(context, uuids, Item.class, this); } @Override public Iterator findAll(Context context, boolean archived, boolean withdrawn) throws SQLException { Query query = createQuery(context, - "FROM Item WHERE inArchive=:in_archive or withdrawn=:withdrawn ORDER BY id"); + "SELECT i.id FROM Item i WHERE inArchive=:in_archive or withdrawn=:withdrawn ORDER BY id"); query.setParameter("in_archive", archived); query.setParameter("withdrawn", withdrawn); - return iterate(context, query, Item.class); + @SuppressWarnings("unchecked") + List uuids = query.getResultList(); + return new UUIDIterator(context, uuids, Item.class, this); } @Override @@ -86,12 +93,14 @@ public Iterator findAllRegularItems(Context context) throws SQLException { // It does not include workspace, workflow or template items. Query query = createQuery( context, - "SELECT i FROM Item as i " + + "SELECT i.id FROM Item as i " + "LEFT JOIN Version as v ON i = v.item " + "WHERE i.inArchive=true or i.withdrawn=true or (i.inArchive=false and v.id IS NOT NULL) " + "ORDER BY i.id" ); - return iterate(context, query, Item.class); + @SuppressWarnings("unchecked") + List uuids = query.getResultList(); + return new UUIDIterator(context, uuids, Item.class, this); } @Override @@ -99,7 +108,7 @@ public Iterator findAll(Context context, boolean archived, boolean withdrawn, boolean discoverable, Date lastModified) throws SQLException { StringBuilder queryStr = new StringBuilder(); - queryStr.append("SELECT i FROM Item i"); + queryStr.append("SELECT i.id FROM Item i"); queryStr.append(" WHERE (inArchive = :in_archive OR withdrawn = :withdrawn)"); queryStr.append(" AND discoverable = :discoverable"); @@ -115,16 +124,20 @@ public Iterator findAll(Context context, boolean archived, if (lastModified != null) { query.setParameter("last_modified", lastModified, TemporalType.TIMESTAMP); } - return iterate(context, query, Item.class); + @SuppressWarnings("unchecked") + List uuids = query.getResultList(); + return new UUIDIterator(context, uuids, Item.class, this); } @Override public Iterator findBySubmitter(Context context, EPerson eperson) throws SQLException { Query query = createQuery(context, - "FROM Item WHERE inArchive=:in_archive and submitter=:submitter ORDER BY id"); + "SELECT i.id FROM Item i WHERE inArchive=:in_archive and submitter=:submitter ORDER BY id"); query.setParameter("in_archive", true); query.setParameter("submitter", eperson); - return iterate(context, query, Item.class); + @SuppressWarnings("unchecked") + List uuids = query.getResultList(); + return new UUIDIterator(context, uuids, Item.class, this); } @Override @@ -133,16 +146,18 @@ public Iterator findBySubmitter(Context context, EPerson eperson, boolean if (!retrieveAllItems) { return findBySubmitter(context, eperson); } - Query query = createQuery(context, "FROM Item WHERE submitter=:submitter ORDER BY id"); + Query query = createQuery(context, "SELECT i.id FROM Item i WHERE submitter=:submitter ORDER BY id"); query.setParameter("submitter", eperson); - return iterate(context, query, Item.class); + @SuppressWarnings("unchecked") + List uuids = query.getResultList(); + return new UUIDIterator(context, uuids, Item.class, this); } @Override public Iterator findBySubmitter(Context context, EPerson eperson, MetadataField metadataField, int limit) throws SQLException { StringBuilder query = new StringBuilder(); - query.append("SELECT item FROM Item as item "); + query.append("SELECT item.id FROM Item as item "); addMetadataLeftJoin(query, Item.class.getSimpleName().toLowerCase(), Collections.singletonList(metadataField)); query.append(" WHERE item.inArchive = :in_archive"); query.append(" AND item.submitter =:submitter"); @@ -154,13 +169,15 @@ public Iterator findBySubmitter(Context context, EPerson eperson, Metadata hibernateQuery.setParameter("in_archive", true); hibernateQuery.setParameter("submitter", eperson); hibernateQuery.setMaxResults(limit); - return iterate(context, hibernateQuery, Item.class); + @SuppressWarnings("unchecked") + List uuids = hibernateQuery.getResultList(); + return new UUIDIterator(context, uuids, Item.class, this); } @Override public Iterator findByMetadataField(Context context, MetadataField metadataField, String value, boolean inArchive) throws SQLException { - String hqlQueryString = "SELECT item FROM Item as item join item.metadata metadatavalue " + + String hqlQueryString = "SELECT item.id FROM Item as item join item.metadata metadatavalue " + "WHERE item.inArchive=:in_archive AND metadatavalue.metadataField = :metadata_field"; if (value != null) { hqlQueryString += " AND STR(metadatavalue.value) = :text_value"; @@ -172,13 +189,15 @@ public Iterator findByMetadataField(Context context, MetadataField metadat if (value != null) { query.setParameter("text_value", value); } - return iterate(context, query, Item.class); + @SuppressWarnings("unchecked") + List uuids = query.getResultList(); + return new UUIDIterator(context, uuids, Item.class, this); } @Override public Iterator findByMetadataField(Context context, MetadataField metadataField, String value) throws SQLException { - String hqlQueryString = "SELECT item FROM Item as item join item.metadata metadatavalue " + + String hqlQueryString = "SELECT item.id FROM Item as item join item.metadata metadatavalue " + "WHERE metadatavalue.metadataField = :metadata_field"; if (value != null) { hqlQueryString += " AND STR(metadatavalue.value) = :text_value"; @@ -189,7 +208,9 @@ public Iterator findByMetadataField(Context context, MetadataField metadat if (value != null) { query.setParameter("text_value", value); } - return iterate(context, query, Item.class); + @SuppressWarnings("unchecked") + List uuids = query.getResultList(); + return new UUIDIterator(context, uuids, Item.class, this); } enum OP { @@ -310,20 +331,22 @@ public Iterator findByMetadataQuery(Context context, List findByAuthorityValue(Context context, MetadataField metadataField, String authority, boolean inArchive) throws SQLException { Query query = createQuery(context, - "SELECT item FROM Item as item join item.metadata metadatavalue " + + "SELECT item.id FROM Item as item join item.metadata metadatavalue " + "WHERE item.inArchive=:in_archive AND metadatavalue.metadataField = :metadata_field AND " + "metadatavalue.authority = :authority ORDER BY item.id"); query.setParameter("in_archive", inArchive); query.setParameter("metadata_field", metadataField); query.setParameter("authority", authority); - return iterate(context, query, Item.class); + @SuppressWarnings("unchecked") + List uuids = query.getResultList(); + return new UUIDIterator(context, uuids, Item.class, this); } @Override public Iterator findArchivedByCollection(Context context, Collection collection, Integer limit, Integer offset) throws SQLException { Query query = createQuery(context, - "select i from Item i join i.collections c " + + "select i.id from Item i join i.collections c " + "WHERE :collection IN c AND i.inArchive=:in_archive ORDER BY i.id"); query.setParameter("collection", collection); query.setParameter("in_archive", true); @@ -333,7 +356,9 @@ public Iterator findArchivedByCollection(Context context, Collection colle if (limit != null) { query.setMaxResults(limit); } - return iterate(context, query, Item.class); + @SuppressWarnings("unchecked") + List uuids = query.getResultList(); + return new UUIDIterator(context, uuids, Item.class, this); } @Override @@ -368,17 +393,18 @@ public int countArchivedByCollectionExcludingOwning(Context context, Collection @Override public Iterator findAllByCollection(Context context, Collection collection) throws SQLException { Query query = createQuery(context, - "select i from Item i join i.collections c WHERE :collection IN c ORDER BY i.id"); + "select i.id from Item i join i.collections c WHERE :collection IN c ORDER BY i.id"); query.setParameter("collection", collection); - - return iterate(context, query, Item.class); + @SuppressWarnings("unchecked") + List uuids = query.getResultList(); + return new UUIDIterator(context, uuids, Item.class, this); } @Override public Iterator findAllByCollection(Context context, Collection collection, Integer limit, Integer offset) throws SQLException { Query query = createQuery(context, - "select i from Item i join i.collections c WHERE :collection IN c ORDER BY i.id"); + "select i.id from Item i join i.collections c WHERE :collection IN c ORDER BY i.id"); query.setParameter("collection", collection); if (offset != null) { @@ -387,8 +413,9 @@ public Iterator findAllByCollection(Context context, Collection collection if (limit != null) { query.setMaxResults(limit); } - - return iterate(context, query, Item.class); + @SuppressWarnings("unchecked") + List uuids = query.getResultList(); + return new UUIDIterator(context, uuids, Item.class, this); } @Override @@ -424,9 +451,12 @@ public int countItems(Context context, List collections, boolean inc public Iterator findByLastModifiedSince(Context context, Date since) throws SQLException { Query query = createQuery(context, - "SELECT i FROM Item i WHERE last_modified > :last_modified ORDER BY id"); + "SELECT i.id FROM Item i WHERE last_modified > :last_modified ORDER BY id"); query.setParameter("last_modified", since, TemporalType.TIMESTAMP); - return iterate(context, query, Item.class); + @SuppressWarnings("unchecked") + List uuids = query.getResultList(); + return new UUIDIterator(context, uuids, Item.class, this); + } @Override @@ -462,22 +492,21 @@ public Iterator findByLikeAuthorityValue(Context context, String likeAuthority, Boolean inArchive) throws SQLException { String allItems = Objects.isNull(inArchive) ? "" : " item.inArchive=:in_archive AND "; Query query = createQuery(context, - "SELECT DISTINCT item FROM Item as item join item.metadata metadatavalue " + "SELECT DISTINCT item.id FROM Item as item join item.metadata metadatavalue " + "WHERE" + allItems + " metadatavalue.authority like :authority ORDER BY item.id"); if (Objects.nonNull(inArchive)) { query.setParameter("in_archive", inArchive); } query.setParameter("authority", likeAuthority); - return iterate(context, query, Item.class); + @SuppressWarnings("unchecked") + List uuids = query.getResultList(); + return new UUIDIterator(context, uuids, Item.class, this); } @Override public Iterator findByIds(Context context, List ids) throws SQLException { - Query query = createQuery(context, - "SELECT item " + "FROM Item as item WHERE item.id IN (:ids)"); - query.setParameter("ids", ids); - return iterate(context, query, Item.class); + return new UUIDIterator(context, ids, Item.class, this); } } diff --git a/dspace-api/src/main/java/org/dspace/content/dao/impl/MetadataValueDAOImpl.java b/dspace-api/src/main/java/org/dspace/content/dao/impl/MetadataValueDAOImpl.java index 2450db5bd19b..f37ced9ab7d4 100644 --- a/dspace-api/src/main/java/org/dspace/content/dao/impl/MetadataValueDAOImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/dao/impl/MetadataValueDAOImpl.java @@ -58,7 +58,7 @@ public Iterator findItemValuesByFieldAndValue(Context context, Query query = createQuery(context, queryString); query.setParameter("metadata_field_id", metadataField.getID()); query.setParameter("text_value", value); - return iterate(context, query, MetadataValue.class); + return iterate(query); } @Override @@ -69,7 +69,7 @@ public Iterator findByValueLike(Context context, String value) th Query query = createQuery(context, queryString); query.setParameter("searchString", value); - return iterate(context, query, MetadataValue.class); + return iterate(query); } @Override diff --git a/dspace-api/src/main/java/org/dspace/content/logic/InCollectionFilter.java b/dspace-api/src/main/java/org/dspace/content/logic/InCollectionFilter.java new file mode 100644 index 000000000000..c7697ce82fa1 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/content/logic/InCollectionFilter.java @@ -0,0 +1,124 @@ +/** + * The contents of this file are subject to the license and copyright + * detailed in the LICENSE and NOTICE files at the root of the source + * tree and available online at + * + * http://www.dspace.org/license/ + */ +package org.dspace.content.logic; + +import java.sql.SQLException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.dspace.content.Collection; +import org.dspace.content.DSpaceObject; +import org.dspace.content.Item; +import org.dspace.content.service.CollectionService; +import org.dspace.content.service.ItemService; +import org.dspace.core.Context; +import org.dspace.handle.service.HandleService; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * A condition that accepts a list of collection handles and returns true + * if the item belongs to any of them. + * + * @author Kim Shepherd + * @author Giuseppe Digilio + */ +public class InCollectionFilter implements Filter { + + @Autowired(required = true) + protected ItemService itemService; + @Autowired(required = true) + protected CollectionService collectionService; + @Autowired(required = true) + protected HandleService handleService; + + private String name; + private Map parameters = new HashMap<>(); + private static Logger log = LogManager.getLogger(InCollectionFilter.class); + + /** + * Get parameters set by spring configuration in item-filters.xml + * These could be any kind of map that the extending condition class needs for evaluation + * @return map of parameters + * @throws LogicalStatementException + */ + public Map getParameters() throws LogicalStatementException { + return this.parameters; + } + + /** + * Set parameters - used by Spring when creating beans from item-filters.xml + * These could be any kind of map that the extending condition class needs for evaluation + * @param parameters + * @throws LogicalStatementException + */ + @Autowired(required = true) + public void setParameters(Map parameters) throws LogicalStatementException { + this.parameters = parameters; + } + + /** + * Return true if item is in one of the specified collections + * Return false if not + * @param context DSpace context + * @param item Item to evaluate + * @return boolean result of evaluation + * @throws LogicalStatementException + */ + @Override + public Boolean getResult(Context context, Item item) throws LogicalStatementException { + + List collectionHandles = (List)getParameters().get("collections"); + List itemCollections = item.getCollections(); + for (Collection collection : itemCollections) { + if (collectionHandles.contains(collection.getHandle())) { + log.debug("item " + item.getHandle() + " is in collection " + + collection.getHandle() + ", returning true"); + return true; + } + } + + // Look for the parent object of the item. This is important as the item.getOwningCollection method + // may return null, even though the item itself does have a parent object, at the point of archival + try { + DSpaceObject parent = itemService.getParentObject(context, item); + if (parent != null) { + log.debug("Got parent DSO for item: " + parent.getID().toString()); + log.debug("Parent DSO handle: " + parent.getHandle()); + if (collectionHandles.contains(parent.getHandle())) { + log.debug("item " + item.getHandle() + " is in collection " + + parent.getHandle() + ", returning true"); + return true; + } + } else { + log.debug("Parent DSO is null..."); + } + } catch (SQLException e) { + log.error("Error obtaining parent DSO", e); + throw new LogicalStatementException(e); + } + + // If we reach this statement, the item did not appear in any of the collections from the parameters + log.debug("item " + item.getHandle() + " not found in the passed collection handle list"); + + return false; + } + + @Override + public void setBeanName(String name) { + log.debug("Initialize bean " + name); + this.name = name; + } + + @Override + public String getName() { + return name; + } +} diff --git a/dspace-api/src/main/java/org/dspace/core/AbstractHibernateDAO.java b/dspace-api/src/main/java/org/dspace/core/AbstractHibernateDAO.java index c217eed6ab92..c18f256d9564 100644 --- a/dspace-api/src/main/java/org/dspace/core/AbstractHibernateDAO.java +++ b/dspace-api/src/main/java/org/dspace/core/AbstractHibernateDAO.java @@ -26,6 +26,7 @@ import javax.persistence.criteria.Path; import javax.persistence.criteria.Root; +import com.google.common.collect.AbstractIterator; import org.apache.commons.collections.CollectionUtils; import org.hibernate.Session; @@ -341,14 +342,22 @@ public T uniqueResult(Query query) { * @param query * The query for which an Iterator will be made * @return The Iterator for the results of this query - * @throws SQLException */ - public Iterator iterate(Context ctx, Query query, Class entityType) throws SQLException { + public Iterator iterate(Query query) { @SuppressWarnings("unchecked") org.hibernate.query.Query hquery = query.unwrap(org.hibernate.query.Query.class); Stream stream = hquery.stream(); Iterator iter = stream.iterator(); - return new UUIDIterator(ctx, iter, entityType); + return new AbstractIterator () { + @Override + protected T computeNext() { + return iter.hasNext() ? iter.next() : endOfData(); + } + @Override + public void finalize() { + stream.close(); + } + }; } /** diff --git a/dspace-api/src/main/java/org/dspace/core/UUIDIterator.java b/dspace-api/src/main/java/org/dspace/core/UUIDIterator.java index f14ece677426..7cd2616ff6e7 100644 --- a/dspace-api/src/main/java/org/dspace/core/UUIDIterator.java +++ b/dspace-api/src/main/java/org/dspace/core/UUIDIterator.java @@ -8,20 +8,15 @@ package org.dspace.core; import java.sql.SQLException; -import java.util.Collection; import java.util.Iterator; -import java.util.LinkedList; import java.util.List; import java.util.UUID; import com.google.common.collect.AbstractIterator; import org.dspace.content.DSpaceObject; -import org.dspace.content.factory.ContentServiceFactory; -import org.dspace.content.service.DSpaceObjectService; +import org.dspace.core.exception.SQLRuntimeException; import org.springframework.beans.factory.annotation.Autowired; - - /** * Iterator implementation which allows to iterate over items and commit while * iterating. Using a list of UUID the iterator doesn't get invalidated after a @@ -30,77 +25,39 @@ * @author stefano.maffei at 4science.com * @param class type */ -public class UUIDIterator extends AbstractIterator { - - private Class entityTypeClass; +public class UUIDIterator extends AbstractIterator { + private Class clazz; - private List cachedUUIDs = new LinkedList<>(); + private Iterator iterator; - private Iterator uuidIterator; - - private Iterator iterator; - - @SuppressWarnings("rawtypes") @Autowired - private DSpaceObjectService dsoService; + private AbstractHibernateDSODAO dao; private Context ctx; - private boolean isSupportedUUIDIterator; - - public UUIDIterator(Context ctx, Iterator i, Class entityTypeClass) throws SQLException { - this.ctx = ctx; - - this.entityTypeClass = entityTypeClass; - isSupportedUUIDIterator = DSpaceObject.class.isAssignableFrom(this.entityTypeClass); - - if (isSupportedUUIDIterator) { - while (i.hasNext()) { - DSpaceObject dso = (DSpaceObject) i.next(); - if (dsoService == null) { - dsoService = ContentServiceFactory.getInstance().getDSpaceObjectService(dso); - } - cachedUUIDs.add(dso.getID()); - } - uuidIterator = cachedUUIDs.iterator(); - } else { - iterator = i; - } - - } - - public UUIDIterator(Context ctx, Collection collection, Class entityTypeClass) throws SQLException { + public UUIDIterator(Context ctx, List uuids, Class clazz, AbstractHibernateDSODAO dao) + throws SQLException { this.ctx = ctx; - - this.entityTypeClass = entityTypeClass; - isSupportedUUIDIterator = DSpaceObject.class.isAssignableFrom(this.entityTypeClass); - - if (isSupportedUUIDIterator) { - for (T obj : collection) { - DSpaceObject dso = (DSpaceObject) obj; - if (dsoService == null) { - dsoService = ContentServiceFactory.getInstance().getDSpaceObjectService(dso); - } - cachedUUIDs.add(dso.getID()); - } - uuidIterator = cachedUUIDs.iterator(); - } else { - throw new UnsupportedOperationException("Cannot generate iterator for this collection"); - } - + this.clazz = clazz; + this.dao = dao; + this.iterator = uuids.iterator(); } - @SuppressWarnings("unchecked") @Override protected T computeNext() { try { - if (isSupportedUUIDIterator) { - return uuidIterator.hasNext() ? (T) dsoService.find(ctx, uuidIterator.next()) : endOfData(); + if (iterator.hasNext()) { + T item = dao.findByID(ctx, clazz, iterator.next()); + if (item != null) { + return item; + } else { + return computeNext(); + } } else { - return iterator.hasNext() ? (T) iterator.next() : endOfData(); + return endOfData(); } } catch (SQLException e) { - throw new RuntimeException(e); + throw new SQLRuntimeException(e); } } diff --git a/dspace-api/src/main/java/org/dspace/curate/Curator.java b/dspace-api/src/main/java/org/dspace/curate/Curator.java index dc160c336d30..670c9bcbe43f 100644 --- a/dspace-api/src/main/java/org/dspace/curate/Curator.java +++ b/dspace-api/src/main/java/org/dspace/curate/Curator.java @@ -28,7 +28,6 @@ import org.dspace.content.service.ItemService; import org.dspace.core.Constants; import org.dspace.core.Context; -import org.dspace.core.UUIDIterator; import org.dspace.core.factory.CoreServiceFactory; import org.dspace.handle.factory.HandleServiceFactory; import org.dspace.handle.service.HandleService; @@ -464,10 +463,10 @@ protected boolean doSite(TaskRunner tr, Site site) throws IOException { //Then, perform this task for all Top-Level Communities in the Site // (this will recursively perform task for all objects in DSpace) - Iterator iterator = new UUIDIterator(ctx, communityService.findAllTop(ctx), - Community.class); - while (iterator.hasNext()) { - if (!doCommunity(tr, iterator.next())) { + for (Community subcomm : communityService.findAllTop(ctx)) { + // force a reload of the community in case a commit was performed + subcomm = ctx.reloadEntity(subcomm); + if (!doCommunity(tr, subcomm)) { return false; } } @@ -488,27 +487,26 @@ protected boolean doSite(TaskRunner tr, Site site) throws IOException { * @throws SQLException */ protected boolean doCommunity(TaskRunner tr, Community comm) throws IOException, SQLException { - UUIDIterator subComIter = new UUIDIterator(curationContext(), comm.getSubcommunities(), - Community.class); - UUIDIterator collectionsIter = new UUIDIterator(curationContext(), - comm.getCollections(), - Collection.class); - if (!tr.run(comm)) { return false; } - - while (subComIter.hasNext()) { - if (!doCommunity(tr, subComIter.next())) { + Context context = curationContext(); + // force a reload in case we are committing after each object + comm = context.reloadEntity(comm); + for (Community subcomm : comm.getSubcommunities()) { + if (!doCommunity(tr, subcomm)) { return false; } } - - while (collectionsIter.hasNext()) { - if (!doCollection(tr, collectionsIter.next())) { + // force a reload in case we are committing after each object + comm = context.reloadEntity(comm); + for (Collection coll : comm.getCollections()) { + context.reloadEntity(coll); + if (!doCollection(tr, coll)) { return false; } } + context.uncacheEntity(comm); return true; } @@ -535,6 +533,7 @@ protected boolean doCollection(TaskRunner tr, Collection coll) throws IOExceptio return false; } } + context.uncacheEntity(coll); } catch (SQLException sqlE) { throw new IOException(sqlE.getMessage(), sqlE); } diff --git a/dspace-api/src/main/java/org/dspace/layout/service/impl/CrisLayoutBoxServiceImpl.java b/dspace-api/src/main/java/org/dspace/layout/service/impl/CrisLayoutBoxServiceImpl.java index 269dd6601853..acd5d38c0b41 100644 --- a/dspace-api/src/main/java/org/dspace/layout/service/impl/CrisLayoutBoxServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/layout/service/impl/CrisLayoutBoxServiceImpl.java @@ -208,7 +208,13 @@ private boolean isMetadataFieldPresent(DSpaceObject item, MetadataField metadata } private boolean isBitstreamPresent(Context context, Item item, CrisLayoutFieldBitstream field) { - Map filters = Map.of(field.getMetadataField().toString('.'), field.getMetadataValue()); + + Map filters = Map.of(); + + if (field.getMetadataField() != null) { + filters = Map.of(field.getMetadataField().toString('.'), field.getMetadataValue()); + } + try { return bitstreamService.findShowableByItem(context, item.getID(), field.getBundle(), filters).size() > 0; } catch (SQLException e) { diff --git a/dspace-api/src/main/java/org/dspace/subscriptions/ContentGenerator.java b/dspace-api/src/main/java/org/dspace/subscriptions/ContentGenerator.java index 80e329ff63f4..65f1ae9dcf9b 100644 --- a/dspace-api/src/main/java/org/dspace/subscriptions/ContentGenerator.java +++ b/dspace-api/src/main/java/org/dspace/subscriptions/ContentGenerator.java @@ -85,7 +85,7 @@ private String generateBodyMail(String type, List subscription for (SubscriptionItem item : subscriptionItems) { out.write("\n".getBytes(UTF_8)); out.write("List of new content for the\n".getBytes(UTF_8)); - out.write((type + " " + item.getName() + " - " + item.getUrl() + "\n") + out.write((type + " \"" + item.getName() + "\" - " + item.getUrl() + "\n") .getBytes(UTF_8)); for (Entry entry : item.getItemUrlsByItemName().entrySet()) { diff --git a/dspace-api/src/main/java/org/dspace/subscriptions/StatisticsGenerator.java b/dspace-api/src/main/java/org/dspace/subscriptions/StatisticsGenerator.java index 842ff9aa0e8f..43ff6b71d4b5 100644 --- a/dspace-api/src/main/java/org/dspace/subscriptions/StatisticsGenerator.java +++ b/dspace-api/src/main/java/org/dspace/subscriptions/StatisticsGenerator.java @@ -51,8 +51,10 @@ public void notifyForSubscriptions(Context c, EPerson ePerson, List String name = configurationService.getProperty("dspace.name"); File attachment = generateExcel(crisMetricsList, c); email.addAttachment(attachment, "subscriptions.xlsx"); + email.setSubject(name + ": Statistics of records which you are subscribed"); email.setContent("intro", - "This automatic email is sent by " + name + " based on the subscribed statistics updates."); + "This automatic email is sent by " + name + " based on the subscribed statistics updates.\n\n" + + "See additional details in the file attached."); email.send(); } } catch (Exception ex) { diff --git a/dspace-api/src/test/data/dspaceFolder/config/item-submission.xml b/dspace-api/src/test/data/dspaceFolder/config/item-submission.xml index 64fbc551def6..d94d1145ee45 100644 --- a/dspace-api/src/test/data/dspaceFolder/config/item-submission.xml +++ b/dspace-api/src/test/data/dspaceFolder/config/item-submission.xml @@ -285,6 +285,17 @@ submission + + submit.progressbar.describe.green + org.dspace.app.rest.submit.step.DescribeStep + submission-form + + + submit.progressbar.describe.green + org.dspace.app.rest.submit.step.DescribeStep + submission-form + + @@ -457,6 +468,17 @@ + + + + + + + + + + + diff --git a/dspace-api/src/test/data/dspaceFolder/config/local.cfg b/dspace-api/src/test/data/dspaceFolder/config/local.cfg index 3618d405f7f2..2f3a64218dbf 100644 --- a/dspace-api/src/test/data/dspaceFolder/config/local.cfg +++ b/dspace-api/src/test/data/dspaceFolder/config/local.cfg @@ -223,4 +223,7 @@ orcid.synchronization-enabled = true # These settings ensure "dspace.object.owner" field are indexed by Authority Control choices.plugin.dspace.object.owner = EPersonAuthority choices.presentation.dspace.object.owner = suggest -authority.controlled.dspace.object.owner = true \ No newline at end of file +authority.controlled.dspace.object.owner = true + +# force the event system to work synchronously during test +system-event.thread.size = 0 \ No newline at end of file diff --git a/dspace-api/src/test/data/dspaceFolder/config/submission-forms.xml b/dspace-api/src/test/data/dspaceFolder/config/submission-forms.xml index fe47289e4315..15c3574951d9 100644 --- a/dspace-api/src/test/data/dspaceFolder/config/submission-forms.xml +++ b/dspace-api/src/test/data/dspaceFolder/config/submission-forms.xml @@ -2073,6 +2073,293 @@ it, please enter the types and the actual numbers or codes. +
+ + + dc + identifier + true + + qualdrop_value + If the item has any identification numbers or codes associated with + it, please enter the types and the actual numbers or codes. + + + + + + + dc + title + false + + onebox + Enter the main title of the item. + You must enter a main title for this item. + + + + + dc + title + alternative + true + + onebox + If the item has any alternative titles, please enter them here. + + + + + + dc + date + issued + false + + date + Please give the date of previous publication or public distribution. + You can leave out the day and/or month if they aren't + applicable. + + You must enter at least the year. + + + + + dc + contributor + author + true + + group + Enter the names of the authors of this item. + + + + + + dc + contributor + group + true + + onebox + The editors of this publication. + + + + + + dc + type + false + + onebox + Select the type(s) of content of the item. + You must select a publication type + publication-coar-types + + +
+
+ + + dc + contributor + author + false + + onebox + Enter the names of the authors of this item in the form Lastname, Firstname [i.e. Smith, Josh + or Smith, J]. + + You must enter at least the author. + + + + + oairecerif + author + affiliation + false + + onebox + Enter the affiliation of the author as stated on the publication. + + + +
+
+ + + dc + contributor + editor + false + + onebox + The editors of this publication. + You must enter at least the author. + + + + + oairecerif + editor + affiliation + false + + onebox + Enter the affiliation of the editor as stated on the publication. + + + +
+ +
+ + + dc + identifier + true + + qualdrop_value + If the item has any identification numbers or codes associated with + it, please enter the types and the actual numbers or codes. + + + + + + + dc + title + false + + onebox + Enter the main title of the item. + You must enter a main title for this item. + + + + + dc + title + alternative + true + + onebox + If the item has any alternative titles, please enter them here. + + + + + + dc + date + issued + false + + date + Please give the date of previous publication or public distribution. + You can leave out the day and/or month if they aren't + applicable. + + You must enter at least the year. + + + + + dc + contributor + author + true + + group + Enter the names of the authors of this item. + + + + + + dc + contributor + group + true + + onebox + The editors of this publication. + + + + + + dc + type + false + + onebox + Select the type(s) of content of the item. + You must select a publication type + publication-coar-types + + +
+
+ + + dc + contributor + author + false + + onebox + Enter the names of the authors of this item in the form Lastname, Firstname [i.e. Smith, Josh or Smith, + J]. + + You must enter at least the author. + + + + + oairecerif + author + affiliation + false + + onebox + Enter the affiliation of the author as stated on the publication. + + + +
+
+ + + dc + contributor + editor + false + + onebox + The editors of this publication. + You must enter at least the author. + + + + + oairecerif + editor + affiliation + false + + onebox + Enter the affiliation of the editor as stated on the publication. + + + +
diff --git a/dspace-api/src/test/java/org/dspace/app/mediafilter/MediaFilterIT.java b/dspace-api/src/test/java/org/dspace/app/mediafilter/MediaFilterIT.java new file mode 100644 index 000000000000..aef2476fdc45 --- /dev/null +++ b/dspace-api/src/test/java/org/dspace/app/mediafilter/MediaFilterIT.java @@ -0,0 +1,237 @@ +/** + * The contents of this file are subject to the license and copyright + * detailed in the LICENSE and NOTICE files at the root of the source + * tree and available online at + * + * http://www.dspace.org/license/ + */ +package org.dspace.app.mediafilter; + +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.io.InputStream; +import java.sql.SQLException; +import java.util.Iterator; +import java.util.List; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; +import org.dspace.AbstractIntegrationTestWithDatabase; +import org.dspace.authorize.AuthorizeException; +import org.dspace.builder.BitstreamBuilder; +import org.dspace.builder.CollectionBuilder; +import org.dspace.builder.CommunityBuilder; +import org.dspace.builder.ItemBuilder; +import org.dspace.content.Bitstream; +import org.dspace.content.Bundle; +import org.dspace.content.Collection; +import org.dspace.content.Community; +import org.dspace.content.DSpaceObject; +import org.dspace.content.Item; +import org.dspace.content.factory.ContentServiceFactory; +import org.dspace.content.service.BitstreamService; +import org.dspace.content.service.ItemService; +import org.junit.Before; +import org.junit.Test; + +/** + * Tests of {@link MediaFilterScript}. + * + * @author Andrea Bollini + */ +public class MediaFilterIT extends AbstractIntegrationTestWithDatabase { + + private ItemService itemService = ContentServiceFactory.getInstance().getItemService(); + private BitstreamService bitstreamService = ContentServiceFactory.getInstance().getBitstreamService(); + protected Community topComm1; + protected Community topComm2; + protected Community childComm1_1; + protected Community childComm1_2; + protected Collection col1_1; + protected Collection col1_2; + protected Collection col1_1_1; + protected Collection col1_1_2; + protected Collection col1_2_1; + protected Collection col1_2_2; + protected Collection col2_1; + protected Item item1_1_a; + protected Item item1_1_b; + protected Item item1_2_a; + protected Item item1_2_b; + protected Item item1_1_1_a; + protected Item item1_1_1_b; + protected Item item1_1_2_a; + protected Item item1_1_2_b; + protected Item item1_2_1_a; + protected Item item1_2_1_b; + protected Item item1_2_2_a; + protected Item item1_2_2_b; + protected Item item2_1_a; + protected Item item2_1_b; + + @Before + public void setup() throws IOException, SQLException, AuthorizeException { + context.turnOffAuthorisationSystem(); + topComm1 = CommunityBuilder.createCommunity(context).withName("Parent Community1").build(); + topComm2 = CommunityBuilder.createCommunity(context).withName("Parent Community2").build(); + childComm1_1 = CommunityBuilder.createCommunity(context).withName("Child Community1_1") + .addParentCommunity(context, topComm1).build(); + childComm1_2 = CommunityBuilder.createCommunity(context).withName("Child Community1_2") + .addParentCommunity(context, topComm1).build(); + col1_1 = CollectionBuilder.createCollection(context, topComm1).withName("Collection 1_1").build(); + col1_2 = CollectionBuilder.createCollection(context, topComm1).withName("Collection 1_2").build(); + col1_1_1 = CollectionBuilder.createCollection(context, childComm1_1).withName("Collection 1_1_1").build(); + col1_1_2 = CollectionBuilder.createCollection(context, childComm1_1).withName("Collection 1_1_2").build(); + col1_2_1 = CollectionBuilder.createCollection(context, childComm1_2).withName("Collection 1_1_1").build(); + col1_2_2 = CollectionBuilder.createCollection(context, childComm1_2).withName("Collection 1_2").build(); + col2_1 = CollectionBuilder.createCollection(context, topComm2).withName("Collection 2_1").build(); + + // Create two items in each collection, one with the test.csv file and one with the test.txt file + item1_1_a = ItemBuilder.createItem(context, col1_1).withTitle("Item 1_1_a").withIssueDate("2017-10-17").build(); + item1_1_b = ItemBuilder.createItem(context, col1_1).withTitle("Item 1_1_b").withIssueDate("2017-10-17").build(); + item1_1_1_a = ItemBuilder.createItem(context, col1_1_1).withTitle("Item 1_1_1_a").withIssueDate("2017-10-17") + .build(); + item1_1_1_b = ItemBuilder.createItem(context, col1_1_1).withTitle("Item 1_1_1_b").withIssueDate("2017-10-17") + .build(); + item1_1_2_a = ItemBuilder.createItem(context, col1_1_2).withTitle("Item 1_1_2_a").withIssueDate("2017-10-17") + .build(); + item1_1_2_b = ItemBuilder.createItem(context, col1_1_2).withTitle("Item 1_1_2_b").withIssueDate("2017-10-17") + .build(); + item1_2_a = ItemBuilder.createItem(context, col1_2).withTitle("Item 1_2_a").withIssueDate("2017-10-17").build(); + item1_2_b = ItemBuilder.createItem(context, col1_2).withTitle("Item 1_2_b").withIssueDate("2017-10-17").build(); + item1_2_1_a = ItemBuilder.createItem(context, col1_2_1).withTitle("Item 1_2_1_a").withIssueDate("2017-10-17") + .build(); + item1_2_1_b = ItemBuilder.createItem(context, col1_2_1).withTitle("Item 1_2_1_b").withIssueDate("2017-10-17") + .build(); + item1_2_2_a = ItemBuilder.createItem(context, col1_2_2).withTitle("Item 1_2_2_a").withIssueDate("2017-10-17") + .build(); + item1_2_2_b = ItemBuilder.createItem(context, col1_2_2).withTitle("Item 1_2_2_b").withIssueDate("2017-10-17") + .build(); + item2_1_a = ItemBuilder.createItem(context, col2_1).withTitle("Item 2_1_a").withIssueDate("2017-10-17").build(); + item2_1_b = ItemBuilder.createItem(context, col2_1).withTitle("Item 2_1_b").withIssueDate("2017-10-17").build(); + addBitstream(item1_1_a, "test.csv"); + addBitstream(item1_1_b, "test.txt"); + addBitstream(item1_2_a, "test.csv"); + addBitstream(item1_2_b, "test.txt"); + addBitstream(item1_1_1_a, "test.csv"); + addBitstream(item1_1_1_b, "test.txt"); + addBitstream(item1_1_2_a, "test.csv"); + addBitstream(item1_1_2_b, "test.txt"); + addBitstream(item1_2_1_a, "test.csv"); + addBitstream(item1_2_1_b, "test.txt"); + addBitstream(item1_2_2_a, "test.csv"); + addBitstream(item1_2_2_b, "test.txt"); + addBitstream(item2_1_a, "test.csv"); + addBitstream(item2_1_b, "test.txt"); + context.restoreAuthSystemState(); + } + + private void addBitstream(Item item, String filename) throws SQLException, AuthorizeException, IOException { + BitstreamBuilder.createBitstream(context, item, getClass().getResourceAsStream(filename)).withName(filename) + .guessFormat().build(); + } + + @Test + public void mediaFilterScriptAllItemsTest() throws Exception { + performMediaFilterScript(null); + Iterator items = itemService.findAll(context); + while (items.hasNext()) { + Item item = items.next(); + checkItemHasBeenProcessed(item); + } + } + + @Test + public void mediaFilterScriptIdentifiersTest() throws Exception { + // process the item 1_1_a and verify that no other items has been processed using the "closer" one + performMediaFilterScript(item1_1_a); + checkItemHasBeenProcessed(item1_1_a); + checkItemHasBeenNotProcessed(item1_1_b); + // process the collection 1_1_1 and verify that items in another collection has not been processed + performMediaFilterScript(col1_1_1); + checkItemHasBeenProcessed(item1_1_1_a); + checkItemHasBeenProcessed(item1_1_1_b); + checkItemHasBeenNotProcessed(item1_1_2_a); + checkItemHasBeenNotProcessed(item1_1_2_b); + // process a top community with only collections + performMediaFilterScript(topComm2); + checkItemHasBeenProcessed(item2_1_a); + checkItemHasBeenProcessed(item2_1_b); + // verify that the other items have not been processed yet + checkItemHasBeenNotProcessed(item1_1_b); + checkItemHasBeenNotProcessed(item1_2_a); + checkItemHasBeenNotProcessed(item1_2_b); + checkItemHasBeenNotProcessed(item1_1_2_a); + checkItemHasBeenNotProcessed(item1_1_2_b); + checkItemHasBeenNotProcessed(item1_2_1_a); + checkItemHasBeenNotProcessed(item1_2_1_b); + checkItemHasBeenNotProcessed(item1_2_2_a); + checkItemHasBeenNotProcessed(item1_2_2_b); + // process a more structured community and verify that all the items at all levels are processed + performMediaFilterScript(topComm1); + // items that were already processed should stay processed + checkItemHasBeenProcessed(item1_1_a); + checkItemHasBeenProcessed(item1_1_1_a); + checkItemHasBeenProcessed(item1_1_1_b); + // residual items should have been processed as well now + checkItemHasBeenProcessed(item1_1_b); + checkItemHasBeenProcessed(item1_2_a); + checkItemHasBeenProcessed(item1_2_b); + checkItemHasBeenProcessed(item1_1_2_a); + checkItemHasBeenProcessed(item1_1_2_b); + checkItemHasBeenProcessed(item1_2_1_a); + checkItemHasBeenProcessed(item1_2_1_b); + checkItemHasBeenProcessed(item1_2_2_a); + checkItemHasBeenProcessed(item1_2_2_b); + } + + private void checkItemHasBeenNotProcessed(Item item) throws IOException, SQLException, AuthorizeException { + List textBundles = item.getBundles("TEXT"); + assertTrue("The item " + item.getName() + " should NOT have the TEXT bundle", textBundles.size() == 0); + } + + private void checkItemHasBeenProcessed(Item item) throws IOException, SQLException, AuthorizeException { + String expectedFileName = StringUtils.endsWith(item.getName(), "_a") ? "test.csv.txt" : "test.txt.txt"; + String expectedContent = StringUtils.endsWith(item.getName(), "_a") ? "data3,3" : "quick brown fox"; + List textBundles = item.getBundles("TEXT"); + assertTrue("The item " + item.getName() + " has NOT the TEXT bundle", textBundles.size() == 1); + List bitstreams = textBundles.get(0).getBitstreams(); + assertTrue("The item " + item.getName() + " has NOT exactly 1 bitstream in the TEXT bundle", + bitstreams.size() == 1); + assertTrue("The text bistream in the " + item.getName() + " is NOT named properly [" + expectedFileName + "]", + StringUtils.equals(bitstreams.get(0).getName(), expectedFileName)); + assertTrue("The text bistream in the " + item.getName() + " doesn't contain the proper content [" + + expectedContent + "]", StringUtils.contains(getContent(bitstreams.get(0)), expectedContent)); + } + + private CharSequence getContent(Bitstream bitstream) throws IOException, SQLException, AuthorizeException { + try (InputStream input = bitstreamService.retrieve(context, bitstream)) { + return IOUtils.toString(input, "UTF-8"); + } + } + + private void performMediaFilterScript(DSpaceObject dso) throws Exception { + if (dso != null) { + runDSpaceScript("filter-media", "-i", dso.getHandle()); + } else { + runDSpaceScript("filter-media"); + } + // reload our items to see the changes + item1_1_a = context.reloadEntity(item1_1_a); + item1_1_b = context.reloadEntity(item1_1_b); + item1_2_a = context.reloadEntity(item1_2_a); + item1_2_b = context.reloadEntity(item1_2_b); + item1_1_1_a = context.reloadEntity(item1_1_1_a); + item1_1_1_b = context.reloadEntity(item1_1_1_b); + item1_1_2_a = context.reloadEntity(item1_1_2_a); + item1_1_2_b = context.reloadEntity(item1_1_2_b); + item1_2_1_a = context.reloadEntity(item1_2_1_a); + item1_2_1_b = context.reloadEntity(item1_2_1_b); + item1_2_2_a = context.reloadEntity(item1_2_2_a); + item1_2_2_b = context.reloadEntity(item1_2_2_b); + item2_1_a = context.reloadEntity(item2_1_a); + item2_1_b = context.reloadEntity(item2_1_b); + + } +} diff --git a/dspace-api/src/test/java/org/dspace/builder/BitstreamBuilder.java b/dspace-api/src/test/java/org/dspace/builder/BitstreamBuilder.java index a4775c4b8358..dbcf3a7972b7 100644 --- a/dspace-api/src/test/java/org/dspace/builder/BitstreamBuilder.java +++ b/dspace-api/src/test/java/org/dspace/builder/BitstreamBuilder.java @@ -20,6 +20,7 @@ import org.dspace.content.MetadataField; import org.dspace.content.MetadataValue; import org.dspace.content.factory.ContentServiceFactory; +import org.dspace.content.service.BitstreamFormatService; import org.dspace.content.service.DSpaceObjectService; import org.dspace.content.service.MetadataValueService; import org.dspace.core.Constants; @@ -167,6 +168,19 @@ public BitstreamBuilder withMimeType(String mimeType) throws SQLException { return this; } + /** + * Guess the bitstream format as during the submission via the + * {@link BitstreamFormatService#guessFormat(Context, Bitstream)} + * + * @return the BitstreamBuilder with the format set according to + * {@link BitstreamFormatService#guessFormat(Context, Bitstream)} + * @throws SQLException + */ + public BitstreamBuilder guessFormat() throws SQLException { + bitstream.setFormat(context, bitstreamFormatService.guessFormat(context, bitstream)); + return this; + } + public BitstreamBuilder withFormat(String format) throws SQLException { bitstreamService.addMetadata(context, bitstream, "dc", "format", null, null, format); diff --git a/dspace-api/src/test/java/org/dspace/layout/service/impl/CrisLayoutBoxServiceImplTest.java b/dspace-api/src/test/java/org/dspace/layout/service/impl/CrisLayoutBoxServiceImplTest.java index fd61aeb0a762..ce539cda67aa 100644 --- a/dspace-api/src/test/java/org/dspace/layout/service/impl/CrisLayoutBoxServiceImplTest.java +++ b/dspace-api/src/test/java/org/dspace/layout/service/impl/CrisLayoutBoxServiceImplTest.java @@ -291,6 +291,31 @@ public void testIiifBoxHasNoContentWithMetadataUndefined() { assertFalse(crisLayoutBoxService.hasContent(context, box, item)); } + @Test + public void testSingleMetadataboxBitstreamWithoutField() throws SQLException { + + CrisLayoutBox singleBitstreamBox = new CrisLayoutBox(); + singleBitstreamBox.setShortname("File"); + singleBitstreamBox.setType(null); + + Item item = item(); + Bitstream bitstream = mock(Bitstream.class); + + CrisLayoutFieldBitstream fieldBitstream = new CrisLayoutFieldBitstream(); + fieldBitstream.setBundle("ORIGINAL"); + fieldBitstream.setMetadataValue(null); + fieldBitstream.setMetadataField(null); + fieldBitstream.setRendering("attachment"); + + singleBitstreamBox.addLayoutField(fieldBitstream); + + when(bitstreamService.findShowableByItem(context, item.getID(), "ORIGINAL", Map.of())) + .thenReturn(List.of(bitstream)); + + assertThat(crisLayoutBoxService.hasContent(context, singleBitstreamBox, item), is(true)); + + } + private CrisLayoutBox crisLayoutMetadataBox(String shortname, MetadataField... metadataFields) { return crisLayoutBox(shortname, CrisLayoutBoxTypes.METADATA.name(), metadataFields); } diff --git a/dspace-api/src/test/java/org/dspace/orcid/service/OrcidProfileSectionFactoryServiceIT.java b/dspace-api/src/test/java/org/dspace/orcid/service/OrcidProfileSectionFactoryServiceIT.java index fa0b47133a7b..a28c968eb992 100644 --- a/dspace-api/src/test/java/org/dspace/orcid/service/OrcidProfileSectionFactoryServiceIT.java +++ b/dspace-api/src/test/java/org/dspace/orcid/service/OrcidProfileSectionFactoryServiceIT.java @@ -417,7 +417,6 @@ public void testDisambiguationFromOrgUnitHierarchyOnEmploymentCreationWithNoId() assertThat(organization.getDisambiguatedOrganization(), nullValue()); } - @Test public void testQualificationCreation() { context.turnOffAuthorisationSystem(); diff --git a/dspace-server-webapp/src/test/data/dspaceFolder/config/item-submission.xml b/dspace-server-webapp/src/test/data/dspaceFolder/config/item-submission.xml index eca9acf79fd7..78d4eb9171c4 100644 --- a/dspace-server-webapp/src/test/data/dspaceFolder/config/item-submission.xml +++ b/dspace-server-webapp/src/test/data/dspaceFolder/config/item-submission.xml @@ -44,7 +44,7 @@ - + @@ -106,14 +106,14 @@ submission - - submit.progressbar.CClicense org.dspace.app.rest.submit.step.CCLicenseStep @@ -121,7 +121,7 @@ @@ -130,9 +130,9 @@ diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ItemRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ItemRestRepositoryIT.java index 7e0edf08bac9..f3877445895a 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ItemRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ItemRestRepositoryIT.java @@ -411,10 +411,13 @@ public void findAllByIdTest() throws Exception { context.restoreAuthSystemState(); String token = getAuthToken(admin.getEmail(), password); - // We want to test that only and exclusively existing items are returned. + // We want to test that only and exclusively existing items are returned + // and each item is returned just one time getClient(token).perform(get("/api/core/items/search/findAllById") .param("id", publicItem1.getID().toString(), + publicItem1.getID().toString(), + UUID.randomUUID().toString(), publicItem2.getID().toString(), UUID.randomUUID().toString() )) diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/SubmissionDefinitionsControllerIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/SubmissionDefinitionsControllerIT.java index 9af95845d407..269de3aefb9d 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/SubmissionDefinitionsControllerIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/SubmissionDefinitionsControllerIT.java @@ -321,10 +321,10 @@ public void findAllPaginationTest() throws Exception { Matchers.containsString("page=1"), Matchers.containsString("size=1")))) .andExpect(jsonPath("$._links.last.href", Matchers.allOf( Matchers.containsString("/api/config/submissiondefinitions?"), - Matchers.containsString("page=16"), Matchers.containsString("size=1")))) + Matchers.containsString("page=18"), Matchers.containsString("size=1")))) .andExpect(jsonPath("$.page.size", is(1))) - .andExpect(jsonPath("$.page.totalElements", is(17))) - .andExpect(jsonPath("$.page.totalPages", is(17))) + .andExpect(jsonPath("$.page.totalElements", is(19))) + .andExpect(jsonPath("$.page.totalPages", is(19))) .andExpect(jsonPath("$.page.number", is(0))); getClient(tokenAdmin).perform(get("/api/config/submissiondefinitions") @@ -347,10 +347,10 @@ public void findAllPaginationTest() throws Exception { Matchers.containsString("page=1"), Matchers.containsString("size=1")))) .andExpect(jsonPath("$._links.last.href", Matchers.allOf( Matchers.containsString("/api/config/submissiondefinitions?"), - Matchers.containsString("page=16"), Matchers.containsString("size=1")))) + Matchers.containsString("page=18"), Matchers.containsString("size=1")))) .andExpect(jsonPath("$.page.size", is(1))) - .andExpect(jsonPath("$.page.totalElements", is(17))) - .andExpect(jsonPath("$.page.totalPages", is(17))) + .andExpect(jsonPath("$.page.totalElements", is(19))) + .andExpect(jsonPath("$.page.totalPages", is(19))) .andExpect(jsonPath("$.page.number", is(1))); } diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/SubmissionFormsControllerIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/SubmissionFormsControllerIT.java index 27a7ccb0985d..d817b573ff2b 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/SubmissionFormsControllerIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/SubmissionFormsControllerIT.java @@ -73,7 +73,7 @@ public void findAll() throws Exception { .andExpect(content().contentType(contentType)) //The configuration file for the test env includes PAGE_TOTAL_ELEMENTS forms .andExpect(jsonPath("$.page.size", is(20))) - .andExpect(jsonPath("$.page.totalElements", equalTo(34))) + .andExpect(jsonPath("$.page.totalElements", equalTo(40))) .andExpect(jsonPath("$.page.totalPages", equalTo(2))) .andExpect(jsonPath("$.page.number", is(0))) .andExpect( @@ -90,7 +90,7 @@ public void findAllWithNewlyCreatedAccountTest() throws Exception { .andExpect(status().isOk()) .andExpect(content().contentType(contentType)) .andExpect(jsonPath("$.page.size", is(20))) - .andExpect(jsonPath("$.page.totalElements", equalTo(34))) + .andExpect(jsonPath("$.page.totalElements", equalTo(40))) .andExpect(jsonPath("$.page.totalPages", equalTo(2))) .andExpect(jsonPath("$.page.number", is(0))) .andExpect(jsonPath("$._links.self.href", Matchers.startsWith(REST_SERVER_URL @@ -670,10 +670,10 @@ public void findAllPaginationTest() throws Exception { Matchers.containsString("page=1"), Matchers.containsString("size=2")))) .andExpect(jsonPath("$._links.last.href", Matchers.allOf( Matchers.containsString("/api/config/submissionforms?"), - Matchers.containsString("page=16"), Matchers.containsString("size=2")))) + Matchers.containsString("page=19"), Matchers.containsString("size=2")))) .andExpect(jsonPath("$.page.size", is(2))) - .andExpect(jsonPath("$.page.totalElements", equalTo(34))) - .andExpect(jsonPath("$.page.totalPages", equalTo(17))) + .andExpect(jsonPath("$.page.totalElements", equalTo(40))) + .andExpect(jsonPath("$.page.totalPages", equalTo(20))) .andExpect(jsonPath("$.page.number", is(0))); getClient(tokenAdmin).perform(get("/api/config/submissionforms") @@ -681,8 +681,8 @@ public void findAllPaginationTest() throws Exception { .param("page", "15")) .andExpect(status().isOk()) .andExpect(content().contentType(contentType)) - .andExpect(jsonPath("$._embedded.submissionforms[0].id", is("publication_indexing"))) - .andExpect(jsonPath("$._embedded.submissionforms[1].id", is("qualdroptest"))) + .andExpect(jsonPath("$._embedded.submissionforms[0].id", is("publication-dc-contributor-author"))) + .andExpect(jsonPath("$._embedded.submissionforms[1].id", is("publication-dc-contributor-editor"))) .andExpect(jsonPath("$._links.first.href", Matchers.allOf( Matchers.containsString("/api/config/submissionforms?"), Matchers.containsString("page=0"), Matchers.containsString("size=2")))) @@ -697,10 +697,10 @@ public void findAllPaginationTest() throws Exception { Matchers.containsString("page=16"), Matchers.containsString("size=2")))) .andExpect(jsonPath("$._links.last.href", Matchers.allOf( Matchers.containsString("/api/config/submissionforms?"), - Matchers.containsString("page=16"), Matchers.containsString("size=2")))) + Matchers.containsString("page=19"), Matchers.containsString("size=2")))) .andExpect(jsonPath("$.page.size", is(2))) - .andExpect(jsonPath("$.page.totalElements", equalTo(34))) - .andExpect(jsonPath("$.page.totalPages", equalTo(17))) + .andExpect(jsonPath("$.page.totalElements", equalTo(40))) + .andExpect(jsonPath("$.page.totalPages", equalTo(20))) .andExpect(jsonPath("$.page.number", is(15))); } @@ -744,10 +744,10 @@ public void visibilityTest() throws Exception { Matchers.containsString("page=4"), Matchers.containsString("size=2")))) .andExpect(jsonPath("$._links.last.href", Matchers.allOf( Matchers.containsString("/api/config/submissionforms?"), - Matchers.containsString("page=16"), Matchers.containsString("size=2")))) + Matchers.containsString("page=19"), Matchers.containsString("size=2")))) .andExpect(jsonPath("$.page.size", is(2))) - .andExpect(jsonPath("$.page.totalElements", equalTo(34))) - .andExpect(jsonPath("$.page.totalPages", equalTo(17))) + .andExpect(jsonPath("$.page.totalElements", equalTo(40))) + .andExpect(jsonPath("$.page.totalPages", equalTo(20))) .andExpect(jsonPath("$.page.number", is(4))); } } diff --git a/dspace-services/pom.xml b/dspace-services/pom.xml index 867ac1dc1a7e..39e2ccf36f38 100644 --- a/dspace-services/pom.xml +++ b/dspace-services/pom.xml @@ -154,5 +154,17 @@ ${spring-boot.version} + + com.google.guava + guava + + + + org.checkerframework + checker-qual + + + + diff --git a/dspace-services/src/main/java/org/dspace/services/events/SystemEventService.java b/dspace-services/src/main/java/org/dspace/services/events/SystemEventService.java index 5a4f118fcdc3..322b0dc8be20 100644 --- a/dspace-services/src/main/java/org/dspace/services/events/SystemEventService.java +++ b/dspace-services/src/main/java/org/dspace/services/events/SystemEventService.java @@ -15,6 +15,7 @@ import java.util.function.Supplier; import javax.annotation.PreDestroy; +import com.google.common.util.concurrent.MoreExecutors; import org.apache.commons.lang3.ArrayUtils; import org.dspace.services.ConfigurationService; import org.dspace.services.EventService; @@ -107,7 +108,11 @@ private void initExecutor() { } ConfigurationService configurationService = DSpaceServicesFactory.getInstance().getConfigurationService(); int threadSize = configurationService.getIntProperty("system-event.thread.size", DEFAULT_THREAD_SIZE); - this.executorService = Executors.newFixedThreadPool(threadSize); + if (threadSize == 0) { + this.executorService = MoreExecutors.newDirectExecutorService(); + } else { + this.executorService = Executors.newFixedThreadPool(threadSize); + } } /* (non-Javadoc) diff --git a/dspace/config/emails/subscriptions_content b/dspace/config/emails/subscriptions_content index e76c8c311a4f..9d2d255c06d3 100644 --- a/dspace/config/emails/subscriptions_content +++ b/dspace/config/emails/subscriptions_content @@ -4,6 +4,7 @@ ## {1} Collections updates block ## {2} Communities updates block ## {3} Entity updates block +#set($subject = "${config.get('dspace.name')}: Statistics of updates on subscribed items") This email is sent from ${config.get('dspace.name')} based on the chosen subscription preferences. You can manage your subscription preferences from ${params[0]} diff --git a/dspace/config/item-submission.xml b/dspace/config/item-submission.xml index d2d159775ad2..35c9ffdc8de4 100644 --- a/dspace/config/item-submission.xml +++ b/dspace/config/item-submission.xml @@ -1,6 +1,5 @@ - @@ -155,16 +154,6 @@ org.dspace.app.rest.submit.step.DescribeStep submission-form - - submit.progressbar.describe.green - org.dspace.app.rest.submit.step.DescribeStep - submission-form - - - submit.progressbar.describe.green - org.dspace.app.rest.submit.step.DescribeStep - submission-form - submit.progressbar.describe.owner org.dspace.app.rest.submit.step.DescribeStep @@ -182,8 +171,8 @@ cclicense - - submit.progressbar.accessCondition + + submit.progressbar.itemAccessConditions org.dspace.app.rest.submit.step.AccessConditionStep accessCondition @@ -202,12 +191,12 @@ submission - submit.progressbar.CustomUrlStep + submit.progressbar.custom-url org.dspace.app.rest.submit.step.CustomUrlStep custom-url - submit.progressbar.correction-step + submit.progressbar.correction org.dspace.app.rest.submit.step.CorrectionStep correction workflow @@ -222,6 +211,7 @@ + @@ -360,16 +350,5 @@ - - - - - - - - - - - diff --git a/dspace/config/modules/authority.cfg b/dspace/config/modules/authority.cfg index 10e4bc36fbb9..037cf01e5d79 100644 --- a/dspace/config/modules/authority.cfg +++ b/dspace/config/modules/authority.cfg @@ -136,9 +136,6 @@ choices.plugin.dc.contributor.author = AuthorAuthority choices.presentation.dc.contributor.author = suggest authority.controlled.dc.contributor.author = true -choices.plugin.green.override.dc.contributor.author = AuthorStrictMatchAuthority -choices.plugin.orange.override.dc.contributor.author = AuthorCoarseMatchAuthority - choices.plugin.oairecerif.author.affiliation = OrgUnitAuthority choices.presentation.oairecerif.author.affiliation = suggest authority.controlled.oairecerif.author.affiliation = true diff --git a/dspace/config/spring/api/item-filters.xml b/dspace/config/spring/api/item-filters.xml index d494d0c1c2ed..2514304151ae 100644 --- a/dspace/config/spring/api/item-filters.xml +++ b/dspace/config/spring/api/item-filters.xml @@ -408,4 +408,20 @@ + + + diff --git a/dspace/config/submission-forms.xml b/dspace/config/submission-forms.xml index c44ac175c1c7..45137c1ab15d 100644 --- a/dspace/config/submission-forms.xml +++ b/dspace/config/submission-forms.xml @@ -1,6 +1,5 @@ -
@@ -8,33 +7,33 @@ dc title - false onebox - + false You must enter a title for the file. + dc description - false textarea - + false + dc type - false dropdown - Personal picture, logo, main article, etc. + false + Personal picture, logo, main article, etc. @@ -55,11 +54,11 @@ dc contributor author - false onebox - Enter the names of the authors of this item in the form Lastname, Firstname [i.e. Smith, Josh or Smith, J]. + false You must enter at least the author. + Enter the names of the authors of this item in the form Lastname, Firstname [i.e. Smith, Josh or Smith, J]. @@ -67,11 +66,11 @@ oairecerif author affiliation - false onebox - Enter the affiliation of the author as stated on the publication. + false + Enter the affiliation of the author as stated on the publication.
@@ -81,11 +80,11 @@ dc contributor editor - false onebox - The editors of this publication. + false You must enter at least the author. + The editors of this publication. @@ -93,11 +92,11 @@ oairecerif editor affiliation - false onebox - Enter the affiliation of the editor as stated on the publication. + false + Enter the affiliation of the editor as stated on the publication. @@ -107,11 +106,11 @@ dc relation funding - false onebox - Enter the name of funding, if any, that has supported this publication + false You must enter at least the funding name. + Enter the name of funding, if any, that has supported this publication @@ -119,11 +118,11 @@ dc relation grantno - false onebox - If the funding is not found in the system please enter the funding identifier / grant no + false + If the funding is not found in the system please enter the funding identifier / grant no @@ -133,11 +132,11 @@ dc relation funding - false onebox - Enter the name of funding, if any, that has supported this product + false You must enter at least the funding name. + Enter the name of funding, if any, that has supported this product @@ -145,11 +144,37 @@ dc relation grantno - false onebox + false + If the funding is not found in the system please enter the funding identifier / grant no + + + +
+ + + dc + relation + publication + + onebox + false + You must enter at least the publication title / citation + + Enter the publication title or citation, if any, that uses this product + + + dc + relation + doi + + onebox + false + + If the publication is not found in the system please enter the DOI identifier
@@ -159,11 +184,11 @@ dc relation funding - false onebox - Enter the name of funding, if any, that has supported this patent + false You must enter at least the funding name. + Enter the name of funding, if any, that has supported this patent @@ -171,11 +196,11 @@ dc relation grantno - false onebox - If the funding is not found in the system please enter the funding identifier / grant no + false + If the funding is not found in the system please enter the funding identifier / grant no @@ -233,45 +258,45 @@ oairecerif affiliation role - false - onebox - + false + + oairecerif person affiliation - false - onebox - + false You must enter at least the organisation of your affiliation. + + oairecerif affiliation startDate - false - date - + false + + oairecerif affiliation endDate - false - date - + false + + @@ -280,45 +305,45 @@ crisrp qualification - false - onebox - + false You must enter the organisation + + crisrp qualification role - false - onebox - + false You must enter the qualification title. + + crisrp qualification start - false - date - + false + + crisrp qualification end - false - date - + false + + @@ -328,44 +353,44 @@ crisrp education role - false - onebox - + false You must enter the degree/title + + crisrp education - false - onebox - + false You must enter the organisation + + crisrp education start - false - date - + false + + crisrp education end - false - date - + false + + @@ -375,11 +400,11 @@ dc contributor author - false - name - Enter the names of the authors of this item in the form Lastname, Firstname [i.e. Smith, Josh or Smith, J]. + onebox + false You must enter at least the author. + Enter the names of the authors of this item in the form Lastname, Firstname [i.e. Smith, Josh or Smith, J]. @@ -387,11 +412,11 @@ oairecerif author affiliation - false onebox - Enter the affiliation of the author as stated on the publication. + false + Enter the affiliation of the author as stated on the publication. @@ -401,11 +426,11 @@ dc contributor author - false - name - Enter the names of the authors of this item in the form Lastname, Firstname [i.e. Smith, Josh or Smith, J]. + onebox + false You must enter at least the inventor. + Enter the names of the authors of this item in the form Lastname, Firstname [i.e. Smith, Josh or Smith, J]. @@ -413,11 +438,11 @@ oairecerif author affiliation - false onebox - Enter the affiliation of the author as stated on the publication. + false + Enter the affiliation of the author as stated on the publication. @@ -427,11 +452,11 @@ oairecerif identifier url - false onebox - + false You must enter at least the site url. + @@ -439,11 +464,11 @@ crisrp site title - false onebox - + false + @@ -453,55 +478,55 @@ dc identifier issn - false onebox - + false + dc title - false onebox - + false You must enter a main title for this item. + dc publisher - false onebox - + false + dc subject - true tag - + true + dc description - false textarea - + false + @@ -510,23 +535,23 @@ dc identifier - true qualdrop_value - If the item has any identification numbers or codes associated with - it, please enter the types and the actual numbers or codes. + true + If the item has any identification numbers or codes associated with +it, please enter the types and the actual numbers or codes. dc title - false onebox - Enter the main title of the item. + false You must enter a main title for this item. + Enter the main title of the item. @@ -534,11 +559,11 @@ dc title alternative - true onebox - If the item has any alternative titles, please enter them here. + true + If the item has any alternative titles, please enter them here. @@ -546,13 +571,13 @@ dc date issued - false date - Please give the date of previous publication or public distribution. - You can leave out the day and/or month if they aren't - applicable. + false You must enter at least the year. + Please give the date of previous publication or public distribution. + You can leave out the day and/or month if they aren't + applicable. @@ -560,11 +585,11 @@ dc contributor author - true group - Enter the names of the authors of this item. + true + Enter the names of the authors of this item. @@ -572,340 +597,61 @@ dc contributor editor - true group - The editors of this publication. + true + The editors of this publication. dc type - false onebox - Select the type(s) of content of the item. + false You must select a publication type + Select the type(s) of content of the item. publication-coar-types -
+ dc - identifier - true - - qualdrop_value - If the item has any identification numbers or codes associated with - it, please enter the types and the actual numbers or codes. + language + iso + + dropdown + false + Select the language of the main content of the item. If the language does not appear in the list, please select 'Other'. If the content does not really have a language (for example, if it is a dataset or an image) please select 'N/A'. dc - title - false - - onebox - Enter the main title of the item. - You must enter a main title for this item. + subject + + tag + true + + Enter appropriate subject keywords or phrases. - dc - title - alternative - true - + datacite + subject + fos + onebox - If the item has any alternative titles, please enter them here. + true - - - - - dc - date - issued - false - - date - Please give the date of previous publication or public distribution. - You can leave out the day and/or month if they aren't - applicable. - You must enter at least the year. - - - - - dc - contributor - author - true - - group - Enter the names of the authors of this item. - - - - - - dc - contributor - group - true - - onebox - The editors of this publication. - - - - - - dc - type - false - - onebox - Select the type(s) of content of the item. - You must select a publication type - publication-coar-types - - -
-
- - - dc - contributor - author - false - - onebox - Enter the names of the authors of this item in the form Lastname, Firstname [i.e. Smith, Josh or Smith, J]. - You must enter at least the author. - - - - - oairecerif - author - affiliation - false - - onebox - Enter the affiliation of the author as stated on the publication. - - - -
-
- - - dc - contributor - editor - false - - onebox - The editors of this publication. - You must enter at least the author. - - - - - oairecerif - editor - affiliation - false - - onebox - Enter the affiliation of the editor as stated on the publication. - - - -
-
- - - dc - identifier - true - - qualdrop_value - If the item has any identification numbers or codes associated with - it, please enter the types and the actual numbers or codes. - - - - - - dc - title - false - - onebox - Enter the main title of the item. - You must enter a main title for this item. - - - - - dc - title - alternative - true - - onebox - If the item has any alternative titles, please enter them here. - - - - - - dc - date - issued - false - - date - Please give the date of previous publication or public distribution. - You can leave out the day and/or month if they aren't - applicable. - You must enter at least the year. - - - - - dc - contributor - author - true - - group - Enter the names of the authors of this item. - - - - - - dc - contributor - group - true - - onebox - The editors of this publication. - - - - - - dc - type - false - - onebox - Select the type(s) of content of the item. - You must select a publication type - publication-coar-types - - -
-
- - - dc - contributor - author - false - - onebox - Enter the names of the authors of this item in the form Lastname, Firstname [i.e. Smith, Josh or Smith, J]. - You must enter at least the author. - - - - - oairecerif - author - affiliation - false - - onebox - Enter the affiliation of the author as stated on the publication. - - - -
-
- - - dc - contributor - editor - false - - onebox - The editors of this publication. - You must enter at least the author. - - - - - oairecerif - editor - affiliation - false - - onebox - Enter the affiliation of the editor as stated on the publication. - - - -
- -
- - - dc - language - iso - false - - dropdown - Select the language of the main content of the item. If the language does not appear in the list, please select 'Other'. If the content does not really have a language (for example, if it is a dataset or an image) please select 'N/A'. - - - - - - dc - subject - true - - tag - Enter appropriate subject keywords or phrases. - - - - - - datacite - subject - fos - true - - onebox - - - oecd + + oecd @@ -913,11 +659,11 @@ dc description abstract - false textarea - Enter the abstract of the item. + false + Enter the abstract of the item.
@@ -927,12 +673,12 @@ dc relation publication - false - publication-coar-types:c_3248,publication-coar-types:c_5794,publication-coar-types:c_6670 onebox - The publication where this publication is included. E.g. a book chapter lists here the book, a contribution to a conference lists here the conference proceeding. + false + The publication where this publication is included. E.g. a book chapter lists here the book, a contribution to a conference lists here the conference proceeding. + publication-coar-types:c_3248,publication-coar-types:c_5794,publication-coar-types:c_6670 @@ -940,12 +686,12 @@ dc relation isbn - false - publication-coar-types:c_3248,publication-coar-types:c_5794,publication-coar-types:c_6670 onebox - The ISBN of the book/report if it was not found in the system + false + The ISBN of the book/report if it was not found in the system + publication-coar-types:c_3248,publication-coar-types:c_5794,publication-coar-types:c_6670 @@ -953,12 +699,12 @@ dc relation doi - false - publication-coar-types:c_3248,publication-coar-types:c_5794,publication-coar-types:c_6670 onebox - The DOI of the book/report if it was not found in the system + false + The DOI of the book/report if it was not found in the system + publication-coar-types:c_3248,publication-coar-types:c_5794,publication-coar-types:c_6670 @@ -966,11 +712,11 @@ dc relation journal - false onebox - The journal or Serie where this publication has been published + false + The journal or Serie where this publication has been published @@ -978,11 +724,11 @@ dc relation ispartofseries - true series - Enter the series and number assigned to this item by your community. + true + Enter the series and number assigned to this item by your community. @@ -990,11 +736,11 @@ dc relation issn - false onebox - The journal or Serie ISSN if it was not found in the system + false + The journal or Serie ISSN if it was not found in the system @@ -1002,12 +748,12 @@ dc coverage publication - false - publication-coar-types:c_efa0,publication-coar-types:c_ba08 onebox - The publication object of the review + false + The publication object of the review + publication-coar-types:c_efa0,publication-coar-types:c_ba08 @@ -1015,12 +761,12 @@ dc coverage isbn - false - publication-coar-types:c_efa0,publication-coar-types:c_ba08 onebox - The ISBN of the reviewed item if it was not found in the system + false + The ISBN of the reviewed item if it was not found in the system + publication-coar-types:c_efa0,publication-coar-types:c_ba08 @@ -1028,24 +774,12 @@ dc coverage doi - false - publication-coar-types:c_efa0,publication-coar-types:c_ba08 onebox - The DOI of the reviewed item if it was not found in the system - - - - - - dc - description - sponsorship - true - - onebox - Enter the name of any sponsors. + false + The DOI of the reviewed item if it was not found in the system + publication-coar-types:c_efa0,publication-coar-types:c_ba08 @@ -1053,11 +787,11 @@ oaire citation volume - false onebox - If applicable, the volume of the publishing channel where this publication appeared + false + If applicable, the volume of the publishing channel where this publication appeared @@ -1065,11 +799,11 @@ oaire citation issue - false onebox - If applicable, the issue of the publishing channel where this publication appeared + false + If applicable, the issue of the publishing channel where this publication appeared @@ -1077,11 +811,11 @@ oaire citation startPage - false onebox - If applicable, the page where this publication starts + false + If applicable, the page where this publication starts @@ -1089,11 +823,11 @@ oaire citation endPage - false onebox - If applicable, the page where this publication ends + false + If applicable, the page where this publication ends @@ -1103,11 +837,11 @@ dc relation funding - true group - Acknowledge the funding received for this publication. + true + Acknowledge the funding received for this publication. @@ -1115,11 +849,11 @@ dc relation project - true onebox - Enter the name of project, if any, that has produced this publication. It is NOT necessary to list the projects connected with an acknowledge funding. + true + Enter the name of project, if any, that has produced this publication. It is NOT necessary to list the projects connected with an acknowledge funding. @@ -1127,11 +861,11 @@ dc relation conference - true onebox - Enter the name of the conference where the item has been presented, if any. + true + Enter the name of the conference where the item has been presented, if any. @@ -1139,11 +873,11 @@ dc relation product - true onebox - Link the item to one or more existent dataset in the repository used or described by the publication or, put here the dataset citation + true + Link the item to one or more existent dataset in the repository used or described by the publication or, put here the dataset citation @@ -1151,22 +885,22 @@ dc identifier citation - false onebox - Enter the standard citation for the previously issued instance of this item. + false + Enter the standard citation for the previously issued instance of this item. dc description - false textarea - Enter any other description or comments in this box. + false + Enter any other description or comments in this box. @@ -1174,11 +908,11 @@ dc description sponsorship - true onebox - Enter the name of any sponsors. + true + Enter the name of any sponsors. @@ -1187,23 +921,23 @@ dc identifier - true qualdrop_value - If the item has any identification numbers or codes associated with - it, please enter the types and the actual numbers or codes. + true + If the item has any identification numbers or codes associated with +it, please enter the types and the actual numbers or codes. dc title - false onebox - Enter the main title of the item. + false You must enter a main title for this item. + Enter the main title of the item. @@ -1211,11 +945,11 @@ dc title alternative - true onebox - If the item has any alternative titles, please enter them here. + true + If the item has any alternative titles, please enter them here. @@ -1223,11 +957,11 @@ dc date issued - false date - Please give the date of previous publication or public distribution. You can leave out the day and/or month if they aren't applicable. + false You must enter at least the year. + Please give the date of previous publication or public distribution. You can leave out the day and/or month if they aren't applicable. @@ -1235,11 +969,11 @@ dc description version - false onebox - If applicable, the version of the product + false + If applicable, the version of the product @@ -1247,22 +981,22 @@ dc contributor author - true group - Enter the names of the authors of this item. + true + Enter the names of the authors of this item. dc type - false onebox - Nothing to do here. Note for administrators, this metadata could be completely hide using template item + false + Nothing to do here. Note for administrators, this metadata could be completely hide using template item product-coar-types @@ -1273,22 +1007,22 @@ dc language iso - false dropdown - Select, if applicable, the language of the main content of the item. If the language does not appear in the list, please select 'Other'. If the content does not really have a language (for example, if it is a dataset or an image) please select 'N/A'. + false + Select, if applicable, the language of the main content of the item. If the language does not appear in the list, please select 'Other'. If the content does not really have a language (for example, if it is a dataset or an image) please select 'N/A'. dc subject - true tag - Enter appropriate subject keywords or phrases. + true + Enter appropriate subject keywords or phrases. @@ -1296,11 +1030,11 @@ datacite subject fos - true onebox - + true + oecd @@ -1309,11 +1043,22 @@ dc description abstract - false textarea + false + Enter the abstract of the item. + + + + + dc + description + + textarea + false + Enter any other relevant information about the dataset. @@ -1322,11 +1067,11 @@ dc publisher - true onebox - The publisher or publishers of this product + true + The publisher or publishers of this product @@ -1334,11 +1079,11 @@ dc relation ispartofseries - true series - Link to the research output of which this product is a part (e.g. a data set collection that contains it). + true + Link to the research output of which this product is a part (e.g. a data set collection that contains it). @@ -1346,11 +1091,11 @@ dc relation issn - false onebox - The journal or Serie ISSN if it was not found in the system + false + The journal or Serie ISSN if it was not found in the system @@ -1358,11 +1103,11 @@ dc relation funding - true group - Acknowledge the funding received for this product. + true + Acknowledge the funding received for this product. @@ -1370,11 +1115,11 @@ dc relation project - true onebox - Enter the name of project, if any, that has produced this product. It is NOT necessary to list the projects connected with an acknowledge funding. + true + Enter the name of project, if any, that has produced this product. It is NOT necessary to list the projects connected with an acknowledge funding. @@ -1382,11 +1127,11 @@ dc relation conference - false onebox - The event where this product was presented or that is recorded in the product. + false + The event where this product was presented or that is recorded in the product. @@ -1394,11 +1139,11 @@ dc relation equipment - true onebox - The equipment that generated this product + true + The equipment that generated this product @@ -1406,11 +1151,11 @@ dc relation references - true onebox - Result outputs that are referenced by this product + true + Result outputs that are referenced by this product @@ -1418,11 +1163,11 @@ dc relation publication - true - - onebox - Result outputs that use this product + + inline-group + true + Result outputs that use this product @@ -1432,11 +1177,11 @@ dc identifier patentno - false onebox - The patent number + false + The patent number @@ -1453,11 +1198,11 @@ dc identifier applicationnumber - false onebox - The application number + false + The application number dc @@ -1465,30 +1210,31 @@ issued date - Date on which the application was physically received at the Patent Authority. Also named Filling Date + false + Date on which the application was physically received at the Patent Authority. Also named Filling Date. dc title - false onebox - The title of the patent + false You must specify a title for the patent + The title of the patent dcterms dateAccepted - false date - Date on which the application has been granted by the Patent Office. + false + Date on which the application has been granted by the Patent Office. @@ -1497,8 +1243,9 @@ dateSubmitted date - Date of making available to the public by printing or similar process of a patent document on which grant has taken place on or before the said date + false + Date of making available to the public by printing or similar process of a patent document on which grant has taken place on or before the said date. @@ -1506,44 +1253,44 @@ dc contributor author - true group - The inventor: The actual devisor of an invention that is the subject of a patent. + true + The inventor: The actual devisor of an invention that is the subject of a patent. dcterms rightsHolder - true onebox - The holders of this patent + true + The holders of this patent dc publisher - true onebox - The issuer of the patent: the patent office + true + The issuer of the patent: the patent office dc type - false onebox - Select the type of content of the patent. + false You must select a patent type + Select the type of content of the patent. patent-coar-types @@ -1566,22 +1313,35 @@ dc language iso - false dropdown - Select the country and its language. + false + Select the country and its language. dc subject - true onebox + true + Enter appropriate subject keywords or phrases. + + + + + datacite + subject + fos + + onebox + true + + oecd @@ -1589,11 +1349,11 @@ dc description abstract - false textarea - Enter the description of the patent. + false + Enter the description of the patent. @@ -1603,11 +1363,11 @@ dc relation funding - true group - Acknowledge the funding received for this patent. + true + Acknowledge the funding received for this patent. @@ -1615,11 +1375,11 @@ dc relation project - true onebox - Enter the name of project, if any, that has produced this patent. It is NOT necessary to list the projects connected with an acknowledge funding. + true + Enter the name of project, if any, that has produced this patent. It is NOT necessary to list the projects connected with an acknowledge funding. @@ -1627,11 +1387,11 @@ dc relation patent - true onebox - Patents that precede (i.e., have priority over) this patent + true + Patents that precede (i.e., have priority over) this patent @@ -1639,11 +1399,11 @@ dc relation references - true onebox - Result outputs that are referenced by this patent + true + Result outputs that are referenced by this patent @@ -1652,22 +1412,22 @@ dc title - false name - + false You must enter least at the Surname. + crisrp name - false name - + false + @@ -1675,11 +1435,11 @@ crisrp name translated - false name - + false + @@ -1687,84 +1447,84 @@ crisrp name variant - true name - + true + person givenName - false onebox - + false + person familyName - false onebox - + false + person birthDate - false date - + false + oairecerif person gender - false dropdown - + false + person jobTitle - false onebox - + false + person affiliation name - false onebox - + false + crisrp workgroup - true onebox - + true + @@ -1772,33 +1532,33 @@ oairecerif identifier url - true group - + true + person email - false onebox - + false + dc subject - true tag - + true + @@ -1806,11 +1566,11 @@ datacite subject fos - true onebox - + true + oecd @@ -1819,11 +1579,11 @@ person identifier orcid - false onebox - Settable by connecting the entity with ORCID + false + Settable by connecting the entity with ORCID all @@ -1832,11 +1592,11 @@ person identifier scopus-author-id - true onebox - + true + @@ -1844,11 +1604,11 @@ person identifier rid - true onebox - + true + @@ -1856,11 +1616,11 @@ oairecerif person affiliation - true inline-group - + true + @@ -1868,55 +1628,55 @@ dc description abstract - false textarea - + false + crisrp education - true inline-group - + true + crisrp country - false dropdown - + false + crisrp qualification - true inline-group - + true + person knowsLanguage - true dropdown - + true + @@ -1924,11 +1684,11 @@ cris policy eperson - false onebox - + false + @@ -1936,11 +1696,11 @@ cris policy group - false onebox - + false + @@ -1949,77 +1709,77 @@ dc title - false onebox - + false You must enter the oganization name. + oairecerif acronym - false onebox - + false + organization parentOrganization - false onebox - + false + crisou director - false onebox - + false + organization foundingDate - false date - + false + crisou boards - true onebox - + true + organization identifier - true qualdrop_value - + true + @@ -2027,11 +1787,11 @@ oairecerif identifier url - true onebox - + true + @@ -2039,11 +1799,11 @@ dc description abstract - false textarea - + false + @@ -2051,32 +1811,32 @@ organization address addressLocality - false onebox - + false + organization address addressCountry - false dropdown - + false + dc type - false dropdown - + false You must specify the organisation type + @@ -2085,88 +1845,88 @@ dc title - false onebox - + false You must enter the project name. + oairecerif acronym - false onebox - + false + crispj coordinator - true onebox - + true + oairecerif internalid - false onebox - + false + crispj partnerou - true onebox - + true + crispj investigator - false onebox - + false You must enter the project coordinator. + crispj openaireid - false onebox - + false + crispj organization - true onebox - + true + @@ -2174,32 +1934,32 @@ oairecerif identifier url - true onebox - + true + oairecerif oamandate - false dropdown - + false + oairecerif oamandate url - false onebox - + false + @@ -2207,21 +1967,21 @@ oairecerif project startDate - false date - + false + oairecerif project endDate - false date - + false + @@ -2229,22 +1989,22 @@ oairecerif project status - false onebox - + false + dc type - false dropdown - + false + @@ -2252,33 +2012,33 @@ dc description abstract - false textarea - + false + crispj coinvestigators - true onebox - + true + dc subject - true tag - + true + @@ -2286,11 +2046,11 @@ datacite subject fos - true onebox - + true + oecd @@ -2299,11 +2059,11 @@ dc relation equipment - true onebox - + true + @@ -2312,31 +2072,31 @@ dc title - false onebox - + false You must enter the equipment name. + oairecerif acronym - false onebox - + false + oairecerif internalid - false onebox - + false + @@ -2344,31 +2104,31 @@ dc relation project - false onebox - + false + oairecerif funder - false onebox - + false + oairecerif fundingParent - false onebox - Link this funding with its upper level if applicable + false + Link this funding with its upper level if applicable @@ -2376,53 +2136,65 @@ crisfund award url - false onebox - + false The url preferably on the funder website of the award notice + + + + + + crisfund + award + uri + + onebox + false + The Award URI + oairecerif oamandate - false dropdown - + false + oairecerif oamandate url - false onebox - + false + oairecerif amount - false onebox - + false + oairecerif amount currency - false dropdown - + false + @@ -2430,97 +2202,97 @@ oairecerif funding identifier - false onebox - + false + oairecerif funding startDate - false date - + false + oairecerif funding endDate - false date - + false + dc type - false dropdown - + false + dc description - false textarea - + false + crisfund investigators - true onebox - + true + crisfund coinvestigators - true onebox - + true + crisfund leadorganizations - true onebox - + true + crisfund leadcoorganizations - true onebox - + true + @@ -2529,66 +2301,66 @@ dc title - false onebox - + false You must enter the equipment name. + oairecerif acronym - false onebox - + false + oairecerif internalid - false onebox - + false + crisequipment ownerou - false onebox - + false + crisequipment ownerrp - false onebox - + false + dc description - false textarea - + false + @@ -2597,33 +2369,33 @@ dc title - false onebox - + false + oairecerif acronym - false onebox - + false + dc type - false dropdown - + false + @@ -2631,21 +2403,21 @@ oairecerif event startDate - false date - + false + oairecerif event endDate - false date - + false + @@ -2653,11 +2425,11 @@ oairecerif event place - false onebox - + false + @@ -2665,77 +2437,77 @@ oairecerif event country - false dropdown - + false + crisevent organizerou - true onebox - + true + crisevent organizerpj - true onebox - + true + crisevent sponsorou - true onebox - + true + crisevent sponsorpj - true onebox - + true + crisevent partnerou - true onebox - + true + crisevent partnerpj - true onebox - + true + @@ -2743,22 +2515,22 @@ dc description abstract - false textarea - + false + dc subject - true tag - + true + @@ -2767,11 +2539,11 @@ cris owner - false onebox - + false + @@ -2932,6 +2704,10 @@ + + N/A + + English (United States) en_US @@ -3330,6 +3106,10 @@ + + Unspecified + + Academic Institute Academic Institute @@ -3384,6 +3164,10 @@ + + Unspecified + + basic research basic research @@ -3398,6 +3182,10 @@ + + Unspecified + + Gift Gift @@ -3420,6 +3208,10 @@ + + Unspecified + + Conference Conference @@ -3430,6 +3222,10 @@ + + Unspecified + + Afghanistan AF @@ -4428,6 +4224,10 @@ + + Unspecified + + Logo logo