use_case_diagram 0.0.2
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 +7 -0
- data/.gitignore +18 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +65 -0
- data/Rakefile +11 -0
- data/bin/use_case_diagram +30 -0
- data/lib/use_case_diagram/Actor.png +0 -0
- data/lib/use_case_diagram/actors.rb +75 -0
- data/lib/use_case_diagram/cu_relations.rb +15 -0
- data/lib/use_case_diagram/diagram.rb +129 -0
- data/lib/use_case_diagram/nodes.rb +63 -0
- data/lib/use_case_diagram/parser.rb +43 -0
- data/lib/use_case_diagram/support_nodes.rb +32 -0
- data/lib/use_case_diagram/use_case_diagram.treetop +181 -0
- data/lib/use_case_diagram/version.rb +3 -0
- data/lib/use_case_diagram.rb +10 -0
- data/test/lib/use_case_diagram/ej1.txt +17 -0
- data/test/lib/use_case_diagram/test_version.rb +64 -0
- data/test/test_helper.rb +3 -0
- data/use_case.gemspec +26 -0
- metadata +102 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 7cb0a1b24c6a4f7893337480579677fb697fdd48
|
4
|
+
data.tar.gz: 0e3d5f298934ee0b888b6b49678ffdd4d77b80eb
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 29219f1c48533930623dbe93733ee629b60577745cf523fbae4155057290181c2dc58220613a1773dda8ee2b3bc261cc752a46ccd4a23aa57eaae0b462283a29
|
7
|
+
data.tar.gz: 5304397c25394106241d7924d4fc1383eaf8376647e1d2d12bb7c80cb52dc8da8646f862cd73055cb8e624ed681c8bbe34b211b1cab8cf4e90d519bdd8c10ad5
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Dario Guerrero
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
# use_case_diagram
|
2
|
+
|
3
|
+
This gem can be used to generate use case diagrams in dot format by using a simpler syntaxis.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
gem install use_case_diagram
|
8
|
+
|
9
|
+
Or you may add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
gem 'use_case_diagram'
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install use_case_diagram
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
Create a text file with the use_case_diagram description (ej1.txt):
|
24
|
+
|
25
|
+
actor :user
|
26
|
+
actor :admin
|
27
|
+
|
28
|
+
node :login
|
29
|
+
node :logout
|
30
|
+
node :other
|
31
|
+
node :askpassword "Ask password"
|
32
|
+
|
33
|
+
:user uses :login, :other
|
34
|
+
|
35
|
+
:admin uses :logout
|
36
|
+
|
37
|
+
:login includes :askpassword, :askname
|
38
|
+
|
39
|
+
:logout extended :extend1_logout, :extend2_logout
|
40
|
+
:askname includes :askfirstname
|
41
|
+
:askname extended :asksecondname
|
42
|
+
|
43
|
+
Then you can parse it to create the dot file:
|
44
|
+
|
45
|
+
use_case_diagram ej1.txt > ej1.dot
|
46
|
+
|
47
|
+
and call dot to create a pdf or png:
|
48
|
+
|
49
|
+
dot -Tpdf -o ej1.pdf ej1.dot
|
50
|
+
|
51
|
+
Obviously, you need dot installed to make this conversion.
|
52
|
+
|
53
|
+
|
54
|
+
You can also use it with pipes:
|
55
|
+
|
56
|
+
use_case_diagram ej1.txt | dot -Tpdf -o ej1.pdf ej1.dot
|
57
|
+
|
58
|
+
|
59
|
+
## Contributing
|
60
|
+
|
61
|
+
1. Fork it
|
62
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
63
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
64
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
65
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'use_case_diagram'
|
4
|
+
|
5
|
+
def help
|
6
|
+
puts "Usage: $0 description_file"
|
7
|
+
end
|
8
|
+
|
9
|
+
|
10
|
+
input_file=ARGV.shift
|
11
|
+
|
12
|
+
if input_file.nil? || !File.exists?(input_file)
|
13
|
+
puts "Need input file"
|
14
|
+
help
|
15
|
+
exit
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
cont=File.read(input_file)
|
20
|
+
|
21
|
+
parse_result=Parser.parse(cont)
|
22
|
+
|
23
|
+
# puts parse_result.obj.inspect
|
24
|
+
|
25
|
+
|
26
|
+
if !parse_result.nil?
|
27
|
+
puts parse_result.obj.to_dot
|
28
|
+
else
|
29
|
+
raise "No dot file produced"
|
30
|
+
end
|
Binary file
|
@@ -0,0 +1,75 @@
|
|
1
|
+
actor_path=File.join(File.dirname(File.dirname(__FILE__)),'use_case_diagram','Actor.png')
|
2
|
+
|
3
|
+
|
4
|
+
ACTOR_TPL =<<END
|
5
|
+
|
6
|
+
#NAME# [shapefile="#{actor_path}", peripheries=0, style=solid, fixedsize=true, height=1.1, labeldistance=100, labelloc="b" #LABEL#];
|
7
|
+
|
8
|
+
END
|
9
|
+
|
10
|
+
class Actor
|
11
|
+
|
12
|
+
attr_accessor :name, :description
|
13
|
+
|
14
|
+
#-----------------------------------------
|
15
|
+
#
|
16
|
+
#-----------------------------------------
|
17
|
+
def initialize(name)
|
18
|
+
@name=name.to_s
|
19
|
+
@description=nil
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_dot
|
24
|
+
res=ACTOR_TPL
|
25
|
+
res=res.gsub('#NAME#',@name)
|
26
|
+
lab=''
|
27
|
+
if !@description.nil?
|
28
|
+
lab=' , label="'+@description.to_s+'"'
|
29
|
+
end
|
30
|
+
res=res.gsub('#LABEL#',lab)
|
31
|
+
return res
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
ACTORS_TPL = <<END
|
38
|
+
/* Actor Nodes */
|
39
|
+
|
40
|
+
#ACTOR#
|
41
|
+
|
42
|
+
END
|
43
|
+
|
44
|
+
|
45
|
+
class Actors
|
46
|
+
|
47
|
+
def initialize
|
48
|
+
@actors=[]
|
49
|
+
end
|
50
|
+
|
51
|
+
def count
|
52
|
+
@actors.count
|
53
|
+
end
|
54
|
+
|
55
|
+
def add(name)
|
56
|
+
a=name
|
57
|
+
if !a.is_a?(Actor)
|
58
|
+
a=Actor.new(name)
|
59
|
+
end
|
60
|
+
|
61
|
+
@actors<<a
|
62
|
+
end
|
63
|
+
|
64
|
+
def to_dot
|
65
|
+
res=ACTORS_TPL
|
66
|
+
@actors.each do |actor|
|
67
|
+
res=res.gsub('#ACTOR#',actor.to_dot+"\n#ACTOR#")
|
68
|
+
|
69
|
+
end
|
70
|
+
res=res.gsub('#ACTOR#',"")
|
71
|
+
|
72
|
+
return res
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
|
2
|
+
class Relation
|
3
|
+
|
4
|
+
attr_accessor :from_u, :to_u, :type
|
5
|
+
|
6
|
+
#-----------------------------------------
|
7
|
+
#
|
8
|
+
#-----------------------------------------
|
9
|
+
def initialize(type, from_u, to_u)
|
10
|
+
@from_u=from_u
|
11
|
+
@to_u=to_u
|
12
|
+
@type=type
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
|
2
|
+
DIAG_TPL = <<END
|
3
|
+
digraph G {
|
4
|
+
rankdir=LR;
|
5
|
+
labelloc="b";
|
6
|
+
peripheries=0;
|
7
|
+
|
8
|
+
#ACTORS#
|
9
|
+
|
10
|
+
#NODES#
|
11
|
+
|
12
|
+
edge [arrowhead=none];
|
13
|
+
|
14
|
+
#USES#
|
15
|
+
|
16
|
+
edge [arrowhead=none, arrowtail=open, label="<<extend>>", style=dashed, dir=both];
|
17
|
+
|
18
|
+
#EXTENDS#
|
19
|
+
|
20
|
+
edge [arrowhead=open, arrowtail=none, label="<<includes>>", style=dashed, dir=both];
|
21
|
+
|
22
|
+
#INCLUDES#
|
23
|
+
|
24
|
+
|
25
|
+
|
26
|
+
// #GENERALISES#
|
27
|
+
|
28
|
+
}
|
29
|
+
END
|
30
|
+
|
31
|
+
require 'actors.rb'
|
32
|
+
require 'nodes.rb'
|
33
|
+
require 'cu_relations'
|
34
|
+
|
35
|
+
class Diagram
|
36
|
+
|
37
|
+
attr_accessor :actors,:nodes
|
38
|
+
|
39
|
+
def initialize(file=nil)
|
40
|
+
@file=file
|
41
|
+
@actors=Actors.new
|
42
|
+
@nodes=Nodes.new
|
43
|
+
@uses={}
|
44
|
+
@extends={}
|
45
|
+
@includes={}
|
46
|
+
@generalises={}
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
def inspect
|
51
|
+
puts "Actors:#{@actors.count}"
|
52
|
+
puts "Nodes:#{@nodes.count}"
|
53
|
+
puts "Uses:#{@uses.count}"
|
54
|
+
puts "Includes:#{@includes.count}"
|
55
|
+
puts "Extends:#{@extends.count}"
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
def relate(relation,from_u,to_u)
|
60
|
+
if relation[from_u].nil?
|
61
|
+
relation[from_u]=[]
|
62
|
+
end
|
63
|
+
|
64
|
+
relation[from_u] << to_u
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
def uses(from_u,to_u)
|
69
|
+
relate(@uses,from_u,to_u)
|
70
|
+
end
|
71
|
+
|
72
|
+
def extends(from_u,to_u)
|
73
|
+
relate(@extends,from_u,to_u)
|
74
|
+
end
|
75
|
+
|
76
|
+
def includes(from_u,to_u)
|
77
|
+
relate(@includes,from_u,to_u)
|
78
|
+
end
|
79
|
+
|
80
|
+
def generalises(from_u,to_u)
|
81
|
+
relate(@generalises,from_u,to_u)
|
82
|
+
end
|
83
|
+
|
84
|
+
|
85
|
+
|
86
|
+
def relations_to_dot(relations)
|
87
|
+
res=''
|
88
|
+
relations.each do |from_use,to_use|
|
89
|
+
to_use.each do |to_u|
|
90
|
+
res += "#{from_use} -> #{to_u};\n"
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
return res
|
95
|
+
end
|
96
|
+
|
97
|
+
def uses_to_dot
|
98
|
+
return relations_to_dot(@uses)
|
99
|
+
end
|
100
|
+
|
101
|
+
def extends_to_dot
|
102
|
+
return relations_to_dot(@extends)
|
103
|
+
end
|
104
|
+
|
105
|
+
|
106
|
+
def includes_to_dot
|
107
|
+
return relations_to_dot(@includes)
|
108
|
+
end
|
109
|
+
|
110
|
+
def generalises_to_dot
|
111
|
+
return relations_to_dot(@generalises)
|
112
|
+
end
|
113
|
+
|
114
|
+
|
115
|
+
def to_dot
|
116
|
+
res=DIAG_TPL;
|
117
|
+
|
118
|
+
res=res.gsub('#ACTORS#',@actors.to_dot)
|
119
|
+
res=res.gsub('#NODES#',@nodes.to_dot)
|
120
|
+
res=res.gsub('#USES#',uses_to_dot)
|
121
|
+
|
122
|
+
res=res.gsub('#EXTENDS#',extends_to_dot)
|
123
|
+
res=res.gsub('#INCLUDES#',includes_to_dot)
|
124
|
+
res=res.gsub('#GENERALISES#',generalises_to_dot)
|
125
|
+
|
126
|
+
return res
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
class Node
|
2
|
+
|
3
|
+
attr_accessor :name,:description
|
4
|
+
|
5
|
+
|
6
|
+
#-----------------------------------------
|
7
|
+
#
|
8
|
+
#-----------------------------------------
|
9
|
+
def initialize(name)
|
10
|
+
@name=name.to_s
|
11
|
+
@description=nil
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
NODES_TPL = <<END
|
17
|
+
/* Use Case Nodes */
|
18
|
+
|
19
|
+
node [shape=ellipse, style=solid];
|
20
|
+
|
21
|
+
#NODE#
|
22
|
+
|
23
|
+
END
|
24
|
+
|
25
|
+
|
26
|
+
class Nodes
|
27
|
+
|
28
|
+
def initialize
|
29
|
+
@nodes=[]
|
30
|
+
end
|
31
|
+
|
32
|
+
def count
|
33
|
+
@nodes.count
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
def add(name)
|
38
|
+
|
39
|
+
n=name
|
40
|
+
if !n.is_a?(Node)
|
41
|
+
n=Node.new(name)
|
42
|
+
end
|
43
|
+
@nodes<<n
|
44
|
+
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
def to_dot
|
49
|
+
res=NODES_TPL
|
50
|
+
@nodes.each do |node|
|
51
|
+
desc=''
|
52
|
+
if !node.description.nil?
|
53
|
+
desc=' [label="'+node.description+'"]'
|
54
|
+
end
|
55
|
+
res=res.gsub('#NODE#',node.name+"#{desc};\n#NODE#")
|
56
|
+
end
|
57
|
+
|
58
|
+
res=res.gsub('#NODE#',"")
|
59
|
+
|
60
|
+
return res
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'treetop'
|
2
|
+
require 'use_case_diagram'
|
3
|
+
require 'support_nodes'
|
4
|
+
|
5
|
+
# Find out what our base path is
|
6
|
+
base_path = File.expand_path(File.dirname(__FILE__))
|
7
|
+
|
8
|
+
# Load our custom syntax node classes so the parser can use them
|
9
|
+
# require File.join(base_path, 'node_extensions.rb')
|
10
|
+
|
11
|
+
class Parser
|
12
|
+
|
13
|
+
base_path = File.expand_path(File.dirname(__FILE__))
|
14
|
+
|
15
|
+
Treetop.load(File.join(base_path, 'use_case_diagram'))
|
16
|
+
|
17
|
+
# puts "- Grammar loaded"
|
18
|
+
@@parser = UCaseParser.new
|
19
|
+
|
20
|
+
# puts "- Parser created loaded"
|
21
|
+
|
22
|
+
def self.parse(data)
|
23
|
+
|
24
|
+
# Pass the data to the parser instance
|
25
|
+
tree = @@parser.parse(data)
|
26
|
+
# puts "- Data parsed"
|
27
|
+
|
28
|
+
# If tree is nil then there was an error during parsing
|
29
|
+
# we need to report a simple error message to help the user
|
30
|
+
if(tree.nil?)
|
31
|
+
puts @@parser.failure_reason
|
32
|
+
puts @@parser.failure_line
|
33
|
+
puts @@parser.failure_column
|
34
|
+
|
35
|
+
puts "LINE WITH ERROR:#{data.split("\n")[@@parser.failure_line]}"
|
36
|
+
|
37
|
+
raise Exception, "Parse error at offset: #{@@parser.index}"
|
38
|
+
end
|
39
|
+
|
40
|
+
return tree
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
class IntegerLiteral < Treetop::Runtime::SyntaxNode
|
2
|
+
end
|
3
|
+
|
4
|
+
class StringLiteral < Treetop::Runtime::SyntaxNode
|
5
|
+
end
|
6
|
+
|
7
|
+
class EmptyLine < Treetop::Runtime::SyntaxNode
|
8
|
+
def obj
|
9
|
+
nil
|
10
|
+
end
|
11
|
+
end
|
12
|
+
class CommentLine < Treetop::Runtime::SyntaxNode
|
13
|
+
|
14
|
+
def obj
|
15
|
+
nil
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class NewLine < Treetop::Runtime::SyntaxNode
|
20
|
+
def obj
|
21
|
+
nil
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class Identifier < Treetop::Runtime::SyntaxNode
|
26
|
+
def obj
|
27
|
+
nil
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class Expression < Treetop::Runtime::SyntaxNode
|
32
|
+
end
|
@@ -0,0 +1,181 @@
|
|
1
|
+
grammar UCase
|
2
|
+
|
3
|
+
rule diagram
|
4
|
+
(actor / node / uses / incl / extd / commentline / whiteline / newline)*
|
5
|
+
{
|
6
|
+
def obj
|
7
|
+
d=Diagram.new
|
8
|
+
elements.map{|e| e.obj}.compact.flatten.each do |e|
|
9
|
+
if e.is_a?(Actor)
|
10
|
+
d.actors.add(e)
|
11
|
+
elsif e.is_a?(Node)
|
12
|
+
d.nodes.add(e)
|
13
|
+
elsif e.is_a?(Relation)
|
14
|
+
if e.type==:uses
|
15
|
+
d.uses(e.from_u,e.to_u)
|
16
|
+
elsif e.type==:includes
|
17
|
+
d.includes(e.from_u,e.to_u)
|
18
|
+
elsif e.type==:extended
|
19
|
+
d.extends(e.from_u,e.to_u)
|
20
|
+
end
|
21
|
+
else
|
22
|
+
raise "Unknown element in parse tree"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
return d
|
27
|
+
end
|
28
|
+
}
|
29
|
+
end
|
30
|
+
|
31
|
+
rule actor
|
32
|
+
space? 'actor' space ident:identifier desc:node_description? space? newline
|
33
|
+
{
|
34
|
+
def obj
|
35
|
+
n=Actor.new(ident.obj)
|
36
|
+
if !desc.nil? && desc.respond_to?(:obj)
|
37
|
+
n.description=desc.obj
|
38
|
+
end
|
39
|
+
return n
|
40
|
+
end
|
41
|
+
}
|
42
|
+
end
|
43
|
+
|
44
|
+
rule node
|
45
|
+
space? 'node' space ident:identifier desc:node_description? space? newline
|
46
|
+
{
|
47
|
+
def obj
|
48
|
+
n=Node.new(ident.obj)
|
49
|
+
if !desc.nil? && desc.respond_to?(:obj)
|
50
|
+
n.description=desc.obj
|
51
|
+
end
|
52
|
+
|
53
|
+
return n
|
54
|
+
end
|
55
|
+
}
|
56
|
+
end
|
57
|
+
|
58
|
+
rule node_description
|
59
|
+
space desc:quotedstring
|
60
|
+
{
|
61
|
+
def obj
|
62
|
+
eval(desc.text_value)
|
63
|
+
end
|
64
|
+
}
|
65
|
+
end
|
66
|
+
|
67
|
+
rule uses
|
68
|
+
space? id1:identifier space 'uses' space id2:identifier id3:id_list* space? newline
|
69
|
+
{
|
70
|
+
def obj
|
71
|
+
r=[]
|
72
|
+
r << Relation.new(:uses,id1.obj,id2.obj)
|
73
|
+
|
74
|
+
id3.elements.each do |rel|
|
75
|
+
r << Relation.new(:uses,id1.obj,rel.obj)
|
76
|
+
end
|
77
|
+
return r
|
78
|
+
end
|
79
|
+
}
|
80
|
+
end
|
81
|
+
|
82
|
+
rule incl
|
83
|
+
space? id1:identifier space 'includes' space id2:identifier id3:id_list* space? newline
|
84
|
+
{
|
85
|
+
def obj
|
86
|
+
r=[]
|
87
|
+
r << Relation.new(:includes,id1.obj,id2.obj)
|
88
|
+
|
89
|
+
id3.elements.each do |rel|
|
90
|
+
r << Relation.new(:includes,id1.obj,rel.obj)
|
91
|
+
end
|
92
|
+
return r
|
93
|
+
end
|
94
|
+
}
|
95
|
+
end
|
96
|
+
|
97
|
+
rule extd
|
98
|
+
space? id1:identifier space 'extended' space id2:identifier id3:id_list* space? newline
|
99
|
+
{
|
100
|
+
def obj
|
101
|
+
r=[]
|
102
|
+
r << Relation.new(:extended,id1.obj,id2.obj)
|
103
|
+
|
104
|
+
id3.elements.each do |rel|
|
105
|
+
r << Relation.new(:extended,id1.obj,rel.obj)
|
106
|
+
end
|
107
|
+
return r
|
108
|
+
end
|
109
|
+
}
|
110
|
+
end
|
111
|
+
|
112
|
+
|
113
|
+
rule id_list
|
114
|
+
space? ',' space? id1:(identifier)
|
115
|
+
{
|
116
|
+
def obj
|
117
|
+
id1.obj
|
118
|
+
end
|
119
|
+
}
|
120
|
+
end
|
121
|
+
|
122
|
+
|
123
|
+
# ':' ident:[a-zA-Z0-9_]+
|
124
|
+
rule identifier
|
125
|
+
':' ident:([^\s\n\,\;\:\-]+)
|
126
|
+
{
|
127
|
+
def obj
|
128
|
+
ident.text_value.to_sym
|
129
|
+
end
|
130
|
+
}
|
131
|
+
end
|
132
|
+
|
133
|
+
rule commentline
|
134
|
+
space? '#' (!"\n" .)+ newline
|
135
|
+
{
|
136
|
+
def obj
|
137
|
+
nil
|
138
|
+
end
|
139
|
+
|
140
|
+
}
|
141
|
+
end
|
142
|
+
|
143
|
+
|
144
|
+
rule quotedstring
|
145
|
+
'"' ('\"' / !'"' .)* '"'
|
146
|
+
{
|
147
|
+
def obj
|
148
|
+
nil
|
149
|
+
end
|
150
|
+
|
151
|
+
}
|
152
|
+
end
|
153
|
+
|
154
|
+
rule space
|
155
|
+
[ \t]+
|
156
|
+
end
|
157
|
+
|
158
|
+
rule whiteline
|
159
|
+
space newline
|
160
|
+
{
|
161
|
+
def obj
|
162
|
+
nil
|
163
|
+
end
|
164
|
+
}
|
165
|
+
end
|
166
|
+
|
167
|
+
rule newline
|
168
|
+
[\n]
|
169
|
+
{
|
170
|
+
def obj
|
171
|
+
nil
|
172
|
+
end
|
173
|
+
}
|
174
|
+
end
|
175
|
+
|
176
|
+
rule emptyline
|
177
|
+
''
|
178
|
+
end
|
179
|
+
|
180
|
+
|
181
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# $: << File.dirname(__FILE__)
|
2
|
+
$: << File.join(File.dirname(__FILE__),File.basename(__FILE__,File.extname(__FILE__)))
|
3
|
+
|
4
|
+
require "use_case_diagram/version"
|
5
|
+
require "use_case_diagram/diagram"
|
6
|
+
require "use_case_diagram/parser"
|
7
|
+
|
8
|
+
module UseCaseDiagram
|
9
|
+
# Your code goes here...
|
10
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
actor :user
|
2
|
+
actor :admin "Admin name"
|
3
|
+
|
4
|
+
node :login
|
5
|
+
node :logout
|
6
|
+
node :other
|
7
|
+
node :askpassword "Ask password"
|
8
|
+
|
9
|
+
:user uses :login, :other
|
10
|
+
|
11
|
+
:admin uses :logout
|
12
|
+
|
13
|
+
:login includes :askpassword, :askname
|
14
|
+
|
15
|
+
:logout extended :extend1_logout, :extend2_logout
|
16
|
+
:askname includes :askfirstname
|
17
|
+
:askname extended :asksecondname
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../test_helper.rb'
|
2
|
+
|
3
|
+
|
4
|
+
class TestUseCase < Test::Unit::TestCase
|
5
|
+
|
6
|
+
@@base_path=File.dirname(__FILE__)
|
7
|
+
|
8
|
+
def test_parse_empty
|
9
|
+
res=Parser.parse("")
|
10
|
+
|
11
|
+
assert(res.obj.is_a?(Diagram))
|
12
|
+
|
13
|
+
assert_equal(res.obj.actors.count,0)
|
14
|
+
assert_equal(res.obj.nodes.count,0)
|
15
|
+
# assert_equal(res.obj.uses.count,0)
|
16
|
+
# assert_equal(res.obj.includes.count,0)
|
17
|
+
# assert_equal(res.obj.extends.count,0)
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_parse_actor
|
22
|
+
res=Parser.parse("actor :dario\n")
|
23
|
+
|
24
|
+
assert(res.obj.is_a?(Diagram))
|
25
|
+
|
26
|
+
assert_equal(res.obj.actors.count,1)
|
27
|
+
assert_equal(res.obj.nodes.count,0)
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_parse_node
|
32
|
+
res=Parser.parse("node :login\n")
|
33
|
+
|
34
|
+
assert(res.obj.is_a?(Diagram))
|
35
|
+
|
36
|
+
assert_equal(res.obj.actors.count,0)
|
37
|
+
assert_equal(res.obj.nodes.count,1)
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_parse
|
42
|
+
res=Parser.parse("actor :dario\n node :login \n node :logout\n")
|
43
|
+
|
44
|
+
assert(res.obj.is_a?(Diagram))
|
45
|
+
|
46
|
+
assert_equal(res.obj.actors.count,1)
|
47
|
+
assert_equal(res.obj.nodes.count,2)
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_uses
|
52
|
+
cont=File.read(File.join(@@base_path,'ej1.txt'))
|
53
|
+
res=Parser.parse(cont)
|
54
|
+
|
55
|
+
assert(res.obj.is_a?(Diagram))
|
56
|
+
|
57
|
+
assert_equal(res.obj.actors.count,2)
|
58
|
+
assert_equal(res.obj.nodes.count,4)
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
|
64
|
+
end
|
data/test/test_helper.rb
ADDED
data/use_case.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'use_case_diagram/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "use_case_diagram"
|
8
|
+
spec.version = UseCaseDiagram::VERSION
|
9
|
+
spec.authors = ["Dario Guerrero"]
|
10
|
+
spec.email = ["dariogf@gmail.com"]
|
11
|
+
spec.description = %q{A gem to generate user cases in UML using dot}
|
12
|
+
spec.summary = %q{A gem to generate user cases in UML using dot}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib","lib/use_case_diagram"]
|
20
|
+
|
21
|
+
spec.add_runtime_dependency(%q<treetop>, ["= 1.4.12"])
|
22
|
+
|
23
|
+
|
24
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
25
|
+
spec.add_development_dependency "rake"
|
26
|
+
end
|
metadata
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: use_case_diagram
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Dario Guerrero
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2013-05-21 00:00:00 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: treetop
|
16
|
+
prerelease: false
|
17
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
18
|
+
requirements:
|
19
|
+
- - "="
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 1.4.12
|
22
|
+
type: :runtime
|
23
|
+
version_requirements: *id001
|
24
|
+
- !ruby/object:Gem::Dependency
|
25
|
+
name: bundler
|
26
|
+
prerelease: false
|
27
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
28
|
+
requirements:
|
29
|
+
- - ~>
|
30
|
+
- !ruby/object:Gem::Version
|
31
|
+
version: "1.3"
|
32
|
+
type: :development
|
33
|
+
version_requirements: *id002
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: rake
|
36
|
+
prerelease: false
|
37
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- &id004
|
40
|
+
- ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: "0"
|
43
|
+
type: :development
|
44
|
+
version_requirements: *id003
|
45
|
+
description: A gem to generate user cases in UML using dot
|
46
|
+
email:
|
47
|
+
- dariogf@gmail.com
|
48
|
+
executables:
|
49
|
+
- use_case_diagram
|
50
|
+
extensions: []
|
51
|
+
|
52
|
+
extra_rdoc_files: []
|
53
|
+
|
54
|
+
files:
|
55
|
+
- .gitignore
|
56
|
+
- Gemfile
|
57
|
+
- LICENSE.txt
|
58
|
+
- README.md
|
59
|
+
- Rakefile
|
60
|
+
- bin/use_case_diagram
|
61
|
+
- lib/use_case_diagram.rb
|
62
|
+
- lib/use_case_diagram/Actor.png
|
63
|
+
- lib/use_case_diagram/actors.rb
|
64
|
+
- lib/use_case_diagram/cu_relations.rb
|
65
|
+
- lib/use_case_diagram/diagram.rb
|
66
|
+
- lib/use_case_diagram/nodes.rb
|
67
|
+
- lib/use_case_diagram/parser.rb
|
68
|
+
- lib/use_case_diagram/support_nodes.rb
|
69
|
+
- lib/use_case_diagram/use_case_diagram.treetop
|
70
|
+
- lib/use_case_diagram/version.rb
|
71
|
+
- test/lib/use_case_diagram/ej1.txt
|
72
|
+
- test/lib/use_case_diagram/test_version.rb
|
73
|
+
- test/test_helper.rb
|
74
|
+
- use_case.gemspec
|
75
|
+
homepage: ""
|
76
|
+
licenses:
|
77
|
+
- MIT
|
78
|
+
metadata: {}
|
79
|
+
|
80
|
+
post_install_message:
|
81
|
+
rdoc_options: []
|
82
|
+
|
83
|
+
require_paths:
|
84
|
+
- lib
|
85
|
+
- lib/use_case_diagram
|
86
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- *id004
|
89
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
90
|
+
requirements:
|
91
|
+
- *id004
|
92
|
+
requirements: []
|
93
|
+
|
94
|
+
rubyforge_project:
|
95
|
+
rubygems_version: 2.0.3
|
96
|
+
signing_key:
|
97
|
+
specification_version: 4
|
98
|
+
summary: A gem to generate user cases in UML using dot
|
99
|
+
test_files:
|
100
|
+
- test/lib/use_case_diagram/ej1.txt
|
101
|
+
- test/lib/use_case_diagram/test_version.rb
|
102
|
+
- test/test_helper.rb
|