1 /* 2 * Copyright (C) 2008-2009 WaveMaker Software, Inc. 3 * 4 * This file is part of the WaveMaker Client Runtime. 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 dojo.provide('wm.base.lib.data'); 19 20 wm.data = wm.data || {}; 21 22 dojo.mixin(wm.data, { 23 // returns fields that should be included for type 24 getIncludeFields: function(inTypeName) { 25 var 26 pi, fields=[], 27 schema = wm.typeManager.getTypeSchema(inTypeName); 28 for (var i in schema) { 29 pi = schema[i]; 30 if (pi.include && pi.include.length) { 31 // composite key 32 if (wm.typeManager.isStructuredType(pi.type)) { 33 var compSchema = wm.typeManager.getTypeSchema(pi.type); 34 for (var j in compSchema) 35 fields.push(i + "." + j); 36 } else 37 fields.push(i); 38 } 39 } 40 return fields; 41 }, 42 // Reports if given data of type has include data. 43 // This is equivalent to having primary key information 44 // that is necessary for initiating update and delete operations. 45 // By default related structured types are not checked for include data 46 // That information is typically not required for update / delete operations. 47 hasIncludeData: function(inTypeName, inData) { 48 if (!inData || wm.isEmpty(inData)) 49 return false; 50 var fields = this.getIncludeFields(inTypeName); 51 for (var i=0, f; f=fields[i]; i++) 52 if (dojo.getObject(f, false, inData) === undefined) 53 return; 54 return true; 55 }, 56 // Reports if given data of type contains necessary contents 57 // to perform given operation. 58 hasOperationData: function(inOperation, inTypeName, inData) { 59 if (!wm.typeManager.getLiveService(inTypeName)) 60 return false; 61 switch(inOperation) { 62 // read ok if we provide no data or we have necessary root include data 63 case "read": 64 return !inData || wm.data.hasIncludeData(inTypeName, inData); 65 // root include data is required for delete and update 66 case "delete": 67 case "update": 68 return wm.data.hasIncludeData(inTypeName, inData); 69 // for insert all required root and provided related required data is necessary 70 case "insert": 71 return wm.data.hasRequiredData(inOperation, inTypeName, inData, true); 72 } 73 }, 74 // Reports if given data of type contains all required data 75 // This info is helpful for determining if there's enough data to perform an insert operation 76 // In this case we want to check structured related data also. 77 // Operation and the structured data flag are provided for additional flexibility... 78 hasRequiredData: function(inOperation, inTypeName, inData, inCheckStructured) { 79 var schema = wm.typeManager.getTypeSchema(inTypeName), 80 s, d, isStructured, hasData, missingRequired, hasExcluded; 81 for (var i in schema) { 82 s = schema[i]; 83 isStructured = wm.typeManager.isStructuredType(s.type); 84 d = inData && inData[i]; 85 // check structured type 86 if (isStructured && inCheckStructured) { 87 if ((d || s.required) && !s.isList && !this.hasRequiredData(s.type, d, inCheckStructured)) 88 return false; 89 } else { 90 hasData = (d !== undefined); 91 missingRequired = s.required && !hasData; 92 // return false if we have excluded data or missing required data. 93 if (dojo.indexOf(s.exclude, inOperation) != -1 ? hasData : missingRequired) 94 return false; 95 } 96 } 97 return true; 98 }, 99 // binding 100 clearBinding: function(inObject, inTargetProperty) { 101 var w = wm.data.getPropWire(inObject, inTargetProperty); 102 if (w) { 103 var b = w.owner, target = w.target, tp = w.targetProperty; 104 // note: removing wire may have side-effects so reset value with care after removing. 105 if (b) 106 b.removeWire(w.getWireId()); 107 // reset value here. 108 if (target && tp) 109 target.setValue(tp, ""); 110 } 111 }, 112 getPropWire: function(inTargetObject, inTargetProperty) { 113 var 114 tp = inTargetProperty, 115 tobj = inTargetObject, 116 binding = tobj && tobj.$.binding, 117 // Note: target bindings are stored in wires hash by targetProperty 118 // source bindings has targetId appended so they will be ignored below 119 w = binding && binding.wires[tp]; 120 // if there's a target binding, return it 121 if (w) 122 return w; 123 // FIXME: design check... 124 var ownerApp = tobj && tobj.isDesignLoaded() ? studio.application : app; 125 // otherwise, if the object is owned by the application try to return a source binding. 126 if (tobj && tobj.isOwnedBy(ownerApp)) 127 return wm.data.findSourceWire((tobj||0).getId(), tp); 128 }, 129 findSourceWire: function(inTargetId, inProp) { 130 if (inTargetId) { 131 var c, o, id, wires, w; 132 // search all components, wee... 133 for (var i in wm.Component.byId) { 134 c = wm.Component.byId[i]; 135 // FIXME: design check... 136 if ((c instanceof wm.Binding) && (c.isDesignLoaded() || !(window.studio && window.studio._isWaveMakerStudio))) { 137 var wires = c.findWiresByProps({targetId: inTargetId, targetProperty: inProp}); 138 if (wires.length) 139 return wires[0]; 140 } 141 } 142 } 143 }, 144 // FIXME: deprecated 145 /*getPropertyBindWire: function(inBinding, inTargetProperty) { 146 var wires = inBinding.wires, w; 147 for (var i in wires) { 148 w = wires[i]; 149 if (w.targetProperty == inTargetProperty) 150 return w; 151 } 152 },*/ 153 getPropBindSource: function(inTargetObject, inTargetProperty) { 154 var w = wm.data.getPropWire(inTargetObject, inTargetProperty); 155 if (w) 156 return inTargetObject.getValueById(w.source); 157 }, 158 // a simple comparator 159 compare: function(a, b) { 160 return a === b ? 0 : 161 a === undefined ? -1 : 162 b === undefined ? 1 : 163 b === null ? 1 : 164 a > b ? 1 : 165 -1; 166 } 167 });