sdl4r 0.9.2 → 0.9.3
Sign up to get free protection for your applications and to get access to all the features.
- data/README +79 -6
- data/Rakefile +15 -2
- data/TODO.txt +37 -6
- data/doc/created.rid +1 -1
- data/doc/fr_class_index.html +0 -4
- data/doc/fr_method_index.html +78 -111
- data/lib/sdl4r/parser.rb +32 -20
- data/lib/sdl4r/parser/reader.rb +3 -1
- data/lib/sdl4r/parser/time_span_with_zone.rb +3 -1
- data/lib/sdl4r/parser/token.rb +3 -1
- data/lib/sdl4r/parser/tokenizer.rb +3 -1
- data/lib/sdl4r/sdl.rb +41 -18
- data/lib/sdl4r/sdl_binary.rb +4 -4
- data/lib/sdl4r/sdl_parse_error.rb +4 -2
- data/lib/sdl4r/sdl_time_span.rb +18 -50
- data/lib/sdl4r/tag.rb +246 -356
- data/test/sdl4r/parser_test.rb +2 -0
- data/test/sdl4r/{test.rb → sdl4r_test.rb} +9 -7
- data/test/sdl4r/tag_test.rb +487 -0
- metadata +48 -49
data/lib/sdl4r/parser/reader.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
#--
|
1
2
|
# Simple Declarative Language (SDL) for Ruby
|
2
3
|
# Copyright 2005 Ikayzo, inc.
|
3
4
|
#
|
@@ -12,6 +13,7 @@
|
|
12
13
|
# You should have received a copy of the GNU Lesser General Public License
|
13
14
|
# along with this program; if not, contact the Free Software Foundation, Inc.,
|
14
15
|
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
16
|
+
#++
|
15
17
|
|
16
18
|
module SDL4R
|
17
19
|
|
@@ -20,7 +22,7 @@ module SDL4R
|
|
20
22
|
# Gives access to the characters read to the Parser.
|
21
23
|
# This class was designed to gather the handling of the UTF-8 issues in one place and shield the
|
22
24
|
# Parser class from these problems.
|
23
|
-
class Reader
|
25
|
+
class Reader # :nodoc: all
|
24
26
|
|
25
27
|
RUBY_1_8_OR_LESS = require 'jcode'
|
26
28
|
|
@@ -1,3 +1,4 @@
|
|
1
|
+
#--
|
1
2
|
# Simple Declarative Language (SDL) for Ruby
|
2
3
|
# Copyright 2005 Ikayzo, inc.
|
3
4
|
#
|
@@ -12,6 +13,7 @@
|
|
12
13
|
# You should have received a copy of the GNU Lesser General Public License
|
13
14
|
# along with this program; if not, contact the Free Software Foundation, Inc.,
|
14
15
|
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
16
|
+
#++
|
15
17
|
|
16
18
|
module SDL4R
|
17
19
|
|
@@ -22,7 +24,7 @@ module SDL4R
|
|
22
24
|
#
|
23
25
|
# +seconds+ can have a fraction
|
24
26
|
# +time_zone_offset+ is a fraction of a day (equal to nil if not specified)
|
25
|
-
class TimeSpanWithZone
|
27
|
+
class TimeSpanWithZone # :nodoc: all
|
26
28
|
|
27
29
|
private
|
28
30
|
|
data/lib/sdl4r/parser/token.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
#--
|
1
2
|
# Simple Declarative Language (SDL) for Ruby
|
2
3
|
# Copyright 2005 Ikayzo, inc.
|
3
4
|
#
|
@@ -12,6 +13,7 @@
|
|
12
13
|
# You should have received a copy of the GNU Lesser General Public License
|
13
14
|
# along with this program; if not, contact the Free Software Foundation, Inc.,
|
14
15
|
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
16
|
+
#++
|
15
17
|
|
16
18
|
module SDL4R
|
17
19
|
|
@@ -23,7 +25,7 @@ module SDL4R
|
|
23
25
|
#
|
24
26
|
# @author Daniel Leuck, Philippe Vosges
|
25
27
|
#
|
26
|
-
class Token
|
28
|
+
class Token # :nodoc: all
|
27
29
|
|
28
30
|
def initialize(text, line = -1, position = -1)
|
29
31
|
@text = text
|
@@ -1,3 +1,4 @@
|
|
1
|
+
#--
|
1
2
|
# Simple Declarative Language (SDL) for Ruby
|
2
3
|
# Copyright 2005 Ikayzo, inc.
|
3
4
|
#
|
@@ -12,6 +13,7 @@
|
|
12
13
|
# You should have received a copy of the GNU Lesser General Public License
|
13
14
|
# along with this program; if not, contact the Free Software Foundation, Inc.,
|
14
15
|
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
16
|
+
#++
|
15
17
|
|
16
18
|
|
17
19
|
module SDL4R
|
@@ -22,7 +24,7 @@ module SDL4R
|
|
22
24
|
class Parser
|
23
25
|
|
24
26
|
# Tokenizer of the SDL parser
|
25
|
-
class Tokenizer
|
27
|
+
class Tokenizer # :nodoc: all
|
26
28
|
|
27
29
|
TOKEN_TYPES = [
|
28
30
|
:IDENTIFIER,
|
data/lib/sdl4r/sdl.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
#--
|
1
2
|
# Simple Declarative Language (SDL) for Ruby
|
2
3
|
# Copyright 2005 Ikayzo, inc.
|
3
4
|
#
|
@@ -12,24 +13,16 @@
|
|
12
13
|
# You should have received a copy of the GNU Lesser General Public License
|
13
14
|
# along with this program; if not, contact the Free Software Foundation, Inc.,
|
14
15
|
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
15
|
-
|
16
|
+
#++
|
16
17
|
|
17
18
|
require 'jcode'
|
18
19
|
require 'base64'
|
19
20
|
require 'rational'
|
20
21
|
require 'date'
|
21
22
|
|
22
|
-
#
|
23
|
+
# Gathers utility methods.
|
23
24
|
#
|
24
25
|
module SDL4R
|
25
|
-
|
26
|
-
# Creates and returns a tag named "root" and add all the tags specified in the given +input+.
|
27
|
-
#
|
28
|
-
# +input+:: String, IO, Pathname or URI.
|
29
|
-
#
|
30
|
-
def self.read(input)
|
31
|
-
Tag.new("root").read(input)
|
32
|
-
end
|
33
26
|
|
34
27
|
MAX_INTEGER_32 = 2**31 - 1
|
35
28
|
MIN_INTEGER_32 = -(2**31)
|
@@ -42,8 +35,7 @@ module SDL4R
|
|
42
35
|
# Creates an SDL string representation for a given object and returns it.
|
43
36
|
#
|
44
37
|
# +o+:: the object to format
|
45
|
-
# +add_quotes+:: indicates whether quotes will be added to Strings and characters
|
46
|
-
# (true by default)
|
38
|
+
# +add_quotes+:: indicates whether quotes will be added to Strings and characters (true by default)
|
47
39
|
# +line_prefix+:: the line prefix to use ("" by default)
|
48
40
|
# +indent+:: the indent string to use ("\t" by default)
|
49
41
|
#
|
@@ -130,7 +122,10 @@ module SDL4R
|
|
130
122
|
end
|
131
123
|
end
|
132
124
|
|
133
|
-
#
|
125
|
+
# Coerce the type to a standard SDL type or raises an ArgumentError.
|
126
|
+
#
|
127
|
+
# For the time being, just returns +o+ thus allowing to add anything to the SDL tags. This might
|
128
|
+
# not be allowed in the future.
|
134
129
|
#
|
135
130
|
def self.coerce_or_fail(o)
|
136
131
|
return o
|
@@ -138,10 +133,10 @@ module SDL4R
|
|
138
133
|
|
139
134
|
# Validates an SDL identifier String. SDL Identifiers must start with a
|
140
135
|
# Unicode letter or underscore (_) and contain only unicode letters,
|
141
|
-
# digits, underscores (_),
|
136
|
+
# digits, underscores (_), dashes(-) and periods (.).
|
142
137
|
#
|
143
|
-
#
|
144
|
-
#
|
138
|
+
# == Raises
|
139
|
+
# ArgumentError if the identifier is not legal
|
145
140
|
#
|
146
141
|
# TODO: support UTF-8 identifiers
|
147
142
|
#
|
@@ -173,8 +168,36 @@ module SDL4R
|
|
173
168
|
end
|
174
169
|
end
|
175
170
|
|
171
|
+
# Creates and returns a tag named "root" and add all the tags specified in the given +input+.
|
172
|
+
#
|
173
|
+
# +input+:: String, IO, Pathname or URI.
|
174
|
+
#
|
175
|
+
# root = SDL4R::read(<<EOF
|
176
|
+
# planets {
|
177
|
+
# earth area_km2=510900000
|
178
|
+
# mars
|
179
|
+
# }
|
180
|
+
# EOF
|
181
|
+
# )
|
182
|
+
#
|
183
|
+
# root = SDL4R::read(Pathname.new("my_dir/my_file.sdl"))
|
184
|
+
#
|
185
|
+
# IO.open("my_dir/my_file.sdl", "r") { |io|
|
186
|
+
# root = SDL4R::read(io)
|
187
|
+
# }
|
188
|
+
#
|
189
|
+
# root = SDL4R::read(URI.new("http://my_site/my_file.sdl"))
|
190
|
+
#
|
191
|
+
def self.read(input)
|
192
|
+
Tag.new("root").read(input)
|
193
|
+
end
|
194
|
+
|
176
195
|
# Parses and returns the value corresponding with the specified SDL literal.
|
177
196
|
#
|
197
|
+
# SDL4R.to_value("\"abcd\"") # => "abcd"
|
198
|
+
# SDL4R.to_value("1") # => 1
|
199
|
+
# SDL4R.to_value("null") # => nil
|
200
|
+
#
|
178
201
|
def self.to_value(s)
|
179
202
|
raise ArgumentError, "'s' cannot be null" if s.nil?
|
180
203
|
return read(s).child.value
|
@@ -185,7 +208,7 @@ module SDL4R
|
|
185
208
|
#
|
186
209
|
# Example
|
187
210
|
#
|
188
|
-
# array = SDL4R.
|
211
|
+
# array = SDL4R.to_value_array("1 true 12:24:01")
|
189
212
|
#
|
190
213
|
# Will return an int, a boolean, and a time span.
|
191
214
|
#
|
@@ -201,7 +224,7 @@ module SDL4R
|
|
201
224
|
#
|
202
225
|
# hash = SDL4R.to_attribute_hash("value=1 debugging=on time=12:24:01");
|
203
226
|
#
|
204
|
-
#
|
227
|
+
# # { "value" => 1, "debugging" => true, "time" => SdlTimeSpan.new(12, 24, 01) }
|
205
228
|
#
|
206
229
|
def self.to_attribute_map(s)
|
207
230
|
raise ArgumentError, "'s' cannot be null" if s.nil?
|
data/lib/sdl4r/sdl_binary.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
#--
|
1
2
|
# Simple Declarative Language (SDL) for Ruby
|
2
3
|
# Copyright 2005 Ikayzo, inc.
|
3
4
|
#
|
@@ -12,12 +13,13 @@
|
|
12
13
|
# You should have received a copy of the GNU Lesser General Public License
|
13
14
|
# along with this program; if not, contact the Free Software Foundation, Inc.,
|
14
15
|
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
16
|
+
#++
|
15
17
|
|
16
18
|
|
17
19
|
module SDL4R
|
18
20
|
|
19
|
-
#
|
20
21
|
# Represents a binary value.
|
22
|
+
#
|
21
23
|
# This class was introduced to avoid the confusion between a Ruby String and a binary literal.
|
22
24
|
#
|
23
25
|
class SdlBinary
|
@@ -35,9 +37,7 @@ module SDL4R
|
|
35
37
|
return self.bytes == o.bytes
|
36
38
|
end
|
37
39
|
|
38
|
-
|
39
|
-
self == o
|
40
|
-
end
|
40
|
+
alias_method :eql?, :==
|
41
41
|
|
42
42
|
def hash
|
43
43
|
return bytes.hash
|
@@ -1,8 +1,9 @@
|
|
1
|
+
#--
|
1
2
|
# Simple Declarative Language (SDL) for Ruby
|
2
3
|
# Copyright 2005 Ikayzo, inc.
|
3
4
|
#
|
4
|
-
# This program is free software. You can distribute or modify it under the
|
5
|
-
# terms of the GNU Lesser General Public License version 2.1 as published by
|
5
|
+
# This program is free software. You can distribute or modify it under the
|
6
|
+
# terms of the GNU Lesser General Public License version 2.1 as published by
|
6
7
|
# the Free Software Foundation.
|
7
8
|
#
|
8
9
|
# This program is distributed AS IS and WITHOUT WARRANTY. OF ANY KIND,
|
@@ -12,6 +13,7 @@
|
|
12
13
|
# You should have received a copy of the GNU Lesser General Public License
|
13
14
|
# along with this program; if not, contact the Free Software Foundation, Inc.,
|
14
15
|
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
16
|
+
#++
|
15
17
|
|
16
18
|
|
17
19
|
module SDL4R
|
data/lib/sdl4r/sdl_time_span.rb
CHANGED
@@ -1,8 +1,9 @@
|
|
1
|
+
#--
|
1
2
|
# Simple Declarative Language (SDL) for Ruby
|
2
3
|
# Copyright 2005 Ikayzo, inc.
|
3
4
|
#
|
4
|
-
# This program is free software. You can distribute or modify it under the
|
5
|
-
# terms of the GNU Lesser General Public License version 2.1 as published by
|
5
|
+
# This program is free software. You can distribute or modify it under the
|
6
|
+
# terms of the GNU Lesser General Public License version 2.1 as published by
|
6
7
|
# the Free Software Foundation.
|
7
8
|
#
|
8
9
|
# This program is distributed AS IS and WITHOUT WARRANTY. OF ANY KIND,
|
@@ -12,6 +13,7 @@
|
|
12
13
|
# You should have received a copy of the GNU Lesser General Public License
|
13
14
|
# along with this program; if not, contact the Free Software Foundation, Inc.,
|
14
15
|
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
16
|
+
#++
|
15
17
|
|
16
18
|
|
17
19
|
module SDL4R
|
@@ -123,120 +125,91 @@ module SDL4R
|
|
123
125
|
|
124
126
|
# Get the total number of hours in this time span. For example, if
|
125
127
|
# this time span represents two days, this method will return 48.
|
126
|
-
#
|
127
|
-
# @return This timespan in hours
|
128
128
|
#
|
129
129
|
def total_hours
|
130
130
|
return sign * (@totalMilliseconds.abs / MILLISECONDS_IN_HOUR)
|
131
131
|
end
|
132
132
|
|
133
|
-
#
|
134
133
|
# Get the total number of minutes in this time span. For example, if
|
135
134
|
# this time span represents two hours, this method will return 120.
|
136
|
-
#
|
137
|
-
# @return This timespan in minutes
|
138
135
|
#
|
139
136
|
def total_minutes
|
140
137
|
return sign * (@totalMilliseconds.abs / MILLISECONDS_IN_MINUTE)
|
141
138
|
end
|
142
139
|
|
143
|
-
#
|
144
140
|
# Get the total number of seconds in this time span. For example, if
|
145
141
|
# this time span represents three minutes, this method will return 180.
|
146
|
-
#
|
147
|
-
# @return This timespan in seconds
|
148
142
|
#
|
149
143
|
def total_seconds
|
150
144
|
return sign * (@totalMilliseconds.abs / MILLISECONDS_IN_SECOND)
|
151
145
|
end
|
152
146
|
|
153
|
-
#
|
154
147
|
# Get the total number of milliseconds in this time span. For example, if
|
155
148
|
# this time span represents 4 seconds, this method will return 4000.
|
156
|
-
#
|
157
|
-
# @return This timespan in milliseconds
|
158
149
|
#
|
159
150
|
def total_milliseconds
|
160
151
|
return @totalMilliseconds
|
161
152
|
end
|
162
153
|
|
163
|
-
#
|
164
154
|
# Returns an new SdlTimeSpan instance that is the opposite of this
|
165
155
|
# instance
|
166
|
-
#
|
167
|
-
# @return An instance representing the inverse of this instance
|
168
156
|
#
|
169
157
|
def negate
|
170
158
|
SdlTimeSpan.new(-@totalMilliseconds)
|
171
159
|
end
|
172
160
|
|
173
|
-
#
|
174
161
|
# Return a new instance with the days adjusted by the given amount.
|
175
|
-
# Positive numbers add days.
|
162
|
+
# Positive numbers add days. Negative numbers remove days.
|
176
163
|
#
|
177
|
-
#
|
178
|
-
# @return A new instance with the given adjustment.
|
164
|
+
# +days+:: The adjustment (days to add or subtract)
|
179
165
|
#
|
180
166
|
def roll_days(days)
|
181
167
|
SdlTimeSpan.new(@totalMilliseconds + (days * MILLISECONDS_IN_DAY))
|
182
168
|
end
|
183
169
|
|
184
|
-
#
|
185
170
|
# Return a new instance with the hours adjusted by the given amount.
|
186
171
|
# Positive numbers add hours. Negative numbers remove hours.
|
187
172
|
#
|
188
|
-
#
|
189
|
-
# @return A new instance with the given adjustment.
|
173
|
+
# +hours+:: The adjustment (hours to add or subtract)
|
190
174
|
#
|
191
175
|
def roll_hours(hours)
|
192
176
|
SdlTimeSpan.new(@totalMilliseconds + (hours * MILLISECONDS_IN_HOUR))
|
193
177
|
end
|
194
178
|
|
195
|
-
#
|
196
179
|
# Return a new instance with the minutes adjusted by the given amount.
|
197
180
|
# Positive numbers add minutes. Negative numbers remove minutes.
|
198
181
|
#
|
199
|
-
#
|
200
|
-
# @return A new instance with the given adjustment.
|
182
|
+
# +minutes+:: The adjustment (minutes to add or subtract)
|
201
183
|
#
|
202
184
|
def roll_minutes(minutes)
|
203
185
|
SdlTimeSpan.new(@totalMilliseconds + (minutes * MILLISECONDS_IN_MINUTE))
|
204
186
|
end
|
205
187
|
|
206
|
-
#
|
207
188
|
# Return a new instance with the seconds adjusted by the given amount.
|
208
189
|
# Positive numbers add seconds. Negative numbers remove seconds.
|
209
190
|
#
|
210
|
-
#
|
211
|
-
# @return A new instance with the given adjustment.
|
191
|
+
# +seconds+:: The adjustment (seconds to add or subtract)
|
212
192
|
#
|
213
193
|
def roll_seconds(seconds)
|
214
194
|
SdlTimeSpan.new(@totalMilliseconds + (seconds * MILLISECONDS_IN_SECOND))
|
215
195
|
end
|
216
196
|
|
217
|
-
#
|
218
197
|
# Return a new instance with the milliseconds adjusted by the given amount.
|
219
198
|
# Positive numbers add milliseconds. Negative numbers remove milliseconds.
|
220
199
|
#
|
221
|
-
#
|
222
|
-
# @return A new instance with the given adjustment.
|
200
|
+
# +milliseconds+:: The adjustment (milliseconds to add or subtract)
|
223
201
|
#
|
224
202
|
def roll_milliseconds(milliseconds)
|
225
203
|
SdlTimeSpan.new(@totalMilliseconds + milliseconds)
|
226
204
|
end
|
227
205
|
|
228
|
-
#
|
229
206
|
# A hashcode based on the canonical string representation.
|
230
|
-
#
|
231
|
-
# @return A hashcode for this time span
|
232
207
|
#
|
233
208
|
def hash
|
234
209
|
to_s.hash
|
235
210
|
end
|
236
211
|
|
237
212
|
# Tests for equivalence.
|
238
|
-
#
|
239
|
-
# @return true If the given object is equivalent
|
240
213
|
#
|
241
214
|
def eql?(other)
|
242
215
|
other.is_a?(SdlTimeSpan) and @totalMilliseconds == other.total_milliseconds
|
@@ -249,27 +222,22 @@ module SDL4R
|
|
249
222
|
@totalMilliseconds <=> other.total_milliseconds
|
250
223
|
end
|
251
224
|
|
252
|
-
#
|
225
|
+
# Returns an SDL representation of this time span using the format:
|
253
226
|
#
|
254
|
-
#
|
255
|
-
# (days:)hours:minutes:seconds(.milliseconds)
|
256
|
-
# </pre>
|
227
|
+
# (days:)hours:minutes:seconds(.milliseconds)
|
257
228
|
#
|
258
|
-
#
|
229
|
+
# (parenthesis indicate optional components)
|
259
230
|
#
|
260
|
-
#
|
261
|
-
# are set to 0. Days must be suffixed with "d" for clarity
|
231
|
+
# The days and milliseconds components will not be included if they
|
232
|
+
# are set to 0. Days must be suffixed with "d" for clarity.
|
262
233
|
#
|
263
|
-
#
|
234
|
+
# Hours, minutes, and seconds will be zero paded to two characters.
|
235
|
+
#
|
236
|
+
# Examples:
|
264
237
|
#
|
265
|
-
# <p>Examples:</p>
|
266
|
-
# <pre>
|
267
238
|
# 23:13:00 (12 hours and 13 minutes)
|
268
239
|
# 24d:12:13:09.234 (24 days, 12 hours, 13 minutes, 9 seconds,
|
269
240
|
# 234 milliseconds)
|
270
|
-
# </pre>
|
271
|
-
#
|
272
|
-
# @return an SDL representation of this time span
|
273
241
|
#
|
274
242
|
def to_s
|
275
243
|
_days = days
|
data/lib/sdl4r/tag.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
#--
|
1
2
|
# Simple Declarative Language (SDL) for Ruby
|
2
3
|
# Copyright 2005 Ikayzo, inc.
|
3
4
|
#
|
@@ -12,6 +13,7 @@
|
|
12
13
|
# You should have received a copy of the GNU Lesser General Public License
|
13
14
|
# along with this program; if not, contact the Free Software Foundation, Inc.,
|
14
15
|
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
16
|
+
#++
|
15
17
|
|
16
18
|
|
17
19
|
module SDL4R
|
@@ -23,306 +25,81 @@ module SDL4R
|
|
23
25
|
require File.dirname(__FILE__) + '/sdl'
|
24
26
|
require File.dirname(__FILE__) + '/parser'
|
25
27
|
|
26
|
-
# SDL
|
27
|
-
# contains
|
28
|
-
#
|
29
|
-
# * a name (if not present, the name "content" is used)
|
30
|
-
# * a namespace (optional)
|
31
|
-
# * 0 or more values (optional)
|
32
|
-
# * 0 or more attributes (optional)
|
33
|
-
# * 0 or more children (optional)
|
34
|
-
#
|
35
|
-
# For the SDL code:
|
36
|
-
#
|
37
|
-
# size 4
|
38
|
-
# smoker false
|
39
|
-
#
|
40
|
-
#
|
41
|
-
# Assuming this code is in a file called values.sdl, the values can be read
|
42
|
-
# using the following code (ignoring exceptions):
|
43
|
-
#
|
44
|
-
# root = Tag.new("root").read(new File("values.sdl"));
|
45
|
-
# int size = root.getChild("size").intValue();
|
46
|
-
# boolean smoker = root.getChild("smoker").booleanValue();
|
47
|
-
#
|
48
|
-
# A tag is basically a data structure with a list of values, a map of
|
49
|
-
# attributes, and (if it has a body) child tags. In the example above, the
|
50
|
-
# "values.sdl" file is read into a tag called "root". It has two children
|
51
|
-
# (tags) called "size" and "smoker". Both these children have one value, no
|
52
|
-
# attributes, and no bodies.
|
53
|
-
#
|
54
|
-
# SDL is often used for simple key-value mappings. To simplify things Tag
|
55
|
-
# has the methods getValue and setValue which operate on the first element in
|
56
|
-
# the values list. Also notice SDL understands types which are determined
|
57
|
-
# using type inference.
|
58
|
-
#
|
59
|
-
# The example above used the simple format common in property files:
|
60
|
-
#
|
61
|
-
# name value
|
62
|
-
#
|
63
|
-
# The full SDL tag format is:
|
64
|
-
#
|
65
|
-
# namespace:name value_list attribute_list {
|
66
|
-
# children_tags
|
67
|
-
# }
|
68
|
-
#
|
69
|
-
# where value_list is zero or more space separated SDL literals and
|
70
|
-
# attribute_list is zero or more space separated (namespace:)key=value pairs.
|
71
|
-
# The name, namespace, and keys are SDL identifiers. Values are SDL literals.
|
72
|
-
# Namespace is optional for both tag names and attributes. Tag bodies are also
|
73
|
-
# optional. SDL identifiers begin with a unicode letter or an underscore (_)
|
74
|
-
# followed by zero or more unicode letters, numbers, underscores (_) and
|
75
|
-
# dashes (-).
|
76
|
-
#
|
77
|
-
# SDL also supports anonymous tags which are assigned the name "content".
|
78
|
-
# An annoymous tag starts with a literal and is followed by zero or more
|
79
|
-
# additional literals and zero or more attributes. The examples section below
|
80
|
-
# demonstrates the use of anonymous tags.
|
81
|
-
#
|
82
|
-
# Tags without bodies are terminated by a new line character (\n) and may be
|
83
|
-
# continue onto the next line by placing a backslash (\) at the end of the
|
84
|
-
# line. Tags may be nested to an arbitrary depth. SDL ignores all other white
|
85
|
-
# space characters between tokens. Although nested blocks are indented by
|
86
|
-
# convention, tabs have no significance in the language.
|
87
|
-
#
|
88
|
-
# There are two ways to write String literals.
|
89
|
-
#
|
90
|
-
# 1. Starting and ending with double quotes ("). Double quotes, backslash
|
91
|
-
# characters (\), and new lines (\n) within this type of String literal
|
92
|
-
# must be escaped like so:
|
93
|
-
#
|
94
|
-
# file "C:\\folder\\file.txt"
|
95
|
-
# say "I said \"something\""
|
96
|
-
#
|
97
|
-
# This type of String literal can be continued on the next line by placing a
|
98
|
-
# backslash (\) at the end of the line like so:
|
99
|
-
#
|
100
|
-
# line "this is a \
|
101
|
-
# long string of text"
|
102
|
-
#
|
103
|
-
# White space before the first character in the second line will be ignored.
|
104
|
-
#
|
105
|
-
# 2. Starting and ending with a backquote (`). This type of string literal
|
106
|
-
# can only be ended with a second backquote (`). It is not necessary (or
|
107
|
-
# possible) to escape any type of character within a backquote string
|
108
|
-
# literal. This type of literal can also span lines. All white spaces are
|
109
|
-
# preserved including new lines.
|
110
|
-
#
|
111
|
-
# Examples:
|
112
|
-
#
|
113
|
-
# file `C:\folder\file.txt`
|
114
|
-
# say `I said "something"`
|
115
|
-
# regex `\w+\.suite\(\)`
|
116
|
-
# long_line `This is
|
117
|
-
# a long line
|
118
|
-
# fee fi fo fum`
|
119
|
-
#
|
120
|
-
# Note: SDL interprets new lines in `` String literals as a single new line
|
121
|
-
# character (\n) regarless of the platform.
|
122
|
-
#
|
123
|
-
# Binary literals use base64 characters enclosed in square brackets ([]).
|
124
|
-
# The binary literal type can also span lines. White space is ignored.
|
125
|
-
#
|
126
|
-
#
|
127
|
-
# Examples:
|
128
|
-
# key [sdf789GSfsb2+3324sf2] name="my key"
|
129
|
-
# image [
|
130
|
-
# R3df789GSfsb2edfSFSDF
|
131
|
-
# uikuikk2349GSfsb2edfS
|
132
|
-
# vFSDFR3df789GSfsb2edf
|
133
|
-
# ]
|
134
|
-
# upload from="ikayzo.com" data=[
|
135
|
-
# R3df789GSfsb2edfSFSDF
|
136
|
-
# uikuikk2349GSfsb2edfS
|
137
|
-
# vFSDFR3df789GSfsb2edf
|
138
|
-
# ]
|
139
|
-
#
|
140
|
-
# SDL supports date, time span, and date/time literals. Date and Date/Time
|
141
|
-
# literals use a 24 hour clock (0-23). If a timezone is not specified, the
|
142
|
-
# default locale's timezone will be used.
|
28
|
+
# SDL documents are made of Tags.
|
143
29
|
#
|
144
|
-
#
|
145
|
-
#
|
146
|
-
#
|
147
|
-
#
|
148
|
-
#
|
149
|
-
#
|
150
|
-
#
|
151
|
-
#
|
152
|
-
#
|
153
|
-
# short_time 00:12:32.423 # 12 minutes, 32 seconds, 423 milliseconds
|
154
|
-
# long_time 30d:15:23:04.023 # 30 days, 15 hours, 23 mins, 4 secs, 23 millis
|
155
|
-
# before -00:02:30 # 2 hours and 30 minutes ago
|
156
|
-
#
|
157
|
-
# # a date time literal
|
158
|
-
# in_japan 2005/12/05 14:12:23.345-JST
|
159
|
-
#
|
160
|
-
#
|
161
|
-
# SDL 1.0 has thirteen literal types (parenthesis indicate optional components)
|
162
|
-
#
|
163
|
-
# 1. string (unicode) - examples: "hello" or `aloha`
|
164
|
-
# 2. character (unicode) - example: '/'
|
165
|
-
# Note: \uXXXX style unicode escapes are not supported (or
|
166
|
-
# needed because sdl files are UTF8)
|
167
|
-
# 3. integer (32 bits signed) - example: 123
|
168
|
-
# 4. long integer (64 bits signed) - examples: 123L or 123l
|
169
|
-
# 5. float (32 bits signed) - examples 123.43F 123.43f
|
170
|
-
# 6. double float (64 bits signed) - example: 123.43 or 123.43d or 123.43D
|
171
|
-
# 7. decimal (128+ bits signed) - example: 123.44BD or 123.44bd
|
172
|
-
# 8. boolean - examples: true or false or on or off
|
173
|
-
# 9. date yyyy/mm/dd - example 2005/12/05
|
174
|
-
# 10. date time yyyy/mm/dd hh:mm(:ss)(.xxx)(-ZONE)
|
175
|
-
# example - 2005/12/05 05:21:23.532-JST
|
176
|
-
# notes: uses a 24 hour clock (0-23), only hours and minutes are
|
177
|
-
# mandatory
|
178
|
-
# 11. time span using the format (d:)hh:mm:ss(.xxx)
|
179
|
-
# notes: if the day component is included it must be suffixed with
|
180
|
-
# a lower case 'd'
|
181
|
-
# examples 12:14:42 (12 hours, 14 minutes, 42 seconds)
|
182
|
-
# 00:09:12 (9 minutes, 12 seconds)
|
183
|
-
# 00:00:01.023 (1 second, 23 milliseconds)
|
184
|
-
# 23d:05:21:23.532 (23 days, 5 hours, 21 minutes,
|
185
|
-
# 23 seconds, 532 milliseconds)
|
186
|
-
# 12. binary [base64] exmaple - [sdf789GSfsb2+3324sf2]
|
187
|
-
# 13. null
|
188
|
-
#
|
189
|
-
#
|
190
|
-
# Timezones must be specified using a valid time zone ID (ex. America/Los_Angeles), three letter
|
191
|
-
# abbreviation (ex. HST), or GMT(+/-)hh(:mm) formatted custom timezone (ex. GMT+02 or GMT+02:30)
|
192
|
-
#
|
193
|
-
# Note: SDL 1.1 will likely add a reference literal type.
|
194
|
-
#
|
195
|
-
# These types are designed to be portable across Java, .NET, and other
|
196
|
-
# popular platforms.
|
197
|
-
#
|
198
|
-
#
|
199
|
-
# SDL supports four comment types.
|
200
|
-
#
|
201
|
-
# 1. // single line comments identicle to those used in Java, C, etc. // style
|
202
|
-
# comments can occur anywhere in a line. All text after // up to the new line
|
203
|
-
# will be ignored.
|
204
|
-
# 2. # property style comments. They work the same way as //
|
205
|
-
# 3. -- separator comments useful for visually dividing content. They work the same way as //
|
206
|
-
# 4. Slash star (/*) style multiline comments. These begin with a slash
|
207
|
-
# star and end with a star slash. Everything in between is ignored.
|
208
|
-
#
|
209
|
-
#
|
210
|
-
#
|
211
|
-
# An example SDL file:
|
212
|
-
#
|
213
|
-
# # a tag having only a name
|
214
|
-
# my_tag
|
215
|
-
#
|
216
|
-
# # three tags acting as name value pairs
|
217
|
-
# first_name "Akiko"
|
218
|
-
# last_name "Johnson"
|
219
|
-
# height 68
|
220
|
-
#
|
221
|
-
# # a tag with a value list
|
222
|
-
# person "Akiko" "Johnson" 68
|
223
|
-
#
|
224
|
-
# # a tag with attributes
|
225
|
-
# person first_name="Akiko" last_name="Johnson" height=68
|
226
|
-
#
|
227
|
-
# # a tag with values and attributes
|
228
|
-
# person "Akiko" "Johnson" height=60
|
229
|
-
#
|
230
|
-
# # a tag with attributes using namespaces
|
231
|
-
# person name:first-name="Akiko" name:last-name="Johnson"
|
232
|
-
#
|
233
|
-
# # a tag with values, attributes, namespaces, and children
|
234
|
-
# my_namespace:person "Akiko" "Johnson" dimensions:height=68 {
|
235
|
-
# son "Nouhiro" "Johnson"
|
236
|
-
# daughter "Sabrina" "Johnson" location="Italy" {
|
237
|
-
# hobbies "swimming" "surfing"
|
238
|
-
# languages "English" "Italian"
|
239
|
-
# smoker false
|
240
|
-
# }
|
241
|
-
# }
|
242
|
-
#
|
243
|
-
# ------------------------------------------------------------------
|
244
|
-
# // (notice the separator style comment above...)
|
245
|
-
#
|
246
|
-
# # a log entry
|
247
|
-
# # note - this tag has two values (date_time and string) and an
|
248
|
-
# # attribute (error)
|
249
|
-
# entry 2005/11/23 10:14:23.253-GMT "Something bad happened" error=true
|
250
|
-
#
|
251
|
-
# # a long line
|
252
|
-
# mylist "something" "another" true "shoe" 2002/12/13 "rock" \
|
253
|
-
# "morestuff" "sink" "penny" 12:15:23.425
|
254
|
-
#
|
255
|
-
# # a long string
|
256
|
-
# text "this is a long rambling line of text with a continuation \
|
257
|
-
# and it keeps going and going..."
|
258
|
-
#
|
259
|
-
# # anonymous tag examples
|
260
|
-
#
|
261
|
-
# files {
|
262
|
-
# "/folder1/file.txt"
|
263
|
-
# "/file2.txt"
|
264
|
-
# }
|
265
|
-
#
|
266
|
-
# # To retrieve the files as a list of strings
|
267
|
-
# #
|
268
|
-
# # List files = tag.getChild("files").getChildrenValues("content");
|
269
|
-
# #
|
270
|
-
# # We us the name "content" because the files tag has two children, each of
|
271
|
-
# # which are anonymous tags (values with no name.) These tags are assigned
|
272
|
-
# # the name "content"
|
273
|
-
#
|
274
|
-
# matrix {
|
275
|
-
# 1 2 3
|
276
|
-
# 4 5 6
|
277
|
-
# }
|
278
|
-
#
|
279
|
-
# # To retrieve the values from the matrix (as a list of lists)
|
280
|
-
# #
|
281
|
-
# # List rows = tag.getChild("matrix").getChildrenValues("content");
|
282
|
-
#
|
283
|
-
#
|
284
|
-
# Example of getting the "location" attribute from the "daughter" tag
|
285
|
-
# above (ignoring exceptions)
|
286
|
-
#
|
287
|
-
# Tag root = new Tag("root").read("myfile.sdl");
|
288
|
-
# Tag daughter = root.getChild("daughter", true); // recursive search
|
289
|
-
# String location = daughter.getAttribute("location").toString();
|
290
|
-
#
|
291
|
-
# SDL is normally stored in a file with the .sdl extension. These files
|
292
|
-
# should always be encoded using UTF8. SDL fully supports unicode in
|
293
|
-
# identifiers and literals.
|
294
|
-
#
|
295
|
-
# @author Daniel Leuck
|
30
|
+
# Do not assume that methods returning sets (Hash, Array, etc) of children/values/attributes/etc
|
31
|
+
# in this class returns copies or implementations. It can be one or the other depending on the
|
32
|
+
# method. The implementations are designed to be fast and correct, not too protect the Tag
|
33
|
+
# instances from ill-use of the returned values.
|
34
|
+
#
|
35
|
+
# See the README[link:files/README.html] for a longer explanation on SDL documents.
|
36
|
+
#
|
37
|
+
# == Authors
|
38
|
+
# Daniel Leuck, Philippe Vosges
|
296
39
|
#
|
297
40
|
class Tag
|
298
41
|
|
299
|
-
#
|
300
42
|
# the name of this Tag
|
301
43
|
#
|
302
44
|
attr_reader :name
|
303
45
|
|
304
|
-
#
|
305
|
-
#
|
46
|
+
# the namespace of this Tag or an empty string when there is no namespace (i.e. default
|
47
|
+
# namespace).
|
306
48
|
#
|
307
49
|
attr_reader :namespace
|
50
|
+
|
51
|
+
# Convenient method to check and handle a pair of parameters namespace/name where, in some
|
52
|
+
# cases, only one is specified (i.e. the name only).
|
53
|
+
#
|
54
|
+
# Use at the beginning of a method in order to have correctly defined parameters:
|
55
|
+
# def foo(namespace, name = nil)
|
56
|
+
# namespace, name = to_nns namespace, name
|
57
|
+
# end
|
58
|
+
#
|
59
|
+
def to_nns(namespace, name)
|
60
|
+
if name.nil? and not namespace.nil?
|
61
|
+
name = namespace
|
62
|
+
namespace = ""
|
63
|
+
end
|
64
|
+
return namespace, name
|
65
|
+
end
|
66
|
+
private :to_nns
|
308
67
|
|
309
|
-
# Creates an empty tag in the given namespace. If the +namespace+ is
|
68
|
+
# Creates an empty tag in the given namespace. If the +namespace+ is nil
|
310
69
|
# it will be coerced to an empty String.
|
311
70
|
#
|
312
|
-
#
|
313
|
-
#
|
314
|
-
#
|
315
|
-
#
|
316
|
-
#
|
71
|
+
# tag = Tag.new("name")
|
72
|
+
# tag = Tag.new("namespace", "name")
|
73
|
+
#
|
74
|
+
# tag = Tag.new("fruit") do
|
75
|
+
# add_value 2
|
76
|
+
# new_child("orange") do
|
77
|
+
# set_attribute("quantity", 2)
|
78
|
+
# end
|
79
|
+
# end
|
80
|
+
#
|
81
|
+
# which builds the following SDL structure
|
82
|
+
#
|
83
|
+
# fruit 2 {
|
84
|
+
# orange quantity=2
|
85
|
+
# }
|
86
|
+
#
|
87
|
+
# ==Raises
|
88
|
+
# ArgumentError if the name is not a legal SDL identifier
|
89
|
+
# (see SDL4R#validate_identifier) or the namespace is non-blank
|
317
90
|
# and is not a legal SDL identifier.
|
318
91
|
#
|
319
|
-
def initialize(
|
320
|
-
namespace = namespace
|
92
|
+
def initialize(namespace, name = nil, &block)
|
93
|
+
namespace, name = to_nns namespace, name
|
94
|
+
|
95
|
+
raise ArgumentError, "tag namespace must be a String" unless namespace.is_a? String
|
96
|
+
raise ArgumentError, "tag name must be a String" unless name.is_a? String
|
97
|
+
|
321
98
|
SDL4R.validate_identifier(namespace) unless namespace.empty?
|
322
99
|
@namespace = namespace
|
323
100
|
|
324
101
|
name = name.to_s.strip
|
325
|
-
raise ArgumentError, "Tag name cannot be
|
102
|
+
raise ArgumentError, "Tag name cannot be nil or empty" if name.empty?
|
326
103
|
SDL4R.validate_identifier(name)
|
327
104
|
@name = name
|
328
105
|
|
@@ -366,9 +143,26 @@ module SDL4R
|
|
366
143
|
|
367
144
|
# Adds the given object as a child if it is a +Tag+, as an attribute if it is a Hash
|
368
145
|
# {key => value} (supports namespaces), or as a value otherwise.
|
146
|
+
# If it is an array, each of its elements is added to this Tag via this operator. If any of its
|
147
|
+
# elements is itself an array, then an anonymous tag is created and the array is passed to it
|
148
|
+
# via this operator (see the examples below)
|
149
|
+
#
|
150
|
+
# tag << Tag.new("child")
|
151
|
+
# tag << 123 # new integer value
|
152
|
+
# tag << "islamabad" # new string value
|
153
|
+
# tag << { "metric:length" => 1027 } # new attribute (with namespace)
|
154
|
+
# tag << [nil, 456, "abc"] # several values added
|
155
|
+
#
|
156
|
+
# tag = Tag.new("tag")
|
157
|
+
# tag << [[1, 2, 3], [4, 5, 6]] # tag {
|
158
|
+
# # 1 2 3
|
159
|
+
# # 4 5 6
|
160
|
+
# # }
|
369
161
|
#
|
370
162
|
# Returns +self+.
|
371
163
|
#
|
164
|
+
# Use other accessors for a stricter and less "magical" behavior.
|
165
|
+
#
|
372
166
|
def <<(o)
|
373
167
|
if o.is_a?(Tag)
|
374
168
|
add_child(o)
|
@@ -376,7 +170,16 @@ module SDL4R
|
|
376
170
|
o.each_pair { |key, value|
|
377
171
|
namespace, key = key.split(/:/) if key.match(/:/)
|
378
172
|
namespace ||= ""
|
379
|
-
set_attribute(key, value
|
173
|
+
set_attribute(namespace, key, value)
|
174
|
+
}
|
175
|
+
elsif o.is_a? Array
|
176
|
+
o.each { |item|
|
177
|
+
if item.is_a? Array
|
178
|
+
anonymous = new_child("content")
|
179
|
+
anonymous << item
|
180
|
+
else
|
181
|
+
self << item
|
182
|
+
end
|
380
183
|
}
|
381
184
|
else
|
382
185
|
add_value(o)
|
@@ -424,16 +227,34 @@ module SDL4R
|
|
424
227
|
@children.size
|
425
228
|
end
|
426
229
|
|
427
|
-
#
|
230
|
+
# children(recursive)
|
231
|
+
# children(recursive, name)
|
232
|
+
# children(recursive, namespace, name)
|
233
|
+
#
|
234
|
+
# children(recursive) { |child| ... }
|
235
|
+
# children(recursive, name) { |child| ... }
|
236
|
+
# children(recursive, namespace, name) { |child| ... }
|
237
|
+
#
|
238
|
+
# Returns an Array of the children Tags of this Tag or enumerates them.
|
428
239
|
#
|
429
240
|
# +recursive+:: if true children and all descendants will be returned. False by default.
|
430
241
|
# +name+:: if not nil, only children having this name will be returned. Nil by default.
|
431
|
-
# +namespace+::
|
432
|
-
# Nil by default.
|
242
|
+
# +namespace+:: use nil for all namespaces and "" for the default one. Nil by default.
|
433
243
|
#
|
434
|
-
|
244
|
+
# tag.children # => array of the children
|
245
|
+
# tag.children(true) { |descendant| ... }
|
246
|
+
#
|
247
|
+
# tag.children(false, "name") # => children of name "name"
|
248
|
+
# tag.children(false, "ns", nil) # => children of namespace "ns"
|
249
|
+
#
|
250
|
+
def children(recursive = false, namespace = nil, name = :DEFAULT, &block) # :yields: child
|
251
|
+
if name == :DEFAULT
|
252
|
+
name = namespace
|
253
|
+
namespace = nil
|
254
|
+
end
|
255
|
+
|
435
256
|
if block_given?
|
436
|
-
each_child(recursive,
|
257
|
+
each_child(recursive, namespace, name, &block)
|
437
258
|
|
438
259
|
else
|
439
260
|
unless recursive or name or namespace
|
@@ -441,7 +262,7 @@ module SDL4R
|
|
441
262
|
|
442
263
|
else
|
443
264
|
result = []
|
444
|
-
each_child(recursive,
|
265
|
+
each_child(recursive, namespace, name) { |child|
|
445
266
|
result << child
|
446
267
|
}
|
447
268
|
return result
|
@@ -450,7 +271,7 @@ module SDL4R
|
|
450
271
|
end
|
451
272
|
|
452
273
|
# Returns the values of all the children with the given +name+. If the child has
|
453
|
-
# more than one value, all the values will be added as
|
274
|
+
# more than one value, all the values will be added as an array. If the child
|
454
275
|
# has no value, +nil+ will be added. The search is not recursive.
|
455
276
|
#
|
456
277
|
# +name+:: if nil, all children are considered (nil by default).
|
@@ -469,6 +290,10 @@ module SDL4R
|
|
469
290
|
return children_values
|
470
291
|
end
|
471
292
|
|
293
|
+
# child
|
294
|
+
# child(name)
|
295
|
+
# child(recursive, name)
|
296
|
+
#
|
472
297
|
# Get the first child with the given name, optionally using a recursive search.
|
473
298
|
#
|
474
299
|
# +name+:: the name of the child Tag. If +nil+, the first child is returned (+nil+ if there are
|
@@ -476,7 +301,12 @@ module SDL4R
|
|
476
301
|
#
|
477
302
|
# Returns the first child tag having the given name or +nil+ if no such child exists
|
478
303
|
#
|
479
|
-
def child(
|
304
|
+
def child(recursive = false, name = nil)
|
305
|
+
if name.nil?
|
306
|
+
name = recursive
|
307
|
+
recursive = false
|
308
|
+
end
|
309
|
+
|
480
310
|
unless name
|
481
311
|
return @children.first
|
482
312
|
else
|
@@ -502,17 +332,22 @@ module SDL4R
|
|
502
332
|
# providing it the child as parameter.
|
503
333
|
#
|
504
334
|
# +recursive+:: if true, enumerate grand-children, etc, recursively
|
505
|
-
# +name+:: if not nil, indicates the name of the children to enumerate
|
506
335
|
# +namespace+:: if not nil, indicates the namespace of the children to enumerate
|
336
|
+
# +name+:: if not nil, indicates the name of the children to enumerate
|
507
337
|
#
|
508
|
-
def each_child(recursive = false,
|
338
|
+
def each_child(recursive = false, namespace = nil, name = :DEFAULT, &block)
|
339
|
+
if name == :DEFAULT
|
340
|
+
name = namespace
|
341
|
+
namespace = nil
|
342
|
+
end
|
343
|
+
|
509
344
|
@children.each do |child|
|
510
345
|
if (name.nil? or child.name == name) and
|
511
346
|
(namespace.nil? or child.namespace == namespace)
|
512
347
|
yield child
|
513
348
|
end
|
514
349
|
|
515
|
-
child.children(recursive,
|
350
|
+
child.children(recursive, namespace, name, &block) if recursive
|
516
351
|
end
|
517
352
|
return nil
|
518
353
|
end
|
@@ -556,14 +391,11 @@ module SDL4R
|
|
556
391
|
return hash
|
557
392
|
end
|
558
393
|
|
559
|
-
# Adds a value to this Tag.
|
560
|
-
#
|
561
|
-
# Date (coerced to Calendar), and null. Passing any other type will
|
562
|
-
# result in an IllegalArgumentException.
|
563
|
-
#
|
394
|
+
# Adds a value to this Tag. See SDL4R#coerce_or_fail to know about the allowable types.
|
395
|
+
#
|
564
396
|
# +v+:: The value to add
|
565
397
|
#
|
566
|
-
# Raises
|
398
|
+
# Raises an +ArgumentError+ if the value is not a legal SDL type
|
567
399
|
#
|
568
400
|
def add_value(v)
|
569
401
|
@values.push(SDL4R::coerce_or_fail(v))
|
@@ -575,14 +407,19 @@ module SDL4R
|
|
575
407
|
@values.include?(v)
|
576
408
|
end
|
577
409
|
|
578
|
-
#
|
410
|
+
# Removes the first occurence of the specified value from this Tag.
|
579
411
|
#
|
580
412
|
# +v+:: The value to remove
|
581
413
|
#
|
582
414
|
# Returns true If the value exists and is removed
|
583
415
|
#
|
584
416
|
def remove_value(v)
|
585
|
-
|
417
|
+
index = @values.index(v)
|
418
|
+
if index
|
419
|
+
return !@values.delete_at(index).nil?
|
420
|
+
else
|
421
|
+
return false
|
422
|
+
end
|
586
423
|
end
|
587
424
|
|
588
425
|
# Removes all values.
|
@@ -591,8 +428,12 @@ module SDL4R
|
|
591
428
|
@values = []
|
592
429
|
end
|
593
430
|
|
594
|
-
# Returns an Array of the values of this Tag
|
595
|
-
|
431
|
+
# Returns an Array of the values of this Tag or enumerates them.
|
432
|
+
#
|
433
|
+
# tag.values # => [123, "spices"]
|
434
|
+
# tag.values { |value| puts value }
|
435
|
+
#
|
436
|
+
def values # :yields: value
|
596
437
|
if block_given?
|
597
438
|
@values.each { |v| yield v }
|
598
439
|
else
|
@@ -616,23 +457,36 @@ module SDL4R
|
|
616
457
|
}
|
617
458
|
end
|
618
459
|
|
460
|
+
# set_attribute(key, value)
|
461
|
+
# set_attribute(namespace, key, value)
|
619
462
|
#
|
620
|
-
# Set an attribute in the given namespace for this tag. The allowable
|
463
|
+
# Set an attribute in the given namespace for this tag. The allowable
|
621
464
|
# attribute value types are the same as those allowed for
|
622
465
|
# {@link #addValue(Object)}
|
623
466
|
#
|
624
467
|
# +namespace+:: The namespace for this attribute
|
625
468
|
# +key+:: The attribute key
|
626
469
|
# +value+:: The attribute value
|
470
|
+
#
|
627
471
|
# @throws IllegalArgumentException if the key is not a legal SDL
|
628
|
-
# identifier (see {@link
|
472
|
+
# identifier (see {@link SDL4R#validateIdentifier(String)}), or the
|
629
473
|
# namespace is non-blank and is not a legal SDL identifier, or the
|
630
474
|
# value is not a legal SDL type
|
631
475
|
#
|
632
|
-
def set_attribute(key, value
|
476
|
+
def set_attribute(namespace, key, value = nil)
|
477
|
+
if value.nil?
|
478
|
+
value = key
|
479
|
+
key = namespace
|
480
|
+
namespace = ""
|
481
|
+
end
|
482
|
+
|
483
|
+
raise ArgumentError, "attribute namespace must be a String" unless namespace.is_a? String
|
484
|
+
raise ArgumentError, "attribute key must be a String" unless key.is_a? String
|
485
|
+
raise ArgumentError, "attribute key cannot be empty" if key.empty?
|
486
|
+
|
633
487
|
SDL4R.validate_identifier(namespace) unless namespace.empty?
|
634
488
|
SDL4R.validate_identifier(key)
|
635
|
-
|
489
|
+
|
636
490
|
attributes = @attributesByNamespace[namespace]
|
637
491
|
|
638
492
|
if attributes.nil?
|
@@ -643,31 +497,51 @@ module SDL4R
|
|
643
497
|
attributes[key] = SDL4R.coerce_or_fail(value)
|
644
498
|
end
|
645
499
|
|
500
|
+
# attribute(key)
|
501
|
+
# attribute(namespace, key)
|
502
|
+
#
|
646
503
|
# Returns the attribute of the specified +namespace+ of specified +key+ or +nil+ if not found.
|
647
504
|
#
|
648
|
-
# +namespace+:: the default namespace ("") by default
|
649
505
|
#
|
650
|
-
def attribute(
|
506
|
+
def attribute(namespace, key = nil)
|
507
|
+
namespace, key = to_nns namespace, key
|
651
508
|
attributes = @attributesByNamespace[namespace]
|
652
509
|
return attributes.nil? ? nil : attributes[key]
|
653
510
|
end
|
654
511
|
|
655
|
-
# Indicates whether
|
512
|
+
# Indicates whether there is at least an attribute in this Tag.
|
513
|
+
# has_attribute?
|
656
514
|
#
|
657
|
-
#
|
658
|
-
#
|
515
|
+
# Indicates whether there is the specified attribute exists in this Tag.
|
516
|
+
# has_attribute?(key)
|
517
|
+
# has_attribute?(namespace, key)
|
659
518
|
#
|
660
|
-
def has_attribute?(
|
661
|
-
|
662
|
-
|
519
|
+
def has_attribute?(namespace = nil, key = nil)
|
520
|
+
namespace, key = to_nns namespace, key
|
521
|
+
|
522
|
+
if namespace or key
|
523
|
+
attributes = @attributesByNamespace[namespace]
|
524
|
+
return attributes.nil? ? false : attributes.has_key?(key)
|
525
|
+
|
526
|
+
else
|
527
|
+
attributes { return true }
|
528
|
+
return false
|
529
|
+
end
|
663
530
|
end
|
664
531
|
|
665
|
-
# Returns a
|
532
|
+
# Returns a Hash of the attributes of the specified +namespace+ (default is all) or enumerates
|
533
|
+
# them.
|
666
534
|
#
|
667
|
-
#
|
668
|
-
#
|
535
|
+
# tag.attributes # => { "length" => 123, "width" = 25.4, "orig:color" => "gray" }
|
536
|
+
# tag.attributes("orig") do |namespace, key, value|
|
537
|
+
# p "#{namespace}:#{key} = #{value}"
|
538
|
+
# end
|
669
539
|
#
|
670
|
-
|
540
|
+
# +namespace+::
|
541
|
+
# namespace of the returned attributes. If nil, all attributes are returned with
|
542
|
+
# qualified names (e.g. "meat:color"). If "", attributes of the default namespace are returned.
|
543
|
+
#
|
544
|
+
def attributes(namespace = nil, &block) # :yields: namespace, key, value
|
671
545
|
if block_given?
|
672
546
|
each_attribute(namespace, &block)
|
673
547
|
|
@@ -675,7 +549,7 @@ module SDL4R
|
|
675
549
|
if namespace.nil?
|
676
550
|
hash = {}
|
677
551
|
|
678
|
-
each_attribute
|
552
|
+
each_attribute do | namespace, key, value |
|
679
553
|
qualified_name = namespace.empty? ? key : namespace + ':' + key
|
680
554
|
hash[qualified_name] = value
|
681
555
|
end
|
@@ -689,6 +563,9 @@ module SDL4R
|
|
689
563
|
end
|
690
564
|
end
|
691
565
|
|
566
|
+
# remove_attribute(key)
|
567
|
+
# remove_attribute(namespace, key)
|
568
|
+
#
|
692
569
|
# Removes the attribute, whose name and namespace are specified.
|
693
570
|
#
|
694
571
|
# +key+:: name of the removed atribute
|
@@ -696,7 +573,8 @@ module SDL4R
|
|
696
573
|
#
|
697
574
|
# Returns the value of the removed attribute or +nil+ if it didn't exist.
|
698
575
|
#
|
699
|
-
def remove_attribute(
|
576
|
+
def remove_attribute(namespace, key = nil)
|
577
|
+
namespace, key = to_nns namespace, key
|
700
578
|
attributes = @attributesByNamespace[namespace]
|
701
579
|
return attributes.nil? ? nil : attributes.delete(key)
|
702
580
|
end
|
@@ -713,11 +591,9 @@ module SDL4R
|
|
713
591
|
end
|
714
592
|
|
715
593
|
# Enumerates the attributes for the specified +namespace+.
|
716
|
-
#
|
717
|
-
# namespace. If +namespace+ is nil, enumerates the attributes of all
|
718
|
-
# namespaces.
|
594
|
+
# Enumerates all the attributes by default.
|
719
595
|
#
|
720
|
-
def each_attribute(namespace =
|
596
|
+
def each_attribute(namespace = nil, &block) # :yields: namespace, key, value
|
721
597
|
if namespace.nil?
|
722
598
|
@attributesByNamespace.each_key { |a_namespace| each_attribute(a_namespace, &block) }
|
723
599
|
|
@@ -725,37 +601,43 @@ module SDL4R
|
|
725
601
|
attributes = @attributesByNamespace[namespace]
|
726
602
|
unless attributes.nil?
|
727
603
|
attributes.each_pair do |key, value|
|
728
|
-
yield key, value
|
604
|
+
yield namespace, key, value
|
729
605
|
end
|
730
606
|
end
|
731
607
|
end
|
732
608
|
end
|
733
609
|
private :each_attribute
|
734
610
|
|
735
|
-
|
736
|
-
#
|
611
|
+
|
612
|
+
# set_attributes(attribute_hash)
|
613
|
+
# set_attributes(namespace, attribute_hash)
|
614
|
+
#
|
615
|
+
# Sets the attributes specified by a Hash in the given +namespace+ in one operation. The
|
616
|
+
# previous attributes of the specified +namespace+ are removed.
|
617
|
+
# See #set_attribute for allowable attribute value types.
|
737
618
|
#
|
738
619
|
# +attributes+:: a Hash where keys are attribute keys
|
739
620
|
# +namespace+:: "" (default namespace) by default
|
740
621
|
#
|
741
622
|
# Raises an +ArgumentError+ if any key in the map is not a legal SDL
|
742
|
-
# identifier (see
|
623
|
+
# identifier (see SDL4R#validate_identifier), or any value
|
743
624
|
# is not a legal SDL type.
|
744
625
|
#
|
745
|
-
def set_attributes(
|
746
|
-
|
747
|
-
|
748
|
-
|
749
|
-
if attributes.nil?
|
750
|
-
attributes = {}
|
751
|
-
@attributesByNamespace[namespace] = attributes
|
752
|
-
else
|
753
|
-
attributes.clear()
|
626
|
+
def set_attributes(namespace, attribute_hash = nil)
|
627
|
+
if attribute_hash.nil?
|
628
|
+
attribute_hash = namespace
|
629
|
+
namespace = ""
|
754
630
|
end
|
755
631
|
|
632
|
+
raise ArgumentError, "namespace can't be nil" if namespace.nil?
|
633
|
+
raise ArgumentError, "attribute_hash should be a Hash" unless attribute_hash.is_a? Hash
|
634
|
+
|
635
|
+
namespace_attributes = @attributesByNamespace[namespace]
|
636
|
+
namespace_attributes.clear if namespace_attributes
|
637
|
+
|
756
638
|
attribute_hash.each_pair do |key, value|
|
757
639
|
# Calling set_attribute() is required to ensure validations
|
758
|
-
set_attribute(key, value)
|
640
|
+
set_attribute(namespace, key, value)
|
759
641
|
end
|
760
642
|
end
|
761
643
|
|
@@ -765,13 +647,13 @@ module SDL4R
|
|
765
647
|
# See #set_attributes
|
766
648
|
#
|
767
649
|
def attributes=(attribute_hash)
|
768
|
-
set_attributes(attribute_hash
|
650
|
+
set_attributes(attribute_hash)
|
769
651
|
end
|
770
652
|
|
771
653
|
# Sets the name of this Tag.
|
772
654
|
#
|
773
655
|
# Raises +ArgumentError+ if the name is not a legal SDL
|
774
|
-
# identifier (see
|
656
|
+
# identifier (see SDL4R#validate_identifier)
|
775
657
|
|
776
658
|
def name=(a_name)
|
777
659
|
a_name = a_name.to_s
|
@@ -779,10 +661,10 @@ module SDL4R
|
|
779
661
|
@name = a_name
|
780
662
|
end
|
781
663
|
|
782
|
-
# The namespace to set.
|
664
|
+
# The namespace to set. +nil+ will be coerced to the empty string.
|
783
665
|
#
|
784
666
|
# Raises +ArgumentError+ if the namespace is non-blank and is not
|
785
|
-
# a legal SDL identifier (see {@link
|
667
|
+
# a legal SDL identifier (see {@link SDL4R#validate_identifier(String)})
|
786
668
|
|
787
669
|
def namespace=(a_namespace)
|
788
670
|
a_namespace = a_namespace.to_s
|
@@ -892,7 +774,7 @@ module SDL4R
|
|
892
774
|
|
893
775
|
# output attributes
|
894
776
|
unless @attributesByNamespace.empty?
|
895
|
-
all_attributes_hash = attributes
|
777
|
+
all_attributes_hash = attributes
|
896
778
|
all_attributes_array = all_attributes_hash.sort { |a, b|
|
897
779
|
namespace1, name1 = a[0].split(':')
|
898
780
|
namespace1, name1 = "", namespace1 if name1.nil?
|
@@ -952,18 +834,27 @@ module SDL4R
|
|
952
834
|
# Returns a string containing an XML representation of this tag. Values
|
953
835
|
# will be represented using _val0, _val1, etc.
|
954
836
|
#
|
955
|
-
#
|
956
|
-
# +
|
957
|
-
# Returns A String containing an XML representation of this tag. Values
|
958
|
-
# will be represented using _val0, _val1, etc.
|
837
|
+
# +line_prefix+:: A prefix to insert before every line.
|
838
|
+
# +uri_by_namespace+:: a Hash giving the URIs for the namespaces. Nil to ignore this.
|
959
839
|
#
|
960
|
-
def to_xml_string(
|
961
|
-
|
840
|
+
def to_xml_string(line_prefix = "", uri_by_namespace = nil)
|
841
|
+
line_prefix ||= ""
|
962
842
|
|
963
843
|
s = ""
|
964
|
-
s <<
|
844
|
+
s << line_prefix << ?<
|
965
845
|
s << "#{namespace}:" unless namespace.empty?
|
966
846
|
s << name
|
847
|
+
|
848
|
+
# output namespace declarations
|
849
|
+
if uri_by_namespace
|
850
|
+
uri_by_namespace.each_pair do |namespace, uri|
|
851
|
+
if namespace
|
852
|
+
s << " xmlns:#{namespace}=\"#{uri}\""
|
853
|
+
else
|
854
|
+
s << " xmlns=\"#{uri}\""
|
855
|
+
end
|
856
|
+
end
|
857
|
+
end
|
967
858
|
|
968
859
|
# output values
|
969
860
|
unless @values.empty?
|
@@ -975,10 +866,9 @@ module SDL4R
|
|
975
866
|
end
|
976
867
|
|
977
868
|
# output attributes
|
978
|
-
|
979
|
-
|
869
|
+
if has_attribute?
|
870
|
+
attributes do |attribute_namespace, attribute_name, attribute_value|
|
980
871
|
s << " "
|
981
|
-
attribute_namespace = @attributeToNamespace[attribute_name]
|
982
872
|
s << "#{attribute_namespace}:" unless attribute_namespace.empty?
|
983
873
|
s << attribute_name << "=\"" << SDL4R.format(attribute_value, false) << ?"
|
984
874
|
end
|
@@ -989,10 +879,10 @@ module SDL4R
|
|
989
879
|
else
|
990
880
|
s << ">\n"
|
991
881
|
@children.each do |child|
|
992
|
-
s << child.to_xml_string(
|
882
|
+
s << child.to_xml_string(line_prefix + " ") << ?\n
|
993
883
|
end
|
994
884
|
|
995
|
-
s <<
|
885
|
+
s << line_prefix << "</"
|
996
886
|
s << "#{namespace}:" unless namespace.empty?
|
997
887
|
s << name << ?>
|
998
888
|
end
|