Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
.bundle
.config
.yardoc
.DS_Store
Gemfile.lock
InstalledFiles
_yardoc
Expand Down
2 changes: 2 additions & 0 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
require "bundler/gem_tasks"

task :default => [:test]

desc 'Test specs'
task 'test' do
sh "bundle exec bacon -a"
Expand Down
17 changes: 17 additions & 0 deletions example/Sample-osx.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Case ID,Activity,Start Date,End Date,Agent Position,Customer ID,Product,Service Type,Resource
Case 1,Inbound Call,9.3.10 8:05,9.3.10 8:10,FL,Customer 1,MacBook Pro,Referred to Servicer,Helen
Case 1,Handle Case,11.3.10 10:30,11.3.10 10:32,FL,Customer 1,MacBook Pro,Referred to Servicer,Helen
Case 1,Call Outbound,11.3.10 11:45,11.3.10 11:52,FL,Customer 1,MacBook Pro,Referred to Servicer,Henk
Case 2,Inbound Call,4.3.10 11:43,4.3.10 11:46,FL,Customer 2,MacBook Pro,Referred to Servicer,Susi
Case 3,Inbound Call,25.3.10 9:32,25.3.10 9:33,FL,Customer 3,MacBook Pro,Referred to Servicer,Mary
Case 4,Inbound Call,6.3.10 11:41,6.3.10 11:51,FL,Customer 4,iPhone,Referred to Servicer,Fred
Case 5,Inbound Call,18.3.10 10:54,18.3.10 11:01,FL,Customer 5,MacBook Pro,Product Assistance,Kenny
Case 6,Inbound Call,25.3.10 17:09,25.3.10 17:13,FL,Customer 6,MacBook Pro,Referred to Servicer,Harold
Case 6,Inbound Call,25.3.10 17:16,25.3.10 17:18,FL,Customer 6,MacBook Pro,Referred to Servicer,Nancy
Case 6,Inbound Call,26.3.10 8:36,26.3.10 8:40,FL,Customer 6,MacBook Pro,Referred to Servicer,Elena
Case 7,Inbound Call,18.3.10 11:49,18.3.10 11:50,FL,Customer 7,MacBook Pro,Product Assistance,Karen
Case 8,Inbound Call,11.3.10 9:20,11.3.10 9:23,FL,Customer 8,MacBook Pro,Referred to Servicer,Karen
Case 9,Inbound Email,19.3.10 19:47,21.3.10 8:17,FL,Customer 9,MacBook Pro,Product Assistance,Samuil
Case 9,Call Outbound,21.3.10 8:32,21.3.10 8:33,FL,Customer 9,MacBook Pro,Product Assistance,Samuil
Case 9,Handle Email,21.3.10 8:33,21.3.10 8:33,FL,Customer 9,MacBook Pro,Product Assistance,Samuil
Case 10,Handle Email,27.3.10 11:29,27.3.10 11:30,FL,Customer 10,iPhone,Product Assistance,Jochem
92 changes: 92 additions & 0 deletions example/example.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# The behaviour of this example will depend on which, if any, ruby-xes gems you have installed
#
# 0. No gem installed
# Uncomment the line to specify the load path and use local code
# 1. ruby-xes-0.1.0
# Comment the line to specify the load path and use ruby-xes-0.1.0
#
# The key thing to note is that the only lice of this program that needs to be different
# when using ruby-xes-0.2.0 is the cline to write the XML to the file

$LOAD_PATH.unshift('../lib')

require 'csv'
require 'xes'

puts "Example using ruby-xes-#{XES::VERSION}"

# Get some test data
csv = CSV.parse(File.read('Sample-osx.csv'), :headers => true)

doc = XES::Document.new
doc.log = log = XES::Log.default
#log = XES::Log.default
# This example does illustrate the use of nested attributes
#doc.log.xes_features = "nested-attributes"

# Add Global attributes here
doc.log.trace_global = XES::Global.new('trace', [
XES::int('CaseID', ''), XES::int('CustomerID', '')
]
)
doc.log.event_global = XES::Global.new('event', [
XES::string('Activity', ''), XES::date('StartDate', ''), XES::date('EndDate', ''),
XES::string('AgentPosition', ''), XES::string('Product', ''),
XES::string('ServiceType', ''), XES::string('Resource', '')
]
)

# Add Classifiers here
doc.log.classifiers = [
XES::Classifier.new('Activity', 'Activity'),
XES::Classifier.new("Resource", "Resource")
]

id = 0
trace = XES::Trace.new
csv.each do |row|

#puts row['Case ID']
caseId = row['Case ID'].split
custId = row['Customer ID'].split

# CSV file is sorted on 'Case ID', so
# Each time we see a new 'Case ID' then we need to start a new trace
if not row['Case ID'].eql?(id)
trace = XES::Trace.new
trace.attributes << XES::int('CaseID', caseId[1])
trace.attributes << XES::int('CustomerID', custId[1])
end

# Each row of the CSV file is an event, and
# Each column of the CSV file is an event attribute
event = XES::Event.new
event.attributes << XES::string('Activity', row['Activity'])
event.attributes << XES::container('times', [
XES::date('StartDate', row['Start Date'], [
XES::boolean('UTC-format', 'false')
]),
XES::date('EndDate', row['End Date'], [
XES::boolean('UTC-format', 'false')
])
])
event.attributes << XES::string('AgentPosition', row['Agent Position'])
event.attributes << XES::string('Product', row['Product'])
event.attributes << XES::string('ServiceType', row['Service Type'])
event.attributes << XES::string('Resource', row['Resource'])
trace.events << event

if not row['Case ID'].eql?(id)
id = row['Case ID']
doc.log.traces << trace
end

end

f = open("example-#{XES::VERSION}.xes", 'w')
if XES::VERSION.eql?("0.2.0")
f.write(doc.format)
else
doc.format.write(f, 2)
end
f.close()
2 changes: 1 addition & 1 deletion lib/xes.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
require "rexml/document"
require "nokogiri"
require "time"

require "xes/version"
Expand Down
38 changes: 33 additions & 5 deletions lib/xes/attribute.rb
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,17 @@ def formattable?
end

# Format as a XML element.
def format
def format(doc)
raise FormatError.new(self) unless formattable?

REXML::Element.new(type).tap do |attribute|
attribute.attributes["key"] = @key
attribute.attributes["value"] = format_value
meta.each {|m| attribute.elements << m.format if m.formattable?}
Nokogiri::XML::Element.new(@type, doc).tap do |el|
el["key"] = "#{@key}"
if not (@type.eql?('list') or @type.eql?('container'))
el["value"] = "#{@value}"
end
meta.each do |m|
el.add_child(m.format(doc)) if m.formattable?
end
end
end

Expand Down Expand Up @@ -197,5 +201,29 @@ def boolean(key, value, meta=[])
def id(key, value, meta=[])
Attribute.new("id", key, value, meta)
end

# Return list attribute object.
#
# @param key [String]
# attribute name
# @param meta [Array<Attribute>]
# meta attributes
# @return [Attribute]
# list attribute
def list(key, meta=[])
Attribute.new("list", key, '', meta)
end

# Return container attribute object.
#
# @param key [String]
# attribute name
# @param meta [Array<Attribute>]
# meta attributes
# @return [Attribute]
# container attribute
def container(key, meta=[])
Attribute.new("container", key, '', meta)
end
end
end
10 changes: 5 additions & 5 deletions lib/xes/classifier.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,14 @@ def formattable?

# Format as a XML element.
#
# @return [REXML::Element]
# @return [Nokogiri::XML::Element]
# XML element
def format
def format(doc)
raise FormatError.new(self) unless formattable?

REXML::Element.new("classifier").tap do |ext|
ext.attributes["name"] = @name
ext.attributes["keys"] = @keys
Nokogiri::XML::Element.new("classifier", doc).tap do |cls|
cls["name"] = "#{@name}"
cls["keys"] = "#{@keys}"
end
end

Expand Down
9 changes: 4 additions & 5 deletions lib/xes/document.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,16 @@ def formattable?

# Format as a XML document.
#
# @return [REXML::Document]
# @return [Nokogiri::XML::Document]
# XML document
# @raise FormatError
# format error when the document is not formattable
def format
raise FormatError.new(self) unless formattable?

REXML::Document.new.tap do |doc|
doc << REXML::XMLDecl.new
doc.elements << @log.format
end
doc = Nokogiri::XML::Document.new
doc.add_child(@log.format(doc))
doc.to_xml
end

# @api private
Expand Down
8 changes: 4 additions & 4 deletions lib/xes/event.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@ def formattable?

# Format as a XML element.
#
# @return [REXML::Element]
# @return [Nokogiri::XML::Element]
# XML element
def format
REXML::Element.new("event").tap do |event|
def format(doc)
Nokogiri::XML::Element.new("event", doc).tap do |evt|
@attributes.each do |attribute|
event.elements << attribute.format if attribute.formattable?
evt.add_child(attribute.format(doc)) if attribute.formattable?
end
end
end
Expand Down
12 changes: 6 additions & 6 deletions lib/xes/extension.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,15 @@ def formattable?

# Format as a XML element.
#
# @return [REXML::Element]
# @return [Nokogiri::XML::Element]
# XML element
def format
def format(doc)
raise FormatError.new(self) unless formattable?

REXML::Element.new("extension").tap do |ext|
ext.attributes["name"] = @name
ext.attributes["prefix"] = @prefix
ext.attributes["uri"] = @uri
Nokogiri::XML::Element.new("extension", doc).tap do |ext|
ext["name"] = "#{@name}"
ext["prefix"] = "#{@prefix}"
ext["uri"] = "#{@uri}"
end
end

Expand Down
12 changes: 7 additions & 5 deletions lib/xes/global.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,16 @@ def formattable?

# Format as a XML element.
#
# @return [REXML::Element]
# @return [Nokogiri::XML::Element]
# XML element
def format
def format(doc)
raise FormatError.new(self) unless formattable?

REXML::Element.new("global").tap do |global|
global.attributes["scope"] = @scope.to_s
@attributes.each {|attribute| global.elements << attribute.format}
Nokogiri::XML::Element.new("global", doc).tap do |gbl|
gbl["scope"] = "#{@scope.to_s}"
@attributes.each do |attribute|
gbl.add_child(attribute.format(doc)) if attribute.formattable?
end
end
end

Expand Down
38 changes: 23 additions & 15 deletions lib/xes/log.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class << self
# new log instance
def default
new.tap do |log|
log.xes_version = "1.4"
log.xes_version = "2.0"
log.xes_features = "nested-attributes"
log.openxes_version = "1.0RC7"
log.extensions = [
Expand Down Expand Up @@ -90,7 +90,7 @@ def default
attr_accessor :traces

def initialize
@xes_version = "1.4"
@xes_version = "2.0"
@xes_features = ""
@openxes_version = nil
@xmlns = "http://www.xes-standard.org/"
Expand All @@ -112,24 +112,32 @@ def formattable?

# Format as a XML element.
#
# @return [REXML::Element]
# @return [Nokogiri::XML::Element]
# XML element
# @raise FormatError
# format error when the log is formattable
def format
def format(doc)
raise FormatError.new(self) unless formattable?

REXML::Element.new("log").tap do |log|
log.attributes["xes.version"] = @xes_version.to_s if @xes_version
log.attributes["xes.features"] = @xes_features.to_s if @xes_features
log.attributes["openxes.version"] = @openxes_version.to_s if @openxes_version
log.attributes["xmlns"] = @xmlns.to_s if @xmlns
@extensions.each {|ext| log.elements << ext.format if ext.formattable?}
@classifiers.each {|classifier| log.elements << classifier.format if classifier.formattable?}
log.elements << @event_global.format if @event_global.formattable?
log.elements << @trace_global.format if @trace_global.formattable?
@attributes.each {|attribute| log.elements << attribute.format if attribute.formattable?}
@traces.each {|trace| log.elements << trace.format if trace.formattable?}
Nokogiri::XML::Element.new("log", doc).tap do |log|
log["xes.version"] = @xes_version.to_s if @xes_version
log["xes.features"] = @xes_features.to_s if @xes_features
log["openxes.version"] = @openxes_version.to_s if @openxes_version
log["xmlns"] = @xmlns.to_s if @xmlns
@extensions.each do |extension|
log.add_child(extension.format(doc)) if extension.formattable?
end
@classifiers.each do |classifier|
log.add_child(classifier.format(doc)) if classifier.formattable?
end
log.add_child(@trace_global.format(doc)) if @trace_global.formattable?
log.add_child(@event_global.format(doc)) if @event_global.formattable?
@attributes.each do |attribute|
log.add_child(attribute.format(doc)) if attribute.formattable?
end
@traces.each do |trace|
log.add_child(trace.format(doc)) if trace.formattable?
end
end
end

Expand Down
14 changes: 9 additions & 5 deletions lib/xes/trace.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,19 @@ def formattable?

# Format as a XML element.
#
# @return [REXML::Element]
# @return [Nokogiri::XML::Element]
# XML element
# @raise FormatError
def format
def format(doc)
raise FormatError.new(self) unless formattable?

REXML::Element.new("trace").tap do |trace|
@attributes.each {|attribute| trace.elements << attribute.format if attribute.formattable?}
@events.each {|event| trace.elements << event.format if event.formattable?}
Nokogiri::XML::Element.new("trace", doc).tap do |trc|
@attributes.each do |attribute|
trc.add_child(attribute.format(doc)) if attribute.formattable?
end
@events.each do |event|
trc.add_child(event.format(doc)) if event.formattable?
end
end
end

Expand Down
2 changes: 1 addition & 1 deletion lib/xes/version.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module XES
# version of ruby-xes
VERSION = "0.1.0"
VERSION = "0.2.0"
end
Loading