expressir 2.1.29 → 2.1.31
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/.github/workflows/docs.yml +98 -0
- data/.github/workflows/links.yml +100 -0
- data/.github/workflows/rake.yml +4 -0
- data/.github/workflows/release.yml +5 -0
- data/.github/workflows/validate_schemas.yml +1 -1
- data/.gitignore +3 -0
- data/.rubocop.yml +1 -1
- data/.rubocop_todo.yml +209 -55
- data/Gemfile +2 -1
- data/README.adoc +650 -83
- data/docs/Gemfile +12 -0
- data/docs/_config.yml +141 -0
- data/docs/_guides/changes/changes-format.adoc +778 -0
- data/docs/_guides/changes/importing-eengine.adoc +898 -0
- data/docs/_guides/changes/index.adoc +396 -0
- data/docs/_guides/changes/programmatic-usage.adoc +1038 -0
- data/docs/_guides/changes/validating-changes.adoc +681 -0
- data/docs/_guides/cli/benchmark-performance.adoc +834 -0
- data/docs/_guides/cli/coverage-analysis.adoc +921 -0
- data/docs/_guides/cli/format-schemas.adoc +547 -0
- data/docs/_guides/cli/index.adoc +8 -0
- data/docs/_guides/cli/managing-changes.adoc +927 -0
- data/docs/_guides/cli/validate-ascii.adoc +645 -0
- data/docs/_guides/cli/validate-schemas.adoc +534 -0
- data/docs/_guides/index.adoc +165 -0
- data/docs/_guides/ler/creating-packages.adoc +664 -0
- data/docs/_guides/ler/index.adoc +305 -0
- data/docs/_guides/ler/loading-packages.adoc +707 -0
- data/docs/_guides/ler/package-formats.adoc +748 -0
- data/docs/_guides/ler/querying-packages.adoc +826 -0
- data/docs/_guides/ler/validating-packages.adoc +750 -0
- data/docs/_guides/liquid/basic-templates.adoc +813 -0
- data/docs/_guides/liquid/documentation-generation.adoc +1042 -0
- data/docs/_guides/liquid/drops-reference.adoc +829 -0
- data/docs/_guides/liquid/filters-and-tags.adoc +912 -0
- data/docs/_guides/liquid/index.adoc +468 -0
- data/docs/_guides/manifests/creating-manifests.adoc +483 -0
- data/docs/_guides/manifests/index.adoc +307 -0
- data/docs/_guides/manifests/resolving-manifests.adoc +557 -0
- data/docs/_guides/manifests/validating-manifests.adoc +713 -0
- data/docs/_guides/ruby-api/formatting-schemas.adoc +605 -0
- data/docs/_guides/ruby-api/index.adoc +257 -0
- data/docs/_guides/ruby-api/parsing-files.adoc +421 -0
- data/docs/_guides/ruby-api/search-engine.adoc +609 -0
- data/docs/_guides/ruby-api/working-with-repository.adoc +577 -0
- data/docs/_pages/data-model.adoc +665 -0
- data/docs/_pages/express-language.adoc +506 -0
- data/docs/_pages/getting-started.adoc +414 -0
- data/docs/_pages/index.adoc +116 -0
- data/docs/_pages/introduction.adoc +256 -0
- data/docs/_pages/ler-packages.adoc +837 -0
- data/docs/_pages/parsers.adoc +683 -0
- data/docs/_pages/schema-manifests.adoc +431 -0
- data/docs/_references/index.adoc +228 -0
- data/docs/_tutorials/creating-ler-package.adoc +735 -0
- data/docs/_tutorials/documentation-coverage.adoc +795 -0
- data/docs/_tutorials/index.adoc +221 -0
- data/docs/_tutorials/liquid-templates.adoc +806 -0
- data/docs/_tutorials/parsing-your-first-schema.adoc +522 -0
- data/docs/_tutorials/querying-schemas.adoc +751 -0
- data/docs/_tutorials/working-with-multiple-schemas.adoc +676 -0
- data/docs/index.adoc +242 -0
- data/docs/lychee.toml +84 -0
- data/examples/demo_ler_usage.sh +86 -0
- data/examples/ler/README.md +111 -0
- data/examples/ler/simple_example.ler +0 -0
- data/examples/ler/simple_schema.exp +33 -0
- data/examples/ler_build.rb +75 -0
- data/examples/ler_cli.rb +79 -0
- data/examples/ler_demo_complete.rb +276 -0
- data/examples/ler_query.rb +91 -0
- data/examples/ler_query_examples.rb +305 -0
- data/examples/ler_stats.rb +81 -0
- data/examples/phase3_demo.rb +159 -0
- data/examples/query_demo_simple.rb +131 -0
- data/expressir.gemspec +2 -0
- data/lib/expressir/changes/schema_change.rb +32 -22
- data/lib/expressir/changes/{edition_change.rb → version_change.rb} +3 -3
- data/lib/expressir/cli.rb +12 -4
- data/lib/expressir/commands/changes_import_eengine.rb +2 -2
- data/lib/expressir/commands/changes_validate.rb +1 -1
- data/lib/expressir/commands/manifest.rb +427 -0
- data/lib/expressir/commands/package.rb +1274 -0
- data/lib/expressir/commands/validate.rb +70 -37
- data/lib/expressir/commands/validate_ascii.rb +607 -0
- data/lib/expressir/commands/validate_load.rb +88 -0
- data/lib/expressir/express/formatter.rb +5 -1
- data/lib/expressir/express/formatters/remark_item_formatter.rb +25 -0
- data/lib/expressir/express/parser.rb +33 -0
- data/lib/expressir/manifest/resolver.rb +213 -0
- data/lib/expressir/manifest/validator.rb +195 -0
- data/lib/expressir/model/declarations/entity.rb +6 -0
- data/lib/expressir/model/dependency_resolver.rb +270 -0
- data/lib/expressir/model/indexes/entity_index.rb +103 -0
- data/lib/expressir/model/indexes/reference_index.rb +148 -0
- data/lib/expressir/model/indexes/type_index.rb +149 -0
- data/lib/expressir/model/interface_validator.rb +384 -0
- data/lib/expressir/model/repository.rb +400 -5
- data/lib/expressir/model/repository_validator.rb +295 -0
- data/lib/expressir/model/search_engine.rb +525 -0
- data/lib/expressir/model.rb +4 -94
- data/lib/expressir/package/builder.rb +200 -0
- data/lib/expressir/package/metadata.rb +81 -0
- data/lib/expressir/package/reader.rb +165 -0
- data/lib/expressir/schema_manifest.rb +11 -1
- data/lib/expressir/version.rb +1 -1
- data/lib/expressir.rb +16 -3
- metadata +115 -5
- data/docs/benchmarking.adoc +0 -107
- data/docs/liquid_drops.adoc +0 -1547
|
@@ -0,0 +1,577 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Working with Repository
|
|
3
|
+
parent: Ruby API
|
|
4
|
+
grand_parent: Guides
|
|
5
|
+
nav_order: 2
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
= Working with Repository
|
|
9
|
+
|
|
10
|
+
== Purpose
|
|
11
|
+
|
|
12
|
+
The Repository class is the central container for managing collections of
|
|
13
|
+
EXPRESS schemas. It provides methods for querying, validation, statistics,
|
|
14
|
+
and export operations across multiple schemas.
|
|
15
|
+
|
|
16
|
+
== References
|
|
17
|
+
|
|
18
|
+
* link:parsing-files.html[Parsing Files] - Creating repositories
|
|
19
|
+
* link:search-engine.html[Search Engine] - Advanced querying
|
|
20
|
+
* link:../../pages/ler-packages.html[LER Packages] - Binary package format
|
|
21
|
+
|
|
22
|
+
== Concepts
|
|
23
|
+
|
|
24
|
+
repository:: Container holding multiple EXPRESS schemas with query and management capabilities
|
|
25
|
+
schema:: Individual EXPRESS schema within a repository
|
|
26
|
+
indexes:: Internal structures for fast entity and type lookup
|
|
27
|
+
validation:: Checking repository consistency and completeness
|
|
28
|
+
enumerable:: Repository implements Ruby's Enumerable interface for iteration
|
|
29
|
+
|
|
30
|
+
== Creating repositories
|
|
31
|
+
|
|
32
|
+
=== From parsed files
|
|
33
|
+
|
|
34
|
+
The most common way to create a repository is through parsing:
|
|
35
|
+
|
|
36
|
+
[source,ruby]
|
|
37
|
+
----
|
|
38
|
+
require "expressir"
|
|
39
|
+
|
|
40
|
+
# Single file creates a repository
|
|
41
|
+
repository = Expressir::Express::Parser.from_file("schema.exp")
|
|
42
|
+
|
|
43
|
+
# Multiple files create a combined repository
|
|
44
|
+
files = Dir.glob("schemas/**/*.exp")
|
|
45
|
+
repository = Expressir::Express::Parser.from_files(files)
|
|
46
|
+
----
|
|
47
|
+
|
|
48
|
+
=== From file paths
|
|
49
|
+
|
|
50
|
+
Build a repository directly from file paths:
|
|
51
|
+
|
|
52
|
+
[source,ruby]
|
|
53
|
+
----
|
|
54
|
+
file_paths = [
|
|
55
|
+
"schemas/action_schema.exp",
|
|
56
|
+
"schemas/approval_schema.exp"
|
|
57
|
+
]
|
|
58
|
+
|
|
59
|
+
repository = Expressir::Model::Repository.from_files(
|
|
60
|
+
file_paths,
|
|
61
|
+
base_dir: "schemas"
|
|
62
|
+
)
|
|
63
|
+
----
|
|
64
|
+
|
|
65
|
+
This automatically parses all files and resolves references.
|
|
66
|
+
|
|
67
|
+
=== From LER package
|
|
68
|
+
|
|
69
|
+
Load a pre-built LER package:
|
|
70
|
+
|
|
71
|
+
[source,ruby]
|
|
72
|
+
----
|
|
73
|
+
# Load from binary package
|
|
74
|
+
repository = Expressir::Model::Repository.from_package("schemas.ler")
|
|
75
|
+
|
|
76
|
+
# Much faster than parsing source files
|
|
77
|
+
puts "Loaded #{repository.schemas.size} schemas from package"
|
|
78
|
+
----
|
|
79
|
+
|
|
80
|
+
=== Creating empty repository
|
|
81
|
+
|
|
82
|
+
Create an empty repository and populate it manually:
|
|
83
|
+
|
|
84
|
+
[source,ruby]
|
|
85
|
+
----
|
|
86
|
+
repository = Expressir::Model::Repository.new(base_dir: "/path/to/schemas")
|
|
87
|
+
|
|
88
|
+
# Add schemas manually if needed
|
|
89
|
+
# repository.schemas << schema
|
|
90
|
+
----
|
|
91
|
+
|
|
92
|
+
== Accessing schemas
|
|
93
|
+
|
|
94
|
+
=== Enumerable interface
|
|
95
|
+
|
|
96
|
+
Repository implements `Enumerable`, enabling Ruby collection methods:
|
|
97
|
+
|
|
98
|
+
[source,ruby]
|
|
99
|
+
----
|
|
100
|
+
# Iterate through schemas
|
|
101
|
+
repository.each do |schema|
|
|
102
|
+
puts "Schema: #{schema.id}"
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Filter schemas
|
|
106
|
+
action_schemas = repository.select { |s| s.id.include?("action") }
|
|
107
|
+
|
|
108
|
+
# Find specific schema
|
|
109
|
+
schema = repository.find { |s| s.id == "action_schema" }
|
|
110
|
+
|
|
111
|
+
# Map over schemas
|
|
112
|
+
schema_names = repository.map(&:id)
|
|
113
|
+
|
|
114
|
+
# Count schemas
|
|
115
|
+
total = repository.count
|
|
116
|
+
----
|
|
117
|
+
|
|
118
|
+
=== Direct access
|
|
119
|
+
|
|
120
|
+
[source,ruby]
|
|
121
|
+
----
|
|
122
|
+
# Access schemas array directly
|
|
123
|
+
all_schemas = repository.schemas
|
|
124
|
+
|
|
125
|
+
# Get first/last schema
|
|
126
|
+
first_schema = repository.schemas.first
|
|
127
|
+
last_schema = repository.schemas.last
|
|
128
|
+
|
|
129
|
+
# Find by index
|
|
130
|
+
schema = repository.schemas[0]
|
|
131
|
+
----
|
|
132
|
+
|
|
133
|
+
=== Schema properties
|
|
134
|
+
|
|
135
|
+
Each schema in the repository has useful properties:
|
|
136
|
+
|
|
137
|
+
[source,ruby]
|
|
138
|
+
----
|
|
139
|
+
schema = repository.schemas.first
|
|
140
|
+
|
|
141
|
+
puts "ID: #{schema.id}"
|
|
142
|
+
puts "File: #{schema.file}"
|
|
143
|
+
puts "Version: #{schema.version&.value}"
|
|
144
|
+
puts "Entities: #{schema.entities&.size}"
|
|
145
|
+
puts "Types: #{schema.types&.size}"
|
|
146
|
+
puts "Functions: #{schema.functions&.size}"
|
|
147
|
+
----
|
|
148
|
+
|
|
149
|
+
== Querying entities and types
|
|
150
|
+
|
|
151
|
+
=== List entities
|
|
152
|
+
|
|
153
|
+
Get all entities across schemas or filtered by schema:
|
|
154
|
+
|
|
155
|
+
[source,ruby]
|
|
156
|
+
----
|
|
157
|
+
# List all entities (returns objects by default)
|
|
158
|
+
entities = repository.list_entities
|
|
159
|
+
|
|
160
|
+
# Filter by schema
|
|
161
|
+
entities = repository.list_entities(schema: "action_schema")
|
|
162
|
+
|
|
163
|
+
# Get as hash
|
|
164
|
+
entities = repository.list_entities(format: :hash)
|
|
165
|
+
|
|
166
|
+
# Get as JSON
|
|
167
|
+
json = repository.list_entities(format: :json)
|
|
168
|
+
|
|
169
|
+
# Get as YAML
|
|
170
|
+
yaml = repository.list_entities(format: :yaml)
|
|
171
|
+
----
|
|
172
|
+
|
|
173
|
+
=== List types
|
|
174
|
+
|
|
175
|
+
Get all types with optional filtering:
|
|
176
|
+
|
|
177
|
+
[source,ruby]
|
|
178
|
+
----
|
|
179
|
+
# List all types
|
|
180
|
+
types = repository.list_types
|
|
181
|
+
|
|
182
|
+
# Filter by schema
|
|
183
|
+
types = repository.list_types(schema: "action_schema")
|
|
184
|
+
|
|
185
|
+
# Filter by category
|
|
186
|
+
select_types = repository.list_types(category: "select")
|
|
187
|
+
enum_types = repository.list_types(category: "enumeration")
|
|
188
|
+
|
|
189
|
+
# Combine filters
|
|
190
|
+
types = repository.list_types(
|
|
191
|
+
schema: "action_schema",
|
|
192
|
+
category: "select",
|
|
193
|
+
format: :hash
|
|
194
|
+
)
|
|
195
|
+
----
|
|
196
|
+
|
|
197
|
+
=== Find specific items
|
|
198
|
+
|
|
199
|
+
Use the index methods for fast lookup:
|
|
200
|
+
|
|
201
|
+
[source,ruby]
|
|
202
|
+
----
|
|
203
|
+
# Find entity by qualified name
|
|
204
|
+
entity = repository.find_entity(
|
|
205
|
+
qualified_name: "action_schema.action"
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
if entity
|
|
209
|
+
puts "Found entity: #{entity.id}"
|
|
210
|
+
puts "Attributes: #{entity.attributes&.size}"
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
# Find type by qualified name
|
|
214
|
+
type = repository.find_type(
|
|
215
|
+
qualified_name: "action_schema.action_items"
|
|
216
|
+
)
|
|
217
|
+
----
|
|
218
|
+
|
|
219
|
+
== Building indexes
|
|
220
|
+
|
|
221
|
+
Repositories use indexes for fast lookups. Indexes are built automatically
|
|
222
|
+
when needed, but you can build them explicitly:
|
|
223
|
+
|
|
224
|
+
[source,ruby]
|
|
225
|
+
----
|
|
226
|
+
# Build all indexes
|
|
227
|
+
repository.build_indexes
|
|
228
|
+
|
|
229
|
+
# Indexes are now available
|
|
230
|
+
puts "Entity index size: #{repository.entity_index.count}"
|
|
231
|
+
puts "Type index size: #{repository.type_index.count}"
|
|
232
|
+
----
|
|
233
|
+
|
|
234
|
+
Indexes are lazy-loaded by default - they're built on first use:
|
|
235
|
+
|
|
236
|
+
[source,ruby]
|
|
237
|
+
----
|
|
238
|
+
# First query builds indexes automatically
|
|
239
|
+
entity = repository.find_entity(qualified_name: "action_schema.action")
|
|
240
|
+
|
|
241
|
+
# Subsequent queries use existing indexes (faster)
|
|
242
|
+
another = repository.find_entity(qualified_name: "action_schema.event")
|
|
243
|
+
----
|
|
244
|
+
|
|
245
|
+
== Validation
|
|
246
|
+
|
|
247
|
+
=== Basic validation
|
|
248
|
+
|
|
249
|
+
Validate repository consistency and completeness:
|
|
250
|
+
|
|
251
|
+
[source,ruby]
|
|
252
|
+
----
|
|
253
|
+
result = repository.validate
|
|
254
|
+
|
|
255
|
+
if result[:valid?]
|
|
256
|
+
puts "Repository is valid"
|
|
257
|
+
else
|
|
258
|
+
puts "Validation failed"
|
|
259
|
+
|
|
260
|
+
result[:errors].each do |error|
|
|
261
|
+
puts "ERROR: #{error}"
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
result[:warnings].each do |warning|
|
|
265
|
+
puts "WARNING: #{warning}"
|
|
266
|
+
end
|
|
267
|
+
end
|
|
268
|
+
----
|
|
269
|
+
|
|
270
|
+
=== Strict validation
|
|
271
|
+
|
|
272
|
+
Enable strict mode for more rigorous checking:
|
|
273
|
+
|
|
274
|
+
[source,ruby]
|
|
275
|
+
----
|
|
276
|
+
result = repository.validate(strict: true)
|
|
277
|
+
|
|
278
|
+
# Strict mode checks:
|
|
279
|
+
# - Interface completeness
|
|
280
|
+
# - Reference integrity
|
|
281
|
+
# - Type consistency
|
|
282
|
+
# - Entity relationships
|
|
283
|
+
----
|
|
284
|
+
|
|
285
|
+
== Statistics and analysis
|
|
286
|
+
|
|
287
|
+
=== Basic statistics
|
|
288
|
+
|
|
289
|
+
Get comprehensive repository statistics:
|
|
290
|
+
|
|
291
|
+
[source,ruby]
|
|
292
|
+
----
|
|
293
|
+
stats = repository.statistics
|
|
294
|
+
|
|
295
|
+
puts "Total schemas: #{stats[:total_schemas]}"
|
|
296
|
+
puts "Total entities: #{stats[:total_entities]}"
|
|
297
|
+
puts "Total types: #{stats[:total_types]}"
|
|
298
|
+
puts "Total functions: #{stats[:total_functions]}"
|
|
299
|
+
puts "Total rules: #{stats[:total_rules]}"
|
|
300
|
+
puts "Total procedures: #{stats[:total_procedures]}"
|
|
301
|
+
|
|
302
|
+
# Entities by schema
|
|
303
|
+
stats[:entities_by_schema].each do |schema, count|
|
|
304
|
+
puts "#{schema}: #{count} entities"
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
# Types by category
|
|
308
|
+
stats[:types_by_category].each do |category, count|
|
|
309
|
+
puts "#{category}: #{count} types"
|
|
310
|
+
end
|
|
311
|
+
----
|
|
312
|
+
|
|
313
|
+
=== Output formats
|
|
314
|
+
|
|
315
|
+
Statistics can be exported in different formats:
|
|
316
|
+
|
|
317
|
+
[source,ruby]
|
|
318
|
+
----
|
|
319
|
+
# As Ruby hash (default)
|
|
320
|
+
stats = repository.statistics(format: :hash)
|
|
321
|
+
|
|
322
|
+
# As JSON string
|
|
323
|
+
json = repository.statistics(format: :json)
|
|
324
|
+
|
|
325
|
+
# As YAML string
|
|
326
|
+
yaml = repository.statistics(format: :yaml)
|
|
327
|
+
----
|
|
328
|
+
|
|
329
|
+
=== Schema categorization
|
|
330
|
+
|
|
331
|
+
Group schemas by their content:
|
|
332
|
+
|
|
333
|
+
[source,ruby]
|
|
334
|
+
----
|
|
335
|
+
categories = repository.schemas_by_category
|
|
336
|
+
|
|
337
|
+
puts "Schemas with entities: #{categories[:with_entities].size}"
|
|
338
|
+
puts "Schemas with types: #{categories[:with_types].size}"
|
|
339
|
+
puts "Schemas with functions: #{categories[:with_functions].size}"
|
|
340
|
+
puts "Schemas with rules: #{categories[:with_rules].size}"
|
|
341
|
+
puts "Interface-only schemas: #{categories[:interface_only].size}"
|
|
342
|
+
puts "Empty schemas: #{categories[:empty].size}"
|
|
343
|
+
----
|
|
344
|
+
|
|
345
|
+
=== Largest schemas
|
|
346
|
+
|
|
347
|
+
Find the largest schemas by element count:
|
|
348
|
+
|
|
349
|
+
[source,ruby]
|
|
350
|
+
----
|
|
351
|
+
# Get top 10 largest schemas
|
|
352
|
+
largest = repository.largest_schemas(10)
|
|
353
|
+
|
|
354
|
+
largest.each do |item|
|
|
355
|
+
schema = item[:schema]
|
|
356
|
+
count = item[:total_elements]
|
|
357
|
+
puts "#{schema.id}: #{count} elements"
|
|
358
|
+
end
|
|
359
|
+
----
|
|
360
|
+
|
|
361
|
+
=== Complexity analysis
|
|
362
|
+
|
|
363
|
+
Calculate schema complexity scores:
|
|
364
|
+
|
|
365
|
+
[source,ruby]
|
|
366
|
+
----
|
|
367
|
+
# Get schemas by complexity
|
|
368
|
+
complex = repository.schemas_by_complexity(10)
|
|
369
|
+
|
|
370
|
+
complex.each do |item|
|
|
371
|
+
schema = item[:schema]
|
|
372
|
+
score = item[:complexity]
|
|
373
|
+
puts "#{schema.id}: complexity score #{score}"
|
|
374
|
+
end
|
|
375
|
+
|
|
376
|
+
# Calculate complexity for specific schema
|
|
377
|
+
schema = repository.schemas.first
|
|
378
|
+
score = repository.schema_complexity(schema)
|
|
379
|
+
puts "Complexity: #{score}"
|
|
380
|
+
----
|
|
381
|
+
|
|
382
|
+
Complexity scoring:
|
|
383
|
+
|
|
384
|
+
* Entities: 2 points each
|
|
385
|
+
* Types: 1 point each
|
|
386
|
+
* Functions: 3 points each
|
|
387
|
+
* Procedures: 3 points each
|
|
388
|
+
* Rules: 4 points each
|
|
389
|
+
* Interfaces: 2 points each
|
|
390
|
+
|
|
391
|
+
=== Dependency statistics
|
|
392
|
+
|
|
393
|
+
Analyze interface dependencies between schemas:
|
|
394
|
+
|
|
395
|
+
[source,ruby]
|
|
396
|
+
----
|
|
397
|
+
deps = repository.dependency_statistics
|
|
398
|
+
|
|
399
|
+
puts "Total interfaces: #{deps[:total_interfaces]}"
|
|
400
|
+
puts "USE FROM: #{deps[:use_from_count]}"
|
|
401
|
+
puts "REFERENCE FROM: #{deps[:reference_from_count]}"
|
|
402
|
+
|
|
403
|
+
# Most referenced schemas
|
|
404
|
+
puts "\nMost referenced schemas:"
|
|
405
|
+
deps[:most_referenced].each do |schema, count|
|
|
406
|
+
puts " #{schema}: #{count} references"
|
|
407
|
+
end
|
|
408
|
+
|
|
409
|
+
# Most dependent schemas
|
|
410
|
+
puts "\nMost dependent schemas:"
|
|
411
|
+
deps[:most_dependent].each do |schema, count|
|
|
412
|
+
puts " #{schema}: #{count} dependencies"
|
|
413
|
+
end
|
|
414
|
+
----
|
|
415
|
+
|
|
416
|
+
== Reference resolution
|
|
417
|
+
|
|
418
|
+
=== Automatic resolution
|
|
419
|
+
|
|
420
|
+
By default, the parser resolves references automatically:
|
|
421
|
+
|
|
422
|
+
[source,ruby]
|
|
423
|
+
----
|
|
424
|
+
# References are resolved during parsing
|
|
425
|
+
repository = Expressir::Express::Parser.from_file("schema.exp")
|
|
426
|
+
|
|
427
|
+
# USE FROM and REFERENCE FROM are linked
|
|
428
|
+
schema = repository.schemas.first
|
|
429
|
+
schema.interfaces&.each do |interface|
|
|
430
|
+
puts "Interface to: #{interface.schema&.id}"
|
|
431
|
+
end
|
|
432
|
+
----
|
|
433
|
+
|
|
434
|
+
=== Manual resolution
|
|
435
|
+
|
|
436
|
+
Resolve references manually if needed:
|
|
437
|
+
|
|
438
|
+
[source,ruby]
|
|
439
|
+
----
|
|
440
|
+
# Parse without resolving references
|
|
441
|
+
repository = Expressir::Express::Parser.from_file(
|
|
442
|
+
"schema.exp",
|
|
443
|
+
skip_references: true
|
|
444
|
+
)
|
|
445
|
+
|
|
446
|
+
# Resolve later
|
|
447
|
+
repository.resolve_all_references
|
|
448
|
+
|
|
449
|
+
# Now references are linked
|
|
450
|
+
----
|
|
451
|
+
|
|
452
|
+
This is useful when building repositories incrementally or when you want
|
|
453
|
+
control over when resolution happens.
|
|
454
|
+
|
|
455
|
+
== Export operations
|
|
456
|
+
|
|
457
|
+
=== Create schema manifest
|
|
458
|
+
|
|
459
|
+
Generate a manifest file describing all schemas:
|
|
460
|
+
|
|
461
|
+
[source,ruby]
|
|
462
|
+
----
|
|
463
|
+
manifest = repository.to_manifest
|
|
464
|
+
|
|
465
|
+
# Save to file
|
|
466
|
+
manifest.to_file("schemas.yml")
|
|
467
|
+
|
|
468
|
+
# Access entries
|
|
469
|
+
manifest.schemas.each do |entry|
|
|
470
|
+
puts "Schema: #{entry.id}"
|
|
471
|
+
puts "Path: #{entry.path}"
|
|
472
|
+
end
|
|
473
|
+
----
|
|
474
|
+
|
|
475
|
+
=== Export to LER package
|
|
476
|
+
|
|
477
|
+
Create a binary LER package for faster loading:
|
|
478
|
+
|
|
479
|
+
[source,ruby]
|
|
480
|
+
----
|
|
481
|
+
# Export with default options
|
|
482
|
+
repository.export_to_package("output.ler")
|
|
483
|
+
|
|
484
|
+
# With custom options
|
|
485
|
+
repository.export_to_package(
|
|
486
|
+
"output.ler",
|
|
487
|
+
name: "My Schema Set",
|
|
488
|
+
version: "1.0",
|
|
489
|
+
description: "Production schemas",
|
|
490
|
+
express_mode: "include_all",
|
|
491
|
+
resolution_mode: "resolved",
|
|
492
|
+
serialization_format: "marshal"
|
|
493
|
+
)
|
|
494
|
+
----
|
|
495
|
+
|
|
496
|
+
Options:
|
|
497
|
+
|
|
498
|
+
`name`:: Package name
|
|
499
|
+
`version`:: Package version
|
|
500
|
+
`description`:: Package description
|
|
501
|
+
`express_mode`:: "include_all", "include_referenced", or "exclude_all"
|
|
502
|
+
`resolution_mode`:: "resolved" or "unresolved"
|
|
503
|
+
`serialization_format`:: "marshal", "yaml", or "json"
|
|
504
|
+
|
|
505
|
+
== Performance best practices
|
|
506
|
+
|
|
507
|
+
=== Use indexes efficiently
|
|
508
|
+
|
|
509
|
+
[source,ruby]
|
|
510
|
+
----
|
|
511
|
+
# Build indexes once for multiple queries
|
|
512
|
+
repository.build_indexes
|
|
513
|
+
|
|
514
|
+
# Fast lookups using indexes
|
|
515
|
+
100.times do |i|
|
|
516
|
+
entity = repository.find_entity(
|
|
517
|
+
qualified_name: "action_schema.entity_#{i}"
|
|
518
|
+
)
|
|
519
|
+
end
|
|
520
|
+
----
|
|
521
|
+
|
|
522
|
+
=== Cache repositories
|
|
523
|
+
|
|
524
|
+
For frequently used schema sets, consider caching:
|
|
525
|
+
|
|
526
|
+
[source,ruby]
|
|
527
|
+
----
|
|
528
|
+
# Enable caching
|
|
529
|
+
Expressir::Express::Cache.cache_path = ".cache"
|
|
530
|
+
|
|
531
|
+
# First load parses and caches
|
|
532
|
+
repository = Expressir::Express::Parser.from_file("schema.exp")
|
|
533
|
+
|
|
534
|
+
# Subsequent loads use cache
|
|
535
|
+
repository = Expressir::Express::Parser.from_file("schema.exp")
|
|
536
|
+
----
|
|
537
|
+
|
|
538
|
+
=== Use LER packages
|
|
539
|
+
|
|
540
|
+
For production environments, use LER packages:
|
|
541
|
+
|
|
542
|
+
[source,ruby]
|
|
543
|
+
----
|
|
544
|
+
# Build package once (development)
|
|
545
|
+
repository = Expressir::Express::Parser.from_files(all_files)
|
|
546
|
+
repository.export_to_package("production.ler")
|
|
547
|
+
|
|
548
|
+
# Load package quickly (production)
|
|
549
|
+
repository = Expressir::Model::Repository.from_package("production.ler")
|
|
550
|
+
# Much faster than parsing source files
|
|
551
|
+
----
|
|
552
|
+
|
|
553
|
+
== Next steps
|
|
554
|
+
|
|
555
|
+
* link:search-engine.html[Search Engine] - Advanced querying capabilities
|
|
556
|
+
* link:formatting-schemas.html[Formatting Schemas] - Convert to EXPRESS
|
|
557
|
+
* link:../../pages/ler-packages.html[LER Packages] - Learn about binary packages
|
|
558
|
+
|
|
559
|
+
== Summary
|
|
560
|
+
|
|
561
|
+
The Repository class provides comprehensive schema management:
|
|
562
|
+
|
|
563
|
+
* Multiple ways to create repositories (parsing, packages, manual)
|
|
564
|
+
* Enumerable interface for Ruby-style collection operations
|
|
565
|
+
* Fast indexed lookups for entities and types
|
|
566
|
+
* Validation and consistency checking
|
|
567
|
+
* Rich statistics and analysis capabilities
|
|
568
|
+
* Dependency tracking and complexity scoring
|
|
569
|
+
* Export to manifests and LER packages
|
|
570
|
+
|
|
571
|
+
Key takeaways:
|
|
572
|
+
|
|
573
|
+
* Repository implements Enumerable for familiar collection methods
|
|
574
|
+
* Indexes provide fast lookups and are built automatically
|
|
575
|
+
* Statistics methods help understand schema characteristics
|
|
576
|
+
* Validation identifies issues before deployment
|
|
577
|
+
* LER packages offer faster loading for production use
|