archimate 1.1.0
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 +22 -0
- data/.projectile +18 -0
- data/.rubocop.yml +13 -0
- data/.travis.yml +4 -0
- data/.yardocs +15 -0
- data/Gemfile +5 -0
- data/Guardfile +27 -0
- data/LICENSE +201 -0
- data/README.md +94 -0
- data/Rakefile +29 -0
- data/TODOs.org +286 -0
- data/archimate.gemspec +51 -0
- data/bin/archimate +17 -0
- data/bin/console +13 -0
- data/bin/setup +8 -0
- data/exe/archidiff +7 -0
- data/exe/archidiff-summary +7 -0
- data/exe/archimate +7 -0
- data/exe/archimerge +7 -0
- data/exe/fmtxml +7 -0
- data/lib/archimate/cli/archi.rb +189 -0
- data/lib/archimate/cli/cleanup.rb +54 -0
- data/lib/archimate/cli/conflict_resolver.rb +39 -0
- data/lib/archimate/cli/convert.rb +39 -0
- data/lib/archimate/cli/diff.rb +31 -0
- data/lib/archimate/cli/diff_summary.rb +101 -0
- data/lib/archimate/cli/duper.rb +85 -0
- data/lib/archimate/cli/lint.rb +16 -0
- data/lib/archimate/cli/mapper.rb +82 -0
- data/lib/archimate/cli/merge.rb +49 -0
- data/lib/archimate/cli/merger.rb +109 -0
- data/lib/archimate/cli/stats.rb +42 -0
- data/lib/archimate/cli/svger.rb +40 -0
- data/lib/archimate/color.rb +53 -0
- data/lib/archimate/config.rb +35 -0
- data/lib/archimate/data_model/any_attribute.rb +13 -0
- data/lib/archimate/data_model/any_element.rb +15 -0
- data/lib/archimate/data_model/archimate_node.rb +181 -0
- data/lib/archimate/data_model/bounds.rb +72 -0
- data/lib/archimate/data_model/color.rb +47 -0
- data/lib/archimate/data_model/concept.rb +14 -0
- data/lib/archimate/data_model/concern.rb +17 -0
- data/lib/archimate/data_model/connection.rb +107 -0
- data/lib/archimate/data_model/constants.rb +82 -0
- data/lib/archimate/data_model/container.rb +17 -0
- data/lib/archimate/data_model/diagram.rb +40 -0
- data/lib/archimate/data_model/diffable_array.rb +213 -0
- data/lib/archimate/data_model/diffable_primitive.rb +83 -0
- data/lib/archimate/data_model/documentation.rb +14 -0
- data/lib/archimate/data_model/element.rb +87 -0
- data/lib/archimate/data_model/font.rb +54 -0
- data/lib/archimate/data_model/label.rb +19 -0
- data/lib/archimate/data_model/lang_string.rb +41 -0
- data/lib/archimate/data_model/location.rb +31 -0
- data/lib/archimate/data_model/metadata.rb +14 -0
- data/lib/archimate/data_model/model.rb +217 -0
- data/lib/archimate/data_model/modeling_note.rb +13 -0
- data/lib/archimate/data_model/named_referenceable.rb +14 -0
- data/lib/archimate/data_model/organization.rb +40 -0
- data/lib/archimate/data_model/property.rb +25 -0
- data/lib/archimate/data_model/property_definition.rb +16 -0
- data/lib/archimate/data_model/referenceable.rb +29 -0
- data/lib/archimate/data_model/relationship.rb +85 -0
- data/lib/archimate/data_model/schema_info.rb +18 -0
- data/lib/archimate/data_model/style.rb +32 -0
- data/lib/archimate/data_model/view.rb +12 -0
- data/lib/archimate/data_model/view_concept.rb +18 -0
- data/lib/archimate/data_model/view_node.rb +114 -0
- data/lib/archimate/data_model/viewpoint.rb +87 -0
- data/lib/archimate/data_model.rb +54 -0
- data/lib/archimate/diff/archimate_array_reference.rb +113 -0
- data/lib/archimate/diff/archimate_identified_node_reference.rb +41 -0
- data/lib/archimate/diff/archimate_node_attribute_reference.rb +70 -0
- data/lib/archimate/diff/archimate_node_reference.rb +80 -0
- data/lib/archimate/diff/change.rb +49 -0
- data/lib/archimate/diff/conflict.rb +31 -0
- data/lib/archimate/diff/conflicts/base_conflict.rb +53 -0
- data/lib/archimate/diff/conflicts/deleted_items_child_updated_conflict.rb +30 -0
- data/lib/archimate/diff/conflicts/deleted_items_referenced_conflict.rb +63 -0
- data/lib/archimate/diff/conflicts/path_conflict.rb +51 -0
- data/lib/archimate/diff/conflicts.rb +89 -0
- data/lib/archimate/diff/delete.rb +41 -0
- data/lib/archimate/diff/difference.rb +113 -0
- data/lib/archimate/diff/insert.rb +43 -0
- data/lib/archimate/diff/merge.rb +70 -0
- data/lib/archimate/diff/move.rb +51 -0
- data/lib/archimate/diff.rb +17 -0
- data/lib/archimate/export/csv_export.rb +32 -0
- data/lib/archimate/export/cypher.rb +171 -0
- data/lib/archimate/export/graph_ml.rb +131 -0
- data/lib/archimate/export/n_quads.rb +142 -0
- data/lib/archimate/file_format.rb +30 -0
- data/lib/archimate/file_formats/archi_file_format.rb +151 -0
- data/lib/archimate/file_formats/archi_file_reader.rb +252 -0
- data/lib/archimate/file_formats/archi_file_writer.rb +230 -0
- data/lib/archimate/file_formats/archimate_v2.rb +461 -0
- data/lib/archimate/file_formats/model_exchange_file/xml_lang_string.rb +35 -0
- data/lib/archimate/file_formats/model_exchange_file/xml_metadata.rb +115 -0
- data/lib/archimate/file_formats/model_exchange_file/xml_property_definitions.rb +28 -0
- data/lib/archimate/file_formats/model_exchange_file/xml_property_defs.rb +27 -0
- data/lib/archimate/file_formats/model_exchange_file_reader.rb +237 -0
- data/lib/archimate/file_formats/model_exchange_file_reader_21.rb +73 -0
- data/lib/archimate/file_formats/model_exchange_file_reader_30.rb +134 -0
- data/lib/archimate/file_formats/model_exchange_file_writer.rb +157 -0
- data/lib/archimate/file_formats/model_exchange_file_writer_21.rb +143 -0
- data/lib/archimate/file_formats/model_exchange_file_writer_30.rb +153 -0
- data/lib/archimate/file_formats/writer.rb +56 -0
- data/lib/archimate/lint/duplicate_entities.rb +121 -0
- data/lib/archimate/lint/linter.rb +146 -0
- data/lib/archimate/logging.rb +55 -0
- data/lib/archimate/maybe_io.rb +34 -0
- data/lib/archimate/progress_indicator.rb +29 -0
- data/lib/archimate/svg/archimate.css +232 -0
- data/lib/archimate/svg/child.rb +29 -0
- data/lib/archimate/svg/connection.rb +184 -0
- data/lib/archimate/svg/css_style.rb +31 -0
- data/lib/archimate/svg/diagram.rb +87 -0
- data/lib/archimate/svg/entity/and_junction.rb +14 -0
- data/lib/archimate/svg/entity/application_collaboration.rb +14 -0
- data/lib/archimate/svg/entity/application_component.rb +41 -0
- data/lib/archimate/svg/entity/application_event.rb +13 -0
- data/lib/archimate/svg/entity/application_function.rb +13 -0
- data/lib/archimate/svg/entity/application_interaction.rb +13 -0
- data/lib/archimate/svg/entity/application_interface.rb +13 -0
- data/lib/archimate/svg/entity/application_process.rb +13 -0
- data/lib/archimate/svg/entity/application_service.rb +13 -0
- data/lib/archimate/svg/entity/artifact.rb +39 -0
- data/lib/archimate/svg/entity/assessment.rb +14 -0
- data/lib/archimate/svg/entity/base_entity.rb +128 -0
- data/lib/archimate/svg/entity/business_actor.rb +14 -0
- data/lib/archimate/svg/entity/business_collaboration.rb +14 -0
- data/lib/archimate/svg/entity/business_event.rb +10 -0
- data/lib/archimate/svg/entity/business_function.rb +13 -0
- data/lib/archimate/svg/entity/business_interaction.rb +13 -0
- data/lib/archimate/svg/entity/business_interface.rb +13 -0
- data/lib/archimate/svg/entity/business_object.rb +13 -0
- data/lib/archimate/svg/entity/business_process.rb +13 -0
- data/lib/archimate/svg/entity/business_role.rb +14 -0
- data/lib/archimate/svg/entity/business_service.rb +13 -0
- data/lib/archimate/svg/entity/capability.rb +14 -0
- data/lib/archimate/svg/entity/communication_network.rb +14 -0
- data/lib/archimate/svg/entity/communication_path.rb +14 -0
- data/lib/archimate/svg/entity/constraint.rb +15 -0
- data/lib/archimate/svg/entity/contract.rb +13 -0
- data/lib/archimate/svg/entity/course_of_action.rb +14 -0
- data/lib/archimate/svg/entity/data_entity.rb +29 -0
- data/lib/archimate/svg/entity/data_object.rb +13 -0
- data/lib/archimate/svg/entity/deliverable.rb +13 -0
- data/lib/archimate/svg/entity/device.rb +48 -0
- data/lib/archimate/svg/entity/diagram_model_reference.rb +22 -0
- data/lib/archimate/svg/entity/diagram_object.rb +30 -0
- data/lib/archimate/svg/entity/distribution_network.rb +14 -0
- data/lib/archimate/svg/entity/driver.rb +14 -0
- data/lib/archimate/svg/entity/equipment.rb +16 -0
- data/lib/archimate/svg/entity/event_entity.rb +36 -0
- data/lib/archimate/svg/entity/facility.rb +16 -0
- data/lib/archimate/svg/entity/function_entity.rb +14 -0
- data/lib/archimate/svg/entity/gap.rb +21 -0
- data/lib/archimate/svg/entity/goal.rb +14 -0
- data/lib/archimate/svg/entity/group.rb +24 -0
- data/lib/archimate/svg/entity/implementation_event.rb +13 -0
- data/lib/archimate/svg/entity/infrastructure_function.rb +13 -0
- data/lib/archimate/svg/entity/infrastructure_interface.rb +13 -0
- data/lib/archimate/svg/entity/infrastructure_service.rb +13 -0
- data/lib/archimate/svg/entity/interaction_entity.rb +14 -0
- data/lib/archimate/svg/entity/interface_entity.rb +35 -0
- data/lib/archimate/svg/entity/junction.rb +19 -0
- data/lib/archimate/svg/entity/location.rb +14 -0
- data/lib/archimate/svg/entity/material.rb +14 -0
- data/lib/archimate/svg/entity/meaning.rb +40 -0
- data/lib/archimate/svg/entity/motivation_entity.rb +40 -0
- data/lib/archimate/svg/entity/network.rb +14 -0
- data/lib/archimate/svg/entity/node.rb +33 -0
- data/lib/archimate/svg/entity/node_shape.rb +64 -0
- data/lib/archimate/svg/entity/note.rb +30 -0
- data/lib/archimate/svg/entity/or_junction.rb +14 -0
- data/lib/archimate/svg/entity/outcome.rb +15 -0
- data/lib/archimate/svg/entity/path.rb +14 -0
- data/lib/archimate/svg/entity/plateau.rb +15 -0
- data/lib/archimate/svg/entity/principle.rb +15 -0
- data/lib/archimate/svg/entity/process_entity.rb +63 -0
- data/lib/archimate/svg/entity/product.rb +20 -0
- data/lib/archimate/svg/entity/rect.rb +13 -0
- data/lib/archimate/svg/entity/rect_entity.rb +25 -0
- data/lib/archimate/svg/entity/representation.rb +31 -0
- data/lib/archimate/svg/entity/requirement.rb +15 -0
- data/lib/archimate/svg/entity/resource.rb +14 -0
- data/lib/archimate/svg/entity/rounded_rect_entity.rb +23 -0
- data/lib/archimate/svg/entity/service_entity.rb +51 -0
- data/lib/archimate/svg/entity/sketch_model_sticky.rb +14 -0
- data/lib/archimate/svg/entity/stakeholder.rb +15 -0
- data/lib/archimate/svg/entity/system_software.rb +14 -0
- data/lib/archimate/svg/entity/technology_collaboration.rb +14 -0
- data/lib/archimate/svg/entity/technology_event.rb +13 -0
- data/lib/archimate/svg/entity/technology_function.rb +13 -0
- data/lib/archimate/svg/entity/technology_interaction.rb +13 -0
- data/lib/archimate/svg/entity/technology_interface.rb +13 -0
- data/lib/archimate/svg/entity/technology_process.rb +13 -0
- data/lib/archimate/svg/entity/technology_service.rb +13 -0
- data/lib/archimate/svg/entity/value.rb +27 -0
- data/lib/archimate/svg/entity/work_package.rb +14 -0
- data/lib/archimate/svg/entity.rb +93 -0
- data/lib/archimate/svg/entity_factory.rb +17 -0
- data/lib/archimate/svg/extents.rb +27 -0
- data/lib/archimate/svg/point.rb +7 -0
- data/lib/archimate/svg/svg_template.rb +27 -0
- data/lib/archimate/svg/svg_template.svg.erb +169 -0
- data/lib/archimate/version.rb +4 -0
- data/lib/archimate.rb +114 -0
- metadata +623 -0
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require "nokogiri"
|
|
3
|
+
|
|
4
|
+
module Archimate
|
|
5
|
+
module FileFormats
|
|
6
|
+
# Archimate version 2.1 Model Exchange Format Writer
|
|
7
|
+
class ModelExchangeFileWriter21 < ModelExchangeFileWriter
|
|
8
|
+
def initialize(model)
|
|
9
|
+
super
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def model_attrs
|
|
13
|
+
model_namespaces.merge(
|
|
14
|
+
"xsi:schemaLocation" => model.schema_locations.join(" "),
|
|
15
|
+
"identifier" => identifier(model.id)
|
|
16
|
+
)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def serialize_model(xml)
|
|
20
|
+
xml.model(model_attrs) do
|
|
21
|
+
ModelExchangeFile::XmlMetadata.new(model.metadata).serialize(xml)
|
|
22
|
+
ModelExchangeFile::XmlLangString.new(model.name, :name).serialize(xml)
|
|
23
|
+
ModelExchangeFile::XmlLangString.new(model.documentation, :documentation).serialize(xml)
|
|
24
|
+
serialize_properties(xml, model)
|
|
25
|
+
serialize_elements(xml)
|
|
26
|
+
serialize_relationships(xml)
|
|
27
|
+
serialize_organization_root(xml, model.organizations)
|
|
28
|
+
serialize_property_defs(xml)
|
|
29
|
+
serialize_views(xml)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def serialize_property_defs(xml)
|
|
34
|
+
return if model.property_definitions.empty?
|
|
35
|
+
ModelExchangeFile::XmlPropertyDefs.new(model.property_definitions).serialize(xml)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def serialize_label(xml, str)
|
|
39
|
+
return if str.nil? || str.strip.empty?
|
|
40
|
+
name_attrs = str.lang && !str.lang.empty? ? {"xml:lang" => str.lang} : {}
|
|
41
|
+
xml.label(name_attrs) { xml.text text_proc(str) }
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def serialize_organization_root(xml, organizations)
|
|
45
|
+
return unless organizations && organizations.size > 0
|
|
46
|
+
xml.organization do
|
|
47
|
+
serialize(xml, organizations)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def serialize_item(xml, item)
|
|
52
|
+
xml.item(identifierref: identifier(item))
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def serialize_property(xml, property)
|
|
56
|
+
xml.property(identifierref: property.property_definition.id) do
|
|
57
|
+
ModelExchangeFile::XmlLangString.new(property.value, :value).serialize(xml)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def serialize_views(xml)
|
|
62
|
+
return if model.diagrams.empty?
|
|
63
|
+
xml.views do
|
|
64
|
+
serialize(xml, model.diagrams)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def serialize_diagram(xml, diagram)
|
|
69
|
+
xml.view(
|
|
70
|
+
remove_nil_values(
|
|
71
|
+
identifier: identifier(diagram.id),
|
|
72
|
+
viewpoint: diagram.viewpoint_type,
|
|
73
|
+
"xsi:type": diagram.type
|
|
74
|
+
)
|
|
75
|
+
) do
|
|
76
|
+
elementbase(xml, diagram)
|
|
77
|
+
serialize(xml, diagram.nodes)
|
|
78
|
+
serialize(xml, diagram.connections)
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def view_node_attrs(view_node, x_offset = 0, y_offset = 0)
|
|
83
|
+
attrs = {
|
|
84
|
+
identifier: identifier(view_node.id),
|
|
85
|
+
elementref: nil,
|
|
86
|
+
x: view_node.bounds ? (view_node.bounds&.x + x_offset).round : nil,
|
|
87
|
+
y: view_node.bounds ? (view_node.bounds&.y + y_offset).round : nil,
|
|
88
|
+
w: view_node.bounds&.width&.round,
|
|
89
|
+
h: view_node.bounds&.height&.round,
|
|
90
|
+
type: nil
|
|
91
|
+
}
|
|
92
|
+
if view_node.archimate_element
|
|
93
|
+
attrs[:elementref] = identifier(view_node.archimate_element)
|
|
94
|
+
elsif view_node.model
|
|
95
|
+
# Since it doesn't seem to be forbidden, we just assume we can use
|
|
96
|
+
# the elementref for views in views
|
|
97
|
+
attrs[:elementref] = view_node.model
|
|
98
|
+
attrs[:type] = "model"
|
|
99
|
+
else
|
|
100
|
+
attrs[:type] = "group"
|
|
101
|
+
end
|
|
102
|
+
remove_nil_values(attrs)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def serialize_view_node(xml, view_node, x_offset = 0, y_offset = 0)
|
|
106
|
+
attrs = view_node_attrs(view_node, x_offset, y_offset)
|
|
107
|
+
xml.node(attrs) do
|
|
108
|
+
serialize_label(xml, view_node.name) if attrs[:type] == "group"
|
|
109
|
+
serialize(xml, view_node.style) if view_node.style
|
|
110
|
+
view_node.nodes.each do |c|
|
|
111
|
+
serialize_view_node(xml, c) # , attrs[:x].to_f, attrs[:y].to_f)
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def font_style_string(font)
|
|
117
|
+
font&.style_string
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def serialize_connection(xml, sc)
|
|
121
|
+
xml.connection(
|
|
122
|
+
identifier: identifier(sc.id),
|
|
123
|
+
relationshipref: identifier(sc.relationship),
|
|
124
|
+
source: identifier(sc.source),
|
|
125
|
+
target: identifier(sc.target)
|
|
126
|
+
) do
|
|
127
|
+
serialize(xml, sc.bendpoints)
|
|
128
|
+
serialize(xml, sc.style)
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def meff_type(el_type)
|
|
133
|
+
el_type = el_type.sub(/^/, "")
|
|
134
|
+
case el_type
|
|
135
|
+
when 'AndJunction', 'OrJunction'
|
|
136
|
+
'Junction'
|
|
137
|
+
else
|
|
138
|
+
el_type
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require "nokogiri"
|
|
3
|
+
|
|
4
|
+
module Archimate
|
|
5
|
+
module FileFormats
|
|
6
|
+
class ModelExchangeFileWriter30 < ModelExchangeFileWriter
|
|
7
|
+
def initialize(model)
|
|
8
|
+
super
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def model_attrs
|
|
12
|
+
remove_nil_values(
|
|
13
|
+
model_namespaces.merge(
|
|
14
|
+
"xsi:schemaLocation" => model.schema_locations.join(" "),
|
|
15
|
+
"identifier" => identifier(model.id),
|
|
16
|
+
"version" => model.version
|
|
17
|
+
)
|
|
18
|
+
)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def serialize_model(xml)
|
|
22
|
+
xml.model(model_attrs) do
|
|
23
|
+
ModelExchangeFile::XmlLangString.new(model.name, :name).serialize(xml)
|
|
24
|
+
ModelExchangeFile::XmlLangString.new(model.documentation, :documentation).serialize(xml)
|
|
25
|
+
ModelExchangeFile::XmlMetadata.new(model.metadata).serialize(xml)
|
|
26
|
+
serialize_properties(xml, model)
|
|
27
|
+
serialize_elements(xml)
|
|
28
|
+
serialize_relationships(xml)
|
|
29
|
+
serialize_organization_root(xml, model.organizations)
|
|
30
|
+
serialize_property_defs(xml)
|
|
31
|
+
serialize_views(xml)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def serialize_property_defs(xml)
|
|
36
|
+
return if model.property_definitions.empty?
|
|
37
|
+
ModelExchangeFile::XmlPropertyDefinitions.new(model.property_definitions).serialize(xml)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def serialize_label(xml, str, tag = :name)
|
|
41
|
+
return if str.nil? || str.strip.empty?
|
|
42
|
+
name_attrs = str.lang && !str.lang.empty? ? {"xml:lang" => str.lang} : {}
|
|
43
|
+
xml.send(tag, name_attrs) { xml.text text_proc(str) }
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def relationship_attributes(relationship)
|
|
47
|
+
attrs = super
|
|
48
|
+
attrs["accessType"] = relationship.access_type if relationship.access_type
|
|
49
|
+
attrs
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def serialize_organization_root(xml, organizations)
|
|
53
|
+
return unless organizations && organizations.size > 0
|
|
54
|
+
xml.organizations do
|
|
55
|
+
serialize_organization_body(xml, organizations[0])
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def serialize_item(xml, item)
|
|
60
|
+
xml.item(identifierRef: identifier(item))
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def serialize_property(xml, property)
|
|
64
|
+
xml.property("propertyDefinitionRef" => property.property_definition.id) do
|
|
65
|
+
ModelExchangeFile::XmlLangString.new(property.value, :value).serialize(xml)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def serialize_views(xml)
|
|
70
|
+
return if model.diagrams.empty?
|
|
71
|
+
xml.views do
|
|
72
|
+
xml.diagrams {
|
|
73
|
+
serialize(xml, model.diagrams)
|
|
74
|
+
}
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def serialize_diagram(xml, diagram)
|
|
79
|
+
xml.view(
|
|
80
|
+
remove_nil_values(
|
|
81
|
+
identifier: identifier(diagram.id),
|
|
82
|
+
"xsi:type": diagram.type,
|
|
83
|
+
viewpoint: diagram.viewpoint_type
|
|
84
|
+
)
|
|
85
|
+
) do
|
|
86
|
+
elementbase(xml, diagram)
|
|
87
|
+
serialize(xml, diagram.nodes)
|
|
88
|
+
serialize(xml, diagram.connections)
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def view_node_attrs(view_node, x_offset = 0, y_offset = 0)
|
|
93
|
+
attrs = {
|
|
94
|
+
identifier: identifier(view_node.id),
|
|
95
|
+
elementRef: nil,
|
|
96
|
+
"xsi:type" => view_node.type,
|
|
97
|
+
"x" => view_node.bounds ? (view_node.bounds&.x + x_offset).round : nil,
|
|
98
|
+
"y" => view_node.bounds ? (view_node.bounds&.y + y_offset).round : nil,
|
|
99
|
+
"w" => view_node.bounds&.width&.round,
|
|
100
|
+
"h" => view_node.bounds&.height&.round
|
|
101
|
+
}
|
|
102
|
+
if view_node.archimate_element
|
|
103
|
+
attrs[:elementRef] = identifier(view_node.archimate_element)
|
|
104
|
+
elsif view_node.model
|
|
105
|
+
# Since it doesn't seem to be forbidden, we just assume we can use
|
|
106
|
+
# the elementref for views in views
|
|
107
|
+
attrs[:elementRef] = view_node.model
|
|
108
|
+
attrs[:type] = "model"
|
|
109
|
+
end
|
|
110
|
+
remove_nil_values(attrs)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def serialize_view_node(xml, view_node, x_offset = 0, y_offset = 0)
|
|
114
|
+
attrs = view_node_attrs(view_node, x_offset, y_offset)
|
|
115
|
+
xml.node(attrs) do
|
|
116
|
+
serialize_label(xml, view_node.name, :label)
|
|
117
|
+
serialize(xml, view_node.style) if view_node.style
|
|
118
|
+
view_node.nodes.each do |c|
|
|
119
|
+
serialize_view_node(xml, c) # , view_node_attrs[:x].to_f, view_node_attrs[:y].to_f)
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def font_style_string(font)
|
|
125
|
+
case font&.style
|
|
126
|
+
when 1
|
|
127
|
+
"italic"
|
|
128
|
+
when 2
|
|
129
|
+
"bold"
|
|
130
|
+
when 3
|
|
131
|
+
"bold italic"
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def serialize_connection(xml, sc)
|
|
136
|
+
xml.connection(
|
|
137
|
+
identifier: identifier(sc.id),
|
|
138
|
+
relationshipRef: identifier(sc.relationship),
|
|
139
|
+
"xsi:type": sc.type,
|
|
140
|
+
source: identifier(sc.source),
|
|
141
|
+
target: identifier(sc.target)
|
|
142
|
+
) do
|
|
143
|
+
serialize(xml, sc.style)
|
|
144
|
+
serialize(xml, sc.bendpoints)
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def meff_type(el_type)
|
|
149
|
+
el_type.sub(/^/, "")
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'archimate/file_formats/model_exchange_file/xml_lang_string'
|
|
4
|
+
|
|
5
|
+
module Archimate
|
|
6
|
+
module FileFormats
|
|
7
|
+
class Writer
|
|
8
|
+
attr_reader :model
|
|
9
|
+
|
|
10
|
+
def self.write(model, output_io)
|
|
11
|
+
writer = new(model)
|
|
12
|
+
writer.write(output_io)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def initialize(model)
|
|
16
|
+
@model = model
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def serialize(xml, collection)
|
|
20
|
+
Array(collection).each do |item|
|
|
21
|
+
case item
|
|
22
|
+
when DataModel::Location
|
|
23
|
+
serialize_location(xml, item)
|
|
24
|
+
when DataModel::Bounds
|
|
25
|
+
serialize_bounds(xml, item)
|
|
26
|
+
when DataModel::ViewNode
|
|
27
|
+
serialize_view_node(xml, item)
|
|
28
|
+
when DataModel::Diagram
|
|
29
|
+
serialize_diagram(xml, item)
|
|
30
|
+
when DataModel::Documentation
|
|
31
|
+
ModelExchangeFile::XmlLangString.new(item, :documentation).serialize(xml)
|
|
32
|
+
when DataModel::Element
|
|
33
|
+
serialize_element(xml, item)
|
|
34
|
+
when DataModel::Organization
|
|
35
|
+
serialize_organization(xml, item)
|
|
36
|
+
when DataModel::Property
|
|
37
|
+
serialize_property(xml, item)
|
|
38
|
+
when DataModel::Relationship
|
|
39
|
+
serialize_relationship(xml, item)
|
|
40
|
+
when DataModel::Connection
|
|
41
|
+
serialize_connection(xml, item)
|
|
42
|
+
when DataModel::Style
|
|
43
|
+
serialize_style(xml, item)
|
|
44
|
+
else
|
|
45
|
+
raise TypeError, "Unexpected item type #{item.class}"
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def remove_nil_values(h)
|
|
51
|
+
h.delete_if { |_k, v| v.nil? }
|
|
52
|
+
h
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
module Archimate
|
|
2
|
+
module Lint
|
|
3
|
+
STOP_WORDS = %w(
|
|
4
|
+
a able about above according accordingly across actually after afterwards again against all allow allows
|
|
5
|
+
almost alone along already also although always am among amongst amoungst amount an and another any anybody
|
|
6
|
+
anyhow anyone anything anyway anyways anywhere apart appear appreciate appropriate are around as aside ask
|
|
7
|
+
asking associated at available away awfully back be became because become becomes becoming been before
|
|
8
|
+
beforehand behind being believe below beside besides best better between beyond bill both bottom brief but
|
|
9
|
+
by call came can can't cannot cant cause causes certain certainly changes clearly co com come comes computer
|
|
10
|
+
con concerning consequently consider considering contain containing contains corresponding could couldn't
|
|
11
|
+
couldnt course cry currently de dear definitely describe described despite detail did didn't different do
|
|
12
|
+
does doesn't doing don't done down downwards due during each edu eg eight either eleven else elsewhere empty
|
|
13
|
+
enough entirely especially et etc even ever every everybody everyone everything everywhere ex exactly example
|
|
14
|
+
except far few fifteen fifth fify fill find fire first five followed following follows for former formerly
|
|
15
|
+
forth forty found four from front full further furthermore get gets getting give given gives go goes going
|
|
16
|
+
gone got gotten greetings had hadn't happens hardly has hasn't hasnt have haven't having he he's hello help
|
|
17
|
+
hence her here here's hereafter hereby herein hereupon hers herself hi him himself his hither hopefully how
|
|
18
|
+
howbeit however hundred i i'd i'll i'm i've ie if ignored immediate in inasmuch inc indeed indicate indicated
|
|
19
|
+
indicates inner insofar instead interest into inward is isn't it it'd it'll it's its itself just keep keeps
|
|
20
|
+
kept know known knows last lately later latter latterly least less lest let let's like liked likely little
|
|
21
|
+
look looking looks ltd made mainly many may maybe me mean meanwhile merely might mill mine more moreover most
|
|
22
|
+
mostly move much must my myself name namely nd near nearly necessary need needs neither never nevertheless
|
|
23
|
+
new next nine no nobody non none noone nor normally not nothing novel now nowhere obviously of off often oh
|
|
24
|
+
ok okay old on once one ones only onto or other others otherwise ought our ours ourselves out outside over
|
|
25
|
+
overall own part particular particularly per perhaps placed please plus possible presumably probably provides
|
|
26
|
+
put que quite qv rather rd re really reasonably regarding regardless regards relatively respectively right
|
|
27
|
+
said same saw say saying says second secondly see seeing seem seemed seeming seems seen self selves sensible
|
|
28
|
+
sent serious seriously seven several shall she should shouldn't show side since sincere six sixty so some
|
|
29
|
+
somebody somehow someone something sometime sometimes somewhat somewhere soon sorry specified specify
|
|
30
|
+
specifying still sub such sup sure system take taken tell ten tends th than thank thanks thanx that that's
|
|
31
|
+
thats the their theirs them themselves then thence there there's thereafter thereby therefore therein theres
|
|
32
|
+
thereupon these they they'd they'll they're they've thick thin think third this thorough thoroughly those
|
|
33
|
+
though three through throughout thru thus tis to together too took top toward towards tried tries truly try
|
|
34
|
+
trying twas twelve twenty twice two un under unfortunately unless unlikely until unto up upon us use used
|
|
35
|
+
useful uses using usually value various very via viz vs want wants was wasn't way we we'd we'll we're we've
|
|
36
|
+
welcome well went were weren't what what's whatever when whence whenever where where's whereafter whereas
|
|
37
|
+
whereby wherein whereupon wherever whether which while whither who who's whoever whole whom whose why will
|
|
38
|
+
willing wish with within without won't wonder would wouldn't yes yet you you'd you'll you're you've your
|
|
39
|
+
yours yourself yourselves zero).freeze
|
|
40
|
+
|
|
41
|
+
class DuplicateEntities
|
|
42
|
+
attr_reader :word_count
|
|
43
|
+
# TODO: Add option to permit additional project specific stop words
|
|
44
|
+
# TODO: Do relationships after elements are merged
|
|
45
|
+
def initialize(model)
|
|
46
|
+
@model = model
|
|
47
|
+
@dupes = nil
|
|
48
|
+
@count = nil
|
|
49
|
+
@word_count = {}
|
|
50
|
+
@ignored_entity_types = %w(Junction AndJunction OrJunction)
|
|
51
|
+
dupe_list
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def count
|
|
55
|
+
@dupes.reduce(0) { |total, (_tag, ary)| total + ary.size }
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def empty?
|
|
59
|
+
count.zero?
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def each(&block)
|
|
63
|
+
@dupes.keys.sort.each do |name|
|
|
64
|
+
ary = @dupes[name]
|
|
65
|
+
element_type = ary.first.type
|
|
66
|
+
block.call(element_type, name, ary)
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
protected
|
|
71
|
+
def candidate_entities
|
|
72
|
+
@model.entities.select do |entity|
|
|
73
|
+
(entity.is_a?(DataModel::Element) || entity.is_a?(DataModel::Relationship)) &&
|
|
74
|
+
!@ignored_entity_types.include?(entity.type)
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def dupe_list
|
|
79
|
+
@dupes = candidate_entities.each_with_object({}) do |entity, hash|
|
|
80
|
+
tag = entity_hash_name(entity)
|
|
81
|
+
hash[tag] = hash.fetch(tag, []) << entity
|
|
82
|
+
end
|
|
83
|
+
@dupes.delete_if { |_tag, entities| entities.size <= 1 }
|
|
84
|
+
# @word_count.sort_by(&:last).reverse.each { |ak, av| puts "#{ak}: #{av}" }
|
|
85
|
+
@dupes
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def entity_hash_name(entity)
|
|
89
|
+
layer = DataModel::Constants::ELEMENT_LAYER.fetch(entity.type, nil)
|
|
90
|
+
layer_sort_order = layer ? DataModel::Constants::LAYER_ELEMENTS.keys.index(layer) : 9
|
|
91
|
+
[
|
|
92
|
+
entity.class.name, # Taking advantage of Element being before Relationship
|
|
93
|
+
layer_sort_order.to_s,
|
|
94
|
+
entity.type,
|
|
95
|
+
simplify(entity)
|
|
96
|
+
].join("/")
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# This method takes an entity name and simplifies it for duplicate determination
|
|
100
|
+
# This might be configurable in the future
|
|
101
|
+
# 1. names are explicitly identical
|
|
102
|
+
# 2. names differ only in case
|
|
103
|
+
# 3. names differ only in whitespace
|
|
104
|
+
# 4. names differ only in punctuation
|
|
105
|
+
# 5. names differ only by stop-words (list of words such as "the", "api", etc.)
|
|
106
|
+
def simplify(entity)
|
|
107
|
+
name = entity.name&.dup || ""
|
|
108
|
+
name.sub!("(copy)", "") # (copy) is a special case inserted by the Archi tool
|
|
109
|
+
name.downcase!
|
|
110
|
+
name.gsub!(/[[:punct:]]/, "") unless entity.is_a?(DataModel::Relationship)
|
|
111
|
+
name.strip!
|
|
112
|
+
words = name.split(/\s/)
|
|
113
|
+
words.each { |word| @word_count[word] = @word_count.fetch(word, 0) + 1 }
|
|
114
|
+
name = words.reject { |word| STOP_WORDS.include?(word) }.join("")
|
|
115
|
+
name.delete!(" \t\n\r")
|
|
116
|
+
name = "#{name}:#{entity.source}:#{entity.target}" if entity.is_a?(DataModel::Relationship)
|
|
117
|
+
name
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Archimate
|
|
3
|
+
module Lint
|
|
4
|
+
# lint notes
|
|
5
|
+
#
|
|
6
|
+
# [x] Unused element (not used in a view)
|
|
7
|
+
# [x] Unused relation (not used in a view)
|
|
8
|
+
# [x] Object in a Viewpoint (invalid object for viewpoint)
|
|
9
|
+
# [x] Duplicate same name for type
|
|
10
|
+
# [x] empty view
|
|
11
|
+
# [?] visual nesting without relationship
|
|
12
|
+
# [ ] Warn about sketch model
|
|
13
|
+
# [x] warn about names with (copy)
|
|
14
|
+
# [x] blank element names
|
|
15
|
+
class Linter
|
|
16
|
+
include FileFormats::ArchimateV2
|
|
17
|
+
|
|
18
|
+
attr_reader :model
|
|
19
|
+
|
|
20
|
+
def initialize(model)
|
|
21
|
+
@model = model
|
|
22
|
+
@indent = "\n" + " " * 8
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# TODO: consider a means to sort lint issues by entity instead of lint category
|
|
26
|
+
# this would point out the particularly problematic items that could be
|
|
27
|
+
# dealt with appropriately.
|
|
28
|
+
def report(output_io)
|
|
29
|
+
[
|
|
30
|
+
[unused_elements, "Unused Element"],
|
|
31
|
+
[duplicate_elements, "Duplicate Items"],
|
|
32
|
+
[entity_naming_rules, "Naming Rules"],
|
|
33
|
+
[unused_relationships, "Unused Relationship"],
|
|
34
|
+
[duplicate_relationships, "Duplicate Relationships"],
|
|
35
|
+
[empty_views, "Empty View"],
|
|
36
|
+
[invalid_for_viewpoint, "Invalid Type for Viewpoint"],
|
|
37
|
+
[nesting_without_relation, "Visual Nesting"]
|
|
38
|
+
]
|
|
39
|
+
.map { |issues, title| issues.map { |issue| "#{title}: #{format_issue(issue)}" } }
|
|
40
|
+
.tap { |issues| report_subsection(issues, output_io) }
|
|
41
|
+
.tap { |issues| output_io.puts("Total Issues: #{issues.flatten.size}") }
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def format_issue(issue)
|
|
45
|
+
ary = Array(issue)
|
|
46
|
+
return issue if ary.size == 1
|
|
47
|
+
"#{@indent}#{ary.join(@indent)}"
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def report_subsection(issues, output_io)
|
|
51
|
+
issues.each do |sub_issues|
|
|
52
|
+
output_io.puts(sub_issues)
|
|
53
|
+
output_io.puts("Sub Total: #{sub_issues.size}")
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def unused_elements
|
|
58
|
+
referenced_elements = diagram_referenced_ids
|
|
59
|
+
model.elements.reject { |el| referenced_elements.include?(el.id) }
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def unused_relationships
|
|
63
|
+
referenced_ids = diagram_referenced_ids
|
|
64
|
+
model.relationships.reject { |el| referenced_ids.include?(el.id) }
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def empty_views
|
|
68
|
+
model.diagrams.select { |diagram| diagram.nodes.empty? }
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def duplicate_elements
|
|
72
|
+
duplicates(model.elements, ->(el) { [el.type, name_for_comparison(el.name)] })
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def duplicate_relationships
|
|
76
|
+
duplicates(model.relationships, ->(el) { [el.type, el.source, el.target, name_for_comparison(el.name)] })
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def name_for_comparison(name)
|
|
80
|
+
name&.strip&.downcase
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def duplicates(array, group_by_proc)
|
|
84
|
+
array
|
|
85
|
+
.group_by { |el| group_by_proc.call(el) }
|
|
86
|
+
.each_with_object([]) do |(_key, ary), dupes|
|
|
87
|
+
dupes << ary.map(&:to_s) if ary.size > 1
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def diagram_referenced_ids
|
|
92
|
+
@ref_ids ||= model.diagrams.inject([]) { |memo, dia| memo.concat(dia.referenced_identified_nodes) }.uniq
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def invalid_for_viewpoint
|
|
96
|
+
model.diagrams.each_with_object([]) do |diagram, errors|
|
|
97
|
+
next if diagram.total_viewpoint?
|
|
98
|
+
valid_entity_types = VIEWPOINTS[diagram.viewpoint][:entities]
|
|
99
|
+
valid_relation_types = VIEWPOINTS[diagram.viewpoint][:relations]
|
|
100
|
+
invalid_elements = diagram.all_nodes.reject do |child|
|
|
101
|
+
child.element&.type.nil? || valid_entity_types.include?(child.element&.type)
|
|
102
|
+
end
|
|
103
|
+
invalid_relations = diagram.connections.reject do |sc|
|
|
104
|
+
sc.element&.type.nil? || valid_relation_types.include?(sc.element&.type)
|
|
105
|
+
end
|
|
106
|
+
next unless !invalid_elements.empty? || !invalid_relations.empty?
|
|
107
|
+
errors << format(
|
|
108
|
+
"%s viewpoint %s#{@indent}%s",
|
|
109
|
+
diagram,
|
|
110
|
+
diagram.viewpoint,
|
|
111
|
+
(invalid_elements + invalid_relations).map(&:element).map(&:to_s).join(@indent)
|
|
112
|
+
)
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# Nesting is valid for relations:
|
|
117
|
+
# * CompositionRelationship
|
|
118
|
+
# * AggregationRelationship
|
|
119
|
+
# * AssignmentRelationship
|
|
120
|
+
def nesting_without_relation
|
|
121
|
+
model.find_by_class(DataModel::ViewNode).each_with_object([]) do |parent, errors|
|
|
122
|
+
missing_relations = parent.nodes.reject do |child|
|
|
123
|
+
model.relationships.any? do |rel|
|
|
124
|
+
parent.archimate_element.nil? ||
|
|
125
|
+
child.archimate_element.nil? ||
|
|
126
|
+
(rel.source == parent.archimate_element && rel.target == child.archimate_element)
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
errors.concat(missing_relations.map { |child| "#{child.element} should not nest in #{parent.element} without valid relationship" })
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def entity_naming_rules
|
|
134
|
+
model.elements.each_with_object([]) do |entity, errors|
|
|
135
|
+
if entity.name.nil? || entity.name.empty?
|
|
136
|
+
errors << "#{entity} name is empty"
|
|
137
|
+
elsif entity.name.size < 2
|
|
138
|
+
errors << "#{entity} name #{entity.name.inspect} is too short"
|
|
139
|
+
elsif entity.name.include?("(copy)")
|
|
140
|
+
errors << "#{entity} name #{entity.name.inspect} contains '(copy)'"
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Archimate
|
|
4
|
+
# This is a helper module to make logging calls a little less clunky
|
|
5
|
+
module Logging
|
|
6
|
+
def update(sym, val)
|
|
7
|
+
@logger = val if sym == :logger
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def logger
|
|
11
|
+
unless defined?(@logger)
|
|
12
|
+
config = Archimate::Config.instance
|
|
13
|
+
config.add_observer(self)
|
|
14
|
+
@logger = config.logger
|
|
15
|
+
end
|
|
16
|
+
@logger
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def debug(progname = nil, &block)
|
|
20
|
+
logger.debug(progname, &block)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def error(progname = nil, &block)
|
|
24
|
+
logger.error(progname, &block)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def fatal(progname = nil, &block)
|
|
28
|
+
logger.fatal(progname, &block)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def info(progname = nil, &block)
|
|
32
|
+
logger.info(progname, &block)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def self.logger
|
|
36
|
+
Archimate::Config.instance.logger
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def self.debug(progname = nil, &block)
|
|
40
|
+
logger.debug(progname, &block)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def self.error(progname = nil, &block)
|
|
44
|
+
logger.error(progname, &block)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def self.fatal(progname = nil, &block)
|
|
48
|
+
logger.fatal(progname, &block)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def self.info(progname = nil, &block)
|
|
52
|
+
logger.info(progname, &block)
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|