package uk.ac.ebi.fg.myequivalents.model; import static uk.ac.ebi.fg.myequivalents.resources.Const.COL_LENGTH_S; import java.io.Serializable; import java.util.Date; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Embeddable; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.Transient; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlRootElement; import org.hibernate.validator.constraints.NotBlank; import uk.ac.ebi.fg.myequivalents.utils.EntityIdResolver; /** * * Entities are single units of information that can cross-reference to other entities. Examples of entities are: * a biological sample, a scientific paper, the web page about a person. Entities are identified by an accession and * a service in the context of which the accession is unique. Another way to identify entities is by means of URIs, * which are assumed to be composed by binding a place-holder in a URI pattern. The URI pattern is provided with by the * service. * * <p/>An entity is effectively a resource in the RDF realm. We avoid the term resource in order to avoid confusion with * the same term used differently in the context of <a href = 'http://www.ebi.ac.uk/miriam/main/'>MIRAM</a> * (entities are equivalent to MIRIAM's physical locations, while they use the word 'resource' to mean what we call * services). * * <dl><dt>date</dt><dd>May 25, 2012</dd></dl> * @author Marco Brandizi * */ @Embeddable @XmlRootElement ( name = "entity" ) @XmlAccessorType ( XmlAccessType.NONE ) public class Entity implements Serializable, MyEquivalentsModelMember { private static final long serialVersionUID = -3887901613707959679L; @ManyToOne( optional = false, cascade = { CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH } ) @JoinColumn ( name = "service_name" ) private Service service; @NotBlank @Column( length = COL_LENGTH_S ) private String accession; /** * This must be transient, cause a specific implementation has to be given in {@link EntityMapping}. */ @Transient private Boolean publicFlag = true; /** * This must be transient, cause a specific implementation has to be given in {@link EntityMapping}. */ @Transient private Date releaseDate = null; protected Entity () { } public Entity ( Service service, String accession ) { this.service = service; this.accession = accession; } public Service getService () { return service; } void setService ( Service service ) { this.service = service; } @XmlAttribute public String getAccession () { return accession; } void setAccession ( String accession ) { this.accession = accession; } @Transient @XmlAttribute ( name = "service-name", required = true ) public String getServiceName () { // We need the accessor in order to prevent this to be called before injection. return this.getService () == null ? null : this.service.getName (); } /** * This is only used with JAXB and implemented in specific sub-classes. */ protected void setServiceName ( String serviceName ) { throw new UnsupportedOperationException ( "Internal error: you cannot call Entity.setServiceName(), this is here just to make JAXB annotations working. " + "You need to override this setter, if you have a reasonable semantics for it" ); } /** * Builds the URI by means of {@link #getAccession()} and * {@link #getService()}.{@link Service#getUriPattern() getUriPattern()}. */ @Transient @XmlAttribute ( name = "uri" ) public String getURI() { return EntityIdResolver.buildUriFromAcc ( this.getAccession (), this.getService ().getUriPattern () ); } /** * This is only used with JAXB and implemented in specific sub-classes. */ protected void setURI ( String uri ) { throw new UnsupportedOperationException ( "Internal error: you cannot call Entity.setURI(), this is here just to make JAXB annotations working. " + "You need to override this setter, if you have a reasonable semantics for it" ); } public void setPublicFlag ( Boolean publicFlag ) { this.publicFlag = publicFlag; } @XmlAttribute ( name = "public-flag" ) public Boolean getPublicFlag () { return this.publicFlag; } @XmlAttribute ( name = "release-date" ) public Date getReleaseDate () { return releaseDate; } public void setReleaseDate ( Date releaseDate ) { this.releaseDate = releaseDate; } /** * isPublic evaluates to {@link #getPublicFlag()} if that's not null, or {@link #getReleaseDate()} not in future. */ @Transient public boolean isPublic () { Date now = new Date (); return this.getPublicFlag () == null ? this.getReleaseDate ().before ( now ) || this.releaseDate.equals ( now ) : this.publicFlag; } @Override public boolean equals ( Object obj ) { if ( this == obj ) return true; if ( !( obj instanceof Entity ) ) return false; Entity other = (Entity) obj; return this.getServiceName ().equals ( other.getServiceName () ) && this.getAccession ().equals ( other.getAccession () ); } @Override public int hashCode () { return 31 * this.getServiceName ().hashCode () + this.getAccession ().hashCode (); } @Override public String toString () { return String.format ( "%s { service.name: '%s', accession: '%s', public-flag: %s, release-date: %s, uri: '%s' }", this.getClass ().getSimpleName (), this.getServiceName (), this.getAccession (), this.getPublicFlag (), this.getReleaseDate (), this.getURI () ); } }