001package org.biopax.paxtools.impl.level3;
002
003
004import org.apache.commons.logging.Log;
005import org.apache.commons.logging.LogFactory;
006import org.biopax.paxtools.model.level3.*;
007import org.biopax.paxtools.util.BPCollections;
008import org.hibernate.annotations.Cache;
009import org.hibernate.annotations.*;
010
011import javax.persistence.Entity;
012import javax.persistence.*;
013import java.util.Set;
014
015@Entity
016@Proxy(proxyClass= EntityReference.class)
017@DynamicUpdate @DynamicInsert
018@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
019public abstract class EntityReferenceImpl extends NamedImpl
020                implements EntityReference
021{
022        private final Log log = LogFactory.getLog(EntityReferenceImpl.class);
023        
024        private Set<EntityFeature> entityFeature;
025        private Set<SimplePhysicalEntity> entityReferenceOf;
026        private Set<Evidence> evidence;
027        Set<EntityReferenceTypeVocabulary> entityReferenceType;
028        Set<EntityReference> memberEntityReference;
029        private Set<EntityReference> ownerEntityReference;
030
031        /**
032         * Constructor.
033         */
034        public EntityReferenceImpl()
035        {
036                this.entityFeature = BPCollections.I.createSafeSet();
037                this.entityReferenceOf = BPCollections.I.createSafeSet();
038                this.evidence = BPCollections.I.createSafeSet();
039                this.entityReferenceType = BPCollections.I.createSafeSet();
040                this.memberEntityReference = BPCollections.I.createSafeSet();
041                this.ownerEntityReference= BPCollections.I.createSafeSet();
042        }
043
044        @Transient
045        public Class<? extends EntityReference> getModelInterface()
046        {
047                return EntityReference.class;
048        }
049
050        /**
051         * The contents of this set should NOT be modified. For manipulating the contents use addNew and
052         * remove instead.
053         *
054         * @return A set of entity features for the reference entity.
055         */
056    @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
057        @OneToMany(targetEntity = EntityFeatureImpl.class, mappedBy = "entityFeatureOf")
058        public Set<EntityFeature> getEntityFeature()
059        {
060                return entityFeature;
061        }
062
063        public void addEntityFeature(EntityFeature entityFeature)
064        {
065                if (entityFeature != null) synchronized (entityFeature)
066                {
067                        EntityReference eFof = entityFeature.getEntityFeatureOf();
068                        
069                        if (eFof != null && !eFof.equals(this))
070                        {                               
071                                log.warn("addEntityFeature: violated the inverse-functional OWL constraint; to fix, " 
072                                        + entityFeature.getModelInterface().getSimpleName() + " " + entityFeature.getRDFId() 
073                                        + " should be REMOVED from " 
074                                        + eFof.getModelInterface().getSimpleName() + " " + eFof.getRDFId());
075                                //TODO eFof.removeEntityFeature(entityFeature) or an exception would be a breaking change (let's shelve for v5.0.0)
076                                //so, we neither fix nor fail here (currently, biopax-validator detects and optionally fixes it).
077                        } 
078
079                        ((EntityFeatureImpl) entityFeature).setEntityFeatureOf(this);   
080                        this.entityFeature.add(entityFeature);
081                }
082        }
083
084
085        public void removeEntityFeature(EntityFeature entityFeature)
086        {
087                if (this.entityFeature.contains(entityFeature))
088                {
089                        this.entityFeature.remove(entityFeature);
090                        
091                        if(entityFeature.getEntityFeatureOf() == this) {
092                                ((EntityFeatureImpl) entityFeature).setEntityFeatureOf(null);
093                        } else if(entityFeature.getEntityFeatureOf() != null) {
094                                //Don't set entityFeatureOf to null here 
095                                //(looks, this EF was previously moved to another ER)
096                                log.warn("removeEntityFeature: removed " 
097                                        + entityFeature.getModelInterface().getSimpleName() + " " + entityFeature.getRDFId() 
098                                        + " from " + getModelInterface().getSimpleName() + " " + getRDFId() 
099                                        + "; though entityFeatureOf was another " 
100                                        + entityFeature.getEntityFeatureOf().getModelInterface().getSimpleName() 
101                                        + " " + entityFeature.getEntityFeatureOf().getRDFId());
102                        } else {
103                                log.warn("removeEntityFeature: removed " 
104                                        + entityFeature.getModelInterface().getSimpleName() + " " + entityFeature.getRDFId() 
105                                        + " from " + getModelInterface().getSimpleName() + " " + getRDFId()
106                                        + ", but entityFeatureOf was already NULL (illegal state)");
107                        }
108                } else {
109                        log.warn("removeEntityFeature: did nothing, because "
110                                        + getRDFId() + " does not contain feature " + entityFeature.getRDFId());
111                }
112        }
113
114        
115        protected void setEntityFeature(Set<EntityFeature> entityFeature)
116        {
117                this.entityFeature = entityFeature;
118        }
119
120
121        @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
122        @OneToMany(targetEntity= SimplePhysicalEntityImpl.class, mappedBy = "entityReferenceX")
123        public Set<SimplePhysicalEntity> getEntityReferenceOf()
124        {
125                return entityReferenceOf;
126        }
127
128    @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
129        @ManyToMany(targetEntity = EntityReferenceTypeVocabularyImpl.class)
130        @JoinTable(name="entityReferenceType")
131        public Set<EntityReferenceTypeVocabulary> getEntityReferenceType()
132        {
133                return entityReferenceType;
134        }
135
136        public void addEntityReferenceType(
137                        EntityReferenceTypeVocabulary entityReferenceType)
138        {
139                if(entityReferenceType != null)
140                        this.entityReferenceType.add(entityReferenceType);
141        }
142
143        public void removeEntityReferenceType(
144                        EntityReferenceTypeVocabulary entityReferenceType)
145        {
146                if(entityReferenceType != null)
147                        this.entityReferenceType.remove(entityReferenceType);
148        }
149
150        protected void setEntityReferenceType(
151                        Set<EntityReferenceTypeVocabulary> entityReferenceType)
152        {
153                this.entityReferenceType=entityReferenceType;
154        }
155
156    @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
157        @ManyToMany(targetEntity = EntityReferenceImpl.class) //TODO generify?
158        @JoinTable(name="memberEntityReference")
159        public Set<EntityReference> getMemberEntityReference()
160        {
161                return memberEntityReference;
162        }
163
164        public void addMemberEntityReference(EntityReference memberEntity)
165        {
166                if (memberEntity != null) {
167                        this.memberEntityReference.add(memberEntity);
168                        memberEntity.getMemberEntityReferenceOf().add(this);
169                }
170        }
171
172        public void removeMemberEntityReference(EntityReference memberEntity)
173        {
174                if (memberEntity != null) {
175                        this.memberEntityReference.remove(memberEntity);
176                        memberEntity.getMemberEntityReferenceOf().remove(this);
177                }
178        }
179
180        public void setMemberEntityReference(Set<EntityReference> memberEntity)
181        {
182                this.memberEntityReference = memberEntity;
183
184        }
185
186
187    @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
188        @ManyToMany(targetEntity = EntityReferenceImpl.class, mappedBy = "memberEntityReference")
189        public Set<EntityReference> getMemberEntityReferenceOf()
190        {
191                return ownerEntityReference;
192        }
193
194        protected  void setMemberEntityReferenceOf(Set<EntityReference> newOwnerEntityReferenceSet)
195        {
196                this.ownerEntityReference = newOwnerEntityReferenceSet;
197        }
198
199    @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
200        @ManyToMany(targetEntity = EvidenceImpl.class)
201        @JoinTable(name="evidence")     
202        public Set<Evidence> getEvidence()
203        {
204                return evidence;
205        }
206
207        public void addEvidence(Evidence evidence)
208        {
209                if(evidence != null)
210                        this.evidence.add(evidence);
211        }
212
213        public void removeEvidence(Evidence evidence)
214        {
215                if(evidence != null)
216                        this.evidence.remove(evidence);
217        }
218
219        public void setEvidence(Set<Evidence> evidence)
220        {
221                this.evidence = evidence;
222        }
223
224        protected void setEntityReferenceOf(Set<SimplePhysicalEntity> entityReferenceOf)
225        {
226                this.entityReferenceOf = entityReferenceOf;
227        }
228
229        protected void setMemberEntity(Set<EntityReference> memberEntity)
230        {
231                this.memberEntityReference = memberEntity;
232        }
233
234}