Class: OData::Service

Inherits:
Object
  • Object
show all
Defined in:
lib/odata/service.rb

Overview

Encapsulates the basic details and functionality needed to interact with an OData service.

Constant Summary collapse

HTTP_TIMEOUT =
20
METADATA_TIMEOUTS =
[20, 60]

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(service_url, options = {}) ⇒ OData::Service

Opens the service based on the requested URL and adds the service to Registry

Parameters:

  • service_url (String)

    the URL to the desired OData service

  • options (Hash) (defaults to: {})

    options to pass to the service


20
21
22
23
24
25
# File 'lib/odata/service.rb', line 20

def initialize(service_url, options = {})
  @service_url = service_url
  @options = default_options.merge(options)
  OData::ServiceRegistry.add(self)
  self
end

Instance Attribute Details

#optionsObject (readonly)

Options to pass around


8
9
10
# File 'lib/odata/service.rb', line 8

def options
  @options
end

#service_urlObject (readonly)

The OData Service's URL


6
7
8
# File 'lib/odata/service.rb', line 6

def service_url
  @service_url
end

Class Method Details

.open(service_url, options = {}) ⇒ OData::Service

Opens the service based on the requested URL and adds the service to Registry

Parameters:

  • service_url (String)

    the URL to the desired OData service

  • options (Hash) (defaults to: {})

    options to pass to the service

Returns:


33
34
35
# File 'lib/odata/service.rb', line 33

def self.open(service_url, options = {})
  Service.new(service_url, options)
end

Instance Method Details

#[](entity_set_name) ⇒ OData::EntitySet

Retrieves the EntitySet associated with a specific EntityType by name

Parameters:

  • entity_set_name (to_s)

    the name of the EntitySet desired

Returns:

Raises:

  • (ArgumentError)

108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/odata/service.rb', line 108

def [](entity_set_name)
  xpath_query = "//EntityContainer/EntitySet[@Name='#{entity_set_name}']"
  entity_set_node = .xpath(xpath_query).first
  raise ArgumentError, "Unknown Entity Set: #{entity_set_name}" if entity_set_node.nil?
  container_name = entity_set_node.parent.attributes['Name'].value
  entity_type_name = entity_set_node.attributes['EntityType'].value.gsub(/#{namespace}\./, '')
  OData::EntitySet.new(name: entity_set_name,
                       namespace: namespace,
                       type: entity_type_name.to_s,
                       service_name: name,
                       container: container_name)
end

#associationsHash<OData::Association>

Returns the associations defined by the service

Returns:


65
66
67
68
69
70
71
72
# File 'lib/odata/service.rb', line 65

def associations
  @associations ||= Hash[.xpath('//Association').collect do |association_definition|
    [
        association_definition.attributes['Name'].value,
        build_association(association_definition)
    ]
  end]
end

#complex_typesObject

Returns a list of ComplexTypes used by the service


59
60
61
# File 'lib/odata/service.rb', line 59

def complex_types
  @complex_types ||= .xpath('//ComplexType').collect {|entity| entity.attributes['Name'].value}
end

#entity_setsObject

Returns a hash of EntitySet names keyed to their respective EntityType name


49
50
51
52
53
54
55
56
# File 'lib/odata/service.rb', line 49

def entity_sets
  @entity_sets ||= Hash[.xpath('//EntityContainer/EntitySet').collect {|entity|
    [
      entity.attributes['EntityType'].value.gsub("#{namespace}.", ''),
      entity.attributes['Name'].value
    ]
  }]
end

#entity_typesObject

Returns a list of entities exposed by the service


44
45
46
# File 'lib/odata/service.rb', line 44

def entity_types
  @entity_types ||= .xpath('//EntityType').collect {|entity| entity.attributes['Name'].value}
end

#execute(url_chunk, additional_options = {}) ⇒ Typhoeus::Response

Execute a request against the service

Parameters:

  • url_chunk (to_s)

    string to append to service url

  • additional_options (Hash) (defaults to: {})

    options to pass to Typhoeus

Returns:

  • (Typhoeus::Response)

126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/odata/service.rb', line 126

def execute(url_chunk, additional_options = {})
  request = ::Typhoeus::Request.new(
      URI.escape("#{service_url}/#{url_chunk}"),
      options[:typhoeus].merge({ method: :get
                               })
                        .merge(additional_options)
  )
  request.run
  response = request.response
  validate_response(response)
  response
end

#find_entities(results) ⇒ Nokogiri::XML::NodeSet

Find entity entries in a result set

Parameters:

  • results (Typhoeus::Response)

Returns:

  • (Nokogiri::XML::NodeSet)

153
154
155
156
157
# File 'lib/odata/service.rb', line 153

def find_entities(results)
  document = ::Nokogiri::XML(results.body)
  document.remove_namespaces!
  document.xpath('//entry')
end

#find_node(results, node_name) ⇒ Nokogiri::XML::Element

Find a specific node in the given result set

Parameters:

  • results (Typhoeus::Response)

Returns:

  • (Nokogiri::XML::Element)

143
144
145
146
147
# File 'lib/odata/service.rb', line 143

def find_node(results, node_name)
  document = ::Nokogiri::XML(results.body)
  document.remove_namespaces!
  document.xpath("//#{node_name}").first
end

#get_property_type(entity_name, property_name) ⇒ String

Get the property type for an entity from metadata.

Parameters:

  • entity_name (to_s)

    the name of the relevant entity

  • property_name (to_s)

    the property name needed

Returns:

  • (String)

    the name of the property's type


164
165
166
# File 'lib/odata/service.rb', line 164

def get_property_type(entity_name, property_name)
  .xpath("//EntityType[@Name='#{entity_name}']/Property[@Name='#{property_name}']").first.attributes['Type'].value
end

#get_summary_property_name(entity_name) ⇒ String

Get the property used as the summary for an entity from metadata.

Parameters:

  • entity_name (to_s)

    the name of the relevant entity

Returns:

  • (String)

    the name of the property used as the entity summary


181
182
183
184
185
# File 'lib/odata/service.rb', line 181

def get_summary_property_name(entity_name)
  .xpath("//EntityType[@Name='#{entity_name}']/Property[@FC_TargetPath='SyndicationSummary']").first.attributes['Name'].value
rescue NoMethodError
  nil
end

#get_title_property_name(entity_name) ⇒ String

Get the property used as the title for an entity from metadata.

Parameters:

  • entity_name (to_s)

    the name of the relevant entity

Returns:

  • (String)

    the name of the property used as the entity title


172
173
174
175
# File 'lib/odata/service.rb', line 172

def get_title_property_name(entity_name)
  node = .xpath("//EntityType[@Name='#{entity_name}']/Property[@FC_TargetPath='SyndicationTitle']").first
  node.nil? ? nil : node.attributes['Name'].value
end

#inspectObject

Returns a more compact inspection of the service object


100
101
102
# File 'lib/odata/service.rb', line 100

def inspect
  "#<#{self.class.name}:#{self.object_id} name='#{name}' service_url='#{self.service_url}'>"
end

#loggerObject


227
228
229
# File 'lib/odata/service.rb', line 227

def logger
  @logger ||= defined?(Rails) ? Rails.logger : Logger.new(STDOUT)
end

#logger=(custom_logger) ⇒ Object


231
232
233
# File 'lib/odata/service.rb', line 231

def logger=(custom_logger)
  @logger = custom_logger
end

#nameString

Returns user supplied name for service, or its URL

Returns:

  • (String)

39
40
41
# File 'lib/odata/service.rb', line 39

def name
  @name ||= options[:name] || service_url
end

#namespaceObject

Returns the namespace defined on the service's schema


95
96
97
# File 'lib/odata/service.rb', line 95

def namespace
  @namespace ||= .xpath('//Schema').first.attributes['Namespace'].value
end

Returns a hash for finding an association through an entity type's defined NavigationProperty elements.

Returns:


77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/odata/service.rb', line 77

def navigation_properties
  @navigation_properties ||= Hash[.xpath('//EntityType').collect do |entity_type_def|
    entity_type_name = entity_type_def.attributes['Name'].value
    [
        entity_type_name,
        Hash[entity_type_def.xpath('./NavigationProperty').collect do |nav_property_def|
          relationship_name = nav_property_def.attributes['Relationship'].value
          relationship_name.gsub!(/^#{namespace}\./, '')
          [
              nav_property_def.attributes['Name'].value,
              associations[relationship_name]
          ]
        end]
    ]
  end]
end

#primary_key_for(entity_name) ⇒ String

Get the primary key for the supplied Entity.

Parameters:

  • entity_name (to_s)

Returns:

  • (String)

191
192
193
# File 'lib/odata/service.rb', line 191

def primary_key_for(entity_name)
  .xpath("//EntityType[@Name='#{entity_name}']/Key/PropertyRef").first.attributes['Name'].value
end

#properties_for_complex_type(type_name) ⇒ Hash

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Get list of properties and their various options for the supplied ComplexType name.

Parameters:

  • type_name (to_s)

Returns:

  • (Hash)

Raises:

  • (ArgumentError)

216
217
218
219
220
221
222
223
224
225
# File 'lib/odata/service.rb', line 216

def properties_for_complex_type(type_name)
  type_definition = .xpath("//ComplexType[@Name='#{type_name}']").first
  raise ArgumentError, "Unknown ComplexType: #{type_name}" if type_definition.nil?
  properties_to_return = {}
  type_definition.xpath('./Property').each do |property_xml|
    property_name, property = process_property_from_xml(property_xml)
    properties_to_return[property_name] = property
  end
  properties_to_return
end

#properties_for_entity(entity_name) ⇒ Hash

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Get the list of properties and their various options for the supplied Entity name.

Parameters:

  • entity_name (to_s)

Returns:

  • (Hash)

Raises:

  • (ArgumentError)

200
201
202
203
204
205
206
207
208
209
# File 'lib/odata/service.rb', line 200

def properties_for_entity(entity_name)
  type_definition = .xpath("//EntityType[@Name='#{entity_name}']").first
  raise ArgumentError, "Unknown EntityType: #{entity_name}" if type_definition.nil?
  properties_to_return = {}
  type_definition.xpath('./Property').each do |property_xml|
    property_name, property = process_property_from_xml(property_xml)
    properties_to_return[property_name] = property
  end
  properties_to_return
end