class LUSI::API::Organisation::Organisation

Represents an organisation as a hierarchy of Units.

The position in the hierarchy is defined by the Unit.type attribute.

For each hierarchy level (Unit type) the Organisation maintains three indices, identified as follows:

:identity   allows retrieval by the Unit.identity attribute
:mnemonic   allows retrieval by the Unit.mnemonic attribute
:title      allows retrieval by the Unit.title attribute

Once an instance is created, it should be populated by calling the load method @example Populating an Organisation instance

api = LUSI::API::Core::API.new(...)
org = LUSI::API::Organisation::Organisation.new
begin
  org.load(api, in_use_only: false)
rescue LUSI::API::Core::APIError => e
  # API error handling
end

Constants

HIERARCHY

Defines the organisation hierarchy as a mapping from unit type to its child unit type and corresponding XPath. A leaf unit with no children maps to nil. The reserved unit type “_root” defines the root of the hierarchy.

Public Class Methods

new(api = nil, lookup = nil) click to toggle source

Initialises a new Organisation instance @param api [LUSI::API::Core::API, nil] an optional LUSI API instance used to retrieve data @param lookup [LUSI::API::Core::Lookup::LookupService, nil] the lookup service for object resolution @return [void]

# File lib/lusi_api/organisation.rb, line 43
def initialize(api = nil, lookup = nil)
  @api = api
  clear
end

Protected Class Methods

key(key) click to toggle source

Returns a normalised index key Normalisation removes redundant whitespace and converts to uppercase for case-insensitivity @param key [any] the key value @return [String, nil] the normalised key value

# File lib/lusi_api/organisation.rb, line 199
def self.key(key)
  return nil if key.nil?
  key = key.to_s.strip
  key.squeeze!(' ')
  key.upcase!
  key
end

Public Instance Methods

[](identity = nil) click to toggle source

Searches the organisation top-down for the specified identity code and returns the first matching Unit @param identity [any] the identity code @return [Unit, nil] the matching Unit instance, or nil if no match is found

# File lib/lusi_api/organisation.rb, line 51
def [](identity = nil)
  key = self.class.key(identity)
  type = HIERARCHY[:_root][:type]
  until type.nil? do
    if @indices[type]
      unit = @indices[type][:identity][key]
      return unit if unit
    end
    type = HIERARCHY[type] ? HIERARCHY[type][:type] : nil
  end
  nil
end
add(unit) click to toggle source

Adds a new Unit to the Organisation Child units are recursively added @param unit [LUSI::API::Organisation::Unit] the Unit instance @return void

# File lib/lusi_api/organisation.rb, line 68
def add(unit)
  
  # Require a Unit instance
  return unless unit.is_a?(Unit)
  
  # Initialise the indices for this Unit type if required
  @indices[unit.type] = { identity: {}, mnemonic: {}, title: {} } unless @indices.include?(unit.type)
  
  # Index the unit
  hash = @indices[unit.type]
  hash[:identity][self.class.key(unit.identity)] = unit
  hash[:mnemonic][self.class.key(unit.mnemonic)] = unit
  hash[:title][self.class.key(unit.title)] = unit
  
  # Index the unit's child units
  unit.children.each { |child| add(child) } if unit.children
  
end
clear() click to toggle source

Clears the organisation structure @return [void]

# File lib/lusi_api/organisation.rb, line 89
def clear
  @indices = {}
end
each(type = nil, index = nil, &block) click to toggle source

Iterates over selected parts of the organisation hierarchy @param type [Symbol, nil] the Unit type to iterate over @param index [Symbol, nil] the Unit type's index to iterate over (:identity | :mnemonic | :title) @return [void] @yield Passes a Unit instance to the block @yieldparam unit [LUSI::API::Organisation::Unit] the current unit of the iterator

# File lib/lusi_api/organisation.rb, line 99
def each(type = nil, index = nil, &block)
  if type
    # Iterate over the selected type; ignore invalid types
    hash = @indices[type]
    if hash
      hash_index = hash.include?(index) ? index : :identity
      hash[hash_index].each_value(&block) if hash[hash_index]
    end
  else
    # Iterate over all types
    @indices.each_value do |type|
      hash_index = type.include?(index) ? index : :identity
      type[hash_index].each_value(&block) if type[hash_index]
    end
  end
end
each_unit_type() { |unit_type| ... } click to toggle source

Iterates over each unit type in the organisation hierarchy starting from the root @return [void] @yield [unit_type] Passes the unit type to the block @yieldparam unit_type [Symbol] the current unit type of the iterator

# File lib/lusi_api/organisation.rb, line 120
def each_unit_type
  unit_type = HIERARCHY[:_root][:type]
  while unit_type
    yield(unit_type)
    unit_type = HIERARCHY[unit_type] ? HIERARCHY[unit_type][:type] : nil
  end
end
empty?() click to toggle source

Indicates whether the organisation is empty (contains units) or not @return [Boolean] true if the organisation contains no units, otherwise false

# File lib/lusi_api/organisation.rb, line 130
def empty?
  # If @indices is not empty, use the #length method to determine emptiness
  @indices.nil? || @indices.empty? || length == 0
end
get(key, type = nil, index: nil) click to toggle source

Returns the Unit instance matching the given parameters Key values are case-insensitive and normalised by removing leading, trailing and redundant whitespace. Title matching is based on the exact title after key normalisation. @param key [any] the Unit attribute value to search for @param type [Symbol, nil] the Unit type to search for (defaults to the root type of the organisation hierarchy) @param index [Symbol, nil] the Unit index to search (:identity, :mnemonic, :title) @return [Unit, nil] the matching Unit instance, or nil if no matches are found

# File lib/lusi_api/organisation.rb, line 142
def get(key, type = nil, index: nil)
  hash = @indices[type] || @indices[HIERARCHY[:_root][:type]]
  if hash
    index = :identity unless hash.include?(index)
    hash[index][self.class.key(key)]
  else
    nil
  end
end
length(type = nil, index: nil) click to toggle source

Returns the number of Units matching the given parameters @param type [Symbol, nil] the Unit type to count (defaults to all units) @param index [Symbol, nil] the Unit index to count (:identity, :mnemonic, :title) @return [Integer, nil] the number of Unit instances for the given parameters, or nil

# File lib/lusi_api/organisation.rb, line 156
def length(type = nil, index: nil)
  count = 0
  types = type.nil? ? @indices.keys : [type]
  types.each do |unit_type|
    hash = @indices[unit_type]
    if hash
      hash_index = hash.include?(index) ? hash[index] : hash[:identity]
      count += hash_index.length if hash_index
    end
  end
  count
end
load(api = nil, in_use_only: true) click to toggle source

Populates the Organisation instance from the LUSI API @param api [LUSI::API::Core::API, nil] the LUSI API instance to use (defaults to the Organisation's @api) @param in_use_only [Boolean] if true, include only current Units; if false, additionally include historic Units @return [Nokogiri::XML::Node] the parsed XML <body/> content from the LUSI API call

# File lib/lusi_api/organisation.rb, line 173
def load(api = nil, in_use_only: true)

  # Call the LUSI API
  api ||= @api
  xml = api.call('LUSIReference', 'General.asmx', 'GetOrganisationStructure', InUseOnly: in_use_only)

  # Clear the existing organisation structure
  clear

  # Add each organisation unit to the structure
  root = HIERARCHY[:_root]
  LUSI::API::Core::XML.xml(xml, root[:path]) do |u|
    add(Unit.new(u, type: root[:type], hierarchy: HIERARCHY))
  end

  # Return the parsed XML body content from the LUSI API call
  xml

end