mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2024-12-27 10:14:17 +08:00
351 lines
15 KiB
Ruby
351 lines
15 KiB
Ruby
|
|
require 'zip'
|
|
|
|
module ProtocolsExporter
|
|
private
|
|
|
|
def get_guid(id)
|
|
str1 = '00000000-0000-'
|
|
str2 = id.to_s
|
|
str2 = '0' * (19 - str2.size) + str2
|
|
str2 = '4' + str2
|
|
str2n = str2[0..3] + '-' + str2[4..7] + '-' + str2[8..-1]
|
|
str1 + str2n
|
|
end
|
|
|
|
def get_protocol_name(protocol)
|
|
## "Inject" module's name
|
|
protocol_name = if protocol.in_module? && protocol.name.blank?
|
|
protocol.my_module.name
|
|
else
|
|
protocol.name
|
|
end
|
|
protocol_name
|
|
end
|
|
|
|
def generate_envelope_xml(protocols)
|
|
envelope_xml = "<envelope xmlns=\"http://www.scinote.net\" " \
|
|
"version=\"1.0\">\n"
|
|
protocols.each do |protocol|
|
|
protocol_name = get_protocol_name(protocol)
|
|
envelope_xml << "<protocol id=\"#{protocol.id}\" " \
|
|
"guid=\"#{get_guid(protocol.id)}\">#{protocol_name}" \
|
|
"</protocol>\n"
|
|
end
|
|
envelope_xml << "</envelope>\n"
|
|
envelope_xml
|
|
end
|
|
|
|
def tiny_mce_asset_present?(object)
|
|
object.tiny_mce_assets.exists?
|
|
end
|
|
|
|
def get_tiny_mce_assets(text)
|
|
return unless text
|
|
|
|
regex = Constants::TINY_MCE_ASSET_REGEX
|
|
tiny_assets_xml = "<descriptionAssets>\n"
|
|
text.gsub(regex) do |el|
|
|
match = el.match(regex)
|
|
img = TinyMceAsset.find_by_id(Base62.decode(match[1]))
|
|
next unless img
|
|
|
|
img_guid = get_guid(img.id)
|
|
asset_file_name = "rte-#{img_guid}#{File.extname(img.file_name)}"
|
|
asset_xml = "<tinyMceAsset tokenId=\"#{match[1]}\" id=\"#{img.id}\" guid=\"#{img_guid}\" " \
|
|
"fileRef=\"#{asset_file_name}\">\n"
|
|
asset_xml << "<fileName>#{img.file_name}</fileName>\n"
|
|
asset_xml << "<fileType>#{img.content_type}</fileType>\n"
|
|
asset_xml << "<fileMetadata><!--[CDATA[ #{img.image.metadata.to_json} ]]--></fileMetadata>\n"
|
|
asset_xml << "</tinyMceAsset>\n"
|
|
tiny_assets_xml << asset_xml
|
|
end
|
|
tiny_assets_xml << "</descriptionAssets>\n"
|
|
tiny_assets_xml
|
|
end
|
|
|
|
def generate_protocol_xml(protocol)
|
|
protocol_name = get_protocol_name(protocol)
|
|
protocol_xml = "<eln xmlns=\"http://www.scinote.net\" version=\"1.0\">\n"
|
|
protocol_xml << "<protocol id=\"#{protocol.id}\" " \
|
|
"guid=\"#{get_guid(protocol.id)}\">\n"
|
|
protocol_xml << "<name>#{protocol_name}</name>\n"
|
|
protocol_xml << "<authors>#{protocol.authors}</authors>\n"
|
|
protocol_xml << "<description>
|
|
<!--[CDATA[ #{Nokogiri::HTML::DocumentFragment.parse(protocol.description)} ]]-->
|
|
</description>\n"
|
|
if tiny_mce_asset_present?(protocol) && protocol.description
|
|
protocol_xml << get_tiny_mce_assets(protocol.description)
|
|
end
|
|
protocol_xml << "<created_at>#{protocol.created_at.as_json}</created_at>\n"
|
|
protocol_xml << "<updated_at>#{protocol.updated_at.as_json}</updated_at>\n"
|
|
|
|
# Steps
|
|
if protocol.steps.count > 0
|
|
protocol_xml << "<steps>\n"
|
|
protocol.steps.order(:id).each do |step|
|
|
step_guid = get_guid(step.id)
|
|
step_xml = "<step id=\"#{step.id}\" guid=\"#{step_guid}\" " \
|
|
"position=\"#{step.position}\">\n"
|
|
step_xml << "<name>#{step.name}</name>\n"
|
|
# uses 2 spaces to make more difficult to remove user data on import
|
|
step_xml << "<description><!--[CDATA[ #{Nokogiri::HTML::DocumentFragment.parse(step.description)} ]]--></description>\n"
|
|
|
|
if tiny_mce_asset_present?(step)
|
|
step_xml << get_tiny_mce_assets(step.description)
|
|
end
|
|
# Assets
|
|
if step.assets.count > 0
|
|
step_xml << "<assets>\n"
|
|
step.assets.order(:id).each do |asset|
|
|
asset_guid = get_guid(asset.id)
|
|
asset_file_name = "#{asset_guid}" \
|
|
"#{File.extname(asset.file_name)}"
|
|
asset_xml = "<asset id=\"#{asset.id}\" guid=\"#{asset_guid}\" " \
|
|
"fileRef=\"#{asset_file_name}\">\n"
|
|
asset_xml << "<fileName>#{asset.file_name}</fileName>\n"
|
|
asset_xml << "<fileType>#{asset.content_type}</fileType>\n"
|
|
asset_xml << "<fileMetadata><!--[CDATA[ #{asset.file.metadata.to_json} ]]--></fileMetadata>\n"
|
|
asset_xml << "</asset>\n"
|
|
step_xml << asset_xml
|
|
end
|
|
step_xml << "</assets>\n"
|
|
end
|
|
|
|
# Tables
|
|
if step.tables.count > 0
|
|
step_xml << "<elnTables>\n"
|
|
step.tables.order(:id).each do |table|
|
|
table_xml = "<elnTable id=\"#{table.id}\" " \
|
|
"guid=\"#{get_guid(table.id)}\">\n"
|
|
table_xml << "<contents>#{table.contents.unpack1('H*')}" \
|
|
"</contents>\n"
|
|
table_xml << "</elnTable>\n"
|
|
step_xml << table_xml
|
|
end
|
|
step_xml << "</elnTables>\n"
|
|
end
|
|
|
|
# Checklists
|
|
if step.checklists.count > 0
|
|
step_xml << "<checklists>\n"
|
|
step.checklists.order(:id).each do |checklist|
|
|
checklist_xml = "<checklist id=\"#{checklist.id}\" " \
|
|
"guid=\"#{get_guid(checklist.id)}\">\n"
|
|
checklist_xml << "<name>#{checklist.name}</name>\n"
|
|
if checklist.checklist_items
|
|
checklist_xml << "<items>\n"
|
|
checklist.checklist_items.each do |item|
|
|
item_xml = "<item id=\"#{item.id}\" " \
|
|
"guid=\"#{get_guid(item.id)}\" " \
|
|
"position=\"#{item.position}\">\n"
|
|
item_xml << "<text>#{item.text}</text>\n"
|
|
item_xml << "</item>\n"
|
|
checklist_xml << item_xml
|
|
end
|
|
checklist_xml << "</items>\n"
|
|
end
|
|
checklist_xml << "</checklist>\n"
|
|
step_xml << checklist_xml
|
|
end
|
|
step_xml << "</checklists>\n"
|
|
end
|
|
protocol_xml << step_xml
|
|
protocol_xml << "</step>\n"
|
|
end
|
|
protocol_xml << "</steps>\n"
|
|
end
|
|
protocol_xml << "</protocol>\n"
|
|
protocol_xml << '</eln>'
|
|
protocol_xml
|
|
end
|
|
|
|
def generate_envelope_xsd
|
|
envelope_xsd = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
|
envelope_xsd << "<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"" \
|
|
" elementFormDefault=\"qualified\" " \
|
|
"attributeFormDefault=\"unqualified\">\n"
|
|
envelope_xsd << "<xs:element name=\"envelope\">\n"
|
|
envelope_xsd << "<xs:complexType>\n"
|
|
envelope_xsd << "<xs:sequence>\n"
|
|
envelope_xsd << "<xs:element name=\"protocol\" maxOccurs=\"unbounded\">\n"
|
|
envelope_xsd << "<xs:complexType>\n"
|
|
envelope_xsd << "<xs:simpleContent>\n"
|
|
envelope_xsd << "<xs:extension base=\"xs:string\">\n"
|
|
envelope_xsd << "<xs:attribute name=\"id\" type=\"xs:int\" " \
|
|
"use=\"required\"></xs:attribute>\n"
|
|
envelope_xsd << "<xs:attribute name=\"guid\" type=\"xs:string\" " \
|
|
"use=\"required\"></xs:attribute>\n"
|
|
envelope_xsd << "</xs:extension>\n"
|
|
envelope_xsd << "</xs:simpleContent>\n"
|
|
envelope_xsd << "</xs:complexType>\n"
|
|
envelope_xsd << "</xs:element>\n"
|
|
envelope_xsd << "</xs:sequence>\n"
|
|
envelope_xsd << "<xs:attribute name=\"xmlns\" type=\"xs:string\" " \
|
|
"use=\"required\"></xs:attribute>\n"
|
|
envelope_xsd << "<xs:attribute name=\"version\" type=\"xs:string\" " \
|
|
"use=\"required\"></xs:attribute>\n"
|
|
envelope_xsd << "</xs:complexType>\n"
|
|
envelope_xsd << "</xs:element>\n"
|
|
envelope_xsd << "</xs:schema>\n"
|
|
envelope_xsd
|
|
end
|
|
|
|
def generate_eln_xsd
|
|
eln_xsd = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
|
eln_xsd << "<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" " \
|
|
"elementFormDefault=\"qualified\" " \
|
|
"attributeFormDefault=\"unqualified\">\n"
|
|
eln_xsd << "<xs:element name=\"eln\">\n"
|
|
eln_xsd << "<xs:complexType>\n"
|
|
eln_xsd << "<xs:all>\n"
|
|
eln_xsd << "<xs:element name=\"protocol\">\n"
|
|
eln_xsd << "<xs:complexType>\n"
|
|
eln_xsd << "<xs:all>\n"
|
|
eln_xsd << "<xs:element name=\"name\" type=\"xs:string\"></xs:element>\n"
|
|
eln_xsd << "<xs:element name=\"authors\" type=\"xs:string\" " \
|
|
"minOccurs=\"0\"></xs:element>\n"
|
|
eln_xsd << "<xs:element name=\"description\" type=\"xs:string\" " \
|
|
"minOccurs=\"0\"></xs:element>\n"
|
|
eln_xsd << "<xs:element name=\"created_at\" " \
|
|
"type=\"xs:string\"></xs:element>\n"
|
|
eln_xsd << "<xs:element name=\"updated_at\" " \
|
|
"type=\"xs:string\"></xs:element>\n"
|
|
eln_xsd << "<xs:element name=\"steps\" minOccurs=\"0\">\n"
|
|
eln_xsd << "<xs:complexType>\n"
|
|
eln_xsd << "<xs:sequence>\n"
|
|
eln_xsd << "<xs:element name=\"step\" maxOccurs=\"unbounded\">\n"
|
|
eln_xsd << "<xs:complexType>\n"
|
|
eln_xsd << "<xs:all>\n"
|
|
eln_xsd << "<xs:element name=\"name\" type=\"xs:string\"></xs:element>\n"
|
|
eln_xsd << "<xs:element name=\"description\" type=\"xs:string\" " \
|
|
"minOccurs=\"0\"></xs:element>\n"
|
|
eln_xsd << "<xs:element name=\"checklists\" minOccurs=\"0\">\n"
|
|
eln_xsd << "<xs:complexType>\n"
|
|
eln_xsd << "<xs:sequence>\n"
|
|
eln_xsd << "<xs:element name=\"checklist\" maxOccurs=\"unbounded\">\n"
|
|
eln_xsd << "<xs:complexType>\n"
|
|
eln_xsd << "<xs:all>\n"
|
|
eln_xsd << "<xs:element name=\"name\" type=\"xs:string\"></xs:element>\n"
|
|
eln_xsd << "<xs:element name=\"items\" minOccurs=\"0\">\n"
|
|
eln_xsd << "<xs:complexType>\n"
|
|
eln_xsd << "<xs:sequence>\n"
|
|
eln_xsd << "<xs:element name=\"item\" maxOccurs=\"unbounded\">\n"
|
|
eln_xsd << "<xs:complexType>\n"
|
|
eln_xsd << "<xs:all>\n"
|
|
eln_xsd << "<xs:element name=\"text\" type=\"xs:string\"></xs:element>\n"
|
|
eln_xsd << "</xs:all>\n"
|
|
eln_xsd << "<xs:attribute name=\"id\" type=\"xs:int\" use=\"required\">" \
|
|
"</xs:attribute>\n"
|
|
eln_xsd << "<xs:attribute name=\"guid\" type=\"xs:string\" " \
|
|
"use=\"required\"></xs:attribute>\n"
|
|
eln_xsd << "<xs:attribute name=\"position\" type=\"xs:int\" " \
|
|
"use=\"required\"></xs:attribute>\n"
|
|
eln_xsd << "</xs:complexType>\n"
|
|
eln_xsd << "</xs:element>\n"
|
|
eln_xsd << "</xs:sequence>\n"
|
|
eln_xsd << "</xs:complexType>\n"
|
|
eln_xsd << "</xs:element>\n"
|
|
eln_xsd << "</xs:all>\n"
|
|
eln_xsd << "<xs:attribute name=\"id\" type=\"xs:int\" " \
|
|
"use=\"required\"></xs:attribute>\n"
|
|
eln_xsd << "<xs:attribute name=\"guid\" type=\"xs:string\" " \
|
|
"use=\"required\"></xs:attribute>\n"
|
|
eln_xsd << "</xs:complexType>\n"
|
|
eln_xsd << "</xs:element>\n"
|
|
eln_xsd << "</xs:sequence>\n"
|
|
eln_xsd << "</xs:complexType>\n"
|
|
eln_xsd << "</xs:element>\n"
|
|
eln_xsd << "<xs:element name=\"descriptionAssets\" minOccurs=\"0\">\n"
|
|
eln_xsd << "<xs:complexType>\n"
|
|
eln_xsd << "<xs:sequence>\n"
|
|
eln_xsd << "<xs:element name=\"tinyMceAsset\" maxOccurs=\"unbounded\">\n"
|
|
eln_xsd << "<xs:complexType>\n"
|
|
eln_xsd << "<xs:all>\n"
|
|
eln_xsd << "<xs:element name=\"fileName\" " \
|
|
"type=\"xs:string\"></xs:element>\n"
|
|
eln_xsd << "<xs:element name=\"fileType\" " \
|
|
"type=\"xs:string\"></xs:element>\n"
|
|
eln_xsd << "</xs:all>\n"
|
|
eln_xsd << "<xs:attribute name=\"id\" type=\"xs:int\" " \
|
|
"use=\"required\"></xs:attribute>\n"
|
|
eln_xsd << "<xs:attribute name=\"tokenId\" type=\"xs:string\" " \
|
|
"use=\"required\"></xs:attribute>\n"
|
|
eln_xsd << "<xs:attribute name=\"guid\" type=\"xs:string\" " \
|
|
"use=\"required\"></xs:attribute>\n"
|
|
eln_xsd << "<xs:attribute name=\"fileRef\" type=\"xs:string\" " \
|
|
"use=\"required\"></xs:attribute>\n"
|
|
eln_xsd << "</xs:complexType>\n"
|
|
eln_xsd << "</xs:element>\n"
|
|
eln_xsd << "</xs:sequence>\n"
|
|
eln_xsd << "</xs:complexType>\n"
|
|
eln_xsd << "</xs:element>\n"
|
|
eln_xsd << "<xs:element name=\"assets\" minOccurs=\"0\">\n"
|
|
eln_xsd << "<xs:complexType>\n"
|
|
eln_xsd << "<xs:sequence>\n"
|
|
eln_xsd << "<xs:element name=\"asset\" maxOccurs=\"unbounded\">\n"
|
|
eln_xsd << "<xs:complexType>\n"
|
|
eln_xsd << "<xs:all>\n"
|
|
eln_xsd << "<xs:element name=\"fileName\" " \
|
|
"type=\"xs:string\"></xs:element>\n"
|
|
eln_xsd << "<xs:element name=\"fileType\" " \
|
|
"type=\"xs:string\"></xs:element>\n"
|
|
eln_xsd << "</xs:all>\n"
|
|
eln_xsd << "<xs:attribute name=\"id\" type=\"xs:int\" " \
|
|
"use=\"required\"></xs:attribute>\n"
|
|
eln_xsd << "<xs:attribute name=\"guid\" type=\"xs:string\" " \
|
|
"use=\"required\"></xs:attribute>\n"
|
|
eln_xsd << "<xs:attribute name=\"fileRef\" type=\"xs:string\" " \
|
|
"use=\"required\"></xs:attribute>\n"
|
|
eln_xsd << "</xs:complexType>\n"
|
|
eln_xsd << "</xs:element>\n"
|
|
eln_xsd << "</xs:sequence>\n"
|
|
eln_xsd << "</xs:complexType>\n"
|
|
eln_xsd << "</xs:element>\n"
|
|
eln_xsd << "<xs:element name=\"elnTables\" minOccurs=\"0\">\n"
|
|
eln_xsd << "<xs:complexType>\n"
|
|
eln_xsd << "<xs:sequence>\n"
|
|
eln_xsd << "<xs:element name=\"elnTable\" maxOccurs=\"unbounded\">\n"
|
|
eln_xsd << "<xs:complexType>\n"
|
|
eln_xsd << "<xs:all>\n"
|
|
eln_xsd << "<xs:element name=\"contents\" " \
|
|
"type=\"xs:string\"></xs:element>\n"
|
|
eln_xsd << "</xs:all>\n"
|
|
eln_xsd << "<xs:attribute name=\"id\" type=\"xs:int\" " \
|
|
"use=\"required\"></xs:attribute>\n"
|
|
eln_xsd << "<xs:attribute name=\"guid\" type=\"xs:string\" " \
|
|
"use=\"required\"></xs:attribute>\n"
|
|
eln_xsd << "</xs:complexType>\n"
|
|
eln_xsd << "</xs:element>\n"
|
|
eln_xsd << "</xs:sequence>\n"
|
|
eln_xsd << "</xs:complexType>\n"
|
|
eln_xsd << "</xs:element>\n"
|
|
eln_xsd << "</xs:all>\n"
|
|
eln_xsd << "<xs:attribute name=\"id\" type=\"xs:int\" " \
|
|
"use=\"required\"></xs:attribute>\n"
|
|
eln_xsd << "<xs:attribute name=\"guid\" type=\"xs:string\" " \
|
|
"use=\"required\"></xs:attribute>\n"
|
|
eln_xsd << "<xs:attribute name=\"position\" type=\"xs:int\" " \
|
|
"use=\"required\"></xs:attribute>\n"
|
|
eln_xsd << "</xs:complexType>\n"
|
|
eln_xsd << "</xs:element>\n"
|
|
eln_xsd << "</xs:sequence>\n"
|
|
eln_xsd << "</xs:complexType>\n"
|
|
eln_xsd << "</xs:element>\n"
|
|
eln_xsd << "</xs:all>\n"
|
|
eln_xsd << "<xs:attribute name=\"id\" type=\"xs:int\" " \
|
|
"use=\"required\"></xs:attribute>\n"
|
|
eln_xsd << "<xs:attribute name=\"guid\" type=\"xs:string\" " \
|
|
"use=\"required\"></xs:attribute>\n"
|
|
eln_xsd << "</xs:complexType>\n"
|
|
eln_xsd << "</xs:element>\n"
|
|
eln_xsd << "</xs:all>\n"
|
|
eln_xsd << "<xs:attribute name=\"xmlns\" type=\"xs:string\" " \
|
|
"use=\"required\"></xs:attribute>\n"
|
|
eln_xsd << "<xs:attribute name=\"version\" type=\"xs:string\" " \
|
|
"use=\"required\"></xs:attribute>\n"
|
|
eln_xsd << "</xs:complexType>\n"
|
|
eln_xsd << "</xs:element>\n"
|
|
eln_xsd << "</xs:schema>\n"
|
|
end
|
|
end
|