var Montage = require("../../core").Montage,
MontageReviver = require("./montage-reviver").MontageReviver,
Promise = require("../../promise").Promise,
deprecate = require("../../deprecate"),
ONE_ASSIGNMENT = "=",
ONE_WAY = "<-",
TWO_WAY = "<->";
/**
* @deprecated
*/
var MontageInterpreter = Montage.specialize({
_require: {value: null},
_reviver: {value: null},
init: {
value: function (_require, reviver) {
deprecate.deprecationWarningOnce("MontageInterpreter", "MontageDeserializer");
if (typeof _require !== "function") {
throw new Error("Function 'require' missing.");
}
this._reviver = reviver;
this._require = _require;
return this;
}
},
instantiate: {
value: function (serialization, objects, element) {
var context;
context = new exports.MontageContext()
.init(serialization, this._reviver, objects, element, this._require);
return context.getObjects();
}
},
preloadModules: {
value: function (serialization) {
var reviver = this._reviver,
moduleLoader = reviver.moduleLoader,
object,
locationId,
locationDesc,
module,
promises = [];
for (var label in serialization) {
if (serialization.hasOwnProperty(label)) {
object = serialization[label];
locationId = object.prototype || object.object;
if (locationId) {
if (typeof locationId !== "string") {
throw new Error(
"Property 'object' of the object with the label '" +
label + "' must be a module id"
);
}
locationDesc = MontageReviver.parseObjectLocationId(locationId);
module = moduleLoader.getModule(
locationDesc.moduleId, label);
if (Promise.is(module)) {
promises.push(module);
}
}
}
}
if (promises.length > 0) {
return Promise.all(promises);
}
}
}
});
var MontageContext = Montage.specialize({
_ELEMENT_ID_ATTRIBUTE: {value: "data-montage-id"},
_unitsToDeserialize: {value: null},
_element: {value: null},
_require: {value: null},
_objects: {value: null},
_userObjects: {value: null},
_serialization: {value: null},
_reviver: { value: null },
_bindingsToDeserialize: { value: null },
constructor: {
value: function () {
this._unitsToDeserialize = [];
}
},
init: {
value: function (serialization, reviver, objects, element, _require) {
this._reviver = reviver;
this._serialization = serialization;
this._objects = Object.create(null);
if (objects) {
this._userObjects = Object.create(null);
/* jshint forin: true */
for (var label in objects) {
/* jshint forin: false */
this._userObjects[label] = objects[label];
}
}
this._element = element;
this._require = _require;
return this;
}
},
setObjectLabel: {
value: function(object, label) {
this._objects[label] = object;
}
},
getObject: {
value: function(label) {
var serialization = this._serialization,
reviver = this._reviver,
objects = this._objects,
object;
if (label in objects) {
return objects[label];
} else if (label in serialization) {
object = reviver.reviveRootObject(serialization[label], this, label);
// If no object has been set by the reviver we safe its
// return, it could be a value or a promise, we need to
// make sure the object won't be revived twice.
if (!(label in objects)) {
objects[label] = object;
}
return object;
} else {
return Promise.reject(
new Error("Object with label '" + label + "' was not found.")
);
}
}
},
getObjects: {
value: function() {
var self = this,
serialization = this._serialization,
promises = [],
result;
for (var label in serialization) {
if (serialization.hasOwnProperty(label)) {
result = this.getObject(label);
if (Promise.is(result)) {
promises.push(result);
}
}
}
if (promises.length === 0) {
return Promise.resolve(this._invokeDidReviveObjects());
} else {
return Promise.all(promises).then(function() {
return self._invokeDidReviveObjects();
});
}
}
},
hasUserObject: {
value: function(label) {
var userObjects = this._userObjects;
if (userObjects) {
return label in userObjects;
} else {
return false;
}
}
},
getUserObject: {
value: function(label) {
var userObjects = this._userObjects;
if (userObjects) {
return userObjects[label];
}
}
},
_invokeDidReviveObjects: {
value: function() {
var self = this,
reviver = this._reviver,
result;
if (typeof reviver.didReviveObjects === "function") {
result = reviver.didReviveObjects(this._objects, this);
if (Promise.is(result)) {
return result.then(function() {
return self._objects;
});
}
}
return this._objects;
}
},
hasObject: {
value: function (label) {
return label in this._serialization;
}
},
getRequire: {
value: function () {
return this._require;
}
},
getElement: {
value: function () {
return this._element;
}
},
getElementById: {
value: function (id) {
var selector = '*[' + this._ELEMENT_ID_ATTRIBUTE + '="' + id + '"]';
return this._element.querySelector(selector);
}
},
_extractBindingsToDeserialize: {
value: function (values, bindings) {
var value;
for (var key in values) {
if (values.hasOwnProperty(key)) {
value = values[key];
if ((typeof value === "object" && value &&
Object.keys(value).length === 1 &&
(ONE_WAY in value || TWO_WAY in value || ONE_ASSIGNMENT in value)) ||
key.indexOf('.') > -1
) {
bindings[key] = value;
delete values[key];
}
}
}
return bindings;
}
},
getBindingsToDeserialize: {
value: function () {
return this._bindingsToDeserialize;
}
},
setBindingsToDeserialize: {
value: function (object, objectDesc) {
var bindings = Object.create(null);
if (objectDesc.values) {
this._extractBindingsToDeserialize(objectDesc.values, bindings);
} else if (objectDesc.properties) { // deprecated
this._extractBindingsToDeserialize(objectDesc.properties, bindings);
}
if (Object.keys(bindings).length > 0) {
if (!this._bindingsToDeserialize) {
this._bindingsToDeserialize = [];
}
this._bindingsToDeserialize.push({
object: object,
bindings: bindings
});
}
}
},
setUnitsToDeserialize: {
value: function (object, objectDesc, unitNames) {
this._unitsToDeserialize.push({
object: object,
objectDesc: objectDesc,
unitNames: unitNames
});
}
},
getUnitsToDeserialize: {
value: function () {
return this._unitsToDeserialize;
}
}
});
exports.MontageInterpreter = MontageInterpreter;
exports.MontageContext = MontageContext;