Class: Ea::Qea::Database

Inherits:
Object
  • Object
show all
Defined in:
lib/ea/qea/database.rb

Overview

Database container for all loaded EA models

This class provides a unified container for all EA table collections loaded from a QEA database. It stores collections by name and provides accessor methods, statistics, and lookup functionality.

Examples:

Load and access database

database = Ea::Qea::Services::DatabaseLoader.new("file.qea").load
puts database.stats
# => {"objects" => 693, "attributes" => 1910, ...}

classes = database.objects.find_by_type("Class")
obj = database.find_object(123)

Constant Summary collapse

COLLECTION_ACCESSORS =
%i[
  attributes operations operation_params connectors packages
  diagrams diagram_objects diagram_links object_constraints
  tagged_values object_properties attribute_tags xrefs
  stereotypes datatypes constraint_types connector_types
  diagram_types object_types status_types complexity_types
  documents scripts
].freeze
TABLE_TO_COLLECTION =

Maps EA SQL table names to collection accessor symbols. Centralised here (MECE) so validators and services don't each maintain their own case/when dispatch. Adding a new table = adding one hash entry.

{
  "t_package"           => :packages,
  "t_object"            => :objects,
  "t_attribute"         => :attributes,
  "t_operation"         => :operations,
  "t_operationparams"   => :operation_params,
  "t_connector"         => :connectors,
  "t_diagram"           => :diagrams,
  "t_diagramobjects"    => :diagram_objects,
  "t_diagramlinks"      => :diagram_links,
  "t_objectconstraint"  => :object_constraints,
  "t_objectproperties"  => :object_properties,
  "t_taggedvalue"       => :tagged_values,
  "t_attributetag"      => :attribute_tags,
  "t_xref"              => :xrefs,
  "t_stereotypes"       => :stereotypes,
  "t_datatypes"         => :datatypes,
  "t_constrainttypes"   => :constraint_types,
  "t_connectortypes"    => :connector_types,
  "t_diagramtypes"      => :diagram_types,
  "t_objecttypes"       => :object_types,
  "t_statustypes"       => :status_types,
  "t_complexitytypes"   => :complexity_types,
  "t_documents"         => :documents,
  "t_scripts"           => :scripts,
}.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(qea_path, connection = nil) ⇒ Database

Returns a new instance of Database.



25
26
27
28
29
30
# File 'lib/ea/qea/database.rb', line 25

def initialize(qea_path, connection = nil)
  @qea_path = qea_path
  @connection = connection
  @collections = {}
  @mutex = Mutex.new
end

Instance Attribute Details

#collectionsHash<Symbol, Array> (readonly)

Returns Collections of records by name.

Returns:

  • (Hash<Symbol, Array>)

    Collections of records by name



20
21
22
# File 'lib/ea/qea/database.rb', line 20

def collections
  @collections
end

#qea_pathString (readonly)

Returns Path to the QEA file.

Returns:

  • (String)

    Path to the QEA file



23
24
25
# File 'lib/ea/qea/database.rb', line 23

def qea_path
  @qea_path
end

Instance Method Details

#add_collection(name, records) ⇒ void

This method returns an undefined value.

Add a collection to the database

Parameters:

  • name (Symbol, String)

    Collection name (e.g., :objects)

  • records (Array)

    Array of model instances



53
54
55
56
57
# File 'lib/ea/qea/database.rb', line 53

def add_collection(name, records)
  @mutex.synchronize do
    @collections[name.to_sym] = records.freeze
  end
end

#attributes_for_object(id) ⇒ Object



175
176
177
178
# File 'lib/ea/qea/database.rb', line 175

def attributes_for_object(id)
  ensure_lookup_indexes
  @attributes_by_object_id[id] || []
end

#child_packages_for(id) ⇒ Object



190
191
192
193
# File 'lib/ea/qea/database.rb', line 190

def child_packages_for(id)
  ensure_lookup_indexes
  @packages_by_parent[id] || []
end

#close_connectionvoid

This method returns an undefined value.

Close the database connection if open



42
43
44
45
46
# File 'lib/ea/qea/database.rb', line 42

def close_connection
  return unless @connection && !@connection.closed?

  @connection.close
end

#collection_for_table(table_name) ⇒ Array

Returns the collection for that table, or [] if unknown.

Parameters:

  • table_name (String)

    EA SQL table name (e.g., "t_object")

Returns:

  • (Array)

    the collection for that table, or [] if unknown



101
102
103
104
105
106
107
108
109
110
111
# File 'lib/ea/qea/database.rb', line 101

def collection_for_table(table_name)
  name = TABLE_TO_COLLECTION[table_name]
  return [] unless name

  records = @collections[name]
  return [] unless records

  # t_object is wrapped in ObjectRepository — call .all to
  # get the plain Array that validators expect.
  records.is_a?(Repositories::ObjectRepository) ? records.all : records
end

#collection_namesArray<Symbol>

Get collection names

Returns:

  • (Array<Symbol>)

    Array of collection names



272
273
274
# File 'lib/ea/qea/database.rb', line 272

def collection_names
  @collections.keys
end

#connection=(connection) ⇒ void

This method returns an undefined value.

Set database connection

Parameters:

  • connection (SQLite3::Database)

    Database connection



36
37
38
# File 'lib/ea/qea/database.rb', line 36

def connection=(connection)
  @connection = connection
end

#connectors_for_object(object_id) ⇒ Object

Get connectors involving a specific object (start or end)



237
238
239
240
# File 'lib/ea/qea/database.rb', line 237

def connectors_for_object(object_id)
  ensure_lookup_indexes
  @connectors_by_object[object_id] || []
end

#constraints_for_object(object_id) ⇒ Object



242
243
244
245
# File 'lib/ea/qea/database.rb', line 242

def constraints_for_object(object_id)
  ensure_lookup_indexes
  @constraints_by_object_id[object_id] || []
end


210
211
212
213
# File 'lib/ea/qea/database.rb', line 210

def diagram_links_for(id)
  ensure_lookup_indexes
  @diagram_links_by_id[id] || []
end

#diagram_objects_for(id) ⇒ Object



205
206
207
208
# File 'lib/ea/qea/database.rb', line 205

def diagram_objects_for(id)
  ensure_lookup_indexes
  @diagram_objects_by_id[id] || []
end

#diagrams_in_package(id) ⇒ Object



200
201
202
203
# File 'lib/ea/qea/database.rb', line 200

def diagrams_in_package(id)
  ensure_lookup_indexes
  @diagrams_by_package_id[id] || []
end

#empty?Boolean

Check if database is empty

Returns:

  • (Boolean)

    true if no collections loaded



265
266
267
# File 'lib/ea/qea/database.rb', line 265

def empty?
  @collections.empty? || total_records.zero?
end

#find_attribute(id) ⇒ Object



160
161
162
163
# File 'lib/ea/qea/database.rb', line 160

def find_attribute(id)
  ensure_lookup_indexes
  @attributes_by_id[id]
end

#find_connector(id) ⇒ Object



165
166
167
168
# File 'lib/ea/qea/database.rb', line 165

def find_connector(id)
  ensure_lookup_indexes
  @connectors_by_id[id]
end

#find_diagram(id) ⇒ Object



170
171
172
173
# File 'lib/ea/qea/database.rb', line 170

def find_diagram(id)
  ensure_lookup_indexes
  @diagrams_by_id[id]
end

#find_object(id) ⇒ Object

Find an object by ID. Uses the repository's primary-key index rather than a scan: the parentid walk in QeaToXmi's cyclic_ancestry? calls this once per ancestor hop per object.

Hash lookup matches on eql?, so it would miss a Float id that a scan's == would have caught. No caller here can do that: t_object.Object_ID is declared Type::Integer and the model coerces on construction, and every caller passes either such an attribute or an explicit to_i. Deliberately left unguarded — a scan fallback on miss would put every absent-parent lookup in the ancestry walk back on a linear scan.



226
227
228
# File 'lib/ea/qea/database.rb', line 226

def find_object(id)
  objects.find(id)
end

#find_object_by_guid(ea_guid) ⇒ Object

Find object by ea_guid



231
232
233
234
# File 'lib/ea/qea/database.rb', line 231

def find_object_by_guid(ea_guid)
  ensure_lookup_indexes
  @objects_by_guid[ea_guid]
end

#find_package(id) ⇒ Object



155
156
157
158
# File 'lib/ea/qea/database.rb', line 155

def find_package(id)
  ensure_lookup_indexes
  @packages_by_id[id]
end

#freezeself

Freeze all collections to make database immutable

Returns:

  • (self)


279
280
281
282
283
284
# File 'lib/ea/qea/database.rb', line 279

def freeze
  objects
  ensure_lookup_indexes
  @collections.freeze
  super
end

#objectsRepositories::ObjectRepository

Get objects collection (special: wrapped in ObjectRepository)

Returns:



122
123
124
125
126
127
128
# File 'lib/ea/qea/database.rb', line 122

def objects
  return @objects if defined?(@objects)

  @objects = Repositories::ObjectRepository.new(
    @collections[:objects] || [],
  )
end

#objects_in_package(id) ⇒ Object



195
196
197
198
# File 'lib/ea/qea/database.rb', line 195

def objects_in_package(id)
  ensure_lookup_indexes
  @objects_by_package_id[id] || []
end

#operation_params_for(id) ⇒ Object



185
186
187
188
# File 'lib/ea/qea/database.rb', line 185

def operation_params_for(id)
  ensure_lookup_indexes
  @operation_params_by_id[id] || []
end

#operations_for_object(id) ⇒ Object



180
181
182
183
# File 'lib/ea/qea/database.rb', line 180

def operations_for_object(id)
  ensure_lookup_indexes
  @operations_by_object_id[id] || []
end

#properties_for_object(object_id) ⇒ Object



252
253
254
255
# File 'lib/ea/qea/database.rb', line 252

def properties_for_object(object_id)
  ensure_lookup_indexes
  @properties_by_object_id[object_id] || []
end

#statsHash<String, Integer>

Get statistics for all collections

Examples:

database.stats
# => {
#   "objects" => 693,
#   "attributes" => 1910,
#   "connectors" => 908,
#   ...
# }

Returns:

  • (Hash<String, Integer>)

    Record counts by collection name



142
143
144
145
146
# File 'lib/ea/qea/database.rb', line 142

def stats
  @collections.each_with_object({}) do |(name, records), hash|
    hash[name.to_s] = records.size
  end
end

#tagged_values_for_element(ea_guid) ⇒ Object



247
248
249
250
# File 'lib/ea/qea/database.rb', line 247

def tagged_values_for_element(ea_guid)
  ensure_lookup_indexes
  @tagged_values_by_element_id[ea_guid] || []
end

#total_recordsInteger

Get total number of records across all collections

Returns:

  • (Integer)

    Total record count



151
152
153
# File 'lib/ea/qea/database.rb', line 151

def total_records
  @collections.values.sum(&:size)
end

#xrefs_for_client(ea_guid) ⇒ Object



257
258
259
260
# File 'lib/ea/qea/database.rb', line 257

def xrefs_for_client(ea_guid)
  ensure_lookup_indexes
  @xrefs_by_client[ea_guid] || []
end