1 // The Antville Project
  2 // http://code.google.com/p/antville
  3 //
  4 // Copyright 2007-2011 by Tobi Schäfer.
  5 //
  6 // Copyright 2001–2007 Robert Gaggl, Hannes Wallnöfer, Tobi Schäfer,
  7 // Matthias & Michael Platzer, Christoph Lincke.
  8 //
  9 // Licensed under the Apache License, Version 2.0 (the ``License'');
 10 // you may not use this file except in compliance with the License.
 11 // You may obtain a copy of the License at
 12 //
 13 //    http://www.apache.org/licenses/LICENSE-2.0
 14 //
 15 // Unless required by applicable law or agreed to in writing, software
 16 // distributed under the License is distributed on an ``AS IS'' BASIS,
 17 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 18 // See the License for the specific language governing permissions and
 19 // limitations under the License.
 20 //
 21 // $Revision$
 22 // $LastChangedBy$
 23 // $LastChangedDate$
 24 // $URL$
 25 
 26 /**
 27  * @fileoverview Defines the Metadata prototype (version 2).
 28  */
 29 
 30 /**
 31  * Get an object representing the type properties settings suitable for 
 32  * defining prototypes with the definePrototype() method.
 33  * @returns {Object} The type properties settings as object.
 34  * @see <a href="http://helma.org/wiki/Defining+HopObject+mappings+programmatically">Helma documentation</a>
 35  */
 36 Metadata.getTypeProperties = function() {
 37    return {
 38       collection: "Metadata",
 39       "local.1": "$id",
 40       "foreign.1": "parent_id",
 41       "local.2": "$prototype",
 42       "foreign.2": "parent_type",
 43       accessName: "name"
 44    }
 45 }
 46 
 47 /**
 48  * Prepare a value for writing it to the metadata database table.
 49  * The type of each metadata is stored along with its value.
 50  * The normalize() method determines the type and possibly modifies 
 51  * the value accordingly.
 52  * @param {Object} value
 53  * @returns {Array} Compound value consisting of two elements, 
 54  * the (normalized) metadata value and its type.
 55  */
 56 Metadata.normalize = function(value) {
 57    if (value === null || value === undefined) {
 58       return [null, null];
 59    }
 60 
 61    if (!value.constructor) {
 62       value = String(value);
 63    }
 64 
 65    var Constructor = value.constructor;
 66    switch (Constructor) {
 67       case Boolean:
 68       case String:
 69       case Number:
 70       value = String(value);
 71       break;
 72 
 73       case Date:
 74       value = Number(value);
 75       break;
 76 
 77       default:
 78       value = value.toSource();
 79    }
 80    return [value, Constructor.name];
 81 }
 82 
 83 /**
 84  * @name Metadata
 85  * @constructor
 86  * @description The Metadata prototype provides means to store one metadata key-value
 87  * pair per record in the metadata database table. Each record is assigned to a
 88  * parent HopObject which is fitted with convenient methods to easily retrieve 
 89  * and modify the attached metadata objects.
 90  * @see HopObject#handleMetadata
 91  * @property {HopObject} parent The HopObject the metadata belongs to.
 92  * @property {String} name The name (key) of the metadata object.
 93  * @property {Object} value The value of the metadata object.
 94  * @property {String} type The type of the metadata object.
 95  */
 96 Metadata.prototype.constructor = function(parent, name, value) {
 97    if (parent && name && value) {
 98       this.parent = parent;
 99       this.name = name;
100       this.setValue(value);
101    }
102    return this;
103 }
104 
105 /**
106  * Set the value of a metadata object. If the value equals null
107  * the metadata object will be removed.
108  * @param {Object} value The desired metadata value.
109  */
110 Metadata.prototype.setValue = function(value) {
111    [this.value, this.type] = Metadata.normalize(value);
112    if (this.value === null) {
113       this.remove();
114    }
115    return;
116 }
117 
118 /**
119  * Get the value of a metadata object.
120  * @returns {Object} The value of the metadata object.
121  */
122 Metadata.prototype.getValue = function() {
123    var Constructor = global[this.type];
124    switch (Constructor) {
125       case null:
126       case undefined:
127       return null;
128 
129       case Boolean:
130       return eval(this.value).valueOf();
131 
132       case Date:
133       return new Date(Number(this.value));
134 
135       case Number:
136       case String:
137       return (new Constructor(this.value)).valueOf();
138 
139       default:
140       return eval(this.value);
141    }
142 }
143 
144 /**
145  * Get a textual representation of the metadata object.
146  * @returns {String} A textual representation of the metadata object. 
147  */
148 Metadata.prototype.toString = function() {
149    return "Metadata of " + this.parent + " (" + this.name + " = " + this.value + ")";
150 }
151 
152 /**
153  * Handle macros which are not defined elsewhere.
154  * @param {String} name The name of the macro.
155  * @returns {Object} The resulting value.
156  */
157 // FIXME: Is this obsolete?
158 Metadata.prototype.onUnhandledMacro = function(name) {
159    return this.get(name);
160 }
161