Class: Ruote::Reader

Inherits:
Object
  • Object
show all
Defined in:
lib/ruote/reader.rb

Overview

A process definition reader.

Can reader XML, JSON, Ruby (and more) process definition representations.

Defined Under Namespace

Classes: Error

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(context) ⇒ Reader

Returns a new instance of Reader.



71
72
73
74
# File 'lib/ruote/reader.rb', line 71

def initialize(context)

  @context = context
end

Class Method Details

._to_xml(tree, indent, level, s) ⇒ Object

Not as good as the builder gem, but at least doesn’t come bundled with lib/blankslate.rb



155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
# File 'lib/ruote/reader.rb', line 155

def self._to_xml(tree, indent, level, s) # :nodoc:

  atts = tree[1].dup

  if t = atts.find { |k, v| v == nil }
    atts.delete(t.first)
    atts[tree[0] == 'if' ? 'test' : 'ref'] = t.first
  end

  atts = atts.remap { |(k, v), h| h[k.to_s.gsub(/\_/, '-')] = v }
  atts = atts.to_a.sort_by { |k, v| k }

  s.print ' ' * level

  s.print '<'
  s.print tree[0]

  if atts.any?
    s.print ' '
    s.print atts.collect { |k, v|
      "#{k}=#{v.is_a?(String) ? v.inspect : v.inspect.inspect}"
    }.join(' ')
  end

  if tree[2].empty?

    s.puts '/>'

  else

    s.puts '>'

    tree[2].each { |child| _to_xml(child, indent, level + (indent || 0), s) }

    s.print ' ' * level
    s.print '</'
    s.print tree[0]
    s.puts '>'
  end
end

.read(d) ⇒ Object

Class method for parsing process definition (XML, Ruby, from file or from a string, …) to syntax trees. Used by ruote-fluo for example.



123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/ruote/reader.rb', line 123

def self.read(d)

  unless @reader

    require 'ostruct'
    require 'ruote/svc/treechecker'

    @reader = Ruote::Reader.new(
      OpenStruct.new('treechecker' => Ruote::TreeChecker.new({})))
  end

  @reader.read(d)
end

.remote?(definition) ⇒ Boolean

Returns true if the defintion is a remote URI

Returns:

  • (Boolean)


281
282
283
284
285
286
# File 'lib/ruote/reader.rb', line 281

def self.remote?(definition)

  u = URI.parse(definition)

  (u.scheme != nil) && ( ! ('A'..'Z').include?(u.scheme))
end

.to_expid_radial(tree) ⇒ Object

Produces an expid annotated radial version of the process definition, like:

0  define name: "nada"
  0_0  sequence
    0_0_0  alpha
    0_0_1  participant "bravo", timeout: "2d", on_board: true

Can be useful when debugging noisy engines.



238
239
240
241
242
243
244
245
246
# File 'lib/ruote/reader.rb', line 238

def self.to_expid_radial(tree)

  lines = to_raw_expid_radial(tree, '0')
  max = lines.collect { |l| l[1].length }.max

  lines.collect { |l|
    "%#{max}s  " % l[1] + "  " * l[0] + l[2] + l[3]
  }.join("\n")
end

.to_json(tree) ⇒ Object

Turns the process definition tree (ruote syntax tree) to a JSON String.



274
275
276
277
# File 'lib/ruote/reader.rb', line 274

def self.to_json(tree)

  tree.to_json
end

.to_radial(tree, level = 0) ⇒ Object

Turns the given tree into a radial process definition.



219
220
221
222
223
224
225
226
# File 'lib/ruote/reader.rb', line 219

def self.to_radial(tree, level=0)

  s = '  ' * level + tree[0] + atts_to_radial(tree[1]) + "\n"

  return s if tree[2].empty?

  tree[2].inject(s) { |ss, child| ss << to_radial(child, level + 1); ss }
end

.to_raw_expid_radial(tree, expid = '0') ⇒ Object

Used by .to_expid_radial. Outputs an array of ‘lines’. Each line is a process definition line, represented as an array:

[ level, expid, name, atts ]

Like in:

[[0, "0", "define", " name: \"nada\""],
 [1, "0_0", "sequence", ""],
 [2, "0_0_0", "alpha", ""],
 [2, "0_0_1", "participant", " \"bravo\", timeout: \"2d\"]]


260
261
262
263
264
265
266
267
268
269
270
# File 'lib/ruote/reader.rb', line 260

def self.to_raw_expid_radial(tree, expid='0')

  i = -1

  [
    [ expid.split('_').size - 1, expid, tree[0], atts_to_radial(tree[1]) ]
  ] +
  tree[2].collect { |t|
    i = i + 1; to_raw_expid_radial(t, "#{expid}_#{i}")
  }.flatten(1)
end

.to_ruby(tree, level = 0) ⇒ Object

Turns the given process definition tree (ruote syntax tree) to a Ruby process definition (a String containing that ruby process definition).

Mainly used by ruote-fluo.



201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
# File 'lib/ruote/reader.rb', line 201

def self.to_ruby(tree, level=0)

  expname = tree[0]
  expname = 'Ruote.process_definition' if level == 0 && expname == 'define'

  s = '  ' * level + expname + atts_to_ruby(tree[1])

  return "#{s}\n" if tree[2].empty?

  s << " do\n"
  tree[2].each { |child| s << to_ruby(child, level + 1) }
  s << "#{'  ' * level}end\n"

  s
end

.to_xml(tree, options = {}) ⇒ Object

Turns the given process definition tree (ruote syntax tree) to an XML String.

Mainly used by ruote-fluo.



142
143
144
145
146
147
148
149
150
# File 'lib/ruote/reader.rb', line 142

def self.to_xml(tree, options={})

  s = StringIO.new
  s.puts('<?xml version="1.0" encoding="UTF-8"?>')

  _to_xml(tree, options[:indent], 0, s)

  s.string
end

Instance Method Details

#read(definition) ⇒ Object

Turns the input into a ruote syntax tree (raw process definition). This method is used by engine.launch(x) for example.

Raises:

  • (ArgumentError)


79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/ruote/reader.rb', line 79

def read(definition)

  return definition if Ruote.is_tree?(definition)

  raise ArgumentError.new(
    "cannot read process definitions of class #{definition.class}"
  ) unless definition.is_a?(String)

  if is_uri?(definition)

    if
      Ruote::Reader.remote?(definition) &&
      @context['remote_definition_allowed'] != true
    then
      raise ArgumentError.new('remote process definitions are not allowed')
    end

    return read(open(definition).read)
  end

  tree = nil
  error = Error.new(definition)

  [
    Ruote::RubyReader, Ruote::RadialReader,
    Ruote::XmlReader, Ruote::JsonReader
  ].each do |reader|

    next if tree
    next unless reader.understands?(definition)

    begin
      tree = reader.read(definition, @context.treechecker)
    rescue => e
      error << [ reader, e ]
    end
  end

  tree || raise(error)
end