comparison src/main/java/edu/harvard/iq/dataverse/DatasetVersion.java @ 10:a50cf11e5178

Rewrite LGDataverse completely upgrading to dataverse4.0
author Zoe Hong <zhong@mpiwg-berlin.mpg.de>
date Tue, 08 Sep 2015 17:00:21 +0200
parents
children
comparison
equal deleted inserted replaced
9:5926d6419569 10:a50cf11e5178
1 package edu.harvard.iq.dataverse;
2
3 import edu.harvard.iq.dataverse.util.StringUtil;
4 import java.io.Serializable;
5 import java.sql.Timestamp;
6 import java.text.SimpleDateFormat;
7 import java.util.ArrayList;
8 import java.util.Collections;
9 import java.util.Comparator;
10 import java.util.Date;
11 import java.util.HashSet;
12 import java.util.LinkedList;
13 import java.util.List;
14 import java.util.Set;
15 import javax.persistence.CascadeType;
16 import javax.persistence.Column;
17 import javax.persistence.Entity;
18 import javax.persistence.EnumType;
19 import javax.persistence.Enumerated;
20 import javax.persistence.GeneratedValue;
21 import javax.persistence.GenerationType;
22 import javax.persistence.Id;
23 import javax.persistence.Index;
24 import javax.persistence.ManyToOne;
25 import javax.persistence.OneToMany;
26 import javax.persistence.OrderBy;
27 import javax.persistence.Table;
28 import javax.persistence.Temporal;
29 import javax.persistence.TemporalType;
30 import javax.persistence.Transient;
31 import javax.persistence.Version;
32 import javax.validation.ConstraintViolation;
33 import javax.validation.Validation;
34 import javax.validation.Validator;
35 import javax.validation.ValidatorFactory;
36
37 /**
38 *
39 * @author skraffmiller
40 */
41 @Entity
42 @Table(indexes = {@Index(columnList="dataset_id")} )
43 public class DatasetVersion implements Serializable {
44
45 /**
46 * Convenience comparator to compare dataset versions by their version number.
47 * The draft version is considered the latest.
48 */
49 public static final Comparator<DatasetVersion> compareByVersion = new Comparator<DatasetVersion>() {
50 @Override
51 public int compare(DatasetVersion o1, DatasetVersion o2) {
52 if ( o1.isDraft() ) {
53 return o2.isDraft() ? 0 : 1;
54 } else {
55 return (int)Math.signum( (o1.getVersionNumber().equals(o2.getVersionNumber())) ?
56 o1.getMinorVersionNumber() - o2.getMinorVersionNumber()
57 : o1.getVersionNumber() - o2.getVersionNumber() );
58 }
59 }
60 };
61
62 // TODO: Determine the UI implications of various version states
63 //IMPORTANT: If you add a new value to this enum, you will also have to modify the
64 // StudyVersionsFragment.xhtml in order to display the correct value from a Resource Bundle
65 public enum VersionState {
66
67 DRAFT, RELEASED, ARCHIVED, DEACCESSIONED
68 };
69
70 public enum License {
71 NONE, CC0
72 }
73
74 /**
75 * @todo What does the GUI use for a default license? What does the "native"
76 * API use? See also https://github.com/IQSS/dataverse/issues/1385
77 */
78 public static DatasetVersion.License defaultLicense = DatasetVersion.License.CC0;
79
80 public DatasetVersion() {
81
82 }
83
84 @Id
85 @GeneratedValue(strategy = GenerationType.IDENTITY)
86 private Long id;
87
88 public Long getId() {
89 return this.id;
90 }
91
92 public void setId(Long id) {
93 this.id = id;
94 }
95
96 public String getUNF() {
97 return UNF;
98 }
99
100 public void setUNF(String UNF) {
101 this.UNF = UNF;
102 }
103
104
105 /**
106 * This is JPA's optimistic locking mechanism, and has no semantic meaning in the DV object model.
107 * @return the object db version
108 */
109 public Long getVersion() {
110 return this.version;
111 }
112
113 public void setVersion(Long version) {
114 }
115
116 private String UNF;
117
118 @Version
119 private Long version;
120
121 private Long versionNumber;
122 private Long minorVersionNumber;
123 public static final int VERSION_NOTE_MAX_LENGTH = 1000;
124 @Column(length = VERSION_NOTE_MAX_LENGTH)
125 private String versionNote;
126
127 @Enumerated(EnumType.STRING)
128 private VersionState versionState;
129
130 @Enumerated(EnumType.STRING)
131 private License license;
132
133 public License getLicense() {
134 return license;
135 }
136
137 public void setLicense(License license) {
138 this.license = license;
139 }
140
141 @ManyToOne
142 private Dataset dataset;
143
144 @OneToMany(mappedBy = "datasetVersion", cascade = {CascadeType.REMOVE, CascadeType.MERGE, CascadeType.PERSIST})
145 @OrderBy("label") // this is not our preferred ordering, which is with the AlphaNumericComparator, but does allow the files to be grouped by category
146 private List<FileMetadata> fileMetadatas = new ArrayList();
147
148 public List<FileMetadata> getFileMetadatas() {
149 return fileMetadatas;
150 }
151
152 public List<FileMetadata> getFileMetadatasSorted() {
153 Collections.sort(fileMetadatas, FileMetadata.compareByLabel);
154 return fileMetadatas;
155 }
156
157 public void setFileMetadatas(List<FileMetadata> fileMetadatas) {
158 this.fileMetadatas = fileMetadatas;
159 }
160
161 @OneToMany(mappedBy = "datasetVersion", orphanRemoval = true, cascade = {CascadeType.REMOVE, CascadeType.MERGE, CascadeType.PERSIST})
162 //@OrderBy("datasetField.displayOrder")
163 private List<DatasetField> datasetFields = new ArrayList();
164
165 public List<DatasetField> getDatasetFields() {
166 return datasetFields;
167 }
168
169 /**
170 * Sets the dataset fields for this version. Also updates the fields to
171 * have @{code this} as their dataset version.
172 * @param datasetFields
173 */
174 public void setDatasetFields(List<DatasetField> datasetFields) {
175 for ( DatasetField dsf : datasetFields ) {
176 dsf.setDatasetVersion(this);
177 }
178 this.datasetFields = datasetFields;
179 }
180
181 /*
182 @OneToMany(mappedBy="studyVersion", cascade={CascadeType.REMOVE, CascadeType.PERSIST})
183 private List<VersionContributor> versionContributors;
184 */
185 @Temporal(value = TemporalType.TIMESTAMP)
186 @Column( nullable=false )
187 private Date createTime;
188 @Temporal(value = TemporalType.TIMESTAMP)
189 @Column( nullable=false )
190 private Date lastUpdateTime;
191 @Temporal(value = TemporalType.TIMESTAMP)
192 private Date releaseTime;
193 @Temporal(value = TemporalType.TIMESTAMP)
194 private Date archiveTime;
195 public static final int ARCHIVE_NOTE_MAX_LENGTH = 1000;
196 @Column(length = ARCHIVE_NOTE_MAX_LENGTH)
197 private String archiveNote;
198 private String deaccessionLink;
199
200 @Column(columnDefinition="TEXT")
201 private String termsOfUse;
202
203 @Column(columnDefinition="TEXT")
204 private String termsOfAccess;
205
206 @Column(columnDefinition="TEXT")
207 private String confidentialityDeclaration;
208
209 @Column(columnDefinition="TEXT")
210 private String specialPermissions;
211
212 @Column(columnDefinition="TEXT")
213 private String restrictions;
214
215 @Column(columnDefinition="TEXT")
216 private String citationRequirements;
217
218 @Column(columnDefinition="TEXT")
219 private String depositorRequirements;
220
221 @Column(columnDefinition="TEXT")
222 private String conditions;
223
224 @Column(columnDefinition="TEXT")
225 private String disclaimer;
226
227 @Column(columnDefinition="TEXT")
228 private String dataAccessPlace;
229
230 @Column(columnDefinition="TEXT")
231 private String originalArchive;
232
233 @Column(columnDefinition="TEXT")
234 private String availabilityStatus;
235
236 @Column(columnDefinition="TEXT")
237 private String contactForAccess;
238
239 @Column(columnDefinition="TEXT")
240 private String sizeOfCollection;
241
242 @Column(columnDefinition="TEXT")
243 private String studyCompletion;
244
245 private boolean fileAccessRequest;
246
247 public boolean isFileAccessRequest() {
248 return fileAccessRequest;
249 }
250
251 public void setFileAccessRequest(boolean fileAccessRequest) {
252 this.fileAccessRequest = fileAccessRequest;
253 }
254
255 private boolean inReview;
256 public void setInReview(boolean inReview){
257 this.inReview = inReview;
258 }
259
260 public boolean isInReview() {
261 return inReview;
262 }
263
264 public String getStudyCompletion() {
265 return studyCompletion;
266 }
267
268 public void setStudyCompletion(String studyCompletion) {
269 this.studyCompletion = studyCompletion;
270 }
271
272
273 public String getTermsOfUse() {
274 return termsOfUse;
275 }
276
277 /**
278 * Quick hack to disable <script> tags
279 * for Terms of Use and Terms of Access.
280 *
281 * Need to add jsoup or something similar.
282 *
283 * @param str
284 * @return
285 */
286 private String stripScriptTags(String str){
287 if (str == null){
288 return null;
289 }
290
291 str = str.replaceAll("(?i)<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>", "");
292 str = str.replaceAll("(?i)<\\/script>", "");
293 str = str.replaceAll("(?i)<script\\b", "");
294
295 return str;
296 }
297
298 public void setTermsOfUse(String termsOfUse) {
299 this.termsOfUse = termsOfUse;
300 }
301
302 public String getTermsOfAccess() {
303 return termsOfAccess;
304 }
305
306 public void setTermsOfAccess(String termsOfAccess) {
307 this.termsOfAccess = termsOfAccess;
308 }
309
310
311 public String getConfidentialityDeclaration() {
312 return confidentialityDeclaration;
313 }
314
315 public void setConfidentialityDeclaration(String confidentialityDeclaration) {
316 this.confidentialityDeclaration = confidentialityDeclaration;
317 }
318
319 public String getSpecialPermissions() {
320 return specialPermissions;
321 }
322
323 public void setSpecialPermissions(String specialPermissions) {
324 this.specialPermissions = specialPermissions;
325 }
326
327 public String getRestrictions() {
328 return restrictions;
329 }
330
331 public void setRestrictions(String restrictions) {
332 this.restrictions = restrictions;
333 }
334
335 public String getCitationRequirements() {
336 return citationRequirements;
337 }
338
339 public void setCitationRequirements(String citationRequirements) {
340 this.citationRequirements = citationRequirements;
341 }
342
343 public String getDepositorRequirements() {
344 return depositorRequirements;
345 }
346
347 public void setDepositorRequirements(String depositorRequirements) {
348 this.depositorRequirements = depositorRequirements;
349 }
350
351 public String getConditions() {
352 return conditions;
353 }
354
355 public void setConditions(String conditions) {
356 this.conditions = conditions;
357 }
358
359 public String getDisclaimer() {
360 return disclaimer;
361 }
362
363 public void setDisclaimer(String disclaimer) {
364 this.disclaimer = disclaimer;
365 }
366
367 public String getDataAccessPlace() {
368 return dataAccessPlace;
369 }
370
371 public void setDataAccessPlace(String dataAccessPlace) {
372 this.dataAccessPlace = dataAccessPlace;
373 }
374
375 public String getOriginalArchive() {
376 return originalArchive;
377 }
378
379 public void setOriginalArchive(String originalArchive) {
380 this.originalArchive = originalArchive;
381 }
382
383 public String getAvailabilityStatus() {
384 return availabilityStatus;
385 }
386
387 public void setAvailabilityStatus(String availabilityStatus) {
388 this.availabilityStatus = availabilityStatus;
389 }
390
391 public String getContactForAccess() {
392 return contactForAccess;
393 }
394
395 public void setContactForAccess(String contactForAccess) {
396 this.contactForAccess = contactForAccess;
397 }
398
399 public String getSizeOfCollection() {
400 return sizeOfCollection;
401 }
402
403 public void setSizeOfCollection(String sizeOfCollection) {
404 this.sizeOfCollection = sizeOfCollection;
405 }
406
407
408 public Date getArchiveTime() {
409 return archiveTime;
410 }
411
412 public void setArchiveTime(Date archiveTime) {
413 this.archiveTime = archiveTime;
414 }
415
416 public String getArchiveNote() {
417 return archiveNote;
418 }
419
420 public void setArchiveNote(String note) {
421 // @todo should this be using bean validation for trsting note length?
422 if (note != null && note.length() > ARCHIVE_NOTE_MAX_LENGTH) {
423 throw new IllegalArgumentException("Error setting archiveNote: String length is greater than maximum (" + ARCHIVE_NOTE_MAX_LENGTH + ")."
424 + " StudyVersion id=" + id + ", archiveNote=" + note);
425 }
426 this.archiveNote = note;
427 }
428
429 public String getDeaccessionLink() {
430 return deaccessionLink;
431 }
432
433 public void setDeaccessionLink(String deaccessionLink) {
434 this.deaccessionLink = deaccessionLink;
435 }
436
437 public GlobalId getDeaccessionLinkAsGlobalId() {
438 return new GlobalId(deaccessionLink);
439 }
440
441 public Date getCreateTime() {
442 return createTime;
443 }
444
445 public void setCreateTime(Date createTime) {
446 this.createTime = createTime;
447 }
448
449 public Date getLastUpdateTime() {
450 return lastUpdateTime;
451 }
452
453 public void setLastUpdateTime(Date lastUpdateTime) {
454 if (createTime == null) {
455 createTime = lastUpdateTime;
456 }
457 this.lastUpdateTime = lastUpdateTime;
458 }
459
460 public String getVersionDate() {
461 if (this.lastUpdateTime == null){
462 return null;
463 }
464 return new SimpleDateFormat("MMMM d, yyyy").format(lastUpdateTime);
465 }
466
467 public String getVersionYear() {
468 return new SimpleDateFormat("yyyy").format(lastUpdateTime);
469 }
470
471 public Date getReleaseTime() {
472 return releaseTime;
473 }
474
475 public void setReleaseTime(Date releaseTime) {
476 this.releaseTime = releaseTime;
477 }
478
479 @OneToMany(mappedBy = "datasetVersion")
480 private List<DatasetVersionUser> datasetVersionUsers;
481
482 public List<DatasetVersionUser> getDatasetVersionUsers() {
483 return datasetVersionUsers;
484 }
485
486 public void setUserDatasets(List<DatasetVersionUser> datasetVersionUsers) {
487 this.datasetVersionUsers = datasetVersionUsers;
488 }
489
490 public List<String> getVersionContributorIdentifiers() {
491 if (this.getDatasetVersionUsers() == null) {
492 return Collections.emptyList();
493 }
494 List<String> ret = new LinkedList<>();
495 for (DatasetVersionUser contributor : this.getDatasetVersionUsers()) {
496 ret.add(contributor.getAuthenticatedUser().getIdentifier());
497 }
498 return ret;
499 }
500
501 @Transient
502 private String contributorNames;
503
504 public String getContributorNames() {
505 return contributorNames;
506 }
507
508 public void setContributorNames(String contributorNames) {
509 this.contributorNames = contributorNames;
510 }
511
512
513 public String getVersionNote() {
514 return versionNote;
515 }
516
517 public DatasetVersionDifference getDefaultVersionDifference() {
518 // if version is deaccessioned ignore it for differences purposes
519 int index = 0;
520 int size = this.getDataset().getVersions().size();
521 if (this.isDeaccessioned()) {
522 return null;
523 }
524 for (DatasetVersion dsv : this.getDataset().getVersions()) {
525 if (this.equals(dsv)) {
526 if ((index + 1) <= (size - 1)) {
527 for (DatasetVersion dvTest : this.getDataset().getVersions().subList(index + 1, size)) {
528 if (!dvTest.isDeaccessioned()) {
529 DatasetVersionDifference dvd = new DatasetVersionDifference(this, dvTest);
530 return dvd;
531 }
532 }
533 }
534 }
535 index++;
536 }
537 return null;
538 }
539
540 public VersionState getPriorVersionState() {
541 int index = 0;
542 int size = this.getDataset().getVersions().size();
543 if (this.isDeaccessioned()) {
544 return null;
545 }
546 for (DatasetVersion dsv : this.getDataset().getVersions()) {
547 if (this.equals(dsv)) {
548 if ((index + 1) <= (size - 1)) {
549 for (DatasetVersion dvTest : this.getDataset().getVersions().subList(index + 1, size)) {
550 return dvTest.getVersionState();
551 }
552 }
553 }
554 index++;
555 }
556 return null;
557 }
558
559 public void setVersionNote(String note) {
560 if (note != null && note.length() > VERSION_NOTE_MAX_LENGTH) {
561 throw new IllegalArgumentException("Error setting versionNote: String length is greater than maximum (" + VERSION_NOTE_MAX_LENGTH + ")."
562 + " StudyVersion id=" + id + ", versionNote=" + note);
563 }
564 this.versionNote = note;
565 }
566
567 public Long getVersionNumber() {
568 return versionNumber;
569 }
570
571 public void setVersionNumber(Long versionNumber) {
572 this.versionNumber = versionNumber;
573 }
574
575 public Long getMinorVersionNumber() {
576 return minorVersionNumber;
577 }
578
579 public void setMinorVersionNumber(Long minorVersionNumber) {
580 this.minorVersionNumber = minorVersionNumber;
581 }
582
583 public String getFriendlyVersionNumber(){
584 if (this.isDraft()) {
585 return "DRAFT";
586 } else {
587 return versionNumber.toString() + "." + minorVersionNumber.toString();
588 }
589 }
590
591 public VersionState getVersionState() {
592 return versionState;
593 }
594
595 public void setVersionState(VersionState versionState) {
596
597 this.versionState = versionState;
598 }
599
600 public boolean isReleased() {
601 return versionState.equals(VersionState.RELEASED);
602 }
603
604 public boolean isDraft() {
605 return versionState.equals(VersionState.DRAFT);
606 }
607
608 public boolean isWorkingCopy() {
609 return versionState.equals(VersionState.DRAFT);
610 }
611
612 public boolean isArchived() {
613 return versionState.equals(VersionState.ARCHIVED);
614 }
615
616 public boolean isDeaccessioned() {
617 return versionState.equals(VersionState.DEACCESSIONED);
618 }
619
620 public boolean isRetiredCopy() {
621 return (versionState.equals(VersionState.ARCHIVED) || versionState.equals(VersionState.DEACCESSIONED));
622 }
623
624 public boolean isMinorUpdate() {
625 if (this.dataset.getLatestVersion().isWorkingCopy()) {
626 if (this.dataset.getVersions().size() > 1 && this.dataset.getVersions().get(1) != null) {
627 if (this.dataset.getVersions().get(1).isDeaccessioned()) {
628 return false;
629 }
630 }
631 }
632 if (this.getDataset().getReleasedVersion() != null) {
633 if (this.getFileMetadatas().size() != this.getDataset().getReleasedVersion().getFileMetadatas().size()){
634 return false;
635 } else {
636 List <DataFile> current = new ArrayList();
637 List <DataFile> previous = new ArrayList();
638 for (FileMetadata fmdc : this.getFileMetadatas()){
639 current.add(fmdc.getDataFile());
640 }
641 for (FileMetadata fmdc : this.getDataset().getReleasedVersion().getFileMetadatas()){
642 previous.add(fmdc.getDataFile());
643 }
644 for (DataFile fmd: current){
645 previous.remove(fmd);
646 }
647 return previous.isEmpty();
648 }
649 }
650 return true;
651 }
652
653 public DatasetVersion getMostRecentlyReleasedVersion() {
654 if (this.isReleased()) {
655 return this;
656 } else {
657 if (this.getDataset().isReleased()) {
658 for (DatasetVersion testVersion : this.dataset.getVersions()) {
659 if (testVersion.isReleased()) {
660 return testVersion;
661 }
662 }
663 }
664 }
665 return null;
666 }
667
668 public DatasetVersion getLargestMinorRelease() {
669
670 if (this.getDataset().isReleased()) {
671 for (DatasetVersion testVersion : this.dataset.getVersions()) {
672 if (testVersion.getVersionNumber() != null && testVersion.getVersionNumber().equals(this.getVersionNumber())) {
673 return testVersion;
674 }
675 }
676 }
677
678 return this;
679 }
680
681 public Dataset getDataset() {
682 return dataset;
683 }
684
685 public void setDataset(Dataset dataset) {
686 this.dataset = dataset;
687 }
688
689 @Override
690 public int hashCode() {
691 int hash = 0;
692 hash += (id != null ? id.hashCode() : 0);
693 return hash;
694 }
695
696 @Override
697 public boolean equals(Object object) {
698 // TODO: Warning - this method won't work in the case the id fields are not set
699 if (!(object instanceof DatasetVersion)) {
700 return false;
701 }
702 DatasetVersion other = (DatasetVersion) object;
703 if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
704 return false;
705 }
706 return true;
707 }
708
709 @Override
710 public String toString() {
711 return "[DatasetVersion id:" + getId() + "]";
712 }
713
714 public boolean isLatestVersion() {
715 return this.equals(this.getDataset().getLatestVersion());
716 }
717
718 public String getTitle() {
719 String retVal = "";
720 for (DatasetField dsfv : this.getDatasetFields()) {
721 if (dsfv.getDatasetFieldType().getName().equals(DatasetFieldConstant.title)) {
722 retVal = dsfv.getDisplayValue();
723 }
724 }
725 return retVal;
726 }
727
728 public String getProductionDate() {
729 //todo get "Production Date" from datasetfieldvalue table
730 return "Production Date";
731 }
732
733 public List<DatasetAuthor> getDatasetAuthors() {
734 //todo get "List of Authors" from datasetfieldvalue table
735 List retList = new ArrayList();
736 for (DatasetField dsf : this.getDatasetFields()) {
737 Boolean addAuthor = true;
738 if (dsf.getDatasetFieldType().getName().equals(DatasetFieldConstant.author)) {
739 for (DatasetFieldCompoundValue authorValue : dsf.getDatasetFieldCompoundValues()) {
740 DatasetAuthor datasetAuthor = new DatasetAuthor();
741 for (DatasetField subField : authorValue.getChildDatasetFields()) {
742 if (subField.getDatasetFieldType().getName().equals(DatasetFieldConstant.authorName)) {
743 if (subField.isEmptyForDisplay()) {
744 addAuthor = false;
745 }
746 datasetAuthor.setName(subField);
747 }
748 if (subField.getDatasetFieldType().getName().equals(DatasetFieldConstant.authorAffiliation)) {
749 datasetAuthor.setAffiliation(subField);
750 }
751 }
752 if (addAuthor) {
753 retList.add(datasetAuthor);
754 }
755 }
756 }
757 }
758 return retList;
759 }
760
761 public String getDatasetProducersString(){
762 String retVal = "";
763 for (DatasetField dsf : this.getDatasetFields()) {
764 if (dsf.getDatasetFieldType().getName().equals(DatasetFieldConstant.producer)) {
765 for (DatasetFieldCompoundValue authorValue : dsf.getDatasetFieldCompoundValues()) {
766 for (DatasetField subField : authorValue.getChildDatasetFields()) {
767 if (subField.getDatasetFieldType().getName().equals(DatasetFieldConstant.producerName)) {
768 if (retVal.isEmpty()){
769 retVal = subField.getDisplayValue();
770 } else {
771 retVal += ", " + subField.getDisplayValue();
772 }
773 }
774 }
775 }
776 }
777 }
778 return retVal;
779 }
780
781 public void setDatasetAuthors(List<DatasetAuthor> authors) {
782 // FIXME add the authores to the relevant fields
783 }
784
785 public String getCitation() {
786 return getCitation(false);
787 }
788
789 public String getCitation(boolean isOnlineVersion) {
790
791 String str = "";
792
793 boolean includeAffiliation = false;
794 String authors = this.getAuthorsStr(includeAffiliation);
795 if (!StringUtil.isEmpty(authors)) {
796 str += authors;
797 } else {
798 str += getDatasetProducersString();
799 }
800
801 if (this.getDataset().getPublicationDate() == null || StringUtil.isEmpty(this.getDataset().getPublicationDate().toString())) {
802
803 if (!this.getDataset().isHarvested()) {
804 //if not released use current year
805 if (!StringUtil.isEmpty(str)) {
806 str += ", ";
807 }
808 str += new SimpleDateFormat("yyyy").format(new Timestamp(new Date().getTime()));
809 } else {
810 String distDate = getDistributionDate();
811 if (distDate != null) {
812 if (!StringUtil.isEmpty(str)) {
813 str += ", ";
814 }
815 str += distDate;
816 }
817 }
818 } else {
819 if (!StringUtil.isEmpty(str)) {
820 str += ", ";
821 }
822 str += new SimpleDateFormat("yyyy").format(new Timestamp(this.getDataset().getPublicationDate().getTime()));
823 }
824 if (this.getTitle() != null) {
825 if (!StringUtil.isEmpty(this.getTitle())) {
826 if (!StringUtil.isEmpty(str)) {
827 str += ", ";
828 }
829 str += "\"" + this.getTitle() + "\"";
830 }
831 }
832
833 if (this.getDataset().isHarvested()) {
834 String distributorName = getDistributorName();
835 if (distributorName != null && distributorName.trim().length() > 0) {
836 if (!StringUtil.isEmpty(str)) {
837 str += ". ";
838 }
839 str += " " + distributorName;
840 str += " [distributor]";
841 }
842 }
843
844 // The Global Identifier:
845 // It is always part of the citation for the local datasets;
846 // And for *some* harvested datasets.
847 if (!this.getDataset().isHarvested()
848 || HarvestingDataverseConfig.HARVEST_STYLE_VDC.equals(this.getDataset().getOwner().getHarvestingDataverseConfig().getHarvestStyle())
849 || HarvestingDataverseConfig.HARVEST_STYLE_ICPSR.equals(this.getDataset().getOwner().getHarvestingDataverseConfig().getHarvestStyle())
850 || HarvestingDataverseConfig.HARVEST_STYLE_DATAVERSE.equals(this.getDataset().getOwner().getHarvestingDataverseConfig().getHarvestStyle())) {
851 if (!StringUtil.isEmpty(this.getDataset().getIdentifier())) {
852 if (!StringUtil.isEmpty(str)) {
853 str += ", ";
854 }
855 if (isOnlineVersion) {
856 str += "<a href=\"" + this.getDataset().getPersistentURL() + "\">" + this.getDataset().getPersistentURL() + "</a>";
857 } else {
858 str += this.getDataset().getPersistentURL();
859 }
860 }
861 }
862
863 // Get root dataverse name for Citation
864 // (only for non-harvested datasets):
865 if (!this.getDataset().isHarvested()) {
866 String dataverseName = getRootDataverseNameforCitation();
867 if (!StringUtil.isEmpty(dataverseName)) {
868 if (!StringUtil.isEmpty(str)) {
869 str += ", ";
870 }
871 str += " " + dataverseName;
872 }
873 }
874
875 // Version status:
876 // Again, this is needed for non-harvested stuff only:
877 // (the check may be redundant - we may already be dropping version
878 // numbers when harvesting -- L.A. 4.0 beta15)
879 if (!this.getDataset().isHarvested()) {
880 if (this.isDraft()) {
881 if (!StringUtil.isEmpty(str)) {
882 str += ", ";
883 }
884 str += " DRAFT VERSION ";
885
886 } else if (this.getVersionNumber() != null) {
887 if (!StringUtil.isEmpty(str)) {
888 str += ", ";
889 }
890 str += " V" + this.getVersionNumber();
891
892 }
893 if (this.isDeaccessioned()) {
894 if (!StringUtil.isEmpty(str)) {
895 str += ", ";
896 }
897 str += " DEACCESSIONED VERSION ";
898
899 }
900 }
901
902 if (!StringUtil.isEmpty(getUNF())) {
903 if (!StringUtil.isEmpty(str)) {
904 str += " ";
905 }
906 str += "[" + getUNF() + "]";
907 }
908 /*
909 String distributorNames = getDistributorNames();
910 if (distributorNames.trim().length() > 0) {
911 str += " " + distributorNames;
912 str += " [Distributor]";
913 }*/
914 return str;
915 }
916
917 public String getDistributionDate() {
918 //todo get dist date from datasetfieldvalue table
919 for (DatasetField dsf : this.getDatasetFields()) {
920 if (DatasetFieldConstant.distributionDate.equals(dsf.getDatasetFieldType().getName())) {
921 String date = dsf.getValue();
922 return date;
923 }
924
925 }
926 return null;
927 }
928
929 public String getDistributorName() {
930 for (DatasetField dsf : this.getDatasetFields()) {
931 if (DatasetFieldConstant.distributorName.equals(dsf.getDatasetFieldType().getName())) {
932 return dsf.getValue();
933 }
934 }
935 return null;
936 }
937
938 public String getRootDataverseNameforCitation(){
939 //Get root dataverse name for Citation
940 Dataverse root = this.getDataset().getOwner();
941 while (root.getOwner() != null) {
942 root = root.getOwner();
943 }
944 String rootDataverseName = root.getName();
945 if (!StringUtil.isEmpty(rootDataverseName)) {
946 return rootDataverseName + " Dataverse";
947 } else {
948 return "";
949 }
950 }
951
952 public List<DatasetDistributor> getDatasetDistributors() {
953 //todo get distributors from DatasetfieldValues
954 return new ArrayList();
955 }
956
957 public void setDatasetDistributors(List<DatasetDistributor> distributors) {
958 //todo implement
959 }
960
961 public String getDistributorNames() {
962 String str = "";
963 for (DatasetDistributor sd : this.getDatasetDistributors()) {
964 if (str.trim().length() > 1) {
965 str += ";";
966 }
967 str += sd.getName();
968 }
969 return str;
970 }
971
972 public String getAuthorsStr() {
973 return getAuthorsStr(true);
974 }
975
976 public String getAuthorsStr(boolean affiliation) {
977 String str = "";
978 for (DatasetAuthor sa : getDatasetAuthors()) {
979 if (sa.getName() == null) {
980 break;
981 }
982 if (str.trim().length() > 1) {
983 str += "; ";
984 }
985 str += sa.getName().getValue();
986 if (affiliation) {
987 if (sa.getAffiliation() != null) {
988 if (!StringUtil.isEmpty(sa.getAffiliation().getValue())) {
989 str += " (" + sa.getAffiliation().getValue() + ")";
990 }
991 }
992 }
993 }
994 return str;
995 }
996
997 // TODO: clean up init methods and get them to work, cascading all the way down.
998 // right now, only work for one level of compound objects
999 private DatasetField initDatasetField(DatasetField dsf) {
1000 if (dsf.getDatasetFieldType().isCompound()) {
1001 for (DatasetFieldCompoundValue cv : dsf.getDatasetFieldCompoundValues()) {
1002 // for each compound value; check the datasetfieldTypes associated with its type
1003 for (DatasetFieldType dsfType : dsf.getDatasetFieldType().getChildDatasetFieldTypes()) {
1004 boolean add = true;
1005 for (DatasetField subfield : cv.getChildDatasetFields()) {
1006 if (dsfType.equals(subfield.getDatasetFieldType())) {
1007 add = false;
1008 break;
1009 }
1010 }
1011
1012 if (add) {
1013 cv.getChildDatasetFields().add(DatasetField.createNewEmptyChildDatasetField(dsfType, cv));
1014 }
1015 }
1016 }
1017 }
1018
1019 return dsf;
1020 }
1021
1022 public List<DatasetField> initDatasetFields() {
1023 //retList - Return List of values
1024 List<DatasetField> retList = new ArrayList();
1025 //Running into null on create new dataset
1026 if (this.getDatasetFields() != null) {
1027 for (DatasetField dsf : this.getDatasetFields()) {
1028 retList.add(initDatasetField(dsf));
1029 }
1030 }
1031
1032 //Test to see that there are values for
1033 // all fields in this dataset via metadata blocks
1034 //only add if not added above
1035 for (MetadataBlock mdb : this.getDataset().getOwner().getMetadataBlocks()) {
1036 for (DatasetFieldType dsfType : mdb.getDatasetFieldTypes()) {
1037 if (!dsfType.isSubField()) {
1038 boolean add = true;
1039 //don't add if already added as a val
1040 for (DatasetField dsf : retList) {
1041 if (dsfType.equals(dsf.getDatasetFieldType())) {
1042 add = false;
1043 break;
1044 }
1045 }
1046
1047 if (add) {
1048 retList.add(DatasetField.createNewEmptyDatasetField(dsfType, this));
1049 }
1050 }
1051 }
1052 }
1053
1054 //sort via display order on dataset field
1055 Collections.sort(retList, DatasetField.DisplayOrder);
1056
1057 return retList;
1058 }
1059
1060 /**
1061 * For the current server, create link back to this Dataset
1062 *
1063 * example:
1064 * http://dvn-build.hmdc.harvard.edu/dataset.xhtml?id=72&versionId=25
1065 *
1066 * @param serverName
1067 * @param dset
1068 * @return
1069 */
1070 public String getReturnToDatasetURL(String serverName, Dataset dset) {
1071 if (serverName == null) {
1072 return null;
1073 }
1074 if (dset == null) {
1075 dset = this.getDataset();
1076 if (dset == null) { // currently postgres allows this, see https://github.com/IQSS/dataverse/issues/828
1077 return null;
1078 }
1079 }
1080 return serverName + "/dataset.xhtml?id=" + dset.getId() + "&versionId" + this.getId();
1081 }
1082
1083 ;
1084
1085 public List<DatasetField> copyDatasetFields(List<DatasetField> copyFromList) {
1086 List<DatasetField> retList = new ArrayList();
1087
1088 for (DatasetField sourceDsf : copyFromList) {
1089 //the copy needs to have the current version
1090 retList.add(sourceDsf.copy(this));
1091 }
1092
1093 return retList;
1094 }
1095
1096 public List<DatasetField> getFlatDatasetFields() {
1097 return getFlatDatasetFields(getDatasetFields());
1098 }
1099
1100 private List<DatasetField> getFlatDatasetFields(List<DatasetField> dsfList) {
1101 List<DatasetField> retList = new LinkedList();
1102 for (DatasetField dsf : dsfList) {
1103 retList.add(dsf);
1104 if (dsf.getDatasetFieldType().isCompound()) {
1105 for (DatasetFieldCompoundValue compoundValue : dsf.getDatasetFieldCompoundValues()) {
1106 retList.addAll(getFlatDatasetFields(compoundValue.getChildDatasetFields()));
1107 }
1108
1109 }
1110 }
1111 return retList;
1112 }
1113
1114 public String getSemanticVersion() {
1115 /**
1116 * Not prepending a "v" like "v1.1" or "v2.0" because while SemVerTag
1117 * was in http://semver.org/spec/v1.0.0.html but later removed in
1118 * http://semver.org/spec/v2.0.0.html
1119 *
1120 * See also to v or not to v · Issue #1 · mojombo/semver -
1121 * https://github.com/mojombo/semver/issues/1#issuecomment-2605236
1122 */
1123 if (this.isReleased()) {
1124 return versionNumber + "." + minorVersionNumber;
1125 } else if (this.isDraft()){
1126 return VersionState.DRAFT.toString();
1127 } else if (this.isDeaccessioned()){
1128 return versionNumber + "." + minorVersionNumber;
1129 } else{
1130 return versionNumber + "." + minorVersionNumber;
1131 }
1132 // return VersionState.DEACCESSIONED.name();
1133 // } else {
1134 // return "-unkwn semantic version-";
1135 // }
1136 }
1137
1138 public List<ConstraintViolation> validateRequired() {
1139 List<ConstraintViolation> returnListreturnList = new ArrayList();
1140 ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
1141 Validator validator = factory.getValidator();
1142 for (DatasetField dsf : this.getFlatDatasetFields()) {
1143 dsf.setValidationMessage(null); // clear out any existing validation message
1144 Set<ConstraintViolation<DatasetField>> constraintViolations = validator.validate(dsf);
1145 for (ConstraintViolation<DatasetField> constraintViolation : constraintViolations) {
1146 dsf.setValidationMessage(constraintViolation.getMessage());
1147 returnListreturnList.add(constraintViolation);
1148 break; // currently only support one message, so we can break out of the loop after the first constraint violation
1149 }
1150
1151 }
1152 return returnListreturnList;
1153 }
1154
1155 public Set<ConstraintViolation> validate() {
1156 Set<ConstraintViolation> returnSet = new HashSet();
1157
1158 ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
1159 Validator validator = factory.getValidator();
1160 for (DatasetField dsf : this.getFlatDatasetFields()) {
1161 dsf.setValidationMessage(null); // clear out any existing validation message
1162 Set<ConstraintViolation<DatasetField>> constraintViolations = validator.validate(dsf);
1163 for (ConstraintViolation<DatasetField> constraintViolation : constraintViolations) {
1164 dsf.setValidationMessage(constraintViolation.getMessage());
1165 returnSet.add(constraintViolation);
1166 break; // currently only support one message, so we can break out of the loop after the first constraint violation
1167 }
1168 for (DatasetFieldValue dsfv : dsf.getDatasetFieldValues()) {
1169 dsfv.setValidationMessage(null); // clear out any existing validation message
1170 Set<ConstraintViolation<DatasetFieldValue>> constraintViolations2 = validator.validate(dsfv);
1171 for (ConstraintViolation<DatasetFieldValue> constraintViolation : constraintViolations2) {
1172 dsfv.setValidationMessage(constraintViolation.getMessage());
1173 returnSet.add(constraintViolation);
1174 break; // currently only support one message, so we can break out of the loop after the first constraint violation
1175 }
1176 }
1177 }
1178 return returnSet;
1179 }
1180 }