001package org.biopax.paxtools.impl.level3;
002
003import org.apache.commons.logging.Log;
004import org.apache.commons.logging.LogFactory;
005import org.biopax.paxtools.model.BioPAXElement;
006import org.biopax.paxtools.model.level3.*;
007import org.biopax.paxtools.util.BPCollections;
008import org.hibernate.annotations.Cache;
009import org.hibernate.annotations.*;
010import org.hibernate.search.annotations.Indexed;
011
012import javax.persistence.Entity;
013import javax.persistence.*;
014import java.util.Set;
015
016@Entity
017@Proxy(proxyClass= EntityFeature.class)
018@Indexed
019@DynamicUpdate @DynamicInsert
020@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
021public class EntityFeatureImpl extends L3ElementImpl implements EntityFeature
022{
023        private final Log LOG = LogFactory.getLog(EntityFeatureImpl.class);
024        
025        private Set<Evidence> evidence;
026        private EntityReference ownerEntityReference;
027        private Set<PhysicalEntity> featureOf;
028        private Set<PhysicalEntity> notFeatureOf;
029        private SequenceLocation featureLocation;
030        private Set<EntityFeature> memberFeature;
031        private SequenceRegionVocabulary featureLocationType;
032        private Set<EntityFeature> memberFeatureOf;
033
034
035        public EntityFeatureImpl()
036        {
037                evidence = BPCollections.I.createSafeSet();
038                featureOf = BPCollections.I.createSafeSet();
039                notFeatureOf = BPCollections.I.createSafeSet();
040                memberFeatureOf = BPCollections.I.createSafeSet();
041                memberFeature = BPCollections.I.createSafeSet();
042        }
043
044
045        @Transient
046        public Class<? extends EntityFeature> getModelInterface()
047        {
048                return EntityFeature.class;
049        }
050
051        @ManyToOne(targetEntity = EntityReferenceImpl.class)
052        public EntityReference getEntityFeatureOf(){
053                return ownerEntityReference;
054        }
055        public void setEntityFeatureOf(EntityReference entityReference){
056                ownerEntityReference = entityReference;
057        }
058        
059    @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
060        @ManyToMany(targetEntity = PhysicalEntityImpl.class, mappedBy = "feature")
061        public Set<PhysicalEntity> getFeatureOf()
062        {
063                return featureOf;
064        }
065
066    @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
067        @ManyToMany(targetEntity = PhysicalEntityImpl.class, mappedBy = "notFeature")
068        public Set<PhysicalEntity> getNotFeatureOf()
069        {
070                return notFeatureOf;
071        }
072
073    @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
074        @ManyToMany(targetEntity = EvidenceImpl.class)
075        @JoinTable(name="evidence")
076        public Set<Evidence> getEvidence()
077        {
078                return evidence;
079        }
080
081        public void addEvidence(Evidence evidence)
082        {
083                if(evidence != null)
084                        this.evidence.add(evidence);
085        }
086
087        public void removeEvidence(Evidence evidence)
088        {
089                if(evidence != null)
090                        this.evidence.remove(evidence);
091        }
092
093        protected void setEvidence(Set<Evidence> evidence)
094        {
095                this.evidence = evidence;
096        }
097
098
099        @ManyToOne(targetEntity = SequenceLocationImpl.class)//, cascade={CascadeType.ALL})
100        public SequenceLocation getFeatureLocation()
101        {
102                return featureLocation;
103        }
104        public void setFeatureLocation(SequenceLocation featureLocation)
105        {
106                this.featureLocation = featureLocation;
107        }
108
109        @ManyToOne(targetEntity = SequenceRegionVocabularyImpl.class)
110        public SequenceRegionVocabulary getFeatureLocationType()
111        {
112                return featureLocationType;
113        }
114
115        public void setFeatureLocationType(SequenceRegionVocabulary regionVocabulary)
116        {
117                this.featureLocationType= regionVocabulary;
118        }
119
120        @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
121        @ManyToMany(targetEntity = EntityFeatureImpl.class)
122        @JoinTable(name="memberFeature")
123        public Set<EntityFeature> getMemberFeature()
124        {
125                return memberFeature;
126        }
127        
128        protected void setMemberFeature(Set<EntityFeature> memberFeature) {
129                this.memberFeature = memberFeature;
130        }
131
132        public void addMemberFeature(EntityFeature feature)
133        {
134                if (feature != null) {
135                        memberFeature.add(feature);
136                        feature.getMemberFeatureOf().add(this);
137                }
138        }
139
140        public void removeMemberFeature(EntityFeature feature)
141        {
142                if (feature != null) {
143                        memberFeature.remove(feature);
144                        feature.getMemberFeatureOf().remove(this);
145                }
146        }
147
148    @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
149        @ManyToMany(targetEntity = EntityFeatureImpl.class, mappedBy = "memberFeature")
150        public Set<EntityFeature> getMemberFeatureOf()
151        {
152                return this.memberFeatureOf;
153        }
154        
155        protected void setMemberFeatureOf(Set<EntityFeature> memberFeatureOf)
156        {
157                this.memberFeatureOf = memberFeatureOf;
158        }
159
160    @Transient
161    /**
162     * This method returns true if and only if two entity features are on the same known location on a known ER.
163     * Unknown location or ER on any one of the features results in a false.
164     */
165    public boolean atEquivalentLocation(EntityFeature that) {
166        return getEntityFeatureOf() != null &&
167                getEntityFeatureOf().isEquivalent(that.getEntityFeatureOf()) &&
168                getFeatureLocation() != null &&
169                getFeatureLocation().isEquivalent(that.getFeatureLocation());
170    }
171
172    @Transient
173    protected int locationCode() {
174        if (this.getEntityFeatureOf() == null || this.getFeatureLocation()==null) return hashCode();
175        else {
176            return
177                    this.getEntityFeatureOf().equivalenceCode()+
178                            13 * this.getFeatureLocation().equivalenceCode();
179        }
180    }
181
182    @Override
183    protected boolean semanticallyEquivalent(BioPAXElement element) {
184        if (!(element instanceof EntityFeature))
185            return false;
186
187        EntityFeature that = (EntityFeature) element;
188        boolean value = atEquivalentLocation(that);
189        if (value) {
190            SequenceRegionVocabulary myType = this.featureLocationType;
191            SequenceRegionVocabulary yourType = that.getFeatureLocationType();
192            value = (yourType == null) ?
193                    myType == null : yourType.isEquivalent(myType);
194        }
195        return value;
196    }
197
198    @Override
199    public int equivalenceCode()
200    {
201        SequenceRegionVocabulary siteType = this.getFeatureLocationType();
202        int code = siteType == null ? 0 : siteType.hashCode();
203        return code + 13 * this.locationCode();
204    }
205
206        protected void setFeatureOf(Set<PhysicalEntity> featureOf)
207        {
208                this.featureOf = featureOf;
209        }
210
211        protected void setNotFeatureOf(Set<PhysicalEntity> notFeatureOf)
212        {
213                this.notFeatureOf = notFeatureOf;
214        }
215}