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
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
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
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
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
Clears the organisation structure @return [void]
# File lib/lusi_api/organisation.rb, line 89 def clear @indices = {} end
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
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
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
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
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
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