import { ElementModel , LinkModel , ElementIri , ElementTypeIri , LinkTypeIri , PropertyTypeIri , LinkDirection , MetadataApi , ValidationApi , ValidationEvent , ElementError , LinkError , DirectedLinkType , CancellationToken , } from '../../src/graph-explorer/index' ; const OWL_PREFIX = 'http://www.w3.org/2002/07/owl#' ; const RDFS_PREFIX = 'http://www.w3.org/2000/01/rdf-schema#' ; const owl = { class : ( OWL_PREFIX + 'Class' ) as ElementTypeIri , objectProperty : ( OWL_PREFIX + 'ObjectProperty' ) as ElementTypeIri , domain : ( OWL_PREFIX + 'domain' ) as LinkTypeIri , range : ( OWL_PREFIX + 'range' ) as LinkTypeIri , } ; const rdfs = { subClassOf : ( RDFS_PREFIX + 'subClassOf' ) as LinkTypeIri , subPropertyOf : ( RDFS_PREFIX + 'subPropertyOf' ) as LinkTypeIri , } ; function hasType ( model , type ) { return Boolean ( model . types . find ( ( t ) => t === type ) ) ; } const SIMULATED_DELAY = 500 ; export class ExampleMetadataApi implements MetadataApi { async canDropOnCanvas ( source , ct ) { await delay ( SIMULATED_DELAY , ct ) ; const elementTypes = await this . typesOfElementsDraggedFrom ( source , ct ) ; CancellationToken . throwIfAborted ( ct ) ; return elementTypes . length > 0 ; } async canDropOnElement ( source , target , ct ) { await delay ( SIMULATED_DELAY , ct ) ; const linkTypes = await this . possibleLinkTypes ( source , target , ct ) ; CancellationToken . throwIfAborted ( ct ) ; return linkTypes . length > 0 ; } async possibleLinkTypes ( source , target , ct ) { await delay ( SIMULATED_DELAY , ct ) ; return hasType ( source , owl . class ) && hasType ( target , owl . class ) ? mapLinkTypes ( [ rdfs . subClassOf ] ) . concat ( mapLinkTypes ( [ rdfs . subClassOf ] , LinkDirection . in ) ) : hasType ( source , owl . objectProperty ) && hasType ( target , owl . class ) ? mapLinkTypes ( [ owl . domain , owl . range ] ) : hasType ( target , owl . objectProperty ) && hasType ( source , owl . class ) ? mapLinkTypes ( [ owl . domain , owl . range ] , LinkDirection . in ) : hasType ( source , owl . objectProperty ) && hasType ( target , owl . objectProperty ) ? mapLinkTypes ( [ rdfs . subPropertyOf ] ) . concat ( mapLinkTypes ( [ rdfs . subPropertyOf ] , LinkDirection . in ) ) : [ ] ; function mapLinkTypes ( types , direction = LinkDirection . out ) { return types . map ( ( linkTypeIri ) => ( { linkTypeIri , direction } ) ) ; } } async typesOfElementsDraggedFrom ( source , ct ) { await delay ( SIMULATED_DELAY , ct ) ; return hasType ( source , owl . class ) ? [ owl . class ] : hasType ( source , owl . objectProperty ) ? [ owl . class , owl . objectProperty ] : [ ] ; } async propertiesForType ( type , ct ) { await delay ( SIMULATED_DELAY , ct ) ; return [ ] ; } async canDeleteElement ( element , ct ) { await delay ( SIMULATED_DELAY , ct ) ; return true ; } async filterConstructibleTypes ( types , ct ) { await delay ( SIMULATED_DELAY , ct ) ; const result = new Set < ElementTypeIri > ( ) ; types . forEach ( ( type ) => { if ( type . length % 2 === 0 ) { result . add ( type ) ; } } ) ; return result ; } async canEditElement ( element , ct ) { await delay ( SIMULATED_DELAY , ct ) ; return true ; } async canLinkElement ( element , ct ) { await delay ( SIMULATED_DELAY , ct ) ; return true ; } async canDeleteLink ( link , source , target , ct ) { await delay ( SIMULATED_DELAY , ct ) ; return true ; } async canEditLink ( link , source , target , ct ) { await delay ( SIMULATED_DELAY , ct ) ; return true ; } async generateNewElement ( types , ct ) { await delay ( SIMULATED_DELAY , ct ) ; const random32BitDigits = Math . floor ( ( 1 + Math . random ( ) ) * 0x100000000 ) . toString ( 16 ) . substring ( 1 ) ; return { id : `${ types [ 0 ] }_${ random32BitDigits }` as ElementIri , types : [ ... types ] , label : { values : [ { value : 'New Entity' , language : '' } ] } , properties : { } , } ; } } export class ExampleValidationApi implements ValidationApi { async validate ( event ) { const errors = [ ] ; if ( event . target . types . indexOf ( owl . class ) >= 0 ) { event . state . links . forEach ( ( e ) => { if ( ! e . before && e . after . sourceId === event . target . id ) { errors . push ( { type : 'link' , target : e . after , message : 'Cannot add any new link from a Class' , } ) ; const linkType = event . model . createLinkType ( e . after . linkTypeId ) ; errors . push ( { type : 'element' , target : event . target . id , message : `Cannot create <${ linkType . id }> link from a Class` , } ) ; } } ) ; } await delay ( SIMULATED_DELAY , event . cancellation ) ; return errors ; } } async function delay ( amountMs , ct ) { CancellationToken . throwIfAborted ( ct ) ; await waitTimeout ( amountMs ) ; CancellationToken . throwIfAborted ( ct ) ; } function waitTimeout ( amountMs ) { if ( amountMs === 0 ) { return Promise . resolve ( ) ; } return new Promise ( ( resolve ) => setTimeout ( resolve , amountMs ) ) ; }