//·························································· // Copyright (c) 2023-2026. Jonathan Bédard ~ JóôòKiwi // // This project is free to use. // All the right is reserved to the author of this project. // My projects: // - https://github.com/joooKiwi/type // - https://github.com/joooKiwi/lazy // - https://github.com/joooKiwi/collection // - https://github.com/joooKiwi/enumeration //·························································· import type {Lazy} from "@joookiwi/lazy" import type {Nullable, NullOr} from "@joookiwi/type" import {CommonLazy, lazy} from "@joookiwi/lazy" import type {EnumerableWithNullableGrandParent} from "./EnumerableWithNullableGrandParent" import type {EnumerableWithNullableParent} from "./EnumerableWithNullableParent" import type {Enumerable} from "./Enumerable" import type {NameOf, PossibleNameOf} from "./type/nameOf" import type {PossibleOrdinalOf} from "./type/ordinalOf" import type {PossibleEnumerableValueOrNameByValueOrCallback} from "./type/possibleInstance" import {EnumWithNullableParent} from "./EnumWithNullableParent" import {EnumConstants} from "./EnumConstants" import {KnownEnumConstructors} from "./KnownEnumConstructors" import {ImpossibleIntegrityException} from "./exception/ImpossibleIntegrityException" import {_getGrandParentValueFromName} from "./method/_getGrandParentValueFromName" /** * An {@link Enum} class in conjuncture with the {@link EnumerableWithNullableGrandParent}. * * Compared to its sibling {@link EnumWithGrandParent}, it can receive `null`. * * But it can still throw a {@link NullReferenceException} in different scenarios: * - An exception is thrown when attempting to retrieve its {@link CompanionEnumWithGrandParent} * - An exception is thrown when attempting to retrieve the value by {@link CompanionEnumWithGrandParentDeclaration.getValue getValue()} * * Also, it can throw a {@link ImpossibleIntegrityException} when receiving a `null` * on a value that was not expected to be null on the {@link EnumWithNullableGrandParent.parent parent} method. * * @see EnumWithGrandParent */ export class EnumWithNullableGrandParent, const GRAND_PARENT extends Enumerable, const ORDINAL extends PossibleOrdinalOf = PossibleOrdinalOf, const NAME extends PossibleNameOf = PossibleNameOf, > extends EnumWithNullableParent implements EnumerableWithNullableGrandParent { //#region -------------------- Fields -------------------- readonly #parent: Lazy> readonly #grandParent: Lazy> static { KnownEnumConstructors.add(EnumWithNullableGrandParent,) } //#endregion -------------------- Fields -------------------- //#region -------------------- Constructor -------------------- /** * Create the instance with both {@link EnumerableWithNullableGrandParent.parent parent} * & {@link EnumerableWithNullableGrandParent.grandParent grandparent} references * with the same {@link Enum.name name} as the current instance */ protected constructor() protected constructor(parent: Nullable,) protected constructor(parent: Nullable, grandParent: Nullable,) protected constructor(parent: Nullable, grandParentName: Nullable>,) protected constructor(parent: Nullable, lateGrandParent: Nullable<() => Nullable>,) protected constructor(parent: Nullable, lateGrandParentName: Nullable<() => Nullable>>,) protected constructor(parentName: Nullable>,) protected constructor(parentName: Nullable>, grandParent: Nullable,) protected constructor(parentName: Nullable>, grandParentName: Nullable>,) protected constructor(parentName: Nullable>, lateGrandParent: Nullable<() => Nullable>,) protected constructor(parentName: Nullable>, lateGrandParentName: Nullable<() => Nullable>>,) protected constructor(lateParent: Nullable<() => Nullable>,) protected constructor(lateParent: Nullable<() => Nullable>, grandParent: Nullable,) protected constructor(lateParent: Nullable<() => Nullable>, grandParentName: Nullable>,) protected constructor(lateParent: Nullable<() => Nullable>, lateGrandParent: Nullable<() => Nullable>,) protected constructor(lateParent: Nullable<() => Nullable>, lateGrandParentName: Nullable<() => Nullable>>,) protected constructor(lateParentName: Nullable<() => Nullable>>,) protected constructor(lateParentName: Nullable<() => Nullable>>, grandParent: Nullable,) protected constructor(lateParentName: Nullable<() => Nullable>>, grandParentName: Nullable>,) protected constructor(lateParentName: Nullable<() => Nullable>>, lateGrandParent: Nullable<() => Nullable>,) protected constructor(lateParentName: Nullable<() => Nullable>>, lateGrandParentName: Nullable<() => Nullable>>,) /** * Create the instance with a parent & a grandparent from any possible values (in Javascript) * * @param parent The parent value (from any possibilities in Javascript) * @param grandParent The grandparent value (from any possibilities in Javascript) * * @typescriptDefinition */ protected constructor(parent?: PossibleEnumerableValueOrNameByValueOrCallback, grandParent?: PossibleEnumerableValueOrNameByValueOrCallback,) protected constructor(parent?: PossibleEnumerableValueOrNameByValueOrCallback, grandParent?: PossibleEnumerableValueOrNameByValueOrCallback,) { if (arguments.length === 0) { super() this.#parent = lazy(() => super.parent,) this.#grandParent = lazy(() => _getGrandParentValueFromName(this, this.name,),) return } super(parent,) if (arguments.length === 1) { this.#parent = lazy(() => super.parent,) this.#grandParent = lazy(() => _getGrandParentValueFromName(this, this.name,),) return } this.#parent = lazy(() => { const parent = super.parent const grandParent = this.grandParent if (parent == null) if (grandParent != null) throw new ImpossibleIntegrityException(`The parent reference in “${this.constructor.name}” was not expected to be null when its grandparent is not-null.`, this,) return parent },) if (grandParent instanceof Function) grandParent = grandParent() if (grandParent == null) { this.#grandParent = CommonLazy.NULL return } this.#grandParent = lazy(() => { if (typeof grandParent == "string") return _getGrandParentValueFromName(this, grandParent,) if (grandParent === EnumConstants.NULL_ENUM_REFERENCE_SYMBOL) return null if (grandParent === EnumConstants.ENUM_REFERENCE_BY_ITS_NAME_SYMBOL) return _getGrandParentValueFromName(this, this.name,) if (grandParent instanceof String) return _getGrandParentValueFromName(this, grandParent.valueOf(),) return grandParent },) } //#endregion -------------------- Constructor -------------------- //#region -------------------- Getter methods -------------------- /** * The {@link NullOr nullable} parent of the current instance * * @lazy * @throws ImpossibleIntegrityException The value was `null` when the {@link grandParent} was not `null` * @throws NullReferenceException An error happened while attempting to retrieve the parent value */ public override get parent(): NullOr { return this.#parent.value } /** * The {@link NullOr nullable} grandparent of the current instance * * @lazy * @throws NullReferenceException An error happened while attempting to retrieve the grandparent value */ public get grandParent(): NullOr { return this.#grandParent.value } //#endregion -------------------- Getter methods -------------------- }