aboutsummaryrefslogtreecommitdiff
path: root/src/fields/Document.ts
blob: ef759615bc4e728e81ddf1d86a9d16268fb9fb75 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import { Field, Cast, Opt } from "./Field"
import { Key, KeyStore } from "./Key"
import { NumberField } from "./NumberField";
import { ObservableMap, computed } from "mobx";
import { TextField } from "./TextField";
import { ListField } from "./ListField";

export class Document extends Field {
    private fields: ObservableMap<Key, Field> = new ObservableMap();

    static _untitledDocName = "<untitled>";
    @computed
    public get Title() { return this.GetFieldValue(KeyStore.Title, TextField, Document._untitledDocName); }

    GetField(key: Key, ignoreProto: boolean = false): Opt<Field> {
        let field: Opt<Field>;
        if (ignoreProto) {
            if (this.fields.has(key)) {
                field = this.fields.get(key);
            }
        } else {
            let doc: Opt<Document> = this;
            while (doc && !(doc.fields.has(key))) {
                doc = doc.GetPrototype();
            }

            if (doc) {
                field = doc.fields.get(key);
            }
        }

        return field;
    }

    GetFieldT<T extends Field = Field>(key: Key, ctor: { new(...args: any[]): T }, ignoreProto: boolean = false): Opt<T> {
        return Cast(this.GetField(key, ignoreProto), ctor);
    }

    GetFieldOrCreate<T extends Field>(key: Key, ctor: { new(): T }, ignoreProto: boolean = false): T {
        const field = this.GetFieldT(key, ctor, ignoreProto);
        if (field) {
            return field;
        }
        const newField = new ctor();
        this.SetField(key, newField);
        return newField;
    }

    GetFieldValue<T, U extends { Data: T }>(key: Key, ctor: { new(): U }, defaultVal: T): T {
        let val = this.GetField(key);
        let vval = (val && val instanceof ctor) ? val.Data : defaultVal;
        return vval;
    }

    GetNumberField(key: Key, defaultVal: number): number {
        return this.GetFieldValue(key, NumberField, defaultVal);
    }

    GetTextField(key: Key, defaultVal: string): string {
        return this.GetFieldValue(key, TextField, defaultVal);
    }

    GetListField<T extends Field>(key: Key, defaultVal: T[]): T[] {
        return this.GetFieldValue<T[], ListField<T>>(key, ListField, defaultVal)
    }

    SetField(key: Key, field: Field | undefined): void {
        if (field) {
            this.fields.set(key, field);
        } else {
            this.fields.delete(key);
        }
    }

    SetFieldValue<T extends Field>(key: Key, value: any, ctor: { new(): T }): boolean {
        let field = this.GetField(key, true);
        if (field != null) {
            return field.TrySetValue(value);
        } else {
            field = new ctor();
            if (field.TrySetValue(value)) {
                this.SetField(key, field);
                return true;
            } else {
                return false;
            }
        }
    }

    GetPrototype(): Opt<Document> {
        return this.GetFieldT(KeyStore.Prototype, Document, true);
    }

    GetAllPrototypes(): Document[] {
        let protos: Document[] = [];
        let doc: Opt<Document> = this;
        while (doc != null) {
            protos.push(doc);
            doc = doc.GetPrototype();
        }
        return protos;
    }

    MakeDelegate(): Document {
        let delegate = new Document();

        delegate.SetField(KeyStore.Prototype, this);

        return delegate;
    }

    TrySetValue(value: any): boolean {
        throw new Error("Method not implemented.");
    }
    GetValue() {
        throw new Error("Method not implemented.");
    }
    Copy(): Field {
        throw new Error("Method not implemented.");
    }


}