Skip to content

Commit

Permalink
feat(core/di/key): create globalKey registry for storing unique servi…
Browse files Browse the repository at this point in the history
…ce names
  • Loading branch information
Hotell committed Jan 17, 2016
1 parent d1beaf0 commit 2e450be
Show file tree
Hide file tree
Showing 2 changed files with 139 additions and 36 deletions.
138 changes: 102 additions & 36 deletions src/core/di/key.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import {isBlank,stringify} from '../../facade/lang';
import {resolveForwardRef} from './forward_ref';
import {StringMapWrapper} from '../../facade/collections';
import {baseToString} from '../../facade/lang';
import {StringWrapper} from '../../facade/primitives';
import {isString} from '../../facade/lang';
import {OpaqueToken} from './opaque_token';
import {ListWrapper} from '../../facade/collections';
import {isType} from '../../facade/lang';

/**
* @TODO
Expand All @@ -21,55 +27,115 @@ import {StringMapWrapper} from '../../facade/collections';
* `Key` should not be created directly. {@link Injector} creates keys automatically when resolving
* providers.
*/
export class Key {
/**
* Private
*/
constructor( public token: Object, public id: number ) {
if ( isBlank( token ) ) {
throw new Error( 'Token must be defined!' );
}
}

/**
* Returns a stringified token.
*/
get displayName(): string { return stringify( this.token ); }

/**
* Retrieves a `Key` for a token.
*/
static get( token: Object ): Key { return _globalKeyRegistry.get( resolveForwardRef( token ) ); }

/**
* @returns the number of keys registered in the system.
*/
static get numberOfKeys(): number { return _globalKeyRegistry.numberOfKeys; }
}
//export class Key {
// /**
// * Private
// */
// constructor( public token: Object, public id: number ) {
// if ( isBlank( token ) ) {
// throw new Error( 'Token must be defined!' );
// }
// }
//
// /**
// * Returns a stringified token.
// */
// get displayName(): string { return stringify( this.token ); }
//
// /**
// * Retrieves a `Key` for a token.
// */
// static get( token: Object ): Key { return _globalKeyRegistry.get( resolveForwardRef( token ) ); }
//
// /**
// * @returns the number of keys registered in the system.
// */
// static get numberOfKeys(): number { return _globalKeyRegistry.numberOfKeys; }
//}

/**
* @internal
*/
export class KeyRegistry {

private _allKeys = StringMapWrapper.create();
private static _suffix = `#`;

get( token: Object ): Key {
if ( token instanceof Key ) return token;
private _allKeys: string[] = ListWrapper.create();
private _idCounter: number = 0;

const tokenString = stringify( token );
//get( token: string | OpaqueToken | Type ): string {
// // Return it if it is already a string like `'$http'` or `'$state'`
// if(isString(token)) {
// return token;
// }
// if(token instanceof OpaqueToken){
// return token.desc;
// }
//
// const tokenString = stringify( token );
// const hasToken = StringMapWrapper.contains( this._allKeys, tokenString );
//
// if ( hasToken ) {
// return tokenString;
// }
//
// const newKey = `${ tokenString }${ this._uniqueId() }`;
// StringMapWrapper.set( this._allKeys, newKey, token );
// return newKey;
//}

const getToken = StringMapWrapper.get( this._allKeys, tokenString );
if ( getToken ) {
return getToken;
/**
*
* @param token
* @returns {*}
*/
get( token: Type ): string {
if ( !isType( token ) ) {
throw new Error( `KeyRegistry#get:
================
you'v tried to create a key for \`${ token }\`
creating and getting key tokens is avaialable only for Type` );
}
const newKey = `${ stringify( token ) }${ KeyRegistry._suffix }${ this._uniqueId() }`;
this._allKeys.push( newKey );

const newKey = new Key( token, Key.numberOfKeys );
StringMapWrapper.set( this._allKeys, tokenString, newKey );
return newKey;

}

get numberOfKeys(): number { return ListWrapper.size( this._allKeys ) }

get allKeys(): Object { return ListWrapper.clone( this._allKeys ) }


/**
* just for testing purposes
* @private
* @internal
*/
_reset() {
ListWrapper.clear( this._allKeys );
this._idCounter = 0;
}

/**
* Generates a unique ID. If `prefix` is provided the ID is appended to it.
*
* @param {string} [prefix] The value to prefix the ID with.
* @returns {string} Returns the unique ID.
* @example
*
* _uniqueId('contact_');
* // => 'contact_104'
*
* _uniqueId();
* // => '105'
*/
private _uniqueId( prefix?: string ) {
const id = ++this._idCounter;
return `${ baseToString( prefix ) }${ id }`;
}

get numberOfKeys(): number { return StringMapWrapper.size( this._allKeys ) }
}

const _globalKeyRegistry = new KeyRegistry();
export const globalKeyRegistry = new KeyRegistry();
37 changes: 37 additions & 0 deletions test/core/di/key.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import {expect} from 'chai';
import {OpaqueToken} from '../../../src/core/di/opaque_token';
import {globalKeyRegistry} from '../../../src/core/di/key';
import {Injectable} from '../../../src/core/di/decorators';

describe( `di/key`, ()=> {

beforeEach( ()=> {
globalKeyRegistry._reset();
} );


it( `should throw if you want create/get key for non Type(Service)`, ()=> {

expect( ()=>globalKeyRegistry.get(('foo' as any)) ).to.throw();
expect( ()=>globalKeyRegistry.get((1312 as any)) ).to.throw();
expect( ()=>globalKeyRegistry.get(( {foo: 21312} as any )) ).to.throw();
expect( ()=>globalKeyRegistry.get(( new OpaqueToken('moo') as any )) ).to.throw();

expect( globalKeyRegistry.numberOfKeys ).to.equal( 0 );

} );

it( `should create and return unique key for classes names`, ()=> {

class Foo{}
class Moo{}

expect( globalKeyRegistry.get( Foo ) ).to.equal( 'Foo#1' );
expect( globalKeyRegistry.get( Moo ) ).to.equal( 'Moo#2' );

expect( globalKeyRegistry.numberOfKeys ).to.equal( 2 );
expect( globalKeyRegistry.allKeys ).to.deep.equal( [ 'Foo#1', 'Moo#2' ] );

} );

} );

0 comments on commit 2e450be

Please sign in to comment.