| 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