1 //
  2 // The Antville Project
  3 // http://code.google.com/p/antville
  4 //
  5 // Copyright 2001-2007 by The Antville People
  6 //
  7 // Licensed under the Apache License, Version 2.0 (the ``License'');
  8 // you may not use this file except in compliance with the License.
  9 // You may obtain a copy of the License at
 10 //
 11 //    http://www.apache.org/licenses/LICENSE-2.0
 12 //
 13 // Unless required by applicable law or agreed to in writing, software
 14 // distributed under the License is distributed on an ``AS IS'' BASIS,
 15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 16 // See the License for the specific language governing permissions and
 17 // limitations under the License.
 18 //
 19 // $Revision$
 20 // $LastChangedBy$
 21 // $LastChangedDate$
 22 // $URL$
 23 //
 24 
 25 /**
 26  * @fileoverview Defines a Metadata prototype.
 27  * @requires Object.js module
 28  */
 29 
 30 // Resolve dependencies
 31 app.addRepository("modules/core/Object.js");
 32 
 33 Metadata.PREFIX = Metadata().__name__.toLowerCase() + "_";
 34 
 35 /**
 36  * This prototype provides dynamic database records by storing data as 
 37  * JavaScript object source (similar to JSON) in a dedicated database column.
 38  * @name Metadata
 39  * @constructor
 40  */
 41 
 42 // Save internal methods for good
 43 /** @ignore */
 44 Metadata.prototype._get = Metadata.prototype.get;
 45 /** @ignore */
 46 Metadata.prototype._set = Metadata.prototype.set;
 47 
 48 /**
 49  * Retrieves the name of the property that contains the data for the 
 50  * Metadata instance. The name is constructed out of the instances's mountpoint 
 51  * and the suffix "_data".
 52  * @returns {String} The resulting value
 53  */
 54 Metadata.prototype.getDataSourceName = function() {
 55    return Metadata.PREFIX + "source";
 56 }
 57 
 58 /**
 59  * Retrieves the properties and values of a Metadata instance from the parent 
 60  * node.
 61  * @returns {Object}
 62  */
 63 Metadata.prototype.load = function() {
 64    return eval(this._parent[this.getDataSourceName()]);
 65 }
 66 
 67 /**
 68  * Copies the properties and values of a Metadata instance to the parent 
 69  * node.
 70  */
 71 Metadata.prototype.save = function() {
 72    var ref = this.cache.data || {};
 73    this._parent[this.getDataSourceName()] = ref.toSource();
 74    return;
 75 }
 76 
 77 /**
 78  * Retrieves the value of a property of a Metadata instance. If no argument
 79  * is given the complete metadata structure is returned.
 80  * @param {String} key The name of the desired property
 81  * @returns {Object} The resulting value
 82  */
 83 Metadata.prototype.get = function(key) {
 84    if (this.cache.data == null) {
 85       this.cache.data = this.load() || {};
 86    }
 87    if (arguments.length < 1) {
 88       return this.cache.data;
 89    }
 90    var value = this.cache.data[key];
 91    if (value !== undefined) {
 92       return value;
 93    }
 94    return null;
 95 }
 96 
 97 /**
 98  * Copies a value into a property of a Metadata instance. If the first 
 99  * argument is omitted the complete metadata is replaced with the second
100  * argument.
101  * @param {String} key The name of the desired property
102  * @param {Object} value The future value of the property
103  */
104 Metadata.prototype.set = function(key, value) {
105    if (arguments.length > 1) {
106       // Coerce Java classes into String prototypes
107       if (value && !value.constructor) {
108          value = String(value);
109       }
110       this.get()[key] = value;
111    } else if (arguments.length > 0) {
112       value = arguments[0];
113       if (value instanceof Object === false) {
114          value = value.clone({});
115       }
116       this.cache.data = value;
117    }
118    this.save();
119    return;
120 }
121 
122 /**
123  * Removes a property from a Metadata instance.
124  * @param {String} key The name of the desired property
125  */
126 Metadata.prototype.remove = function(key) {
127    delete this.cache.data[key];
128    this.save();
129    return;
130 }
131 
132 /**
133  * Removes all properties and values from a Metadata instance.
134  */
135 Metadata.prototype.destroy = function() {
136    delete this.cache.data;
137    this.save();
138    return;
139 }
140 
141 /**
142  * Get all valid keys of a Metadata instance.
143  * @returns {String[]} The list of valid keys
144  */
145 Metadata.prototype.keys = function() {
146    var cache = this.get();
147    var keys = [];
148    for (var i in cache) {
149       keys.push(i);
150    }
151    return keys;
152 }
153 
154 /**
155  * Retrieves the number of properties contained in a Metadata instance.
156  * @returns {Number} The size of a Metadata instance
157  */
158 Metadata.prototype.size = function() {
159    return this.keys().length;   
160 }
161 
162 /**
163  * Concatenates a string representation of a Metadata instance.
164  * @returns {String} A string representing a Metadata object
165  */
166 Metadata.prototype.toString = function() {
167    res.push();
168    var keys = this.keys();
169    res.write("[Metadata (");
170    if (keys.length < 1) {
171       res.write("empty");
172    } else {
173       res.write(keys.length);
174       res.write(" element");
175       if (keys.length > 1) {
176          res.write("s");
177       }
178    }
179    res.write(")]");
180    return res.pop();
181 }
182 
183 /**
184  * Concatenates the source of the underlying HopObject of a Metadata 
185  * instance. Useful for debugging purposes.
186  * @returns {String} The source of the underlying HopObject
187  */
188 Metadata.prototype.toSource = function() {
189    return this.get().toSource();
190 }
191 
192 /**
193  * Retrieves all properties and values of a Metadata instance.
194  * @returns {Object} The property map of a Metadata instance
195  * @deprecated Use get() with no arguments instead
196  */
197 Metadata.prototype.getData = function() {
198    return this.get();
199 }
200 
201 /**
202  * Replaces all properties and values of a Metadata instance with those of
203  * another object.
204  * @param {Object} obj The replacing data
205  * @deprecated Use set() with a single argument instead
206  */
207 Metadata.prototype.setData = function(obj) {
208    obj && this.set(obj);
209    return;
210 }
211 
212 // FIXME: This is Antville-specific code and should be removed from here
213 Metadata.prototype.getFormValue = function(name) {
214    if (req.isPost()) {
215       return req.postParams[name];
216    } else {
217       return this.get(name) || req.queryParams[name] || String.EMPTY;
218    }
219 }
220 
221 /**
222  * 
223  * @param {String} name
224  * @returns {HopObject}
225  */
226 Metadata.prototype.onUnhandledMacro = function(name) {
227    return this.get(name);
228 }
229