Skip to content

Commit b0d9ab0

Browse files
authored
Merge pull request #11343 from GlobalDataverseCommunityConsortium/10476-display-on-create-field-option-new
DisplayOnCreate Fixes
2 parents 1480dbc + d66ca3b commit b0d9ab0

18 files changed

+167
-125
lines changed

src/main/java/edu/harvard/iq/dataverse/DatasetFieldServiceBean.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -944,7 +944,7 @@ private Predicate buildFieldPresentInDataversePredicate(Dataverse dataverse, boo
944944
// Predicate for displayOnCreate in input level
945945
Predicate displayOnCreateInputLevelPredicate = criteriaBuilder.and(
946946
criteriaBuilder.equal(datasetFieldTypeRoot, datasetFieldTypeInputLevelJoin.get("datasetFieldType")),
947-
criteriaBuilder.isTrue(datasetFieldTypeInputLevelJoin.get("displayOnCreate"))
947+
criteriaBuilder.equal(datasetFieldTypeInputLevelJoin.get("displayOnCreate"), Boolean.TRUE)
948948
);
949949

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

959960
// Define a predicate to exclude DatasetFieldTypes that have no associated input level (i.e., the subquery does not return a result).

src/main/java/edu/harvard/iq/dataverse/DatasetFieldType.java

+21-7
Original file line numberDiff line numberDiff line change
@@ -273,21 +273,35 @@ public void setValidationFormat(String validationFormat) {
273273
* Determines whether this field type is displayed in the form when creating
274274
* the Dataset (or only later when editing after the initial creation).
275275
*/
276-
@Column(name = "displayoncreate", nullable = true)
277-
private Boolean displayOnCreate;
276+
private boolean displayOnCreate;
278277

279-
public Boolean isDisplayOnCreate() {
278+
public boolean isDisplayOnCreate() {
280279
return displayOnCreate;
281280
}
282281

283-
public Boolean getDisplayOnCreate() {
284-
return displayOnCreate;
282+
public void setDisplayOnCreate(boolean displayOnCreate) {
283+
this.displayOnCreate = displayOnCreate;
285284
}
286285

287-
public void setDisplayOnCreate(Boolean displayOnCreate) {
288-
this.displayOnCreate = displayOnCreate;
286+
/**
287+
* Determines whether this field type is displayed in the form when creating
288+
* the Dataset (or only later when editing after the initial creation).
289+
*/
290+
@Transient
291+
private Boolean localDisplayOnCreate;
292+
293+
public Boolean getLocalDisplayOnCreate() {
294+
return localDisplayOnCreate;
295+
}
296+
297+
public void setLocalDisplayOnCreate(Boolean localDisplayOnCreate) {
298+
this.localDisplayOnCreate = localDisplayOnCreate;
289299
}
290300

301+
public boolean shouldDisplayOnCreate() {
302+
return (localDisplayOnCreate == null) ? displayOnCreate : localDisplayOnCreate;
303+
}
304+
291305
public boolean isControlledVocabulary() {
292306
return allowControlledVocabulary;
293307
}

src/main/java/edu/harvard/iq/dataverse/DatasetPage.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -1856,7 +1856,10 @@ private void updateDatasetFieldInputLevels() {
18561856
if (dsf != null){
18571857
// Yes, call "setInclude"
18581858
dsf.setInclude(oneDSFieldTypeInputLevel.isInclude());
1859-
dsf.getDatasetFieldType().setDisplayOnCreate(oneDSFieldTypeInputLevel.isDisplayOnCreate());
1859+
Boolean displayOnCreate = oneDSFieldTypeInputLevel.getDisplayOnCreate();
1860+
if (displayOnCreate!= null) {
1861+
dsf.getDatasetFieldType().setLocalDisplayOnCreate(displayOnCreate);
1862+
}
18601863
// remove from hash
18611864
mapDatasetFields.remove(oneDSFieldTypeInputLevel.getDatasetFieldType().getId());
18621865
}

src/main/java/edu/harvard/iq/dataverse/Dataverse.java

+8-1
Original file line numberDiff line numberDiff line change
@@ -438,10 +438,17 @@ public boolean isDatasetFieldTypeInInputLevels(Long datasetFieldTypeId) {
438438
.anyMatch(inputLevel -> inputLevel.getDatasetFieldType().getId().equals(datasetFieldTypeId));
439439
}
440440

441+
public DataverseFieldTypeInputLevel getDatasetFieldTypeInInputLevels(Long datasetFieldTypeId) {
442+
return dataverseFieldTypeInputLevels.stream()
443+
.filter(inputLevel -> inputLevel.getDatasetFieldType().getId().equals(datasetFieldTypeId))
444+
.findFirst()
445+
.orElse(null);
446+
}
447+
441448
public boolean isDatasetFieldTypeDisplayOnCreateAsInputLevel(Long datasetFieldTypeId) {
442449
return dataverseFieldTypeInputLevels.stream()
443450
.anyMatch(inputLevel -> inputLevel.getDatasetFieldType().getId().equals(datasetFieldTypeId)
444-
&& inputLevel.isDisplayOnCreate());
451+
&& Boolean.TRUE.equals(inputLevel.getDisplayOnCreate()));
445452
}
446453

447454
public Template getDefaultTemplate() {

src/main/java/edu/harvard/iq/dataverse/DataverseFieldTypeInputLevel.java

+12-6
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
package edu.harvard.iq.dataverse;
77

88
import java.io.Serializable;
9+
10+
import jakarta.persistence.Column;
911
import jakarta.persistence.Entity;
1012
import jakarta.persistence.GeneratedValue;
1113
import jakarta.persistence.GenerationType;
@@ -38,8 +40,9 @@
3840
, uniqueConstraints={
3941
@UniqueConstraint(columnNames={"dataverse_id", "datasetfieldtype_id"})}
4042
, indexes = {@Index(columnList="dataverse_id")
41-
, @Index(columnList="datasetfieldtype_id")
42-
, @Index(columnList="required")}
43+
, @Index(columnList="datasetfieldtype_id")
44+
, @Index(columnList="required")
45+
, @Index(columnList="displayOnCreate")}
4346
)
4447
@Entity
4548
public class DataverseFieldTypeInputLevel implements Serializable {
@@ -58,11 +61,14 @@ public class DataverseFieldTypeInputLevel implements Serializable {
5861
private DatasetFieldType datasetFieldType;
5962
private boolean include;
6063
private boolean required;
61-
private boolean displayOnCreate;
64+
65+
66+
@Column(nullable = true)
67+
private Boolean displayOnCreate;
6268

6369
public DataverseFieldTypeInputLevel () {}
6470

65-
public DataverseFieldTypeInputLevel (DatasetFieldType fieldType, Dataverse dataverse, boolean required, boolean include, boolean displayOnCreate) {
71+
public DataverseFieldTypeInputLevel (DatasetFieldType fieldType, Dataverse dataverse, boolean required, boolean include, Boolean displayOnCreate) {
6672
this.datasetFieldType = fieldType;
6773
this.dataverse = dataverse;
6874
this.required = required;
@@ -117,11 +123,11 @@ public void setRequired(boolean required) {
117123
this.required = required;
118124
}
119125

120-
public boolean isDisplayOnCreate() {
126+
public Boolean getDisplayOnCreate() {
121127
return displayOnCreate;
122128
}
123129

124-
public void setDisplayOnCreate(boolean displayOnCreate) {
130+
public void setDisplayOnCreate(Boolean displayOnCreate) {
125131
this.displayOnCreate = displayOnCreate;
126132
}
127133

src/main/java/edu/harvard/iq/dataverse/DataversePage.java

+5-6
Original file line numberDiff line numberDiff line change
@@ -1025,12 +1025,11 @@ private void loadInputLevels(DatasetFieldType dsft, Long dataverseIdForInputLeve
10251025
if (dsfIl != null) {
10261026
dsft.setRequiredDV(dsfIl.isRequired());
10271027
dsft.setInclude(dsfIl.isInclude());
1028-
dsft.setDisplayOnCreate(dsfIl.isDisplayOnCreate());
1028+
dsft.setLocalDisplayOnCreate(dsfIl.getDisplayOnCreate());
10291029
} else {
10301030
// If there is no input level, use the default values
10311031
dsft.setRequiredDV(dsft.isRequired());
10321032
dsft.setInclude(true);
1033-
dsft.setDisplayOnCreate(false);
10341033
}
10351034
}
10361035

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

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

13501349
if (existingLevel != null) {
1351-
existingLevel.setDisplayOnCreate(dsft.isDisplayOnCreate());
1350+
existingLevel.setDisplayOnCreate(dsft.getLocalDisplayOnCreate());
13521351
existingLevel.setInclude(dsft.isInclude());
13531352
existingLevel.setRequired(dsft.isRequiredDV());
13541353
listDFTIL.add(existingLevel);
1355-
} else if (dsft.isInclude() || dsft.isDisplayOnCreate() || dsft.isRequiredDV()) {
1354+
} else if (dsft.isInclude() || (dsft.getLocalDisplayOnCreate()!=null) || dsft.isRequiredDV()) {
13561355
// Only create new input level if there is any specific configuration
13571356
listDFTIL.add(new DataverseFieldTypeInputLevel(
13581357
dsft,
13591358
dataverse,
13601359
dsft.isRequiredDV(),
13611360
dsft.isInclude(),
1362-
dsft.isDisplayOnCreate()
1361+
dsft.getLocalDisplayOnCreate()
13631362
));
13641363
}
13651364
}

src/main/java/edu/harvard/iq/dataverse/DataverseServiceBean.java

+6-4
Original file line numberDiff line numberDiff line change
@@ -961,13 +961,13 @@ public String getCollectionDatasetSchema(String dataverseAlias, Map<String, Map
961961
if (dsfIl != null) {
962962
dsft.setRequiredDV(dsfIl.isRequired());
963963
dsft.setInclude(dsfIl.isInclude());
964-
dsft.setDisplayOnCreate(dsfIl.isDisplayOnCreate());
964+
dsft.setLocalDisplayOnCreate(dsfIl.getDisplayOnCreate());
965965
} else {
966966
dsft.setRequiredDV(dsft.isRequired());
967967
dsft.setInclude(true);
968+
// Default displayOnCreate to true for required fields
969+
dsft.setLocalDisplayOnCreate(dsft.isRequired());
968970
}
969-
970-
// Process child fields if any
971971
List<String> childrenRequired = new ArrayList<>();
972972
List<String> childrenAllowed = new ArrayList<>();
973973
if (dsft.isHasChildren()) {
@@ -976,10 +976,12 @@ public String getCollectionDatasetSchema(String dataverseAlias, Map<String, Map
976976
if (dsfIlChild != null) {
977977
child.setRequiredDV(dsfIlChild.isRequired());
978978
child.setInclude(dsfIlChild.isInclude());
979-
child.setDisplayOnCreate(dsfIlChild.isDisplayOnCreate());
979+
child.setLocalDisplayOnCreate(dsfIlChild.getDisplayOnCreate());
980980
} else {
981981
child.setRequiredDV(child.isRequired() && dsft.isRequired());
982982
child.setInclude(true);
983+
// Default displayOnCreate to true for required child fields
984+
child.setLocalDisplayOnCreate(child.isRequired());
983985
}
984986
if (child.isRequired()) {
985987
childrenRequired.add(child.getName());

src/main/java/edu/harvard/iq/dataverse/MetadataBlock.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,8 @@ public void setDatasetFieldTypes(List<DatasetFieldType> datasetFieldTypes) {
102102

103103
public boolean isDisplayOnCreate() {
104104
for (DatasetFieldType dsfType : datasetFieldTypes) {
105-
Boolean displayOnCreate = dsfType.isDisplayOnCreate();
106-
if (displayOnCreate != null && displayOnCreate) {
105+
boolean shouldDisplayOnCreate = dsfType.shouldDisplayOnCreate();
106+
if (shouldDisplayOnCreate) {
107107
return true;
108108
}
109109
}

src/main/java/edu/harvard/iq/dataverse/MetadataBlockServiceBean.java

+47-52
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import jakarta.persistence.TypedQuery;
99
import jakarta.persistence.criteria.*;
1010

11+
import java.util.Comparator;
1112
import java.util.List;
1213

1314
/**
@@ -52,68 +53,62 @@ public MetadataBlock findByName(String name) {
5253
public List<MetadataBlock> listMetadataBlocksDisplayedOnCreate(Dataverse ownerDataverse) {
5354
CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
5455
CriteriaQuery<MetadataBlock> criteriaQuery = criteriaBuilder.createQuery(MetadataBlock.class);
55-
Root<MetadataBlock> metadataBlockRoot = criteriaQuery.from(MetadataBlock.class);
56-
Join<MetadataBlock, DatasetFieldType> datasetFieldTypeJoin = metadataBlockRoot.join("datasetFieldTypes");
57-
56+
Root<Dataverse> dataverseRoot = criteriaQuery.from(Dataverse.class);
57+
58+
// Join metadataBlocks from Dataverse
59+
Join<Dataverse, MetadataBlock> metadataBlockJoin = dataverseRoot.join("metadataBlocks");
60+
61+
// Join datasetFieldTypes from MetadataBlock
62+
Join<MetadataBlock, DatasetFieldType> datasetFieldTypeJoin = metadataBlockJoin.join("datasetFieldTypes");
63+
64+
Predicate displayOnCreatePredicate = criteriaBuilder.isTrue(datasetFieldTypeJoin.get("displayOnCreate"));
65+
Predicate requiredPredicate = criteriaBuilder.isTrue(datasetFieldTypeJoin.get("required"));
66+
5867
if (ownerDataverse != null) {
59-
Root<Dataverse> dataverseRoot = criteriaQuery.from(Dataverse.class);
60-
Join<Dataverse, DataverseFieldTypeInputLevel> datasetFieldTypeInputLevelJoin =
61-
dataverseRoot.join("dataverseFieldTypeInputLevels", JoinType.LEFT);
62-
63-
// Subquery to check if the input level exists
64-
Subquery<Long> inputLevelSubquery = criteriaQuery.subquery(Long.class);
65-
Root<DataverseFieldTypeInputLevel> subqueryRoot = inputLevelSubquery.from(DataverseFieldTypeInputLevel.class);
66-
inputLevelSubquery.select(criteriaBuilder.literal(1L))
67-
.where(
68-
criteriaBuilder.equal(subqueryRoot.get("dataverse"), dataverseRoot),
69-
criteriaBuilder.equal(subqueryRoot.get("datasetFieldType"), datasetFieldTypeJoin)
70-
);
71-
72-
// Predicate for displayOnCreate in the input level
73-
Predicate displayOnCreateInputLevelPredicate = criteriaBuilder.and(
74-
datasetFieldTypeInputLevelJoin.get("datasetFieldType").in(metadataBlockRoot.get("datasetFieldTypes")),
75-
criteriaBuilder.isNotNull(datasetFieldTypeInputLevelJoin.get("displayOnCreate")),
76-
criteriaBuilder.isTrue(datasetFieldTypeInputLevelJoin.get("displayOnCreate")));
77-
78-
// Predicate for required fields
79-
Predicate requiredPredicate = criteriaBuilder.and(
80-
datasetFieldTypeInputLevelJoin.get("datasetFieldType").in(metadataBlockRoot.get("datasetFieldTypes")),
81-
criteriaBuilder.isTrue(datasetFieldTypeInputLevelJoin.get("required")));
82-
83-
// Predicate for default displayOnCreate (when there is no input level)
84-
Predicate defaultDisplayOnCreatePredicate = criteriaBuilder.and(
85-
criteriaBuilder.not(criteriaBuilder.exists(inputLevelSubquery)),
86-
criteriaBuilder.or(
87-
criteriaBuilder.isTrue(datasetFieldTypeJoin.get("displayOnCreate")),
88-
criteriaBuilder.isTrue(datasetFieldTypeJoin.get("required"))
89-
));
90-
91-
Predicate unionPredicate = criteriaBuilder.or(
92-
displayOnCreateInputLevelPredicate,
93-
requiredPredicate,
94-
defaultDisplayOnCreatePredicate
68+
// Ensure we filter for the specific Dataverse
69+
Predicate dataversePredicate = criteriaBuilder.equal(dataverseRoot.get("id"), ownerDataverse.getId());
70+
71+
// Join DataverseFieldTypeInputLevel (LEFT JOIN)
72+
Join<Dataverse, DataverseFieldTypeInputLevel> datasetFieldTypeInputLevelJoin =
73+
dataverseRoot.join("dataverseFieldTypeInputLevels", JoinType.LEFT);
74+
75+
// Check if input level explicitly defines displayOnCreate
76+
Predicate inputLevelDisplayPredicate = criteriaBuilder.and(
77+
criteriaBuilder.equal(datasetFieldTypeInputLevelJoin.get("datasetFieldType"), datasetFieldTypeJoin),
78+
criteriaBuilder.isTrue(datasetFieldTypeInputLevelJoin.get("displayOnCreate"))
79+
);
80+
81+
// Check if input level explicitly defines required
82+
Predicate inputLevelRequiredPredicate = criteriaBuilder.and(
83+
criteriaBuilder.equal(datasetFieldTypeInputLevelJoin.get("datasetFieldType"), datasetFieldTypeJoin),
84+
criteriaBuilder.isTrue(datasetFieldTypeInputLevelJoin.get("required"))
9585
);
9686

97-
criteriaQuery.where(criteriaBuilder.and(
98-
criteriaBuilder.equal(dataverseRoot.get("id"), ownerDataverse.getId()),
99-
metadataBlockRoot.in(dataverseRoot.get("metadataBlocks")),
100-
unionPredicate
101-
));
87+
Predicate finalDisplayPredicate = criteriaBuilder.or(inputLevelDisplayPredicate, displayOnCreatePredicate);
88+
Predicate finalRequiredPredicate = criteriaBuilder.or(inputLevelRequiredPredicate, requiredPredicate);
89+
90+
criteriaQuery.where(
91+
dataversePredicate,
92+
criteriaBuilder.or(finalDisplayPredicate, finalRequiredPredicate)
93+
);
10294
} else {
10395
// When ownerDataverse is null, we need to include fields that are either displayOnCreate=true OR required=true
104-
Predicate displayOnCreatePredicate = criteriaBuilder.isTrue(datasetFieldTypeJoin.get("displayOnCreate"));
105-
Predicate requiredPredicate = criteriaBuilder.isTrue(datasetFieldTypeJoin.get("required"));
106-
10796
// We also need to ensure that fields from linked metadata blocks are included
10897
Predicate linkedFieldsPredicate = criteriaBuilder.and(
109-
criteriaBuilder.isNotNull(datasetFieldTypeJoin.get("id")),
110-
criteriaBuilder.or(displayOnCreatePredicate, requiredPredicate)
98+
criteriaBuilder.isNotNull(datasetFieldTypeJoin.get("id")),
99+
criteriaBuilder.or(displayOnCreatePredicate, requiredPredicate)
111100
);
112-
101+
113102
criteriaQuery.where(linkedFieldsPredicate);
114103
}
115104

116-
criteriaQuery.select(metadataBlockRoot).distinct(true);
117-
return em.createQuery(criteriaQuery).getResultList();
105+
criteriaQuery.select(metadataBlockJoin).distinct(true);
106+
107+
List<MetadataBlock> result = em.createQuery(criteriaQuery).getResultList();
108+
109+
// Order by id
110+
result.sort(Comparator.comparing(MetadataBlock::getId));
111+
112+
return result;
118113
}
119114
}

src/main/java/edu/harvard/iq/dataverse/TemplatePage.java

+1-2
Original file line numberDiff line numberDiff line change
@@ -172,10 +172,9 @@ private void updateDatasetFieldInputLevels(){
172172
);
173173
if (dsfIl != null) {
174174
dsf.setInclude(dsfIl.isInclude());
175-
dsf.getDatasetFieldType().setDisplayOnCreate(dsfIl.isDisplayOnCreate());
175+
dsf.getDatasetFieldType().setLocalDisplayOnCreate(dsfIl.getDisplayOnCreate());
176176
} else {
177177
dsf.setInclude(true);
178-
dsf.getDatasetFieldType().setDisplayOnCreate(false);
179178
}
180179
}
181180
}

src/main/java/edu/harvard/iq/dataverse/api/Dataverses.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -803,7 +803,10 @@ private List<DataverseFieldTypeInputLevel> parseInputLevels(JsonArray inputLevel
803803

804804
boolean required = inputLevel.getBoolean("required");
805805
boolean include = inputLevel.getBoolean("include");
806-
boolean displayOnCreate = inputLevel.getBoolean("displayOnCreate", false);
806+
Boolean displayOnCreate = null;
807+
if(inputLevel.containsKey("displayOnCreate")) {
808+
displayOnCreate = inputLevel.getBoolean("displayOnCreate", false);
809+
}
807810

808811
if (required && !include) {
809812
String errorMessage = MessageFormat.format(BundleUtil.getStringFromBundle("dataverse.inputlevels.error.cannotberequiredifnotincluded"), datasetFieldTypeName);

src/main/java/edu/harvard/iq/dataverse/util/json/BriefJsonPrinter.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,10 @@ public JsonObjectBuilder json( DatasetVersion dsv ) {
2525

2626
public JsonObjectBuilder json( MetadataBlock blk ) {
2727
if (blk == null) return null;
28-
Boolean displayOnCreate = blk.isDisplayOnCreate();
28+
boolean displayOnCreate = blk.isDisplayOnCreate();
2929
return jsonObjectBuilder().add("id", blk.getId())
3030
.add("displayName", blk.getDisplayName())
31-
.add("displayOnCreate", displayOnCreate == null ? false : displayOnCreate)
31+
.add("displayOnCreate", displayOnCreate)
3232
.add("name", blk.getName())
3333
;
3434
}

0 commit comments

Comments
 (0)