ooor-doc 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +20 -0
- data/README.md +3 -0
- data/Rakefile +5 -0
- data/lib/ooor-doc.rb +16 -0
- data/lib/ooor-doc/uml.rb +210 -0
- data/lib/ooor-doc/version.rb +3 -0
- data/lib/tasks/ooor-doc_tasks.rake +4 -0
- data/spec/helpers/test_helper.rb +11 -0
- data/spec/ooor_spec.rb +76 -0
- data/spec/requirements.txt +19 -0
- metadata +74 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2013 YOURNAME
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
data/Rakefile
ADDED
data/lib/ooor-doc.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
require 'active_support/dependencies/autoload'
|
3
|
+
require 'ooor'
|
4
|
+
require 'ooor/base'
|
5
|
+
require 'ooor-doc/uml'
|
6
|
+
|
7
|
+
module OoorDoc
|
8
|
+
module PrintUml
|
9
|
+
extend ActiveSupport::Concern
|
10
|
+
module ClassMethods
|
11
|
+
def print_uml(options={}); OoorDoc::UML.print_uml([self], options); end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
Ooor::Base.send :include, PrintUml
|
16
|
+
end
|
data/lib/ooor-doc/uml.rb
ADDED
@@ -0,0 +1,210 @@
|
|
1
|
+
# OOOR: OpenObject On Ruby
|
2
|
+
# Copyright (C) 2009-2012 Akretion LTDA (<http://www.akretion.com>).
|
3
|
+
# Author: Raphaël Valyi
|
4
|
+
# Licensed under the MIT license, see MIT-LICENSE file
|
5
|
+
|
6
|
+
module OoorDoc
|
7
|
+
module UML
|
8
|
+
#usage: UML.print_uml or with options: UML.print_uml(:all, :detailed) or MyOpenObjectResource.print_uml or UML.print_uml([list_of_classes], :all, :detailed)
|
9
|
+
|
10
|
+
def print_uml(options={})
|
11
|
+
ooor = self.class.connection
|
12
|
+
UML.print_uml(ooor.config[:models] && ooor.loaded_models.select {|model| ooor.config[:models].index(model.openerp_model)} || ooor.loaded_models, options)
|
13
|
+
end
|
14
|
+
|
15
|
+
def serve_uml(options={})#TODO port
|
16
|
+
ooor = self
|
17
|
+
require 'sinatra'
|
18
|
+
set :public, File.dirname(__FILE__) + '/../../'
|
19
|
+
|
20
|
+
get '/model/:model_name' do
|
21
|
+
model_name = params[:model_name]
|
22
|
+
model = ooor.const_get(model_name)
|
23
|
+
model.print_uml
|
24
|
+
s = ""#"Hello world! #{model_name}"
|
25
|
+
s << "<IMG SRC='/x.png' USEMAP='#UMLbyOOOR' />"
|
26
|
+
f = File.open('x.map')
|
27
|
+
f.each_line {|l| s << l}
|
28
|
+
s
|
29
|
+
end
|
30
|
+
|
31
|
+
Sinatra::Application.run!
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.display_fields(clazz)
|
35
|
+
s = ""
|
36
|
+
clazz.reload_fields_definition if clazz.fields.empty?
|
37
|
+
#clazz.fields.sort {|a,b| a[1]['type'] <=> b[1]['type']}.each {|i| s << "+ #{i[1]['type']} : #{i[0]}\\l\\n"}
|
38
|
+
clazz.fields.sort {|a,b| a[1]['type'] <=> b[1]['type']}.each {|i| s << "<TR><TD COLSPAN=\"2\" BGCOLOR=\"#bed1b8\" ALIGN=\"LEFT\">#{i[0]}</TD><TD ALIGN=\"LEFT\">#{i[1]['type']}</TD></TR>\\l\\n"}
|
39
|
+
s
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.print_uml(classes, options={})
|
43
|
+
# options = options[0] if options[0].is_a?(Array)
|
44
|
+
# local = (options.index(:all) == nil)
|
45
|
+
# detailed = (options.index(:detailed) != nil) || local && (options.index(:nodetail) == nil)
|
46
|
+
return if classes.empty?
|
47
|
+
local = true
|
48
|
+
detailed = true
|
49
|
+
file_name = options[:file_name] || classes[0].name
|
50
|
+
if classes.size > 8
|
51
|
+
enabled_targets = classes.map {|i| i.openerp_model} #classes[0].ooor.config[:models] #defines the scope of the UML for option local
|
52
|
+
else
|
53
|
+
enabled_targets = classes[0].connection.config[:models] #defines the scope of the UML for option local
|
54
|
+
end
|
55
|
+
|
56
|
+
m2o_edges = {}
|
57
|
+
o2m_edges = {}
|
58
|
+
m2m_edges = {}
|
59
|
+
#instead of diplaying several relations of the same kind between two nodes which would bloat the graph,
|
60
|
+
#we track them all and factor them on a common multiline edge label:
|
61
|
+
connex_classes = UML.collect_edges(false, local, classes, enabled_targets, m2o_edges, o2m_edges, m2m_edges)
|
62
|
+
#back links from connex classes:
|
63
|
+
connex_classes += UML.collect_edges(true, local, connex_classes - classes, classes, m2o_edges, o2m_edges, m2m_edges)
|
64
|
+
|
65
|
+
File.open("#{file_name}.dot", 'w') do |f|
|
66
|
+
f << <<-eos
|
67
|
+
digraph UMLbyOOOR {
|
68
|
+
fontname = "Helvetica"
|
69
|
+
#{classes.size < 5 && "layout = fdp" || ""}
|
70
|
+
fontsize = 11
|
71
|
+
splines = polyline
|
72
|
+
label = "*** generated by OOOR by www.akretion.com ***"
|
73
|
+
node [
|
74
|
+
fontname = "Helvetica"
|
75
|
+
fontsize = 11
|
76
|
+
shape = "record"
|
77
|
+
fillcolor=orange
|
78
|
+
style="rounded,filled"
|
79
|
+
]
|
80
|
+
edge [
|
81
|
+
arrowhead = "none"
|
82
|
+
fontname = "Helvetica"
|
83
|
+
fontsize = 9
|
84
|
+
]
|
85
|
+
eos
|
86
|
+
|
87
|
+
#UML nodes definitions
|
88
|
+
((connex_classes - classes) + classes - [IrModel, IrModel.const_get('ir.model.fields')]).each do |model|
|
89
|
+
#f << " #{model} [ label = \"{#{model.name}#{detailed ? '|' + display_fields(model) : ''}}\" URL=\"/model/#{model.openerp_model}\"];\n"
|
90
|
+
f << "#{model}[label=<<TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" BGCOLOR=\"#ffffff\"><TR><TD COLSPAN=\"3\" BGCOLOR=\"#9bab96\" ALIGN=\"CENTER\">#{model.name}</TD></TR>#{(classes.index(model) || classes.size == 1) && display_fields(model) || ''}</TABLE>> URL=\"/model/#{model.openerp_model}\"];\n"
|
91
|
+
end
|
92
|
+
|
93
|
+
#many2one:
|
94
|
+
f << <<-eos
|
95
|
+
edge [
|
96
|
+
headlabel = "1"
|
97
|
+
taillabel = "n"
|
98
|
+
]
|
99
|
+
eos
|
100
|
+
m2o_edges.each do |k, v|
|
101
|
+
reverse_part = v[3].size > 0 ? "\\n/#{v[3].join("\\n")}\"]\n" : "\"]\n"
|
102
|
+
f << "edge [label = \"#{v[2].join("\\n")}#{reverse_part}"
|
103
|
+
f << "#{v[0]} -> #{v[1]}\n"
|
104
|
+
end
|
105
|
+
|
106
|
+
#one2many:
|
107
|
+
f << <<-eos
|
108
|
+
edge [
|
109
|
+
headlabel = "n"
|
110
|
+
taillabel = "1"
|
111
|
+
]
|
112
|
+
eos
|
113
|
+
o2m_edges.each do |k, v|
|
114
|
+
f << "edge [label = \"#{v[3].join("\\n")}\"]\n"
|
115
|
+
f << "#{v[0]} -> #{v[1]}\n"
|
116
|
+
end
|
117
|
+
|
118
|
+
#many2many:
|
119
|
+
f << <<-eos
|
120
|
+
edge [
|
121
|
+
headlabel = "n"
|
122
|
+
taillabel = "n"
|
123
|
+
]
|
124
|
+
eos
|
125
|
+
m2m_edges.each do |k, v|
|
126
|
+
reverse_part = v[3].size > 0 ? "\\n/#{v[3].join("\\n")}\"]\n" : "\"]\n"
|
127
|
+
f << "edge [label = \"#{v[2].join("\\n")}}#{reverse_part}"
|
128
|
+
f << "#{v[0]} -> #{v[1]}\n"
|
129
|
+
end
|
130
|
+
|
131
|
+
f << "}"
|
132
|
+
end
|
133
|
+
|
134
|
+
begin
|
135
|
+
cmd_line1 = "rm #{file_name}.png"
|
136
|
+
#system(cmd_line1)
|
137
|
+
rescue
|
138
|
+
end
|
139
|
+
#cmd_line2 = "dot -Tpng uml.dot -o uml.png"
|
140
|
+
cmd_line2 = "dot -Tcmapx -o#{file_name}.map -Tpng -o#{file_name}.png #{file_name}.dot"
|
141
|
+
system(cmd_line2)
|
142
|
+
end
|
143
|
+
|
144
|
+
def self.collect_edges(is_reverse, local, classes, enabled_targets, m2o_edges, o2m_edges, m2m_edges)
|
145
|
+
connex_classes = Set.new
|
146
|
+
|
147
|
+
classes.each do |model|
|
148
|
+
model.reload_fields_definition if model.fields.empty?
|
149
|
+
|
150
|
+
#many2one:
|
151
|
+
model.many2one_associations.each do |k, field|
|
152
|
+
target = UML.get_target(is_reverse, local, enabled_targets, field, model)
|
153
|
+
if target
|
154
|
+
connex_classes.add(target)
|
155
|
+
if m2o_edges["#{model}-#{target}"]
|
156
|
+
m2o_edges["#{model}-#{target}"][2] += [k]
|
157
|
+
else
|
158
|
+
m2o_edges["#{model}-#{target}"] = [model, target, [k], []]
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
classes.each do |model|
|
166
|
+
#one2many:
|
167
|
+
model.one2many_associations.each do |k, field|
|
168
|
+
target = UML.get_target(is_reverse, local, enabled_targets, field, model)
|
169
|
+
if target
|
170
|
+
connex_classes.add(target)
|
171
|
+
if m2o_edges["#{target}-#{model}"]
|
172
|
+
m2o_edges["#{target}-#{model}"][3] += [k]
|
173
|
+
elsif o2m_edges["#{model}-#{target}"]
|
174
|
+
o2m_edges["#{model}-#{target}"][3] += [k]
|
175
|
+
else
|
176
|
+
o2m_edges["#{model}-#{target}"] = [model, target, [], [k]]
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
#many2many:
|
182
|
+
model.many2many_associations.each do |k, field|
|
183
|
+
target = UML.get_target(is_reverse, local, enabled_targets, field, model)
|
184
|
+
if target
|
185
|
+
connex_classes.add(target)
|
186
|
+
if m2m_edges["#{model}-#{target}"]
|
187
|
+
m2m_edges["#{model}-#{target}"][2] += [k]
|
188
|
+
elsif m2m_edges["#{target}-#{model}"]
|
189
|
+
m2m_edges["#{target}-#{model}"][3] += [k]
|
190
|
+
else
|
191
|
+
m2m_edges["#{model}-#{target}"] = [model, target, [k], []]
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
end
|
197
|
+
connex_classes
|
198
|
+
end
|
199
|
+
|
200
|
+
private
|
201
|
+
|
202
|
+
def self.get_target(is_reverse, local, enabled_targets, field, model)
|
203
|
+
if (is_reverse && !local) || (!enabled_targets) || enabled_targets.index(field['relation'])
|
204
|
+
model.const_get(field['relation'])
|
205
|
+
else
|
206
|
+
false
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
data/spec/ooor_spec.rb
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
# OOOR: OpenObject On Ruby
|
2
|
+
# Copyright (C) 2009-2012 Akretion LTDA (<http://www.akretion.com>).
|
3
|
+
# Author: Raphaël Valyi
|
4
|
+
# Licensed under the MIT license, see MIT-LICENSE file
|
5
|
+
|
6
|
+
require File.dirname(__FILE__) + '/../lib/ooor-doc'
|
7
|
+
|
8
|
+
#RSpec executable specification; see http://rspec.info/ for more information.
|
9
|
+
#Run the file with the rspec command from the rspec gem
|
10
|
+
describe Ooor do
|
11
|
+
before(:all) do
|
12
|
+
@url = 'http://localhost:8069/xmlrpc'
|
13
|
+
@db_password = 'admin'
|
14
|
+
@username = 'admin'
|
15
|
+
@password = 'admin'
|
16
|
+
@database = 'ooor_test'
|
17
|
+
@ooor = Ooor.new(:url => @url, :username => @username, :password => @password)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should keep quiet if no database is mentioned" do
|
21
|
+
@ooor.loaded_models.should be_empty
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should be able to list databases" do
|
25
|
+
@ooor.list.should be_kind_of(Array)
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should be able to create a new database with demo data" do
|
29
|
+
unless @ooor.list.index(@database)
|
30
|
+
@ooor.create(@db_password, @database)
|
31
|
+
end
|
32
|
+
@ooor.list.index(@database).should_not be_nil
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
describe "Configure existing database" do
|
37
|
+
before(:all) do
|
38
|
+
@ooor = Ooor.new(:url => @url, :username => @username, :password => @password, :database => @database)
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should be able to load a profile" do
|
42
|
+
module_ids = IrModuleModule.search(['name','=', 'sale']) + IrModuleModule.search(['name','=', 'account_voucher']) + IrModuleModule.search(['name','=', 'sale_stock'])
|
43
|
+
module_ids.each do |accounting_module_id|
|
44
|
+
mod = IrModuleModule.find(accounting_module_id)
|
45
|
+
unless mod.state == "installed"
|
46
|
+
mod.button_install
|
47
|
+
end
|
48
|
+
end
|
49
|
+
wizard = BaseModuleUpgrade.create
|
50
|
+
wizard.upgrade_module
|
51
|
+
@ooor.load_models
|
52
|
+
@ooor.loaded_models.should_not be_empty
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
describe "UML features" do
|
58
|
+
before(:all) do
|
59
|
+
@ooor = Ooor.new(:url => @url, :username => @username, :password => @password, :database => @database,
|
60
|
+
:models => ['res.user', 'res.partner', 'product.product', 'sale.order', 'account.invoice', 'product.category', 'stock.move', 'ir.ui.menu'])
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should be able to draw the UML of any class" do
|
64
|
+
SaleOrder.print_uml.should be_true
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should be able to draw the UML of several classes" do
|
68
|
+
OoorDoc::UML.print_uml([SaleOrder, SaleShop]).should be_true
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should accept rendering options" do
|
72
|
+
SaleOrder.print_uml({:detailed => true}).should be_true
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
metadata
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ooor-doc
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Raphael Valyi - www.akretion.com
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-05-17 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: ooor
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
description: UML and OpenERP classes auto-documentation OOOR tools
|
31
|
+
email:
|
32
|
+
- raphael.valyi@akretion.com
|
33
|
+
executables: []
|
34
|
+
extensions: []
|
35
|
+
extra_rdoc_files: []
|
36
|
+
files:
|
37
|
+
- lib/tasks/ooor-doc_tasks.rake
|
38
|
+
- lib/ooor-doc/version.rb
|
39
|
+
- lib/ooor-doc/uml.rb
|
40
|
+
- lib/ooor-doc.rb
|
41
|
+
- MIT-LICENSE
|
42
|
+
- Rakefile
|
43
|
+
- README.md
|
44
|
+
- spec/requirements.txt
|
45
|
+
- spec/helpers/test_helper.rb
|
46
|
+
- spec/ooor_spec.rb
|
47
|
+
homepage: http://github.com/akretion/ooor-doc
|
48
|
+
licenses: []
|
49
|
+
post_install_message:
|
50
|
+
rdoc_options: []
|
51
|
+
require_paths:
|
52
|
+
- lib
|
53
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
54
|
+
none: false
|
55
|
+
requirements:
|
56
|
+
- - ! '>='
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: '0'
|
59
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
60
|
+
none: false
|
61
|
+
requirements:
|
62
|
+
- - ! '>='
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: '0'
|
65
|
+
requirements: []
|
66
|
+
rubyforge_project:
|
67
|
+
rubygems_version: 1.8.24
|
68
|
+
signing_key:
|
69
|
+
specification_version: 3
|
70
|
+
summary: UML and OpenERP classes auto-documentation OOOR tools
|
71
|
+
test_files:
|
72
|
+
- spec/requirements.txt
|
73
|
+
- spec/helpers/test_helper.rb
|
74
|
+
- spec/ooor_spec.rb
|