accelerator-core
Version:
[](https://travis-ci.org/furkleindustries/accelerator-core)
253 lines (213 loc) • 5.96 kB
text/typescript
import {
addTag,
} from '../../tags/addTag';
import {
EpistemicTypes,
} from '../epistemology/EpistemicTypes';
import {
getStructuredTags,
} from '../../tags/getStructuredTags';
import {
getTag,
} from '../../tags/getTag';
import {
IEpistemology,
} from '../epistemology/IEpistemology';
import {
IFindBaseArgs,
} from '../querying/FindModelArgs';
import {
IModel,
} from './IModel';
import {
IModelConstructorArgs,
} from './IModelConstructorArgs';
import {
IOntology,
} from '../ontology/IOntology';
import {
ISerializedModel,
} from './ISerializedModel';
import {
ITag,
} from '../../tags/ITag';
import {
IWorld,
} from '../world/IWorld';
import {
ModelType,
} from './ModelType';
import {
OnticTypes,
} from '../ontology/OnticTypes';
import {
removeTag,
} from '../../tags/removeTag';
import {
Tag,
} from '../../tags/Tag';
import {
assert,
assertValid,
} from 'ts-assertions';
export abstract class ModelBase<
Type extends ModelType,
Being extends OnticTypes = any,
Knowledge extends ModelType = any,
> implements IModel<Type, Being, Knowledge>
{
public abstract readonly being: Type extends OnticTypes ?
IOntology<Type, Being> :
null;
public abstract readonly knowledge: Type extends EpistemicTypes ?
IEpistemology<Type, Knowledge> :
null;
private readonly __name: string;
public get name() {
return this.__name;
}
private __tags: readonly ITag[] = Object.freeze<ITag>([]);
public get tags() {
return this.__tags;
}
protected readonly __type: Type;
public get type() {
return this.__type;
}
private readonly __world: IWorld;
public get world() {
return this.__world;
}
constructor(
world: IWorld,
args: IModelConstructorArgs<Type, Being, Knowledge>,
) {
this.__world = assertValid(
world,
'The world argument was not provided to the ModelBase constructor.',
);
assert(
args,
'The args argument was not provided to the ModelBase constructor.',
);
const {
name,
tags,
type,
} = args;
assert(
name && typeof name === 'string',
'The name property of the argument provided to the ModelBase ' +
'constructor was not a string with content.',
);
assert(
Object.values(ModelType).includes(type),
'The type property of the argument provided to the ModelBase ' +
'constructor was not a valid ModelType.',
);
this.__name = name;
this.__type = type;
if (tags) {
this.__tags = this.tags.concat(getStructuredTags(tags));
}
this.initialize(this as any);
}
public readonly addTag = (tag: Tag) => (
void (this.__tags = Object.freeze(addTag(tag, this.tags)))
);
public readonly clone = (
self: IModel<Type, Being, Knowledge>,
): IModel<Type, Being, Knowledge> => {
const copy = Object.assign(
Object.create(Object.getPrototypeOf(self)),
self,
);
copy.__being = self.being ? self.being.clone(self.being as any) : null;
copy.__name = self.name;
copy.__knowledge = self.knowledge ?
self.knowledge.clone(self.knowledge!) :
null;
copy.__tags = self.tags.slice();
copy.__type = self.type;
copy.__world = self.world;
return copy;
};
public readonly destroy = (self: IModel<Type, Being, Knowledge>): void => {
((self: any) => {
self.finalize(self);
if (self.being) {
self.being.destroy(self.being);
}
if (self.knowledge) {
self.knowledge.destroy(self.knowledge);
}
self.tags.forEach(self.removeTag);
delete self.__being;
delete self.being;
delete self.__knowledge;
delete self.knowledge;
delete self.__tags;
delete self.tags;
delete self.__type;
delete self.type;
delete self.__world;
delete self.world;
})(self);
};
public readonly finalize = (self: IModel<Type, Being, Knowledge>): void => {
if (self.being && typeof self.being.finalize === 'function') {
self.being.finalize(self.being as any);
}
if (self.knowledge && typeof self.knowledge.finalize === 'function') {
self.knowledge.finalize(self.knowledge!);
}
};
public readonly find = (
args: string | IFindBaseArgs<ModelType>,
): IModel<ModelType, Being, Knowledge> | null => this.findAllGenerator(
typeof args === 'string' ?
{ name: args } :
args,
).next().value || null;
public readonly findAll = (
args: '*' | IFindBaseArgs<ModelType>,
): readonly IModel<ModelType, Being, Knowledge>[] => {
const ret = [];
for (const model of this.findAllGenerator(args)) {
ret.push(model);
}
return ret;
};
public abstract readonly findAllGenerator: (
args: '*' | IFindBaseArgs<ModelType>,
) => IterableIterator<IModel<ModelType, Being, Knowledge>>;
public readonly getTag = (toSearch: Tag) => (
getTag(this.tags, toSearch)
);
public readonly initialize = (self: IModel<Type, Being, Knowledge>): void => {
if (self.being && typeof self.being.initialize === 'function') {
self.being.initialize(self.being as any);
}
if (self.knowledge && typeof self.knowledge.initialize === 'function') {
self.knowledge.initialize(self.knowledge!);
}
};
public readonly removeTag = (tag: Tag) => (
void (this.__tags = Object.freeze(removeTag(this.tags, tag)))
);
public readonly serialize = (
self: IModel<Type, Being, Knowledge>,
spaces: number = 0,
) => JSON.stringify(self.serializeToObject(self), null, spaces);
public readonly serializeToObject = (
self: IModel<Type, Being, Knowledge>,
): ISerializedModel => ({
being: self.being ? self.being.serializeToObject(self.being as any) : null,
knowledge: self.knowledge ?
self.knowledge.serializeToObject(self.knowledge!) :
null,
name: self.name,
tags: [ ...self.tags ],
type: self.type,
});
}