diff --git a/dspace-api/pom.xml b/dspace-api/pom.xml index 1ce9be2d2e..d96d9ef612 100644 --- a/dspace-api/pom.xml +++ b/dspace-api/pom.xml @@ -635,7 +635,7 @@ org.flywaydb flyway-core - 3.2.1 + 4.0.3 diff --git a/dspace-api/src/main/java/org/dspace/app/bulkedit/DSpaceCSV.java b/dspace-api/src/main/java/org/dspace/app/bulkedit/DSpaceCSV.java index 617bd63197..441b6636b1 100644 --- a/dspace-api/src/main/java/org/dspace/app/bulkedit/DSpaceCSV.java +++ b/dspace-api/src/main/java/org/dspace/app/bulkedit/DSpaceCSV.java @@ -631,7 +631,7 @@ public class DSpaceCSV implements Serializable int c = 1; while (i.hasNext()) { - csvLines[c++] = i.next().toCSV(headingsCopy, fieldSeparator); + csvLines[c++] = i.next().toCSV(headingsCopy, fieldSeparator, valueSeparator); } return csvLines; diff --git a/dspace-api/src/main/java/org/dspace/app/bulkedit/DSpaceCSVLine.java b/dspace-api/src/main/java/org/dspace/app/bulkedit/DSpaceCSVLine.java index d8d793f063..bb5fdd4bb3 100644 --- a/dspace-api/src/main/java/org/dspace/app/bulkedit/DSpaceCSVLine.java +++ b/dspace-api/src/main/java/org/dspace/app/bulkedit/DSpaceCSVLine.java @@ -150,16 +150,17 @@ public class DSpaceCSVLine implements Serializable * Write this line out as a CSV formatted string, in the order given by the headings provided * * @param headings The headings which define the order the elements must be presented in - * @param fieldSeparator field separator + * @param fieldSeparator separator between metadata fields + * @param valueSeparator separator between metadata values (within a field) * @return The CSV formatted String */ - protected String toCSV(List headings, String fieldSeparator) + protected String toCSV(List headings, String fieldSeparator, String valueSeparator) { StringBuilder bits = new StringBuilder(); // Add the id bits.append("\"").append(id).append("\"").append(fieldSeparator); - bits.append(valueToCSV(items.get("collection"), fieldSeparator)); + bits.append(valueToCSV(items.get("collection"),valueSeparator)); // Add the rest of the elements for (String heading : headings) @@ -168,7 +169,7 @@ public class DSpaceCSVLine implements Serializable List values = items.get(heading); if (values != null && !"collection".equals(heading)) { - bits.append(valueToCSV(values, fieldSeparator)); + bits.append(valueToCSV(values, valueSeparator)); } } diff --git a/dspace-api/src/main/java/org/dspace/app/bulkedit/MetadataImport.java b/dspace-api/src/main/java/org/dspace/app/bulkedit/MetadataImport.java index 82598b1c2e..2beb5f3dea 100644 --- a/dspace-api/src/main/java/org/dspace/app/bulkedit/MetadataImport.java +++ b/dspace-api/src/main/java/org/dspace/app/bulkedit/MetadataImport.java @@ -203,14 +203,11 @@ public class MetadataImport } // Remove the item - List owners = item.getCollections(); - for (Collection owner : owners) - { - if (change) - { - collectionService.removeItem(c, owner, item); - } - } + + if (change) { + itemService.delete(c, item); + } + whatHasChanged.setDeleted(); } else if ("withdraw".equals(action)) diff --git a/dspace-api/src/main/java/org/dspace/app/itemimport/ItemImportServiceImpl.java b/dspace-api/src/main/java/org/dspace/app/itemimport/ItemImportServiceImpl.java index d07ab61ec5..176d82b451 100644 --- a/dspace-api/src/main/java/org/dspace/app/itemimport/ItemImportServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/app/itemimport/ItemImportServiceImpl.java @@ -1721,7 +1721,7 @@ public class ItemImportServiceImpl implements ItemImportService, InitializingBea /** * Generate a random filename based on current time - * @param hidden: add . as a prefix to make the file hidden + * @param hidden set to add . as a prefix to make the file hidden * @return the filename */ protected String generateRandomFilename(boolean hidden) diff --git a/dspace-api/src/main/java/org/dspace/app/statistics/package.html b/dspace-api/src/main/java/org/dspace/app/statistics/package.html index 2e6f80e7c4..a6d8d8699c 100644 --- a/dspace-api/src/main/java/org/dspace/app/statistics/package.html +++ b/dspace-api/src/main/java/org/dspace/app/statistics/package.html @@ -33,7 +33,7 @@ class, defined in this package, to select an event processing implementation.

-Three "stock" implementations are provided. +Several "stock" implementations are provided.

{@link org.dspace.usage.PassiveUsageEventListener PassiveUsageEventListener}
@@ -42,9 +42,12 @@ Three "stock" implementations are provided. if no plugin is configured.
{@link org.dspace.usage.TabFileUsageEventListener TabFileUsageEventListener}
writes event records to a file in Tab Separated Values format.
-
{@link org.dspace.app.statistics.UsageEventXMLLogger UsageEventXMLLogger}
-
writes event records to a file in an XML format. Suitable mainly for - testing.
+
{@link org.dspace.usage.LoggerUsageEventListener LoggerUsageEventListener}
+
writes event records to the Java logger.
+
{@link org.dspace.statistics.SolrLoggerUsageEventListener SolrLoggerUsageEventListener}
+
writes event records to Solr.
+
{@link org.dspace.google.GoogleRecorderEventListener GoogleRecorderEventListener}<.dt> +
writes event records to Google Analytics.
diff --git a/dspace-api/src/main/java/org/dspace/app/util/CollectionDropDown.java b/dspace-api/src/main/java/org/dspace/app/util/CollectionDropDown.java index 823f9390be..06f4ce5276 100644 --- a/dspace-api/src/main/java/org/dspace/app/util/CollectionDropDown.java +++ b/dspace-api/src/main/java/org/dspace/app/util/CollectionDropDown.java @@ -12,7 +12,10 @@ import java.util.*; import org.dspace.content.Collection; import org.dspace.content.Community; +import org.dspace.content.factory.ContentServiceFactory; +import org.dspace.content.service.CommunityService; import org.dspace.core.ConfigurationManager; +import org.dspace.core.Context; /** * Utility class for lists of collections. @@ -20,6 +23,9 @@ import org.dspace.core.ConfigurationManager; public class CollectionDropDown { + + private static final CommunityService communityService = ContentServiceFactory.getInstance().getCommunityService(); + /** * Get full path starting from a top-level community via subcommunities down to a collection. * The full path will not be truncated. @@ -29,9 +35,9 @@ public class CollectionDropDown { * @return Full path to the collection * @throws SQLException if database error */ - public static String collectionPath(Collection col) throws SQLException + public static String collectionPath(Context context, Collection col) throws SQLException { - return CollectionDropDown.collectionPath(col, 0); + return CollectionDropDown.collectionPath(context, col, 0); } /** @@ -45,7 +51,7 @@ public class CollectionDropDown { * @return Full path to the collection (truncated) * @throws SQLException if database error */ - public static String collectionPath(Collection col, int maxchars) throws SQLException + public static String collectionPath(Context context, Collection col, int maxchars) throws SQLException { String separator = ConfigurationManager.getProperty("subcommunity.separator"); if (separator == null) @@ -55,7 +61,7 @@ public class CollectionDropDown { List getCom = null; StringBuffer name = new StringBuffer(""); - getCom = col.getCommunities(); // all communities containing given collection + getCom = communityService.getAllParents(context, col); // all communities containing given collection for (Community com : getCom) { name.insert(0, com.getName() + separator); @@ -83,13 +89,13 @@ public class CollectionDropDown { * @return A sorted array of collection path entries (essentially collection/path pairs). * @throws SQLException In case there are problems annotating a collection with its path. */ - public static CollectionPathEntry[] annotateWithPaths(List collections) throws SQLException + public static CollectionPathEntry[] annotateWithPaths(Context context, List collections) throws SQLException { CollectionPathEntry[] result = new CollectionPathEntry[collections.size()]; for (int i = 0; i < collections.size(); i++) { Collection collection = collections.get(i); - CollectionPathEntry entry = new CollectionPathEntry(collection, collectionPath(collection)); + CollectionPathEntry entry = new CollectionPathEntry(collection, collectionPath(context, collection)); result[i] = entry; } Arrays.sort(result); diff --git a/dspace-api/src/main/java/org/dspace/app/util/GoogleMetadata.java b/dspace-api/src/main/java/org/dspace/app/util/GoogleMetadata.java index 0a05620f4c..d9995251e1 100644 --- a/dspace-api/src/main/java/org/dspace/app/util/GoogleMetadata.java +++ b/dspace-api/src/main/java/org/dspace/app/util/GoogleMetadata.java @@ -229,7 +229,7 @@ public class GoogleMetadata * first-encountered instance of the field for this Item. * * @param fieldName - * @return + * @return successful? */ protected boolean addSingleField(String fieldName) { @@ -445,7 +445,7 @@ public class GoogleMetadata * configuration. * * @param configFilter - * @return + * @return array of parsed options or null */ protected ArrayList> parseOptions(String configFilter) { @@ -1046,7 +1046,7 @@ public class GoogleMetadata * * Additionally, this bitstream must be publicly viewable. * @param item - * @return + * @return a linkable bitstream or null if none found * @throws SQLException if database error */ protected Bitstream findLinkableFulltext(Item item) throws SQLException { @@ -1201,7 +1201,7 @@ public class GoogleMetadata * metadata practice. * * @param dConfig - * @return + * @return item matches configuration */ protected boolean identifyItemType(String dConfig) { diff --git a/dspace-api/src/main/java/org/dspace/authenticate/LDAPAuthentication.java b/dspace-api/src/main/java/org/dspace/authenticate/LDAPAuthentication.java index 984904d35b..7cb5a33d21 100644 --- a/dspace-api/src/main/java/org/dspace/authenticate/LDAPAuthentication.java +++ b/dspace-api/src/main/java/org/dspace/authenticate/LDAPAuthentication.java @@ -481,9 +481,6 @@ public class LDAPAuthentication env.put(javax.naming.Context.SECURITY_AUTHENTICATION, "simple"); env.put(javax.naming.Context.SECURITY_PRINCIPAL, adminUser); env.put(javax.naming.Context.SECURITY_CREDENTIALS, adminPassword); - - // Create initial context - ctx = new InitialLdapContext(env, null); } } else @@ -491,6 +488,11 @@ public class LDAPAuthentication // Use anonymous authentication env.put(javax.naming.Context.SECURITY_AUTHENTICATION, "none"); } + + if (ctx == null) { + // Create initial context + ctx = new InitialLdapContext(env, null); + } Attributes matchAttrs = new BasicAttributes(true); matchAttrs.put(new BasicAttribute(ldap_id_field, netid)); diff --git a/dspace-api/src/main/java/org/dspace/authority/AuthorityValue.java b/dspace-api/src/main/java/org/dspace/authority/AuthorityValue.java index 5791fab9d4..c164392c35 100644 --- a/dspace-api/src/main/java/org/dspace/authority/AuthorityValue.java +++ b/dspace-api/src/main/java/org/dspace/authority/AuthorityValue.java @@ -14,12 +14,12 @@ import org.apache.solr.common.SolrInputDocument; import org.dspace.authorize.AuthorizeException; import org.dspace.content.Item; import org.dspace.content.MetadataValue; +import org.dspace.content.factory.ContentServiceFactory; import org.dspace.content.service.MetadataValueService; import org.dspace.core.Context; import org.joda.time.DateTime; import org.joda.time.format.DateTimeFormatter; import org.joda.time.format.ISODateTimeFormat; -import org.springframework.beans.factory.annotation.Autowired; import java.sql.SQLException; import java.util.*; @@ -64,12 +64,6 @@ public class AuthorityValue { */ private Date lastModified; - @Autowired(required = true) - protected AuthorityTypes authorityTypes; - - @Autowired(required = true) - protected MetadataValueService metadataValueService; - public AuthorityValue() { } @@ -187,7 +181,7 @@ public class AuthorityValue { public void updateItem(Context context, Item currentItem, MetadataValue value) throws SQLException, AuthorizeException { value.setValue(getValue()); value.setAuthority(getId()); - metadataValueService.update(context, value, true); + ContentServiceFactory.getInstance().getMetadataValueService().update(context, value, true); } /** @@ -248,9 +242,9 @@ public class AuthorityValue { } /** - * Provides a string that will be allow a this AuthorityType to be recognized and provides information to create a new instance to be created using public AuthorityValue newInstance(String info). - * See the implementation of com.atmire.org.dspace.authority.AuthorityValueGenerator#generateRaw(java.lang.String, java.lang.String) for more precisions. - * @return + * Provides a string that will allow this AuthorityType to be recognized and provides information to create a new instance to be created using public AuthorityValue newInstance(String info). + * See the implementation of {@link com.atmire.org.dspace.authority.AuthorityValueGenerator#generateRaw(java.lang.String, java.lang.String) AuthorityValueGenerator#generateRaw(java.lang.String, java.lang.String)} for more details. + * @return see {@link org.dspace.authority.service.AuthorityValueService#GENERATE AuthorityValueService.GENERATE} */ public String generateString() { return AuthorityValueServiceImpl.GENERATE; diff --git a/dspace-api/src/main/java/org/dspace/authorize/ResourcePolicy.java b/dspace-api/src/main/java/org/dspace/authorize/ResourcePolicy.java index 4a11838d7b..ff6199880a 100644 --- a/dspace-api/src/main/java/org/dspace/authorize/ResourcePolicy.java +++ b/dspace-api/src/main/java/org/dspace/authorize/ResourcePolicy.java @@ -42,9 +42,15 @@ public class ResourcePolicy implements ReloadableEntity { @JoinColumn(name = "dspace_object") private DSpaceObject dSpaceObject; + /* + * {@see org.dspace.core.Constants#Constants Constants} + */ @Column(name = "resource_type_id") private int resourceTypeId; + /* + * {@see org.dspace.core.Constants#Constants Constants} + */ @Column(name="action_id") private int actionId; @@ -293,4 +299,4 @@ public class ResourcePolicy implements ReloadableEntity { public void setRpDescription(String description){ this.rpdescription = description; } -} \ No newline at end of file +} diff --git a/dspace-api/src/main/java/org/dspace/authorize/dao/impl/ResourcePolicyDAOImpl.java b/dspace-api/src/main/java/org/dspace/authorize/dao/impl/ResourcePolicyDAOImpl.java index bdb67edf07..215c972ec5 100644 --- a/dspace-api/src/main/java/org/dspace/authorize/dao/impl/ResourcePolicyDAOImpl.java +++ b/dspace-api/src/main/java/org/dspace/authorize/dao/impl/ResourcePolicyDAOImpl.java @@ -87,7 +87,7 @@ public class ResourcePolicyDAOImpl extends AbstractHibernateDAO List results; if (notPolicyID != -1) { - criteria.add(Restrictions.and(Restrictions.not(Restrictions.eq("id", action)))); + criteria.add(Restrictions.and(Restrictions.not(Restrictions.eq("id", notPolicyID)))); } return list(criteria); diff --git a/dspace-api/src/main/java/org/dspace/authorize/service/AuthorizeService.java b/dspace-api/src/main/java/org/dspace/authorize/service/AuthorizeService.java index e6d4d02616..0b0903ad64 100644 --- a/dspace-api/src/main/java/org/dspace/authorize/service/AuthorizeService.java +++ b/dspace-api/src/main/java/org/dspace/authorize/service/AuthorizeService.java @@ -107,7 +107,7 @@ public interface AuthorizeService { * @param o DSpaceObject * @param a action being attempted, from * org.dspace.core.Constants - * @return true if the current user in the context is + * @return {@code true} if the current user in the context is * authorized to perform the given action on the given object * @throws SQLException if database error */ @@ -124,7 +124,7 @@ public interface AuthorizeService { * @param useInheritance * flag to say if ADMIN action on the current object or parent * object can be used - * @return true if the current user in the context is + * @return {@code true} if the current user in the context is * authorized to perform the given action on the given object * @throws SQLException if database error */ @@ -142,7 +142,7 @@ public interface AuthorizeService { * @param useInheritance * flag to say if ADMIN action on the current object or parent * object can be used - * @return true if the requested user is + * @return {@code true} if the requested user is * authorized to perform the given action on the given object * @throws SQLException if database error */ @@ -154,14 +154,14 @@ public interface AuthorizeService { /** * Check to see if the current user is an Administrator of a given object - * within DSpace. Always return true if the user is a System + * within DSpace. Always return {@code true} if the user is a System * Admin * * @param c current context * @param o current DSpace Object, if null the call will be * equivalent to a call to the isAdmin(Context c) * method - * @return true if user has administrative privileges on the + * @return {@code true} if user has administrative privileges on the * given DSpace object * @throws SQLException if database error */ @@ -170,11 +170,11 @@ public interface AuthorizeService { /** * Check to see if the current user is a System Admin. Always return - * true if c.ignoreAuthorization is set. Anonymous users + * {@code true} if c.ignoreAuthorization is set. Anonymous users * can't be Admins (EPerson set to NULL) * * @param c current context - * @return true if user is an admin or ignore authorization + * @return {@code true} if user is an admin or ignore authorization * flag set * @throws SQLException if database error */ @@ -240,7 +240,7 @@ public interface AuthorizeService { * * @param c current context * @param o object to retrieve policies for - * @return List of ResourcePolicy objects + * @return List of {@code ResourcePolicy} objects * @throws SQLException if database error */ public List getPolicies(Context c, DSpaceObject o) throws SQLException; @@ -251,7 +251,7 @@ public interface AuthorizeService { * @param c current context * @param o object to retrieve policies for * @param type type - * @return List of ResourcePolicy objects + * @return List of {@code ResourcePolicy} objects * @throws SQLException if database error */ public List findPoliciesByDSOAndType(Context c, DSpaceObject o, String type) throws SQLException; @@ -261,8 +261,8 @@ public interface AuthorizeService { * * @param c current context * @param g group to retrieve policies for - * @return List of ResourcePolicy objects - * @@throws SQLException if database error + * @return List of {@code ResourcePolicy} objects + * @throws SQLException if database error */ public List getPoliciesForGroup(Context c, Group g) throws SQLException; @@ -338,7 +338,7 @@ public interface AuthorizeService { * @param context current context * @param dso object to remove policies from * @param actionID ID of action to match from - * org.dspace.core.Constants, or -1=all + * {@link org.dspace.core.Constants#Constants Constants}, or -1=all * @throws SQLException if there's a database problem * @throws AuthorizeException if authorization error */ @@ -384,8 +384,8 @@ public interface AuthorizeService { * * @param c current context * @param o object - * @param actionID ID of action from org.dspace.core.Constants - * @return array of Groups that can perform the specified + * @param actionID ID of action from {@link org.dspace.core.Constants#Constants Constants} + * @return array of {@link org.dspace.eperson.Group#Group Groups} that can perform the specified * action on the specified object * @throws SQLException if there's a database problem */ @@ -400,7 +400,7 @@ public interface AuthorizeService { * @param c current context * @param o object * @param group group - * @param actionID ID of action from org.dspace.core.Constants + * @param actionID ID of action from {@link org.dspace.core.Constants#Constants Constants} * @param policyID ID of an existing policy. If -1 is specified, this parameter will be ignored * @return true if such a policy exists, false otherwise * @throws SQLException if there's a database problem diff --git a/dspace-api/src/main/java/org/dspace/browse/ItemListConfig.java b/dspace-api/src/main/java/org/dspace/browse/ItemListConfig.java index 7ad053f203..98c892a72d 100644 --- a/dspace-api/src/main/java/org/dspace/browse/ItemListConfig.java +++ b/dspace-api/src/main/java/org/dspace/browse/ItemListConfig.java @@ -11,8 +11,10 @@ import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.StringTokenizer; +import org.apache.commons.lang.ArrayUtils; -import org.dspace.core.ConfigurationManager; +import org.dspace.services.ConfigurationService; +import org.dspace.services.factory.DSpaceServicesFactory; /** * Class to mediate with the item list configuration @@ -33,6 +35,9 @@ public class ItemListConfig /** constant for a TEXT column */ private static final int TEXT = 2; + + private final transient ConfigurationService configurationService + = DSpaceServicesFactory.getInstance().getConfigurationService(); /** * Create a new instance of the Item list configuration. This loads @@ -45,21 +50,19 @@ public class ItemListConfig { try { - String configLine = ConfigurationManager.getProperty("webui.itemlist.columns"); + String[] browseFields = configurationService.getArrayProperty("webui.itemlist.columns"); - if (configLine == null || "".equals(configLine)) + if (ArrayUtils.isEmpty(browseFields)) { throw new BrowseException("There is no configuration for webui.itemlist.columns"); } // parse the config - StringTokenizer st = new StringTokenizer(configLine, ","); int i = 1; - while (st.hasMoreTokens()) + for(String token : browseFields) { Integer key = Integer.valueOf(i); - String token = st.nextToken(); - + // find out if the field is a date if (token.indexOf("(date)") > 0) { diff --git a/dspace-api/src/main/java/org/dspace/checker/package.html b/dspace-api/src/main/java/org/dspace/checker/package.html index 24761ccb2b..d6c4661c89 100644 --- a/dspace-api/src/main/java/org/dspace/checker/package.html +++ b/dspace-api/src/main/java/org/dspace/checker/package.html @@ -37,7 +37,7 @@

Dispatchers that generate bitstream ordering: -

    -
  • {@link org.dspace.checker.ListDispatcher}
  • +
  • {@link org.dspace.checker.IteratorDispatcher}
  • {@link org.dspace.checker.SimpleDispatcher}

diff --git a/dspace-api/src/main/java/org/dspace/content/BundleServiceImpl.java b/dspace-api/src/main/java/org/dspace/content/BundleServiceImpl.java index f3c905be8c..7ef6d0b9f1 100644 --- a/dspace-api/src/main/java/org/dspace/content/BundleServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/BundleServiceImpl.java @@ -306,7 +306,7 @@ public class BundleServiceImpl extends DSpaceObjectServiceImpl implement collection = item.getOwningCollection(); if (collection != null) { - community = collection.getCommunities().iterator().next(); + community = collection.getCommunities().get(0); } } switch (action) diff --git a/dspace-api/src/main/java/org/dspace/content/CollectionServiceImpl.java b/dspace-api/src/main/java/org/dspace/content/CollectionServiceImpl.java index c4f9399c41..4c3c20d798 100644 --- a/dspace-api/src/main/java/org/dspace/content/CollectionServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/CollectionServiceImpl.java @@ -123,14 +123,23 @@ public class CollectionServiceImpl extends DSpaceObjectServiceImpl i @Override public List findAll(Context context) throws SQLException { - MetadataField nameField = metadataFieldService.findByElement(context, "dc", "title", null); - return collectionDAO.findAll(context, nameField); + MetadataField nameField = metadataFieldService.findByElement(context, MetadataSchema.DC_SCHEMA, "title", null); + if(nameField==null) + { + throw new IllegalArgumentException("Required metadata field '" + MetadataSchema.DC_SCHEMA + ".title' doesn't exist!"); + } + return collectionDAO.findAll(context, nameField); } @Override public List findAll(Context context, Integer limit, Integer offset) throws SQLException { - MetadataField nameField = metadataFieldService.findByElement(context, "dc", "title", null); + MetadataField nameField = metadataFieldService.findByElement(context, MetadataSchema.DC_SCHEMA, "title", null); + if(nameField==null) + { + throw new IllegalArgumentException("Required metadata field '" + MetadataSchema.DC_SCHEMA + ".title' doesn't exist!"); + } + return collectionDAO.findAll(context, nameField, limit, offset); } @@ -619,7 +628,7 @@ public class CollectionServiceImpl extends DSpaceObjectServiceImpl i @Override public void canEdit(Context context, Collection collection, boolean useInheritance) throws SQLException, AuthorizeException { - List parents = collection.getCommunities(); + List parents = communityService.getAllParents(context, collection); for (Community parent : parents) { if (authorizeService.authorizeActionBoolean(context, parent, Constants.WRITE, useInheritance)) { @@ -794,7 +803,7 @@ public class CollectionServiceImpl extends DSpaceObjectServiceImpl i List communities = collection.getCommunities(); if (CollectionUtils.isNotEmpty(communities)) { - community = communities.iterator().next(); + community = communities.get(0); } switch (action) @@ -827,7 +836,7 @@ public class CollectionServiceImpl extends DSpaceObjectServiceImpl i public DSpaceObject getParentObject(Context context, Collection collection) throws SQLException { List communities = collection.getCommunities(); if(CollectionUtils.isNotEmpty(communities)){ - return communities.iterator().next(); + return communities.get(0); }else{ return null; } diff --git a/dspace-api/src/main/java/org/dspace/content/CommunityServiceImpl.java b/dspace-api/src/main/java/org/dspace/content/CommunityServiceImpl.java index 6c0711f5b2..0002871a0a 100644 --- a/dspace-api/src/main/java/org/dspace/content/CommunityServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/CommunityServiceImpl.java @@ -137,12 +137,22 @@ public class CommunityServiceImpl extends DSpaceObjectServiceImpl imp @Override public List findAll(Context context) throws SQLException { MetadataField sortField = metadataFieldService.findByElement(context, MetadataSchema.DC_SCHEMA, "title", null); + if(sortField==null) + { + throw new IllegalArgumentException("Required metadata field '" + MetadataSchema.DC_SCHEMA + ".title' doesn't exist!"); + } + return communityDAO.findAll(context, sortField); } @Override public List findAll(Context context, Integer limit, Integer offset) throws SQLException { MetadataField nameField = metadataFieldService.findByElement(context, MetadataSchema.DC_SCHEMA, "title", null); + if(nameField==null) + { + throw new IllegalArgumentException("Required metadata field '" + MetadataSchema.DC_SCHEMA + ".title' doesn't exist!"); + } + return communityDAO.findAll(context, nameField, limit, offset); } @@ -151,6 +161,11 @@ public class CommunityServiceImpl extends DSpaceObjectServiceImpl imp { // get all communities that are not children MetadataField sortField = metadataFieldService.findByElement(context, MetadataSchema.DC_SCHEMA, "title", null); + if(sortField==null) + { + throw new IllegalArgumentException("Required metadata field '" + MetadataSchema.DC_SCHEMA + ".title' doesn't exist!"); + } + return communityDAO.findAllNoParent(context, sortField); } @@ -308,6 +323,17 @@ public class CommunityServiceImpl extends DSpaceObjectServiceImpl imp return parentList; } + @Override + public List getAllParents(Context context, Collection collection) throws SQLException { + List result = new ArrayList<>(); + List communities = collection.getCommunities(); + result.addAll(communities); + for (Community community : communities) { + result.addAll(getAllParents(context, community)); + } + return result; + } + @Override public List getAllCollections(Context context, Community community) throws SQLException { List collectionList = new ArrayList(); diff --git a/dspace-api/src/main/java/org/dspace/content/DSpaceObjectServiceImpl.java b/dspace-api/src/main/java/org/dspace/content/DSpaceObjectServiceImpl.java index 91f1b7a833..d322b6c552 100644 --- a/dspace-api/src/main/java/org/dspace/content/DSpaceObjectServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/DSpaceObjectServiceImpl.java @@ -207,7 +207,7 @@ public abstract class DSpaceObjectServiceImpl implements public void addMetadata(Context context, T dso, String schema, String element, String qualifier, String lang, List values) throws SQLException { MetadataField metadataField = metadataFieldService.findByElement(context, schema, element, qualifier); if (metadataField == null) { - throw new SQLException("bad_dublin_core schema=" + schema + "." + element + "." + qualifier); + throw new SQLException("bad_dublin_core schema=" + schema + "." + element + "." + qualifier + ". Metadata field does not exist!"); } addMetadata(context, dso, metadataField, lang, values); @@ -219,7 +219,7 @@ public abstract class DSpaceObjectServiceImpl implements // until update() is called. MetadataField metadataField = metadataFieldService.findByElement(context, schema, element, qualifier); if (metadataField == null) { - throw new SQLException("bad_dublin_core schema=" + schema + "." + element + "." + qualifier); + throw new SQLException("bad_dublin_core schema=" + schema + "." + element + "." + qualifier + ". Metadata field does not exist!"); } addMetadata(context, dso, metadataField, lang, values, authorities, confidences); } @@ -332,16 +332,15 @@ public abstract class DSpaceObjectServiceImpl implements @Override public void clearMetadata(Context context, T dso, String schema, String element, String qualifier, String lang) throws SQLException { - // We will build a list of values NOT matching the values to clear Iterator metadata = dso.getMetadata().iterator(); while (metadata.hasNext()) { MetadataValue metadataValue = metadata.next(); + // If this value matches, delete it if (match(schema, element, qualifier, lang, metadataValue)) { - metadataValue.setDSpaceObject(null); metadata.remove(); -// metadataValueService.delete(context, metadataValue); + metadataValueService.delete(context, metadataValue); } } dso.setMetadataModified(); @@ -355,7 +354,7 @@ public abstract class DSpaceObjectServiceImpl implements if(values.contains(metadataValue)) { metadata.remove(); -// metadataValueService.delete(context, metadataValue); + metadataValueService.delete(context, metadataValue); } } dso.setMetadataModified(); @@ -364,11 +363,17 @@ public abstract class DSpaceObjectServiceImpl implements /** * Retrieve first metadata field value * @param dso - * @param language - * @param element + * The DSpaceObject which we ask for metadata. * @param schema + * the schema for the metadata field. Must match + * the name of an existing metadata schema. + * @param element + * the element to match, or Item.ANY * @param qualifier - * @return + * the qualifier to match, or Item.ANY + * @param language + * the language to match, or Item.ANY + * @return the first metadata field value */ @Override public String getMetadataFirstValue(T dso, String schema, String element, String qualifier, String language){ diff --git a/dspace-api/src/main/java/org/dspace/content/ItemComparator.java b/dspace-api/src/main/java/org/dspace/content/ItemComparator.java index f7d3900445..734169c100 100644 --- a/dspace-api/src/main/java/org/dspace/content/ItemComparator.java +++ b/dspace-api/src/main/java/org/dspace/content/ItemComparator.java @@ -225,7 +225,7 @@ public class ItemComparator implements Comparator, Serializable /** * Normalize the title of a Metadatum. * @param value - * @return + * @return normalized title */ protected String normalizeTitle(MetadataValue value) { diff --git a/dspace-api/src/main/java/org/dspace/content/ItemServiceImpl.java b/dspace-api/src/main/java/org/dspace/content/ItemServiceImpl.java index eed6c462fd..54f0cddf79 100644 --- a/dspace-api/src/main/java/org/dspace/content/ItemServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/ItemServiceImpl.java @@ -206,6 +206,11 @@ public class ItemServiceImpl extends DSpaceObjectServiceImpl implements It public Iterator findBySubmitterDateSorted(Context context, EPerson eperson, Integer limit) throws SQLException { MetadataField metadataField = metadataFieldService.findByElement(context, MetadataSchema.DC_SCHEMA, "date", "accessioned"); + if(metadataField==null) + { + throw new IllegalArgumentException("Required metadata field '" + MetadataSchema.DC_SCHEMA + ".date.accessioned' doesn't exist!"); + } + return itemDAO.findBySubmitter(context, eperson, metadataField, limit); } @@ -250,11 +255,7 @@ public class ItemServiceImpl extends DSpaceObjectServiceImpl implements It List result = new ArrayList<>(); List collections = item.getCollections(); for (Collection collection : collections) { - List owningCommunities = collection.getCommunities(); - for (Community community : owningCommunities) { - result.add(community); - result.addAll(communityService.getAllParents(context, community)); - } + result.addAll(communityService.getAllParents(context, collection)); } return result; diff --git a/dspace-api/src/main/java/org/dspace/content/MetadataFieldServiceImpl.java b/dspace-api/src/main/java/org/dspace/content/MetadataFieldServiceImpl.java index 805a5a8c70..490ab7fef8 100644 --- a/dspace-api/src/main/java/org/dspace/content/MetadataFieldServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/MetadataFieldServiceImpl.java @@ -20,6 +20,7 @@ import org.springframework.beans.factory.annotation.Autowired; import java.io.IOException; import java.sql.SQLException; import java.util.List; +import org.apache.commons.collections.CollectionUtils; /** * Service implementation for the MetadataField object. @@ -140,11 +141,29 @@ public class MetadataFieldServiceImpl implements MetadataFieldService { "Only administrators may modify the metadata registry"); } + // Check for existing usages of this field + List values = null; + try + { + values = metadataValueService.findByField(context, metadataField); + } + catch(IOException io) + { + // ignore + } + + // Only remove this field if it is NOT in use (as we don't want to bulk delete metadata values) + if(CollectionUtils.isEmpty(values)) + { + metadataFieldDAO.delete(context, metadataField); + } + else + { + throw new IllegalStateException("Metadata field " + metadataField.toString() + " cannot be deleted as it is currently used by one or more objects."); + } + log.info(LogManager.getHeader(context, "delete_metadata_field", "metadata_field_id=" + metadataField.getID())); - - metadataValueService.deleteByMetadataField(context, metadataField); - metadataFieldDAO.delete(context, metadataField); } /** diff --git a/dspace-api/src/main/java/org/dspace/content/crosswalk/METSRightsCrosswalk.java b/dspace-api/src/main/java/org/dspace/content/crosswalk/METSRightsCrosswalk.java index a2bf63ddcd..226b2808d7 100644 --- a/dspace-api/src/main/java/org/dspace/content/crosswalk/METSRightsCrosswalk.java +++ b/dspace-api/src/main/java/org/dspace/content/crosswalk/METSRightsCrosswalk.java @@ -475,179 +475,136 @@ public class METSRightsCrosswalk { //get what class of context this is String contextClass = element.getAttributeValue("CONTEXTCLASS"); - - if ((element.getAttributeValue("start-date") != null) - || (element.getAttributeValue("end-date") != null) - || (element.getAttributeValue("rpName") != null)) - { - SimpleDateFormat sdf = new SimpleDateFormat( "yyyy-MM-dd" ); - try { - ResourcePolicy rp = resourcePolicyService.create(context); - if (element.getAttributeValue("CONTEXTCLASS").equalsIgnoreCase("GENERAL PUBLIC")) { - Group anonGroup = groupService.findByName(context, Group.ANONYMOUS); - rp.setGroup(anonGroup); - } - else - { - if (element.getAttributeValue("CONTEXTCLASS").equalsIgnoreCase("REPOSITORY MGR")) { - Group adminGroup = groupService.findByName(context, Group.ADMIN); - rp.setGroup(adminGroup); - } - } - if (element.getAttributeValue("rpName") != null) - { - rp.setRpName(element.getAttributeValue("rpName")); - } - try { - if (element.getAttributeValue("start-date") != null) - { - rp.setStartDate(sdf.parse(element.getAttributeValue("start-date"))); - } - if (element.getAttributeValue("end-date") != null) - { - rp.setEndDate(sdf.parse(element.getAttributeValue("end-date"))); - } - }catch (ParseException ex) { - java.util.logging.Logger.getLogger(METSRightsCrosswalk.class.getName()).log(Level.SEVERE, null, ex); - } - - List le = new ArrayList(element.getChildren()); - for (Element el : le) - { - if ((el.getAttributeValue("DISCOVER").equalsIgnoreCase("true")) - && (el.getAttributeValue("DISPLAY").equalsIgnoreCase("true"))) - { - if (el.getAttributeValue("DELETE").equalsIgnoreCase("false")) - { - if (el.getAttributeValue("MODIFY").equalsIgnoreCase("false")) - { - rp.setAction(Constants.READ); - } - else - { - rp.setAction(Constants.WRITE); - } - } - else - { - if (el.getAttributeValue("MODIFY").equalsIgnoreCase("true")) - { - rp.setAction(Constants.DELETE); - if ((el.getAttributeValue("COPY").equalsIgnoreCase("true")) - &&(el.getAttributeValue("DUPLICATE").equalsIgnoreCase("true")) - &&(el.getAttributeValue("PRINT").equalsIgnoreCase("true"))) - { - rp.setAction(Constants.ADMIN); - } - } - } - } - } - policies.add(rp); - } catch (NullPointerException ex) { - java.util.logging.Logger.getLogger(METSRightsCrosswalk.class.getName()).log(Level.SEVERE, null, ex); - } - assignPermissions(context, dso, policies); + + ResourcePolicy rp = resourcePolicyService.create(context); + SimpleDateFormat sdf = new SimpleDateFormat( "yyyy-MM-dd" ); + + // get reference to the element + // Note: we are assuming here that there will only ever be ONE + // element. Currently there are no known use cases for multiple. + Element permsElement = element.getChild("Permissions", METSRights_NS); + if(permsElement == null) { + log.error("No element was found. Skipping this element."); + continue; } - else + + if (element.getAttributeValue("rpName") != null) { - //also get reference to the element - Element permsElement = element.getChild("Permissions", METSRights_NS); - - //Check if this permission pertains to Anonymous users - if(ANONYMOUS_CONTEXTCLASS.equals(contextClass)) + rp.setRpName(element.getAttributeValue("rpName")); + } + try { + if (element.getAttributeValue("start-date") != null) { - //get DSpace Anonymous group, ID=0 - Group anonGroup = groupService.findByName(context, Group.ANONYMOUS); - if(anonGroup==null) - { - throw new CrosswalkInternalException("The DSpace database has not been properly initialized. The Anonymous Group is missing from the database."); - } - - assignPermissions(context, dso, anonGroup, permsElement); - } // else if this permission declaration pertains to Administrators - else if(ADMIN_CONTEXTCLASS.equals(contextClass)) + rp.setStartDate(sdf.parse(element.getAttributeValue("start-date"))); + } + if (element.getAttributeValue("end-date") != null) { - //get DSpace Administrator group, ID=1 - Group adminGroup = groupService.findByName(context, Group.ADMIN); - if(adminGroup==null) - { - throw new CrosswalkInternalException("The DSpace database has not been properly initialized. The Administrator Group is missing from the database."); - } - - assignPermissions(context, dso, adminGroup, permsElement); - } // else if this permission pertains to another DSpace group - else if(GROUP_CONTEXTCLASS.equals(contextClass)) + rp.setEndDate(sdf.parse(element.getAttributeValue("end-date"))); + } + }catch (ParseException ex) { + log.error("Failed to parse embargo date. The date needs to be in the format 'yyyy-MM-dd'.", ex); + } + + //Check if this permission pertains to Anonymous users + if(ANONYMOUS_CONTEXTCLASS.equals(contextClass)) + { + //get DSpace Anonymous group, ID=0 + Group anonGroup = groupService.findByName(context, Group.ANONYMOUS); + if(anonGroup==null) { - try - { - //we need to find the name of DSpace group it pertains to - //Get the text within the child element, - // this is the group's name - String groupName = element.getChildTextTrim("UserName", METSRights_NS); + throw new CrosswalkInternalException("The DSpace database has not been properly initialized. The Anonymous Group is missing from the database."); + } - //Translate Group name back to internal ID format (e.g. COLLECTION__ADMIN) - // from its external format (e.g. COLLECTION__ADMIN) - groupName = PackageUtils.translateGroupNameForImport(context, groupName); - - //Check if this group exists in DSpace already - Group group = groupService.findByName(context, groupName); - - //if not found, throw an error -- user should restore group from the SITE AIP - if(group==null) - { - throw new CrosswalkInternalException("Cannot restore Group permissions on object (" - + "type=" + Constants.typeText[dso.getType()] + ", " - + "handle=" + dso.getHandle() + ", " - + "ID=" + dso.getID() - + "). The Group named '" + groupName + "' is missing from DSpace. " - + "Please restore this group using the SITE AIP, or recreate it."); - } - - //assign permissions to group on this object - assignPermissions(context, dso, group, permsElement); - } - catch(PackageException pe) - { - //A PackageException will only be thrown if translateDefaultGroupName() fails - //We'll just wrap it as a CrosswalkException and throw it upwards - throw new CrosswalkException(pe); - } - }//end if Group - else if(PERSON_CONTEXTCLASS.equals(contextClass)) + rp.setGroup(anonGroup); + } // else if this permission declaration pertains to Administrators + else if(ADMIN_CONTEXTCLASS.equals(contextClass)) + { + //get DSpace Administrator group, ID=1 + Group adminGroup = groupService.findByName(context, Group.ADMIN); + if(adminGroup==null) { - //we need to find the person it pertains to - // Get the text within the child element, - // this is the person's email address - String personEmail = element.getChildTextTrim("UserName", METSRights_NS); + throw new CrosswalkInternalException("The DSpace database has not been properly initialized. The Administrator Group is missing from the database."); + } - //Check if this person exists in DSpace already - EPerson person = ePersonService.findByEmail(context, personEmail); + rp.setGroup(adminGroup); + } // else if this permission pertains to another DSpace group + else if(GROUP_CONTEXTCLASS.equals(contextClass)) + { + try + { + //we need to find the name of DSpace group it pertains to + //Get the text within the child element, + // this is the group's name + String groupName = element.getChildTextTrim("UserName", METSRights_NS); - //If cannot find by email, try by netID - //(though METSRights should contain email if it was exported by DSpace) - if(person==null) + //Translate Group name back to internal ID format (e.g. COLLECTION__ADMIN) + // from its external format (e.g. COLLECTION__ADMIN) + groupName = PackageUtils.translateGroupNameForImport(context, groupName); + + //Check if this group exists in DSpace already + Group group = groupService.findByName(context, groupName); + + //if not found, throw an error -- user should restore group from the SITE AIP + if(group==null) { - person = ePersonService.findByNetid(context, personEmail); - } - - //if not found, throw an error -- user should restore person from the SITE AIP - if(person==null) - { - throw new CrosswalkInternalException("Cannot restore Person permissions on object (" + throw new CrosswalkInternalException("Cannot restore Group permissions on object (" + "type=" + Constants.typeText[dso.getType()] + ", " + "handle=" + dso.getHandle() + ", " + "ID=" + dso.getID() - + "). The Person with email/netid '" + personEmail + "' is missing from DSpace. " - + "Please restore this Person object using the SITE AIP, or recreate it."); + + "). The Group named '" + groupName + "' is missing from DSpace. " + + "Please restore this group using the SITE AIP, or recreate it."); } - //assign permissions to person on this object - assignPermissions(context, dso, person, permsElement); - }//end if Person - else - log.error("Unrecognized CONTEXTCLASS: " + contextClass); + //assign group to policy + rp.setGroup(group); + } + catch(PackageException pe) + { + //A PackageException will only be thrown if translateDefaultGroupName() fails + //We'll just wrap it as a CrosswalkException and throw it upwards + throw new CrosswalkException(pe); + } + }// else if this permission pertains to a DSpace person + else if(PERSON_CONTEXTCLASS.equals(contextClass)) + { + //we need to find the person it pertains to + // Get the text within the child element, + // this is the person's email address + String personEmail = element.getChildTextTrim("UserName", METSRights_NS); + + //Check if this person exists in DSpace already + EPerson person = ePersonService.findByEmail(context, personEmail); + + //If cannot find by email, try by netID + //(though METSRights should contain email if it was exported by DSpace) + if(person==null) + { + person = ePersonService.findByNetid(context, personEmail); + } + + //if not found, throw an error -- user should restore person from the SITE AIP + if(person==null) + { + throw new CrosswalkInternalException("Cannot restore Person permissions on object (" + + "type=" + Constants.typeText[dso.getType()] + ", " + + "handle=" + dso.getHandle() + ", " + + "ID=" + dso.getID() + + "). The Person with email/netid '" + personEmail + "' is missing from DSpace. " + + "Please restore this Person object using the SITE AIP, or recreate it."); + } + + //assign person to the policy + rp.setEPerson(person); + }//end if Person + else { + log.error("Unrecognized CONTEXTCLASS: " + contextClass); } + + //set permissions on policy and add to object + rp.setAction(parsePermissions(permsElement)); + policies.add(rp); + assignPermissions(context, dso, policies); + } //end if "Context" element }//end while loop } diff --git a/dspace-api/src/main/java/org/dspace/content/packager/METSManifest.java b/dspace-api/src/main/java/org/dspace/content/packager/METSManifest.java index 160b413b6b..44a5c49334 100644 --- a/dspace-api/src/main/java/org/dspace/content/packager/METSManifest.java +++ b/dspace-api/src/main/java/org/dspace/content/packager/METSManifest.java @@ -1194,9 +1194,9 @@ public class METSManifest } /** - * Get an aray of all AMDID values for this object + * Get an array of all AMDID values for this object * - * @return + * @return array of all AMDID values for this object * @throws MetadataValidationException if metadata validation error */ protected String[] getAmdIDs() diff --git a/dspace-api/src/main/java/org/dspace/content/packager/PackageUtils.java b/dspace-api/src/main/java/org/dspace/content/packager/PackageUtils.java index 402763a6b7..15d0c64174 100644 --- a/dspace-api/src/main/java/org/dspace/content/packager/PackageUtils.java +++ b/dspace-api/src/main/java/org/dspace/content/packager/PackageUtils.java @@ -14,6 +14,8 @@ import java.io.IOException; import java.io.InputStream; import java.sql.SQLException; import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; @@ -815,12 +817,21 @@ public class PackageUtils public static String translateGroupNameForExport(Context context, String groupName) throws PackageException { - // See if this resembles a default Group name + Pattern defaultGroupNamePattern = Pattern.compile("^([^_]+)_([^_]+)_(.+)$"); + // Check if this looks like a default Group name + Matcher matcher = defaultGroupNamePattern.matcher(groupName); + if(!matcher.matches()) + { + //if this is not a valid default group name, just return group name as-is (no crosswalking necessary) + return groupName; + } - String objID = StringUtils.substringBetween(groupName, "_", "_"); - int objType = StringUtils.startsWith(groupName, "COLLECTION_") ? Constants.COLLECTION : (StringUtils.startsWith(groupName, "COMMUNITY_") ? Constants.COMMUNITY : -1); - String groupType = StringUtils.substringAfterLast(groupName, "_"); - if (objID == null && objType != -1) + String objTypeText = matcher.group(1); + String objID = matcher.group(2); + String groupType = matcher.group(3); + + int objType = Constants.getTypeID(objTypeText); + if (objID == null || objType == -1) return groupName; @@ -863,7 +874,7 @@ public class PackageUtils //Create an updated group name, using the Handle to replace the InternalID // Format: _hdl:_ - return objType + "_" + "hdl:" + dso.getHandle() + "_" + groupType; + return objTypeText + "_" + "hdl:" + dso.getHandle() + "_" + groupType; } catch (SQLException sqle) { diff --git a/dspace-api/src/main/java/org/dspace/content/service/CommunityService.java b/dspace-api/src/main/java/org/dspace/content/service/CommunityService.java index ab45f0d637..020854b99b 100644 --- a/dspace-api/src/main/java/org/dspace/content/service/CommunityService.java +++ b/dspace-api/src/main/java/org/dspace/content/service/CommunityService.java @@ -189,6 +189,13 @@ public interface CommunityService extends DSpaceObjectService, DSpace */ public List getAllParents(Context context, Community community) throws SQLException; + /** + * Return an array of parent communities of this collection. + * + * @return an array of parent communities + */ + public List getAllParents(Context context, Collection collection) throws SQLException; + /** * Return an array of collections of this community and its subcommunities * diff --git a/dspace-api/src/main/java/org/dspace/content/service/ItemService.java b/dspace-api/src/main/java/org/dspace/content/service/ItemService.java index 8f45b82fb2..038ca637ad 100644 --- a/dspace-api/src/main/java/org/dspace/content/service/ItemService.java +++ b/dspace-api/src/main/java/org/dspace/content/service/ItemService.java @@ -95,11 +95,11 @@ public interface ItemService extends DSpaceObjectService, DSpaceObjectLega throws SQLException; /** - * Retrieve the list of Items submitted by eperson, ordered by recently submitted, optionally limitable + * Retrieve the list of items submitted by eperson, ordered by recently submitted, optionally limitable * @param context context * @param eperson eperson * @param limit a positive integer to limit, -1 or null for unlimited - * @return + * @return an iterator over the items submitted by eperson * @throws SQLException if database error */ public Iterator findBySubmitterDateSorted(Context context, EPerson eperson, Integer limit) throws SQLException; diff --git a/dspace-api/src/main/java/org/dspace/content/service/MetadataValueService.java b/dspace-api/src/main/java/org/dspace/content/service/MetadataValueService.java index 71356f0292..841c75d542 100644 --- a/dspace-api/src/main/java/org/dspace/content/service/MetadataValueService.java +++ b/dspace-api/src/main/java/org/dspace/content/service/MetadataValueService.java @@ -91,7 +91,7 @@ public interface MetadataValueService { * * @param context * @param metadataFieldId unique identifier of the interesting field. - * @return + * @return the minimum value of the metadata field * @throws SQLException if database error */ public MetadataValue getMinimum(Context context, int metadataFieldId) diff --git a/dspace-api/src/main/java/org/dspace/content/service/WorkspaceItemService.java b/dspace-api/src/main/java/org/dspace/content/service/WorkspaceItemService.java index 061dd0dd24..68900d3a6a 100644 --- a/dspace-api/src/main/java/org/dspace/content/service/WorkspaceItemService.java +++ b/dspace-api/src/main/java/org/dspace/content/service/WorkspaceItemService.java @@ -143,7 +143,7 @@ public interface WorkspaceItemService extends InProgressSubmissionService> getStageReachedCounts(Context context) throws SQLException; diff --git a/dspace-api/src/main/java/org/dspace/core/AbstractHibernateDAO.java b/dspace-api/src/main/java/org/dspace/core/AbstractHibernateDAO.java index 3d83109e3d..4708739e1c 100644 --- a/dspace-api/src/main/java/org/dspace/core/AbstractHibernateDAO.java +++ b/dspace-api/src/main/java/org/dspace/core/AbstractHibernateDAO.java @@ -94,8 +94,8 @@ public abstract class AbstractHibernateDAO implements GenericDAO { * Execute a JPA Criteria query and return a collection of results. * * @param context - * @param query - * @return + * @param query JPQL query string + * @return list of DAOs specified by the query string * @throws SQLException if database error */ public List findMany(Context context, Query query) throws SQLException { @@ -135,7 +135,7 @@ public abstract class AbstractHibernateDAO implements GenericDAO { * retrieved an exception will be thrown, * so only use when the criteria state uniqueness in the database. * @param criteria - * @return + * @return a DAO specified by the criteria */ public T uniqueResult(Criteria criteria) { @@ -148,7 +148,7 @@ public abstract class AbstractHibernateDAO implements GenericDAO { * Retrieve a single result from the query. Best used if you expect a * single result, but this isn't enforced on the database. * @param criteria - * @return + * @return a DAO specified by the criteria */ public T singleResult(Criteria criteria) { diff --git a/dspace-api/src/main/java/org/dspace/core/Context.java b/dspace-api/src/main/java/org/dspace/core/Context.java index 56512ce986..5f87d20998 100644 --- a/dspace-api/src/main/java/org/dspace/core/Context.java +++ b/dspace-api/src/main/java/org/dspace/core/Context.java @@ -16,6 +16,7 @@ import org.dspace.event.Event; import org.dspace.event.factory.EventServiceFactory; import org.dspace.event.service.EventService; import org.dspace.storage.rdbms.DatabaseConfigVO; +import org.dspace.storage.rdbms.DatabaseUtils; import org.dspace.utils.DSpace; import org.springframework.util.CollectionUtils; @@ -83,6 +84,21 @@ public class Context private DBConnection dbConnection; + static + { + // Before initializing a Context object, we need to ensure the database + // is up-to-date. This ensures any outstanding Flyway migrations are run + // PRIOR to Hibernate initializing (occurs when DBConnection is loaded in init() below). + try + { + DatabaseUtils.updateDatabase(); + } + catch(SQLException sqle) + { + log.fatal("Cannot initialize database via Flyway!", sqle); + } + } + protected Context(EventService eventService, DBConnection dbConnection) { this.eventService = eventService; this.dbConnection = dbConnection; @@ -93,9 +109,6 @@ public class Context /** * Construct a new context object with default options. A database connection is opened. * No user is authenticated. - * - * @exception SQLException - * if there was an error obtaining a database connection */ public Context() { diff --git a/dspace-api/src/main/java/org/dspace/core/GenericDAO.java b/dspace-api/src/main/java/org/dspace/core/GenericDAO.java index 6e13e9e73a..2013905879 100644 --- a/dspace-api/src/main/java/org/dspace/core/GenericDAO.java +++ b/dspace-api/src/main/java/org/dspace/core/GenericDAO.java @@ -34,7 +34,7 @@ public interface GenericDAO * * @param context * @param clazz the desired type. - * @return + * @return list of DAOs of the same type as clazz * @throws SQLException if database error */ public List findAll(Context context, Class clazz) throws SQLException; @@ -43,8 +43,8 @@ public interface GenericDAO * Execute a JPQL query returning a unique result. * * @param context - * @param query - * @return + * @param query JPQL query string + * @return a DAO specified by the query string * @throws SQLException if database error */ public T findUnique(Context context, String query) throws SQLException; @@ -57,8 +57,8 @@ public interface GenericDAO * Execute a JPQL query and return a collection of results. * * @param context - * @param query - * @return + * @param query JPQL query string + * @return list of DAOs specified by the query string * @throws SQLException if database error */ public List findMany(Context context, String query) throws SQLException; diff --git a/dspace-api/src/main/java/org/dspace/curate/TaskResolver.java b/dspace-api/src/main/java/org/dspace/curate/TaskResolver.java index 516395d99b..b640b5b8dd 100644 --- a/dspace-api/src/main/java/org/dspace/curate/TaskResolver.java +++ b/dspace-api/src/main/java/org/dspace/curate/TaskResolver.java @@ -58,7 +58,7 @@ import org.dspace.services.factory.DSpaceServicesFactory; * {@code My descriptor $td=ruby|rubytask.rb|LinkChecker.new} * * For portability, the {@code } component may be omitted in this context. - * Thus, {@code$td=ruby||LinkChecker.new} will be expanded to a descriptor + * Thus, {@code $td=ruby||LinkChecker.new} will be expanded to a descriptor * with the name of the embedding file. * * @author richardrodgers diff --git a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java index 63fc69ea97..ff7b4b1fc7 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java @@ -677,10 +677,10 @@ public class SolrServiceImpl implements SearchService, IndexingService { return locations; } - protected List getCollectionLocations(Collection target) throws SQLException { + protected List getCollectionLocations(Context context, Collection target) throws SQLException { List locations = new Vector(); // build list of community ids - List communities = target.getCommunities(); + List communities = communityService.getAllParents(context, target); // now put those into strings for (Community community : communities) @@ -798,7 +798,7 @@ public class SolrServiceImpl implements SearchService, IndexingService { */ protected void buildDocument(Context context, Collection collection) throws SQLException, IOException { - List locations = getCollectionLocations(collection); + List locations = getCollectionLocations(context, collection); // Create Lucene Document SolrInputDocument doc = buildDocument(Constants.COLLECTION, collection.getID(), @@ -1524,8 +1524,12 @@ public class SolrServiceImpl implements SearchService, IndexingService { public String locationToName(Context context, String field, String value) throws SQLException { if("location.comm".equals(field) || "location.coll".equals(field)) { - int type = field.equals("location.comm") ? Constants.COMMUNITY : Constants.COLLECTION; - DSpaceObject commColl = contentServiceFactory.getDSpaceObjectService(type).find(context, UUID.fromString(value)); + int type = ("location.comm").equals(field) ? Constants.COMMUNITY : Constants.COLLECTION; + DSpaceObject commColl = null; + if (StringUtils.isNotBlank(value)) + { + commColl = contentServiceFactory.getDSpaceObjectService(type).find(context, UUID.fromString(value)); + } if(commColl != null) { return commColl.getName(); @@ -2017,7 +2021,7 @@ public class SolrServiceImpl implements SearchService, IndexingService { DiscoverFilterQuery result = new DiscoverFilterQuery(); StringBuilder filterQuery = new StringBuilder(); - if(StringUtils.isNotBlank(field)) + if(StringUtils.isNotBlank(field) && StringUtils.isNotBlank(value)) { filterQuery.append(field); if("equals".equals(operator)) @@ -2069,10 +2073,9 @@ public class SolrServiceImpl implements SearchService, IndexingService { } } - + result.setDisplayedValue(transformDisplayedValue(context, field, value)); } - result.setDisplayedValue(transformDisplayedValue(context, field, value)); result.setFilterQuery(filterQuery.toString()); return result; } diff --git a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceResourceRestrictionPlugin.java b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceResourceRestrictionPlugin.java index 0b7ea83651..fc1e740605 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceResourceRestrictionPlugin.java +++ b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceResourceRestrictionPlugin.java @@ -69,7 +69,12 @@ public class SolrServiceResourceRestrictionPlugin implements SolrServiceIndexPlu if(!authorizeService.isAdmin(context)){ StringBuilder resourceQuery = new StringBuilder(); //Always add the anonymous group id to the query - resourceQuery.append("read:(g0"); + Group anonymousGroup = groupService.findByName(context,Group.ANONYMOUS); + String anonGroupId = ""; + if(anonymousGroup!=null){ + anonGroupId = anonymousGroup.getID().toString(); + } + resourceQuery.append("read:(g"+anonGroupId); EPerson currentUser = context.getCurrentUser(); if(currentUser != null){ resourceQuery.append(" OR e").append(currentUser.getID()); diff --git a/dspace-api/src/main/java/org/dspace/handle/Handle.java b/dspace-api/src/main/java/org/dspace/handle/Handle.java index 0c17894293..2fca3a6d4d 100644 --- a/dspace-api/src/main/java/org/dspace/handle/Handle.java +++ b/dspace-api/src/main/java/org/dspace/handle/Handle.java @@ -37,6 +37,9 @@ public class Handle implements ReloadableEntity { @JoinColumn(name = "resource_id") private DSpaceObject dso; + /* + * {@see org.dspace.core.Constants#Constants Constants} + */ @Column(name = "resource_type_id") private Integer resourceTypeId; @@ -74,10 +77,16 @@ public class Handle implements ReloadableEntity { return dso; } + /* + * @param resourceTypeId the integer constant of the DSO, see {@link org.dspace.core.Constants#Constants Constants} + */ public void setResourceTypeId(Integer resourceTypeId) { this.resourceTypeId = resourceTypeId; } + /* + * @return the integer constant of the DSO, see {@link org.dspace.core.Constants#Constants Constants} + */ public Integer getResourceTypeId() { return resourceTypeId; } diff --git a/dspace-api/src/main/java/org/dspace/health/ItemCheck.java b/dspace-api/src/main/java/org/dspace/health/ItemCheck.java index a0aae9392e..bdea65faae 100644 --- a/dspace-api/src/main/java/org/dspace/health/ItemCheck.java +++ b/dspace-api/src/main/java/org/dspace/health/ItemCheck.java @@ -128,7 +128,7 @@ public class ItemCheck extends Check { return sb.toString(); } - public String getCollectionSizesInfo(Context context) throws SQLException { + public String getCollectionSizesInfo(final Context context) throws SQLException { final StringBuffer ret = new StringBuffer(); List> colBitSizes = collectionService.getCollectionsWithBitstreamSizesTotal(context); long total_size = 0; @@ -137,8 +137,8 @@ public class ItemCheck extends Check { @Override public int compare(Map.Entry o1, Map.Entry o2) { try { - return CollectionDropDown.collectionPath(o1.getKey()).compareTo( - CollectionDropDown.collectionPath(o2.getKey()) + return CollectionDropDown.collectionPath(context, o1.getKey()).compareTo( + CollectionDropDown.collectionPath(context, o2.getKey()) ); } catch (Exception e) { ret.append(e.getMessage()); @@ -151,7 +151,7 @@ public class ItemCheck extends Check { total_size += size; Collection col = row.getKey(); ret.append(String.format( - "\t%s: %s\n", CollectionDropDown.collectionPath(col), FileUtils.byteCountToDisplaySize((long) size))); + "\t%s: %s\n", CollectionDropDown.collectionPath(context, col), FileUtils.byteCountToDisplaySize((long) size))); } ret.append(String.format( "Total size: %s\n", FileUtils.byteCountToDisplaySize(total_size))); diff --git a/dspace-api/src/main/java/org/dspace/identifier/DOI.java b/dspace-api/src/main/java/org/dspace/identifier/DOI.java index 7ee083de73..8c8307abfa 100644 --- a/dspace-api/src/main/java/org/dspace/identifier/DOI.java +++ b/dspace-api/src/main/java/org/dspace/identifier/DOI.java @@ -88,7 +88,7 @@ public class DOI * returns the resource type of the DSpaceObject the DOI is or was assigned * to. The resource type is set automatically when a DOI is assigned to a * DSpaceObject, using {@link #setDSpaceObject(org.dspace.content.DSpaceObject) }. - * @return + * @return the integer constant of the DSO, see {@link org.dspace.core.Constants#Constants Constants} */ public Integer getResourceTypeId() { return this.resourceTypeId; diff --git a/dspace-api/src/main/java/org/dspace/identifier/DOIIdentifierProvider.java b/dspace-api/src/main/java/org/dspace/identifier/DOIIdentifierProvider.java index 3369dc2a98..1e91297b71 100644 --- a/dspace-api/src/main/java/org/dspace/identifier/DOIIdentifierProvider.java +++ b/dspace-api/src/main/java/org/dspace/identifier/DOIIdentifierProvider.java @@ -144,7 +144,7 @@ public class DOIIdentifierProvider * This identifier provider supports identifiers of type * {@link org.dspace.identifier.DOI}. * @param identifier to check if it will be supported by this provider. - * @return + * @return boolean */ @Override public boolean supports(Class identifier) @@ -160,7 +160,7 @@ public class DOIIdentifierProvider *
  • http://dx.doi.org/10.123/456
  • * * @param identifier to check if it is in a supported format. - * @return + * @return boolean */ @Override public boolean supports(String identifier) @@ -231,7 +231,7 @@ public class DOIIdentifierProvider * @param dso DSpaceObject the DOI should be reserved for. Some metadata of * this object will be send to the registration agency. * @param identifier DOI to register in a format that - * {@link FormatIdentifier(String)} accepts. + * {@link org.dspace.identifier.service.DOIService#formatIdentifier(String)} accepts. * @throws IdentifierException If the format of {@code identifier} was * unrecognized or if it was impossible to * reserve the DOI (registration agency denied @@ -239,7 +239,7 @@ public class DOIIdentifierProvider * @throws IllegalArgumentException If {@code identifier} is a DOI already * registered for another DSpaceObject then * {@code dso}. - * @see IdentifierProvider.reserve(Context, DSpaceObject, String) + * @see org.dspace.identifier.IdentifierProvider#reserve(Context, DSpaceObject, String) */ @Override public void reserve(Context context, DSpaceObject dso, String identifier) @@ -696,7 +696,7 @@ public class DOIIdentifierProvider * Returns a DSpaceObject depending on its DOI. * @param context the context * @param identifier The DOI in a format that is accepted by - * {@link formatIdentifier(String)}. + * {@link org.dspace.identifier.service.DOIService#formatIdentifier(String)}. * @return Null if the DOI couldn't be found or the associated DSpaceObject. * @throws SQLException if database error * @throws IdentifierException If {@code identifier} is null or an empty string. diff --git a/dspace-api/src/main/java/org/dspace/identifier/DataCiteXMLCreator.java b/dspace-api/src/main/java/org/dspace/identifier/DataCiteXMLCreator.java index 46e76ef7fd..2acfa6ff3f 100644 --- a/dspace-api/src/main/java/org/dspace/identifier/DataCiteXMLCreator.java +++ b/dspace-api/src/main/java/org/dspace/identifier/DataCiteXMLCreator.java @@ -54,8 +54,8 @@ public class DataCiteXMLCreator /** * DisseminationCrosswalk to map local metadata into DataCite metadata. The - * name of the crosswalk is set by {@link setDisseminationCrosswalk(String) - * setDisseminationCrosswalk} which instantiates the crosswalk. + * name of the crosswalk is set by {@link #setDisseminationCrosswalkName(String) + * setDisseminationCrosswalkName} which instantiates the crosswalk. */ protected ParameterizedDisseminationCrosswalk xwalk; diff --git a/dspace-api/src/main/java/org/dspace/identifier/doi/DOIConnector.java b/dspace-api/src/main/java/org/dspace/identifier/doi/DOIConnector.java index f02fcb7477..286a24d8d8 100644 --- a/dspace-api/src/main/java/org/dspace/identifier/doi/DOIConnector.java +++ b/dspace-api/src/main/java/org/dspace/identifier/doi/DOIConnector.java @@ -17,9 +17,10 @@ import org.dspace.core.Context; * A DOIConnector should care about rules of the registration agency. For * example, if the registration agency wants us to reserve a DOI before we can * register it, the DOIConnector should check if a DOI is reserved. Use a - * {@link DOIIdenfierException} and set its error code in case of any errors. + * {@link org.dspace.identifier.doi.DOIIdentifierException#DOIIdentifierException DOIIdentifierException}. + * and set its error code in case of any errors. * For the given example you should use - * {@code DOIIdentifierException.RESERVER_FIRST} as error code. + * {@code DOIIdentifierException.RESERVE_FIRST} as error code. * * @author Pascal-Nicolas Becker */ @@ -49,7 +50,8 @@ public interface DOIConnector { * Sends a request to the DOI registry to reserve a DOI. * * The DOIConnector should check weather this DOI is reserved for another - * object already. In this case it should throw an {@link + * object already. In this case it should throw an + * {@link org.dspace.identifier.doi.DOIIdentifierException#DOIIdentifierException DOIIdentifierException}. * DOIIdentifierException} and set the error code to {@code * DOIIdentifierException.DOI_ALREADY_EXISTS}. * @@ -66,8 +68,10 @@ public interface DOIConnector { * The DOIConnector ensures compliance with the workflow of the registration * agency. For example, if a DOI has to be reserved before it can be * registered the DOIConnector has to check if it is reserved. In this case - * you can throw an DOIIdentifierExcpetion and set the error code to - * {@link DOIIdentifierException.RESERVE_FIRST}. + * you can throw an + * {@link org.dspace.identifier.doi.DOIIdentifierException#DOIIdentifierException DOIIdentifierException}. + * and set the error code to + * {@code DOIIdentifierException.RESERVE_FIRST}. * * @param context * @param dso diff --git a/dspace-api/src/main/java/org/dspace/identifier/doi/DataCiteConnector.java b/dspace-api/src/main/java/org/dspace/identifier/doi/DataCiteConnector.java index 588cab7cbe..94957eadac 100644 --- a/dspace-api/src/main/java/org/dspace/identifier/doi/DataCiteConnector.java +++ b/dspace-api/src/main/java/org/dspace/identifier/doi/DataCiteConnector.java @@ -103,7 +103,7 @@ implements DOIConnector /** * DisseminationCrosswalk to map local metadata into DataCite metadata. * The name of the crosswalk is set by spring dependency injection using - * {@link setDisseminationCrosswalk(String) setDisseminationCrosswalk} which + * {@link #setDisseminationCrosswalkName(String) setDisseminationCrosswalkName} which * instantiates the crosswalk. */ protected ParameterizedDisseminationCrosswalk xwalk; @@ -545,7 +545,7 @@ implements DOIConnector // 412 Precondition failed: DOI was not reserved before registration! case (412) : { - log.error("We tried to register a DOI {} that was not reserved " + log.error("We tried to register a DOI {} that has not been reserved " + "before! The registration agency told us: {}.", doi, resp.getContent()); throw new DOIIdentifierException("There was an error in handling " @@ -571,8 +571,8 @@ implements DOIConnector public void updateMetadata(Context context, DSpaceObject dso, String doi) throws DOIIdentifierException { - // We can use reserveDOI to update metadata. Datacite API uses the same - // request for reservartion as for updating metadata. + // We can use reserveDOI to update metadata. DataCite API uses the same + // request for reservation as for updating metadata. this.reserveDOI(context, dso, doi); } @@ -612,7 +612,7 @@ implements DOIConnector } finally { - // release ressources + // release resources try { EntityUtils.consume(reqEntity); @@ -731,7 +731,7 @@ implements DOIConnector } finally { - // release ressources + // release resources try { EntityUtils.consume(reqEntity); @@ -748,7 +748,7 @@ implements DOIConnector * * @param req * @param doi - * @return + * @return response from DataCite * @throws DOIIdentifierException if DOI error */ protected DataCiteResponse sendHttpRequest(HttpUriRequest req, String doi) @@ -774,7 +774,7 @@ implements DOIConnector content = EntityUtils.toString(entity, "UTF-8"); } - /* While debugging it can be useful to see whitch requests are send: + /* While debugging it can be useful to see which requests are sent: * * log.debug("Going to send HTTP request of type " + req.getMethod() + "."); * log.debug("Will be send to " + req.getURI().toString() + "."); @@ -861,7 +861,7 @@ implements DOIConnector { try { - // Release any ressources used by HTTP-Request. + // Release any resources used by HTTP-Request. if (null != entity) { EntityUtils.consume(entity); diff --git a/dspace-api/src/main/java/org/dspace/identifier/ezid/EZIDRequest.java b/dspace-api/src/main/java/org/dspace/identifier/ezid/EZIDRequest.java index 799bed1b24..589633358a 100644 --- a/dspace-api/src/main/java/org/dspace/identifier/ezid/EZIDRequest.java +++ b/dspace-api/src/main/java/org/dspace/identifier/ezid/EZIDRequest.java @@ -159,10 +159,10 @@ public class EZIDRequest /** * Create an identifier with a given name. The name is the end of the * request path. Note: to "reserve" a given identifier, include "_status = - * reserved" in {@link metadata}. + * reserved" in {@code metadata}. * * @param metadata ANVL-encoded key/value pairs. - * @return + * @return Decoded response data evoked by a request made to EZID. */ public EZIDResponse create(String name, Map metadata) throws IOException, IdentifierException, URISyntaxException @@ -182,10 +182,10 @@ public class EZIDRequest /** * Ask EZID to create a unique identifier and return its name. NOTE: to - * "reserve" a unique identifier, include "_status = reserved" in {@link metadata}. + * "reserve" a unique identifier, include "_status = reserved" in {@code metadata}. * * @param metadata ANVL-encoded key/value pairs. - * @return + * @return Decoded response data evoked by a request made to EZID. */ public EZIDResponse mint(Map metadata) throws IOException, IdentifierException, URISyntaxException @@ -209,7 +209,7 @@ public class EZIDRequest * * @param metadata fields to be altered. Leave the value of a field's empty * to delete the field. - * @return + * @return Decoded response data evoked by a request made to EZID. */ public EZIDResponse modify(String name, Map metadata) throws IOException, IdentifierException, URISyntaxException diff --git a/dspace-api/src/main/java/org/dspace/identifier/service/IdentifierService.java b/dspace-api/src/main/java/org/dspace/identifier/service/IdentifierService.java index 2e858882bd..ad0d9d65bb 100644 --- a/dspace-api/src/main/java/org/dspace/identifier/service/IdentifierService.java +++ b/dspace-api/src/main/java/org/dspace/identifier/service/IdentifierService.java @@ -48,7 +48,7 @@ public interface IdentifierService { * @return the matching identifiers, or the site identifier if the object * is a Site, or an empty array if no matching identifier is found. */ - List lookup(Context contex, DSpaceObject dso); + List lookup(Context context, DSpaceObject dso); /** * diff --git a/dspace-api/src/main/java/org/dspace/importer/external/MetadataSourceException.java b/dspace-api/src/main/java/org/dspace/importer/external/MetadataSourceException.java deleted file mode 100644 index 13739852ac..0000000000 --- a/dspace-api/src/main/java/org/dspace/importer/external/MetadataSourceException.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * 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.importer.external; - -/** Represents a problem with the input source: e.g. cannot connect to the source. - * Created by Roeland Dillen (roeland at atmire dot com) - * Date: 19/09/12 - * Time: 13:17 - */ -public class MetadataSourceException extends Exception { - public MetadataSourceException() { - } - - public MetadataSourceException(String s) { - super(s); - } - - public MetadataSourceException(String s, Throwable throwable) { - super(s, throwable); - } - - public MetadataSourceException(Throwable throwable) { - super(throwable); - } -} diff --git a/dspace-api/src/main/java/org/dspace/importer/external/Query.java b/dspace-api/src/main/java/org/dspace/importer/external/Query.java deleted file mode 100644 index cf82afaaef..0000000000 --- a/dspace-api/src/main/java/org/dspace/importer/external/Query.java +++ /dev/null @@ -1,55 +0,0 @@ -/** - * 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.importer.external; - -import org.apache.commons.collections.map.MultiValueMap; - -import java.util.Collection; - -/** - * Created by Roeland Dillen (roeland at atmire dot com) - * Date: 27/09/12 - * Time: 15:26 - */ -public class Query { - private MultiValueMap parameters = new MultiValueMap(); - - public MultiValueMap getParameters() { - return parameters; - } - - public void addParameter(String key,Object value){ - parameters.put(key,value); - } - - protected void addSingletonParameter(String key,Object value){ - parameters.remove(key); - parameters.put(key,value); - } - - public T getParameterAsClass(String key, Class clazz){ - Collection c=parameters.getCollection(key); - if(c==null||c.isEmpty()) return null; - else { - Object o=c.iterator().next(); - if(clazz.isAssignableFrom(o.getClass())) - return (T) o ; - else return null; - } - - } - - public Collection getParameter(String key){ - return parameters.getCollection(key); - } - - public void setParameters(MultiValueMap parameters) { - this.parameters = parameters; - } -} diff --git a/dspace-api/src/main/java/org/dspace/importer/external/README.md b/dspace-api/src/main/java/org/dspace/importer/external/README.md index e55aed8299..66f22d9e27 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/README.md +++ b/dspace-api/src/main/java/org/dspace/importer/external/README.md @@ -10,7 +10,19 @@ # Introduction # -This documentation explains the features and the usage of the importer framework. +This documentation explains the features and the usage of the importer framework. +Enabling the framework can be achieved by removing the comment block from the following step in item-submission.xml +Implementation specific or additional configuration can be found in their related documentation, if any. (Some implementations use other submission steps altogether, so make sure to double check) + +``` + + submit.progressbar.lookup + org.dspace.submit.step.XMLUIStartSubmissionLookupStep + org.dspace.app.webui.submit.step.JSPStartSubmissionLookupStep + org.dspace.app.xmlui.aspect.submission.submit.StartSubmissionLookupStep + true + +``` ## Features ## @@ -38,17 +50,17 @@ This modular design also allows it to be completely independent of the user inte # Implementation of an import source # -Each importer implementation must at least implement interface *org.dspace.importer.external.service.other.Imports* and implement the inherited methods. +Each importer implementation must at least implement interface *org.dspace.importer.external.service.components.MetadataSource* and implement the inherited methods. -One can also choose to implement class *org.dspace.importer.external.service.other.Source* next to the Imports interface. This class contains functionality to handle request timeouts and to retry requests. +One can also choose to implement class *org.dspace.importer.external.service.components.AbstractRemoteMetadataSource* next to the MetadataSource interface. This class contains functionality to handle request timeouts and to retry requests. -A third option is to implement class *org.dspace.importer.external.service.AbstractImportSourceService*. This class already implements both the Imports interface and Source class. AbstractImportSourceService has a generic type set 'RecordType'. In the importer implementation this type set should be the class of the records received from the remote source's response (e.g. when using axiom to get the records from the remote source's XML response, the importer implementation's type set is *org.apache.axiom.om.OMElement*). +A third option is to implement class *org.dspace.importer.external.service.AbstractImportSourceService*. This class already implements both the MetadataSource interface and Source class. AbstractImportSourceService has a generic type set 'RecordType'. In the importer implementation this type set should be the class of the records received from the remote source's response (e.g. when using axiom to get the records from the remote source's XML response, the importer implementation's type set is *org.apache.axiom.om.OMElement*). Implementing the AbstractImportSourceService allows the importer implementation to use the framework's build-in support to transform a record received from the remote source to an object of class *org.dspace.importer.external.datamodel.ImportRecord* containing DSpace metadata fields, as explained here: [Metadata mapping](#Mapping). ## Inherited methods ## -Method getImportSource() should return a unique identifier. Importer implementations should not be called directly, but class *org.dspace.importer.external.service.ImportService* should be called instead. This class contains the same methods as the importer implementatons, but with an extra parameter 'url'. This url parameter should contain the same identifier that is returned by the getImportSource() method of the importer implementation you want to use. +Method getImportSource() should return a unique identifier. Importer implementations should not be called directly, but class *org.dspace.importer.external.service.ImportService* should be called instead. This class contains the same methods as the importer implementations, but with an extra parameter 'url'. This url parameter should contain the same identifier that is returned by the getImportSource() method of the importer implementation you want to use. The other inherited methods are used to query the remote source. diff --git a/dspace-api/src/main/java/org/dspace/importer/external/SourceExceptionHandler.java b/dspace-api/src/main/java/org/dspace/importer/external/SourceExceptionHandler.java deleted file mode 100644 index 84e7ef67b3..0000000000 --- a/dspace-api/src/main/java/org/dspace/importer/external/SourceExceptionHandler.java +++ /dev/null @@ -1,21 +0,0 @@ -/** - * 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.importer.external; - -import org.dspace.importer.external.service.other.MetadataSource; - -/** - * Created by: Antoine Snyers (antoine at atmire dot com) - * Date: 27 Oct 2014 - */ -public abstract interface SourceExceptionHandler { - - public abstract void handle(T source); - -} diff --git a/dspace-api/src/main/java/org/dspace/importer/external/datamodel/ImportRecord.java b/dspace-api/src/main/java/org/dspace/importer/external/datamodel/ImportRecord.java index ee253afba4..516b612104 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/datamodel/ImportRecord.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/datamodel/ImportRecord.java @@ -15,22 +15,37 @@ import java.util.LinkedList; import java.util.List; /** - * Created by Roeland Dillen (roeland at atmire dot com) - * Date: 17/09/12 - * Time: 14:03 + * This class contains all MetadatumDTO objects from an imported item + * + * @author Roeland Dillen (roeland at atmire dot com) */ public class ImportRecord { private List valueList = null; + /** + * Retrieve an unmodifiableList of MetadatumDTO + * @return List of MetadatumDTO + */ public List getValueList() { return Collections.unmodifiableList(valueList); } + /** + * Create an ImportRecord instance initialized with a List of MetadatumDTO objects + * @param valueList + */ public ImportRecord(List valueList) { //don't want to alter the original list. Also now I can control the type of list - this.valueList = new LinkedList(valueList); + this.valueList = new LinkedList<>(valueList); } + /** + * Build a string based on the values in the valueList object + * The syntax will be + * Record{valueList={"schema"; "element" ; "qualifier"; "value"}} + * + * @return a concatenated string containing all values of the MetadatumDTO objects in valueList + */ @Override public String toString() { final StringBuilder sb = new StringBuilder(); @@ -55,6 +70,13 @@ public class ImportRecord { return sb.toString(); } + /** + * Return the MetadatumDTO's that are related to a given schema/element/qualifier pair/triplet + * @param schema + * @param element + * @param qualifier + * @return the MetadatumDTO's that are related to a given schema/element/qualifier pair/triplet + */ public Collection getValue(String schema, String element, String qualifier){ List values=new LinkedList(); for(MetadatumDTO value:valueList){ @@ -69,6 +91,10 @@ public class ImportRecord { return values; } + /** + * Add a value to the valueList + * @param value The MetadatumDTO to add to the valueList + */ public void addValue(MetadatumDTO value){ this.valueList.add(value); } diff --git a/dspace-api/src/main/java/org/dspace/importer/external/datamodel/Query.java b/dspace-api/src/main/java/org/dspace/importer/external/datamodel/Query.java new file mode 100644 index 0000000000..4266742f19 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/importer/external/datamodel/Query.java @@ -0,0 +1,92 @@ +/** + * 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.importer.external.datamodel; + +import org.apache.commons.collections.map.MultiValueMap; + +import java.util.Collection; + +/** Represents a query to a source. Subclasses may enforce stricter typing or more verbose setting of parameters. + * @author Roeland Dillen (roeland at atmire dot com) + */ +public class Query { + + private MultiValueMap parameters = new MultiValueMap(); + /** + * Retrieve the parameters set to this Query object + * + * @return the {@link org.apache.commons.collections.map.MultiValueMap} set to this object + */ + public MultiValueMap getParameters() { + return parameters; + } + + /** + * In the parameters variable, adds the value to the collection associated with the specified key. + *

    + * Unlike a normal Map the previous value is not replaced. + * Instead the new value is added to the collection stored against the key. + * + * @param key the key to store against + * @param value the value to add to the collection at the key + */ + public void addParameter(String key,Object value){ + parameters.put(key,value); + } + + /** + * In the parameters variable, adds the value to the collection associated with the specified key. + *

    + * Unlike {@link #addParameter(String, Object)} the previous value is overridden. + * First, any existing values are removed, then the new value is added to the collection at the specified key + * + * @param key the key to store against + * @param value the value to add to the collection at the key + */ + protected void addSingletonParameter(String key,Object value){ + parameters.remove(key); + parameters.put(key,value); + } + + /** + * Retrieve a parameter as a certain given class + * @param key the key to retrieve the parameter from + * @param clazz The classtype to retrieve. (If no parameter with that class is found, a null value is returned + */ + public T getParameterAsClass(String key, Class clazz){ + Collection c=parameters.getCollection(key); + if(c==null||c.isEmpty()) return null; + else { + Object o=c.iterator().next(); + if(clazz.isAssignableFrom(o.getClass())) + return (T) o ; + else return null; + } + + } + /** + * Gets the collection mapped to the specified key. + * This method is a convenience method to typecast the result of get(key). + * + * @param key the key used to retrieve the collection + * @return the collection mapped to the key, null if no mapping + */ + public Collection getParameter(String key){ + return parameters.getCollection(key); + } + + + /** + * Set the parameters of this query object based on a given {@link org.apache.commons.collections.map.MultiValueMap} + * @param parameters a {@link org.apache.commons.collections.map.MultiValueMap} to set to this Query object + */ + public void setParameters(MultiValueMap parameters) { + this.parameters = parameters; + } +} diff --git a/dspace-api/src/main/java/org/dspace/importer/external/datamodel/package-info.java b/dspace-api/src/main/java/org/dspace/importer/external/datamodel/package-info.java new file mode 100644 index 0000000000..a68b019c4b --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/importer/external/datamodel/package-info.java @@ -0,0 +1,14 @@ +/** + * 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 containing datamodel classes which are constructed/used during the retrieval of Records + * Strictly data-centric classes + * @author Roeland Dillen (roeland at atmire dot com) + * @author Jonas Van Goolen (jonas at atmire dot com) + */ +package org.dspace.importer.external.datamodel; \ No newline at end of file diff --git a/dspace-api/src/main/java/org/dspace/importer/external/exception/MetadataSourceException.java b/dspace-api/src/main/java/org/dspace/importer/external/exception/MetadataSourceException.java new file mode 100644 index 0000000000..968dbebaa9 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/importer/external/exception/MetadataSourceException.java @@ -0,0 +1,70 @@ +/** + * 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.importer.external.exception; + +/** Represents a problem with the input source: e.g. cannot connect to the source. + * @author Roeland Dillen (roeland at atmire dot com) + */ +public class MetadataSourceException extends Exception { + + /** + * Constructs a new exception with {@code null} as its detail message. + * The cause is not initialized, and may subsequently be initialized by a + * call to {@link #initCause}. + */ + public MetadataSourceException() { + super(); + } + + /** + * Constructs a new exception with the specified detail message. The + * cause is not initialized, and may subsequently be initialized by + * a call to {@link #initCause}. + * + * @param message the detail message. The detail message is saved for + * later retrieval by the {@link #getMessage()} method. + */ + public MetadataSourceException(String message) { + super(message); + } + + /** + * Constructs a new exception with the specified detail message and + * cause.

    Note that the detail message associated with + * {@code cause} is not automatically incorporated in + * this exception's detail message. + * + * @param message the detail message (which is saved for later retrieval + * by the {@link #getMessage()} method). + * @param cause the cause (which is saved for later retrieval by the + * {@link #getCause()} method). (A null value is + * permitted, and indicates that the cause is nonexistent or + * unknown.) + */ + public MetadataSourceException(String message, Throwable cause) { + super(message, cause); + } + + /** + * Constructs a new exception with the specified cause and a detail + * message of (cause==null ? null : cause.toString()) (which + * typically contains the class and detail message of cause). + * This constructor is useful for exceptions that are little more than + * wrappers for other throwables (for example, {@link + * java.security.PrivilegedActionException}). + * + * @param cause the cause (which is saved for later retrieval by the + * {@link #getCause()} method). (A null value is + * permitted, and indicates that the cause is nonexistent or + * unknown.) + */ + public MetadataSourceException(Throwable cause) { + super(cause); + } +} diff --git a/dspace-api/src/main/java/org/dspace/importer/external/exception/SourceExceptionHandler.java b/dspace-api/src/main/java/org/dspace/importer/external/exception/SourceExceptionHandler.java new file mode 100644 index 0000000000..55ed247f6e --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/importer/external/exception/SourceExceptionHandler.java @@ -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.importer.external.exception; + +import org.dspace.importer.external.service.components.AbstractRemoteMetadataSource; + +/** + * Represent a handler that forces implementations to define their own behaviour for exceptions originating from + * @author Antoine Snyers (antoine at atmire dot com) + */ +public abstract interface SourceExceptionHandler { + + /** + * Represents a method contract to handle Exceptions originating from the source in a specific way + * Implementations define their own desired behaviour + * @param source The source of the exception + */ + public abstract void handle(T source); + +} diff --git a/dspace-api/src/main/java/org/dspace/importer/external/exception/package-info.java b/dspace-api/src/main/java/org/dspace/importer/external/exception/package-info.java new file mode 100644 index 0000000000..8ea7d0e2c0 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/importer/external/exception/package-info.java @@ -0,0 +1,13 @@ +/** + * 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/ + */ + +/** + * External importer Exception classes + possible handlers + * @author Jonas Van Goolen (jonas at atmire dot com) + */ +package org.dspace.importer.external.exception; \ No newline at end of file diff --git a/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/AbstractMetadataFieldMapping.java b/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/AbstractMetadataFieldMapping.java index 1c77628bb0..72cd96806f 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/AbstractMetadataFieldMapping.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/AbstractMetadataFieldMapping.java @@ -10,7 +10,7 @@ package org.dspace.importer.external.metadatamapping; import org.apache.log4j.Logger; import org.dspace.importer.external.metadatamapping.contributor.MetadataContributor; -import org.dspace.importer.external.metadatamapping.service.MetadataProcessorService; +import org.dspace.importer.external.metadatamapping.transform.MetadataProcessorService; import java.util.Collection; import java.util.LinkedList; @@ -18,9 +18,10 @@ import java.util.List; import java.util.Map; /** - * Created by Roeland Dillen (roeland at atmire dot com) - * Date: 19/09/12 - * Time: 10:09 + * Abstract class that implements {@link MetadataFieldMapping} + * This class adds a default implementation for the MetadataFieldMapping methods + * + * @author Roeland Dillen (roeland at atmire dot com) */ public abstract class AbstractMetadataFieldMapping implements MetadataFieldMapping> { @@ -31,13 +32,25 @@ public abstract class AbstractMetadataFieldMapping implements Metada */ private static Logger log = Logger.getLogger(AbstractMetadataFieldMapping.class); + /* A map containing what processing has to be done on a given metadataFieldConfig. + * The processing of a value is used to determine the actual value that will be returned used. + */ private Map metadataProcessorMap; + /** + * Set a map of metadataprocessors. This map is used to process metadata to make it more compliant for certain metadata fields + * @param metadataProcessorMap + */ public void setMetadataProcessorMap(Map metadataProcessorMap) { this.metadataProcessorMap = metadataProcessorMap; } + /** + * Return the metadataProcessor used to update values to make them more compliant for certain goals + * @param metadataField to retrieve processor for + * @return metadataProcessor + */ public MetadataProcessorService getMetadataProcessor(MetadataFieldConfig metadataField) { if(metadataProcessorMap != null) @@ -48,11 +61,14 @@ public abstract class AbstractMetadataFieldMapping implements Metada } } + /** + * @param field MetadataFieldConfig representing what to map the value to + * @param value The value to map to a MetadatumDTO + * @return A metadatumDTO created from the field and value + */ public MetadatumDTO toDCValue(MetadataFieldConfig field, String value) { MetadatumDTO dcValue = new MetadatumDTO(); - - if (field == null) return null; MetadataProcessorService metadataProcessor = getMetadataProcessor(field); if(metadataProcessor != null) @@ -66,48 +82,31 @@ public abstract class AbstractMetadataFieldMapping implements Metada return dcValue; } - private boolean reverseDifferent = false; - - private String AND = "AND"; - private String OR = "OR"; - private String NOT = "NOT"; - - public String getAND() { - return AND; - } - - public void setAND(String AND) { - this.AND = AND; - } - - public String getOR() { - return OR; - } - - public void setOR(String OR) { - this.OR = OR; - } - - public String getNOT() { - return NOT; - } - - public void setNOT(String NOT) { - this.NOT = NOT; - } - + /** + * Retrieve the metadataFieldMap set to this class + * @return Map> representing the metadataFieldMap + */ public Map> getMetadataFieldMap() { return metadataFieldMap; } + /** Defines which metadatum is mapped on which metadatum. Note that while the key must be unique it + * only matters here for postprocessing of the value. The mapped MetadatumContributor has full control over + * what metadatafield is generated. + * @param metadataFieldMap The map containing the link between retrieve metadata and metadata that will be set to the item. + */ public void setMetadataFieldMap(Map> metadataFieldMap) { this.metadataFieldMap = metadataFieldMap; for(MetadataContributor mc:metadataFieldMap.values()){ mc.setMetadataFieldMapping(this); } - } + /** + * Loop over the MetadataContributors and return their concatenated retrieved metadatumDTO objects + * @param record Used to retrieve the MetadatumDTO + * @return Lit of metadatumDTO + */ @Override public Collection resultToDCValueMapping(RecordType record) { List values=new LinkedList(); diff --git a/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/MetadataFieldConfig.java b/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/MetadataFieldConfig.java index 357c14a71d..279dd3789f 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/MetadataFieldConfig.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/MetadataFieldConfig.java @@ -8,9 +8,10 @@ package org.dspace.importer.external.metadatamapping; /** - * Created by Roeland Dillen (roeland at atmire dot com) - * Date: 19/09/12 - * Time: 10:11 + * A generalised configuration for metadatafields. + * This is used to make the link between values and the actual MetadatumDTO object. + * + * @author Roeland Dillen (roeland at atmire dot com) */ public class MetadataFieldConfig { private String schema; @@ -18,6 +19,12 @@ public class MetadataFieldConfig { private String qualifier; + /** + * Indicates whether some other object is "equal to" this one. + * @param o the reference object with which to compare. + * @return {@code true} if this object is the same as the obj + * argument; {@code false} otherwise. + */ @Override public boolean equals(Object o) { if (this == o) return true; @@ -32,6 +39,10 @@ public class MetadataFieldConfig { return true; } + /** + * Create the String representation of the MetadataFieldConfig + * @return a string representation of the MetadataFieldConfig + */ @Override public String toString() { final StringBuilder sb = new StringBuilder(); @@ -43,6 +54,12 @@ public class MetadataFieldConfig { return sb.toString(); } + /** + * Returns a hash code value for the object. This method is + * supported for the benefit of hash tables such as those provided by + * {@link java.util.HashMap}. + * @return a hash code value for this object. + */ @Override public int hashCode() { int result = schema.hashCode(); @@ -51,26 +68,41 @@ public class MetadataFieldConfig { return result; } - public String getSchema() { - - return schema; - } + /** + * Create a MetadataFieldConfig based on a given MetadatumDTO + * This MetadatumDTO object contains the schema, element and qualifier needed to initialize the MetadataFieldConfig + * @param value + */ public MetadataFieldConfig(MetadatumDTO value) { this.schema = value.getSchema(); this.element = value.getElement(); this.qualifier = value.getQualifier(); } + /** + * An empty initialization of MetadataFieldConfig + */ public MetadataFieldConfig() { } + /** + * Create a MetadataFieldConfig using a schema,element and qualifier + * @param schema The schema to set to this object + * @param element The element to set to this object + * @param qualifier The qualifier to set to this object + */ public MetadataFieldConfig(String schema, String element, String qualifier) { this.schema = schema; this.element = element; this.qualifier = qualifier; } + /** + * Create a MetadataFieldConfig using a single value. + * This value is split up into schema, element and qualifier, based on a dot(.) + * @param full A string representing the schema.element.qualifier triplet + */ public MetadataFieldConfig(String full) { String elements[]=full.split("\\."); if(elements.length==2){ @@ -83,34 +115,75 @@ public class MetadataFieldConfig { } } - + /** + * Create a MetadataFieldConfig using a schema and element + * qualifier will be set to null + * @param schema The schema to set to this object + * @param element The element to set to this object + */ public MetadataFieldConfig(String schema, String element) { this.schema = schema; this.element = element; this.qualifier = null; } + /** + * Set the schema to this MetadataFieldConfig + * @param schema The schema to set to this object + */ public void setSchema(String schema) { this.schema = schema; } + /** + * Return the schema set to this object. + * null if nothing is set + * @return The schema of this object + */ + public String getSchema() { + + return schema; + } + + /** + * Return a string representing the field of this object + * @return The field that is set to this object, in the form of schema.element.qualifier + */ public String getField() { return schema + "." + element + (qualifier==null?"":("." + qualifier)); } + /** + * Return the qualifier set to this object. + * null if nothing is set + * @return The qualifier of this object + */ public String getElement() { return element; } + /** + * Set the element to this MetadataFieldConfig + * @param element The element to set to this object + */ public void setElement(String element) { this.element = element; } + /** + * Return the qualifier set to this object. + * null if nothing is set + * @return The qualifier of this object + */ public String getQualifier() { return qualifier; } + /** + * Set the qualifier to this MetadataFieldConfig + * @param qualifier The qualifier to set to this object + */ public void setQualifier(String qualifier) { this.qualifier = qualifier; } diff --git a/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/MetadataFieldMapping.java b/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/MetadataFieldMapping.java index 00a47afdda..7037a07e48 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/MetadataFieldMapping.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/MetadataFieldMapping.java @@ -10,16 +10,27 @@ package org.dspace.importer.external.metadatamapping; import java.util.Collection; /** - * Created by Roeland Dillen (roeland at atmire dot com) - * Date: 18/09/12 - * Time: 14:41 + * Represents an interface for the mapping of the metadatum fields + * + * @author Roeland Dillen (roeland at atmire dot com) */ -public interface MetadataFieldMapping { +public interface MetadataFieldMapping { - public MetadatumDTO toDCValue(MetadataFieldConfig field, String mf); + /** + * @param field MetadataFieldConfig representing what to map the value to + * @param value The value to map to a MetadatumDTO + * @return A metadatumDTO created from the field and value + */ + public MetadatumDTO toDCValue(MetadataFieldConfig field, String value); - public Collection resultToDCValueMapping(RecordType record); + + /** + * Create a collection of MetadatumDTO retrieved from a given RecordType + * @param record Used to retrieve the MetadatumDTO + * @return Collection of MetadatumDTO + */ + public Collection resultToDCValueMapping(RecordType record); diff --git a/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/MetadatumDTO.java b/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/MetadatumDTO.java index a5de8b717c..d5fa961814 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/MetadatumDTO.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/MetadatumDTO.java @@ -8,9 +8,13 @@ package org.dspace.importer.external.metadatamapping; /** - * Created by Philip Vissenaekens (philip at atmire dot com) - * Date: 21/10/15 - * Time: 09:52 + * This class is used to cary data between processes. + * Using this class, we have a uniform, generalised single Object type containing the information used by different classes. + * This Data Transfer Object contains all data for a call pertaining metadata, resulting in the possibility to return a larger quantity of information. + * As this is a generalised class, we can use this across the external imports implementations + * + * @author Philip Vissenaekens (philip at atmire dot com) + * */ public class MetadatumDTO { @@ -19,33 +23,68 @@ public class MetadatumDTO { private String qualifier; private String value; + /** + * An empty MetadatumDTO constructor + */ public MetadatumDTO() { } + /** + * Retrieve the schema set to this MetadatumDTO. + * Returns null of no schema is set + * @return schema + */ public String getSchema() { return schema; } + /** + * Set the schema to this MetadatumDTO + * @param schema + */ public void setSchema(String schema) { this.schema = schema; } + /** + * Retrieve the element set to this MetadatumDTO. + * Returns null of no element is set + * @return element + */ public String getElement() { return element; } + /** + * Set the element to this MetadatumDTO + * @param element + */ public void setElement(String element) { this.element = element; } + /** + * Retrieve the qualifier set to this MetadatumDTO. + * Returns null of no qualifier is set + * @return qualifier + */ public String getQualifier() { return qualifier; } + /** + * Set the qualifier to this MetadatumDTO + * @param qualifier + */ public void setQualifier(String qualifier) { this.qualifier = qualifier; } + /** + * Retrieve the value set to this MetadatumDTO. + * Returns null of no value is set + * @return value + */ public String getValue() { return value; } diff --git a/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/contributor/CombinedMetadatumContributor.java b/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/contributor/CombinedMetadatumContributor.java index 8a557a5023..8987115f59 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/contributor/CombinedMetadatumContributor.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/contributor/CombinedMetadatumContributor.java @@ -16,9 +16,8 @@ import java.util.LinkedList; import java.util.List; /** - * Created by Philip Vissenaekens (philip at atmire dot com) - * Date: 17/06/15 - * Time: 11:02 + * Wrapper class used to accommodate for the possibility of correlations between multiple MetadatumContributor objects + * @author Philip Vissenaekens (philip at atmire dot com) */ public class CombinedMetadatumContributor implements MetadataContributor { private MetadataFieldConfig field; @@ -29,15 +28,28 @@ public class CombinedMetadatumContributor implements MetadataContributor { private MetadataFieldMapping> metadataFieldMapping; + /** + * Initialize an empty CombinedMetadatumContributor object + */ public CombinedMetadatumContributor() { } + /** + * + * @param field {@link org.dspace.importer.external.metadatamapping.MetadataFieldConfig} used in mapping + * @param metadatumContributors A list of MetadataContributor + * @param separator A separator used to differentiate between different values + */ public CombinedMetadatumContributor(MetadataFieldConfig field, List metadatumContributors, String separator) { this.field = field; this.metadatumContributors = (LinkedList) metadatumContributors; this.separator = separator; } + /** + * Set the metadatafieldMapping used in the transforming of a record to actual metadata + * @param metadataFieldMapping + */ @Override public void setMetadataFieldMapping(MetadataFieldMapping> metadataFieldMapping) { this.metadataFieldMapping = metadataFieldMapping; @@ -47,18 +59,16 @@ public class CombinedMetadatumContributor implements MetadataContributor { } } - - /** * a separate Metadatum object is created for each index of Metadatum returned from the calls to * MetadatumContributor.contributeMetadata(t) for each MetadatumContributor in the metadatumContributors list. * We assume that each contributor returns the same amount of Metadatum objects * @param t the object we are trying to translate - * @return + * @return a collection of metadata composed by each MetadataContributor */ @Override public Collection contributeMetadata(T t) { - List values=new LinkedList(); + List values=new LinkedList<>(); LinkedList> metadatumLists = new LinkedList<>(); @@ -84,26 +94,50 @@ public class CombinedMetadatumContributor implements MetadataContributor { return values; } + /** + * Return the MetadataFieldConfig used while retrieving MetadatumDTO + * @return MetadataFieldConfig + */ public MetadataFieldConfig getField() { return field; } + /** + * Setting the MetadataFieldConfig + * @param field MetadataFieldConfig used while retrieving MetadatumDTO + */ public void setField(MetadataFieldConfig field) { this.field = field; } + /** + * Return the List of MetadataContributor objects set to this class + * @return metadatumContributors, list of MetadataContributor + */ public LinkedList getMetadatumContributors() { return metadatumContributors; } + /** + * Set the List of MetadataContributor objects set to this class + * @param metadatumContributors A list of MetadatumContributor classes + */ public void setMetadatumContributors(LinkedList metadatumContributors) { this.metadatumContributors = metadatumContributors; } + /** + * Return the separator used to differentiate between distinct values + * @return the separator used to differentiate between distinct values + */ public String getSeparator() { return separator; } + /** + * Set the separator used to differentiate between distinct values + * @param separator + */ public void setSeparator(String separator) { this.separator = separator; } diff --git a/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/contributor/MetadataContributor.java b/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/contributor/MetadataContributor.java index f9dd2a43a6..34e09de96e 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/contributor/MetadataContributor.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/contributor/MetadataContributor.java @@ -13,13 +13,21 @@ import org.dspace.importer.external.metadatamapping.MetadatumDTO; import java.util.Collection; /** - * Created by Roeland Dillen (roeland at atmire dot com) - * Date: 11/01/13 - * Time: 09:18 + * @author Roeland Dillen (roeland at atmire dot com) */ public interface MetadataContributor { + /** + * Set the metadataFieldMapping + * @param rt the MetadataFieldMapping object to set to the MetadataContributor + */ public void setMetadataFieldMapping(MetadataFieldMapping> rt); + /** + * Implementations have the responsibility to process/map their own type of metadata based on a given record + * and return a collection of the generalised MetadatumDTO objects + * @param t The recordType object to retrieve metadata from + * @return A collection of MetadatumDTO objects, retrieve from the recordtype + */ public Collection contributeMetadata(RecordType t); } diff --git a/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/contributor/SimpleXpathMetadatumContributor.java b/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/contributor/SimpleXpathMetadatumContributor.java index ac710026c5..e8d599a0bb 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/contributor/SimpleXpathMetadatumContributor.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/contributor/SimpleXpathMetadatumContributor.java @@ -24,27 +24,42 @@ import java.util.List; import java.util.Map; /** - * Created by Roeland Dillen (roeland at atmire dot com) - * Date: 11/01/13 - * Time: 09:21 + * Metadata contributor that takes an axiom OMElement and turns it into a metadatum + * @author Roeland Dillen (roeland at atmire dot com) */ public class SimpleXpathMetadatumContributor implements MetadataContributor { private MetadataFieldConfig field; + /** + * Return prefixToNamespaceMapping + * @return Map prefixToNamespaceMapping + */ public Map getPrefixToNamespaceMapping() { return prefixToNamespaceMapping; } private MetadataFieldMapping> metadataFieldMapping; + /** + * Return metadataFieldMapping + * @return MetadataFieldMapping> metadataFieldMapping + */ public MetadataFieldMapping> getMetadataFieldMapping() { return metadataFieldMapping; } + /** + * Set the metadataFieldMapping of this SimpleXpathMetadatumContributor + * @param metadataFieldMapping + */ public void setMetadataFieldMapping(MetadataFieldMapping> metadataFieldMapping) { this.metadataFieldMapping = metadataFieldMapping; } + /** + * Set the prefixToNamespaceMapping for this object, + * @param prefixToNamespaceMapping + */ @Resource(name="isiFullprefixMapping") public void setPrefixToNamespaceMapping(Map prefixToNamespaceMapping) { this.prefixToNamespaceMapping = prefixToNamespaceMapping; @@ -52,26 +67,47 @@ public class SimpleXpathMetadatumContributor implements MetadataContributor prefixToNamespaceMapping; + /** + * Initialize SimpleXpathMetadatumContributor with a query, Map(prefixToNamespaceMapping) and MetadataFieldConfig(field) + * @param query String + * @param prefixToNamespaceMapping Map + * @param field MetadataFieldConfig + */ public SimpleXpathMetadatumContributor(String query, Map prefixToNamespaceMapping, MetadataFieldConfig field) { this.query = query; this.prefixToNamespaceMapping = prefixToNamespaceMapping; this.field = field; } + /** + * Empty constructor for SimpleXpathMetadatumContributor + */ public SimpleXpathMetadatumContributor() { } private String query; + /** + * Return the MetadataFieldConfig used while retrieving MetadatumDTO + * @return MetadataFieldConfig + */ public MetadataFieldConfig getField() { return field; } + /** + * Setting the MetadataFieldConfig + * @param field MetadataFieldConfig used while retrieving MetadatumDTO + */ @Required public void setField(MetadataFieldConfig field) { this.field = field; } + /** + * Return query used to create an xpathExpression on, this query is used to + * @return the query this instance is based on + */ public String getQuery() { return query; } @@ -80,9 +116,15 @@ public class SimpleXpathMetadatumContributor implements MetadataContributor contributeMetadata(OMElement t) { - List values=new LinkedList(); + List values=new LinkedList<>(); try { AXIOMXPath xpath=new AXIOMXPath(query); for(String ns:prefixToNamespaceMapping.keySet()){ diff --git a/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/contributor/package-info.java b/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/contributor/package-info.java new file mode 100644 index 0000000000..4be1bd19a6 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/contributor/package-info.java @@ -0,0 +1,16 @@ +/** + * 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/ + */ + +/** + * Contains the classes used to map between retrieved records and actual usable {@link org.dspace.importer.external.metadatamapping.MetadatumDTO} + * Classes are used in the spring config of implementations of {@link org.dspace.importer.external.metadatamapping.AbstractMetadataFieldMapping} + * which query to an element in the retrieved record and map it to a metadatafield. + * @author Roeland Dillen (roeland at atmire dot com) + * @author Jonas Van Goolen (jonas at atmire dot com) + */ +package org.dspace.importer.external.metadatamapping.contributor; \ No newline at end of file diff --git a/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/package-info.java b/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/package-info.java new file mode 100644 index 0000000000..fb077d65fc --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/package-info.java @@ -0,0 +1,14 @@ +/** + * 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/ + */ + +/** + * Main package used for any mapping/processing of retrieved metadata + * @author Roeland Dillen (roeland at atmire dot com) + * @author Jonas Van Goolen (jonas at atmire dot com) + */ +package org.dspace.importer.external.metadatamapping; \ No newline at end of file diff --git a/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/service/GenerateQueryService.java b/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/service/GenerateQueryService.java deleted file mode 100644 index d0e050e062..0000000000 --- a/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/service/GenerateQueryService.java +++ /dev/null @@ -1,22 +0,0 @@ -/** - * 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.importer.external.metadatamapping.service; - -import org.dspace.content.Item; -import org.dspace.importer.external.Query; -import org.dspace.importer.external.MetadataSourceException; - -/** - * Created by Roeland Dillen (roeland at atmire dot com) - * Date: 14/12/12 - * Time: 11:44 - */ -public interface GenerateQueryService { - - public Query generateQueryForItem(Item item) throws MetadataSourceException; -} diff --git a/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/service/MetadataProcessorService.java b/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/service/MetadataProcessorService.java deleted file mode 100644 index 85d54e86da..0000000000 --- a/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/service/MetadataProcessorService.java +++ /dev/null @@ -1,18 +0,0 @@ -/** - * 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.importer.external.metadatamapping.service; - -/** - * User: kevin (kevin at atmire.com) - * Date: 23/10/12 - * Time: 09:49 - */ -public interface MetadataProcessorService { - - public String processMetadataValue(String value); -} diff --git a/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/processor/AuthorMetadataProcessorService.java b/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/transform/AuthorMetadataProcessorService.java similarity index 61% rename from dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/processor/AuthorMetadataProcessorService.java rename to dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/transform/AuthorMetadataProcessorService.java index c25021f3b6..af649a6901 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/processor/AuthorMetadataProcessorService.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/transform/AuthorMetadataProcessorService.java @@ -5,20 +5,22 @@ * * http://www.dspace.org/license/ */ -package org.dspace.importer.external.metadatamapping.processor; +package org.dspace.importer.external.metadatamapping.transform; import org.apache.commons.lang.StringUtils; -import org.dspace.importer.external.metadatamapping.service.MetadataProcessorService; /** - * Removes the last point from an author name, this is required for the SAP lookup + * Removes the last point from an author name. * - * User: kevin (kevin at atmire.com) - * Date: 23/10/12 - * Time: 09:50 + * @author Kevin Van de Velde (kevin at atmire dot com) */ public class AuthorMetadataProcessorService implements MetadataProcessorService { + /** + * Strip a given value of its last dot (.) + * @param value the value to run the processing over + * @return The initial param with its ending dot stripped + */ @Override public String processMetadataValue(String value) { String ret=value; diff --git a/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/transform/GenerateQueryService.java b/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/transform/GenerateQueryService.java new file mode 100644 index 0000000000..42f2422f0f --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/transform/GenerateQueryService.java @@ -0,0 +1,25 @@ +/** + * 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.importer.external.metadatamapping.transform; + +import org.dspace.content.Item; +import org.dspace.importer.external.datamodel.Query; +import org.dspace.importer.external.exception.MetadataSourceException; + +/** + * Represent a service to generate a query based on an item + * + * @author Roeland Dillen (roeland at atmire dot com) + */ +public interface GenerateQueryService { + + /* Create a Query object based on a given item. + * Implementations need to make their own decisions as what to add in or leave out of the query + */ + public Query generateQueryForItem(Item item) throws MetadataSourceException; +} diff --git a/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/transform/MetadataProcessorService.java b/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/transform/MetadataProcessorService.java new file mode 100644 index 0000000000..a8e0251509 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/transform/MetadataProcessorService.java @@ -0,0 +1,21 @@ +/** + * 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.importer.external.metadatamapping.transform; + +/** + * Represents an interface to do processing of metadataValues + * + * @author kevin (kevin at atmire.com) + */ +public interface MetadataProcessorService { + + /* Process a given metadataValue to make them compliant to specific rules. + * Implementations should regulate their own processing as to what is required for a specific cause + */ + public String processMetadataValue(String value); +} diff --git a/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/transform/package-info.java b/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/transform/package-info.java new file mode 100644 index 0000000000..e27ad2317c --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/transform/package-info.java @@ -0,0 +1,13 @@ +/** + * 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/ + */ + +/** + * Transformer classes used by services classes (Such as processing/generating queries, altering results, etc) + * @author Jonas Van Goolen (jonas at atmire dot com) + */ +package org.dspace.importer.external.metadatamapping.transform; \ No newline at end of file diff --git a/dspace-api/src/main/java/org/dspace/importer/external/package-info.java b/dspace-api/src/main/java/org/dspace/importer/external/package-info.java new file mode 100644 index 0000000000..accadc4bf4 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/importer/external/package-info.java @@ -0,0 +1,14 @@ +/** + * 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/ + */ + +/** + * Main package for the live importing from external sources + * @author Roeland Dillen (roeland at atmire dot com) + * @author Jonas Van Goolen (jonas at atmire dot com) + */ +package org.dspace.importer.external; \ No newline at end of file diff --git a/dspace-api/src/main/java/org/dspace/importer/external/pubmed/README.md b/dspace-api/src/main/java/org/dspace/importer/external/pubmed/README.md index 408117421c..1329dee22a 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/pubmed/README.md +++ b/dspace-api/src/main/java/org/dspace/importer/external/pubmed/README.md @@ -16,10 +16,10 @@ I will not go into detail to what exactly is configured for the pubmed integrati # Additional Config # To be able to do the lookup for our configured import-service, we need to be able to know what url to use to check for publications. -This can be done by setting the publication.url property though maven using 2 different ways. +This can be done by setting the `publication-lookup.url` property in `publication-lookup.cfg` to one of two settings. -- Setting the publication.url property to the address as defined in the configured importservice (PubmedImportService in this case) in the file spring-dspace-addon-import-services.xml. This will check this single configured url for publications. -- Setting the publication url property to an askterisk '*'. This will check all configured importServices for their urls to base the search for publications on. +- Setting the `publication-lookup.url` property to the address as defined in the configured importservice (PubmedImportService in this case) in the file `spring-dspace-addon-import-services.xml`. This will check this single configured url for publications. +- Setting the `publication-lookup.url` property to an askterisk '*'. This will check all configured importServices for their urls to base the search for publications on. # Pubmed specific classes Config # @@ -33,4 +33,4 @@ These classes are simply implementations based of the base classes defined in im ## Service classes ## - "GeneratePubmedQueryService". Generates the pubmed query which is used to retrieve the records. This is based on a given item. -- "ImportMetadataSourceServiceImpl". Child class of "AbstractImportMetadataSourceService", retrieving the records from pubmed. \ No newline at end of file +- "PubmedImportMetadataSourceServiceImpl". Child class of "AbstractImportMetadataSourceService", retrieving the records from pubmed. diff --git a/dspace-api/src/main/java/org/dspace/importer/external/pubmed/metadatamapping/PubmedFieldMapping.java b/dspace-api/src/main/java/org/dspace/importer/external/pubmed/metadatamapping/PubmedFieldMapping.java index a387af0229..89d57bbd19 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/pubmed/metadatamapping/PubmedFieldMapping.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/pubmed/metadatamapping/PubmedFieldMapping.java @@ -14,10 +14,18 @@ import javax.annotation.Resource; import java.util.Map; /** - * Created by jonas - jonas@atmire.com on 06/11/15. + * An implementation of {@link AbstractMetadataFieldMapping} + * Responsible for defining the mapping of the Pubmed metadatum fields on the DSpace metadatum fields + * + * @author jonas - (jonas at atmire dot com) */ public class PubmedFieldMapping extends AbstractMetadataFieldMapping { + /** Defines which metadatum is mapped on which metadatum. Note that while the key must be unique it + * only matters here for postprocessing of the value. The mapped MetadatumContributor has full control over + * what metadatafield is generated. + * @param metadataFieldMap The map containing the link between retrieve metadata and metadata that will be set to the item. + */ @Override @Resource (name = "pubmedMetadataFieldMap") public void setMetadataFieldMap(Map metadataFieldMap) { diff --git a/dspace-api/src/main/java/org/dspace/importer/external/pubmed/metadatamapping/PubmedDateMetadatumContributor.java b/dspace-api/src/main/java/org/dspace/importer/external/pubmed/metadatamapping/contributor/PubmedDateMetadatumContributor.java similarity index 57% rename from dspace-api/src/main/java/org/dspace/importer/external/pubmed/metadatamapping/PubmedDateMetadatumContributor.java rename to dspace-api/src/main/java/org/dspace/importer/external/pubmed/metadatamapping/contributor/PubmedDateMetadatumContributor.java index 79459a9e95..ae99f873f7 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/pubmed/metadatamapping/PubmedDateMetadatumContributor.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/pubmed/metadatamapping/contributor/PubmedDateMetadatumContributor.java @@ -6,7 +6,7 @@ * http://www.dspace.org/license/ */ -package org.dspace.importer.external.pubmed.metadatamapping; +package org.dspace.importer.external.pubmed.metadatamapping.contributor; import org.apache.log4j.Logger; import org.dspace.content.DCDate; @@ -24,15 +24,17 @@ import java.util.LinkedList; import java.util.List; /** - * Created by Philip Vissenaekens (philip at atmire dot com) - * Date: 06/07/15 - * Time: 13:48 + * Pubmed specific implementation of {@link MetadataContributor} + * Responsible for generating a set of Date metadata from the retrieved document. + * + * @author Philip Vissenaekens (philip at atmire dot com) */ public class PubmedDateMetadatumContributor implements MetadataContributor { Logger log = Logger.getLogger(PubmedDateMetadatumContributor.class); private MetadataFieldMapping> metadataFieldMapping; + /* A list of all the dateFormats to attempt, these should be configured to have the most specific first and the more lenient at the back */ private List dateFormatsToAttempt; @@ -49,6 +51,10 @@ public class PubmedDateMetadatumContributor implements MetadataContributor private MetadataContributor month; private MetadataContributor year; + /** + * Set the metadatafieldMapping used in the transforming of a record to actual metadata + * @param metadataFieldMapping + */ @Override public void setMetadataFieldMapping(MetadataFieldMapping> metadataFieldMapping) { this.metadataFieldMapping = metadataFieldMapping; @@ -56,10 +62,19 @@ public class PubmedDateMetadatumContributor implements MetadataContributor month.setMetadataFieldMapping(metadataFieldMapping); year.setMetadataFieldMapping(metadataFieldMapping); } - + /** + * Initialize an empty PubmedDateMetadatumContributor object + */ public PubmedDateMetadatumContributor() { } + /** + * + * @param field {@link org.dspace.importer.external.metadatamapping.MetadataFieldConfig} used in mapping + * @param day a MetadataContributor, representing a day + * @param month a {@link MetadataContributor}, representing a month + * @param year a {@link MetadataContributor}, representing a year + */ public PubmedDateMetadatumContributor(MetadataFieldConfig field, MetadataContributor day, MetadataContributor month, MetadataContributor year) { this.field = field; this.day = day; @@ -67,9 +82,16 @@ public class PubmedDateMetadatumContributor implements MetadataContributor this.year = year; } + /** + * Retrieve the metadata associated with the given object. + * The code will loop over the different dates and attempt to format them using the configured dateFormats to attempt. + * For each date, once a format is successful, this result is used. Make sure that dateFormatsToAttempt is configured from most restrictive to most lenient to try and get the most precise result + * @param t A class to retrieve metadata from. + * @return a collection of import records. Only the identifier of the found records may be put in the record. + */ @Override public Collection contributeMetadata(T t) { - List values = new LinkedList(); + List values = new LinkedList<>(); try { @@ -89,18 +111,21 @@ public class PubmedDateMetadatumContributor implements MetadataContributor dateString = yearList.get(i).getValue(); } - - for (String dateFormat : dateFormatsToAttempt) { + int j = 0 ; + // Use the first dcDate that has been formatted (Config should go from most specific to most lenient) + while (j implements MetadataContributor return values; } + /** + * Return the MetadataFieldConfig used while retrieving MetadatumDTO + * @return MetadataFieldConfig + */ public MetadataFieldConfig getField() { return field; } + /** + * Setting the MetadataFieldConfig + * @param field MetadataFieldConfig used while retrieving MetadatumDTO + */ public void setField(MetadataFieldConfig field) { this.field = field; } + /** + * Retrieve the day from the object + * @return {@link MetadataContributor}, representing a day + */ public MetadataContributor getDay() { return day; } + /** + * Set a day ({@link MetadataContributor}) to this object + * @param day a {@link MetadataContributor}, representing a day + */ public void setDay(MetadataContributor day) { this.day = day; } + /** + * Retrieve the month from the object + * @return {@link MetadataContributor}, representing a month + */ public MetadataContributor getMonth() { return month; } + /** + * Set a month ({@link MetadataContributor}) to this object + * @param month a {@link MetadataContributor}, representing a month + */ public void setMonth(MetadataContributor month) { this.month = month; } + /** + * Retrieve the year from the object + * @return {@link MetadataContributor}, representing a year + */ public MetadataContributor getYear() { return year; } + /** + * Set a year ({@link MetadataContributor}) to this object + * @param year a {@link MetadataContributor}, representing a year + */ public void setYear(MetadataContributor year) { this.year = year; } diff --git a/dspace-api/src/main/java/org/dspace/importer/external/pubmed/metadatamapping/PubmedLanguageMetadatumContributor.java b/dspace-api/src/main/java/org/dspace/importer/external/pubmed/metadatamapping/contributor/PubmedLanguageMetadatumContributor.java similarity index 57% rename from dspace-api/src/main/java/org/dspace/importer/external/pubmed/metadatamapping/PubmedLanguageMetadatumContributor.java rename to dspace-api/src/main/java/org/dspace/importer/external/pubmed/metadatamapping/contributor/PubmedLanguageMetadatumContributor.java index cda2456415..99f4b501df 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/pubmed/metadatamapping/PubmedLanguageMetadatumContributor.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/pubmed/metadatamapping/contributor/PubmedLanguageMetadatumContributor.java @@ -6,7 +6,7 @@ * http://www.dspace.org/license/ */ -package org.dspace.importer.external.pubmed.metadatamapping; +package org.dspace.importer.external.pubmed.metadatamapping.contributor; import org.apache.log4j.Logger; import org.dspace.importer.external.metadatamapping.MetadataFieldConfig; import org.dspace.importer.external.metadatamapping.MetadataFieldMapping; @@ -16,9 +16,10 @@ import org.dspace.importer.external.metadatamapping.contributor.MetadataContribu import java.util.*; /** - * Created by Philip Vissenaekens (philip at atmire dot com) - * Date: 07/07/15 - * Time: 15:08 + * Pubmed specific implementation of {@link MetadataContributor} + * Responsible for generating a set of Language metadata from the retrieved document. + * + * @author Philip Vissenaekens (philip at atmire dot com) */ public class PubmedLanguageMetadatumContributor implements MetadataContributor { Logger log = Logger.getLogger(PubmedDateMetadatumContributor.class); @@ -29,25 +30,42 @@ public class PubmedLanguageMetadatumContributor implements MetadataContributo private MetadataFieldConfig field; private MetadataContributor language; + /** + * Initialize PubmedLanguageMetadatumContributor and create the iso3toiso2 mapping used in the transforming of language codes + */ public PubmedLanguageMetadatumContributor() { iso3toIso2=new HashMap<>(); + // Populate the languageMap with the mapping between iso3 and iso2 language codes for (Locale locale : Locale.getAvailableLocales()) { iso3toIso2.put(locale.getISO3Language(),locale.getLanguage()); } } + /** + * Initialize the PubmedLanguageMetadatumContributor class using a {@link org.dspace.importer.external.metadatamapping.MetadataFieldConfig} and a language -{@link org.dspace.importer.external.metadatamapping.contributor.MetadataContributor} + * @param field {@link org.dspace.importer.external.metadatamapping.MetadataFieldConfig} used in mapping + * @param language + */ public PubmedLanguageMetadatumContributor(MetadataFieldConfig field, MetadataContributor language) { this(); this.field = field; this.language = language; } + /** + * Set the metadatafieldMapping used in the transforming of a record to actual metadata + * @param metadataFieldMapping + */ @Override public void setMetadataFieldMapping(MetadataFieldMapping> metadataFieldMapping) { this.metadataFieldMapping = metadataFieldMapping; language.setMetadataFieldMapping(metadataFieldMapping); } + /** + * @param t A class to retrieve metadata from. + * @return a collection of import records. Only the identifier of the found records may be put in the record. + */ @Override public Collection contributeMetadata(T t) { List values=new LinkedList(); @@ -56,7 +74,7 @@ public class PubmedLanguageMetadatumContributor implements MetadataContributo LinkedList languageList = (LinkedList) language.contributeMetadata(t); for (MetadatumDTO metadatum : languageList) { - + // Add the iso2 language code corresponding to the retrieved iso3 code to the metadata values.add(metadataFieldMapping.toDCValue(field, iso3toIso2.get(metadatum.getValue().toLowerCase()))); } } catch (Exception e) { @@ -66,18 +84,34 @@ public class PubmedLanguageMetadatumContributor implements MetadataContributo return values; } + /** + * Return the MetadataContributor used while retrieving MetadatumDTO + * @return MetadataContributor + */ public MetadataContributor getLanguage() { return language; } + /** + * Setting the MetadataContributor + * @param language MetadataContributor used while retrieving MetadatumDTO + */ public void setLanguage(MetadataContributor language) { this.language = language; } + /** + * Return the MetadataFieldConfig used while retrieving MetadatumDTO + * @return MetadataFieldConfig + */ public MetadataFieldConfig getField() { return field; } + /** + * Setting the MetadataFieldConfig + * @param field MetadataFieldConfig used while retrieving MetadatumDTO + */ public void setField(MetadataFieldConfig field) { this.field = field; } diff --git a/dspace-api/src/main/java/org/dspace/importer/external/pubmed/metadatamapping/contributor/package-info.java b/dspace-api/src/main/java/org/dspace/importer/external/pubmed/metadatamapping/contributor/package-info.java new file mode 100644 index 0000000000..9df0032d57 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/importer/external/pubmed/metadatamapping/contributor/package-info.java @@ -0,0 +1,15 @@ +/** + * 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/ + */ + +/** + * Pubmed implementation of specific {@link org.dspace.importer.external.metadatamapping.contributor} classes, + * defining the mapping between the retrieved record and dspace metadata + * @author Roeland Dillen (roeland at atmire dot com) + * @author Jonas Van Goolen (jonas at atmire dot com) + */ +package org.dspace.importer.external.pubmed.metadatamapping.contributor; \ No newline at end of file diff --git a/dspace-api/src/main/java/org/dspace/importer/external/pubmed/metadatamapping/package-info.java b/dspace-api/src/main/java/org/dspace/importer/external/pubmed/metadatamapping/package-info.java new file mode 100644 index 0000000000..ccd2336ef8 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/importer/external/pubmed/metadatamapping/package-info.java @@ -0,0 +1,14 @@ +/** + * 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/ + */ + +/** + * Pubmed implementation of {@link org.dspace.importer.external.metadatamapping.contributor.MetadataContributor}, + * Responsible for generating a set of specific metadata from the retrieved document. + * @author Roeland Dillen (roeland at atmire dot com) + */ +package org.dspace.importer.external.pubmed.metadatamapping; \ No newline at end of file diff --git a/dspace-api/src/main/java/org/dspace/importer/external/pubmed/metadatamapping/service/GeneratePubmedQueryService.java b/dspace-api/src/main/java/org/dspace/importer/external/pubmed/metadatamapping/transform/GeneratePubmedQueryService.java similarity index 58% rename from dspace-api/src/main/java/org/dspace/importer/external/pubmed/metadatamapping/service/GeneratePubmedQueryService.java rename to dspace-api/src/main/java/org/dspace/importer/external/pubmed/metadatamapping/transform/GeneratePubmedQueryService.java index 7ce603912b..c35aa15ab5 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/pubmed/metadatamapping/service/GeneratePubmedQueryService.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/pubmed/metadatamapping/transform/GeneratePubmedQueryService.java @@ -6,26 +6,40 @@ * http://www.dspace.org/license/ */ -package org.dspace.importer.external.pubmed.metadatamapping.service; +package org.dspace.importer.external.pubmed.metadatamapping.transform; 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.importer.external.MetadataSourceException; -import org.dspace.importer.external.Query; -import org.dspace.importer.external.metadatamapping.service.GenerateQueryService; +import org.dspace.importer.external.exception.MetadataSourceException; +import org.dspace.importer.external.datamodel.Query; +import org.dspace.importer.external.metadatamapping.transform.GenerateQueryService; import java.util.List; /** - * Created by jonas - jonas@atmire.com on 06/11/15. + * This class is an implementation of {@link GenerateQueryService} + * Represents a service that generates the pubmed query which is used to retrieve the records. + * This is based on a given item. + * + * @author Jonas - (jonas at atmire dot com) */ public class GeneratePubmedQueryService implements GenerateQueryService { + + + /** + * Create a Query object based on a given item. + * If the item has at least 1 value for dc.identifier.doi, the first one will be used. + * If no DOI is found, the title will be used. + * When no DOI or title is found, an null object is returned instead. + * @param item the Item to create a Query from + */ @Override public Query generateQueryForItem(Item item) throws MetadataSourceException { Query query = new Query(); + // Retrieve an instance of the ItemService to access business calls on an item. ItemService itemService = ContentServiceFactory.getInstance().getItemService(); List doi = itemService.getMetadata(item, "dc", "identifier", "doi", Item.ANY); diff --git a/dspace-api/src/main/java/org/dspace/importer/external/pubmed/metadatamapping/transform/package-info.java b/dspace-api/src/main/java/org/dspace/importer/external/pubmed/metadatamapping/transform/package-info.java new file mode 100644 index 0000000000..33e0b64965 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/importer/external/pubmed/metadatamapping/transform/package-info.java @@ -0,0 +1,13 @@ +/** + * 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/ + */ + +/** + * Pubmed implementation of specific {@link org.dspace.importer.external.metadatamapping.transform} classes + * @author Jonas Van Goolen (jonas at atmire dot com) + */ +package org.dspace.importer.external.pubmed.metadatamapping.transform; \ No newline at end of file diff --git a/dspace-api/src/main/java/org/dspace/importer/external/pubmed/package-info.java b/dspace-api/src/main/java/org/dspace/importer/external/pubmed/package-info.java new file mode 100644 index 0000000000..c600986cc7 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/importer/external/pubmed/package-info.java @@ -0,0 +1,14 @@ +/** + * 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/ + */ + +/** + * Pubmed implementation of {@link org.dspace.importer.external.service.components.MetadataSource} + * Based on metadata support in {@link org.dspace.importer.external.metadatamapping} + * @author Roeland Dillen (roeland at atmire dot com) + */ +package org.dspace.importer.external.pubmed; \ No newline at end of file diff --git a/dspace-api/src/main/java/org/dspace/importer/external/pubmed/service/other/ImportMetadataSourceServiceImpl.java b/dspace-api/src/main/java/org/dspace/importer/external/pubmed/service/PubmedImportMetadataSourceServiceImpl.java similarity index 74% rename from dspace-api/src/main/java/org/dspace/importer/external/pubmed/service/other/ImportMetadataSourceServiceImpl.java rename to dspace-api/src/main/java/org/dspace/importer/external/pubmed/service/PubmedImportMetadataSourceServiceImpl.java index 85e8e2f54f..d99d5aa180 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/pubmed/service/other/ImportMetadataSourceServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/pubmed/service/PubmedImportMetadataSourceServiceImpl.java @@ -6,16 +6,17 @@ * http://www.dspace.org/license/ */ -package org.dspace.importer.external.pubmed.service.other; +package org.dspace.importer.external.pubmed.service; import org.apache.axiom.om.OMElement; import org.apache.axiom.om.OMXMLBuilderFactory; import org.apache.axiom.om.OMXMLParserWrapper; import org.apache.axiom.om.xpath.AXIOMXPath; import org.dspace.content.Item; -import org.dspace.importer.external.MetadataSourceException; -import org.dspace.importer.external.Query; +import org.dspace.importer.external.exception.MetadataSourceException; +import org.dspace.importer.external.datamodel.Query; import org.dspace.importer.external.datamodel.ImportRecord; +import org.dspace.importer.external.service.AbstractImportMetadataSourceService; import org.jaxen.JaxenException; import javax.ws.rs.client.Client; @@ -31,69 +32,135 @@ import java.util.List; import java.util.concurrent.Callable; /** - * Created by jonas - jonas@atmire.com on 06/11/15. + * Implements a data source for querying pubmed central + * + * @author Roeland Dillen (roeland at atmire dot com) */ -public class ImportMetadataSourceServiceImpl extends org.dspace.importer.external.service.AbstractImportMetadataSourceService { +public class PubmedImportMetadataSourceServiceImpl extends AbstractImportMetadataSourceService { private String baseAddress; private WebTarget pubmedWebTarget; - + /** Find the number of records matching a query; + * + * @param query a query string to base the search on. + * @return the sum of the matching records over this import source + * @throws MetadataSourceException + */ @Override public int getNbRecords(String query) throws MetadataSourceException { return retry(new GetNbRecords(query)); } - @Override + /** Find the number of records matching a query; + * + * @param query a query object to base the search on. + * @return the sum of the matching records over this import source + * @throws MetadataSourceException + */ @Override public int getNbRecords(Query query) throws MetadataSourceException { return retry(new GetNbRecords(query)); } + /** Find the number of records matching a string query. Supports pagination + * + * @param query a query string to base the search on. + * @param start offset to start at + * @param count number of records to retrieve. + * @return a set of records. Fully transformed. + * @throws MetadataSourceException + */ @Override public Collection getRecords(String query, int start, int count) throws MetadataSourceException { return retry(new GetRecords(query, start, count)); } + /** Find records based on a object query. + * + * @param query a query object to base the search on. + * @return a set of records. Fully transformed. + * @throws MetadataSourceException + */ @Override - public Collection getRecords(Query q) throws MetadataSourceException { - return retry(new GetRecords(q)); + public Collection getRecords(Query query) throws MetadataSourceException { + return retry(new GetRecords(query)); } + /** Get a single record from the source. + * The first match will be returned + * @param id identifier for the record + * @return a matching record + * @throws MetadataSourceException + */ @Override public ImportRecord getRecord(String id) throws MetadataSourceException { return retry(new GetRecord(id)); } + /** Get a single record from the source. + * The first match will be returned + * @param query a query matching a single record + * @return a matching record + * @throws MetadataSourceException + */ @Override - public ImportRecord getRecord(Query q) throws MetadataSourceException { - return retry(new GetRecord(q)); + public ImportRecord getRecord(Query query) throws MetadataSourceException { + return retry(new GetRecord(query)); } + /** + * The string that identifies this import implementation. Preferable a URI + * @return the identifying uri + */ @Override public String getImportSource() { - return baseAddress; + return "http://eutils.ncbi.nlm.nih.gov/entrez/eutils/"; } + /** Finds records based on an item + * @param item an item to base the search on + * @return a collection of import records. Only the identifier of the found records may be put in the record. + * @throws MetadataSourceException if the underlying methods throw any exception. + */ @Override public Collection findMatchingRecords(Item item) throws MetadataSourceException { return retry(new FindMatchingRecords(item)); } + /** Finds records based on query object. + * Delegates to one or more MetadataSource implementations based on the uri. Results will be aggregated. + * @param query a query object to base the search on. + * @return a collection of import records. Only the identifier of the found records may be put in the record. + * @throws MetadataSourceException + */ @Override - public Collection findMatchingRecords(Query q) throws MetadataSourceException { - return retry(new FindMatchingRecords(q)); + public Collection findMatchingRecords(Query query) throws MetadataSourceException { + return retry(new FindMatchingRecords(query)); } + /** + * Initialize the class + * @throws Exception + */ @Override public void init() throws Exception { Client client = ClientBuilder.newClient(); WebTarget webTarget = client.target(baseAddress); pubmedWebTarget = webTarget.queryParam("db", "pubmed"); } + + /** + * Return the baseAddress set to this object + * @return The String object that represents the baseAddress of this object + */ public String getBaseAddress() { return baseAddress; } + /** + * Set the baseAddress to this object + * @param baseAddress The String object that represents the baseAddress of this object + */ public void setBaseAddress(String baseAddress) { this.baseAddress = baseAddress; } diff --git a/dspace-api/src/main/java/org/dspace/importer/external/pubmed/service/package-info.java b/dspace-api/src/main/java/org/dspace/importer/external/pubmed/service/package-info.java new file mode 100644 index 0000000000..71d6c14f68 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/importer/external/pubmed/service/package-info.java @@ -0,0 +1,13 @@ +/** + * 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/ + */ + +/** + * Pubmed implementation of specific {@link org.dspace.importer.external.service} classes + * @author Jonas Van Goolen (jonas at atmire dot com) + */ +package org.dspace.importer.external.pubmed.service; \ No newline at end of file diff --git a/dspace-api/src/main/java/org/dspace/importer/external/service/AbstractImportMetadataSourceService.java b/dspace-api/src/main/java/org/dspace/importer/external/service/AbstractImportMetadataSourceService.java index 4d7eed933a..ecee6ffc4c 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/service/AbstractImportMetadataSourceService.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/service/AbstractImportMetadataSourceService.java @@ -10,44 +10,68 @@ package org.dspace.importer.external.service; import org.dspace.importer.external.datamodel.ImportRecord; import org.dspace.importer.external.metadatamapping.MetadataFieldMapping; -import org.dspace.importer.external.metadatamapping.MetadatumDTO; import org.dspace.importer.external.metadatamapping.contributor.MetadataContributor; -import org.dspace.importer.external.metadatamapping.service.GenerateQueryService; -import org.dspace.importer.external.service.other.Imports; -import org.dspace.importer.external.service.other.MetadataSource; +import org.dspace.importer.external.service.components.MetadataSource; +import org.dspace.importer.external.service.components.AbstractRemoteMetadataSource; +import org.dspace.importer.external.metadatamapping.transform.GenerateQueryService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Required; import java.util.LinkedList; /** - * Created by: Roeland Dillen (roeland at atmire dot com) - * Date: 29 May 2015 + * This class is a partial implementation of {@link MetadataSource}. It provides assistance with mapping metadata from source format to DSpace format. + * AbstractImportSourceService has a generic type set 'RecordType'. + * In the importer implementation this type set should be the class of the records received from the remote source's response. + * + * @author Roeland Dillen (roeland at atmire dot com) + * */ -public abstract class AbstractImportMetadataSourceService extends MetadataSource implements Imports { +public abstract class AbstractImportMetadataSourceService extends AbstractRemoteMetadataSource implements MetadataSource { private GenerateQueryService generateQueryForItem = null; private MetadataFieldMapping> metadataFieldMapping; + /** + * Retrieve the {@link GenerateQueryService} + * @return A GenerateForQueryService object set to this class + */ public GenerateQueryService getGenerateQueryForItem() { return generateQueryForItem; } - @Autowired + /** + * Set the {@link GenerateQueryService} used to create a {@link org.dspace.importer.external.datamodel.Query} for a DSpace {@link org.dspace.content.Item} + * @param generateQueryForItem + */ + @Autowired public void setGenerateQueryForItem(GenerateQueryService generateQueryForItem) { this.generateQueryForItem = generateQueryForItem; } + /** + * Retrieve the MetadataFieldMapping containing the mapping between RecordType and Metadata + * @return The configured MetadataFieldMapping + */ public MetadataFieldMapping> getMetadataFieldMapping() { return metadataFieldMapping; } + /** + * Sets the MetadataFieldMapping to base the mapping of RecordType and + * @param metadataFieldMapping + */ @Required public void setMetadataFieldMapping( MetadataFieldMapping> metadataFieldMapping) { this.metadataFieldMapping = metadataFieldMapping; } - public ImportRecord transformSourceRecords(RecordType rt){ - return new ImportRecord(new LinkedList(getMetadataFieldMapping().resultToDCValueMapping(rt))); + /** + * Return an ImportRecord constructed from the results in a RecordType + * @param recordType The recordtype to retrieve the DCValueMapping from + * @return An {@link ImportRecord}, This is based on the results retrieved from the recordTypeMapping + */ + public ImportRecord transformSourceRecords(RecordType recordType){ + return new ImportRecord(new LinkedList<>(getMetadataFieldMapping().resultToDCValueMapping(recordType))); } } diff --git a/dspace-api/src/main/java/org/dspace/importer/external/service/ImportService.java b/dspace-api/src/main/java/org/dspace/importer/external/service/ImportService.java index 7dd6e75b0b..8cb6dca95c 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/service/ImportService.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/service/ImportService.java @@ -10,62 +10,86 @@ package org.dspace.importer.external.service; import org.apache.log4j.Logger; import org.dspace.content.Item; -import org.dspace.importer.external.MetadataSourceException; -import org.dspace.importer.external.Query; +import org.dspace.importer.external.exception.MetadataSourceException; +import org.dspace.importer.external.datamodel.Query; import org.dspace.importer.external.datamodel.ImportRecord; -import org.dspace.importer.external.service.other.Destroyable; -import org.dspace.importer.external.service.other.Imports; +import org.dspace.importer.external.service.components.Destroyable; +import org.dspace.importer.external.service.components.MetadataSource; import org.springframework.beans.factory.annotation.Autowired; import java.util.*; -/** - * Created by Roeland Dillen (roeland at atmire dot com) - * Date: 17/09/12 - * Time: 14:19 +/** Main entry point for the import framework. + * Instead of calling the different importer implementations, the ImportService should be called instead. + * This class contains the same methods as the other implementations, but has an extra parameter URL. + * This URL should be the same identifier that is returned by the "getImportSource" method that is defined in the importer implementation you want to use. + * @author Roeland Dillen (roeland at atmire dot com) */ public class ImportService implements Destroyable { - private HashMap importSources = new HashMap(); + private HashMap importSources = new HashMap<>(); Logger log = Logger.getLogger(ImportService.class); + /** + * Constructs an empty ImportService class object + */ public ImportService() { } protected static final String ANY = "*"; + /** + * Sets the importsources that will be used to delegate the retrieving and matching of records to + * @param importSources A list of {@link MetadataSource} to set to this service + * @throws MetadataSourceException + */ @Autowired(required = false) - public void setImportSources(List importSources) throws MetadataSourceException { + public void setImportSources(List importSources) throws MetadataSourceException { log.info("Loading " + importSources.size() + " import sources."); - for (Imports imports : importSources) { - this.importSources.put(imports.getImportSource(), imports); + for (MetadataSource metadataSource : importSources) { + this.importSources.put(metadataSource.getImportSource(), metadataSource); } } - protected Map getImportSources() { + /** + * Retrieve the importSources set to this class. + * @return An unmodifiableMap of importSources + */ + protected Map getImportSources() { return Collections.unmodifiableMap(importSources); } - protected Collection matchingImports(String url) { - if (ANY.equals(url)) { + /** + * Utility method to find what import implementations match the imports uri. + * @param uri the identifier of the import implementation or * for all + * @return matching MetadataSource implementations + */ + protected Collection matchingImports(String uri) { + if (ANY.equals(uri)) { return importSources.values(); } else { - if(importSources.containsKey(url)) - return Collections.singletonList(importSources.get(url)); + if(importSources.containsKey(uri)) + return Collections.singletonList(importSources.get(uri)); else return Collections.emptyList(); } } - - public Collection findMatchingRecords(String url, Item item) throws MetadataSourceException { + /** Finds records based on an item + * Delegates to one or more MetadataSource implementations based on the uri. Results will be aggregated. + * @param uri the identifier of the import implementation or * for all + * @param item an item to base the search on + * @return a collection of import records. Only the identifier of the found records may be put in the record. + * @throws MetadataSourceException if the underlying imports throw any exception. + */ + public Collection findMatchingRecords(String uri, Item item) throws MetadataSourceException { try { List recordList = new LinkedList(); - for (Imports imports : matchingImports(url)) { - recordList.addAll(imports.findMatchingRecords(item)); + for (MetadataSource metadataSource : matchingImports(uri)) { + recordList.addAll(metadataSource.findMatchingRecords(item)); } return recordList; @@ -74,11 +98,18 @@ public class ImportService implements Destroyable { } } - public Collection findMatchingRecords(String url, Query query) throws MetadataSourceException { + /** Finds records based on query object. + * Delegates to one or more MetadataSource implementations based on the uri. Results will be aggregated. + * @param uri the identifier of the import implementation or * for all + * @param query a query object to base the search on. The implementation decides how the query is interpreted. + * @return a collection of import records. Only the identifier of the found records may be put in the record. + * @throws MetadataSourceException + */ + public Collection findMatchingRecords(String uri, Query query) throws MetadataSourceException { try { List recordList = new LinkedList(); - for (Imports imports : matchingImports(url)) { - recordList.addAll(imports.findMatchingRecords(query)); + for (MetadataSource metadataSource : matchingImports(uri)) { + recordList.addAll(metadataSource.findMatchingRecords(query)); } return recordList; @@ -87,11 +118,36 @@ public class ImportService implements Destroyable { } } - public int getNbRecords(String url, String query) throws MetadataSourceException { + /** Find the number of records matching a string query; + * + * @param uri the identifier of the import implementation or * for all + * @param query a query to base the search on + * @return the sum of the matching records over all import sources + * @throws MetadataSourceException + */ + public int getNbRecords(String uri, String query) throws MetadataSourceException { try { int total = 0; - for (Imports Imports : matchingImports(url)) { - total += Imports.getNbRecords(query); + for (MetadataSource MetadataSource : matchingImports(uri)) { + total += MetadataSource.getNbRecords(query); + } + return total; + } catch (Exception e) { + throw new MetadataSourceException(e); + } + } + /** Find the number of records matching a query; + * + * @param uri the identifier of the import implementation or * for all + * @param query a query object to base the search on The implementation decides how the query is interpreted. + * @return the sum of the matching records over all import sources + * @throws MetadataSourceException + */ + public int getNbRecords(String uri, Query query) throws MetadataSourceException { + try { + int total = 0; + for (MetadataSource MetadataSource : matchingImports(uri)) { + total += MetadataSource.getNbRecords(query); } return total; } catch (Exception e) { @@ -99,35 +155,20 @@ public class ImportService implements Destroyable { } } - public int getNbRecords(String url, Query query) throws MetadataSourceException { + /** Find the number of records matching a string query. Supports pagination + * + * @param uri the identifier of the import implementation or * for all + * @param query a query object to base the search on. The implementation decides how the query is interpreted. + * @param start offset to start at + * @param count number of records to retrieve. + * @return a set of records. Fully transformed. + * @throws MetadataSourceException + */ + public Collection getRecords(String uri, String query, int start, int count) throws MetadataSourceException { try { - int total = 0; - for (Imports Imports : matchingImports(url)) { - total += Imports.getNbRecords(query); - } - return total; - } catch (Exception e) { - throw new MetadataSourceException(e); - } - } - - - public Collection getRecords(String url, String query, int start, int count) throws MetadataSourceException { - try { - List recordList = new LinkedList(); - for (Imports imports : matchingImports(url)) { - recordList.addAll(imports.getRecords(query, start, count)); - } - return recordList; - } catch (Exception e) { - throw new MetadataSourceException(e); - } - } - public Collection getRecords(String url, Query query) throws MetadataSourceException { - try { - List recordList = new LinkedList(); - for (Imports imports : matchingImports(url)) { - recordList.addAll(imports.getRecords(query)); + List recordList = new LinkedList<>(); + for (MetadataSource metadataSource : matchingImports(uri)) { + recordList.addAll(metadataSource.getRecords(query, start, count)); } return recordList; } catch (Exception e) { @@ -135,23 +176,54 @@ public class ImportService implements Destroyable { } } - - public ImportRecord getRecord(String url, String id) throws MetadataSourceException { + /** Find the number of records matching a object query. + * + * @param uri the identifier of the import implementation or * for all + * @param query a query object to base the search on. The implementation decides how the query is interpreted. + * @return a set of records. Fully transformed. + * @throws MetadataSourceException + */ + public Collection getRecords(String uri, Query query) throws MetadataSourceException { try { - for (Imports imports : matchingImports(url)) { - if (imports.getRecord(id) != null) return imports.getRecord(id); - - } - return null; - } catch (Exception e) { - throw new MetadataSourceException(e); - } - } - - public ImportRecord getRecord(String url, Query query) throws MetadataSourceException { - try { - for (Imports imports : matchingImports(url)) { - if (imports.getRecord(query) != null) return imports.getRecord(query); + List recordList = new LinkedList<>(); + for (MetadataSource metadataSource : matchingImports(uri)) { + recordList.addAll(metadataSource.getRecords(query)); + } + return recordList; + } catch (Exception e) { + throw new MetadataSourceException(e); + } + } + + /** Get a single record from a source. + * The first match will be returned + * @param uri uri the identifier of the import implementation or * for all + * @param id identifier for the record + * @return a matching record + * @throws MetadataSourceException + */ + public ImportRecord getRecord(String uri, String id) throws MetadataSourceException { + try { + for (MetadataSource metadataSource : matchingImports(uri)) { + if (metadataSource.getRecord(id) != null) return metadataSource.getRecord(id); + + } + return null; + } catch (Exception e) { + throw new MetadataSourceException(e); + } + } + /** Get a single record from the source. + * The first match will be returned + * @param uri uri the identifier of the import implementation or * for all + * @param query a query matching a single record + * @return a matching record + * @throws MetadataSourceException + */ + public ImportRecord getRecord(String uri, Query query) throws MetadataSourceException { + try { + for (MetadataSource metadataSource : matchingImports(uri)) { + if (metadataSource.getRecord(query) != null) return metadataSource.getRecord(query); } return null; @@ -160,15 +232,19 @@ public class ImportService implements Destroyable { } } + /** Retrieve the importUrls that are set on the importSources . + * @return a Collection of string, representing the configured importUrls + */ public Collection getImportUrls() { return importSources.keySet(); } - + /** Call destroy on all {@link Destroyable} {@link MetadataSource} objects set in this ImportService + */ @Override public void destroy() throws Exception { - for (Imports imports : importSources.values()) { - if (imports instanceof Destroyable) ((Destroyable) imports).destroy(); + for (MetadataSource metadataSource : importSources.values()) { + if (metadataSource instanceof Destroyable) ((Destroyable) metadataSource).destroy(); } } } diff --git a/dspace-api/src/main/java/org/dspace/importer/external/service/other/MetadataSource.java b/dspace-api/src/main/java/org/dspace/importer/external/service/components/AbstractRemoteMetadataSource.java similarity index 53% rename from dspace-api/src/main/java/org/dspace/importer/external/service/other/MetadataSource.java rename to dspace-api/src/main/java/org/dspace/importer/external/service/components/AbstractRemoteMetadataSource.java index cbf0512737..5a35389810 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/service/other/MetadataSource.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/service/components/AbstractRemoteMetadataSource.java @@ -6,11 +6,11 @@ * http://www.dspace.org/license/ */ -package org.dspace.importer.external.service.other; +package org.dspace.importer.external.service.components; import org.apache.log4j.Logger; -import org.dspace.importer.external.MetadataSourceException; -import org.dspace.importer.external.SourceExceptionHandler; +import org.dspace.importer.external.exception.MetadataSourceException; +import org.dspace.importer.external.exception.SourceExceptionHandler; import javax.annotation.Resource; import java.util.LinkedHashMap; @@ -21,10 +21,14 @@ import java.util.concurrent.Callable; import java.util.concurrent.locks.ReentrantLock; /** - * Created by: Antoine Snyers (antoine at atmire dot com) - * Date: 27 Oct 2014 + * This class contains primitives to handle request timeouts and to retry requests. + * This is achieved by classifying exceptions as fatal or as non fatal/retryable. + * Evidently only subclasses can make the proper determination of what is retryable and what isn't. + * This is useful in case the service employs throttling and to deal with general network issues. + * @author Roeland Dillen (roeland at atmire dot com) + * @author Antoine Snyers (antoine at atmire dot com) */ -public abstract class MetadataSource { +public abstract class AbstractRemoteMetadataSource { protected long lastRequest = 0; protected long interRequestTime; @@ -39,45 +43,82 @@ public abstract class MetadataSource { protected Map> exceptionHandlersMap; protected Exception error; - - protected MetadataSource() { + /** + * Constructs an empty MetadataSource class object and initializes the Exceptionhandlers + */ + protected AbstractRemoteMetadataSource() { initExceptionHandlers(); } + /** + * initialize the exceptionHandlersMap with an empty {@link java.util.LinkedHashMap} + */ protected void initExceptionHandlers() { - exceptionHandlersMap = new LinkedHashMap>(); + exceptionHandlersMap = new LinkedHashMap<>(); // if an exception is thrown that is not in there, it is not recoverable and the retry chain will stop // by default all exceptions are fatal, but subclasses can add their own handlers for their own exceptions } + /** + * Return the warning message used for logging during exception catching + * @return a "warning" String + */ public String getWarning() { return warning; } + /** + * Set the warning message used for logging + * @param warning + */ public void setWarning(String warning) { this.warning = warning; } + /** + * Return the number of retries that have currently been undertaken + * @return the number of retries + */ public int getRetry() { return retry; } - + /** + * Return the number of max retries that can be undertaken before separate functionality kicks in + * @return the number of maximum retries + */ public int getMaxRetry() { return maxRetry; } + + /** + * Set the number of maximum retries before throwing on the exception + * @param maxRetry + */ @Resource(name="maxRetry") public void setMaxRetry(int maxRetry) { this.maxRetry = maxRetry; } + /** + * Retrieve the operationId + * @return A randomly generated UUID. generated during the retry method + */ public String getOperationId() { return operationId; } + /** + * Retrieve the last encountered exception + * @return An Exception object, the last one encountered in the retry method + */ public Exception getError() { return error; } + /** + * Set the last encountered error + * @param error + */ public void setError(Exception error) { this.error = error; } @@ -85,7 +126,7 @@ public abstract class MetadataSource { /** * log4j logger */ - private static Logger log = Logger.getLogger(MetadataSource.class); + private static Logger log = Logger.getLogger(AbstractRemoteMetadataSource.class); /** * Command pattern implementation. the callable.call method will be retried @@ -96,7 +137,7 @@ public abstract class MetadataSource { * the public methods of this class. * @param return type. Generics for type safety. * @return The result of the call - * @throws com.atmire.import_citations.configuration.SourceException if something unrecoverable happens (e.g. network failures) + * @throws org.dspace.importer.external.exception.MetadataSourceException if something unrecoverable happens (e.g. network failures) */ protected T retry(Callable callable) throws MetadataSourceException { @@ -144,34 +185,53 @@ public abstract class MetadataSource { } - protected void handleException(int retry, Exception e, String operationId) throws MetadataSourceException { + /** + * Handles a given exception or throws on a {@link org.dspace.importer.external.exception.MetadataSourceException} if no ExceptionHandler is set + * @param retry The number of retries before the exception was thrown on + * @param exception The exception to handle + * @param operationId The id of the operation that threw the exception + * @throws MetadataSourceException if no ExceptionHandler is configured for the given exception + */ + protected void handleException(int retry, Exception exception, String operationId) throws MetadataSourceException { - List exceptionHandlers = getExceptionHandler(e); + List exceptionHandlers = getExceptionHandler(exception); if (exceptionHandlers != null && !exceptionHandlers.isEmpty()) { for (SourceExceptionHandler exceptionHandler : exceptionHandlers) { exceptionHandler.handle(this); } }else{ - throwSourceException(retry, e, operationId); + throwSourceException(retry, exception, operationId); } } - protected List getExceptionHandler(Exception e) { + /** Retrieve a list of SourceExceptionHandler objects that have an instanceof the exception configured to them. + * @param exception The exception to base the retrieval of {@link org.dspace.importer.external.exception.SourceExceptionHandler} on + * @return a list of {@link org.dspace.importer.external.exception.SourceExceptionHandler} objects + */ + protected List getExceptionHandler(Exception exception) { for (Class aClass : exceptionHandlersMap.keySet()) { - if (aClass.isInstance(e)) { + if (aClass.isInstance(exception)) { return exceptionHandlersMap.get(aClass); } } return null; } - protected void throwSourceException(int retry, Exception e, String operationId) throws MetadataSourceException { + /** Throw a {@link MetadataSourceException} + * @param retry The number of retries before the exception was thrown on + * @param exception The exception to throw + * @param operationId The id of the operation that threw the exception + * @throws MetadataSourceException + */ + protected void throwSourceException(int retry, Exception exception, String operationId) throws MetadataSourceException { throwSourceExceptionHook(); -// log.error("Source exception", e); - log.error("Source exception " + e.getMessage()); - throw new MetadataSourceException("At retry of operation " + operationId + " " + retry, e); + log.error("Source exception " + exception.getMessage(),exception); + throw new MetadataSourceException("At retry of operation " + operationId + " " + retry, exception); } + /** + * A specified point where methods can be specified or callbacks can be executed + */ protected void throwSourceExceptionHook() { } @@ -179,7 +239,7 @@ public abstract class MetadataSource { /** * Attempts to init a session * - * @throws Exception if error + * @throws Exception */ public abstract void init() throws Exception; diff --git a/dspace-api/src/main/java/org/dspace/importer/external/service/other/Destroyable.java b/dspace-api/src/main/java/org/dspace/importer/external/service/components/Destroyable.java similarity index 62% rename from dspace-api/src/main/java/org/dspace/importer/external/service/other/Destroyable.java rename to dspace-api/src/main/java/org/dspace/importer/external/service/components/Destroyable.java index b754a37557..5bb54f8ff0 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/service/other/Destroyable.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/service/components/Destroyable.java @@ -6,13 +6,16 @@ * http://www.dspace.org/license/ */ -package org.dspace.importer.external.service.other; +package org.dspace.importer.external.service.components; /** - * Created by Roeland Dillen (roeland at atmire dot com) - * Date: 26/09/12 - * Time: 11:09 + * @author Roeland Dillen (roeland at atmire dot com) */ public interface Destroyable { + + /** + * Destroy the object + * @throws Exception + */ public void destroy() throws Exception; } diff --git a/dspace-api/src/main/java/org/dspace/importer/external/service/components/MetadataSource.java b/dspace-api/src/main/java/org/dspace/importer/external/service/components/MetadataSource.java new file mode 100644 index 0000000000..eae04dbe75 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/importer/external/service/components/MetadataSource.java @@ -0,0 +1,92 @@ +/** + * 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.importer.external.service.components; + +import org.dspace.content.Item; +import org.dspace.importer.external.exception.MetadataSourceException; +import org.dspace.importer.external.datamodel.Query; +import org.dspace.importer.external.datamodel.ImportRecord; + +import java.util.Collection; + +/** Common interface for all import implementations. + * @author Roeland Dillen (roeland at atmire dot com) + */ +public interface MetadataSource { + /** + * Gets the number of records matching a query + * @param query the query in string format + * @return the number of records matching the query + * @throws MetadataSourceException + */ + public int getNbRecords(String query) throws MetadataSourceException; + /** + * Gets the number of records matching a query + * @param query the query object + * @return the number of records matching the query + * @throws MetadataSourceException + */ + public int getNbRecords(Query query) throws MetadataSourceException; + + /** + * Gets a set of records matching a query. Supports pagination + * @param query the query. The query will generally be posted 'as is' to the source + * @param start offset + * @param count page size + * @return a collection of fully transformed id's + * @throws MetadataSourceException + */ + public Collection getRecords(String query, int start, int count)throws MetadataSourceException; + + /** Find records based on a object query. + * + * @param query a query object to base the search on. + * @return a set of records. Fully transformed. + * @throws MetadataSourceException + */ + public Collection getRecords(Query query)throws MetadataSourceException; + + /** Get a single record from the source. + * The first match will be returned + * @param id identifier for the record + * @return a matching record + * @throws MetadataSourceException + */ + public ImportRecord getRecord(String id)throws MetadataSourceException; + + /** Get a single record from the source. + * The first match will be returned + * @param query a query matching a single record + * @return a matching record + * @throws MetadataSourceException + */ + public ImportRecord getRecord(Query query)throws MetadataSourceException; + + /** + * The string that identifies this import implementation. Preferable a URI + * @return the identifying uri + */ + public String getImportSource(); + + /** Finds records based on an item + * Delegates to one or more MetadataSource implementations based on the uri. Results will be aggregated. + * @param item an item to base the search on + * @return a collection of import records. Only the identifier of the found records may be put in the record. + * @throws MetadataSourceException if the underlying imports throw any exception. + */ + public Collection findMatchingRecords(Item item) throws MetadataSourceException; + + /** Finds records based on query object. + * Delegates to one or more MetadataSource implementations based on the uri. Results will be aggregated. + * @param query a query object to base the search on. + * @return a collection of import records. Only the identifier of the found records may be put in the record. + * @throws MetadataSourceException + */ + public Collection findMatchingRecords(Query query) throws MetadataSourceException; +} diff --git a/dspace-api/src/main/java/org/dspace/importer/external/service/components/package-info.java b/dspace-api/src/main/java/org/dspace/importer/external/service/components/package-info.java new file mode 100644 index 0000000000..f36c6cb29e --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/importer/external/service/components/package-info.java @@ -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/ + */ +/** + * Service components that are aggregated/used in the {@link org.dspace.importer.external.service.AbstractImportMetadataSourceService} and {@link org.dspace.importer.external.service.ImportService} + * @author Roeland Dillen (roeland at atmire dot com) + */ +package org.dspace.importer.external.service.components; \ No newline at end of file diff --git a/dspace-api/src/main/java/org/dspace/importer/external/service/other/Imports.java b/dspace-api/src/main/java/org/dspace/importer/external/service/other/Imports.java deleted file mode 100644 index 84ee5bbbd2..0000000000 --- a/dspace-api/src/main/java/org/dspace/importer/external/service/other/Imports.java +++ /dev/null @@ -1,35 +0,0 @@ -/** - * 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.importer.external.service.other; - -import org.dspace.content.Item; -import org.dspace.importer.external.MetadataSourceException; -import org.dspace.importer.external.Query; -import org.dspace.importer.external.datamodel.ImportRecord; - -import java.util.Collection; - -/** - * Created by Roeland Dillen (roeland at atmire dot com) - * Date: 17/09/12 - * Time: 14:08 - */ -public interface Imports { - public int getNbRecords(String query) throws MetadataSourceException; - public int getNbRecords(Query query) throws MetadataSourceException; - public Collection getRecords(String query, int start, int count)throws MetadataSourceException; - public Collection getRecords(Query q)throws MetadataSourceException; - public ImportRecord getRecord(String id)throws MetadataSourceException; - public ImportRecord getRecord(Query q)throws MetadataSourceException; - public String getImportSource(); - - public Collection findMatchingRecords(Item item) throws MetadataSourceException; - - public Collection findMatchingRecords(Query q) throws MetadataSourceException; -} diff --git a/dspace-api/src/main/java/org/dspace/importer/external/service/package-info.java b/dspace-api/src/main/java/org/dspace/importer/external/service/package-info.java new file mode 100644 index 0000000000..57ae9e0106 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/importer/external/service/package-info.java @@ -0,0 +1,13 @@ +/** + * 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/ + */ + +/** + * Main import framework services. + * @author Roeland Dillen (roeland at atmire dot com) + */ +package org.dspace.importer.external.service; \ No newline at end of file diff --git a/dspace-api/src/main/java/org/dspace/rdf/RDFizer.java b/dspace-api/src/main/java/org/dspace/rdf/RDFizer.java index 6e5d8f55ac..7fa57e7ce7 100644 --- a/dspace-api/src/main/java/org/dspace/rdf/RDFizer.java +++ b/dspace-api/src/main/java/org/dspace/rdf/RDFizer.java @@ -118,7 +118,7 @@ public class RDFizer { /** * Returns whether all converted data is printed to stdout. Turtle will be * used as serialization. - * @return + * @return {@code true} if print all generated data is to be printed to stdout */ public boolean isStdout() { return stdout; @@ -137,7 +137,7 @@ public class RDFizer { /** * Returns whether verbose information is printed to System.err. Probably * this is helpful for CLI only. - * @return + * @return {@code true} if verbose mode is on */ public boolean isVerbose() { return verbose; @@ -154,7 +154,7 @@ public class RDFizer { /** * Returns whether this is a dry run. Probably this is helpful for CLI only. - * @return + * @return {@code true} if dry-run mode is on */ public boolean isDryrun() { return dryrun; @@ -214,7 +214,7 @@ public class RDFizer { System.err.println("Cannot determine RDF URI for " + contentServiceFactory.getDSpaceObjectService(dso).getTypeText(dso) + " " + dso.getID() + "(handle " + dso.getHandle() + ")" + ", skipping. Please " - + "delete it specifing the RDF URI."); + + "delete it specifying the RDF URI."); log.error("Cannot detgermine RDF URI for " + contentServiceFactory.getDSpaceObjectService(dso).getTypeText(dso) + " " + dso.getID() + "(handle " + dso.getHandle() + ")" + ", skipping deletion."); @@ -417,7 +417,7 @@ public class RDFizer { } } -// Currently Bundles and Bitsreams aren't supported as independent entities. +// Currently Bundles and Bitstreams aren't supported as independent entities. // They should be converted as part of an item. So we do not need to make // the recursive call for them. An item itself will be converted as part // of the callback call below. diff --git a/dspace-api/src/main/java/org/dspace/rdf/conversion/DMRM.java b/dspace-api/src/main/java/org/dspace/rdf/conversion/DMRM.java index b785f28197..b953976f29 100644 --- a/dspace-api/src/main/java/org/dspace/rdf/conversion/DMRM.java +++ b/dspace-api/src/main/java/org/dspace/rdf/conversion/DMRM.java @@ -16,7 +16,7 @@ import com.hp.hpl.jena.rdf.model.Resource; /** * Schema for DSpace Metadata RDF Mappings. * @author Pascal-Nicolas Becker (dspace -at- pascal -hyphen- becker -dot- de) - * @see http://digital-repositories.org/ontologies/dspace-metadata-mapping/0.2.0 + * @see http://digital-repositories.org/ontologies/dspace-metadata-mapping/0.2.0 */ public class DMRM { /**

    The RDF model that holds the vocabulary terms

    */ diff --git a/dspace-api/src/main/java/org/dspace/rdf/conversion/SimpleDSORelationsConverterPlugin.java b/dspace-api/src/main/java/org/dspace/rdf/conversion/SimpleDSORelationsConverterPlugin.java index a75121ef71..83c9d91cbe 100644 --- a/dspace-api/src/main/java/org/dspace/rdf/conversion/SimpleDSORelationsConverterPlugin.java +++ b/dspace-api/src/main/java/org/dspace/rdf/conversion/SimpleDSORelationsConverterPlugin.java @@ -377,7 +377,7 @@ implements ConverterPlugin } // add all parents - for (DSpaceObject parent : collection.getCommunities()) + for (DSpaceObject parent : communityService.getAllParents(context, collection)) { if (!RDFUtil.isPublicBoolean(context, parent)) { diff --git a/dspace-api/src/main/java/org/dspace/rdf/negotiation/Negotiator.java b/dspace-api/src/main/java/org/dspace/rdf/negotiation/Negotiator.java index fd8d28b69d..488577a376 100644 --- a/dspace-api/src/main/java/org/dspace/rdf/negotiation/Negotiator.java +++ b/dspace-api/src/main/java/org/dspace/rdf/negotiation/Negotiator.java @@ -170,7 +170,6 @@ public class Negotiator { * equals! Caution should be exercised when using it to order a sorted set * or a sorted map. Take a look at the java.util.Comparator for further * information.

    - * @param mediaRangeRegex * @return A comparator that imposes orderings that are inconsistent with equals! */ public static Comparator getMediaRangeComparator() { diff --git a/dspace-api/src/main/java/org/dspace/rdf/storage/RDFStorage.java b/dspace-api/src/main/java/org/dspace/rdf/storage/RDFStorage.java index ca2262a998..0e18a2fcec 100644 --- a/dspace-api/src/main/java/org/dspace/rdf/storage/RDFStorage.java +++ b/dspace-api/src/main/java/org/dspace/rdf/storage/RDFStorage.java @@ -18,21 +18,21 @@ import java.util.List; public interface RDFStorage { /** * Don't use this method directly, use - * {@link org.dspace.rdf.RDFizer#convert(org.dspace.core.Context, - * org.dspace.content.DSpaceObject) RDFizer.convert(...)} to convert and store DSpaceObjets. + * {@link org.dspace.rdf.RDFUtil#convert(org.dspace.core.Context, org.dspace.content.DSpaceObject) RDFizer.convert(...)} + * to convert and store DSpaceObjets. * @param uri Identifier for this DSO - * ({@link org.dspace.rdf.RDFizer#generateIdentifier(org.dspace.core.Context, - * org.dspace.content.DSpaceObject) RDFizer.generateIdentifier(...)}). You can load this model by using this URI. + * ({@link org.dspace.rdf.RDFUtil#generateIdentifier(org.dspace.core.Context, org.dspace.content.DSpaceObject) RDFizer.generateIdentifier(...)}). + * You can load this model by using this URI. * @param model The model to store. - * @see org.dspace.rdf.RDFizer; + * @see org.dspace.rdf.RDFizer#RDFizer */ public void store(String uri, Model model); /** * Don't use this method directly, use - * {@link org.dspace.rdf.RDFizer#loadModel(String) RDFizer.loadModel(...)} instead. + * {@link org.dspace.rdf.RDFUtil#loadModel(String) RDFizer.loadModel(...)} instead. * @param uri - * @return + * @return the model */ public Model load(String uri); diff --git a/dspace-api/src/main/java/org/dspace/rdf/storage/URIGenerator.java b/dspace-api/src/main/java/org/dspace/rdf/storage/URIGenerator.java index 2336f4e442..d659ade4af 100644 --- a/dspace-api/src/main/java/org/dspace/rdf/storage/URIGenerator.java +++ b/dspace-api/src/main/java/org/dspace/rdf/storage/URIGenerator.java @@ -23,12 +23,12 @@ import org.dspace.core.Context; * type SITE, COMMUNITY, COLLECTION or ITEM only. Currently dspace-rdf * doesn't support Bundles or Bitstreams as independent entity. * - * @class{org.dspace.rdf.RDFizer} uses a URIGenerator to generate URIs to + * {@link org.dspace.rdf.RDFizer#RDFizer} uses a URIGenerator to generate URIs to * Identify DSpaceObjects in RDF. You can configure which URIGenerator should be * used. See DSpace documentation on how to configure RDFizer. * @author Pascal-Nicolas Becker (dspace -at- pascal -hyphen- becker -dot- de) - * @see org.dspace.rdf.RDFizer - * @see org.dspace.rdf.RDFUtil + * @see org.dspace.rdf.RDFizer#RDFizer + * @see org.dspace.rdf.RDFUtil#RDFUtil */ public interface URIGenerator { @@ -39,7 +39,10 @@ public interface URIGenerator { * doesn't support Bundles or Bitstreams as independent entity. This method * should work even if the DSpaceObject does not exist anymore. * @param context - * @param dso + * @param type + * @param id + * @param handle + * @param identifiers * @return May return null, if no URI could be generated. * @see org.dspace.rdf.RDFUtil#generateIdentifier(Context, DSpaceObject) */ @@ -47,8 +50,7 @@ public interface URIGenerator { throws SQLException; /** - * Shortcut for {@code generateIdentifier(context, dso.getType(), - * dso.getID(), dso.getHandle())}. + * Shortcut for {@code generateIdentifier(context, dso.getType(), dso.getID(), dso.getHandle())}. * * @param context * @param dso diff --git a/dspace-api/src/main/java/org/dspace/statistics/ElasticSearchLoggerEventListener.java b/dspace-api/src/main/java/org/dspace/statistics/ElasticSearchLoggerEventListener.java index 293deb8a47..aa1afc81d9 100644 --- a/dspace-api/src/main/java/org/dspace/statistics/ElasticSearchLoggerEventListener.java +++ b/dspace-api/src/main/java/org/dspace/statistics/ElasticSearchLoggerEventListener.java @@ -16,6 +16,10 @@ import org.dspace.usage.AbstractUsageEventListener; import org.dspace.usage.UsageEvent; import org.springframework.beans.factory.annotation.Autowired; +/* + * @deprecated As of DSpace 6.0, ElasticSearch statistics are replaced by Solr statistics + * @see org.dspace.statistics.service.SolrLoggerUsageEventListener#SolrLoggerUsageEventListener + */ public class ElasticSearchLoggerEventListener extends AbstractUsageEventListener { private static Logger log = Logger.getLogger(ElasticSearchLoggerEventListener.class); diff --git a/dspace-api/src/main/java/org/dspace/statistics/ElasticSearchLoggerServiceImpl.java b/dspace-api/src/main/java/org/dspace/statistics/ElasticSearchLoggerServiceImpl.java index 625b198318..37f8c0dc97 100644 --- a/dspace-api/src/main/java/org/dspace/statistics/ElasticSearchLoggerServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/statistics/ElasticSearchLoggerServiceImpl.java @@ -51,6 +51,10 @@ import java.net.URL; import java.sql.SQLException; import java.util.*; +/* + * @deprecated As of DSpace 6.0, ElasticSearch statistics are replaced by Solr statistics + * @see org.dspace.statistics.SolrLoggerServiceImpl#SolrLoggerServiceImpl + */ public class ElasticSearchLoggerServiceImpl implements ElasticSearchLoggerService, InitializingBean { private static Logger log = Logger.getLogger(ElasticSearchLoggerServiceImpl.class); diff --git a/dspace-api/src/main/java/org/dspace/statistics/service/ElasticSearchLoggerService.java b/dspace-api/src/main/java/org/dspace/statistics/service/ElasticSearchLoggerService.java index 6814634bcc..9e851cfeb8 100644 --- a/dspace-api/src/main/java/org/dspace/statistics/service/ElasticSearchLoggerService.java +++ b/dspace-api/src/main/java/org/dspace/statistics/service/ElasticSearchLoggerService.java @@ -21,6 +21,9 @@ import java.util.HashMap; /** * Service interface class for the Elastic Search logging. * The implementation of this class is responsible for all business logic calls for the Elastic Search logging and is autowired by spring + * + * @deprecated As of DSpace 6.0, ElasticSearch statistics are replaced by Solr statistics + * @see org.dspace.statistics.service.SolrLoggerService#SolrLoggerService * * @author kevinvandevelde at atmire.com */ diff --git a/dspace-api/src/main/java/org/dspace/statistics/util/SpiderDetector.java b/dspace-api/src/main/java/org/dspace/statistics/util/SpiderDetector.java index 460871e385..e508d03618 100644 --- a/dspace-api/src/main/java/org/dspace/statistics/util/SpiderDetector.java +++ b/dspace-api/src/main/java/org/dspace/statistics/util/SpiderDetector.java @@ -90,7 +90,7 @@ public class SpiderDetector { /** * Get an immutable Set representing all the Spider Addresses here * - * @return + * @return a set of IP addresses as strings */ public static Set getSpiderIpAddresses() { diff --git a/dspace-api/src/main/java/org/dspace/storage/bitstore/BitStoreService.java b/dspace-api/src/main/java/org/dspace/storage/bitstore/BitStoreService.java index 8113e980c4..bdcc622fe6 100644 --- a/dspace-api/src/main/java/org/dspace/storage/bitstore/BitStoreService.java +++ b/dspace-api/src/main/java/org/dspace/storage/bitstore/BitStoreService.java @@ -21,20 +21,20 @@ import java.util.Map; public interface BitStoreService { - /** + /** * Initialize the asset store * */ public void init() throws IOException; - /** + /** * Return an identifier unique to this asset store instance * * @return a unique ID */ public String generateId(); - /** + /** * Retrieve the bits for bitstream * * @param bitstream @@ -56,13 +56,11 @@ public interface BitStoreService *

    * * @param bitstream - * The bitsream object + * The bitstream object * @param inputStream * The stream of bits * @exception java.io.IOException * If a problem occurs while storing the bits - * - * @return Map containing technical metadata (size, checksum, etc) */ public void put(Bitstream bitstream, InputStream inputStream) throws IOException; diff --git a/dspace-api/src/main/java/org/dspace/storage/bitstore/DSBitStoreService.java b/dspace-api/src/main/java/org/dspace/storage/bitstore/DSBitStoreService.java index 78336ff1e0..380b476e23 100644 --- a/dspace-api/src/main/java/org/dspace/storage/bitstore/DSBitStoreService.java +++ b/dspace-api/src/main/java/org/dspace/storage/bitstore/DSBitStoreService.java @@ -108,8 +108,6 @@ public class DSBitStoreService implements BitStoreService * The stream of bits to store * @exception java.io.IOException * If a problem occurs while storing the bits - * - * @return Map containing technical metadata (size, checksum, etc) */ public void put(Bitstream bitstream, InputStream in) throws IOException { diff --git a/dspace-api/src/main/java/org/dspace/storage/bitstore/S3BitStoreService.java b/dspace-api/src/main/java/org/dspace/storage/bitstore/S3BitStoreService.java index f445296741..fb3a5756c5 100644 --- a/dspace-api/src/main/java/org/dspace/storage/bitstore/S3BitStoreService.java +++ b/dspace-api/src/main/java/org/dspace/storage/bitstore/S3BitStoreService.java @@ -160,8 +160,6 @@ public class S3BitStoreService implements BitStoreService * The stream of bits to store * @exception java.io.IOException * If a problem occurs while storing the bits - * - * @return Map containing technical metadata (size, checksum, etc) */ public void put(Bitstream bitstream, InputStream in) throws IOException { @@ -260,7 +258,7 @@ public class S3BitStoreService implements BitStoreService /** * Utility Method: Prefix the key with a subfolder, if this instance assets are stored within subfolder * @param id - * @return + * @return full key prefixed with a subfolder, if applicable */ public String getFullKey(String id) { if(StringUtils.isNotEmpty(subfolder)) { diff --git a/dspace-api/src/main/java/org/dspace/storage/rdbms/DatabaseRegistryUpdater.java b/dspace-api/src/main/java/org/dspace/storage/rdbms/DatabaseRegistryUpdater.java index 39e069de89..6e983d5829 100644 --- a/dspace-api/src/main/java/org/dspace/storage/rdbms/DatabaseRegistryUpdater.java +++ b/dspace-api/src/main/java/org/dspace/storage/rdbms/DatabaseRegistryUpdater.java @@ -140,16 +140,6 @@ public class DatabaseRegistryUpdater implements FlywayCallback } - @Override - public void beforeInit(Connection connection) { - - } - - @Override - public void afterInit(Connection connection) { - - } - @Override public void beforeBaseline(Connection connection) { diff --git a/dspace-api/src/main/java/org/dspace/storage/rdbms/DatabaseUtils.java b/dspace-api/src/main/java/org/dspace/storage/rdbms/DatabaseUtils.java index 4c279b1765..3811c8bd28 100644 --- a/dspace-api/src/main/java/org/dspace/storage/rdbms/DatabaseUtils.java +++ b/dspace-api/src/main/java/org/dspace/storage/rdbms/DatabaseUtils.java @@ -80,13 +80,11 @@ public class DatabaseUtils */ public static void main(String[] argv) { - ConfigurationService config = DSpaceServicesFactory.getInstance().getConfigurationService(); - // Usage checks if (argv.length < 1) { System.out.println("\nDatabase action argument is missing."); - System.out.println("Valid actions: 'test', 'info', 'migrate', 'repair' or 'clean'"); + System.out.println("Valid actions: 'test', 'info', 'migrate', 'repair', 'validate' or 'clean'"); System.out.println("\nOr, type 'database help' for more information.\n"); System.exit(1); } @@ -106,15 +104,19 @@ public class DatabaseUtils System.out.println("\nAttempting to connect to database"); try(Connection connection = dataSource.getConnection()) { - // Just do a high level test by getting our configured DataSource and attempting to connect to it - DatabaseMetaData meta = connection.getMetaData(); System.out.println("Connected successfully!"); - System.out.println("Database Software: " + meta.getDatabaseProductName() + " version " + meta.getDatabaseProductVersion()); - System.out.println(" - URL: " + meta.getURL()); - System.out.println(" - Driver: " + meta.getDriverName() + " version " + meta.getDriverVersion()); - System.out.println(" - Username: " + meta.getUserName()); - System.out.println(" - Password: [hidden]"); - System.out.println(" - Schema: " + getSchemaName(connection)); + + // Print basic database connection information + printDBInfo(connection); + + // Print any database warnings/errors found (if any) + boolean issueFound = printDBIssues(connection); + + // If issues found, exit with an error status (even if connection succeeded). + if(issueFound) + System.exit(1); + else + System.exit(0); } catch (SQLException sqle) { @@ -129,23 +131,8 @@ public class DatabaseUtils { try(Connection connection = dataSource.getConnection()) { - // Get basic Database info - DatabaseMetaData meta = connection.getMetaData(); - String dbType = getDbType(connection); - System.out.println("\nDatabase Type: " + dbType); - System.out.println("Database URL: " + meta.getURL()); - System.out.println("Database Schema: " + getSchemaName(connection)); - System.out.println("Database Software: " + meta.getDatabaseProductName() + " version " + meta.getDatabaseProductVersion()); - System.out.println("Database Driver: " + meta.getDriverName() + " version " + meta.getDriverVersion()); - - // For Postgres, report whether pgcrypto is installed - // (If it isn't, we'll also write out warnings...see below) - if(dbType.equals(DBMS_POSTGRES)) - { - boolean pgcryptoUpToDate = PostgresUtils.isPgcryptoUpToDate(); - Double pgcryptoVersion = PostgresUtils.getPgcryptoInstalledVersion(connection); - System.out.println("PostgreSQL '" + PostgresUtils.PGCRYPTO + "' extension installed/up-to-date? " + pgcryptoUpToDate + " " + ((pgcryptoVersion!=null) ? "(version=" + pgcryptoVersion + ")" : "(not installed)")); - } + // Print basic Database info + printDBInfo(connection); // Get info table from Flyway System.out.println("\n" + MigrationInfoDumper.dumpToAsciiTable(flyway.info().all())); @@ -166,55 +153,14 @@ public class DatabaseUtils } } - // For PostgreSQL databases, we need to check for the 'pgcrypto' extension. - // If it is NOT properly installed, we'll need to warn the user, as DSpace will be unable to proceed. - if(dbType.equals(DBMS_POSTGRES)) - { - // Get version of pgcrypto available in this postgres instance - Double pgcryptoAvailable = PostgresUtils.getPgcryptoAvailableVersion(connection); + // Print any database warnings/errors found (if any) + boolean issueFound = printDBIssues(connection); - // Generic requirements message - String requirementsMsg = "\n** DSpace REQUIRES PostgreSQL >= " + PostgresUtils.POSTGRES_VERSION + " AND " + PostgresUtils.PGCRYPTO + " extension >= " + PostgresUtils.PGCRYPTO_VERSION + " **\n"; - - // Check if installed in PostgreSQL & a supported version - if(pgcryptoAvailable!=null && pgcryptoAvailable.compareTo(PostgresUtils.PGCRYPTO_VERSION)>=0) - { - // We now know it's available in this Postgres. Let's see if it is installed in this database. - Double pgcryptoInstalled = PostgresUtils.getPgcryptoInstalledVersion(connection); - - // Check if installed in database, but outdated version - if(pgcryptoInstalled!=null && pgcryptoInstalled.compareTo(PostgresUtils.PGCRYPTO_VERSION)<0) - { - System.out.println("\nWARNING: PostgreSQL '" + PostgresUtils.PGCRYPTO + "' extension is OUTDATED (installed version=" + pgcryptoInstalled + ", available version = " + pgcryptoAvailable + ")."); - System.out.println(requirementsMsg); - System.out.println("To update it, please connect to your DSpace database as a 'superuser' and manually run the following command: "); - System.out.println("\n ALTER EXTENSION " + PostgresUtils.PGCRYPTO + " UPDATE TO '" + pgcryptoAvailable + "';\n"); - } - else if(pgcryptoInstalled==null) // If it's not installed in database - { - System.out.println("\nWARNING: PostgreSQL '" + PostgresUtils.PGCRYPTO + "' extension is NOT INSTALLED on this database."); - System.out.println(requirementsMsg); - System.out.println("To install it, please connect to your DSpace database as a 'superuser' and manually run the following command: "); - System.out.println("\n CREATE EXTENSION " + PostgresUtils.PGCRYPTO + ";\n"); - } - } - // Check if installed in Postgres, but an unsupported version - else if(pgcryptoAvailable!=null && pgcryptoAvailable.compareTo(PostgresUtils.PGCRYPTO_VERSION)<0) - { - System.out.println("\nWARNING: UNSUPPORTED version of PostgreSQL '" + PostgresUtils.PGCRYPTO + "' extension found (version=" + pgcryptoAvailable + ")."); - System.out.println(requirementsMsg); - System.out.println("Make sure you are running a supported version of PostgreSQL, and then install " + PostgresUtils.PGCRYPTO + " version >= " + PostgresUtils.PGCRYPTO_VERSION); - System.out.println("The '" + PostgresUtils.PGCRYPTO + "' extension is often provided in the 'postgresql-contrib' package for your operating system."); - } - else if(pgcryptoAvailable==null) // If it's not installed in Postgres - { - System.out.println("\nWARNING: PostgreSQL '" + PostgresUtils.PGCRYPTO + "' extension is NOT AVAILABLE. Please install it into this PostgreSQL instance."); - System.out.println(requirementsMsg); - System.out.println("The '" + PostgresUtils.PGCRYPTO + "' extension is often provided in the 'postgresql-contrib' package for your operating system."); - System.out.println("Once the extension is installed globally, please connect to your DSpace database as a 'superuser' and manually run the following command: "); - System.out.println("\n CREATE EXTENSION " + PostgresUtils.PGCRYPTO + ";\n"); - } - } + // If issues found, exit with an error status + if(issueFound) + System.exit(1); + else + System.exit(0); } catch (SQLException e) { @@ -260,6 +206,7 @@ public class DatabaseUtils updateDatabase(dataSource, connection); } System.out.println("Done."); + System.exit(0); } catch(SQLException e) { @@ -277,6 +224,7 @@ public class DatabaseUtils System.out.println("Attempting to repair any previously failed migrations (or mismatched checksums) via FlywayDB... (Check dspace logs for details)"); flyway.repair(); System.out.println("Done."); + System.exit(0); } catch(SQLException|FlywayException e) { @@ -285,9 +233,35 @@ public class DatabaseUtils System.exit(1); } } + // "validate" = Run Flyway validation to check for database errors/issues + else if(argv[0].equalsIgnoreCase("validate")) + { + try (Connection connection = dataSource.getConnection();) + { + System.out.println("\nDatabase URL: " + connection.getMetaData().getURL()); + System.out.println("Attempting to validate database status (and migration checksums) via FlywayDB..."); + flyway.validate(); + System.out.println("No errors thrown. Validation succeeded. (Check dspace logs for more details)"); + System.exit(0); + } + catch(SQLException|FlywayException e) + { + System.err.println("Validation exception:"); + e.printStackTrace(); + System.exit(1); + } + } // "clean" = Run Flyway clean script else if(argv[0].equalsIgnoreCase("clean")) { + // If clean is disabled, return immediately + if(flyway.isCleanDisabled()) + { + System.out.println("\nWARNING: 'clean' command is currently disabled, as it is dangerous to run in Production scenarios!"); + System.out.println("\nIn order to run a 'clean' you first must enable it in your DSpace config by specifying 'db.cleanDisabled=false'.\n"); + System.exit(1); + } + try (Connection connection = dataSource.getConnection()) { String dbType = getDbType(connection); @@ -304,7 +278,7 @@ public class DatabaseUtils System.out.println("\nERROR: The database user '" + username + "' does not have sufficient privileges to run a 'database clean' (via Flyway)."); System.out.println("\nIn order to run a 'clean', the database user MUST have 'superuser' privileges"); System.out.println("OR the '" + PostgresUtils.PGCRYPTO + "' extension must be installed in a separate schema (see documentation)."); - System.out.println("\nOptionally, you could also manually remove the '" + PostgresUtils.PGCRYPTO + "' extension first (DROP EXTENSION " + PostgresUtils.PGCRYPTO + " CASCADE), then rerun the 'clean'"); + System.out.println("\nOptionally, you could also manually remove the '" + PostgresUtils.PGCRYPTO + "' extension first (DROP EXTENSION " + PostgresUtils.PGCRYPTO + " CASCADE;), then rerun the 'clean'"); System.exit(1); } } @@ -331,6 +305,7 @@ public class DatabaseUtils System.out.println("Scrubbing database clean... (Check dspace logs for details)"); cleanDatabase(flyway, dataSource); System.out.println("Done."); + System.exit(0); } } catch(SQLException e) @@ -348,8 +323,10 @@ public class DatabaseUtils System.out.println(" - info / status = Describe basic info/status about database, including validating the compatibility of this database"); System.out.println(" - migrate = Migrate the database to the latest version"); System.out.println(" - repair = Attempt to repair any previously failed database migrations or checksum mismatches (via Flyway repair)"); - System.out.println(" - clean = DESTROY all data and tables in database (WARNING there is no going back!)"); + System.out.println(" - validate = Validate current database's migration status (via Flyway validate), validating all migration checksums."); + System.out.println(" - clean = DESTROY all data and tables in database (WARNING there is no going back!). Requires 'db.cleanDisabled=false' setting in config."); System.out.println(""); + System.exit(0); } } @@ -361,7 +338,103 @@ public class DatabaseUtils } } + /** + * Print basic information about the current database to System.out. + * This is utilized by both the 'test' and 'info' commandline options. + * @param connection current database connection + * @throws SQLException if database error occurs + */ + private static void printDBInfo(Connection connection) throws SQLException + { + // Get basic Database info from connection + DatabaseMetaData meta = connection.getMetaData(); + String dbType = getDbType(connection); + System.out.println("\nDatabase Type: " + dbType); + System.out.println("Database URL: " + meta.getURL()); + System.out.println("Database Schema: " + getSchemaName(connection)); + System.out.println("Database Username: " + meta.getUserName()); + System.out.println("Database Software: " + meta.getDatabaseProductName() + " version " + meta.getDatabaseProductVersion()); + System.out.println("Database Driver: " + meta.getDriverName() + " version " + meta.getDriverVersion()); + // For Postgres, report whether pgcrypto is installed + // (If it isn't, we'll also write out warnings...see below) + if(dbType.equals(DBMS_POSTGRES)) + { + boolean pgcryptoUpToDate = PostgresUtils.isPgcryptoUpToDate(); + Double pgcryptoVersion = PostgresUtils.getPgcryptoInstalledVersion(connection); + System.out.println("PostgreSQL '" + PostgresUtils.PGCRYPTO + "' extension installed/up-to-date? " + pgcryptoUpToDate + " " + ((pgcryptoVersion!=null) ? "(version=" + pgcryptoVersion + ")" : "(not installed)")); + } + } + + /** + * Print any warnings about current database setup to System.err (if any). + * This is utilized by both the 'test' and 'info' commandline options. + * @param connection current database connection + * @return boolean true if database issues found, false otherwise + * @throws SQLException if database error occurs + */ + private static boolean printDBIssues(Connection connection) throws SQLException + { + boolean issueFound = false; + + // Get the DB Type + String dbType = getDbType(connection); + + // For PostgreSQL databases, we need to check for the 'pgcrypto' extension. + // If it is NOT properly installed, we'll need to warn the user, as DSpace will be unable to proceed. + if(dbType.equals(DBMS_POSTGRES)) + { + // Get version of pgcrypto available in this postgres instance + Double pgcryptoAvailable = PostgresUtils.getPgcryptoAvailableVersion(connection); + + // Generic requirements message + String requirementsMsg = "\n** DSpace REQUIRES PostgreSQL >= " + PostgresUtils.POSTGRES_VERSION + " AND " + PostgresUtils.PGCRYPTO + " extension >= " + PostgresUtils.PGCRYPTO_VERSION + " **\n"; + + // Check if installed in PostgreSQL & a supported version + if(pgcryptoAvailable!=null && pgcryptoAvailable.compareTo(PostgresUtils.PGCRYPTO_VERSION)>=0) + { + // We now know it's available in this Postgres. Let's see if it is installed in this database. + Double pgcryptoInstalled = PostgresUtils.getPgcryptoInstalledVersion(connection); + + // Check if installed in database, but outdated version + if(pgcryptoInstalled!=null && pgcryptoInstalled.compareTo(PostgresUtils.PGCRYPTO_VERSION)<0) + { + System.out.println("\nWARNING: Required PostgreSQL '" + PostgresUtils.PGCRYPTO + "' extension is OUTDATED (installed version=" + pgcryptoInstalled + ", available version = " + pgcryptoAvailable + ")."); + System.out.println(requirementsMsg); + System.out.println("To update it, please connect to your DSpace database as a 'superuser' and manually run the following command: "); + System.out.println("\n ALTER EXTENSION " + PostgresUtils.PGCRYPTO + " UPDATE TO '" + pgcryptoAvailable + "';\n"); + issueFound = true; + } + else if(pgcryptoInstalled==null) // If it's not installed in database + { + System.out.println("\nWARNING: Required PostgreSQL '" + PostgresUtils.PGCRYPTO + "' extension is NOT INSTALLED on this database."); + System.out.println(requirementsMsg); + System.out.println("To install it, please connect to your DSpace database as a 'superuser' and manually run the following command: "); + System.out.println("\n CREATE EXTENSION " + PostgresUtils.PGCRYPTO + ";\n"); + issueFound = true; + } + } + // Check if installed in Postgres, but an unsupported version + else if(pgcryptoAvailable!=null && pgcryptoAvailable.compareTo(PostgresUtils.PGCRYPTO_VERSION)<0) + { + System.out.println("\nWARNING: UNSUPPORTED version of PostgreSQL '" + PostgresUtils.PGCRYPTO + "' extension found (version=" + pgcryptoAvailable + ")."); + System.out.println(requirementsMsg); + System.out.println("Make sure you are running a supported version of PostgreSQL, and then install " + PostgresUtils.PGCRYPTO + " version >= " + PostgresUtils.PGCRYPTO_VERSION); + System.out.println("The '" + PostgresUtils.PGCRYPTO + "' extension is often provided in the 'postgresql-contrib' package for your operating system."); + issueFound = true; + } + else if(pgcryptoAvailable==null) // If it's not installed in Postgres + { + System.out.println("\nWARNING: PostgreSQL '" + PostgresUtils.PGCRYPTO + "' extension is NOT AVAILABLE. Please install it into this PostgreSQL instance."); + System.out.println(requirementsMsg); + System.out.println("The '" + PostgresUtils.PGCRYPTO + "' extension is often provided in the 'postgresql-contrib' package for your operating system."); + System.out.println("Once the extension is installed globally, please connect to your DSpace database as a 'superuser' and manually run the following command: "); + System.out.println("\n CREATE EXTENSION " + PostgresUtils.PGCRYPTO + ";\n"); + issueFound = true; + } + } + return issueFound; + } /** * Setup/Initialize the Flyway API to run against our DSpace database @@ -384,6 +457,9 @@ public class DatabaseUtils flywaydb.setDataSource(datasource); flywaydb.setEncoding("UTF-8"); + // Default cleanDisabled to "true" (which disallows the ability to run 'database clean') + flywaydb.setCleanDisabled(config.getBooleanProperty("db.cleanDisabled", true)); + // Migration scripts are based on DBMS Keyword (see full path below) String dbType = getDbType(connection); connection.close(); diff --git a/dspace-api/src/main/java/org/dspace/storage/rdbms/GroupServiceInitializer.java b/dspace-api/src/main/java/org/dspace/storage/rdbms/GroupServiceInitializer.java index 21e63c2585..c6179bfc53 100644 --- a/dspace-api/src/main/java/org/dspace/storage/rdbms/GroupServiceInitializer.java +++ b/dspace-api/src/main/java/org/dspace/storage/rdbms/GroupServiceInitializer.java @@ -97,16 +97,6 @@ public class GroupServiceInitializer implements FlywayCallback { } - @Override - public void beforeInit(Connection connection) { - - } - - @Override - public void afterInit(Connection connection) { - - } - @Override public void beforeBaseline(Connection connection) { diff --git a/dspace-api/src/main/java/org/dspace/storage/rdbms/PostgreSQLCryptoChecker.java b/dspace-api/src/main/java/org/dspace/storage/rdbms/PostgreSQLCryptoChecker.java index 456cc83c73..3b50c89ed9 100644 --- a/dspace-api/src/main/java/org/dspace/storage/rdbms/PostgreSQLCryptoChecker.java +++ b/dspace-api/src/main/java/org/dspace/storage/rdbms/PostgreSQLCryptoChecker.java @@ -146,16 +146,6 @@ public class PostgreSQLCryptoChecker implements FlywayCallback } - @Override - public void beforeInit(Connection connection) { - - } - - @Override - public void afterInit(Connection connection) { - - } - @Override public void beforeBaseline(Connection connection) { // Before initializing database, check for pgcrypto diff --git a/dspace-api/src/main/java/org/dspace/storage/rdbms/SiteServiceInitializer.java b/dspace-api/src/main/java/org/dspace/storage/rdbms/SiteServiceInitializer.java index 4c37e38c3f..243cc50d53 100644 --- a/dspace-api/src/main/java/org/dspace/storage/rdbms/SiteServiceInitializer.java +++ b/dspace-api/src/main/java/org/dspace/storage/rdbms/SiteServiceInitializer.java @@ -100,16 +100,6 @@ public class SiteServiceInitializer implements FlywayCallback { } - @Override - public void beforeInit(Connection connection) { - - } - - @Override - public void afterInit(Connection connection) { - - } - @Override public void beforeBaseline(Connection connection) { diff --git a/dspace-api/src/main/java/org/dspace/storage/rdbms/hibernate/postgres/DSpacePostgreSQL82Dialect.java b/dspace-api/src/main/java/org/dspace/storage/rdbms/hibernate/postgres/DSpacePostgreSQL82Dialect.java index f8e48009d4..dfacf980c2 100644 --- a/dspace-api/src/main/java/org/dspace/storage/rdbms/hibernate/postgres/DSpacePostgreSQL82Dialect.java +++ b/dspace-api/src/main/java/org/dspace/storage/rdbms/hibernate/postgres/DSpacePostgreSQL82Dialect.java @@ -45,8 +45,8 @@ public class DSpacePostgreSQL82Dialect extends PostgreSQL82Dialect /** * Override is needed to properly support the CLOB on metadatavalue in postgres & oracle. - * @param sqlCode - * @return + * @param sqlCode {@linkplain java.sql.Types JDBC type-code} for the column mapped by this type. + * @return Descriptor for the SQL/JDBC side of a value mapping. */ @Override public SqlTypeDescriptor getSqlTypeDescriptorOverride(int sqlCode) { diff --git a/dspace-api/src/main/java/org/dspace/submit/lookup/LanguageCodeModifier.java b/dspace-api/src/main/java/org/dspace/submit/lookup/LanguageCodeModifier.java index d0f1bc5b20..ae25444a1f 100644 --- a/dspace-api/src/main/java/org/dspace/submit/lookup/LanguageCodeModifier.java +++ b/dspace-api/src/main/java/org/dspace/submit/lookup/LanguageCodeModifier.java @@ -78,10 +78,10 @@ public class LanguageCodeModifier extends AbstractModifier implements Initializi /** * Covert ISO 639-2 alpha-3 code to ISO 639-1 alpha-2 code * - * @param lang - * 3char language code + * @param lang3 + * ISO 639-1 alpha-3 language code * - * @return String 2char language code ("other" unless code has 2 char code) + * @return String ISO 639-1 alpha-2 language code ("other" if code is not alpha-2) * */ protected String getLang2(String lang3) diff --git a/dspace-api/src/main/java/org/dspace/submit/step/XMLUIStartSubmissionLookupStep.java b/dspace-api/src/main/java/org/dspace/submit/step/XMLUIStartSubmissionLookupStep.java index 47a48706e6..f65899c3d8 100644 --- a/dspace-api/src/main/java/org/dspace/submit/step/XMLUIStartSubmissionLookupStep.java +++ b/dspace-api/src/main/java/org/dspace/submit/step/XMLUIStartSubmissionLookupStep.java @@ -17,7 +17,7 @@ import org.dspace.content.MetadataValue; import org.dspace.content.factory.ContentServiceFactory; import org.dspace.content.service.ItemService; import org.dspace.core.Context; -import org.dspace.importer.external.MetadataSourceException; +import org.dspace.importer.external.exception.MetadataSourceException; import org.dspace.importer.external.datamodel.ImportRecord; import org.dspace.importer.external.metadatamapping.MetadatumDTO; import org.dspace.importer.external.service.ImportService; @@ -44,7 +44,8 @@ public class XMLUIStartSubmissionLookupStep extends AbstractProcessingStep { String publicationID = request.getParameter("publication_id"); if (StringUtils.isNotBlank(publicationID)) { - ImportService importService = new DSpace().getServiceManager().getServiceByName(null, ImportService.class); + /* Get an instance of the ImportService to be able to retrieve records based on several factors, such as url, publicationID, etc*/ + ImportService importService = new DSpace().getServiceManager().getServiceByName("importService", ImportService.class); Item item = subInfo.getSubmissionItem().getItem(); try { ImportRecord record = importService.getRecord(getPublicationUrl(), publicationID); @@ -77,7 +78,7 @@ public class XMLUIStartSubmissionLookupStep extends AbstractProcessingStep { public String getPublicationUrl(){ if(publicationUrl==null){ - publicationUrl=configurationService.getProperty("publication-lookup.publication.url"); + publicationUrl=configurationService.getProperty("publication-lookup.url", "*"); } return publicationUrl; } diff --git a/dspace-api/src/main/java/org/dspace/util/MultiFormatDateParser.java b/dspace-api/src/main/java/org/dspace/util/MultiFormatDateParser.java index 5b4f19f629..869e5a2aff 100644 --- a/dspace-api/src/main/java/org/dspace/util/MultiFormatDateParser.java +++ b/dspace-api/src/main/java/org/dspace/util/MultiFormatDateParser.java @@ -30,7 +30,7 @@ import org.slf4j.LoggerFactory; /** * Attempt to parse date strings in a variety of formats. This uses an external * list of regular expressions and associated SimpleDateFormat strings. Inject - * the list as pairs of strings using {@link setPatterns}. {@link parse} walks + * the list as pairs of strings using {@link #setPatterns}. {@link #parse} walks * the provided list in the order provided and tries each entry against a String. * * Dates are parsed as being in the UTC zone. diff --git a/dspace-api/src/main/java/org/dspace/versioning/VersionHistory.java b/dspace-api/src/main/java/org/dspace/versioning/VersionHistory.java index ca231cbc98..c0fbc45c94 100644 --- a/dspace-api/src/main/java/org/dspace/versioning/VersionHistory.java +++ b/dspace-api/src/main/java/org/dspace/versioning/VersionHistory.java @@ -56,10 +56,10 @@ public class VersionHistory implements ReloadableEntity { } /** - * Please use {@link VersioningService#getVersionsByHistory(Context, VersionHistory)} instead. + * Please use {@link org.dspace.versioning.service.VersioningService#getVersionsByHistory(Context, VersionHistory)} instead. * * To keep version number stables we keep information about deleted Versions. - * {@code VersioningService.getVersionsByHistory(Context, VersionHistory)} filters + * {@code org.dspace.versioning.service.VersioningService#getVersionsByHistory(Context, VersionHistory) VersioningService#getVersionsByHistory} filters * such versions and returns only active versions. */ protected List getVersions() { @@ -109,4 +109,4 @@ public class VersionHistory implements ReloadableEntity { return hash; } -} \ No newline at end of file +} diff --git a/dspace-api/src/main/resources/org/dspace/storage/rdbms/sqlmigration/oracle/V6.0_2016.07.21__DS-2775.sql b/dspace-api/src/main/resources/org/dspace/storage/rdbms/sqlmigration/oracle/V6.0_2016.07.21__DS-2775.sql new file mode 100644 index 0000000000..7478397446 --- /dev/null +++ b/dspace-api/src/main/resources/org/dspace/storage/rdbms/sqlmigration/oracle/V6.0_2016.07.21__DS-2775.sql @@ -0,0 +1,30 @@ +-- +-- 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/ +-- + +------------------------------------------------------ +-- DS-2775 Drop unused sequences +------------------------------------------------------ + +DROP SEQUENCE bitstream_seq; +DROP SEQUENCE bundle2bitstream_seq; +DROP SEQUENCE bundle_seq; +DROP SEQUENCE collection2item_seq; +DROP SEQUENCE collection_seq; +DROP SEQUENCE community2collection_seq; +DROP SEQUENCE community2community_seq; +DROP SEQUENCE community_seq; +DROP SEQUENCE dcvalue_seq; +DROP SEQUENCE eperson_seq; +DROP SEQUENCE epersongroup2eperson_seq; +DROP SEQUENCE epersongroup2workspaceitem_seq; +DROP SEQUENCE epersongroup_seq; +DROP SEQUENCE group2group_seq; +DROP SEQUENCE group2groupcache_seq; +DROP SEQUENCE historystate_seq; +DROP SEQUENCE item2bundle_seq; +DROP SEQUENCE item_seq; diff --git a/dspace-api/src/main/resources/org/dspace/storage/rdbms/sqlmigration/postgres/V6.0_2016.07.21__DS-2775.sql b/dspace-api/src/main/resources/org/dspace/storage/rdbms/sqlmigration/postgres/V6.0_2016.07.21__DS-2775.sql new file mode 100644 index 0000000000..7478397446 --- /dev/null +++ b/dspace-api/src/main/resources/org/dspace/storage/rdbms/sqlmigration/postgres/V6.0_2016.07.21__DS-2775.sql @@ -0,0 +1,30 @@ +-- +-- 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/ +-- + +------------------------------------------------------ +-- DS-2775 Drop unused sequences +------------------------------------------------------ + +DROP SEQUENCE bitstream_seq; +DROP SEQUENCE bundle2bitstream_seq; +DROP SEQUENCE bundle_seq; +DROP SEQUENCE collection2item_seq; +DROP SEQUENCE collection_seq; +DROP SEQUENCE community2collection_seq; +DROP SEQUENCE community2community_seq; +DROP SEQUENCE community_seq; +DROP SEQUENCE dcvalue_seq; +DROP SEQUENCE eperson_seq; +DROP SEQUENCE epersongroup2eperson_seq; +DROP SEQUENCE epersongroup2workspaceitem_seq; +DROP SEQUENCE epersongroup_seq; +DROP SEQUENCE group2group_seq; +DROP SEQUENCE group2groupcache_seq; +DROP SEQUENCE historystate_seq; +DROP SEQUENCE item2bundle_seq; +DROP SEQUENCE item_seq; diff --git a/dspace-api/src/main/resources/spring/spring-dspace-addon-import-services.xml b/dspace-api/src/main/resources/spring/spring-dspace-addon-import-services.xml index fc551948b5..997e658698 100644 --- a/dspace-api/src/main/resources/spring/spring-dspace-addon-import-services.xml +++ b/dspace-api/src/main/resources/spring/spring-dspace-addon-import-services.xml @@ -24,7 +24,15 @@ - + + + @@ -38,4 +46,4 @@ - \ No newline at end of file + diff --git a/dspace-api/src/test/java/org/dspace/content/ItemComparatorTest.java b/dspace-api/src/test/java/org/dspace/content/ItemComparatorTest.java index 30420e754f..e9e2f8fd78 100644 --- a/dspace-api/src/test/java/org/dspace/content/ItemComparatorTest.java +++ b/dspace-api/src/test/java/org/dspace/content/ItemComparatorTest.java @@ -34,6 +34,7 @@ public class ItemComparatorTest extends AbstractUnitTest protected InstallItemService installItemService = ContentServiceFactory.getInstance().getInstallItemService(); protected MetadataSchemaService metadataSchemaService = ContentServiceFactory.getInstance().getMetadataSchemaService(); protected MetadataFieldService metadataFieldService = ContentServiceFactory.getInstance().getMetadataFieldService(); + private MetadataValueService metadataValueService = ContentServiceFactory.getInstance().getMetadataValueService(); /** * Item instance for the tests @@ -104,6 +105,9 @@ public class ItemComparatorTest extends AbstractUnitTest { context.turnOffAuthorisationSystem(); try{ + // Remove all values added to the test MetadataField (MetadataField cannot be deleted if it is still used) + metadataValueService.deleteByMetadataField(context, metadataField); + // Delete the (unused) metadataField metadataFieldService.delete(context, metadataField); communityService.delete(context, owningCommunity); context.restoreAuthSystemState(); diff --git a/dspace-api/src/test/java/org/dspace/content/packager/PackageUtilsTest.java b/dspace-api/src/test/java/org/dspace/content/packager/PackageUtilsTest.java new file mode 100644 index 0000000000..481140a914 --- /dev/null +++ b/dspace-api/src/test/java/org/dspace/content/packager/PackageUtilsTest.java @@ -0,0 +1,222 @@ +/** + * 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.packager; + +import org.apache.log4j.Logger; +import org.dspace.AbstractUnitTest; +import org.dspace.authorize.AuthorizeException; +import org.dspace.content.Collection; +import org.dspace.content.Community; +import org.dspace.content.MetadataSchema; +import org.dspace.content.factory.ContentServiceFactory; +import org.dspace.content.service.*; +import org.dspace.core.Context; +import org.dspace.eperson.Group; +import org.dspace.eperson.factory.EPersonServiceFactory; +import org.dspace.eperson.service.GroupService; +import org.dspace.handle.factory.HandleServiceFactory; +import org.dspace.handle.service.HandleService; +import org.junit.*; + +import java.sql.SQLException; + +import static org.hamcrest.CoreMatchers.containsString; +import static org.junit.Assert.*; + +/** + * @author Andrea Schweer schweer@waikato.ac.nz + * for the University of Waikato's Institutional Research Repositories + */ +public class PackageUtilsTest extends AbstractUnitTest +{ + private static final Logger log = Logger.getLogger(PackageUtilsTest.class); + + protected CommunityService communityService = ContentServiceFactory.getInstance().getCommunityService(); + protected CollectionService collectionService = ContentServiceFactory.getInstance().getCollectionService(); + protected ItemService itemService = ContentServiceFactory.getInstance().getItemService(); + + protected WorkspaceItemService workspaceItemService = ContentServiceFactory.getInstance().getWorkspaceItemService(); + protected InstallItemService installItemService = ContentServiceFactory.getInstance().getInstallItemService(); + protected HandleService handleService = HandleServiceFactory.getInstance().getHandleService(); + + /** Handles for Test objects initialized in setUpClass() and used in various tests below **/ + private static String topCommunityHandle = null; + private static String testCollectionHandle = null; + + /** + * This method will be run during class initialization. It will initialize + * shared resources required for all the tests. It is only run once. + * + * Other methods can be annotated with @Before here or in subclasses + * but no execution order is guaranteed + */ + @BeforeClass + public static void setUpClass() + { + try + { + Context context = new Context(); + // Create a dummy Community hierarchy to test with + // Turn off authorization temporarily to create some test objects. + context.turnOffAuthorisationSystem(); + + CommunityService communityService = ContentServiceFactory.getInstance().getCommunityService(); + CollectionService collectionService = ContentServiceFactory.getInstance().getCollectionService(); + + log.info("setUpClass() - CREATE TEST HIERARCHY"); + // Create a hierachy of sub-Communities and Collections + // which looks like this: + // "Top Community" + // - "Child Community" + // - "Grandchild Collection" + // + Community topCommunity = communityService.create(null, context); + communityService.addMetadata(context, topCommunity, MetadataSchema.DC_SCHEMA, "title", null, null, "Top Community"); + communityService.update(context, topCommunity); + topCommunityHandle = topCommunity.getHandle(); + + Community child = communityService.createSubcommunity(context, topCommunity); + communityService.addMetadata(context, child, MetadataSchema.DC_SCHEMA, "title", null, null, "Child Community"); + communityService.update(context, child); + + // Create our primary Test Collection + Collection grandchildCol = collectionService.create(context, child); + collectionService.addMetadata(context, grandchildCol, "dc", "title", null, null, "Grandchild Collection"); + collectionService.update(context, grandchildCol); + testCollectionHandle = grandchildCol.getHandle(); + + // Commit these changes to our DB + context.restoreAuthSystemState(); + context.complete(); + } + catch (AuthorizeException ex) + { + log.error("Authorization Error in setUpClass()", ex); + fail("Authorization Error in setUpClass(): " + ex.getMessage()); + } + catch (SQLException ex) + { + log.error("SQL Error in setUpClass()", ex); + fail("SQL Error in setUpClass(): " + ex.getMessage()); + } + } + + /** + * This method will be run once at the very end + */ + @AfterClass + public static void tearDownClass() + { + try + { + Context context = new Context(); + CommunityService communityService = ContentServiceFactory.getInstance().getCommunityService(); + HandleService handleService = HandleServiceFactory.getInstance().getHandleService(); + Community topCommunity = (Community) handleService.resolveToObject(context, topCommunityHandle); + + // Delete top level test community and test hierarchy under it + if(topCommunity!=null) + { + log.info("tearDownClass() - DESTROY TEST HIERARCHY"); + context.turnOffAuthorisationSystem(); + communityService.delete(context, topCommunity); + context.restoreAuthSystemState(); + context.complete(); + } + + if(context.isValid()) + context.abort(); + } + catch (Exception ex) + { + log.error("Error in tearDownClass()", ex); + } + } + + /** + * Pass through initialisation; turn off authorisation + */ + @Before + @Override + public void init() + { + // call init() from AbstractUnitTest to initialize testing framework + super.init(); + context.turnOffAuthorisationSystem(); + } + + @Test + public void testCrosswalkGroupNameWithoutUnderscore() throws Exception + { + Collection testCollection = (Collection) handleService.resolveToObject(context, testCollectionHandle); + Group originalFirstStepWorkflowGroup = testCollection.getWorkflowStep1(); + + GroupService groupService = EPersonServiceFactory.getInstance().getGroupService(); + Group testGroup = groupService.create(context); + groupService.setName(testGroup, "TESTGROUP"); + testCollection.setWorkflowGroup(1, testGroup); + + String exportName = PackageUtils.translateGroupNameForExport(context, + testGroup.getName()); + assertEquals("Group name without underscore unchanged by translation for export", testGroup.getName(), exportName); + + String importName = PackageUtils.translateGroupNameForImport(context, exportName); + assertEquals("Exported Group name without underscore unchanged by translation for import", exportName, importName); + + testCollection.setWorkflowGroup(1, originalFirstStepWorkflowGroup); + } + + @Test + public void testCrosswalkGroupNameUnderscoresNoDSO() throws Exception + { + Collection testCollection = (Collection) handleService.resolveToObject(context, testCollectionHandle); + Group originalFirstStepWorkflowGroup = testCollection.getWorkflowStep1(); + + GroupService groupService = EPersonServiceFactory.getInstance().getGroupService(); + Group testGroup = groupService.create(context); + groupService.setName(testGroup, "TESTGROUP_ABC_TEST"); + testCollection.setWorkflowGroup(1, testGroup); + + String exportName = PackageUtils.translateGroupNameForExport(context, + testGroup.getName()); + assertEquals("Group name with underscores but no DSO unchanged by translation for export", testGroup.getName(), exportName); + + String importName = PackageUtils.translateGroupNameForImport(context, exportName); + assertEquals("Exported Group name with underscores but no DSO unchanged by translation for import", exportName, importName); + + testCollection.setWorkflowGroup(1, originalFirstStepWorkflowGroup); + } + + @Test + public void testCrosswalkGroupNameUnderscoresAndDSO() throws Exception + { + Collection testCollection = (Collection) handleService.resolveToObject(context, testCollectionHandle); + Group originalFirstStepWorkflowGroup = testCollection.getWorkflowStep1(); + + Group group = collectionService.createWorkflowGroup(context, testCollection, 1); + + String exportName = PackageUtils.translateGroupNameForExport(context, + group.getName()); + assertNotEquals("Exported group name should differ from original", group.getName(), exportName); + assertThat("Exported group name should contain '_hdl:' substring", exportName, containsString("_hdl:")); + + String importName = PackageUtils.translateGroupNameForImport(context, exportName); + assertEquals("Exported Group name with dso unchanged by roundtrip translation for export/import", group.getName(), importName); + + testCollection.setWorkflowGroup(1, originalFirstStepWorkflowGroup); + } + + @After + @Override + public void destroy() { + context.abort(); + context.restoreAuthSystemState(); + super.destroy(); + } + +} diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/discovery/DiscoverUtility.java b/dspace-jspui/src/main/java/org/dspace/app/webui/discovery/DiscoverUtility.java index 327ef2d789..2dc3b55b91 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/discovery/DiscoverUtility.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/discovery/DiscoverUtility.java @@ -247,9 +247,13 @@ public class DiscoverUtility { try { - String newFilterQuery = SearchUtils.getSearchService() - .toFilterQuery(context, f[0], f[1], f[2]) - .getFilterQuery(); + String newFilterQuery = null; + if (StringUtils.isNotBlank(f[0]) && StringUtils.isNotBlank(f[2])) + { + newFilterQuery = SearchUtils.getSearchService() + .toFilterQuery(context, f[0], f[1], f[2]) + .getFilterQuery(); + } if (newFilterQuery != null) { queryArgs.addFilterQueries(newFilterQuery); diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/jsptag/AccessSettingTag.java b/dspace-jspui/src/main/java/org/dspace/app/webui/jsptag/AccessSettingTag.java index bc447a428f..def7abb51e 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/jsptag/AccessSettingTag.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/jsptag/AccessSettingTag.java @@ -253,10 +253,10 @@ public class AccessSettingTag extends TagSupport } /** - * Set the browseInfo + * Set the subInfo (SubmissionInfo) * - * @param browseInfo - * the browseInfo + * @param subInfo + * the subInfo */ public void setSubInfo(SubmissionInfo subInfo) { @@ -276,7 +276,7 @@ public class AccessSettingTag extends TagSupport /** * Set the the dso * - * @param the dso + * @param dso * the dso */ public void setDso(DSpaceObject dso) @@ -297,7 +297,7 @@ public class AccessSettingTag extends TagSupport /** * Set the the rp * - * @param the rp + * @param rp * the rp */ public void setRp(ResourcePolicy rp) diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/jsptag/ItemTag.java b/dspace-jspui/src/main/java/org/dspace/app/webui/jsptag/ItemTag.java index 5983435d43..c28352fc22 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/jsptag/ItemTag.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/jsptag/ItemTag.java @@ -1040,7 +1040,7 @@ public class ItemTag extends TagSupport // won't have a big problem here rp = policy; // if we found a policy allowing anonymous - // group to read the bitsream, mark it as + // group to read the bitstream, mark it as // being anoymous readable and leave the loop if (resourcePolicyService.isDateValid(policy)) { diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/jsptag/PoliciesListTag.java b/dspace-jspui/src/main/java/org/dspace/app/webui/jsptag/PoliciesListTag.java index 5326c8de5b..9f4372ef46 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/jsptag/PoliciesListTag.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/jsptag/PoliciesListTag.java @@ -130,7 +130,7 @@ public class PoliciesListTag extends TagSupport /** * Set the policies to list * - * @param itemsIn + * @param policies * the policies */ public void setPolicies(List policies) diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/jsptag/SelectCollectionTag.java b/dspace-jspui/src/main/java/org/dspace/app/webui/jsptag/SelectCollectionTag.java index af78aa72cd..e6d422dfe9 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/jsptag/SelectCollectionTag.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/jsptag/SelectCollectionTag.java @@ -88,7 +88,7 @@ public class SelectCollectionTag extends TagSupport { sb.append(" selected=\"selected\""); } - sb.append(">").append(CollectionDropDown.collectionPath(coll)).append("\n"); + sb.append(">").append(CollectionDropDown.collectionPath(context, coll)).append("\n"); } sb.append("\n"); diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/admin/EditItemServlet.java b/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/admin/EditItemServlet.java index d7b5607e1c..74e78fb996 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/admin/EditItemServlet.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/admin/EditItemServlet.java @@ -228,18 +228,9 @@ public class EditItemServlet extends DSpaceServlet case CONFIRM_DELETE: // Delete the item - if "cancel" was pressed this would be - // picked up above - // FIXME: Don't know if this does all it should - remove Handle? - Iterator collIter = item.getCollections().iterator(); + // picked up above + itemService.delete(context, item); - // Remove item from all the collections it's in - while(collIter.hasNext()) - { - Collection c = collIter.next(); - collIter.remove(); - collectionService.removeItem(context, c, item); - } - JSPManager.showJSP(request, response, "/tools/get-item-id.jsp"); context.complete(); diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/submit/step/JSPStartSubmissionLookupStep.java b/dspace-jspui/src/main/java/org/dspace/app/webui/submit/step/JSPStartSubmissionLookupStep.java index d244a405ef..4c151357d7 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/submit/step/JSPStartSubmissionLookupStep.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/submit/step/JSPStartSubmissionLookupStep.java @@ -79,6 +79,8 @@ public class JSPStartSubmissionLookupStep extends JSPStep private CollectionService collectionService = ContentServiceFactory.getInstance().getCollectionService(); + private final String DEFAULT_COLLECTION_ID = "-1"; + /** * Do any pre-processing to determine which JSP (if any) is used to generate * the UI for this step. This method should include the gathering and @@ -124,13 +126,19 @@ public class JSPStartSubmissionLookupStep extends JSPStep * With no parameters, this servlet prepares for display of the Select * Collection JSP. */ - UUID collection_id = UIUtil.getUUIDParameter(request, "collection"); - UUID collectionID = UIUtil.getUUIDParameter(request, "collectionid"); + UUID collection_id = null; + if(!DEFAULT_COLLECTION_ID.equals(request.getParameter("collection"))) { + collection_id = UIUtil.getUUIDParameter(request, "collection"); + } + + if(collection_id == null && !DEFAULT_COLLECTION_ID.equals(request.getParameter("collectionid"))) { + collection_id = UIUtil.getUUIDParameter(request, "collectionid"); + } Collection col = null; - if (collectionID != null) + if (collection_id != null) { - col = collectionService.find(context, collectionID); + col = collectionService.find(context, collection_id); } // if we already have a valid collection, then we can forward directly @@ -138,7 +146,7 @@ public class JSPStartSubmissionLookupStep extends JSPStep if (col != null) { log.debug("Select Collection page skipped, since a Collection ID was already found. Collection ID=" - + collectionID); + + collection_id); } else { @@ -162,8 +170,14 @@ public class JSPStartSubmissionLookupStep extends JSPStep // save collections to request for JSP request.setAttribute("collections", collections); - request.setAttribute("collection_id", collection_id); - request.setAttribute("collectionID", collectionID); + + if(collection_id!=null) { + request.setAttribute("collection_id", collection_id); + } + else { + request.setAttribute("collection_id", DEFAULT_COLLECTION_ID); + } + request.setAttribute("collectionID", collection_id); Map> identifiers2providers = slService .getProvidersIdentifiersMap(); diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/submit/step/JSPUploadWithEmbargoStep.java b/dspace-jspui/src/main/java/org/dspace/app/webui/submit/step/JSPUploadWithEmbargoStep.java index 115fd32b32..a2945e2fea 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/submit/step/JSPUploadWithEmbargoStep.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/submit/step/JSPUploadWithEmbargoStep.java @@ -67,7 +67,7 @@ import com.google.gson.Gson; * * @see org.dspace.app.webui.servlet.SubmissionController * @see org.dspace.app.webui.submit.JSPStep - * @see org.dspace.app.webui.submit.JSPUploadStep + * @see org.dspace.app.webui.submit.step.JSPUploadStep * @see org.dspace.submit.step.UploadStep * * @author Tim Donohue diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/util/UIUtil.java b/dspace-jspui/src/main/java/org/dspace/app/webui/util/UIUtil.java index 822e153ae7..953c891b23 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/util/UIUtil.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/util/UIUtil.java @@ -208,7 +208,8 @@ public class UIUtil extends Util * * @param ctx DSpace Context * @param item the item - * @return + * @return string array containing URL or null if no ID found; string + array contains null if no handle, but a DOI is found * @throws SQLException */ public static String[] getItemIdentifier(Context ctx, Item item) @@ -600,7 +601,7 @@ public class UIUtil extends Util * @param hrq The servlet request * @param dso The DSpaceObject to mark (it can be a BrowseItem or an Item) * @param markType the type of the mark. - * @return + * @return (X)HTML markup * @throws JspException */ public static String getMarkingMarkup(HttpServletRequest hrq, DSpaceObject dso, String markType) @@ -610,8 +611,8 @@ public class UIUtil extends Util try { - String contextPath = hrq.getContextPath(); - + String contextPath = hrq.getContextPath(); + Context c = UIUtil.obtainContext(hrq); Item item = (Item) dso; diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/util/VersionUtil.java b/dspace-jspui/src/main/java/org/dspace/app/webui/util/VersionUtil.java index 409b6933c5..88dcc155eb 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/util/VersionUtil.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/util/VersionUtil.java @@ -325,7 +325,7 @@ public class VersionUtil * * @param context * @param stringVersionID - * @return + * @return version summary string */ public static String getSummary(Context context, String stringVersionID) { diff --git a/dspace-jspui/src/main/webapp/mydspace/subscriptions.jsp b/dspace-jspui/src/main/webapp/mydspace/subscriptions.jsp index 1cf02aced7..344da80ea5 100644 --- a/dspace-jspui/src/main/webapp/mydspace/subscriptions.jsp +++ b/dspace-jspui/src/main/webapp/mydspace/subscriptions.jsp @@ -30,6 +30,8 @@ <%@ page import="org.dspace.app.util.CollectionDropDown" %> <%@ page import="org.dspace.eperson.Subscription" %> <%@ page import="java.util.List" %> +<%@ page import="org.dspace.app.webui.util.UIUtil" %> +<%@ page import="org.dspace.core.Context" %> <% List availableSubscriptions = @@ -38,6 +40,7 @@ (List) request.getAttribute("subscriptions"); boolean updated = ((Boolean) request.getAttribute("updated")).booleanValue(); + Context context = UIUtil.obtainContext(request); %> <% } @@ -110,7 +113,7 @@ for (int i = 0; i < availableSubscriptions.size(); i++) - <%= CollectionDropDown.collectionPath(subscriptions.get(i).getCollection(),0) %> + <%= CollectionDropDown.collectionPath(context, subscriptions.get(i).getCollection(),0) %> diff --git a/dspace-jspui/src/main/webapp/search/discovery.jsp b/dspace-jspui/src/main/webapp/search/discovery.jsp index 818b5e4ace..306ffd9b03 100644 --- a/dspace-jspui/src/main/webapp/search/discovery.jsp +++ b/dspace-jspui/src/main/webapp/search/discovery.jsp @@ -67,7 +67,7 @@ <% // Get the attributes DSpaceObject scope = (DSpaceObject) request.getAttribute("scope" ); - String searchScope = scope!=null?scope.getHandle():""; + String searchScope = scope!=null ? scope.getHandle() : ""; List scopes = (List) request.getAttribute("scopes"); List sortOptions = (List) request.getAttribute("sortOptions"); @@ -77,7 +77,7 @@ query = ""; } Boolean error_b = (Boolean)request.getAttribute("search.error"); - boolean error = (error_b == null ? false : error_b.booleanValue()); + boolean error = error_b==null ? false : error_b.booleanValue(); DiscoverQuery qArgs = (DiscoverQuery) request.getAttribute("queryArgs"); String sortedBy = qArgs.getSortField(); @@ -94,6 +94,13 @@ int idx = 1; for (String[] filter : appliedFilters) { + if (filter == null + || filter[0] == null || filter[0].trim().equals("") + || filter[2] == null || filter[2].trim().equals("")) + { + idx++; + continue; + } httpFilters += "&filter_field_"+idx+"="+URLEncoder.encode(filter[0],"UTF-8"); httpFilters += "&filter_type_"+idx+"="+URLEncoder.encode(filter[1],"UTF-8"); httpFilters += "&filter_value_"+idx+"="+URLEncoder.encode(filter[2],"UTF-8"); @@ -217,7 +224,7 @@ { String fkey = "jsp.search.filter." + Escape.uriParam(searchFilter.getIndexFieldName()); %> - + Defines how an org.dspace.content.Item is mapped to a query in scopus. Please note that exactly one of these must be present. If multiple are present the result is undefined. diff --git a/dspace/etc/oracle/update-sequences.sql b/dspace/etc/oracle/update-sequences.sql index 9288805c24..9b941bde31 100644 --- a/dspace/etc/oracle/update-sequences.sql +++ b/dspace/etc/oracle/update-sequences.sql @@ -1,11 +1,7 @@ -- -- update-sequences.sql -- --- Version: $Revision$ --- --- Date: $Date$ --- --- Copyright (c) 2002-2009, The DSpace Foundation. All rights reserved. +-- Copyright (c) 2002-2016, The DSpace Foundation. All rights reserved. -- -- Redistribution and use in source and binary forms, with or without -- modification, are permitted provided that the following conditions are @@ -47,40 +43,19 @@ -- org.dspace.content API which is safe to use concurrently and in multiple -- JVMs. The SQL code below will typically only be required after a direct -- SQL data dump from a backup or somesuch. - --- There should be one of these calls for every ID sequence defined in --- database_schema.sql. - --- depends on being run from sqlplus with incseq.sql in the current path --- you can find incseq.sql at: http://akadia.com/services/scripts/incseq.sql +-- Depends on being run from sqlplus with incseq.sql in the current path +-- you can find incseq.sql at: http://www.akadia.com/services/scripts/incseq.sql +-- Here that script was renamed to updateseq.sql. @updateseq.sql bitstreamformatregistry_seq bitstreamformatregistry bitstream_format_id "" @updateseq.sql fileextension_seq fileextension file_extension_id "" -@updateseq.sql bitstream_seq bitstream bitstream_id "" -@updateseq.sql eperson_seq eperson eperson_id "" -@updateseq.sql epersongroup_seq epersongroup eperson_group_id "" -@updateseq.sql group2group_seq group2group id "" -@updateseq.sql group2groupcache_seq group2groupcache id "" -@updateseq.sql item_seq item item_id "" -@updateseq.sql bundle_seq bundle bundle_id "" -@updateseq.sql item2bundle_seq item2bundle id "" -@updateseq.sql bundle2bitstream_seq bundle2bitstream id "" -@updateseq.sql dcvalue_seq dcvalue dc_value_id "" -@updateseq.sql community_seq community community_id "" -@updateseq.sql community2community_seq community2community id "" -@updateseq.sql collection_seq collection collection_id "" -@updateseq.sql community2collection_seq community2collection id "" -@updateseq.sql collection2item_seq collection2item id "" @updateseq.sql resourcepolicy_seq resourcepolicy policy_id "" -@updateseq.sql epersongroup2eperson_seq epersongroup2eperson id "" @updateseq.sql workspaceitem_seq workspaceitem workspace_item_id "" @updateseq.sql workflowitem_seq workflowitem workflow_id "" @updateseq.sql tasklistitem_seq tasklistitem tasklist_id "" @updateseq.sql registrationdata_seq registrationdata registrationdata_id "" @updateseq.sql subscription_seq subscription subscription_id "" -@updateseq.sql communities2item_seq communities2item id "" -@updateseq.sql epersongroup2workspaceitem_seq epersongroup2workspaceitem id "" @updateseq.sql metadatafieldregistry_seq metadatafieldregistry metadata_field_id "" @updateseq.sql metadatavalue_seq metadatavalue metadata_value_id "" @updateseq.sql metadataschemaregistry_seq metadataschemaregistry metadata_schema_id "" @@ -95,4 +70,4 @@ -- For all 'handle' values which have a number in their suffix (after '/'), find the maximum -- suffix value, convert it to a number, and set the 'handle_seq' to start at the next value -- (see updateseq.sql script for more) -@updateseq.sql handle_seq handle "to_number(regexp_replace(handle, '.*/', ''), '999999999999')" "WHERE REGEXP_LIKE(handle, '^.*/[0123456789]*$')" \ No newline at end of file +@updateseq.sql handle_seq handle "to_number(regexp_replace(handle, '.*/', ''), '999999999999')" "WHERE REGEXP_LIKE(handle, '^.*/[0123456789]*$')" diff --git a/dspace/etc/postgres/update-sequences.sql b/dspace/etc/postgres/update-sequences.sql index f1a96d564f..fd06aa3f49 100644 --- a/dspace/etc/postgres/update-sequences.sql +++ b/dspace/etc/postgres/update-sequences.sql @@ -1,11 +1,7 @@ -- -- update-sequences.sql -- --- Version: $Revision$ --- --- Date: $Date$ --- --- Copyright (c) 2002-2009, The DSpace Foundation. All rights reserved. +-- Copyright (c) 2002-2016, The DSpace Foundation. All rights reserved. -- -- Redistribution and use in source and binary forms, with or without -- modification, are permitted provided that the following conditions are @@ -47,38 +43,16 @@ -- org.dspace.content API which is safe to use concurrently and in multiple -- JVMs. The SQL code below will typically only be required after a direct -- SQL data dump from a backup or somesuch. - - --- There should be one of these calls for every ID sequence defined in --- database_schema.sql. SELECT setval('bitstreamformatregistry_seq', max(bitstream_format_id)) FROM bitstreamformatregistry; SELECT setval('fileextension_seq', max(file_extension_id)) FROM fileextension; -SELECT setval('bitstream_seq', max(bitstream_id)) FROM bitstream; -SELECT setval('eperson_seq', max(eperson_id)) FROM eperson; -SELECT setval('epersongroup_seq', max(eperson_group_id)) FROM epersongroup; -SELECT setval('group2group_seq', max(id)) FROM group2group; -SELECT setval('group2groupcache_seq', max(id)) FROM group2groupcache; -SELECT setval('item_seq', max(item_id)) FROM item; -SELECT setval('bundle_seq', max(bundle_id)) FROM bundle; -SELECT setval('item2bundle_seq', max(id)) FROM item2bundle; -SELECT setval('bundle2bitstream_seq', max(id)) FROM bundle2bitstream; -SELECT setval('dcvalue_seq', max(dc_value_id)) FROM dcvalue; -SELECT setval('community_seq', max(community_id)) FROM community; -SELECT setval('community2community_seq', max(id)) FROM community2community; -SELECT setval('collection_seq', max(collection_id)) FROM collection; -SELECT setval('community2collection_seq', max(id)) FROM community2collection; -SELECT setval('collection2item_seq', max(id)) FROM collection2item; SELECT setval('resourcepolicy_seq', max(policy_id)) FROM resourcepolicy; -SELECT setval('epersongroup2eperson_seq', max(id)) FROM epersongroup2eperson; SELECT setval('workspaceitem_seq', max(workspace_item_id)) FROM workspaceitem; SELECT setval('workflowitem_seq', max(workflow_id)) FROM workflowitem; SELECT setval('tasklistitem_seq', max(tasklist_id)) FROM tasklistitem; SELECT setval('registrationdata_seq', max(registrationdata_id)) FROM registrationdata; SELECT setval('subscription_seq', max(subscription_id)) FROM subscription; -SELECT setval('communities2item_seq', max(id)) FROM communities2item; -SELECT setval('epersongroup2workspaceitem_seq', max(id)) FROM epersongroup2workspaceitem; SELECT setval('metadatafieldregistry_seq', max(metadata_field_id)) FROM metadatafieldregistry; SELECT setval('metadatavalue_seq', max(metadata_value_id)) FROM metadatavalue; SELECT setval('metadataschemaregistry_seq', max(metadata_schema_id)) FROM metadataschemaregistry; diff --git a/dspace/modules/oai/pom.xml b/dspace/modules/oai/pom.xml index 6c6632ba03..0a738b05fd 100644 --- a/dspace/modules/oai/pom.xml +++ b/dspace/modules/oai/pom.xml @@ -98,18 +98,10 @@ org.dspace.modules additions - - org.ow2.asm - asm - com.lyncode builder-commons - - org.apache.commons - commons-lang3 - @@ -165,4 +157,3 @@ - diff --git a/dspace/src/main/assembly/release.xml b/dspace/src/main/assembly/release.xml index 9ab778583d..a91d03f523 100644 --- a/dspace/src/main/assembly/release.xml +++ b/dspace/src/main/assembly/release.xml @@ -34,8 +34,7 @@ dspace/** LICENSE* NOTICE - README - local.cfg + README.md pom.xml diff --git a/dspace/src/main/config/build.xml b/dspace/src/main/config/build.xml index e2c8ffb8cd..e587121c69 100644 --- a/dspace/src/main/config/build.xml +++ b/dspace/src/main/config/build.xml @@ -135,7 +135,7 @@ Common usage: - + @@ -176,7 +176,7 @@ Common usage: - + @@ -797,16 +797,6 @@ Common usage: - - - - - - - - - - @@ -864,7 +854,7 @@ Common usage: diff --git a/pom.xml b/pom.xml index 3cbae9f9c2..4cdb5644d3 100644 --- a/pom.xml +++ b/pom.xml @@ -493,6 +493,25 @@ + + + doclint-java8-disable + + [1.8,) + + + + -Xdoclint:none + + +