package models; import java.sql.Timestamp; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.UUID; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.OneToMany; import javax.persistence.Table; import javax.persistence.Transient; import play.Logger; import play.data.validation.Constraints.Required; import play.db.ebean.Model; import scala.NotImplementedError; import uk.bl.Const; import uk.bl.api.Utils; import com.avaje.ebean.ExpressionList; import com.avaje.ebean.Page; import com.fasterxml.jackson.annotation.JsonIgnore; /** * This calls supports crawl permissions workflow and * handles crawl permission requests sent by e-mail to the owner. */ @Entity @Table(name = "crawl_permission") public class CrawlPermission extends ActModel { /** * file id */ private static final long serialVersionUID = -2250099575463302989L; @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "crawl_permission_seq") public Long id; // the permission can be inherited from a 'parent' target. // Targets could in theory have multiple crawl permissions. This is most likely in the case where a // permission was sent and then cancelled for whatever reason, and then another one sent to supersede it. @JsonIgnore @ManyToOne(cascade = CascadeType.REFRESH) @JoinColumn(name="target_id") @Required(message="Target is required") public Target target; @JsonIgnore @OneToMany(mappedBy = "crawlPermission", cascade = CascadeType.ALL, fetch=FetchType.EAGER) public List<CommunicationLog> communicationLogs; //bi-directional many-to-one association to MailTemplate @ManyToOne(cascade = CascadeType.REFRESH, fetch=FetchType.EAGER) @JoinColumn(name="mailtemplate_permission_request_id") public MailTemplate permissionRequestMailTemplate; //bi-directional many-to-one association to MailTemplate @ManyToOne(cascade = CascadeType.REFRESH, fetch=FetchType.EAGER) @JoinColumn(name="mailtemplate_acknowledgement_id") public MailTemplate acknowledgementMailTemplate; //bi-directional many-to-one association to ContactPerson @ManyToOne(cascade = CascadeType.REFRESH, fetch=FetchType.EAGER) @JoinColumn(name="contactPerson_id") @Required(message="Contact Person is required") public ContactPerson contactPerson; @Column(columnDefinition = "text") @Required(message="Name is required") public String name; @Column(columnDefinition = "text") public String description; @Column(columnDefinition = "text") public String anyOtherInformation; @JsonIgnore @ManyToOne(cascade = CascadeType.REFRESH, fetch=FetchType.EAGER) @JoinColumn(name="archivist_id") public User user; /** * Records status of permission process e.g. * Not Initiated, Queued, Pending, Refused, Granted * Usually populated by system actions, but may also be modified by Archivist */ @Column(columnDefinition = "text") public String status; @ManyToOne @JoinColumn(name="license_id") private License license; // Do not include the token as this is the 'secret' used to grant licenses @JsonIgnore public String token; /** * This is a checkbox defining whether follow up e-mails should be send. */ public Boolean requestFollowup; /** * This is a checkbox defining whether any content on this web site subject * to copyright and/or the database right held by another party. */ public Boolean thirdPartyContent; /** * This is a checkbox defining whether owner allows the archived web site * to be used in any future publicity for the Web Archive. */ public Boolean publish; /** * This is a checkbox defining whether owner agrees to archive web site. */ public Boolean agree; /** * This is a string which captures the date on which the licence is requested. */ @Column(name="requested_at") public Timestamp requestedAt; /** * This is a readonly field which captures the date on which the licence is agreed. */ @Column(name="granted_at") public Timestamp grantedAt; @Transient public String requestedAtISO; @Transient public String grantedAtISO; public String getRequestedAtISO() { if (requestedAt != null) { requestedAtISO = Utils.INSTANCE.convertToDateTimeISO(requestedAt); } return requestedAtISO; } public String getGrantedAtISO() { if (grantedAt != null) { grantedAtISO = Utils.INSTANCE.convertToDateTimeISO(grantedAt); } return grantedAtISO; } public static final Model.Finder<Long, CrawlPermission> find = new Model.Finder<Long, CrawlPermission>(Long.class, CrawlPermission.class); public CrawlPermission() { this(null, null, null); } public CrawlPermission(Long id, String url) { this(id, url, null); } public CrawlPermission(Long id, String url, String name) { this.id = id; this.url = url; this.name = name; this.token = UUID.randomUUID().toString(); } public License getLicense() { return this.license; } public void setLicense( License l ) { this.license = l; } public MailTemplate getPermissionRequestMailTemplate() { return permissionRequestMailTemplate; } public void setPermissionRequestMailTemplate(MailTemplate permissionRequestMailTemplate) { this.permissionRequestMailTemplate = permissionRequestMailTemplate; } public MailTemplate getAcknowledgementMailTemplate() { return acknowledgementMailTemplate; } public void setAcknowledgementMailTemplate(MailTemplate acknowledgementMailTemplate) { this.acknowledgementMailTemplate = acknowledgementMailTemplate; } /** * This method evaluates if element is in a list separated by list delimiter e.g. ', '. * @param subject * @return true if in list */ @Transient @JsonIgnore public boolean hasContactPerson(String curContactPerson) { // boolean res = false; // res = Utils.hasElementInList(curContactPerson, contactPerson); // return res; throw new NotImplementedError(); } @Transient @JsonIgnore public boolean isCompleted() { if( Const.CrawlPermissionStatus.GRANTED.toString().equals(this.status) || Const.CrawlPermissionStatus.SUPERSEDED.toString().equals(this.status) || Const.CrawlPermissionStatus.REFUSED.toString().equals(this.status) || Const.CrawlPermissionStatus.EMAIL_REJECTED.toString().equals(this.status) ) { return true; } return false; } @Override public int hashCode() { final int prime = 31; int result = super.hashCode(); result = prime * result + ((name == null) ? 0 : name.hashCode()); result = prime * result + ((id == null) ? 0 : id.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (!super.equals(obj)) return false; if (getClass() != obj.getClass()) return false; CrawlPermission other = (CrawlPermission) obj; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; if (id == null) { if (other.id != null) return false; } else if (!id.equals(other.id)) return false; return true; } public static CrawlPermission findByName(String name) { return find.where() .eq("name", name) .findUnique(); } /** * Retrieve an object by Id (id). * @param nid * @return object */ public static CrawlPermission findById(Long id) { CrawlPermission res = find .fetch("permissionRequestMailTemplate") /* Don't know why this is necessary, but these entities are not fetched otherwise */ .fetch("acknowledgementMailTemplate") .where().eq(Const.ID, id).findUnique(); return res; } /** * The number of requests that were sent. */ public Long numberRequests; public static CrawlPermission findByToken(String token) { CrawlPermission res = find .fetch("license") .fetch("contactPerson") .fetch("permissionRequestMailTemplate") /* Don't know why this is necessary, but these entities are not fetched otherwise */ .fetch("acknowledgementMailTemplate") .where().eq("token", token).findUnique(); return res; } /** * Retrieve a crawl permission by URL. * @param url * @return crawl permission name */ public static CrawlPermission findByUrl(String url) { // Logger.debug("permission findByUrl: " + url); CrawlPermission res = new CrawlPermission(); if (url != null && url.length() > 0 && !url.equals(Const.NONE)) { res = find.where().eq(Const.URL, url).findUnique(); } else { res.name = Const.NONE; } return res; } /** * @param target The field URL * @return */ public static CrawlPermission findByTarget(String target) { CrawlPermission res = new CrawlPermission(); if (target != null && target.length() > 0 && !target.equals(Const.NONE)) { res = find.where().eq(Const.TARGET, target).findUnique(); } else { res.name = Const.NONE; } return res; } /** * This method is used to show crawl permission in a table. * It shows none value if no entry was found in database. * @param url * @return */ public static CrawlPermission showByUrl(String url) { // Logger.debug("permission findByUrl: " + url); CrawlPermission res = new CrawlPermission(); if (url != null && url.length() > 0 && !url.equals(Const.NONE)) { try { res = find.where().eq(Const.URL, url).findUnique(); if (res == null) { res = new CrawlPermission(); res.name = Const.NONE; } } catch (Exception e) { Logger.debug("crawl permission could not be find in database: " + e); } } else { res.name = Const.NONE; } // Logger.debug("permission res: " + res); return res; } public static CrawlPermission showByToken(String token) { CrawlPermission crawlPermission = CrawlPermission.findByToken(token); return crawlPermission; } /** * This method filters crawl permissions by name and returns a list * of filtered CrawlPermission objects. * @param name * @return */ public static List<CrawlPermission> filterByName(String name) { List<CrawlPermission> res = new ArrayList<CrawlPermission>(); ExpressionList<CrawlPermission> ll = find.where().icontains(Const.NAME, name); res = ll.findList(); return res; } /** * This method filters crawl permissions by contact person and returns a list * of filtered CrawlPermission objects. * @param url The identifier for contact person * @return */ public static List<CrawlPermission> filterByContactPerson(String url) { List<CrawlPermission> res = new ArrayList<CrawlPermission>(); ExpressionList<CrawlPermission> ll = find.where().icontains(Const.CONTACT_PERSON, url); res = ll.findList(); return res; } /** * Find out crawl permission by target that was submitted by owner. * @param cur_target * @return permission list */ public static List<CrawlPermission> filterByTarget(String cur_target) { List<CrawlPermission> res = new ArrayList<CrawlPermission>(); ExpressionList<CrawlPermission> ll = find.where().icontains(Const.TARGET, cur_target); res = ll.findList(); return res; } /** * This method filters crawl permissions by status and returns a list * of filtered CrawlPermission objects. * @param status * @return */ public static List<CrawlPermission> filterByStatus(String status) { List<CrawlPermission> res = new ArrayList<CrawlPermission>(); ExpressionList<CrawlPermission> ll = find.where().icontains(Const.STATUS, status); res = ll.findList(); return res; } /** * Retrieve all crawl permissions. */ public static List<CrawlPermission> findAll() { return find.all(); } /** * This method enables replacing of placeholders in mail text by given value. * @param text The text of an email. * @param placeHolder The placeholder string e.g. ||URL|| * @param value The value that overwrites placeholder * @return updated text */ public static String replaceStringInText(String text, String placeHolder, String value) { String res = text; res = text.replace(placeHolder, value); return res; } /** * This method enables replacing of two place holders in mail text by given values. * @param text The text of an email. * @param placeHolderUrl The placeholder string for crawl URL ||URL|| * @param placeHolderLink The placeholder string for unique license URL ||LINK|| * @param valueUrl The value that overwrites associated placeholder * @param valueLink The value that overwrites associated placeholder * @return updated text */ public static String replaceTwoStringsInText(String text, String placeHolderUrl, String placeHolderLink, String valueUrl, String valueLink) { String res = text; // Logger.debug("replaceTwoStringsInText valueUrl: " + valueUrl); List<String> placeHolders = new ArrayList<String>(); placeHolders.add(placeHolderUrl); placeHolders.add(placeHolderLink); List<String> values = new ArrayList<String>(); values.add(valueUrl); values.add(valueLink); res = replacePlaceholdersInText(text, placeHolders, values); return res; } /** * This method enables replacing of place holders in mail text by given values. * @param text The text of an email. * @param placeHolders The placeholder list in string format e.g. ||URL||, ||LINK|| * @param values The value that overwrites place holders * @return updated text */ public static String replacePlaceholdersInText(String text, List<String> placeHolders, List<String> values) { String res = text; if (placeHolders != null && placeHolders.size() > 0 && values != null && values.size() > 0 && placeHolders.size() == values.size()) { int counter = placeHolders.size(); for (int i = 0; i < counter; i++) { Logger.debug("replacePlaceholdersInText placeholder: " + placeHolders.get(i) + ", value: " + values.get(i)); res = res.replace(placeHolders.get(i), values.get(i)); } } return res; } /** * Return a page of crawl permission * * @param page Page to display * @param pageSize Number of Users per page * @param sortBy Crawl permission property used for sorting * @param order Sort order (either or asc or desc) * @param filter Filter applied on the name column * @param status The status of crawl permission request (e.g. QUEUED, PENDING...) * @param target The field URL */ public static Page<CrawlPermission> page(int page, int pageSize, String sortBy, String order, String filter, String status) { // Set up query: ExpressionList<CrawlPermission> q = find.where().icontains("name", filter); // Add optional status filter: if( ! "-1".equals(status)) { q = q .eq("status", status); } // Strip out NULLs when sorting by these dates: if( "grantedAt".equals(sortBy) ||"requestedAt".equals(sortBy) ) { q = q.isNotNull(sortBy); } // Query and return paged list: return q.orderBy(sortBy + " " + order) .findPagingList(pageSize) .setFetchAhead(false) .getPage(page); } public static Page<CrawlPermission> targetPager(int page, int pageSize, String sortBy, String order, Long targetId) { return find.where() .eq("target.id", targetId) .orderBy(sortBy + " " + order) .findPagingList(pageSize) .setFetchAhead(false) .getPage(page); } public static CrawlPermission create(Long id, String url) { return new CrawlPermission(id, url); } public static CrawlPermission create(Long id, String url, String name) { return new CrawlPermission(id, url, name); } public static Map<String,String> options() { LinkedHashMap<String,String> options = new LinkedHashMap<String,String>(); for(CrawlPermission c: find.all()) { options.put(c.id.toString(), c.name); } return options; } @Override public String toString() { return "CrawlPermission [target=" + ((target!=null) ? target.id : "NULL") + ", permissionRequestMailTemplate=" + permissionRequestMailTemplate + ", acknowledgementMailTemplate=" + acknowledgementMailTemplate + ", contactPerson=" + contactPerson + ", name=" + name + ", description=" + description + ", anyOtherInformation=" + anyOtherInformation + ", user=" + user + ", status=" + status + ", license=" + license + ", requestFollowup=" + requestFollowup + ", numberRequests=" + numberRequests + ", thirdPartyContent=" + thirdPartyContent + ", publish=" + publish + ", agree=" + agree + ", requestedAt=" + requestedAt + ", grantedAt=" + grantedAt + ", token=" + token + "]"; } }