mirror of
https://github.com/DSpace/DSpace.git
synced 2025-10-17 23:13:10 +00:00
Merged main into DURACOM-126
This commit is contained in:
@@ -51,6 +51,7 @@ 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.core.I18nUtil;
|
||||
import org.dspace.discovery.IndexableObject;
|
||||
import org.dspace.discovery.indexobject.IndexableCollection;
|
||||
import org.dspace.discovery.indexobject.IndexableCommunity;
|
||||
@@ -91,6 +92,7 @@ public class SyndicationFeed {
|
||||
|
||||
// default DC fields for entry
|
||||
protected String defaultTitleField = "dc.title";
|
||||
protected String defaultDescriptionField = "dc.description";
|
||||
protected String defaultAuthorField = "dc.contributor.author";
|
||||
protected String defaultDateField = "dc.date.issued";
|
||||
private static final String[] defaultDescriptionFields =
|
||||
@@ -196,15 +198,15 @@ public class SyndicationFeed {
|
||||
// dso is null for the whole site, or a search without scope
|
||||
if (dso == null) {
|
||||
defaultTitle = configurationService.getProperty("dspace.name");
|
||||
feed.setDescription(localize(labels, MSG_FEED_DESCRIPTION));
|
||||
defaultDescriptionField = localize(labels, MSG_FEED_DESCRIPTION);
|
||||
objectURL = resolveURL(request, null);
|
||||
} else {
|
||||
Bitstream logo = null;
|
||||
if (dso instanceof IndexableCollection) {
|
||||
Collection col = ((IndexableCollection) dso).getIndexedObject();
|
||||
defaultTitle = col.getName();
|
||||
feed.setDescription(collectionService.getMetadataFirstValue(col,
|
||||
CollectionService.MD_SHORT_DESCRIPTION, Item.ANY));
|
||||
defaultDescriptionField = collectionService.getMetadataFirstValue(col,
|
||||
CollectionService.MD_SHORT_DESCRIPTION, Item.ANY);
|
||||
logo = col.getLogo();
|
||||
String cols = configurationService.getProperty("webui.feed.podcast.collections");
|
||||
if (cols != null && cols.length() > 1 && cols.contains(col.getHandle())) {
|
||||
@@ -214,8 +216,8 @@ public class SyndicationFeed {
|
||||
} else if (dso instanceof IndexableCommunity) {
|
||||
Community comm = ((IndexableCommunity) dso).getIndexedObject();
|
||||
defaultTitle = comm.getName();
|
||||
feed.setDescription(communityService.getMetadataFirstValue(comm,
|
||||
CommunityService.MD_SHORT_DESCRIPTION, Item.ANY));
|
||||
defaultDescriptionField = communityService.getMetadataFirstValue(comm,
|
||||
CommunityService.MD_SHORT_DESCRIPTION, Item.ANY);
|
||||
logo = comm.getLogo();
|
||||
String comms = configurationService.getProperty("webui.feed.podcast.communities");
|
||||
if (comms != null && comms.length() > 1 && comms.contains(comm.getHandle())) {
|
||||
@@ -230,6 +232,12 @@ public class SyndicationFeed {
|
||||
}
|
||||
feed.setTitle(labels.containsKey(MSG_FEED_TITLE) ?
|
||||
localize(labels, MSG_FEED_TITLE) : defaultTitle);
|
||||
|
||||
if (defaultDescriptionField == null || defaultDescriptionField == "") {
|
||||
defaultDescriptionField = I18nUtil.getMessage("org.dspace.app.util.SyndicationFeed.no-description");
|
||||
}
|
||||
|
||||
feed.setDescription(defaultDescriptionField);
|
||||
feed.setLink(objectURL);
|
||||
feed.setPublishedDate(new Date());
|
||||
feed.setUri(objectURL);
|
||||
|
@@ -52,11 +52,6 @@ public class IPAuthentication implements AuthenticationMethod {
|
||||
*/
|
||||
private static Logger log = org.apache.logging.log4j.LogManager.getLogger(IPAuthentication.class);
|
||||
|
||||
/**
|
||||
* Whether to look for x-forwarded headers for logging IP addresses
|
||||
*/
|
||||
protected static Boolean useProxies;
|
||||
|
||||
/**
|
||||
* All the IP matchers
|
||||
*/
|
||||
@@ -250,7 +245,7 @@ public class IPAuthentication implements AuthenticationMethod {
|
||||
|
||||
log.debug(LogHelper.getHeader(context, "authenticated",
|
||||
"special_groups=" + gsb.toString()
|
||||
+ " (by IP=" + addr + ", useProxies=" + useProxies.toString() + ")"
|
||||
+ " (by IP=" + addr + ")"
|
||||
));
|
||||
}
|
||||
|
||||
|
@@ -48,6 +48,12 @@ public abstract class DSpaceObject implements Serializable, ReloadableEntity<jav
|
||||
@Transient
|
||||
private StringBuffer eventDetails = null;
|
||||
|
||||
/**
|
||||
* The same order should be applied inside this comparator
|
||||
* {@link MetadataValueComparators#defaultComparator} to preserve
|
||||
* ordering while the list has been modified and not yet persisted
|
||||
* and reloaded.
|
||||
*/
|
||||
@OneToMany(fetch = FetchType.LAZY, mappedBy = "dSpaceObject", cascade = CascadeType.ALL, orphanRemoval = true)
|
||||
@OrderBy("metadataField, place")
|
||||
private List<MetadataValue> metadata = new ArrayList<>();
|
||||
@@ -116,7 +122,7 @@ public abstract class DSpaceObject implements Serializable, ReloadableEntity<jav
|
||||
* @return summary of event details, or null if there are none.
|
||||
*/
|
||||
public String getDetails() {
|
||||
return (eventDetails == null ? null : eventDetails.toString());
|
||||
return eventDetails == null ? null : eventDetails.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -145,7 +151,7 @@ public abstract class DSpaceObject implements Serializable, ReloadableEntity<jav
|
||||
* one
|
||||
*/
|
||||
public String getHandle() {
|
||||
return (CollectionUtils.isNotEmpty(handles) ? handles.get(0).getHandle() : null);
|
||||
return CollectionUtils.isNotEmpty(handles) ? handles.get(0).getHandle() : null;
|
||||
}
|
||||
|
||||
void setHandle(List<Handle> handle) {
|
||||
|
@@ -126,6 +126,11 @@ public abstract class DSpaceObjectServiceImpl<T extends DSpaceObject> implements
|
||||
}
|
||||
}
|
||||
|
||||
// Sort the metadataValues if they have been modified,
|
||||
// is used to preserve the default order.
|
||||
if (dso.isMetadataModified()) {
|
||||
values.sort(MetadataValueComparators.defaultComparator);
|
||||
}
|
||||
// Create an array of matching values
|
||||
return values;
|
||||
}
|
||||
@@ -542,7 +547,7 @@ public abstract class DSpaceObjectServiceImpl<T extends DSpaceObject> implements
|
||||
|
||||
int add = 4 - tokens.length;
|
||||
if (add > 0) {
|
||||
tokens = (String[]) ArrayUtils.addAll(tokens, new String[add]);
|
||||
tokens = ArrayUtils.addAll(tokens, new String[add]);
|
||||
}
|
||||
|
||||
return tokens;
|
||||
@@ -603,21 +608,18 @@ public abstract class DSpaceObjectServiceImpl<T extends DSpaceObject> implements
|
||||
//If two places are the same then the MetadataValue instance will be placed before the
|
||||
//RelationshipMetadataValue instance.
|
||||
//This is done to ensure that the order is correct.
|
||||
metadataValues.sort(new Comparator<MetadataValue>() {
|
||||
@Override
|
||||
public int compare(MetadataValue o1, MetadataValue o2) {
|
||||
int compare = o1.getPlace() - o2.getPlace();
|
||||
if (compare == 0) {
|
||||
if (o1 instanceof RelationshipMetadataValue && o2 instanceof RelationshipMetadataValue) {
|
||||
return compare;
|
||||
} else if (o1 instanceof RelationshipMetadataValue) {
|
||||
return 1;
|
||||
} else if (o2 instanceof RelationshipMetadataValue) {
|
||||
return -1;
|
||||
}
|
||||
metadataValues.sort((o1, o2) -> {
|
||||
int compare = o1.getPlace() - o2.getPlace();
|
||||
if (compare == 0) {
|
||||
if (o1 instanceof RelationshipMetadataValue && o2 instanceof RelationshipMetadataValue) {
|
||||
return compare;
|
||||
} else if (o1 instanceof RelationshipMetadataValue) {
|
||||
return 1;
|
||||
} else if (o2 instanceof RelationshipMetadataValue) {
|
||||
return -1;
|
||||
}
|
||||
return compare;
|
||||
}
|
||||
return compare;
|
||||
});
|
||||
for (MetadataValue metadataValue : metadataValues) {
|
||||
//Retrieve & store the place for each metadata value
|
||||
@@ -634,7 +636,7 @@ public abstract class DSpaceObjectServiceImpl<T extends DSpaceObject> implements
|
||||
String authority = metadataValue.getAuthority();
|
||||
String relationshipId = StringUtils.split(authority, "::")[1];
|
||||
Relationship relationship = relationshipService.find(context, Integer.parseInt(relationshipId));
|
||||
if (relationship.getLeftItem().equals((Item) dso)) {
|
||||
if (relationship.getLeftItem().equals(dso)) {
|
||||
relationship.setLeftPlace(mvPlace);
|
||||
} else {
|
||||
relationship.setRightPlace(mvPlace);
|
||||
|
@@ -12,7 +12,6 @@ import java.io.InputStream;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
@@ -288,9 +287,10 @@ public class ItemServiceImpl extends DSpaceObjectServiceImpl<Item> implements It
|
||||
return itemDAO.findAll(context, true, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Item> findAllRegularItems(Context context) throws SQLException {
|
||||
return itemDAO.findAllRegularItems(context);
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Item> findBySubmitter(Context context, EPerson eperson) throws SQLException {
|
||||
@@ -1054,7 +1054,7 @@ public class ItemServiceImpl extends DSpaceObjectServiceImpl<Item> implements It
|
||||
List<Collection> linkedCollections = item.getCollections();
|
||||
List<Collection> notLinkedCollections = new ArrayList<>(allCollections.size() - linkedCollections.size());
|
||||
|
||||
if ((allCollections.size() - linkedCollections.size()) == 0) {
|
||||
if (allCollections.size() - linkedCollections.size() == 0) {
|
||||
return notLinkedCollections;
|
||||
}
|
||||
for (Collection collection : allCollections) {
|
||||
@@ -1149,6 +1149,7 @@ public class ItemServiceImpl extends DSpaceObjectServiceImpl<Item> implements It
|
||||
* @return <code>true</code> if the item is an inprogress submission, i.e. a WorkspaceItem or WorkflowItem
|
||||
* @throws SQLException An exception that provides information on a database access error or other errors.
|
||||
*/
|
||||
@Override
|
||||
public boolean isInProgressSubmission(Context context, Item item) throws SQLException {
|
||||
return workspaceItemService.findByItem(context, item) != null
|
||||
|| workflowItemService.findByItem(context, item) != null;
|
||||
@@ -1179,8 +1180,8 @@ prevent the generation of resource policy entry values with null dspace_object a
|
||||
if (!authorizeService
|
||||
.isAnIdenticalPolicyAlreadyInPlace(context, dso, defaultPolicy.getGroup(), Constants.READ,
|
||||
defaultPolicy.getID()) &&
|
||||
((!appendMode && this.isNotAlreadyACustomRPOfThisTypeOnDSO(context, dso)) ||
|
||||
(appendMode && this.shouldBeAppended(context, dso, defaultPolicy)))) {
|
||||
(!appendMode && this.isNotAlreadyACustomRPOfThisTypeOnDSO(context, dso) ||
|
||||
appendMode && this.shouldBeAppended(context, dso, defaultPolicy))) {
|
||||
ResourcePolicy newPolicy = resourcePolicyService.clone(context, defaultPolicy);
|
||||
newPolicy.setdSpaceObject(dso);
|
||||
newPolicy.setAction(Constants.READ);
|
||||
@@ -1222,7 +1223,7 @@ prevent the generation of resource policy entry values with null dspace_object a
|
||||
* Check if the provided default policy should be appended or not to the final
|
||||
* item. If an item has at least one custom READ policy any anonymous READ
|
||||
* policy with empty start/end date should be skipped
|
||||
*
|
||||
*
|
||||
* @param context DSpace context
|
||||
* @param dso DSpace object to check for custom read RP
|
||||
* @param defaultPolicy The policy to check
|
||||
@@ -1611,7 +1612,7 @@ prevent the generation of resource policy entry values with null dspace_object a
|
||||
fullMetadataValueList.addAll(relationshipMetadataService.getRelationshipMetadata(item, true));
|
||||
fullMetadataValueList.addAll(dbMetadataValues);
|
||||
|
||||
item.setCachedMetadata(sortMetadataValueList(fullMetadataValueList));
|
||||
item.setCachedMetadata(MetadataValueComparators.sort(fullMetadataValueList));
|
||||
}
|
||||
|
||||
log.debug("Called getMetadata for " + item.getID() + " based on cache");
|
||||
@@ -1653,28 +1654,6 @@ prevent the generation of resource policy entry values with null dspace_object a
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will sort the List of MetadataValue objects based on the MetadataSchema, MetadataField Element,
|
||||
* MetadataField Qualifier and MetadataField Place in that order.
|
||||
* @param listToReturn The list to be sorted
|
||||
* @return The list sorted on those criteria
|
||||
*/
|
||||
private List<MetadataValue> sortMetadataValueList(List<MetadataValue> listToReturn) {
|
||||
Comparator<MetadataValue> comparator = Comparator.comparing(
|
||||
metadataValue -> metadataValue.getMetadataField().getMetadataSchema().getName(),
|
||||
Comparator.nullsFirst(Comparator.naturalOrder()));
|
||||
comparator = comparator.thenComparing(metadataValue -> metadataValue.getMetadataField().getElement(),
|
||||
Comparator.nullsFirst(Comparator.naturalOrder()));
|
||||
comparator = comparator.thenComparing(metadataValue -> metadataValue.getMetadataField().getQualifier(),
|
||||
Comparator.nullsFirst(Comparator.naturalOrder()));
|
||||
comparator = comparator.thenComparing(metadataValue -> metadataValue.getPlace(),
|
||||
Comparator.nullsFirst(Comparator.naturalOrder()));
|
||||
|
||||
Stream<MetadataValue> metadataValueStream = listToReturn.stream().sorted(comparator);
|
||||
listToReturn = metadataValueStream.collect(Collectors.toList());
|
||||
return listToReturn;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MetadataValue addMetadata(Context context, Item dso, String schema, String element, String qualifier,
|
||||
String lang, String value, String authority, int confidence, int place) throws SQLException {
|
||||
|
@@ -19,6 +19,7 @@ import javax.persistence.Lob;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.SequenceGenerator;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Transient;
|
||||
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.core.ReloadableEntity;
|
||||
@@ -171,6 +172,14 @@ public class MetadataValue implements ReloadableEntity<Integer> {
|
||||
this.metadataField = metadataField;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@code MetadataField#getID()}
|
||||
*/
|
||||
@Transient
|
||||
protected Integer getMetadataFieldId() {
|
||||
return getMetadataField().getID();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the metadata value.
|
||||
*
|
||||
|
@@ -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.content;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* This class contains only static members that can be used
|
||||
* to sort list of {@link MetadataValue}
|
||||
*
|
||||
* @author Vincenzo Mecca (vins01-4science - vincenzo.mecca at 4science.com)
|
||||
*
|
||||
*/
|
||||
public final class MetadataValueComparators {
|
||||
|
||||
private MetadataValueComparators() {}
|
||||
|
||||
/**
|
||||
* This is the default comparator that mimics the ordering
|
||||
* applied by the standard {@code @OrderBy} annotation inside
|
||||
* {@link DSpaceObject#getMetadata()}
|
||||
*/
|
||||
public static final Comparator<MetadataValue> defaultComparator =
|
||||
Comparator.comparing(MetadataValue::getMetadataFieldId)
|
||||
.thenComparing(
|
||||
MetadataValue::getPlace,
|
||||
Comparator.nullsFirst(Comparator.naturalOrder())
|
||||
);
|
||||
|
||||
/**
|
||||
* This method creates a new {@code List<MetadataValue>} ordered by the
|
||||
* {@code MetadataComparators#defaultComparator}.
|
||||
*
|
||||
* @param metadataValues
|
||||
* @return {@code List<MetadataValue>} ordered copy list using stream.
|
||||
*/
|
||||
public static final List<MetadataValue> sort(List<MetadataValue> metadataValues) {
|
||||
return metadataValues
|
||||
.stream()
|
||||
.sorted(MetadataValueComparators.defaultComparator)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
}
|
@@ -306,6 +306,7 @@ public class VersionedHandleIdentifierProviderWithCanonicalHandles extends Ident
|
||||
public DSpaceObject resolve(Context context, String identifier, String... attributes) {
|
||||
// We can do nothing with this, return null
|
||||
try {
|
||||
identifier = handleService.parseHandle(identifier);
|
||||
return handleService.resolveToObject(context, identifier);
|
||||
} catch (IllegalStateException | SQLException e) {
|
||||
log.error(LogHelper.getHeader(context, "Error while resolving handle to item", "handle: " + identifier),
|
||||
@@ -426,6 +427,19 @@ public class VersionedHandleIdentifierProviderWithCanonicalHandles extends Ident
|
||||
}
|
||||
}
|
||||
|
||||
DSpaceObject itemWithCanonicalHandle = handleService.resolveToObject(context, canonical);
|
||||
if (itemWithCanonicalHandle != null) {
|
||||
if (itemWithCanonicalHandle.getID() != previous.getItem().getID()) {
|
||||
log.warn("The previous version's item (" + previous.getItem().getID() +
|
||||
") does not match with the item containing handle " + canonical +
|
||||
" (" + itemWithCanonicalHandle.getID() + ")");
|
||||
}
|
||||
// Move the original handle from whatever item it's on to the newest version
|
||||
handleService.modifyHandleDSpaceObject(context, canonical, dso);
|
||||
} else {
|
||||
handleService.createHandle(context, dso, canonical);
|
||||
}
|
||||
|
||||
// add a new Identifier for this item: 12345/100.x
|
||||
String idNew = canonical + DOT + version.getVersionNumber();
|
||||
//Make sure we don't have an old handle hanging around (if our previous version was deleted in the workspace)
|
||||
|
@@ -121,12 +121,14 @@ public class PubmedDateMetadatumContributor<T> implements MetadataContributor<T>
|
||||
|
||||
int j = 0;
|
||||
// Use the first dcDate that has been formatted (Config should go from most specific to most lenient)
|
||||
while (j < dateFormatsToAttempt.size() && dcDate == null) {
|
||||
while (j < dateFormatsToAttempt.size()) {
|
||||
String dateFormat = dateFormatsToAttempt.get(j);
|
||||
try {
|
||||
SimpleDateFormat formatter = new SimpleDateFormat(dateFormat);
|
||||
Date date = formatter.parse(dateString);
|
||||
dcDate = new DCDate(date);
|
||||
values.add(metadataFieldMapping.toDCValue(field, formatter.format(date)));
|
||||
break;
|
||||
} catch (ParseException e) {
|
||||
// Multiple dateformats can be configured, we don't want to print the entire stacktrace every
|
||||
// time one of those formats fails.
|
||||
@@ -136,9 +138,7 @@ public class PubmedDateMetadatumContributor<T> implements MetadataContributor<T>
|
||||
}
|
||||
j++;
|
||||
}
|
||||
if (dcDate != null) {
|
||||
values.add(metadataFieldMapping.toDCValue(field, dcDate.toString()));
|
||||
} else {
|
||||
if (dcDate == null) {
|
||||
log.info(
|
||||
"Failed parsing " + dateString + ", check " +
|
||||
"the configured dataformats in config/spring/api/pubmed-integration.xml");
|
||||
|
@@ -51,6 +51,7 @@ metadata.bitstream.iiif-virtual.bytes = File size
|
||||
metadata.bitstream.iiif-virtual.checksum = Checksum
|
||||
|
||||
org.dspace.app.itemexport.no-result = The DSpaceObject that you specified has no items.
|
||||
org.dspace.app.util.SyndicationFeed.no-description = No Description
|
||||
org.dspace.checker.ResultsLogger.bitstream-format = Bitstream format
|
||||
org.dspace.checker.ResultsLogger.bitstream-found = Bitstream found
|
||||
org.dspace.checker.ResultsLogger.bitstream-id = Bitstream ID
|
||||
|
@@ -13,15 +13,6 @@
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
|
||||
|
||||
|
||||
<!-- Identifier Service Application Interface. Will be autowired with
|
||||
any Identifier Providers present in Spring context.
|
||||
-->
|
||||
<bean id="org.dspace.identifier.service.IdentifierService"
|
||||
class="org.dspace.identifier.IdentifierServiceImpl"
|
||||
autowire="byType"
|
||||
scope="singleton"/>
|
||||
|
||||
<bean id="org.dspace.services.ConfigurationService"
|
||||
class="org.dspace.servicemanager.config.DSpaceConfigurationService" scope="singleton"/>
|
||||
|
||||
@@ -31,12 +22,6 @@
|
||||
<property name="configurationService" ref="org.dspace.services.ConfigurationService"/>
|
||||
</bean-->
|
||||
|
||||
<bean id="org.dspace.identifier.VersionedHandleIdentifierProvider"
|
||||
class="org.dspace.identifier.VersionedHandleIdentifierProvider"
|
||||
scope="singleton">
|
||||
<property name="configurationService" ref="org.dspace.services.ConfigurationService"/>
|
||||
</bean>
|
||||
|
||||
<bean name="org.dspace.core.DBConnection" class="org.dspace.core.HibernateDBConnection" lazy-init="true" scope="prototype"/>
|
||||
|
||||
<!-- Register all our Flyway callback classes (which run before/after database migrations) -->
|
||||
|
@@ -19,7 +19,18 @@
|
||||
<bean id="org.dspace.identifier.service.IdentifierService"
|
||||
class="org.dspace.identifier.IdentifierServiceImpl"
|
||||
autowire="byType"
|
||||
scope="singleton"/>
|
||||
scope="singleton">
|
||||
<property name="providers">
|
||||
<list>
|
||||
<ref bean="org.dspace.identifier.HandleIdentifierProvider"/>
|
||||
<ref bean="org.dspace.identifier.DOIIdentifierProvider"/>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="org.dspace.identifier.HandleIdentifierProvider" class="org.dspace.identifier.VersionedHandleIdentifierProvider" scope="singleton">
|
||||
<property name="configurationService" ref="org.dspace.services.ConfigurationService"/>
|
||||
</bean>
|
||||
|
||||
<!-- provider to mint and register DOIs with DSpace.
|
||||
To mint DOIs you need a registration agency. The DOIIdentifierProvider
|
||||
|
@@ -9,6 +9,7 @@ package org.dspace.content.service;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.fail;
|
||||
@@ -112,6 +113,177 @@ public class ItemServiceTest extends AbstractIntegrationTestWithDatabase {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void preserveMetadataOrder() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
itemService
|
||||
.addMetadata(
|
||||
context, item, dcSchema, contributorElement, authorQualifier, null, "test, one", null, 0, 2
|
||||
);
|
||||
MetadataValue placeZero =
|
||||
itemService
|
||||
.addMetadata(
|
||||
context, item, dcSchema, contributorElement, authorQualifier, null, "test, two", null, 0, 0
|
||||
);
|
||||
itemService
|
||||
.addMetadata(
|
||||
context, item, dcSchema, contributorElement, authorQualifier, null, "test, three", null, 0, 1
|
||||
);
|
||||
|
||||
context.commit();
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
// check the correct order using default method `getMetadata`
|
||||
List<MetadataValue> defaultMetadata =
|
||||
this.itemService.getMetadata(item, dcSchema, contributorElement, authorQualifier, Item.ANY);
|
||||
|
||||
assertThat(defaultMetadata,hasSize(3));
|
||||
|
||||
assertMetadataValue(
|
||||
authorQualifier, contributorElement, dcSchema, "test, two", null, 0, defaultMetadata.get(0)
|
||||
);
|
||||
assertMetadataValue(
|
||||
authorQualifier, contributorElement, dcSchema, "test, three", null, 1, defaultMetadata.get(1)
|
||||
);
|
||||
assertMetadataValue(
|
||||
authorQualifier, contributorElement, dcSchema, "test, one", null, 2, defaultMetadata.get(2)
|
||||
);
|
||||
|
||||
// check the correct order using the method `getMetadata` without virtual fields
|
||||
List<MetadataValue> nonVirtualMetadatas =
|
||||
this.itemService.getMetadata(item, dcSchema, contributorElement, authorQualifier, Item.ANY, false);
|
||||
|
||||
// if we don't reload the item the place order is not applied correctly
|
||||
// item = context.reloadEntity(item);
|
||||
|
||||
assertThat(nonVirtualMetadatas,hasSize(3));
|
||||
|
||||
assertMetadataValue(
|
||||
authorQualifier, contributorElement, dcSchema, "test, two", null, 0, nonVirtualMetadatas.get(0)
|
||||
);
|
||||
assertMetadataValue(
|
||||
authorQualifier, contributorElement, dcSchema, "test, three", null, 1, nonVirtualMetadatas.get(1)
|
||||
);
|
||||
assertMetadataValue(
|
||||
authorQualifier, contributorElement, dcSchema, "test, one", null, 2, nonVirtualMetadatas.get(2)
|
||||
);
|
||||
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
||||
item = context.reloadEntity(item);
|
||||
|
||||
// now just add one metadata to be the last
|
||||
this.itemService.addMetadata(
|
||||
context, item, dcSchema, contributorElement, authorQualifier, Item.ANY, "test, latest", null, 0
|
||||
);
|
||||
// now just remove first metadata
|
||||
this.itemService.removeMetadataValues(context, item, List.of(placeZero));
|
||||
// now just add one metadata to place 0
|
||||
this.itemService.addAndShiftRightMetadata(
|
||||
context, item, dcSchema, contributorElement, authorQualifier, Item.ANY, "test, new", null, 0, 0
|
||||
);
|
||||
|
||||
// check the metadata using method `getMetadata`
|
||||
defaultMetadata =
|
||||
this.itemService.getMetadata(item, dcSchema, contributorElement, authorQualifier, Item.ANY);
|
||||
|
||||
// check correct places
|
||||
assertThat(defaultMetadata,hasSize(4));
|
||||
|
||||
assertMetadataValue(
|
||||
authorQualifier, contributorElement, dcSchema, "test, new", null, 0, defaultMetadata.get(0)
|
||||
);
|
||||
assertMetadataValue(
|
||||
authorQualifier, contributorElement, dcSchema, "test, three", null, 1, defaultMetadata.get(1)
|
||||
);
|
||||
assertMetadataValue(
|
||||
authorQualifier, contributorElement, dcSchema, "test, one", null, 2, defaultMetadata.get(2)
|
||||
);
|
||||
assertMetadataValue(
|
||||
authorQualifier, contributorElement, dcSchema, "test, latest", null, 3, defaultMetadata.get(3)
|
||||
);
|
||||
|
||||
// check metadata using nonVirtualMethod
|
||||
nonVirtualMetadatas =
|
||||
this.itemService.getMetadata(item, dcSchema, contributorElement, authorQualifier, Item.ANY, false);
|
||||
|
||||
// check correct places
|
||||
assertThat(nonVirtualMetadatas,hasSize(4));
|
||||
|
||||
assertMetadataValue(
|
||||
authorQualifier, contributorElement, dcSchema, "test, new", null, 0, nonVirtualMetadatas.get(0)
|
||||
);
|
||||
assertMetadataValue(
|
||||
authorQualifier, contributorElement, dcSchema, "test, three", null, 1, nonVirtualMetadatas.get(1)
|
||||
);
|
||||
assertMetadataValue(
|
||||
authorQualifier, contributorElement, dcSchema, "test, one", null, 2, nonVirtualMetadatas.get(2)
|
||||
);
|
||||
assertMetadataValue(
|
||||
authorQualifier, contributorElement, dcSchema, "test, latest", null, 3, nonVirtualMetadatas.get(3)
|
||||
);
|
||||
|
||||
// check both lists
|
||||
assertThat(defaultMetadata.size(), equalTo(nonVirtualMetadatas.size()));
|
||||
assertThat(defaultMetadata.get(0), equalTo(nonVirtualMetadatas.get(0)));
|
||||
assertThat(defaultMetadata.get(1), equalTo(nonVirtualMetadatas.get(1)));
|
||||
assertThat(defaultMetadata.get(2), equalTo(nonVirtualMetadatas.get(2)));
|
||||
assertThat(defaultMetadata.get(3), equalTo(nonVirtualMetadatas.get(3)));
|
||||
|
||||
context.commit();
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
item = context.reloadEntity(item);
|
||||
|
||||
// check after commit
|
||||
defaultMetadata =
|
||||
this.itemService.getMetadata(item, dcSchema, contributorElement, authorQualifier, Item.ANY);
|
||||
|
||||
// check correct places
|
||||
assertThat(defaultMetadata,hasSize(4));
|
||||
|
||||
assertMetadataValue(
|
||||
authorQualifier, contributorElement, dcSchema, "test, new", null, 0, defaultMetadata.get(0)
|
||||
);
|
||||
assertMetadataValue(
|
||||
authorQualifier, contributorElement, dcSchema, "test, three", null, 1, defaultMetadata.get(1)
|
||||
);
|
||||
assertMetadataValue(
|
||||
authorQualifier, contributorElement, dcSchema, "test, one", null, 2, defaultMetadata.get(2)
|
||||
);
|
||||
assertMetadataValue(
|
||||
authorQualifier, contributorElement, dcSchema, "test, latest", null, 3, defaultMetadata.get(3)
|
||||
);
|
||||
|
||||
// check metadata using nonVirtualMethod
|
||||
nonVirtualMetadatas =
|
||||
this.itemService.getMetadata(item, dcSchema, contributorElement, authorQualifier, Item.ANY, false);
|
||||
|
||||
// check correct places
|
||||
assertThat(nonVirtualMetadatas,hasSize(4));
|
||||
|
||||
assertMetadataValue(
|
||||
authorQualifier, contributorElement, dcSchema, "test, new", null, 0, nonVirtualMetadatas.get(0)
|
||||
);
|
||||
assertMetadataValue(
|
||||
authorQualifier, contributorElement, dcSchema, "test, three", null, 1, nonVirtualMetadatas.get(1)
|
||||
);
|
||||
assertMetadataValue(
|
||||
authorQualifier, contributorElement, dcSchema, "test, one", null, 2, nonVirtualMetadatas.get(2)
|
||||
);
|
||||
assertMetadataValue(
|
||||
authorQualifier, contributorElement, dcSchema, "test, latest", null, 3, nonVirtualMetadatas.get(3)
|
||||
);
|
||||
|
||||
// check both lists
|
||||
assertThat(defaultMetadata.size(), equalTo(nonVirtualMetadatas.size()));
|
||||
assertThat(defaultMetadata.get(0), equalTo(nonVirtualMetadatas.get(0)));
|
||||
assertThat(defaultMetadata.get(1), equalTo(nonVirtualMetadatas.get(1)));
|
||||
assertThat(defaultMetadata.get(2), equalTo(nonVirtualMetadatas.get(2)));
|
||||
assertThat(defaultMetadata.get(3), equalTo(nonVirtualMetadatas.get(3)));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void InsertAndMoveMetadataShiftPlaceTest() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
@@ -0,0 +1,115 @@
|
||||
/**
|
||||
* 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.identifier;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.dspace.AbstractIntegrationTestWithDatabase;
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.builder.CollectionBuilder;
|
||||
import org.dspace.builder.CommunityBuilder;
|
||||
import org.dspace.builder.ItemBuilder;
|
||||
import org.dspace.builder.VersionBuilder;
|
||||
import org.dspace.content.Collection;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.kernel.ServiceManager;
|
||||
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
public class VersionedHandleIdentifierProviderTest extends AbstractIntegrationTestWithDatabase {
|
||||
private ServiceManager serviceManager;
|
||||
private IdentifierServiceImpl identifierService;
|
||||
|
||||
private String firstHandle;
|
||||
|
||||
private Collection collection;
|
||||
private Item itemV1;
|
||||
private Item itemV2;
|
||||
private Item itemV3;
|
||||
|
||||
@Before
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
||||
serviceManager = DSpaceServicesFactory.getInstance().getServiceManager();
|
||||
identifierService = serviceManager.getServicesByType(IdentifierServiceImpl.class).get(0);
|
||||
// Clean out providers to avoid any being used for creation of community and collection
|
||||
identifierService.setProviders(new ArrayList<>());
|
||||
|
||||
parentCommunity = CommunityBuilder.createCommunity(context)
|
||||
.withName("Parent Community")
|
||||
.build();
|
||||
collection = CollectionBuilder.createCollection(context, parentCommunity)
|
||||
.withName("Collection")
|
||||
.build();
|
||||
}
|
||||
|
||||
private void registerProvider(Class type) {
|
||||
// Register our new provider
|
||||
serviceManager.registerServiceClass(type.getName(), type);
|
||||
IdentifierProvider identifierProvider =
|
||||
(IdentifierProvider) serviceManager.getServiceByName(type.getName(), type);
|
||||
|
||||
// Overwrite the identifier-service's providers with the new one to ensure only this provider is used
|
||||
identifierService.setProviders(List.of(identifierProvider));
|
||||
}
|
||||
|
||||
private void createVersions() throws SQLException, AuthorizeException {
|
||||
itemV1 = ItemBuilder.createItem(context, collection)
|
||||
.withTitle("First version")
|
||||
.build();
|
||||
firstHandle = itemV1.getHandle();
|
||||
itemV2 = VersionBuilder.createVersion(context, itemV1, "Second version").build().getItem();
|
||||
itemV3 = VersionBuilder.createVersion(context, itemV1, "Third version").build().getItem();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultVersionedHandleProvider() throws Exception {
|
||||
registerProvider(VersionedHandleIdentifierProvider.class);
|
||||
createVersions();
|
||||
|
||||
// Confirm the original item only has its original handle
|
||||
assertEquals(firstHandle, itemV1.getHandle());
|
||||
assertEquals(1, itemV1.getHandles().size());
|
||||
// Confirm the second item has the correct version handle
|
||||
assertEquals(firstHandle + ".2", itemV2.getHandle());
|
||||
assertEquals(1, itemV2.getHandles().size());
|
||||
// Confirm the last item has the correct version handle
|
||||
assertEquals(firstHandle + ".3", itemV3.getHandle());
|
||||
assertEquals(1, itemV3.getHandles().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCanonicalVersionedHandleProvider() throws Exception {
|
||||
registerProvider(VersionedHandleIdentifierProviderWithCanonicalHandles.class);
|
||||
createVersions();
|
||||
|
||||
// Confirm the original item only has a version handle
|
||||
assertEquals(firstHandle + ".1", itemV1.getHandle());
|
||||
assertEquals(1, itemV1.getHandles().size());
|
||||
// Confirm the second item has the correct version handle
|
||||
assertEquals(firstHandle + ".2", itemV2.getHandle());
|
||||
assertEquals(1, itemV2.getHandles().size());
|
||||
// Confirm the last item has both the correct version handle and the original handle
|
||||
assertEquals(firstHandle, itemV3.getHandle());
|
||||
assertEquals(2, itemV3.getHandles().size());
|
||||
containsHandle(itemV3, firstHandle + ".3");
|
||||
}
|
||||
|
||||
private void containsHandle(Item item, String handle) {
|
||||
assertTrue(item.getHandles().stream().anyMatch(h -> handle.equals(h.getHandle())));
|
||||
}
|
||||
}
|
@@ -249,4 +249,24 @@ public class OpenSearchControllerIT extends AbstractControllerIntegrationTest {
|
||||
</OpenSearchDescription>
|
||||
*/
|
||||
}
|
||||
|
||||
@Test
|
||||
public void emptyDescriptionTest() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
parentCommunity = CommunityBuilder.createCommunity(context)
|
||||
.withName("Parent Community")
|
||||
.build();
|
||||
Community child1 = CommunityBuilder.createSubCommunity(context, parentCommunity)
|
||||
.withName("Sub Community")
|
||||
.build();
|
||||
Collection collection1 = CollectionBuilder.createCollection(context, child1).withName("Collection 1")
|
||||
.build();
|
||||
|
||||
getClient().perform(get("/opensearch/search")
|
||||
.param("format", "rss")
|
||||
.param("scope", collection1.getID().toString())
|
||||
.param("query", "*"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(xpath("rss/channel/description").string("No Description"));
|
||||
}
|
||||
}
|
||||
|
@@ -15,6 +15,7 @@ import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
@@ -30,6 +31,9 @@ import org.dspace.app.rest.matcher.BitstreamFormatMatcher;
|
||||
import org.dspace.app.rest.matcher.BitstreamMatcher;
|
||||
import org.dspace.app.rest.matcher.BundleMatcher;
|
||||
import org.dspace.app.rest.matcher.HalMatcher;
|
||||
import org.dspace.app.rest.matcher.MetadataMatcher;
|
||||
import org.dspace.app.rest.model.patch.Operation;
|
||||
import org.dspace.app.rest.model.patch.ReplaceOperation;
|
||||
import org.dspace.app.rest.test.AbstractControllerIntegrationTest;
|
||||
import org.dspace.app.rest.test.MetadataPatchSuite;
|
||||
import org.dspace.authorize.service.ResourcePolicyService;
|
||||
@@ -45,6 +49,7 @@ import org.dspace.content.Bundle;
|
||||
import org.dspace.content.Collection;
|
||||
import org.dspace.content.Community;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.content.MetadataSchemaEnum;
|
||||
import org.dspace.content.service.BitstreamFormatService;
|
||||
import org.dspace.content.service.BitstreamService;
|
||||
import org.dspace.content.service.ItemService;
|
||||
@@ -1222,6 +1227,92 @@ public class BitstreamRestRepositoryIT extends AbstractControllerIntegrationTest
|
||||
+ parentCommunity.getLogo().getID(), expectedStatus);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void patchReplaceMultipleDescriptionBitstream() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
||||
List<String> bitstreamDescriptions = List.of(
|
||||
"FIRST",
|
||||
"SECOND",
|
||||
"THIRD"
|
||||
);
|
||||
|
||||
parentCommunity = CommunityBuilder.createCommunity(context)
|
||||
.withName("Parent Community")
|
||||
.build();
|
||||
Community child1 =
|
||||
CommunityBuilder.createSubCommunity(context, parentCommunity).withName("Sub Community").build();
|
||||
Collection col1 = CollectionBuilder.createCollection(context, child1).withName("Collection 1").build();
|
||||
|
||||
Item publicItem1 = ItemBuilder.createItem(context, col1).withTitle("Test").build();
|
||||
|
||||
String bitstreamContent = "ThisIsSomeDummyText";
|
||||
Bitstream bitstream = null;
|
||||
try (InputStream is = IOUtils.toInputStream(bitstreamContent, CharEncoding.UTF_8)) {
|
||||
bitstream = BitstreamBuilder.
|
||||
createBitstream(context, publicItem1, is)
|
||||
.withName("Bitstream")
|
||||
.withMimeType("text/plain")
|
||||
.build();
|
||||
}
|
||||
|
||||
this.bitstreamService
|
||||
.addMetadata(
|
||||
context, bitstream,
|
||||
MetadataSchemaEnum.DC.getName(), "description", null,
|
||||
Item.ANY, bitstreamDescriptions
|
||||
);
|
||||
|
||||
context.restoreAuthSystemState();
|
||||
String token = getAuthToken(admin.getEmail(), password);
|
||||
|
||||
getClient(token)
|
||||
.perform(get("/api/core/bitstreams/" + bitstream.getID()))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(
|
||||
jsonPath("$.metadata",
|
||||
Matchers.allOf(
|
||||
MetadataMatcher.matchMetadata("dc.description", bitstreamDescriptions.get(0), 0),
|
||||
MetadataMatcher.matchMetadata("dc.description", bitstreamDescriptions.get(1), 1),
|
||||
MetadataMatcher.matchMetadata("dc.description", bitstreamDescriptions.get(2), 2)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
List<Operation> ops = List.of(
|
||||
new ReplaceOperation("/metadata/dc.description/0", bitstreamDescriptions.get(2)),
|
||||
new ReplaceOperation("/metadata/dc.description/1", bitstreamDescriptions.get(0)),
|
||||
new ReplaceOperation("/metadata/dc.description/2", bitstreamDescriptions.get(1))
|
||||
);
|
||||
String requestBody = getPatchContent(ops);
|
||||
getClient(token)
|
||||
.perform(patch("/api/core/bitstreams/" + bitstream.getID())
|
||||
.content(requestBody)
|
||||
.contentType(javax.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(
|
||||
jsonPath("$.metadata",
|
||||
Matchers.allOf(
|
||||
MetadataMatcher.matchMetadata("dc.description", bitstreamDescriptions.get(2), 0),
|
||||
MetadataMatcher.matchMetadata("dc.description", bitstreamDescriptions.get(0), 1),
|
||||
MetadataMatcher.matchMetadata("dc.description", bitstreamDescriptions.get(1), 2)
|
||||
)
|
||||
)
|
||||
);
|
||||
getClient(token)
|
||||
.perform(get("/api/core/bitstreams/" + bitstream.getID()))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(
|
||||
jsonPath("$.metadata",
|
||||
Matchers.allOf(
|
||||
MetadataMatcher.matchMetadata("dc.description", bitstreamDescriptions.get(2), 0),
|
||||
MetadataMatcher.matchMetadata("dc.description", bitstreamDescriptions.get(0), 1),
|
||||
MetadataMatcher.matchMetadata("dc.description", bitstreamDescriptions.get(1), 2)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testHiddenMetadataForAnonymousUser() throws Exception {
|
||||
|
@@ -37,6 +37,7 @@ import org.dspace.app.rest.model.MetadataRest;
|
||||
import org.dspace.app.rest.model.MetadataValueRest;
|
||||
import org.dspace.app.rest.model.patch.MoveOperation;
|
||||
import org.dspace.app.rest.model.patch.Operation;
|
||||
import org.dspace.app.rest.model.patch.ReplaceOperation;
|
||||
import org.dspace.app.rest.test.AbstractControllerIntegrationTest;
|
||||
import org.dspace.authorize.ResourcePolicy;
|
||||
import org.dspace.authorize.service.ResourcePolicyService;
|
||||
@@ -51,6 +52,8 @@ import org.dspace.content.Bitstream;
|
||||
import org.dspace.content.Bundle;
|
||||
import org.dspace.content.Collection;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.content.MetadataSchemaEnum;
|
||||
import org.dspace.content.service.BundleService;
|
||||
import org.dspace.content.service.ItemService;
|
||||
import org.dspace.core.Constants;
|
||||
import org.dspace.eperson.EPerson;
|
||||
@@ -68,6 +71,9 @@ public class BundleRestRepositoryIT extends AbstractControllerIntegrationTest {
|
||||
@Autowired
|
||||
ItemService itemService;
|
||||
|
||||
@Autowired
|
||||
BundleService bundleService;
|
||||
|
||||
private Collection collection;
|
||||
private Item item;
|
||||
private Bundle bundle1;
|
||||
@@ -515,6 +521,77 @@ public class BundleRestRepositoryIT extends AbstractControllerIntegrationTest {
|
||||
)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void patchReplaceMultipleDescriptionBundle() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
||||
List<String> bundleDescriptions = List.of(
|
||||
"FIRST",
|
||||
"SECOND",
|
||||
"THIRD"
|
||||
);
|
||||
|
||||
bundle1 = BundleBuilder.createBundle(context, item)
|
||||
.withName("testname")
|
||||
.build();
|
||||
|
||||
this.bundleService
|
||||
.addMetadata(
|
||||
context, bundle1,
|
||||
MetadataSchemaEnum.DC.getName(), "description", null,
|
||||
Item.ANY, bundleDescriptions
|
||||
);
|
||||
|
||||
context.restoreAuthSystemState();
|
||||
String token = getAuthToken(admin.getEmail(), password);
|
||||
|
||||
getClient(token)
|
||||
.perform(get("/api/core/bundles/" + bundle1.getID()))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(
|
||||
jsonPath("$.metadata",
|
||||
Matchers.allOf(
|
||||
MetadataMatcher.matchMetadata("dc.description", bundleDescriptions.get(0), 0),
|
||||
MetadataMatcher.matchMetadata("dc.description", bundleDescriptions.get(1), 1),
|
||||
MetadataMatcher.matchMetadata("dc.description", bundleDescriptions.get(2), 2)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
List<Operation> ops = List.of(
|
||||
new ReplaceOperation("/metadata/dc.description/0", bundleDescriptions.get(2)),
|
||||
new ReplaceOperation("/metadata/dc.description/1", bundleDescriptions.get(0)),
|
||||
new ReplaceOperation("/metadata/dc.description/2", bundleDescriptions.get(1))
|
||||
);
|
||||
String requestBody = getPatchContent(ops);
|
||||
getClient(token)
|
||||
.perform(patch("/api/core/bundles/" + bundle1.getID())
|
||||
.content(requestBody)
|
||||
.contentType(javax.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(
|
||||
jsonPath("$.metadata",
|
||||
Matchers.allOf(
|
||||
MetadataMatcher.matchMetadata("dc.description", bundleDescriptions.get(2), 0),
|
||||
MetadataMatcher.matchMetadata("dc.description", bundleDescriptions.get(0), 1),
|
||||
MetadataMatcher.matchMetadata("dc.description", bundleDescriptions.get(1), 2)
|
||||
)
|
||||
)
|
||||
);
|
||||
getClient(token)
|
||||
.perform(get("/api/core/bundles/" + bundle1.getID()))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(
|
||||
jsonPath("$.metadata",
|
||||
Matchers.allOf(
|
||||
MetadataMatcher.matchMetadata("dc.description", bundleDescriptions.get(2), 0),
|
||||
MetadataMatcher.matchMetadata("dc.description", bundleDescriptions.get(0), 1),
|
||||
MetadataMatcher.matchMetadata("dc.description", bundleDescriptions.get(1), 2)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteBundle() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
@@ -69,6 +69,7 @@ import org.dspace.content.Collection;
|
||||
import org.dspace.content.Community;
|
||||
import org.dspace.content.EntityType;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.content.MetadataSchemaEnum;
|
||||
import org.dspace.content.service.CollectionService;
|
||||
import org.dspace.core.Constants;
|
||||
import org.dspace.eperson.EPerson;
|
||||
@@ -499,13 +500,13 @@ public class CollectionRestRepositoryIT extends AbstractControllerIntegrationTes
|
||||
getClient(tokenParentAdmin).perform(get("/api/core/collections/" + col1.getID()))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$",
|
||||
Matchers.is((CollectionMatcher.matchCollection(col1)))));
|
||||
Matchers.is(CollectionMatcher.matchCollection(col1))));
|
||||
|
||||
String tokenCol1Admin = getAuthToken(col1Admin.getEmail(), "qwerty02");
|
||||
getClient(tokenCol1Admin).perform(get("/api/core/collections/" + col1.getID()))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$",
|
||||
Matchers.is((CollectionMatcher.matchCollection(col1)))));
|
||||
Matchers.is(CollectionMatcher.matchCollection(col1))));
|
||||
|
||||
String tokenCol2Admin = getAuthToken(col2Admin.getEmail(), "qwerty03");
|
||||
getClient(tokenCol2Admin).perform(get("/api/core/collections/" + col1.getID()))
|
||||
@@ -1206,7 +1207,7 @@ public class CollectionRestRepositoryIT extends AbstractControllerIntegrationTes
|
||||
)
|
||||
)))
|
||||
.andDo(result -> idRef
|
||||
.set(UUID.fromString(read(result.getResponse().getContentAsString(), "$.id"))));;
|
||||
.set(UUID.fromString(read(result.getResponse().getContentAsString(), "$.id"))));
|
||||
|
||||
|
||||
getClient(authToken).perform(post("/api/core/collections")
|
||||
@@ -3101,6 +3102,81 @@ public class CollectionRestRepositoryIT extends AbstractControllerIntegrationTes
|
||||
.andExpect(status().isUnauthorized());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void patchReplaceMultipleDescriptionCollection() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
||||
List<String> collectionDescriptions = List.of(
|
||||
"FIRST",
|
||||
"SECOND",
|
||||
"THIRD"
|
||||
);
|
||||
|
||||
parentCommunity =
|
||||
CommunityBuilder.createCommunity(context)
|
||||
.withName("Parent Community")
|
||||
.build();
|
||||
|
||||
Collection col =
|
||||
CollectionBuilder.createCollection(context, parentCommunity)
|
||||
.withName("MyTest")
|
||||
.build();
|
||||
|
||||
this.collectionService
|
||||
.addMetadata(
|
||||
context, col, MetadataSchemaEnum.DC.getName(), "description", null, Item.ANY, collectionDescriptions
|
||||
);
|
||||
|
||||
context.restoreAuthSystemState();
|
||||
String token = getAuthToken(admin.getEmail(), password);
|
||||
|
||||
getClient(token)
|
||||
.perform(get("/api/core/collections/" + col.getID()))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(
|
||||
jsonPath("$.metadata",
|
||||
Matchers.allOf(
|
||||
MetadataMatcher.matchMetadata("dc.description", collectionDescriptions.get(0), 0),
|
||||
MetadataMatcher.matchMetadata("dc.description", collectionDescriptions.get(1), 1),
|
||||
MetadataMatcher.matchMetadata("dc.description", collectionDescriptions.get(2), 2)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
List<Operation> ops = List.of(
|
||||
new ReplaceOperation("/metadata/dc.description/0", collectionDescriptions.get(2)),
|
||||
new ReplaceOperation("/metadata/dc.description/1", collectionDescriptions.get(0)),
|
||||
new ReplaceOperation("/metadata/dc.description/2", collectionDescriptions.get(1))
|
||||
);
|
||||
String requestBody = getPatchContent(ops);
|
||||
getClient(token)
|
||||
.perform(patch("/api/core/collections/" + col.getID())
|
||||
.content(requestBody)
|
||||
.contentType(javax.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(
|
||||
jsonPath("$.metadata",
|
||||
Matchers.allOf(
|
||||
MetadataMatcher.matchMetadata("dc.description", collectionDescriptions.get(2), 0),
|
||||
MetadataMatcher.matchMetadata("dc.description", collectionDescriptions.get(0), 1),
|
||||
MetadataMatcher.matchMetadata("dc.description", collectionDescriptions.get(1), 2)
|
||||
)
|
||||
)
|
||||
);
|
||||
getClient(token)
|
||||
.perform(get("/api/core/collections/" + col.getID()))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(
|
||||
jsonPath("$.metadata",
|
||||
Matchers.allOf(
|
||||
MetadataMatcher.matchMetadata("dc.description", collectionDescriptions.get(2), 0),
|
||||
MetadataMatcher.matchMetadata("dc.description", collectionDescriptions.get(0), 1),
|
||||
MetadataMatcher.matchMetadata("dc.description", collectionDescriptions.get(1), 2)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void patchMetadataCheckReindexingTest() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
@@ -20,6 +20,7 @@ import static org.springframework.data.rest.webmvc.RestMediaTypes.TEXT_URI_LIST_
|
||||
import static org.springframework.http.MediaType.parseMediaType;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
||||
@@ -44,6 +45,8 @@ import org.dspace.app.rest.model.CommunityRest;
|
||||
import org.dspace.app.rest.model.GroupRest;
|
||||
import org.dspace.app.rest.model.MetadataRest;
|
||||
import org.dspace.app.rest.model.MetadataValueRest;
|
||||
import org.dspace.app.rest.model.patch.Operation;
|
||||
import org.dspace.app.rest.model.patch.ReplaceOperation;
|
||||
import org.dspace.app.rest.projection.Projection;
|
||||
import org.dspace.app.rest.test.AbstractControllerIntegrationTest;
|
||||
import org.dspace.app.rest.test.MetadataPatchSuite;
|
||||
@@ -56,6 +59,8 @@ import org.dspace.builder.GroupBuilder;
|
||||
import org.dspace.builder.ResourcePolicyBuilder;
|
||||
import org.dspace.content.Collection;
|
||||
import org.dspace.content.Community;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.content.MetadataSchemaEnum;
|
||||
import org.dspace.content.service.CommunityService;
|
||||
import org.dspace.core.Constants;
|
||||
import org.dspace.eperson.EPerson;
|
||||
@@ -1935,6 +1940,78 @@ public class CommunityRestRepositoryIT extends AbstractControllerIntegrationTest
|
||||
runPatchMetadataTests(eperson, 403);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void patchReplaceMultipleDescriptionCommunity() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
||||
List<String> communityDescriptions = List.of(
|
||||
"FIRST",
|
||||
"SECOND",
|
||||
"THIRD"
|
||||
);
|
||||
|
||||
parentCommunity =
|
||||
CommunityBuilder.createCommunity(context)
|
||||
.withName("Parent Community")
|
||||
.build();
|
||||
|
||||
this.communityService
|
||||
.addMetadata(
|
||||
context, parentCommunity,
|
||||
MetadataSchemaEnum.DC.getName(), "description", null,
|
||||
Item.ANY, communityDescriptions
|
||||
);
|
||||
|
||||
context.restoreAuthSystemState();
|
||||
String token = getAuthToken(admin.getEmail(), password);
|
||||
|
||||
getClient(token)
|
||||
.perform(get("/api/core/communities/" + parentCommunity.getID()))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(
|
||||
jsonPath("$.metadata",
|
||||
Matchers.allOf(
|
||||
MetadataMatcher.matchMetadata("dc.description", communityDescriptions.get(0), 0),
|
||||
MetadataMatcher.matchMetadata("dc.description", communityDescriptions.get(1), 1),
|
||||
MetadataMatcher.matchMetadata("dc.description", communityDescriptions.get(2), 2)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
List<Operation> ops = List.of(
|
||||
new ReplaceOperation("/metadata/dc.description/0", communityDescriptions.get(2)),
|
||||
new ReplaceOperation("/metadata/dc.description/1", communityDescriptions.get(0)),
|
||||
new ReplaceOperation("/metadata/dc.description/2", communityDescriptions.get(1))
|
||||
);
|
||||
String requestBody = getPatchContent(ops);
|
||||
getClient(token)
|
||||
.perform(patch("/api/core/communities/" + parentCommunity.getID())
|
||||
.content(requestBody)
|
||||
.contentType(javax.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(
|
||||
jsonPath("$.metadata",
|
||||
Matchers.allOf(
|
||||
MetadataMatcher.matchMetadata("dc.description", communityDescriptions.get(2), 0),
|
||||
MetadataMatcher.matchMetadata("dc.description", communityDescriptions.get(0), 1),
|
||||
MetadataMatcher.matchMetadata("dc.description", communityDescriptions.get(1), 2)
|
||||
)
|
||||
)
|
||||
);
|
||||
getClient(token)
|
||||
.perform(get("/api/core/communities/" + parentCommunity.getID()))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(
|
||||
jsonPath("$.metadata",
|
||||
Matchers.allOf(
|
||||
MetadataMatcher.matchMetadata("dc.description", communityDescriptions.get(2), 0),
|
||||
MetadataMatcher.matchMetadata("dc.description", communityDescriptions.get(0), 1),
|
||||
MetadataMatcher.matchMetadata("dc.description", communityDescriptions.get(1), 2)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private void runPatchMetadataTests(EPerson asUser, int expectedStatus) throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
parentCommunity = CommunityBuilder.createCommunity(context).withName("Community").build();
|
||||
|
@@ -72,6 +72,7 @@ import org.dspace.builder.GroupBuilder;
|
||||
import org.dspace.builder.WorkflowItemBuilder;
|
||||
import org.dspace.content.Collection;
|
||||
import org.dspace.content.Community;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.core.I18nUtil;
|
||||
import org.dspace.eperson.EPerson;
|
||||
import org.dspace.eperson.Group;
|
||||
@@ -155,7 +156,7 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
|
||||
.andExpect(content().contentType(contentType))
|
||||
.andExpect(jsonPath("$", HalMatcher.matchNoEmbeds()))
|
||||
.andDo(result -> idRefNoEmbeds
|
||||
.set(UUID.fromString(read(result.getResponse().getContentAsString(), "$.id"))));;
|
||||
.set(UUID.fromString(read(result.getResponse().getContentAsString(), "$.id"))));
|
||||
|
||||
} finally {
|
||||
EPersonBuilder.deleteEPerson(idRef.get());
|
||||
@@ -1217,7 +1218,7 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
|
||||
.content(patchBody)
|
||||
.contentType(MediaType.APPLICATION_JSON_PATCH_JSON))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.canLogIn", Matchers.is(true)));;
|
||||
.andExpect(jsonPath("$.canLogIn", Matchers.is(true)));
|
||||
|
||||
|
||||
List<Operation> ops2 = new ArrayList<Operation>();
|
||||
@@ -1295,7 +1296,7 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
|
||||
.content(patchBody)
|
||||
.contentType(MediaType.APPLICATION_JSON_PATCH_JSON))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.requireCertificate", Matchers.is(true)));;
|
||||
.andExpect(jsonPath("$.requireCertificate", Matchers.is(true)));
|
||||
|
||||
List<Operation> ops2 = new ArrayList<Operation>();
|
||||
ReplaceOperation replaceOperation2 = new ReplaceOperation("/certificate",null);
|
||||
@@ -1858,6 +1859,78 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
|
||||
matchMetadata("eperson.firstname", newName)))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void patchMultipleReplaceMetadataByAdmin() throws Exception {
|
||||
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
||||
String first = "First";
|
||||
String second = "Second";
|
||||
String third = "Third";
|
||||
|
||||
EPerson ePerson = EPersonBuilder.createEPerson(context)
|
||||
.withEmail("Johndoe@example.com")
|
||||
.build();
|
||||
|
||||
this.ePersonService
|
||||
.addMetadata(context, ePerson, "eperson", "firstname", null, Item.ANY, List.of(first, second, third));
|
||||
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
String token = getAuthToken(admin.getEmail(), password);
|
||||
|
||||
// The replacement of the eperson.firstname value is persisted
|
||||
getClient(token).perform(get("/api/eperson/epersons/" + ePerson.getID()))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(
|
||||
jsonPath("$.metadata",
|
||||
Matchers.allOf(
|
||||
MetadataMatcher.matchMetadata("eperson.firstname", first, 0),
|
||||
MetadataMatcher.matchMetadata("eperson.firstname", second, 1),
|
||||
MetadataMatcher.matchMetadata("eperson.firstname", third, 2)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
List<Operation> ops = new ArrayList<Operation>();
|
||||
|
||||
ReplaceOperation replaceFirst = new ReplaceOperation("/metadata/eperson.firstname/0", third);
|
||||
ReplaceOperation replaceSecond = new ReplaceOperation("/metadata/eperson.firstname/1", second);
|
||||
ReplaceOperation replaceThird = new ReplaceOperation("/metadata/eperson.firstname/2", first);
|
||||
|
||||
ops.add(replaceFirst);
|
||||
ops.add(replaceSecond);
|
||||
ops.add(replaceThird);
|
||||
|
||||
String patchBody = getPatchContent(ops);
|
||||
|
||||
getClient(token).perform(patch("/api/eperson/epersons/" + ePerson.getID())
|
||||
.content(patchBody)
|
||||
.contentType(MediaType.APPLICATION_JSON_PATCH_JSON))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(
|
||||
jsonPath("$.metadata",
|
||||
Matchers.allOf(
|
||||
MetadataMatcher.matchMetadata("eperson.firstname", third, 0),
|
||||
MetadataMatcher.matchMetadata("eperson.firstname", second, 1),
|
||||
MetadataMatcher.matchMetadata("eperson.firstname", first, 2)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
getClient(token).perform(get("/api/eperson/epersons/" + ePerson.getID()))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(
|
||||
jsonPath("$.metadata",
|
||||
Matchers.allOf(
|
||||
MetadataMatcher.matchMetadata("eperson.firstname", third, 0),
|
||||
MetadataMatcher.matchMetadata("eperson.firstname", second, 1),
|
||||
MetadataMatcher.matchMetadata("eperson.firstname", first, 2)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void patchOwnMetadataByNonAdminUser() throws Exception {
|
||||
|
||||
|
@@ -40,6 +40,7 @@ import org.dspace.app.rest.exception.GroupNameNotProvidedException;
|
||||
import org.dspace.app.rest.matcher.EPersonMatcher;
|
||||
import org.dspace.app.rest.matcher.GroupMatcher;
|
||||
import org.dspace.app.rest.matcher.HalMatcher;
|
||||
import org.dspace.app.rest.matcher.MetadataMatcher;
|
||||
import org.dspace.app.rest.model.GroupRest;
|
||||
import org.dspace.app.rest.model.MetadataRest;
|
||||
import org.dspace.app.rest.model.MetadataValueRest;
|
||||
@@ -56,6 +57,8 @@ import org.dspace.builder.GroupBuilder;
|
||||
import org.dspace.builder.ResourcePolicyBuilder;
|
||||
import org.dspace.content.Collection;
|
||||
import org.dspace.content.Community;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.content.MetadataSchemaEnum;
|
||||
import org.dspace.content.factory.ContentServiceFactory;
|
||||
import org.dspace.content.service.CollectionService;
|
||||
import org.dspace.content.service.CommunityService;
|
||||
@@ -558,6 +561,68 @@ public class GroupRestRepositoryIT extends AbstractControllerIntegrationTest {
|
||||
));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void patchReplaceMultipleDescriptionGroupName() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
List<String> groupDescription = List.of(
|
||||
"FIRST",
|
||||
"SECOND",
|
||||
"THIRD"
|
||||
);
|
||||
|
||||
Group group =
|
||||
GroupBuilder.createGroup(context)
|
||||
.build();
|
||||
GroupService groupService = EPersonServiceFactory.getInstance().getGroupService();
|
||||
groupService
|
||||
.addMetadata(
|
||||
context, group, MetadataSchemaEnum.DC.getName(), "description", null, Item.ANY, groupDescription
|
||||
);
|
||||
context.restoreAuthSystemState();
|
||||
String token = getAuthToken(admin.getEmail(), password);
|
||||
|
||||
getClient(token)
|
||||
.perform(get("/api/eperson/groups/" + group.getID()))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(
|
||||
jsonPath("$.metadata",
|
||||
Matchers.allOf(
|
||||
MetadataMatcher.matchMetadata("dc.description", groupDescription.get(0), 0),
|
||||
MetadataMatcher.matchMetadata("dc.description", groupDescription.get(1), 1),
|
||||
MetadataMatcher.matchMetadata("dc.description", groupDescription.get(2), 2)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
List<Operation> ops = List.of(
|
||||
new ReplaceOperation("/metadata/dc.description/0", groupDescription.get(2)),
|
||||
new ReplaceOperation("/metadata/dc.description/1", groupDescription.get(0)),
|
||||
new ReplaceOperation("/metadata/dc.description/2", groupDescription.get(1))
|
||||
);
|
||||
String requestBody = getPatchContent(ops);
|
||||
|
||||
getClient(token)
|
||||
.perform(
|
||||
patch("/api/eperson/groups/" + group.getID())
|
||||
.content(requestBody)
|
||||
.contentType(MediaType.APPLICATION_JSON_PATCH_JSON)
|
||||
)
|
||||
.andExpect(status().isOk());
|
||||
|
||||
getClient(token)
|
||||
.perform(get("/api/eperson/groups/" + group.getID()))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(
|
||||
jsonPath("$.metadata",
|
||||
Matchers.allOf(
|
||||
MetadataMatcher.matchMetadata("dc.description", groupDescription.get(2), 0),
|
||||
MetadataMatcher.matchMetadata("dc.description", groupDescription.get(0), 1),
|
||||
MetadataMatcher.matchMetadata("dc.description", groupDescription.get(1), 2)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void patchGroupWithParentUnprocessable() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
@@ -11,8 +11,8 @@ import static com.jayway.jsonpath.JsonPath.read;
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.not;
|
||||
import static org.hamcrest.CoreMatchers.startsWith;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
@@ -23,8 +23,11 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import org.dspace.app.rest.matcher.MetadataMatcher;
|
||||
@@ -50,6 +53,7 @@ import org.dspace.content.service.EntityTypeService;
|
||||
import org.dspace.content.service.ItemService;
|
||||
import org.dspace.content.service.RelationshipTypeService;
|
||||
import org.dspace.content.service.WorkspaceItemService;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.hamcrest.Matcher;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.After;
|
||||
@@ -63,6 +67,13 @@ import org.springframework.http.MediaType;
|
||||
*/
|
||||
public class PatchMetadataIT extends AbstractEntityIntegrationTest {
|
||||
|
||||
private static final String SECTIONS_TRADITIONALPAGEONE_DC_CONTRIBUTOR_AUTHOR =
|
||||
"/sections/traditionalpageone/dc.contributor.author/%1$s";
|
||||
|
||||
private static final String getPath(Object element) {
|
||||
return String.format(SECTIONS_TRADITIONALPAGEONE_DC_CONTRIBUTOR_AUTHOR, element);
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private RelationshipTypeService relationshipTypeService;
|
||||
|
||||
@@ -75,6 +86,9 @@ public class PatchMetadataIT extends AbstractEntityIntegrationTest {
|
||||
@Autowired
|
||||
private WorkspaceItemService workspaceItemService;
|
||||
|
||||
@Autowired
|
||||
private ConfigurationService configurationService;
|
||||
|
||||
private Collection collection;
|
||||
private Collection collection2;
|
||||
private WorkspaceItem publicationWorkspaceItem;
|
||||
@@ -297,8 +311,6 @@ public class PatchMetadataIT extends AbstractEntityIntegrationTest {
|
||||
.withEntityType("Publication")
|
||||
.build();
|
||||
|
||||
String adminToken = getAuthToken(admin.getEmail(), password);
|
||||
|
||||
// Make sure we grab the latest instance of the Item from the database before adding a regular author
|
||||
WorkspaceItem publication = workspaceItemService.find(context, publicationWorkspaceItem.getID());
|
||||
itemService.addMetadata(context, publication.getItem(),
|
||||
@@ -920,6 +932,41 @@ public class PatchMetadataIT extends AbstractEntityIntegrationTest {
|
||||
replaceTraditionalPageOneAuthorTest(3, expectedOrder);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void replaceMultipleTraditionalPageOnePlainTextAuthorTest() throws Exception {
|
||||
final boolean virtualMetadataEnabled =
|
||||
configurationService.getBooleanProperty("item.enable-virtual-metadata", false);
|
||||
|
||||
configurationService.setProperty("item.enable-virtual-metadata", false);
|
||||
try {
|
||||
initPlainTextPublicationWorkspace();
|
||||
|
||||
Map<Integer, String> replacedAuthors =
|
||||
Map.of(
|
||||
0, authorsOriginalOrder.get(4),
|
||||
1, authorsOriginalOrder.get(1),
|
||||
2, authorsOriginalOrder.get(2),
|
||||
3, authorsOriginalOrder.get(3),
|
||||
4, authorsOriginalOrder.get(0)
|
||||
);
|
||||
|
||||
List<String> expectedOrder =
|
||||
List.of(
|
||||
authorsOriginalOrder.get(4),
|
||||
authorsOriginalOrder.get(1),
|
||||
authorsOriginalOrder.get(2),
|
||||
authorsOriginalOrder.get(3),
|
||||
authorsOriginalOrder.get(0)
|
||||
);
|
||||
|
||||
replaceTraditionalPageMultipleAuthorsTest(replacedAuthors, expectedOrder);
|
||||
} catch (Exception e) {
|
||||
throw e;
|
||||
} finally {
|
||||
configurationService.setProperty("item.enable-virtual-metadata", virtualMetadataEnabled);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This test will add an author (dc.contributor.author) within a workspace publication's "traditionalpageone"
|
||||
@@ -1393,24 +1440,7 @@ public class PatchMetadataIT extends AbstractEntityIntegrationTest {
|
||||
ops.add(moveOperation);
|
||||
String patchBody = getPatchContent(ops);
|
||||
|
||||
String token = getAuthToken(admin.getEmail(), password);
|
||||
|
||||
getClient(token).perform(patch("/api/submission/workspaceitems/" + publicationWorkspaceItem.getID())
|
||||
.content(patchBody)
|
||||
.contentType(javax.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON))
|
||||
.andExpect(status().isOk());
|
||||
|
||||
String authorField = "dc.contributor.author";
|
||||
getClient(token).perform(get("/api/submission/workspaceitems/" + publicationWorkspaceItem.getID()))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(contentType))
|
||||
.andExpect(jsonPath("$.sections.traditionalpageone", Matchers.allOf(
|
||||
Matchers.is(MetadataMatcher.matchMetadata(authorField, expectedOrder.get(0), 0)),
|
||||
Matchers.is(MetadataMatcher.matchMetadata(authorField, expectedOrder.get(1), 1)),
|
||||
Matchers.is(MetadataMatcher.matchMetadata(authorField, expectedOrder.get(2), 2)),
|
||||
Matchers.is(MetadataMatcher.matchMetadata(authorField, expectedOrder.get(3), 3)),
|
||||
Matchers.is(MetadataMatcher.matchMetadata(authorField, expectedOrder.get(4), 4))
|
||||
)));
|
||||
assertReplacementOrder(expectedOrder, patchBody);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1450,33 +1480,66 @@ public class PatchMetadataIT extends AbstractEntityIntegrationTest {
|
||||
* @param expectedOrder A list of author names sorted in the expected order
|
||||
*/
|
||||
private void replaceTraditionalPageOneAuthorTest(int path, List<String> expectedOrder) throws Exception {
|
||||
List<Operation> ops = new ArrayList<Operation>();
|
||||
MetadataValueRest value = new MetadataValueRest();
|
||||
value.setValue(replacedAuthor);
|
||||
String patchBody =
|
||||
getPatchContent(
|
||||
List.of(
|
||||
this.mapToReplaceOperation(path, replacedAuthor)
|
||||
)
|
||||
);
|
||||
|
||||
assertReplacementOrder(expectedOrder, patchBody);
|
||||
}
|
||||
|
||||
private void replaceTraditionalPageMultipleAuthorsTest(
|
||||
Map<Integer, String> values, List<String> expectedOrder
|
||||
) throws Exception {
|
||||
List<Operation> ops =
|
||||
values
|
||||
.entrySet()
|
||||
.stream()
|
||||
.sorted(Comparator.comparing(Map.Entry::getKey))
|
||||
.map(entry -> mapToReplaceOperation(entry.getKey(), entry.getValue()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
ReplaceOperation replaceOperation = new ReplaceOperation("/sections/traditionalpageone/dc.contributor.author/"
|
||||
+ path, value);
|
||||
ops.add(replaceOperation);
|
||||
String patchBody = getPatchContent(ops);
|
||||
|
||||
assertReplacementOrder(expectedOrder, patchBody);
|
||||
}
|
||||
|
||||
private ReplaceOperation mapToReplaceOperation(int path, String author) {
|
||||
return new ReplaceOperation(getPath(path), new MetadataValueRest(author));
|
||||
}
|
||||
|
||||
private void assertReplacementOrder(List<String> expectedOrder, String patchBody) throws Exception, SQLException {
|
||||
String token = getAuthToken(admin.getEmail(), password);
|
||||
|
||||
getClient(token).perform(patch("/api/submission/workspaceitems/" + publicationWorkspaceItem.getID())
|
||||
.content(patchBody)
|
||||
.contentType(javax.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON))
|
||||
.andExpect(status().isOk());
|
||||
getClient(token)
|
||||
.perform(
|
||||
patch("/api/submission/workspaceitems/" + publicationWorkspaceItem.getID())
|
||||
.content(patchBody)
|
||||
.contentType(javax.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)
|
||||
)
|
||||
.andExpect(status().isOk());
|
||||
|
||||
String authorField = "dc.contributor.author";
|
||||
getClient(token).perform(get("/api/submission/workspaceitems/" + publicationWorkspaceItem.getID()))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(contentType))
|
||||
.andExpect(jsonPath("$.sections.traditionalpageone", Matchers.allOf(
|
||||
Matchers.is(MetadataMatcher.matchMetadata(authorField, expectedOrder.get(0), 0)),
|
||||
Matchers.is(MetadataMatcher.matchMetadata(authorField, expectedOrder.get(1), 1)),
|
||||
Matchers.is(MetadataMatcher.matchMetadata(authorField, expectedOrder.get(2), 2)),
|
||||
Matchers.is(MetadataMatcher.matchMetadata(authorField, expectedOrder.get(3), 3)),
|
||||
Matchers.is(MetadataMatcher.matchMetadata(authorField, expectedOrder.get(4), 4))
|
||||
)));
|
||||
getClient(token)
|
||||
.perform(get("/api/submission/workspaceitems/" + publicationWorkspaceItem.getID()))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(
|
||||
content().contentType(contentType)
|
||||
)
|
||||
.andExpect(
|
||||
jsonPath(
|
||||
"$.sections.traditionalpageone",
|
||||
Matchers.allOf(
|
||||
Matchers.is(MetadataMatcher.matchMetadata(authorField, expectedOrder.get(0), 0)),
|
||||
Matchers.is(MetadataMatcher.matchMetadata(authorField, expectedOrder.get(1), 1)),
|
||||
Matchers.is(MetadataMatcher.matchMetadata(authorField, expectedOrder.get(2), 2)),
|
||||
Matchers.is(MetadataMatcher.matchMetadata(authorField, expectedOrder.get(3), 3)),
|
||||
Matchers.is(MetadataMatcher.matchMetadata(authorField, expectedOrder.get(4), 4))
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1490,8 +1553,7 @@ public class PatchMetadataIT extends AbstractEntityIntegrationTest {
|
||||
List<Operation> ops = new ArrayList<Operation>();
|
||||
MetadataValueRest value = new MetadataValueRest();
|
||||
value.setValue(addedAuthor);
|
||||
AddOperation addOperation = new AddOperation("/sections/traditionalpageone/dc.contributor.author/" + path,
|
||||
value);
|
||||
AddOperation addOperation = new AddOperation(getPath(path), value);
|
||||
ops.add(addOperation);
|
||||
String patchBody = getPatchContent(ops);
|
||||
|
||||
@@ -1525,8 +1587,7 @@ public class PatchMetadataIT extends AbstractEntityIntegrationTest {
|
||||
*/
|
||||
private void removeTraditionalPageOneAuthorTest(int path, List<String> expectedOrder) throws Exception {
|
||||
List<Operation> ops = new ArrayList<Operation>();
|
||||
RemoveOperation removeOperation = new RemoveOperation("/sections/traditionalpageone/dc.contributor.author/"
|
||||
+ path);
|
||||
RemoveOperation removeOperation = new RemoveOperation(getPath(path));
|
||||
ops.add(removeOperation);
|
||||
String patchBody = getPatchContent(ops);
|
||||
|
||||
@@ -1600,8 +1661,10 @@ public class PatchMetadataIT extends AbstractEntityIntegrationTest {
|
||||
* @param path The "path" index to use for the Move operation
|
||||
*/
|
||||
private MoveOperation getTraditionalPageOneMoveAuthorOperation(int from, int path) {
|
||||
return new MoveOperation("/sections/traditionalpageone/dc.contributor.author/" + path,
|
||||
"/sections/traditionalpageone/dc.contributor.author/" + from);
|
||||
return new MoveOperation(
|
||||
getPath(path),
|
||||
getPath(from)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -9,22 +9,34 @@ package org.dspace.app.rest;
|
||||
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.dspace.app.rest.matcher.MetadataMatcher;
|
||||
import org.dspace.app.rest.matcher.SiteMatcher;
|
||||
import org.dspace.app.rest.model.patch.Operation;
|
||||
import org.dspace.app.rest.model.patch.ReplaceOperation;
|
||||
import org.dspace.app.rest.test.AbstractControllerIntegrationTest;
|
||||
import org.dspace.app.rest.test.MetadataPatchSuite;
|
||||
import org.dspace.builder.SiteBuilder;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.content.MetadataSchemaEnum;
|
||||
import org.dspace.content.Site;
|
||||
import org.dspace.content.service.SiteService;
|
||||
import org.dspace.eperson.EPerson;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
public class SiteRestRepositoryIT extends AbstractControllerIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
private SiteService siteService;
|
||||
|
||||
@Test
|
||||
public void findAll() throws Exception {
|
||||
|
||||
@@ -77,6 +89,75 @@ public class SiteRestRepositoryIT extends AbstractControllerIntegrationTest {
|
||||
runPatchMetadataTests(eperson, 403);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void patchReplaceMultipleDescriptionSite() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
||||
List<String> siteDescriptions = List.of(
|
||||
"FIRST",
|
||||
"SECOND",
|
||||
"THIRD"
|
||||
);
|
||||
|
||||
Site site = SiteBuilder.createSite(context).build();
|
||||
|
||||
this.siteService
|
||||
.addMetadata(
|
||||
context, site,
|
||||
MetadataSchemaEnum.DC.getName(), "description", null,
|
||||
Item.ANY, siteDescriptions
|
||||
);
|
||||
|
||||
context.restoreAuthSystemState();
|
||||
String token = getAuthToken(admin.getEmail(), password);
|
||||
|
||||
getClient(token)
|
||||
.perform(get("/api/core/sites/" + site.getID()))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(
|
||||
jsonPath("$.metadata",
|
||||
Matchers.allOf(
|
||||
MetadataMatcher.matchMetadata("dc.description", siteDescriptions.get(0), 0),
|
||||
MetadataMatcher.matchMetadata("dc.description", siteDescriptions.get(1), 1),
|
||||
MetadataMatcher.matchMetadata("dc.description", siteDescriptions.get(2), 2)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
List<Operation> ops = List.of(
|
||||
new ReplaceOperation("/metadata/dc.description/0", siteDescriptions.get(2)),
|
||||
new ReplaceOperation("/metadata/dc.description/1", siteDescriptions.get(0)),
|
||||
new ReplaceOperation("/metadata/dc.description/2", siteDescriptions.get(1))
|
||||
);
|
||||
String requestBody = getPatchContent(ops);
|
||||
getClient(token)
|
||||
.perform(patch("/api/core/sites/" + site.getID())
|
||||
.content(requestBody)
|
||||
.contentType(javax.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(
|
||||
jsonPath("$.metadata",
|
||||
Matchers.allOf(
|
||||
MetadataMatcher.matchMetadata("dc.description", siteDescriptions.get(2), 0),
|
||||
MetadataMatcher.matchMetadata("dc.description", siteDescriptions.get(0), 1),
|
||||
MetadataMatcher.matchMetadata("dc.description", siteDescriptions.get(1), 2)
|
||||
)
|
||||
)
|
||||
);
|
||||
getClient(token)
|
||||
.perform(get("/api/core/sites/" + site.getID()))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(
|
||||
jsonPath("$.metadata",
|
||||
Matchers.allOf(
|
||||
MetadataMatcher.matchMetadata("dc.description", siteDescriptions.get(2), 0),
|
||||
MetadataMatcher.matchMetadata("dc.description", siteDescriptions.get(0), 1),
|
||||
MetadataMatcher.matchMetadata("dc.description", siteDescriptions.get(1), 2)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private void runPatchMetadataTests(EPerson asUser, int expectedStatus) throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
Site site = SiteBuilder.createSite(context).build();
|
||||
|
@@ -56,10 +56,12 @@
|
||||
<constructor-arg value="dc.description.abstract"/>
|
||||
</bean>
|
||||
|
||||
<bean id="arxivPublishedContrib" class="org.dspace.importer.external.metadatamapping.contributor.SimpleXpathMetadatumContributor">
|
||||
<bean id="arxivPublishedContrib" class="org.dspace.importer.external.metadatamapping.contributor.SimpleXpathDateFormatMetadataContributor">
|
||||
<property name="field" ref="arxiv.published"/>
|
||||
<property name="query" value="ns:published"/>
|
||||
<property name="prefixToNamespaceMapping" ref="arxivBasePrefixToNamespaceMapping"/>
|
||||
<property name="dateFormatFrom" value="yyyy-MM-dd'T'HH:mm:ss'Z'"/>
|
||||
<property name="dateFormatTo" value="yyyy-MM-dd"></property>
|
||||
</bean>
|
||||
<bean id="arxiv.published" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
|
||||
<constructor-arg value="dc.date.issued"/>
|
||||
|
@@ -17,11 +17,9 @@
|
||||
The VersionedHandleIdentifierProvider creates a new versioned
|
||||
handle for every new version.
|
||||
-->
|
||||
<!--
|
||||
<bean id="org.dspace.identifier.HandleIdentifierProvider" class="org.dspace.identifier.VersionedHandleIdentifierProvider" scope="singleton">
|
||||
<property name="configurationService" ref="org.dspace.services.ConfigurationService"/>
|
||||
</bean>
|
||||
-->
|
||||
<!--
|
||||
The VersionedHandleIdentifierProviderWithCanonicalHandles
|
||||
preserves the first handle for every new version. Whenever
|
||||
|
@@ -38,6 +38,7 @@
|
||||
<value>yyyy-MMM-dd</value>
|
||||
<value>yyyy-MMM</value>
|
||||
<value>yyyy-MM-dd</value>
|
||||
<value>yyyy</value>
|
||||
</list>
|
||||
</property>
|
||||
<property name="year" ref="yearContrib"/>
|
||||
@@ -160,4 +161,4 @@
|
||||
</bean>
|
||||
|
||||
|
||||
</beans>
|
||||
</beans>
|
||||
|
Reference in New Issue
Block a user