Class: ActiveFacts::Generators::Composition

Inherits:
Object
  • Object
show all
Includes:
RMap
Defined in:
lib/activefacts/generators/composition.rb

Overview

afgen –composition <file>.cql Options are comma or space separated:

Instance Method Summary collapse

Instance Method Details

#generate(out = $>) ⇒ Object

:nodoc:



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/activefacts/generators/composition.rb', line 32

def generate(out = $>)      #:nodoc:
	@out = out

	tables_emitted = {}

	puts "require '#{@vocabulary.name}'"
	puts "require 'activefacts/composition'"
	puts "\n#{@vocabulary.name}_ER = ActiveFacts::Composition.new(#{@vocabulary.name}) do"
	@vocabulary.tables.each do |table|
	  puts "  composite :\"#{table.name.gsub(' ',@underscore)}\" do"

	  pk = table.identifier_columns
	  identity_column = pk[0] if pk[0].is_auto_assigned

	  fk_refs = table.references_from.select{|ref| ref.is_simple_reference }
	  fk_columns = table.columns.select do |column|
	    column.references[0].is_simple_reference
	  end

	  columns =
	    table.columns.map do |column|
 [column, column.references.map{|r| r.to_names }]
	    end.sort_by do |column, refnames|
 refnames
	    end
	  previous_flattening = []
	  ref_prefix = []
	  columns.each do |column, refnames|
	    ref_prefix = column.references[0...previous_flattening.size]
	    # Pop back. Not a succinct algorithm, but easy to check
	    while previous_flattening.size > ref_prefix.size
 previous_flattening.pop
 puts '    '+'  '*previous_flattening.size+"end\n"
	    end
	    while ref_prefix.size > 0 and previous_flattening != ref_prefix
 previous_flattening.pop
 ref_prefix.pop
 puts '    '+'  '*previous_flattening.size+"end\n"
	    end
	    loop do
 ref = column.references[ref_prefix.size]
 if ref.is_self_value
		# REVISIT: I think these should be 'insert :value, :as => "XYZ"'
		role_name = "value".snakecase
		reading = "Intrinsic value of #{role_name}"
 elsif ref.is_to_objectified_fact
		# REVISIT: It's ugly to have to handle these special cases here
		role_name = ref.to.name.words.snakecase
		reading = ref.from_role.link_fact_type.default_reading
 else
		if ref.is_unary && ref.is_from_objectified_fact && ref != column.references.last
		  # Use the name of the objectification on the path to other absorbed fact types:
		  role_name = ref.to_role.fact_type.entity_type.name.words.snakecase
		else
		  role_name = ref.to_role.preferred_role_name
		end
		# puts ">>>>> #{ref.inspect}: #{role_name} <<<<<<"
		reading = ref.fact_type.default_reading
 end
 if ref == column.references.last
		# REVISIT: Avoid the "as" here when the value is implied by the role_name:
		puts '    '+'  '*ref_prefix.size+"nest :#{role_name}, :as => \"#{column.name}\"\t\t# #{reading}"
		break
 else
		puts '    '+'  '*ref_prefix.size+"flatten :#{role_name} do\t\t# #{reading}"
		ref_prefix.push ref
 end
	    end
	    previous_flattening = ref_prefix
	  end

	  while previous_flattening.size > 0
	    previous_flattening.pop
	    puts '    '+'  '*previous_flattening.size+"end\n"
	  end
	  puts "  end\n\n"

	  tables_emitted[table] = true

	end
	puts "end\n"
end