001package org.biopax.paxtools.impl.level3; 002 003import org.apache.commons.logging.Log; 004import org.apache.commons.logging.LogFactory; 005import org.biopax.paxtools.util.*; 006import org.biopax.paxtools.impl.BioPAXElementImpl; 007import org.biopax.paxtools.model.BioPAXElement; 008import org.biopax.paxtools.model.level3.*; 009import org.biopax.paxtools.util.SetEquivalenceChecker; 010import org.hibernate.annotations.Cache; 011import org.hibernate.annotations.CacheConcurrencyStrategy; 012import org.hibernate.annotations.Proxy; 013import org.hibernate.annotations.DynamicInsert; 014import org.hibernate.annotations.DynamicUpdate; 015import org.hibernate.search.annotations.*; 016 017import javax.persistence.JoinTable; 018import javax.persistence.ManyToMany; 019import javax.persistence.ManyToOne; 020import javax.persistence.Transient; 021import java.util.Set; 022 023@javax.persistence.Entity 024@Proxy(proxyClass=PhysicalEntity.class) 025@Indexed 026@Boost(1.3f) 027@FullTextFilterDefs( { //these filters are global (can be defined on any @Indexed entity), names - unique! 028 @FullTextFilterDef(name = BioPAXElementImpl.FILTER_BY_ORGANISM, impl = OrganismFilterFactory.class), 029 @FullTextFilterDef(name = BioPAXElementImpl.FILTER_BY_DATASOURCE, impl = DataSourceFilterFactory.class) 030}) 031@DynamicUpdate @DynamicInsert 032@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) 033public class PhysicalEntityImpl extends EntityImpl implements PhysicalEntity 034{ 035 private CellularLocationVocabulary cellularLocation; 036 private Set<PhysicalEntity> memberPhysicalEntity; 037 private Set<Complex> componentOf; 038 private Set<EntityFeature> feature; 039 private Set<EntityFeature> notFeature; 040 private Set<Control> controllerOf; 041 private final Log log = LogFactory.getLog(PhysicalEntityImpl.class); 042 private Set<PhysicalEntity> memberPhysicalEntityOf; 043 044 public PhysicalEntityImpl() 045 { 046 feature = BPCollections.I.createSafeSet(); 047 notFeature = BPCollections.I.createSafeSet(); 048 controllerOf = BPCollections.I.createSafeSet(); 049 componentOf = BPCollections.I.createSafeSet(); 050 memberPhysicalEntityOf = BPCollections.I.createSafeSet(); //TODO make generic? 051 memberPhysicalEntity = BPCollections.I.createSafeSet(); 052 } 053 054 @Transient 055 public Class<? extends PhysicalEntity> getModelInterface() 056 { 057 return PhysicalEntity.class; 058 } 059 060 @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) 061 @ManyToMany(targetEntity = ComplexImpl.class, mappedBy = "component") 062 public Set<Complex> getComponentOf() 063 { 064 return componentOf; 065 } 066 067 @ManyToOne(targetEntity = CellularLocationVocabularyImpl.class) 068 public CellularLocationVocabulary getCellularLocation() 069 { 070 return cellularLocation; 071 } 072 073 public void setCellularLocation(CellularLocationVocabulary location) 074 { 075 this.cellularLocation = location; 076 } 077 078 @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) 079 @ManyToMany(targetEntity = EntityFeatureImpl.class) 080 @JoinTable(name="feature") 081 public Set<EntityFeature> getFeature() 082 { 083 return feature; 084 } 085 086 public void addFeature(EntityFeature feature) 087 { 088 if (feature != null) { 089 checkAndAddFeature(feature, feature.getFeatureOf()); 090 this.feature.add(feature); 091 } 092 } 093 094 095 public void removeFeature(EntityFeature feature) 096 { 097 if (feature != null) { 098 synchronized (feature) { 099 assert feature.getFeatureOf().contains(this) ^ feature.getNotFeatureOf().contains(this) 100 : feature + " is both 'feature' and 'notFeature' of " + this; 101 //TODO even if the assertion fails, so what? (in any case, we still want to remove this PE from the set) 102 feature.getFeatureOf().remove(this); 103 } 104 this.feature.remove(feature); 105 } 106 } 107 108 protected void setFeature(Set<EntityFeature> feature) 109 { 110 this.feature = feature; 111 } 112 113 @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) 114 @ManyToMany(targetEntity = EntityFeatureImpl.class) 115 @JoinTable(name="notfeature") 116 public Set<EntityFeature> getNotFeature() 117 { 118 return notFeature; 119 } 120 121 122 public void addNotFeature(EntityFeature feature) 123 { 124 if (feature != null) { 125 checkAndAddFeature(feature, feature.getNotFeatureOf()); 126 this.notFeature.add(feature); 127 } 128 } 129 130 public void removeNotFeature(EntityFeature feature) 131 { 132 if (feature != null) { 133 synchronized (feature) { 134 assert feature.getFeatureOf().contains(this) ^ feature.getNotFeatureOf().contains(this) 135 : feature + " is both 'feature' and 'notFeature' of " + this; 136 //TODO even if the assertion fails, so what? (in any case, we still want to remove this PE from the set) 137 feature.getNotFeatureOf().remove(this); 138 } 139 this.notFeature.remove(feature); 140 } 141 } 142 143 protected void setNotFeature(Set<EntityFeature> featureSet) 144 { 145 this.notFeature = featureSet; 146 } 147 148 149 @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) 150 @ManyToMany(targetEntity = PhysicalEntityImpl.class) 151 @JoinTable(name="memberPhysicalEntity") 152 public Set<PhysicalEntity> getMemberPhysicalEntity() 153 { 154 return this.memberPhysicalEntity; //TODO (what?) 155 } 156 157 public void addMemberPhysicalEntity(PhysicalEntity newMember) 158 { 159 if (newMember != null) { 160 this.memberPhysicalEntity.add(newMember); 161 synchronized (newMember) { 162 newMember.getMemberPhysicalEntityOf().add(this); 163 } 164 } 165 } 166 167 public void removeMemberPhysicalEntity(PhysicalEntity oldMember) 168 { 169 if (oldMember != null) { 170 this.memberPhysicalEntity.remove(oldMember); 171 synchronized (oldMember) { 172 oldMember.getMemberPhysicalEntityOf().remove(this); 173 } 174 } 175 } 176 177 protected void setMemberPhysicalEntity(Set<PhysicalEntity> memberPhysicalEntity) 178 { 179 this.memberPhysicalEntity = memberPhysicalEntity; //TODO (what?) 180 } 181 182 183 @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) 184 @ManyToMany(targetEntity = PhysicalEntityImpl.class, mappedBy = "memberPhysicalEntity") 185 public Set<PhysicalEntity> getMemberPhysicalEntityOf() 186 { 187 return memberPhysicalEntityOf; 188 } 189 190 191 private void checkAndAddFeature(EntityFeature feature, 192 Set<PhysicalEntity> target) 193 { 194 if (feature.getFeatureOf().contains(this) || 195 feature.getNotFeatureOf().contains(this)) 196 { 197 if(log.isWarnEnabled()) 198 log.warn("Redundant attempt to set the inverse link! " 199 + " this " + getModelInterface().getSimpleName() 200 + " " + getRDFId() + " and - " 201 + feature.getModelInterface().getSimpleName() + " " 202 + feature.getRDFId()); 203 } 204 target.add(this); 205 } 206 207 // --------------------- Interface BioPAXElement --------------------- 208 209 210 @Override 211 protected boolean semanticallyEquivalent(BioPAXElement element) 212 { 213 if (!(element instanceof PhysicalEntity)) 214 return false; 215 216 PhysicalEntity that = (PhysicalEntity) element; 217 return hasEquivalentCellularLocation(that) 218 && hasEquivalentFeatures(that) 219 && SetEquivalenceChecker 220 .isEquivalent(getMemberPhysicalEntity(), that.getMemberPhysicalEntity()) 221 && 222 super.semanticallyEquivalent(element); // StackOverflow BUG fixed: was isEquivalent ! 223 } 224 225 @Override 226 public int equivalenceCode() 227 { 228 return hashCode(); 229 } 230 231 public boolean hasEquivalentCellularLocation(PhysicalEntity that) 232 { 233 boolean equivalency = false; 234 if (that != null) 235 { 236 equivalency = (cellularLocation != null) 237 ? cellularLocation.isEquivalent(that.getCellularLocation()) 238 : that.getCellularLocation() == null; 239 } 240 return equivalency; 241 } 242 243 public boolean hasEquivalentFeatures(PhysicalEntity that) 244 { 245 boolean equivalency = false; 246 if (that != null) 247 { 248 equivalency = 249 SetEquivalenceChecker.isEquivalent(this.getFeature(), that.getFeature()) && 250 SetEquivalenceChecker.isEquivalent(this.getNotFeature(), that.getNotFeature()); 251 } 252 return equivalency; 253 } 254 255 protected int locationAndFeatureCode() 256 { 257 int result = (cellularLocation != null ? cellularLocation.hashCode() : 0); 258 result = 31 * result + (feature != null ? feature.hashCode() : 0); 259 result = 31 * result + (notFeature != null ? notFeature.hashCode() : 0); 260 return result; 261 262 } 263 264 @ManyToMany(targetEntity = ControlImpl.class, mappedBy = "peController") 265 public Set<Control> getControllerOf() 266 { 267 return controllerOf; 268 } 269 270 protected void setControllerOf(Set<Control> controllerOf) 271 { 272 this.controllerOf = controllerOf; 273 } 274 275 protected void setMemberPhysicalEntityOf(Set<PhysicalEntity> memberPhysicalEntityOf) 276 { 277 this.memberPhysicalEntityOf = memberPhysicalEntityOf; 278 } 279 280 protected void setComponentOf(Set<Complex> componentOf) 281 { 282 this.componentOf = componentOf; 283 } 284 285}