aboutsummaryrefslogtreecommitdiff
path: root/node_modules/montage/data/objectproperty.js
blob: de2e861b2234970a033fc011f656af38a3933d1d (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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
/* <copyright>
 This file contains proprietary software owned by Motorola Mobility, Inc.<br/>
 No rights, expressed or implied, whatsoever to this software are provided by Motorola Mobility, Inc. hereunder.<br/>
 (c) Copyright 2011 Motorola Mobility, Inc.  All Rights Reserved.
 </copyright> */
/**
	@module montage/data/objectproperty
    @requires montage/core/core
    @requires montage/core/logger
*/
var Montage = require("montage").Montage;
var Pledge = require("data/pledge").Pledge;
var PledgedSortedSet = require("data/pledge").PledgedSortedSet;
var logger = require("core/logger").logger("objectproperty");
/**
  Description TODO
  @private
*/
var _objectPropertyManager = null;
/**
    @class module:montage/data/objectproperty.ObjectProperty
    @extends module:montage/core/core.Montage
*/
var ObjectProperty = exports.ObjectProperty = Montage.create(Montage,/** @lends module:montage/data/objectproperty.ObjectProperty# */ {
/**
    Description TODO
    @function
    @returns itself
    */
    init: {
        serializable: false,
        enumerable: false,
        value: function() {
            return this;
        }
    },

/**
    Add all the properties defined in the blueprint to the target prototype.<br>
    If the blueprint is null, this method will make a best attempt to locate it.
    @function
    @param {Property} prototype TODO
    @param {Object} blueprint TODO
    */
    apply: {
        value: function(prototype, blueprint) {
            if (! prototype.hasOwnProperty("blueprint")) {
                var info;
                info = Montage.getInfoForObject(prototype);
                if (info != null && info.isInstance === false) {
                    if (typeof blueprint === "undefined") {
                        blueprint = Store.defaultManager.blueprintForPrototype(info.objectName, info.moduleId);
                    } else if ((blueprint.prototypeName !== info.objectName) || (blueprint.moduleId !== info.moduleId)) {
                        // Something is wrong, the hierarchies are out of wack
                        blueprint = null;
                    }
                    this.applyWithBlueprint(prototype, blueprint);
                }
            }
        }
    },

/**
    Add all the properties defined in the blueprint to the target prototype.
    @function
    @param {Property} prototype TODO
    @param {Object} blueprint TODO
    */
    applyWithBlueprint: {
        value: function(prototype, blueprint) {
            if (blueprint != null) {
                this.addProperties(prototype, blueprint);
                if (blueprint.parent !== null) {
                    this.apply(Object.getPrototypeOf(prototype), blueprint);
                }
            }
        }
    },
/**
    Description TODO
    @function
    @param {Property} prototype TODO
    @param {Object} blueprint TODO
    */
    addProperties: {
        value: function(prototype, blueprint) {
            //for loop over attributes
            var i, attribute;
            for (i = 0; attribute = blueprint.attributes[i]; i++) {
                if (attribute.isDerived) {
                    this.addDerivedProperty(prototype, attribute);
                } else {
                    this.addProperty(prototype, attribute);
                }
            }

            Montage.defineProperty(prototype, "context", { serializable: false, enumerable: true, value: null });
            Montage.defineProperty(prototype, "_objectId", { serializable: true, enumerable: false, value: null });
            Montage.defineProperty(prototype, "objectId", {
                enumerable: true,
                serializable: false,
                get: function() {
                    if (this._objectId === null) {
                        this._objectId = this.blueprint.objectId$Implementation;
                    }
                    return this._objectId;
                },
                set: function(value) {
                    if (value !== null) {
                        this._objectId = value;
                    } else {
                        throw Exception.create().initWithMessageTargetAndMethod("Cannot set object Id to null", this, "objectId.set");
                    }
                }
            });
            Montage.defineProperty(prototype, "_blueprint", { serializable: false, enumerable: false, value: blueprint });
            Montage.defineProperty(prototype, "blueprint", { enumerable: false, serializable: false, get: function() {
                return this._blueprint;
            }});
            Montage.defineProperty(prototype, "isPledge", { serializable: false, enumerable: true, value: false });
            Montage.defineProperty(prototype, "withProperties", { serializable: false, enumerable: false, value: function() {
                return null;
            }});
            Montage.defineProperty(prototype, "willRead", { serializable: false, enumerable: false, value: this.willRead });
            Montage.defineProperty(prototype, "willModify", { serializable: false, enumerable: false, value: this.willModify });
            // Enable access to the 'inherited' get method for easy override.
            Montage.defineProperty(prototype, "blueprintGet", { serializable: false, enumerable: false, value: blueprint.blueprintGet});
            // Enable access to the 'inherited' set method for easy override.
            Montage.defineProperty(prototype, "blueprintSet", { serializable: false, enumerable: false, value: blueprint.blueprintSet});
            // Provide a storage property for any state the access layer need to store in teh object. This would typically be a database snapshot reference.
            Montage.defineProperty(prototype, "_opaqueAccessState", { serializable: false, enumerable: false, value: null});
        }
    },
/**
    Description TODO
    @function
    @param {Property} prototype TODO
    @param {Object} attribute TODO
    */
    addProperty: {
        value: function(prototype, attribute) {
            this.addPropertyStorage(prototype, attribute);
            this.addPropertyDefinition(prototype, attribute);
            this.addPropertyStoredValue(prototype, attribute);
        }
    },
/**
    Description TODO
    @function
    @param {Property} prototype TODO
    @param {Object} attribute TODO
    */
    addPropertyStorage: {
        value: function(prototype, attribute) {
            var storageKey = "_" + attribute.name,
                storageDefinition = null;
            if (! prototype.hasOwnProperty(storageKey)) {
                if (attribute.isToMany) {
                    storageDefinition = {
                        value: [],
                        enumerable: false,
                        serializable: true,
                        distinct: true
                    };
                } else {
                    storageDefinition = {
                        value: null,
                        enumerable: false,
                        serializable: true
                    };
                }
                Montage.defineProperty(prototype, storageKey, storageDefinition);
            } else {
                // We have an issue here. The developer should not override the storage value.
            }
        }
    },
/**
    Description TODO
    @function
    @param {Property} prototype TODO
    @param {Object} attribute TODO
    */
    addPropertyDefinition: {
        value : function(prototype, attribute) {
            var propertyKey = attribute.name,
                propertyDefinition = null;
            if (! prototype.hasOwnProperty(propertyKey)) {
                propertyDefinition = {
                    get: function() {
                        return this.blueprintGet(propertyKey);
                    },
                    enumerable: true,
                    serializable: false
                };
                if (! attribute.readOnly) {
                    propertyDefinition.set = function(value) {
                        return this.blueprintSet(propertyKey, value);
                    };
                }
                Montage.defineProperty(prototype, propertyKey, propertyDefinition);
            } else {
                // The developer has already created the property method do nothing.
            }
        }
    },
/**
    Description TODO
    @function
    @param {Property} prototype TODO
    @param {Object} attribute TODO
    */
    addPropertyStoredValue: {
        value: function(prototype, attribute) {
            var storedValueKey = attribute.name + "$Storage",
                storedValueDefinition = null;
            if (! prototype.hasOwnProperty(storedValueKey)) {
                if (attribute.isToMany) {
                    storedValueDefinition = {
                        value: [],
                        enumerable: false,
                        serializable: false,
                        distinct: true
                    }
                } else {
                    storedValueDefinition = {
                        value: null,
                        enumerable: false,
                        serializable: false
                    }
                }
                Montage.defineProperty(prototype, storedValueKey, storedValueDefinition);
            } else {
                // We have an issue here. The developer should not override the stored value.
            }
        }
    },
/**
    Description TODO
    @function
    @param {Property} prototype TODO
    @param {Object} attribute TODO
    */
    addDerivedProperty: {
        value: function(prototype, attribute) {
        }
    },

/**
    Description TODO
    @function
    @param {Object} attribute TODO
    */
    willRead: {
        value: function(attribute) {
            var storageKey = "_" + attribute.name;
            if (typeof this[storageKey] !== 'undefined') {
                // the property is already resolved nothing to do.
                return;
            }
            if ((typeof this.context !== 'undefined') && (this.context !== null)) {
                this.context.fulfillPropertyForInstance(attribute, this);
            }
        }
    },
/**
    Description TODO
    @function
    @param {Object} attribute TODO
    @param {Property} value TODO
    */
    willModify: {
        value: function(attribute, value) {
            var storageKey = "_" + attribute.name;
            var previousValue = this[storageKey];
            if ((typeof previousValue === 'undefined') || (previousValue !== value)) {
                if ((typeof this.context !== 'undefined') && (this.context !== null)) {
                    this.context.willModifyPropertyForInstance(attribute, this);
                }
            }
        }
    },
    /**
    Returns the transaction manager.<br>
    The transaction manager is a unique object in charge of openning and closing transactions.
    @function
    @returns object
    */
    manager: {
        get: function() {
            if (_objectPropertyManager === null) {
                _objectPropertyManager = Object.freeze(ObjectProperty.create().init());
            }
            return _objectPropertyManager;
        }
    }

});