-
Notifications
You must be signed in to change notification settings - Fork 0
/
app.rb
executable file
·203 lines (175 loc) · 5.99 KB
/
app.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
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
195
196
197
198
199
200
201
202
203
require 'sinatra'
require 'sinatra/reloader' if development?
require 'securerandom' # UUIDs
require 'fileutils'
require 'base64'
class CEMLTransformService < Sinatra::Base
configure do
enable :threaded
end
configure :development do
register Sinatra::Reloader
require 'byebug'
end
TEMPLATE_CEM = File.join('./', 'cem')
TEMPLATE_DEF = File.join('./', 'def')
TEMPLATE_FHIR = File.join('./', 'fhir')
# TODO Allow configuration via environment variable.
OUTPUT_ROOT = File.join('/tmp', 'ceml-service')
# Change this to support different compiler targets and file extensions.
# These are the only ones needed right now.
SUPPORTED_FORMATS =
{
'fsh' =>
{
'file-extension' => 'fsh',
'compiler-option' => 'fsh'
},
'jsoncf' =>
{
'file-extension' => 'json',
'compiler-option' => 'jsoncf'
},
'xcemcf' =>
{
'file-extension' => 'xml',
'compiler-option' => 'xcemcf'
}
}
before do
content_type :json
end
def get_listing(path)
files = Dir.children(path).sort
puts "Returning #{files.length} names"
files.to_json
end
def get_file(path, name)
resp = {}
begin
path = File.join(path, name)
file = File.open(path, 'r')
content = file.read
resp = {name: name, content: Base64.encode64(content)}
rescue => exception
status 404
end
resp.to_json
end
get '/cem' do
get_listing(TEMPLATE_CEM)
end
get '/def' do
get_listing(TEMPLATE_DEF)
end
get '/fhir' do
get_listing(TEMPLATE_FHIR)
end
get '/cem/:name' do |name|
get_file(TEMPLATE_CEM, name)
end
get '/def/:name' do |name|
get_file(TEMPLATE_DEF, name)
end
get '/fhir/:name' do |name|
get_file(TEMPLATE_FHIR, name)
end
get '/' do
{message: 'This is an API for developers. Please see the documentation for proper usage.', uuid: SecureRandom.uuid}.to_json
end
get '/transforms/formats' do
SUPPORTED_FORMATS.keys.to_json
end
post '/transforms/:format' do |format|
halt(406, {message: "Unsupported target format. Must be one: #{SUPPORTED_FORMATS.keys.join(', ')}"}.to_json) unless SUPPORTED_FORMATS.keys.include? format
json = {}
begin
json = JSON.parse request.body.read
rescue => e
halt 406, {message: "Body must be valid JSON."}.to_json
end
u = SecureRandom.uuid
puts 'Creating processing space with template content...'
d_name = File.join(OUTPUT_ROOT, u)
FileUtils.mkdir_p d_name
dest_src = File.join(d_name, 'src')
# dest_cem = File.join(d_name, 'cem')
# dest_def = File.join(d_name, 'def')
# dest_fhir = File.join(d_name, 'fhir')
dest_out = File.join(d_name, 'out')
Dir.mkdir dest_src
Dir.mkdir dest_out
# FileUtils.copy_entry(TEMPLATE_CEM, dest_cem)
# FileUtils.copy_entry(TEMPLATE_DEF, dest_def)
# FileUtils.copy_entry(TEMPLATE_FHIR, dest_fhir)
puts 'Checking for submitted models...'
inputs = []
json.each_with_index do |n, i|
name = n['name']
content = n['content']
inputs.push name
f_dest = File.join(dest_src, name)
puts "Writing \##{i} content to #{f_dest}"
File.open(f_dest, 'w') do |f|
f.puts Base64.decode64(content)
end
end
puts "Running compiler for '#{format}' target..."
msg = ''
compilerOption = SUPPORTED_FORMATS[format]['compiler-option']
p = IO.popen(['java', '-jar', 'ceml-3.0.4-jar-with-dependencies.jar', '-d', TEMPLATE_DEF, '-i', dest_src, '-p', TEMPLATE_CEM, '-f', TEMPLATE_FHIR, '-dest', compilerOption, '-o', dest_out, *inputs, err: [:child, :out]], 'r') do |java_io|
msg = java_io.read
msg_name = File.join(d_name, 'message')
# byebug
puts msg
File.open(msg_name, 'w') do |f|
f.puts(msg)# until java_io.eof?
end
puts "Wrote to #{msg_name}"
end
root = URI.parse(request.url)
root.path = ''
gets = inputs.map {|i|
root.to_s + "/transforms/#{u}/" +
i.gsub(/cem$/, SUPPORTED_FORMATS[format]['file-extension'])
}
{uuid: u, gets: gets, delete: "#{root.to_s}/transforms/#{u}", message: msg}.to_json
end
get '/transforms/:uuid/:file' do |uuid, file|
puts 'Getting result for #{uuid}'
content = ''
res = {uuid: uuid, file: file}
begin
path = File.join(OUTPUT_ROOT, uuid, 'out', file)
f = File.open(path, 'r')
content = f.read
f.close
res['content'] = Base64.encode64(content)
# attachment
# content_type :binary
# msg
rescue => exception
status 404
puts "File at #{path} not found"
end
res.to_json
end
delete '/transforms/:uuid' do |uuid|
d = File.join(OUTPUT_ROOT, uuid)
puts "Deleting #{d}"
FileUtils.remove_dir d, true
{message: 'deleted'}.to_json
end
post '/reset' do
puts "Delete everything in #{OUTPUT_ROOT}"
msg = {}
begin
FileUtils.remove_dir OUTPUT_ROOT
msg['message'] = "Service has been fully reset"
rescue => Errno::ENOENT
puts "#{OUTPUT_ROOT} does not exist"
msg['message'] = "Output directory did not exist, so nothing has been done. Service may have already been reset."
end
msg.to_json
end
end