archimate 2.0.2 → 2.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.travis.yml +1 -1
- data/Gemfile +1 -0
- data/README.md +10 -55
- data/Rakefile +19 -1
- data/archimate.gemspec +16 -14
- data/bin/archimate +12 -0
- data/lib/archimate/cli/archi.rb +38 -19
- data/lib/archimate/cli/cleanup.rb +41 -25
- data/lib/archimate/cli/duper.rb +0 -1
- data/lib/archimate/cli/mapper.rb +53 -40
- data/lib/archimate/cli/svger.rb +33 -4
- data/lib/archimate/core_refinements.rb +41 -0
- data/lib/archimate/data_model/bounds.rb +14 -4
- data/lib/archimate/data_model/comparison.rb +3 -27
- data/lib/archimate/data_model/connection.rb +26 -11
- data/lib/archimate/data_model/diagram.rb +17 -10
- data/lib/archimate/data_model/element.rb +21 -9
- data/lib/archimate/data_model/elements.rb +24 -18
- data/lib/archimate/data_model/lang_string.rb +34 -10
- data/lib/archimate/data_model/layer.rb +6 -0
- data/lib/archimate/data_model/location.rb +10 -13
- data/lib/archimate/data_model/model.rb +55 -43
- data/lib/archimate/data_model/organization.rb +21 -5
- data/lib/archimate/data_model/property.rb +0 -6
- data/lib/archimate/data_model/referenceable.rb +29 -3
- data/lib/archimate/data_model/referenceable_list.rb +34 -14
- data/lib/archimate/data_model/relationship.rb +29 -8
- data/lib/archimate/data_model/relationship_references.rb +115 -6
- data/lib/archimate/data_model/relationships.rb +15 -0
- data/lib/archimate/data_model/view_node.rb +20 -13
- data/lib/archimate/data_model/viewpoint.rb +13 -1
- data/lib/archimate/data_model/viewpoints.rb +416 -0
- data/lib/archimate/data_model.rb +7 -1
- data/lib/archimate/derived_relations.rb +2 -11
- data/lib/archimate/export/cypher.rb +6 -5
- data/lib/archimate/file_format.rb +1 -0
- data/lib/archimate/file_formats/archi_file_reader.rb +11 -1
- data/lib/archimate/file_formats/archi_file_writer.rb +15 -46
- data/lib/archimate/file_formats/archi_file_writer_4.rb +14 -0
- data/lib/archimate/file_formats/model_exchange_file_reader.rb +2 -1
- data/lib/archimate/file_formats/model_exchange_file_writer_21.rb +1 -0
- data/lib/archimate/file_formats/sax/archi/diagram.rb +53 -13
- data/lib/archimate/file_formats/sax/archi/location.rb +1 -3
- data/lib/archimate/file_formats/sax/model_exchange_file/diagram.rb +13 -2
- data/lib/archimate/file_formats/sax.rb +1 -0
- data/lib/archimate/file_formats/serializer/archi/archi_file_writer.rb +63 -0
- data/lib/archimate/file_formats/serializer/archi/archi_file_writer_3.rb +18 -0
- data/lib/archimate/file_formats/serializer/archi/archi_file_writer_4.rb +18 -0
- data/lib/archimate/file_formats/serializer/archi/bounds.rb +2 -2
- data/lib/archimate/file_formats/serializer/archi/connection.rb +24 -13
- data/lib/archimate/file_formats/serializer/archi/diagram.rb +3 -3
- data/lib/archimate/file_formats/serializer/archi/element.rb +2 -2
- data/lib/archimate/file_formats/serializer/archi/organization.rb +1 -1
- data/lib/archimate/file_formats/serializer/archi/property.rb +1 -1
- data/lib/archimate/file_formats/serializer/archi/relationship.rb +2 -2
- data/lib/archimate/file_formats/serializer/archi/view_node.rb +20 -22
- data/lib/archimate/file_formats/serializer/archi/viewpoint3.rb +43 -0
- data/lib/archimate/file_formats/serializer/archi/viewpoint4.rb +41 -0
- data/lib/archimate/file_formats/serializer/model_exchange_file/style.rb +3 -7
- data/lib/archimate/file_formats/serializer/model_exchange_file/v21/diagram.rb +3 -3
- data/lib/archimate/file_formats/serializer/model_exchange_file/v21/model.rb +9 -2
- data/lib/archimate/file_formats/serializer/model_exchange_file/v21/view_node.rb +1 -1
- data/lib/archimate/file_formats/serializer/model_exchange_file/v21/viewpoint.rb +23 -0
- data/lib/archimate/file_formats/serializer/model_exchange_file/v30/diagram.rb +3 -3
- data/lib/archimate/file_formats/serializer/model_exchange_file/v30/model.rb +5 -7
- data/lib/archimate/file_formats/serializer/model_exchange_file/v30/view_node.rb +3 -3
- data/lib/archimate/file_formats/serializer/writer.rb +0 -5
- data/lib/archimate/file_formats/serializer.rb +6 -2
- data/lib/archimate/lint/duplicate_entities.rb +5 -5
- data/lib/archimate/lint/linter.rb +4 -4
- data/lib/archimate/maybe_io.rb +3 -2
- data/lib/archimate/svg/archimate.css +19 -21
- data/lib/archimate/svg/connection.rb +1 -1
- data/lib/archimate/svg/diagram.rb +1 -6
- data/lib/archimate/svg/entity/application_component.rb +9 -3
- data/lib/archimate/svg/entity/constraint.rb +0 -1
- data/lib/archimate/svg/entity/contract.rb +9 -0
- data/lib/archimate/svg/entity/data_entity.rb +1 -1
- data/lib/archimate/svg/entity/device.rb +1 -1
- data/lib/archimate/svg/entity/event_entity.rb +24 -7
- data/lib/archimate/svg/entity/group.rb +23 -4
- data/lib/archimate/svg/entity/grouping.rb +37 -0
- data/lib/archimate/svg/entity/interface_entity.rb +1 -1
- data/lib/archimate/svg/entity/node.rb +1 -1
- data/lib/archimate/svg/entity/outcome.rb +0 -1
- data/lib/archimate/svg/entity/principle.rb +0 -1
- data/lib/archimate/svg/entity/process_entity.rb +1 -1
- data/lib/archimate/svg/entity/requirement.rb +0 -1
- data/lib/archimate/svg/entity/service_entity.rb +6 -13
- data/lib/archimate/svg/entity.rb +1 -0
- data/lib/archimate/svg/entity_factory.rb +9 -5
- data/lib/archimate/svg/path.rb +57 -46
- data/lib/archimate/svg/point.rb +4 -0
- data/lib/archimate/svg/segment.rb +30 -0
- data/lib/archimate/svg/svg_template.svg.erb +11 -3
- data/lib/archimate/svg/view_node.rb +22 -0
- data/lib/archimate/version.rb +1 -1
- data/lib/archimate.rb +3 -2
- metadata +54 -54
- data/exe/archidiff +0 -7
- data/exe/archidiff-summary +0 -7
- data/exe/archimerge +0 -7
- data/exe/fmtxml +0 -7
- data/lib/archimate/data_model/viewpoint_type.rb +0 -389
- data/lib/archimate/file_formats/serializer/archi/location.rb +0 -26
- data/lib/archimate/file_formats/serializer/archi/viewpoint_type.rb +0 -45
- data/lib/archimate/svg/child.rb +0 -29
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 24983cbe0a25eb6b4fdd4592faf9d424f3f6dab8a0a28495cfa0c79f81bf6f18
|
4
|
+
data.tar.gz: 91796ec52b8680a1449c8a9e424894e786191a82b2e96679ca767dee69ffa04a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6b3d2698127d1aad4f6f729ef1735322658670e8527ab0d7a746ca23c9c7d77669ccb9751d731a4efe431355bf376904237f3a85fd60edf260f252a411a1a6be
|
7
|
+
data.tar.gz: 530ce2ba4cb376a6120fcb2c80c7aab6f2eed57c02a6dff21825de3018079c3714e39fec69728bc6dd38bbc0e8433e87d9c9d9fd458c9a4914738af2ad1cb0c5
|
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -26,62 +26,17 @@ Or install it yourself as:
|
|
26
26
|
|
27
27
|
The example scripts are (some are planned):
|
28
28
|
|
29
|
-
command
|
30
|
-
|
31
|
-
`archimate
|
29
|
+
command | description
|
30
|
+
----------------------------- | -----------
|
31
|
+
`archimate clean ARCHIFILE` | Clean up unreferenced elements and relations
|
32
32
|
`archimate convert ARCHIFILE` | Convert the incoming file to the desired type
|
33
|
-
`archimate dedupe ARCHIFILE`
|
34
|
-
`archimate
|
35
|
-
`archimate
|
36
|
-
`archimate
|
37
|
-
`archimate
|
38
|
-
`archimate
|
39
|
-
|
40
|
-
### archidiff & archimerge
|
41
|
-
|
42
|
-
Archidiff is a set of tools to help with versioning an `.archimate` file from Archi in a version control system (like git). Eventually I want to provide diff and (3-way) merge tools that understand how *Archi* files are structured and avoid problems that happen when multiple people collaborate on a model.
|
43
|
-
|
44
|
-
To enable using these from the command line git, add these lines to your `~/.gitconfig` replacing `{PATH_TO_ARCHIDIFF}` with the path to the archidiff binaries.
|
45
|
-
|
46
|
-
```
|
47
|
-
[difftool "archidiff"]
|
48
|
-
cmd = {PATH_TO_ARCHIDIFF}/archidiff $LOCAL $REMOTE
|
49
|
-
|
50
|
-
[difftool "archidiff-summary"]
|
51
|
-
cmd = {PATH_TO_ARCHIDIFF}/archidiff-summary $LOCAL $REMOTE
|
52
|
-
|
53
|
-
[mergetool "archimerge"]
|
54
|
-
cmd = {PATH_TO_ARCHIDIFF}/archimerge $PWD/$BASE $PWD/$REMOTE $PWD/$LOCAL $PWD/$MERGED
|
55
|
-
trustExitCode = false
|
56
|
-
```
|
57
|
-
|
58
|
-
Then to use the tool for diffing you can do this:
|
59
|
-
|
60
|
-
```sh
|
61
|
-
git difftool --tool archidiff 833cbb7 HEAD -- path_to/my.archimate
|
62
|
-
```
|
63
|
-
|
64
|
-
or to see a summary of what changed between versions:
|
65
|
-
|
66
|
-
```sh
|
67
|
-
git difftool --tool archidiff-summary 833cbb7 HEAD -- path_to/my.archimate
|
68
|
-
```
|
69
|
-
|
70
|
-
Finally, if you have a merge conflict, you can use archimerge to help make the merge sane:
|
71
|
-
|
72
|
-
```sh
|
73
|
-
git mergetool --tool archimerge -- path_to/my.archimate
|
74
|
-
```
|
75
|
-
|
76
|
-
### fmtxml
|
77
|
-
|
78
|
-
Can be used as a `textconv` filter in .gitconfig to pre-format files for better diff use (for visual scanning). You'd set this up in your `$HOME/.gitconfig` file like this.
|
79
|
-
|
80
|
-
```
|
81
|
-
[diff "archimate"]
|
82
|
-
textconv = fmtxml
|
83
|
-
cachetextconv = true
|
84
|
-
```
|
33
|
+
`archimate dedupe ARCHIFILE` | de-duplicate elements in Archi file
|
34
|
+
`archimate dupes ARCHIFILE` | List (potential) duplicate elements in Archi file
|
35
|
+
`archimate help [COMMAND]` | Describe available commands or one specific command
|
36
|
+
`archimate lint ARCHIFILE` | Examine the ArchiMate file for potential problems
|
37
|
+
`archimate map ARCHIFILE` | Produce a map of diagram links to a diagram
|
38
|
+
`archimate stats ARCHIFILE` | Show some statistics about the model
|
39
|
+
`archimate svg -o OUTPUTDIR ARCHIFILE o, --output=OUTPUT` | Produce semantically meaningful SVG files from an Archi file
|
85
40
|
|
86
41
|
## Development
|
87
42
|
|
data/Rakefile
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
# frozen_string_literal:
|
1
|
+
# frozen_string_literal: false
|
2
|
+
|
2
3
|
require "bundler/gem_tasks"
|
3
4
|
require "rake/testtask"
|
4
5
|
require "yard"
|
@@ -9,6 +10,23 @@ Rake::TestTask.new(:test) do |t|
|
|
9
10
|
t.test_files = FileList['test/**/*_test.rb']
|
10
11
|
end
|
11
12
|
|
13
|
+
namespace :test do
|
14
|
+
desc "Run only integration tests."
|
15
|
+
Rake::TestTask.new(:integration) do |t|
|
16
|
+
t.libs << "test"
|
17
|
+
t.libs << "lib"
|
18
|
+
t.test_files = FileList['test/integration/**/*_test.rb']
|
19
|
+
end
|
20
|
+
|
21
|
+
desc "Run tests and report slowest tests."
|
22
|
+
Rake::TestTask.new(:profile) do |t|
|
23
|
+
t.libs << "test"
|
24
|
+
t.libs << "lib"
|
25
|
+
t.options = "--profile"
|
26
|
+
t.test_files = FileList['test/**/*_test.rb']
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
12
30
|
YARD::Rake::YardocTask.new do |t|
|
13
31
|
t.options += ['--title', "YARD #{YARD::VERSION} Documentation"]
|
14
32
|
end
|
data/archimate.gemspec
CHANGED
@@ -21,32 +21,34 @@ Gem::Specification.new do |spec|
|
|
21
21
|
spec.metadata["yard.run"] = "yri" # use "yard" to build full HTML docs.
|
22
22
|
spec.required_ruby_version = '>= 2.3.0'
|
23
23
|
|
24
|
-
spec.add_runtime_dependency "nokogiri", "~> 1.6"
|
25
|
-
spec.add_runtime_dependency "thor", "~> 0.19"
|
26
24
|
spec.add_runtime_dependency "highline", "~> 1.7"
|
27
|
-
spec.add_runtime_dependency "
|
25
|
+
spec.add_runtime_dependency "nokogiri", "~> 1.6"
|
28
26
|
spec.add_runtime_dependency "parallel", "~> 1.11"
|
29
27
|
spec.add_runtime_dependency "ruby-enum", "~> 0.7.1"
|
28
|
+
spec.add_runtime_dependency "ruby-progressbar", "~>1.8.1"
|
29
|
+
spec.add_runtime_dependency "thor", "~> 0.19"
|
30
30
|
|
31
|
+
spec.add_development_dependency "awesome_print"
|
31
32
|
spec.add_development_dependency "bundler"
|
32
|
-
spec.add_development_dependency "
|
33
|
+
spec.add_development_dependency "faker"
|
34
|
+
spec.add_development_dependency "kramdown"
|
33
35
|
spec.add_development_dependency "minitest"
|
34
|
-
spec.add_development_dependency "minitest-matchers"
|
35
36
|
spec.add_development_dependency "minitest-color"
|
37
|
+
spec.add_development_dependency "minitest-matchers"
|
36
38
|
spec.add_development_dependency "minitest-profile"
|
37
39
|
spec.add_development_dependency "pry"
|
38
|
-
spec.add_development_dependency "
|
40
|
+
spec.add_development_dependency "rake"
|
41
|
+
spec.add_development_dependency "rubocop"
|
42
|
+
spec.add_development_dependency "yard"
|
43
|
+
|
44
|
+
# TODO: These should be in an MRI block
|
39
45
|
spec.add_development_dependency "guard"
|
40
|
-
spec.add_development_dependency "guard-minitest"
|
41
46
|
spec.add_development_dependency "guard-bundler"
|
47
|
+
spec.add_development_dependency "guard-ctags-bundler"
|
48
|
+
spec.add_development_dependency "guard-minitest"
|
49
|
+
spec.add_development_dependency "pry-byebug"
|
50
|
+
spec.add_development_dependency "rsense"
|
42
51
|
spec.add_development_dependency "ruby-prof"
|
43
52
|
spec.add_development_dependency "simplecov"
|
44
53
|
spec.add_development_dependency "simplecov-json"
|
45
|
-
spec.add_development_dependency "kramdown"
|
46
|
-
spec.add_development_dependency "yard"
|
47
|
-
spec.add_development_dependency "guard-ctags-bundler"
|
48
|
-
spec.add_development_dependency "faker"
|
49
|
-
spec.add_development_dependency "rsense"
|
50
|
-
spec.add_development_dependency "awesome_print"
|
51
|
-
spec.add_development_dependency "rubocop"
|
52
54
|
end
|
data/bin/archimate
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# frozen_string_literal: true
|
3
|
+
|
3
4
|
#
|
4
5
|
# This file was generated by Bundler.
|
5
6
|
#
|
@@ -11,6 +12,17 @@ require "pathname"
|
|
11
12
|
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
12
13
|
Pathname.new(__FILE__).realpath)
|
13
14
|
|
15
|
+
bundle_binstub = File.expand_path("../bundle", __FILE__)
|
16
|
+
|
17
|
+
if File.file?(bundle_binstub)
|
18
|
+
if File.read(bundle_binstub, 150) =~ /This file was generated by Bundler/
|
19
|
+
load(bundle_binstub)
|
20
|
+
else
|
21
|
+
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
22
|
+
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
14
26
|
require "rubygems"
|
15
27
|
require "bundler/setup"
|
16
28
|
|
data/lib/archimate/cli/archi.rb
CHANGED
@@ -48,7 +48,7 @@ module Archimate
|
|
48
48
|
).map
|
49
49
|
end
|
50
50
|
|
51
|
-
desc "svg -o OUTPUTDIR ARCHIFILE", "
|
51
|
+
desc "svg -o OUTPUTDIR ARCHIFILE", "Produce semantically meaningful SVG files from an Archi file"
|
52
52
|
option :output,
|
53
53
|
aliases: :o,
|
54
54
|
required: true,
|
@@ -58,39 +58,53 @@ module Archimate
|
|
58
58
|
type: :boolean,
|
59
59
|
default: false,
|
60
60
|
desc: "Don't provide interactive feedback"
|
61
|
+
option :name,
|
62
|
+
type: :boolean,
|
63
|
+
default: false,
|
64
|
+
desc: "Use diagram name for filename (default: diagram id)"
|
61
65
|
def svg(archifile)
|
62
66
|
Config.instance.interactive = !options.fetch("noninteractive", false)
|
63
67
|
Archimate::Cli::Svger.export_svgs(
|
64
68
|
archifile,
|
65
|
-
options.fetch("output", Dir.pwd)
|
69
|
+
options.fetch("output", Dir.pwd),
|
70
|
+
options["name"] ? :name : :id
|
66
71
|
)
|
67
72
|
end
|
68
73
|
|
69
74
|
desc "clean ARCHIFILE", "Clean up unreferenced elements and relations"
|
70
75
|
option :output,
|
71
76
|
aliases: :o,
|
72
|
-
desc: "Write output to
|
77
|
+
desc: "Write output to OUTPUT instead of replacing ARCHIFILE"
|
73
78
|
option :saveremoved,
|
74
79
|
aliases: :r,
|
75
|
-
desc: "Write removed elements into
|
80
|
+
desc: "Write removed elements into SAVEREMOVED"
|
76
81
|
option :noninteractive,
|
77
82
|
aliases: :n,
|
78
83
|
type: :boolean,
|
79
84
|
default: false,
|
80
85
|
desc: "Don't provide interactive feedback"
|
86
|
+
option :force,
|
87
|
+
aliases: :f,
|
88
|
+
type: :boolean,
|
89
|
+
default: false,
|
90
|
+
desc: "Force overwriting of existing output file"
|
81
91
|
def clean(archifile)
|
82
92
|
Config.instance.interactive = !options.fetch("noninteractive", false)
|
83
|
-
|
93
|
+
output_io = Cli.output_io(
|
94
|
+
options.fetch("output", archifile),
|
95
|
+
options.fetch("force", false)
|
96
|
+
)
|
84
97
|
Archimate::MaybeIO.new(options.fetch(:saveremoved, nil)) do |removed_element_io|
|
85
|
-
Archimate::Cli::Cleanup.new(Archimate.read(archifile),
|
98
|
+
Archimate::Cli::Cleanup.new(Archimate.read(archifile), output_io, removed_element_io).clean
|
86
99
|
end
|
100
|
+
output_io.close
|
87
101
|
end
|
88
102
|
|
89
103
|
desc "dupes ARCHIFILE", "List (potential) duplicate elements in Archi file"
|
90
104
|
def dupes(archifile)
|
91
105
|
Archimate::Cli::Duper.new(
|
92
|
-
|
93
|
-
|
106
|
+
Archimate.read(archifile),
|
107
|
+
$stdout
|
94
108
|
).list
|
95
109
|
end
|
96
110
|
|
@@ -115,27 +129,32 @@ module Archimate
|
|
115
129
|
desc: "Don't provide interactive feedback"
|
116
130
|
def dedupe(archifile)
|
117
131
|
Config.instance.interactive = !options.fetch("noninteractive", false)
|
132
|
+
output_io = Cli.output_io(
|
133
|
+
options.fetch("output", archifile),
|
134
|
+
options[:force]
|
135
|
+
)
|
118
136
|
Archimate::Cli::Duper.new(
|
119
137
|
Archimate.read(archifile),
|
120
|
-
|
121
|
-
options.fetch("output", archifile),
|
122
|
-
options[:force]
|
123
|
-
),
|
138
|
+
output_io,
|
124
139
|
options[:mergeall]
|
125
140
|
).merge
|
141
|
+
output_io.close
|
126
142
|
end
|
127
143
|
|
128
144
|
desc "convert ARCHIFILE", "Convert the incoming file to the desired type"
|
145
|
+
long_desc <<~CONVERT_DESC
|
146
|
+
Converts the input ArchiMate file into another format. Options are:
|
147
|
+
\x5 • 'archi' for Archi file format (http://archimatetool.com),
|
148
|
+
\x5 • 'meff2.1' for Open Group Model Exchange File Format for ArchiMate 2.1,
|
149
|
+
\x5 • 'nquads' for RDF 1.1 N-Quads format https://www.w3.org/TR/n-quads/,
|
150
|
+
\x5 • 'graphml' for GraphML,
|
151
|
+
\x5 • 'csv' for CSV files (one file per element/relationship type)
|
152
|
+
CONVERT_DESC
|
129
153
|
option :to,
|
130
154
|
aliases: :t,
|
131
155
|
default: Archimate::Cli::Convert::SUPPORTED_FORMATS.first,
|
132
|
-
|
133
|
-
|
134
|
-
"'archi' for Archi http://archimatetool.com/ file format " \
|
135
|
-
"'nquads' for RDF 1.1 N-Quads format https://www.w3.org/TR/n-quads/" \
|
136
|
-
"'graphml' for GraphML" \
|
137
|
-
"'csv' for CSV files (one file per element/relationship type",
|
138
|
-
enum: Archimate::Cli::Convert::SUPPORTED_FORMATS
|
156
|
+
enum: Archimate::Cli::Convert::SUPPORTED_FORMATS,
|
157
|
+
desc: "Output format to convert to"
|
139
158
|
option :output,
|
140
159
|
aliases: :o,
|
141
160
|
desc: "Write output to FILE instead of stdout."
|
@@ -1,52 +1,68 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require "nokogiri"
|
3
4
|
|
4
5
|
#
|
5
6
|
# The point of this script is to identify elements that aren't a part of any
|
6
7
|
# relationship and not referenced on any diagrams.
|
7
|
-
|
8
8
|
module Archimate
|
9
9
|
module Cli
|
10
10
|
class Cleanup
|
11
11
|
attr_reader :model
|
12
12
|
|
13
|
-
def
|
14
|
-
cleaner = new(Archimate.read(input), output, options)
|
15
|
-
cleaner.clean
|
16
|
-
end
|
17
|
-
|
18
|
-
def initialize(model, output, options)
|
13
|
+
def initialize(model, output, removed_items_io)
|
19
14
|
@model = model
|
20
15
|
@output = output
|
21
|
-
@
|
22
|
-
@trash = Nokogiri::XML::Document.new("<deleted></deleted>")
|
16
|
+
@removed_items_io = removed_items_io
|
23
17
|
@model_set = nil
|
24
|
-
@progressbar = ProgressIndicator.new(total:
|
18
|
+
@progressbar = ProgressIndicator.new(total: unreferenced_nodes.size, title: "Unreferenced Elements and Relationships")
|
19
|
+
@unref_set = []
|
25
20
|
end
|
26
21
|
|
27
|
-
|
28
|
-
|
29
|
-
|
22
|
+
# detects elements not referenced by a relationship or a diagram
|
23
|
+
def unreferenced_elements
|
24
|
+
model
|
25
|
+
.elements
|
26
|
+
.select { |el| el.references.none?(&ref_is_relationship_or_diagram) }
|
27
|
+
end
|
30
28
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
@progressbar.increment
|
36
|
-
end
|
29
|
+
def unreferenced_relationships
|
30
|
+
model
|
31
|
+
.relationships
|
32
|
+
.select { |rel| rel.references.none?(&ref_is_relationship_or_diagram) }
|
37
33
|
end
|
38
34
|
|
39
|
-
def
|
40
|
-
|
35
|
+
def unreferenced_nodes
|
36
|
+
unreferenced_relationships + unreferenced_elements
|
37
|
+
end
|
38
|
+
|
39
|
+
def destroy_nodes(nodes)
|
40
|
+
nodes.each do |unreferenced_node|
|
41
|
+
unreferenced_node.destroy
|
42
|
+
@removed_items_io.write(Color.uncolor(unreferenced_node.to_s) + "\n")
|
43
|
+
@unref_set << unreferenced_node
|
44
|
+
@progressbar.increment
|
45
|
+
end
|
41
46
|
end
|
42
47
|
|
43
48
|
def clean
|
44
49
|
return unless model
|
45
50
|
|
46
|
-
|
47
|
-
puts "
|
48
|
-
|
49
|
-
|
51
|
+
rels = unreferenced_relationships
|
52
|
+
$stdout.puts "Unreferenced Relationships: #{rels.size}"
|
53
|
+
destroy_nodes rels
|
54
|
+
els = unreferenced_elements
|
55
|
+
$stdout.puts "Unreferenced Elements: #{els.size}"
|
56
|
+
destroy_nodes els
|
57
|
+
|
58
|
+
$stdout.puts "Found #{@unref_set.size} model items unreferenced by diagram or relationships"
|
59
|
+
Archimate::FileFormats::ArchiFileWriter.write(model, @output)
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def ref_is_relationship_or_diagram
|
65
|
+
->(ref) { ref.is_a?(DataModel::Relationship) || ref.is_a?(DataModel::Diagram) }
|
50
66
|
end
|
51
67
|
end
|
52
68
|
end
|
data/lib/archimate/cli/duper.rb
CHANGED
data/lib/archimate/cli/mapper.rb
CHANGED
@@ -13,34 +13,57 @@ module Archimate
|
|
13
13
|
@output = output_io
|
14
14
|
end
|
15
15
|
|
16
|
+
def map
|
17
|
+
widths = compute_column_widths(process_diagrams(model.diagrams), HEADERS)
|
18
|
+
adjusted_widths = widths.inject(COL_DIVIDER.size * (HEADERS.size - 1), &:+)
|
19
|
+
header_row(widths, HEADERS)
|
20
|
+
organization_paths = build_organization_hash(model.organizations)
|
21
|
+
organization_paths.keys.sort.each do |organization_name|
|
22
|
+
diagrams = organization_paths[organization_name].select { |i| i.is_a?(DataModel::Diagram) }
|
23
|
+
next if diagrams.empty?
|
24
|
+
@output.puts(Color.color(format("%-#{adjusted_widths}s", organization_name), %i[bold green on_light_black]))
|
25
|
+
output_diagrams(process_diagrams(diagrams), widths)
|
26
|
+
end
|
27
|
+
|
28
|
+
@output.puts "\n#{model.diagrams.size} Diagrams"
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
16
33
|
def header_row(widths, headers)
|
17
|
-
titles =
|
18
|
-
|
19
|
-
|
20
|
-
|
34
|
+
titles = widths
|
35
|
+
.zip(headers)
|
36
|
+
.map(&header_cell_format)
|
37
|
+
.join(col_divider)
|
38
|
+
@output.puts titles
|
39
|
+
@output.puts header_border(widths)
|
40
|
+
end
|
41
|
+
|
42
|
+
def col_divider
|
43
|
+
Color.color(COL_DIVIDER, :light_black)
|
44
|
+
end
|
45
|
+
|
46
|
+
def header_border(widths)
|
47
|
+
Color.color(widths.map { |w| "-" * w }.join("-+-"), :light_black)
|
48
|
+
end
|
49
|
+
|
50
|
+
def header_cell_format
|
51
|
+
->((width, header)) { Color.color(format("%-#{width}s", header).capitalize, %i[bold blue]) }
|
21
52
|
end
|
22
53
|
|
23
54
|
def process_diagrams(diagrams)
|
24
|
-
diagrams.map
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
when "archimate:ArchimateDiagramModel"
|
31
|
-
DataModel::ViewpointType.values[(row[2] || 0).to_i].to_s
|
32
|
-
else
|
33
|
-
row[3]
|
34
|
-
end
|
35
|
-
row[0] = Color.color("#{row[0]}.png", :underline)
|
36
|
-
row
|
55
|
+
diagrams.map do |diagram|
|
56
|
+
[
|
57
|
+
"#{diagram.id}.png",
|
58
|
+
diagram.name.to_s,
|
59
|
+
diagram.viewpoint_description
|
60
|
+
]
|
37
61
|
end
|
38
62
|
end
|
39
63
|
|
40
64
|
def compute_column_widths(diagrams, headers)
|
41
|
-
|
42
|
-
|
43
|
-
diagram.slice(0, headers.size).each_with_index do |o, i|
|
65
|
+
diagrams.each_with_object(headers.map(&:size)) do |diagram, memo|
|
66
|
+
diagram.each_with_index do |o, i|
|
44
67
|
memo[i] = !o.nil? && Color.uncolor(o).size > memo[i] ? Color.uncolor(o).size : memo[i]
|
45
68
|
end
|
46
69
|
memo
|
@@ -49,33 +72,23 @@ module Archimate
|
|
49
72
|
|
50
73
|
def output_diagrams(diagrams, widths)
|
51
74
|
diagrams.sort_by { |a| a[1] }.each do |m|
|
52
|
-
|
53
|
-
|
54
|
-
|
75
|
+
@output.puts(
|
76
|
+
widths
|
77
|
+
.zip(m)
|
78
|
+
.map { |(width, col)| format("%-#{width}s", col) }
|
79
|
+
.join(Color.color(COL_DIVIDER, :light_black))
|
80
|
+
)
|
55
81
|
end
|
56
82
|
end
|
57
83
|
|
58
84
|
def build_organization_hash(organizations, parent = "", hash = {})
|
59
|
-
organizations.each_with_object(hash) do |i, a|
|
85
|
+
organization_paths = organizations.each_with_object(hash) do |i, a|
|
60
86
|
organization_path = [parent, i.name].join("/")
|
61
|
-
a[organization_path] = i
|
87
|
+
a[organization_path] = i.items
|
62
88
|
build_organization_hash(i.organizations, organization_path, a)
|
63
89
|
end
|
64
|
-
|
65
|
-
|
66
|
-
def map
|
67
|
-
widths = compute_column_widths(process_diagrams(model.diagrams), HEADERS)
|
68
|
-
adjusted_widths = widths.inject(COL_DIVIDER.size * (HEADERS.size - 1), &:+)
|
69
|
-
header_row(widths, HEADERS)
|
70
|
-
organization_paths = build_organization_hash(model.organizations)
|
71
|
-
organization_paths.keys.sort.each do |organization_name|
|
72
|
-
diagrams = organization_paths[organization_name].items.map { |i| model.lookup(i) }.select { |i| i.is_a?(DataModel::Diagram) }
|
73
|
-
next if diagrams.empty?
|
74
|
-
@output.puts(Color.color(format("%-#{adjusted_widths}s", organization_name), %i[bold green on_light_black]))
|
75
|
-
output_diagrams(process_diagrams(diagrams), widths)
|
76
|
-
end
|
77
|
-
|
78
|
-
@output.puts "\n#{model.diagrams.size} Diagrams"
|
90
|
+
organization_paths = { "/" => model.diagrams } if organization_paths.empty?
|
91
|
+
organization_paths
|
79
92
|
end
|
80
93
|
end
|
81
94
|
end
|
data/lib/archimate/cli/svger.rb
CHANGED
@@ -2,21 +2,26 @@
|
|
2
2
|
|
3
3
|
module Archimate
|
4
4
|
module Cli
|
5
|
+
SVG_NAME_OPTION = [:id, :name] # TODO: add a way to export in folders with :folder_name]
|
6
|
+
|
5
7
|
# This class is used to export SVG diagrams as defined in the given model
|
6
8
|
class Svger
|
7
|
-
def self.export_svgs(archi_file, output_dir)
|
8
|
-
new(Archimate.read(archi_file).diagrams, output_dir).export_svgs
|
9
|
+
def self.export_svgs(archi_file, output_dir, name_option = :id)
|
10
|
+
new(Archimate.read(archi_file).diagrams, output_dir, name_option).export_svgs
|
9
11
|
end
|
10
12
|
|
11
|
-
def initialize(diagrams, output_dir)
|
13
|
+
def initialize(diagrams, output_dir, name_option = :id)
|
12
14
|
@diagrams = diagrams
|
13
15
|
@output_dir = output_dir
|
16
|
+
@name_option = name_option
|
17
|
+
@diagram_base_names = {}
|
14
18
|
end
|
15
19
|
|
16
20
|
def export_svgs
|
21
|
+
@diagram_base_names = {}
|
17
22
|
progress = ProgressIndicator.new(total: @diagrams.size, title: "Writing SVGs")
|
18
23
|
@diagrams.each do |diagram|
|
19
|
-
export(diagram)
|
24
|
+
export(diagram, filename_for(diagram, @name_option))
|
20
25
|
progress.increment
|
21
26
|
end
|
22
27
|
ensure
|
@@ -29,6 +34,30 @@ module Archimate
|
|
29
34
|
svg_file.write(Svg::Diagram.new(diagram).to_svg)
|
30
35
|
end
|
31
36
|
end
|
37
|
+
|
38
|
+
# TODO: in case of duplicate name in a model, we need to extend the filename with a numeric or something.
|
39
|
+
def filename_for(diagram, name_option)
|
40
|
+
base_name = diagram_base_name(diagram, name_option)
|
41
|
+
if @diagram_base_names.include?(base_name)
|
42
|
+
idx = 2
|
43
|
+
while @diagram_base_names.include?(base_name + " - #{idx}") do
|
44
|
+
idx += 1
|
45
|
+
end
|
46
|
+
base_name = base_name + " - #{idx}"
|
47
|
+
end
|
48
|
+
base_name
|
49
|
+
end
|
50
|
+
|
51
|
+
def diagram_base_name(diagram, name_option)
|
52
|
+
case name_option
|
53
|
+
when :name
|
54
|
+
diagram.name
|
55
|
+
# when :folder_name
|
56
|
+
# diagram.name # TODO: add the path
|
57
|
+
else
|
58
|
+
diagram.id
|
59
|
+
end
|
60
|
+
end
|
32
61
|
end
|
33
62
|
|
34
63
|
def self.process_svg_filename(name)
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Archimate
|
4
|
+
module CoreRefinements
|
5
|
+
refine String do
|
6
|
+
# Converts a mixed case string to a snake case string
|
7
|
+
# @return String
|
8
|
+
def snake_case
|
9
|
+
gsub(/([A-Z])/, '_\1').downcase.sub(/^_/, "")
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_method_name(suffix = nil)
|
13
|
+
[tr(' ', '_'), suffix]
|
14
|
+
.compact
|
15
|
+
.join("_")
|
16
|
+
.to_sym
|
17
|
+
end
|
18
|
+
|
19
|
+
# A helper that makes it easier to compare a string to a DataModel::LangString
|
20
|
+
# @param [String, DataModel::LangString] other string to compare
|
21
|
+
# @returns [Boolean]
|
22
|
+
def ==(other)
|
23
|
+
super(other.to_s)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
refine Range do
|
28
|
+
# Returns midpoint of overlap between numeric ranges or nil if there
|
29
|
+
# is no overlap
|
30
|
+
# @param r [Range] a numeric range
|
31
|
+
# @return [Numeric] if the ranges overlap, the midpoint of the overlap
|
32
|
+
# @return [Nil] if the ranges do not overlap
|
33
|
+
def overlap_midpoint(r)
|
34
|
+
begin_max = [self, r].map(&:begin).max
|
35
|
+
end_min = [self, r].map(&:end).min
|
36
|
+
return nil if begin_max > end_min
|
37
|
+
(begin_max + end_min) / 2.0
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|