1// Copyright (C) 2018 The Android Open Source Project 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15export interface HasKind { kind: string; } 16 17export class Registry<T> { 18 private key: (t: T) => string; 19 protected registry: Map<string, T>; 20 21 static kindRegistry<T extends HasKind>(): Registry<T> { 22 return new Registry<T>((t) => t.kind); 23 } 24 25 constructor(key: (t: T) => string) { 26 this.registry = new Map<string, T>(); 27 this.key = key; 28 } 29 30 register(registrant: T) { 31 const kind = this.key(registrant); 32 if (this.registry.has(kind)) { 33 throw new Error(`Registrant ${kind} already exists in the registry`); 34 } 35 this.registry.set(kind, registrant); 36 } 37 38 has(kind: string): boolean { 39 return this.registry.has(kind); 40 } 41 42 get(kind: string): T { 43 const registrant = this.registry.get(kind); 44 if (registrant === undefined) { 45 throw new Error(`${kind} has not been registered.`); 46 } 47 return registrant; 48 } 49 50 // Support iteration: for (const foo of fooRegistry.values()) { ... } 51 * values() { 52 yield* this.registry.values(); 53 } 54 55 unregisterAllForTesting(): void { 56 this.registry.clear(); 57 } 58} 59