Class: HQ::Engine::Engine

Inherits:
Object
  • Object
show all
Includes:
LibXmlRubyMixin
Defined in:
lib/hq/engine/engine.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from LibXmlRubyMixin

#field_to_json, #field_to_xml, #get_record_id_long, #get_record_id_short, #js_to_xml, #load_data_file, #load_data_string, #load_schema_file, #to_xml_string, #write_data_file, #xml_to_json

Instance Attribute Details

#config_dirObject

Returns the value of attribute config_dir.



17
18
19
# File 'lib/hq/engine/engine.rb', line 17

def config_dir
  @config_dir
end

#loggerObject

Returns the value of attribute logger.



14
15
16
# File 'lib/hq/engine/engine.rb', line 14

def logger
  @logger
end

#resultsObject

Returns the value of attribute results.



20
21
22
# File 'lib/hq/engine/engine.rb', line 20

def results
  @results
end

#transform_backendObject

Returns the value of attribute transform_backend.



15
16
17
# File 'lib/hq/engine/engine.rb', line 15

def transform_backend
  @transform_backend
end

#work_dirObject

Returns the value of attribute work_dir.



18
19
20
# File 'lib/hq/engine/engine.rb', line 18

def work_dir
  @work_dir
end

Instance Method Details

#abstractObject



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/hq/engine/engine.rb', line 24

def abstract

	return @abstract if @abstract

	abstract = {}

	results.each do
		|result_name, result|

		abstract[result_name] =
			result[:doc].root

	end

	return @abstract = abstract

end

#create_default_schemaObject



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/hq/engine/engine.rb', line 53

def create_default_schema

	return if File.exists? schema_file

	logger.trace "writing schema.xml (empty)"

	File.open schema_file, "w" do |f|
		f.print "<data>\n"
		f.print "\t<schema name=\"schema\">\n"
		f.print "\t\t<id>\n"
		f.print "\t\t\t<text name=\"name\"/>\n"
		f.print "\t\t</id>\n"
		f.print "\t\t<fields>\n"
		f.print "\t\t</fields>\n"
		f.print "\t\t<table>\n"
		f.print "\t\t\t<col name=\"name\"/>\n"
		f.print "\t\t</table>\n"
		f.print "\t</schema>\n"
		f.print "</data>\n"
	end

end

#create_work_dirObject



42
43
44
45
46
47
48
49
50
51
# File 'lib/hq/engine/engine.rb', line 42

def create_work_dir

	if File.exist? "#{work_dir}/error-flag"
		logger.warning "removing work directory due to previous error"
		FileUtils.rm_rf work_dir
	end

	FileUtils.mkdir_p work_dir

end

#input_dumpObject



184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
# File 'lib/hq/engine/engine.rb', line 184

def input_dump

	logger.notice "converting input"

	logger.time "converting input" do

		@input_docs = {}
		@input_strs = {}

		FileUtils.remove_entry_secure "#{work_dir}/input" \
			if File.directory? "#{work_dir}/input"

		FileUtils.mkdir_p "#{work_dir}/input", :mode => 0700

		values_by_type = Hash.new

		inputs = YAML.load File.read "#{work_dir}/input.yaml"

		inputs.each do
			|input|

			id = input["id"]
			type = input["type"]
			value = input["value"]

			value["_id"] = id

			values_by_type[type] ||= Hash.new
			values_by_type[type][id] = value

		end

		schema =
			load_schema_file "#{work_dir}/schema.xml"

		schema_types =
			schema
			.keys
			.map {
				|name|
				name =~ /^schema\/(.+)$/ ? $1 : nil
			}
			.compact
			.sort
			.uniq

		schema_types.each do
			|type|

			values = values_by_type[type] ||= {}

			input_doc = XML::Document.new
			input_doc.root = XML::Node.new "data"

			sorted_values =
				values.values.sort {
					|a,b|
					a["_id"] <=> b["_id"]
				}

			xml_values =
				sorted_values.map {
					|value|
					js_to_xml schema, type, value
				}

			write_data_file \
				"#{work_dir}/input/#{type}.xml",
				xml_values

		end

	end

end

#input_readyObject



176
177
178
179
180
181
182
# File 'lib/hq/engine/engine.rb', line 176

def input_ready
	if $no_database
		logger.warning "using previous input due to --no-database option"
	else
		input_dump
	end
end

#load_resultsObject



260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
# File 'lib/hq/engine/engine.rb', line 260

def load_results

	@results = {}

	item_path_regex =
		/^#{Regexp.escape work_dir}\/output\/data\/(.+)\.xml$/

	Dir["#{work_dir}/output/data/**/*.xml"].each do
		|item_path|

		item_path =~ item_path_regex
		item_id = $1

		item_doc =
			XML::Document.file \
				item_path,
				:options => XML::Parser::Options::NOBLANKS

		item_dom = item_doc.root
		item_type = item_dom.name

		result = @results[item_type]

		unless result

			result = {}

			result[:doc] = XML::Document.new
			result[:doc].root = XML::Node.new "data"

			@results[item_type] = result

		end

		doc = result[:doc]
		doc.root << doc.import(item_dom)

	end

end

#schema_fileObject



22
# File 'lib/hq/engine/engine.rb', line 22

def schema_file() "#{work_dir}/schema.xml" end

#transformObject



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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
# File 'lib/hq/engine/engine.rb', line 76

def transform

	return if warn_no_config

	create_work_dir

	create_default_schema

	old_schemas_str =
		File.read schema_file

	loop do

		input_ready

		# process abstract config

		transformer = HQ::Engine::Transformer.new
		transformer.parent = self

		transformer.schema_file = schema_file

		transformer.rules_dir = "#{config_dir}/rules"
		transformer.include_dir = "#{config_dir}/include"

		transformer.input_dir = "#{work_dir}/input"
		transformer.output_dir = "#{work_dir}/output"

		transform_result =
			transformer.rebuild

		# write new schema file

		logger.trace "writing schema.xml"

		new_schemas =
			transformer.data.select {
				|item_id, item_xml|
				item_id =~ /^(schema|schema-option|abstract-rule)\//
			}
			.map {
				|item_id, item_xml|
				item_doc = XML::Document.string item_xml
				item_doc.root
			}

		write_data_file schema_file, new_schemas

		# restart if schema changed

		new_schemas_str =
			File.read schema_file

		if new_schemas_str != old_schemas_str

			old_schemas_str = new_schemas_str
			new_schemas_str = nil

			logger.notice "restart due to schema changes"

			next

		end

		# error if the transform was not complete

		unless transform_result[:success]

			transform_result[:missing_types].each do
				|type_name|
				logger.warning "type missing: #{type_name}"
			end

			transform_result[:remaining_rules].each do
				|rule_name|
				logger.warning "rule could not be run: #{rule_name}"
			end

			logger.die "exiting due to failed transformation"

		end

		# we're done

		load_results

		return

	end

end

#warn_no_configObject



168
169
170
171
172
173
174
# File 'lib/hq/engine/engine.rb', line 168

def warn_no_config
	return false unless $no_config
	return true if @warned_no_config
	logger.warning "not rebuilding configuration due to --no-config option"
	@warned_no_config = true
	return true
end