128 lines
4.0 KiB
Ruby
128 lines
4.0 KiB
Ruby
# 스크립트 기반 클래스
|
|
# 각 스크립트별 규칙 검증를 위한 하위 클래스들은 이 기반 클래스에서 파생
|
|
class Script
|
|
attr_accessor :name, :path, :checker
|
|
def initialize(required, name, path)
|
|
@required = required # 필수 스크립트인가
|
|
@name = name # 스크립트 이름
|
|
@path = path # 디렉토리 기준 파일 경로
|
|
@checker = nil
|
|
@head_array = [] # 컬럼 헤더 문자열 배열
|
|
@head_hash = {} # 컬럼 헤더 => 컬럼 인덱스 해시
|
|
@line_num = 0 # 현재 처리 중인 행 번호
|
|
@should_check_space = true
|
|
end
|
|
def check(dir)
|
|
unless File.exist?(File.join(dir, path))
|
|
if @required
|
|
puts "[ERROR] #{@name} : 파일을 찾을 수 없음"
|
|
set_error
|
|
else
|
|
puts "[WARNING] #{@name} : 파일을 찾을 수 없음"
|
|
end
|
|
return
|
|
end
|
|
@line_num = 0
|
|
got_head_line = false
|
|
IO.foreach(File.join(dir, path)) do |line|
|
|
@line_num += 1
|
|
s = line.lstrip # 선행 공백 삭제
|
|
next if s[0..1] == '//' # 주석 라인은 건너뛴다
|
|
tokens = s.split("\t") # 각 컬럼은 탭("\t")으로 구분
|
|
next unless tokens
|
|
|
|
if @should_check_space
|
|
# 탭("\t")으로 분리된 토큰 중 공백 문자(" ")가 포함된 것이 있는가
|
|
# 토큰 중간의 공백 문자는 파서 오류를 유발한다
|
|
col_num = Script.has_inner_space(tokens)
|
|
if col_num >= 0
|
|
puts "[ERROR] #{@name} : 잘못된 공백 문자 (line #{@line_num} col #{col_num})"
|
|
set_error
|
|
next
|
|
end
|
|
end
|
|
|
|
unless got_head_line
|
|
@head_array = tokens # 주석이 아닌 첫 라인은 컬럼 헤더여야 한다
|
|
col_index = -1
|
|
@head_array.each do |col_name|
|
|
col_index += 1
|
|
if col_name.strip != '' and @head_hash.has_key?(col_name)
|
|
puts "[ERROR] Duplicated column header '#{col_name}' (line #{@line_num})"
|
|
set_error
|
|
next
|
|
end
|
|
@head_hash[col_name] = col_index
|
|
end
|
|
got_head_line = true
|
|
else
|
|
# 현재 포맷에서 내용 컬럼 수 체크 의미 없음
|
|
|
|
# 스크립트별 상세 검증
|
|
check_rule(tokens)
|
|
end
|
|
end
|
|
end
|
|
def check_rule(columns)
|
|
# 모든 스크립트에 공통되는 사항이 아니라면 하위 클래스에서 구현
|
|
end
|
|
def col_index(col_name)
|
|
@head_hash[col_name]
|
|
end
|
|
def Script.has_inner_space(tokens)
|
|
col_num = 0
|
|
tokens.each do |token|
|
|
col_num += 1
|
|
stripped = token.strip
|
|
break if stripped.include?('//') # '//' 이후로 검사하지 않음
|
|
next unless stripped.include?(' ')
|
|
return col_num
|
|
end
|
|
return -1
|
|
end
|
|
end
|
|
|
|
class ScriptChecker
|
|
attr_accessor :dir, :item_table
|
|
def initialize
|
|
@script_array = []
|
|
@script_hash = {}
|
|
@dir = '.'
|
|
@item_table = {}
|
|
end
|
|
# 검증 대상 스크립트 추가
|
|
def add(required, name, path = name)
|
|
if @script_hash.has_key?(name)
|
|
if script_hash[name].path != path
|
|
puts "[ERROR] Duplicated script name '#{name}'"
|
|
set_error
|
|
end
|
|
return
|
|
end
|
|
script = ScriptFactory.create(required, name, path)
|
|
script.checker = self
|
|
@script_array.push(script)
|
|
@script_hash[name] = script
|
|
end
|
|
# 검증 대상 스크립트 갯수 얻기
|
|
def num_scripts
|
|
@script_array.length
|
|
end
|
|
# 주어진 이름에 맵핑된 스크립트 객체 얻기
|
|
def get_script(name)
|
|
@script_hash[name]
|
|
end
|
|
# 검증 실행
|
|
def run
|
|
@script_array.each do |script|
|
|
begin
|
|
puts "Checking #{script.name}"
|
|
script.check(@dir)
|
|
rescue Exception => e
|
|
puts '[ERROR] ' + e
|
|
set_error
|
|
end
|
|
end
|
|
end
|
|
end
|