voruby2-preview 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +339 -0
 - data/Rakefile.rb +113 -0
 - data/lib/symphony.rb +1 -0
 - data/lib/symphony/symphony.rb +247 -0
 - data/lib/voruby.rb +186 -0
 - data/lib/voruby/misc/libxml_ext.rb +121 -0
 - data/lib/voruby/misc/rexml_ext.rb +223 -0
 - data/lib/voruby/resolver/resolver.rb +12 -0
 - data/lib/voruby/resolver/sesame.rb +299 -0
 - data/lib/voruby/votable/1.0/votable.rb +1807 -0
 - data/lib/voruby/votable/1.1/votable.rb +2100 -0
 - data/lib/voruby/votable/votable.rb +308 -0
 - data/lib/voruby/wesix/wesix.rb +491 -0
 - data/test/voruby/resolver/sesame/test.rb +56 -0
 - data/test/voruby/votable/1.0/test.rb +714 -0
 - data/test/voruby/votable/1.0/votable.basic.xml +660 -0
 - data/test/voruby/votable/1.0/votable.html +86 -0
 - data/test/voruby/votable/1.0/votable.ns.xml +56 -0
 - data/test/voruby/votable/1.1/test.rb +785 -0
 - data/test/voruby/votable/1.1/votable.basic.xml +38 -0
 - data/test/voruby/votable/1.1/votable.html +86 -0
 - data/test/voruby/votable/1.1/votable.large.xml +168492 -0
 - data/test/voruby/votable/1.1/votable.ns.xml +56 -0
 - data/test/voruby/votable/test.rb +15 -0
 - data/test/voruby/wesix/test.rb +268 -0
 - data/test/voruby/wesix/testr.fits +28 -0
 - metadata +119 -0
 
| 
         @@ -0,0 +1,223 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'rexml/document'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module REXML
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Object
         
     | 
| 
      
 5 
     | 
    
         
            +
                
         
     | 
| 
      
 6 
     | 
    
         
            +
                class ReflectiveElementList
         
     | 
| 
      
 7 
     | 
    
         
            +
                  include Enumerable
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                  attr_reader :parent, :xpath
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                  def initialize(parent, *xpath)
         
     | 
| 
      
 12 
     | 
    
         
            +
                    @parent = parent
         
     | 
| 
      
 13 
     | 
    
         
            +
                    @xpath = xpath
         
     | 
| 
      
 14 
     | 
    
         
            +
                  end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                  def [](i)
         
     | 
| 
      
 17 
     | 
    
         
            +
                    path = "#{self.xpath.first}[#{i+1}]"
         
     | 
| 
      
 18 
     | 
    
         
            +
                    XPath.first(self.parent, path, self.xpath.last)
         
     | 
| 
      
 19 
     | 
    
         
            +
                  end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                  def []=(i, element)
         
     | 
| 
      
 22 
     | 
    
         
            +
                    el = self[i]
         
     | 
| 
      
 23 
     | 
    
         
            +
                    el ? el.replace_with(element) : self<<(element)
         
     | 
| 
      
 24 
     | 
    
         
            +
                  end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                  def <<(element)
         
     | 
| 
      
 27 
     | 
    
         
            +
                    path = "#{self.xpath.first}[last()]"
         
     | 
| 
      
 28 
     | 
    
         
            +
                    last = XPath.first(self.parent, path, self.xpath.last)
         
     | 
| 
      
 29 
     | 
    
         
            +
                    last ? last.next_sibling = element : self.parent << element
         
     | 
| 
      
 30 
     | 
    
         
            +
                  end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                  def last
         
     | 
| 
      
 33 
     | 
    
         
            +
                    path = "#{self.xpath.first}[last()]"
         
     | 
| 
      
 34 
     | 
    
         
            +
                    XPath.first(self.parent, path, self.xpath.last)
         
     | 
| 
      
 35 
     | 
    
         
            +
                  end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                  def first
         
     | 
| 
      
 38 
     | 
    
         
            +
                    path = "#{self.xpath.first}[1]"
         
     | 
| 
      
 39 
     | 
    
         
            +
                    XPath.first(self.parent, path, self.xpath.last)
         
     | 
| 
      
 40 
     | 
    
         
            +
                  end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                  def delete_at(i)
         
     | 
| 
      
 43 
     | 
    
         
            +
                    path = "#{self.xpath.first}[#{i+1}]"
         
     | 
| 
      
 44 
     | 
    
         
            +
                    XPath.first(self.parent, path, self.xpath.last).remove
         
     | 
| 
      
 45 
     | 
    
         
            +
                  end
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                  def size
         
     | 
| 
      
 48 
     | 
    
         
            +
                    path = "count(#{self.xpath.first})"
         
     | 
| 
      
 49 
     | 
    
         
            +
                    XPath.first(self.parent, path, self.xpath.last)
         
     | 
| 
      
 50 
     | 
    
         
            +
                  end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                  def to_a
         
     | 
| 
      
 53 
     | 
    
         
            +
                    XPath.match(self.parent, *self.xpath)
         
     | 
| 
      
 54 
     | 
    
         
            +
                  end
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                  def clear
         
     | 
| 
      
 57 
     | 
    
         
            +
                    self.each { |el| el.remove }
         
     | 
| 
      
 58 
     | 
    
         
            +
                  end
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                  def replace(ary)
         
     | 
| 
      
 61 
     | 
    
         
            +
                    self.clear
         
     | 
| 
      
 62 
     | 
    
         
            +
                    ary.each { |el| self<<(el) }
         
     | 
| 
      
 63 
     | 
    
         
            +
                  end
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                  def each
         
     | 
| 
      
 66 
     | 
    
         
            +
                    XPath.each(self.parent, *self.xpath) { |el| yield el }
         
     | 
| 
      
 67 
     | 
    
         
            +
                  end
         
     | 
| 
      
 68 
     | 
    
         
            +
                end
         
     | 
| 
      
 69 
     | 
    
         
            +
                
         
     | 
| 
      
 70 
     | 
    
         
            +
                class ClassifiedElementList < ReflectiveElementList
         
     | 
| 
      
 71 
     | 
    
         
            +
                  attr_reader :klass
         
     | 
| 
      
 72 
     | 
    
         
            +
                  
         
     | 
| 
      
 73 
     | 
    
         
            +
                  def initialize(klass, parent, *xpath)
         
     | 
| 
      
 74 
     | 
    
         
            +
                    @klass = klass
         
     | 
| 
      
 75 
     | 
    
         
            +
                    super(parent, *xpath)
         
     | 
| 
      
 76 
     | 
    
         
            +
                  end
         
     | 
| 
      
 77 
     | 
    
         
            +
                  
         
     | 
| 
      
 78 
     | 
    
         
            +
                  def [](i)
         
     | 
| 
      
 79 
     | 
    
         
            +
                    self.klass.new(super(i))
         
     | 
| 
      
 80 
     | 
    
         
            +
                  end
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
                  def []=(i, obj)
         
     | 
| 
      
 83 
     | 
    
         
            +
                    el = self[i]
         
     | 
| 
      
 84 
     | 
    
         
            +
                    el ? el.node.replace_with(obj.node) : self<<(obj.node)
         
     | 
| 
      
 85 
     | 
    
         
            +
                  end
         
     | 
| 
      
 86 
     | 
    
         
            +
                  
         
     | 
| 
      
 87 
     | 
    
         
            +
                  def <<(obj)
         
     | 
| 
      
 88 
     | 
    
         
            +
                    super(obj.node)
         
     | 
| 
      
 89 
     | 
    
         
            +
                  end
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
                  def last
         
     | 
| 
      
 92 
     | 
    
         
            +
                    self.klass.new(super())
         
     | 
| 
      
 93 
     | 
    
         
            +
                  end
         
     | 
| 
      
 94 
     | 
    
         
            +
             
     | 
| 
      
 95 
     | 
    
         
            +
                  def first
         
     | 
| 
      
 96 
     | 
    
         
            +
                    self.klass.new(super())
         
     | 
| 
      
 97 
     | 
    
         
            +
                  end
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
      
 99 
     | 
    
         
            +
                  def to_a
         
     | 
| 
      
 100 
     | 
    
         
            +
                    super().collect{ |el| self.klass.new(el) }
         
     | 
| 
      
 101 
     | 
    
         
            +
                  end
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
                  def replace(ary)
         
     | 
| 
      
 104 
     | 
    
         
            +
                    self.clear
         
     | 
| 
      
 105 
     | 
    
         
            +
                    ary.each { |obj| self<<(obj) }
         
     | 
| 
      
 106 
     | 
    
         
            +
                  end
         
     | 
| 
      
 107 
     | 
    
         
            +
             
     | 
| 
      
 108 
     | 
    
         
            +
                  def each
         
     | 
| 
      
 109 
     | 
    
         
            +
                    XPath.each(self.parent, *self.xpath) { |el| yield self.klass.new(el) }
         
     | 
| 
      
 110 
     | 
    
         
            +
                  end
         
     | 
| 
      
 111 
     | 
    
         
            +
                  
         
     | 
| 
      
 112 
     | 
    
         
            +
                  def clear
         
     | 
| 
      
 113 
     | 
    
         
            +
                    self.each { |el| el.node.remove }
         
     | 
| 
      
 114 
     | 
    
         
            +
                  end
         
     | 
| 
      
 115 
     | 
    
         
            +
                  
         
     | 
| 
      
 116 
     | 
    
         
            +
                  def ==(ary)
         
     | 
| 
      
 117 
     | 
    
         
            +
                    return false if self.size != ary.size
         
     | 
| 
      
 118 
     | 
    
         
            +
                    
         
     | 
| 
      
 119 
     | 
    
         
            +
                    self.each_with_index do |item, i|
         
     | 
| 
      
 120 
     | 
    
         
            +
                      return false if item != ary[i]
         
     | 
| 
      
 121 
     | 
    
         
            +
                    end
         
     | 
| 
      
 122 
     | 
    
         
            +
                    
         
     | 
| 
      
 123 
     | 
    
         
            +
                    return true
         
     | 
| 
      
 124 
     | 
    
         
            +
                  end
         
     | 
| 
      
 125 
     | 
    
         
            +
                end
         
     | 
| 
      
 126 
     | 
    
         
            +
                
         
     | 
| 
      
 127 
     | 
    
         
            +
                class Base
         
     | 
| 
      
 128 
     | 
    
         
            +
                  attr_reader :node, :xml_element_name
         
     | 
| 
      
 129 
     | 
    
         
            +
             
     | 
| 
      
 130 
     | 
    
         
            +
                  def self.xsi_namespace; 'http://www.w3.org/2001/XMLSchema-instance' end
         
     | 
| 
      
 131 
     | 
    
         
            +
                  def self.xsd_namespace; 'http://www.w3.org/2001/XMLSchema' end
         
     | 
| 
      
 132 
     | 
    
         
            +
                  def self.xml_type; self.class.to_s.split('::').last end
         
     | 
| 
      
 133 
     | 
    
         
            +
             
     | 
| 
      
 134 
     | 
    
         
            +
                  def initialize(defn=nil)
         
     | 
| 
      
 135 
     | 
    
         
            +
                    @node = case defn
         
     | 
| 
      
 136 
     | 
    
         
            +
                      when Document      then defn.root
         
     | 
| 
      
 137 
     | 
    
         
            +
                      when Element       then defn
         
     | 
| 
      
 138 
     | 
    
         
            +
                      when Hash          then Element.new(self.xml_element_name)
         
     | 
| 
      
 139 
     | 
    
         
            +
                      when NilClass      then Element.new(self.xml_element_name)
         
     | 
| 
      
 140 
     | 
    
         
            +
                      else
         
     | 
| 
      
 141 
     | 
    
         
            +
                        Document.new(defn).root
         
     | 
| 
      
 142 
     | 
    
         
            +
                    end
         
     | 
| 
      
 143 
     | 
    
         
            +
             
     | 
| 
      
 144 
     | 
    
         
            +
                    initialize_members(defn) if defn.is_a?(Hash)
         
     | 
| 
      
 145 
     | 
    
         
            +
                  end
         
     | 
| 
      
 146 
     | 
    
         
            +
             
     | 
| 
      
 147 
     | 
    
         
            +
                  def xml_element_name; self.class.to_s.split('::').last end
         
     | 
| 
      
 148 
     | 
    
         
            +
             
     | 
| 
      
 149 
     | 
    
         
            +
                  def find_namespace_by_href(href)
         
     | 
| 
      
 150 
     | 
    
         
            +
                    self.node.namespaces.find{ |prefix, uri| uri == href }
         
     | 
| 
      
 151 
     | 
    
         
            +
                  end
         
     | 
| 
      
 152 
     | 
    
         
            +
             
     | 
| 
      
 153 
     | 
    
         
            +
                  def get_attribute(name, ns=nil)
         
     | 
| 
      
 154 
     | 
    
         
            +
                    attribute = self.node.attributes.get_attribute_ns(ns, name)
         
     | 
| 
      
 155 
     | 
    
         
            +
                    attribute ? attribute.value : nil
         
     | 
| 
      
 156 
     | 
    
         
            +
                  end
         
     | 
| 
      
 157 
     | 
    
         
            +
             
     | 
| 
      
 158 
     | 
    
         
            +
                  def set_attribute(name, value, ns=nil)
         
     | 
| 
      
 159 
     | 
    
         
            +
                    self.node.attributes[attribute_xpath_for(name, ns)] = value.to_s
         
     | 
| 
      
 160 
     | 
    
         
            +
                  end
         
     | 
| 
      
 161 
     | 
    
         
            +
             
     | 
| 
      
 162 
     | 
    
         
            +
                  def get_element(name, ns=nil)
         
     | 
| 
      
 163 
     | 
    
         
            +
                    XPath.first(self.node, *element_xpath_for(name, ns))
         
     | 
| 
      
 164 
     | 
    
         
            +
                  end
         
     | 
| 
      
 165 
     | 
    
         
            +
             
     | 
| 
      
 166 
     | 
    
         
            +
                  def set_element(name, value, ns)
         
     | 
| 
      
 167 
     | 
    
         
            +
                    el = get_element(name, ns)
         
     | 
| 
      
 168 
     | 
    
         
            +
             
     | 
| 
      
 169 
     | 
    
         
            +
                    # The element doesn't exist...
         
     | 
| 
      
 170 
     | 
    
         
            +
                    if !el
         
     | 
| 
      
 171 
     | 
    
         
            +
                      el = REXML::Element.new(name)
         
     | 
| 
      
 172 
     | 
    
         
            +
                      @node << el # so insert it
         
     | 
| 
      
 173 
     | 
    
         
            +
                    end
         
     | 
| 
      
 174 
     | 
    
         
            +
                    
         
     | 
| 
      
 175 
     | 
    
         
            +
                    case value
         
     | 
| 
      
 176 
     | 
    
         
            +
                      when String               then el.text = value.to_s
         
     | 
| 
      
 177 
     | 
    
         
            +
                      when REXML::Element       then value.name = name; el.replace_with(value)
         
     | 
| 
      
 178 
     | 
    
         
            +
                    end
         
     | 
| 
      
 179 
     | 
    
         
            +
                    
         
     | 
| 
      
 180 
     | 
    
         
            +
                    el.add_namespace(ns) if !find_namespace_by_href(ns)
         
     | 
| 
      
 181 
     | 
    
         
            +
                  end
         
     | 
| 
      
 182 
     | 
    
         
            +
                  
         
     | 
| 
      
 183 
     | 
    
         
            +
                  def get_elements(name, ns=nil)
         
     | 
| 
      
 184 
     | 
    
         
            +
                    ReflectiveElementList.new(self.node, *element_xpath_for(name, ns))
         
     | 
| 
      
 185 
     | 
    
         
            +
                  end
         
     | 
| 
      
 186 
     | 
    
         
            +
                  
         
     | 
| 
      
 187 
     | 
    
         
            +
                  def set_elements(name, values, ns=nil)
         
     | 
| 
      
 188 
     | 
    
         
            +
                    get_elements(name, ns).replace(values)
         
     | 
| 
      
 189 
     | 
    
         
            +
                  end
         
     | 
| 
      
 190 
     | 
    
         
            +
             
     | 
| 
      
 191 
     | 
    
         
            +
                  def to_s
         
     | 
| 
      
 192 
     | 
    
         
            +
                    formatter = Formatters::Default.new
         
     | 
| 
      
 193 
     | 
    
         
            +
                    xml = ''
         
     | 
| 
      
 194 
     | 
    
         
            +
                    formatter.write(self.node, xml)
         
     | 
| 
      
 195 
     | 
    
         
            +
                    xml
         
     | 
| 
      
 196 
     | 
    
         
            +
                  end
         
     | 
| 
      
 197 
     | 
    
         
            +
             
     | 
| 
      
 198 
     | 
    
         
            +
                  protected
         
     | 
| 
      
 199 
     | 
    
         
            +
             
     | 
| 
      
 200 
     | 
    
         
            +
                  def attribute_xpath_for(name, ns=nil)
         
     | 
| 
      
 201 
     | 
    
         
            +
                    if ns
         
     | 
| 
      
 202 
     | 
    
         
            +
                      namespace = find_namespace_by_href(ns)
         
     | 
| 
      
 203 
     | 
    
         
            +
                      namespace ? "#{namespace.first}:#{name}" : name
         
     | 
| 
      
 204 
     | 
    
         
            +
                    else
         
     | 
| 
      
 205 
     | 
    
         
            +
                      name
         
     | 
| 
      
 206 
     | 
    
         
            +
                    end
         
     | 
| 
      
 207 
     | 
    
         
            +
                  end
         
     | 
| 
      
 208 
     | 
    
         
            +
             
     | 
| 
      
 209 
     | 
    
         
            +
                  def element_xpath_for(name, ns=nil)
         
     | 
| 
      
 210 
     | 
    
         
            +
                    ns ? ["x:#{name}", {'x' => ns}] : [name]
         
     | 
| 
      
 211 
     | 
    
         
            +
                  end
         
     | 
| 
      
 212 
     | 
    
         
            +
             
     | 
| 
      
 213 
     | 
    
         
            +
                  private
         
     | 
| 
      
 214 
     | 
    
         
            +
             
     | 
| 
      
 215 
     | 
    
         
            +
                  def initialize_members(args)
         
     | 
| 
      
 216 
     | 
    
         
            +
                    args.each do |name, value|
         
     | 
| 
      
 217 
     | 
    
         
            +
                      send("#{name}=", value)
         
     | 
| 
      
 218 
     | 
    
         
            +
                    end
         
     | 
| 
      
 219 
     | 
    
         
            +
                  end
         
     | 
| 
      
 220 
     | 
    
         
            +
                end
         
     | 
| 
      
 221 
     | 
    
         
            +
             
     | 
| 
      
 222 
     | 
    
         
            +
              end
         
     | 
| 
      
 223 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,12 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'soap/rpc/driver'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'ostruct'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            begin
         
     | 
| 
      
 5 
     | 
    
         
            +
              require 'rubygems'
         
     | 
| 
      
 6 
     | 
    
         
            +
            rescue LoadError; end
         
     | 
| 
      
 7 
     | 
    
         
            +
            require 'xml/libxml'
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            module VORuby
         
     | 
| 
      
 10 
     | 
    
         
            +
              # Name resolvers (i.e. the CDS's sesame[http://cdsweb.u-strasbg.fr/cdsws/name_resolver.gml] service)
         
     | 
| 
      
 11 
     | 
    
         
            +
              module Resolver; end
         
     | 
| 
      
 12 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,299 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'voruby/resolver/resolver'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module VORuby
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Resolver
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                # Sesame[http://cdsweb.u-strasbg.fr/cdsws/name_resolver.gml] is the standard
         
     | 
| 
      
 7 
     | 
    
         
            +
                # name resolution service of the virtual observatory.  There are a couple of
         
     | 
| 
      
 8 
     | 
    
         
            +
                # ways to use it, but typically one wants the RA and Dec of the target:
         
     | 
| 
      
 9 
     | 
    
         
            +
                #
         
     | 
| 
      
 10 
     | 
    
         
            +
                #   ra, dec = Sesame.resolve_position('m51')  # => the primary J2000 RA and Dec of M 51 in degrees
         
     | 
| 
      
 11 
     | 
    
         
            +
                #   sesame = Sesame.resolve('m51')            # => a Sesame object with in-depth information about the name resolution
         
     | 
| 
      
 12 
     | 
    
         
            +
                #   puts sesame.jradeg, sesame.jdedeg
         
     | 
| 
      
 13 
     | 
    
         
            +
                #
         
     | 
| 
      
 14 
     | 
    
         
            +
                # It's also possible to change the location of the web service used (to a mirror, say) and to specify
         
     | 
| 
      
 15 
     | 
    
         
            +
                # which resolvers sesame should aggregate over (by default Simbad is used).     
         
     | 
| 
      
 16 
     | 
    
         
            +
                class Sesame
         
     | 
| 
      
 17 
     | 
    
         
            +
                  # The result of the name resolution as an XML::Node.
         
     | 
| 
      
 18 
     | 
    
         
            +
                  # Not available until after #resolve has been called.
         
     | 
| 
      
 19 
     | 
    
         
            +
                  attr_reader :xml
         
     | 
| 
      
 20 
     | 
    
         
            +
                  
         
     | 
| 
      
 21 
     | 
    
         
            +
                  # Whether to try to determine if the sesame service
         
     | 
| 
      
 22 
     | 
    
         
            +
                  # is available or not before each name resolution.
         
     | 
| 
      
 23 
     | 
    
         
            +
                  # The default is false.
         
     | 
| 
      
 24 
     | 
    
         
            +
                  attr_accessor :check_availability
         
     | 
| 
      
 25 
     | 
    
         
            +
                  
         
     | 
| 
      
 26 
     | 
    
         
            +
                  # Resolve the <tt>target</tt>.
         
     | 
| 
      
 27 
     | 
    
         
            +
                  # The optional <tt>against</tt> may be one of <tt>:simbad</tt>, <tt>:ned</tt>, <tt>:vizier</tt> or <tt>:all</tt>.
         
     | 
| 
      
 28 
     | 
    
         
            +
                  # Simbad is the most reliable, so that's the default.
         
     | 
| 
      
 29 
     | 
    
         
            +
                  # <tt>options</tt> is a hash with the following keys:
         
     | 
| 
      
 30 
     | 
    
         
            +
                  #
         
     | 
| 
      
 31 
     | 
    
         
            +
                  # [<tt>:end_point</tt>]     the sesame SOAP endpoint to use (default: http://cdsws.u-strasbg.fr/axis/services/Sesame)
         
     | 
| 
      
 32 
     | 
    
         
            +
                  # [<tt>:check_availability</tt>] whether to try to determine if the sesame service is available or not before each name resolution (default: false)
         
     | 
| 
      
 33 
     | 
    
         
            +
                  #
         
     | 
| 
      
 34 
     | 
    
         
            +
                  # Returns a Sesame object, and is exactly equivalent to:
         
     | 
| 
      
 35 
     | 
    
         
            +
                  #
         
     | 
| 
      
 36 
     | 
    
         
            +
                  #   sesame = Sesame.new
         
     | 
| 
      
 37 
     | 
    
         
            +
                  #   sesame.resolve
         
     | 
| 
      
 38 
     | 
    
         
            +
                  def self.resolve(target, against=:simbad, options={})
         
     | 
| 
      
 39 
     | 
    
         
            +
                    sesame = Sesame.new(options)
         
     | 
| 
      
 40 
     | 
    
         
            +
                    sesame.resolve(target, against)
         
     | 
| 
      
 41 
     | 
    
         
            +
                    
         
     | 
| 
      
 42 
     | 
    
         
            +
                    sesame
         
     | 
| 
      
 43 
     | 
    
         
            +
                  end
         
     | 
| 
      
 44 
     | 
    
         
            +
                  
         
     | 
| 
      
 45 
     | 
    
         
            +
                  # Resolve the <tt>target</tt>, but return only the primary position and no
         
     | 
| 
      
 46 
     | 
    
         
            +
                  # other information.  The parameters are as for #resolve with the addition
         
     | 
| 
      
 47 
     | 
    
         
            +
                  # of <tt>as</tt> which may be <tt>:degrees</tt> (default) or <tt>:sexigesimal</tt>.
         
     | 
| 
      
 48 
     | 
    
         
            +
                  # In the former case, an array of floats (ra, dec) is returned while in the latter
         
     | 
| 
      
 49 
     | 
    
         
            +
                  # an array of strings.
         
     | 
| 
      
 50 
     | 
    
         
            +
                  #
         
     | 
| 
      
 51 
     | 
    
         
            +
                  #   Sesame.resolve_position('m51')                # => [202.4682083, 47.1946667]
         
     | 
| 
      
 52 
     | 
    
         
            +
                  #   Sesame.resolve_position('m51', :sexigesimal)  # => ['13:29:52.36', '+47:11:40.8']
         
     | 
| 
      
 53 
     | 
    
         
            +
                  def self.resolve_position(target, against=:simbad, as=:degrees, options={})
         
     | 
| 
      
 54 
     | 
    
         
            +
                    self.resolve(target, against, options).position(as)
         
     | 
| 
      
 55 
     | 
    
         
            +
                  end
         
     | 
| 
      
 56 
     | 
    
         
            +
                  
         
     | 
| 
      
 57 
     | 
    
         
            +
                  # Create a new sesame name resolver.
         
     | 
| 
      
 58 
     | 
    
         
            +
                  # <tt>options</tt> is a hash with the following keys:
         
     | 
| 
      
 59 
     | 
    
         
            +
                  #
         
     | 
| 
      
 60 
     | 
    
         
            +
                  # [<tt>:end_point</tt>]     the sesame SOAP endpoint to use (default: http://cdsws.u-strasbg.fr/axis/services/Sesame)
         
     | 
| 
      
 61 
     | 
    
         
            +
                  # [<tt>:check_availability</tt>] whether to try to determine if the sesame service is available or not before each name resolution (default: false)
         
     | 
| 
      
 62 
     | 
    
         
            +
                  #
         
     | 
| 
      
 63 
     | 
    
         
            +
                  #   sesame = Sesame.new(
         
     | 
| 
      
 64 
     | 
    
         
            +
                  #     :end_point => 'http://vizier.nao.ac.jp:8080/axis/services/Sesame' # maybe we're in Japan...
         
     | 
| 
      
 65 
     | 
    
         
            +
                  #     :check_availability => true # and we want to always check the availability of the service
         
     | 
| 
      
 66 
     | 
    
         
            +
                  #   )
         
     | 
| 
      
 67 
     | 
    
         
            +
                  def initialize(options={})        
         
     | 
| 
      
 68 
     | 
    
         
            +
                    self.end_point = options[:end_point] || 'http://cdsws.u-strasbg.fr/axis/services/Sesame'
         
     | 
| 
      
 69 
     | 
    
         
            +
                    self.check_availability = options[:check_availability] || false
         
     | 
| 
      
 70 
     | 
    
         
            +
                  end
         
     | 
| 
      
 71 
     | 
    
         
            +
                  
         
     | 
| 
      
 72 
     | 
    
         
            +
                  # The "end-point" or location of the name resolver's webservice.
         
     | 
| 
      
 73 
     | 
    
         
            +
                  def end_point
         
     | 
| 
      
 74 
     | 
    
         
            +
                    @end_point
         
     | 
| 
      
 75 
     | 
    
         
            +
                  end
         
     | 
| 
      
 76 
     | 
    
         
            +
                  
         
     | 
| 
      
 77 
     | 
    
         
            +
                  # Set the end-point or location of the name resolver's webservice.
         
     | 
| 
      
 78 
     | 
    
         
            +
                  #   sesame.end_point = 'http://vizier.nao.ac.jp:8080/axis/services/Sesame'
         
     | 
| 
      
 79 
     | 
    
         
            +
                  def end_point=(epoint)
         
     | 
| 
      
 80 
     | 
    
         
            +
                    @end_point = epoint
         
     | 
| 
      
 81 
     | 
    
         
            +
                    
         
     | 
| 
      
 82 
     | 
    
         
            +
                    # We don't use the WSDL for this because ruby doesn't deal well with method overloading.
         
     | 
| 
      
 83 
     | 
    
         
            +
                    @resolver = SOAP::RPC::Driver.new(@end_point)
         
     | 
| 
      
 84 
     | 
    
         
            +
                    @resolver.add_rpc_method('sesame', 'name', 'resultType', 'all', 'service')
         
     | 
| 
      
 85 
     | 
    
         
            +
                    @resolver.add_rpc_method('getAvailability')
         
     | 
| 
      
 86 
     | 
    
         
            +
                  end
         
     | 
| 
      
 87 
     | 
    
         
            +
                
         
     | 
| 
      
 88 
     | 
    
         
            +
                  # Retrieve whatever information we can about the position of the specified <tt>target</tt>.
         
     | 
| 
      
 89 
     | 
    
         
            +
                  # The optional <tt>against</tt> may be one of <tt>:simbad</tt>, <tt>:ned</tt>, <tt>:vizier</tt> or <tt>:all</tt>.
         
     | 
| 
      
 90 
     | 
    
         
            +
                  # Simbad is the most reliable, so that's the default.
         
     | 
| 
      
 91 
     | 
    
         
            +
                  #
         
     | 
| 
      
 92 
     | 
    
         
            +
                  #   sesame.resolve('m51', :all)  # use all the resources at sesame's disposal
         
     | 
| 
      
 93 
     | 
    
         
            +
                  #
         
     | 
| 
      
 94 
     | 
    
         
            +
                  # This method may throw an exception if:
         
     | 
| 
      
 95 
     | 
    
         
            +
                  #
         
     | 
| 
      
 96 
     | 
    
         
            +
                  # * #end_point doesn't exist
         
     | 
| 
      
 97 
     | 
    
         
            +
                  # * you have set #check_availabilty to true and the resolver has indicated it is not available
         
     | 
| 
      
 98 
     | 
    
         
            +
                  def resolve(target, against=:simbad)
         
     | 
| 
      
 99 
     | 
    
         
            +
                    raise "Sesame at #{self.end_point} is not currently available" if self.check_availability and !self.available?
         
     | 
| 
      
 100 
     | 
    
         
            +
                    
         
     | 
| 
      
 101 
     | 
    
         
            +
                    parser = XML::Parser.new
         
     | 
| 
      
 102 
     | 
    
         
            +
                    parser.string = 
         
     | 
| 
      
 103 
     | 
    
         
            +
                      @resolver.sesame(target.to_s, 'x', true, service_designation(against))
         
     | 
| 
      
 104 
     | 
    
         
            +
                    @xml = parser.parse.root
         
     | 
| 
      
 105 
     | 
    
         
            +
                  end
         
     | 
| 
      
 106 
     | 
    
         
            +
                  
         
     | 
| 
      
 107 
     | 
    
         
            +
                  # The target you requested name resolution on.
         
     | 
| 
      
 108 
     | 
    
         
            +
                  def target
         
     | 
| 
      
 109 
     | 
    
         
            +
                    self.xml.find_first('target').content
         
     | 
| 
      
 110 
     | 
    
         
            +
                  end
         
     | 
| 
      
 111 
     | 
    
         
            +
                  
         
     | 
| 
      
 112 
     | 
    
         
            +
                  # Any information that sesame sent back with your results.
         
     | 
| 
      
 113 
     | 
    
         
            +
                  def infos
         
     | 
| 
      
 114 
     | 
    
         
            +
                    self.xml.find('INFO').collect{ |i| i.content }
         
     | 
| 
      
 115 
     | 
    
         
            +
                  end
         
     | 
| 
      
 116 
     | 
    
         
            +
                  
         
     | 
| 
      
 117 
     | 
    
         
            +
                  # Any errors reported by sesame sent back with your results.
         
     | 
| 
      
 118 
     | 
    
         
            +
                  def errors
         
     | 
| 
      
 119 
     | 
    
         
            +
                    self.xml.find('ERROR').collect{ |e| e.content }
         
     | 
| 
      
 120 
     | 
    
         
            +
                  end
         
     | 
| 
      
 121 
     | 
    
         
            +
                  
         
     | 
| 
      
 122 
     | 
    
         
            +
                  # Sesame actually aggregates results from a number of sources.
         
     | 
| 
      
 123 
     | 
    
         
            +
                  # Returns an array of ResolvedInfo objects, one for each resource
         
     | 
| 
      
 124 
     | 
    
         
            +
                  # polled (i.e. some combination of Simbad, VizieR and Ned).
         
     | 
| 
      
 125 
     | 
    
         
            +
                  def resolvers
         
     | 
| 
      
 126 
     | 
    
         
            +
                    self.xml.find('Resolver').collect{ |r| ResolvedInfo.new(r) }
         
     | 
| 
      
 127 
     | 
    
         
            +
                  end
         
     | 
| 
      
 128 
     | 
    
         
            +
                  
         
     | 
| 
      
 129 
     | 
    
         
            +
                  # A shortcut for ResolvedInfo#position.
         
     | 
| 
      
 130 
     | 
    
         
            +
                  # Assumes the first resolver is the one you're most
         
     | 
| 
      
 131 
     | 
    
         
            +
                  # interested in.
         
     | 
| 
      
 132 
     | 
    
         
            +
                  def position(as=:degrees)
         
     | 
| 
      
 133 
     | 
    
         
            +
                    self.resolvers.first.position(as)
         
     | 
| 
      
 134 
     | 
    
         
            +
                  end
         
     | 
| 
      
 135 
     | 
    
         
            +
                  
         
     | 
| 
      
 136 
     | 
    
         
            +
                  # Checks to see whether sesame is available.
         
     | 
| 
      
 137 
     | 
    
         
            +
                  # At this point it's assumed the service is present at
         
     | 
| 
      
 138 
     | 
    
         
            +
                  # the location specified by #end_point.  This just checks
         
     | 
| 
      
 139 
     | 
    
         
            +
                  # to see whether sesame reports itself as available or not.
         
     | 
| 
      
 140 
     | 
    
         
            +
                  def available?
         
     | 
| 
      
 141 
     | 
    
         
            +
                    # We don't use an XML parser here because (as of 2007-01-04)
         
     | 
| 
      
 142 
     | 
    
         
            +
                    # the validTo tag isn't closed properly, rendering the XML
         
     | 
| 
      
 143 
     | 
    
         
            +
                    # malformed.
         
     | 
| 
      
 144 
     | 
    
         
            +
                    result = @resolver.getAvailability
         
     | 
| 
      
 145 
     | 
    
         
            +
                    result.match(/<available>\s*(.*)\s*<\/available>/)[1] == 'true'
         
     | 
| 
      
 146 
     | 
    
         
            +
                  end
         
     | 
| 
      
 147 
     | 
    
         
            +
                
         
     | 
| 
      
 148 
     | 
    
         
            +
                  private
         
     | 
| 
      
 149 
     | 
    
         
            +
                
         
     | 
| 
      
 150 
     | 
    
         
            +
                  def service_designation(svc)
         
     | 
| 
      
 151 
     | 
    
         
            +
                    {
         
     | 
| 
      
 152 
     | 
    
         
            +
                      :simbad => 'S',
         
     | 
| 
      
 153 
     | 
    
         
            +
                      :ned => 'N',
         
     | 
| 
      
 154 
     | 
    
         
            +
                      :vizier => 'V',
         
     | 
| 
      
 155 
     | 
    
         
            +
                      :all => 'A'
         
     | 
| 
      
 156 
     | 
    
         
            +
                    }[svc] || svc
         
     | 
| 
      
 157 
     | 
    
         
            +
                  end
         
     | 
| 
      
 158 
     | 
    
         
            +
                  
         
     | 
| 
      
 159 
     | 
    
         
            +
                  # A simple object that represents a name resolution attempt.
         
     | 
| 
      
 160 
     | 
    
         
            +
                  class ResolvedInfo
         
     | 
| 
      
 161 
     | 
    
         
            +
                    attr_reader :xml
         
     | 
| 
      
 162 
     | 
    
         
            +
                    
         
     | 
| 
      
 163 
     | 
    
         
            +
                    # Create a ResolvedInfo object from an appropriate
         
     | 
| 
      
 164 
     | 
    
         
            +
                    # XML::Node (one that represents a <Resolver> XML element).
         
     | 
| 
      
 165 
     | 
    
         
            +
                    def initialize(xml)
         
     | 
| 
      
 166 
     | 
    
         
            +
                      @xml = xml
         
     | 
| 
      
 167 
     | 
    
         
            +
                    end
         
     | 
| 
      
 168 
     | 
    
         
            +
                    
         
     | 
| 
      
 169 
     | 
    
         
            +
                    # The name of the resolver (i.e. Simbad).
         
     | 
| 
      
 170 
     | 
    
         
            +
                    def name
         
     | 
| 
      
 171 
     | 
    
         
            +
                      self.xml['name']
         
     | 
| 
      
 172 
     | 
    
         
            +
                    end
         
     | 
| 
      
 173 
     | 
    
         
            +
                    
         
     | 
| 
      
 174 
     | 
    
         
            +
                    def code
         
     | 
| 
      
 175 
     | 
    
         
            +
                      self.xml['code']
         
     | 
| 
      
 176 
     | 
    
         
            +
                    end
         
     | 
| 
      
 177 
     | 
    
         
            +
                    
         
     | 
| 
      
 178 
     | 
    
         
            +
                    # Any info accompanying the name resolution.
         
     | 
| 
      
 179 
     | 
    
         
            +
                    # Returns an array of strings.
         
     | 
| 
      
 180 
     | 
    
         
            +
                    def infos
         
     | 
| 
      
 181 
     | 
    
         
            +
                      self.xml.find('INFO').collect{ |i| i.content }
         
     | 
| 
      
 182 
     | 
    
         
            +
                    end
         
     | 
| 
      
 183 
     | 
    
         
            +
                    
         
     | 
| 
      
 184 
     | 
    
         
            +
                    # Any errors accompanying the name resolution.
         
     | 
| 
      
 185 
     | 
    
         
            +
                    # Returns an array of string.
         
     | 
| 
      
 186 
     | 
    
         
            +
                    def errors
         
     | 
| 
      
 187 
     | 
    
         
            +
                      self.xml.find('ERROR').collect{ |e| e.content }
         
     | 
| 
      
 188 
     | 
    
         
            +
                    end
         
     | 
| 
      
 189 
     | 
    
         
            +
                    
         
     | 
| 
      
 190 
     | 
    
         
            +
                    # The classification of the object (i.e. Seyfert_2 or QSO).
         
     | 
| 
      
 191 
     | 
    
         
            +
                    def otype
         
     | 
| 
      
 192 
     | 
    
         
            +
                      self.xml.find_first('otype').content if self.xml.find_first('otype')
         
     | 
| 
      
 193 
     | 
    
         
            +
                    end
         
     | 
| 
      
 194 
     | 
    
         
            +
                    
         
     | 
| 
      
 195 
     | 
    
         
            +
                    # The J2000 coordinates of the object in sexigesimal format (i.e. '13:29:52.36 +47:11:40.8')
         
     | 
| 
      
 196 
     | 
    
         
            +
                    def jpos
         
     | 
| 
      
 197 
     | 
    
         
            +
                      self.xml.find_first('jpos').content if self.xml.find_first('jpos')
         
     | 
| 
      
 198 
     | 
    
         
            +
                    end
         
     | 
| 
      
 199 
     | 
    
         
            +
                    
         
     | 
| 
      
 200 
     | 
    
         
            +
                    # The J2000 right ascension of the object in decimal degrees.
         
     | 
| 
      
 201 
     | 
    
         
            +
                    def jradeg
         
     | 
| 
      
 202 
     | 
    
         
            +
                      self.xml.find_first('jradeg').content.to_f if self.xml.find_first('jradeg')
         
     | 
| 
      
 203 
     | 
    
         
            +
                    end
         
     | 
| 
      
 204 
     | 
    
         
            +
                    
         
     | 
| 
      
 205 
     | 
    
         
            +
                    # The J2000 declination of the object in decimal degrees.
         
     | 
| 
      
 206 
     | 
    
         
            +
                    def jdedeg
         
     | 
| 
      
 207 
     | 
    
         
            +
                      self.xml.find_first('jdedeg').content.to_f if self.xml.find_first('jdedeg')
         
     | 
| 
      
 208 
     | 
    
         
            +
                    end
         
     | 
| 
      
 209 
     | 
    
         
            +
                    
         
     | 
| 
      
 210 
     | 
    
         
            +
                    # A bibcode that corresponds to the publication in which the position
         
     | 
| 
      
 211 
     | 
    
         
            +
                    # of the object was determined.
         
     | 
| 
      
 212 
     | 
    
         
            +
                    def ref_pos
         
     | 
| 
      
 213 
     | 
    
         
            +
                      self.xml.find_first('refPos').content if self.xml.find_first('refPos')
         
     | 
| 
      
 214 
     | 
    
         
            +
                    end
         
     | 
| 
      
 215 
     | 
    
         
            +
                    
         
     | 
| 
      
 216 
     | 
    
         
            +
                    # The error of the right ascension in milliarcseconds.
         
     | 
| 
      
 217 
     | 
    
         
            +
                    def err_ra_mas
         
     | 
| 
      
 218 
     | 
    
         
            +
                      self.xml.find_first('errRAmas').content.to_f if self.xml.find_first('errRAmas')
         
     | 
| 
      
 219 
     | 
    
         
            +
                    end
         
     | 
| 
      
 220 
     | 
    
         
            +
                    
         
     | 
| 
      
 221 
     | 
    
         
            +
                    # The error of the declination in milliarcseconds.
         
     | 
| 
      
 222 
     | 
    
         
            +
                    def err_de_mas
         
     | 
| 
      
 223 
     | 
    
         
            +
                      self.xml.find_first('errDEmas').content.to_f if self.xml.find_first('errDEmas')
         
     | 
| 
      
 224 
     | 
    
         
            +
                    end
         
     | 
| 
      
 225 
     | 
    
         
            +
                    
         
     | 
| 
      
 226 
     | 
    
         
            +
                    # The redshift of the object.
         
     | 
| 
      
 227 
     | 
    
         
            +
                    def z
         
     | 
| 
      
 228 
     | 
    
         
            +
                      self.xml.find_first('z').content.to_f if self.xml.find_first('z')
         
     | 
| 
      
 229 
     | 
    
         
            +
                    end
         
     | 
| 
      
 230 
     | 
    
         
            +
                    
         
     | 
| 
      
 231 
     | 
    
         
            +
                    # The error in the redshift of the object.
         
     | 
| 
      
 232 
     | 
    
         
            +
                    def errz
         
     | 
| 
      
 233 
     | 
    
         
            +
                      self.xml.find_first('errz').content.to_i if self.xml.find_first('errz')
         
     | 
| 
      
 234 
     | 
    
         
            +
                    end
         
     | 
| 
      
 235 
     | 
    
         
            +
                    
         
     | 
| 
      
 236 
     | 
    
         
            +
                    # A bibcode that corresponds to the publication in which the redshift
         
     | 
| 
      
 237 
     | 
    
         
            +
                    # of the object was determined.
         
     | 
| 
      
 238 
     | 
    
         
            +
                    def refz
         
     | 
| 
      
 239 
     | 
    
         
            +
                      self.xml.find_first('refz').content if self.xml.find_first('refz')
         
     | 
| 
      
 240 
     | 
    
         
            +
                    end
         
     | 
| 
      
 241 
     | 
    
         
            +
                    
         
     | 
| 
      
 242 
     | 
    
         
            +
                    # The velocity of the object in km/s.
         
     | 
| 
      
 243 
     | 
    
         
            +
                    def vel
         
     | 
| 
      
 244 
     | 
    
         
            +
                      self.xml.find_first('Vel').content.to_f if self.xml.find_first('Vel')
         
     | 
| 
      
 245 
     | 
    
         
            +
                    end
         
     | 
| 
      
 246 
     | 
    
         
            +
                    
         
     | 
| 
      
 247 
     | 
    
         
            +
                    # The error in the velocity of the object in km/s.
         
     | 
| 
      
 248 
     | 
    
         
            +
                    def err_vel
         
     | 
| 
      
 249 
     | 
    
         
            +
                      self.xml.find_first('errVel').content.to_if if self.xml.find_first('errVel')
         
     | 
| 
      
 250 
     | 
    
         
            +
                    end
         
     | 
| 
      
 251 
     | 
    
         
            +
                    
         
     | 
| 
      
 252 
     | 
    
         
            +
                    # A bibcode that corresponds to the publication in which the velocity
         
     | 
| 
      
 253 
     | 
    
         
            +
                    # of the object was determined.
         
     | 
| 
      
 254 
     | 
    
         
            +
                    def ref_vel
         
     | 
| 
      
 255 
     | 
    
         
            +
                      self.xml.find_first('refVel').content if self.xml.find_first('refVel')
         
     | 
| 
      
 256 
     | 
    
         
            +
                    end
         
     | 
| 
      
 257 
     | 
    
         
            +
                    
         
     | 
| 
      
 258 
     | 
    
         
            +
                    # The morphological type of the object (i.e. Sc).
         
     | 
| 
      
 259 
     | 
    
         
            +
                    def mtype
         
     | 
| 
      
 260 
     | 
    
         
            +
                      self.xml.find_first('MType').content if self.xml.find_first('MType')
         
     | 
| 
      
 261 
     | 
    
         
            +
                    end
         
     | 
| 
      
 262 
     | 
    
         
            +
                    
         
     | 
| 
      
 263 
     | 
    
         
            +
                    # The spectral type of the object (i.e. A10)
         
     | 
| 
      
 264 
     | 
    
         
            +
                    def sptype
         
     | 
| 
      
 265 
     | 
    
         
            +
                      self.xml.find_first('spType').content if self.xml.find_first('spType')
         
     | 
| 
      
 266 
     | 
    
         
            +
                    end
         
     | 
| 
      
 267 
     | 
    
         
            +
                    
         
     | 
| 
      
 268 
     | 
    
         
            +
                    # The canonical name of the object.
         
     | 
| 
      
 269 
     | 
    
         
            +
                    def oname
         
     | 
| 
      
 270 
     | 
    
         
            +
                      self.xml.find_first('oname').content if self.xml.find_first('oname')
         
     | 
| 
      
 271 
     | 
    
         
            +
                    end
         
     | 
| 
      
 272 
     | 
    
         
            +
                    
         
     | 
| 
      
 273 
     | 
    
         
            +
                    # The number of references to this object.
         
     | 
| 
      
 274 
     | 
    
         
            +
                    def nrefs
         
     | 
| 
      
 275 
     | 
    
         
            +
                      self.xml.find_first('nrefs').content.to_i if self.xml.find_first('nrefs')
         
     | 
| 
      
 276 
     | 
    
         
            +
                    end
         
     | 
| 
      
 277 
     | 
    
         
            +
                    
         
     | 
| 
      
 278 
     | 
    
         
            +
                    # A list of aliases for the object.
         
     | 
| 
      
 279 
     | 
    
         
            +
                    # Returns a list of strings.
         
     | 
| 
      
 280 
     | 
    
         
            +
                    def aliases
         
     | 
| 
      
 281 
     | 
    
         
            +
                      self.xml.find('alias').collect{ |a| a.content }
         
     | 
| 
      
 282 
     | 
    
         
            +
                    end
         
     | 
| 
      
 283 
     | 
    
         
            +
                    
         
     | 
| 
      
 284 
     | 
    
         
            +
                    # The J2000 position of the object in degrees or sexigesimal format.
         
     | 
| 
      
 285 
     | 
    
         
            +
                    #   info.position(:degrees)     # => [202.4682083, 47.1946667]
         
     | 
| 
      
 286 
     | 
    
         
            +
                    #   info.position(:sexigesimal) # => ['13:29:52.36', '+47:11:40.8']
         
     | 
| 
      
 287 
     | 
    
         
            +
                    def position(as=:degrees)
         
     | 
| 
      
 288 
     | 
    
         
            +
                      case as
         
     | 
| 
      
 289 
     | 
    
         
            +
                      when :sexigesimal        then (self.jpos || '').split(/\s+/)
         
     | 
| 
      
 290 
     | 
    
         
            +
                      else
         
     | 
| 
      
 291 
     | 
    
         
            +
                        [self.jradeg, self.jdedeg]
         
     | 
| 
      
 292 
     | 
    
         
            +
                      end
         
     | 
| 
      
 293 
     | 
    
         
            +
                    end
         
     | 
| 
      
 294 
     | 
    
         
            +
                  end
         
     | 
| 
      
 295 
     | 
    
         
            +
                  
         
     | 
| 
      
 296 
     | 
    
         
            +
                end
         
     | 
| 
      
 297 
     | 
    
         
            +
                  
         
     | 
| 
      
 298 
     | 
    
         
            +
              end
         
     | 
| 
      
 299 
     | 
    
         
            +
            end
         
     |