package org.gmod.schema.feature;
import org.gmod.schema.cfg.FeatureType;
import org.gmod.schema.mapped.CvTerm;
import org.gmod.schema.mapped.Feature;
import org.gmod.schema.mapped.FeatureLoc;
import org.gmod.schema.mapped.FeatureRelationship;
import org.gmod.schema.mapped.Organism;
import org.apache.log4j.Logger;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Entity;
/**
* ProteinMatch features are currently used in two rather different ways.
* <ul>
* <li> They are used to represent /similarity data. In this case, the ProteinMatch
* has two FeatureLocs representing the source (rank 0) and target (rank 1)
* of the match.
* </ul> They are used to represent orthologue clusters. In this case, the ProteinMatch
* belongs to the "dummy" organism and has no FeatureLocs. It is the object of a
* number of <code>orthologous_to</code> FeatureRelationships from Polypeptide
* features.
*
* @author rh11
*
*/
@Entity
@FeatureType(cv="sequence", term="protein_match")
public class ProteinMatch extends Match {
private static final Logger logger = Logger.getLogger(ProteinMatch.class);
ProteinMatch() {
// empty
}
public ProteinMatch(Organism organism, String uniqueName, boolean analysis, boolean obsolete) {
super(organism, uniqueName, analysis, obsolete);
}
public ProteinMatch(Organism organism, String uniqueName) {
super(organism, uniqueName);
}
/**
* Check that this ProteinMatch feature represents a similarity.
* @throws IllegalStateException if this ProteinMatch feature does not represent a similarity.
*/
private void thisIsASimilarity() {
if (getFeatureLoc(0, 0) == null) {
throw new IllegalStateException("This ProteinMatch feature does not have a rank=0 FeatureLoc. " +
"Are you sure it represents a similarity?");
}
if (getFeatureLoc(0, 1) == null) {
throw new IllegalStateException("This ProteinMatch feature does not have a rank=1 FeatureLoc. " +
"Are you sure it represents a similarity?");
}
if (getOrganism().getCommonName().equals("dummy")) {
throw new IllegalStateException("This ProteinMatch feature belongs to the 'dummy' organism." +
"Are you sure it represents a similarity?");
}
}
/**
* Check that this ProteinMatch feature represents an orthologue cluster.
* @throws IllegalStateException if this ProteinMatch feature does not represent an orthologue cluster.
*/
private void thisIsACluster() {
if (! getFeatureLocs().isEmpty()) {
throw new IllegalStateException("This ProteinMatch feature has FeatureLocs. " +
"Are you sure it represents an orthologue cluster?");
}
if (! getOrganism().getCommonName().equals("dummy")) {
throw new IllegalStateException("This ProteinMatch feature does not belong to the 'dummy' organism." +
"Are you sure it represents an orthologue cluster?");
}
}
/**
* Get the subject feature of this similarity, which is a Region belonging to the dummy
* organism, and has various bits of similarity metadata as FeatureProps
* (with types <code>feature_property:organism</code>, <code>genedb_misc:product</code>
* and <code>sequence:gene</code>). The primary reference is also stored as the primary
* DbXRef of the subject feature, and any secondary references are related to it via
* FeatureDbXRef.
*
* @return
*/
public Region getSubject() {
thisIsASimilarity();
FeatureLoc featureLoc = this.getFeatureLoc(0, 1);
if (featureLoc == null) {
logger.error(String.format("Could not find subject featureloc for ProteinMatch '%s' (ID=%d)",
getUniqueName(), getFeatureId()));
return null;
}
Feature subjectFeature = featureLoc.getSourceFeature();
if (subjectFeature == null) {
logger.error(String.format("Could not find subject feature for ProteinMatch '%s' (ID=%d)",
getUniqueName(), getFeatureId()));
return null;
}
if (! (subjectFeature instanceof Region) ) {
logger.error(String.format("Subject feature '%s' (ID=%d) for ProteinMatch '%s' (ID=%d) is %s, not Region",
subjectFeature.getUniqueName(), subjectFeature.getFeatureId(), getUniqueName(), getFeatureId(), subjectFeature.getClass()));
return null;
}
return (Region) subjectFeature;
}
/**
* Get the query feature of this similarity, which is the polypeptide it's associated with.
*
* @return
*/
public Polypeptide getPolypeptide() {
thisIsASimilarity();
FeatureLoc featureLoc = this.getFeatureLoc(0, 0);
if (featureLoc == null) {
logger.error(String.format("Could not find query featureloc for ProteinMatch '%s' (ID=%d)",
getUniqueName(), getFeatureId()));
return null;
}
Feature targetFeature = featureLoc.getSourceFeature();
if (targetFeature == null) {
logger.error(String.format("Could not find query feature for ProteinMatch '%s' (ID=%d)",
getUniqueName(), getFeatureId()));
return null;
}
if (! (targetFeature instanceof Polypeptide)) {
logger.error(String.format("Query feature '%s' (ID=%d) for ProteinMatch '%s' (ID=%d) is %s, not Polypeptide",
targetFeature.getUniqueName(), targetFeature.getFeatureId(), getUniqueName(), getFeatureId(), targetFeature.getClass()));
return null;
}
return (Polypeptide) targetFeature;
}
/**
* Add an orthologue link from the specified polypeptide to this cluster.
* @param source the source polypeptide
* @return the new FeatureRelationship relating the polypeptide to this cluster
*/
public FeatureRelationship addOrthologue(Polypeptide source) {
thisIsACluster();
return this.addFeatureRelationship(source, "sequence", "orthologous_to");
}
/**
* Add a paralogue link from the specified polypeptide to this cluster.
* @param source the source polypeptide
* @return the new FeatureRelationship relating the polypeptide to this cluster
*/
public FeatureRelationship addParalogue(Polypeptide source) {
thisIsACluster();
return this.addFeatureRelationship(source, "sequence", "paralogous_to");
}
/**
* Get all the polypeptides that belong to this cluster.
* @return a collection of all the polypeptides that belong to this cluster
*/
public Collection<Polypeptide> getPolypeptidesInCluster() {
thisIsACluster();
Set<Polypeptide> polypeptides = new HashSet<Polypeptide>();
for (FeatureRelationship featureRelationship: getFeatureRelationshipsForObjectId()) {
CvTerm relationshipType = featureRelationship.getType();
if (relationshipType.getCv().getName().equals("sequence")
&& relationshipType.getName().equals("orthologous_to")) {
Feature subject = featureRelationship.getSubjectFeature();
if (! (subject instanceof Polypeptide)) {
throw new IllegalStateException(
String.format("The cluster '%s' (ID=%d) contains something other than a Polypeptide" +
"(%s, ID=%d, %s)", getUniqueName(), getFeatureId(), subject.getUniqueName(),
subject.getFeatureId(), subject.getClass()));
}
polypeptides.add((Polypeptide) subject);
}
}
return polypeptides;
}
}