Completed
Push — master ( d362a9...56faa4 )
by Mark
14s queued 11s
created

Table.toComposedKey   B

Complexity

Conditions 6

Size

Total Lines 16
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 13
dl 0
loc 16
rs 8.6666
c 0
b 0
f 0
1
import {Model} from "./Model.js";
2
import Collection from "./Collection.js";
3
import Index from "./Table/Index";
4
import {TableInterface, ModelInterface, ModelStaticInterface} from "../JeloquentInterfaces";
5
6
/**
7
 *
8
 */
9
export default class Table implements TableInterface {
10
11
    name: string;
12
13
    private _index: Index;
14
15
    private _model: ModelInterface;
16
17
    private _models: Map<string|number, ModelInterface>;
18
19
    private _primaryKeyFieldNames: Array<string>;
20
21
    constructor (model: ModelStaticInterface) {
22
        this.setup(model.getInstance());
23
    }
24
25
    get ids():Array<string|number> {
26
        return [...this._models.keys()];
27
    }
28
29
    get indexes(): Map<string, Map<string|number, Set<string|number>>> {
30
        return this._index.indexes;
31
    }
32
33
    get models(): Map<string|number, ModelInterface> {
34
        return this._models;
35
    }
36
37
    static make(model: ModelStaticInterface): Table {
38
        return new Table(model);
39
    }
40
41
    public addIndex(indexName:string, lookUpKey:string, id:string|number): void {
42
        this._index.addValue(indexName, lookUpKey, id);
43
    }
44
45
    public all(): Collection {
46
        const values = [...this._models.values()];
47
        const numberOfValues = values.length;
48
        const collection = new Collection();
49
        for (let i = 0; i < numberOfValues; i += 10000) {
50
            collection.push(...values.slice(i, i + 10000));
51
        }
52
53
        return collection;
54
    }
55
56
    /**
57
     * @deprecated
58
     */
59
    public allModels(): Map<string | number, ModelInterface> {
60
        return this.models;
61
    }
62
63
    public delete(id:string|number): void {
64
        if (!this._models.has(id)) {
65
            throw new Error('Record doesn\'t exists');
66
        }
67
68
        this._index.removeValueByModel(this.findOne(id));
69
70
        this._models.delete(id);
71
    }
72
73
    public find(id:number|string|object|Array<string|number|object>): Collection|ModelInterface|null {
74
        const hasComposedPrimaryKey = this._primaryKeyFieldNames.length > 1;
75
        if (Array.isArray(id)) {
76
            if (hasComposedPrimaryKey) {
77
                return this.findCollectionComposedPrimaryKey(id as Array<object>);
78
            }
79
            return this.findCollection(id as Array<string|number>);
80
        }
81
82
        if (hasComposedPrimaryKey) {
83
            return this.findOneComposedPrimaryKey(id as object);
84
        }
85
86
        return this.findOne(id as (string|number));
87
    }
88
89
    public getIndexByKey(key: string): Map<string|number, Set<string|number>> {
90
        return this._index.getIndexByKey(key);
91
    }
92
93
    public insert(model: ModelInterface): void {
94
        if (this._models.has(model.primaryKey)) {
95
            throw new Error('Record already exists');
96
        }
97
98
        if (!(model instanceof Model)) {
99
            throw new Error('Record should be instance of model');
100
        }
101
102
        model.resetDirty();
103
104
        if (model.primaryKey != null) {
105
            this._models.set(model.primaryKey, model);
106
        }
107
108
        this._index.addValueByModel(model);
109
    }
110
111
    public registerIndex(indexName:string): void {
112
        this._index.register(indexName);
113
    }
114
115
    public removeIndex(indexName:string, lookUpKey:string, id:string|number): void {
116
        this._index.removeValue(indexName, lookUpKey, id)
117
    }
118
119
    public select(id:string|number): Collection|ModelInterface|null {
120
        if (!this._models.has(id)) {
121
            throw new Error('Record doesn\'t exists');
122
        }
123
124
        return this.find(id);
125
    }
126
127
    public setupIndexes(): void {
128
        this._model.tableSetup(this);
129
    }
130
131
    public truncate(): void {
132
        this._models.clear();
133
        this._index.truncate();
134
    }
135
136
    public update(model: ModelInterface): void {
137
        if (!this.models.has(model.primaryKey)) {
138
            throw new Error('Record doesn\'t exists');
139
        }
140
141
        if (!(model instanceof Model)) {
142
            throw new Error('Record should be instance of model');
143
        }
144
145
        this._index.removeValueByModel(model);
146
147
        model.resetDirty();
148
149
        this._index.addValueByModel(model);
150
151
        this._models.set(model.primaryKey, model);
152
    }
153
154
    private findCollection(id:Array<string|number>): Collection {
155
        const result = [];
156
        for (let i = 0; i < id.length; i++) {
157
            result.push(
158
                this._models.get(id[i])
159
            );
160
        }
161
        return new Collection(...result);
162
    }
163
164
    private findCollectionComposedPrimaryKey(id: Array<object>): Collection {
165
        const result = [];
166
        for (let i = 0; i < id.length; i++) {
167
            result.push(
168
                this._models.get(
169
                    this.toComposedKey(id[i])
170
                )
171
            );
172
        }
173
        return new Collection(...result);
174
    }
175
176
    private findOne(id: string|number): ModelInterface|null {
177
        return this._models.get(id) ?? null;
178
    }
179
180
    private findOneComposedPrimaryKey(id: object|string): ModelInterface|null {
181
        return this._models.get(this.toComposedKey(id)) ?? null;
182
    }
183
184
    private setup(model: ModelInterface) {
185
        this.name = model.className;
186
        this._primaryKeyFieldNames = model.primaryKeyName;
187
188
        this._model = model;
189
        this._models = new Map();
190
        this._index = new Index();
191
    }
192
193
    private toComposedKey(id:string|object): string|null {
194
        if (typeof id === 'string') {
195
            return id;
196
        }
197
198
        if (id === null) {
199
            return null;
200
        }
201
202
        const key = [];
203
        for (let i = 0; i < this._primaryKeyFieldNames.length; i++) {
204
            key.push(id[this._primaryKeyFieldNames[i]] ?? '');
205
        }
206
207
        return key.join('-');
208
    }
209
}