Class | SOAP::Property |
In: |
lib/soap/property.rb
|
Parent: | Object |
Property stream format:
line separator is \r?\n. 1 line per a property. line which begins with '#' is a comment line. empty line is ignored, too. key/value separator is ':' or '='. '\' as escape character. but line separator cannot be escaped. \s at the head/tail of key/value are trimmed. '[' + key + ']' indicates property section. for example, [aaa.bbb] ccc = ddd eee.fff = ggg [] aaa.hhh = iii is the same as; aaa.bbb.ccc = ddd aaa.bbb.eee.fff = ggg aaa.hhh = iii
FrozenError | = | (RUBY_VERSION >= "1.9.0") ? RuntimeError : TypeError |
KEY_REGSRC | = | '([^=:\\\\]*(?:\\\\.[^=:\\\\]*)*)' |
DEF_REGSRC | = | '\\s*' + KEY_REGSRC + '\\s*[=:]\\s*(.*)' |
COMMENT_REGEXP | = | Regexp.new('^(?:#.*|)$') |
CATDEF_REGEXP | = | Regexp.new("^\\[\\s*#{KEY_REGSRC}\\s*\\]$") |
LINE_REGEXP | = | Regexp.new("^#{DEF_REGSRC}$") |
NO_HOOK | = | [].freeze |
# File lib/soap/property.rb, line 55 55: def self.loadproperty(propname) 56: new.loadproperty(propname) 57: end
# File lib/soap/property.rb, line 59 59: def initialize 60: @store = Hash.new 61: @hook = Hash.new 62: @self_hook = Array.new 63: @locked = false 64: end
name: a Symbol, String or an Array; nil means hook to the root cascade: true/false; for cascading hook of sub key hook: block which will be called with 2 args, name and value
# File lib/soap/property.rb, line 129 129: def add_hook(name = nil, cascade = false, &hook) 130: if name == nil or name == true or name == false 131: cascade = name 132: assign_self_hook(cascade, &hook) 133: else 134: assign_hook(name_to_a(name), cascade, &hook) 135: end 136: end
# File lib/soap/property.rb, line 138 138: def each 139: @store.each do |key, value| 140: yield(key, value) 141: end 142: end
# File lib/soap/property.rb, line 71 71: def load(stream) 72: key_prefix = "" 73: stream.each_with_index do |line, lineno| 74: line.sub!(/\r?\n\z/, '') 75: case line 76: when COMMENT_REGEXP 77: next 78: when CATDEF_REGEXP 79: key_prefix = $1.strip 80: when LINE_REGEXP 81: key, value = $1.strip, $2.strip 82: key = "#{key_prefix}.#{key}" unless key_prefix.empty? 83: key, value = loadstr(key), loadstr(value) 84: self[key] = value 85: else 86: raise TypeError.new( 87: "property format error at line #{lineno + 1}: `#{line}'") 88: end 89: end 90: self 91: end
find property from $:.
# File lib/soap/property.rb, line 94 94: def loadproperty(propname) 95: return loadpropertyfile(propname) if File.file?(propname) 96: $:.each do |path| 97: if File.file?(file = File.join(path, propname)) 98: return loadpropertyfile(file) 99: end 100: end 101: nil 102: end
# File lib/soap/property.rb, line 156 156: def lock(cascade = false) 157: if cascade 158: each_key do |key| 159: key.lock(cascade) 160: end 161: end 162: @locked = true 163: self 164: end
# File lib/soap/property.rb, line 166 166: def unlock(cascade = false) 167: @locked = false 168: if cascade 169: each_key do |key| 170: key.unlock(cascade) 171: end 172: end 173: self 174: end
# File lib/soap/property.rb, line 182 182: def deref_key(key) 183: check_lock(key) 184: ref = @store[key] ||= self.class.new 185: unless propkey?(ref) 186: raise ArgumentError.new("key `#{key}' already defined as a value") 187: end 188: ref 189: end
# File lib/soap/property.rb, line 199 199: def local_assign(key, value) 200: check_lock(key) 201: if @locked 202: if propkey?(value) 203: raise FrozenError.new("cannot add any key to locked property") 204: elsif propkey?(@store[key]) 205: raise FrozenError.new("cannot override any key in locked property") 206: end 207: end 208: @store[key] = value 209: end
# File lib/soap/property.rb, line 219 219: def local_assign_hook(key, cascade, &hook) 220: check_lock(key) 221: @store[key] ||= nil 222: (@hook[key] ||= []) << [hook, cascade] 223: end
# File lib/soap/property.rb, line 211 211: def local_hook(key, direct) 212: hooks = [] 213: (@self_hook + (@hook[key] || NO_HOOK)).each do |hook, cascade| 214: hooks << hook if direct or cascade 215: end 216: hooks 217: end
# File lib/soap/property.rb, line 191 191: def local_referent(key) 192: check_lock(key) 193: if propkey?(@store[key]) and @store[key].locked? 194: raise FrozenError.new("cannot split any key from locked property") 195: end 196: @store[key] 197: end
# File lib/soap/property.rb, line 235 235: def assign(ary, value) 236: ref = self 237: hook = NO_HOOK 238: ary[0..-2].each do |name| 239: key = to_key(name) 240: hook += ref.local_hook(key, false) 241: ref = ref.deref_key(key) 242: end 243: last_key = to_key(ary.last) 244: ref.local_assign(last_key, value) 245: hook + ref.local_hook(last_key, true) 246: end
# File lib/soap/property.rb, line 248 248: def assign_hook(ary, cascade, &hook) 249: ary[0..-2].inject(self) { |ref, name| 250: ref.deref_key(to_key(name)) 251: }.local_assign_hook(to_key(ary.last), cascade, &hook) 252: end
# File lib/soap/property.rb, line 254 254: def assign_self_hook(cascade, &hook) 255: check_lock(nil) 256: @self_hook << [hook, cascade] 257: end
# File lib/soap/property.rb, line 267 267: def check_lock(key) 268: if @locked and (key.nil? or !@store.key?(key)) 269: raise FrozenError.new("cannot add any key to locked property") 270: end 271: end
# File lib/soap/property.rb, line 259 259: def each_key 260: self.each do |key, value| 261: if propkey?(value) 262: yield(value) 263: end 264: end 265: end
# File lib/soap/property.rb, line 294 294: def generate_new_key 295: if @store.empty? 296: "0" 297: else 298: (key_max + 1).to_s 299: end 300: end
# File lib/soap/property.rb, line 302 302: def key_max 303: (@store.keys.max { |l, r| l.to_s.to_i <=> r.to_s.to_i }).to_s.to_i 304: end
# File lib/soap/property.rb, line 306 306: def loadpropertyfile(file) 307: puts "find property at #{file}" if $DEBUG 308: File.open(file) do |f| 309: load(f) 310: end 311: end
# File lib/soap/property.rb, line 313 313: def loadstr(str) 314: str.gsub(/\\./) { |c| eval("\"#{c}\"") } 315: end
# File lib/soap/property.rb, line 277 277: def name_to_a(name) 278: case name 279: when Symbol 280: [name] 281: when String 282: name.scan(/[^.\\]+(?:\\.[^.\\])*/) # split with unescaped '.' 283: when Array 284: name 285: else 286: raise ArgumentError.new("Unknown name #{name}(#{name.class})") 287: end 288: end
# File lib/soap/property.rb, line 273 273: def propkey?(value) 274: value.is_a?(::SOAP::Property) 275: end
# File lib/soap/property.rb, line 229 229: def referent(ary) 230: ary[0..-2].inject(self) { |ref, name| 231: ref.deref_key(to_key(name)) 232: }.local_referent(to_key(ary.last)) 233: end