ea 0.5.0 → 0.5.1
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 +4 -4
- data/CHANGELOG.md +128 -1
- data/TODO.complete/51-remove-respond-to.md +25 -0
- data/TODO.complete/52-xsd-decouple-fixtures.md +23 -0
- data/TODO.complete/53-xmi-public-send-cleanup.md +26 -0
- data/TODO.complete/54-wire-stereotype-icon-renderer.md +20 -0
- data/TODO.complete/55-wire-shapescript.md +20 -0
- data/TODO.complete/56-wire-emf-renderer.md +27 -0
- data/TODO.complete/57-wire-ocl-evaluator.md +23 -0
- data/TODO.complete/58-diff-modifications.md +21 -0
- data/TODO.complete/59-delete-toy-xmi-export.md +30 -0
- data/TODO.complete/60-curate-json-export.md +20 -0
- data/TODO.complete/61-plantuml-relationships.md +22 -0
- data/TODO.complete/62-changelog.md +17 -0
- data/TODO.complete/63-dependabot-fix.md +18 -0
- data/TODO.complete/STATUS.md +40 -64
- data/lib/ea/cli/command/export.rb +23 -2
- data/lib/ea/diff/comparator.rb +28 -1
- data/lib/ea/export/json/generator.rb +84 -8
- data/lib/ea/export/plantuml/generator.rb +95 -28
- data/lib/ea/export/xsd/generator.rb +10 -15
- data/lib/ea/export.rb +0 -1
- data/lib/ea/lint/rules/missing_stereotype.rb +16 -11
- data/lib/ea/ocl/evaluator.rb +2 -2
- data/lib/ea/qea/models/ea_implement.rb +2 -2
- data/lib/ea/qea/models/ea_object_effort.rb +2 -2
- data/lib/ea/qea/models/ea_object_problem.rb +2 -2
- data/lib/ea/qea/models/ea_object_require.rb +2 -2
- data/lib/ea/qea/models/ea_object_resource.rb +2 -2
- data/lib/ea/qea/models/ea_object_risk.rb +2 -2
- data/lib/ea/qea/models/ea_object_scenario.rb +2 -2
- data/lib/ea/qea/models/ea_object_test.rb +2 -2
- data/lib/ea/qea/models/ea_object_trx.rb +2 -2
- data/lib/ea/qea/models/ea_palette_item.rb +2 -2
- data/lib/ea/qea/models/ea_role_constraint.rb +2 -2
- data/lib/ea/qea/models/ea_secrypt.rb +2 -2
- data/lib/ea/qea/validation/database/ocl_constraint_validator.rb +65 -0
- data/lib/ea/qea/validation/database.rb +2 -0
- data/lib/ea/qea/validation/validation_engine.rb +2 -0
- data/lib/ea/qea/validation.rb +2 -0
- data/lib/ea/query/builder.rb +22 -3
- data/lib/ea/svg/ea_emitter/compartment/stereotype_icon.rb +32 -0
- data/lib/ea/svg/ea_emitter/compartment.rb +2 -0
- data/lib/ea/svg/ea_emitter/document.rb +33 -0
- data/lib/ea/svg/ea_emitter/element/stereotype_icon_renderer.rb +49 -12
- data/lib/ea/validation/xmi_parity.rb +80 -0
- data/lib/ea/validation.rb +12 -0
- data/lib/ea/version.rb +1 -1
- data/lib/ea.rb +1 -0
- metadata +18 -3
- data/lib/ea/export/xmi/generator.rb +0 -77
- data/lib/ea/export/xmi.rb +0 -11
data/lib/ea/diff/comparator.rb
CHANGED
|
@@ -53,6 +53,8 @@ module Ea
|
|
|
53
53
|
add(:removed, name, id, old_entry[:label])
|
|
54
54
|
elsif new_entry[:label] != old_entry[:label]
|
|
55
55
|
add(:renamed, name, id, "#{old_entry[:label]} → #{new_entry[:label]}")
|
|
56
|
+
else
|
|
57
|
+
compare_modifications(name, id, old_entry[:record], new_entry[:record])
|
|
56
58
|
end
|
|
57
59
|
end
|
|
58
60
|
|
|
@@ -61,6 +63,30 @@ module Ea
|
|
|
61
63
|
end
|
|
62
64
|
end
|
|
63
65
|
|
|
66
|
+
# Compares two records of the same type by their to_hash
|
|
67
|
+
# representation. If they differ beyond identity (id and the
|
|
68
|
+
# label attribute), emit a :modified change with a list of
|
|
69
|
+
# the differing field names in #details.
|
|
70
|
+
def compare_modifications(collection, id, old_record, new_record)
|
|
71
|
+
old_hash = old_record.to_hash
|
|
72
|
+
new_hash = new_record.to_hash
|
|
73
|
+
changed = []
|
|
74
|
+
(old_hash.keys | new_hash.keys).each do |key|
|
|
75
|
+
next if key == "record_type"
|
|
76
|
+
|
|
77
|
+
old_val = old_hash[key]
|
|
78
|
+
new_val = new_hash[key]
|
|
79
|
+
next if old_val == new_val
|
|
80
|
+
|
|
81
|
+
changed << key
|
|
82
|
+
end
|
|
83
|
+
return if changed.empty?
|
|
84
|
+
|
|
85
|
+
@differences << Change.new(change: :modified, kind: collection,
|
|
86
|
+
id: id, name: changed.first(5).join(", "),
|
|
87
|
+
details: changed)
|
|
88
|
+
end
|
|
89
|
+
|
|
64
90
|
def index_by_id(db, collection_name, label_attr)
|
|
65
91
|
records = db.collections[collection_name] || []
|
|
66
92
|
records.each_with_object({}) do |record, acc|
|
|
@@ -69,7 +95,8 @@ module Ea
|
|
|
69
95
|
|
|
70
96
|
acc[id] = {
|
|
71
97
|
id: id,
|
|
72
|
-
label: record.public_send(label_attr).to_s
|
|
98
|
+
label: record.public_send(label_attr).to_s,
|
|
99
|
+
record: record
|
|
73
100
|
}
|
|
74
101
|
end
|
|
75
102
|
end
|
|
@@ -5,9 +5,14 @@ require "json"
|
|
|
5
5
|
module Ea
|
|
6
6
|
module Export
|
|
7
7
|
module Json
|
|
8
|
-
# Generates a JSON snapshot of a parsed QEA model.
|
|
9
|
-
#
|
|
10
|
-
#
|
|
8
|
+
# Generates a curated JSON snapshot of a parsed QEA model.
|
|
9
|
+
#
|
|
10
|
+
# Each collection is projected through a per-model schema so the
|
|
11
|
+
# output is stable and free of Lutaml::Model internals.
|
|
12
|
+
# Collections without a projection are emitted as
|
|
13
|
+
# `{ "name" => ..., "id" => ..., "record_type" => ... }` triples
|
|
14
|
+
# — enough metadata for downstream tools without leaking
|
|
15
|
+
# implementation details.
|
|
11
16
|
class Generator
|
|
12
17
|
def self.call(model, **_opts)
|
|
13
18
|
new(model).call
|
|
@@ -26,16 +31,87 @@ module Ea
|
|
|
26
31
|
private
|
|
27
32
|
|
|
28
33
|
def document_hash
|
|
34
|
+
{
|
|
35
|
+
"schema_version" => "1.0",
|
|
36
|
+
"collections" => projected_collections
|
|
37
|
+
}
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def projected_collections
|
|
29
41
|
model.collections.each_with_object({}) do |(name, records), acc|
|
|
30
|
-
acc[name] = records.map { |r|
|
|
42
|
+
acc[name.to_s] = records.map { |r| project(r) }
|
|
31
43
|
end
|
|
32
44
|
end
|
|
33
45
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
46
|
+
# @return [Hash] curated fields per record type
|
|
47
|
+
def project(record)
|
|
48
|
+
projector = PROJECTORS[record.class]
|
|
49
|
+
return projector.call(record) if projector
|
|
50
|
+
|
|
51
|
+
default_projection(record)
|
|
38
52
|
end
|
|
53
|
+
|
|
54
|
+
# Fallback: name + id + record_type only
|
|
55
|
+
def default_projection(record)
|
|
56
|
+
{
|
|
57
|
+
"id" => safe_id(record),
|
|
58
|
+
"name" => record_name(record),
|
|
59
|
+
"record_type" => record.class.name.split("::").last
|
|
60
|
+
}
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def safe_id(record)
|
|
64
|
+
pk = record.class.respond_to?(:primary_key_column) ?
|
|
65
|
+
record.class.primary_key_column : nil
|
|
66
|
+
return nil unless pk
|
|
67
|
+
|
|
68
|
+
record.to_hash[pk.to_s] || record.to_hash[pk.to_sym]
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def record_name(record)
|
|
72
|
+
return record.name if record.respond_to?(:name)
|
|
73
|
+
|
|
74
|
+
record.to_hash["name"]
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Per-class projections: each entry is a proc returning a Hash.
|
|
78
|
+
# Add new entries here as we curate more model types.
|
|
79
|
+
PROJECTORS = {
|
|
80
|
+
Ea::Qea::Models::EaObject => ->(r) do
|
|
81
|
+
{
|
|
82
|
+
"id" => r.ea_object_id, "name" => r.name,
|
|
83
|
+
"type" => r.object_type, "author" => r.author,
|
|
84
|
+
"package_id" => r.package_id, "version" => r.version
|
|
85
|
+
}
|
|
86
|
+
end,
|
|
87
|
+
Ea::Qea::Models::EaAttribute => ->(r) do
|
|
88
|
+
{
|
|
89
|
+
"id" => r.id, "name" => r.name,
|
|
90
|
+
"type" => r.type, "object_id" => r.ea_object_id,
|
|
91
|
+
"visibility" => r.scope
|
|
92
|
+
}
|
|
93
|
+
end,
|
|
94
|
+
Ea::Qea::Models::EaPackage => ->(r) do
|
|
95
|
+
{
|
|
96
|
+
"id" => r.package_id, "name" => r.name,
|
|
97
|
+
"parent_id" => r.parent_id
|
|
98
|
+
}
|
|
99
|
+
end,
|
|
100
|
+
Ea::Qea::Models::EaConnector => ->(r) do
|
|
101
|
+
{
|
|
102
|
+
"id" => r.connector_id, "name" => r.name,
|
|
103
|
+
"type" => r.connector_type,
|
|
104
|
+
"start_object_id" => r.start_object_id,
|
|
105
|
+
"end_object_id" => r.end_object_id
|
|
106
|
+
}
|
|
107
|
+
end,
|
|
108
|
+
Ea::Qea::Models::EaDiagram => ->(r) do
|
|
109
|
+
{
|
|
110
|
+
"id" => r.diagram_id, "name" => r.name,
|
|
111
|
+
"type" => r.diagram_type, "package_id" => r.package_id
|
|
112
|
+
}
|
|
113
|
+
end
|
|
114
|
+
}.freeze
|
|
39
115
|
end
|
|
40
116
|
end
|
|
41
117
|
end
|
|
@@ -1,18 +1,16 @@
|
|
|
1
|
-
#
|
|
1
|
+
# frozen_string: true
|
|
2
2
|
|
|
3
3
|
module Ea
|
|
4
4
|
module Export
|
|
5
5
|
module PlantUml
|
|
6
6
|
# Generates PlantUML class diagram text from a parsed QEA model.
|
|
7
7
|
#
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
#
|
|
11
|
-
#
|
|
12
|
-
#
|
|
13
|
-
#
|
|
14
|
-
# Person "1" --> "0..*" Address : lives_at
|
|
15
|
-
# @enduml
|
|
8
|
+
# Emits:
|
|
9
|
+
# - Package nesting (`package "X" { ... }`)
|
|
10
|
+
# - Class declarations with attributes and operations
|
|
11
|
+
# - Generalizations (`Parent <|-- Child`)
|
|
12
|
+
# - Associations with multiplicities and role names
|
|
13
|
+
# - Enumerations as `enum` blocks
|
|
16
14
|
class Generator
|
|
17
15
|
def self.call(model, **_opts)
|
|
18
16
|
new(model).call
|
|
@@ -25,8 +23,8 @@ module Ea
|
|
|
25
23
|
end
|
|
26
24
|
|
|
27
25
|
def call
|
|
28
|
-
lines = ["@startuml"]
|
|
29
|
-
lines.concat(
|
|
26
|
+
lines = ["@startuml", "skinparam classAttributeIconSize 0"]
|
|
27
|
+
lines.concat(package_lines)
|
|
30
28
|
lines.concat(connector_lines)
|
|
31
29
|
lines << "@enduml"
|
|
32
30
|
lines.join("\n") + "\n"
|
|
@@ -34,38 +32,107 @@ module Ea
|
|
|
34
32
|
|
|
35
33
|
private
|
|
36
34
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
35
|
+
# Wrap classes/enums in their containing packages.
|
|
36
|
+
def package_lines
|
|
37
|
+
packages_by_id = packages_index
|
|
38
|
+
root_objects = (model.collections[:objects] || [])
|
|
39
|
+
|
|
40
|
+
# Group classes by their package_id; emit each package.
|
|
41
|
+
grouped = root_objects.group_by(&:package_id)
|
|
42
|
+
grouped.flat_map do |pkg_id, objs|
|
|
43
|
+
next ungrouped_lines(objs) if pkg_id.nil?
|
|
44
|
+
|
|
45
|
+
pkg = packages_by_id[pkg_id]
|
|
46
|
+
pkg_name = pkg&.name || "Package#{pkg_id}"
|
|
47
|
+
inner = objs.flat_map { |o| class_block(o) }
|
|
48
|
+
next inner if inner.empty?
|
|
49
|
+
|
|
50
|
+
["package \"#{pkg_name}\" {",
|
|
51
|
+
*inner.map { |line| " #{line}" },
|
|
52
|
+
"}"]
|
|
53
|
+
end.compact
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def ungrouped_lines(objs)
|
|
57
|
+
objs.flat_map { |o| class_block(o) }
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Emit `class X { +attr: T ... }` or `enum X { LITERAL1 ... }`.
|
|
61
|
+
def class_block(obj)
|
|
62
|
+
case obj.object_type
|
|
63
|
+
when "Class"
|
|
64
|
+
attrs = class_attributes(obj)
|
|
65
|
+
body = attrs.map { |a| "+#{a.name}: #{a.type || 'String'}" }
|
|
66
|
+
return ["class #{obj.name}"] if body.empty?
|
|
67
|
+
|
|
68
|
+
["class #{obj.name} {", *body.map { |b| " #{b}" }, "}"]
|
|
69
|
+
when "Enumeration"
|
|
70
|
+
literals = enum_literals(obj)
|
|
71
|
+
return ["enum #{obj.name}"] if literals.empty?
|
|
72
|
+
|
|
73
|
+
["enum #{obj.name} {",
|
|
74
|
+
*literals.map { |l| " #{l.name || l}" },
|
|
75
|
+
"}"]
|
|
76
|
+
when "Interface"
|
|
77
|
+
["interface #{obj.name}"]
|
|
78
|
+
when "DataType"
|
|
79
|
+
["abstract class #{obj.name}"]
|
|
80
|
+
else
|
|
81
|
+
["class #{obj.name}"]
|
|
42
82
|
end
|
|
43
83
|
end
|
|
44
84
|
|
|
85
|
+
# Generalizations: `<|`-style inheritance.
|
|
86
|
+
# Associations: multiplicity + role names.
|
|
45
87
|
def connector_lines
|
|
46
|
-
(model.collections[:connectors] || []).
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
next nil unless
|
|
88
|
+
(model.collections[:connectors] || []).filter_map do |conn|
|
|
89
|
+
src = find_object(conn.start_object_id)
|
|
90
|
+
tgt = find_object(conn.end_object_id)
|
|
91
|
+
next nil unless src && tgt
|
|
50
92
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
93
|
+
case conn.connector_type
|
|
94
|
+
when "Generalization"
|
|
95
|
+
"#{tgt.name} <|-- #{src.name}"
|
|
96
|
+
when "Association", "Aggregation", "Composition"
|
|
97
|
+
assoc_arrow(src, tgt, conn)
|
|
98
|
+
else
|
|
99
|
+
label = conn.name ? " : #{conn.name}" : ""
|
|
100
|
+
"#{src.name} --> #{tgt.name}#{label}"
|
|
101
|
+
end
|
|
102
|
+
end
|
|
54
103
|
end
|
|
55
104
|
|
|
56
|
-
def
|
|
57
|
-
|
|
58
|
-
|
|
105
|
+
def assoc_arrow(src, tgt, conn)
|
|
106
|
+
arrow = case conn.connector_type
|
|
107
|
+
when "Composition" then "*--"
|
|
108
|
+
when "Aggregation" then "o--"
|
|
109
|
+
else "--"
|
|
110
|
+
end
|
|
111
|
+
label = conn.name ? " : #{conn.name}" : ""
|
|
112
|
+
"#{src.name} #{arrow} #{tgt.name}#{label}"
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def packages_index
|
|
116
|
+
(model.collections[:packages] || []).each_with_object({}) do |p, acc|
|
|
117
|
+
acc[p.package_id] = p
|
|
118
|
+
end
|
|
59
119
|
end
|
|
60
120
|
|
|
61
121
|
def class_attributes(klass)
|
|
62
122
|
attrs = model.collections[:attributes] || []
|
|
63
|
-
attrs.select { |a| a.
|
|
123
|
+
attrs.select { |a| a.ea_object_id == klass.ea_object_id }
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def enum_literals(enum)
|
|
127
|
+
literals = model.collections[:enumeration_literals] ||
|
|
128
|
+
model.collections[:enum_literals] || []
|
|
129
|
+
# Enumeration literals are linked to the enum via object_id.
|
|
130
|
+
literals.select { |l| l.respond_to?(:ea_object_id) && l.ea_object_id == enum.ea_object_id }
|
|
64
131
|
end
|
|
65
132
|
|
|
66
133
|
def find_object(object_id)
|
|
67
134
|
(model.collections[:objects] || [])
|
|
68
|
-
.find { |o| o.object_id == object_id }
|
|
135
|
+
.find { |o| o.ea_object_id == object_id || o.object_id == object_id }
|
|
69
136
|
end
|
|
70
137
|
end
|
|
71
138
|
end
|
|
@@ -7,26 +7,21 @@ module Ea
|
|
|
7
7
|
module Xsd
|
|
8
8
|
# Generates an XSD schema string from a parsed QEA model.
|
|
9
9
|
#
|
|
10
|
-
#
|
|
11
|
-
#
|
|
12
|
-
#
|
|
13
|
-
#
|
|
14
|
-
#
|
|
15
|
-
# Both class_mapping and namespaces default to the EA-bundled
|
|
16
|
-
# GML fixtures when present, so callers can do
|
|
17
|
-
# Ea::Export::Xsd::Generator.call(model, target_namespace: ...)
|
|
18
|
-
# without manually loading XML fixtures.
|
|
10
|
+
# Pure: takes already-loaded ClassMapping and NamespaceRegistry
|
|
11
|
+
# instances. No file IO, no fixture-path coupling. The CLI
|
|
12
|
+
# layer is responsible for loading GMLClassMapping.xml and
|
|
13
|
+
# GMLNamespaces.xml from disk.
|
|
19
14
|
class Generator
|
|
20
15
|
XSD_NS = "http://www.w3.org/2001/XMLSchema"
|
|
21
16
|
|
|
22
|
-
DEFAULT_MAPPING_PATH = "spec/fixtures/mdg/ea_config/gml/GMLClassMapping.xml".freeze
|
|
23
|
-
DEFAULT_NAMESPACES_PATH = "spec/fixtures/mdg/ea_config/gml/GMLNamespaces.xml".freeze
|
|
24
|
-
|
|
25
17
|
attr_reader :class_mapping, :namespaces
|
|
26
18
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
19
|
+
# @param class_mapping [ClassMapping] type translation rules
|
|
20
|
+
# @param namespaces [NamespaceRegistry] namespace declarations
|
|
21
|
+
def initialize(class_mapping: ClassMapping.new,
|
|
22
|
+
namespaces: NamespaceRegistry.new)
|
|
23
|
+
@class_mapping = class_mapping
|
|
24
|
+
@namespaces = namespaces
|
|
30
25
|
end
|
|
31
26
|
|
|
32
27
|
# Class-method shortcut. Accepts the same options as #initialize
|
data/lib/ea/export.rb
CHANGED
|
@@ -5,7 +5,6 @@ module Ea
|
|
|
5
5
|
# One sub-namespace per output format; each is independent and
|
|
6
6
|
# autoloadable.
|
|
7
7
|
module Export
|
|
8
|
-
autoload :Xmi, "ea/export/xmi"
|
|
9
8
|
autoload :Json, "ea/export/json"
|
|
10
9
|
autoload :JsonSchema, "ea/export/json_schema"
|
|
11
10
|
autoload :PlantUml, "ea/export/plantuml"
|
|
@@ -3,31 +3,36 @@
|
|
|
3
3
|
module Ea
|
|
4
4
|
module Lint
|
|
5
5
|
module Rules
|
|
6
|
-
#
|
|
7
|
-
#
|
|
6
|
+
# Flags classes with no applied stereotype. Stereotype
|
|
7
|
+
# detection walks t_xref for `@STEREO;Name=...;` blocks
|
|
8
|
+
# referencing the class's ea_guid.
|
|
8
9
|
class MissingStereotypeRule < LintRule
|
|
9
10
|
self.severity = :info
|
|
10
11
|
|
|
11
|
-
GML_STEREOTYPES = %w[FeatureType Type DataType CodeList
|
|
12
|
-
Enumeration ObjectType].freeze
|
|
13
|
-
|
|
14
12
|
def check(model)
|
|
15
13
|
classes = (model.collections[:objects] || [])
|
|
16
14
|
.select { |o| o.object_type == "Class" }
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
xrefs = model.collections[:xrefs] || []
|
|
16
|
+
classes.map do |klass|
|
|
17
|
+
next nil if stereotype_name_for(klass, xrefs)
|
|
18
|
+
|
|
19
19
|
offense(entity_id: klass.object_id,
|
|
20
20
|
entity_name: klass.name,
|
|
21
21
|
message: "Class has no applied stereotype",
|
|
22
22
|
severity: :info)
|
|
23
|
-
end
|
|
23
|
+
end.compact
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
private
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
# Find the first @STEREO application in t_xref that references
|
|
29
|
+
# the class's ea_guid.
|
|
30
|
+
def stereotype_name_for(klass, xrefs)
|
|
31
|
+
return nil unless klass.is_a?(Ea::Qea::Models::EaObject)
|
|
32
|
+
|
|
33
|
+
xrefs.find do |xr|
|
|
34
|
+
xr.client == klass.ea_guid && xr.description&.include?("@STEREO")
|
|
35
|
+
end&.description&.match(/Name=([^;]+)/)&.[](1)
|
|
31
36
|
end
|
|
32
37
|
end
|
|
33
38
|
end
|
data/lib/ea/ocl/evaluator.rb
CHANGED
|
@@ -38,7 +38,7 @@ module Ea
|
|
|
38
38
|
|
|
39
39
|
def eval_exists(ast, context)
|
|
40
40
|
collection = evaluate(ast.collection, context)
|
|
41
|
-
return false unless collection.
|
|
41
|
+
return false unless collection.is_a?(Array)
|
|
42
42
|
|
|
43
43
|
var_name = ast.var
|
|
44
44
|
predicate = ast.predicate
|
|
@@ -49,7 +49,7 @@ module Ea
|
|
|
49
49
|
|
|
50
50
|
def eval_for_all(ast, context)
|
|
51
51
|
collection = evaluate(ast.collection, context)
|
|
52
|
-
return true unless collection.
|
|
52
|
+
return true unless collection.is_a?(Array)
|
|
53
53
|
|
|
54
54
|
var_name = ast.var
|
|
55
55
|
predicate = ast.predicate
|
|
@@ -6,7 +6,7 @@ module Ea
|
|
|
6
6
|
# UML-to-code mapping hint from t_implement.
|
|
7
7
|
class EaImplement < BaseModel
|
|
8
8
|
attribute :implement_id, :integer
|
|
9
|
-
attribute :
|
|
9
|
+
attribute :ea_object_id, :integer
|
|
10
10
|
attribute :language, :string
|
|
11
11
|
attribute :code, :string
|
|
12
12
|
|
|
@@ -20,7 +20,7 @@ module Ea
|
|
|
20
20
|
|
|
21
21
|
COLUMN_MAP = {
|
|
22
22
|
"ImplementID" => :implement_id,
|
|
23
|
-
"Object_ID" => :
|
|
23
|
+
"Object_ID" => :ea_object_id
|
|
24
24
|
}.freeze
|
|
25
25
|
|
|
26
26
|
def self.column_map
|
|
@@ -6,7 +6,7 @@ module Ea
|
|
|
6
6
|
# Effort estimate from t_objecteffort.
|
|
7
7
|
class EaObjectEffort < BaseModel
|
|
8
8
|
attribute :object_effort_id, :integer
|
|
9
|
-
attribute :
|
|
9
|
+
attribute :ea_object_id, :integer
|
|
10
10
|
attribute :effort, :string
|
|
11
11
|
attribute :effort_type, :string
|
|
12
12
|
attribute :notes, :string
|
|
@@ -21,7 +21,7 @@ module Ea
|
|
|
21
21
|
|
|
22
22
|
COLUMN_MAP = {
|
|
23
23
|
"ObjectEffortID" => :object_effort_id,
|
|
24
|
-
"Object_ID" => :
|
|
24
|
+
"Object_ID" => :ea_object_id,
|
|
25
25
|
"EffortType" => :effort_type
|
|
26
26
|
}.freeze
|
|
27
27
|
|
|
@@ -6,7 +6,7 @@ module Ea
|
|
|
6
6
|
# Object problem record from t_objectproblems.
|
|
7
7
|
class EaObjectProblem < BaseModel
|
|
8
8
|
attribute :object_problem_id, :integer
|
|
9
|
-
attribute :
|
|
9
|
+
attribute :ea_object_id, :integer
|
|
10
10
|
attribute :problem, :string
|
|
11
11
|
attribute :problem_type, :string
|
|
12
12
|
attribute :date_resolved, :string
|
|
@@ -23,7 +23,7 @@ module Ea
|
|
|
23
23
|
|
|
24
24
|
COLUMN_MAP = {
|
|
25
25
|
"ObjectProblemID" => :object_problem_id,
|
|
26
|
-
"Object_ID" => :
|
|
26
|
+
"Object_ID" => :ea_object_id,
|
|
27
27
|
"ProblemType" => :problem_type,
|
|
28
28
|
"DateResolved" => :date_resolved
|
|
29
29
|
}.freeze
|
|
@@ -6,7 +6,7 @@ module Ea
|
|
|
6
6
|
# Requirement trace from t_objectrequires.
|
|
7
7
|
class EaObjectRequire < BaseModel
|
|
8
8
|
attribute :object_require_id, :integer
|
|
9
|
-
attribute :
|
|
9
|
+
attribute :ea_object_id, :integer
|
|
10
10
|
attribute :requirement, :string
|
|
11
11
|
attribute :requirement_type, :string
|
|
12
12
|
attribute :notes, :string
|
|
@@ -21,7 +21,7 @@ module Ea
|
|
|
21
21
|
|
|
22
22
|
COLUMN_MAP = {
|
|
23
23
|
"ObjectReqID" => :object_require_id,
|
|
24
|
-
"Object_ID" => :
|
|
24
|
+
"Object_ID" => :ea_object_id,
|
|
25
25
|
"ReqType" => :requirement_type
|
|
26
26
|
}.freeze
|
|
27
27
|
|
|
@@ -6,7 +6,7 @@ module Ea
|
|
|
6
6
|
# Resource allocation from t_objectresource.
|
|
7
7
|
class EaObjectResource < BaseModel
|
|
8
8
|
attribute :object_resource_id, :integer
|
|
9
|
-
attribute :
|
|
9
|
+
attribute :ea_object_id, :integer
|
|
10
10
|
attribute :resource, :string
|
|
11
11
|
attribute :role, :string
|
|
12
12
|
attribute :time_allocated, :string
|
|
@@ -22,7 +22,7 @@ module Ea
|
|
|
22
22
|
|
|
23
23
|
COLUMN_MAP = {
|
|
24
24
|
"ObjectResourceID" => :object_resource_id,
|
|
25
|
-
"Object_ID" => :
|
|
25
|
+
"Object_ID" => :ea_object_id
|
|
26
26
|
}.freeze
|
|
27
27
|
|
|
28
28
|
def self.column_map
|
|
@@ -6,7 +6,7 @@ module Ea
|
|
|
6
6
|
# Risk register entry from t_objectrisks.
|
|
7
7
|
class EaObjectRisk < BaseModel
|
|
8
8
|
attribute :object_risk_id, :integer
|
|
9
|
-
attribute :
|
|
9
|
+
attribute :ea_object_id, :integer
|
|
10
10
|
attribute :risk, :string
|
|
11
11
|
attribute :risk_type, :string
|
|
12
12
|
attribute :notes, :string
|
|
@@ -21,7 +21,7 @@ module Ea
|
|
|
21
21
|
|
|
22
22
|
COLUMN_MAP = {
|
|
23
23
|
"ObjectRiskID" => :object_risk_id,
|
|
24
|
-
"Object_ID" => :
|
|
24
|
+
"Object_ID" => :ea_object_id,
|
|
25
25
|
"RiskType" => :risk_type
|
|
26
26
|
}.freeze
|
|
27
27
|
|
|
@@ -6,7 +6,7 @@ module Ea
|
|
|
6
6
|
# Use case scenario from t_objectscenarios.
|
|
7
7
|
class EaObjectScenario < BaseModel
|
|
8
8
|
attribute :object_scenario_id, :integer
|
|
9
|
-
attribute :
|
|
9
|
+
attribute :ea_object_id, :integer
|
|
10
10
|
attribute :scenario, :string
|
|
11
11
|
attribute :scenario_type, :string
|
|
12
12
|
attribute :notes, :string
|
|
@@ -21,7 +21,7 @@ module Ea
|
|
|
21
21
|
|
|
22
22
|
COLUMN_MAP = {
|
|
23
23
|
"ObjectScenarioID" => :object_scenario_id,
|
|
24
|
-
"Object_ID" => :
|
|
24
|
+
"Object_ID" => :ea_object_id,
|
|
25
25
|
"ScenarioType" => :scenario_type
|
|
26
26
|
}.freeze
|
|
27
27
|
|
|
@@ -6,7 +6,7 @@ module Ea
|
|
|
6
6
|
# Test case from t_objecttests.
|
|
7
7
|
class EaObjectTest < BaseModel
|
|
8
8
|
attribute :object_test_id, :integer
|
|
9
|
-
attribute :
|
|
9
|
+
attribute :ea_object_id, :integer
|
|
10
10
|
attribute :test, :string
|
|
11
11
|
attribute :test_type, :string
|
|
12
12
|
attribute :status, :string
|
|
@@ -22,7 +22,7 @@ module Ea
|
|
|
22
22
|
|
|
23
23
|
COLUMN_MAP = {
|
|
24
24
|
"ObjectTestID" => :object_test_id,
|
|
25
|
-
"Object_ID" => :
|
|
25
|
+
"Object_ID" => :ea_object_id,
|
|
26
26
|
"TestType" => :test_type
|
|
27
27
|
}.freeze
|
|
28
28
|
|
|
@@ -6,7 +6,7 @@ module Ea
|
|
|
6
6
|
# Transaction record from t_objecttrx.
|
|
7
7
|
class EaObjectTrx < BaseModel
|
|
8
8
|
attribute :object_trx_id, :integer
|
|
9
|
-
attribute :
|
|
9
|
+
attribute :ea_object_id, :integer
|
|
10
10
|
attribute :trx, :string
|
|
11
11
|
attribute :trx_type, :string
|
|
12
12
|
attribute :notes, :string
|
|
@@ -21,7 +21,7 @@ module Ea
|
|
|
21
21
|
|
|
22
22
|
COLUMN_MAP = {
|
|
23
23
|
"ObjectTrxID" => :object_trx_id,
|
|
24
|
-
"Object_ID" => :
|
|
24
|
+
"Object_ID" => :ea_object_id,
|
|
25
25
|
"TrxType" => :trx_type
|
|
26
26
|
}.freeze
|
|
27
27
|
|
|
@@ -7,7 +7,7 @@ module Ea
|
|
|
7
7
|
# entry to its visual icon and default toolbox slot.
|
|
8
8
|
class EaPaletteItem < BaseModel
|
|
9
9
|
attribute :palette_id, :string
|
|
10
|
-
attribute :
|
|
10
|
+
attribute :ea_object_id, :integer
|
|
11
11
|
attribute :name, :string
|
|
12
12
|
attribute :alias, :string
|
|
13
13
|
attribute :image_id, :integer
|
|
@@ -23,7 +23,7 @@ module Ea
|
|
|
23
23
|
|
|
24
24
|
COLUMN_MAP = {
|
|
25
25
|
"PaletteID" => :palette_id,
|
|
26
|
-
"Object_ID" => :
|
|
26
|
+
"Object_ID" => :ea_object_id,
|
|
27
27
|
"Image_ID" => :image_id
|
|
28
28
|
}.freeze
|
|
29
29
|
|
|
@@ -6,7 +6,7 @@ module Ea
|
|
|
6
6
|
# Role-based constraint from t_roleconstraint.
|
|
7
7
|
class EaRoleConstraint < BaseModel
|
|
8
8
|
attribute :roleconstraint_id, :integer
|
|
9
|
-
attribute :
|
|
9
|
+
attribute :ea_object_id, :integer
|
|
10
10
|
attribute :role, :string
|
|
11
11
|
attribute :notes, :string
|
|
12
12
|
|
|
@@ -20,7 +20,7 @@ module Ea
|
|
|
20
20
|
|
|
21
21
|
COLUMN_MAP = {
|
|
22
22
|
"RoleConstraintID" => :roleconstraint_id,
|
|
23
|
-
"Object_ID" => :
|
|
23
|
+
"Object_ID" => :ea_object_id
|
|
24
24
|
}.freeze
|
|
25
25
|
|
|
26
26
|
def self.column_map
|
|
@@ -7,7 +7,7 @@ module Ea
|
|
|
7
7
|
# the QEA are encrypted and what algorithm was used.
|
|
8
8
|
class EaSecrypt < BaseModel
|
|
9
9
|
attribute :secrypt_id, :integer
|
|
10
|
-
attribute :
|
|
10
|
+
attribute :ea_object_id, :integer
|
|
11
11
|
attribute :encrypt, :string
|
|
12
12
|
attribute :password_hash, :string
|
|
13
13
|
|
|
@@ -21,7 +21,7 @@ module Ea
|
|
|
21
21
|
|
|
22
22
|
COLUMN_MAP = {
|
|
23
23
|
"SecryptID" => :secrypt_id,
|
|
24
|
-
"Object_ID" => :
|
|
24
|
+
"Object_ID" => :ea_object_id,
|
|
25
25
|
"PasswordHash" => :password_hash
|
|
26
26
|
}.freeze
|
|
27
27
|
|