001 package edu.nrao.sss.model.resource; 002 003 import java.util.ArrayList; 004 import java.util.Date; 005 import java.util.List; 006 007 import edu.nrao.sss.math.Polynomial; 008 import edu.nrao.sss.measure.TimeDuration; 009 import edu.nrao.sss.measure.TimeInterval; 010 import edu.nrao.sss.measure.TimeUnits; 011 import edu.nrao.sss.util.Identifiable; 012 import edu.nrao.sss.util.LookupTable; 013 014 /** 015 * A resource specification for pulsar observations. 016 * <p> 017 * <b>Version Info:</b> 018 * <table style="margin-left:2em"> 019 * <tr><td>$Revision: 1709 $</td></tr> 020 * <tr><td>$Date: 2008-11-14 11:22:37 -0700 (Fri, 14 Nov 2008) $</td></tr> 021 * <tr><td>$Author: dharland $</td></tr> 022 * </table></p> 023 * 024 * @author David M. Harland 025 * @since 2006-09-08 026 */ 027 public class PulsarSpecification 028 implements Cloneable 029 { 030 //This ID field is here for the persistance layer 031 @SuppressWarnings("unused") 032 private Long id; 033 034 //These 3 properties will probably be removed, because they are 035 //really properties of the source. 036 private TimeDuration pulsePeriod; 037 private double dispersion; 038 private LookupTable<Date, Polynomial> phasePolynomials; 039 //Wrote email to Walter B. re: phase bins 040 private List<TimeInterval> phaseBins; 041 042 /** Creates a new instance. */ 043 public PulsarSpecification() 044 { 045 id = Identifiable.UNIDENTIFIED; 046 047 //TODO find out what default values are reasonable 048 049 pulsePeriod = new TimeDuration("0.0", TimeUnits.MILLISECOND); 050 dispersion = 0.0; 051 phasePolynomials = new LookupTable<Date, Polynomial>(); 052 phaseBins = new ArrayList<TimeInterval>(); 053 } 054 055 /** 056 * Resets the identifier of this specification 057 * to a value that represents the unidentified state. 058 * <p> 059 * This method is useful for preparing a specification for storage in a 060 * database. 061 * The ID property (as of now, though this may change in the future) is 062 * used by our persistence mechanism to identify objects. If you are 063 * persisting this object for the first time, you may need to call 064 * this method before performing a save. This is especially true if 065 * you have created this object from XML, as the XML unmarshalling 066 * brings along the ID property.</p> 067 */ 068 void clearId() 069 { 070 this.id = Identifiable.UNIDENTIFIED; 071 } 072 073 //============================================================================ 074 // 075 //============================================================================ 076 077 /** 078 * Returns a pulsar specification that is a copy of this one. 079 * <p> 080 * If anything goes wrong during the cloning procedure, 081 * a {@code RuntimeException} will be thrown.</p> 082 */ 083 @Override 084 public PulsarSpecification clone() 085 { 086 PulsarSpecification clone = null; 087 088 try 089 { 090 //This line handles the primitive and immutable instance variables 091 clone = (PulsarSpecification)super.clone(); 092 093 //We do NOT want the clone to have the same ID as the original. 094 //The ID is here for the persistence layer; it is in charge of 095 //setting IDs. To help it, we put the clone's ID in the uninitialized 096 //state. 097 clone.id = Identifiable.UNIDENTIFIED; 098 099 clone.pulsePeriod = this.pulsePeriod.clone(); 100 101 //Clone the collection AND the contained elements 102 clone.phasePolynomials = new LookupTable<Date, Polynomial>(); 103 for (Date key : this.phasePolynomials.getKeySet()) 104 clone.phasePolynomials.put(key, this.phasePolynomials.get(key).clone()); 105 106 clone.phaseBins = new ArrayList<TimeInterval>(); 107 for (TimeInterval interval : this.phaseBins) 108 clone.phaseBins.add(interval.clone()); 109 } 110 catch (Exception ex) 111 { 112 throw new RuntimeException(ex); 113 } 114 115 return clone; 116 } 117 118 /** Returns <i>true</i> if {@code o} is equal to this specification. */ 119 @Override 120 public boolean equals(Object o) 121 { 122 //Quick exit if o is this 123 if (o == this) 124 return true; 125 126 //Quick exit if o is null 127 if (o == null) 128 return false; 129 130 //Quick exit if classes are different 131 if (!o.getClass().equals(this.getClass())) 132 return false; 133 134 PulsarSpecification other = (PulsarSpecification)o; 135 136 //NOTE: absence of ID field is intentional 137 138 return other.dispersion == this.dispersion && 139 other.pulsePeriod.equals(this.pulsePeriod) && 140 other.phaseBins.equals(this.phaseBins) && 141 other.phasePolynomials.equals(this.phasePolynomials); 142 } 143 144 /** Returns a hash code value for this specification. */ 145 @Override 146 public int hashCode() 147 { 148 //Taken from the Effective Java book by Joshua Bloch. 149 //The constants 17 & 37 are arbitrary & carry no meaning. 150 int result = 17; 151 152 result = 37 * result + new Double(dispersion).hashCode(); 153 result = 37 * result + pulsePeriod.hashCode(); 154 result = 37 * result + phaseBins.hashCode(); 155 result = 37 * result + phasePolynomials.hashCode(); 156 157 return result; 158 } 159 }