import { PiCompositeProjection , PiError , PiLogger , PiModel , PiNamedElement } from "@projectit/core" ; import { get } from "svelte/store" ; import { currentModelName , currentUnitName , fileExtensions , languageName , noUnitAvailable , projectionNames , severityType , units , unitTypes } from "../webapp-ts-utils/WebappStore" ; import { modelErrors } from "../webapp-ts-utils/ModelErrorsStore" ; import { setUserMessage } from "../webapp-ts-utils/UserMessageUtils" ; import { editorEnvironment , serverCommunication } from "../WebappConfiguration" ; const LOGGER = new PiLogger ( "EditorCommunication" ) ; export class EditorCommunication { private static instance : EditorCommunication = null ; static getInstance ( ) { if ( EditorCommunication . instance === null ) { EditorCommunication . instance = new EditorCommunication ( ) ; } return EditorCommunication . instance ; } /**
     * fills the WebappStore with initial values that describe the language
     */ static initialize ( ) { languageName . set ( editorEnvironment . languageName ) ; unitTypes . set ( editorEnvironment . unitNames ) ; const tmp = [ ] ; for ( const val of editorEnvironment . fileExtensions . values ( ) ) { tmp . push ( val ) ; } fileExtensions . set ( tmp ) ; EditorCommunication . setProjectionNames ( ) ; } /**
     * Sets the list of projection names in the right order, such that it can
     * be used in the projection menu.
     */ static setProjectionNames ( ) { const proj = editorEnvironment . editor . projection ; let nameList = proj instanceof PiCompositeProjection ? proj . projectionNames ( ) : [ proj . name ] ; nameList = nameList . reverse ( ) ; if ( nameList [ 0 ] !== "default" ) { const i = nameList . indexOf ( "default" ) ; if ( i > 0 ) { nameList . splice ( i , 1 ) ; } nameList . unshift ( "default" ) ; } projectionNames . set ( nameList ) ; } currentUnit : PiNamedElement = null ; currentModel : PiModel = null ; hasChanges : boolean = false ; param modelName param unitName newModel ( modelName ) { LOGGER . log ( "new model called: " + modelName ) ; this . saveCurrentUnit ( ) ; this . resetGlobalVariables ( ) ; this . currentModel = editorEnvironment . newModel ( modelName ) ; currentModelName . set ( this . currentModel . name ) ; } param newName param unitType newUnit ( newName , unitType ) { LOGGER . log ( "new unit called, unitType: " + unitType + ", name: " + newName ) ; this . saveCurrentUnit ( ) ; const oldName = get ( currentUnitName ) ; if ( ! ! oldName && oldName !== "" ) { serverCommunication . loadModelUnitInterface ( get ( currentModelName ) , get ( currentUnitName ) , ( oldUnitInterface ) => { if ( ! ! oldUnitInterface ) { EditorCommunication . getInstance ( ) . currentModel . replaceUnit ( EditorCommunication . getInstance ( ) . currentUnit , oldUnitInterface ) ; } this . createNewUnit ( newName , unitType ) ; } ) ; } else { this . createNewUnit ( newName , unitType ) ; } } param newName param unitType private private createNewUnit ( newName , unitType ) { LOGGER . log ( "private createNewUnit called, unitType: " + unitType + " name: " + newName ) ; this . saveCurrentUnit ( ) ; const newUnit = EditorCommunication . getInstance ( ) . currentModel . newUnit ( unitType ) ; newUnit . name = newName ; if ( ! ! newUnit ) { this . showUnitAndErrors ( newUnit ) ; } else { setUserMessage ( `Model unit of type '${ unitType }' could not be created.` ) ; } currentUnitName . set ( newName ) ; } /**
     * Pushes the current unit to the server
     */ async saveCurrentUnit ( ) { LOGGER . log ( "EditorCommunication.saveCurrentUnit: " + get ( currentUnitName ) ) ; const unit = editorEnvironment . editor . rootElement as PiNamedElement ; if ( ! ! unit ) { if ( unit . name && unit . name . length > 0 ) { await serverCommunication . putModelUnit ( this . currentModel . name , this . currentUnit . name , unit ) ; currentUnitName . set ( unit . name ) ; EditorCommunication . getInstance ( ) . setUnitLists ( ) ; this . hasChanges = false ; } else { setUserMessage ( `Unit without name cannot be saved. Please, name it and try again.` ) ; } } else { LOGGER . log ( "No current model unit" ) ; } } param unit async deleteModelUnit ( unit ) { LOGGER . log ( "delete called for unit: " + unit . name ) ; await serverCommunication . deleteModelUnit ( get ( currentModelName ) , unit . name ) ; this . currentModel . removeUnit ( unit ) ; if ( this . currentUnit === unit ) { editorEnvironment . editor . rootElement = null ; noUnitAvailable . set ( true ) ; modelErrors . set ( [ ] ) ; } this . setUnitLists ( ) ; } private private setUnitLists ( ) { console . log ( "setUnitLists" ) ; const newUnitList = [ ] ; for ( const name of editorEnvironment . unitNames ) { newUnitList . push ( this . currentModel . getUnitsForType ( name ) ) ; } units . set ( newUnitList ) ; } param modelName async openModel ( modelName ) { LOGGER . log ( "EditorCommunication.openmodel(" + modelName + ")" ) ; this . resetGlobalVariables ( ) ; this . saveCurrentUnit ( ) ; const model = editorEnvironment . newModel ( modelName ) ; this . currentModel = model ; currentModelName . set ( modelName ) ; serverCommunication . loadUnitList ( modelName , ( unitNames ) => { if ( unitNames && unitNames . length > 0 ) { let first = true ; for ( const unitName of unitNames ) { if ( first ) { serverCommunication . loadModelUnit ( modelName , unitName , ( unit ) => { this . currentModel . addUnit ( unit ) ; this . currentUnit = unit ; currentUnitName . set ( this . currentUnit . name ) ; EditorCommunication . getInstance ( ) . showUnitAndErrors ( this . currentUnit ) ; } ) ; first = false ; } else { serverCommunication . loadModelUnitInterface ( modelName , unitName , ( unit ) => { this . currentModel . addUnit ( unit ) ; this . setUnitLists ( ) ; } ) ; } } } } ) ; } private private resetGlobalVariables ( ) { noUnitAvailable . set ( true ) ; units . set ( [ ] ) ; modelErrors . set ( [ ] ) ; } param newUnit async openModelUnit ( newUnit ) { LOGGER . log ( "openModelUnit called, unitName: " + newUnit . name ) ; if ( ! ! this . currentUnit && newUnit . name === this . currentUnit . name ) { LOGGER . log ( "openModelUnit doing NOTHING" ) ; return ; } this . saveCurrentUnit ( ) ; await serverCommunication . loadModelUnit ( this . currentModel . name , newUnit . name , ( newCompleteUnit ) => { this . swapInterfaceAndUnits ( newCompleteUnit , newUnit ) ; } ) ; } param newCompleteUnit param newUnitInterface private private swapInterfaceAndUnits ( newCompleteUnit , newUnitInterface ) { if ( ! ! EditorCommunication . getInstance ( ) . currentUnit ) { serverCommunication . loadModelUnitInterface ( EditorCommunication . getInstance ( ) . currentModel . name , EditorCommunication . getInstance ( ) . currentUnit . name , ( oldUnitInterface ) => { if ( ! ! newCompleteUnit ) { if ( ! ! oldUnitInterface ) { EditorCommunication . getInstance ( ) . currentModel . replaceUnit ( EditorCommunication . getInstance ( ) . currentUnit , oldUnitInterface ) ; } EditorCommunication . getInstance ( ) . currentModel . replaceUnit ( newUnitInterface , newCompleteUnit ) ; this . showUnitAndErrors ( newCompleteUnit ) ; } } ) ; } else { EditorCommunication . getInstance ( ) . currentModel . replaceUnit ( newUnitInterface , newCompleteUnit ) ; this . showUnitAndErrors ( newCompleteUnit ) ; } } param content param metaType unitFromFile ( content , metaType ) { this . saveCurrentUnit ( ) ; let elem = null ; elem = editorEnvironment . reader . readFromString ( content , metaType ) as PiNamedElement ; if ( elem ) { if ( this . currentModel . getUnits ( ) . filter ( unit => unit . name === elem . name ) . length > 0 ) { setUserMessage ( `Unit named '${ elem . name }' already exists.` , severityType . error ) ; return ; } this . currentModel . addUnit ( elem ) ; this . setUnitLists ( ) ; this . showUnitAndErrors ( elem ) ; } } /**
     * Unparses the current model unit to a string, which can be used as content in a
     * downloadable file.
     */ unitAsText ( ) { return editorEnvironment . writer . writeToString ( this . currentUnit ) ; } /**
     * Returns the right file extension for the current unit, based on the type of the unit.
     */ unitFileExtension ( ) { const unitType = this . currentUnit . piLanguageConcept ( ) ; return editorEnvironment . fileExtensions . get ( unitType ) ; } param newUnit private private showUnitAndErrors ( newUnit ) { LOGGER . log ( "showUnitAndErrors called, unitName: " + newUnit . name ) ; if ( ! ! newUnit ) { noUnitAvailable . set ( false ) ; editorEnvironment . editor . rootElement = newUnit ; this . currentUnit = newUnit ; currentUnitName . set ( newUnit . name ) ; this . setUnitLists ( ) ; this . hasChanges = true ; this . getErrors ( ) ; } else { noUnitAvailable . set ( true ) ; editorEnvironment . editor . rootElement = null ; this . currentUnit = null ; currentUnitName . set ( "<noUnit>" ) ; this . setUnitLists ( ) ; this . hasChanges = false ; } } param error errorSelected ( error ) { LOGGER . log ( "Error selected: '" + error . message + "', location:  '" + error . locationdescription + "'" ) ; if ( Array . isArray ( error . reportedOn ) ) { editorEnvironment . editor . selectElement ( error . reportedOn [ 0 ] ) ; } else { editorEnvironment . editor . selectElement ( error . reportedOn ) ; } } /**
     * Runs the validator for the current unit
     */ getErrors ( ) { LOGGER . log ( "EditorCommunication.getErrors() for " + this . currentUnit . name ) ; if ( ! ! this . currentUnit ) { const list = editorEnvironment . validator . validate ( this . currentUnit ) ; modelErrors . set ( list ) ; } } param name setProjection ( name ) { LOGGER . log ( "setting Projection " + name ) ; const proj = editorEnvironment . editor . projection ; if ( proj instanceof PiCompositeProjection ) { proj . projectiontoFront ( name ) ; } } param name unsetProjection ( name ) { LOGGER . log ( "unsetting Projection " + name ) ; const proj = editorEnvironment . editor . projection ; if ( proj instanceof PiCompositeProjection ) { proj . projectionToBack ( name ) ; } } redo ( ) { LOGGER . log ( "redo called" ) ; return undefined ; } undo ( ) { LOGGER . log ( "undo called" ) ; return undefined ; } validate ( ) { LOGGER . log ( "validate called" ) ; EditorCommunication . getInstance ( ) . getErrors ( ) ; } replace ( ) { LOGGER . log ( "replace called" ) ; return undefined ; } findText ( ) { LOGGER . log ( "findText called" ) ; return undefined ; } findElement ( ) { LOGGER . log ( "findElement called" ) ; return undefined ; } }