001 /** 002 * Copyright (C) 2010 The Roslin Institute <contact andy.law@roslin.ed.ac.uk> 003 * 004 * This file is part of the Ensembl Java API demonstration project developed by the 005 * Bioinformatics Group at The Roslin Institute, The Royal (Dick) School of 006 * Veterinary Studies, University of Edinburgh. 007 * 008 * This is free software: you can redistribute it and/or modify 009 * it under the terms of the GNU General Public License (version 3) as published by 010 * the Free Software Foundation. 011 * 012 * This software is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 015 * GNU General Public License for more details. 016 * 017 * You should have received a copy of the GNU General Public License 018 * in this software distribution. If not, see <http://www.gnu.org/licenses/gpl-3.0.html/>. 019 */ 020 021 package uk.ac.roslin.ensembl.model; 022 023 import java.io.Serializable; 024 import java.util.Comparator; 025 import uk.ac.roslin.ensembl.model.core.CoordinateSystem; 026 027 /** 028 * Used to be abstract 029 * @author paterson 030 */ 031 public class Mapping implements Serializable { 032 033 protected MappableObject source=null; 034 protected MappableObject target=null; 035 protected Coordinate sourceCoordinates=null; 036 protected Coordinate targetCoordinates=null; 037 protected CoordinateSystem sourceCoordSystem=null; 038 protected CoordinateSystem targetCoordSystem=null; 039 protected Mapping reverseMapping=null; 040 041 public Mapping() { 042 } 043 044 public static boolean addReverseMapping(Mapping originalMapping) { 045 try { 046 //don't add the reverse mapping if we already have it 047 // for (Mapping mapping : ((MappingSet) originalMapping.getTarget().getMappings())) { 048 // if (mapping.getTarget().getId().equals(originalMapping.getSource().getId())) { 049 // return; 050 // } 051 // } 052 053 Mapping reverseMapping = new Mapping(); 054 reverseMapping.setReverseMapping(originalMapping); 055 056 reverseMapping.setSource(originalMapping.getTarget()); 057 reverseMapping.setTarget(originalMapping.getSource()); 058 059 reverseMapping.setSourceCoordinates(originalMapping.getTargetCoordinates()); 060 reverseMapping.setTargetCoordinates(originalMapping.getSourceCoordinates()); 061 062 reverseMapping.getSource().addMapping(reverseMapping); 063 originalMapping.setReverseMapping(reverseMapping); 064 065 } catch (Exception e) { 066 return false; 067 } 068 return true; 069 } 070 071 public void setSource(MappableObject source) { 072 this.source = source; 073 } 074 075 public void setTarget(MappableObject target) { 076 this.target = target; 077 } 078 079 public MappableObject getSource() { 080 return source; 081 } 082 083 public MappableObject getTarget() { 084 return target; 085 } 086 087 public ObjectType getTargetType() { 088 return (this.getTarget()!=null) ? this.getTarget().getType() : null; 089 } 090 091 public ObjectType getSourceType() { 092 return (this.getSource()!=null) ? this.getSource().getType() : null; 093 } 094 095 public String getTargetHashID() { 096 //make it an empty string if there is no target set 097 return (this.getTarget()!=null) ? this.getTarget().getHashID() : ""; 098 } 099 100 public String getSourceHashID() { 101 //make it an empty string if there is no source set 102 return (this.getSource()!=null) ? this.getSource().getHashID() : ""; 103 } 104 105 public Coordinate getSourceCoordinates() { 106 return this.sourceCoordinates; 107 } 108 109 public Coordinate getTargetCoordinates() { 110 return this.targetCoordinates; 111 } 112 113 public void setSourceCoordinates(Coordinate coord) { 114 this.sourceCoordinates = coord; 115 } 116 117 public void setTargetCoordinates(Coordinate coord) { 118 this.targetCoordinates = coord; 119 } 120 121 public void setSourceCoordinates(Integer start, Integer end, Coordinate.Strand strand) { 122 this.sourceCoordinates = new Coordinate(start, end, strand); 123 } 124 public void setSourceCoordinates(Integer start, Integer end, Integer strand) { 125 this.sourceCoordinates = new Coordinate(start, end, strand); 126 } 127 128 public void setTargetCoordinates(Integer start, Integer end, Coordinate.Strand strand) { 129 this.targetCoordinates = new Coordinate(start, end, strand); 130 } 131 public void setTargetCoordinates(Integer start, Integer end, Integer strand) { 132 this.targetCoordinates = new Coordinate(start, end, strand); 133 } 134 135 @Override 136 public boolean equals(Object mapping) { 137 138 if (this == mapping ) { 139 return true; 140 } 141 142 //this checks for null too.. 143 if ( ! (mapping instanceof Mapping )) { 144 return false; 145 } 146 147 Mapping m = (Mapping) mapping; 148 149 boolean out = true; 150 151 //this checks for identity if source and target are set on both mappings 152 //and each pair has the same hashcode 153 //the hashcode method will be based on objectID, objectType and probably SpeciesID 154 155 if ( !( !this.getSourceHashID().equals("") 156 && !m.getSourceHashID().equals("") 157 && !this.getTargetHashID().equals("") 158 && !m.getTargetHashID().equals("") 159 && this.getSourceHashID().equals(m.getSourceHashID()) 160 && this.getTargetHashID().equals(m.getTargetHashID()) 161 ) ) { 162 return false; 163 } 164 165 return out; 166 167 } 168 169 @Override 170 public int hashCode() { 171 172 return this.getSourceHashID().hashCode()+this.getTargetHashID().hashCode(); 173 174 } 175 176 public Mapping getReverseMapping() { 177 if (reverseMapping==null) { 178 Mapping.addReverseMapping(this); 179 } 180 return reverseMapping; 181 } 182 183 protected void setReverseMapping(Mapping reverseMapping) { 184 this.reverseMapping = reverseMapping; 185 } 186 187 public static final MappingOnSourceComparator mappingOnSourceComparator 188 = new MappingOnSourceComparator(); 189 190 public static final MappingOnTargetComparator mappingOnTargetComparator 191 = new MappingOnTargetComparator(); 192 193 } 194 195 /** 196 * Comparator Class for Mappings, based primarily on their source coordinates. 197 * This will sort a set of Mappings on the order of the source coordinates 198 * or failing that on the ids on the target object, then source object. Beware 199 * that this comparison doesn't match the equals logic. 200 * @author tpaterso 201 */ 202 class MappingOnSourceComparator implements Comparator<Mapping>, Serializable { 203 public int compare(Mapping o1, Mapping o2) { 204 // this would only sort mappings with non identical source coordinates 205 // however we want to sort multiple things with the same source coordinates if they are different things! 206 //return o1.getSourceCoordinates().compareTo(o2.getSourceCoordinates()); 207 208 if (o1==null) { 209 if (o2 == null) { 210 return 0; 211 } else { 212 return -1; 213 } 214 } else if (o2==null) { 215 return +1; 216 } 217 218 int out; 219 220 if (o1.getSourceCoordinates()==null) { 221 if (o2.getSourceCoordinates()== null) { 222 out=0; 223 } else { 224 return -1; 225 } 226 } else if (o2.getSourceCoordinates()== null) { 227 return +1; 228 } else { 229 out = o1.getSourceCoordinates().compareTo(o2.getSourceCoordinates()); 230 } 231 232 if (out != 0) { 233 return out; 234 } else { 235 236 //if both pairs of hashIDs are same this could break the contract of equals 237 //for the set - however it could happen cos the mappings are mutable 238 if (o1.getTargetHashID().equals(o2.getTargetHashID()) && 239 o1.getSourceHashID().equals(o2.getSourceHashID()) ) { 240 //it looks like the mappings really are for the same things! 241 //so return this 242 return 0; 243 } else { 244 245 //not the same 246 out = -1; 247 248 try { 249 //try to order them by the Target's ID number 250 out = o1.getTargetHashID().compareTo(o2.getTargetHashID()); 251 // but if they have the same ID ignore this 252 if (out == 0) { 253 out = o1.getSourceHashID().compareTo(o2.getSourceHashID()); 254 } 255 // but if these also have the same ID ignore this and return a random ordering 256 if (out == 0) { 257 out = -1; 258 } 259 } catch (Exception e) { 260 } 261 return out; 262 } 263 } 264 } 265 } 266 267 /** 268 * Comparator Class for Mappings, based primarily on their target coordinates. 269 * This will sort a set of Mappings on the order of the target coordinates 270 * or failing that on the ids on the source object, then target object. Beware 271 * that this comparison doesn't match the equals logic. 272 * @author tpaterso 273 */ 274 class MappingOnTargetComparator implements Comparator<Mapping>, Serializable { 275 public int compare(Mapping o1, Mapping o2) { 276 // this would only sort mappings with non identical source coordinates 277 // however we want to sort multiple things with the same source coordinates if they are different things! 278 //return o1.getSourceCoordinates().compareTo(o2.getSourceCoordinates()); 279 280 if (o1==null) { 281 if (o2 == null) { 282 return 0; 283 } else { 284 return -1; 285 } 286 } else if (o2==null) { 287 return +1; 288 } 289 290 int out; 291 292 if (o1.getTargetCoordinates()==null) { 293 if (o2.getTargetCoordinates()== null) { 294 out=0; 295 } else { 296 return -1; 297 } 298 } else if (o2.getTargetCoordinates()== null) { 299 return +1; 300 } else { 301 out = o1.getTargetCoordinates().compareTo(o2.getTargetCoordinates()); 302 } 303 304 if (out != 0) { 305 return out; 306 } else { 307 308 //if both pairs of hashIDs are same this could break the contract of equals 309 //for the set - however it could happen cos the mappings are mutable 310 if (o1.getTargetHashID().equals(o2.getTargetHashID()) && 311 o1.getSourceHashID().equals(o2.getSourceHashID()) ) { 312 //it looks like the mappings really are for the same things! 313 //so return this 314 return 0; 315 } else { 316 317 //not the same 318 out = -1; 319 320 try { 321 //try to order them by the Target's ID number 322 out = o1.getSourceHashID().compareTo(o2.getSourceHashID()); 323 // but if they have the same ID ignore this 324 if (out == 0) { 325 out = o1.getTargetHashID().compareTo(o2.getTargetHashID()); 326 } 327 // but if these also have the same ID ignore this and return a random ordering 328 if (out == 0) { 329 out = -1; 330 } 331 } catch (Exception e) { 332 } 333 return out; 334 } 335 } 336 } 337 } 338 339