Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -944,7 +944,7 @@ private Predicate buildFieldPresentInDataversePredicate(Dataverse dataverse, boo
// Predicate for displayOnCreate in input level
Predicate displayOnCreateInputLevelPredicate = criteriaBuilder.and(
criteriaBuilder.equal(datasetFieldTypeRoot, datasetFieldTypeInputLevelJoin.get("datasetFieldType")),
criteriaBuilder.isTrue(datasetFieldTypeInputLevelJoin.get("displayOnCreate"))
criteriaBuilder.equal(datasetFieldTypeInputLevelJoin.get("displayOnCreate"), Boolean.TRUE)
);

// Create a subquery to check for the absence of a specific DataverseFieldTypeInputLevel.
Expand All @@ -953,7 +953,8 @@ private Predicate buildFieldPresentInDataversePredicate(Dataverse dataverse, boo
subquery.select(criteriaBuilder.literal(1L))
.where(
criteriaBuilder.equal(subqueryRoot.get("dataverse"), dataverseRoot),
criteriaBuilder.equal(subqueryRoot.get("datasetFieldType"), datasetFieldTypeRoot)
criteriaBuilder.equal(subqueryRoot.get("datasetFieldType"), datasetFieldTypeRoot),
criteriaBuilder.isNotNull(subqueryRoot.get("displayOnCreate"))
);

// Define a predicate to exclude DatasetFieldTypes that have no associated input level (i.e., the subquery does not return a result).
Expand Down
28 changes: 21 additions & 7 deletions src/main/java/edu/harvard/iq/dataverse/DatasetFieldType.java
Original file line number Diff line number Diff line change
Expand Up @@ -273,21 +273,35 @@ public void setValidationFormat(String validationFormat) {
* Determines whether this field type is displayed in the form when creating
* the Dataset (or only later when editing after the initial creation).
*/
@Column(name = "displayoncreate", nullable = true)
private Boolean displayOnCreate;
private boolean displayOnCreate;

public Boolean isDisplayOnCreate() {
public boolean isDisplayOnCreate() {
return displayOnCreate;
}

public Boolean getDisplayOnCreate() {
return displayOnCreate;
public void setDisplayOnCreate(boolean displayOnCreate) {
this.displayOnCreate = displayOnCreate;
}

public void setDisplayOnCreate(Boolean displayOnCreate) {
this.displayOnCreate = displayOnCreate;
/**
* Determines whether this field type is displayed in the form when creating
* the Dataset (or only later when editing after the initial creation).
*/
@Transient
private Boolean localDisplayOnCreate;

public Boolean getLocalDisplayOnCreate() {
return localDisplayOnCreate;
}

public void setLocalDisplayOnCreate(Boolean localDisplayOnCreate) {
this.localDisplayOnCreate = localDisplayOnCreate;
}

public boolean shouldDisplayOnCreate() {
return (localDisplayOnCreate == null) ? displayOnCreate : localDisplayOnCreate;
}

public boolean isControlledVocabulary() {
return allowControlledVocabulary;
}
Expand Down
5 changes: 4 additions & 1 deletion src/main/java/edu/harvard/iq/dataverse/DatasetPage.java
Original file line number Diff line number Diff line change
Expand Up @@ -1856,7 +1856,10 @@ private void updateDatasetFieldInputLevels() {
if (dsf != null){
// Yes, call "setInclude"
dsf.setInclude(oneDSFieldTypeInputLevel.isInclude());
dsf.getDatasetFieldType().setDisplayOnCreate(oneDSFieldTypeInputLevel.isDisplayOnCreate());
Boolean displayOnCreate = oneDSFieldTypeInputLevel.getDisplayOnCreate();
if (displayOnCreate!= null) {
dsf.getDatasetFieldType().setLocalDisplayOnCreate(displayOnCreate);
}
// remove from hash
mapDatasetFields.remove(oneDSFieldTypeInputLevel.getDatasetFieldType().getId());
}
Expand Down
9 changes: 8 additions & 1 deletion src/main/java/edu/harvard/iq/dataverse/Dataverse.java
Original file line number Diff line number Diff line change
Expand Up @@ -438,10 +438,17 @@ public boolean isDatasetFieldTypeInInputLevels(Long datasetFieldTypeId) {
.anyMatch(inputLevel -> inputLevel.getDatasetFieldType().getId().equals(datasetFieldTypeId));
}

public DataverseFieldTypeInputLevel getDatasetFieldTypeInInputLevels(Long datasetFieldTypeId) {
return dataverseFieldTypeInputLevels.stream()
.filter(inputLevel -> inputLevel.getDatasetFieldType().getId().equals(datasetFieldTypeId))
.findFirst()
.orElse(null);
}

public boolean isDatasetFieldTypeDisplayOnCreateAsInputLevel(Long datasetFieldTypeId) {
return dataverseFieldTypeInputLevels.stream()
.anyMatch(inputLevel -> inputLevel.getDatasetFieldType().getId().equals(datasetFieldTypeId)
&& inputLevel.isDisplayOnCreate());
&& Boolean.TRUE.equals(inputLevel.getDisplayOnCreate()));
}

public Template getDefaultTemplate() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
package edu.harvard.iq.dataverse;

import java.io.Serializable;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
Expand Down Expand Up @@ -38,8 +40,9 @@
, uniqueConstraints={
@UniqueConstraint(columnNames={"dataverse_id", "datasetfieldtype_id"})}
, indexes = {@Index(columnList="dataverse_id")
, @Index(columnList="datasetfieldtype_id")
, @Index(columnList="required")}
, @Index(columnList="datasetfieldtype_id")
, @Index(columnList="required")
, @Index(columnList="displayOnCreate")}
)
@Entity
public class DataverseFieldTypeInputLevel implements Serializable {
Expand All @@ -58,11 +61,14 @@ public class DataverseFieldTypeInputLevel implements Serializable {
private DatasetFieldType datasetFieldType;
private boolean include;
private boolean required;
private boolean displayOnCreate;


@Column(nullable = true)
private Boolean displayOnCreate;

public DataverseFieldTypeInputLevel () {}

public DataverseFieldTypeInputLevel (DatasetFieldType fieldType, Dataverse dataverse, boolean required, boolean include, boolean displayOnCreate) {
public DataverseFieldTypeInputLevel (DatasetFieldType fieldType, Dataverse dataverse, boolean required, boolean include, Boolean displayOnCreate) {
this.datasetFieldType = fieldType;
this.dataverse = dataverse;
this.required = required;
Expand Down Expand Up @@ -117,11 +123,11 @@ public void setRequired(boolean required) {
this.required = required;
}

public boolean isDisplayOnCreate() {
public Boolean getDisplayOnCreate() {
return displayOnCreate;
}

public void setDisplayOnCreate(boolean displayOnCreate) {
public void setDisplayOnCreate(Boolean displayOnCreate) {
this.displayOnCreate = displayOnCreate;
}

Expand Down
11 changes: 5 additions & 6 deletions src/main/java/edu/harvard/iq/dataverse/DataversePage.java
Original file line number Diff line number Diff line change
Expand Up @@ -1025,12 +1025,11 @@ private void loadInputLevels(DatasetFieldType dsft, Long dataverseIdForInputLeve
if (dsfIl != null) {
dsft.setRequiredDV(dsfIl.isRequired());
dsft.setInclude(dsfIl.isInclude());
dsft.setDisplayOnCreate(dsfIl.isDisplayOnCreate());
dsft.setLocalDisplayOnCreate(dsfIl.getDisplayOnCreate());
} else {
// If there is no input level, use the default values
dsft.setRequiredDV(dsft.isRequired());
dsft.setInclude(true);
dsft.setDisplayOnCreate(false);
}
}

Expand Down Expand Up @@ -1317,7 +1316,7 @@ public void updateDisplayOnCreate(Long mdbId, Long dsftId, boolean currentValue)
for (DatasetFieldType dsft : mdb.getDatasetFieldTypes()) {
if (dsft.getId().equals(dsftId)) {
// Update value in memory
dsft.setDisplayOnCreate(!currentValue);
dsft.setLocalDisplayOnCreate(!currentValue);

// Update or create input level
DataverseFieldTypeInputLevel existingLevel = dataverseFieldTypeInputLevelService
Expand Down Expand Up @@ -1348,18 +1347,18 @@ private void saveInputLevels(List<DataverseFieldTypeInputLevel> listDFTIL, Datas
.findByDataverseIdDatasetFieldTypeId(dataverse.getId(), dsft.getId());

if (existingLevel != null) {
existingLevel.setDisplayOnCreate(dsft.isDisplayOnCreate());
existingLevel.setDisplayOnCreate(dsft.getLocalDisplayOnCreate());
existingLevel.setInclude(dsft.isInclude());
existingLevel.setRequired(dsft.isRequiredDV());
listDFTIL.add(existingLevel);
} else if (dsft.isInclude() || dsft.isDisplayOnCreate() || dsft.isRequiredDV()) {
} else if (dsft.isInclude() || (dsft.getLocalDisplayOnCreate()!=null) || dsft.isRequiredDV()) {
// Only create new input level if there is any specific configuration
listDFTIL.add(new DataverseFieldTypeInputLevel(
dsft,
dataverse,
dsft.isRequiredDV(),
dsft.isInclude(),
dsft.isDisplayOnCreate()
dsft.getLocalDisplayOnCreate()
));
}
}
Expand Down
10 changes: 6 additions & 4 deletions src/main/java/edu/harvard/iq/dataverse/DataverseServiceBean.java
Original file line number Diff line number Diff line change
Expand Up @@ -961,13 +961,13 @@ public String getCollectionDatasetSchema(String dataverseAlias, Map<String, Map
if (dsfIl != null) {
dsft.setRequiredDV(dsfIl.isRequired());
dsft.setInclude(dsfIl.isInclude());
dsft.setDisplayOnCreate(dsfIl.isDisplayOnCreate());
dsft.setLocalDisplayOnCreate(dsfIl.getDisplayOnCreate());
} else {
dsft.setRequiredDV(dsft.isRequired());
dsft.setInclude(true);
// Default displayOnCreate to true for required fields
dsft.setLocalDisplayOnCreate(dsft.isRequired());
}

// Process child fields if any
List<String> childrenRequired = new ArrayList<>();
List<String> childrenAllowed = new ArrayList<>();
if (dsft.isHasChildren()) {
Expand All @@ -976,10 +976,12 @@ public String getCollectionDatasetSchema(String dataverseAlias, Map<String, Map
if (dsfIlChild != null) {
child.setRequiredDV(dsfIlChild.isRequired());
child.setInclude(dsfIlChild.isInclude());
child.setDisplayOnCreate(dsfIlChild.isDisplayOnCreate());
child.setLocalDisplayOnCreate(dsfIlChild.getDisplayOnCreate());
} else {
child.setRequiredDV(child.isRequired() && dsft.isRequired());
child.setInclude(true);
// Default displayOnCreate to true for required child fields
child.setLocalDisplayOnCreate(child.isRequired());
}
if (child.isRequired()) {
childrenRequired.add(child.getName());
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/edu/harvard/iq/dataverse/MetadataBlock.java
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,8 @@ public void setDatasetFieldTypes(List<DatasetFieldType> datasetFieldTypes) {

public boolean isDisplayOnCreate() {
for (DatasetFieldType dsfType : datasetFieldTypes) {
Boolean displayOnCreate = dsfType.isDisplayOnCreate();
if (displayOnCreate != null && displayOnCreate) {
boolean shouldDisplayOnCreate = dsfType.shouldDisplayOnCreate();
if (shouldDisplayOnCreate) {
return true;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import jakarta.persistence.TypedQuery;
import jakarta.persistence.criteria.*;

import java.util.Comparator;
import java.util.List;

/**
Expand Down Expand Up @@ -52,68 +53,62 @@ public MetadataBlock findByName(String name) {
public List<MetadataBlock> listMetadataBlocksDisplayedOnCreate(Dataverse ownerDataverse) {
CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
CriteriaQuery<MetadataBlock> criteriaQuery = criteriaBuilder.createQuery(MetadataBlock.class);
Root<MetadataBlock> metadataBlockRoot = criteriaQuery.from(MetadataBlock.class);
Join<MetadataBlock, DatasetFieldType> datasetFieldTypeJoin = metadataBlockRoot.join("datasetFieldTypes");

Root<Dataverse> dataverseRoot = criteriaQuery.from(Dataverse.class);

// Join metadataBlocks from Dataverse
Join<Dataverse, MetadataBlock> metadataBlockJoin = dataverseRoot.join("metadataBlocks");

// Join datasetFieldTypes from MetadataBlock
Join<MetadataBlock, DatasetFieldType> datasetFieldTypeJoin = metadataBlockJoin.join("datasetFieldTypes");

Predicate displayOnCreatePredicate = criteriaBuilder.isTrue(datasetFieldTypeJoin.get("displayOnCreate"));
Predicate requiredPredicate = criteriaBuilder.isTrue(datasetFieldTypeJoin.get("required"));

if (ownerDataverse != null) {
Root<Dataverse> dataverseRoot = criteriaQuery.from(Dataverse.class);
Join<Dataverse, DataverseFieldTypeInputLevel> datasetFieldTypeInputLevelJoin =
dataverseRoot.join("dataverseFieldTypeInputLevels", JoinType.LEFT);

// Subquery to check if the input level exists
Subquery<Long> inputLevelSubquery = criteriaQuery.subquery(Long.class);
Root<DataverseFieldTypeInputLevel> subqueryRoot = inputLevelSubquery.from(DataverseFieldTypeInputLevel.class);
inputLevelSubquery.select(criteriaBuilder.literal(1L))
.where(
criteriaBuilder.equal(subqueryRoot.get("dataverse"), dataverseRoot),
criteriaBuilder.equal(subqueryRoot.get("datasetFieldType"), datasetFieldTypeJoin)
);

// Predicate for displayOnCreate in the input level
Predicate displayOnCreateInputLevelPredicate = criteriaBuilder.and(
datasetFieldTypeInputLevelJoin.get("datasetFieldType").in(metadataBlockRoot.get("datasetFieldTypes")),
criteriaBuilder.isNotNull(datasetFieldTypeInputLevelJoin.get("displayOnCreate")),
criteriaBuilder.isTrue(datasetFieldTypeInputLevelJoin.get("displayOnCreate")));

// Predicate for required fields
Predicate requiredPredicate = criteriaBuilder.and(
datasetFieldTypeInputLevelJoin.get("datasetFieldType").in(metadataBlockRoot.get("datasetFieldTypes")),
criteriaBuilder.isTrue(datasetFieldTypeInputLevelJoin.get("required")));

// Predicate for default displayOnCreate (when there is no input level)
Predicate defaultDisplayOnCreatePredicate = criteriaBuilder.and(
criteriaBuilder.not(criteriaBuilder.exists(inputLevelSubquery)),
criteriaBuilder.or(
criteriaBuilder.isTrue(datasetFieldTypeJoin.get("displayOnCreate")),
criteriaBuilder.isTrue(datasetFieldTypeJoin.get("required"))
));

Predicate unionPredicate = criteriaBuilder.or(
displayOnCreateInputLevelPredicate,
requiredPredicate,
defaultDisplayOnCreatePredicate
// Ensure we filter for the specific Dataverse
Predicate dataversePredicate = criteriaBuilder.equal(dataverseRoot.get("id"), ownerDataverse.getId());

// Join DataverseFieldTypeInputLevel (LEFT JOIN)
Join<Dataverse, DataverseFieldTypeInputLevel> datasetFieldTypeInputLevelJoin =
dataverseRoot.join("dataverseFieldTypeInputLevels", JoinType.LEFT);

// Check if input level explicitly defines displayOnCreate
Predicate inputLevelDisplayPredicate = criteriaBuilder.and(
criteriaBuilder.equal(datasetFieldTypeInputLevelJoin.get("datasetFieldType"), datasetFieldTypeJoin),
criteriaBuilder.isTrue(datasetFieldTypeInputLevelJoin.get("displayOnCreate"))
);

// Check if input level explicitly defines required
Predicate inputLevelRequiredPredicate = criteriaBuilder.and(
criteriaBuilder.equal(datasetFieldTypeInputLevelJoin.get("datasetFieldType"), datasetFieldTypeJoin),
criteriaBuilder.isTrue(datasetFieldTypeInputLevelJoin.get("required"))
);

criteriaQuery.where(criteriaBuilder.and(
criteriaBuilder.equal(dataverseRoot.get("id"), ownerDataverse.getId()),
metadataBlockRoot.in(dataverseRoot.get("metadataBlocks")),
unionPredicate
));
Predicate finalDisplayPredicate = criteriaBuilder.or(inputLevelDisplayPredicate, displayOnCreatePredicate);
Predicate finalRequiredPredicate = criteriaBuilder.or(inputLevelRequiredPredicate, requiredPredicate);

criteriaQuery.where(
dataversePredicate,
criteriaBuilder.or(finalDisplayPredicate, finalRequiredPredicate)
);
} else {
// When ownerDataverse is null, we need to include fields that are either displayOnCreate=true OR required=true
Predicate displayOnCreatePredicate = criteriaBuilder.isTrue(datasetFieldTypeJoin.get("displayOnCreate"));
Predicate requiredPredicate = criteriaBuilder.isTrue(datasetFieldTypeJoin.get("required"));

// We also need to ensure that fields from linked metadata blocks are included
Predicate linkedFieldsPredicate = criteriaBuilder.and(
criteriaBuilder.isNotNull(datasetFieldTypeJoin.get("id")),
criteriaBuilder.or(displayOnCreatePredicate, requiredPredicate)
criteriaBuilder.isNotNull(datasetFieldTypeJoin.get("id")),
criteriaBuilder.or(displayOnCreatePredicate, requiredPredicate)
);

criteriaQuery.where(linkedFieldsPredicate);
}

criteriaQuery.select(metadataBlockRoot).distinct(true);
return em.createQuery(criteriaQuery).getResultList();
criteriaQuery.select(metadataBlockJoin).distinct(true);

List<MetadataBlock> result = em.createQuery(criteriaQuery).getResultList();

// Order by id
result.sort(Comparator.comparing(MetadataBlock::getId));

return result;
}
}
3 changes: 1 addition & 2 deletions src/main/java/edu/harvard/iq/dataverse/TemplatePage.java
Original file line number Diff line number Diff line change
Expand Up @@ -172,10 +172,9 @@ private void updateDatasetFieldInputLevels(){
);
if (dsfIl != null) {
dsf.setInclude(dsfIl.isInclude());
dsf.getDatasetFieldType().setDisplayOnCreate(dsfIl.isDisplayOnCreate());
dsf.getDatasetFieldType().setLocalDisplayOnCreate(dsfIl.getDisplayOnCreate());
} else {
dsf.setInclude(true);
dsf.getDatasetFieldType().setDisplayOnCreate(false);
}
}
}
Expand Down
5 changes: 4 additions & 1 deletion src/main/java/edu/harvard/iq/dataverse/api/Dataverses.java
Original file line number Diff line number Diff line change
Expand Up @@ -803,7 +803,10 @@ private List<DataverseFieldTypeInputLevel> parseInputLevels(JsonArray inputLevel

boolean required = inputLevel.getBoolean("required");
boolean include = inputLevel.getBoolean("include");
boolean displayOnCreate = inputLevel.getBoolean("displayOnCreate", false);
Boolean displayOnCreate = null;
if(inputLevel.containsKey("displayOnCreate")) {
displayOnCreate = inputLevel.getBoolean("displayOnCreate", false);
}

if (required && !include) {
String errorMessage = MessageFormat.format(BundleUtil.getStringFromBundle("dataverse.inputlevels.error.cannotberequiredifnotincluded"), datasetFieldTypeName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ public JsonObjectBuilder json( DatasetVersion dsv ) {

public JsonObjectBuilder json( MetadataBlock blk ) {
if (blk == null) return null;
Boolean displayOnCreate = blk.isDisplayOnCreate();
boolean displayOnCreate = blk.isDisplayOnCreate();
return jsonObjectBuilder().add("id", blk.getId())
.add("displayName", blk.getDisplayName())
.add("displayOnCreate", displayOnCreate == null ? false : displayOnCreate)
.add("displayOnCreate", displayOnCreate)
.add("name", blk.getName())
;
}
Expand Down
Loading