#!/usr/local/bin/ruby require 'kconv' require 'webua.rb' require 'base64.rb' module FMPro4 def tokcode(str) retrun str unless $KCODE case $KCODE[0,1] when 'e', 'E' Kconv.toeuc(str) when 'j', 'J' Kconv.tojis(str) else str end end module_function :tokcode class FMProError 'eq', 'contains' => 'cn', 'begins with' => 'bw', 'ends with' => 'ew', 'greater than' => 'gt', 'greater than or equals' => 'gte', 'less than' => 'lt', 'less than or equals' => 'lte', 'not equals' => 'neq' } end def logical_operators "and or".split end end class FMProField def initialize(res, name) @name = name end attr(:name) attr(:repeating, true) attr(:notnull, true) attr(:datatype, true) attr(:displaystyle, true) attr(:valuelist, true) def to_value(str) if self.repeating list = [] str.split("\f").each do |v| list.push(self.to_value1(v)) end list else self.to_value1(str) end end def to_value1(str) return nil if str == "\a" case @datatype when 'n' if str =~ /^[0-9]*$/ str.to_i else str.to_f end else str end end end class FMProRecord def initialize(response, recid, numfields) @recordid = recid @values = Array.new(numfields) @res = response end attr (:recordid) attr (:values) def [](key) if key.is_a? String key = @res.fieldname2index(key) return nil unless key end @values[key] end end class FMProResponse @DATATYPE = { 'c' => 'TYPE_TEXT', 'n' => 'TYPE_NUMBER', 'd' => 'TYPE_DATE', 't' => 'TYPE_TIME', 'x' => 'TYPE_CONTAINER', 'i' => 'TYPE_INVALID' } @STYLE = { 'e' => 'STYLE_EDIT_TEXT', 'p' => 'STYLE_POPUP_LIST', 'm' => 'STYLE_POPUP_MENU', 'c' => 'STYLE_CHECK_BOX', 'r' => 'STYLE_RADIO_BUTTONS', 't' => 'STYLE_SCROLL_TEXT' } attr :DATATYPE attr :STYLE module_function :DATATYPE, :STYLE def initialize(req, src) @req = req list = FMPro4::tokcode(src.to_s).split("\v") self.decode(list) end attr :req attr :fields attr :records attr :numfound attr :numtotal def decode(list) head = list.shift raise(FMProError, head) unless head == '0' # フィールドの作成 num = list.shift.to_i @fields = Array.new(num) @fields.each_index do |i| @fields[i] = FMProField.new(self, list.shift) end # 繰返し情報の取得 desc = list.shift.split(/ */) @fields.each do |fld| if desc.shift == 't' fld.repeating = desc.shift.to_i end end # 必須/省略可? desc = list.shift.split(/ */) @fields.each do |fld| fld.notnull = true if desc.shift == 'f' end # フィールド種 desc = list.shift.split(/ */) @fields.each do |fld| fld.datatype = desc.shift end # displaystyle desc = list.shift.split(/ */) @fields.each do |fld| fld.displaystyle = desc.shift end # 値リスト @fields.each do |fld| num = list.shift.to_i if num > 0 vlist = Array.new(num) vlist.each_index do |i| vlist[i] = list.shift end if fld.displaystyle != 'e' and fld.displaystyle != 't' fld.valuelist = vlist end end end # レコードの作成 num = list.shift.to_i @records = Array.new(num) @records.each_index do |i| num = list.shift.to_i rec = FMProRecord.new(self, num, @fields.size) @records[i] = rec end @records.each do |rec| rec.values.each_index do |j| rec.values[j] = @fields[j].to_value(list.shift) end end # おわり @numfound = list.shift.to_i @numtotal = list.shift.to_i # 空でなければ decode 失敗 raise(FMProError, list.inspect) unless list.size == 0 end def fieldname2index(name) unless @fieldnames @fieldnames = Hash.new @fields.each_index do |i| @fieldnames[@fields[i].name] = i end end @fieldnames[name] end end end if __FILE__ == $0 fmpro = FMPro4::FMProProxy.new('http://lc630/') p fmpro.database_names fmpro.set_password('seki', 'seki') p fmpro.layout_names('kounyuu.fmj') p fmpro.script_names('kounyuu.fmj') req = FMPro4::FMProRequest.new('kounyuu.fmj', '作成') req.add('ID', 53) req.add('-Find') res = fmpro.process_request(req) p res.records[0] i = res.fieldname2index('ID') p res.fields[i] end