Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,13 @@ require "opencdd"
db = Opencdd::Database.load("downloads/iec63213")

# Find a class and walk its hierarchy
vehicle = db.find_by_code("AAA001")
vehicle = db.find_by_code("ORA001")
puts vehicle.preferred_name # => "Vehicle"
puts vehicle.children.map(&:code) # => ["AAA010", "AAA020", "AAA030", ...]
puts vehicle.children.map(&:code) # => ["ORA010", "ORA020", "ORA030", ...]
puts vehicle.effective_properties.map(&:code) # inherited + declared properties

# Powertype API: what configuration options does EngineType offer?
engine_type = db.find_by_code("AAA200")
engine_type = db.find_by_code("ORA200")
engine_type.powertype? # => true
db.instances_of(engine_type).map(&:preferred_name)
# => ["Single Diesel Engine", "Twin Diesel Engine", "Electric Hybrid Engine"]
Expand Down Expand Up @@ -146,8 +146,8 @@ M2 Meta-model The meta-classes: Class, Property, Unit, ValueList,
Modeled as Opencdd::MetaClass instances.
Fixed set per the standard.

M1 Model The dictionary content: AAA001 "Vehicle",
AAAP001 "vehicle length", etc. Instances of M2
M1 Model The dictionary content: ORA001 "Vehicle",
ORB001 "vehicle length", etc. Instances of M2
meta-classes. Modeled as Opencdd::Entity
subclasses (Klass, Property, Unit, ...).

Expand Down
8 changes: 4 additions & 4 deletions docs/src/content/docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -205,17 +205,17 @@ with semantic names (not wire-format keys):

```yaml
---
irdi: AAA001
irdi: ORA001
type: class
code: AAA001
code: ORA001
preferred_name:
en: Vehicle
fr: Véhicule
class_type: ITEM_CLASS
superclass: UNIVERSE
applicable_properties:
- AAAP001
- AAAP002
- ORB001
- ORB002
```

Conversion between the YAML model and the existing Entity model is via
Expand Down
20 changes: 10 additions & 10 deletions docs/src/content/docs/cddal-syntax.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ meta-class MDC_C002 {
}

instance Vehicle < MDC_C002 {
code: AAA001
code: ORA001
preferred_name.en: "Vehicle"
class_type: ITEM_CLASS
}
Expand All @@ -43,7 +43,7 @@ Parse it:

```ruby
db = Opencdd::Cddal.parse(source)
db.find_by_code("AAA001").preferred_name # => "Vehicle"
db.find_by_code("ORA001").preferred_name # => "Vehicle"
```

## Lexical structure
Expand Down Expand Up @@ -86,7 +86,7 @@ Usually you don't write these — the runtime provides defaults.

```cddal
instance Vehicle < MDC_C002 {
code: AAA001
code: ORA001
preferred_name.en: "Vehicle"
preferred_name.fr: "Véhicule"
definition.en: "device that transports people or goods"
Expand All @@ -108,7 +108,7 @@ Anonymous form (no `<`):

```cddal
instance MDC_C002 {
code: AAA001
code: ORA001
preferred_name.en: "Vehicle"
}
```
Expand Down Expand Up @@ -149,7 +149,7 @@ Form: `<identifier-or-alias>[:.<language-tag>]: <value>`
preferred_name.en: "Vehicle" # language-tagged (English)
preferred_name.fr: "Véhicule" # language-tagged (French)
superclass: Vehicle # symbolic reference
code: AAA001 # short code
code: ORA001 # short code
data_type: REAL_TYPE # type identifier
applicable_properties: { vehicle_length, vehicle_weight }
condition: operating_mode == surface_water
Expand Down Expand Up @@ -179,8 +179,8 @@ Three equivalent forms for references:

```cddal
superclass: Vehicle # by symbolic name
superclass: AAA001 # by short code
superclass: 0112/2///61360_4#AAA001 # by full IRDI
superclass: ORA001 # by short code
superclass: 0112/2///OCEANRUNNER#ORA001 # by full IRDI
```

Resolution order: full IRDI → symbolic name → code.
Expand Down Expand Up @@ -311,7 +311,7 @@ fetcher = Opencdd::Cddal::Fetcher::NetHttp.new(offline: true)
Every entity created from CDDAL carries a `source_location`:

```ruby
entity = db.find_by_code("AAA001")
entity = db.find_by_code("ORA001")
entity.source_location.file # => "/path/to/file.cddal"
entity.source_location.line # => 42
```
Expand Down Expand Up @@ -349,15 +349,15 @@ meta-class MDC_C002 {

# 3. Instance declarations (the meat)
instance Vehicle < MDC_C002 {
code: AAA001
code: ORA001
preferred_name.en: "Vehicle"
superclass: UNIVERSE
class_type: ITEM_CLASS
applicable_properties: { vehicle_length }
}

instance vehicle_length < MDC_C003 {
code: AAAP001
code: ORB001
preferred_name.en: "vehicle length"
definition_class: Vehicle
data_type: REAL_TYPE
Expand Down
40 changes: 20 additions & 20 deletions docs/src/content/docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,22 +63,22 @@ regardless of which format the data came from.

```ruby
# By IRDI (canonical key)
db.find(Opencdd::IRDI.parse("0112/2///61360_4#AAA001"))
db.find(Opencdd::IRDI.parse("0112/2///OCEANRUNNER#ORA001"))

# By short code (most common)
db.find_by_code("AAA001") # => #<Opencdd::Klass AAA001 "Vehicle">
db.find_by_code("ORA001") # => #<Opencdd::Klass ORA001 "Vehicle">

# By preferred name
db.find_by_name("Boat", type: :class) # => #<Opencdd::Klass AAA010>
db.find_by_name("Boat", type: :class) # => #<Opencdd::Klass ORA010>
```

### Type-partitioned accessors

```ruby
db.classes # => [#<Klass AAA001>, #<Klass AAA010>, ...]
db.properties # => [#<Property AAAP001>, ...]
db.classes # => [#<Klass ORA001>, #<Klass ORA010>, ...]
db.properties # => [#<Property ORB001>, ...]
db.units # => [#<Unit ...>]
db.value_lists # => [#<ValueList AAAE001>]
db.value_lists # => [#<ValueList ORE001>]
db.value_terms # => [#<ValueTerm ...>]
db.relations # => [#<Relation ...>]
db.view_controls # => [#<ViewControl ...>]
Expand All @@ -88,28 +88,28 @@ db.entities # => everything flat
### Class hierarchy

```ruby
vehicle = db.find_by_code("AAA001")
vehicle = db.find_by_code("ORA001")
vehicle.parent_irdi # => nil (root)
vehicle.children.map(&:code) # => ["AAA010", "AAA020", "AAA030", "AAA100"]
vehicle.children.map(&:code) # => ["ORA010", "ORA020", "ORA030", "ORA100"]
vehicle.ancestors # => [vehicle] (root)
vehicle.descendants.map(&:code).size # => 19

boat = db.find_by_code("AAA010")
boat.parent.code # => "AAA001"
boat = db.find_by_code("ORA010")
boat.parent.code # => "ORA001"
boat.parent.preferred_name # => "Vehicle"
```

### Properties on a class

```ruby
vehicle.properties_on_class(db).map(&:code) # declared only
# => ["AAAP001", "AAAP002", "AAAP003"]
# => ["ORB001", "ORB002", "ORB003"]

vehicle.effective_properties.map(&:code) # inherited + declared
# => ["AAAP001", "AAAP002", "AAAP003"]
# => ["ORB001", "ORB002", "ORB003"]

# Walks superclass + is_case_of chains, cycle-safe
transmedium = db.find_by_code("AAA100")
transmedium = db.find_by_code("ORA100")
transmedium.effective_properties.map(&:preferred_name).size
# => 14 (3 own + 3 from Vehicle + 3 from Boat + 3 from Car + 2 from Submarine)
```
Expand All @@ -120,23 +120,23 @@ This is where CDD gets interesting. A `CATEGORICAL_CLASS` is a
*class whose instances are themselves classes*.

```ruby
engine_type = db.find_by_code("AAA200")
engine_type = db.find_by_code("ORA200")
engine_type.powertype? # => true

# The powertype instances — EngineType's subclasses that ARE its
# categorical options
engine_type.categorical_instances(db).map(&:code)
# => ["AAA201", "AAA202", "AAA203"] # SingleDiesel, TwinDiesel, ElectricHybrid
# => ["ORA201", "ORA202", "ORA203"] # SingleDiesel, TwinDiesel, ElectricHybrid

# Database-driven entry point (accepts Klass, IRDI, or code String)
db.instances_of(engine_type).map(&:preferred_name)
# => ["Single Diesel Engine", "Twin Diesel Engine", "Electric Hybrid Engine"]

# Predicate: is this value a valid option for CLASS_REFERENCE(EngineType)?
single_diesel = db.find_by_code("AAA201")
single_diesel = db.find_by_code("ORA201")
db.valid_class_reference?(engine_type, single_diesel) # => true

vehicle = db.find_by_code("AAA001")
vehicle = db.find_by_code("ORA001")
db.valid_class_reference?(engine_type, vehicle) # => false
```

Expand Down Expand Up @@ -210,11 +210,11 @@ Opencdd::Exporters::Mermaid.new.to_diagram(db) # Mermaid markdown
```ruby
errors = Opencdd::Validator.run(db)
errors.first.rule # => "R08"
errors.first.entity_irdi.to_s # => "0112/2///61360_4#AAA001"
errors.first.entity_irdi.to_s # => "0112/2///OCEANRUNNER#ORA001"
errors.first.message # => "R08: reference \"UNIVERSE\" does not resolve..."

# Rule predicates — usable directly from the editor's live validator
Opencdd::Validator.irdi_well_formed?("AAA001") # => true
Opencdd::Validator.irdi_well_formed?("ORA001") # => true
Opencdd::Validator.irdi_well_formed?("garbage") # => true (IRDI is permissive)
Opencdd::Validator.class_hierarchy_acyclic?(db) # => true
```
Expand All @@ -239,7 +239,7 @@ import "./engines.cddal" as engines # qualified
from "./colors.cddal" import { Red, Blue } # selective

instance MyProduct < MDC_C002 {
code: AAA999
code: ORA999
superclass: Vehicle
engine_type: CLASS_REFERENCE(EngineType)
color: Red
Expand Down
16 changes: 8 additions & 8 deletions docs/src/content/docs/model/yaml-persistence.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ translation_languages:
- fr
- ja
entities:
- irdi: AAA001
- irdi: ORA001
type: class
code: AAA001
code: ORA001
preferred_name:
en: Vehicle
fr: Véhicule
Expand All @@ -41,15 +41,15 @@ entities:
class_type: ITEM_CLASS
superclass: UNIVERSE
applicable_properties:
- AAAP001
- AAAP002
- irdi: AAAP001
- ORB001
- ORB002
- irdi: ORB001
type: property
code: AAAP001
code: ORB001
preferred_name:
en: vehicle length
data_type: REAL_TYPE
definition_class: AAA001
definition_class: ORA001
unit: metre
property_data_element_type: NON_DEPENDENT_P_DET
```
Expand Down Expand Up @@ -143,7 +143,7 @@ db2 = Opencdd::Database.from_yaml(yaml)
db.entities.size == db2.entities.size # true
db.classes.size == db2.classes.size # true
db.properties.size == db2.properties.size # true
db2.find_by_code("AAA200").powertype? # true
db2.find_by_code("ORA200").powertype? # true
```

The YAML round-trip preserves entity count, types, multilingual
Expand Down
24 changes: 12 additions & 12 deletions docs/src/content/docs/ontology.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ ISO/IEC 11179, but with a twist.
│ M1 Model The dictionary content — instances of M2 │
│ ↓ meta-classes. This is what authors write. │
│ │
│ AAA001 "Vehicle" (instance of Class) │
│ AAAP001 "vehicle length" (instance of Property)│
│ ORA001 "Vehicle" (instance of Class) │
│ ORB001 "vehicle length" (instance of Property)│
│ UAC001 "metre" (instance of Unit) │
│ │
│ Modeled by: Opencdd::Entity subclasses │
Expand Down Expand Up @@ -79,24 +79,24 @@ Concretely, in the OceanRunner fixture:

```cddal
instance EngineType < MDC_C002 {
code: AAA200
code: ORA200
class_type: CATEGORICAL_CLASS
}

instance SingleDieselEngine < MDC_C002 {
code: AAA201
code: ORA201
superclass: EngineType
class_type: ITEM_CLASS
}

instance TwinDieselEngine < MDC_C002 {
code: AAA202
code: ORA202
superclass: EngineType
class_type: ITEM_CLASS
}

instance ElectricHybridEngine < MDC_C002 {
code: AAA203
code: ORA203
superclass: EngineType
class_type: ITEM_CLASS
}
Expand All @@ -114,7 +114,7 @@ IRDI as a *value* of a property whose type is `CLASS_REFERENCE(EngineType)`:

```cddal
instance engine_type < MDC_C003 {
code: AAAP200
code: ORB200
definition_class: OceanRunner
data_type: CLASS_REFERENCE(EngineType)
}
Expand All @@ -125,7 +125,7 @@ categorical instances:

```cddal
instance ORCA30_TwinDiesel_Premium_CarbonBlack < MDC_C002 {
code: BBB100
code: ORA400
superclass: ORCA30
sub_class_selection: { TwinDieselEngine, PremiumInterior, CarbonBlackHull }
}
Expand All @@ -140,23 +140,23 @@ require "opencdd"

db = Opencdd::Cddal.parse_file("reference-docs/examples/oceanrunner.cddal")

engine_type = db.find_by_code("AAA200")
single_diesel = db.find_by_code("AAA201")
engine_type = db.find_by_code("ORA200")
single_diesel = db.find_by_code("ORA201")

# Predicate: is this a categorical (powertype) class?
engine_type.powertype? # => true

# What are its instances?
engine_type.categorical_instances(db).map(&:code)
# => ["AAA201", "AAA202", "AAA203"]
# => ["ORA201", "ORA202", "ORA203"]

# Or from the database side:
db.instances_of(engine_type).map(&:preferred_name)
# => ["Single Diesel Engine", "Twin Diesel Engine", "Electric Hybrid Engine"]

# Validate a CLASS_REFERENCE value
db.valid_class_reference?(engine_type, single_diesel) # => true
db.valid_class_reference?(engine_type, "AAA001") # => false (Vehicle isn't an EngineType instance)
db.valid_class_reference?(engine_type, "ORA001") # => false (Vehicle isn't an EngineType instance)
```

The R16 validator rule enforces `CLASS_REFERENCE` constraints:
Expand Down
4 changes: 2 additions & 2 deletions lib/opencdd/cddal/builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ def resolve_meta_class(ref)
def build_properties(decl)
# Resolve the meta-class once so per-assignment code-alias
# resolution can be context-aware. Without this, a CDDAL
# `code: AAAP001` on a Property stores the value under
# `code: ORB001` on a Property stores the value under
# MDC_P001_5 (the Class code) — Parcel readers look for
# MDC_P001_6 (the Property code) and miss it, dropping the
# entity on round-trip.
Expand Down Expand Up @@ -225,7 +225,7 @@ def resolve_meta_class_code(ref)
# canonical code property), and the resolved ID is one of the
# MDC_P001_X code variants for a *different* meta-class,
# we redirect to the canonical. This makes the CDDAL `code`
# alias context-aware: writing `code: AAA001` on a Property
# alias context-aware: writing `code: ORA001` on a Property
# stores the value under MDC_P001_6, not MDC_P001_5.
def resolve_property_id(name, canonical_code_pid: nil)
s = name.to_s
Expand Down
Loading
Loading