uml_architect 0.0.2 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/README.md +40 -2
- data/architect.gemspec +1 -0
- data/bin/architect +9 -8
- data/examples/class_with_details.yuml +1 -1
- data/examples/composition_and_aggregation.yuml +2 -0
- data/examples/dependancy.yuml +1 -0
- data/examples/inheritance.yuml +2 -0
- data/examples/notes.yuml +2 -1
- data/examples/{color_and_utf8.yuml → pending/color_and_utf8.yuml} +0 -0
- data/examples/{interface.yuml → pending/interface.yuml} +0 -0
- data/examples/{interface_inheritance.yuml → pending/interface_inheritance.yuml} +0 -0
- data/examples/{international_characters.yuml → pending/international_characters.yuml} +0 -0
- data/examples/{something_meaty.yuml → pending/something_meaty.yuml} +0 -0
- data/examples/simple_association.yuml +1 -1
- data/examples/{class.yuml → simple_class.yuml} +0 -0
- data/lib/architect.rb +1 -1
- data/lib/architect/association.rb +22 -8
- data/lib/architect/class.rb +2 -1
- data/lib/architect/diagram.rb +5 -4
- data/lib/architect/edge.rb +0 -1
- data/lib/architect/node.rb +0 -1
- data/lib/architect/note.rb +17 -0
- data/lib/architect/parser.rb +21 -9
- data/lib/architect/runner.rb +1 -0
- data/lib/architect/version.rb +1 -1
- data/spec/lib/association_spec.rb +9 -3
- data/spec/lib/diagram_spec.rb +8 -4
- data/spec/lib/note_spec.rb +12 -0
- data/spec/lib/parser_spec.rb +5 -0
- data/spec/lib/runner_spec.rb +2 -2
- metadata +27 -12
- data/examples/aggregation.yuml +0 -1
- data/examples/cardinality.yuml +0 -1
- data/examples/composition.yuml +0 -1
- data/examples/dependancies.yuml +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fcf588256acefa798a448fa32320d55ee3f05a55
|
4
|
+
data.tar.gz: c1e2454709dac2ab62e0b19e314c4116769829fa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4f9ebbe1d97f49c96afd4fad7daeaecaaae01aa2c21525ab05a52b17c1d039d064195cbd60cc0fe256a3bb2bafa52b929e6423b87ccf21f0668a703da08ee3cc
|
7
|
+
data.tar.gz: 508072ac21f5e4223c247b2fdd07aaf58e4ffeb6e2d97748b90d843011fc024f66c7112f2408292474dd7faa92b5d9d38da1c169738cbca2335246a16e33a6c7
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -9,9 +9,47 @@ Create UML Class diagrams using a [yUML](http://yuml.me/diagram/scruffy/class/sa
|
|
9
9
|
|
10
10
|
## Usage
|
11
11
|
|
12
|
-
$ architect file
|
12
|
+
$ architect [file ...]
|
13
13
|
|
14
|
-
|
14
|
+
This generates a output file with a svg extension with the same base name as the
|
15
|
+
input file.
|
16
|
+
|
17
|
+
## Examples
|
18
|
+
|
19
|
+
### Simple Class
|
20
|
+
[User]
|
21
|
+
![Simple Class](http://whistler.github.io/architect/examples/simple_class.svg)
|
22
|
+
|
23
|
+
### Class with methods and attributes
|
24
|
+
[User|+Firstname;+Lasname;-Password;|+Login();+Logout()]
|
25
|
+
![Class with details](http://whistler.github.io/architect/examples/class_with_details.svg)
|
26
|
+
|
27
|
+
### Simple Association
|
28
|
+
[User]-[Tweet]
|
29
|
+
![Simple Association](http://whistler.github.io/architect/examples/simple_association.svg)
|
30
|
+
|
31
|
+
### Inheritance
|
32
|
+
[Animal]^-[Cat]
|
33
|
+
[Animal]^-[Dog]
|
34
|
+
![Inheritance](http://whistler.github.io/architect/examples/inheritance.svg)
|
35
|
+
|
36
|
+
### Composition and Aggregation
|
37
|
+
[Car]++0..1-1[Carburetor]
|
38
|
+
[Pong]+0..1-0..*[Duck]
|
39
|
+
![Composition and Aggregation](http://whistler.github.io/architect/examples/composition_and_aggregation.svg)
|
40
|
+
|
41
|
+
### Directional Association
|
42
|
+
[Order]-billing >[Address], [Order]-shipping >[Address]
|
43
|
+
![Directional Association](http://whistler.github.io/architect/examples/directional_association.svg)
|
44
|
+
|
45
|
+
### Dependency
|
46
|
+
[REST]uses-.->[HTTP]
|
47
|
+
![Dependency](http://whistler.github.io/architect/examples/dependancy.svg)
|
48
|
+
|
49
|
+
### Notes
|
50
|
+
[note: this is a note]
|
51
|
+
[note: This is a note about user]-.-[User]
|
52
|
+
![Notes](http://whistler.github.io/architect/examples/notes.svg)
|
15
53
|
|
16
54
|
## Contributing
|
17
55
|
|
data/architect.gemspec
CHANGED
data/bin/architect
CHANGED
@@ -2,13 +2,14 @@
|
|
2
2
|
$: << "./lib"
|
3
3
|
require 'architect/runner'
|
4
4
|
|
5
|
-
if ARGV.count
|
6
|
-
puts "usage: architect file"
|
5
|
+
if ARGV.count == 0
|
6
|
+
puts "usage: architect [file ...]"
|
7
7
|
else
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
8
|
+
ARGV.each do |file|
|
9
|
+
if File.exists?(file)
|
10
|
+
Architect::Runner.new(file, 'svg')
|
11
|
+
else
|
12
|
+
puts file + ": file does not exist"
|
13
|
+
end
|
13
14
|
end
|
14
|
-
end
|
15
|
+
end
|
@@ -1 +1 @@
|
|
1
|
-
[User|+
|
1
|
+
[User|+Firstname;+Lasname;-Password;|+Login();+Logout()]
|
@@ -0,0 +1 @@
|
|
1
|
+
[Service]uses-.->[HTTP]
|
data/examples/inheritance.yuml
CHANGED
data/examples/notes.yuml
CHANGED
@@ -1 +1,2 @@
|
|
1
|
-
[
|
1
|
+
[note: this is a note]
|
2
|
+
[note: This is a note about user]-.-[User]
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -1 +1 @@
|
|
1
|
-
[
|
1
|
+
[User]-[Tweet]
|
File without changes
|
data/lib/architect.rb
CHANGED
@@ -3,16 +3,16 @@ require_relative 'edge'
|
|
3
3
|
|
4
4
|
module Architect
|
5
5
|
|
6
|
+
## Association between two classes
|
6
7
|
class Association < Edge
|
7
8
|
|
8
|
-
attr_accessor :attributes, :graph
|
9
|
-
|
10
9
|
TYPES = {
|
11
10
|
"<>" => "odiamond",
|
12
11
|
"+" => "odiamond",
|
13
12
|
"++" => "diamond",
|
14
13
|
"" => "none",
|
15
|
-
">" => "vee"
|
14
|
+
">" => "vee",
|
15
|
+
"^" => "empty"
|
16
16
|
}
|
17
17
|
|
18
18
|
def initialize(node1, node2, markup="->")
|
@@ -21,16 +21,20 @@ module Architect
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def parse_markup(markup)
|
24
|
-
matches = /(.*)
|
24
|
+
matches = /(.*)-\.-(.*)/.match(markup)
|
25
|
+
matches = /(.*)-(.*)/.match(markup) if matches == nil
|
25
26
|
left = matches[1]
|
26
27
|
right = matches[2]
|
28
|
+
style = get_linestyle(markup)
|
27
29
|
{arrowhead: get_arrow(right), arrowtail: get_arrow(left),
|
28
|
-
headlabel:
|
29
|
-
|
30
|
+
headlabel: " " + get_label(right) + " ",
|
31
|
+
taillabel: " " + get_label(left) + " ",
|
32
|
+
dir: "both", style: style}
|
30
33
|
end
|
31
34
|
|
35
|
+
# Return the type of arrow contained in the markup
|
32
36
|
def get_arrow(string)
|
33
|
-
tokens = /([
|
37
|
+
tokens = /([<>+\^]+)/.match(string)
|
34
38
|
if tokens == nil
|
35
39
|
return "none"
|
36
40
|
else
|
@@ -38,7 +42,8 @@ module Architect
|
|
38
42
|
end
|
39
43
|
end
|
40
44
|
|
41
|
-
|
45
|
+
# Remove the arrow to get label
|
46
|
+
def get_label(string)
|
42
47
|
return "" if string == nil
|
43
48
|
TYPES.keys.each do |arrow|
|
44
49
|
string = string.gsub(arrow, "")
|
@@ -46,6 +51,15 @@ module Architect
|
|
46
51
|
return string
|
47
52
|
end
|
48
53
|
|
54
|
+
def get_linestyle(string)
|
55
|
+
if /-\.-/.match(string) == nil
|
56
|
+
return "solid"
|
57
|
+
else
|
58
|
+
return "dashed"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# Add associations to Graphviz
|
49
63
|
def graph(g)
|
50
64
|
g.add_edges(@node1.graphnode, @node2.graphnode, @attributes)
|
51
65
|
end
|
data/lib/architect/class.rb
CHANGED
@@ -2,8 +2,8 @@ require_relative 'node'
|
|
2
2
|
|
3
3
|
module Architect
|
4
4
|
|
5
|
+
# Class in a class diagram
|
5
6
|
class Class < Architect::Node
|
6
|
-
|
7
7
|
attr_accessor :graphnode, :markup
|
8
8
|
|
9
9
|
def initialize(markup)
|
@@ -21,6 +21,7 @@ module Architect
|
|
21
21
|
return "{" + markup.gsub(";", "\\n") + "}"
|
22
22
|
end
|
23
23
|
|
24
|
+
# Add class to Graphviz
|
24
25
|
def graph(g)
|
25
26
|
@graphnode = g.add_nodes(@markup, @style)
|
26
27
|
end
|
data/lib/architect/diagram.rb
CHANGED
@@ -2,21 +2,22 @@ require 'graphviz'
|
|
2
2
|
require_relative 'parser'
|
3
3
|
|
4
4
|
module Architect
|
5
|
-
|
5
|
+
|
6
6
|
# Diagram is the base class for generating any diagram.
|
7
7
|
class Diagram
|
8
|
+
|
8
9
|
# Draw
|
9
10
|
# [diagram] string containing the markup of the diagram
|
10
|
-
def draw(diagram, output = "class_diagram.
|
11
|
+
def draw(diagram, output = "class_diagram.svg", ext = 'svg')
|
11
12
|
parser = Parser.new
|
12
13
|
elements = parser.parse(diagram)
|
13
14
|
graph = GraphViz.new("ClassDiagram", type: "digraph")
|
14
|
-
graph.node["fillcolor"] = "
|
15
|
+
graph.node["fillcolor"] = "lightgrey"
|
15
16
|
graph.node["style"] = "filled"
|
16
17
|
elements.each do |element|
|
17
18
|
element.graph(graph)
|
18
19
|
end
|
19
|
-
graph.output(ext.to_sym => output)
|
20
|
+
graph.output(ext.to_sym => output, nothugly: true)
|
20
21
|
end
|
21
22
|
|
22
23
|
end
|
data/lib/architect/edge.rb
CHANGED
data/lib/architect/node.rb
CHANGED
@@ -0,0 +1,17 @@
|
|
1
|
+
module Architect
|
2
|
+
|
3
|
+
# A note in a class diagram
|
4
|
+
class Note < Architect::Node
|
5
|
+
attr_accessor :graphnode
|
6
|
+
|
7
|
+
def initialize(markup)
|
8
|
+
matches = /note:(.+)/i.match(markup)
|
9
|
+
@markup = matches[1].strip
|
10
|
+
@style = {shape: "note", style: "filled", fillcolor: "lightgrey"}
|
11
|
+
end
|
12
|
+
|
13
|
+
def graph(g)
|
14
|
+
@graphnode = g.add_nodes(@markup, @style)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/architect/parser.rb
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
require_relative 'class'
|
2
|
+
require_relative 'note'
|
2
3
|
require_relative 'association'
|
3
4
|
|
4
5
|
module Architect
|
5
|
-
|
6
|
+
|
6
7
|
# Parses yUML files
|
7
8
|
class Parser
|
8
9
|
|
@@ -36,18 +37,29 @@ module Architect
|
|
36
37
|
# [statement] String containing statement
|
37
38
|
# Returns a list of classes markup and association markup in the statement
|
38
39
|
def parse_statement(statement)
|
39
|
-
pattern = /\[(?<
|
40
|
+
pattern = /\[(?<node1>.+?)\](?<association>.+?)\[(?<node2>.+)\]/
|
40
41
|
tokens = pattern.match(statement)
|
41
42
|
if tokens
|
42
|
-
|
43
|
-
|
44
|
-
association = Association.new(
|
45
|
-
return [
|
43
|
+
node1 = get_node(tokens[:node1])
|
44
|
+
node2 = get_node(tokens[:node2])
|
45
|
+
association = Association.new(node1, node2, tokens[:association])
|
46
|
+
return [node1, node2, association]
|
46
47
|
else
|
47
|
-
tokens = /\[(?<
|
48
|
-
|
49
|
-
return [
|
48
|
+
tokens = /\[(?<node1>.*)\]/.match(statement)
|
49
|
+
node1 = get_node(tokens[:node1])
|
50
|
+
return [node1]
|
50
51
|
end
|
51
52
|
end
|
53
|
+
|
54
|
+
# [markup] string containing content inside square brackets
|
55
|
+
# Returns Note or Class
|
56
|
+
def get_node(markup)
|
57
|
+
if /^note/i.match(markup) != nil
|
58
|
+
return Note.new(markup)
|
59
|
+
else
|
60
|
+
return Class.new(markup)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
52
64
|
end
|
53
65
|
end
|
data/lib/architect/runner.rb
CHANGED
data/lib/architect/version.rb
CHANGED
@@ -10,12 +10,13 @@ describe Architect::Association do
|
|
10
10
|
end
|
11
11
|
|
12
12
|
it "parses simple association" do
|
13
|
-
@association.attributes
|
13
|
+
attributes = @association.instance_eval("@attributes")
|
14
|
+
attributes[:arrowhead].should == "none"
|
14
15
|
end
|
15
16
|
|
16
17
|
it "parses association markup" do
|
17
18
|
dot = {arrowhead: "vee", arrowtail: "odiamond",
|
18
|
-
headlabel: "n", taillabel: "1", dir: "both"}
|
19
|
+
headlabel: " n ", taillabel: " 1 ", dir: "both", style: "solid"}
|
19
20
|
@association.parse_markup("<>1-n>").should == dot
|
20
21
|
end
|
21
22
|
|
@@ -24,7 +25,12 @@ describe Architect::Association do
|
|
24
25
|
end
|
25
26
|
|
26
27
|
it "strips arrows from strings" do
|
27
|
-
@association.
|
28
|
+
@association.get_label(">1").should == "1"
|
29
|
+
end
|
30
|
+
|
31
|
+
it "can draw dashed and solid lines" do
|
32
|
+
@association.get_linestyle("-").should == "solid"
|
33
|
+
@association.get_linestyle("-.-").should == "dashed"
|
28
34
|
end
|
29
35
|
|
30
36
|
end
|
data/spec/lib/diagram_spec.rb
CHANGED
@@ -8,19 +8,23 @@ describe Architect::Diagram do
|
|
8
8
|
end
|
9
9
|
|
10
10
|
it "can draw a class" do
|
11
|
-
@diagram.send("draw", "[User]", "class.
|
11
|
+
@diagram.send("draw", "[User]", "class.svg")
|
12
12
|
end
|
13
13
|
|
14
14
|
it "can draw an association" do
|
15
|
-
@diagram.send("draw", "[User]-[Pet]", "association.
|
15
|
+
@diagram.send("draw", "[User]-[Pet]", "association.svg")
|
16
16
|
end
|
17
17
|
|
18
18
|
it "can draw a class with attributes and methods" do
|
19
|
-
@diagram.send("draw", "[User|name; age; height|login(); logout()]-[Pet]", "record.
|
19
|
+
@diagram.send("draw", "[User|name; age; height|login(); logout()]-[Pet]", "record.svg")
|
20
20
|
end
|
21
21
|
|
22
22
|
it "can draw a diagram with composition" do
|
23
|
-
@diagram.send("draw", "[Pond]<>0..1-0..*[Duck]", "composition.
|
23
|
+
@diagram.send("draw", "[Pond]<>0..1-0..*[Duck]", "composition.svg")
|
24
|
+
end
|
25
|
+
|
26
|
+
it "can draw a note" do
|
27
|
+
@diagram.send("draw", "[note: This is a note about user]-.-[User]\n[note: this is a note]", "note.svg")
|
24
28
|
end
|
25
29
|
|
26
30
|
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'note'
|
3
|
+
|
4
|
+
describe Architect::Note do
|
5
|
+
it "can create note from markup" do
|
6
|
+
note = Architect::Note.new("note: hello world")
|
7
|
+
g = double()
|
8
|
+
g.should_receive(:add_nodes).with("hello world", {style: "filled",
|
9
|
+
shape: "note", fillcolor: "lightgrey"})
|
10
|
+
note.graph(g)
|
11
|
+
end
|
12
|
+
end
|
data/spec/lib/parser_spec.rb
CHANGED
data/spec/lib/runner_spec.rb
CHANGED
@@ -7,12 +7,12 @@ describe Architect::Runner do
|
|
7
7
|
it "should draw from file" do
|
8
8
|
Architect::Diagram.any_instance.should_receive(:draw)
|
9
9
|
Kernel.stub_chain(:open, :read).and_return("[User]")
|
10
|
-
architect = Architect::Runner.new("tmp/example.yuml", 'png'
|
10
|
+
architect = Architect::Runner.new("tmp/example.yuml", 'png')
|
11
11
|
end
|
12
12
|
|
13
13
|
it "should be able to change extension" do
|
14
14
|
Kernel.stub_chain(:open, :read).and_return("[User]")
|
15
|
-
architect = Architect::Runner.new("test.yuml", "png"
|
15
|
+
architect = Architect::Runner.new("test.yuml", "png")
|
16
16
|
architect.send(:change_extension, "test.yuml", "png").should == "test.png"
|
17
17
|
end
|
18
18
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: uml_architect
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ibrahim Muhammad
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-10-
|
11
|
+
date: 2013-10-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ruby-graphviz
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - '>='
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: libxslt-ruby
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: listen
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -125,27 +139,26 @@ files:
|
|
125
139
|
- Rakefile
|
126
140
|
- architect.gemspec
|
127
141
|
- bin/architect
|
128
|
-
- examples/aggregation.yuml
|
129
|
-
- examples/cardinality.yuml
|
130
|
-
- examples/class.yuml
|
131
142
|
- examples/class_with_details.yuml
|
132
|
-
- examples/
|
133
|
-
- examples/
|
134
|
-
- examples/dependancies.yuml
|
143
|
+
- examples/composition_and_aggregation.yuml
|
144
|
+
- examples/dependancy.yuml
|
135
145
|
- examples/directional_association.yuml
|
136
146
|
- examples/inheritance.yuml
|
137
|
-
- examples/interface.yuml
|
138
|
-
- examples/interface_inheritance.yuml
|
139
|
-
- examples/international_characters.yuml
|
140
147
|
- examples/notes.yuml
|
148
|
+
- examples/pending/color_and_utf8.yuml
|
149
|
+
- examples/pending/interface.yuml
|
150
|
+
- examples/pending/interface_inheritance.yuml
|
151
|
+
- examples/pending/international_characters.yuml
|
152
|
+
- examples/pending/something_meaty.yuml
|
141
153
|
- examples/simple_association.yuml
|
142
|
-
- examples/
|
154
|
+
- examples/simple_class.yuml
|
143
155
|
- lib/architect.rb
|
144
156
|
- lib/architect/association.rb
|
145
157
|
- lib/architect/class.rb
|
146
158
|
- lib/architect/diagram.rb
|
147
159
|
- lib/architect/edge.rb
|
148
160
|
- lib/architect/node.rb
|
161
|
+
- lib/architect/note.rb
|
149
162
|
- lib/architect/parser.rb
|
150
163
|
- lib/architect/runner.rb
|
151
164
|
- lib/architect/version.rb
|
@@ -154,6 +167,7 @@ files:
|
|
154
167
|
- spec/lib/diagram_spec.rb
|
155
168
|
- spec/lib/edge_spec.rb
|
156
169
|
- spec/lib/node_spec.rb
|
170
|
+
- spec/lib/note_spec.rb
|
157
171
|
- spec/lib/parser_spec.rb
|
158
172
|
- spec/lib/runner_spec.rb
|
159
173
|
- spec/spec_helper.rb
|
@@ -187,6 +201,7 @@ test_files:
|
|
187
201
|
- spec/lib/diagram_spec.rb
|
188
202
|
- spec/lib/edge_spec.rb
|
189
203
|
- spec/lib/node_spec.rb
|
204
|
+
- spec/lib/note_spec.rb
|
190
205
|
- spec/lib/parser_spec.rb
|
191
206
|
- spec/lib/runner_spec.rb
|
192
207
|
- spec/spec_helper.rb
|
data/examples/aggregation.yuml
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
[Company]<>-1>[Location], [Location]+->[Point]
|
data/examples/cardinality.yuml
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
[Customer]1-0..*[Address]
|
data/examples/composition.yuml
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
[Company]++-1>[Location]
|
data/examples/dependancies.yuml
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
[HttpContext]uses -.->[Response]
|