Class: UniProp::BlockGenerator
- Inherits:
-
Object
- Object
- UniProp::BlockGenerator
- Defined in:
- lib/uniprop/metadata_generator.rb
Overview
既存のメタデータを使用し、メタデータ未知のPropFileに関するblocksを作成するクラス
Instance Attribute Summary collapse
-
#generated_file ⇒ Object
readonly
Returns the value of attribute generated_file.
-
#generated_version ⇒ Object
readonly
Returns the value of attribute generated_version.
-
#using_file ⇒ Object
readonly
Returns the value of attribute using_file.
-
#using_file_metadata ⇒ Object
readonly
Returns the value of attribute using_file_metadata.
-
#using_version_metadata ⇒ Object
readonly
Returns the value of attribute using_version_metadata.
Instance Method Summary collapse
-
#block_format_type(content) ⇒ Array<Object>
blockの再生成に使用するフォーマットとして最も適切なものを取得.
-
#block_format_types ⇒ Array<Array<Object>>
using_fileのblocksのフォーマットを取得.
- #column_format_type(column) ⇒ Object
-
#generate_raw_blocks ⇒ Array<RawBlock>
generated_fileのblocksに相当するArray<RawBlock>を作成.
-
#has_multiple_free_value_block? ⇒ Boolean
using_fileに、binary,enumerated,catalog以外の型のプロパティを含むブロックが2つ以上存在するか判定.
-
#initialize(using_file, generated_file, using_file_metadata) ⇒ BlockGenerator
constructor
A new instance of BlockGenerator.
-
#line_format(row) ⇒ Array<Integer>
N番目のblockのフォーマットに一致する場合、n。どのブロックにもマッチしない場合、nil。.
-
#lines_format ⇒ Array<Integer?>
generated_fileの各行が、何番目のブロックのblock_format_typeにマッチするか判定.
-
#match_format?(row, codepoint_column_no, block_no) ⇒ Boolean
row行目がformat_typeの形式に一致するか判定.
-
#matched_ranges ⇒ Array<Range<Integer>>
各ブロックがgenerated_fileにおいてマッチした行数の範囲を取得.
Constructor Details
#initialize(using_file, generated_file, using_file_metadata) ⇒ BlockGenerator
Returns a new instance of BlockGenerator.
171 172 173 174 175 176 177 |
# File 'lib/uniprop/metadata_generator.rb', line 171 def initialize(using_file, generated_file, ) @using_file = using_file @generated_file = generated_file @generated_version = generated_file.version = = using_file.version. end |
Instance Attribute Details
#generated_file ⇒ Object (readonly)
Returns the value of attribute generated_file.
166 167 168 |
# File 'lib/uniprop/metadata_generator.rb', line 166 def generated_file @generated_file end |
#generated_version ⇒ Object (readonly)
Returns the value of attribute generated_version.
166 167 168 |
# File 'lib/uniprop/metadata_generator.rb', line 166 def generated_version @generated_version end |
#using_file ⇒ Object (readonly)
Returns the value of attribute using_file.
166 167 168 |
# File 'lib/uniprop/metadata_generator.rb', line 166 def using_file @using_file end |
#using_file_metadata ⇒ Object (readonly)
Returns the value of attribute using_file_metadata.
166 167 168 |
# File 'lib/uniprop/metadata_generator.rb', line 166 def end |
#using_version_metadata ⇒ Object (readonly)
Returns the value of attribute using_version_metadata.
166 167 168 |
# File 'lib/uniprop/metadata_generator.rb', line 166 def end |
Instance Method Details
#block_format_type(content) ⇒ Array<Object>
blockの再生成に使用するフォーマットとして最も適切なものを取得
226 227 228 |
# File 'lib/uniprop/metadata_generator.rb', line 226 def block_format_type(content) content.map { column_format_type(_1) } end |
#block_format_types ⇒ Array<Array<Object>>
返り値のn番目の要素はblocks内のn番目のblockのフォーマットに対応
using_fileのblocksのフォーマットを取得
200 201 202 |
# File 'lib/uniprop/metadata_generator.rb', line 200 def block_format_types @block_format_types ||= .blocks.map { block_format_type(_1.content) } end |
#column_format_type(column) ⇒ Object
230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 |
# File 'lib/uniprop/metadata_generator.rb', line 230 def column_format_type(column) # columnがArrayの場合、その列には固有の表記法が使用されており、一様に判定を行う事はできないため、:text を返す return Format.new(:text, column) if column.class == Array # columnがnilの場合、nil (その列には判定を行わない) return nil if !column if has_multiple_free_value_block? # 列挙型以外のプロパティを取るブロックが2つ以上存在する場合、 # コードポイントと値の対応を調べないと、同じプロパティに関する記述かの判定が不可能 return column else # 列挙型以外のプロパティを取るブロックが1つだけの場合、 # 記述されている値の型を調べるだけで、同じプロパティに関する記述かの判定が可能 type = (column.property_value_type==:miscellaneous) ? column.miscellaneous_format : column.property_value_type # type==:uniqueの場合、判定時には:textと同様に扱いたいため、:textに変更 type = :text if type==:unique return Format.new(type, column) end end |
#generate_raw_blocks ⇒ Array<RawBlock>
generated_fileのblocksに相当するArray<RawBlock>を作成
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 |
# File 'lib/uniprop/metadata_generator.rb', line 181 def generate_raw_blocks return @raw_blocks if @raw_blocks @raw_blocks = [] .blocks.size.times do |block_no| range = matched_ranges[block_no] if range content = .raw_blocks[block_no].content @raw_blocks << RawBlock.new(content, range.to_s) end end @raw_blocks end |
#has_multiple_free_value_block? ⇒ Boolean
using_fileに、binary,enumerated,catalog以外の型のプロパティを含むブロックが2つ以上存在するか判定
206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 |
# File 'lib/uniprop/metadata_generator.rb', line 206 def has_multiple_free_value_block? return @multiple_free_value_block_f if @multiple_free_value_block_f free_value_exist_f = [] .blocks.each do |block| block_properties = block.content.reject { _1.class == Array } .compact free_value_exist_f << !block_properties.all? { _1.property_value_type==:binary || _1.property_value_type==:enumerated || _1.property_value_type==:catalog } end @multiple_free_value_block_f = free_value_exist_f.filter { _1 }.size > 1 @multiple_free_value_block_f end |
#line_format(row) ⇒ Array<Integer>
Returns n番目のblockのフォーマットに一致する場合、n。どのブロックにもマッチしない場合、nil。.
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 300 301 302 303 304 305 |
# File 'lib/uniprop/metadata_generator.rb', line 273 def line_format(row) matched_blocks = [] .blocks.size.times do |block_no| codepoint_col_no = .codepoint_column_nos[block_no] matched_blocks << block_no if match_format?(row, codepoint_col_no, block_no) end if matched_blocks.size == 1 # line_formatの結果のサイズが1の場合 # row行目がマッチするブロックが一意に絞れているため、結果として使用 return matched_blocks[0] else # row行目がマッチするブロックが一意に絞れていない場合 # この場合、ある行がどのプロパティについて記述されているか、データファイルに記述されている場合が多い # そのため、row行目の中に含まれるプロパティ名で判定 prop_including_blocks = [] .blocks.size.times do |block_no| .blocks[block_no].content.compact.each do |prop| next if prop.class == Array prop_including_blocks << block_no if generated_file.has_property_alias?(row, prop) end end if prop_including_blocks.size == 1 return prop_including_blocks[0] else # プロパティ名を使用しても一意に絞れない場合、nil return nil end end end |
#lines_format ⇒ Array<Integer?>
generated_fileの各行が、何番目のブロックのblock_format_typeにマッチするか判定
255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 |
# File 'lib/uniprop/metadata_generator.rb', line 255 def lines_format return @lines_format if @lines_format @lines_format = [] generated_file.lines.size.times do |row| # n行目がコメントの場合、line_formatによる判定は行わずnilを追加 if generated_file.comment?(row) @lines_format << nil next end @lines_format << line_format(row) end @lines_format end |
#match_format?(row, codepoint_column_no, block_no) ⇒ Boolean
row行目がformat_typeの形式に一致するか判定
311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 |
# File 'lib/uniprop/metadata_generator.rb', line 311 def match_format?(row, codepoint_column_no, block_no) shaped_line = generated_file.shaped_lines[row] format_type = block_format_types[block_no] # row行目の中にcol_formatと異なるフォーマットの列が存在する場合、その時点でfalseを返す format_type.each_with_index do |col_format, col_no| next if !col_format # formatがnilの場合には判定を行わない if col_format.class == Format if [:enumerated, :catalog, :binary].include?(col_format.type) && generated_version.has_property?(col_format.property) # 列挙型のプロパティ(enumerated, catalog, binary)の場合、 prop.version == generated_version でないと、propに新しいバージョンで追加された値が含まれず、プロパティの範囲の正確な推測が不可能 prop = generated_version.find_property(col_format.property) else prop = col_format.property end if generated_file.type_match?(row, col_no, col_format.type, prop) next else return false end else # col_format.class==Property の場合、型での判定はできない # generated_fileのrow行目のcodepointがusing_fileで取っている値が、generated_fileと同じであるかを判定する bvg = .(using_file).block_value_group(block_no) shaped_line_dup = shaped_line.dup codepoint = shaped_line_dup.delete_at(codepoint_column_no) # codepointがnnnn..mmmm形式の場合、最初のnnnnのみを比較に使用 # nnnn..mmmmの範囲では同じ値を持つため、nnnnのみを使用すれば十分 codepoint = codepoint.split("..")[0] generated_file_value = generated_file.value_at(row, col_no) using_file_value = bvg.values_of(codepoint) if using_file_value.class==String && using_file_value==generated_file_value || using_file_value.class==Array && using_file_value.include?(generated_file_value) next else return false end end end true end |
#matched_ranges ⇒ Array<Range<Integer>>
n番目の要素はn番目のブロックがマッチした範囲
各ブロックがgenerated_fileにおいてマッチした行数の範囲を取得
361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 |
# File 'lib/uniprop/metadata_generator.rb', line 361 def matched_ranges return @matched_ranges if @matched_ranges block_no_to_ranges = Hash.new { |hash,key| hash[key]=[] } measured_block_no = nil # 範囲を計測中のblock_no start_idx = nil # measured_block_noが最初に現れたidx end_idx = nil # measured_block_noが最後に現れたidx pre_idx = nil # 前回のblock_no(nil以外のInteger)が現れたidx lines_format_dup = lines_format.dup lines_format_dup << Float::NAN # 最後の要素まで処理を行うため、最後にNANを入れておく lines_format_dup.each_with_index do |block_no, i| next if !block_no # i行目がコメント行などの場合 if block_no != measured_block_no # 前回までのmeasured_block_noの計測を終了 end_idx = pre_idx if measured_block_no && start_idx && end_idx block_no_to_ranges[measured_block_no] << Range.new(start_idx, end_idx) end # measured_block_noをblock_noに切り替え measured_block_no = block_no start_idx = i end pre_idx = i end # 同一ブロックが2つ以上に分かれた範囲に記述されていると判定されている場合、 # 最初の範囲だけをn番目のブロックの範囲として採用 # その場合、誤ったメタデータが生成されることになるが、検証メソッドにより検出され、ユーザに修正される @matched_ranges = [] .blocks.size.times do |block_no| @matched_ranges[block_no] = block_no_to_ranges[block_no][0] end @matched_ranges end |