mirror of
https://github.com/DSpace/DSpace.git
synced 2025-10-07 10:04:21 +00:00
Re-assemble pull request
This commit is contained in:
@@ -937,6 +937,13 @@ public class ItemServiceImpl extends DSpaceObjectServiceImpl<Item> implements It
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Item> findByMetadataQuery(Context context, List<List<MetadataField>> listFieldList, List<String> query_op, List<String> query_val, List<UUID> collectionUuids, String regexClause, int offset, int limit)
|
||||
throws SQLException, AuthorizeException, IOException
|
||||
{
|
||||
return itemDAO.findByMetadataQuery(context, listFieldList, query_op, query_val, collectionUuids, regexClause, offset, limit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DSpaceObject getAdminObject(Context context, Item item, int action) throws SQLException {
|
||||
DSpaceObject adminObject = null;
|
||||
|
@@ -87,6 +87,11 @@ public class MetadataFieldServiceImpl implements MetadataFieldService {
|
||||
return metadataFieldDAO.findByElement(context, metadataSchemaName, element, qualifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MetadataField> findFieldsByElementNameUnqualified(Context context, String metadataSchemaName, String element) throws SQLException {
|
||||
return metadataFieldDAO.findFieldsByElementNameUnqualified(context, metadataSchemaName, element);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MetadataField> findAll(Context context) throws SQLException
|
||||
{
|
||||
|
@@ -16,6 +16,8 @@ import org.dspace.eperson.EPerson;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Database Access Object interface class for the Item object.
|
||||
@@ -46,6 +48,8 @@ public interface ItemDAO extends DSpaceObjectLegacySupportDAO<Item>
|
||||
|
||||
public Iterator<Item> findByMetadataField(Context context, MetadataField metadataField, String value, boolean inArchive) throws SQLException;
|
||||
|
||||
public Iterator<Item> findByMetadataQuery(Context context, List<List<MetadataField>> listFieldList, List<String> query_op, List<String> query_val, List<UUID> collectionUuids, String regexClause, int offset, int limit) throws SQLException;
|
||||
|
||||
public Iterator<Item> findByAuthorityValue(Context context, MetadataField metadataField, String authority, boolean inArchive) throws SQLException;
|
||||
|
||||
public Iterator<Item> findArchivedByCollection(Context context, Collection collection, Integer limit, Integer offset) throws SQLException;
|
||||
|
@@ -33,6 +33,9 @@ public interface MetadataFieldDAO extends GenericDAO<MetadataField> {
|
||||
public MetadataField findByElement(Context context, String metadataSchema, String element, String qualifier)
|
||||
throws SQLException;
|
||||
|
||||
public List<MetadataField> findFieldsByElementNameUnqualified(Context context, String metadataSchema, String element)
|
||||
throws SQLException;
|
||||
|
||||
public List<MetadataField> findAllInSchema(Context context, MetadataSchema metadataSchema)
|
||||
throws SQLException;
|
||||
|
||||
|
@@ -7,19 +7,33 @@
|
||||
*/
|
||||
package org.dspace.content.dao.impl;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.dspace.content.Collection;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.content.MetadataField;
|
||||
import org.dspace.content.MetadataSchema;
|
||||
import org.dspace.content.MetadataValue;
|
||||
import org.dspace.content.dao.ItemDAO;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.core.AbstractHibernateDSODAO;
|
||||
import org.dspace.eperson.EPerson;
|
||||
import org.hibernate.Criteria;
|
||||
import org.hibernate.Query;
|
||||
import org.hibernate.criterion.DetachedCriteria;
|
||||
import org.hibernate.criterion.Projections;
|
||||
import org.hibernate.criterion.Property;
|
||||
import org.hibernate.criterion.Restrictions;
|
||||
import org.hibernate.criterion.Subqueries;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Hibernate implementation of the Database Access Object interface class for the Item object.
|
||||
@@ -29,6 +43,7 @@ import java.util.Iterator;
|
||||
* @author kevinvandevelde at atmire.com
|
||||
*/
|
||||
public class ItemDAOImpl extends AbstractHibernateDSODAO<Item> implements ItemDAO {
|
||||
private static final Logger log = Logger.getLogger(ItemDAOImpl.class);
|
||||
@Override
|
||||
public Iterator<Item> findAll(Context context, boolean archived) throws SQLException {
|
||||
Query query = createQuery(context, "FROM Item WHERE inArchive= :in_archive");
|
||||
@@ -113,6 +128,73 @@ public class ItemDAOImpl extends AbstractHibernateDSODAO<Item> implements ItemDA
|
||||
return iterate(query);
|
||||
}
|
||||
|
||||
enum OP {equals,not_equals,like,not_like,contains,doesnt_contain,exists,doesnt_exist,matches,doesnt_match;}
|
||||
|
||||
@Override
|
||||
public Iterator<Item> findByMetadataQuery(Context context, List<List<MetadataField>> listFieldList, List<String> query_op, List<String> query_val, List<UUID> collectionUuids, String regexClause, int offset, int limit) throws SQLException {
|
||||
Criteria criteria = createCriteria(context, Item.class, "item");
|
||||
criteria.setFirstResult(offset);
|
||||
criteria.setMaxResults(limit);
|
||||
|
||||
if (!collectionUuids.isEmpty()){
|
||||
DetachedCriteria dcollCriteria = DetachedCriteria.forClass(Collection.class, "coll");
|
||||
dcollCriteria.setProjection(Projections.property("coll.id"));
|
||||
dcollCriteria.add(Restrictions.eqProperty("coll.id", "item.owningCollection"));
|
||||
dcollCriteria.add(Restrictions.in("coll.id", collectionUuids));
|
||||
criteria.add(Subqueries.exists(dcollCriteria));
|
||||
}
|
||||
|
||||
int index = Math.min(listFieldList.size(), Math.min(query_op.size(), query_val.size()));
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
for(int i=0; i<index; i++) {
|
||||
OP op = OP.valueOf(query_op.get(i));
|
||||
if (op == null) {
|
||||
log.warn("Skipping Invalid Operator: " + query_op.get(i));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (op == OP.matches || op == OP.doesnt_match) {
|
||||
if (regexClause.isEmpty()) {
|
||||
log.warn("Skipping Unsupported Regex Operator: " + query_op.get(i));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
DetachedCriteria subcriteria = DetachedCriteria.forClass(MetadataValue.class,"mv");
|
||||
subcriteria.add(Property.forName("mv.dSpaceObject").eqProperty("item.id"));
|
||||
subcriteria.setProjection(Projections.property("mv.dSpaceObject"));
|
||||
|
||||
if (!listFieldList.get(i).isEmpty()) {
|
||||
subcriteria.add(Restrictions.in("metadataField", listFieldList.get(i)));
|
||||
}
|
||||
|
||||
sb.append(op.name() + " ");
|
||||
if (op == OP.equals || op == OP.not_equals){
|
||||
subcriteria.add(Property.forName("mv.value").eq(query_val.get(i)));
|
||||
sb.append(query_val.get(i));
|
||||
} else if (op == OP.like || op == OP.not_like){
|
||||
subcriteria.add(Property.forName("mv.value").like(query_val.get(i)));
|
||||
sb.append(query_val.get(i));
|
||||
} else if (op == OP.contains || op == OP.doesnt_contain){
|
||||
subcriteria.add(Property.forName("mv.value").like("%"+query_val.get(i)+"%"));
|
||||
sb.append(query_val.get(i));
|
||||
} else if (op == OP.matches || op == OP.doesnt_match) {
|
||||
subcriteria.add(Restrictions.sqlRestriction(regexClause, query_val.get(i), StandardBasicTypes.STRING));
|
||||
sb.append(query_val.get(i));
|
||||
}
|
||||
|
||||
if (op == OP.exists || op == OP.equals || op == OP.like || op == OP.contains || op == OP.matches) {
|
||||
criteria.add(Subqueries.exists(subcriteria));
|
||||
} else {
|
||||
criteria.add(Subqueries.notExists(subcriteria));
|
||||
}
|
||||
}
|
||||
log.debug(String.format("Running custom query with %d filters", index));
|
||||
|
||||
return list(criteria).iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Item> 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 WHERE item.inArchive=:in_archive AND metadatavalue.metadataField = :metadata_field AND metadatavalue.authority = :authority");
|
||||
|
@@ -70,6 +70,20 @@ public class MetadataFieldDAOImpl extends AbstractHibernateDAO<MetadataField> im
|
||||
return singleResult(criteria);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MetadataField> findFieldsByElementNameUnqualified(Context context, String metadataSchema, String element) throws SQLException
|
||||
{
|
||||
Criteria criteria = createCriteria(context, MetadataField.class);
|
||||
criteria.createAlias("metadataSchema", "s").add(
|
||||
Restrictions.and(
|
||||
Restrictions.eq("s.name", metadataSchema),
|
||||
Restrictions.eq("element", element)
|
||||
)
|
||||
);
|
||||
return list(criteria);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<MetadataField> findAllInSchema(Context context, MetadataSchema metadataSchema) throws SQLException {
|
||||
// Get all the metadatafieldregistry rows
|
||||
|
@@ -20,6 +20,7 @@ import java.sql.SQLException;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Service interface class for the Item object.
|
||||
@@ -403,6 +404,8 @@ public interface ItemService extends DSpaceObjectService<Item>, DSpaceObjectLega
|
||||
String schema, String element, String qualifier, String value)
|
||||
throws SQLException, AuthorizeException, IOException;
|
||||
|
||||
public Iterator<Item> findByMetadataQuery(Context context, List<List<MetadataField>> listFieldList, List<String> query_op, List<String> query_val, List<UUID> collectionUuids, String regexClause, int offset, int limit)
|
||||
throws SQLException, AuthorizeException, IOException;
|
||||
|
||||
/**
|
||||
* Find all the items in the archive with a given authority key value
|
||||
|
@@ -67,6 +67,9 @@ public interface MetadataFieldService {
|
||||
public MetadataField findByElement(Context context, String metadataSchemaName, String element, String qualifier)
|
||||
throws SQLException;
|
||||
|
||||
public List<MetadataField> findFieldsByElementNameUnqualified(Context context, String metadataSchema, String element)
|
||||
throws SQLException;
|
||||
|
||||
/**
|
||||
* Retrieve all metadata field types from the registry
|
||||
*
|
||||
|
@@ -30,6 +30,18 @@
|
||||
<filteringDeploymentDescriptors>true</filteringDeploymentDescriptors>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>com.mycila</groupId>
|
||||
<artifactId>license-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<!--Exclude license check for XMLUI files which don't need it-->
|
||||
<excludes>
|
||||
<exclude>**/static/reports/spin.js</exclude>
|
||||
<exclude>**/static/reports/README.md</exclude>
|
||||
<exclude>**/*.xsd</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
@@ -0,0 +1,193 @@
|
||||
/**
|
||||
* 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.rest;
|
||||
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.dspace.authorize.factory.AuthorizeServiceFactory;
|
||||
import org.dspace.authorize.service.AuthorizeService;
|
||||
import org.dspace.content.factory.ContentServiceFactory;
|
||||
import org.dspace.content.service.CollectionService;
|
||||
import org.dspace.core.ConfigurationManager;
|
||||
import org.dspace.rest.common.FilteredCollection;
|
||||
import org.dspace.rest.exceptions.ContextException;
|
||||
import org.dspace.usage.UsageEvent;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.ws.rs.*;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.HttpHeaders;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/*
|
||||
* This class provides the items within a collection evaluated against a set of Item Filters.
|
||||
*
|
||||
* @author Terry Brady, Georgetown University
|
||||
*/
|
||||
@Path("/filtered-collections")
|
||||
public class FilteredCollectionsResource extends Resource {
|
||||
protected AuthorizeService authorizeService = AuthorizeServiceFactory.getInstance().getAuthorizeService();
|
||||
protected CollectionService collectionService = ContentServiceFactory.getInstance().getCollectionService();
|
||||
private static Logger log = Logger.getLogger(FilteredCollectionsResource.class);
|
||||
|
||||
/**
|
||||
* Return array of all collections in DSpace. You can add more properties
|
||||
* through expand parameter.
|
||||
*
|
||||
* @param expand
|
||||
* String in which is what you want to add to returned instance
|
||||
* of collection. Options are: "all", "parentCommunityList",
|
||||
* "parentCommunity", "topCommunity", "items", "license" and "logo".
|
||||
* If you want to use multiple options, it must be separated by commas.
|
||||
* @param limit
|
||||
* Limit value for items in list in collection. Default value is
|
||||
* 100.
|
||||
* @param offset
|
||||
* Offset of start index in list of items of collection. Default
|
||||
* value is 0.
|
||||
* @param headers
|
||||
* If you want to access to collections under logged user into
|
||||
* context. In headers must be set header "rest-dspace-token"
|
||||
* with passed token from login method.
|
||||
* @return Return array of collection, on which has logged user permission
|
||||
* to view.
|
||||
* @throws WebApplicationException
|
||||
* It is thrown when was problem with database reading
|
||||
* (SQLException) or problem with creating
|
||||
* context(ContextException).
|
||||
*/
|
||||
@GET
|
||||
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
|
||||
public org.dspace.rest.common.FilteredCollection[] getCollections(@QueryParam("expand") String expand,
|
||||
@QueryParam("limit") @DefaultValue("100") Integer limit, @QueryParam("offset") @DefaultValue("0") Integer offset,
|
||||
@QueryParam("userIP") String user_ip, @QueryParam("userAgent") String user_agent,
|
||||
@QueryParam("filters") @DefaultValue("is_item") String filters,
|
||||
@QueryParam("xforwardedfor") String xforwardedfor, @Context HttpHeaders headers, @Context HttpServletRequest request)
|
||||
throws WebApplicationException
|
||||
{
|
||||
|
||||
log.info("Reading all filtered collections.(offset=" + offset + ",limit=" + limit + ")");
|
||||
org.dspace.core.Context context = null;
|
||||
List<FilteredCollection> collections = new ArrayList<FilteredCollection>();
|
||||
|
||||
try
|
||||
{
|
||||
context = createContext(getUser(headers));
|
||||
if (ConfigurationManager.getBooleanProperty("rest", "rest-reporting-authenticate", true) == false) {
|
||||
context.turnOffAuthorisationSystem();
|
||||
}
|
||||
|
||||
if (!((limit != null) && (limit >= 0) && (offset != null) && (offset >= 0)))
|
||||
{
|
||||
log.warn("Paging was badly set.");
|
||||
limit = 100;
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
List<org.dspace.content.Collection> dspaceCollections = collectionService.findAll(context, limit, offset);
|
||||
for(org.dspace.content.Collection dspaceCollection : dspaceCollections)
|
||||
{
|
||||
if (authorizeService.authorizeActionBoolean(context, dspaceCollection, org.dspace.core.Constants.READ))
|
||||
{
|
||||
FilteredCollection collection = new org.dspace.rest.common.FilteredCollection(dspaceCollection, filters, expand, context, limit,
|
||||
offset);
|
||||
collections.add(collection);
|
||||
writeStats(dspaceCollection, UsageEvent.Action.VIEW, user_ip, user_agent,
|
||||
xforwardedfor, headers, request, context);
|
||||
}
|
||||
}
|
||||
context.complete();
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
processException("Something went wrong while reading collections from database. Message: " + e, context);
|
||||
}
|
||||
catch (ContextException e)
|
||||
{
|
||||
processException("Something went wrong while reading collections, ContextError. Message: " + e.getMessage(), context);
|
||||
}
|
||||
finally
|
||||
{
|
||||
processFinally(context);
|
||||
}
|
||||
|
||||
log.trace("All collections were successfully read.");
|
||||
return collections.toArray(new org.dspace.rest.common.FilteredCollection[0]);
|
||||
}
|
||||
/**
|
||||
* Return instance of collection with passed id. You can add more properties
|
||||
* through expand parameter.
|
||||
*
|
||||
* @param collectionId
|
||||
* Id of collection in DSpace.
|
||||
* @param expand
|
||||
* String in which is what you want to add to returned instance
|
||||
* of collection. Options are: "all", "parentCommunityList",
|
||||
* "parentCommunity", "topCommunity", "items", "license" and "logo".
|
||||
* If you want to use multiple options, it must be separated by commas.
|
||||
* @param limit
|
||||
* Limit value for items in list in collection. Default value is
|
||||
* 100.
|
||||
* @param offset
|
||||
* Offset of start index in list of items of collection. Default
|
||||
* value is 0.
|
||||
* @param filters
|
||||
* Comma separated list of Item Filters to use to evaluate against
|
||||
* the items in a collection
|
||||
* @param headers
|
||||
* If you want to access to collection under logged user into
|
||||
* context. In headers must be set header "rest-dspace-token"
|
||||
* with passed token from login method.
|
||||
* @return Return instance of collection. It can also return status code
|
||||
* NOT_FOUND(404) if id of collection is incorrect or status code
|
||||
* UNATHORIZED(401) if user has no permission to read collection.
|
||||
* @throws WebApplicationException
|
||||
* It is thrown when was problem with database reading
|
||||
* (SQLException) or problem with creating
|
||||
* context(ContextException). It is thrown by NOT_FOUND and
|
||||
* UNATHORIZED status codes, too.
|
||||
*/
|
||||
@GET
|
||||
@Path("/{collection_id}")
|
||||
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
|
||||
public org.dspace.rest.common.FilteredCollection getCollection(@PathParam("collection_id") String collection_id, @QueryParam("expand") String expand,
|
||||
@QueryParam("limit") @DefaultValue("1000") Integer limit, @QueryParam("offset") @DefaultValue("0") Integer offset,
|
||||
@QueryParam("userIP") String user_ip, @QueryParam("userAgent") String user_agent, @QueryParam("xforwarderfor") String xforwarderfor,
|
||||
@QueryParam("filters") @DefaultValue("is_item") String filters,
|
||||
@Context HttpHeaders headers, @Context HttpServletRequest request) {
|
||||
org.dspace.core.Context context = null;
|
||||
FilteredCollection retColl = new org.dspace.rest.common.FilteredCollection();
|
||||
try {
|
||||
context = createContext(getUser(headers));
|
||||
if (!ConfigurationManager.getBooleanProperty("rest", "rest-reporting-authenticate", false)) {
|
||||
context.turnOffAuthorisationSystem();
|
||||
}
|
||||
|
||||
org.dspace.content.Collection collection = collectionService.findByIdOrLegacyId(context, collection_id);
|
||||
if(authorizeService.authorizeActionBoolean(context, collection, org.dspace.core.Constants.READ)) {
|
||||
writeStats(collection, UsageEvent.Action.VIEW, user_ip, user_agent, xforwarderfor, headers, request, context);
|
||||
retColl = new org.dspace.rest.common.FilteredCollection(collection, filters, expand, context, limit, offset);
|
||||
} else {
|
||||
throw new WebApplicationException(Response.Status.UNAUTHORIZED);
|
||||
}
|
||||
context.complete();
|
||||
} catch (SQLException e) {
|
||||
processException(e.getMessage(), context);
|
||||
} catch (ContextException e) {
|
||||
processException(String.format("Could not read collection %d. %s", collection_id, e.getMessage()), context);
|
||||
} finally {
|
||||
processFinally(context);
|
||||
}
|
||||
return retColl;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,202 @@
|
||||
/**
|
||||
* 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.rest;
|
||||
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.content.MetadataField;
|
||||
import org.dspace.content.factory.ContentServiceFactory;
|
||||
import org.dspace.content.service.CollectionService;
|
||||
import org.dspace.content.service.ItemService;
|
||||
import org.dspace.content.service.MetadataFieldService;
|
||||
import org.dspace.content.service.MetadataSchemaService;
|
||||
import org.dspace.content.service.SiteService;
|
||||
import org.dspace.core.ConfigurationManager;
|
||||
import org.dspace.rest.exceptions.ContextException;
|
||||
import org.dspace.rest.common.ItemFilter;
|
||||
import org.dspace.rest.common.ItemFilterQuery;
|
||||
import org.dspace.rest.filter.ItemFilterSet;
|
||||
import org.dspace.usage.UsageEvent;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.ws.rs.*;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.HttpHeaders;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/*
|
||||
* This class retrieves items by a constructed metadata query evaluated against a set of Item Filters.
|
||||
*
|
||||
* @author Terry Brady, Georgetown University
|
||||
*/
|
||||
@Path("/filtered-items")
|
||||
public class FilteredItemsResource extends Resource {
|
||||
protected ItemService itemService = ContentServiceFactory.getInstance().getItemService();
|
||||
protected MetadataFieldService metadataFieldService = ContentServiceFactory.getInstance().getMetadataFieldService();
|
||||
protected MetadataSchemaService metadataSchemaService = ContentServiceFactory.getInstance().getMetadataSchemaService();
|
||||
protected CollectionService collectionService = ContentServiceFactory.getInstance().getCollectionService();
|
||||
protected SiteService siteService = ContentServiceFactory.getInstance().getSiteService();
|
||||
|
||||
private static Logger log = Logger.getLogger(FilteredItemsResource.class);
|
||||
|
||||
/**
|
||||
* Return instance of collection with passed id. You can add more properties
|
||||
* through expand parameter.
|
||||
*
|
||||
* @param expand
|
||||
* String in which is what you want to add to returned instance
|
||||
* of collection. Options are: "all", "parentCommunityList",
|
||||
* "parentCommunity", "items", "license" and "logo". If you want
|
||||
* to use multiple options, it must be separated by commas.
|
||||
* @param limit
|
||||
* Limit value for items in list in collection. Default value is
|
||||
* 100.
|
||||
* @param offset
|
||||
* Offset of start index in list of items of collection. Default
|
||||
* value is 0.
|
||||
* @param filters
|
||||
* Comma separated list of Item Filters to use to evaluate against
|
||||
* the items in a collection
|
||||
* @param query_field
|
||||
* List of metadata fields to evaluate in a metadata query.
|
||||
* Each list value is used in conjunction with a query_op and query_field.
|
||||
* @param query_op
|
||||
* List of metadata operators to use in a metadata query.
|
||||
* Each list value is used in conjunction with a query_field and query_field.
|
||||
* @param query_val
|
||||
* List of metadata values to evaluate in a metadata query.
|
||||
* Each list value is used in conjunction with a query_value and query_op.
|
||||
* @param collSel
|
||||
* List of collections to query.
|
||||
* @param headers
|
||||
* If you want to access to collection under logged user into
|
||||
* context. In headers must be set header "rest-dspace-token"
|
||||
* with passed token from login method.
|
||||
* @return Return instance of collection. It can also return status code
|
||||
* NOT_FOUND(404) if id of collection is incorrect or status code
|
||||
* UNATHORIZED(401) if user has no permission to read collection.
|
||||
* @throws WebApplicationException
|
||||
* It is thrown when was problem with database reading
|
||||
* (SQLException) or problem with creating
|
||||
* context(ContextException). It is thrown by NOT_FOUND and
|
||||
* UNATHORIZED status codes, too.
|
||||
*/
|
||||
@GET
|
||||
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
|
||||
public org.dspace.rest.common.ItemFilter getItemQuery(@QueryParam("expand") String expand,
|
||||
@QueryParam("limit") @DefaultValue("100") Integer limit, @QueryParam("offset") @DefaultValue("0") Integer offset,
|
||||
@QueryParam("userIP") String user_ip, @QueryParam("userAgent") String user_agent, @QueryParam("xforwarderfor") String xforwarderfor,
|
||||
@QueryParam("filters") @DefaultValue("is_item,all_filters") String filters,
|
||||
@QueryParam("query_field[]") @DefaultValue("dc.title") List<String> query_field,
|
||||
@QueryParam("query_op[]") @DefaultValue("exists") List<String> query_op,
|
||||
@QueryParam("query_val[]") @DefaultValue("") List<String> query_val,
|
||||
@QueryParam("collSel[]") @DefaultValue("") List<String> collSel,
|
||||
@Context HttpHeaders headers, @Context HttpServletRequest request) {
|
||||
org.dspace.core.Context context = null;
|
||||
ItemFilterSet itemFilterSet = new ItemFilterSet(filters, true);
|
||||
ItemFilter result = itemFilterSet.getAllFiltersFilter();
|
||||
try {
|
||||
context = createContext(getUser(headers));
|
||||
if (ConfigurationManager.getBooleanProperty("rest", "rest-reporting-authenticate", true) == false) {
|
||||
context.turnOffAuthorisationSystem();
|
||||
}
|
||||
|
||||
int index = Math.min(query_field.size(), Math.min(query_op.size(), query_val.size()));
|
||||
List<ItemFilterQuery> itemFilterQueries = new ArrayList<ItemFilterQuery>();
|
||||
for(int i=0; i<index; i++){
|
||||
itemFilterQueries.add(new ItemFilterQuery(query_field.get(i), query_op.get(i), query_val.get(i)));
|
||||
}
|
||||
|
||||
String regexClause = ConfigurationManager.getProperty("rest", "rest-regex-clause");
|
||||
if (regexClause == null) {
|
||||
regexClause = "";
|
||||
}
|
||||
|
||||
List<UUID> uuids = getUuidsFromStrings(collSel);
|
||||
List<List<MetadataField>> listFieldList = getMetadataFieldsList(context, query_field);
|
||||
|
||||
Iterator<org.dspace.content.Item> childItems = itemService.findByMetadataQuery(context, listFieldList, query_op, query_val, uuids, regexClause, offset, limit);
|
||||
|
||||
int count = itemFilterSet.processSaveItems(context, childItems, true, expand);
|
||||
writeStats(siteService.findSite(context), UsageEvent.Action.VIEW, user_ip, user_agent, xforwarderfor, headers, request, context);
|
||||
result.annotateQuery(query_field, query_op, query_val);
|
||||
result.setUnfilteredItemCount(count);
|
||||
context.complete();
|
||||
} catch (IOException e) {
|
||||
processException(e.getMessage(), context);
|
||||
} catch (SQLException e) {
|
||||
processException(e.getMessage(), context);
|
||||
} catch (AuthorizeException e) {
|
||||
processException(e.getMessage(), context);
|
||||
} catch (ContextException e) {
|
||||
processException("Unauthorized filtered item query. " + e.getMessage(), context);
|
||||
} finally {
|
||||
processFinally(context);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<List<MetadataField>> getMetadataFieldsList(org.dspace.core.Context context, List<String> query_field) throws SQLException {
|
||||
List<List<MetadataField>> listFieldList = new ArrayList<List<MetadataField>>();
|
||||
for(String s: query_field) {
|
||||
ArrayList<MetadataField> fields = new ArrayList<MetadataField>();
|
||||
listFieldList.add(fields);
|
||||
if (s.equals("*")) {
|
||||
continue;
|
||||
}
|
||||
String schema = "";
|
||||
String element = "";
|
||||
String qualifier = null;
|
||||
String[] parts = s.split("\\.");
|
||||
if (parts.length>0) {
|
||||
schema = parts[0];
|
||||
}
|
||||
if (parts.length>1) {
|
||||
element = parts[1];
|
||||
}
|
||||
if (parts.length>2) {
|
||||
qualifier = parts[2];
|
||||
}
|
||||
|
||||
if (Item.ANY.equals(qualifier)) {
|
||||
for(MetadataField mf: metadataFieldService.findFieldsByElementNameUnqualified(context, schema, element)){
|
||||
fields.add(mf);
|
||||
}
|
||||
} else {
|
||||
MetadataField mf = metadataFieldService.findByElement(context, schema, element, qualifier);
|
||||
if (mf != null) {
|
||||
fields.add(mf);
|
||||
}
|
||||
}
|
||||
}
|
||||
return listFieldList;
|
||||
}
|
||||
|
||||
private List<UUID> getUuidsFromStrings(List<String> collSel) {
|
||||
List<UUID> uuids = new ArrayList<UUID>();
|
||||
for(String s: collSel) {
|
||||
try {
|
||||
uuids.add(UUID.fromString(s));
|
||||
} catch (IllegalArgumentException e) {
|
||||
log.warn("Invalid collection UUID: " + s);
|
||||
}
|
||||
}
|
||||
return uuids;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* 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.rest;
|
||||
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.WebApplicationException;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.HttpHeaders;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.dspace.rest.common.ItemFilter;
|
||||
|
||||
/**
|
||||
* Class which provides read methods over the metadata registry.
|
||||
*
|
||||
* @author Terry Brady, Georgetown University
|
||||
*
|
||||
*/
|
||||
@Path("/filters")
|
||||
public class FiltersResource
|
||||
{
|
||||
private static Logger log = Logger.getLogger(FiltersResource.class);
|
||||
|
||||
/**
|
||||
* Return all Use Case Item Filters in DSpace.
|
||||
*
|
||||
* @return Return array of metadata schemas.
|
||||
* @throws WebApplicationException
|
||||
* It can be caused by creating context or while was problem
|
||||
* with reading community from database(SQLException).
|
||||
*/
|
||||
@GET
|
||||
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
|
||||
public ItemFilter[] getFilters(@QueryParam("userIP") String user_ip, @QueryParam("userAgent") String user_agent,
|
||||
@QueryParam("xforwarderfor") String xforwarderfor, @Context HttpHeaders headers, @Context HttpServletRequest request)
|
||||
throws WebApplicationException
|
||||
{
|
||||
|
||||
log.info("Reading all Item Filters.");
|
||||
return ItemFilter.getItemFilters(ItemFilter.ALL, false).toArray(new ItemFilter[0]);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,751 @@
|
||||
/**
|
||||
* 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.rest;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.DELETE;
|
||||
import javax.ws.rs.DefaultValue;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.PUT;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.WebApplicationException;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.HttpHeaders;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.authorize.factory.AuthorizeServiceFactory;
|
||||
import org.dspace.authorize.service.AuthorizeService;
|
||||
import org.dspace.content.NonUniqueMetadataException;
|
||||
import org.dspace.content.factory.ContentServiceFactory;
|
||||
import org.dspace.content.service.MetadataFieldService;
|
||||
import org.dspace.content.service.MetadataSchemaService;
|
||||
import org.dspace.content.service.SiteService;
|
||||
import org.dspace.rest.common.MetadataSchema;
|
||||
import org.dspace.rest.exceptions.ContextException;
|
||||
import org.dspace.usage.UsageEvent;
|
||||
import org.dspace.rest.common.MetadataField;
|
||||
|
||||
/**
|
||||
* Class which provides read methods over the metadata registry.
|
||||
*
|
||||
* @author Terry Brady, Georgetown University
|
||||
*
|
||||
* GET /registries/schema - Return the list of schemas in the registry
|
||||
* GET /registries/schema/{schema_prefix} - Returns the specified schema
|
||||
* GET /registries/schema/{schema_prefix}/metadata-fields/{element} - Returns the metadata field within a schema with an unqualified element name
|
||||
* GET /registries/schema/{schema_prefix}/metadata-fields/{element}/{qualifier} - Returns the metadata field within a schema with a qualified element name
|
||||
* POST /registries/schema/ - Add a schema to the schema registry
|
||||
* POST /registries/schema/{schema_prefix}/metadata-fields - Add a metadata field to the specified schema
|
||||
* GET /registries/metadata-fields/{field_id} - Return the specified metadata field
|
||||
* PUT /registries/metadata-fields/{field_id} - Update the specified metadata field
|
||||
* DELETE /registries/metadata-fields/{field_id} - Delete the specified metadata field from the metadata field registry
|
||||
* DELETE /registries/schema/{schema_id} - Delete the specified schema from the schema registry
|
||||
*
|
||||
* Note: intentionally not providing since there is no date to update other than the namespace
|
||||
* PUT /registries/schema/{schema_id}
|
||||
*/
|
||||
@Path("/registries")
|
||||
public class MetadataRegistryResource extends Resource
|
||||
{
|
||||
protected AuthorizeService authorizeService = AuthorizeServiceFactory.getInstance().getAuthorizeService();
|
||||
protected MetadataFieldService metadataFieldService = ContentServiceFactory.getInstance().getMetadataFieldService();
|
||||
protected MetadataSchemaService metadataSchemaService = ContentServiceFactory.getInstance().getMetadataSchemaService();
|
||||
protected SiteService siteService = ContentServiceFactory.getInstance().getSiteService();
|
||||
private static Logger log = Logger.getLogger(MetadataRegistryResource.class);
|
||||
|
||||
/**
|
||||
* Return all metadata registry items in DSpace.
|
||||
*
|
||||
* @param expand
|
||||
* String in which is what you want to add to returned instance
|
||||
* of metadata schema. Options are: "all", "fields". Default value "fields".
|
||||
* @return Return array of metadata schemas.
|
||||
* @throws WebApplicationException
|
||||
* It can be caused by creating context or while was problem
|
||||
* with reading schema from database(SQLException).
|
||||
*/
|
||||
@GET
|
||||
@Path("/schema")
|
||||
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
|
||||
public MetadataSchema[] getSchemas(@QueryParam("expand") @DefaultValue("fields") String expand,
|
||||
@QueryParam("userIP") String user_ip, @QueryParam("userAgent") String user_agent,
|
||||
@QueryParam("xforwarderfor") String xforwarderfor, @Context HttpHeaders headers, @Context HttpServletRequest request)
|
||||
throws WebApplicationException
|
||||
{
|
||||
|
||||
log.info("Reading all metadata schemas.");
|
||||
org.dspace.core.Context context = null;
|
||||
ArrayList<MetadataSchema> metadataSchemas = null;
|
||||
|
||||
try
|
||||
{
|
||||
context = createContext(getUser(headers));
|
||||
|
||||
List<org.dspace.content.MetadataSchema> schemas = metadataSchemaService.findAll(context);
|
||||
metadataSchemas = new ArrayList<MetadataSchema>();
|
||||
for(org.dspace.content.MetadataSchema schema: schemas) {
|
||||
metadataSchemas.add(new MetadataSchema(schema, expand, context));
|
||||
}
|
||||
|
||||
context.complete();
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
processException("Could not read metadata schemas, SQLException. Message:" + e, context);
|
||||
}
|
||||
catch (ContextException e)
|
||||
{
|
||||
processException("Could not read metadata schemas, ContextException. Message:" + e.getMessage(), context);
|
||||
}
|
||||
finally
|
||||
{
|
||||
processFinally(context);
|
||||
}
|
||||
|
||||
log.trace("All metadata schemas successfully read.");
|
||||
return metadataSchemas.toArray(new MetadataSchema[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns metadata schema with basic properties. If you want more, use expand
|
||||
* parameter or method for metadata fields.
|
||||
*
|
||||
* @param schemaPrefix
|
||||
* Prefix for schema in DSpace.
|
||||
* @param expand
|
||||
* String in which is what you want to add to returned instance
|
||||
* of metadata schema. Options are: "all", "fields". Default value "fields".
|
||||
* @param headers
|
||||
* If you want to access to metadata schema under logged user into
|
||||
* context. In headers must be set header "rest-dspace-token"
|
||||
* with passed token from login method.
|
||||
* @return Return instance of org.dspace.rest.common.MetadataSchema.
|
||||
* @throws WebApplicationException
|
||||
* It is throw when was problem with creating context or problem
|
||||
* with database reading. Also if id/prefix of schema is incorrect
|
||||
* or logged user into context has no permission to read.
|
||||
*/
|
||||
@GET
|
||||
@Path("/schema/{schema_prefix}")
|
||||
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
|
||||
public MetadataSchema getSchema(@PathParam("schema_prefix") String schemaPrefix, @QueryParam("expand") @DefaultValue("fields") String expand,
|
||||
@QueryParam("userIP") String user_ip, @QueryParam("userAgent") String user_agent,
|
||||
@QueryParam("xforwarderfor") String xforwarderfor, @Context HttpHeaders headers, @Context HttpServletRequest request)
|
||||
throws WebApplicationException
|
||||
{
|
||||
|
||||
log.info("Reading metadata schemas.");
|
||||
org.dspace.core.Context context = null;
|
||||
MetadataSchema metadataSchema = null;
|
||||
|
||||
try
|
||||
{
|
||||
context = createContext(getUser(headers));
|
||||
|
||||
org.dspace.content.MetadataSchema schema = metadataSchemaService.find(context, schemaPrefix);
|
||||
metadataSchema = new MetadataSchema(schema, expand, context);
|
||||
if (schema == null) {
|
||||
processException(String.format("Schema not found for index %s", schemaPrefix), context);
|
||||
}
|
||||
|
||||
context.complete();
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
processException("Could not read metadata schema, SQLException. Message:" + e, context);
|
||||
}
|
||||
catch (ContextException e)
|
||||
{
|
||||
processException("Could not read metadata schema, ContextException. Message:" + e.getMessage(), context);
|
||||
}
|
||||
finally
|
||||
{
|
||||
processFinally(context);
|
||||
}
|
||||
|
||||
log.trace("Metadata schemas successfully read.");
|
||||
return metadataSchema;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns metadata field with basic properties.
|
||||
*
|
||||
* @param schemaPreix
|
||||
* Prefix for schema in DSpace.
|
||||
* @param element
|
||||
* Unqualified element name for field in the metadata registry.
|
||||
* @param expand
|
||||
* String in which is what you want to add to returned instance
|
||||
* of the metadata field. Options are: "all", "parentSchema". Default value "".
|
||||
* @param headers
|
||||
* If you want to access to community under logged user into
|
||||
* context. In headers must be set header "rest-dspace-token"
|
||||
* with passed token from login method.
|
||||
* @return Return instance of org.dspace.rest.common.MetadataField.
|
||||
* @throws WebApplicationException
|
||||
* It is throw when was problem with creating context or problem
|
||||
* with database reading. Also if id of field is incorrect
|
||||
* or logged user into context has no permission to read.
|
||||
*/
|
||||
@GET
|
||||
@Path("/schema/{schema_prefix}/metadata-fields/{element}")
|
||||
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
|
||||
public MetadataField getMetadataFieldUnqualified(@PathParam("schema_prefix") String schemaPrefix,
|
||||
@PathParam("element") String element,
|
||||
@QueryParam("expand") String expand,
|
||||
@QueryParam("userIP") String user_ip, @QueryParam("userAgent") String user_agent,
|
||||
@QueryParam("xforwarderfor") String xforwarderfor, @Context HttpHeaders headers, @Context HttpServletRequest request)
|
||||
throws WebApplicationException
|
||||
{
|
||||
return getMetadataFieldQualified(schemaPrefix, element, "", expand, user_ip, user_agent, xforwarderfor, headers, request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns metadata field with basic properties.
|
||||
*
|
||||
* @param schemaPreix
|
||||
* Prefix for schema in DSpace.
|
||||
* @param element
|
||||
* Element name for field in the metadata registry.
|
||||
* @param qualifier
|
||||
* Element name qualifier for field in the metadata registry.
|
||||
* @param expand
|
||||
* String in which is what you want to add to returned instance
|
||||
* of the metadata field. Options are: "all", "parentSchema". Default value "".
|
||||
* @param headers
|
||||
* If you want to access to community under logged user into
|
||||
* context. In headers must be set header "rest-dspace-token"
|
||||
* with passed token from login method.
|
||||
* @return Return instance of org.dspace.rest.common.MetadataField.
|
||||
* @throws WebApplicationException
|
||||
* It is throw when was problem with creating context or problem
|
||||
* with database reading. Also if id of field is incorrect
|
||||
* or logged user into context has no permission to read.
|
||||
*/
|
||||
@GET
|
||||
@Path("/schema/{schema_prefix}/metadata-fields/{element}/{qualifier}")
|
||||
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
|
||||
public MetadataField getMetadataFieldQualified(@PathParam("schema_prefix") String schemaPrefix,
|
||||
@PathParam("element") String element,
|
||||
@PathParam("qualifier") @DefaultValue("") String qualifier,
|
||||
@QueryParam("expand") String expand,
|
||||
@QueryParam("userIP") String user_ip, @QueryParam("userAgent") String user_agent,
|
||||
@QueryParam("xforwarderfor") String xforwarderfor, @Context HttpHeaders headers, @Context HttpServletRequest request)
|
||||
throws WebApplicationException
|
||||
{
|
||||
|
||||
log.info("Reading metadata field.");
|
||||
org.dspace.core.Context context = null;
|
||||
MetadataField metadataField = null;
|
||||
|
||||
try
|
||||
{
|
||||
context = createContext(getUser(headers));
|
||||
|
||||
org.dspace.content.MetadataSchema schema = metadataSchemaService.find(context, schemaPrefix);
|
||||
|
||||
if (schema == null) {
|
||||
log.error(String.format("Schema not found for prefix %s", schemaPrefix));
|
||||
throw new WebApplicationException(Response.Status.NOT_FOUND);
|
||||
}
|
||||
|
||||
org.dspace.content.MetadataField field = metadataFieldService.findByElement(context, schema, element, qualifier);
|
||||
if (field == null) {
|
||||
log.error(String.format("Field %s.%s.%s not found", schemaPrefix, element, qualifier));
|
||||
throw new WebApplicationException(Response.Status.NOT_FOUND);
|
||||
}
|
||||
metadataField = new MetadataField(schema, field, expand, context);
|
||||
|
||||
context.complete();
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
processException("Could not read metadata field, SQLException. Message:" + e, context);
|
||||
}
|
||||
catch (ContextException e)
|
||||
{
|
||||
processException("Could not read metadata field, ContextException. Message:" + e.getMessage(), context);
|
||||
}
|
||||
finally
|
||||
{
|
||||
processFinally(context);
|
||||
}
|
||||
|
||||
log.trace("Metadata field successfully read.");
|
||||
return metadataField;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns metadata field with basic properties.
|
||||
*
|
||||
* @param fieldId
|
||||
* Id of metadata field in DSpace.
|
||||
* @param expand
|
||||
* String in which is what you want to add to returned instance
|
||||
* of the metadata field. Options are: "all", "parentSchema". Default value "parentSchema".
|
||||
* @param headers
|
||||
* If you want to access to community under logged user into
|
||||
* context. In headers must be set header "rest-dspace-token"
|
||||
* with passed token from login method.
|
||||
* @return Return instance of org.dspace.rest.common.MetadataField.
|
||||
* @throws WebApplicationException
|
||||
* It is throw when was problem with creating context or problem
|
||||
* with database reading. Also if id of field is incorrect
|
||||
* or logged user into context has no permission to read.
|
||||
*/
|
||||
@GET
|
||||
@Path("/metadata-fields/{field_id}")
|
||||
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
|
||||
public MetadataField getMetadataField(@PathParam("field_id") Integer fieldId,
|
||||
@QueryParam("expand") @DefaultValue("parentSchema") String expand,
|
||||
@QueryParam("userIP") String user_ip, @QueryParam("userAgent") String user_agent,
|
||||
@QueryParam("xforwarderfor") String xforwarderfor, @Context HttpHeaders headers, @Context HttpServletRequest request)
|
||||
throws WebApplicationException
|
||||
{
|
||||
|
||||
log.info("Reading metadata field.");
|
||||
org.dspace.core.Context context = null;
|
||||
MetadataField metadataField = null;
|
||||
|
||||
try
|
||||
{
|
||||
context = createContext(getUser(headers));
|
||||
|
||||
org.dspace.content.MetadataField field = metadataFieldService.find(context, fieldId);
|
||||
if (field == null) {
|
||||
log.error(String.format("Metadata Field %d not found", fieldId));
|
||||
throw new WebApplicationException(Response.Status.NOT_FOUND);
|
||||
}
|
||||
org.dspace.content.MetadataSchema schema = field.getMetadataSchema();
|
||||
if (schema == null) {
|
||||
log.error(String.format("Parent Schema not found for Metadata Field %d not found", fieldId));
|
||||
throw new WebApplicationException(Response.Status.NOT_FOUND);
|
||||
}
|
||||
metadataField = new MetadataField(schema, field, expand, context);
|
||||
|
||||
context.complete();
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
processException("Could not read metadata field, SQLException. Message:" + e, context);
|
||||
}
|
||||
catch (ContextException e)
|
||||
{
|
||||
processException("Could not read metadata field, ContextException. Message:" + e.getMessage(), context);
|
||||
}
|
||||
finally
|
||||
{
|
||||
processFinally(context);
|
||||
}
|
||||
|
||||
log.trace("Metadata field successfully read.");
|
||||
return metadataField;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create schema in the schema registry. Creating a schema is restricted to admin users.
|
||||
*
|
||||
* @param schema
|
||||
* Schema that will be added to the metadata registry.
|
||||
* @param headers
|
||||
* If you want to access to schema under logged user into
|
||||
* context. In headers must be set header "rest-dspace-token"
|
||||
* with passed token from login method.
|
||||
* @return Return response 200 if was everything all right. Otherwise 400
|
||||
* when id of community was incorrect or 401 if was problem with
|
||||
* permission to write into collection.
|
||||
* Returns the schema (schemaId), if was all ok.
|
||||
* @throws WebApplicationException
|
||||
* It can be thrown by SQLException, AuthorizeException and
|
||||
* ContextException.
|
||||
*/
|
||||
@POST
|
||||
@Path("/schema")
|
||||
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
|
||||
public MetadataSchema createSchema(MetadataSchema schema, @QueryParam("userIP") String user_ip,
|
||||
@QueryParam("userAgent") String user_agent, @QueryParam("xforwardedfor") String xforwardedfor,
|
||||
@Context HttpHeaders headers, @Context HttpServletRequest request) throws WebApplicationException
|
||||
{
|
||||
|
||||
log.info("Creating a schema.");
|
||||
org.dspace.core.Context context = null;
|
||||
MetadataSchema retSchema = null;
|
||||
|
||||
try
|
||||
{
|
||||
context = createContext(getUser(headers));
|
||||
|
||||
if (!authorizeService.isAdmin(context))
|
||||
{
|
||||
context.abort();
|
||||
String user = "anonymous";
|
||||
if (context.getCurrentUser() != null)
|
||||
{
|
||||
user = context.getCurrentUser().getEmail();
|
||||
}
|
||||
log.error("User(" + user + ") does not have permission to create a metadata schema!");
|
||||
throw new WebApplicationException(Response.Status.UNAUTHORIZED);
|
||||
}
|
||||
|
||||
log.debug(String.format("Admin user creating schema with namespace %s and prefix %s", schema.getNamespace(), schema.getPrefix()));
|
||||
|
||||
org.dspace.content.MetadataSchema dspaceSchema = metadataSchemaService.create(context, schema.getNamespace(), schema.getPrefix());
|
||||
log.debug("Creating return object.");
|
||||
retSchema = new MetadataSchema(dspaceSchema, "", context);
|
||||
|
||||
writeStats(siteService.findSite(context), UsageEvent.Action.CREATE, user_ip, user_agent, xforwardedfor,
|
||||
headers, request, context);
|
||||
|
||||
context.complete();
|
||||
log.info("Schema created" + retSchema.getPrefix());
|
||||
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
processException("Could not create new metadata schema, SQLException. Message: " + e, context);
|
||||
}
|
||||
catch (ContextException e)
|
||||
{
|
||||
processException("Could not create new metadata schema, ContextException. Message: " + e.getMessage(), context);
|
||||
}
|
||||
catch (AuthorizeException e)
|
||||
{
|
||||
processException("Could not create new metadata schema, AuthorizeException. Message: " + e.getMessage(), context);
|
||||
}
|
||||
catch (NonUniqueMetadataException e) {
|
||||
processException("Could not create new metadata schema, NonUniqueMetadataException. Message: " + e.getMessage(), context);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
processException("Could not create new metadata schema, Exception. Class: " + e.getClass(), context);
|
||||
}
|
||||
finally
|
||||
{
|
||||
processFinally(context);
|
||||
}
|
||||
|
||||
return retSchema;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a new metadata field within a schema.
|
||||
* Creating a metadata field is restricted to admin users.
|
||||
*
|
||||
* @param field
|
||||
* Field that will be added to the metadata registry for a schema.
|
||||
* @param headers
|
||||
* If you want to access to schema under logged user into
|
||||
* context. In headers must be set header "rest-dspace-token"
|
||||
* with passed token from login method.
|
||||
* @return Return response 200 if was everything all right. Otherwise 400
|
||||
* when id of community was incorrect or 401 if was problem with
|
||||
* permission to write into collection.
|
||||
* Returns the field (with fieldId), if was all ok.
|
||||
* @throws WebApplicationException
|
||||
* It can be thrown by SQLException, AuthorizeException and
|
||||
* ContextException.
|
||||
*/
|
||||
@POST
|
||||
@Path("/schema/{schema_prefix}/metadata-fields")
|
||||
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
|
||||
public MetadataField createMetadataField(@PathParam("schema_prefix") String schemaPrefix,
|
||||
MetadataField field, @QueryParam("userIP") String user_ip,
|
||||
@QueryParam("userAgent") String user_agent, @QueryParam("xforwardedfor") String xforwardedfor,
|
||||
@Context HttpHeaders headers, @Context HttpServletRequest request) throws WebApplicationException
|
||||
{
|
||||
|
||||
log.info(String.format("Creating metadataField within schema %s.", schemaPrefix));
|
||||
org.dspace.core.Context context = null;
|
||||
MetadataField retField = null;
|
||||
|
||||
try
|
||||
{
|
||||
context = createContext(getUser(headers));
|
||||
|
||||
if (!authorizeService.isAdmin(context))
|
||||
{
|
||||
context.abort();
|
||||
String user = "anonymous";
|
||||
if (context.getCurrentUser() != null)
|
||||
{
|
||||
user = context.getCurrentUser().getEmail();
|
||||
}
|
||||
log.error("User(" + user + ") does not have permission to create a metadata field!");
|
||||
throw new WebApplicationException(Response.Status.UNAUTHORIZED);
|
||||
}
|
||||
|
||||
org.dspace.content.MetadataSchema schema = metadataSchemaService.find(context, schemaPrefix);
|
||||
if (schema == null) {
|
||||
log.error(String.format("Schema not found for prefix %s", schemaPrefix));
|
||||
throw new WebApplicationException(Response.Status.NOT_FOUND);
|
||||
}
|
||||
org.dspace.content.MetadataField dspaceField = metadataFieldService.create(context, schema, field.getElement(), field.getQualifier(), field.getDescription());
|
||||
writeStats(siteService.findSite(context), UsageEvent.Action.CREATE, user_ip, user_agent, xforwardedfor,
|
||||
headers, request, context);
|
||||
|
||||
retField = new MetadataField(schema, dspaceField, "", context);
|
||||
context.complete();
|
||||
log.info("Metadata field created within schema" + retField.getName());
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
processException("Could not create new metadata field, SQLException. Message: " + e, context);
|
||||
}
|
||||
catch (ContextException e)
|
||||
{
|
||||
processException("Could not create new metadata field, ContextException. Message: " + e.getMessage(), context);
|
||||
}
|
||||
catch (AuthorizeException e)
|
||||
{
|
||||
processException("Could not create new metadata field, AuthorizeException. Message: " + e.getMessage(), context);
|
||||
}
|
||||
catch (NonUniqueMetadataException e) {
|
||||
processException("Could not create new metadata field, NonUniqueMetadataException. Message: " + e.getMessage(), context);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
processException("Could not create new metadata field, Exception. Message: " + e.getMessage(), context);
|
||||
}
|
||||
finally
|
||||
{
|
||||
processFinally(context);
|
||||
}
|
||||
|
||||
return retField;
|
||||
}
|
||||
|
||||
//@PUT
|
||||
//@Path("/schema/{schema_prefix}")
|
||||
//Assumption - there are no meaningful fields to update for a schema
|
||||
|
||||
/**
|
||||
* Update metadata field. Replace all information about community except the id and the containing schema.
|
||||
*
|
||||
* @param fieldId
|
||||
* Id of the field in the DSpace metdata registry.
|
||||
* @param field
|
||||
* Instance of the metadata field which will replace actual metadata field in
|
||||
* DSpace.
|
||||
* @param headers
|
||||
* If you want to access to metadata field under logged user into
|
||||
* context. In headers must be set header "rest-dspace-token"
|
||||
* with passed token from login method.
|
||||
* @return Response 200 if was all ok. Otherwise 400 if was id incorrect or
|
||||
* 401 if logged user has no permission to update the metadata field.
|
||||
* @throws WebApplicationException
|
||||
* It is throw when was problem with creating context or problem
|
||||
* with database reading or writing. Or problem with writing to
|
||||
* community caused by authorization.
|
||||
*/
|
||||
@PUT
|
||||
@Path("/metadata-fields/{field_id}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
|
||||
public Response updateMetadataField(@PathParam("field_id") Integer fieldId, MetadataField field,
|
||||
@QueryParam("userIP") String user_ip, @QueryParam("userAgent") String user_agent,
|
||||
@QueryParam("xforwardedfor") String xforwardedfor, @Context HttpHeaders headers, @Context HttpServletRequest request)
|
||||
throws WebApplicationException
|
||||
{
|
||||
|
||||
log.info("Updating metadata field(id=" + fieldId + ").");
|
||||
org.dspace.core.Context context = null;
|
||||
|
||||
try
|
||||
{
|
||||
context = createContext(getUser(headers));
|
||||
|
||||
org.dspace.content.MetadataField dspaceField = metadataFieldService.find(context, fieldId);
|
||||
if (field == null) {
|
||||
log.error(String.format("Metadata Field %d not found", fieldId));
|
||||
throw new WebApplicationException(Response.Status.NOT_FOUND);
|
||||
}
|
||||
|
||||
writeStats(siteService.findSite(context), UsageEvent.Action.UPDATE, user_ip, user_agent, xforwardedfor,
|
||||
headers, request, context);
|
||||
|
||||
dspaceField.setElement(field.getElement());
|
||||
dspaceField.setQualifier(field.getQualifier());
|
||||
dspaceField.setScopeNote(field.getDescription());
|
||||
metadataFieldService.update(context, dspaceField);
|
||||
|
||||
context.complete();
|
||||
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
processException("Could not update metadata field(id=" + fieldId + "), AuthorizeException. Message:" + e, context);
|
||||
}
|
||||
catch (ContextException e)
|
||||
{
|
||||
processException("Could not update metadata field(id=" + fieldId + "), ContextException Message:" + e, context);
|
||||
}
|
||||
catch (AuthorizeException e)
|
||||
{
|
||||
processException("Could not update metadata field(id=" + fieldId + "), AuthorizeException. Message:" + e, context);
|
||||
}
|
||||
catch (NonUniqueMetadataException e) {
|
||||
processException("Could not update metadata field(id=" + fieldId + "), NonUniqueMetadataException. Message:" + e, context);
|
||||
}
|
||||
catch (IOException e) {
|
||||
processException("Could not update metadata field(id=" + fieldId + "), IOException. Message:" + e, context);
|
||||
}
|
||||
finally
|
||||
{
|
||||
processFinally(context);
|
||||
}
|
||||
|
||||
log.info("Metadata Field(id=" + fieldId + ") has been successfully updated.");
|
||||
return Response.ok().build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete metadata field from the DSpace metadata registry
|
||||
*
|
||||
* @param fieldId
|
||||
* Id of the metadata field in DSpace.
|
||||
* @param headers
|
||||
* If you want to access to metadata field under logged user into
|
||||
* context. In headers must be set header "rest-dspace-token"
|
||||
* with passed token from login method.
|
||||
* @return Return response code OK(200) if was everything all right.
|
||||
* Otherwise return NOT_FOUND(404) if was id of metadata field is incorrect.
|
||||
* Or (UNAUTHORIZED)401 if was problem with permission to metadata field.
|
||||
* @throws WebApplicationException
|
||||
* It is throw when was problem with creating context or problem
|
||||
* with database reading or deleting. Or problem with deleting
|
||||
* metadata field caused by IOException or authorization.
|
||||
*/
|
||||
@DELETE
|
||||
@Path("/metadata-fields/{field_id}")
|
||||
public Response deleteMetadataField(@PathParam("field_id") Integer fieldId, @QueryParam("userIP") String user_ip,
|
||||
@QueryParam("userAgent") String user_agent, @QueryParam("xforwardedfor") String xforwardedfor,
|
||||
@Context HttpHeaders headers, @Context HttpServletRequest request) throws WebApplicationException
|
||||
{
|
||||
|
||||
log.info("Deleting metadata field(id=" + fieldId + ").");
|
||||
org.dspace.core.Context context = null;
|
||||
|
||||
try
|
||||
{
|
||||
context = createContext(getUser(headers));
|
||||
|
||||
org.dspace.content.MetadataField dspaceField = metadataFieldService.find(context, fieldId);
|
||||
if (dspaceField == null) {
|
||||
log.error(String.format("Metadata Field %d not found", fieldId));
|
||||
throw new WebApplicationException(Response.Status.NOT_FOUND);
|
||||
}
|
||||
writeStats(siteService.findSite(context), UsageEvent.Action.DELETE, user_ip, user_agent, xforwardedfor, headers,
|
||||
request, context);
|
||||
|
||||
metadataFieldService.delete(context, dspaceField);
|
||||
context.complete();
|
||||
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
processException("Could not delete metadata field(id=" + fieldId + "), SQLException. Message:" + e, context);
|
||||
}
|
||||
catch (AuthorizeException e)
|
||||
{
|
||||
processException("Could not delete metadata field(id=" + fieldId + "), AuthorizeException. Message:" + e, context);
|
||||
}
|
||||
catch (ContextException e)
|
||||
{
|
||||
processException("Could not delete metadata field(id=" + fieldId + "), ContextException. Message:" + e.getMessage(),
|
||||
context);
|
||||
}
|
||||
finally
|
||||
{
|
||||
processFinally(context);
|
||||
}
|
||||
|
||||
|
||||
log.info("Metadata field(id=" + fieldId + ") was successfully deleted.");
|
||||
return Response.status(Response.Status.OK).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete metadata schema from the DSpace metadata registry
|
||||
*
|
||||
* @param schemaId
|
||||
* Id of the metadata schema in DSpace.
|
||||
* @param headers
|
||||
* If you want to access to metadata schema under logged user into
|
||||
* context. In headers must be set header "rest-dspace-token"
|
||||
* with passed token from login method.
|
||||
* @return Return response code OK(200) if was everything all right.
|
||||
* Otherwise return NOT_FOUND(404) if was id of metadata schema is incorrect.
|
||||
* Or (UNAUTHORIZED)401 if was problem with permission to metadata schema.
|
||||
* @throws WebApplicationException
|
||||
* It is throw when was problem with creating context or problem
|
||||
* with database reading or deleting. Or problem with deleting
|
||||
* metadata schema caused by IOException or authorization.
|
||||
*/
|
||||
@DELETE
|
||||
@Path("/schema/{schema_id}")
|
||||
public Response deleteSchema(@PathParam("schema_id") Integer schemaId, @QueryParam("userIP") String user_ip,
|
||||
@QueryParam("userAgent") String user_agent, @QueryParam("xforwardedfor") String xforwardedfor,
|
||||
@Context HttpHeaders headers, @Context HttpServletRequest request) throws WebApplicationException
|
||||
{
|
||||
|
||||
log.info("Deleting metadata schema(id=" + schemaId + ").");
|
||||
org.dspace.core.Context context = null;
|
||||
|
||||
try
|
||||
{
|
||||
context = createContext(getUser(headers));
|
||||
|
||||
org.dspace.content.MetadataSchema dspaceSchema = metadataSchemaService.find(context, schemaId);
|
||||
if (dspaceSchema == null) {
|
||||
log.error(String.format("Metadata Schema %d not found", schemaId));
|
||||
throw new WebApplicationException(Response.Status.NOT_FOUND);
|
||||
}
|
||||
writeStats(siteService.findSite(context), UsageEvent.Action.DELETE, user_ip, user_agent, xforwardedfor, headers,
|
||||
request, context);
|
||||
|
||||
metadataSchemaService.delete(context, dspaceSchema);
|
||||
context.complete();
|
||||
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
processException("Could not delete metadata schema(id=" + schemaId + "), SQLException. Message:" + e, context);
|
||||
}
|
||||
catch (AuthorizeException e)
|
||||
{
|
||||
processException("Could not delete metadata schema(id=" + schemaId + "), AuthorizeException. Message:" + e, context);
|
||||
}
|
||||
catch (ContextException e)
|
||||
{
|
||||
processException("Could not delete metadata schema(id=" + schemaId + "), ContextException. Message:" + e.getMessage(),
|
||||
context);
|
||||
}
|
||||
finally
|
||||
{
|
||||
processFinally(context);
|
||||
}
|
||||
|
||||
|
||||
log.info("Metadata schema(id=" + schemaId + ") was successfully deleted.");
|
||||
return Response.status(Response.Status.OK).build();
|
||||
}
|
||||
|
||||
}
|
@@ -121,6 +121,28 @@ public class RestIndex {
|
||||
"<ul>" +
|
||||
"<li>GET /hierarchy - Return hierarchy of communities and collections in tree form. Each object is minimally populated (name, handle, id) for efficient retrieval.</li>" +
|
||||
"</ul>" +
|
||||
"<h2>Metadata and Schema Registry</h2>" +
|
||||
"<ul>" +
|
||||
"<li>GET /registries/schema - Return the list of metadata schemas in the registry</li>" +
|
||||
"<li>GET /registries/schema/{schema_prefix} - Returns the specified metadata schema</li>" +
|
||||
"<li>GET /registries/schema/{schema_prefix}/metadata-fields/{element} - Returns the metadata field within a schema with an unqualified element name</li>" +
|
||||
"<li>GET /registries/schema/{schema_prefix}/metadata-fields/{element}/{qualifier} - Returns the metadata field within a schema with a qualified element name</li>" +
|
||||
"<li>POST /registries/schema/ - Add a schema to the schema registry</li>" +
|
||||
"<li>POST /registries/schema/{schema_prefix}/metadata-fields - Add a metadata field to the specified schema</li>" +
|
||||
"<li>GET /registries/metadata-fields/{field_id} - Return the specified metadata field</li>" +
|
||||
"<li>PUT /registries/metadata-fields/{field_id} - Update the specified metadata field</li>" +
|
||||
"<li>DELETE /registries/metadata-fields/{field_id} - Delete the specified metadata field from the metadata field registry</li>" +
|
||||
"<li>DELETE /registries/schema/{schema_id} - Delete the specified schema from the schema registry</li>" +
|
||||
"</ul>" +
|
||||
"<h2>Query/Reporting Tools</h2>" +
|
||||
"<ul>" +
|
||||
"<li>GET /reports - Return a list of report tools built on the rest api</li>" +
|
||||
"<li>GET /reports/{nickname} - Return a redirect to a specific report</li>" +
|
||||
"<li>GET /filters - Return a list of use case filters available for quality control reporting</li>" +
|
||||
"<li>GET /filtered-collections - Return collections and item counts based on pre-defined filters</li>" +
|
||||
"<li>GET /filtered-collections/{collection_id} - Return items and item counts for a collection based on pre-defined filters</li>" +
|
||||
"<li>GET /filtered-items - Retrieve a set of items based on a metadata query and a set of filters</li>" +
|
||||
"</ul>" +
|
||||
"</body></html> ";
|
||||
}
|
||||
|
||||
|
90
dspace-rest/src/main/java/org/dspace/rest/RestReports.java
Normal file
90
dspace-rest/src/main/java/org/dspace/rest/RestReports.java
Normal file
@@ -0,0 +1,90 @@
|
||||
/**
|
||||
* 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.rest;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.WebApplicationException;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.dspace.core.ConfigurationManager;
|
||||
import org.dspace.rest.common.Report;
|
||||
|
||||
|
||||
/**
|
||||
* Root of RESTful api. It provides login and logout. Also have method for
|
||||
* printing every method which is provides by RESTful api.
|
||||
*
|
||||
* @author Terry Brady, Georgetown University
|
||||
*
|
||||
*/
|
||||
@Path("/reports")
|
||||
public class RestReports {
|
||||
private static Logger log = Logger.getLogger(RestReports.class);
|
||||
|
||||
@javax.ws.rs.core.Context public static ServletContext servletContext;
|
||||
public static final String REST_RPT_URL = "rest-report-url.";
|
||||
|
||||
/**
|
||||
* Return html page with information about REST api. It contains methods all
|
||||
* methods provide by REST api.
|
||||
*
|
||||
* @return HTML page which has information about all methods of REST api.
|
||||
*/
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_XML)
|
||||
public Report[] reportIndex()
|
||||
throws WebApplicationException {
|
||||
ArrayList<Report> reports = new ArrayList<Report>();
|
||||
Properties props = ConfigurationManager.getProperties("rest");
|
||||
for(Object prop: props.keySet()) {
|
||||
String sprop = prop.toString();
|
||||
if (sprop.startsWith(REST_RPT_URL)) {
|
||||
String nickname = sprop.substring(REST_RPT_URL.length());
|
||||
String url = props.getProperty(sprop);
|
||||
reports.add(new Report(nickname, url));
|
||||
}
|
||||
}
|
||||
return reports.toArray(new Report[0]);
|
||||
}
|
||||
|
||||
@Path("/{report_nickname}")
|
||||
@GET
|
||||
public Response customReport(@PathParam("report_nickname") String report_nickname, @Context UriInfo uriInfo)
|
||||
throws WebApplicationException {
|
||||
URI uri = null;
|
||||
if (!report_nickname.isEmpty()){
|
||||
log.info(String.format("Seeking report %s", report_nickname));
|
||||
String url = ConfigurationManager.getProperty("rest", REST_RPT_URL + report_nickname);
|
||||
|
||||
log.info(String.format("URL for report %s found: [%s]", report_nickname, url));
|
||||
if (!url.isEmpty()) {
|
||||
uri = uriInfo.getBaseUriBuilder().path(url).build("");
|
||||
log.info(String.format("URI for report %s", uri));
|
||||
}
|
||||
}
|
||||
|
||||
if (uri != null) {
|
||||
return Response.temporaryRedirect(uri).build();
|
||||
}
|
||||
|
||||
return Response.noContent().build();
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,178 @@
|
||||
/**
|
||||
* 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.rest.common;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.dspace.content.factory.ContentServiceFactory;
|
||||
import org.dspace.content.service.CollectionService;
|
||||
import org.dspace.content.service.CommunityService;
|
||||
import org.dspace.content.service.ItemService;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.rest.filter.ItemFilterSet;
|
||||
|
||||
import javax.ws.rs.WebApplicationException;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Retrieve items within a collection that match a specific set of Item Filters of interest
|
||||
*
|
||||
* @author Terry Brady, Georgetown University
|
||||
*/
|
||||
@XmlRootElement(name = "filtered-collection")
|
||||
public class FilteredCollection extends DSpaceObject {
|
||||
protected CommunityService communityService = ContentServiceFactory.getInstance().getCommunityService();
|
||||
protected CollectionService collectionService = ContentServiceFactory.getInstance().getCollectionService();
|
||||
protected ItemService itemService = ContentServiceFactory.getInstance().getItemService();
|
||||
Logger log = Logger.getLogger(FilteredCollection.class);
|
||||
|
||||
//Relationships
|
||||
private Community parentCommunity;
|
||||
private Community topCommunity;
|
||||
private List<Community> parentCommunityList = new ArrayList<Community>();
|
||||
|
||||
private List<Item> items = new ArrayList<Item>();
|
||||
|
||||
private List<ItemFilter> itemFilters = new ArrayList<ItemFilter>();
|
||||
|
||||
//Calculated
|
||||
private Integer numberItems;
|
||||
private Integer numberItemsProcessed;
|
||||
|
||||
public FilteredCollection(){}
|
||||
|
||||
/**
|
||||
* Evaluate a collection against of set of Item Filters
|
||||
* @param collection
|
||||
* DSpace Collection to evaluate
|
||||
* @param filters
|
||||
* String representing a list of filters
|
||||
* @param expand
|
||||
* @param context
|
||||
* @param limit
|
||||
* @param offset
|
||||
* @throws SQLException
|
||||
* @throws WebApplicationException
|
||||
*/
|
||||
public FilteredCollection(org.dspace.content.Collection collection, String filters, String expand, Context context, Integer limit, Integer offset) throws SQLException, WebApplicationException{
|
||||
super(collection);
|
||||
setup(collection, expand, context, limit, offset, filters);
|
||||
}
|
||||
|
||||
private void setup(org.dspace.content.Collection collection, String expand, Context context, Integer limit, Integer offset, String filters) throws SQLException{
|
||||
List<String> expandFields = new ArrayList<String>();
|
||||
if(expand != null) {
|
||||
expandFields = Arrays.asList(expand.split(","));
|
||||
}
|
||||
|
||||
if(expandFields.contains("parentCommunityList") || expandFields.contains("all")) {
|
||||
List<org.dspace.content.Community> parentCommunities = collection.getCommunities();
|
||||
List<Community> parentCommunityList = new ArrayList<Community>();
|
||||
for(org.dspace.content.Community parentCommunity : parentCommunities) {
|
||||
parentCommunityList.add(new Community(parentCommunity, null, context));
|
||||
}
|
||||
this.setParentCommunityList(parentCommunityList);
|
||||
} else {
|
||||
this.addExpand("parentCommunityList");
|
||||
}
|
||||
|
||||
if(expandFields.contains("parentCommunity") | expandFields.contains("all")) {
|
||||
org.dspace.content.Community parentCommunity = collection.getCommunities().get(0);
|
||||
this.setParentCommunity(new Community(parentCommunity, null, context));
|
||||
} else {
|
||||
this.addExpand("parentCommunity");
|
||||
}
|
||||
|
||||
if(expandFields.contains("topCommunity") | expandFields.contains("all")) {
|
||||
List<org.dspace.content.Community> parentCommunities = collection.getCommunities();
|
||||
if (parentCommunities.size() > 0) {
|
||||
org.dspace.content.Community topCommunity = parentCommunities.get(parentCommunities.size()-1);
|
||||
this.setTopCommunity(new Community(topCommunity, null, context));
|
||||
}
|
||||
} else {
|
||||
this.addExpand("topCommunity");
|
||||
}
|
||||
|
||||
|
||||
boolean reportItems = expandFields.contains("items") || expandFields.contains("all");
|
||||
ItemFilterSet itemFilterSet = new ItemFilterSet(filters, reportItems);
|
||||
this.setItemFilters(itemFilterSet.getItemFilters());
|
||||
|
||||
this.setNumberItemsProcessed(0);
|
||||
if (itemFilters.size() > 0) {
|
||||
Iterator<org.dspace.content.Item> childItems = itemService.findByCollection(context, collection, limit, offset);
|
||||
int numProc = itemFilterSet.processSaveItems(context, childItems, items, reportItems, expand);
|
||||
this.setNumberItemsProcessed(numProc);
|
||||
}
|
||||
|
||||
if(!expandFields.contains("all")) {
|
||||
this.addExpand("all");
|
||||
}
|
||||
this.setNumberItems(itemService.countItems(context, collection));
|
||||
}
|
||||
|
||||
public Integer getNumberItems() {
|
||||
return numberItems;
|
||||
}
|
||||
|
||||
public void setNumberItems(Integer numberItems) {
|
||||
this.numberItems = numberItems;
|
||||
}
|
||||
public Integer getNumberItemsProcessed() {
|
||||
return numberItemsProcessed;
|
||||
}
|
||||
|
||||
public void setNumberItemsProcessed(Integer numberItemsProcessed) {
|
||||
this.numberItemsProcessed = numberItemsProcessed;
|
||||
}
|
||||
|
||||
public Community getParentCommunity() {
|
||||
return parentCommunity;
|
||||
}
|
||||
|
||||
public void setParentCommunity(Community parentCommunity) {
|
||||
this.parentCommunity = parentCommunity;
|
||||
}
|
||||
|
||||
public Community getTopCommunity() {
|
||||
return topCommunity;
|
||||
}
|
||||
|
||||
public void setTopCommunity(Community topCommunity) {
|
||||
this.topCommunity = topCommunity;
|
||||
}
|
||||
|
||||
|
||||
public List<Item> getItems() {
|
||||
return items;
|
||||
}
|
||||
|
||||
public void setItems(List<Item> items) {
|
||||
this.items = items;
|
||||
}
|
||||
|
||||
public void setParentCommunityList(List<Community> parentCommunityList) {
|
||||
this.parentCommunityList = parentCommunityList;
|
||||
}
|
||||
|
||||
public List<Community> getParentCommunityList() {
|
||||
return parentCommunityList;
|
||||
}
|
||||
|
||||
public List<ItemFilter> getItemFilters() {
|
||||
return itemFilters;
|
||||
}
|
||||
|
||||
public void setItemFilters(List<ItemFilter> itemFilters) {
|
||||
this.itemFilters = itemFilters;
|
||||
}
|
||||
}
|
@@ -86,10 +86,14 @@ public class Item extends DSpaceObject {
|
||||
this.setLastModified(item.getLastModified().toString());
|
||||
|
||||
if(expandFields.contains("parentCollection") || expandFields.contains("all")) {
|
||||
if (item.getOwningCollection() != null) {
|
||||
this.parentCollection = new Collection(item.getOwningCollection(), null, context, null, null);
|
||||
} else {
|
||||
this.addExpand("parentCollection");
|
||||
}
|
||||
} else {
|
||||
this.addExpand("parentCollection");
|
||||
}
|
||||
|
||||
if(expandFields.contains("parentCollectionList") || expandFields.contains("all")) {
|
||||
this.parentCollectionList = new ArrayList<Collection>();
|
||||
|
265
dspace-rest/src/main/java/org/dspace/rest/common/ItemFilter.java
Normal file
265
dspace-rest/src/main/java/org/dspace/rest/common/ItemFilter.java
Normal file
@@ -0,0 +1,265 @@
|
||||
/**
|
||||
* 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.rest.common;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.core.PluginManager;
|
||||
import org.dspace.rest.filter.ItemFilterDefs;
|
||||
import org.dspace.rest.filter.ItemFilterList;
|
||||
import org.dspace.rest.filter.ItemFilterTest;
|
||||
|
||||
import javax.ws.rs.WebApplicationException;
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Use Case Item Filters that match a specific set of criteria.
|
||||
* @author Terry Brady, Georgetown University
|
||||
*/
|
||||
@XmlRootElement(name = "item-filter")
|
||||
public class ItemFilter {
|
||||
static Logger log = Logger.getLogger(ItemFilter.class);
|
||||
|
||||
private ItemFilterTest itemFilterTest = null;
|
||||
private String filterName = "";
|
||||
private String title;
|
||||
private String description;
|
||||
private String category;
|
||||
private String queryAnnotation;
|
||||
private List<org.dspace.rest.common.Item> items = new ArrayList<org.dspace.rest.common.Item>();
|
||||
private List<ItemFilterQuery> itemFilterQueries = new ArrayList<ItemFilterQuery>();
|
||||
private List<MetadataEntry> metadata = new ArrayList<MetadataEntry>();
|
||||
private Integer itemCount;
|
||||
private Integer unfilteredItemCount;
|
||||
private boolean saveItems = false;
|
||||
|
||||
public ItemFilter(){}
|
||||
|
||||
public static final String ALL_FILTERS = "all_filters";
|
||||
public static final String ALL = "all";
|
||||
|
||||
public static List<ItemFilter> getItemFilters(String filters, boolean saveItems) {
|
||||
LinkedHashMap<String,ItemFilterTest> availableTests = new LinkedHashMap<String,ItemFilterTest>();
|
||||
for(ItemFilterList plugobj: (ItemFilterList[])PluginManager.getPluginSequence("rest", ItemFilterList.class)) {
|
||||
for(ItemFilterTest defFilter: plugobj.getFilters()) {
|
||||
availableTests.put(defFilter.getName(), defFilter);
|
||||
}
|
||||
}
|
||||
List<ItemFilter> itemFilters = new ArrayList<ItemFilter>();
|
||||
ItemFilter allFilters = new ItemFilter(ItemFilter.ALL_FILTERS, "Matches all specified filters",
|
||||
"This filter includes all items that matched ALL specified filters", ItemFilterDefs.CAT_ITEM, saveItems);
|
||||
|
||||
if (filters.equals(ALL)) {
|
||||
for(ItemFilterTest itemFilterDef: availableTests.values()) {
|
||||
itemFilters.add(new ItemFilter(itemFilterDef, saveItems));
|
||||
}
|
||||
itemFilters.add(allFilters);
|
||||
} else {
|
||||
for(String filter: Arrays.asList(filters.split(","))) {
|
||||
if (filter.equals(ItemFilter.ALL_FILTERS)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ItemFilterTest itemFilterDef;
|
||||
itemFilterDef = availableTests.get(filter);
|
||||
if (itemFilterDef == null) {
|
||||
continue;
|
||||
}
|
||||
itemFilters.add(new ItemFilter(itemFilterDef, saveItems));
|
||||
}
|
||||
itemFilters.add(allFilters);
|
||||
}
|
||||
return itemFilters;
|
||||
}
|
||||
|
||||
public static ItemFilter getAllFiltersFilter(List<ItemFilter> itemFilters) {
|
||||
for(ItemFilter itemFilter: itemFilters) {
|
||||
if (itemFilter.getFilterName().equals(ALL_FILTERS)) {
|
||||
itemFilter.initCount();
|
||||
return itemFilter;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public ItemFilter(ItemFilterTest itemFilterTest, boolean saveItems) throws WebApplicationException{
|
||||
this.itemFilterTest = itemFilterTest;
|
||||
this.saveItems = saveItems;
|
||||
setup(itemFilterTest.getName(), itemFilterTest.getTitle(), itemFilterTest.getDescription(), itemFilterTest.getCategory());
|
||||
}
|
||||
|
||||
public ItemFilter(String name, String title, String description, String category, boolean saveItems) throws WebApplicationException{
|
||||
this.saveItems = saveItems;
|
||||
setup(name, title, description, category);
|
||||
}
|
||||
|
||||
private void setup(String name, String title, String description, String category) {
|
||||
this.setFilterName(name);
|
||||
this.setTitle(title);
|
||||
this.setDescription(description);
|
||||
this.setCategory(category);
|
||||
}
|
||||
|
||||
private void initCount() {
|
||||
if (itemCount == null) {
|
||||
itemCount = 0;
|
||||
}
|
||||
if (unfilteredItemCount == null) {
|
||||
unfilteredItemCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasItemTest() {
|
||||
return itemFilterTest != null;
|
||||
}
|
||||
|
||||
public void addItem(org.dspace.rest.common.Item restItem) {
|
||||
initCount();
|
||||
if (saveItems){
|
||||
items.add(restItem);
|
||||
}
|
||||
itemCount++;
|
||||
}
|
||||
|
||||
public boolean testItem(Context context, org.dspace.content.Item item, org.dspace.rest.common.Item restItem) {
|
||||
initCount();
|
||||
if (itemFilterTest == null) {
|
||||
return false;
|
||||
}
|
||||
if (itemFilterTest.testItem(context, item)) {
|
||||
addItem(restItem);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@XmlAttribute(name="filter-name")
|
||||
public String getFilterName() {
|
||||
return filterName;
|
||||
}
|
||||
|
||||
public void setFilterName(String name) {
|
||||
this.filterName = name;
|
||||
}
|
||||
|
||||
@XmlAttribute(name="title")
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
@XmlAttribute(name="category")
|
||||
public String getCategory() {
|
||||
return category;
|
||||
}
|
||||
|
||||
public void setCategory(String category) {
|
||||
this.category = category;
|
||||
}
|
||||
|
||||
@XmlAttribute(name="description")
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
@XmlAttribute(name="query-annotation")
|
||||
public String getQueryAnnotation() {
|
||||
return queryAnnotation;
|
||||
}
|
||||
|
||||
public void annotateQuery(List<String> query_field, List<String> query_op, List<String> query_val) throws SQLException {
|
||||
int index = Math.min(query_field.size(), Math.min(query_op.size(), query_val.size()));
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
for(int i=0; i<index; i++) {
|
||||
if (!sb.toString().isEmpty()) {
|
||||
sb.append(" and ");
|
||||
}
|
||||
sb.append("(");
|
||||
sb.append(query_field.get(i));
|
||||
sb.append(" ");
|
||||
sb.append(query_op.get(i));
|
||||
sb.append(" ");
|
||||
sb.append(query_val.get(i));
|
||||
sb.append(")");
|
||||
}
|
||||
setQueryAnnotation(sb.toString());
|
||||
}
|
||||
|
||||
public void setQueryAnnotation(String queryAnnotation) {
|
||||
this.queryAnnotation = queryAnnotation;
|
||||
}
|
||||
|
||||
@XmlAttribute(name="item-count")
|
||||
public Integer getItemCount() {
|
||||
return itemCount;
|
||||
}
|
||||
|
||||
public void setItemCount(Integer itemCount) {
|
||||
this.itemCount = itemCount;
|
||||
}
|
||||
|
||||
@XmlAttribute(name="unfiltered-item-count")
|
||||
public Integer getUnfilteredItemCount() {
|
||||
return unfilteredItemCount;
|
||||
}
|
||||
|
||||
public void setUnfilteredItemCount(Integer unfilteredItemCount) {
|
||||
this.unfilteredItemCount = unfilteredItemCount;
|
||||
}
|
||||
|
||||
public List<org.dspace.rest.common.Item> getItems() {
|
||||
return items;
|
||||
}
|
||||
|
||||
public void setItems(List<org.dspace.rest.common.Item> items) {
|
||||
this.items = items;
|
||||
}
|
||||
|
||||
public List<ItemFilterQuery> getItemFilterQueries() {
|
||||
return itemFilterQueries;
|
||||
}
|
||||
|
||||
public void setItemFilterQueries(List<ItemFilterQuery> itemFilterQueries) {
|
||||
this.itemFilterQueries = itemFilterQueries;
|
||||
}
|
||||
|
||||
public void initMetadataList(List<String> show_fields) {
|
||||
if (show_fields != null) {
|
||||
List<MetadataEntry> returnFields = new ArrayList<MetadataEntry>();
|
||||
for(String field: show_fields) {
|
||||
returnFields.add(new MetadataEntry(field, null, null));
|
||||
}
|
||||
setMetadata(returnFields);
|
||||
}
|
||||
}
|
||||
|
||||
public List<MetadataEntry> getMetadata() {
|
||||
return metadata;
|
||||
}
|
||||
|
||||
@XmlElement(required = true)
|
||||
public void setMetadata(List<MetadataEntry> metadata) {
|
||||
this.metadata = metadata;
|
||||
}
|
||||
}
|
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
* 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.rest.common;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import javax.ws.rs.WebApplicationException;
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
/**
|
||||
* Metadata Query for DSpace Items using the REST API
|
||||
* @author Terry Brady, Georgetown University
|
||||
*/
|
||||
@XmlRootElement(name = "item-filter-query")
|
||||
public class ItemFilterQuery {
|
||||
Logger log = Logger.getLogger(ItemFilterQuery.class);
|
||||
|
||||
private String field = "";
|
||||
private String operation = "";
|
||||
private String value = "";
|
||||
|
||||
public ItemFilterQuery(){}
|
||||
|
||||
/**
|
||||
* Construct a metadata query for DSpace items
|
||||
* @param field
|
||||
* Name of the metadata field to query
|
||||
* @param operation
|
||||
* Operation to perform on a metadata field
|
||||
* @param value
|
||||
* @throws WebApplicationException
|
||||
*/
|
||||
public ItemFilterQuery(String field, String operation, String value) throws WebApplicationException{
|
||||
setup(field, operation, value);
|
||||
}
|
||||
|
||||
private void setup(String field, String operation, String value) {
|
||||
this.setField(field);
|
||||
this.setOperation(operation);
|
||||
this.setValue(value);
|
||||
}
|
||||
|
||||
@XmlAttribute(name="field")
|
||||
public String getField() {
|
||||
return field;
|
||||
}
|
||||
|
||||
public void setField(String field) {
|
||||
this.field = field;
|
||||
}
|
||||
|
||||
@XmlAttribute(name="operation")
|
||||
public String getOperation() {
|
||||
return operation;
|
||||
}
|
||||
|
||||
public void setOperation(String operation) {
|
||||
this.operation = operation;
|
||||
}
|
||||
@XmlAttribute(name="value")
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,120 @@
|
||||
/**
|
||||
* 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.rest.common;
|
||||
|
||||
import org.dspace.core.Context;
|
||||
|
||||
import javax.ws.rs.WebApplicationException;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Metadata field representation
|
||||
* @author Terry Brady, Georgetown University.
|
||||
*/
|
||||
@XmlRootElement(name = "field")
|
||||
public class MetadataField {
|
||||
private int fieldId;
|
||||
private String name;
|
||||
private String element;
|
||||
private String qualifier;
|
||||
private String description;
|
||||
|
||||
private MetadataSchema parentSchema;
|
||||
|
||||
@XmlElement(required = true)
|
||||
private ArrayList<String> expand = new ArrayList<String>();
|
||||
|
||||
public MetadataField(){}
|
||||
|
||||
public MetadataField(org.dspace.content.MetadataSchema schema, org.dspace.content.MetadataField field, String expand, Context context) throws SQLException, WebApplicationException{
|
||||
setup(schema, field, expand, context);
|
||||
}
|
||||
|
||||
private void setup(org.dspace.content.MetadataSchema schema, org.dspace.content.MetadataField field, String expand, Context context) throws SQLException{
|
||||
List<String> expandFields = new ArrayList<String>();
|
||||
if(expand != null) {
|
||||
expandFields = Arrays.asList(expand.split(","));
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(schema.getName());
|
||||
sb.append(".");
|
||||
sb.append(field.getElement());
|
||||
if (field.getQualifier()!=null) {
|
||||
sb.append(".");
|
||||
sb.append(field.getQualifier());
|
||||
}
|
||||
|
||||
this.setName(sb.toString());
|
||||
this.setFieldId(field.getFieldID());
|
||||
this.setElement(field.getElement());
|
||||
this.setQualifier(field.getQualifier());
|
||||
this.setDescription(field.getScopeNote());
|
||||
|
||||
if (expandFields.contains("parentSchema") || expandFields.contains("all")) {
|
||||
this.addExpand("parentSchema");
|
||||
parentSchema = new MetadataSchema(schema, "", context);
|
||||
}
|
||||
}
|
||||
|
||||
public void setParentSchema(MetadataSchema schema) {
|
||||
this.parentSchema = schema;
|
||||
}
|
||||
|
||||
public MetadataSchema getParentSchema() {
|
||||
return this.parentSchema;
|
||||
}
|
||||
|
||||
public void setFieldId(int fieldId) {
|
||||
this.fieldId = fieldId;
|
||||
}
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
public void setElement(String element) {
|
||||
this.element = element;
|
||||
}
|
||||
public void setQualifier(String qualifier) {
|
||||
this.qualifier = qualifier;
|
||||
}
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public int getFieldId() {
|
||||
return fieldId;
|
||||
}
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getQualifier() {
|
||||
return qualifier;
|
||||
}
|
||||
public String getElement() {
|
||||
return element;
|
||||
}
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
public List<String> getExpand() {
|
||||
return expand;
|
||||
}
|
||||
|
||||
public void setExpand(ArrayList<String> expand) {
|
||||
this.expand = expand;
|
||||
}
|
||||
|
||||
public void addExpand(String expandableAttribute) {
|
||||
this.expand.add(expandableAttribute);
|
||||
}
|
||||
}
|
@@ -0,0 +1,99 @@
|
||||
/**
|
||||
* 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.rest.common;
|
||||
|
||||
import org.dspace.content.factory.ContentServiceFactory;
|
||||
import org.dspace.content.service.MetadataFieldService;
|
||||
import org.dspace.core.Context;
|
||||
|
||||
import javax.ws.rs.WebApplicationException;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Metadata schema representation
|
||||
* @author Terry Brady, Georgetown University.
|
||||
*/
|
||||
@XmlRootElement(name = "schema")
|
||||
public class MetadataSchema {
|
||||
protected MetadataFieldService metadataFieldService = ContentServiceFactory.getInstance().getMetadataFieldService();
|
||||
|
||||
private int schemaID;
|
||||
private String prefix;
|
||||
private String namespace;
|
||||
|
||||
@XmlElement(required = true)
|
||||
private ArrayList<String> expand = new ArrayList<String>();
|
||||
|
||||
@XmlElement(name = "fields", required = true)
|
||||
private List<MetadataField> fields = new ArrayList<MetadataField>();
|
||||
|
||||
public MetadataSchema(){}
|
||||
|
||||
public MetadataSchema(org.dspace.content.MetadataSchema schema, String expand, Context context) throws SQLException, WebApplicationException{
|
||||
setup(schema, expand, context);
|
||||
}
|
||||
|
||||
private void setup(org.dspace.content.MetadataSchema schema, String expand, Context context) throws SQLException{
|
||||
List<String> expandFields = new ArrayList<String>();
|
||||
if(expand != null) {
|
||||
expandFields = Arrays.asList(expand.split(","));
|
||||
}
|
||||
this.setSchemaID(schema.getSchemaID());
|
||||
this.setPrefix(schema.getName());
|
||||
this.setNamespace(schema.getNamespace());
|
||||
if (expandFields.contains("fields") || expandFields.contains("all")) {
|
||||
List<org.dspace.content.MetadataField> fields = metadataFieldService.findAllInSchema(context, schema);
|
||||
this.addExpand("fields");
|
||||
for(org.dspace.content.MetadataField field: fields) {
|
||||
this.fields.add(new MetadataField(schema, field, "", context));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setPrefix(String prefix) {
|
||||
this.prefix = prefix;
|
||||
}
|
||||
public void setNamespace(String namespace) {
|
||||
this.namespace = namespace;
|
||||
}
|
||||
|
||||
public String getPrefix() {
|
||||
return prefix;
|
||||
}
|
||||
public String getNamespace() {
|
||||
return namespace;
|
||||
}
|
||||
public int getSchemaID()
|
||||
{
|
||||
return this.schemaID;
|
||||
}
|
||||
|
||||
public void setSchemaID(int schemaID)
|
||||
{
|
||||
this.schemaID = schemaID;
|
||||
}
|
||||
public List<MetadataField> getMetadataFields() {
|
||||
return fields;
|
||||
}
|
||||
public List<String> getExpand() {
|
||||
return expand;
|
||||
}
|
||||
|
||||
public void setExpand(ArrayList<String> expand) {
|
||||
this.expand = expand;
|
||||
}
|
||||
|
||||
public void addExpand(String expandableAttribute) {
|
||||
this.expand.add(expandableAttribute);
|
||||
}
|
||||
}
|
51
dspace-rest/src/main/java/org/dspace/rest/common/Report.java
Normal file
51
dspace-rest/src/main/java/org/dspace/rest/common/Report.java
Normal file
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* 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.rest.common;
|
||||
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
/**
|
||||
* Used to handle/determine status of REST API.
|
||||
* Mainly to know your authentication status
|
||||
*
|
||||
*/
|
||||
@XmlRootElement(name = "report")
|
||||
public class Report
|
||||
{
|
||||
private String nickname;
|
||||
private String url;
|
||||
|
||||
public Report() {
|
||||
setNickname("na");
|
||||
setUrl("");
|
||||
}
|
||||
|
||||
|
||||
public Report(String nickname, String url) {
|
||||
setNickname(nickname);
|
||||
setUrl(url);
|
||||
}
|
||||
public String getUrl()
|
||||
{
|
||||
return this.url;
|
||||
}
|
||||
public String getNickname()
|
||||
{
|
||||
return this.nickname;
|
||||
}
|
||||
|
||||
public void setUrl(String url)
|
||||
{
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public void setNickname(String nickname)
|
||||
{
|
||||
this.nickname = nickname;
|
||||
}
|
||||
}
|
@@ -0,0 +1,144 @@
|
||||
/**
|
||||
* 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.rest.filter;
|
||||
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.core.Context;
|
||||
|
||||
/**
|
||||
* Define the set of use cases for filtering items of interest through the REST API.
|
||||
* @author Terry Brady, Georgetown University
|
||||
*
|
||||
*/
|
||||
|
||||
public class ItemFilterDefs implements ItemFilterList {
|
||||
public static final String CAT_ITEM = "Item Property Filters";
|
||||
public static final String CAT_BASIC = "Basic Bitstream Filters";
|
||||
public static final String CAT_MIME = "Bitstream Filters by MIME Type";
|
||||
private enum EnumItemFilterDefs implements ItemFilterTest {
|
||||
is_item("Is Item - always true", null, CAT_ITEM) {
|
||||
public boolean testItem(Context context, Item item) {
|
||||
return true;
|
||||
}
|
||||
},
|
||||
is_not_withdrawn("Withdrawn Items", null, CAT_ITEM) {
|
||||
public boolean testItem(Context context, Item item) {
|
||||
return item.isWithdrawn();
|
||||
}
|
||||
},
|
||||
is_withdrawn("Available Items - Not Withdrawn", null, CAT_ITEM) {
|
||||
public boolean testItem(Context context, Item item) {
|
||||
return !item.isWithdrawn();
|
||||
}
|
||||
},
|
||||
is_discoverable("Discoverable Items - Not Private", null, CAT_ITEM) {
|
||||
public boolean testItem(Context context, Item item) {
|
||||
return item.isDiscoverable();
|
||||
}
|
||||
},
|
||||
is_not_discoverable("Not Discoverable - Private Item", null, CAT_ITEM) {
|
||||
public boolean testItem(Context context, Item item) {
|
||||
return !item.isDiscoverable();
|
||||
}
|
||||
},
|
||||
has_multiple_originals("Item has Multiple Original Bitstreams", null, CAT_BASIC) {
|
||||
public boolean testItem(Context context, Item item) {
|
||||
return ItemFilterUtil.countOriginalBitstream(item) > 1;
|
||||
}
|
||||
},
|
||||
has_no_originals("Item has No Original Bitstreams", null, CAT_BASIC) {
|
||||
public boolean testItem(Context context, Item item) {
|
||||
return ItemFilterUtil.countOriginalBitstream(item) == 0;
|
||||
}
|
||||
},
|
||||
has_one_original("Item has One Original Bitstream", null, CAT_BASIC) {
|
||||
public boolean testItem(Context context, Item item) {
|
||||
return ItemFilterUtil.countOriginalBitstream(item) == 1;
|
||||
}
|
||||
},
|
||||
has_doc_original("Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", null, CAT_MIME) {
|
||||
public boolean testItem(Context context, Item item) {
|
||||
return ItemFilterUtil.countOriginalBitstreamMime(context, item, ItemFilterUtil.getDocumentMimeTypes()) > 0;
|
||||
}
|
||||
},
|
||||
has_image_original("Item has an Image Original Bitstream", null, CAT_MIME) {
|
||||
public boolean testItem(Context context, Item item) {
|
||||
return ItemFilterUtil.countOriginalBitstreamMimeStartsWith(context, item, "image") > 0;
|
||||
}
|
||||
},
|
||||
has_unsupp_type("Has Other Bitstream Types (not Doc or Image)", null, ItemFilterDefs.CAT_MIME) {
|
||||
public boolean testItem(Context context, Item item) {
|
||||
int bitCount = ItemFilterUtil.countOriginalBitstream(item);
|
||||
if (bitCount == 0) {
|
||||
return false;
|
||||
}
|
||||
int docCount = ItemFilterUtil.countOriginalBitstreamMime(context, item, ItemFilterUtil.getDocumentMimeTypes());
|
||||
int imgCount = ItemFilterUtil.countOriginalBitstreamMimeStartsWith(context, item, "image");
|
||||
return (bitCount - docCount - imgCount) > 0;
|
||||
}
|
||||
},
|
||||
has_mixed_original("Item has multiple types of Original Bitstreams (Doc, Image, Other)", null, CAT_MIME) {
|
||||
public boolean testItem(Context context, Item item) {
|
||||
int countBit = ItemFilterUtil.countOriginalBitstream(item);
|
||||
if (countBit <= 1) return false;
|
||||
int countDoc = ItemFilterUtil.countOriginalBitstreamMime(context, item, ItemFilterUtil.getDocumentMimeTypes());
|
||||
if (countDoc > 0) {
|
||||
return countDoc != countBit;
|
||||
}
|
||||
int countImg = ItemFilterUtil.countOriginalBitstreamMimeStartsWith(context, item, "image");
|
||||
if (countImg > 0) {
|
||||
return countImg != countBit;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
},
|
||||
has_pdf_original("Item has a PDF Original Bitstream", null, CAT_MIME) {
|
||||
public boolean testItem(Context context, Item item) {
|
||||
return ItemFilterUtil.countOriginalBitstreamMime(context, item, "application/pdf") > 0;
|
||||
}
|
||||
},
|
||||
has_jpg_original("Item has JPG Original Bitstream", null, CAT_MIME) {
|
||||
public boolean testItem(Context context, Item item) {
|
||||
return ItemFilterUtil.countOriginalBitstreamMime(context, item, "image/jpeg") > 0;
|
||||
}
|
||||
},
|
||||
;
|
||||
|
||||
private String title = null;
|
||||
private String description = null;
|
||||
private EnumItemFilterDefs(String title, String description, String category) {
|
||||
this.title = title;
|
||||
this.description = description;
|
||||
this.category = category;
|
||||
}
|
||||
|
||||
private EnumItemFilterDefs() {
|
||||
this(null, null, null);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name();
|
||||
}
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
private String category = null;
|
||||
public String getCategory() {
|
||||
return category;
|
||||
}
|
||||
}
|
||||
|
||||
public ItemFilterDefs() {
|
||||
}
|
||||
public ItemFilterTest[] getFilters() {
|
||||
return EnumItemFilterDefs.values();
|
||||
}
|
||||
}
|
@@ -0,0 +1,162 @@
|
||||
/**
|
||||
* 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.rest.filter;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.content.factory.ContentServiceFactory;
|
||||
import org.dspace.content.service.ItemService;
|
||||
import org.dspace.core.ConfigurationManager;
|
||||
import org.dspace.core.Context;
|
||||
|
||||
/**
|
||||
* Define the set of use cases for filtering items of interest through the REST API.
|
||||
* @author Terry Brady, Georgetown University
|
||||
*
|
||||
*/
|
||||
|
||||
public class ItemFilterDefsMeta implements ItemFilterList {
|
||||
protected static ItemService itemService = ContentServiceFactory.getInstance().getItemService();
|
||||
static Logger log = Logger.getLogger(ItemFilterDefsMeta.class);
|
||||
|
||||
public static final String CAT_META_GEN = "General Metadata Filters";
|
||||
public static final String CAT_META_SPEC = "Specific Metadata Filters";
|
||||
public static final String CAT_MOD = "Recently Modified";
|
||||
private enum EnumItemFilterDefs implements ItemFilterTest {
|
||||
has_no_title("Has no dc.title", null, CAT_META_SPEC) {
|
||||
public boolean testItem(Context context, Item item) {
|
||||
return itemService.getMetadataByMetadataString(item, "dc.title").size() == 0;
|
||||
}
|
||||
},
|
||||
has_no_uri("Has no dc.identifier.uri", null, CAT_META_SPEC) {
|
||||
public boolean testItem(Context context, Item item) {
|
||||
return itemService.getMetadataByMetadataString(item, "dc.identifier.uri").size() == 0;
|
||||
}
|
||||
},
|
||||
has_mult_uri("Has multiple dc.identifier.uri", null, CAT_META_SPEC) {
|
||||
public boolean testItem(Context context, Item item) {
|
||||
return itemService.getMetadataByMetadataString(item, "dc.identifier.uri").size() > 1;
|
||||
}
|
||||
},
|
||||
has_compound_subject("Has compound subject", null, CAT_META_SPEC) {
|
||||
public boolean testItem(Context context, Item item) {
|
||||
String regex = ConfigurationManager.getProperty("rest","rest-report-regex-compound-subject");
|
||||
return ItemFilterUtil.hasMetadataMatch(item, "dc.subject.*", Pattern.compile(regex));
|
||||
}
|
||||
},
|
||||
has_compound_author("Has compound author", null, CAT_META_SPEC) {
|
||||
public boolean testItem(Context context, Item item) {
|
||||
String regex = ConfigurationManager.getProperty("rest","rest-report-regex-compound-author");
|
||||
return ItemFilterUtil.hasMetadataMatch(item, "dc.creator,dc.contributor.author", Pattern.compile(regex));
|
||||
}
|
||||
},
|
||||
has_empty_metadata("Has empty metadata", null, CAT_META_GEN) {
|
||||
public boolean testItem(Context context, Item item) {
|
||||
return ItemFilterUtil.hasMetadataMatch(item, "*", Pattern.compile("^\\s*$"));
|
||||
}
|
||||
},
|
||||
has_unbreaking_metadata("Has unbreaking metadata", null, CAT_META_GEN) {
|
||||
public boolean testItem(Context context, Item item) {
|
||||
String regex = ConfigurationManager.getProperty("rest","rest-report-regex-unbreaking");
|
||||
return ItemFilterUtil.hasMetadataMatch(item, "*", Pattern.compile(regex));
|
||||
}
|
||||
},
|
||||
has_long_metadata("Has long metadata field", null, CAT_META_GEN) {
|
||||
public boolean testItem(Context context, Item item) {
|
||||
String regex = ConfigurationManager.getProperty("rest","rest-report-regex-long");
|
||||
return ItemFilterUtil.hasMetadataMatch(item, "*", Pattern.compile(regex));
|
||||
}
|
||||
},
|
||||
has_xml_entity("Has XML entity in metadata", null, CAT_META_GEN) {
|
||||
public boolean testItem(Context context, Item item) {
|
||||
String regex = ConfigurationManager.getProperty("rest","rest-report-regex-xml-entity");
|
||||
return ItemFilterUtil.hasMetadataMatch(item, "*", Pattern.compile(regex));
|
||||
}
|
||||
},
|
||||
has_non_ascii("Has non-ascii in metadata", null, CAT_META_GEN) {
|
||||
public boolean testItem(Context context, Item item) {
|
||||
String regex = ConfigurationManager.getProperty("rest","rest-report-regex-non-ascii");
|
||||
return ItemFilterUtil.hasMetadataMatch(item, "*", Pattern.compile(regex));
|
||||
}
|
||||
},
|
||||
has_desc_url("Has url in description", null, CAT_META_SPEC) {
|
||||
public boolean testItem(Context context, Item item) {
|
||||
String regex = ConfigurationManager.getProperty("rest","rest-report-regex-url");
|
||||
return ItemFilterUtil.hasMetadataMatch(item, "dc.description.*", Pattern.compile(regex));
|
||||
}
|
||||
},
|
||||
has_fulltext_provenance("Has fulltext in provenance", null, CAT_META_SPEC) {
|
||||
public boolean testItem(Context context, Item item) {
|
||||
String regex = ConfigurationManager.getProperty("rest","rest-report-regex-fulltext");
|
||||
return ItemFilterUtil.hasMetadataMatch(item, "dc.description.provenance", Pattern.compile(regex));
|
||||
}
|
||||
},
|
||||
no_fulltext_provenance("Doesn't have fulltext in provenance", null, CAT_META_SPEC) {
|
||||
public boolean testItem(Context context, Item item) {
|
||||
String regex = ConfigurationManager.getProperty("rest","rest-report-regex-fulltext");
|
||||
return !ItemFilterUtil.hasMetadataMatch(item, "dc.description.provenance", Pattern.compile(regex));
|
||||
}
|
||||
},
|
||||
mod_last_day("Modified in last 1 day", null, CAT_MOD) {
|
||||
public boolean testItem(Context context, Item item) {
|
||||
return ItemFilterUtil.recentlyModified(item, 1);
|
||||
}
|
||||
},
|
||||
mod_last_7_days("Modified in last 7 days", null, CAT_MOD) {
|
||||
public boolean testItem(Context context, Item item) {
|
||||
return ItemFilterUtil.recentlyModified(item, 7);
|
||||
}
|
||||
},
|
||||
mod_last_30_days("Modified in last 30 days", null, CAT_MOD) {
|
||||
public boolean testItem(Context context, Item item) {
|
||||
return ItemFilterUtil.recentlyModified(item, 30);
|
||||
}
|
||||
},
|
||||
mod_last_90_days("Modified in last 60 days", null, CAT_MOD) {
|
||||
public boolean testItem(Context context, Item item) {
|
||||
return ItemFilterUtil.recentlyModified(item, 60);
|
||||
}
|
||||
},
|
||||
;
|
||||
|
||||
private String title = null;
|
||||
private String description = null;
|
||||
private EnumItemFilterDefs(String title, String description, String category) {
|
||||
this.title = title;
|
||||
this.description = description;
|
||||
this.category = category;
|
||||
}
|
||||
|
||||
private EnumItemFilterDefs() {
|
||||
this(null, null, null);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name();
|
||||
}
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
private String category = null;
|
||||
public String getCategory() {
|
||||
return category;
|
||||
}
|
||||
}
|
||||
|
||||
public ItemFilterDefsMeta() {
|
||||
}
|
||||
public ItemFilterTest[] getFilters() {
|
||||
return EnumItemFilterDefs.values();
|
||||
}
|
||||
}
|
@@ -0,0 +1,185 @@
|
||||
/**
|
||||
* 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.rest.filter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.core.ConfigurationManager;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.rest.filter.ItemFilterUtil.BundleName;
|
||||
|
||||
/**
|
||||
* Define the set of use cases for filtering items of interest through the REST API.
|
||||
* @author Terry Brady, Georgetown University
|
||||
*
|
||||
*/
|
||||
|
||||
public class ItemFilterDefsMisc implements ItemFilterList {
|
||||
public static final String CAT_MISC = "Bitstream Bundle Filters";
|
||||
public static final String CAT_MIME_SUPP = "Supported MIME Type Filters";
|
||||
private enum EnumItemFilterDefs implements ItemFilterTest {
|
||||
has_only_supp_image_type("Item Image Bitstreams are Supported", null, CAT_MIME_SUPP) {
|
||||
public boolean testItem(Context context, Item item) {
|
||||
int imageCount = ItemFilterUtil.countOriginalBitstreamMimeStartsWith(context, item, "image/");
|
||||
if (imageCount == 0) {
|
||||
return false;
|
||||
}
|
||||
int suppImageCount = ItemFilterUtil.countOriginalBitstreamMime(context, item, ItemFilterUtil.getSupportedImageMimeTypes());
|
||||
return (imageCount == suppImageCount);
|
||||
}
|
||||
},
|
||||
has_unsupp_image_type("Item has Image Bitstream that is Unsupported", null, CAT_MIME_SUPP) {
|
||||
public boolean testItem(Context context, Item item) {
|
||||
int imageCount = ItemFilterUtil.countOriginalBitstreamMimeStartsWith(context, item, "image/");
|
||||
if (imageCount == 0) {
|
||||
return false;
|
||||
}
|
||||
int suppImageCount = ItemFilterUtil.countOriginalBitstreamMime(context, item, ItemFilterUtil.getSupportedImageMimeTypes());
|
||||
return (imageCount - suppImageCount) > 0;
|
||||
}
|
||||
},
|
||||
has_only_supp_doc_type("Item Document Bitstreams are Supported", null, CAT_MIME_SUPP) {
|
||||
public boolean testItem(Context context, Item item) {
|
||||
int docCount = ItemFilterUtil.countOriginalBitstreamMime(context, item, ItemFilterUtil.getDocumentMimeTypes());
|
||||
if (docCount == 0) {
|
||||
return false;
|
||||
}
|
||||
int suppDocCount = ItemFilterUtil.countOriginalBitstreamMime(context, item, ItemFilterUtil.getSupportedDocumentMimeTypes());
|
||||
return docCount == suppDocCount;
|
||||
}
|
||||
},
|
||||
has_unsupp_doc_type("Item has Document Bitstream that is Unsupported", null, CAT_MIME_SUPP) {
|
||||
public boolean testItem(Context context, Item item) {
|
||||
int docCount = ItemFilterUtil.countOriginalBitstreamMime(context, item, ItemFilterUtil.getDocumentMimeTypes());
|
||||
if (docCount == 0) {
|
||||
return false;
|
||||
}
|
||||
int suppDocCount = ItemFilterUtil.countOriginalBitstreamMime(context, item, ItemFilterUtil.getSupportedDocumentMimeTypes());
|
||||
return (docCount - suppDocCount) > 0;
|
||||
}
|
||||
},
|
||||
has_small_pdf("Has unusually small PDF", null, ItemFilterDefs.CAT_MIME) {
|
||||
public boolean testItem(Context context, Item item) {
|
||||
return ItemFilterUtil.countBitstreamSmallerThanMinSize(context, BundleName.ORIGINAL, item, "application/pdf", "rest-report-pdf-min-size") > 0;
|
||||
}
|
||||
},
|
||||
has_large_pdf("Has unusually large PDF", null, ItemFilterDefs.CAT_MIME) {
|
||||
public boolean testItem(Context context, Item item) {
|
||||
return ItemFilterUtil.countBitstreamLargerThanMaxSize(context, BundleName.ORIGINAL, item, "application/pdf", "rest-report-pdf-max-size") > 0;
|
||||
}
|
||||
},
|
||||
has_unsupported_bundle("Has bitstream in an unsuppored bundle", null, CAT_MISC) {
|
||||
public boolean testItem(Context context, Item item) {
|
||||
String bundleList = ConfigurationManager.getProperty("rest","rest-report-supp-bundles");
|
||||
return ItemFilterUtil.hasUnsupportedBundle(item, bundleList);
|
||||
}
|
||||
},
|
||||
has_small_thumbnail("Has unusually small thumbnail", null, CAT_MISC) {
|
||||
public boolean testItem(Context context, Item item) {
|
||||
return ItemFilterUtil.countBitstreamSmallerThanMinSize(context, BundleName.THUMBNAIL, item, "image/jpeg", "rest-report-thumbnail-min-size") > 0;
|
||||
}
|
||||
},
|
||||
has_doc_without_text("Has document bitstream without TEXT item", null, ItemFilterDefs.CAT_MIME) {
|
||||
public boolean testItem(Context context, Item item) {
|
||||
int countDoc = ItemFilterUtil.countOriginalBitstreamMime(context, item, ItemFilterUtil.getDocumentMimeTypes());
|
||||
if (countDoc == 0) {
|
||||
return false;
|
||||
}
|
||||
int countText = ItemFilterUtil.countBitstream(BundleName.TEXT, item);
|
||||
return countDoc > countText;
|
||||
}
|
||||
},
|
||||
has_original_without_thumbnail("Has original bitstream without thumbnail", null, CAT_MISC) {
|
||||
public boolean testItem(Context context, Item item) {
|
||||
int countBit = ItemFilterUtil.countOriginalBitstream(item);
|
||||
if (countBit == 0) {
|
||||
return false;
|
||||
}
|
||||
int countThumb = ItemFilterUtil.countBitstream(BundleName.THUMBNAIL, item);
|
||||
return countBit > countThumb;
|
||||
}
|
||||
},
|
||||
has_invalid_thumbnail_name("Has invalid thumbnail name (assumes one thumbnail for each original)", null, CAT_MISC) {
|
||||
public boolean testItem(Context context, Item item) {
|
||||
List<String> originalNames = ItemFilterUtil.getBitstreamNames(BundleName.ORIGINAL, item);
|
||||
List<String> thumbNames = ItemFilterUtil.getBitstreamNames(BundleName.THUMBNAIL, item);
|
||||
if (thumbNames.size() != originalNames.size()) {
|
||||
return false;
|
||||
}
|
||||
for(String name: originalNames) {
|
||||
if (!thumbNames.contains(name+".jpg")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
},
|
||||
has_non_generated_thumb("Has non generated thumbnail", null, CAT_MISC) {
|
||||
public boolean testItem(Context context, Item item) {
|
||||
String generatedThumbDesc = ConfigurationManager.getProperty("rest","rest-report-gen-thumbnail-desc");
|
||||
int countThumb = ItemFilterUtil.countBitstream(BundleName.THUMBNAIL, item);
|
||||
if (countThumb == 0) {
|
||||
return false;
|
||||
}
|
||||
int countGen = ItemFilterUtil.countBitstreamByDesc(BundleName.THUMBNAIL, item, generatedThumbDesc);
|
||||
return (countThumb > countGen);
|
||||
}
|
||||
},
|
||||
no_license("Doesn't have a license", null, CAT_MISC) {
|
||||
public boolean testItem(Context context, Item item) {
|
||||
return ItemFilterUtil.countBitstream(BundleName.LICENSE, item) == 0;
|
||||
}
|
||||
},
|
||||
has_license_documentation("Has documentation in the license bundle", null, CAT_MISC) {
|
||||
public boolean testItem(Context context, Item item) {
|
||||
List<String> names = ItemFilterUtil.getBitstreamNames(BundleName.LICENSE, item);
|
||||
for(String name: names) {
|
||||
if (!name.equals("license.txt")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
},
|
||||
;
|
||||
|
||||
private String title = null;
|
||||
private String description = null;
|
||||
private EnumItemFilterDefs(String title, String description, String category) {
|
||||
this.title = title;
|
||||
this.description = description;
|
||||
this.category = category;
|
||||
}
|
||||
|
||||
private EnumItemFilterDefs() {
|
||||
this(null, null, null);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name();
|
||||
}
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
private String category = null;
|
||||
public String getCategory() {
|
||||
return category;
|
||||
}
|
||||
}
|
||||
|
||||
public ItemFilterDefsMisc() {
|
||||
}
|
||||
public ItemFilterTest[] getFilters() {
|
||||
return EnumItemFilterDefs.values();
|
||||
}
|
||||
}
|
@@ -0,0 +1,126 @@
|
||||
/**
|
||||
* 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.rest.filter;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.dspace.authorize.factory.AuthorizeServiceFactory;
|
||||
import org.dspace.authorize.service.AuthorizeService;
|
||||
import org.dspace.content.Bitstream;
|
||||
import org.dspace.content.Bundle;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.rest.filter.ItemFilterUtil.BundleName;
|
||||
|
||||
/**
|
||||
* Define the set of use cases for filtering items of interest through the REST API.
|
||||
* @author Terry Brady, Georgetown University
|
||||
*
|
||||
*/
|
||||
public class ItemFilterDefsPerm implements ItemFilterList {
|
||||
protected static AuthorizeService authorizeService = AuthorizeServiceFactory.getInstance().getAuthorizeService();
|
||||
public static final String CAT_PERM = "Perimission Filters";
|
||||
private static Logger log = Logger.getLogger(ItemFilterDefsPerm.class);
|
||||
public ItemFilterDefsPerm(){
|
||||
}
|
||||
public enum EnumItemFilterPermissionDefs implements ItemFilterTest {
|
||||
has_restricted_original("Item has Restricted Original Bitstream",
|
||||
"Item has at least one original bitstream that is not accessible to Anonymous user", CAT_PERM) {
|
||||
public boolean testItem(Context context, Item item) {
|
||||
try {
|
||||
for(Bundle bundle: item.getBundles()){
|
||||
if (!bundle.getName().equals(BundleName.ORIGINAL)) {
|
||||
continue;
|
||||
}
|
||||
for(Bitstream bit: bundle.getBitstreams()) {
|
||||
if (!authorizeService.authorizeActionBoolean(getAnonContext(), bit, org.dspace.core.Constants.READ)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
ItemFilterDefsPerm.log.warn("SQL Exception testing original bitstream access " + e.getMessage(), e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
},
|
||||
has_restricted_thumbnail("Item has Restricted Thumbnail",
|
||||
"Item has at least one thumbnail that is not accessible to Anonymous user", CAT_PERM) {
|
||||
public boolean testItem(Context context, Item item) {
|
||||
try {
|
||||
for(Bundle bundle: item.getBundles()){
|
||||
if (!bundle.getName().equals(BundleName.THUMBNAIL)) {
|
||||
continue;
|
||||
}
|
||||
for(Bitstream bit: bundle.getBitstreams()) {
|
||||
if (!authorizeService.authorizeActionBoolean(getAnonContext(), bit, org.dspace.core.Constants.READ)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
ItemFilterDefsPerm.log.warn("SQL Exception testing thumbnail bitstream access " + e.getMessage(), e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
},
|
||||
has_restricted_metadata("Item has Restricted Metadata",
|
||||
"Item has metadata that is not accessible to Anonymous user", CAT_PERM) {
|
||||
public boolean testItem(Context context, Item item) {
|
||||
try {
|
||||
return !authorizeService.authorizeActionBoolean(getAnonContext(), item, org.dspace.core.Constants.READ);
|
||||
} catch (SQLException e) {
|
||||
ItemFilterDefsPerm.log.warn("SQL Exception testing item metadata access " + e.getMessage(), e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
},
|
||||
;
|
||||
|
||||
private static Context anonContext;
|
||||
private static Context getAnonContext() {
|
||||
if (anonContext == null) {
|
||||
anonContext = new Context();
|
||||
}
|
||||
return anonContext;
|
||||
}
|
||||
|
||||
|
||||
private String title = null;
|
||||
private String description = null;
|
||||
private EnumItemFilterPermissionDefs(String title, String description, String category) {
|
||||
this.title = title;
|
||||
this.description = description;
|
||||
this.category = category;
|
||||
}
|
||||
|
||||
private EnumItemFilterPermissionDefs() {
|
||||
this(null, null, null);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name();
|
||||
}
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
private String category = null;
|
||||
public String getCategory() {
|
||||
return category;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemFilterTest[] getFilters() {
|
||||
return EnumItemFilterPermissionDefs.values();
|
||||
}
|
||||
}
|
@@ -0,0 +1,12 @@
|
||||
/**
|
||||
* 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.rest.filter;
|
||||
|
||||
public interface ItemFilterList {
|
||||
public ItemFilterTest[] getFilters();
|
||||
}
|
@@ -0,0 +1,148 @@
|
||||
/**
|
||||
* 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.rest.filter;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import javax.ws.rs.WebApplicationException;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.dspace.authorize.factory.AuthorizeServiceFactory;
|
||||
import org.dspace.authorize.service.AuthorizeService;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.rest.common.Item;
|
||||
import org.dspace.rest.common.ItemFilter;
|
||||
|
||||
/**
|
||||
* The set of Item Filter Use Cases to apply to a collection of items.
|
||||
*
|
||||
* @author Terry Brady, Georgetown University
|
||||
*
|
||||
*/
|
||||
public class ItemFilterSet {
|
||||
protected AuthorizeService authorizeService = AuthorizeServiceFactory.getInstance().getAuthorizeService();
|
||||
static Logger log = Logger.getLogger(ItemFilterSet.class);
|
||||
|
||||
private List<ItemFilter> itemFilters;
|
||||
private ItemFilter allFiltersFilter;
|
||||
|
||||
/**
|
||||
* Construct a set of Item Filters identified by a list string.
|
||||
*
|
||||
* @param filterList
|
||||
* Comma separated list of filter names to include
|
||||
* @see ItemFilter.ALL to retrieve all filters
|
||||
* @param reportItems
|
||||
* If true, return item details. If false, return only counts of items.
|
||||
*
|
||||
* @author Terry Brady, Georgetown University
|
||||
*
|
||||
*/
|
||||
public ItemFilterSet(String filterList, boolean reportItems) {
|
||||
log.debug(String.format("Create ItemFilterSet: %s", filterList));
|
||||
itemFilters = ItemFilter.getItemFilters(filterList, reportItems);
|
||||
allFiltersFilter = ItemFilter.getAllFiltersFilter(itemFilters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the special filter that represents the intersection of all items in the Item Filter Set.
|
||||
* @return the special Item Filter that contains items that satisfied every other Item Filter in the Item Filter Set
|
||||
*/
|
||||
public ItemFilter getAllFiltersFilter() {
|
||||
return allFiltersFilter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate an item against the use cases in the Item Filter Set.
|
||||
*
|
||||
* If an item satisfies all items in the Item Filter Set, it should also ve added to the special all items filter.
|
||||
*
|
||||
* @param context
|
||||
* Active DSpace Context
|
||||
* @param item
|
||||
* DSpace Object to evaluate
|
||||
* @param restItem
|
||||
* REST representation of the DSpace Object being evaluated
|
||||
*/
|
||||
public void testItem(Context context, org.dspace.content.Item item, Item restItem) {
|
||||
boolean bAllTrue = true;
|
||||
for(ItemFilter itemFilter: itemFilters) {
|
||||
if (itemFilter.hasItemTest()) {
|
||||
bAllTrue &= itemFilter.testItem(context, item, restItem);
|
||||
}
|
||||
}
|
||||
if (bAllTrue && allFiltersFilter != null) {
|
||||
allFiltersFilter.addItem(restItem);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the Item Filters initialized into the Item Filter Sest
|
||||
* @return a list of Item Filters initialized into the Item Filter Set
|
||||
*/
|
||||
public List<ItemFilter> getItemFilters() {
|
||||
return itemFilters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate a set of Items against the Item Filters in the Item Filter Set
|
||||
* Current DSpace Context
|
||||
* @param childItems
|
||||
* Collection of Items to Evaluate
|
||||
* @param save
|
||||
* If true, save the details of each item that is evaluated
|
||||
* @param expand
|
||||
* List of item details to include in the results
|
||||
* @return
|
||||
* The number of items evaluated
|
||||
* @throws WebApplicationException
|
||||
* @throws SQLException
|
||||
*/
|
||||
public int processSaveItems(Context context, Iterator<org.dspace.content.Item> childItems, boolean save, String expand) throws WebApplicationException, SQLException {
|
||||
return processSaveItems(context, childItems, new ArrayList<Item>(), save, expand);
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate a set of Items against the Item Filters in the Item Filter Set
|
||||
* Current DSpace Context
|
||||
* @param childItems
|
||||
* Collection of Items to Evaluate
|
||||
* @param items
|
||||
* List of items to contain saved results
|
||||
* @param save
|
||||
* If true, save the details of each item that is evaluated
|
||||
* @param expand
|
||||
* List of item details to include in the results
|
||||
* @return
|
||||
* The number of items evaluated
|
||||
* @throws WebApplicationException
|
||||
* @throws SQLException
|
||||
*/
|
||||
public int processSaveItems(Context context, Iterator<org.dspace.content.Item> childItems, List<Item> items, boolean save, String expand) throws WebApplicationException, SQLException {
|
||||
int count = 0;
|
||||
while(childItems.hasNext()) {
|
||||
count++;
|
||||
org.dspace.content.Item item = childItems.next();
|
||||
log.debug(item.getHandle() + " evaluate.");
|
||||
if(authorizeService.authorizeActionBoolean(context, item, org.dspace.core.Constants.READ)) {
|
||||
Item restItem = new Item(item, expand, context);
|
||||
if(save) {
|
||||
items.add(restItem);
|
||||
}
|
||||
testItem(context, item, restItem);
|
||||
} else {
|
||||
log.debug(item.getHandle() + " not authorized - not included in result set.");
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* 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.rest.filter;
|
||||
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.core.Context;
|
||||
|
||||
/**
|
||||
* Item Filter Use Case Interface.
|
||||
* Items will be evaluated against a set of filters.
|
||||
*
|
||||
* @author Terry Brady, Georgetown University
|
||||
*
|
||||
*/
|
||||
public interface ItemFilterTest {
|
||||
public String getName();
|
||||
public String getTitle();
|
||||
public String getDescription();
|
||||
public String getCategory();
|
||||
public boolean testItem(Context context, Item i);
|
||||
}
|
@@ -0,0 +1,257 @@
|
||||
/**
|
||||
* 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.rest.filter;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.dspace.content.Bitstream;
|
||||
import org.dspace.content.Bundle;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.content.MetadataValue;
|
||||
import org.dspace.content.factory.ContentServiceFactory;
|
||||
import org.dspace.content.service.ItemService;
|
||||
import org.dspace.core.ConfigurationManager;
|
||||
import org.dspace.core.Context;
|
||||
|
||||
import com.ibm.icu.util.Calendar;
|
||||
|
||||
public class ItemFilterUtil {
|
||||
protected static ItemService itemService = ContentServiceFactory.getInstance().getItemService();
|
||||
static Logger log = Logger.getLogger(ItemFilterUtil.class);
|
||||
public enum BundleName{ORIGINAL,TEXT,LICENSE,THUMBNAIL;}
|
||||
|
||||
static String getDocumentMimeTypes() {
|
||||
return ConfigurationManager.getProperty("rest", "rest-report-mime-document");
|
||||
}
|
||||
|
||||
static String getSupportedDocumentMimeTypes() {
|
||||
return ConfigurationManager.getProperty("rest", "rest-report-mime-document-supported");
|
||||
}
|
||||
|
||||
static String getSupportedImageMimeTypes() {
|
||||
return ConfigurationManager.getProperty("rest", "rest-report-mime-document-image");
|
||||
}
|
||||
|
||||
static int countOriginalBitstream(Item item) {
|
||||
return countBitstream(BundleName.ORIGINAL, item);
|
||||
}
|
||||
static int countBitstream(BundleName bundleName, Item item) {
|
||||
int count = 0;
|
||||
for(Bundle bundle: item.getBundles()){
|
||||
if (!bundle.getName().equals(bundleName.name())){
|
||||
continue;
|
||||
}
|
||||
count += bundle.getBitstreams().size();
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static List<String> getBitstreamNames(BundleName bundleName, Item item) {
|
||||
ArrayList<String> names = new ArrayList<String>();
|
||||
for(Bundle bundle: item.getBundles()){
|
||||
if (!bundle.getName().equals(bundleName.name())){
|
||||
continue;
|
||||
}
|
||||
for(Bitstream bit: bundle.getBitstreams()) {
|
||||
names.add(bit.getName());
|
||||
}
|
||||
}
|
||||
return names;
|
||||
}
|
||||
|
||||
|
||||
static int countOriginalBitstreamMime(Context context, Item item, String mimeList) {
|
||||
return countBitstreamMime(context, BundleName.ORIGINAL, item, mimeList);
|
||||
}
|
||||
static int countBitstreamMime(Context context, BundleName bundleName, Item item, String mimeList) {
|
||||
int count = 0;
|
||||
for(Bundle bundle: item.getBundles()){
|
||||
if (!bundle.getName().equals(bundleName.name())){
|
||||
continue;
|
||||
}
|
||||
for(Bitstream bit: bundle.getBitstreams()) {
|
||||
for(String mime: mimeList.split(",")) {
|
||||
try {
|
||||
if (bit.getFormat(context).getMIMEType().equals(mime.trim())) {
|
||||
count++;
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
log.error("Get format error for bitstream " + bit.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static int countBitstreamByDesc(BundleName bundleName, Item item, String descList) {
|
||||
int count = 0;
|
||||
for(Bundle bundle: item.getBundles()){
|
||||
if (!bundle.getName().equals(bundleName.name())){
|
||||
continue;
|
||||
}
|
||||
for(Bitstream bit: bundle.getBitstreams()) {
|
||||
for(String desc: descList.split(",")) {
|
||||
String bitDesc = bit.getDescription();
|
||||
if (bitDesc == null) {
|
||||
continue;
|
||||
}
|
||||
if (bitDesc.equals(desc.trim())) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static int countBitstreamSmallerThanMinSize(Context context, BundleName bundleName, Item item, String mimeList, String prop) {
|
||||
long size = ConfigurationManager.getLongProperty("rest", prop);
|
||||
int count = 0;
|
||||
try {
|
||||
for(Bundle bundle: item.getBundles()){
|
||||
if (!bundle.getName().equals(bundleName.name())){
|
||||
continue;
|
||||
}
|
||||
for(Bitstream bit: bundle.getBitstreams()) {
|
||||
for(String mime: mimeList.split(",")) {
|
||||
if (bit.getFormat(context).getMIMEType().equals(mime.trim())) {
|
||||
if (bit.getSize() < size) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static int countBitstreamLargerThanMaxSize(Context context, BundleName bundleName, Item item, String mimeList, String prop) {
|
||||
long size = ConfigurationManager.getLongProperty("rest", prop);
|
||||
int count = 0;
|
||||
try {
|
||||
for(Bundle bundle: item.getBundles()){
|
||||
if (!bundle.getName().equals(bundleName.name())){
|
||||
continue;
|
||||
}
|
||||
for(Bitstream bit: bundle.getBitstreams()) {
|
||||
for(String mime: mimeList.split(",")) {
|
||||
if (bit.getFormat(context).getMIMEType().equals(mime.trim())) {
|
||||
if (bit.getSize() > size) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static int countOriginalBitstreamMimeStartsWith(Context context, Item item, String prefix) {
|
||||
return countBitstreamMimeStartsWith(context, BundleName.ORIGINAL, item, prefix);
|
||||
}
|
||||
static int countBitstreamMimeStartsWith(Context context, BundleName bundleName, Item item, String prefix) {
|
||||
int count = 0;
|
||||
try {
|
||||
for(Bundle bundle: item.getBundles()){
|
||||
if (!bundle.getName().equals(bundleName.name())){
|
||||
continue;
|
||||
}
|
||||
for(Bitstream bit: bundle.getBitstreams()) {
|
||||
if (bit.getFormat(context).getMIMEType().startsWith(prefix)) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static boolean hasUnsupportedBundle(Item item, String bundleList) {
|
||||
if (bundleList == null) {
|
||||
return false;
|
||||
}
|
||||
ArrayList<String> bundles = new ArrayList<String>();
|
||||
for(String bundleName: bundleList.split(",")) {
|
||||
bundles.add(bundleName.trim());
|
||||
}
|
||||
for(Bundle bundle: item.getBundles()) {
|
||||
if (!bundles.contains(bundle.getName())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
static boolean hasOriginalBitstreamMime(Context context, Item item, String mimeList) {
|
||||
return hasBitstreamMime(context, BundleName.ORIGINAL, item, mimeList);
|
||||
}
|
||||
static boolean hasBitstreamMime(Context context, BundleName bundleName, Item item, String mimeList) {
|
||||
return countBitstreamMime(context, bundleName, item, mimeList) > 0;
|
||||
}
|
||||
|
||||
static boolean hasMetadataMatch(Item item, String fieldList, Pattern regex) {
|
||||
if (fieldList.equals("*")) {
|
||||
for(MetadataValue md: itemService.getMetadata(item, org.dspace.content.Item.ANY, org.dspace.content.Item.ANY, org.dspace.content.Item.ANY, org.dspace.content.Item.ANY)){
|
||||
if (regex.matcher(md.getValue()).matches()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for(String field: fieldList.split(",")) {
|
||||
for(MetadataValue md: itemService.getMetadataByMetadataString(item, field.trim())){
|
||||
if (regex.matcher(md.getValue()).matches()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static boolean hasOnlyMetadataMatch(Item item, String fieldList, Pattern regex) {
|
||||
boolean matches = false;
|
||||
if (fieldList.equals("*")) {
|
||||
for(MetadataValue md: itemService.getMetadata(item, org.dspace.content.Item.ANY, org.dspace.content.Item.ANY, org.dspace.content.Item.ANY, org.dspace.content.Item.ANY)){
|
||||
if (regex.matcher(md.getValue()).matches()) {
|
||||
matches = true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for(String field: fieldList.split(",")) {
|
||||
for(MetadataValue md: itemService.getMetadataByMetadataString(item, field.trim())){
|
||||
if (regex.matcher(md.getValue()).matches()) {
|
||||
matches = true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return matches;
|
||||
}
|
||||
|
||||
static boolean recentlyModified(Item item, int days) {
|
||||
Calendar cal = Calendar.getInstance();
|
||||
cal.add(Calendar.DATE, -days);
|
||||
return cal.getTime().before(item.getLastModified());
|
||||
}
|
||||
}
|
@@ -42,6 +42,11 @@
|
||||
<url-pattern>/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>default</servlet-name>
|
||||
<url-pattern>/static/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<!-- Security settings and mapping -->
|
||||
<security-constraint>
|
||||
<web-resource-collection>
|
||||
|
66
dspace-rest/src/main/webapp/static/reports/index.html
Normal file
66
dspace-rest/src/main/webapp/static/reports/index.html
Normal file
@@ -0,0 +1,66 @@
|
||||
<!--
|
||||
|
||||
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/
|
||||
|
||||
-->
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
|
||||
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.9.1/jquery-ui.min.js"></script>
|
||||
|
||||
<!-- sortable.js can be obtained at http://www.kryogenix.org/code/browser/sorttable/ -->
|
||||
<!-- <script src="sorttable.js"></script> -->
|
||||
|
||||
<script src="restReport.js"></script>
|
||||
<script src="restCollReport.js"></script>
|
||||
<script src="spin.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/themes/smoothness/jquery-ui.css"></link>
|
||||
<link rel="stylesheet" type="text/css" href="restClient.css"></link>
|
||||
<title>DSpace REST QC Client</title>
|
||||
</head>
|
||||
<body>
|
||||
<a href="query.html">Query Tool</a>
|
||||
<hr/>
|
||||
<h1>DSpace REST QC Client</h1>
|
||||
<div id='metadatadiv'>
|
||||
<h3>Filters</h3>
|
||||
<div>
|
||||
<div>
|
||||
<button disabled="disabled" class="activate showCollections">Show Collections</button>
|
||||
</div>
|
||||
<div id='filterdiv'>
|
||||
</div>
|
||||
<div>
|
||||
<button disabled="disabled" class="activate showCollections">Show Collections</button>
|
||||
</div>
|
||||
</div>
|
||||
<h3>Collection Report</h3>
|
||||
<div>
|
||||
<div><a class="this-search" href="#">URL to current search</a></div>
|
||||
<div id="report">..</div>
|
||||
</div>
|
||||
<h3>Item Results</h3>
|
||||
<div id="itemResults">
|
||||
<h3>Additional data to return</h3>
|
||||
<div id="queries-aux">
|
||||
<button id="refresh-fields">Refresh Items</button>
|
||||
<div id="show-fields"></div>
|
||||
</div>
|
||||
<h3>Results</h3>
|
||||
<div id='itemdiv'>
|
||||
<h3></h3>
|
||||
<div><a class="this-search" href="#">URL to current search</a></div>
|
||||
<div><button id="prev">Prev Page</button><button id="next">Next Page</button><button id="export">Export for Metadata Update</button></div>
|
||||
<input type="hidden" id="ifilter"/>
|
||||
<input type="hidden" id="icollection"/>
|
||||
<table id="itemtable" class="sortable"></table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
94
dspace-rest/src/main/webapp/static/reports/query.html
Normal file
94
dspace-rest/src/main/webapp/static/reports/query.html
Normal file
@@ -0,0 +1,94 @@
|
||||
<!--
|
||||
|
||||
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/
|
||||
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
|
||||
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.9.1/jquery-ui.min.js"></script>
|
||||
|
||||
<!-- sortable.js can be obtained at http://www.kryogenix.org/code/browser/sorttable/ -->
|
||||
<!-- <script src="sorttable.js"></script> -->
|
||||
|
||||
<script src="restReport.js"></script>
|
||||
<script src="restQueryReport.js"></script>
|
||||
<script src="spin.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/themes/smoothness/jquery-ui.css"></link>
|
||||
<link rel="stylesheet" type="text/css" href="restClient.css"></link>
|
||||
<title>DSpace REST Query Client</title>
|
||||
</head>
|
||||
<body>
|
||||
<a href="index.html">Collection Filter</a>
|
||||
<hr/>
|
||||
<h1>DSpace REST Query Client</h1>
|
||||
<div id="querydiv">
|
||||
<div id='metadatadiv'>
|
||||
<h3>Collection Selector</h3>
|
||||
<div id="collSelector">
|
||||
</div>
|
||||
<h3>Metadata Field Queries</h3>
|
||||
<div>
|
||||
<fieldset id="predefqueries">
|
||||
<label>Pre-defined Queries</label>
|
||||
<select id="predefselect">
|
||||
</select>
|
||||
</fieldset>
|
||||
<div id="queries">
|
||||
</div>
|
||||
<div>
|
||||
<button class="query-button" disabled="disabled" class="activate">Run Item Query</button>
|
||||
</div>
|
||||
</div>
|
||||
<h3>Limit/Paginate Queries</h3>
|
||||
<div id="queries-page">
|
||||
<div>
|
||||
<label for="limit">Limit:</label>
|
||||
<select id="limit" name="limit">
|
||||
<option value="10">10</option>
|
||||
<option value="25">25</option>
|
||||
<option value="50">50</option>
|
||||
<option value="100" selected>100</option>
|
||||
<option value="250">250</option>
|
||||
<option value="1000">1000</option>
|
||||
</select>
|
||||
<label for="offset"> Offset:</label><input id="offset" name="offset" value="0"/>
|
||||
</div>
|
||||
<div>
|
||||
<button class="query-button" disabled="disabled" class="activate">Run Item Query</button>
|
||||
</div>
|
||||
</div>
|
||||
<h3>Filters</h3>
|
||||
<div>
|
||||
<div>
|
||||
<button class="query-button" disabled="disabled" class="activate">Run Item Query</button>
|
||||
</div>
|
||||
<div id='filterdiv'>
|
||||
</div>
|
||||
<div>
|
||||
<button class="query-button" disabled="disabled" class="activate">Run Item Query</button>
|
||||
</div>
|
||||
</div>
|
||||
<h3>Additional data to return</h3>
|
||||
<div id="queries-aux">
|
||||
<div id="show-fields"></div>
|
||||
<div>
|
||||
<button class="query-button" disabled="disabled" class="activate">Run Item Query</button>
|
||||
</div>
|
||||
</div>
|
||||
<h3>Item Results</h3>
|
||||
<div id='itemdiv'>
|
||||
<h3></h3>
|
||||
<div><a class="this-search" href="#">URL to current search</a></div>
|
||||
<div><button id="prev">Prev Page</button><button id="next">Next Page</button><button id="export">Export for Metadata Update</button></div>
|
||||
<table id="itemtable" class="sortable">
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
82
dspace-rest/src/main/webapp/static/reports/restClient.css
Normal file
82
dspace-rest/src/main/webapp/static/reports/restClient.css
Normal file
@@ -0,0 +1,82 @@
|
||||
/**
|
||||
* 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/
|
||||
*/
|
||||
table {border-collapse: collapse;border-right:solid thin black;}
|
||||
table td, table th {border: thin solid black; padding: 4px;}
|
||||
tr.header {background-color: #EEEEEE;}
|
||||
tr:hover td, tr:hover th {background-color: #DDDDDD;}
|
||||
tr.even td {border-bottom: thin dotted black;}
|
||||
tr.odd td {border-top: thin dotted black;}
|
||||
td.even {background-color: #EEFFEE;}
|
||||
td.head {background-color: #EEEEFF;}
|
||||
td.num {text-align: right;}
|
||||
td.link {text-decoration: underline; color: blue;}
|
||||
td, th {width: 100px;}
|
||||
td.error {color: red;background-color: yellow;}
|
||||
td.title, th.title {width: 400px;}
|
||||
td.mod, th.mod {width: 200px;}
|
||||
#itemtable {width: 100%;}
|
||||
#itemdiv {display: none;}
|
||||
td.ititle, th.ititle {width: 600px;}
|
||||
|
||||
button:disabled {
|
||||
background-color:gray;
|
||||
}
|
||||
input:read-only {
|
||||
background-color: gray;
|
||||
}
|
||||
div.metadata {
|
||||
padding: 2px;
|
||||
width: 880px;
|
||||
}
|
||||
#metadatadiv select, #metadatadiv input {
|
||||
padding: 2px;
|
||||
margin: 4px;
|
||||
}
|
||||
#metadatadiv fieldset {
|
||||
margin: 6px 15px;
|
||||
width: 850px;
|
||||
}
|
||||
|
||||
#metadatadiv label {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#itemtable td div:not(:first-child) {
|
||||
border-top: thin solid gray;
|
||||
}
|
||||
|
||||
body {
|
||||
min-height: 700px;
|
||||
min-width: 700px;
|
||||
}
|
||||
|
||||
tr.header th {
|
||||
vertical-align: bottom;
|
||||
}
|
||||
|
||||
a.partial::after {
|
||||
content:" ?";
|
||||
}
|
||||
|
||||
fieldset.catdiv {
|
||||
border: thin solid black;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
fieldset.catdiv div {
|
||||
width: 380px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
#collSel {
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
#filterdiv label {
|
||||
font-weight: normal;
|
||||
}
|
344
dspace-rest/src/main/webapp/static/reports/restCollReport.js
Normal file
344
dspace-rest/src/main/webapp/static/reports/restCollReport.js
Normal file
@@ -0,0 +1,344 @@
|
||||
/*
|
||||
* 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/
|
||||
*/
|
||||
var CollReport = function() {
|
||||
Report.call(this);
|
||||
//If sortable.js is included, uncomment the following
|
||||
//this.hasSorttable = function(){return true;}
|
||||
|
||||
this.COLL_LIMIT = 25;
|
||||
this.loadId = 0;
|
||||
this.THREADS =11;
|
||||
this.THREADSP = 11;
|
||||
this.ACCIDX_COLL = 1;
|
||||
this.ACCIDX_ITEM = 2;
|
||||
this.getDefaultParameters = function(){
|
||||
return {
|
||||
"show_fields[]" : [],
|
||||
filters : "",
|
||||
limit : this.COUNT_LIMIT,
|
||||
offset : 0,
|
||||
icollection : "",
|
||||
ifilter : "",
|
||||
};
|
||||
}
|
||||
this.getCurrentParameters = function(){
|
||||
return {
|
||||
"show_fields[]" : this.myMetadataFields.getShowFields(),
|
||||
filters : this.myFilters.getFilterList(),
|
||||
limit : this.myReportParameters.getLimit(),
|
||||
offset : this.myReportParameters.getOffset(),
|
||||
icollection : $("#icollection").val(),
|
||||
ifilter : $("#ifilter").val(),
|
||||
};
|
||||
}
|
||||
var self = this;
|
||||
|
||||
this.init = function() {
|
||||
this.baseInit();
|
||||
$("#icollection").val(self.myReportParameters.params.icollection);
|
||||
$("#ifilter").val(self.myReportParameters.params.ifilter);
|
||||
$("#itemResults").accordion({
|
||||
heightStyle: "content",
|
||||
collapsible: true,
|
||||
active: 1
|
||||
});
|
||||
}
|
||||
|
||||
this.myAuth.callback = function(data) {
|
||||
self.createCollectionTable();
|
||||
$(".showCollections").bind("click", function(){
|
||||
self.loadData();
|
||||
});
|
||||
$("#refresh-fields").bind("click", function(){
|
||||
self.drawItemTable($("#icollection").val(), $("#ifilter").val(), 0);
|
||||
});
|
||||
}
|
||||
|
||||
this.createCollectionTable = function() {
|
||||
var self = this;
|
||||
var tbl = $("<table/>");
|
||||
tbl.attr("id","table");
|
||||
$("#report").replaceWith(tbl);
|
||||
|
||||
var thead = $("<thead/>");
|
||||
tbl.append(thead);
|
||||
var tbody = $("<tbody/>");
|
||||
tbl.append(tbody);
|
||||
var tr = self.myHtmlUtil.addTr(thead).addClass("header");
|
||||
self.myHtmlUtil.addTh(tr, "Num").addClass("num").addClass("sorttable_numeric");
|
||||
self.myHtmlUtil.addTh(tr, "Community").addClass("title");
|
||||
self.myHtmlUtil.addTh(tr, "Collection").addClass("title");
|
||||
var thn = self.myHtmlUtil.addTh(tr, "Num Items").addClass("sorttable_numeric");
|
||||
self.myHtmlUtil.makeTotalCol(thn);
|
||||
|
||||
self.addCollectionRows(tbl, 0);
|
||||
}
|
||||
|
||||
this.addCollectionRows = function(tbl, offset) {
|
||||
var self = this;
|
||||
|
||||
$.ajax({
|
||||
url: "/rest/filtered-collections",
|
||||
data: {
|
||||
limit : self.COLL_LIMIT,
|
||||
expand : "topCommunity",
|
||||
offset : offset,
|
||||
},
|
||||
dataType: "json",
|
||||
headers: self.myAuth.getHeaders(),
|
||||
success: function(data){
|
||||
$.each(data, function(index, coll){
|
||||
var tr = self.myHtmlUtil.addTr($("#table tbody"));
|
||||
tr.attr("cid", self.getId(coll)).attr("index",index + offset).addClass(index % 2 == 0 ? "odd data" : "even data");
|
||||
self.myHtmlUtil.addTd(tr, index + offset + 1).addClass("num");
|
||||
var parval = "";
|
||||
|
||||
if ("topCommunity" in coll) {
|
||||
var par = coll.topCommunity;
|
||||
parval = par ? self.myHtmlUtil.getAnchor(par.name, "/handle/" + par.handle) : "";
|
||||
} else if ("parCommunityList" in coll) {
|
||||
var par = coll.parentCommunityList[coll.parentCommunityList.length-1];
|
||||
parval = par ? self.myHtmlUtil.getAnchor(par.name, "/handle/" + par.handle) : "";
|
||||
}
|
||||
self.myHtmlUtil.addTd(tr, parval).addClass("title comm");
|
||||
self.myHtmlUtil.addTdAnchor(tr, coll.name, "/handle/" + coll.handle).addClass("title");
|
||||
var td = self.myHtmlUtil.addTd(tr, coll.numberItems).addClass("num").addClass("link");
|
||||
td.on("click", function(){
|
||||
self.drawItemTable(self.getId(coll),'',0);
|
||||
$("#icollection").val(self.getId(coll));
|
||||
$("#ifilter").val("");
|
||||
});
|
||||
});
|
||||
|
||||
if (data.length == self.COLL_LIMIT) {
|
||||
self.addCollectionRows(tbl, offset + self.COLL_LIMIT);
|
||||
return;
|
||||
}
|
||||
self.myHtmlUtil.totalCol(3);
|
||||
$("#table").addClass("sortable");
|
||||
if (self.hasSorttable()) {
|
||||
sorttable.makeSortable($("#table")[0]);
|
||||
}
|
||||
|
||||
if (self.myFilters.getFilterList() != "") {
|
||||
self.loadData();
|
||||
if ($("#icollection").val() != "") {
|
||||
self.drawItemTable($("#icollection").val(), $("#ifilter").val(), 0);
|
||||
}
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, errorThrown) {
|
||||
alert("Error in /rest/filtered-collections "+ status+ " " + errorThrown);
|
||||
},
|
||||
complete: function(xhr, status) {
|
||||
self.spinner.stop();
|
||||
$(".showCollections").attr("disabled", false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.loadData = function() {
|
||||
self.spinner.spin($("h1")[0]);
|
||||
$(".showCollections").attr("disabled", true);
|
||||
$("#metadatadiv").accordion("option", "active", self.ACCIDX_COLL);
|
||||
self.loadId++;
|
||||
$("td.datacol,th.datacol").remove();
|
||||
$("#table tr.data").addClass("processing");
|
||||
self.myFilters.filterString = self.myFilters.getFilterList();
|
||||
self.doRow(0, self.THREADS, self.loadId);
|
||||
}
|
||||
|
||||
this.doRow = function(row, threads, curLoadId) {
|
||||
if (self.loadId != curLoadId) return;
|
||||
var tr = $("tr[index="+row+"]");
|
||||
if (!tr.is("*")){
|
||||
return;
|
||||
}
|
||||
|
||||
var cid = tr.attr("cid");
|
||||
$.ajax({
|
||||
url: "/rest/filtered-collections/"+cid,
|
||||
data: {
|
||||
limit : self.COUNT_LIMIT,
|
||||
filters : self.myFilters.filterString,
|
||||
},
|
||||
dataType: "json",
|
||||
headers: self.myAuth.getHeaders(),
|
||||
success: function(data) {
|
||||
var numItems = data.numberItems;
|
||||
var numItemsProcessed = data.numberItemsProcessed;
|
||||
$.each(data.itemFilters, function(index, itemFilter){
|
||||
if (self.loadId != curLoadId) {
|
||||
return;
|
||||
}
|
||||
var trh = $("#table tr.header");
|
||||
var filterName = itemFilter["filter-name"];
|
||||
var filterTitle = itemFilter.title == null ? filterName : itemFilter.title;
|
||||
var icount = itemFilter["item-count"];
|
||||
if (!trh.find("th."+filterName).is("*")) {
|
||||
var th = self.myHtmlUtil.addTh(trh, filterTitle);
|
||||
th.addClass(filterName).addClass("datacol").addClass("sorttable_numeric");
|
||||
self.myHtmlUtil.makeTotalCol(th);
|
||||
|
||||
if (itemFilter.description != null) {
|
||||
th.attr("title", itemFilter.description);
|
||||
}
|
||||
|
||||
$("tr.data").each(function(){
|
||||
var td = self.myHtmlUtil.addTd($(this), "");
|
||||
td.addClass(filterName).addClass("num").addClass("datacol");
|
||||
});
|
||||
}
|
||||
|
||||
var td = tr.find("td."+filterName);
|
||||
if (icount == null) {
|
||||
icount = "0";
|
||||
}
|
||||
td.text(icount);
|
||||
if (icount != "0") {
|
||||
td.addClass("link");
|
||||
td.on("click", function(){
|
||||
self.drawItemTable(cid,filterName,0);
|
||||
$("#icollection").val(cid);
|
||||
$("#ifilter").val(filterName);
|
||||
});
|
||||
if (numItems != numItemsProcessed) {
|
||||
td.addClass("partial");
|
||||
td.attr("title", "Collection partially processed, item counts are incomplete");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
|
||||
tr.removeClass("processing");
|
||||
if (!$("#table tr.processing").is("*")) {
|
||||
if (self.hasSorttable()) {
|
||||
$("#table").removeClass("sortable");
|
||||
$("#table").addClass("sortable");
|
||||
sorttable.makeSortable($("#table")[0]);
|
||||
}
|
||||
var colcount = $("#table tr th").length;
|
||||
for(var i=4; i<colcount; i++) {
|
||||
self.myHtmlUtil.totalCol(i);
|
||||
}
|
||||
self.spinner.stop();
|
||||
$(".showCollections").attr("disabled", false);
|
||||
return;
|
||||
}
|
||||
if (row % threads == 0 || threads == 1) {
|
||||
for(var i=1; i<=threads; i++) {
|
||||
self.doRow(row+i, threads, curLoadId);
|
||||
}
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, errorThrown) {
|
||||
alert("Error in /rest/filtered-collections "+ status+ " " + errorThrown);
|
||||
},
|
||||
complete: function(xhr, status) {
|
||||
self.spinner.stop();
|
||||
$(".showCollections").attr("disabled", false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.drawItemTable = function(cid, filter, offset) {
|
||||
self = this;
|
||||
self.spinner.spin($("h1")[0]);
|
||||
$("#itemtable").replaceWith($('<table id="itemtable" class="sortable"></table>'));
|
||||
var itbl = $("#itemtable");
|
||||
//itbl.find("tr").remove("*");
|
||||
var tr = self.myHtmlUtil.addTr(itbl).addClass("header");
|
||||
self.myHtmlUtil.addTh(tr, "Num").addClass("num").addClass("sorttable_numeric");
|
||||
self.myHtmlUtil.addTh(tr, "id");
|
||||
self.myHtmlUtil.addTh(tr, "Handle");
|
||||
self.myHtmlUtil.addTh(tr, "dc.title" + self.getLangSuffix()).addClass("title");
|
||||
var fields = $("#show-fields select").val();
|
||||
if (fields != null) {
|
||||
$.each(fields, function(index, field){
|
||||
self.myHtmlUtil.addTh(tr, field + self.getLangSuffix());
|
||||
});
|
||||
}
|
||||
|
||||
var params = {
|
||||
expand: fields == null ? "items" : "items,metadata",
|
||||
limit: self.ITEM_LIMIT,
|
||||
filters: filter,
|
||||
offset: offset,
|
||||
"show_fields[]" : fields,
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
url: "/rest/filtered-collections/"+cid,
|
||||
data: params,
|
||||
dataType: "json",
|
||||
headers: self.myAuth.getHeaders(),
|
||||
success: function(data){
|
||||
var source = filter == "" ? data.items : data.itemFilters[0].items;
|
||||
|
||||
$.each(source, function(index, item){
|
||||
var tr = self.myHtmlUtil.addTr(itbl);
|
||||
tr.addClass(index % 2 == 0 ? "odd data" : "even data");
|
||||
self.myHtmlUtil.addTd(tr, offset+index+1).addClass("num");
|
||||
self.myHtmlUtil.addTd(tr, self.getId(item));
|
||||
self.myHtmlUtil.addTdAnchor(tr, item.handle, "/handle/" + item.handle);
|
||||
self.myHtmlUtil.addTd(tr, item.name).addClass("ititle");
|
||||
if (fields != null) {
|
||||
$.each(fields, function(index, field){
|
||||
var text = "";
|
||||
$.each(item.metadata, function(mindex,mv){
|
||||
if (mv.key == field) {
|
||||
if (text != "") {
|
||||
text += "<hr/>";
|
||||
}
|
||||
text += mv.value;
|
||||
}
|
||||
});
|
||||
self.myHtmlUtil.addTd(tr, text);
|
||||
});
|
||||
}
|
||||
});
|
||||
self.displayItems(filter + " Items in " + data.name,
|
||||
offset,
|
||||
self.ITEM_LIMIT,
|
||||
data.numberItems,
|
||||
function(){self.drawItemTable(cid, filter, (offset - self.ITEM_LIMIT < 0) ? 0 : offset - self.ITEM_LIMIT);},
|
||||
function(){self.drawItemTable(cid, filter, offset + self.ITEM_LIMIT);}
|
||||
);
|
||||
|
||||
if (self.hasSorttable()){
|
||||
sorttable.makeSortable(itbl[0]);
|
||||
}
|
||||
$("#metadatadiv").accordion("option", "active", self.ACCIDX_ITEM);
|
||||
},
|
||||
error: function(xhr, status, errorThrown) {
|
||||
alert("Error in /rest/filtered-collections "+ status+ " " + errorThrown);
|
||||
},
|
||||
complete: function(xhr, status) {
|
||||
self.spinner.stop();
|
||||
$(".showCollections").attr("disabled", false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//Ignore the first column containing a row number and the item handle
|
||||
this.exportCol = function(colnum, col) {
|
||||
var data = "";
|
||||
if (colnum == 0) return "";
|
||||
if (colnum == 2) return "";
|
||||
data += (colnum == 1) ? "" : ",";
|
||||
data += self.exportCell(col);
|
||||
return data;
|
||||
}
|
||||
}
|
||||
CollReport.prototype = Object.create(Report.prototype);
|
||||
|
||||
$(document).ready(function(){
|
||||
var myReport=new CollReport();
|
||||
myReport.init();
|
||||
});
|
320
dspace-rest/src/main/webapp/static/reports/restQueryReport.js
Normal file
320
dspace-rest/src/main/webapp/static/reports/restQueryReport.js
Normal file
@@ -0,0 +1,320 @@
|
||||
/*
|
||||
* 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/
|
||||
*/
|
||||
var QueryReport = function() {
|
||||
Report.call(this);
|
||||
|
||||
//If sortable.js is included, uncomment the following
|
||||
//this.hasSorttable = function(){return true;}
|
||||
|
||||
this.getDefaultParameters = function(){
|
||||
return {
|
||||
"collSel[]" : [],
|
||||
"query_field[]" : [],
|
||||
"query_op[]" : [],
|
||||
"query_val[]" : [],
|
||||
"show_fields[]" : [],
|
||||
"filters" : "",
|
||||
"limit" : this.ITEM_LIMIT,
|
||||
"offset" : 0,
|
||||
};
|
||||
}
|
||||
this.getCurrentParameters = function(){
|
||||
var params = {
|
||||
"query_field[]" : [],
|
||||
"query_op[]" : [],
|
||||
"query_val[]" : [],
|
||||
"collSel[]" : ($("#collSel").val() == null) ? [""] : $("#collSel").val(),
|
||||
limit : this.myReportParameters.getLimit(),
|
||||
offset : this.myReportParameters.getOffset(),
|
||||
"expand" : "parentCollection,metadata",
|
||||
filters : this.myFilters.getFilterList(),
|
||||
"show_fields[]" : this.myMetadataFields.getShowFields(),
|
||||
};
|
||||
$("select.query-tool,input.query-tool").each(function() {
|
||||
var paramArr = params[$(this).attr("name")];
|
||||
paramArr[paramArr.length] = $(this).val();
|
||||
});
|
||||
return params;
|
||||
}
|
||||
var self = this;
|
||||
|
||||
this.init = function() {
|
||||
this.baseInit();
|
||||
var communitySelector = new CommunitySelector(this, $("#collSelector"), this.myReportParameters.params["collSel[]"]);
|
||||
}
|
||||
|
||||
this.initMetadataFields = function() {
|
||||
this.myMetadataFields = new QueryableMetadataFields(self);
|
||||
this.myMetadataFields.load();
|
||||
}
|
||||
this.myAuth.callback = function(data) {
|
||||
$(".query-button").click(function(){self.runQuery();})
|
||||
}
|
||||
|
||||
this.runQuery = function() {
|
||||
this.spinner.spin($("body")[0]);
|
||||
$("button").attr("disabled", true);
|
||||
$.ajax({
|
||||
url: "/rest/filtered-items",
|
||||
data: this.getCurrentParameters(),
|
||||
dataType: "json",
|
||||
headers: self.myAuth.getHeaders(),
|
||||
success: function(data){
|
||||
data.metadata = $("#show-fields select").val();
|
||||
self.drawItemFilterTable(data);
|
||||
self.spinner.stop();
|
||||
$("button").not("#next,#prev").attr("disabled", false);
|
||||
},
|
||||
error: function(xhr, status, errorThrown) {
|
||||
alert("Error in /rest/filtered-items "+ status+ " " + errorThrown);
|
||||
},
|
||||
complete: function(xhr, status, errorThrown) {
|
||||
self.spinner.stop();
|
||||
$("button").not("#next,#prev").attr("disabled", false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.drawItemFilterTable = function(data) {
|
||||
$("#itemtable").replaceWith($('<table id="itemtable" class="sortable"></table>'));
|
||||
var itbl = $("#itemtable");
|
||||
var tr = self.myHtmlUtil.addTr(itbl).addClass("header");
|
||||
self.myHtmlUtil.addTh(tr, "Num").addClass("num").addClass("sorttable_numeric");
|
||||
self.myHtmlUtil.addTh(tr, "id");
|
||||
self.myHtmlUtil.addTh(tr, "collection");
|
||||
self.myHtmlUtil.addTh(tr, "Item Handle");
|
||||
self.myHtmlUtil.addTh(tr, "dc.title" + self.getLangSuffix());
|
||||
|
||||
var mdCols = [];
|
||||
if (data.metadata) {
|
||||
$.each(data.metadata, function(index, field) {
|
||||
if (field != "") {
|
||||
self.myHtmlUtil.addTh(tr,field + self.getLangSuffix()).addClass("returnFields");
|
||||
mdCols[mdCols.length] = field;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$.each(data.items, function(index, item){
|
||||
var tr = self.myHtmlUtil.addTr(itbl);
|
||||
tr.addClass(index % 2 == 0 ? "odd data" : "even data");
|
||||
self.myHtmlUtil.addTd(tr, self.myReportParameters.getOffset()+index+1).addClass("num");
|
||||
self.myHtmlUtil.addTd(tr, self.getId(item));
|
||||
if (item.parentCollection == null) {
|
||||
self.myHtmlUtil.addTd(tr, "--");
|
||||
} else {
|
||||
self.myHtmlUtil.addTdAnchor(tr, item.parentCollection.name, "/handle/" + item.parentCollection.handle);
|
||||
}
|
||||
self.myHtmlUtil.addTdAnchor(tr, item.handle, "/handle/" + item.handle);
|
||||
self.myHtmlUtil.addTd(tr, item.name);
|
||||
|
||||
for(var i=0; i<mdCols.length; i++) {
|
||||
var key = mdCols[i];
|
||||
var td = self.myHtmlUtil.addTd(tr, "");
|
||||
$.each(item.metadata, function(colindex, metadata) {
|
||||
if (metadata.key == key) {
|
||||
if (metadata.value != null) {
|
||||
var div = $("<div>"+metadata.value+"</div>");
|
||||
td.append(div);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
this.displayItems(data["query-annotation"],
|
||||
this.myReportParameters.getOffset(),
|
||||
this.myReportParameters.getLimit(),
|
||||
data["unfiltered-item-count"],
|
||||
function(){
|
||||
self.myReportParameters.updateOffset(false);
|
||||
self.runQuery();
|
||||
},
|
||||
function(){
|
||||
self.myReportParameters.updateOffset(true);
|
||||
self.runQuery();
|
||||
}
|
||||
);
|
||||
|
||||
if (this.hasSorttable()) {
|
||||
sorttable.makeSortable(itbl[0]);
|
||||
}
|
||||
$("#metadatadiv").accordion("option", "active", $("#metadatadiv > h3").length - 1);
|
||||
}
|
||||
|
||||
//Ignore the first column containing a row number and the item handle, get handle for the collection
|
||||
this.exportCol = function(colnum, col) {
|
||||
var data = "";
|
||||
if (colnum == 0) return "";
|
||||
if (colnum == 3) return "";
|
||||
data += (colnum == 1) ? "" : ",";
|
||||
|
||||
if (colnum == 2) {
|
||||
var anchor = $(col).find("a");
|
||||
var href = anchor.is("a") ? anchor.attr("href").replace(/\/handle\//,"") : $(col).text();
|
||||
data += "\"" + href + "\"";
|
||||
} else {
|
||||
data += self.exportCell(col); }
|
||||
return data;
|
||||
}
|
||||
}
|
||||
QueryReport.prototype = Object.create(Report.prototype);
|
||||
|
||||
$(document).ready(function(){
|
||||
var myReport=new QueryReport();
|
||||
myReport.init();
|
||||
});
|
||||
|
||||
var QueryableMetadataFields = function(report) {
|
||||
MetadataFields.call(this, report);
|
||||
var self = this;
|
||||
|
||||
this.initFields = function(data, report) {
|
||||
self.metadataSchemas = data;
|
||||
var params = report.myReportParameters.params;
|
||||
var fields = params["query_field[]"];
|
||||
var ops = params["query_op[]"];
|
||||
var vals = params["query_val[]"];
|
||||
if (fields && ops && vals) {
|
||||
if (fields.length == 0) {
|
||||
self.drawFilterQuery("*","exists","");
|
||||
} else {
|
||||
for(var i=0; i<fields.length; i++) {
|
||||
var op = ops.length > i ? ops[i] : "";
|
||||
var val = vals.length > i ? vals[i] : "";
|
||||
self.drawFilterQuery(fields[i],op,val);
|
||||
}
|
||||
}
|
||||
}
|
||||
self.drawShowFields(params["show_fields[]"]);
|
||||
self.initQueries();
|
||||
report.spinner.stop();
|
||||
$(".query-button").attr("disabled", false);
|
||||
}
|
||||
|
||||
this.initQueries = function() {
|
||||
$("#predefselect")
|
||||
.append($("<option value='new'>New Query</option>"))
|
||||
.append($("<option value='q1'>Has No Title</option>"))
|
||||
.append($("<option value='q2'>Has No dc.identifier.uri</option>"))
|
||||
.append($("<option value='q3'>Has compound subject</option>"))
|
||||
.append($("<option value='q4'>Has compound dc.contributor.author</option>"))
|
||||
.append($("<option value='q5'>Has compound dc.creator</option>"))
|
||||
.append($("<option value='q6'>Has URL in dc.description</option>"))
|
||||
.append($("<option value='q7'>Has full text in dc.description.provenance</option>"))
|
||||
.append($("<option value='q8'>Has non-full text in dc.description.provenance</option>"))
|
||||
.append($("<option value='q9'>Has empty metadata</option>"))
|
||||
.append($("<option value='q10'>Has unbreaking metadata in description</option>"))
|
||||
.append($("<option value='q12'>Has XML entity in metadata</option>"))
|
||||
.append($("<option value='q13'>Has non-ascii character in metadata</option>"))
|
||||
.on("change",function(){
|
||||
$("div.metadata").remove();
|
||||
var val = $("#predefselect").val();
|
||||
if (val == 'new') {
|
||||
self.drawFilterQuery("","","");
|
||||
} else if (val == 'q1') {
|
||||
self.drawFilterQuery("dc.title","doesnt_exist","");
|
||||
} else if (val == 'q2') {
|
||||
self.drawFilterQuery("dc.identifier.uri","doesnt_exist","");
|
||||
} else if (val == 'q3') {
|
||||
self.drawFilterQuery("dc.subject.*","like","%;%");
|
||||
} else if (val == 'q4') {
|
||||
self.drawFilterQuery("dc.contributor.author","like","% and %");
|
||||
} else if (val == 'q5') {
|
||||
self.drawFilterQuery("dc.creator","like","% and %");
|
||||
} else if (val == 'q6') {
|
||||
self.drawFilterQuery("dc.description","matches","^.*(http://|https://|mailto:).*$");
|
||||
} else if (val == 'q7') {
|
||||
self.drawFilterQuery("dc.description.provenance","matches","^.*No\\. of bitstreams(.|\\r|\\n|\\r\\n)*\\.(PDF|pdf|DOC|doc|PPT|ppt|DOCX|docx|PPTX|pptx).*$");
|
||||
} else if (val == 'q8') {
|
||||
self.drawFilterQuery("dc.description.provenance","doesnt_match","^.*No\\. of bitstreams(.|\\r|\\n|\\r\\n)*\\.(PDF|pdf|DOC|doc|PPT|ppt|DOCX|docx|PPTX|pptx).*$");
|
||||
} else if (val == 'q9') {
|
||||
self.drawFilterQuery("*","matches","^\\s*$");
|
||||
} else if (val == 'q10') {
|
||||
self.drawFilterQuery("dc.description.*","matches","^.*[^\\s]{50,}.*$");
|
||||
} else if (val == 'q12') {
|
||||
self.drawFilterQuery("*","matches","^.*&#.*$");
|
||||
} else if (val == 'q13') {
|
||||
self.drawFilterQuery("*","matches","^.*[^[:ascii:]].*$");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.drawFilterQuery = function(pField, pOp, pVal) {
|
||||
var div = $("<div class='metadata'/>").appendTo("#queries");
|
||||
var sel = $("<select class='query-tool' name='query_field[]'/>");
|
||||
var opt = $("<option value='*'>Any Field</option>");
|
||||
sel.append(opt);
|
||||
$.each(self.metadataSchemas, function(index, schema){
|
||||
$.each(schema.fields, function(findex, field) {
|
||||
var name = field.name;
|
||||
var parts = name.match(/^([^\.]+)\.([^\.]+)\.([^\.]+)$/);
|
||||
if (parts == null) {
|
||||
var wildname = name + ".*";
|
||||
var opt = $("<option/>");
|
||||
opt.attr("value",wildname).text(wildname);
|
||||
sel.append(opt);
|
||||
}
|
||||
var opt = $("<option/>");
|
||||
opt.attr("value",name).text(name);
|
||||
sel.append(opt);
|
||||
});
|
||||
});
|
||||
sel.val(pField);
|
||||
div.append(sel);
|
||||
var opsel = $("<select class='query-tool' name='query_op[]'/>");
|
||||
$("<option>exists</option>").val("exists").appendTo(opsel);
|
||||
$("<option>does not exist</option>").val("doesnt_exist").appendTo(opsel);
|
||||
$("<option selected>equals</option>").val("equals").appendTo(opsel);
|
||||
$("<option>does not equal</option>").val("not_equals").appendTo(opsel);
|
||||
$("<option>like</option>").val("like").appendTo(opsel);
|
||||
$("<option>not like</option>").val("not_like").appendTo(opsel);
|
||||
$("<option>contains</option>").val("contains").appendTo(opsel);
|
||||
$("<option>does not contain</option>").val("doesnt_contain").appendTo(opsel);
|
||||
$("<option>matches</option>").val("matches").appendTo(opsel);
|
||||
$("<option>does not match</option>").val("doesnt_match").appendTo(opsel);
|
||||
opsel.val(pOp);
|
||||
opsel.change(function(){
|
||||
self.valField($(this));
|
||||
});
|
||||
div.append(opsel);
|
||||
var input = $("<input class='query-tool' name='query_val[]'/>");
|
||||
div.append(input);
|
||||
input.val(pVal);
|
||||
self.valField(opsel);
|
||||
$("<button class='field_plus'>+</button>").appendTo(div).click(function(){
|
||||
self.drawFilterQuery();
|
||||
self.queryButtons();
|
||||
});
|
||||
$("<button class='field_minus'>-</button>").appendTo(div).click(function(){
|
||||
$(this).parent("div.metadata").remove();
|
||||
self.queryButtons();
|
||||
});
|
||||
self.queryButtons();
|
||||
}
|
||||
|
||||
this.valField = function(valop) {
|
||||
var val = valop.val();
|
||||
var disableval = (val == "exists" || val == "not_exists");
|
||||
var valinput = valop.parent("div.metadata").find("input[name='query_val[]']");
|
||||
valinput.attr("readonly",disableval);
|
||||
if (disableval) {
|
||||
valinput.val("");
|
||||
}
|
||||
}
|
||||
|
||||
this.queryButtons = function() {
|
||||
$("button.field_plus").attr("disabled",true);
|
||||
$("button.field_plus:last").attr("disabled",false);
|
||||
$("button.field_minus").attr("disabled",false);
|
||||
if ($("button.field_minus").length == 1) {
|
||||
$("button.field_minus").attr("disabled",true);
|
||||
}
|
||||
}
|
||||
}
|
||||
QueryableMetadataFields.prototype = Object.create(MetadataFields.prototype);
|
548
dspace-rest/src/main/webapp/static/reports/restReport.js
Normal file
548
dspace-rest/src/main/webapp/static/reports/restReport.js
Normal file
@@ -0,0 +1,548 @@
|
||||
/*
|
||||
* 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/
|
||||
*/
|
||||
var Report = function() {
|
||||
var self = this;
|
||||
this.COLL_LIMIT = 500;
|
||||
this.COUNT_LIMIT = 500;
|
||||
this.ITEM_LIMIT = 100;
|
||||
|
||||
//Override this to return obj.id for DSpace 5 versions
|
||||
this.getId = function(obj) {
|
||||
return obj.uuid;
|
||||
}
|
||||
|
||||
//Override this method is sortable.js has been included
|
||||
this.hasSorttable = function() {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.getDefaultParameters = function(){
|
||||
return {};
|
||||
}
|
||||
this.getCurrentParameters = function(){
|
||||
return {};
|
||||
}
|
||||
|
||||
this.saveUrl = function() {
|
||||
this.myReportParameters.saveAsUrl(this.getCurrentParameters());
|
||||
}
|
||||
|
||||
this.getLoginPayload = function() {
|
||||
//Example of how to pass credentials to the service
|
||||
//return {"email" : "Email@my.edu","password" : "my-password"};
|
||||
return undefined;
|
||||
}
|
||||
this.getLangSuffix = function(){
|
||||
return "";
|
||||
}
|
||||
this.myAuth = new Auth(this.getLoginPayload());
|
||||
this.myAuth.callback = function(data) {
|
||||
self.spinner.stop();
|
||||
}
|
||||
this.myHtmlUtil = new HtmlUtil();
|
||||
this.spinner = new Spinner({
|
||||
lines: 13, // The number of lines to draw
|
||||
length: 20, // The length of each line
|
||||
width: 10, // The line thickness
|
||||
radius: 30, // The radius of the inner circle
|
||||
corners: 1, // Corner roundness (0..1)
|
||||
rotate: 0, // The rotation offset
|
||||
direction: 1, // 1: clockwise, -1: counterclockwise
|
||||
color: '#000', // #rgb or #rrggbb or array of colors
|
||||
speed: 1, // Rounds per second
|
||||
trail: 60, // Afterglow percentage
|
||||
shadow: false, // Whether to render a shadow
|
||||
hwaccel: false, // Whether to use hardware acceleration
|
||||
className: 'spinner', // The CSS class to assign to the spinner
|
||||
zIndex: 2e9, // The z-index (defaults to 2000000000)
|
||||
top: '400px', // Top position relative to parent
|
||||
left: '600px' // Left position relative to parent
|
||||
});
|
||||
|
||||
this.displayItems = function(itemsTitle, offset, limit, total, funcdec, funcinc) {
|
||||
var count = $("#itemtable tr.data").length;
|
||||
|
||||
var last = offset + limit;
|
||||
var suff = "";
|
||||
|
||||
if (total == null) {
|
||||
last = offset + count;
|
||||
suff = (count == limit) ? " of " + last + "+ " : " of " + last;
|
||||
} else if (limit == total) {
|
||||
//total may only be accurate to page size
|
||||
suff = " of " + total + "+ ";
|
||||
} else {
|
||||
last = (last > total) ? total : last;
|
||||
suff = " of " + total;
|
||||
}
|
||||
suff += " unfiltered; displaying " + count + " filtered" ;
|
||||
|
||||
itemsTitle += " (" + (offset+1) + " - " + last + suff + ")";
|
||||
$("#prev,#next").attr("disabled",true);
|
||||
$("#itemdiv h3").text(itemsTitle);
|
||||
if (offset > 0) $("#prev").attr("disabled", false);
|
||||
$("#prev").off("click").on("click", funcdec);
|
||||
//in case of filters, always allow next
|
||||
|
||||
if (total == null) {
|
||||
$("#next").attr("disabled", false);
|
||||
} else if (offset + limit < total) {
|
||||
$("#next").attr("disabled", false);
|
||||
} else if (limit == total) {
|
||||
//total may only be accurate to one page
|
||||
$("#next").attr("disabled", false);
|
||||
}
|
||||
$("#next").off("click").on("click", funcinc);
|
||||
}
|
||||
|
||||
this.myReportParameters = undefined;
|
||||
this.myFilters = undefined;
|
||||
this.myMetadataFields = undefined;
|
||||
|
||||
this.initMetadataFields = function() {
|
||||
this.myMetadataFields = new MetadataFields(self);
|
||||
this.myMetadataFields.load();
|
||||
}
|
||||
|
||||
this.baseInit = function() {
|
||||
this.myReportParameters = new ReportParameters(
|
||||
this.getDefaultParameters(),
|
||||
window.location.search.substr(1)
|
||||
);
|
||||
this.spinner.spin($("h1")[0]);
|
||||
this.myFilters = new Filters(this.myReportParameters.params["filters"]);
|
||||
this.initMetadataFields();
|
||||
$("#metadatadiv").accordion({
|
||||
heightStyle: "content",
|
||||
collapsible: true,
|
||||
active: $("#metadatadiv > h3").length - 2
|
||||
});
|
||||
$("#export").click(function(){
|
||||
self.export($("#itemtable tr"));
|
||||
});
|
||||
$("a.this-search").on("click",function(){
|
||||
self.saveUrl();
|
||||
});
|
||||
this.myFilters.createFilterTable(this.myReportParameters.params.filters);
|
||||
this.myAuth.init();
|
||||
}
|
||||
|
||||
this.export = function(rows) {
|
||||
var itemdata = "data:text/csv;charset=utf-8,";
|
||||
rows.each(function(rownum, row){
|
||||
itemdata += (rownum == 0) ? "" : "\r\n";
|
||||
$(row).find("td,th").each(function(colnum, col){
|
||||
itemdata += self.exportCol(colnum, col);
|
||||
});
|
||||
});
|
||||
var encodedUri = encodeURI(itemdata);
|
||||
window.open(encodedUri);
|
||||
}
|
||||
|
||||
//this is meant to be overridden for each report
|
||||
this.exportCol = function(colnum, col) {
|
||||
var data = "";
|
||||
data += (colnum == 0) ? "" : ",";
|
||||
data += self.exportCell(col);
|
||||
return data;
|
||||
}
|
||||
|
||||
this.exportCell = function(col) {
|
||||
data = "\"";
|
||||
$(col).contents().each(function(i, node){
|
||||
if ($(node).is("hr")) {
|
||||
data += "||";
|
||||
} else {
|
||||
data += $(node).text().replace(/\n/g," ").replace(/"/g,"\"\"");
|
||||
if ($(node).is("div:not(:last-child)")) {
|
||||
data += "||";
|
||||
}
|
||||
}
|
||||
});
|
||||
data += "\"";
|
||||
return data;
|
||||
}
|
||||
|
||||
this.init = function() {
|
||||
this.baseInit();
|
||||
}
|
||||
}
|
||||
|
||||
var Auth = function(loginPayload) {
|
||||
this.TOKEN = undefined;
|
||||
this.callback = function(data) {
|
||||
alert("auth complete " + this.TOKEN);
|
||||
};
|
||||
this.saveToken = function(data) {
|
||||
this.TOKEN = data;
|
||||
}
|
||||
this.init = function() {
|
||||
if (loginPayload == undefined) {
|
||||
this.callback();
|
||||
return;
|
||||
}
|
||||
|
||||
var self = this;
|
||||
$.ajax({
|
||||
url : "/rest/login",
|
||||
contentType : "application/json",
|
||||
accepts : "application/json",
|
||||
type : "POST",
|
||||
data : JSON.stringify(loginPayload),
|
||||
success : function(data){
|
||||
self.saveToken(data);
|
||||
self.callback();
|
||||
},
|
||||
error: function(xhr, status, errorThrown) {
|
||||
alert("Error in /rest/login "+ status+ " " + errorThrown);
|
||||
},
|
||||
complete: function(xhr, status) {
|
||||
self.callback();
|
||||
}
|
||||
});
|
||||
}
|
||||
this.getHeaders = function() {
|
||||
var HEADERS = {};
|
||||
if (this.TOKEN != null) {
|
||||
HEADERS['rest-dspace-token'] = this.TOKEN;
|
||||
}
|
||||
return HEADERS;
|
||||
}
|
||||
}
|
||||
|
||||
var ReportParameters = function(defaultParams, prmstr) {
|
||||
this.params = defaultParams;
|
||||
|
||||
if (prmstr == null) prmstr = "";
|
||||
var prmarr = prmstr.split("&");
|
||||
for ( var i = 0; i < prmarr.length; i++) {
|
||||
var tmparr = prmarr[i].split("=");
|
||||
var field = tmparr[0];
|
||||
var val = decodeURIComponent(tmparr[1]);
|
||||
var pval = this.params[field];
|
||||
|
||||
if ($.isArray(pval)) {
|
||||
pval[pval.length] = val;
|
||||
} else {
|
||||
this.params[field] = val;
|
||||
}
|
||||
}
|
||||
$("#limit").val(this.params.limit);
|
||||
$("#offset").val(this.params.offset);
|
||||
this.limit = this.params.limit;
|
||||
this.offset = this.params.offset;
|
||||
|
||||
this.getOffset = function() {
|
||||
var offset = $("#offset").val();
|
||||
return $.isNumeric(offset) ? Number(offset) : this.offset;
|
||||
}
|
||||
|
||||
this.getNextOffset = function() {
|
||||
return this.getOffset() + this.getLimit();
|
||||
}
|
||||
|
||||
this.getPrevOffset = function() {
|
||||
var v = this.getOffset() - this.getLimit();
|
||||
return v < 0 ? 0 : v;
|
||||
}
|
||||
|
||||
this.getLimit = function() {
|
||||
var limit = $("#limit").val();
|
||||
return $.isNumeric(limit) ? Number(limit) : this.limit;
|
||||
}
|
||||
|
||||
this.updateOffset = function(increment) {
|
||||
var val = $("#offset").val();
|
||||
var lim = $("#limit").val();
|
||||
if ($.isNumeric(val) && $.isNumeric(lim)) {
|
||||
if (increment) {
|
||||
$("#offset").val(this.getNextOffset());
|
||||
} else {
|
||||
$("#offset").val(this.getPrevOffset());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.saveAsUrl = function(params) {
|
||||
var pstr = $.param(params).replace(/%5B%5D/g,"[]");
|
||||
window.location.search = pstr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var Filters = function() {
|
||||
this.createFilterTable = function(filterList) {
|
||||
self = this;
|
||||
var paramFilterSel = filterList == null ? new Array() : filterList.split(",");
|
||||
var categories = new Array();
|
||||
self.addFilter("", categories, "General", "None", "De-select all filters", "none").click(
|
||||
function(){
|
||||
$("input.filter,input.all").attr("checked",false);
|
||||
$("#filter-reload").attr("disabled", false);
|
||||
}
|
||||
);
|
||||
self.addFilter("all", categories, "General", "All", "Show all filters", "all").click(
|
||||
function(){
|
||||
$("input.filter,input.none").attr("checked",false);
|
||||
$("#filter-reload").attr("disabled", false);
|
||||
}
|
||||
);
|
||||
|
||||
$.getJSON(
|
||||
"/rest/filters",
|
||||
function(data){
|
||||
$.each(data, function(index, filter){
|
||||
var checkbox = self.addFilter(filter["filter-name"], categories, filter.category, filter.title, filter.description, "filter").click(
|
||||
function(){
|
||||
$("input.none,input.all").attr("checked",false);
|
||||
$("#filter-reload").attr("disabled", false);
|
||||
}
|
||||
);
|
||||
$.each(paramFilterSel, function(index, filtername){
|
||||
if (filtername == filter["filter-name"]) {
|
||||
checkbox.attr("checked", true);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
this.addFilter = function(val, categories, category, title, description, cname) {
|
||||
var catdiv = null;
|
||||
for(var i=0; i<categories.length; i++) {
|
||||
if (categories[i].name == category) {
|
||||
catdiv = categories[i].div;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (catdiv == null) {
|
||||
catdiv = $("<fieldset class='catdiv'/>");
|
||||
catdiv.append($("<legend>"+category+"</legend>"));
|
||||
$("#filterdiv").append(catdiv);
|
||||
categories[categories.length] = {name: category, div: catdiv};
|
||||
}
|
||||
var div = $("<div/>");
|
||||
var input = $("<input name='filters[]' type='checkbox'/>");
|
||||
input.attr("id",val);
|
||||
input.val(val);
|
||||
input.addClass(cname);
|
||||
div.append(input);
|
||||
var ftitle = (title == null) ? val : title;
|
||||
var label = $("<label>" + ftitle + "</label>");
|
||||
label.attr("title", description);
|
||||
div.append(label);
|
||||
catdiv.append(div);
|
||||
return input;
|
||||
}
|
||||
|
||||
this.getFilterList = function() {
|
||||
var list="";
|
||||
$("input:checked[name='filters[]']").each(
|
||||
function(){
|
||||
if (list != "") {
|
||||
list += ",";
|
||||
}
|
||||
list += $(this).val();
|
||||
}
|
||||
);
|
||||
if (list == "") {
|
||||
list = "none";
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
var MetadataFields = function(report) {
|
||||
this.metadataSchemas = undefined;
|
||||
var self = this;
|
||||
|
||||
this.load = function(){
|
||||
$.ajax({
|
||||
url: "/rest/registries/schema",
|
||||
dataType: "json",
|
||||
success: function(data){
|
||||
self.initFields(data, report);
|
||||
},
|
||||
error: function(xhr, status, errorThrown) {
|
||||
alert("Error in /rest/registries/schema "+ status+ " " + errorThrown);
|
||||
},
|
||||
complete: function(xhr, status) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.initFields = function(data, report) {
|
||||
var params = report.myReportParameters.params;
|
||||
self.metadataSchemas = data;
|
||||
self.drawShowFields(params["show_fields[]"]);
|
||||
}
|
||||
|
||||
this.getShowFields = function(){
|
||||
var val = $("#show-fields select").val();
|
||||
return val == null ? Array() : val;
|
||||
}
|
||||
|
||||
this.drawShowFields = function(pfields) {
|
||||
var self = this;
|
||||
var sel = $("<select name='show_fields'/>").attr("multiple","true").attr("size","8").appendTo("#show-fields");
|
||||
$.each(this.metadataSchemas, function(index, schema){
|
||||
if (schema.prefix == 'eperson') {
|
||||
return;
|
||||
}
|
||||
$.each(schema.fields, function(findex, field) {
|
||||
var name = field.name;
|
||||
var opt = $("<option/>");
|
||||
opt.attr("value",name).text(name);
|
||||
for(var i=0; i<pfields.length; i++) {
|
||||
if (pfields[i] == name) {
|
||||
opt.attr("selected", true);
|
||||
}
|
||||
}
|
||||
sel.append(opt);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
this.initQueries = function(){};
|
||||
}
|
||||
|
||||
var HtmlUtil = function() {
|
||||
this.addTr = function(tbl) {
|
||||
var tr = $("<tr/>");
|
||||
tbl.append(tr);
|
||||
return tr;
|
||||
}
|
||||
|
||||
this.addTd = function(tr, val) {
|
||||
var td = $("<td/>");
|
||||
if (val != null) {
|
||||
td.append(val);
|
||||
}
|
||||
tr.append(td);
|
||||
return td;
|
||||
}
|
||||
|
||||
this.addTh = function(tr, val) {
|
||||
var th = $("<th/>");
|
||||
if (val != null) {
|
||||
th.append(val);
|
||||
}
|
||||
tr.append(th);
|
||||
return th;
|
||||
}
|
||||
|
||||
|
||||
this.addTdAnchor = function(tr, val, href) {
|
||||
return this.addTd(tr, this.getAnchor(val, href));
|
||||
}
|
||||
|
||||
this.getAnchor = function(val, href) {
|
||||
var a = $("<a/>");
|
||||
a.append(val);
|
||||
a.attr("href", href);
|
||||
a.attr("target", "_blank");
|
||||
return a;
|
||||
}
|
||||
|
||||
this.createOpt = function(name, val) {
|
||||
var opt = $("<option/>");
|
||||
opt.attr("value", val).text(name);
|
||||
return opt;
|
||||
}
|
||||
|
||||
this.addOpt = function(sel, name, val) {
|
||||
var opt = this.createOpt(name, val);
|
||||
sel.append(opt);
|
||||
return opt;
|
||||
}
|
||||
|
||||
this.addDisabledOpt = function(sel, name, val) {
|
||||
var opt = this.createOpt(name, val).attr("disabled",true);
|
||||
sel.append(opt);
|
||||
return opt;
|
||||
}
|
||||
|
||||
this.makeTotalCol = function(th) {
|
||||
th.append($("<hr><span class='num'>-</span>"));
|
||||
}
|
||||
|
||||
this.totalCol = function(index){
|
||||
var total = 0;
|
||||
$("#table tr.data").each(function(){
|
||||
var val = $($(this).find("td")[index]).text();
|
||||
if ($.isNumeric(val)) {
|
||||
total += Number(val);
|
||||
}
|
||||
});
|
||||
$($("#table tr.header th")[index]).find("span.num").text(total);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var CommunitySelector = function(report, parent, paramCollSel) {
|
||||
var self = this;
|
||||
var collSel = $("<select/>").attr("id","collSel").attr("name","collSel").attr("multiple", true).attr("size",15);
|
||||
parent.append(collSel);
|
||||
report.myHtmlUtil.addOpt(collSel, "Whole Repository", "");
|
||||
|
||||
$.ajax({
|
||||
url: "/rest/communities",
|
||||
data: {
|
||||
limit : report.COLL_LIMIT,
|
||||
expand : "subCommunities,collections"
|
||||
},
|
||||
dataType: "json",
|
||||
headers: report.myAuth.getHeaders(),
|
||||
success: function(data){
|
||||
var collSel = $("#collSel");
|
||||
var COMMS = {};
|
||||
var TOPCOMMS = {};
|
||||
$.each(data, function(index, comm){
|
||||
COMMS["comm"+report.getId(comm)] = comm;
|
||||
TOPCOMMS["comm"+report.getId(comm)] = comm;
|
||||
});
|
||||
$.each(data, function(index, comm){
|
||||
$.each(comm.subcommunities, function(index, scomm){
|
||||
delete TOPCOMMS["comm"+report.getId(scomm)];
|
||||
});
|
||||
});
|
||||
for(var commindex in TOPCOMMS) {
|
||||
self.addCommLabel(collSel, COMMS, COMMS[commindex], 0, paramCollSel);
|
||||
};
|
||||
},
|
||||
error: function(xhr, status, errorThrown) {
|
||||
alert("Error in /rest/communities "+ status+ " " + errorThrown);
|
||||
},
|
||||
complete: function(xhr, status) {
|
||||
}
|
||||
});
|
||||
|
||||
this.addCommLabel = function(collSel, COMMS, comm, indent, paramCollSel) {
|
||||
var prefix = "";
|
||||
for(var i=0; i<indent; i++) {
|
||||
prefix += "--";
|
||||
}
|
||||
report.myHtmlUtil.addDisabledOpt(collSel, prefix + comm.name, "comm" + report.getId(comm));
|
||||
if (comm.collections != null) {
|
||||
$.each(comm.collections, function(index, coll) {
|
||||
var opt = report.myHtmlUtil.addOpt(collSel, prefix + "--" + coll.name, report.getId(coll));
|
||||
$.each(paramCollSel, function(index, collid){
|
||||
if (collid == report.getId(coll)) {
|
||||
opt.attr("selected", true);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
if (comm.subcommunities != null) {
|
||||
$.each(comm.subcommunities, function(index, scomm) {
|
||||
self.addCommLabel(collSel, COMMS, COMMS["comm"+report.getId(scomm)], indent + 1, paramCollSel);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
361
dspace-rest/src/main/webapp/static/reports/spin.js
Normal file
361
dspace-rest/src/main/webapp/static/reports/spin.js
Normal file
@@ -0,0 +1,361 @@
|
||||
/**
|
||||
* Copyright (c) 2011-2014 Felix Gnass
|
||||
* Licensed under the MIT license
|
||||
*/
|
||||
|
||||
/*
|
||||
* The MIT License
|
||||
|
||||
Copyright (c) 2011-2014 Felix Gnass [fgnass at neteye dot de]
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
(function(root, factory) {
|
||||
|
||||
/* CommonJS */
|
||||
if (typeof exports == 'object') module.exports = factory()
|
||||
|
||||
/* AMD module */
|
||||
else if (typeof define == 'function' && define.amd) define(factory)
|
||||
|
||||
/* Browser global */
|
||||
else root.Spinner = factory()
|
||||
}
|
||||
(this, function() {
|
||||
"use strict";
|
||||
|
||||
var prefixes = ['webkit', 'Moz', 'ms', 'O'] /* Vendor prefixes */
|
||||
, animations = {} /* Animation rules keyed by their name */
|
||||
, useCssAnimations /* Whether to use CSS animations or setTimeout */
|
||||
|
||||
/**
|
||||
* Utility function to create elements. If no tag name is given,
|
||||
* a DIV is created. Optionally properties can be passed.
|
||||
*/
|
||||
function createEl(tag, prop) {
|
||||
var el = document.createElement(tag || 'div')
|
||||
, n
|
||||
|
||||
for(n in prop) el[n] = prop[n]
|
||||
return el
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends children and returns the parent.
|
||||
*/
|
||||
function ins(parent /* child1, child2, ...*/) {
|
||||
for (var i=1, n=arguments.length; i<n; i++)
|
||||
parent.appendChild(arguments[i])
|
||||
|
||||
return parent
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a new stylesheet to hold the @keyframe or VML rules.
|
||||
*/
|
||||
var sheet = (function() {
|
||||
var el = createEl('style', {type : 'text/css'})
|
||||
ins(document.getElementsByTagName('head')[0], el)
|
||||
return el.sheet || el.styleSheet
|
||||
}())
|
||||
|
||||
/**
|
||||
* Creates an opacity keyframe animation rule and returns its name.
|
||||
* Since most mobile Webkits have timing issues with animation-delay,
|
||||
* we create separate rules for each line/segment.
|
||||
*/
|
||||
function addAnimation(alpha, trail, i, lines) {
|
||||
var name = ['opacity', trail, ~~(alpha*100), i, lines].join('-')
|
||||
, start = 0.01 + i/lines * 100
|
||||
, z = Math.max(1 - (1-alpha) / trail * (100-start), alpha)
|
||||
, prefix = useCssAnimations.substring(0, useCssAnimations.indexOf('Animation')).toLowerCase()
|
||||
, pre = prefix && '-' + prefix + '-' || ''
|
||||
|
||||
if (!animations[name]) {
|
||||
sheet.insertRule(
|
||||
'@' + pre + 'keyframes ' + name + '{' +
|
||||
'0%{opacity:' + z + '}' +
|
||||
start + '%{opacity:' + alpha + '}' +
|
||||
(start+0.01) + '%{opacity:1}' +
|
||||
(start+trail) % 100 + '%{opacity:' + alpha + '}' +
|
||||
'100%{opacity:' + z + '}' +
|
||||
'}', sheet.cssRules.length)
|
||||
|
||||
animations[name] = 1
|
||||
}
|
||||
|
||||
return name
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries various vendor prefixes and returns the first supported property.
|
||||
*/
|
||||
function vendor(el, prop) {
|
||||
var s = el.style
|
||||
, pp
|
||||
, i
|
||||
|
||||
prop = prop.charAt(0).toUpperCase() + prop.slice(1)
|
||||
for(i=0; i<prefixes.length; i++) {
|
||||
pp = prefixes[i]+prop
|
||||
if(s[pp] !== undefined) return pp
|
||||
}
|
||||
if(s[prop] !== undefined) return prop
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets multiple style properties at once.
|
||||
*/
|
||||
function css(el, prop) {
|
||||
for (var n in prop)
|
||||
el.style[vendor(el, n)||n] = prop[n]
|
||||
|
||||
return el
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills in default values.
|
||||
*/
|
||||
function merge(obj) {
|
||||
for (var i=1; i < arguments.length; i++) {
|
||||
var def = arguments[i]
|
||||
for (var n in def)
|
||||
if (obj[n] === undefined) obj[n] = def[n]
|
||||
}
|
||||
return obj
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the line color from the given string or array.
|
||||
*/
|
||||
function getColor(color, idx) {
|
||||
return typeof color == 'string' ? color : color[idx % color.length]
|
||||
}
|
||||
|
||||
// Built-in defaults
|
||||
|
||||
var defaults = {
|
||||
lines: 12, // The number of lines to draw
|
||||
length: 7, // The length of each line
|
||||
width: 5, // The line thickness
|
||||
radius: 10, // The radius of the inner circle
|
||||
rotate: 0, // Rotation offset
|
||||
corners: 1, // Roundness (0..1)
|
||||
color: '#000', // #rgb or #rrggbb
|
||||
direction: 1, // 1: clockwise, -1: counterclockwise
|
||||
speed: 1, // Rounds per second
|
||||
trail: 100, // Afterglow percentage
|
||||
opacity: 1/4, // Opacity of the lines
|
||||
fps: 20, // Frames per second when using setTimeout()
|
||||
zIndex: 2e9, // Use a high z-index by default
|
||||
className: 'spinner', // CSS class to assign to the element
|
||||
top: '50%', // center vertically
|
||||
left: '50%', // center horizontally
|
||||
position: 'absolute' // element position
|
||||
}
|
||||
|
||||
/** The constructor */
|
||||
function Spinner(o) {
|
||||
this.opts = merge(o || {}, Spinner.defaults, defaults)
|
||||
}
|
||||
|
||||
// Global defaults that override the built-ins:
|
||||
Spinner.defaults = {}
|
||||
|
||||
merge(Spinner.prototype, {
|
||||
|
||||
/**
|
||||
* Adds the spinner to the given target element. If this instance is already
|
||||
* spinning, it is automatically removed from its previous target b calling
|
||||
* stop() internally.
|
||||
*/
|
||||
spin: function(target) {
|
||||
this.stop()
|
||||
|
||||
var self = this
|
||||
, o = self.opts
|
||||
, el = self.el = css(createEl(0, {className: o.className}), {position: o.position, width: 0, zIndex: o.zIndex})
|
||||
|
||||
css(el, {
|
||||
left: o.left,
|
||||
top: o.top
|
||||
})
|
||||
|
||||
if (target) {
|
||||
target.insertBefore(el, target.firstChild||null)
|
||||
}
|
||||
|
||||
el.setAttribute('role', 'progressbar')
|
||||
self.lines(el, self.opts)
|
||||
|
||||
if (!useCssAnimations) {
|
||||
// No CSS animation support, use setTimeout() instead
|
||||
var i = 0
|
||||
, start = (o.lines - 1) * (1 - o.direction) / 2
|
||||
, alpha
|
||||
, fps = o.fps
|
||||
, f = fps/o.speed
|
||||
, ostep = (1-o.opacity) / (f*o.trail / 100)
|
||||
, astep = f/o.lines
|
||||
|
||||
;(function anim() {
|
||||
i++;
|
||||
for (var j = 0; j < o.lines; j++) {
|
||||
alpha = Math.max(1 - (i + (o.lines - j) * astep) % f * ostep, o.opacity)
|
||||
|
||||
self.opacity(el, j * o.direction + start, alpha, o)
|
||||
}
|
||||
self.timeout = self.el && setTimeout(anim, ~~(1000/fps))
|
||||
})()
|
||||
}
|
||||
return self
|
||||
},
|
||||
|
||||
/**
|
||||
* Stops and removes the Spinner.
|
||||
*/
|
||||
stop: function() {
|
||||
var el = this.el
|
||||
if (el) {
|
||||
clearTimeout(this.timeout)
|
||||
if (el.parentNode) el.parentNode.removeChild(el)
|
||||
this.el = undefined
|
||||
}
|
||||
return this
|
||||
},
|
||||
|
||||
/**
|
||||
* Internal method that draws the individual lines. Will be overwritten
|
||||
* in VML fallback mode below.
|
||||
*/
|
||||
lines: function(el, o) {
|
||||
var i = 0
|
||||
, start = (o.lines - 1) * (1 - o.direction) / 2
|
||||
, seg
|
||||
|
||||
function fill(color, shadow) {
|
||||
return css(createEl(), {
|
||||
position: 'absolute',
|
||||
width: (o.length+o.width) + 'px',
|
||||
height: o.width + 'px',
|
||||
background: color,
|
||||
boxShadow: shadow,
|
||||
transformOrigin: 'left',
|
||||
transform: 'rotate(' + ~~(360/o.lines*i+o.rotate) + 'deg) translate(' + o.radius+'px' +',0)',
|
||||
borderRadius: (o.corners * o.width>>1) + 'px'
|
||||
})
|
||||
}
|
||||
|
||||
for (; i < o.lines; i++) {
|
||||
seg = css(createEl(), {
|
||||
position: 'absolute',
|
||||
top: 1+~(o.width/2) + 'px',
|
||||
transform: o.hwaccel ? 'translate3d(0,0,0)' : '',
|
||||
opacity: o.opacity,
|
||||
animation: useCssAnimations && addAnimation(o.opacity, o.trail, start + i * o.direction, o.lines) + ' ' + 1/o.speed + 's linear infinite'
|
||||
})
|
||||
|
||||
if (o.shadow) ins(seg, css(fill('#000', '0 0 4px ' + '#000'), {top: 2+'px'}))
|
||||
ins(el, ins(seg, fill(getColor(o.color, i), '0 0 1px rgba(0,0,0,.1)')))
|
||||
}
|
||||
return el
|
||||
},
|
||||
|
||||
/**
|
||||
* Internal method that adjusts the opacity of a single line.
|
||||
* Will be overwritten in VML fallback mode below.
|
||||
*/
|
||||
opacity: function(el, i, val) {
|
||||
if (i < el.childNodes.length) el.childNodes[i].style.opacity = val
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
|
||||
function initVML() {
|
||||
|
||||
/* Utility function to create a VML tag */
|
||||
function vml(tag, attr) {
|
||||
return createEl('<' + tag + ' xmlns="urn:schemas-microsoft.com:vml" class="spin-vml">', attr)
|
||||
}
|
||||
|
||||
// No CSS transforms but VML support, add a CSS rule for VML elements:
|
||||
sheet.addRule('.spin-vml', 'behavior:url(#default#VML)')
|
||||
|
||||
Spinner.prototype.lines = function(el, o) {
|
||||
var r = o.length+o.width
|
||||
, s = 2*r
|
||||
|
||||
function grp() {
|
||||
return css(
|
||||
vml('group', {
|
||||
coordsize: s + ' ' + s,
|
||||
coordorigin: -r + ' ' + -r
|
||||
}),
|
||||
{ width: s, height: s }
|
||||
)
|
||||
}
|
||||
|
||||
var margin = -(o.width+o.length)*2 + 'px'
|
||||
, g = css(grp(), {position: 'absolute', top: margin, left: margin})
|
||||
, i
|
||||
|
||||
function seg(i, dx, filter) {
|
||||
ins(g,
|
||||
ins(css(grp(), {rotation: 360 / o.lines * i + 'deg', left: ~~dx}),
|
||||
ins(css(vml('roundrect', {arcsize: o.corners}), {
|
||||
width: r,
|
||||
height: o.width,
|
||||
left: o.radius,
|
||||
top: -o.width>>1,
|
||||
filter: filter
|
||||
}),
|
||||
vml('fill', {color: getColor(o.color, i), opacity: o.opacity}),
|
||||
vml('stroke', {opacity: 0}) // transparent stroke to fix color bleeding upon opacity change
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
if (o.shadow)
|
||||
for (i = 1; i <= o.lines; i++)
|
||||
seg(i, -2, 'progid:DXImageTransform.Microsoft.Blur(pixelradius=2,makeshadow=1,shadowopacity=.3)')
|
||||
|
||||
for (i = 1; i <= o.lines; i++) seg(i)
|
||||
return ins(el, g)
|
||||
}
|
||||
|
||||
Spinner.prototype.opacity = function(el, i, val, o) {
|
||||
var c = el.firstChild
|
||||
o = o.shadow && o.lines || 0
|
||||
if (c && i+o < c.childNodes.length) {
|
||||
c = c.childNodes[i+o]; c = c && c.firstChild; c = c && c.firstChild
|
||||
if (c) c.opacity = val
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var probe = css(createEl('group'), {behavior: 'url(#default#VML)'})
|
||||
|
||||
if (!vendor(probe, 'transform') && probe.adj) initVML()
|
||||
else useCssAnimations = vendor(probe, 'animation')
|
||||
|
||||
return Spinner
|
||||
|
||||
}));
|
@@ -11,3 +11,135 @@ stats = true
|
||||
# By default, the DSpace REST API will only return communities/collections/items that are accessible to a particular user.
|
||||
# Set the rest-hierarchy-authenticate option to false to bypass authorization
|
||||
# rest-hierarchy-authenticate = false
|
||||
#------------------------------------------------------------------#
|
||||
# REST API Reporting Tools #
|
||||
#------------------------------------------------------------------#
|
||||
# This project is intended as an optional add-on to DSpace to provide
|
||||
# Quality Control Reporting for Collection Managers.
|
||||
#
|
||||
# See https://github.com/DSpace-Labs/DSpace-REST-Reports
|
||||
#
|
||||
# These reports utilize the DSpace REST API to provide a Collection
|
||||
# Manager with
|
||||
# - an overview of their collections
|
||||
# - a tool to query metadata for consistency
|
||||
#
|
||||
# When deploying the DSpace REST API, and institution may choose to
|
||||
# make the API publicly accessible or to restrict access to the API.
|
||||
# If these reports are deployed in a protected manner, the reporting
|
||||
# tools can be configured to bypass DSpace authorization when
|
||||
# reporting on collections and items.
|
||||
|
||||
##### Enable/disable authorization for the reporting tools. #####
|
||||
# By default, the DSpace REST API will only return communities/collections/items that are accessible to a particular user.
|
||||
# If the REST API has been deployed in a protected manner, the reporting tools can be configured to bypass authorization checks.
|
||||
# This will allow all items/collections/communities to be returned to the report user.
|
||||
# Set the rest-reporting-authenticate option to false to bypass authorization
|
||||
# rest-reporting-authenticate = false
|
||||
|
||||
##### Configure the report pages that can be requested by name #####
|
||||
# Create a map of named reports that are available to a report tool user
|
||||
# Each map entry should be prefixed with rest-report-url
|
||||
# The map key is a name for a report
|
||||
# The map value is a URL to a report page
|
||||
# A list of available reports will be available with the call /rest/reports.
|
||||
# If a request is sent to /rest/reports/[report key], the request will be re-directed to the specified URL
|
||||
#
|
||||
# This project currently contains 2 sample reports. Eventually, additional reports could be introduced through this mechanism.
|
||||
rest-report-url.collections = static/reports/index.html
|
||||
rest-report-url.item-query = static/reports/query.html
|
||||
#rest-report-url.custom =
|
||||
|
||||
##### database specific way to format a regex SQL clause #####
|
||||
# The REST Report Tools may pass a regular expression test to the database.
|
||||
# The following configuration setting will construct a SQL regular expression test appropriate to your database engine
|
||||
rest-regex-clause = text_value ~ ?
|
||||
|
||||
##### Configure REST Report Filters #####
|
||||
# A filter contains a set of tests that will be applied to an item to determine its inclusion in a particular report.
|
||||
# Private items and withdrawn items are frequently excluded from DSpace reports.
|
||||
# Additional filters can be configured to examine other item properties.
|
||||
# For instance, items containing an image bitstream often have different requirements from a item containing a PDF.
|
||||
# The DSpace REST reports come with a variety of filters that examine item properties, item bitstream properties,
|
||||
# and item authorization policies. The existing filters can be used as an example to construct institution specific filters
|
||||
# that will test conformity to a set of institutional policies.
|
||||
# plugin.sequence.org.dspace.rest.filter points to a list of classes that contain available filters.
|
||||
# Each class must implement the ItemFilterList interface.
|
||||
# ItemFilterDefs: Filters that examine simple item and bitstream type properties
|
||||
# ItemFilterDefsMisc: Filters that examine bitstream mime types and dependencies between bitstreams
|
||||
# ItemFilterDefsMeta: Filters that examine metadata properties
|
||||
# ItemFilterDefsPerm: Filters that examine item and bitstream authorization policies
|
||||
plugin.sequence.org.dspace.rest.filter.ItemFilterList = \
|
||||
org.dspace.rest.filter.ItemFilterDefs,\
|
||||
org.dspace.rest.filter.ItemFilterDefsMisc,\
|
||||
org.dspace.rest.filter.ItemFilterDefsPerm
|
||||
|
||||
# org.dspace.rest.filter.ItemFilterDefsMeta,\
|
||||
|
||||
##### Configuration Settings used by REST Report Filters #####
|
||||
|
||||
# Define the set of supported bitstream bundle names for your repository as a comma separated list
|
||||
rest-report-supp-bundles = ORIGINAL,THUMBNAIL,TEXT,LICENSE
|
||||
|
||||
# Define the bitstream mime types that will be interpreted as a "document".
|
||||
# Generally, a "document" should be expected to be searchable and to have a TEXT bitstream. An institution may expect document types to
|
||||
# have a thumbnail.
|
||||
rest-report-mime-document = text/plain,application/pdf,text/html,application/msword,text/xml,application/vnd.openxmlformats-officedocument.wordprocessingml.document,application/vnd.ms-powerpoint,application/vnd.openxmlformats-officedocument.presentationml.presentation,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
|
||||
|
||||
# Define the standard/preferred bitstream mime types for document items for your repository
|
||||
# This setting allows the reporting tools to report on "supported" and "unsupported" document types.
|
||||
rest-report-mime-document-supported = application/pdf
|
||||
|
||||
# Define the standard/preferred bitstream mime types for image items for your repository
|
||||
# This setting allows the reporting tools to report on "supported" and "unsupported" image types.
|
||||
rest-report-mime-document-image = image/jpeg,image/jp2
|
||||
|
||||
# Minimum size for a supported PDF in the repository
|
||||
# PDF bitstreams smaller than this size will be highlighted in a report.
|
||||
# PDF files smaller than this size are potentially corrupt.
|
||||
rest-report-pdf-min-size = 20000
|
||||
|
||||
# Maximum size for a typical PDF in the repository
|
||||
# PDF bitstreams larger than this size will be highlighted in a report.
|
||||
# PDF files larger than this size may be slow to retrieve.
|
||||
rest-report-pdf-max-size = 25000000
|
||||
|
||||
# Minimum size for a thumbnail - could indicate a corrupted original
|
||||
# Thumbnail bitstreams smaller than this size will be highlighted in a report.
|
||||
# Thumbnail files smaller than this size are potentially corrupt.
|
||||
rest-report-thumbnail-min-size = 400
|
||||
|
||||
# Bitstream descriptor to identify generated thumbnails
|
||||
# The ImageMagick Thumbnail generator tags the thumbnails it has created with a standard description.
|
||||
# This description identifies thumbnails that can safely be re-generated.
|
||||
rest-report-gen-thumbnail-desc = Generated Thumbnail
|
||||
|
||||
#### Metadata Filtering by Regular Expression #####
|
||||
# Used by org.dspace.rest.filter.ItemFilterDefsMeta
|
||||
# This class filters items based on metadata properties.
|
||||
# These filters are useful for filtering a small set of items. These filters will be inefficient as a query tool.
|
||||
|
||||
# regex to detect compound subjects - detect subject terms that should be split into individual terms
|
||||
rest-report-regex-compound-subject = .*;.*
|
||||
|
||||
# regex to detect compound authors - detect author/creator names taht should be split into individual fields
|
||||
rest-report-regex-compound-author = .* and .*
|
||||
|
||||
# regex to detect unbreaking metadata - detect long unbreaking text that may not render properly on a page
|
||||
rest-report-regex-unbreaking = ^.*[^ ]{50,50}.*$
|
||||
|
||||
# regex to detect url in description - detect description fields that contain URL's
|
||||
rest-report-regex-url = ^.*(http://|https://|mailto:).*$
|
||||
|
||||
# regex to identify full text content from the provenance field
|
||||
# This test has been used to identfiy "full-text" content when harvesting DSpace content by Summon
|
||||
rest-report-regex-fulltext = ^.*No\\. of bitstreams(.|\\r|\\n|\\r\\n)*\\.(PDF|pdf|DOC|doc|PPT|ppt|DOCX|docx|PPTX|pptx).*$
|
||||
|
||||
# regex to identify very long metadata fields that may be slow to render
|
||||
rest-report-regex-long = ^[\\s\\S]{6000,}$
|
||||
|
||||
# regex to identify partial XML entities within a description field (a frequent problem found in ProQuest ETD's)
|
||||
rest-report-regex-xml-entity = ^.*&#.*$
|
||||
|
||||
# regex to identify non ascii characters in metadata
|
||||
rest-report-regex-non-ascii = ^.*[^\\p{ASCII}].*$
|
||||
|
Reference in New Issue
Block a user