// Vocabulary for the Draw.io file format
vocabulary <http://flandersmake.be/cdf/vocabulary/drawio#> as drawio {

	extends <http://flandersmake.be/cdf/vocabulary/object_diagram#> as object_diagram
	extends <http://flandersmake.be/cdf/vocabulary/acyclic#> as acyclic
	extends <http://flandersmake.be/cdf/vocabulary/dict#> as dict
//	extends <http://flandersmake.be/cdf/vocabulary/ordered#> as ordered
	extends <http://www.w3.org/2001/XMLSchema#> as xsd

	aspect element :> object_diagram:Object []
	
	// Cells and Pages have a GUID generated by drawio.
	aspect elementWithDrawioId :> element [
		restricts scalar property hasDrawioId to exactly 1
	]
	scalar property hasDrawioId [
		domain elementWithDrawioId
		range xsd:string
		functional
	]

	// All cells are vertices or edges, except for:
	//   (1) The root cell of a page
	//   (2) The cells that represent layers (direct children of the root cell)
	aspect AbstractCell :> elementWithDrawioId []

	scalar property hasValue [
		domain Cell
		range xsd:string
		functional
	]
	
	relation entity HasParentCell :> acyclic:Acyclic, object_diagram:Link [
		from AbstractCell
		to AbstractCell
		forward hasParent
		reverse hasChild
		asymmetric
		irreflexive
		functional // all cells have one parent, except for the root cell
	]
	
	relation entity HasProperty :> object_diagram:Link [
		from AbstractCell
		to CellProperty
		forward hasProperty
		reverse propertyOf
		asymmetric
		irreflexive
		inverse functional
	]
	relation entity HasStyleEntry :> object_diagram:Link [
		from AbstractCell
		to CellStyleEntry
		forward hasStyleEntry
		reverse styleEntryOf
		asymmetric
		irreflexive
		inverse functional
	]
	relation entity HasCellAttribute :> object_diagram:Link [
		from AbstractCell
		to CellAttribute
		forward hasCellAttribute
		reverse attributeOf
		asymmetric
		irreflexive
		inverse functional
	]
	
	concept CellProperty :> dict:DictEntry, element []
	concept CellStyleEntry :> dict:DictEntry, element []
	concept CellAttribute :> dict:DictEntry, element []
	
	structure Point [
		restricts scalar property hasX to exactly 1
		restricts scalar property hasY to exactly 1
	]
	scalar property hasX :> object_diagram:hasField [
		domain Point
		range xsd:decimal
		functional
	]
	scalar property hasY :> object_diagram:hasField [
		domain Point
		range xsd:decimal
		functional
	]
	
	structure CellGeometry :> Point [
		restricts scalar property hasWidth to exactly 1
		restricts scalar property hasHeight to exactly 1
	]
	scalar property hasWidth :> object_diagram:hasField [
		domain CellGeometry
		range xsd:decimal
		functional
	]
	scalar property hasHeight :> object_diagram:hasField [
		domain CellGeometry
		range xsd:decimal
		functional
	]
	
	// An edge may have an ordered sequence of 'waypoints'
	// We'll add a 'list index' property to store the order.
	structure PointListItem :> Point [
		restricts scalar property hasListIndex to exactly 1
	]
	scalar property hasListIndex [
		domain PointListItem
		range xsd:nonNegativeInteger
		functional
	]
	
	structure EdgeGeometry []
	structured property hasPoint [
		domain EdgeGeometry
		range PointListItem
		// not functional: any number of points allowed
	]
	structured property hasSourcePoint [
		domain EdgeGeometry
		range Point
		functional
	]
	structured property hasTargetPoint [
		domain EdgeGeometry
		range Point
		functional
	]
	
	concept Cell :> AbstractCell []
	concept Edge :> AbstractCell []
	
	structured property hasCellGeometry [
		domain Cell
		range CellGeometry
		functional
	]
	structured property hasEdgeGeometry [
		domain Edge
		range EdgeGeometry
		functional
	]
	
	relation entity EdgeHasSource [
		from Edge
		to Cell
		forward hasSource
		reverse sourceOf
		functional
		asymmetric
		irreflexive
	]
	relation entity EdgeHasTarget [
		from Edge
		to Cell
		forward hasTarget
		reverse targetOf
		functional
		asymmetric
		irreflexive
	]
	
	concept Page :> elementWithDrawioId [
		restricts relation ofModel to exactly 1
		restricts scalar property hasName to exactly 1
		restricts relation hasRootCell to exactly 1
	]
	
	relation entity HasPageAttribute :> object_diagram:Link [
		from Page
		to PageAttribute
		forward hasPageAttribute
		reverse ofPage
		asymmetric
		irreflexive
		inverse functional
	]
	relation entity HasRootCell :> object_diagram:Link [
		from Page
		to Cell
		forward hasRootCell
		reverse isRootOf
		asymmetric
		irreflexive
		functional // every page has exactly one root cell
		inverse functional // a cell can be the root of at most one page
	]
	
	concept PageAttribute :> dict:DictEntry, element []
	
	scalar property hasName [
		domain Page
		range xsd:string
		functional
	]
	
	
	// A Drawio file:
	concept Model :> object_diagram:Model [
		restricts all relation object_diagram:hasObject to element
		restricts scalar property isCompressed to exactly 1
		restricts scalar property hasDrawioVersion to exactly 1
	]
	
	relation entity HasPage [
		from Model
		to Page
		forward hasPage
		reverse ofModel
		inverse functional
		asymmetric
		irreflexive
	]

	scalar property isCompressed [
		domain Model
		range xsd:boolean
		functional
	]
	
	scalar property hasDrawioVersion [
		domain Model
		range xsd:string
		functional
	]
}