1 (function (GCN) {
  2 
  3 	'use strict';
  4 
  5 	/**
  6 	 * Maps contracts that were fetched via the Rest API into a flat hash map.
  7 	 *
  8 	 * @param {object<string, object>} categories
  9 	 * @return {object<string, object>}
 10 	 */
 11 	function mapConstructs(categories) {
 12 		var groupName;
 13 		var group;
 14 		var constructName;
 15 		var construct;
 16 		var map = {};
 17 
 18 		for (groupName in categories) {
 19 			if (categories.hasOwnProperty(groupName)) {
 20 				group = categories[groupName].constructs;
 21 
 22 				for (constructName in group) {
 23 					if (group.hasOwnProperty(constructName)) {
 24 						construct = group[constructName];
 25 						map[constructName] = construct;
 26 					}
 27 				}
 28 			}
 29 		}
 30 
 31 		return map;
 32 	}
 33 
 34 	/**
 35 	 * Node object.
 36 	 *
 37 	 * @name NodeAPI
 38 	 * @class
 39 	 * @augments Chainback
 40 	 */
 41 	var NodeAPI = GCN.defineChainback({
 42 		/** @lends NodeAPI */
 43 
 44 		__chainbacktype__: 'NodeAPI',
 45 		_extends: GCN.ContentObjectAPI,
 46 		_type: 'folder',
 47 
 48 		_data: {
 49 			folderId: null
 50 		},
 51 
 52 		/**
 53 		 * @protected
 54 		 * @type {object<string, number} Constructs for this node are cached
 55 		 *                               here so that we only need to fetch
 56 		 *                               this once.
 57 		 */
 58 		_constructs: null,
 59 
 60 		/**
 61 		 * Retrieves a list of constructs and constructs categories that are
 62 		 * assigned to this node and passes it as the only argument into the
 63 		 * the `success()' callback.
 64 		 *
 65 		 * @param {function(Array.<object>)=} success Callback to receive an
 66 		 *                                            array of constructs.
 67 		 * @param {function(GCNError):boolean=} error Custom error handler.
 68 		 * @return Returns the constructs / categories
 69 		 * @throws INVALID_ARGUMENTS
 70 		 */
 71 		constructs: function (success, error) {
 72 			if (!success) {
 73 				GCN.error('INVALID_ARGUMENTS', 'the `constructs()\' method ' +
 74 					'requires at least a success callback to be given');
 75 			}
 76 
 77 			if (this._constructs) {
 78 				success(this._constructs);
 79 			} else {
 80 				var that = this;
 81 
 82 				this._continueWith(function (child) {
 83 					that._data.id = child._data.nodeId;
 84 
 85 					that.constructCategories(function (categories) {
 86 						that._constructs = mapConstructs(categories);
 87 						success(that._constructs);
 88 					}, error);
 89 				}, error);
 90 			}
 91 		},
 92 
 93 		/**
 94 		 * Removes this node object.
 95 		 *
 96 		 * @param {function()=} success Callback.
 97 		 * @param {function(GCNError):boolean=} error Custom error handler.
 98 		 * @param {function} success callback
 99 		 */
100 		remove: function (success, error) {
101 
102 		},
103 
104 		/**
105 		 * @FIXME: Is it really possible to save changes to a node?  If not,
106 		 *         then we should not surface this method.
107 		 */
108 		save: function () {},
109 
110 		/**
111 		 * Retreives the top-level folders of this node's root folder.
112 		 *
113 		 * @param {function(FolderAPI)=} success
114 		 * @param {function(GCNError):boolean=} error Custom error handler.
115 		 */
116 		'!folders': function (success, error) {
117 			return this.folder(null, error).folders(success, error);
118 		},
119 
120 		/**
121 		 * Helper method that will load the constructs of this node.
122 		 *
123 		 * @private
124 		 * @this {NodeAPI}
125 		 * @param {function(Array.<object>)} success callback
126 		 * @param {function(GCNError):boolean=} error callback
127 		 */
128 		constructCategories: function (success, error) {
129 			this._authAjax({
130 				url   : GCN.settings.BACKEND_PATH + '/rest/construct/load.json',
131 				type  : 'GET',
132 				error : function (xhr, status, msg) {
133 					GCN.handleHttpError(xhr, msg, error);
134 				},
135 				success: function (response) {
136 					if (GCN.getResponseCode(response) === 'OK') {
137 						success(response.constructCategories);
138 					} else {
139 						GCN.handleResponseError(response, error);
140 					}
141 				}
142 			});
143 		}
144 
145 	});
146 
147 	GCN.node = GCN.exposeAPI(NodeAPI);
148 	GCN.NodeAPI = NodeAPI;
149 
150 }(GCN));
151