/*
* This is eMonocot, a global online biodiversity information resource.
*
* Copyright © 2011–2015 The Board of Trustees of the Royal Botanic Gardens, Kew and The University of Oxford
*
* eMonocot is free software: you can redistribute it and/or modify it under the terms of the
* GNU Affero General Public License as published by the Free Software Foundation, either version 3
* of the License, or (at your option) any later version.
*
* eMonocot is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* The complete text of the GNU Affero General Public License is in the source repository as the file
* ‘COPYING’. It is also available from <http://www.gnu.org/licenses/>.
*/
package org.emonocot.model.registry;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.ManyToOne;
import javax.persistence.Transient;
import javax.validation.constraints.NotNull;
import org.apache.solr.common.SolrInputDocument;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.emonocot.model.Base;
import org.emonocot.model.Searchable;
import org.emonocot.model.constants.ResourceType;
import org.emonocot.model.constants.SchedulingPeriod;
import org.emonocot.model.marshall.json.OrganisationDeserialiser;
import org.emonocot.model.marshall.json.OrganisationSerializer;
import org.hibernate.annotations.NaturalId;
import org.hibernate.annotations.Type;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.NotEmpty;
import org.hibernate.validator.constraints.URL;
import org.joda.time.DateTime;
import org.joda.time.Duration;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.springframework.batch.core.BatchStatus;
/**
*
* @author ben
*
*/
@Entity
public class Resource extends Base implements Searchable {
private static final long serialVersionUID = 5676965857186600965L;
private Long id;
private ResourceType resourceType;
private String uri;
private DateTime lastHarvested;
private DateTime lastAttempt;
private String resource;
private Long jobId;
private BatchStatus status;
private DateTime startTime;
private String exitCode;
private Duration duration;
private String exitDescription;
private String jobInstance;
private Organisation organisation;
private String title;
private Boolean scheduled = Boolean.FALSE;
private SchedulingPeriod schedulingPeriod;
private DateTime nextAvailableDate;
private Integer recordsRead = 0;
private Integer readSkip = 0;
private Integer processSkip = 0;
private Integer writeSkip = 0;
private Integer written = 0;
private Map<String,String> parameters = new HashMap<String,String>();
private String baseUrl;
private Long lastHarvestedJobId;
public Resource() {
this.identifier = UUID.randomUUID().toString();
}
@NotEmpty
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
/**
* @return the readSkip
*/
public Integer getReadSkip() {
return readSkip;
}
/**
* @param readSkip
* the readSkip to set
*/
public void setReadSkip(Integer readSkip) {
this.readSkip = readSkip;
}
/**
* @return the writeSkip
*/
public Integer getWriteSkip() {
return writeSkip;
}
/**
* @param writeSkip
* the writeSkip to set
*/
public void setWriteSkip(Integer writeSkip) {
this.writeSkip = writeSkip;
}
/**
*
* @return The unique identifier of the object
*/
@NaturalId
@NotEmpty
public String getIdentifier() {
return identifier;
}
/**
*
* @param identifier
* Set the unique identifier of the object
*/
public void setIdentifier(String identifier) {
this.identifier = identifier;
}
/**
* @return the Id
*/
@Id
@GeneratedValue(generator = "table-hilo", strategy = GenerationType.TABLE)
public Long getId() {
return id;
}
/**
* @return the jobType
*/
@NotNull
@Enumerated(value = EnumType.STRING)
public ResourceType getResourceType() {
return resourceType;
}
/**
* @param newJobType
* Set the job type
*/
public void setResourceType(ResourceType newJobType) {
this.resourceType = newJobType;
}
/**
* @return the uri
*/
@NotEmpty(groups = ReadResource.class)
@URL
public String getUri() {
return uri;
}
/**
* @param newUri
* Set the uri
*/
public void setUri(String newUri) {
this.uri = newUri;
}
/**
* @return the last date the resource was last harvested
*/
@Type(type = "dateTimeUserType")
public DateTime getLastHarvested() {
return lastHarvested;
}
/**
* @param newLastHarvested
* Set the date the resource was last harvested
*/
public void setLastHarvested(DateTime newLastHarvested) {
this.lastHarvested = newLastHarvested;
}
/**
* @return the resource
*/
@URL
public String getResource() {
return resource;
}
/**
* @param newResource
* Set the resource
*/
public void setResource(String newResource) {
this.resource = newResource;
}
/**
* @return the jobId
*/
public Long getJobId() {
return jobId;
}
/**
* @param newJobId
* the jobId to set
*/
public void setJobId(Long newJobId) {
this.jobId = newJobId;
}
/**
* @return the status
*/
@Enumerated(value = EnumType.STRING)
public BatchStatus getStatus() {
return status;
}
/**
* @param newStatus
* the status to set
*/
public void setStatus(BatchStatus newStatus) {
this.status = newStatus;
}
/**
* @return the startTime
*/
@Type(type = "dateTimeUserType")
public DateTime getStartTime() {
return startTime;
}
/**
* @param newStartTime
* Set the start time
*/
public void setStartTime(DateTime newStartTime) {
this.startTime = newStartTime;
}
/**
* @return the exit code
*/
public String getExitCode() {
return exitCode;
}
/**
* @param newExitCode
* Set the exit status
*/
public void setExitCode(String newExitCode) {
this.exitCode = newExitCode;
}
/**
* @return the duration
*/
@Type(type = "durationUserType")
public Duration getDuration() {
return duration;
}
/**
* @param newDuration
* Set the duration
*/
public void setDuration(Duration newDuration) {
this.duration = newDuration;
}
/**
* @return the exitDescription
*/
@Lob
@Length(max = 1431655761)
public String getExitDescription() {
return exitDescription;
}
/**
* @param newExitDescription
* Set the exit description
*/
public void setExitDescription(String newExitDescription) {
this.exitDescription = newExitDescription;
}
/**
* @return the jobInstance
*/
public String getJobInstance() {
return jobInstance;
}
/**
* @param newJobInstance
* Set the job instance
*/
public void setJobInstance(String newJobInstance) {
this.jobInstance = newJobInstance;
}
/**
* @return the source
*/
@JsonSerialize(using = OrganisationSerializer.class)
@ManyToOne(fetch = FetchType.LAZY)
public Organisation getOrganisation() {
return organisation;
}
/**
* @param organisation
* the source to set
*/
@JsonDeserialize(using = OrganisationDeserialiser.class)
public void setOrganisation(Organisation organisation) {
this.organisation = organisation;
}
/**
* @param id
* the id to set
*/
public void setId(Long id) {
this.id = id;
}
/**
* @return the read
*/
public Integer getRecordsRead() {
return recordsRead;
}
/**
* @param read
* the read to set
*/
public void setRecordsRead(Integer read) {
this.recordsRead = read;
}
/**
* @return the processed
*/
public Integer getProcessSkip() {
return processSkip;
}
/**
* @param processed
* the processed to set
*/
public void setProcessSkip(Integer processed) {
this.processSkip = processed;
}
/**
* @return the written
*/
public Integer getWritten() {
return written;
}
/**
* @param written
* the written to set
*/
public void setWritten(Integer written) {
this.written = written;
}
/**
* @return the parameters
*/
@ElementCollection
public Map<String, String> getParameters() {
return parameters;
}
/**
* @param parameters the parameters to set
*/
public void setParameters(Map<String, String> parameters) {
this.parameters = parameters;
}
/**
* @return the scheduled
*/
public Boolean getScheduled() {
return scheduled;
}
/**
* @param scheduled the scheduled to set
*/
public void setScheduled(Boolean scheduled) {
this.scheduled = scheduled;
}
@Type(type = "dateTimeUserType")
public DateTime getNextAvailableDate() {
return nextAvailableDate;
}
public void setNextAvailableDate(DateTime nextAvailableDate) {
this.nextAvailableDate = nextAvailableDate;
}
public void setBaseUrl(String baseUrl) {
this.baseUrl = baseUrl;
}
public String getBaseUrl() {
return baseUrl;
}
@Enumerated(value = EnumType.STRING)
public SchedulingPeriod getSchedulingPeriod() {
return schedulingPeriod;
}
public void setSchedulingPeriod(SchedulingPeriod schedulingPeriod) {
this.schedulingPeriod = schedulingPeriod;
}
public void updateNextAvailableDate() {
if(getScheduled()) {
DateTime nextAvailableDate = new DateTime();
switch (getSchedulingPeriod()) {
case YEARLY:
nextAvailableDate = nextAvailableDate.plusYears(1);
break;
case MONTHLY:
nextAvailableDate = nextAvailableDate.plusMonths(1);
break;
case WEEKLY:
nextAvailableDate = nextAvailableDate.plusWeeks(1);
break;
case DAILY:
nextAvailableDate = nextAvailableDate.plusDays(1);
break;
default:
nextAvailableDate = null;
}
setNextAvailableDate(nextAvailableDate);
}
}
@Override
@Transient
@JsonIgnore
public String getDocumentId() {
return getClassName() + "_" + getId();
}
@Transient
@JsonIgnore
public String getClassName() {
return "Resource";
}
@Override
public SolrInputDocument toSolrInputDocument() {
DateTimeFormatter solrDateTimeFormat = DateTimeFormat.forPattern("yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'");
SolrInputDocument sid = new SolrInputDocument();
sid.addField("id", getClassName() + "_" + getId());
sid.addField("base.id_l", getId());
sid.addField("base.class_searchable_b", false);
sid.addField("base.class_s", getClass().getName());
if(getDuration() != null) {
sid.addField("resource.duration_l",getDuration().getStandardSeconds());
}
sid.addField("resource.exit_code_s",getExitCode());
sid.addField("resource.exit_description_t",getExitDescription());
if(getLastHarvested() != null) {
sid.addField("resource.last_harvested_dt",solrDateTimeFormat.print(getLastHarvested()));
}
if(getNextAvailableDate() != null) {
sid.addField("resource.next_available_date_dt",solrDateTimeFormat.print(getNextAvailableDate()));
}
sid.addField("resource.process_skip_l",getProcessSkip());
sid.addField("resource.records_read_l",getRecordsRead());
sid.addField("resource.resource_type_s", getResourceType());
sid.addField("resource.scheduled_b", getScheduled());
sid.addField("resource.scheduling_period_s", getSchedulingPeriod());
if(getOrganisation() != null) {
sid.addField("resource.organisation_s",getOrganisation().getIdentifier());
}
if(getStartTime() != null) {
sid.addField("resource.start_time_dt",solrDateTimeFormat.print(getStartTime()));
}
sid.addField("resource.status_s", getStatus());
sid.addField("resource.title_t", getTitle());
sid.addField("resource.write_skip_l",getWriteSkip());
sid.addField("resource.written_l",getWritten());
sid.addField("searchable.label_sort", getTitle());
StringBuilder summary = new StringBuilder().append(getExitDescription()).append(" ").append(getTitle());
sid.addField("searchable.solrsummary_t", summary);
return sid;
}
public void setLastHarvestedJobId(Long lastHarvestedJobId) {
this.lastHarvestedJobId = lastHarvestedJobId;
}
public Long getLastHarvestedJobId() {
return lastHarvestedJobId;
}
public interface ReadResource {
}
@Type(type = "dateTimeUserType")
public DateTime getLastAttempt() {
return lastAttempt;
}
public void setLastAttempt(DateTime lastAttempt) {
this.lastAttempt = lastAttempt;
}
}