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(logger, sources) ⇒ Root

fetcher is a proc that inverts control to the client to retrieve metadata types



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

def initialize(logger, sources)
  @logger = logger
  @tree = nil
  @metadata_types = nil # TODO think up a better name ... containers?
  @sources = sources
end

Instance Attribute Details

#loggerObject (readonly)

Metadata can be unmarshalled from cache. @logger is not set during that process, constructor is not called. Client code must set it after unmarshalling.



54
55
56
# File 'lib/rets/metadata/root.rb', line 54

def logger
  @logger
end

#metadata_typesObject



115
116
117
118
119
120
121
122
123
124
125
# File 'lib/rets/metadata/root.rb', line 115

def 
  return @metadata_types if @metadata_types

  h = {}

  sources.each do |name, source|
    h[name.downcase.to_sym] = build_containers(Nokogiri.parse(source))
  end

  @metadata_types = h
end

#sourcesObject (readonly)

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



50
51
52
# File 'lib/rets/metadata/root.rb', line 50

def sources
  @sources
end

#treeObject



105
106
107
# File 'lib/rets/metadata/root.rb', line 105

def tree
  @tree ||= build_tree
end

Instance Method Details

#build_container(fragment) ⇒ Object



136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/rets/metadata/root.rb', line 136

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"

  if ::RUBY_VERSION < '1.9'
    container_class = Containers.const_defined?(container_name) ? Containers.const_get(container_name) : Containers::Container
  else
    container_class = Containers.const_defined?(container_name, true) ? Containers.const_get(container_name, true) : Containers::Container
  end
  container_class.new(fragment)
end

#build_containers(doc) ⇒ Object

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



129
130
131
132
133
134
# File 'lib/rets/metadata/root.rb', line 129

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



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/rets/metadata/root.rb', line 89

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

  resource_containers = [:resource]

  resource_containers.each do |resource_container|
    resource_container.rows.each do |resource_fragment|
      resource = Resource.build(resource_fragment, , @logger)
      #some mlses list resource types without an associated data, throw those away
      tree[resource.id.downcase] = resource if 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.

Returns:

  • (Boolean)


81
82
83
84
85
86
87
# File 'lib/rets/metadata/root.rb', line 81

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



73
74
75
# File 'lib/rets/metadata/root.rb', line 73

def date
  [:system].first.date
end

#marshal_dumpObject



65
66
67
# File 'lib/rets/metadata/root.rb', line 65

def marshal_dump
  sources
end


109
110
111
112
113
# File 'lib/rets/metadata/root.rb', line 109

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

#versionObject



69
70
71
# File 'lib/rets/metadata/root.rb', line 69

def version
  [:system].first.version
end