summaryrefslogtreecommitdiff
path: root/src/core/DataObject.vala
blob: 4d4566e0f5906778b49dfeac236eff6b588c63fa (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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/* Copyright 2016 Software Freedom Conservancy Inc.
 *
 * This software is licensed under the GNU LGPL (version 2.1 or later).
 * See the COPYING file in this distribution.
 */

//
// DataObject
//
// Object IDs are incremented for each DataObject, and therefore may be used to compare
// creation order.  This behavior may be relied upon elsewhere.  Object IDs may be recycled when
// DataObjects are reconstituted by a proxy.
//
// Ordinal IDs are supplied by DataCollections to record the ordering of the object being added
// to the collection.  This value is primarily only used by DataCollection, but may be used
// elsewhere to resolve ordering questions (including stabilizing a sort).
//

// Have to inherit from Object due to ContainerSource and this bug:
// https://bugzilla.gnome.org/show_bug.cgi?id=615904
public abstract class DataObject : Object {
    public const int64 INVALID_OBJECT_ID = -1;
    
    private static int64 object_id_generator = 0;
    
#if TRACE_DTORS
    // because calling to_string() in a destructor is dangerous, stash to_string()'s result in
    // this variable for reporting
    protected string dbg_to_string = null;
#endif
    
    private int64 object_id = INVALID_OBJECT_ID;
    private DataCollection member_of = null;
    private int64 ordinal = DataCollection.INVALID_OBJECT_ORDINAL;
    
    // NOTE: Supplying an object ID should *only* be used when reconstituting the object (generally
    // only done by DataSources).
    public DataObject(int64 object_id = INVALID_OBJECT_ID) {
        this.object_id = (object_id == INVALID_OBJECT_ID) ? object_id_generator++ : object_id;
    }
    
    public virtual void notify_altered(Alteration alteration) {
        if (member_of != null)
            member_of.internal_notify_altered(this, alteration);
    }
    
    // There is no membership_changed signal as it's expensive (esp. at startup) and not needed
    // at this time.  The notify_membership_changed mechanism is still in place for subclasses.
    //
    // This is called after the change has occurred (i.e., after the DataObject has been added
    // to the DataCollection, or after it has been remove from the same).  It is also called after
    // the DataCollection has reported the change on its own signals, so it and its children can
    // properly integrate the DataObject into its pools.
    //
    // This is only called by DataCollection.
    public virtual void notify_membership_changed(DataCollection? collection) {
    }
    
    // Generally, this is only called by DataCollection.  No signal is bound to this because
    // it's not needed currently and affects performance.
    public virtual void notify_collection_property_set(string name, Value? old, Value val) {
    }
    
    // Generally, this is only called by DataCollection.  No signal is bound to this because
    // it's not needed currently and affects performance.
    public virtual void notify_collection_property_cleared(string name) {
    }
    
    public abstract string get_name();
    
    public abstract string to_string();
    
    public DataCollection? get_membership() {
        return member_of;
    }
    
    public bool has_membership() {
        return member_of != null;
    }
    
    // This method is only called by DataCollection.  It's called after the DataObject has been
    // assigned to a DataCollection.
    public void internal_set_membership(DataCollection collection, int64 ordinal) {
        assert(member_of == null);
        
        member_of = collection;
        this.ordinal = ordinal;
        
#if TRACE_DTORS
        dbg_to_string = to_string();
#endif
    }
    
    // This method is only called by SourceHoldingTank (to give ordinality to its unassociated
    // members).  DataCollections should call internal_set_membership.
    public void internal_set_ordinal(int64 ordinal) {
        assert(member_of == null);
        
        this.ordinal = ordinal;
    }
    
    // This method is only called by DataCollection.  It's called after the DataObject has been
    // assigned to a DataCollection.
    public void internal_clear_membership() {
        member_of = null;
        ordinal = DataCollection.INVALID_OBJECT_ORDINAL;
    }
    
    // This method is only called by DataCollection, DataSet, and SourceHoldingTank.
    public inline int64 internal_get_ordinal() {
        return ordinal;
    }
    
    public inline int64 get_object_id() {
        return object_id;
    }
    
    public Value? get_collection_property(string name, Value? def = null) {
        if (member_of == null)
            return def;
        
        Value? result = member_of.get_property(name);
        
        return (result != null) ? result : def;
    }
    
    public void set_collection_property(string name, Value val, ValueEqualFunc? value_equals = null) {
        if (member_of != null)
            member_of.set_property(name, val, value_equals);
    }
    
    public void clear_collection_property(string name) {
        if (member_of != null)
            member_of.clear_property(name);
    }
}