(function(window) { var Gitana = window.Gitana; Gitana.AbstractNode = Gitana.AbstractRepositoryObject.extend( /** @lends Gitana.AbstractNode.prototype */ { /** * @constructs * @augments Gitana.AbstractRepositoryObject * * @class Abstract base class for Gitana Node implementations. * * @param {Gitana.Branch} branch * @param {Object} [object] */ constructor: function(branch, object) { // helper methods for system-managed state this.__qname = (function() { var _qname = null; return function(qname) { if (!Gitana.isUndefined(qname)) { _qname = qname; } return _qname; }; })(); this.__type = (function() { var _type = null; return function(type) { if (!Gitana.isUndefined(type)) { _type = type; } return _type; }; })(); this.__features = (function() { var _features = {}; return function(features) { if (!Gitana.isUndefined(features)) { _features = features; } return _features; }; })(); this.__stats = (function() { var _stats = {}; return function(stats) { if (!Gitana.isUndefined(stats)) { _stats = stats; } return _stats; }; })(); this.__is_association = (function() { var _is_association = false; return function(is_association) { if (!Gitana.isUndefined(is_association)) { _is_association = is_association; } return _is_association; }; })(); // now call base // important this happens AFTER helpers above so that handleSystemProperties works this.base(branch.getRepository(), object); ////////////////////////////////////////////////////////////////////////////////////////////// // // PRIVILEGED METHODS // ////////////////////////////////////////////////////////////////////////////////////////////// /** * Gets the Gitana Branch object. * * @inner * * @returns {Gitana.Branch} The Gitana Branch object */ this.getBranch = function() { return branch; }; /** * Gets the Gitana Branch id. * * @inner * * @returns {String} The Gitana Branch id */ this.getBranchId = function() { return branch.getId(); }; }, /** * @override */ getUri: function() { return "/repositories/" + this.getRepositoryId() + "/branches/" + this.getBranchId() + "/nodes/" + this.getId(); }, /** * @override */ ref: function() { return "node://" + this.getPlatformId() + "/" + this.getRepositoryId() + "/" + this.getBranchId() + "/" + this.getId(); }, /** * @override */ clone: function() { return this.getFactory().node(this.getBranch(), this); }, /** * @override */ handleSystemProperties: function(response) { this.base(response); // strip out "_qname" if (this["_qname"]) { var _qname = this["_qname"]; delete this["_qname"]; this.__qname(_qname); } // strip out "_type" if (this["_type"]) { var _type = this["_type"]; delete this["_type"]; this.__type(_type); } // strip out "_features" if (this["_features"]) { var _features = this["_features"]; delete this["_features"]; this.__features(_features); } // strip out "_statistics" if (this["_statistics"] && typeof(this["_statistics"]) == "object") { var stats = this["_statistics"]; delete this["_statistics"]; this.__stats(stats); } // strip out "_is_association" if (!Gitana.isUndefined(this["_is_association"])) { var _is_association = this["_is_association"]; delete this["_is_association"]; this.__is_association(_is_association); } }, /** * Override to include: * * __qname * __type * __features * __stats * __is_association * * @param otherObject */ chainCopyState: function(otherObject) { this.base(otherObject); if (otherObject.__qname) { this.__qname(otherObject.__qname()); } if (otherObject.__type) { this.__type(otherObject.__type()); } if (otherObject.__features) { this.__features(otherObject.__features()); } if (otherObject.__stats) { this.__stats(otherObject.__stats()); } if (otherObject.__is_association) { this.__is_association(otherObject.__is_association()); } }, /** * Hands back the stats. */ stats: function() { return this.__stats(); }, /////////////////////////////////////////////////////////////////////////////////////////////////////////// // // FEATURES // /////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Hands back a list of the feature ids that this node has. * * @public * * @param [Function] callback optional callback * * @returns {Array} An array of strings that are the ids of the features. */ getFeatureIds: function(callback) { var self = this; var f = function() { var featureIds = []; for (var featureId in this.__features()) { featureIds[featureIds.length] = featureId; } return featureIds; }; if (callback) { return this.then(function() { callback.call(this, f.call(self)); }); } return f.call(self); }, /** * Gets the configuration for a given feature. * * @public * * @param {String} featureId the id of the feature * @param [Function] callback optional callback * * @returns {Object} the JSON object configuration for the feature */ getFeature: function(featureId, callback) { var self = this; if (callback) { return this.then(function() { callback.call(this, self.__features()[featureId]); }); } return self.__features()[featureId]; }, /** * Removes a feature from this node. * * @public * * @param {String} featureId the id of the feature */ removeFeature: function(featureId) { var self = this; var uriFunction = function() { return self.getUri() + "/features/" + featureId; }; return this.chainDelete(this, uriFunction).reload().then(function() { self.loadFrom(this); }); }, /** * Adds a feature to this node. * * @public * @param {String} featureId the id of the feature * @param [Object] featureConfig the JSON object configuration for the feature */ addFeature: function(featureId, featureConfig) { var self = this; var uriFunction = function() { return self.getUri() + "/features/" + featureId; }; if (!featureConfig) { featureConfig = {}; } return this.chainPostEmpty(null, uriFunction, {}, featureConfig).reload().then(function() { self.loadFrom(this); }); }, /** * Indicates whether this node has the given feature. * * @public * * @param {String} featureId the id of the feature * @param [Function] callback optional callback to receive result (for chaining) * * @returns {Boolean} whether this node has this feature */ hasFeature: function(featureId, callback) { if (callback) { return this.then(function() { var hasFeature = !Gitana.isEmpty(this.__features()[featureId]); callback.call(this, hasFeature); }); } return !Gitana.isEmpty(this.__features()[featureId]); }, /** * Indicates whether the current object is an association. * * @public * * @returns {Boolean} whether this node is an association */ isAssociation: function() { return this.__is_association(); }, /** * Indicates whether this node has the "f:container" feature * * @public * * @returns {Boolean} whether this node has the "f:container" feature */ isContainer: function() { return this.hasFeature("f:container"); }, /** * Touches the node. * * @public * * @chained node (this) */ touch: function() { var self = this; var uriFunction = function() { return self.getUri() + "/touch"; }; return this.chainPost(null, uriFunction); }, /** * Refreshes the node. This allows the node to reindex and regenerate any renditions it may * have associated with it. * * @public * * @chained node (this) */ refresh: function() { var self = this; var uriFunction = function() { return self.getUri() + "/refresh"; }; return this.chainPost(null, uriFunction); }, ////////////////////////////////////////////////////////////////////////////////////////// // // TYPE // ////////////////////////////////////////////////////////////////////////////////////////// /** * Gets the type QName for this node. * * @public * * @returns {String} the type qname of this node. */ getTypeQName: function() { return this.__type(); }, /** * Changes the type QName for this node. * * @public * @param {String} typeQName the qname of the type to change to */ changeTypeQName: function(typeQName) { var self = this; var uriFunction = function() { return self.getUri() + "/change_type?type=" + typeQName; }; return this.chainPostEmpty(null, uriFunction).reload().then(function() { self.loadFrom(this); }); }, ////////////////////////////////////////////////////////////////////////////////////////// // // QNAME // ////////////////////////////////////////////////////////////////////////////////////////// /** * Gets the QName for this node. * * @public * * @returns {String} the qname of this node. */ getQName: function() { return this.__qname(); }, /** * Sets the QName of this node. * * @public * @param {String} typeQName the qname of the type to change to */ changeQName: function(qname) { var self = this; var uriFunction = function() { return self.getUri() + "/change_qname?qname=" + qname; }; return this.chainPostEmpty(null, uriFunction).reload().then(function() { self.loadFrom(this); }); }, ////////////////////////////////////////////////////////////////////////////////////////// // // ATTACHMENTS // ////////////////////////////////////////////////////////////////////////////////////////// /** * Lists the attachments of this node. * * If local is set to true, the attachments are drawn from precached values on the node. * * @chained attachment map * * @param local * * @public */ listAttachments: Gitana.Methods.listAttachments(Gitana.NodeAttachmentMap), /** * Picks off a single attachment * * @chained attachment * * @param attachmentId (null for default) */ attachment: function(attachmentId) { return this.listAttachments().select(attachmentId); }, /** * Non-chained method for getting a download URI for this node's attachment. */ attachmentDownloadUri: function(attachmentId) { return this.getDriver().baseURL + this.getUri() + "/attachments/" + attachmentId; }, /** * Creates an attachment. * * When using this method from within the browser, it really only works for text-based content such * as JSON or text. * * @chained attachment * * @param attachmentId (use null or false for default attachment) * @param contentType * @param data * @param filename */ attach: function(attachmentId, contentType, data, filename) { var paramsFunction = function(params) { if (filename) { params["filename"] = filename; } }; var delegate = Gitana.Methods.attach.call(this, Gitana.NodeAttachment, paramsFunction); return delegate.call(this, attachmentId, contentType, data); }, /** * Generates a URI to a preview resource. */ getPreviewUri: Gitana.Methods.getPreviewUri(), /** * Deletes an attachment. * * @param attachmentId */ unattach: Gitana.Methods.unattach() }); })(window);