Il seguente frammento di schema specifica il contenuto previsto contenuto in questa classe.
+ *
+ *
> nameOrNamespace;
+
+ /**
+ * Gets the value of the nameOrNamespace property.
+ *
+ *
+ * This accessor method returns a reference to the live list,
+ * not a snapshot. Therefore any modification you make to the
+ * returned list will be present inside the JAXB object.
+ * This is why there is not a set
method for the nameOrNamespace property.
+ *
+ *
+ * For example, to add a new item, do as follows:
+ *
+ * getNameOrNamespace().add(newItem);
+ *
+ *
+ *
+ *
+ * Objects of the following type(s) are allowed in the list
+ * {@link JAXBElement }{@code <}{@link String }{@code >}
+ * {@link JAXBElement }{@code <}{@link String }{@code >}
+ */
+ public List> getNameOrNamespace() {
+ if (nameOrNamespace == null) {
+ nameOrNamespace = new ArrayList>();
+ }
+ return this.nameOrNamespace;
+ }
+
+}
diff --git a/dspace-api/src/main/java/org/dspace/app/metadata/export/model/DcSchemaBuilder.java b/dspace-api/src/main/java/org/dspace/app/metadata/export/model/DcSchemaBuilder.java
new file mode 100644
index 00000000000..fe7144bda85
--- /dev/null
+++ b/dspace-api/src/main/java/org/dspace/app/metadata/export/model/DcSchemaBuilder.java
@@ -0,0 +1,39 @@
+/**
+ * The contents of this file are subject to the license and copyright
+ * detailed in the LICENSE and NOTICE files at the root of the source
+ * tree and available online at
+ *
+ * http://www.dspace.org/license/
+ */
+package org.dspace.app.metadata.export.model;
+
+import javax.xml.bind.JAXBElement;
+
+/**
+ * @author Vincenzo Mecca (vins01-4science - vincenzo.mecca at 4science.com)
+ **/
+public class DcSchemaBuilder extends AbstractJaxbBuilder {
+
+ protected DcSchemaBuilder() {
+ super(DcSchema.class);
+ }
+
+ public static DcSchemaBuilder createBuilder() {
+ return new DcSchemaBuilder();
+ }
+
+ public DcSchemaBuilder withName(String name) {
+ this.addChildElement(name, objectFactory::createName);
+ return this;
+ }
+
+ public DcSchemaBuilder withNamespace(String namespace) {
+ this.addChildElement(namespace, objectFactory::createNamespace);
+ return this;
+ }
+
+ @Override
+ protected void addChildElement(JAXBElement v) {
+ getObejct().getNameOrNamespace().add(v);
+ }
+}
diff --git a/dspace-api/src/main/java/org/dspace/app/metadata/export/model/DcType.java b/dspace-api/src/main/java/org/dspace/app/metadata/export/model/DcType.java
new file mode 100644
index 00000000000..bff2fc77978
--- /dev/null
+++ b/dspace-api/src/main/java/org/dspace/app/metadata/export/model/DcType.java
@@ -0,0 +1,86 @@
+/**
+ * The contents of this file are subject to the license and copyright
+ * detailed in the LICENSE and NOTICE files at the root of the source
+ * tree and available online at
+ *
+ * http://www.dspace.org/license/
+ */
+package org.dspace.app.metadata.export.model;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElementRef;
+import javax.xml.bind.annotation.XmlElementRefs;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+
+/**
+ * Classe Java per anonymous complex type.
+ *
+ *
Il seguente frammento di schema specifica il contenuto previsto contenuto in questa classe.
+ *
+ *
+ * <complexType>
+ * <complexContent>
+ * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * <choice maxOccurs="unbounded" minOccurs="0">
+ * <element ref="{}schema"/>
+ * <element ref="{}element"/>
+ * <element ref="{}qualifier"/>
+ * <element ref="{}scope_note"/>
+ * </choice>
+ * </restriction>
+ * </complexContent>
+ * </complexType>
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "", propOrder = {
+ "schemaOrElementOrQualifier"
+})
+@XmlRootElement(name = "dc-type")
+public class DcType {
+
+ @XmlElementRefs({
+ @XmlElementRef(name = "schema", type = JAXBElement.class, required = false),
+ @XmlElementRef(name = "element", type = JAXBElement.class, required = false),
+ @XmlElementRef(name = "qualifier", type = JAXBElement.class, required = false),
+ @XmlElementRef(name = "scope_note", type = JAXBElement.class, required = false)
+ })
+ protected List> schemaOrElementOrQualifier;
+
+ /**
+ * Gets the value of the schemaOrElementOrQualifier property.
+ *
+ *
+ * This accessor method returns a reference to the live list,
+ * not a snapshot. Therefore any modification you make to the
+ * returned list will be present inside the JAXB object.
+ * This is why there is not a set
method for the schemaOrElementOrQualifier property.
+ *
+ *
+ * For example, to add a new item, do as follows:
+ *
+ * getSchemaOrElementOrQualifier().add(newItem);
+ *
+ *
+ *
+ *
+ * Objects of the following type(s) are allowed in the list
+ * {@link JAXBElement }{@code <}{@link String }{@code >}
+ * {@link JAXBElement }{@code <}{@link String }{@code >}
+ * {@link JAXBElement }{@code <}{@link String }{@code >}
+ * {@link JAXBElement }{@code <}{@link String }{@code >}
+ */
+ public List> getSchemaOrElementOrQualifier() {
+ if (schemaOrElementOrQualifier == null) {
+ schemaOrElementOrQualifier = new ArrayList>();
+ }
+ return this.schemaOrElementOrQualifier;
+ }
+
+}
diff --git a/dspace-api/src/main/java/org/dspace/app/metadata/export/model/DcTypeBuilder.java b/dspace-api/src/main/java/org/dspace/app/metadata/export/model/DcTypeBuilder.java
new file mode 100644
index 00000000000..47fd64763ea
--- /dev/null
+++ b/dspace-api/src/main/java/org/dspace/app/metadata/export/model/DcTypeBuilder.java
@@ -0,0 +1,49 @@
+/**
+ * The contents of this file are subject to the license and copyright
+ * detailed in the LICENSE and NOTICE files at the root of the source
+ * tree and available online at
+ *
+ * http://www.dspace.org/license/
+ */
+package org.dspace.app.metadata.export.model;
+
+import javax.xml.bind.JAXBElement;
+
+/**
+ * @author Vincenzo Mecca (vins01-4science - vincenzo.mecca at 4science.com)
+ **/
+public class DcTypeBuilder extends AbstractJaxbBuilder {
+
+ protected DcTypeBuilder() {
+ super(DcType.class);
+ }
+
+ public static DcTypeBuilder createBuilder() {
+ return new DcTypeBuilder();
+ }
+
+ public DcTypeBuilder withSchema(String schema) {
+ addChildElement(schema, objectFactory::createSchema);
+ return this;
+ }
+
+ public DcTypeBuilder withElement(String element) {
+ addChildElement(element, objectFactory::createElement);
+ return this;
+ }
+
+ public DcTypeBuilder withQualifier(String qualifier) {
+ addChildElement(qualifier, objectFactory::createQualifier);
+ return this;
+ }
+
+ public DcTypeBuilder withScopeNote(String scopeNote) {
+ addChildElement(scopeNote, objectFactory::createScopeNote);
+ return this;
+ }
+
+ @Override
+ protected void addChildElement(JAXBElement v) {
+ getObejct().getSchemaOrElementOrQualifier().add(v);
+ }
+}
diff --git a/dspace-api/src/main/java/org/dspace/app/metadata/export/model/DspaceDcTypes.java b/dspace-api/src/main/java/org/dspace/app/metadata/export/model/DspaceDcTypes.java
new file mode 100644
index 00000000000..4cba081a8a3
--- /dev/null
+++ b/dspace-api/src/main/java/org/dspace/app/metadata/export/model/DspaceDcTypes.java
@@ -0,0 +1,82 @@
+/**
+ * The contents of this file are subject to the license and copyright
+ * detailed in the LICENSE and NOTICE files at the root of the source
+ * tree and available online at
+ *
+ * http://www.dspace.org/license/
+ */
+package org.dspace.app.metadata.export.model;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElements;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+
+/**
+ * Classe Java per anonymous complex type.
+ *
+ *
Il seguente frammento di schema specifica il contenuto previsto contenuto in questa classe.
+ *
+ *
+ * <complexType>
+ * <complexContent>
+ * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * <choice maxOccurs="unbounded" minOccurs="0">
+ * <element ref="{}dspace-header"/>
+ * <element ref="{}dc-schema"/>
+ * <element ref="{}dc-type"/>
+ * </choice>
+ * </restriction>
+ * </complexContent>
+ * </complexType>
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "", propOrder = {
+ "dspaceHeaderOrDcSchemaOrDcType"
+})
+@XmlRootElement(name = "dspace-dc-types")
+public class DspaceDcTypes {
+
+ @XmlElements({
+ @XmlElement(name = "dspace-header", type = DspaceHeader.class),
+ @XmlElement(name = "dc-schema", type = DcSchema.class),
+ @XmlElement(name = "dc-type", type = DcType.class)
+ })
+ protected List dspaceHeaderOrDcSchemaOrDcType;
+
+ /**
+ * Gets the value of the dspaceHeaderOrDcSchemaOrDcType property.
+ *
+ *
+ * This accessor method returns a reference to the live list,
+ * not a snapshot. Therefore any modification you make to the
+ * returned list will be present inside the JAXB object.
+ * This is why there is not a set
method for the dspaceHeaderOrDcSchemaOrDcType property.
+ *
+ *
+ * For example, to add a new item, do as follows:
+ *
+ * getDspaceHeaderOrDcSchemaOrDcType().add(newItem);
+ *
+ *
+ *
+ *
+ * Objects of the following type(s) are allowed in the list
+ * {@link DspaceHeader }
+ * {@link DcSchema }
+ * {@link DcType }
+ */
+ public List getDspaceHeaderOrDcSchemaOrDcType() {
+ if (dspaceHeaderOrDcSchemaOrDcType == null) {
+ dspaceHeaderOrDcSchemaOrDcType = new ArrayList();
+ }
+ return this.dspaceHeaderOrDcSchemaOrDcType;
+ }
+
+}
diff --git a/dspace-api/src/main/java/org/dspace/app/metadata/export/model/DspaceDcTypesBuilder.java b/dspace-api/src/main/java/org/dspace/app/metadata/export/model/DspaceDcTypesBuilder.java
new file mode 100644
index 00000000000..1e4cdb83393
--- /dev/null
+++ b/dspace-api/src/main/java/org/dspace/app/metadata/export/model/DspaceDcTypesBuilder.java
@@ -0,0 +1,59 @@
+/**
+ * The contents of this file are subject to the license and copyright
+ * detailed in the LICENSE and NOTICE files at the root of the source
+ * tree and available online at
+ *
+ * http://www.dspace.org/license/
+ */
+package org.dspace.app.metadata.export.model;
+
+import java.util.Collection;
+
+/**
+ * @author Vincenzo Mecca (vins01-4science - vincenzo.mecca at 4science.com)
+ **/
+public class DspaceDcTypesBuilder {
+
+ private DspaceDcTypes dcTypes;
+
+ private final ObjectFactory objectFactory = new ObjectFactory();
+
+ private DspaceDcTypes getDcTypes() {
+ if (dcTypes == null) {
+ dcTypes = new DspaceDcTypes();
+ }
+ return dcTypes;
+ }
+
+ private DspaceDcTypesBuilder() {
+ }
+
+ public static DspaceDcTypesBuilder createBuilder() {
+ return new DspaceDcTypesBuilder();
+ }
+
+ public DspaceDcTypesBuilder witheader(DspaceHeader header) {
+ this.getDcTypes().getDspaceHeaderOrDcSchemaOrDcType().add(header);
+ return this;
+ }
+
+ public DspaceDcTypesBuilder withSchema(DcSchema schema) {
+ this.getDcTypes().getDspaceHeaderOrDcSchemaOrDcType().add(schema);
+ return this;
+ }
+
+ public DspaceDcTypesBuilder withDcType(DcType dcType) {
+ this.getDcTypes().getDspaceHeaderOrDcSchemaOrDcType().add(dcType);
+ return this;
+ }
+
+ public DspaceDcTypesBuilder withDcTypes(Collection dcTypes) {
+ this.getDcTypes().getDspaceHeaderOrDcSchemaOrDcType().addAll(dcTypes);
+ return this;
+ }
+
+ public DspaceDcTypes build() {
+ return dcTypes;
+ }
+
+}
diff --git a/dspace-api/src/main/java/org/dspace/app/metadata/export/model/DspaceHeader.java b/dspace-api/src/main/java/org/dspace/app/metadata/export/model/DspaceHeader.java
new file mode 100644
index 00000000000..151c8b28292
--- /dev/null
+++ b/dspace-api/src/main/java/org/dspace/app/metadata/export/model/DspaceHeader.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.app.metadata.export.model;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElementRef;
+import javax.xml.bind.annotation.XmlElementRefs;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+
+/**
+ * Classe Java per anonymous complex type.
+ *
+ *
Il seguente frammento di schema specifica il contenuto previsto contenuto in questa classe.
+ *
+ *
+ * <complexType>
+ * <complexContent>
+ * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * <choice maxOccurs="unbounded" minOccurs="0">
+ * <element ref="{}title"/>
+ * <element ref="{}contributor.author"/>
+ * <element ref="{}contributor.editor"/>
+ * <element ref="{}date.created"/>
+ * <element ref="{}description"/>
+ * <element ref="{}description.version"/>
+ * </choice>
+ * </restriction>
+ * </complexContent>
+ * </complexType>
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "", propOrder = {
+ "titleOrContributorAuthorOrContributorEditor"
+})
+@XmlRootElement(name = "dspace-header")
+public class DspaceHeader {
+
+ @XmlElementRefs({
+ @XmlElementRef(name = "title", type = JAXBElement.class, required = false),
+ @XmlElementRef(name = "contributor.author", type = JAXBElement.class, required = false),
+ @XmlElementRef(name = "contributor.editor", type = JAXBElement.class, required = false),
+ @XmlElementRef(name = "date.created", type = JAXBElement.class, required = false),
+ @XmlElementRef(name = "description", type = JAXBElement.class, required = false),
+ @XmlElementRef(name = "description.version", type = JAXBElement.class, required = false)
+ })
+ protected List> titleOrContributorAuthorOrContributorEditor;
+
+ /**
+ * Gets the value of the titleOrContributorAuthorOrContributorEditor property.
+ *
+ *
+ * This accessor method returns a reference to the live list,
+ * not a snapshot. Therefore any modification you make to the
+ * returned list will be present inside the JAXB object.
+ * This is why there is not a set
method for the titleOrContributorAuthorOrContributorEditor property.
+ *
+ *
+ * For example, to add a new item, do as follows:
+ *
+ * getTitleOrContributorAuthorOrContributorEditor().add(newItem);
+ *
+ *
+ *
+ *
+ * Objects of the following type(s) are allowed in the list
+ * {@link JAXBElement }{@code <}{@link String }{@code >}
+ * {@link JAXBElement }{@code <}{@link String }{@code >}
+ * {@link JAXBElement }{@code <}{@link String }{@code >}
+ * {@link JAXBElement }{@code <}{@link String }{@code >}
+ * {@link JAXBElement }{@code <}{@link String }{@code >}
+ * {@link JAXBElement }{@code <}{@link String }{@code >}
+ */
+ public List> getTitleOrContributorAuthorOrContributorEditor() {
+ if (titleOrContributorAuthorOrContributorEditor == null) {
+ titleOrContributorAuthorOrContributorEditor = new ArrayList>();
+ }
+ return this.titleOrContributorAuthorOrContributorEditor;
+ }
+
+}
diff --git a/dspace-api/src/main/java/org/dspace/app/metadata/export/model/DspaceHeaderBuilder.java b/dspace-api/src/main/java/org/dspace/app/metadata/export/model/DspaceHeaderBuilder.java
new file mode 100644
index 00000000000..fb4028a2057
--- /dev/null
+++ b/dspace-api/src/main/java/org/dspace/app/metadata/export/model/DspaceHeaderBuilder.java
@@ -0,0 +1,59 @@
+/**
+ * The contents of this file are subject to the license and copyright
+ * detailed in the LICENSE and NOTICE files at the root of the source
+ * tree and available online at
+ *
+ * http://www.dspace.org/license/
+ */
+package org.dspace.app.metadata.export.model;
+
+import javax.xml.bind.JAXBElement;
+
+/**
+ * @author Vincenzo Mecca (vins01-4science - vincenzo.mecca at 4science.com)
+ **/
+public class DspaceHeaderBuilder extends AbstractJaxbBuilder {
+
+ protected DspaceHeaderBuilder() {
+ super(DspaceHeader.class);
+ }
+
+ public static DspaceHeaderBuilder createBuilder() {
+ return new DspaceHeaderBuilder();
+ }
+
+ public DspaceHeaderBuilder withTitle(String title) {
+ addChildElement(title, objectFactory::createTitle);
+ return this;
+ }
+
+ public DspaceHeaderBuilder withContributorAuthor(String contributorAuthor) {
+ addChildElement(contributorAuthor, objectFactory::createContributorAuthor);
+ return this;
+ }
+
+ public DspaceHeaderBuilder withContributorEditor(String contributorEditor) {
+ addChildElement(contributorEditor, objectFactory::createContributorEditor);
+ return this;
+ }
+
+ public DspaceHeaderBuilder withDateCreated(String dateCreated) {
+ addChildElement(dateCreated, objectFactory::createDateCreated);
+ return this;
+ }
+
+ public DspaceHeaderBuilder withDescription(String description) {
+ addChildElement(description, objectFactory::createDescription);
+ return this;
+ }
+
+ public DspaceHeaderBuilder withDescriptionVersion(String descriptionVersion) {
+ addChildElement(descriptionVersion, objectFactory::createDescriptionVersion);
+ return this;
+ }
+
+ @Override
+ protected void addChildElement(JAXBElement v) {
+ getObejct().getTitleOrContributorAuthorOrContributorEditor().add(v);
+ }
+}
diff --git a/dspace-api/src/main/java/org/dspace/app/metadata/export/model/ObjectFactory.java b/dspace-api/src/main/java/org/dspace/app/metadata/export/model/ObjectFactory.java
new file mode 100644
index 00000000000..085e8af5f81
--- /dev/null
+++ b/dspace-api/src/main/java/org/dspace/app/metadata/export/model/ObjectFactory.java
@@ -0,0 +1,212 @@
+/**
+ * The contents of this file are subject to the license and copyright
+ * detailed in the LICENSE and NOTICE files at the root of the source
+ * tree and available online at
+ *
+ * http://www.dspace.org/license/
+ */
+package org.dspace.app.metadata.export.model;
+
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.annotation.XmlElementDecl;
+import javax.xml.bind.annotation.XmlRegistry;
+import javax.xml.namespace.QName;
+
+
+/**
+ * This object contains factory methods for each
+ * Java content interface and Java element interface
+ * generated in the org.dspace.app.metadata.export.model package.
+ * An ObjectFactory allows you to programatically
+ * construct new instances of the Java representation
+ * for XML content. The Java representation of XML
+ * content can consist of schema derived interfaces
+ * and classes representing the binding of schema
+ * type definitions, element declarations and model
+ * groups. Factory methods for each of these are
+ * provided in this class.
+ */
+@XmlRegistry
+public class ObjectFactory {
+
+ private final static QName _Title_QNAME = new QName("", "title");
+ private final static QName _ContributorAuthor_QNAME = new QName("", "contributor.author");
+ private final static QName _ContributorEditor_QNAME = new QName("", "contributor.editor");
+ private final static QName _DateCreated_QNAME = new QName("", "date.created");
+ private final static QName _Description_QNAME = new QName("", "description");
+ private final static QName _DescriptionVersion_QNAME = new QName("", "description.version");
+ private final static QName _Name_QNAME = new QName("", "name");
+ private final static QName _Namespace_QNAME = new QName("", "namespace");
+ private final static QName _Schema_QNAME = new QName("", "schema");
+ private final static QName _Element_QNAME = new QName("", "element");
+ private final static QName _Qualifier_QNAME = new QName("", "qualifier");
+ private final static QName _ScopeNote_QNAME = new QName("", "scope_note");
+
+ /**
+ * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: org
+ * .dspace.app.metadata.export.model
+ */
+ public ObjectFactory() {
+ }
+
+ /**
+ * Create an instance of {@link DspaceDcTypes }
+ */
+ public DspaceDcTypes createDspaceDcTypes() {
+ return new DspaceDcTypes();
+ }
+
+ /**
+ * Create an instance of {@link DspaceHeader }
+ */
+ public DspaceHeader createDspaceHeader() {
+ return new DspaceHeader();
+ }
+
+ /**
+ * Create an instance of {@link DcSchema }
+ */
+ public DcSchema createDcSchema() {
+ return new DcSchema();
+ }
+
+ /**
+ * Create an instance of {@link DcType }
+ */
+ public DcType createDcType() {
+ return new DcType();
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link String }{@code >}
+ *
+ * @param value Java instance representing xml element's value.
+ * @return the new instance of {@link JAXBElement }{@code <}{@link String }{@code >}
+ */
+ @XmlElementDecl(namespace = "", name = "title")
+ public JAXBElement createTitle(String value) {
+ return new JAXBElement(_Title_QNAME, String.class, null, value);
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link String }{@code >}
+ *
+ * @param value Java instance representing xml element's value.
+ * @return the new instance of {@link JAXBElement }{@code <}{@link String }{@code >}
+ */
+ @XmlElementDecl(namespace = "", name = "contributor.author")
+ public JAXBElement createContributorAuthor(String value) {
+ return new JAXBElement(_ContributorAuthor_QNAME, String.class, null, value);
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link String }{@code >}
+ *
+ * @param value Java instance representing xml element's value.
+ * @return the new instance of {@link JAXBElement }{@code <}{@link String }{@code >}
+ */
+ @XmlElementDecl(namespace = "", name = "contributor.editor")
+ public JAXBElement createContributorEditor(String value) {
+ return new JAXBElement(_ContributorEditor_QNAME, String.class, null, value);
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link String }{@code >}
+ *
+ * @param value Java instance representing xml element's value.
+ * @return the new instance of {@link JAXBElement }{@code <}{@link String }{@code >}
+ */
+ @XmlElementDecl(namespace = "", name = "date.created")
+ public JAXBElement createDateCreated(String value) {
+ return new JAXBElement(_DateCreated_QNAME, String.class, null, value);
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link String }{@code >}
+ *
+ * @param value Java instance representing xml element's value.
+ * @return the new instance of {@link JAXBElement }{@code <}{@link String }{@code >}
+ */
+ @XmlElementDecl(namespace = "", name = "description")
+ public JAXBElement createDescription(String value) {
+ return new JAXBElement(_Description_QNAME, String.class, null, value);
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link String }{@code >}
+ *
+ * @param value Java instance representing xml element's value.
+ * @return the new instance of {@link JAXBElement }{@code <}{@link String }{@code >}
+ */
+ @XmlElementDecl(namespace = "", name = "description.version")
+ public JAXBElement createDescriptionVersion(String value) {
+ return new JAXBElement(_DescriptionVersion_QNAME, String.class, null, value);
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link String }{@code >}
+ *
+ * @param value Java instance representing xml element's value.
+ * @return the new instance of {@link JAXBElement }{@code <}{@link String }{@code >}
+ */
+ @XmlElementDecl(namespace = "", name = "name")
+ public JAXBElement createName(String value) {
+ return new JAXBElement(_Name_QNAME, String.class, null, value);
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link String }{@code >}
+ *
+ * @param value Java instance representing xml element's value.
+ * @return the new instance of {@link JAXBElement }{@code <}{@link String }{@code >}
+ */
+ @XmlElementDecl(namespace = "", name = "namespace")
+ public JAXBElement createNamespace(String value) {
+ return new JAXBElement(_Namespace_QNAME, String.class, null, value);
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link String }{@code >}
+ *
+ * @param value Java instance representing xml element's value.
+ * @return the new instance of {@link JAXBElement }{@code <}{@link String }{@code >}
+ */
+ @XmlElementDecl(namespace = "", name = "schema")
+ public JAXBElement createSchema(String value) {
+ return new JAXBElement(_Schema_QNAME, String.class, null, value);
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link String }{@code >}
+ *
+ * @param value Java instance representing xml element's value.
+ * @return the new instance of {@link JAXBElement }{@code <}{@link String }{@code >}
+ */
+ @XmlElementDecl(namespace = "", name = "element")
+ public JAXBElement createElement(String value) {
+ return new JAXBElement(_Element_QNAME, String.class, null, value);
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link String }{@code >}
+ *
+ * @param value Java instance representing xml element's value.
+ * @return the new instance of {@link JAXBElement }{@code <}{@link String }{@code >}
+ */
+ @XmlElementDecl(namespace = "", name = "qualifier")
+ public JAXBElement createQualifier(String value) {
+ return new JAXBElement(_Qualifier_QNAME, String.class, null, value);
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link String }{@code >}
+ *
+ * @param value Java instance representing xml element's value.
+ * @return the new instance of {@link JAXBElement }{@code <}{@link String }{@code >}
+ */
+ @XmlElementDecl(namespace = "", name = "scope_note")
+ public JAXBElement createScopeNote(String value) {
+ return new JAXBElement(_ScopeNote_QNAME, String.class, null, value);
+ }
+
+}
diff --git a/dspace-api/src/main/java/org/dspace/app/metadata/export/service/MetadataExportServiceFactory.java b/dspace-api/src/main/java/org/dspace/app/metadata/export/service/MetadataExportServiceFactory.java
new file mode 100644
index 00000000000..3553cbcba2f
--- /dev/null
+++ b/dspace-api/src/main/java/org/dspace/app/metadata/export/service/MetadataExportServiceFactory.java
@@ -0,0 +1,28 @@
+/**
+ * The contents of this file are subject to the license and copyright
+ * detailed in the LICENSE and NOTICE files at the root of the source
+ * tree and available online at
+ *
+ * http://www.dspace.org/license/
+ */
+package org.dspace.app.metadata.export.service;
+
+import org.dspace.services.factory.DSpaceServicesFactory;
+
+/**
+ * Factory for the export services related to metadata-schema and metadata-fields.
+ *
+ * @author Vincenzo Mecca (vins01-4science - vincenzo.mecca at 4science.com)
+ **/
+public abstract class MetadataExportServiceFactory {
+
+ public static MetadataExportServiceFactory getInstance() {
+ return DSpaceServicesFactory
+ .getInstance().getServiceManager()
+ .getServiceByName("metadataExportServiceFactory", MetadataExportServiceFactory.class);
+ }
+
+ public abstract MetadataSchemaExportService getMetadataSchemaExportService();
+ public abstract MetadataFieldExportService getMetadataFieldExportService();
+
+}
diff --git a/dspace-api/src/main/java/org/dspace/app/metadata/export/service/MetadataExportServiceFactoryImpl.java b/dspace-api/src/main/java/org/dspace/app/metadata/export/service/MetadataExportServiceFactoryImpl.java
new file mode 100644
index 00000000000..a69d5dfd0fd
--- /dev/null
+++ b/dspace-api/src/main/java/org/dspace/app/metadata/export/service/MetadataExportServiceFactoryImpl.java
@@ -0,0 +1,31 @@
+/**
+ * The contents of this file are subject to the license and copyright
+ * detailed in the LICENSE and NOTICE files at the root of the source
+ * tree and available online at
+ *
+ * http://www.dspace.org/license/
+ */
+package org.dspace.app.metadata.export.service;
+
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ * @author Vincenzo Mecca (vins01-4science - vincenzo.mecca at 4science.com)
+ **/
+public class MetadataExportServiceFactoryImpl extends MetadataExportServiceFactory {
+
+ @Autowired
+ private MetadataSchemaExportService metadataSchemaExportService;
+ @Autowired
+ private MetadataFieldExportService metadataFieldExportService;
+
+ @Override
+ public MetadataSchemaExportService getMetadataSchemaExportService() {
+ return metadataSchemaExportService;
+ }
+
+ @Override
+ public MetadataFieldExportService getMetadataFieldExportService() {
+ return metadataFieldExportService;
+ }
+}
diff --git a/dspace-api/src/main/java/org/dspace/app/metadata/export/service/MetadataFieldExportService.java b/dspace-api/src/main/java/org/dspace/app/metadata/export/service/MetadataFieldExportService.java
new file mode 100644
index 00000000000..ace31288523
--- /dev/null
+++ b/dspace-api/src/main/java/org/dspace/app/metadata/export/service/MetadataFieldExportService.java
@@ -0,0 +1,35 @@
+/**
+ * The contents of this file are subject to the license and copyright
+ * detailed in the LICENSE and NOTICE files at the root of the source
+ * tree and available online at
+ *
+ * http://www.dspace.org/license/
+ */
+package org.dspace.app.metadata.export.service;
+
+import java.sql.SQLException;
+import java.util.List;
+
+import org.dspace.app.metadata.export.model.DcType;
+import org.dspace.content.MetadataField;
+import org.dspace.content.MetadataSchema;
+import org.dspace.core.Context;
+
+/**
+ * Exports {@code MetadataField} into {@code DcType}
+ *
+ * @author Vincenzo Mecca (vins01-4science - vincenzo.mecca at 4science.com)
+ **/
+public interface MetadataFieldExportService {
+
+ /**
+ * Creates a one {@link DCType} for each {@link MetadataField}
+ * in the given {@link MetadataSchema}, and returns them in a list
+ *
+ * @param context
+ * @param metadataSchema
+ * @return
+ * @throws SQLException
+ */
+ List exportMetadataFieldsBy(Context context, MetadataSchema metadataSchema) throws SQLException;
+}
diff --git a/dspace-api/src/main/java/org/dspace/app/metadata/export/service/MetadataFieldExportServiceImpl.java b/dspace-api/src/main/java/org/dspace/app/metadata/export/service/MetadataFieldExportServiceImpl.java
new file mode 100644
index 00000000000..1ace35f4e45
--- /dev/null
+++ b/dspace-api/src/main/java/org/dspace/app/metadata/export/service/MetadataFieldExportServiceImpl.java
@@ -0,0 +1,49 @@
+/**
+ * The contents of this file are subject to the license and copyright
+ * detailed in the LICENSE and NOTICE files at the root of the source
+ * tree and available online at
+ *
+ * http://www.dspace.org/license/
+ */
+package org.dspace.app.metadata.export.service;
+
+import java.sql.SQLException;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import org.dspace.app.metadata.export.model.DcType;
+import org.dspace.app.metadata.export.model.DcTypeBuilder;
+import org.dspace.content.MetadataField;
+import org.dspace.content.MetadataSchema;
+import org.dspace.content.factory.ContentServiceFactory;
+import org.dspace.content.service.MetadataFieldService;
+import org.dspace.core.Context;
+
+/**
+ * @author Vincenzo Mecca (vins01-4science - vincenzo.mecca at 4science.com)
+ **/
+public class MetadataFieldExportServiceImpl implements MetadataFieldExportService {
+
+ private MetadataFieldService metadataFieldService =
+ ContentServiceFactory.getInstance().getMetadataFieldService();
+
+ public List exportMetadataFieldsBy(Context context, MetadataSchema metadataSchema) throws SQLException {
+ return metadataFieldService
+ .findAllInSchema(context, metadataSchema)
+ .stream()
+ .map(this::toDcType)
+ .collect(Collectors.toList());
+ }
+
+ private DcType toDcType(MetadataField metadataField) {
+ return DcTypeBuilder
+ .createBuilder()
+ .withSchema(metadataField.getMetadataSchema().getName())
+ .withElement(metadataField.getElement())
+ .withQualifier(metadataField.getQualifier())
+ .withScopeNote(metadataField.getScopeNote())
+ .build();
+ }
+
+}
+
diff --git a/dspace-api/src/main/java/org/dspace/app/metadata/export/service/MetadataSchemaExportService.java b/dspace-api/src/main/java/org/dspace/app/metadata/export/service/MetadataSchemaExportService.java
new file mode 100644
index 00000000000..cd1f35e2ef9
--- /dev/null
+++ b/dspace-api/src/main/java/org/dspace/app/metadata/export/service/MetadataSchemaExportService.java
@@ -0,0 +1,68 @@
+/**
+ * The contents of this file are subject to the license and copyright
+ * detailed in the LICENSE and NOTICE files at the root of the source
+ * tree and available online at
+ *
+ * http://www.dspace.org/license/
+ */
+package org.dspace.app.metadata.export.service;
+
+import java.io.File;
+import java.sql.SQLException;
+
+import org.dspace.app.metadata.export.DspaceExportMetadataSchemaException;
+import org.dspace.app.metadata.export.model.DspaceDcTypes;
+import org.dspace.content.MetadataSchema;
+import org.dspace.core.Context;
+
+/**
+ * @author Vincenzo Mecca (vins01-4science - vincenzo.mecca at 4science.com)
+ **/
+public interface MetadataSchemaExportService {
+
+ /**
+ * Exports the given {@code schemaId} into a {@link DspaceDcTypes} entity
+ *
+ * @param context
+ * @param schemaId
+ * @return
+ * @throws SQLException
+ */
+ DspaceDcTypes exportMetadataSchema(Context context, int schemaId) throws SQLException;
+
+ /**
+ * Exports the given {@code metadataSchema} into a {@link DspaceDcTypes} entity
+ *
+ * @param context
+ * @param metadataSchema
+ * @return
+ * @throws SQLException
+ */
+ DspaceDcTypes exportMetadataSchema(Context context, MetadataSchema metadataSchema) throws SQLException;
+
+ /**
+ * Exports the given {@code metadataSchema} to a temporary {@code File},
+ * that will respect the {@code registry} xml format of dspace
+ *
+ * @param context
+ * @param metadataSchema
+ * @return
+ * @throws DspaceExportMetadataSchemaException
+ */
+ File exportMetadataSchemaToFile(Context context, MetadataSchema metadataSchema)
+ throws DspaceExportMetadataSchemaException;
+
+ /**
+ * Exports the given {@code metadataSchema} to a target {@code File},
+ * that will respect the {@code registry} xml format of dspace
+ *
+ * @param context
+ * @param metadataSchema
+ * @param file
+ * @return
+ * @throws DspaceExportMetadataSchemaException
+ */
+ File exportMetadataSchemaToFile(Context context, MetadataSchema metadataSchema, File file)
+ throws DspaceExportMetadataSchemaException;
+
+}
diff --git a/dspace-api/src/main/java/org/dspace/app/metadata/export/service/MetadataSchemaExportServiceImpl.java b/dspace-api/src/main/java/org/dspace/app/metadata/export/service/MetadataSchemaExportServiceImpl.java
new file mode 100644
index 00000000000..eea9a09f797
--- /dev/null
+++ b/dspace-api/src/main/java/org/dspace/app/metadata/export/service/MetadataSchemaExportServiceImpl.java
@@ -0,0 +1,107 @@
+/**
+ * The contents of this file are subject to the license and copyright
+ * detailed in the LICENSE and NOTICE files at the root of the source
+ * tree and available online at
+ *
+ * http://www.dspace.org/license/
+ */
+package org.dspace.app.metadata.export.service;
+
+import java.io.File;
+import java.io.IOException;
+import java.sql.SQLException;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+
+import org.dspace.app.metadata.export.DspaceExportMetadataSchemaException;
+import org.dspace.app.metadata.export.model.DcSchema;
+import org.dspace.app.metadata.export.model.DcSchemaBuilder;
+import org.dspace.app.metadata.export.model.DspaceDcTypes;
+import org.dspace.app.metadata.export.model.DspaceDcTypesBuilder;
+import org.dspace.content.MetadataSchema;
+import org.dspace.content.factory.ContentServiceFactory;
+import org.dspace.content.service.MetadataSchemaService;
+import org.dspace.core.Context;
+
+/**
+ * This service can be used to export a target schema into a registry-file
+ *
+ * @author Vincenzo Mecca (vins01-4science - vincenzo.mecca at 4science.com)
+ **/
+public class MetadataSchemaExportServiceImpl implements MetadataSchemaExportService {
+
+ private MetadataSchemaService metadataSchemaService =
+ ContentServiceFactory.getInstance().getMetadataSchemaService();
+
+ @Override
+ public DspaceDcTypes exportMetadataSchema(Context context, int schemaId) throws SQLException {
+ return this.exportMetadataSchema(context, metadataSchemaService.find(context, schemaId));
+ }
+
+ @Override
+ public DspaceDcTypes exportMetadataSchema(Context context, MetadataSchema metadataSchema) throws SQLException {
+ return DspaceDcTypesBuilder
+ .createBuilder()
+ .withSchema(this.mapToDcSchema(metadataSchema))
+ .withDcTypes(
+ MetadataExportServiceFactory.getInstance()
+ .getMetadataFieldExportService()
+ .exportMetadataFieldsBy(context, metadataSchema)
+ )
+ .build();
+ }
+
+ @Override
+ public File exportMetadataSchemaToFile(Context context, MetadataSchema metadataSchema)
+ throws DspaceExportMetadataSchemaException {
+ File tempFile;
+ try {
+ tempFile =
+ File.createTempFile(
+ metadataSchema.getName() + "-" + metadataSchema.getID(),
+ ".xml"
+ );
+ tempFile.deleteOnExit();
+ return this.exportMetadataSchemaToFile(context, metadataSchema, tempFile);
+ } catch (IOException e) {
+ throw new DspaceExportMetadataSchemaException(
+ "Probelm occured during while exporting to temporary file!",
+ e
+ );
+ }
+ }
+
+ @Override
+ public File exportMetadataSchemaToFile(Context context, MetadataSchema metadataSchema, File file)
+ throws DspaceExportMetadataSchemaException {
+ try {
+ DspaceDcTypes dspaceDcTypes = this.exportMetadataSchema(context, metadataSchema);
+
+ JAXBContext jaxb = JAXBContext.newInstance(DspaceDcTypes.class);
+ Marshaller jaxbMarshaller = jaxb.createMarshaller();
+ jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
+ jaxbMarshaller.marshal(dspaceDcTypes, file);
+ } catch (SQLException e) {
+ throw new DspaceExportMetadataSchemaException(
+ "Problem occured while retrieving data from DB!",
+ e
+ );
+ } catch (JAXBException e) {
+ throw new DspaceExportMetadataSchemaException(
+ "Problem occured during the export to XML file!",
+ e
+ );
+ }
+ return file;
+ }
+
+ private DcSchema mapToDcSchema(MetadataSchema metadataSchema) {
+ return DcSchemaBuilder
+ .createBuilder()
+ .withName(metadataSchema.getName())
+ .withNamespace(metadataSchema.getNamespace())
+ .build();
+ }
+
+}
diff --git a/dspace-api/src/main/java/org/dspace/app/util/DCInputsReader.java b/dspace-api/src/main/java/org/dspace/app/util/DCInputsReader.java
index ac803188023..86b45c36794 100644
--- a/dspace-api/src/main/java/org/dspace/app/util/DCInputsReader.java
+++ b/dspace-api/src/main/java/org/dspace/app/util/DCInputsReader.java
@@ -316,6 +316,9 @@ public List getInputsByGroup(String formName)
// cache miss - construct new DCInputSet
List>> pages = formDefns.get(formName);
+ if (pages == null) {
+ return results;
+ }
Iterator>> iterator = pages.iterator();
diff --git a/dspace-api/src/main/java/org/dspace/app/util/TypeBindUtils.java b/dspace-api/src/main/java/org/dspace/app/util/TypeBindUtils.java
new file mode 100644
index 00000000000..97104bbb63f
--- /dev/null
+++ b/dspace-api/src/main/java/org/dspace/app/util/TypeBindUtils.java
@@ -0,0 +1,73 @@
+/**
+ * The contents of this file are subject to the license and copyright
+ * detailed in the LICENSE and NOTICE files at the root of the source
+ * tree and available online at
+ *
+ * http://www.dspace.org/license/
+ */
+package org.dspace.app.util;
+
+import java.util.List;
+
+import org.apache.commons.lang3.StringUtils;
+import org.dspace.content.InProgressSubmission;
+import org.dspace.content.MetadataValue;
+import org.dspace.content.authority.factory.ContentAuthorityServiceFactory;
+import org.dspace.content.authority.service.MetadataAuthorityService;
+import org.dspace.content.factory.ContentServiceFactory;
+import org.dspace.content.service.ItemService;
+import org.dspace.core.Constants;
+import org.dspace.services.ConfigurationService;
+import org.dspace.services.factory.DSpaceServicesFactory;
+
+/**
+ * Utility methods for the type bind functionality.
+ *
+ * @author Francesco Pio Scognamiglio (francescopio.scognamiglio at 4science.com)
+ *
+ */
+public class TypeBindUtils {
+
+ private static final ConfigurationService configurationService = DSpaceServicesFactory
+ .getInstance().getConfigurationService();
+ private static final ItemService itemService = ContentServiceFactory
+ .getInstance().getItemService();
+ private static final MetadataAuthorityService metadataAuthorityService = ContentAuthorityServiceFactory
+ .getInstance().getMetadataAuthorityService();
+
+ private TypeBindUtils() {}
+
+ /**
+ * This method gets the field used for type-bind.
+ * @return the field used for type-bind.
+ */
+ public static String getTypeBindField() {
+ return configurationService.getProperty("submit.type-bind.field", "dc.type");
+ }
+
+ /**
+ * This method gets the value of the type-bind field from the current item.
+ * @return the value of the type-bind field from the current item.
+ */
+ public static String getTypeBindValue(InProgressSubmission> obj) {
+ List documentType = itemService.getMetadataByMetadataString(
+ obj.getItem(), getTypeBindField());
+
+ // check empty type-bind field
+ if (documentType == null || documentType.isEmpty()
+ || StringUtils.isBlank(documentType.get(0).getValue())) {
+ return null;
+ }
+
+ MetadataValue typeBindValue = documentType.get(0);
+
+ boolean isAuthorityAllowed = metadataAuthorityService.isAuthorityAllowed(
+ getTypeBindField().replace(".","_"), Constants.ITEM, obj.getCollection());
+ if (isAuthorityAllowed && typeBindValue.getAuthority() != null) {
+ return typeBindValue.getAuthority();
+ }
+
+ return typeBindValue.getValue();
+ }
+
+}
diff --git a/dspace-api/src/main/java/org/dspace/authenticate/OrcidAuthenticationBean.java b/dspace-api/src/main/java/org/dspace/authenticate/OrcidAuthenticationBean.java
index f77d7e57119..88797e9b1a7 100644
--- a/dspace-api/src/main/java/org/dspace/authenticate/OrcidAuthenticationBean.java
+++ b/dspace-api/src/main/java/org/dspace/authenticate/OrcidAuthenticationBean.java
@@ -27,7 +27,10 @@
import org.dspace.core.Context;
import org.dspace.eperson.EPerson;
import org.dspace.eperson.Group;
+import org.dspace.eperson.RegistrationData;
+import org.dspace.eperson.RegistrationTypeEnum;
import org.dspace.eperson.service.EPersonService;
+import org.dspace.eperson.service.RegistrationDataService;
import org.dspace.orcid.OrcidToken;
import org.dspace.orcid.client.OrcidClient;
import org.dspace.orcid.client.OrcidConfiguration;
@@ -47,11 +50,15 @@
* ORCID authentication for DSpace.
*
* @author Luca Giamminonni (luca.giamminonni at 4science.it)
- *
*/
public class OrcidAuthenticationBean implements AuthenticationMethod {
+
+ public static final String ORCID_DEFAULT_FIRSTNAME = "Unnamed";
+ public static final String ORCID_DEFAULT_LASTNAME = ORCID_DEFAULT_FIRSTNAME;
public static final String ORCID_AUTH_ATTRIBUTE = "orcid-authentication";
+ public static final String ORCID_REGISTRATION_TOKEN = "orcid-registration-token";
+ public static final String ORCID_DEFAULT_REGISTRATION_URL = "/external-login/{0}";
private final static Logger LOGGER = LoggerFactory.getLogger(OrcidAuthenticationBean.class);
@@ -78,6 +85,9 @@ public class OrcidAuthenticationBean implements AuthenticationMethod {
@Autowired
private OrcidTokenService orcidTokenService;
+ @Autowired
+ private RegistrationDataService registrationDataService;
+
@Override
public int authenticate(Context context, String username, String password, String realm, HttpServletRequest request)
throws SQLException {
@@ -184,7 +194,7 @@ private int authenticateWithOrcid(Context context, String code, HttpServletReque
return ePerson.canLogIn() ? logInEPerson(context, token, ePerson) : BAD_ARGS;
}
- return canSelfRegister() ? registerNewEPerson(context, person, token) : NO_SUCH_USER;
+ return canSelfRegister() ? createRegistrationData(context, request, person, token) : NO_SUCH_USER;
}
@@ -212,48 +222,59 @@ private ResearcherProfile findProfile(Context context, EPerson ePerson) throws S
}
}
- private int registerNewEPerson(Context context, Person person, OrcidTokenResponseDTO token) throws SQLException {
+ private int createRegistrationData(
+ Context context, HttpServletRequest request, Person person, OrcidTokenResponseDTO token
+ ) throws SQLException {
try {
context.turnOffAuthorisationSystem();
- String email = getEmail(person)
- .orElseThrow(() -> new IllegalStateException("The email is configured private on orcid"));
-
- String orcid = token.getOrcid();
-
- EPerson eperson = ePersonService.create(context);
+ RegistrationData registrationData =
+ this.registrationDataService.create(context, token.getOrcid(), RegistrationTypeEnum.ORCID);
- eperson.setNetid(orcid);
+ registrationData.setEmail(getEmail(person).orElse(null));
+ setOrcidMetadataOnRegistration(context, registrationData, person, token);
- eperson.setEmail(email);
+ registrationDataService.update(context, registrationData);
- Optional firstName = getFirstName(person);
- if (firstName.isPresent()) {
- eperson.setFirstName(context, firstName.get());
- }
-
- Optional lastName = getLastName(person);
- if (lastName.isPresent()) {
- eperson.setLastName(context, lastName.get());
- }
- eperson.setCanLogIn(true);
- eperson.setSelfRegistered(true);
-
- setOrcidMetadataOnEPerson(context, eperson, token);
-
- ePersonService.update(context, eperson);
- context.setCurrentUser(eperson);
+ request.setAttribute(ORCID_REGISTRATION_TOKEN, registrationData.getToken());
+ context.commit();
context.dispatchEvents();
- return SUCCESS;
-
} catch (Exception ex) {
LOGGER.error("An error occurs registering a new EPerson from ORCID", ex);
context.rollback();
- return NO_SUCH_USER;
} finally {
context.restoreAuthSystemState();
+ return NO_SUCH_USER;
+ }
+ }
+
+ private void setOrcidMetadataOnRegistration(
+ Context context, RegistrationData registration, Person person, OrcidTokenResponseDTO token
+ ) throws SQLException, AuthorizeException {
+ String orcid = token.getOrcid();
+
+ setRegistrationMetadata(context, registration, "eperson.firstname", getFirstName(person));
+ setRegistrationMetadata(context, registration, "eperson.lastname", getLastName(person));
+ registrationDataService.setRegistrationMetadataValue(context, registration, "eperson", "orcid", null, orcid);
+
+ for (String scope : token.getScopeAsArray()) {
+ registrationDataService.addMetadata(context, registration, "eperson", "orcid", "scope", scope);
+ }
+ }
+
+ private void setRegistrationMetadata(
+ Context context, RegistrationData registration, String metadataString, String value) {
+ String[] split = metadataString.split("\\.");
+ String qualifier = split.length > 2 ? split[2] : null;
+ try {
+ registrationDataService.setRegistrationMetadataValue(
+ context, registration, split[0], split[1], qualifier, value
+ );
+ } catch (SQLException | AuthorizeException ex) {
+ LOGGER.error("An error occurs setting metadata", ex);
+ throw new RuntimeException(ex);
}
}
@@ -296,16 +317,20 @@ private Optional getEmail(Person person) {
return Optional.ofNullable(emails.get(0).getEmail());
}
- private Optional getFirstName(Person person) {
+ private String getFirstName(Person person) {
return Optional.ofNullable(person.getName())
- .map(name -> name.getGivenNames())
- .map(givenNames -> givenNames.getContent());
+ .map(name -> name.getGivenNames())
+ .map(givenNames -> givenNames.getContent())
+ .filter(StringUtils::isNotBlank)
+ .orElse(ORCID_DEFAULT_FIRSTNAME);
}
- private Optional getLastName(Person person) {
+ private String getLastName(Person person) {
return Optional.ofNullable(person.getName())
- .map(name -> name.getFamilyName())
- .map(givenNames -> givenNames.getContent());
+ .map(name -> name.getFamilyName())
+ .map(givenNames -> givenNames.getContent())
+ .filter(StringUtils::isNotBlank)
+ .orElse(ORCID_DEFAULT_LASTNAME);
}
private boolean canSelfRegister() {
diff --git a/dspace-api/src/main/java/org/dspace/authority/CrisConsumer.java b/dspace-api/src/main/java/org/dspace/authority/CrisConsumer.java
index eec4412c0c9..f5d88e1045e 100644
--- a/dspace-api/src/main/java/org/dspace/authority/CrisConsumer.java
+++ b/dspace-api/src/main/java/org/dspace/authority/CrisConsumer.java
@@ -255,7 +255,7 @@ private String getFieldKey(MetadataValue metadata) {
private Item buildRelatedItem(Context context, Item item, Collection collection, MetadataValue metadata,
String entityType, String crisSourceId) throws Exception {
- WorkspaceItem workspaceItem = workspaceItemService.create(context, collection, false);
+ WorkspaceItem workspaceItem = workspaceItemService.create(context, collection, useOfTemplate(metadata));
Item relatedItem = workspaceItem.getItem();
itemService.addMetadata(context, relatedItem, CRIS.getName(), "sourceId", null, null, crisSourceId);
if (!hasEntityType(relatedItem, entityType)) {
@@ -299,6 +299,17 @@ private boolean isSubmissionEnabled(MetadataValue value) {
}
}
+ private boolean useOfTemplate(MetadataValue value) {
+
+ String useOfTemplateByMetadata = "cris.import.submission.enabled.entity."
+ + getFieldKey(value) + ".use-template";
+ if (configurationService.hasProperty(useOfTemplateByMetadata)) {
+ return configurationService.getBooleanProperty(useOfTemplateByMetadata);
+ }
+
+ return configurationService.getBooleanProperty("cris.import.submission.enabled.entity.use-template");
+ }
+
private void fillRelatedItem(Context context, MetadataValue metadata, Item relatedItem, boolean alreadyPresent)
throws SQLException {
diff --git a/dspace-api/src/main/java/org/dspace/content/BitstreamServiceImpl.java b/dspace-api/src/main/java/org/dspace/content/BitstreamServiceImpl.java
index f2a8680ee58..b07f23ee23f 100644
--- a/dspace-api/src/main/java/org/dspace/content/BitstreamServiceImpl.java
+++ b/dspace-api/src/main/java/org/dspace/content/BitstreamServiceImpl.java
@@ -7,12 +7,15 @@
*/
package org.dspace.content;
+import static org.apache.commons.lang.StringUtils.startsWith;
+
import java.io.IOException;
import java.io.InputStream;
import java.sql.SQLException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.Spliterators;
import java.util.UUID;
import java.util.regex.Pattern;
@@ -606,4 +609,63 @@ private Stream streamOf(Iterator iterator) {
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, 0), false);
}
+ @Override
+ public boolean isOriginalBitstream(DSpaceObject dso) throws SQLException {
+
+ if (dso.getType() != Constants.BITSTREAM) {
+ return false;
+ }
+
+ Bitstream bitstream = (Bitstream) dso;
+
+ return bitstream.getBundles().stream()
+ .anyMatch(bundle -> "ORIGINAL".equals(bundle.getName()));
+
+ }
+
+ @Override
+ public void updateThumbnailResourcePolicies(Context context, Bitstream bitstream) throws SQLException {
+ getThumbnail(bitstream)
+ .ifPresent(thumbnail -> replacePolicies(context, bitstream, thumbnail));
+ }
+
+ private void replacePolicies(Context context, Bitstream bitstream, Bitstream thumbnail) {
+ try {
+ authorizeService.replaceAllPolicies(context, bitstream, thumbnail);
+ } catch (SQLException | AuthorizeException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private Optional getThumbnail(Bitstream bitstream) throws SQLException {
+ return getItem(bitstream)
+ .flatMap(item -> getThumbnail(item, bitstream.getName()));
+ }
+
+ private Optional- getItem(Bitstream bitstream) throws SQLException {
+ return bitstream.getBundles().stream()
+ .flatMap(bundle -> bundle.getItems().stream())
+ .findFirst();
+ }
+
+ private Optional
getThumbnail(Item item, String name) {
+ List bundles = getThumbnailBundles(item);
+ if (CollectionUtils.isEmpty(bundles)) {
+ return Optional.empty();
+ }
+
+ return bundles.stream()
+ .flatMap(bundle -> bundle.getBitstreams().stream())
+ .filter(bitstream -> startsWith(bitstream.getName(), name))
+ .findFirst();
+ }
+
+ private List getThumbnailBundles(Item item) {
+ try {
+ return itemService.getBundles(item, "THUMBNAIL");
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
}
diff --git a/dspace-api/src/main/java/org/dspace/content/authority/ChoiceAuthorityServiceImpl.java b/dspace-api/src/main/java/org/dspace/content/authority/ChoiceAuthorityServiceImpl.java
index 6e080045739..cbc92c3be5f 100644
--- a/dspace-api/src/main/java/org/dspace/content/authority/ChoiceAuthorityServiceImpl.java
+++ b/dspace-api/src/main/java/org/dspace/content/authority/ChoiceAuthorityServiceImpl.java
@@ -7,6 +7,7 @@
*/
package org.dspace.content.authority;
+import static java.lang.Integer.MAX_VALUE;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import java.util.ArrayList;
@@ -21,6 +22,7 @@
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
+import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dspace.app.util.DCInput;
import org.dspace.app.util.DCInputSet;
@@ -64,7 +66,7 @@
* @see ChoiceAuthority
*/
public final class ChoiceAuthorityServiceImpl implements ChoiceAuthorityService {
- private Logger log = org.apache.logging.log4j.LogManager.getLogger(ChoiceAuthorityServiceImpl.class);
+ private Logger log = LogManager.getLogger(ChoiceAuthorityServiceImpl.class);
// map of field key to authority plugin
protected Map controller = new HashMap();
@@ -343,16 +345,26 @@ private void loadChoiceAuthorityConfigurations() {
*/
private void autoRegisterChoiceAuthorityFromInputReader() {
try {
- List submissionConfigs = itemSubmissionConfigReader
- .getAllSubmissionConfigs(Integer.MAX_VALUE, 0);
+ List submissionConfigs = itemSubmissionConfigReader.getAllSubmissionConfigs(MAX_VALUE, 0);
DCInputsReader dcInputsReader = new DCInputsReader();
// loop over all the defined item submission configuration
for (SubmissionConfig subCfg : submissionConfigs) {
String submissionName = subCfg.getSubmissionName();
List inputsBySubmissionName = dcInputsReader.getInputsBySubmissionName(submissionName);
- autoRegisterChoiceAuthorityFromSubmissionForms(Constants.ITEM, submissionName,
- inputsBySubmissionName);
+ List inputsByGroupOfAllSteps = new ArrayList();
+ try {
+ List inputsByGroup = dcInputsReader.getInputsByGroup(submissionName);
+ inputsByGroupOfAllSteps.addAll(inputsByGroup);
+ for (DCInputSet step : inputsBySubmissionName) {
+ List inputsByGroupOfStep = dcInputsReader.getInputsByGroup(step.getFormName());
+ inputsByGroupOfAllSteps.addAll(inputsByGroupOfStep);
+ }
+ } catch (DCInputsReaderException e) {
+ log.warn("Cannot load the groups of the submission: " + submissionName, e);
+ }
+ inputsBySubmissionName.addAll(inputsByGroupOfAllSteps);
+ autoRegisterChoiceAuthorityFromSubmissionForms(Constants.ITEM, submissionName, inputsBySubmissionName);
}
// loop over all the defined bitstream metadata submission configuration
for (UploadConfiguration uploadCfg : uploadConfigurationService.getMap().values()) {
@@ -363,8 +375,7 @@ private void autoRegisterChoiceAuthorityFromInputReader() {
}
} catch (DCInputsReaderException e) {
// the system is in an illegal state as the submission definition is not valid
- throw new IllegalStateException("Error reading the item submission configuration: " + e.getMessage(),
- e);
+ throw new IllegalStateException("Error reading the item submission configuration: " + e.getMessage(), e);
}
}
diff --git a/dspace-api/src/main/java/org/dspace/content/authority/DCInputAuthority.java b/dspace-api/src/main/java/org/dspace/content/authority/DCInputAuthority.java
index 9695f9c3255..ca9f42f13a3 100644
--- a/dspace-api/src/main/java/org/dspace/content/authority/DCInputAuthority.java
+++ b/dspace-api/src/main/java/org/dspace/content/authority/DCInputAuthority.java
@@ -48,6 +48,8 @@
* fields.
*/
public class DCInputAuthority extends SelfNamedPlugin implements ChoiceAuthority {
+ public static final String UNKNOWN_KEY = "UNKNOWN KEY ";
+
private static Logger log = org.apache.logging.log4j.LogManager.getLogger(DCInputAuthority.class);
/**
@@ -92,7 +94,7 @@ public static String[] getPluginNames() {
initPluginNames();
}
- return (String[]) ArrayUtils.clone(pluginNames);
+ return ArrayUtils.clone(pluginNames);
}
private static synchronized void initPluginNames() {
@@ -205,17 +207,17 @@ public String getLabel(String key, String locale) {
String[] labelsLocale = labels.get(locale);
int pos = -1;
// search in the values to return the label
- for (int i = 0; i < valuesLocale.length; i++) {
+ for (int i = 0; valuesLocale != null && i < valuesLocale.length; i++) {
if (valuesLocale[i].equals(key)) {
pos = i;
break;
}
}
- if (pos != -1) {
+ if (pos != -1 && labelsLocale != null) {
// return the label in the same position where we found the value
return labelsLocale[pos];
} else {
- return "UNKNOWN KEY " + key;
+ return UNKNOWN_KEY + key;
}
}
diff --git a/dspace-api/src/main/java/org/dspace/content/authority/ItemAuthority.java b/dspace-api/src/main/java/org/dspace/content/authority/ItemAuthority.java
index 6ec39db9764..173ea83f62a 100644
--- a/dspace-api/src/main/java/org/dspace/content/authority/ItemAuthority.java
+++ b/dspace-api/src/main/java/org/dspace/content/authority/ItemAuthority.java
@@ -42,6 +42,7 @@
import org.dspace.util.ItemAuthorityUtils;
import org.dspace.util.UUIDUtils;
import org.dspace.utils.DSpace;
+import org.dspace.web.ContextUtil;
/**
* Sample authority to link a dspace item with another (i.e a publication with
@@ -58,7 +59,7 @@ public class ItemAuthority implements ChoiceAuthority, LinkableEntityAuthority {
/** the name assigned to the specific instance by the PluginService, @see {@link NameAwarePlugin} **/
private String authorityName;
- private DSpace dspace = new DSpace();
+ protected DSpace dspace = new DSpace();
protected ItemService itemService = ContentServiceFactory.getInstance().getItemService();
@@ -181,9 +182,8 @@ private List getChoiceListFromQueryResults(SolrDocumentList results, Str
public String getLabel(String key, String locale) {
String title = key;
if (key != null) {
- Context context = null;
+ Context context = getContext();
try {
- context = new Context();
DSpaceObject dso = itemService.find(context, UUIDUtils.fromString(key));
if (dso != null) {
title = dso.getName();
@@ -292,4 +292,9 @@ private boolean hasValidExternalSource(String sourceIdentifier) {
return false;
}
+ private Context getContext() {
+ Context context = ContextUtil.obtainCurrentRequestContext();
+ return context != null ? context : new Context();
+ }
+
}
diff --git a/dspace-api/src/main/java/org/dspace/content/authority/RorOrgUnitAuthority.java b/dspace-api/src/main/java/org/dspace/content/authority/RorOrgUnitAuthority.java
new file mode 100644
index 00000000000..09f7330b62f
--- /dev/null
+++ b/dspace-api/src/main/java/org/dspace/content/authority/RorOrgUnitAuthority.java
@@ -0,0 +1,86 @@
+/**
+ * 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.authority;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import org.dspace.content.authority.factory.ItemAuthorityServiceFactory;
+import org.dspace.ror.ROROrgUnitDTO;
+import org.dspace.ror.service.RORApiService;
+import org.dspace.ror.service.RORApiServiceImpl;
+import org.dspace.services.ConfigurationService;
+import org.dspace.services.factory.DSpaceServicesFactory;
+
+public class RorOrgUnitAuthority extends ItemAuthority {
+
+ private final RORApiService rorApiService = dspace.getSingletonService(RORApiServiceImpl.class);
+ private final ItemAuthorityServiceFactory itemAuthorityServiceFactory =
+ dspace.getServiceManager().getServiceByName("itemAuthorityServiceFactory", ItemAuthorityServiceFactory.class);
+ private final ConfigurationService configurationService =
+ DSpaceServicesFactory.getInstance().getConfigurationService();
+
+ private String authorityName;
+
+ @Override
+ public Choices getMatches(String text, int start, int limit, String locale) {
+ super.setPluginInstanceName(authorityName);
+ Choices solrChoices = super.getMatches(text, start, limit, locale);
+
+ return solrChoices.values.length == 0 ? getRORApiMatches(text, start, limit) : solrChoices;
+ }
+
+ private Choices getRORApiMatches(String text, int start, int limit) {
+ Choice[] rorApiChoices = getChoiceFromRORQueryResults(
+ rorApiService.getOrgUnits(text).stream()
+ .filter(ou -> "active".equals(ou.getStatus()))
+ .collect(Collectors.toList())
+ ).toArray(new Choice[0]);
+
+ int confidenceValue = itemAuthorityServiceFactory.getInstance(authorityName)
+ .getConfidenceForChoices(rorApiChoices);
+
+ return new Choices(rorApiChoices, start, rorApiChoices.length, confidenceValue,
+ rorApiChoices.length > (start + limit), 0);
+ }
+
+ private List getChoiceFromRORQueryResults(List orgUnits) {
+ return orgUnits
+ .stream()
+ .map(orgUnit -> new Choice(composeAuthorityValue(orgUnit.getIdentifier()), orgUnit.getName(),
+ orgUnit.getName(), buildExtras(orgUnit)))
+ .collect(Collectors.toList());
+ }
+
+ private Map buildExtras(ROROrgUnitDTO orgUnit) {
+ return new HashMap<>();
+ }
+
+ private String composeAuthorityValue(String rorId) {
+ String prefix = configurationService.getProperty("ror.authority.prefix", "will be referenced::ROR-ID::");
+ return prefix + rorId;
+ }
+
+ @Override
+ public String getLinkedEntityType() {
+ return configurationService.getProperty("cris.ItemAuthority." + authorityName + ".entityType");
+ }
+
+ @Override
+ public void setPluginInstanceName(String name) {
+ authorityName = name;
+ }
+
+ @Override
+ public String getPluginInstanceName() {
+ return authorityName;
+ }
+}
diff --git a/dspace-api/src/main/java/org/dspace/content/dto/MetadataValueDTO.java b/dspace-api/src/main/java/org/dspace/content/dto/MetadataValueDTO.java
index 630efd5b028..7bfa8504f90 100644
--- a/dspace-api/src/main/java/org/dspace/content/dto/MetadataValueDTO.java
+++ b/dspace-api/src/main/java/org/dspace/content/dto/MetadataValueDTO.java
@@ -69,6 +69,14 @@ public MetadataValueDTO(String schema, String element, String qualifier, String
this.confidence = confidence;
}
+ public MetadataValueDTO(String metadataField, String value) {
+ MetadataFieldName fieldName = new MetadataFieldName(metadataField);
+ this.schema = fieldName.schema;
+ this.element = fieldName.element;
+ this.qualifier = fieldName.qualifier;
+ this.value = value;
+ }
+
/**
* Constructor for the MetadataValueDTO class
* @param schema The schema to be assigned to this MetadataValueDTO object
diff --git a/dspace-api/src/main/java/org/dspace/content/edit/CorrectItemMode.java b/dspace-api/src/main/java/org/dspace/content/edit/CorrectItemMode.java
index b374861db9a..2945065db4e 100644
--- a/dspace-api/src/main/java/org/dspace/content/edit/CorrectItemMode.java
+++ b/dspace-api/src/main/java/org/dspace/content/edit/CorrectItemMode.java
@@ -10,6 +10,7 @@
import java.util.ArrayList;
import java.util.List;
+import org.dspace.content.logic.Filter;
import org.dspace.content.security.AccessItemMode;
import org.dspace.content.security.CrisSecurity;
@@ -42,6 +43,7 @@ public class CorrectItemMode implements AccessItemMode {
* Contains the list of users metadata for CUSTOM security
*/
private List items = new ArrayList();
+ private Filter additionalFilter;
@Override
public List getSecurities() {
@@ -87,4 +89,13 @@ public void setItems(List items) {
public List getGroups() {
return groups;
}
+
+ public void setAdditionalFilter(Filter additionalFilter) {
+ this.additionalFilter = additionalFilter;
+ }
+
+ @Override
+ public Filter getAdditionalFilter() {
+ return additionalFilter;
+ }
}
diff --git a/dspace-api/src/main/java/org/dspace/content/edit/EditItemMode.java b/dspace-api/src/main/java/org/dspace/content/edit/EditItemMode.java
index 4d56ddafe73..6f6b33ecaa2 100644
--- a/dspace-api/src/main/java/org/dspace/content/edit/EditItemMode.java
+++ b/dspace-api/src/main/java/org/dspace/content/edit/EditItemMode.java
@@ -9,6 +9,7 @@
import java.util.List;
+import org.dspace.content.logic.Filter;
import org.dspace.content.security.AccessItemMode;
import org.dspace.content.security.CrisSecurity;
@@ -49,6 +50,7 @@ public class EditItemMode implements AccessItemMode {
* Contains the list of items metadata for CUSTOM security
*/
private List items;
+ private Filter additionalFilter;
@Override
public List getSecurities() {
@@ -100,6 +102,15 @@ public void setItems(List items) {
this.items = items;
}
+ public void setAdditionalFilter(Filter additionalFilter) {
+ this.additionalFilter = additionalFilter;
+ }
+
+ @Override
+ public Filter getAdditionalFilter() {
+ return additionalFilter;
+ }
+
@Override
public List getGroups() {
return groups;
diff --git a/dspace-api/src/main/java/org/dspace/content/enhancer/impl/RelatedEntityItemEnhancer.java b/dspace-api/src/main/java/org/dspace/content/enhancer/impl/RelatedEntityItemEnhancer.java
index a5d95582e41..a6c97cc84e6 100644
--- a/dspace-api/src/main/java/org/dspace/content/enhancer/impl/RelatedEntityItemEnhancer.java
+++ b/dspace-api/src/main/java/org/dspace/content/enhancer/impl/RelatedEntityItemEnhancer.java
@@ -78,7 +78,7 @@ private void cleanObsoleteVirtualFields(Context context, Item item) throws SQLEx
}
private void updateVirtualFieldsPlaces(Context context, Item item) {
- List virtualSourceFields = getMetadataValues(item, getVirtualSourceMetadataField());
+ List virtualSourceFields = getVirtualSourceFields(item);
for (MetadataValue virtualSourceField : virtualSourceFields) {
metadataWithPlaceToUpdate(item, virtualSourceField)
.ifPresent(updatePlaces(item, virtualSourceField));
@@ -113,9 +113,9 @@ private List getObsoleteVirtualFields(Item item) {
List obsoleteVirtualFields = new ArrayList<>();
- List virtualSourceFields = getMetadataValues(item, getVirtualSourceMetadataField());
+ List virtualSourceFields = getVirtualSourceFields(item);
for (MetadataValue virtualSourceField : virtualSourceFields) {
- if (isRelatedSourceNoMorePresent(item, virtualSourceField)) {
+ if (!isPlaceholder(virtualSourceField) && isRelatedSourceNoMorePresent(item, virtualSourceField)) {
obsoleteVirtualFields.add(virtualSourceField);
getRelatedVirtualField(item, virtualSourceField).ifPresent(obsoleteVirtualFields::add);
}
@@ -131,7 +131,7 @@ private boolean isRelatedSourceNoMorePresent(Item item, MetadataValue virtualSou
}
private Optional getRelatedVirtualField(Item item, MetadataValue virtualSourceField) {
- return getMetadataValues(item, getVirtualMetadataField()).stream()
+ return getVirtualFields(item).stream()
.filter(metadataValue -> metadataValue.getPlace() == virtualSourceField.getPlace())
.findFirst();
}
@@ -141,6 +141,7 @@ private void performEnhancement(Context context, Item item) throws SQLException
if (noEnhanceableMetadata(context, item)) {
return;
}
+
for (MetadataValue metadataValue : getEnhanceableMetadataValue(item)) {
if (wasValueAlreadyUsedForEnhancement(item, metadataValue)) {
@@ -191,9 +192,19 @@ private List getEnhanceableMetadataValue(Item item) {
}
private boolean wasValueAlreadyUsedForEnhancement(Item item, MetadataValue metadataValue) {
- return getMetadataValues(item, getVirtualSourceMetadataField()).stream()
+
+ if (isPlaceholderAtPlace(getVirtualFields(item), metadataValue.getPlace())) {
+ return true;
+ }
+
+ return getVirtualSourceFields(item).stream()
.anyMatch(virtualSourceField -> virtualSourceField.getPlace() == metadataValue.getPlace()
&& hasAuthorityEqualsTo(metadataValue, virtualSourceField.getValue()));
+
+ }
+
+ private boolean isPlaceholderAtPlace(List metadataValues, int place) {
+ return place < metadataValues.size() ? isPlaceholder(metadataValues.get(place)) : false;
}
private boolean hasAuthorityEqualsTo(MetadataValue metadataValue, String authority) {
@@ -209,10 +220,22 @@ private Item findRelatedEntityItem(Context context, MetadataValue metadataValue)
}
}
+ private boolean isPlaceholder(MetadataValue metadataValue) {
+ return PLACEHOLDER_PARENT_METADATA_VALUE.equals(metadataValue.getValue());
+ }
+
private List getMetadataValues(Item item, String metadataField) {
return itemService.getMetadataByMetadataString(item, metadataField);
}
+ private List getVirtualSourceFields(Item item) {
+ return getMetadataValues(item, getVirtualSourceMetadataField());
+ }
+
+ private List getVirtualFields(Item item) {
+ return getMetadataValues(item, getVirtualMetadataField());
+ }
+
private void addVirtualField(Context context, Item item, String value) throws SQLException {
itemService.addMetadata(context, item, VIRTUAL_METADATA_SCHEMA, VIRTUAL_METADATA_ELEMENT,
getVirtualQualifier(), null, value);
diff --git a/dspace-api/src/main/java/org/dspace/content/integration/crosswalks/XlsCrosswalk.java b/dspace-api/src/main/java/org/dspace/content/integration/crosswalks/XlsCrosswalk.java
index 026b6f375df..cbbfee4fb49 100644
--- a/dspace-api/src/main/java/org/dspace/content/integration/crosswalks/XlsCrosswalk.java
+++ b/dspace-api/src/main/java/org/dspace/content/integration/crosswalks/XlsCrosswalk.java
@@ -11,6 +11,7 @@
import java.io.OutputStream;
import java.util.List;
+import org.apache.commons.lang.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
@@ -45,7 +46,7 @@ protected void writeRows(List> rows, OutputStream out) {
int cellCount = 0;
for (String field : row) {
Cell cell = sheetRow.createCell(cellCount++);
- cell.setCellValue(field);
+ cell.setCellValue(StringUtils.length(field) > 32726 ? field.substring(0, 32725) + "…" : field );
}
}
diff --git a/dspace-api/src/main/java/org/dspace/content/integration/crosswalks/script/ItemExport.java b/dspace-api/src/main/java/org/dspace/content/integration/crosswalks/script/ItemExport.java
index d52287ad363..43b5d0b0971 100644
--- a/dspace-api/src/main/java/org/dspace/content/integration/crosswalks/script/ItemExport.java
+++ b/dspace-api/src/main/java/org/dspace/content/integration/crosswalks/script/ItemExport.java
@@ -10,6 +10,7 @@
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.sql.SQLException;
+import java.util.Objects;
import java.util.UUID;
import org.apache.commons.cli.ParseException;
@@ -67,6 +68,7 @@ public void internalRun() throws Exception {
context = new Context(Context.Mode.READ_ONLY);
assignCurrentUserInContext();
+ assignHandlerLocaleInContext();
assignSpecialGroupsInContext();
if (exportFormat == null) {
@@ -140,6 +142,16 @@ private void assignSpecialGroupsInContext() throws SQLException {
}
}
+ private void assignHandlerLocaleInContext() {
+ if (Objects.nonNull(this.handler) &&
+ Objects.nonNull(this.context) &&
+ Objects.nonNull(this.handler.getLocale()) &&
+ !this.handler.getLocale().equals(this.context.getCurrentLocale())
+ ) {
+ this.context.setCurrentLocale(this.handler.getLocale());
+ }
+ }
+
private StreamDisseminationCrosswalk getCrosswalkByType(String type) {
return new DSpace().getSingletonService(StreamDisseminationCrosswalkMapper.class).getByType(type);
}
diff --git a/dspace-api/src/main/java/org/dspace/content/integration/crosswalks/virtualfields/ItemDOIService.java b/dspace-api/src/main/java/org/dspace/content/integration/crosswalks/virtualfields/ItemDOIService.java
new file mode 100644
index 00000000000..03229f634a6
--- /dev/null
+++ b/dspace-api/src/main/java/org/dspace/content/integration/crosswalks/virtualfields/ItemDOIService.java
@@ -0,0 +1,59 @@
+/**
+ * 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.integration.crosswalks.virtualfields;
+
+import java.util.Comparator;
+import java.util.List;
+
+import org.dspace.content.Item;
+import org.dspace.content.MetadataValue;
+import org.dspace.content.service.ItemService;
+import org.dspace.services.ConfigurationService;
+import org.springframework.beans.factory.annotation.Autowired;
+
+
+public class ItemDOIService {
+ static final String CFG_PREFIX = "identifier.doi.prefix";
+
+ static final String DOI_METADATA = "dc.identifier.doi";
+
+ @Autowired
+ protected ItemService itemService;
+ @Autowired
+ private ConfigurationService configurationService;
+
+ public String[] getAlternativeDOIFromItem(Item item) {
+ List metadataValueList = itemService.getMetadataByMetadataString(item, DOI_METADATA);
+ return getAlternativeDOI(metadataValueList, getPrimaryDOI(metadataValueList));
+ }
+ private String[] getAlternativeDOI(List metadataValueList, String primaryValue) {
+ return metadataValueList.stream().map(MetadataValue::getValue)
+ .filter(value -> !value.equals(primaryValue)).toArray(String[]::new);
+ }
+
+ public String getPrimaryDOIFromItem(Item item) {
+ return getPrimaryDOI(itemService.getMetadataByMetadataString(item, DOI_METADATA));
+ }
+
+ private String getPrimaryDOI(List metadataValueList) {
+ return metadataValueList.stream().filter(metadata -> metadata.getValue().contains(getPrefix()))
+ .min(Comparator.comparingInt(MetadataValue::getPlace)).map(MetadataValue::getValue)
+ .orElse(!metadataValueList.isEmpty() ? metadataValueList.get(0).getValue() : null);
+ }
+
+ protected String getPrefix() {
+ String prefix;
+ prefix = this.configurationService.getProperty(CFG_PREFIX);
+ if (null == prefix) {
+ throw new RuntimeException("Unable to load DOI prefix from "
+ + "configuration. Cannot find property " +
+ CFG_PREFIX + ".");
+ }
+ return prefix;
+ }
+}
diff --git a/dspace-api/src/main/java/org/dspace/content/integration/crosswalks/virtualfields/VirtualFieldAlternativeDOI.java b/dspace-api/src/main/java/org/dspace/content/integration/crosswalks/virtualfields/VirtualFieldAlternativeDOI.java
new file mode 100644
index 00000000000..3966566196c
--- /dev/null
+++ b/dspace-api/src/main/java/org/dspace/content/integration/crosswalks/virtualfields/VirtualFieldAlternativeDOI.java
@@ -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/
+ */
+package org.dspace.content.integration.crosswalks.virtualfields;
+
+import org.apache.commons.lang3.StringUtils;
+import org.dspace.content.Item;
+import org.dspace.core.Context;
+import org.springframework.beans.factory.annotation.Autowired;
+
+
+public class VirtualFieldAlternativeDOI implements VirtualField {
+
+ @Autowired
+ private ItemDOIService itemDOIService;
+
+ @Override
+ public String[] getMetadata(Context context, Item item, String fieldName) {
+ String[] qualifiers = StringUtils.split(fieldName, ".");
+ if (qualifiers.length != 3) {
+ throw new IllegalArgumentException("Invalid field name " + fieldName);
+ }
+
+ return itemDOIService.getAlternativeDOIFromItem(item);
+ }
+}
diff --git a/dspace-api/src/main/java/org/dspace/content/integration/crosswalks/virtualfields/VirtualFieldPrimaryDOI.java b/dspace-api/src/main/java/org/dspace/content/integration/crosswalks/virtualfields/VirtualFieldPrimaryDOI.java
new file mode 100644
index 00000000000..3039ded0df8
--- /dev/null
+++ b/dspace-api/src/main/java/org/dspace/content/integration/crosswalks/virtualfields/VirtualFieldPrimaryDOI.java
@@ -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/
+ */
+package org.dspace.content.integration.crosswalks.virtualfields;
+
+import org.apache.commons.lang3.StringUtils;
+import org.dspace.content.Item;
+import org.dspace.core.Context;
+import org.springframework.beans.factory.annotation.Autowired;
+
+
+public class VirtualFieldPrimaryDOI implements VirtualField {
+
+ @Autowired
+ private ItemDOIService itemDOIService;
+
+ @Override
+ public String[] getMetadata(Context context, Item item, String fieldName) {
+ String[] qualifiers = StringUtils.split(fieldName, ".");
+ if (qualifiers.length != 3) {
+ throw new IllegalArgumentException("Invalid field name " + fieldName);
+ }
+
+ return new String[] {itemDOIService.getPrimaryDOIFromItem(item)};
+ }
+}
diff --git a/dspace-api/src/main/java/org/dspace/content/integration/crosswalks/virtualfields/VirtualFieldVocabularyI18nValuePair.java b/dspace-api/src/main/java/org/dspace/content/integration/crosswalks/virtualfields/VirtualFieldVocabularyI18nValuePair.java
new file mode 100644
index 00000000000..89d9181c20b
--- /dev/null
+++ b/dspace-api/src/main/java/org/dspace/content/integration/crosswalks/virtualfields/VirtualFieldVocabularyI18nValuePair.java
@@ -0,0 +1,193 @@
+/**
+ * The contents of this file are subject to the license and copyright
+ * detailed in the LICENSE and NOTICE files at the root of the source
+ * tree and available online at
+ *
+ * http://www.dspace.org/license/
+ */
+package org.dspace.content.integration.crosswalks.virtualfields;
+
+import java.util.Locale;
+import java.util.Objects;
+import java.util.Optional;
+
+import org.apache.commons.lang3.StringUtils;
+import org.dspace.content.Item;
+import org.dspace.content.MetadataValue;
+import org.dspace.content.authority.ChoiceAuthority;
+import org.dspace.content.authority.DCInputAuthority;
+import org.dspace.content.authority.service.ChoiceAuthorityService;
+import org.dspace.content.service.ItemService;
+import org.dspace.core.Context;
+import org.dspace.core.I18nUtil;
+import org.dspace.core.factory.CoreServiceFactory;
+import org.dspace.core.service.PluginService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ * Implementation of {@link VirtualField} that translates {@code value-pair}
+ * and {@code vocabulary-fields} into displayable labels.
+ * Internally uses the {@link ChoiceAuthorityService} to translate them.
+ *
+ *
+ * (Example: {@code @virtual.vocabulary_18n.metadataField@})
+ *
+ * @author Mykhaylo Boychuk (mykhaylo.boychuk at 4science.com)
+ */
+public class VirtualFieldVocabularyI18nValuePair implements VirtualField {
+
+ private final static Logger LOGGER = LoggerFactory.getLogger(VirtualFieldVocabularyI18nValuePair.class);
+
+ @Autowired
+ private ItemService itemService;
+ @Autowired
+ private ChoiceAuthorityService choiceAuthorityService;
+
+ private PluginService pluginService = CoreServiceFactory.getInstance().getPluginService();
+
+ @Override
+ public String[] getMetadata(Context context, Item item, String fieldName) {
+ String[] virtualFieldName = fieldName.split("\\.", 4);
+
+ if (virtualFieldName.length < 3 || virtualFieldName.length > 4) {
+ LOGGER.warn("Invalid value-pairs virtual field: " + fieldName);
+ return new String[] {};
+ }
+ String vocabularyName = getVocabularyName(virtualFieldName);
+ String metadataField = virtualFieldName[2].replaceAll("-", ".");
+ Locale locale = getLocale(context);
+
+ return itemService.getMetadataByMetadataString(item, metadataField)
+ .stream()
+ .map(metadataValue ->
+ getLabelForVocabulary(vocabularyName, metadataValue, locale)
+ .orElse(getDisplayableLabel(item, metadataValue, locale.getLanguage()))
+ )
+ .toArray(String[]::new);
+ }
+
+ protected Optional getLabelForVocabulary(
+ String vocabularyName, MetadataValue metadataValue, Locale locale
+ ) {
+ return Optional.ofNullable(vocabularyName)
+ .map(vocabulary -> (ChoiceAuthority) pluginService.getNamedPlugin(ChoiceAuthority.class, vocabulary))
+ .filter(Objects::nonNull)
+ .flatMap(choiceAuthority -> Optional.ofNullable(metadataValue.getAuthority())
+ .flatMap(
+ authority -> getLabelWithFallback(choiceAuthority, authority, locale, I18nUtil.getDefaultLocale())
+ )
+ .or(
+ () -> getLabelWithFallback(
+ choiceAuthority, metadataValue.getValue(),
+ locale, I18nUtil.getDefaultLocale()
+ )
+ )
+ );
+ }
+
+ private Optional getLabelWithFallback(
+ ChoiceAuthority choiceAuthority, String authKey, Locale locale, Locale fallbackLocale
+ ) {
+ return getValidLabel(
+ Optional.ofNullable(choiceAuthority.getLabel(authKey, locale.getLanguage()))
+ )
+ .or(
+ () -> getValidLabel(
+ Optional.ofNullable(
+ choiceAuthority.getLabel(
+ authKey,
+ fallbackLocale.getLanguage()
+ )
+ )
+ )
+ );
+ }
+
+ protected String getDisplayableLabel(Item item, MetadataValue metadataValue, String language) {
+ return getLabelForCurrentLanguage(item, metadataValue, language)
+ .or(() -> getLabelForDefaultLanguage(item, metadataValue))
+ .orElse(metadataValue.getValue());
+ }
+
+ protected Optional getLabelForDefaultLanguage(Item item, MetadataValue metadataValue) {
+ return getLabelForVocabulary(item, metadataValue, I18nUtil.getDefaultLocale().getLanguage())
+ .or(() -> getLabelForValuePair(item, metadataValue, I18nUtil.getDefaultLocale().getLanguage()));
+ }
+
+ protected Optional getLabelForCurrentLanguage(Item item, MetadataValue metadataValue, String language) {
+ return getLabelForVocabulary(item, metadataValue, language)
+ .or(() -> getLabelForValuePair(item, metadataValue, language));
+ }
+
+ private Optional getLabelForVocabulary(Item item, MetadataValue metadataValue, String language) {
+ return getValidLabel(
+ Optional.ofNullable(metadataValue)
+ .filter(mv -> StringUtils.isNotBlank(mv.getAuthority()))
+ .map(mv -> getVocabulary(item, mv, language))
+ );
+ }
+
+ private Optional getLabelForValuePair(Item item, MetadataValue metadataValue, String language) {
+ return getValidLabel(
+ Optional.ofNullable(metadataValue)
+ .filter(mv -> StringUtils.isNotBlank(mv.getValue()))
+ .map(mv -> getValuePair(item, mv, language))
+ );
+ }
+
+ private String getVocabulary(Item item, MetadataValue metadataValue, String language) {
+ try {
+ return this.choiceAuthorityService
+ .getLabel(
+ metadataValue, item.getType(),
+ item.getOwningCollection(), language
+ );
+ } catch (Exception e) {
+ LOGGER.warn("Error while retrieving the vocabulary for: " +
+ metadataValue.getMetadataField().toString(), e
+ );
+ }
+ return null;
+ }
+
+
+ private String getValuePair(Item item, MetadataValue metadataValue, String language) {
+ try {
+ return this.choiceAuthorityService
+ .getLabel(
+ metadataValue.getMetadataField().toString(), item.getType(),
+ item.getOwningCollection(), metadataValue.getValue(), language
+ );
+ } catch (Exception e) {
+ LOGGER.warn(
+ "Error while retrievingthe value-pair for: " +
+ metadataValue.getMetadataField().toString(),
+ e
+ );
+ }
+ return null;
+ }
+
+ private String getVocabularyName(String[] virtualFieldName) {
+ return Optional.of(virtualFieldName.length)
+ .filter(l -> l == 4)
+ .map(l -> virtualFieldName[l - 1])
+ .orElse(null);
+ }
+
+ private Optional getValidLabel(Optional label) {
+ return label.filter(this::isValidLabel);
+ }
+
+ private boolean isValidLabel(String s) {
+ return s != null && !s.contains(DCInputAuthority.UNKNOWN_KEY);
+ }
+
+ private Locale getLocale(Context context) {
+ return Optional.ofNullable(context.getCurrentLocale())
+ .orElse(I18nUtil.getDefaultLocale());
+ }
+
+}
diff --git a/dspace-api/src/main/java/org/dspace/content/security/AccessItemMode.java b/dspace-api/src/main/java/org/dspace/content/security/AccessItemMode.java
index 2aee66fed1f..e2954bf8f83 100644
--- a/dspace-api/src/main/java/org/dspace/content/security/AccessItemMode.java
+++ b/dspace-api/src/main/java/org/dspace/content/security/AccessItemMode.java
@@ -9,6 +9,8 @@
import java.util.List;
+import org.dspace.content.logic.Filter;
+
/**
* Interface to be extended for the configuration related to access item modes.
*
@@ -50,4 +52,6 @@ public interface AccessItemMode {
* @return the group list
*/
public List getGroups();
+
+ public Filter getAdditionalFilter();
}
diff --git a/dspace-api/src/main/java/org/dspace/content/security/CrisSecurity.java b/dspace-api/src/main/java/org/dspace/content/security/CrisSecurity.java
index 3fcd8386417..9a472b8a40c 100644
--- a/dspace-api/src/main/java/org/dspace/content/security/CrisSecurity.java
+++ b/dspace-api/src/main/java/org/dspace/content/security/CrisSecurity.java
@@ -23,6 +23,7 @@ public enum CrisSecurity {
ITEM_ADMIN,
SUBMITTER,
SUBMITTER_GROUP,
- GROUP;
+ GROUP,
+ ALL;
}
diff --git a/dspace-api/src/main/java/org/dspace/content/security/CrisSecurityServiceImpl.java b/dspace-api/src/main/java/org/dspace/content/security/CrisSecurityServiceImpl.java
index 4a8b2c31384..99add81e862 100644
--- a/dspace-api/src/main/java/org/dspace/content/security/CrisSecurityServiceImpl.java
+++ b/dspace-api/src/main/java/org/dspace/content/security/CrisSecurityServiceImpl.java
@@ -11,6 +11,7 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
+import java.util.Optional;
import java.util.UUID;
import org.apache.commons.collections.CollectionUtils;
@@ -55,37 +56,46 @@ public boolean hasAccess(Context context, Item item, EPerson user, AccessItemMod
.anyMatch(security -> hasAccess(context, item, user, accessMode, security));
}
- private boolean hasAccess(Context context, Item item, EPerson user, AccessItemMode accessMode,
- CrisSecurity crisSecurity) {
-
+ private boolean hasAccess(
+ Context context, Item item, EPerson user, AccessItemMode accessMode, CrisSecurity crisSecurity
+ ) {
try {
+ final boolean checkSecurity = checkSecurity(context, item, user, accessMode, crisSecurity);
- switch (crisSecurity) {
- case ADMIN:
- return authorizeService.isAdmin(context, user);
- case CUSTOM:
- return hasAccessByCustomPolicy(context, item, user, accessMode);
- case GROUP:
- return hasAccessByGroup(context, user, accessMode.getGroups());
- case ITEM_ADMIN:
- return authorizeService.isAdmin(context, user, item);
- case OWNER:
- return isOwner(user, item);
- case SUBMITTER:
- return user != null && user.equals(item.getSubmitter());
- case SUBMITTER_GROUP:
- return isUserInSubmitterGroup(context, item, user);
- case NONE:
- default:
- return false;
- }
-
+ return Optional.ofNullable(accessMode.getAdditionalFilter())
+ .map(filter -> checkSecurity && filter.getResult(context, item))
+ .orElse(checkSecurity);
} catch (SQLException e) {
- throw new RuntimeException(e);
+ throw new SQLRuntimeException(e);
}
}
+ private boolean checkSecurity(Context context, Item item, EPerson user, AccessItemMode accessMode,
+ CrisSecurity crisSecurity) throws SQLException {
+ switch (crisSecurity) {
+ case ADMIN:
+ return authorizeService.isAdmin(context, user);
+ case CUSTOM:
+ return hasAccessByCustomPolicy(context, item, user, accessMode);
+ case GROUP:
+ return hasAccessByGroup(context, user, accessMode.getGroups());
+ case ITEM_ADMIN:
+ return authorizeService.isAdmin(context, user, item);
+ case OWNER:
+ return isOwner(user, item);
+ case SUBMITTER:
+ return user != null && user.equals(item.getSubmitter());
+ case SUBMITTER_GROUP:
+ return isUserInSubmitterGroup(context, item, user);
+ case ALL:
+ return true;
+ case NONE:
+ default:
+ return false;
+ }
+ }
+
private boolean isOwner(EPerson eperson, Item item) {
return ePersonService.isOwnerOfItem(eperson, item);
}
diff --git a/dspace-api/src/main/java/org/dspace/content/service/BitstreamService.java b/dspace-api/src/main/java/org/dspace/content/service/BitstreamService.java
index 3f5b17630a2..85a4fd140e9 100644
--- a/dspace-api/src/main/java/org/dspace/content/service/BitstreamService.java
+++ b/dspace-api/src/main/java/org/dspace/content/service/BitstreamService.java
@@ -22,6 +22,7 @@
import org.dspace.content.Bundle;
import org.dspace.content.Collection;
import org.dspace.content.Community;
+import org.dspace.content.DSpaceObject;
import org.dspace.content.Item;
import org.dspace.core.Context;
@@ -243,4 +244,8 @@ List findShowableByItem(Context context, UUID itemId, String bundleNa
List findByItemAndBundleAndMetadata(Context context, Item item, String bundleName,
Map filterMetadata);
+ boolean isOriginalBitstream(DSpaceObject dso) throws SQLException;
+
+ void updateThumbnailResourcePolicies(Context context, Bitstream bitstream) throws SQLException;
+
}
diff --git a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceFileInfoPlugin.java b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceFileInfoPlugin.java
index ab56e4692e3..a2c3056ae38 100644
--- a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceFileInfoPlugin.java
+++ b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceFileInfoPlugin.java
@@ -7,16 +7,31 @@
*/
package org.dspace.discovery;
+import java.sql.SQLException;
+import java.util.Collection;
import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.function.BiFunction;
+import java.util.function.Consumer;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
+import org.apache.commons.lang3.StringUtils;
import org.apache.solr.common.SolrInputDocument;
import org.dspace.content.Bitstream;
+import org.dspace.content.BitstreamFormat;
import org.dspace.content.Bundle;
-import org.dspace.content.Item;
+import org.dspace.content.MetadataField;
+import org.dspace.content.MetadataFieldName;
+import org.dspace.content.MetadataValue;
import org.dspace.core.Context;
import org.dspace.discovery.indexobject.IndexableItem;
+import org.joda.time.format.DateTimeFormat;
+import org.joda.time.format.DateTimeFormatter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
*
@@ -36,41 +51,272 @@
*
*
* @author Martin Walk
+ * @author Vincenzo Mecca (vins01-4science - vincenzo.mecca at 4science.com)
+ *
*/
public class SolrServiceFileInfoPlugin implements SolrServiceIndexPlugin {
- private static final Logger log = LogManager.getLogger(SolrServiceFileInfoPlugin.class);
+ /**
+ * Class used to map a target metadata into a solr index using {@code SolrInputDocument}
+ *
+ * @author Vincenzo Mecca (vins01-4science - vincenzo.mecca at 4science.com)
+ *
+ * @param
+ */
+ private static class SolrFieldMetadataMapper {
+ private final String solrField;
+ private final BiFunction> fieldAdder;
+
+ public SolrFieldMetadataMapper(
+ String metadata,
+ BiFunction> fieldAdder
+ ) {
+ super();
+ this.solrField = metadata;
+ this.fieldAdder = fieldAdder;
+ }
+
+ public void map(SolrInputDocument document, T value) {
+ this.fieldAdder.apply(document, this.solrField).accept(value);
+ }
+
+ }
+
+ private static final Logger logger = LoggerFactory.getLogger(SolrServiceFileInfoPlugin.class);
+
+ private static final DateTimeFormatter dtf = DateTimeFormat.forPattern("yyyy-MM-dd");
private static final String BUNDLE_NAME = "ORIGINAL";
private static final String SOLR_FIELD_NAME_FOR_FILENAMES = "original_bundle_filenames";
private static final String SOLR_FIELD_NAME_FOR_DESCRIPTIONS = "original_bundle_descriptions";
+ private static final String SOLR_FIELD_NAME_FOR_OAIRE_LICENSE_CONDITION = "original_bundle_oaire_licenseCondition";
+ private static final String SOLR_FIELD_NAME_FOR_DATACITE_RIGHTS = "original_bundle_datacite_rights";
+ private static final String SOLR_FIELD_NAME_FOR_DATACITE_AVAILABLE = "original_bundle_datacite_available";
+ private static final String SOLR_FIELD_NAME_FOR_MIMETYPE = "original_bundle_mime_type";
+ private static final String SOLR_FIELD_NAME_FOR_CHECKSUM = "original_bundle_checksum";
+ private static final String SOLR_FIELD_NAME_FOR_SIZEBYTES = "original_bundle_sizebytes";
+ private static final String SOLR_FIELD_NAME_FOR_SHORT_DESCRIPTION = "original_bundle_short_description";
+ private static final String SOLR_POSTFIX_FILTER = "_filter";
+ private static final String SOLR_POSTFIX_KEYWORD = "_keyword";
+ private static final String BITSTREAM_METADATA_SOLR_PREFIX_KEYWORD = "bitstreams.";
+ // used for facets and filters of type Date to correctly search them and visualize in facets.
+ private static final String SOLR_POSTFIX_YEAR = ".year";
+ private static final MetadataFieldName METADATA_DATACITE_RIGHTS = new MetadataFieldName("datacite", "rights");
+ private static final MetadataFieldName METADATA_DATACITE_AVAILABLE = new MetadataFieldName("datacite", "available");
+ private static final MetadataFieldName METADATA_LICENSE_CONDITION =
+ new MetadataFieldName("oaire", "licenseCondition");
+
+ private static final BiFunction> defaultSolrIndexAdder =
+ (document, fieldName) -> value -> {
+ Collection fieldValues = document.getFieldValues(fieldName);
+ if (fieldValues == null || !fieldValues.contains(value)) {
+ addField(document, fieldName, value);
+ addField(document, fieldName.concat(SOLR_POSTFIX_KEYWORD), value);
+ addField(document, fieldName.concat(SOLR_POSTFIX_FILTER), value);
+ }
+ };
+
+ private static final BiFunction> simpleSolrIndexAdder =
+ (document, fieldName) -> value -> {
+ Collection fieldValues = document.getFieldValues(fieldName);
+ if (fieldValues == null || !fieldValues.contains(value)) {
+ addField(document, fieldName, value);
+ }
+ };
+
+ private static final BiFunction> bitstreamMetadataSolrIndexAdder =
+ (document, fieldName) -> value -> {
+ String baseIndex = BITSTREAM_METADATA_SOLR_PREFIX_KEYWORD.concat(fieldName);
+ Collection fieldValues = document.getFieldValues(baseIndex);
+ if (fieldValues == null || !fieldValues.contains(value)) {
+ addField(document, baseIndex, value);
+ addField(document, baseIndex.concat(SOLR_POSTFIX_KEYWORD), value);
+ addField(document, baseIndex.concat(SOLR_POSTFIX_FILTER), value);
+ }
+ };
+
+ private static final BiFunction> yearSolrIndexAdder =
+ (document, fieldName) -> value -> {
+ Collection fieldValues = document.getFieldValues(fieldName);
+ if (fieldValues == null || !fieldValues.contains(value)) {
+ addField(document, fieldName, value);
+ addField(document, fieldName.concat(SOLR_POSTFIX_KEYWORD), value);
+ addField(document, fieldName.concat(SOLR_POSTFIX_FILTER), value);
+ addField(document, fieldName.concat(SOLR_POSTFIX_YEAR), dtf.parseLocalDate(value).getYear());
+ }
+ };
+
+ private static final SolrFieldMetadataMapper getFieldMapper(
+ String solrField,
+ BiFunction> adder
+ ) {
+ return new SolrFieldMetadataMapper(solrField, adder);
+ }
+
+ private static final SolrFieldMetadataMapper OAIRE_LICENSE_MAPPER =
+ new SolrFieldMetadataMapper(
+ SOLR_FIELD_NAME_FOR_OAIRE_LICENSE_CONDITION,
+ defaultSolrIndexAdder
+ );
+
+ private static final SolrFieldMetadataMapper DATACITE_RIGHTS_MAPPER =
+ new SolrFieldMetadataMapper(
+ SOLR_FIELD_NAME_FOR_DATACITE_RIGHTS,
+ defaultSolrIndexAdder
+ );
+
+ private static final SolrFieldMetadataMapper DATACITE_AVAILABLE_MAPPER =
+ new SolrFieldMetadataMapper(
+ SOLR_FIELD_NAME_FOR_DATACITE_AVAILABLE,
+ yearSolrIndexAdder
+ );
+
+ private static final Map> mappableMetadatas =
+ Stream.of(
+ Map.entry(METADATA_LICENSE_CONDITION.toString(), OAIRE_LICENSE_MAPPER),
+ Map.entry(METADATA_DATACITE_RIGHTS.toString(), DATACITE_RIGHTS_MAPPER),
+ Map.entry(METADATA_DATACITE_AVAILABLE.toString(), DATACITE_AVAILABLE_MAPPER)
+ )
+ .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
+
+
+ private static void addField(SolrInputDocument document, String name, Object value) {
+ document.addField(name, value);
+ }
@Override
public void additionalIndex(Context context, IndexableObject indexableObject, SolrInputDocument document) {
if (indexableObject instanceof IndexableItem) {
- Item item = ((IndexableItem) indexableObject).getIndexedObject();
- List bundles = item.getBundles();
- if (bundles != null) {
- for (Bundle bundle : bundles) {
- String bundleName = bundle.getName();
- if ((bundleName != null) && bundleName.equals(BUNDLE_NAME)) {
- List bitstreams = bundle.getBitstreams();
- if (bitstreams != null) {
- for (Bitstream bitstream : bitstreams) {
- try {
- document.addField(SOLR_FIELD_NAME_FOR_FILENAMES, bitstream.getName());
-
- String description = bitstream.getDescription();
- if ((description != null) && !description.isEmpty()) {
- document.addField(SOLR_FIELD_NAME_FOR_DESCRIPTIONS, description);
- }
- } catch (Exception e) {
- log.warn("Error occurred during update index for item {}", item.getID());
- }
- }
- }
- }
+ generateBundleIndex(context, document, ((IndexableItem) indexableObject).getIndexedObject().getBundles());
+ }
+ }
+
+ private void generateBundleIndex(Context context, SolrInputDocument document, List bundles) {
+ if (bundles != null) {
+ for (Bundle bundle : bundles) {
+ String bundleName = bundle.getName();
+ if (bundleName != null && bundleName.equals(BUNDLE_NAME)) {
+ generateBitstreamIndex(context, document, bundle.getBitstreams());
}
}
}
}
-}
\ No newline at end of file
+
+ /**
+ * Method that adds index to {@link SolrInputDocument}, iterates between {@code bitstreams} and {@code mappableMetadatas}
+ * then applies the corresponding mapping function to the bitstream
+ *
+ * @param document solr document
+ * @param bitstreams list of bitstreams to analyze
+ */
+ private void generateBitstreamIndex(Context context, SolrInputDocument document, List bitstreams) {
+ if (document != null && bitstreams != null) {
+ for (Bitstream bitstream : bitstreams) {
+
+ indexBitstreamFields(context, document, bitstream);
+
+ indexBitstreamsMetadatadas(document, bitstream);
+ }
+ }
+ }
+
+ private void indexBitstreamFields(Context context, SolrInputDocument document, Bitstream bitstream) {
+ addAndHandleException(
+ simpleSolrIndexAdder, document, bitstream, SOLR_FIELD_NAME_FOR_FILENAMES, bitstream.getName()
+ );
+
+ Optional.ofNullable(bitstream.getDescription())
+ .filter(StringUtils::isNotEmpty)
+ .ifPresent(
+ (description) ->
+ addAndHandleException(
+ simpleSolrIndexAdder, document, bitstream, SOLR_FIELD_NAME_FOR_DESCRIPTIONS, description
+ )
+ );
+
+ try {
+ Optional formatOptional =
+ Optional.ofNullable(bitstream.getFormat(context))
+ .filter(Objects::nonNull);
+
+ formatOptional
+ .map(BitstreamFormat::getMIMEType)
+ .filter(StringUtils::isNotBlank)
+ .ifPresent(format ->
+ addAndHandleException(
+ defaultSolrIndexAdder, document, bitstream, SOLR_FIELD_NAME_FOR_MIMETYPE, format
+ )
+ );
+
+ formatOptional
+ .map(BitstreamFormat::getShortDescription)
+ .ifPresent(format ->
+ addAndHandleException(
+ simpleSolrIndexAdder, document, bitstream, SOLR_FIELD_NAME_FOR_SHORT_DESCRIPTION, format
+ )
+ );
+ } catch (SQLException e) {
+ logger.error("Error while retrievig bitstream format", e);
+ throw new RuntimeException("Error while retrievig bitstream format", e);
+ }
+
+ Optional.ofNullable(bitstream.getChecksum())
+ .filter(StringUtils::isNotBlank)
+ .map(checksum -> bitstream.getChecksumAlgorithm() + ":" + bitstream.getChecksum())
+ .ifPresent(checksum ->
+ addAndHandleException(
+ defaultSolrIndexAdder, document, bitstream, SOLR_FIELD_NAME_FOR_CHECKSUM, checksum
+ )
+ );
+
+ Optional.ofNullable(bitstream.getSizeBytes())
+ .filter(l -> l > 0)
+ .map(String::valueOf)
+ .ifPresent(size ->
+ addAndHandleException(
+ simpleSolrIndexAdder, document, bitstream, SOLR_FIELD_NAME_FOR_SIZEBYTES, size
+ )
+ );
+ }
+
+ protected void addAndHandleException(
+ BiFunction> solrIndexAdder,
+ SolrInputDocument document, Bitstream bitstream,
+ String field, String value
+ ) {
+ try {
+ solrIndexAdder.apply(document, field).accept(value);
+ } catch (Exception e) {
+ logger.warn(
+ "Error occurred during the update of index field {} for bitstream {}",
+ field,
+ bitstream.getID()
+ );
+ }
+ }
+
+ private void indexBitstreamsMetadatadas(SolrInputDocument document, Bitstream bitstream) {
+ bitstream
+ .getMetadata()
+ .stream()
+ .filter(metadata -> metadata != null && StringUtils.isNotBlank(metadata.getValue()))
+ .forEach(metadata -> {
+ MetadataField metadataField = metadata.getMetadataField();
+ String bitstreamMetadata = metadataField.toString('.');
+ Optional.ofNullable(mappableMetadatas.get(bitstreamMetadata))
+ .filter(Objects::nonNull)
+ .orElse(
+ getFieldMapper(
+ metadataField.toString(),
+ bitstreamMetadataSolrIndexAdder
+ )
+ )
+ .map(document, metadata.getValue());
+ });
+ }
+
+ private boolean areEquals(MetadataFieldName metadataFieldName, MetadataValue metadata) {
+ return StringUtils.equals(metadataFieldName.schema, metadata.getSchema()) &&
+ StringUtils.equals(metadataFieldName.element, metadata.getElement()) &&
+ StringUtils.equals(metadataFieldName.qualifier, metadata.getQualifier());
+ }
+}
diff --git a/dspace-api/src/main/java/org/dspace/eperson/AccountServiceImpl.java b/dspace-api/src/main/java/org/dspace/eperson/AccountServiceImpl.java
index 283f101f2ba..8be6aac7e39 100644
--- a/dspace-api/src/main/java/org/dspace/eperson/AccountServiceImpl.java
+++ b/dspace-api/src/main/java/org/dspace/eperson/AccountServiceImpl.java
@@ -11,25 +11,36 @@
import java.sql.SQLException;
import java.util.List;
import java.util.Locale;
+import java.util.Map;
import java.util.Objects;
+import java.util.Optional;
import java.util.UUID;
+import java.util.function.BiConsumer;
+import java.util.function.Consumer;
+import java.util.stream.Stream;
import javax.mail.MessagingException;
import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dspace.authenticate.service.AuthenticationService;
import org.dspace.authorize.AuthorizeException;
+import org.dspace.content.Item;
+import org.dspace.content.MetadataValue;
+import org.dspace.content.service.MetadataValueService;
import org.dspace.core.Context;
import org.dspace.core.Email;
import org.dspace.core.I18nUtil;
import org.dspace.core.Utils;
+import org.dspace.eperson.dto.RegistrationDataPatch;
import org.dspace.eperson.service.AccountService;
import org.dspace.eperson.service.EPersonService;
import org.dspace.eperson.service.GroupService;
import org.dspace.eperson.service.RegistrationDataService;
import org.dspace.services.ConfigurationService;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.log.LogMessage;
/**
* Methods for handling registration by email and forgotten passwords. When
@@ -50,8 +61,16 @@ public class AccountServiceImpl implements AccountService {
* log4j log
*/
private static final Logger log = LogManager.getLogger(AccountServiceImpl.class);
+
+ private static final Map> allowedMergeArguments =
+ Map.of(
+ "email",
+ (RegistrationData registrationData, EPerson eperson) -> eperson.setEmail(registrationData.getEmail())
+ );
+
@Autowired(required = true)
protected EPersonService ePersonService;
+
@Autowired(required = true)
protected RegistrationDataService registrationDataService;
@Autowired
@@ -63,6 +82,9 @@ public class AccountServiceImpl implements AccountService {
@Autowired
private AuthenticationService authenticationService;
+ @Autowired
+ private MetadataValueService metadataValueService;
+
protected AccountServiceImpl() {
}
@@ -79,9 +101,9 @@ protected AccountServiceImpl() {
*
* @param context DSpace context
* @param email Email address to send the registration email to
- * @throws java.sql.SQLException passed through.
- * @throws java.io.IOException passed through.
- * @throws javax.mail.MessagingException passed through.
+ * @throws java.sql.SQLException passed through.
+ * @throws java.io.IOException passed through.
+ * @throws javax.mail.MessagingException passed through.
* @throws org.dspace.authorize.AuthorizeException passed through.
*/
@Override
@@ -94,7 +116,7 @@ public void sendRegistrationInfo(Context context, String email, List group
if (!authenticationService.canSelfRegister(context, null, email)) {
throw new IllegalStateException("self registration is not allowed with this email address");
}
- sendInfo(context, email, groups, true, true);
+ sendInfo(context, email, groups, RegistrationTypeEnum.REGISTER, true);
}
/**
@@ -108,19 +130,36 @@ public void sendRegistrationInfo(Context context, String email, List group
* Authorization error (throws AuthorizeException).
*