scjson 0.3.3 → 0.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/LEGAL.md +5 -0
- data/LICENSE +21 -0
- data/README.md +37 -0
- data/lib/scjson/cli.rb +86 -2
- data/lib/scjson/engine/context.rb +1597 -0
- data/lib/scjson/engine.rb +187 -0
- data/lib/scjson/types.rb +1964 -0
- data/lib/scjson/version.rb +1 -1
- data/lib/scjson.rb +76 -16
- metadata +19 -6
data/lib/scjson/version.rb
CHANGED
data/lib/scjson.rb
CHANGED
|
@@ -7,9 +7,16 @@
|
|
|
7
7
|
# Licensed under the BSD 1-Clause License.
|
|
8
8
|
|
|
9
9
|
require 'json'
|
|
10
|
-
|
|
10
|
+
begin
|
|
11
|
+
require 'nokogiri'
|
|
12
|
+
NOKOGIRI_AVAILABLE = true
|
|
13
|
+
rescue LoadError
|
|
14
|
+
NOKOGIRI_AVAILABLE = false
|
|
15
|
+
end
|
|
16
|
+
require 'shellwords'
|
|
11
17
|
|
|
12
18
|
require_relative 'scjson/version'
|
|
19
|
+
require_relative 'scjson/types'
|
|
13
20
|
|
|
14
21
|
# Canonical SCXML <-> scjson conversion for the Ruby agent.
|
|
15
22
|
module Scjson
|
|
@@ -45,14 +52,41 @@ module Scjson
|
|
|
45
52
|
# @param [Boolean] omit_empty Remove empty containers when true.
|
|
46
53
|
# @return [String] Canonical scjson output.
|
|
47
54
|
def xml_to_json(xml_str, omit_empty = true)
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
55
|
+
if NOKOGIRI_AVAILABLE
|
|
56
|
+
doc = Nokogiri::XML(xml_str) { |cfg| cfg.strict.nonet }
|
|
57
|
+
root = locate_root(doc)
|
|
58
|
+
raise ArgumentError, 'Document missing <scxml> root element' unless root
|
|
59
|
+
|
|
60
|
+
map = element_to_hash(root)
|
|
61
|
+
collapse_whitespace(map)
|
|
62
|
+
remove_empty(map) if omit_empty
|
|
63
|
+
return JSON.pretty_generate(map)
|
|
64
|
+
end
|
|
65
|
+
# Fallback: use Python CLI converter when Nokogiri is unavailable.
|
|
66
|
+
begin
|
|
67
|
+
require 'tmpdir'
|
|
68
|
+
Dir.mktmpdir('scjson-rb-xml2json') do |dir|
|
|
69
|
+
in_path = File.join(dir, 'in.scxml')
|
|
70
|
+
out_path = File.join(dir, 'out.scjson')
|
|
71
|
+
File.write(in_path, xml_str)
|
|
72
|
+
py_candidates = [ENV['PYTHON'], 'python3', 'python'].compact.uniq
|
|
73
|
+
ok = false
|
|
74
|
+
py_candidates.each do |py|
|
|
75
|
+
# Try package entrypoint; add repo-local 'py' to PYTHONPATH for import
|
|
76
|
+
repo_py = File.expand_path('../../py', __dir__)
|
|
77
|
+
env = {}
|
|
78
|
+
current_pp = ENV['PYTHONPATH']
|
|
79
|
+
env['PYTHONPATH'] = current_pp ? (repo_py + File::PATH_SEPARATOR + current_pp) : repo_py
|
|
80
|
+
cmd = [py, '-m', 'scjson.cli', 'json', in_path, '-o', out_path]
|
|
81
|
+
ok = system(env, *cmd, out: File::NULL, err: File::NULL) && File.file?(out_path)
|
|
82
|
+
break if ok
|
|
83
|
+
end
|
|
84
|
+
raise 'python converter failed' unless ok
|
|
85
|
+
return File.read(out_path)
|
|
86
|
+
end
|
|
87
|
+
rescue StandardError => e
|
|
88
|
+
raise LoadError, "SCXML->JSON conversion unavailable: Nokogiri missing and external converter failed (#{e})"
|
|
89
|
+
end
|
|
56
90
|
end
|
|
57
91
|
|
|
58
92
|
##
|
|
@@ -61,13 +95,39 @@ module Scjson
|
|
|
61
95
|
# @param [String] json_str Canonical scjson input.
|
|
62
96
|
# @return [String] XML document encoded as UTF-8.
|
|
63
97
|
def json_to_xml(json_str)
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
98
|
+
if NOKOGIRI_AVAILABLE
|
|
99
|
+
data = JSON.parse(json_str)
|
|
100
|
+
remove_empty(data)
|
|
101
|
+
doc = Nokogiri::XML::Document.new
|
|
102
|
+
doc.encoding = 'utf-8'
|
|
103
|
+
root = build_element(doc, 'scxml', data)
|
|
104
|
+
doc.root = root
|
|
105
|
+
return doc.to_xml
|
|
106
|
+
end
|
|
107
|
+
# Fallback: use Python CLI converter when Nokogiri is unavailable.
|
|
108
|
+
begin
|
|
109
|
+
require 'tmpdir'
|
|
110
|
+
Dir.mktmpdir('scjson-rb-json2xml') do |dir|
|
|
111
|
+
in_path = File.join(dir, 'in.scjson')
|
|
112
|
+
out_path = File.join(dir, 'out.scxml')
|
|
113
|
+
File.write(in_path, json_str)
|
|
114
|
+
py_candidates = [ENV['PYTHON'], 'python3', 'python'].compact.uniq
|
|
115
|
+
ok = false
|
|
116
|
+
py_candidates.each do |py|
|
|
117
|
+
repo_py = File.expand_path('../../py', __dir__)
|
|
118
|
+
env = {}
|
|
119
|
+
current_pp = ENV['PYTHONPATH']
|
|
120
|
+
env['PYTHONPATH'] = current_pp ? (repo_py + File::PATH_SEPARATOR + current_pp) : repo_py
|
|
121
|
+
cmd = [py, '-m', 'scjson.cli', 'xml', in_path, '-o', out_path]
|
|
122
|
+
ok = system(env, *cmd, out: File::NULL, err: File::NULL) && File.file?(out_path)
|
|
123
|
+
break if ok
|
|
124
|
+
end
|
|
125
|
+
raise 'python converter failed' unless ok
|
|
126
|
+
return File.read(out_path)
|
|
127
|
+
end
|
|
128
|
+
rescue StandardError => e
|
|
129
|
+
raise LoadError, "JSON->SCXML conversion unavailable: Nokogiri missing and external converter failed (#{e})"
|
|
130
|
+
end
|
|
71
131
|
end
|
|
72
132
|
|
|
73
133
|
# ----------------------------
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: scjson
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.3.
|
|
4
|
+
version: 0.3.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Softoboros Technology Inc.
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2025-10-
|
|
11
|
+
date: 2025-10-04 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: nokogiri
|
|
@@ -24,7 +24,9 @@ dependencies:
|
|
|
24
24
|
- - ">="
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
26
|
version: '0'
|
|
27
|
-
description:
|
|
27
|
+
description: 'scjson: SCXML ↔ JSON converter, validator, and execution trace interface.
|
|
28
|
+
Provides CLI tools for conversion, validation, and emitting deterministic traces
|
|
29
|
+
compatible with SCION semantics.'
|
|
28
30
|
email:
|
|
29
31
|
- info@softoboros.com
|
|
30
32
|
executables:
|
|
@@ -32,14 +34,25 @@ executables:
|
|
|
32
34
|
extensions: []
|
|
33
35
|
extra_rdoc_files: []
|
|
34
36
|
files:
|
|
37
|
+
- LEGAL.md
|
|
38
|
+
- LICENSE
|
|
39
|
+
- README.md
|
|
35
40
|
- bin/scjson
|
|
36
41
|
- lib/scjson.rb
|
|
37
42
|
- lib/scjson/cli.rb
|
|
43
|
+
- lib/scjson/engine.rb
|
|
44
|
+
- lib/scjson/engine/context.rb
|
|
45
|
+
- lib/scjson/types.rb
|
|
38
46
|
- lib/scjson/version.rb
|
|
39
|
-
homepage:
|
|
47
|
+
homepage: https://github.com/SoftOboros/scjson
|
|
40
48
|
licenses:
|
|
41
49
|
- BSD-1-Clause
|
|
42
|
-
metadata:
|
|
50
|
+
metadata:
|
|
51
|
+
source_code_uri: https://github.com/SoftOboros/scjson
|
|
52
|
+
documentation_uri: https://github.com/SoftOboros/scjson/tree/main/docs
|
|
53
|
+
changelog_uri: https://github.com/SoftOboros/scjson/releases
|
|
54
|
+
homepage_uri: https://github.com/SoftOboros/scjson
|
|
55
|
+
keywords: scxml,statecharts,state-machine,scjson,scml,execution
|
|
43
56
|
post_install_message:
|
|
44
57
|
rdoc_options: []
|
|
45
58
|
require_paths:
|
|
@@ -58,5 +71,5 @@ requirements: []
|
|
|
58
71
|
rubygems_version: 3.4.19
|
|
59
72
|
signing_key:
|
|
60
73
|
specification_version: 4
|
|
61
|
-
summary: SCXML <-> scjson converter and validator
|
|
74
|
+
summary: SCXML/SCML execution, SCXML <-> scjson converter and validator
|
|
62
75
|
test_files: []
|