lib/ncs_navigator/mdes/variable.rb in ncs_mdes-0.2.0 vs lib/ncs_navigator/mdes/variable.rb in ncs_mdes-0.3.0

- old
+ new

@@ -35,10 +35,17 @@ # # @return [Boolean] attr_accessor :required alias :required? :required + ## + # If this variable is a foreign key, this is the {table + # TransmissionTable} to which it refers. + # + # @return [TransmissionTable,nil] the parent table. + attr_accessor :table_reference + class << self ## # Examines the given parsed element and creates a new # variable. The resulting variable has all the attributes set # which can be set without reference to any other parts of the @@ -111,9 +118,61 @@ match = types.find { |t| t.name == ncs_type_name } if match self.type = match else log.warn("Undefined type #{type.name} for #{name}.") if log + end + end + + ## + # Attempts to resolve this variable as a {reference to another + # table #table_reference}. There are two mechanisms for performing + # the resolution: + # + # 1. If an `override_name` is provided, that table will be looked + # up in the provided table list. If it exists, it will be used, + # otherwise nothing will be set. + # 2. If the type of this variable is one of the NCS FK types and + # there exists exactly one table in `tables` whose primary key + # has the same name as this variable, that table will be used. + # + # Alternatively, to suppress the heuristics without providing a + # replacement, pass `false` as the `override_name` + # + # @param [Array<TransmissionTable>] tables the tables to search + # for a parent. + # @param [String,nil] override_name the name of a table to use as + # the parent. Supplying a value in this parameter bypasses the + # search heuristic. + # @return [void] + def resolve_foreign_key!(tables, override_name=nil, options={}) + log = options[:log] || NcsNavigator::Mdes.default_logger + + case override_name + when String + self.table_reference = tables.detect { |t| t.name == override_name } + unless table_reference + log.warn("Foreign key #{name.inspect} explicitly mapped " << + "to unknown table #{override_name.inspect}.") + end + when nil + return unless (self.type && self.type.name =~ /^foreignKey/) + + candidates = tables.select do |t| + t.variables.detect { |v| (v.name == name) && (v.type && (v.type.name =~ /^primaryKey/)) } + end + + case candidates.size + when 0 + log.warn("Foreign key not resolvable: " << + "no tables have a primary key named #{name.inspect}.") + when 1 + self.table_reference = candidates.first + else + log.warn( + "#{candidates.size} possible parent tables found for foreign key #{name.inspect}: " << + "#{candidates.collect { |c| c.name.inspect }.join(', ')}. None used due to ambiguity.") + end end end end end