2019-08-13 15:36:46 -04:00
import MODULE_TYPES from './MODULE_TYPES.js' ;
import log from './../log.js' ;
export default class ExtensionManager {
2020-05-06 14:17:44 -03:00
constructor ({ commandsManager , servicesManager , api , appConfig = {} }) {
2019-08-13 15:36:46 -04:00
this . modules = {};
this . registeredExtensionIds = [];
2020-09-03 12:58:04 +02:00
this . registeredExtensionVesions = {};
2019-08-13 15:36:46 -04:00
this . moduleTypeNames = Object . values ( MODULE_TYPES );
//
this . _commandsManager = commandsManager ;
2019-11-13 17:02:14 -03:00
this . _servicesManager = servicesManager ;
2019-12-16 16:07:53 -03:00
this . _appConfig = appConfig ;
2020-05-06 14:17:44 -03:00
this . _api = api ;
2019-08-13 15:36:46 -04:00
this . moduleTypeNames . forEach ( moduleType => {
this . modules [ moduleType ] = [];
});
}
/**
* An array of extensions, or an array of arrays that contains extension
* configuration pairs.
*
* @param {Object[]} extensions - Array of extensions
*/
registerExtensions ( extensions ) {
extensions . forEach ( extension => {
const hasConfiguration = Array . isArray ( extension );
if ( hasConfiguration ) {
2019-12-09 14:47:23 -03:00
const [ ohifExtension , configuration ] = extension ;
2019-08-13 15:36:46 -04:00
this . registerExtension ( ohifExtension , configuration );
} else {
this . registerExtension ( extension );
}
});
}
/**
*
* TODO: Id Management: SopClassHandlers currently refer to viewport module by id; setting the extension id as viewport module id is a workaround for now
* @param {Object} extension
* @param {Object} configuration
*/
registerExtension ( extension , configuration = {}) {
if ( ! extension ) {
log . warn (
'Attempting to register a null/undefined extension. Exiting early.'
);
return ;
}
let extensionId = extension . id ;
2020-09-03 12:58:04 +02:00
const version = extension . version ;
2019-08-13 15:36:46 -04:00
if ( ! extensionId ) {
extensionId = Math . random ()
. toString ( 36 )
. substr ( 2 , 5 );
log . warn ( `Extension ID not set. Using random string ID: ${ extensionId } ` );
}
if ( this . registeredExtensionIds . includes ( extensionId )) {
log . warn (
`Extension ID ${ extensionId } has already been registered. Exiting before duplicating modules.`
);
return ;
}
// preRegistrationHook
if ( extension . preRegistration ) {
2019-11-13 17:02:14 -03:00
extension . preRegistration ({
2019-11-14 11:50:37 -03:00
servicesManager : this . _servicesManager ,
2019-12-02 13:29:04 -03:00
commandsManager : this . _commandsManager ,
2019-12-16 16:07:53 -03:00
appConfig : this . _appConfig ,
2019-11-13 17:02:14 -03:00
configuration ,
});
2019-08-13 15:36:46 -04:00
}
// Register Modules
this . moduleTypeNames . forEach ( moduleType => {
const extensionModule = this . _getExtensionModule (
moduleType ,
extension ,
2019-12-16 16:07:53 -03:00
extensionId ,
configuration
2019-08-13 15:36:46 -04:00
);
if ( extensionModule ) {
this . _initSpecialModuleTypes ( moduleType , extensionModule );
this . modules [ moduleType ]. push ({
extensionId ,
module : extensionModule ,
});
}
});
// Track extension registration
this . registeredExtensionIds . push ( extensionId );
2020-09-03 12:58:04 +02:00
this . registeredExtensionVesions [ extensionId ] = version ;
2019-08-13 15:36:46 -04:00
}
/**
* @private
* @param {string} moduleType
* @param {Object} extension
* @param {string} extensionId - Used for logging warnings
*/
2019-12-16 16:07:53 -03:00
_getExtensionModule ( moduleType , extension , extensionId , configuration ) {
2019-08-13 15:36:46 -04:00
const getModuleFnName = 'get' + _capitalizeFirstCharacter ( moduleType );
const getModuleFn = extension [ getModuleFnName ];
if ( ! getModuleFn ) {
return ;
}
try {
2019-11-14 19:29:40 -03:00
const extensionModule = getModuleFn ({
servicesManager : this . _servicesManager ,
2019-12-02 13:29:04 -03:00
commandsManager : this . _commandsManager ,
2019-12-16 16:07:53 -03:00
appConfig : this . _appConfig ,
configuration ,
2020-09-03 12:58:04 +02:00
api : this . _api ,
extensionManager : this ,
2019-11-14 19:29:40 -03:00
});
2019-08-13 15:36:46 -04:00
if ( ! extensionModule ) {
log . warn (
`Null or undefined returned when registering the ${ getModuleFnName } module for the ${ extensionId } extension`
);
}
return extensionModule ;
} catch ( ex ) {
log . error (
`Exception thrown while trying to call ${ getModuleFnName } for the ${ extensionId } extension`
);
}
}
_initSpecialModuleTypes ( moduleType , extensionModule ) {
switch ( moduleType ) {
case 'commandsModule' : {
const { definitions , defaultContext } = extensionModule ;
if ( ! definitions || Object . keys ( definitions ). length === 0 ) {
log . warn ( 'Commands Module contains no command definitions' );
return ;
}
this . _initCommandsModule ( definitions , defaultContext );
break ;
}
default :
// code block
}
}
/**
*
* @private
* @param {Object[]} commandDefinitions
*/
_initCommandsModule ( commandDefinitions , defaultContext = 'VIEWER' ) {
if ( ! this . _commandsManager . getContext ( defaultContext )) {
this . _commandsManager . createContext ( defaultContext );
}
Object . keys ( commandDefinitions ). forEach ( commandName => {
const commandDefinition = commandDefinitions [ commandName ];
const commandHasContextThatDoesNotExist =
commandDefinition . context &&
! this . _commandsManager . getContext ( commandDefinition . context );
if ( commandHasContextThatDoesNotExist ) {
this . _commandsManager . createContext ( commandDefinition . context );
}
this . _commandsManager . registerCommand (
commandDefinition . context || defaultContext ,
commandName ,
commandDefinition
);
});
}
}
/**
* @private
* @param {string} lower
*/
function _capitalizeFirstCharacter ( lower ) {
return lower . charAt ( 0 ). toUpperCase () + lower . substr ( 1 );
}