Dataset.java
/*
* Copyright 2019 Global Crop Diversity Trust
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.genesys.server.model.dataset;
import java.time.Instant;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import javax.persistence.Cacheable;
import javax.persistence.CascadeType;
import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.Index;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.Lob;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OrderColumn;
import javax.persistence.PostLoad;
import javax.persistence.PrePersist;
import javax.persistence.PreUpdate;
import javax.persistence.Table;
import javax.persistence.Transient;
import javax.persistence.UniqueConstraint;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import lombok.Getter;
import lombok.Setter;
import org.genesys.blocks.annotations.NotCopyable;
import org.genesys.blocks.auditlog.annotations.Audited;
import org.genesys.blocks.model.JsonViews;
import org.genesys.blocks.model.Publishable;
import org.genesys.blocks.model.SelfCleaning;
import org.genesys.blocks.security.model.AclAwareModel;
import org.genesys.filerepository.model.RepositoryFile;
import org.genesys.server.model.Partner;
import org.genesys.server.model.PublishState;
import org.genesys.server.model.impl.Crop;
import org.genesys.server.model.impl.TranslatedUuidModel;
import org.genesys.server.model.traits.Descriptor;
import org.genesys.util.MCPDUtil;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
import com.fasterxml.jackson.annotation.JsonGetter;
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonView;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
/**
* {@link Dataset} captures the metadata information as a snapshot. Multiple
* versions of the versions may exist.
*
* @author Matija Obreza
* @author Andrey Lugovskoy
* @author Maxym Borodenko
*/
@Entity
@Table(name = "dataset", uniqueConstraints = @UniqueConstraint(name = "UQ_current_dataset_version", columnNames={"versionsId", "current"}))
@Cacheable
@Audited
@Document(indexName = "dataset")
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "uuid", scope = Dataset.class)
@Getter
@Setter
public class Dataset extends TranslatedUuidModel<DatasetLang, Dataset> implements Publishable, SelfCleaning, AclAwareModel {
/** The Constant serialVersionUID. */
private static final long serialVersionUID = -4601980446454791177L;
/** The versions. */
@ManyToOne(cascade = { CascadeType.MERGE, CascadeType.REFRESH }, optional = false)
@JoinColumn(name = "versionsId", updatable = false)
@JsonIgnore
private DatasetVersions versions;
private Boolean current;
/** The owner. */
@ManyToOne(cascade = {}, optional = false)
@JoinColumn(name = "partnerId", updatable = false)
@NotNull
@Field(type = FieldType.Object)
private Partner owner;
/** The accession identifiers. */
@OneToMany(mappedBy = "list", cascade = { CascadeType.REMOVE }, fetch = FetchType.LAZY)
@Field(type = FieldType.Object)
@JsonIgnore
private List<DatasetAccessionRef> accessionRefs;
/** The descriptors. */
@ManyToMany(fetch = FetchType.LAZY, cascade = {})
@JoinTable(name = "dataset_descriptor", joinColumns = @JoinColumn(name = "datasetId", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "descriptorId", referencedColumnName = "id"))
@OrderColumn(name = "position")
@Field(type = FieldType.Object)
@JsonView({ JsonViews.Public.class })
private List<Descriptor> descriptors;
/** The repository files. */
@OneToMany(fetch = FetchType.LAZY, cascade = { })
@JoinTable(name = "dataset_repositoryfile", joinColumns = @JoinColumn(name = "datasetId", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "repositoryfileId", referencedColumnName = "id"))
@OrderColumn(name = "position")
@Field(type = FieldType.Object)
@JsonView({ JsonViews.Public.class })
private List<RepositoryFile> repositoryFiles;
/** The creators. */
@OneToMany(cascade = { CascadeType.ALL }, mappedBy = "dataset", orphanRemoval = true, fetch = FetchType.LAZY)
@Field(type = FieldType.Object)
@JsonView({ JsonViews.Public.class })
private List<DatasetCreator> creators;
/** The locations. */
@OneToMany(cascade = { CascadeType.ALL }, mappedBy = "dataset", orphanRemoval = true, fetch = FetchType.LAZY)
@Field(type = FieldType.Object)
@JsonView({ JsonViews.Public.class })
private List<DatasetLocation> locations;
/** The min start date of all locations */
@Size(max = 8)
@Column(length = 8)
private String startDate;
/** The max end date of all locations */
@Size(max = 8)
@Column(length = 8)
private String endDate;
/** The accession count. */
// Number of accessions in the {@link #accessionRefs} list
@Column(name = "accessions")
private int accessionCount = 0;
/** The descriptor count. */
// Number of descriptors in the {@link #descriptors} list
@Column(name = "descriptors")
private Integer descriptorCount;
/** The crops. */
@ElementCollection(fetch = FetchType.EAGER)
@CollectionTable(name = "dataset_crops", joinColumns = @JoinColumn(name = "datasetId"),
// index
indexes = { @Index(columnList = "datasetId, crop") })
@Column(name = "crop", nullable = false, length = Crop.CROP_SHORTNAME_LENGTH)
@JsonView({ JsonViews.Minimal.class })
private Set<String> crops;
/**
* User-specified versions version tag. E.g. "1.0", "1.1"
*/
private String versionTag;
/**
* DatasetVersions title in English.
*/
@Column(length = 255)
@Field(type = FieldType.Text)
private String title;
/**
* DatasetVersions description in English.
*/
@Lob
private String description;
/**
* DatasetVersions format in English.
*/
private String format;
/** The subject of the dataset. */
private String subject;
/** The rights. */
private String rights;
/** The source. */
private String source;
/** Information about time of creation of the dataset. */
@Size(max = 200)
@Column(nullable = true, length = 200)
private String created;
@Column(name = "firstPublishedDate")
@NotCopyable
private Instant firstPublishedDate;
/** The publish state. */
@Enumerated(EnumType.ORDINAL)
private PublishState state = PublishState.DRAFT;
@Transient
private UUID currentVersion;
@PostLoad
protected void postLoad() {
if (this.versions != null && versions.getCurrentVersion() != null && !this.uuid.equals(versions.getCurrentVersion().getUuid())) {
this.currentVersion = versions.getCurrentVersion().getUuid();
}
}
/**
* Preupdate.
*/
@PreUpdate
@PrePersist
private void preupdate() {
// if (accessionRefs != null) {
// this.accessionCount = accessionRefs.size();
// }
if (descriptors != null) {
this.descriptorCount = descriptors.size();
}
if (locations != null) {
this.startDate = locations.stream().map(DatasetLocation::getStartDate).filter(d -> d != null).min(String::compareTo).orElse(null);
this.endDate = locations.stream().map(DatasetLocation::getEndDate).filter(d -> d != null).max(String::compareTo).orElse(null);
}
if (Objects.isNull(firstPublishedDate) && Objects.equals(state, PublishState.PUBLISHED)) {
firstPublishedDate = Instant.now();
}
trimStringsToNull();
}
/**
* Gets the UUID of current dataset
*
* @return the UUID of current dataset
*/
@JsonGetter
public UUID getCurrentVersion() {
return currentVersion;
}
/**
* Datasets have no parent ACL object.
*/
@Override
public AclAwareModel aclParentObject() {
return null;
}
/**
* Sets the start date if startDate is valid McpdDate.
*
* @param startDate the new start date
*/
public void setStartDate(String startDate) {
if (MCPDUtil.isMcpdDate(startDate)) {
this.startDate = startDate;
}
}
/**
* Sets the end date if endDate is valid McpdDate.
*
* @param endDate the new start date
*/
public void setEndDate(String endDate) {
if (MCPDUtil.isMcpdDate(endDate)) {
this.endDate = endDate;
}
}
/*
* (non-Javadoc)
* @see org.genesys.blocks.model.Publishable#isPublished()
*/
@Override
public boolean isPublished() {
return this.state == PublishState.PUBLISHED;
}
@Override
public boolean canEqual(Object other) {
return other instanceof Dataset;
}
@Override
public void prepareForIndexing() {
super.prepareForIndexing();
if (this.owner.getInstitutes() != null) {
this.owner.getInstitutes().size();
}
}
}