Class: Rets::Metadata::Root

Inherits:
Object
  • Object
show all
Defined in:
lib/rets/metadata/root.rb

Overview

It’s useful when dealing with the Rets standard to represent their relatively flat namespace of interweived components as a Tree. With a collection of resources at the top, and their various, classes, tables, lookups, and lookup types underneath.

It looks something like …

Resource
 |
Class
 |
 `-- Table
 |
 `-- Lookups
       |
       `-- LookupType

For our purposes it was helpful to denormalize some of the more deeply nested branches. In particular by relating Lookups to LookupTypes, and Tables to lookups with can simplify this diagram.

Resource
 |
Class
 |
 `-- Table
      |
      `-- Lookups

By associating Tables and lookups when we parse this structure. It allows us to seemlessly map Lookup values to their Long or Short value forms.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(client) ⇒ Root



60
61
62
63
64
65
# File 'lib/rets/metadata/root.rb', line 60

def initialize(client)
  @tree = nil
   = {} # TODO think up a better name ... containers?
  @sources = {}
  @client = client
end

Instance Attribute Details

#metadata_typesObject



137
138
139
140
141
142
143
# File 'lib/rets/metadata/root.rb', line 137

def 
  sources.each do |name, source|
    [name.downcase.to_sym] ||= (source)
  end

  
end

#sourcesObject

Sources are the raw xml documents fetched for each metadata type they are stored as a hash with the type names as their keys and the raw xml as the values



58
59
60
# File 'lib/rets/metadata/root.rb', line 58

def sources
  @sources
end

#treeObject



122
123
124
# File 'lib/rets/metadata/root.rb', line 122

def tree
  @tree ||= build_tree
end

Instance Method Details

#build_container(fragment) ⇒ Object



158
159
160
161
162
163
164
165
166
167
# File 'lib/rets/metadata/root.rb', line 158

def build_container(fragment)
  tag  = fragment.name             # METADATA-RESOURCE
  type = tag.sub(/^METADATA-/, "") # RESOURCE

  class_name = type.capitalize.gsub(/_(\w)/) { $1.upcase }
  container_name = "#{class_name}Container"

  container_class = Containers.constants.include?(container_name.to_sym) ? Containers.const_get(container_name) : Containers::Container
  container_class.new(fragment)
end

#build_containers(doc) ⇒ Object

Returns an array of container classes that represents the metadata stored in the document provided.



151
152
153
154
155
156
# File 'lib/rets/metadata/root.rb', line 151

def build_containers(doc)
  # find all tags that match /RETS/METADATA-*
  fragments = doc.xpath("/RETS/*[starts-with(name(), 'METADATA-')]")

  fragments.map { |fragment| build_container(fragment) }
end

#build_treeObject



107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/rets/metadata/root.rb', line 107

def build_tree
  tree = Hash.new { |h, k| h.key?(k.downcase) ? h[k.downcase] : nil }

  resource_containers = 

  resource_containers.each do |resource_container|
    resource_container.rows.each do |resource_fragment|
      resource = Resource.build(resource_fragment, )
      tree[resource.id.downcase] = resource
    end
  end

  tree
end

#current?(current_timestamp, current_version) ⇒ Boolean

Wether there exists a more up to date version of the metadata to fetch is dependant on either a timestamp indicating when the most recent version was published, or a version number. These values may or may not exist on any given rets server.



99
100
101
102
103
104
105
# File 'lib/rets/metadata/root.rb', line 99

def current?(current_timestamp, current_version)
  if !current_version.to_s.empty? && !version.to_s.empty?
    current_version == version 
  else
    current_timestamp ? current_timestamp == date : true
  end
end

#dateObject



91
92
93
# File 'lib/rets/metadata/root.rb', line 91

def date
  [:system].first.date
end

#fetch_source_by_type(type) ⇒ Object



75
76
77
# File 'lib/rets/metadata/root.rb', line 75

def fetch_source_by_type(type)
  self.sources[type] ||= @client.(type)
end

#fetch_sourcesObject



71
72
73
# File 'lib/rets/metadata/root.rb', line 71

def fetch_sources
  @fetch_sources ||= Hash[*.map {|type| [type, @client.(type)] }.flatten]
end

#for(metadata_key) ⇒ Object



132
133
134
135
# File 'lib/rets/metadata/root.rb', line 132

def for()
  raise "Unknown metatadata key '#{metadata_key}'" unless key = []
  [key] ||= (fetch_source_by_type(key))
end

#marshal_dumpObject



79
80
81
# File 'lib/rets/metadata/root.rb', line 79

def marshal_dump
  sources
end

#marshal_load(sources) ⇒ Object



83
84
85
# File 'lib/rets/metadata/root.rb', line 83

def marshal_load(sources)
  self.sources = sources
end

#metadata_type(source) ⇒ Object



145
146
147
# File 'lib/rets/metadata/root.rb', line 145

def (source)
  build_containers(Nokogiri.parse(source))
end


126
127
128
129
130
# File 'lib/rets/metadata/root.rb', line 126

def print_tree
  tree.each do |name, value|
    value.print_tree
  end
end

#versionObject



87
88
89
# File 'lib/rets/metadata/root.rb', line 87

def version
  [:system].first.version
end