diff --git a/README.md b/README.md index e57079c..4df7b16 100644 --- a/README.md +++ b/README.md @@ -275,7 +275,7 @@ It auto-deploys via GitHub Actions on every push to `main` that touches ## Examples -- [`reference-docs/examples/oceanrunner.cddal`](reference-docs/examples/oceanrunner.cddal) — the canonical powertype demo (40 entities, 20 classes) +- [`oceanrunner.cddal`](https://github.com/opencdd/data-oceanrunner/blob/main/reference-docs/examples/oceanrunner.cddal) (in data-oceanrunner) — the canonical powertype demo - [`reference-docs/202003-kagoshima-iec-def-sample.cddal`](reference-docs/202003-kagoshima-iec-def-sample.cddal) — minimal bare-`instance` form ## Standards background diff --git a/docs/src/content/docs/cddal-syntax.md b/docs/src/content/docs/cddal-syntax.md index cf23bad..7c62b5b 100644 --- a/docs/src/content/docs/cddal-syntax.md +++ b/docs/src/content/docs/cddal-syntax.md @@ -385,6 +385,6 @@ and property defined by IEC 61360-1. ## Further reading - [Normative CDDAL specification](https://github.com/opencdd/cddal-spec) -- [OceanRunner worked example](../reference-docs/examples/oceanrunner.cddal) +- [OceanRunner worked example](https://github.com/opencdd/data-oceanrunner/blob/main/reference-docs/examples/oceanrunner.cddal) - [Kagoshima bare-instance example](../reference-docs/202003-kagoshima-iec-def-sample.cddal) - [Parcel format guide](parcel-format.md) diff --git a/docs/src/content/docs/getting-started.md b/docs/src/content/docs/getting-started.md index a9a17b4..bdde34a 100644 --- a/docs/src/content/docs/getting-started.md +++ b/docs/src/content/docs/getting-started.md @@ -49,7 +49,7 @@ powertype pattern: ```ruby require "opencdd" -db = Opencdd::Cddal.parse_file("reference-docs/examples/oceanrunner.cddal") +db = Opencdd::Cddal.parse_file("oceanrunner.cddal") # from opencdd/data-oceanrunner # => # ``` @@ -259,5 +259,5 @@ end-to-end. See [cddal-syntax.md](cddal-syntax.md). structure, header layout, and round-trip semantics - **[architecture.md](architecture.md)** — how the gem is structured internally, where to extend it -- **The fixtures** at `reference-docs/examples/oceanrunner.cddal` +- **The fixture** in [opencdd/data-oceanrunner](https://github.com/opencdd/data-oceanrunner) (read it — it's heavily commented and exercises every feature) diff --git a/docs/src/content/docs/ontology.md b/docs/src/content/docs/ontology.md index cd416b0..6b6725c 100644 --- a/docs/src/content/docs/ontology.md +++ b/docs/src/content/docs/ontology.md @@ -138,7 +138,7 @@ The powertype pattern is modeled explicitly: ```ruby require "opencdd" -db = Opencdd::Cddal.parse_file("reference-docs/examples/oceanrunner.cddal") +db = Opencdd::Cddal.parse_file("oceanrunner.cddal") # from opencdd/data-oceanrunner engine_type = db.find_by_code("ORA200") single_diesel = db.find_by_code("ORA201") @@ -202,7 +202,7 @@ explicit. ## Worked example: OceanRunner -Read [`reference-docs/examples/oceanrunner.cddal`](../reference-docs/examples/oceanrunner.cddal) +Read [`oceanrunner.cddal` in data-oceanrunner](https://github.com/opencdd/data-oceanrunner/blob/main/reference-docs/examples/oceanrunner.cddal) alongside this section. It exercises: - **M2 layer**: the `meta-class MDC_C002 { ... }` declarations register diff --git a/reference-docs/examples/oceanrunner.cddal b/reference-docs/examples/oceanrunner.cddal deleted file mode 100644 index a42729a..0000000 --- a/reference-docs/examples/oceanrunner.cddal +++ /dev/null @@ -1,839 +0,0 @@ -# ============================================================================= -# OceanRunner Transmedium Vehicle — CDD worked example -# -# Demonstrates the full power-type modelling capability of CDD: -# -# * Multi-domain inheritance via is_case_of (Boat + Car + Submarine) -# * Conditional properties via CONDITION_DET -# * CATEGORICAL_CLASS option types (EngineType, InteriorPackage, HullFinish) -# * CLASS_REFERENCE data types for configurable product properties -# * Configured product subclasses via sub_class_selection -# * Individual serial-numbered unit instances -# -# Brand: OceanRunner (submersible boat-car manufacturer) -# Products: ORCA 30 (compact), ORCA 50 (full-size) -# -# Code allocation (OpenCDD house convention): -# — stem is unique per dictionary, T is the entity type: -# A class · B property · E value list · T value term · I individual · U unit -# OR = oceanrunner: ORA001 Vehicle … ORA200 EngineType (powertype), -# ORA300 OceanRunner (brand), ORA400 configured subclass, ORI0001 hull unit. -# Blocks: 0xx base hierarchy · 1xx transmedium · 2xx option types · -# 3xx brand & product lines · 4xx configured subclasses. -# IEC CDD allocates its own opaque blocks (AA, AB, AC, U, KE, KD, SA, C*) -# for its dictionaries; OpenCDD stems never collide with them. -# ============================================================================= - -import "https://cdd.opencdd.org/dictionaries/rec20-units.cddal" - -# ----------------------------------------------------------------------------- -# Aliases (re-declare built-ins for reader clarity) -# ----------------------------------------------------------------------------- - -alias code: MDC_P001_5 -alias preferred_name: MDC_P004 -alias short_name: MDC_P005 -alias definition: MDC_P006 -alias synonym: MDC_P007 -alias note: MDC_P008 -alias remark: MDC_P009 -alias superclass: MDC_P010 -alias class_type: MDC_P011 -alias is_case_of: MDC_P013 -alias applicable_properties: MDC_P014 -alias property_data_element_type: MDC_P020 -alias definition_class: MDC_P021 -alias data_type: MDC_P022 -alias unit: MDC_P041 -alias condition: MDC_P028 -alias sub_class_selection: MDC_P016 -alias imported_properties: MDC_P090 -alias enumerated_values: MDC_P044 - -# ----------------------------------------------------------------------------- -# Meta-class schema -# ----------------------------------------------------------------------------- - -meta-class MDC_C002 { - code - preferred_name - short_name - definition - note - remark - synonym - superclass - class_type - is_case_of - applicable_properties - sub_class_selection - imported_properties -} - -meta-class MDC_C003 { - code - preferred_name - short_name - definition - note - remark - property_data_element_type - definition_class - data_type - unit - condition -} - -meta-class MDC_C005 { - code - preferred_name - definition - note - remark - enumerated_values -} - -meta-class MDC_C009 { - code - preferred_name - short_name - definition - note - remark -} - -# ============================================================================= -# Base vehicle hierarchy -# ============================================================================= -# -# UNIVERSE -# └── Vehicle (ORA001) -# ├── Boat (ORA010) -# ├── Car (ORA020) -# └── Submarine (ORA030) -# ============================================================================= - -instance Vehicle < MDC_C002 { - code: ORA001 - preferred_name.en: "Vehicle" - preferred_name.fr: "Véhicule" - preferred_name.ja: "車両" - definition.en: "device that transports people or goods" - superclass: UNIVERSE - class_type: ITEM_CLASS - applicable_properties: { vehicle_length, vehicle_beam, vehicle_height, vehicle_weight, vehicle_capacity, propulsion_power, operating_range, fuel_capacity } -} - -instance vehicle_beam < MDC_C003 { - code: ORB004 - preferred_name.en: "vehicle beam" - definition.en: "maximum width of the vehicle at its widest point" - property_data_element_type: NON_DEPENDENT_P_DET - definition_class: Vehicle - data_type: REAL_TYPE - unit: metre -} - -instance vehicle_height < MDC_C003 { - code: ORB005 - preferred_name.en: "vehicle height" - definition.en: "height of the vehicle from waterline or ground to its highest fixed point" - property_data_element_type: NON_DEPENDENT_P_DET - definition_class: Vehicle - data_type: REAL_TYPE - unit: metre -} - -instance propulsion_power < MDC_C003 { - code: ORB006 - preferred_name.en: "propulsion power" - definition.en: "combined rated power of all propulsion units" - property_data_element_type: NON_DEPENDENT_P_DET - definition_class: Vehicle - data_type: REAL_TYPE - unit: kilowatt -} - -instance operating_range < MDC_C003 { - code: ORB007 - preferred_name.en: "operating range" - definition.en: "distance the vehicle can travel on one full load of fuel or energy" - property_data_element_type: NON_DEPENDENT_P_DET - definition_class: Vehicle - data_type: REAL_TYPE - unit: nautical_mile -} - -instance fuel_capacity < MDC_C003 { - code: ORB008 - preferred_name.en: "fuel capacity" - definition.en: "total volume of fuel or energy carrier stored on board" - property_data_element_type: NON_DEPENDENT_P_DET - definition_class: Vehicle - data_type: REAL_TYPE - unit: litre -} - -instance vehicle_length < MDC_C003 { - code: ORB001 - preferred_name.en: "vehicle length" - definition.en: "overall length of the vehicle, inclusive of all fixed structures" - property_data_element_type: NON_DEPENDENT_P_DET - definition_class: Vehicle - data_type: REAL_TYPE - unit: metre -} - -instance vehicle_weight < MDC_C003 { - code: ORB002 - preferred_name.en: "vehicle weight" - definition.en: "mass of the vehicle in ready-to-operate condition" - property_data_element_type: NON_DEPENDENT_P_DET - definition_class: Vehicle - data_type: REAL_TYPE - unit: kilogram -} - -instance vehicle_capacity < MDC_C003 { - code: ORB003 - preferred_name.en: "vehicle capacity" - definition.en: "maximum number of occupants the vehicle is type-approved to carry" - property_data_element_type: NON_DEPENDENT_P_DET - definition_class: Vehicle - data_type: INT_TYPE -} - -# ----------------------------------------------------------------------------- -# Boat -# ----------------------------------------------------------------------------- - -instance Boat < MDC_C002 { - code: ORA010 - preferred_name.en: "Boat" - definition.en: "vehicle that travels on the surface of water" - superclass: Vehicle - class_type: ITEM_CLASS - applicable_properties: { hull_length, draft, water_displacement, max_speed_knots, hull_form, berth_count } -} - -instance draft < MDC_C003 { - code: ORB013 - preferred_name.en: "draft" - definition.en: "depth of the hull below the waterline when fully laden" - property_data_element_type: NON_DEPENDENT_P_DET - definition_class: Boat - data_type: REAL_TYPE - unit: metre -} - -instance berth_count < MDC_C003 { - code: ORB014 - preferred_name.en: "berth count" - definition.en: "number of sleeping berths fitted below deck" - property_data_element_type: NON_DEPENDENT_P_DET - definition_class: Boat - data_type: INT_TYPE -} - -instance hull_form < MDC_C003 { - code: ORB015 - preferred_name.en: "hull form" - definition.en: "arrangement of hull bodies" - property_data_element_type: NON_DEPENDENT_P_DET - definition_class: Boat - data_type: ENUM_STRING_TYPE(hull_form_enum) -} - -instance hull_length < MDC_C003 { - code: ORB010 - preferred_name.en: "hull length" - definition.en: "overall length of the hull measured at the design waterline" - property_data_element_type: NON_DEPENDENT_P_DET - definition_class: Boat - data_type: REAL_TYPE - unit: metre -} - -instance water_displacement < MDC_C003 { - code: ORB011 - preferred_name.en: "water displacement" - definition.en: "mass of water displaced by the hull at rest in fresh water" - property_data_element_type: NON_DEPENDENT_P_DET - definition_class: Boat - data_type: REAL_TYPE - unit: kilogram -} - -instance max_speed_knots < MDC_C003 { - code: ORB012 - preferred_name.en: "maximum speed in knots" - definition.en: "maximum sustained speed on the water surface" - property_data_element_type: NON_DEPENDENT_P_DET - definition_class: Boat - data_type: REAL_TYPE - unit: knot -} - -# ----------------------------------------------------------------------------- -# Car -# ----------------------------------------------------------------------------- - -instance Car < MDC_C002 { - code: ORA020 - preferred_name.en: "Car" - definition.en: "vehicle that travels on paved roads" - superclass: Vehicle - class_type: ITEM_CLASS - applicable_properties: { wheelbase, ground_clearance, turning_circle, tire_count, seating_capacity, drive_layout, road_speed_max } -} - -instance ground_clearance < MDC_C003 { - code: ORB023 - preferred_name.en: "ground clearance" - definition.en: "distance between the lowest fixed point of the vehicle and the road surface" - property_data_element_type: NON_DEPENDENT_P_DET - definition_class: Car - data_type: REAL_TYPE - unit: metre -} - -instance seating_capacity < MDC_C003 { - code: ORB024 - preferred_name.en: "seating capacity" - definition.en: "number of seated occupants on the road" - property_data_element_type: NON_DEPENDENT_P_DET - definition_class: Car - data_type: INT_TYPE -} - -instance drive_layout < MDC_C003 { - code: ORB025 - preferred_name.en: "drive layout" - definition.en: "which wheels are driven by the powertrain on the road" - property_data_element_type: NON_DEPENDENT_P_DET - definition_class: Car - data_type: ENUM_STRING_TYPE(drive_layout_enum) -} - -instance turning_circle < MDC_C003 { - code: ORB026 - preferred_name.en: "turning circle" - definition.en: "diameter of the smallest full turn on a paved surface" - property_data_element_type: NON_DEPENDENT_P_DET - definition_class: Car - data_type: REAL_TYPE - unit: metre -} - -instance wheelbase < MDC_C003 { - code: ORB020 - preferred_name.en: "wheelbase" - definition.en: "distance between the centres of the front and rear wheel contact patches" - property_data_element_type: NON_DEPENDENT_P_DET - definition_class: Car - data_type: REAL_TYPE - unit: metre -} - -instance tire_count < MDC_C003 { - code: ORB021 - preferred_name.en: "tire count" - definition.en: "number of road-contacting tires fitted as standard equipment" - property_data_element_type: NON_DEPENDENT_P_DET - definition_class: Car - data_type: INT_TYPE -} - -instance road_speed_max < MDC_C003 { - code: ORB022 - preferred_name.en: "maximum road speed" - definition.en: "maximum sustained speed on a paved, level road" - property_data_element_type: NON_DEPENDENT_P_DET - definition_class: Car - data_type: REAL_TYPE - unit: kilometre_per_hour -} - -# ----------------------------------------------------------------------------- -# Submarine -# ----------------------------------------------------------------------------- - -instance Submarine < MDC_C002 { - code: ORA030 - preferred_name.en: "Submarine" - definition.en: "vehicle that travels fully submerged beneath the water surface" - superclass: Vehicle - class_type: ITEM_CLASS - applicable_properties: { max_depth_rating, test_depth, submerged_endurance, acoustic_signature, ballast_capacity } -} - -instance test_depth < MDC_C003 { - code: ORB032 - preferred_name.en: "test depth" - definition.en: "depth at which the pressure hull was certified by trial" - property_data_element_type: NON_DEPENDENT_P_DET - definition_class: Submarine - data_type: REAL_TYPE - unit: metre -} - -instance acoustic_signature < MDC_C003 { - code: ORB033 - preferred_name.en: "acoustic signature" - definition.en: "broadband radiated noise level at cruise, referenced to 1 micropascal at 1 metre" - property_data_element_type: NON_DEPENDENT_P_DET - definition_class: Submarine - data_type: REAL_TYPE - unit: decibel -} - -instance ballast_capacity < MDC_C003 { - code: ORB034 - preferred_name.en: "ballast capacity" - definition.en: "total volume of the ballast tanks" - property_data_element_type: NON_DEPENDENT_P_DET - definition_class: Submarine - data_type: REAL_TYPE - unit: litre -} - -instance max_depth_rating < MDC_C003 { - code: ORB030 - preferred_name.en: "maximum depth rating" - definition.en: "maximum depth at which the vehicle is certified to operate" - property_data_element_type: NON_DEPENDENT_P_DET - definition_class: Submarine - data_type: REAL_TYPE - unit: metre -} - -instance submerged_endurance < MDC_C003 { - code: ORB031 - preferred_name.en: "submerged endurance" - definition.en: "maximum time the vehicle can remain continuously submerged" - property_data_element_type: NON_DEPENDENT_P_DET - definition_class: Submarine - data_type: REAL_TYPE - unit: hour -} - -# ============================================================================= -# TransmediumVehicle — combines Boat + Car + Submarine via is_case_of -# ============================================================================= -# -# The TransmediumVehicle inherits ALL applicable properties from Boat, Car, -# and Submarine via the is_case_of relationship. It is simultaneously a boat, -# a car, and a submarine — without triple-inheriting a superclass chain. -# -# Vehicle (ORA001) -# ├── Boat (ORA010) ─┐ -# ├── Car (ORA020) ├── is_case_of -# ├── Submarine (ORA030) ─┘ -# └── TransmediumVehicle (ORA100) -# ============================================================================= - -instance TransmediumVehicle < MDC_C002 { - code: ORA100 - preferred_name.en: "Transmedium Vehicle" - definition.en: "vehicle capable of operating on the water surface, on paved roads, and fully submerged" - superclass: Vehicle - class_type: ITEM_CLASS - is_case_of: { Boat, Car, Submarine } - applicable_properties: { operating_mode, surface_water_speed, road_speed, submerged_speed, transition_time, crew_size } -} - -# --- Operating mode enumeration --- - -instance vehicle_mode_enum < MDC_C005 { - code: ORE001 - preferred_name.en: "vehicle operating mode" - definition.en: "enumeration of the operating regimes of a transmedium vehicle" - enumerated_values: { surface_water, road, underwater } -} - -instance hull_form_enum < MDC_C005 { - code: ORE002 - preferred_name.en: "hull form categories" - definition.en: "enumeration of the hull body arrangements" - enumerated_values: { Monohull, Catamaran, Trimaran } -} - -instance drive_layout_enum < MDC_C005 { - code: ORE003 - preferred_name.en: "drive layout categories" - definition.en: "enumeration of road drivetrain layouts" - enumerated_values: { Front_wheel_drive, Rear_wheel_drive, All_wheel_drive } -} - -instance navigation_package_enum < MDC_C005 { - code: ORE004 - preferred_name.en: "navigation package categories" - definition.en: "enumeration of navigation electronics suites" - enumerated_values: { Standard, Chartplotter, Full_avionics } -} - -# --- Driving property: operating_mode --- -# The value of this property determines which conditional speed property -# is active on the TransmediumVehicle. - -instance operating_mode < MDC_C003 { - code: ORB100 - preferred_name.en: "operating mode" - definition.en: "current operating regime of the transmedium vehicle" - property_data_element_type: NON_DEPENDENT_P_DET - definition_class: TransmediumVehicle - data_type: ENUM_STRING_TYPE(vehicle_mode_enum) -} - -# --- Conditional speed properties (CONDITION_DET) --- -# Each speed property is semantically meaningful only when the vehicle is -# in the corresponding operating_mode. The condition expression gates -# applicability. - -instance surface_water_speed < MDC_C003 { - code: ORB101 - preferred_name.en: "surface water speed" - definition.en: "maximum sustained speed while operating on the water surface" - property_data_element_type: CONDITION_DET - definition_class: TransmediumVehicle - data_type: REAL_TYPE - unit: knot - condition: operating_mode == surface_water -} - -instance road_speed < MDC_C003 { - code: ORB102 - preferred_name.en: "road speed" - definition.en: "maximum sustained speed while operating on a paved road" - property_data_element_type: CONDITION_DET - definition_class: TransmediumVehicle - data_type: REAL_TYPE - unit: kilometre_per_hour - condition: operating_mode == road -} - -instance submerged_speed < MDC_C003 { - code: ORB103 - preferred_name.en: "submerged speed" - definition.en: "maximum sustained speed while fully submerged" - property_data_element_type: CONDITION_DET - definition_class: TransmediumVehicle - data_type: REAL_TYPE - unit: knot - condition: operating_mode == underwater -} - -instance transition_time < MDC_C003 { - code: ORB104 - preferred_name.en: "transition time" - definition.en: "time to change between two operating modes, e.g. road to surface water" - property_data_element_type: NON_DEPENDENT_P_DET - definition_class: TransmediumVehicle - data_type: REAL_TYPE - unit: minute -} - -instance crew_size < MDC_C003 { - code: ORB105 - preferred_name.en: "crew size" - definition.en: "number of crew required to operate the vehicle" - property_data_element_type: NON_DEPENDENT_P_DET - definition_class: TransmediumVehicle - data_type: INT_TYPE -} - -# ============================================================================= -# Categorical option types (power-type modelling) -# ============================================================================= -# -# These CATEGORICAL_CLASSes are the "option menus" for configuring an -# OceanRunner product. Each one's subclasses are the selectable option values. -# -# EngineType (CATEGORICAL_CLASS) -# ├── SingleDieselEngine -# ├── TwinDieselEngine -# └── ElectricHybridEngine -# -# InteriorPackage (CATEGORICAL_CLASS) -# ├── StandardInterior -# └── PremiumInterior -# -# HullFinish (CATEGORICAL_CLASS) -# ├── GelcoatWhite -# └── CarbonBlack -# -# Power-type modelling note: each option value is itself a CLASS that can be -# further specialized. The CATEGORICAL_CLASS is a "powertype" — its instances -# are classes. -# ============================================================================= - -# --- EngineType --- - -instance EngineType < MDC_C002 { - code: ORA200 - preferred_name.en: "Engine Type" - definition.en: "categorical class whose subclasses enumerate the propulsion options available on an OceanRunner product" - superclass: Vehicle - class_type: CATEGORICAL_CLASS -} - -instance SingleDieselEngine < MDC_C002 { - code: ORA201 - preferred_name.en: "Single Diesel Engine" - definition.en: "single inline diesel powerplant driving one propeller and one axle" - superclass: EngineType - class_type: ITEM_CLASS -} - -instance TwinDieselEngine < MDC_C002 { - code: ORA202 - preferred_name.en: "Twin Diesel Engine" - definition.en: "paired diesel powerplants, one per hull sponson, driving dual propellers" - superclass: EngineType - class_type: ITEM_CLASS -} - -instance ElectricHybridEngine < MDC_C002 { - code: ORA203 - preferred_name.en: "Electric Hybrid Engine" - definition.en: "battery-electric primary propulsion with diesel range extender" - superclass: EngineType - class_type: ITEM_CLASS - applicable_properties: { battery_capacity, charging_power, electric_range } -} - -instance battery_capacity < MDC_C003 { - code: ORB307 - preferred_name.en: "battery capacity" - definition.en: "usable energy capacity of the propulsion battery pack" - property_data_element_type: NON_DEPENDENT_P_DET - definition_class: ElectricHybridEngine - data_type: REAL_TYPE - unit: kilowatt_hour -} - -instance charging_power < MDC_C003 { - code: ORB308 - preferred_name.en: "charging power" - definition.en: "maximum shore-power charging rate the battery pack accepts" - property_data_element_type: NON_DEPENDENT_P_DET - definition_class: ElectricHybridEngine - data_type: REAL_TYPE - unit: kilowatt -} - -instance electric_range < MDC_C003 { - code: ORB309 - preferred_name.en: "electric range" - definition.en: "distance the vessel covers on battery power alone at cruising speed" - property_data_element_type: NON_DEPENDENT_P_DET - definition_class: ElectricHybridEngine - data_type: REAL_TYPE - unit: kilometre -} - -# --- InteriorPackage --- - -instance InteriorPackage < MDC_C002 { - code: ORA210 - preferred_name.en: "Interior Package" - definition.en: "categorical class whose subclasses enumerate the interior trim levels" - superclass: Vehicle - class_type: CATEGORICAL_CLASS -} - -instance StandardInterior < MDC_C002 { - code: ORA211 - preferred_name.en: "Standard Interior" - definition.en: "marine-grade vinyl trim with analogue instrumentation" - superclass: InteriorPackage - class_type: ITEM_CLASS -} - -instance PremiumInterior < MDC_C002 { - code: ORA212 - preferred_name.en: "Premium Interior" - definition.en: "hand-stitched leather trim with glass cockpit display and rear bench seat" - superclass: InteriorPackage - class_type: ITEM_CLASS -} - -# --- HullFinish --- - -instance HullFinish < MDC_C002 { - code: ORA220 - preferred_name.en: "Hull Finish" - definition.en: "categorical class whose subclasses enumerate the hull surface treatments" - superclass: Vehicle - class_type: CATEGORICAL_CLASS -} - -instance GelcoatWhite < MDC_C002 { - code: ORA221 - preferred_name.en: "Gelcoat White" - definition.en: "standard white gelcoat hull with antifouling bottom paint" - superclass: HullFinish - class_type: ITEM_CLASS -} - -instance CarbonBlack < MDC_C002 { - code: ORA222 - preferred_name.en: "Carbon Black" - definition.en: "carbon-fibre reinforced hull with black epoxy topcoat" - superclass: HullFinish - class_type: ITEM_CLASS -} - -# ============================================================================= -# OceanRunner brand -# ============================================================================= -# -# TransmediumVehicle (ORA100) -# └── OceanRunner (ORA300) -# ├── ORCA 30 (ORA310) ← compact product line, 8 m hull -# └── ORCA 50 (ORA311) ← full-size product line, 12 m hull -# -# The OceanRunner brand defines four configuration properties that every -# product line inherits: engine_type, interior_package, hull_finish, and -# hull_identification_number. -# ============================================================================= - -instance OceanRunner < MDC_C002 { - code: ORA300 - preferred_name.en: "OceanRunner" - definition.en: "brand of transmedium vehicles manufactured by OceanRunner Marine" - superclass: TransmediumVehicle - class_type: ITEM_CLASS - applicable_properties: { engine_type, interior_package, hull_finish, hull_identification_number, navigation_package, warranty_period } -} - -# --- OceanRunner configuration properties --- -# Each CLASS_REFERENCE data_type constrains the value to be a subclass of -# the named CATEGORICAL_CLASS. - -instance engine_type < MDC_C003 { - code: ORB301 - preferred_name.en: "engine type" - definition.en: "propulsion configuration selected for this OceanRunner product" - property_data_element_type: NON_DEPENDENT_P_DET - definition_class: OceanRunner - data_type: CLASS_REFERENCE(EngineType) -} - -instance interior_package < MDC_C003 { - code: ORB302 - preferred_name.en: "interior package" - definition.en: "interior trim level selected for this OceanRunner product" - property_data_element_type: NON_DEPENDENT_P_DET - definition_class: OceanRunner - data_type: CLASS_REFERENCE(InteriorPackage) -} - -instance hull_finish < MDC_C003 { - code: ORB303 - preferred_name.en: "hull finish" - definition.en: "hull surface treatment selected for this OceanRunner product" - property_data_element_type: NON_DEPENDENT_P_DET - definition_class: OceanRunner - data_type: CLASS_REFERENCE(HullFinish) -} - -instance hull_identification_number < MDC_C003 { - code: ORB304 - preferred_name.en: "hull identification number" - definition.en: "unique serial number stamped on the hull at manufacture" - property_data_element_type: NON_DEPENDENT_P_DET - definition_class: OceanRunner - data_type: STRING_TYPE -} - -instance navigation_package < MDC_C003 { - code: ORB305 - preferred_name.en: "navigation package" - definition.en: "navigation electronics suite fitted as standard" - property_data_element_type: NON_DEPENDENT_P_DET - definition_class: OceanRunner - data_type: ENUM_STRING_TYPE(navigation_package_enum) -} - -instance warranty_period < MDC_C003 { - code: ORB306 - preferred_name.en: "warranty period" - definition.en: "duration of the structural hull warranty" - property_data_element_type: NON_DEPENDENT_P_DET - definition_class: OceanRunner - data_type: REAL_TYPE - unit: month -} - -# ============================================================================= -# Product lines -# ============================================================================= - -instance ORCA30 < MDC_C002 { - code: ORA310 - preferred_name.en: "ORCA 30" - short_name.en: "ORCA30" - definition.en: "compact transmedium vehicle, 8 m hull, 4 occupants, road-towed" - superclass: OceanRunner - class_type: ITEM_CLASS -} - -instance ORCA50 < MDC_C002 { - code: ORA311 - preferred_name.en: "ORCA 50" - short_name.en: "ORCA50" - definition.en: "full-size transmedium vehicle, 12 m hull, 6 occupants, standalone trailer" - superclass: OceanRunner - class_type: ITEM_CLASS -} - -# ============================================================================= -# Configured product subclass -# ============================================================================= -# -# ORCA30_TwinDiesel_Premium_CarbonBlack is a specific build configuration of -# the ORCA 30. Its sub_class_selection nails down the three CLASS_REFERENCE -# properties to specific categorical instances. -# -# This is power-type modelling in action: the categorical instances -# (TwinDieselEngine, PremiumInterior, CarbonBlack) are used as class -# discriminators that specialize the product class into a concrete variant. -# -# The configured subclass inherits ALL applicable properties from: -# ORCA30 → OceanRunner → TransmediumVehicle → Vehicle → UNIVERSE -# plus is_case_of: Boat + Car + Submarine -# ============================================================================= - -instance ORCA30_TwinDiesel_Premium_CarbonBlack < MDC_C002 { - code: ORA400 - preferred_name.en: "ORCA 30 Twin Diesel Premium Carbon Black" - short_name.en: "ORCA30-TD-P-CB" - definition.en: "ORCA 30 configured with twin diesel engines, premium interior, and carbon black hull" - superclass: ORCA30 - class_type: ITEM_CLASS - sub_class_selection: { TwinDieselEngine, PremiumInterior, CarbonBlack } -} - -# ============================================================================= -# Individual unit instance -# ============================================================================= -# -# A specific, physical, serial-numbered vehicle that rolled off the line. -# This is a leaf node — it has no further subclasses. Its property values -# are concrete data element values, not further specializations. -# -# The unit inherits the entire class hierarchy above it, including the -# is_case_of set (Boat + Car + Submarine) and the configured options -# (TwinDiesel + Premium + CarbonBlack). -# ============================================================================= - -instance ORCA30_UNIT_0001 < MDC_C002 { - code: ORI0001 - preferred_name.en: "ORCA 30 Hull #0001" - definition.en: "individual ORCA 30 Twin Diesel Premium Carbon Black, hull number ORCA30-TH-0001" - superclass: ORCA30_TwinDiesel_Premium_CarbonBlack - class_type: ITEM_CLASS - hull_identification_number: "ORCA30-TH-0001" - vehicle_weight: 4200 -} diff --git a/spec/cddal/per_entity_emit_spec.rb b/spec/cddal/per_entity_emit_spec.rb index e27b6bc..f459caa 100644 --- a/spec/cddal/per_entity_emit_spec.rb +++ b/spec/cddal/per_entity_emit_spec.rb @@ -3,7 +3,8 @@ require "spec_helper" RSpec.describe Opencdd::Cddal::Serializer do - let(:example_path) { REFERENCE_DOCS.join("examples/oceanrunner.cddal") } + before { require_fixture OCEANRUNNER } + let(:example_path) { OCEANRUNNER } let(:database) { Opencdd::Cddal.parse_file(example_path) } let(:serializer) { described_class.new(database) } diff --git a/spec/cddal_spec.rb b/spec/cddal_spec.rb index 397a037..6ed911f 100644 --- a/spec/cddal_spec.rb +++ b/spec/cddal_spec.rb @@ -4,7 +4,8 @@ require "tempfile" RSpec.describe Opencdd::Cddal do - let(:example_path) { REFERENCE_DOCS.join("examples/oceanrunner.cddal") } + before { require_fixture OCEANRUNNER } + let(:example_path) { OCEANRUNNER } let(:database) { described_class.parse_file(example_path) } describe ".parse_file" do @@ -173,14 +174,14 @@ RSpec.describe "Opencdd::Database#semantically_equal?" do it "compares two databases parsed from the same source as equal" do - path = REFERENCE_DOCS.join("examples/oceanrunner.cddal") + path = OCEANRUNNER a = Opencdd::Cddal.parse_file(path) b = Opencdd::Cddal.parse_file(path) expect(a.semantically_equal?(b)).to be(true) end it "detects inequality when one database is missing entities" do - path = REFERENCE_DOCS.join("examples/oceanrunner.cddal") + path = OCEANRUNNER a = Opencdd::Cddal.parse_file(path) b = Opencdd::Database.new expect(a.semantically_equal?(b)).to be(false) diff --git a/spec/composition_tree_spec.rb b/spec/composition_tree_spec.rb index b9ccc9c..078f9b1 100644 --- a/spec/composition_tree_spec.rb +++ b/spec/composition_tree_spec.rb @@ -3,7 +3,8 @@ require "spec_helper" RSpec.describe Opencdd::CompositionTree do - let(:oceanrunner_db) { Opencdd::Cddal.parse_file(REFERENCE_DOCS.join("examples/oceanrunner.cddal")) } + before { require_fixture OCEANRUNNER } + let(:oceanrunner_db) { Opencdd::Cddal.parse_file(OCEANRUNNER) } describe Opencdd::CompositionTree::Node do it "is a Struct exposing entity and children" do diff --git a/spec/effective_properties_spec.rb b/spec/effective_properties_spec.rb index 4c6369b..809a38c 100644 --- a/spec/effective_properties_spec.rb +++ b/spec/effective_properties_spec.rb @@ -3,7 +3,8 @@ require "spec_helper" RSpec.describe Opencdd::EffectiveProperties do - let(:database) { Opencdd::Cddal.parse_file(REFERENCE_DOCS.join("examples/oceanrunner.cddal")) } + before { require_fixture OCEANRUNNER } + let(:database) { Opencdd::Cddal.parse_file(OCEANRUNNER) } describe "#for" do it "returns a Result that exposes properties and sources" do diff --git a/spec/entity_diff_spec.rb b/spec/entity_diff_spec.rb index 62ace5c..c3240a4 100644 --- a/spec/entity_diff_spec.rb +++ b/spec/entity_diff_spec.rb @@ -123,7 +123,8 @@ def build_entity(properties) end describe "with real entities from the oceanrunner fixture" do - let(:database) { Opencdd::Cddal.parse_file(REFERENCE_DOCS.join("examples/oceanrunner.cddal")) } + before { require_fixture OCEANRUNNER } + let(:database) { Opencdd::Cddal.parse_file(OCEANRUNNER) } let(:klass) { database.classes.first } it "produces an empty diff between an entity and itself" do diff --git a/spec/exporters/per_entity_json_spec.rb b/spec/exporters/per_entity_json_spec.rb index 97da7af..8100611 100644 --- a/spec/exporters/per_entity_json_spec.rb +++ b/spec/exporters/per_entity_json_spec.rb @@ -4,7 +4,8 @@ require "json" RSpec.describe Opencdd::Exporters::Json do - let(:example_path) { REFERENCE_DOCS.join("examples/oceanrunner.cddal") } + before { require_fixture OCEANRUNNER } + let(:example_path) { OCEANRUNNER } let(:database) { Opencdd::Cddal.parse_file(example_path) } let(:exporter) { described_class.new } diff --git a/spec/exporters_spec.rb b/spec/exporters_spec.rb index 5ce5286..efa9dcc 100644 --- a/spec/exporters_spec.rb +++ b/spec/exporters_spec.rb @@ -5,7 +5,8 @@ require "yaml" RSpec.describe Opencdd::Exporters do - let(:database) { Opencdd::Cddal.parse_file(REFERENCE_DOCS.join("examples/oceanrunner.cddal")) } + before { require_fixture OCEANRUNNER } + let(:database) { Opencdd::Cddal.parse_file(OCEANRUNNER) } describe Opencdd::Exporters::Json do it "produces parseable JSON with class, property, and value_list nodes" do diff --git a/spec/import_pipeline_spec.rb b/spec/import_pipeline_spec.rb index a280eec..2663955 100644 --- a/spec/import_pipeline_spec.rb +++ b/spec/import_pipeline_spec.rb @@ -130,7 +130,7 @@ def write_parcel(database, parcel_id:, **opts) end describe "scenario 4: cddal → parcel → cddal (round-trip)" do - let(:source_cddal) { Opencdd::Cddal.parse_file(REFERENCE_DOCS.join("examples/oceanrunner.cddal")) } + let(:source_cddal) { Opencdd::Cddal.parse_file(OCEANRUNNER) } it "preserves semantic equality through a parcel detour" do parcel_path = write_parcel(source_cddal, parcel_id: "OCDDRT4") @@ -172,7 +172,7 @@ def write_parcel(database, parcel_id:, **opts) end describe "scenario 6: import cddal into an existing Database (upsert)" do - let(:source_cddal) { Opencdd::Cddal.parse_file(REFERENCE_DOCS.join("examples/oceanrunner.cddal")) } + let(:source_cddal) { Opencdd::Cddal.parse_file(OCEANRUNNER) } it "merges a CDDAL-parsed database into an existing one" do target = Opencdd::Database.new diff --git a/spec/model/entity_store_spec.rb b/spec/model/entity_store_spec.rb index 6ce937a..b3b828f 100644 --- a/spec/model/entity_store_spec.rb +++ b/spec/model/entity_store_spec.rb @@ -4,7 +4,7 @@ require "tmpdir" RSpec.describe "Per-entity YAML persistence", :yaml do - let(:oceanrunner) { Opencdd::Cddal.parse_file(REFERENCE_DOCS.join("examples/oceanrunner.cddal")) } + let(:oceanrunner) { Opencdd::Cddal.parse_file(OCEANRUNNER) } describe "Database#save_to_directory / load_from_directory" do it "writes one YAML file per entity (via lutaml-store DatabaseStore)" do diff --git a/spec/model/yaml_model_spec.rb b/spec/model/yaml_model_spec.rb index e66ac31..d1c5acb 100644 --- a/spec/model/yaml_model_spec.rb +++ b/spec/model/yaml_model_spec.rb @@ -8,7 +8,7 @@ # wire-format keys (MDC_P004, MDC_P010). RSpec.describe "CDD-native YAML model", :yaml do - let(:oceanrunner) { Opencdd::Cddal.parse_file(REFERENCE_DOCS.join("examples/oceanrunner.cddal")) } + let(:oceanrunner) { Opencdd::Cddal.parse_file(OCEANRUNNER) } describe "Database#to_yaml → Database.from_yaml round-trip" do it "produces valid YAML" do diff --git a/spec/parcel/round_trip_matrix_spec.rb b/spec/parcel/round_trip_matrix_spec.rb index 04a163f..ae5fd23 100644 --- a/spec/parcel/round_trip_matrix_spec.rb +++ b/spec/parcel/round_trip_matrix_spec.rb @@ -12,7 +12,7 @@ # the canonical model. RSpec.describe "Round-trip matrix", :round_trip do - let(:oceanrunner_path) { REFERENCE_DOCS.join("examples/oceanrunner.cddal") } + let(:oceanrunner_path) { OCEANRUNNER } let(:kagoshima_path) { REFERENCE_DOCS.join("202003-kagoshima-iec-def-sample.cddal") } let(:oceanrunner) { Opencdd::Cddal.parse_file(oceanrunner_path.to_s) } diff --git a/spec/poi_spec.rb b/spec/poi_spec.rb new file mode 100644 index 0000000..74095e1 --- /dev/null +++ b/spec/poi_spec.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true + +require "spec_helper" + +# The POI dictionary carries the verified global spot registry that +# data-poi's pipeline generates (DBpedia harvest, per-entry Wikipedia +# verification, Wikidata enrichment). Codes POInn country blocks. +POI = public_fixture("data-poi", "poi.cddal") + +RSpec.describe "POI registry dictionary" do + before { require_fixture POI } + let(:db) { Opencdd::Cddal.parse_file(POI) } + + it "loads every entity" do + expect(db.entities.size).to eq(742) + end + + it "carries six hundred plus registered spots" do + indiv = db.entities.map(&:code).grep(/\APOI/) + expect(indiv.size).to be > 600 + end + + it "enumerates thirty countries" do + country = db.find_by_code("POA010") + expect(db.instances_of(country).map(&:code).size).to eq(30) + end + + it "uses PO codes throughout" do + prefixes = db.entities.map(&:code).map { |c| c.to_s[/\A[A-Z]+/] }.uniq.sort + expect(prefixes).to eq(%w[POA POB POI]) + end + + it "binds coordinates and cities on verified individuals" do + spot = db.entities.find { |e| e.code.to_s.start_with?("POI") && e.respond_to?(:read_field) } + with_coords = db.entities.count do |e| + raw = e.respond_to?(:properties) && e.properties.key?("latitude") + raw + end + expect(with_coords).to be > 350 + end +end diff --git a/spec/powertype_spec.rb b/spec/powertype_spec.rb index 40aaf44..6867c04 100644 --- a/spec/powertype_spec.rb +++ b/spec/powertype_spec.rb @@ -16,7 +16,7 @@ # └── ElectricHybridEngine (ITEM_CLASS) — categorical instance RSpec.describe "Powertype API (4-layer ontology)", :cddal do - let(:db) { Opencdd::Cddal.parse_file(REFERENCE_DOCS.join("examples/oceanrunner.cddal")) } + let(:db) { Opencdd::Cddal.parse_file(OCEANRUNNER) } let(:engine_type) { db.find_by_code("ORA200") } let(:interior_package) { db.find_by_code("ORA210") } diff --git a/spec/scenicspots_spec.rb b/spec/scenicspots_spec.rb index 072dbbc..bf4ce2b 100644 --- a/spec/scenicspots_spec.rb +++ b/spec/scenicspots_spec.rb @@ -13,7 +13,7 @@ let(:db) { Opencdd::Cddal.parse_file(SCENICSPOTS) } it "loads every entity" do - expect(db.entities.size).to eq(805) + expect(db.entities.size).to eq(164) end describe "powertypes" do @@ -125,9 +125,9 @@ expect(inari.preferred_name(:ja)).to eq("伏見稲荷大社") end - it "carries a bulk registry of two hundred plus spots across ten countries" do + it "is the curated learning dictionary — the bulk registry lives in data-poi" do indiv = db.entities.map(&:code).grep(/\ASPI/) - expect(indiv.size).to be > 400 + expect(indiv.size).to eq(26) expect(db.find_by_code("SPA019").preferred_name("zh-CN")).to eq("中國") end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index caaa9a6..0c10c60 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -15,11 +15,30 @@ NUTS_XLSX = PRIVATE_REFERENCE_DOCS.join("parcelmaker/(ParcelMaker)example_nut.xlsx") KAGOSHIMA_CDDAL = REFERENCE_DOCS.join("202003-kagoshima-iec-def-sample.cddal") LEGACY_XLS_DIR = PRIVATE_REFERENCE_DOCS.join("export_CDD_IEC62368 in EXCEL format") -# Generated demo dictionaries (scenicspots, antiques) are data, not -# implementation: they are harvested, verified, and machine-rewritten -# by data-private's pipeline, so they live in that repo. -SCENICSPOTS = PRIVATE_REFERENCE_DOCS.join("examples/scenicspots.cddal") -ANTIQUES = PRIVATE_REFERENCE_DOCS.join("examples/antiques.cddal") + +# Dictionary fixtures are DATA and live in their own repositories +# (data-oceanrunner, data-scenicspots, data-antiques, data-poi). +# Resolution order: sibling checkout, then a cached download from the +# public repository (so CI stays covered without sibling checkouts). +def public_fixture(repo, name) + local = Pathname.new(File.expand_path("../../#{repo}/reference-docs/examples/#{name}", __dir__)) + return local if local.exist? + + require "open-uri" + cache = Pathname.new(Dir.tmpdir) / "opencdd-fixtures" / repo / name + return cache if cache.exist? + + cache.dirname.mkpath + source = "https://raw.githubusercontent.com/opencdd/#{repo}/main/reference-docs/examples/#{name}" + cache.write(URI.open(source).read) + cache +rescue StandardError, OpenURI::HTTPError + Pathname.new("/nonexistent/#{repo}/#{name}") +end + +OCEANRUNNER = public_fixture("data-oceanrunner", "oceanrunner.cddal") +SCENICSPOTS = public_fixture("data-scenicspots", "scenicspots.cddal") +ANTIQUES = public_fixture("data-antiques", "antiques.cddal") LEGACY_SINGLE_XLS = PRIVATE_REFERENCE_DOCS.join("export_CDD_ISO ICS in EXCEL format.xls") module FixtureGuard diff --git a/spec/validator/class_reference_rule_spec.rb b/spec/validator/class_reference_rule_spec.rb index 946a510..3bf60ea 100644 --- a/spec/validator/class_reference_rule_spec.rb +++ b/spec/validator/class_reference_rule_spec.rb @@ -156,7 +156,7 @@ def context_for(property, data_type_override = nil) # The OceanRunner fixture exercises CLASS_REFERENCE extensively # (engine_type, interior_package, hull_finish). All declared # Property CLASS_REFERENCEs point to valid categorical classes. - let(:ocean) { Opencdd::Cddal.parse_file(REFERENCE_DOCS.join("examples/oceanrunner.cddal")) } + let(:ocean) { Opencdd::Cddal.parse_file(OCEANRUNNER) } it "R16 produces no errors on valid OceanRunner data" do errors = Opencdd::Validator.run(ocean) diff --git a/spec/visitor_spec.rb b/spec/visitor_spec.rb index 12ad553..ad94116 100644 --- a/spec/visitor_spec.rb +++ b/spec/visitor_spec.rb @@ -3,7 +3,8 @@ require "spec_helper" RSpec.describe Opencdd::Visitor do - let(:database) { Opencdd::Cddal.parse_file(REFERENCE_DOCS.join("examples/oceanrunner.cddal")) } + before { require_fixture OCEANRUNNER } + let(:database) { Opencdd::Cddal.parse_file(OCEANRUNNER) } describe "#visit_database" do it "visits every class, property, and value_list in the database" do