DataAbstract.js 72 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947
  1. RemObjects.UTIL.toBase64 = function (aValue) {
  2. if (typeof (btoa) != 'undefined') {
  3. return btoa(aValue);
  4. } else {
  5. throw (new Error("Base64 encoding is not supported by your browser."));
  6. //return $.base64Encode(aValue);
  7. };
  8. };
  9. RemObjects.UTIL.fromBase64 = function (aValue) {
  10. if (typeof (atob) != 'undefined') {
  11. return atob(aValue.replace(/(\n|\r)+/g, ""));
  12. } else {
  13. throw (new Error("Base64 decoding is not supported by your browser."));
  14. // return $.base64Decode(aValue);
  15. };
  16. };
  17. RemObjects.DataAbstract = {
  18. Enum: {},
  19. Util: {},
  20. Views: {},
  21. Scripting: {},
  22. DADataType: ["datUnknown", "datString", "datDateTime", "datFloat", "datCurrency",
  23. "datAutoInc", "datInteger", "datLargeInt", "datBoolean", "datMemo",
  24. "datBlob", "datWideString", "datWideMemo", "datLargeAutoInc", "datByte",
  25. "datShortInt", "datWord", "datSmallInt", "datCardinal", "datLargeUInt",
  26. "datGuid", "datXml", "datDecimal", "datSingleFloat", "datFixedChar", "datFixedWideChar", "datCursor"],
  27. // RemoteDataAdapter : function RemoteDataAdapter(aDataService, aLoginService, aStreamerClass) { //old api
  28. RemoteDataAdapter: function RemoteDataAdapter(aURL, aDataServiceName, aLoginServiceName, aStreamerClass) {
  29. var that = this;
  30. this.fService = new RemObjects.DataAbstract.Server.DataAbstractService(arguments[0]);
  31. this.fLoginService = new RemObjects.SDK.RemoteService(this.fService.fChannel, this.fService.fMessage, "LoginService");
  32. if (arguments.length == 0)
  33. this.fService.fChannel = { onLoginNeeded: null }; //hack for docGen
  34. if (!(arguments[0] instanceof RemObjects.SDK.RemoteService)) this.fService.fServiceName = "DataService";
  35. this.fStreamerClass = RemObjects.DataAbstract.Bin2DataStreamer;
  36. if (RemObjects.UTIL.checkArgumentTypes(arguments, [RemObjects.SDK.RemoteService, RemObjects.SDK.RemoteService])) {
  37. this.fLoginService = arguments[1];
  38. this.fStreamerClass = arguments[2] || RemObjects.DataAbstract.Bin2DataStreamer;
  39. } else if (RemObjects.UTIL.checkArgumentTypes(arguments, ["string", "string", "string"])) { //URL, DataServiceName, LoginServiceName
  40. this.fService.fServiceName = arguments[1];
  41. this.fLoginService.fServiceName = arguments[2];
  42. if (RemObjects.UTIL.checkArgumentTypes(arguments, ["string", "string", "string", Function])) {
  43. this.fStreamerClass = arguments[3];
  44. };
  45. } else if (RemObjects.UTIL.checkArgumentTypes(arguments, ["string", "string"])) { //URL, DataServiceName
  46. this.fService.fServiceName = arguments[1];
  47. if (RemObjects.UTIL.checkArgumentTypes(arguments, ["string", "string", Function])) {
  48. this.fStreamerClass = arguments[2];
  49. };
  50. } else if (RemObjects.UTIL.checkArgumentTypes(arguments, ["string"])) { //URL
  51. if (RemObjects.UTIL.checkArgumentTypes(arguments, ["string", Function])) {
  52. this.fStreamerClass = arguments[1];
  53. };
  54. };
  55. this.fSavedOnLoginNeeded = this.fService.fChannel.onLoginNeeded;
  56. this.fService.fChannel.onLoginNeeded = function (aCallback) { that.intOnLoginNeeded(aCallback) };
  57. this.fSendReducedDelta = false;
  58. this.fAutoGetScripts = false;
  59. //methods:
  60. //setSendReducedDelta
  61. //buildDelta
  62. //createStreamer
  63. //onLoginNeeded
  64. //login
  65. //asynchronous methods (pass callback function):
  66. //getSchema
  67. //createTableFromSchema
  68. //getData
  69. //applyUpdates
  70. //getDataService
  71. //getLoginService
  72. //executeCommand
  73. },
  74. Deltas: function Deltas() {
  75. this.deltas = [];
  76. //methods
  77. //findByName
  78. },
  79. Delta: function Delta() {
  80. this.name = "";
  81. this.loggedfields = [];
  82. this.keyfields = [];
  83. this.data = [];
  84. },
  85. Change: function Change() {
  86. this.recid = 0;
  87. this.changetype = "";
  88. this.status = "";
  89. this.message = "";
  90. this["old"] = [];
  91. this["new"] = [];
  92. },
  93. DataTable: function DataTable(aName) {
  94. this.name = aName || "";
  95. this.fields = [];
  96. this.keyfields = [];
  97. this.rows = [];
  98. this.deletedRows = [];
  99. this.fRecordBuffer = [];
  100. this.fNextRecId = 0;
  101. this.fIndex = -1;
  102. this.bofFlag = true;
  103. this.eofFlag = true;
  104. this.dynamicWhere = null;
  105. this.onNewRecord = null;
  106. this.onBeforeDelete = null;
  107. this.onAfterDelete = null;
  108. this.onBeforeScroll = null;
  109. this.onAfterScroll = null;
  110. //methods
  111. //appendRow
  112. //deleteRow
  113. //markDeleted
  114. //currentRow
  115. //first
  116. //next
  117. //prev
  118. //last
  119. //findId
  120. //intFindDeleted
  121. //eof
  122. //bof
  123. //getFieldValue
  124. //setFieldValue
  125. //getFieldAsString
  126. //setFieldAsString
  127. //addLookupField
  128. //fieldNumByName
  129. //fieldByName
  130. //locate
  131. },
  132. Field: function Field(aName, aType) {
  133. this.name = aName || "";
  134. this.type = aType || "";
  135. this.logChanges = true;
  136. },
  137. LookupField: function LookupField(aName, aType) {
  138. RemObjects.DataAbstract.Field.call(this, aName, aType);
  139. this.logChanges = false;
  140. this.sourceField = "";
  141. this.lookupTable = null;
  142. this.lookupKeyField = "";
  143. this.lookupResultField = "";
  144. },
  145. DataTableRow: function DataTableRow() {
  146. this.recId = 0;
  147. this.state = RemObjects.DataAbstract.Enum.RowStates.rsUnchanged;
  148. this.__oldValues = [];
  149. this.__newValues = [];
  150. },
  151. DataStreamer: function DataStreamer() {
  152. },
  153. JSONDataStreamer: function JSONDataStreamer() {
  154. //methods:
  155. //setStream
  156. //getStream
  157. //initializeRead
  158. //initializeWrite
  159. },
  160. Bin2DataStreamer: function Bin2DataStreamer() {
  161. this.fStream = "";
  162. this.fStreamPos = 0;
  163. this.fStreamInfoPos = 0;
  164. this.fParser = new BinaryParser();
  165. //methods:
  166. //setStream
  167. //getStream
  168. //initializeRead
  169. //initializeWrite
  170. //readByte
  171. //readInteger
  172. //readAnsiStringWithLength
  173. //readDataSet
  174. //readField
  175. //writeDelta
  176. },
  177. DynamicWhere: function DynamicWhere(anExpression) {
  178. this.fExpression = anExpression;
  179. //toXML
  180. },
  181. ConstantExpression: function ConstantExpression(aType, aValue, aNull) {
  182. this.fType = aType;
  183. this.fValue = aValue;
  184. this.fNull = aNull;
  185. //toXML
  186. },
  187. NullExpression: function NullExpression() {
  188. },
  189. FieldExpression: function FieldExpression(aName) {
  190. this.fName = aName;
  191. },
  192. MacroExpression: function MacroExpression(aName) {
  193. this.fName = aName;
  194. },
  195. UnaryExpression: function UnaryExpression(aNode, anOperator) {
  196. this.fNode = aNode;
  197. this.fOperator = anOperator;
  198. },
  199. BinaryExpression: function BinaryExpression(aNode1, aNode2, anOperator) {
  200. this.fNode1 = aNode1;
  201. this.fNode2 = aNode2;
  202. this.fOperator = anOperator;
  203. },
  204. BetweenExpression: function BetweenExpression(aNode1, aNode2, aNode3) {
  205. this.fNode1 = aNode1;
  206. this.fNode2 = aNode2;
  207. this.fNode3 = aNode3;
  208. },
  209. ParameterExpression: function ParameterExpression(aName, aType, aSize) {
  210. this.fName = aName;
  211. this.fType = aType;
  212. this.fSize = aSize;
  213. },
  214. ListExpression: function ListExpression(anItems) {
  215. this.fItems = anItems;
  216. }
  217. };
  218. RemObjects.DataAbstract.Enum.RowStates = {
  219. //DataTableRow states
  220. rsUnchanged: 0,
  221. rsModified: 1,
  222. rsNew: 2,
  223. rsDeleted: 3
  224. };
  225. RemObjects.DataAbstract.Enum.ChangeType = { ctInsert: 0, ctUpdate: 1, ctDelete: 2 };
  226. RemObjects.DataAbstract.Enum.ChangeTypeNames = ["insert", "update", "delete"];
  227. RemObjects.DataAbstract.Enum.ChangeStatus = { csPending: 0, csResolved: 1, csFailed: 2 };
  228. RemObjects.DataAbstract.Enum.ChangeStatusNames = ["pending", "resolved", "failed"];
  229. RemObjects.DataAbstract.Util.createDataParameter = function createDataParameter(aName, aValue) {
  230. var result = new RemObjects.DataAbstract.Server.DataParameter();
  231. result.Name.value = aName;
  232. result.Value.value = aValue;
  233. return result;
  234. };
  235. RemObjects.DataAbstract.Util.createRequestInfo = function createRequestInfo(includeSchema, maxRecords, userFilter, parameters) {
  236. var result = new RemObjects.DataAbstract.Server.TableRequestInfo();
  237. if (arguments.length == 0) {
  238. result.IncludeSchema.value = true;
  239. result.MaxRecords.value = -1;
  240. result.UserFilter.value = "";
  241. result.Parameters.value = new RemObjects.DataAbstract.Server.DataParameterArray();
  242. result.Parameters.value.items = [];
  243. } else {
  244. result.IncludeSchema.value = includeSchema;
  245. result.MaxRecords.value = maxRecords;
  246. result.UserFilter.value = userFilter;
  247. result.Parameters.value = new RemObjects.DataAbstract.Server.DataParameterArray();
  248. result.Parameters.value.items = parameters;
  249. };
  250. return result;
  251. };
  252. RemObjects.DataAbstract.Util.createRequestInfoV5 = function createRequestInfoV5(includeSchema, maxRecords, userFilter, parameters) {
  253. var ri = RemObjects.DataAbstract.Util.createRequestInfo.apply(this, arguments);
  254. var result = new RemObjects.DataAbstract.Server.TableRequestInfoV5();
  255. result.IncludeSchema = ri.IncludeSchema;
  256. result.MaxRecords = ri.MaxRecords;
  257. result.UserFilter = ri.UserFilter;
  258. result.Parameters = ri.Parameters;
  259. result.WhereClause = { dataType: "Xml", value: null };
  260. result.DynamicSelectFieldNames = { dataType: "StringArray", value: new RemObjects.DataAbstract.Server.StringArray() };
  261. result.DynamicSelectFieldNames.value.items = [];
  262. result.Sorting = { dataType: "ColumnSorting", value: new RemObjects.DataAbstract.Server.ColumnSorting() };
  263. result.Sorting.value.fromObject({ FieldName: "", SortDirection: "Ascending" });
  264. return result;
  265. };
  266. RemObjects.DataAbstract.Util.createRequestInfoV6 = function createRequestInfoV6(sql, maxRecords, userFilter, parameters) {
  267. var result = new RemObjects.DataAbstract.Server.TableRequestInfoV6();
  268. if (arguments.length == 1) {
  269. result.Sql.value = sql;
  270. result.IncludeSchema.value = true;
  271. result.MaxRecords.value = -1;
  272. result.UserFilter.value = "";
  273. result.Parameters.value = new RemObjects.DataAbstract.Server.DataParameterArray();
  274. result.Parameters.value.items = [];
  275. } else {
  276. result.Sql.value = sql;
  277. result.IncludeSchema.value = true;
  278. result.MaxRecords.value = maxRecords;
  279. result.UserFilter.value = userFilter;
  280. result.Parameters.value = new RemObjects.DataAbstract.Server.DataParameterArray();
  281. result.Parameters.value.items = parameters;
  282. };
  283. return result;
  284. };
  285. RemObjects.DataAbstract.Util.setupScriptingCallbacks = function setupScriptingCallbacks() {
  286. for (var p in RemObjects.DataAbstract.Scripting) {
  287. eval("var " + p + " = RemObjects.DataAbstract.Scripting." + p);
  288. console.log("var " + p + " = RemObjects.DataAbstract.Scripting." + p);
  289. };
  290. };
  291. RemObjects.DataAbstract.Scripting.log = function log(str) {
  292. console.log(str);
  293. };
  294. RemObjects.DataAbstract.Scripting.fail = function fail(str) {
  295. throw new Error(str);
  296. };
  297. RemObjects.DataAbstract.Scripting.newGuidString = function newGuidString() {
  298. return RemObjects.UTIL.NewGuid();
  299. };
  300. //RO.DA implementation
  301. RemObjects.DataAbstract.Deltas.prototype.findByName = function findByName(aName) {
  302. for (var i = 0; i < this.deltas.length; i++) {
  303. if (this.deltas[i].name.toUpperCase() == aName.toUpperCase()) {
  304. return this.deltas[i];
  305. };
  306. };
  307. return null;
  308. };
  309. RemObjects.DataAbstract.Delta.prototype.intFindId = function intFindId(anId) {
  310. for (var i = 0; i < this.data.length; i++) {
  311. if (this.data[i].recid == anId) {
  312. return i;
  313. };
  314. };
  315. return null;
  316. };
  317. RemObjects.DataAbstract.Field.prototype.checkReadOnly = function checkReadOnly() {
  318. if (this instanceof RemObjects.DataAbstract.LookupField) {
  319. throw new Error(this.name + ": lookup fields are read only");
  320. };
  321. if (this.readOnly == "True") {
  322. throw new Error(this.name + " is read only.");
  323. };
  324. };
  325. RemObjects.DataAbstract.LookupField.prototype = new RemObjects.DataAbstract.Field();
  326. RemObjects.DataAbstract.DataTable.prototype.checkRequired = function checkRequired() {
  327. if (this.fIndex < 0) return;
  328. for (var i = 0; i < this.fields.length; i++) {
  329. if (this.fields[i].required == "True" && (this.fRecordBuffer[i] == null || this.fRecordBuffer[i] == undefined)) {
  330. throw new Error("Field " + this.fields[i].name + " is required.");
  331. };
  332. };
  333. };
  334. RemObjects.DataAbstract.DataTable.prototype.locate = function locate(aName, aValue) {
  335. this.post();
  336. var result = false;
  337. var fieldNum = this.fieldNumByName(aName);
  338. for (var i = 0; i < this.rows.length; i++) {
  339. if (this.rows[i].__newValues[fieldNum] == aValue) {
  340. this.fIndex = i;
  341. result = true;
  342. break;
  343. };
  344. };
  345. return result;
  346. };
  347. RemObjects.DataAbstract.DataTable.prototype.addLookupField = function addLookupField(aName, aSourceField, aLookupTable, aLookupKeyField, aLookupResultField) {
  348. var f = new RemObjects.DataAbstract.LookupField(aName);
  349. f.type = aLookupTable.fieldByName(aLookupResultField).type;
  350. f.lookupTable = aLookupTable;
  351. f.sourceField = aSourceField;
  352. f.lookupKeyField = aLookupKeyField;
  353. f.lookupResultField = aLookupResultField;
  354. this.fields.push(f);
  355. };
  356. RemObjects.DataAbstract.DataTable.prototype.getNextId = function getNextId() {
  357. return this.fNextRecId++;
  358. };
  359. RemObjects.DataAbstract.DataTable.prototype.intSetupProperties = function intSetupProperties(aRow) {
  360. if (!Object.defineProperty) return;
  361. var that = this;
  362. for (var j = 0; j < this.fields.length; j++) {
  363. (function (fieldNum) {
  364. Object.defineProperty(aRow, that.fields[fieldNum].name, {
  365. get: function () {
  366. return this.__newValues[fieldNum];
  367. },
  368. set: function (aValue) {
  369. if (this.__oldValues.length == 0)
  370. this.__oldValues = this.__newValues.slice();
  371. this.__oldValues[fieldNum] = this.__newValues[fieldNum];
  372. this.__newValues[fieldNum] = aValue;
  373. if (this.state == RemObjects.DataAbstract.Enum.RowStates.rsUnchanged)
  374. this.state = RemObjects.DataAbstract.Enum.RowStates.rsModified;
  375. }
  376. });
  377. })(j);
  378. };
  379. };
  380. RemObjects.DataAbstract.DataTable.prototype.intAppendRow = function intAppendRow() {
  381. var row = new RemObjects.DataAbstract.DataTableRow();
  382. row.recId = this.getNextId();
  383. row.state = RemObjects.DataAbstract.Enum.RowStates.rsNew;
  384. row.__newValues = new Array(this.fields.length);
  385. this.rows.push(row);
  386. this.fIndex = this.rows.length - 1;
  387. this.eofFlag = false;
  388. this.bofFlag = false;
  389. this.intSetupProperties(row);
  390. return row;
  391. };
  392. RemObjects.DataAbstract.DataTable.prototype.appendRow = function appendRow() {
  393. //this.checkRequired();
  394. this.post();
  395. var row = this.intAppendRow();
  396. for (var i = 0; i < this.fields.length; i++) {
  397. if (typeof (this.fields[i].fAutoIncSequence) != 'undefined') {
  398. row.__newValues[i] = this.fields[i].fAutoIncSequence--;
  399. } else if (this.fields[i].defaultValue != "") {
  400. row.__newValues[i] = this.fields[i].defaultValue;
  401. };
  402. };
  403. if (this.__onNewRow) {
  404. var lRow = {};
  405. for (var i = 0; i < this.fields.length; i++) {
  406. lRow[this.fields[i].name] = row.__newValues[i];
  407. };
  408. this.__onNewRow(lRow);
  409. for (var i = 0; i < this.fields.length; i++) {
  410. row.__newValues[i] = lRow[this.fields[i].name];
  411. };
  412. };
  413. this.fRecordBuffer = row.__newValues.slice();
  414. if (this.onNewRecord) this.onNewRecord(row);
  415. return row;
  416. };
  417. RemObjects.DataAbstract.DataTable.prototype.deleteRow = function deleteRow() {
  418. if (this.rows.length == 0)
  419. throw new Error("DataTable.deleteRow: table is empty");
  420. if (this.__beforeDelete) {
  421. var row = this.currentRow();
  422. var lRow = {};
  423. for (var i = 0; i < this.fields.length; i++) {
  424. lRow[this.fields[i].name] = row.__newValues[i];
  425. };
  426. this.__beforeDelete(lRow);
  427. };
  428. if (this.onBeforeDelete) this.onBeforeDelete(this.currentRow());
  429. this.markDeleted();
  430. this.deletedRows.push(this.rows[this.fIndex]);
  431. this.rows.splice(this.fIndex, 1);
  432. if (this.fIndex == this.rows.length)
  433. this.fIndex--;
  434. this.eofFlag = (this.rows.length == 0);
  435. this.bofFlag = (this.rows.length == 0);
  436. this.fRecordBuffer = [];
  437. if (this.onAfterDelete && this.rows.length) this.onAfterDelete(this.currentRow());
  438. };
  439. RemObjects.DataAbstract.DataTable.prototype.markDeleted = function markDeleted() {
  440. if (this.rows[this.fIndex].__oldValues.length == 0)
  441. this.rows[this.fIndex].__oldValues = this.rows[this.fIndex].__newValues.slice();
  442. this.rows[this.fIndex].state = RemObjects.DataAbstract.Enum.RowStates.rsDeleted;
  443. };
  444. RemObjects.DataAbstract.DataTable.prototype.fieldNumByName = function fieldNumByName(aName) {
  445. var fieldNum = -1;
  446. for (var i = 0; i < this.fields.length; i++) {
  447. if (this.fields[i].name.toUpperCase() == aName.toUpperCase()) {
  448. fieldNum = i;
  449. break;
  450. };
  451. };
  452. if (fieldNum == -1)
  453. throw new Error("DataTable.fieldNumByName: no such field name - " + aName);
  454. return fieldNum;
  455. };
  456. RemObjects.DataAbstract.DataTable.prototype.fieldByName = function fieldByName(aName) {
  457. return this.fields[this.fieldNumByName(aName)];
  458. };
  459. RemObjects.DataAbstract.DataTable.prototype.setFieldValue = function setFieldValue(aField, aValue) {
  460. if (this.rows.length == 0)
  461. throw new Error("DataTable.setFieldValue: table is empty");
  462. var fieldNum = this.fieldNumByName(aField);
  463. var f = this.fields[fieldNum];
  464. f.checkReadOnly();
  465. if (this.rows[this.fIndex].__oldValues.length == 0)
  466. this.rows[this.fIndex].__oldValues = this.rows[this.fIndex].__newValues.slice();
  467. if (this.rows[this.fIndex].state == RemObjects.DataAbstract.Enum.RowStates.rsUnchanged)
  468. this.rows[this.fIndex].state = RemObjects.DataAbstract.Enum.RowStates.rsModified;
  469. if (this.fRecordBuffer.length == 0)
  470. this.fRecordBuffer = this.rows[this.fIndex].__newValues.slice();
  471. this.fRecordBuffer[fieldNum] = aValue;
  472. };
  473. RemObjects.DataAbstract.DataTable.prototype.getFieldValue = function getFieldValue(aField) {
  474. if (this.rows.length == 0)
  475. throw new Error("DataTable.getFieldValue: table is empty");
  476. var fieldNum = this.fieldNumByName(aField);
  477. var f = this.fields[fieldNum];
  478. if (f instanceof RemObjects.DataAbstract.LookupField) {
  479. if (f.lookupTable.locate(f.lookupKeyField, this.getFieldValue(f.sourceField))) {
  480. return f.lookupTable.getFieldValue(f.lookupResultField);
  481. } else {
  482. return null;
  483. };
  484. } else if (this.fRecordBuffer.length == 0) {
  485. return this.rows[this.fIndex].__newValues[fieldNum];
  486. } else {
  487. return this.fRecordBuffer[fieldNum];
  488. };
  489. };
  490. RemObjects.DataAbstract.DataTable.prototype.setFieldAsString = function setFieldAsString(aField, aValue) {
  491. if (this.rows.length == 0)
  492. throw new Error("DataTable.setFieldAsString: table is empty");
  493. var tempValue;
  494. var fieldNum = this.fieldNumByName(aField);
  495. var f = this.fields[fieldNum];
  496. f.checkReadOnly();
  497. if (this.rows[this.fIndex].__oldValues.length == 0)
  498. this.rows[this.fIndex].__oldValues = this.rows[this.fIndex].__newValues.slice();
  499. if (this.rows[this.fIndex].state == RemObjects.DataAbstract.Enum.RowStates.rsUnchanged)
  500. this.rows[this.fIndex].state = RemObjects.DataAbstract.Enum.RowStates.rsModified;
  501. if (this.fRecordBuffer.length == 0)
  502. this.fRecordBuffer = this.rows[this.fIndex].__newValues.slice();
  503. if (aValue == "") {
  504. if (this.rows[this.fIndex].__oldValues[fieldNum] == null)
  505. tempValue = null;
  506. } else {
  507. switch (this.fields[fieldNum].type) {
  508. //case "datBlob": return;
  509. case "datInteger":
  510. case "datAutoInc":
  511. case "datSmallInt":
  512. case "datByte":
  513. case "datLargeInt":
  514. case "datLargeAutoInc":
  515. case "datLargeUInt":
  516. case "datShortInt":
  517. case "datWord":
  518. case "datCardinal":
  519. tempValue = parseInt(aValue);
  520. break;
  521. case "datFloat":
  522. case "datCurrency":
  523. case "datSingleFloat":
  524. case "datDecimal":
  525. tempValue = parseFloat(aValue);
  526. break;
  527. case "datDateTime":
  528. tempValue = new Date(aValue);
  529. break;
  530. case "datBoolean":
  531. tempValue = (aValue.toUpperCase() == "TRUE");
  532. default:
  533. tempValue = aValue;
  534. //todo
  535. };
  536. };
  537. this.fRecordBuffer[fieldNum] = tempValue;
  538. };
  539. RemObjects.DataAbstract.DataTable.prototype.getFieldAsString = function getFieldAsString(aField) {
  540. var fieldNum = this.fieldNumByName(aField);
  541. var value = this.getFieldValue(aField);
  542. return (this.fields[fieldNum].type == "datBlob" ? "(Blob)" : (
  543. (value != undefined && value != null)
  544. ? value : "").toString());
  545. };
  546. RemObjects.DataAbstract.DataTable.prototype.currentRow = function currentRow() {
  547. return (this.rows.length ? this.rows[this.fIndex] : null);
  548. };
  549. RemObjects.DataAbstract.DataTable.prototype.intGoToIndex = function intGoToIndex(anIndex) {
  550. if (this.onBeforeScroll) this.onBeforeScroll(this.currentRow());
  551. this.fIndex = anIndex;
  552. if (this.onAfterScroll) this.onAfterScroll(this.currentRow());
  553. };
  554. RemObjects.DataAbstract.DataTable.prototype.first = function first() {
  555. this.post();
  556. if (this.rows.length > 0)
  557. this.intGoToIndex(0);
  558. this.bofFlag = true;
  559. this.eofFlag = false;
  560. return this.currentRow();
  561. };
  562. RemObjects.DataAbstract.DataTable.prototype.last = function last() {
  563. this.post();
  564. if (this.rows.length > 0)
  565. this.intGoToIndex(this.rows.length - 1);
  566. this.eofFlag = true;
  567. this.bofFlag = false;
  568. return this.currentRow();
  569. };
  570. RemObjects.DataAbstract.DataTable.prototype.next = function next() {
  571. this.post();
  572. if (this.fIndex < this.rows.length - 1) {
  573. this.intGoToIndex(this.fIndex + 1);
  574. this.bofFlag = false;
  575. return this.currentRow();
  576. } else {
  577. this.eofFlag = true;
  578. return null;
  579. };
  580. };
  581. RemObjects.DataAbstract.DataTable.prototype.prev = function prev() {
  582. this.post();
  583. if (this.fIndex > 0) {
  584. this.intGoToIndex(this.fIndex - 1);
  585. this.eofFlag = false;
  586. return this.currentRow();
  587. } else {
  588. this.bofFlag = true;
  589. return null;
  590. };
  591. };
  592. RemObjects.DataAbstract.DataTable.prototype.findId = function findId(anId) {
  593. this.post();
  594. for (var i = 0; i < this.rows.length; i++) {
  595. if (this.rows[i].recId == anId) {
  596. this.intGoToIndex(i);
  597. return this.currentRow();
  598. };
  599. };
  600. return null;
  601. };
  602. RemObjects.DataAbstract.DataTable.prototype.intFindDeleted = function intFindDeleted(anId) {
  603. for (var i = 0; i < this.deletedRows.length; i++) {
  604. if (this.deletedRows[i].recId == anId) {
  605. return i;
  606. };
  607. };
  608. return null;
  609. };
  610. RemObjects.DataAbstract.DataTable.prototype.eof = function eof() {
  611. return this.eofFlag;
  612. };
  613. RemObjects.DataAbstract.DataTable.prototype.bof = function bof() {
  614. return this.bofFlag;
  615. };
  616. RemObjects.DataAbstract.DataTable.prototype.post = function post() {
  617. var bufferNotSet = true;
  618. for (var i = 0; i < this.fRecordBuffer.length; i++) {
  619. if (typeof this.fRecordBuffer[i] != 'undefined')
  620. {
  621. bufferNotSet = false;
  622. break;
  623. }
  624. }
  625. if (bufferNotSet) {
  626. return;
  627. }
  628. if (this.__beforePost) {
  629. var lRow = {};
  630. for (var i = 0; i < this.fields.length; i++) {
  631. lRow[this.fields[i].name] = this.fRecordBuffer[i];
  632. };
  633. try {
  634. this.__beforePost(lRow);
  635. for (var i = 0; i < this.fields.length; i++) {
  636. this.fRecordBuffer[i] = lRow[this.fields[i].name];
  637. };
  638. } catch (e) { throw e };
  639. };
  640. this.checkRequired();
  641. this.rows[this.fIndex].__newValues = this.fRecordBuffer;
  642. this.fRecordBuffer = [];
  643. };
  644. RemObjects.DataAbstract.DataTable.prototype.cancel = function cancel() {
  645. this.fRecordBuffer = [];
  646. };
  647. RemObjects.DataAbstract.RemoteDataAdapter.prototype.getDataService = function getDataService() {
  648. return this.fService;
  649. };
  650. RemObjects.DataAbstract.RemoteDataAdapter.prototype.getLoginService = function getLoginService() {
  651. return this.fLoginService;
  652. };
  653. RemObjects.DataAbstract.RemoteDataAdapter.prototype.intOnLoginNeeded = function intOnLoginNeeded(aCallback) {
  654. if (this.onLoginNeeded) {
  655. this.onLoginNeeded(aCallback)
  656. } else {
  657. this.fSavedOnLoginNeeded(aCallback);
  658. };
  659. };
  660. RemObjects.DataAbstract.RemoteDataAdapter.prototype.onLoginNeeded = function onLoginNeeded(aCallback) {
  661. RemObjects.UTIL.showMessage("Default onLoginNeeded handler: assign remoteDataAdapter.onLoginNeeded and call aCallback there after successful login");
  662. //example:
  663. // this.login("John", "password", function(result) {
  664. // if (aCallback)
  665. // aCallback();
  666. // }, function(msg, e) {
  667. // if (e)
  668. // throw e
  669. // else
  670. // throw new Error(msg.getErrorMessage());
  671. // });
  672. };
  673. RemObjects.DataAbstract.RemoteDataAdapter.prototype.login = function login(aUserID, aPassword, aConnectionName, onSuccessFunction, onErrorFunction) {
  674. if (!this.fLoginService)
  675. throw new Error("RemoteDataAdapter.login: login service not assigned");
  676. var svc;
  677. switch (arguments.length - 2) {
  678. case 1: //loginString
  679. svc = new RemObjects.DataAbstract.Server.BaseLoginService(this.fLoginService);
  680. svc.LoginEx(arguments[0], arguments[1], arguments[2]);
  681. break;
  682. case 2: //userID, password
  683. svc = new RemObjects.DataAbstract.Server.SimpleLoginService(this.fLoginService);
  684. svc.Login(arguments[0], arguments[1], arguments[2], arguments[3]);
  685. break;
  686. case 3: //userID, password, connection
  687. svc = new RemObjects.DataAbstract.Server.MultiDbLoginService(this.fLoginService);
  688. svc.Login(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4]);
  689. break;
  690. default:
  691. throw new Error("RemoteDataAdapter.login: incorrect number of arguments");
  692. };
  693. };
  694. RemObjects.DataAbstract.RemoteDataAdapter.prototype.logout = function logout(onSuccessFunction, onErrorFunction) {
  695. if (!this.fLoginService)
  696. throw new Error("RemoteDataAdapter.logout: login service not assigned");
  697. var svc = new RemObjects.DataAbstract.Server.BaseLoginService(this.fLoginService);
  698. svc.Logout(onSuccessFunction, onErrorFunction);
  699. };
  700. RemObjects.DataAbstract.RemoteDataAdapter.prototype.getSchema = function getSchema(aFilter, aCallback, onFailure) {
  701. var that = this;
  702. this.fService.GetSchema(aFilter, aCallback, onFailure || RemObjects.UTIL.showError);
  703. };
  704. RemObjects.DataAbstract.RemoteDataAdapter.prototype.createStreamer = function createStreamer() {
  705. return new this.fStreamerClass();
  706. };
  707. RemObjects.DataAbstract.RemoteDataAdapter.prototype.setSendReducedDelta = function setSendReducedDelta(aValue) {
  708. this.fSendReducedDelta = aValue;
  709. };
  710. RemObjects.DataAbstract.RemoteDataAdapter.prototype.buildDelta = function buildDelta(aTable) {
  711. function processRows(aRows, aDelta) {
  712. for (var i = 0; i < aRows.length; i++) {
  713. var c = new RemObjects.DataAbstract.Change();
  714. c.status = "pending";
  715. c.recid = aRows[i].recId;
  716. if (aRows[i].state == RemObjects.DataAbstract.Enum.RowStates.rsNew) {
  717. c.old = aRows[i].__newValues.slice();
  718. } else {
  719. c.old = aRows[i].__oldValues.slice();
  720. };
  721. c["new"] = aRows[i].__newValues.slice();
  722. excludeItems(c.old);
  723. excludeItems(c["new"]);
  724. switch (aRows[i].state) {
  725. case RemObjects.DataAbstract.Enum.RowStates.rsModified: c.changetype = "update"; break;
  726. case RemObjects.DataAbstract.Enum.RowStates.rsNew: c.changetype = "insert"; break;
  727. case RemObjects.DataAbstract.Enum.RowStates.rsDeleted: c.changetype = "delete"; break;
  728. };
  729. aDelta.data.push(c);
  730. };
  731. };
  732. function excludeItems(anArray) {
  733. for (var i = excludedFields.length - 1; i >= 0; i--) {
  734. anArray.splice(excludedFields[i], 1);
  735. };
  736. };
  737. var excludedFields = [];
  738. for (var i = 0; i < aTable.fields.length; i++) {
  739. if (!aTable.fields[i].logChanges) {
  740. excludedFields.push(i);
  741. };
  742. };
  743. var changedRows = [];
  744. for (var i = 0; i < aTable.rows.length; i++) {
  745. if (aTable.rows[i].state != RemObjects.DataAbstract.Enum.RowStates.rsUnchanged) changedRows.push(aTable.rows[i]);
  746. };
  747. if ((changedRows.length > 0) || (aTable.deletedRows.length > 0)) {
  748. d = new RemObjects.DataAbstract.Delta();
  749. d.name = aTable.name;
  750. d.keyfields = aTable.keyfields.slice();
  751. d.loggedfields = aTable.fields.slice();
  752. excludeItems(d.loggedfields);
  753. processRows(changedRows, d);
  754. processRows(aTable.deletedRows, d);
  755. return d;
  756. } else {
  757. return null;
  758. };
  759. };
  760. RemObjects.DataAbstract.RemoteDataAdapter.prototype.createTableFromSchema = function createTableFromSchema(aTableName, aTable, aCallback) {
  761. var that = this;
  762. var tablesArray = new RemObjects.DataAbstract.Server.StringArray();
  763. tablesArray.items = [aTableName];
  764. this.fService.GetTableSchema(tablesArray, function (result) {
  765. var xmlDoc;
  766. if (typeof (DOMParser) != 'undefined') {
  767. var parser = new DOMParser();
  768. xmlDoc = parser.parseFromString(result, "text/xml");
  769. } else // Internet Explorer
  770. {
  771. xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
  772. xmlDoc.async = "false";
  773. xmlDoc.loadXML(result);
  774. };
  775. var fieldsNode = xmlDoc.getElementsByTagName("Fields")[0];
  776. for (i = 0; i < fieldsNode.childElementCount; i++) {
  777. var f = new RemObjects.DataAbstract.Field();
  778. f.name = fieldsNode.childNodes[i].getElementsByTagName('Name')[0].textContent;
  779. f.type = fieldsNode.childNodes[i].getElementsByTagName('DataType')[0].textContent;
  780. f.logChanges = (fieldsNode.childNodes[i].getElementsByTagName('LogChanges')[0].textContent == "True");
  781. if (fieldsNode.childNodes[i].getElementsByTagName('InPrimaryKey')[0].textContent == "True")
  782. aTable.keyfields.push(f.name);
  783. aTable.fields.push(f);
  784. };
  785. if (aCallback)
  786. aCallback();
  787. }, RemObjects.UTIL.showError);
  788. };
  789. RemObjects.DataAbstract.RemoteDataAdapter.prototype.executeCommand = function executeCommand(aName, aParameters, onSuccess, onError) {
  790. if (aParameters.constructor != Array) {
  791. aParameters = [aParameters];
  792. };
  793. var params = new RemObjects.DataAbstract.Server.DataParameterArray();
  794. params.items = aParameters;
  795. this.fService.ExecuteCommand(aName, params, onSuccess, onError)
  796. };
  797. RemObjects.DataAbstract.RemoteDataAdapter.prototype.getSQLData = function getSQLData(aTable, aSQL, onSuccess, onError) {
  798. var ria = new RemObjects.DataAbstract.Server.TableRequestInfoArray();
  799. ria.elementType = "TableRequestInfoV6";
  800. if (aTable.constructor != Array) {
  801. aTable = [aTable];
  802. };
  803. switch (aSQL.constructor) {
  804. case RemObjects.DataAbstract.Server.TableRequestInfoV6:
  805. ria.items.push(aSQL);
  806. break;
  807. case Array:
  808. for (var i = 0; i < aTable.length; i++) {
  809. switch (aSQL[i].constructor) {
  810. case RemObjects.DataAbstract.Server.TableRequestInfoV6:
  811. ria.items.push(aSQL[i]);
  812. break;
  813. case String:
  814. ria.items.push(RemObjects.DataAbstract.Util.createRequestInfoV6(aSQL[i]));
  815. break;
  816. default:
  817. throw new Error("rda.getSQLData: incorrect aRequestInfo array item");
  818. };
  819. };
  820. break;
  821. case String:
  822. ria.items.push(RemObjects.DataAbstract.Util.createRequestInfoV6(aSQL));
  823. break;
  824. default:
  825. throw new Error("rda.getSQLData: incorrect aSQL");
  826. };
  827. this.getData(aTable, ria, onSuccess, onError);
  828. };
  829. RemObjects.DataAbstract.RemoteDataAdapter.prototype.getAutoGetScripts = function getAutoGetScripts() {
  830. return this.fAutoGetScripts;
  831. };
  832. RemObjects.DataAbstract.RemoteDataAdapter.prototype.setAutoGetScripts = function setAutoGetScripts(aValue) {
  833. this.fAutoGetScripts = aValue;
  834. };
  835. RemObjects.DataAbstract.RemoteDataAdapter.prototype.intGetScripts = function intGetScripts(aTable, onSuccess, onError) {
  836. var tableNames = [];
  837. if (aTable.constructor != Array) {
  838. aTable = [aTable];
  839. };
  840. for (var i = 0; i < aTable.length; tableNames.push(aTable[i++].name));
  841. this.fService.GetDatasetScripts(tableNames.join(","), function (aScript) {
  842. for (var t = 0; t < aTable.length; t++) {
  843. var __tbl = aTable[t];
  844. __tbl.__onNewRow = null;
  845. __tbl.__beforeDelete = null;
  846. __tbl.__beforePost = null;
  847. var r = new RegExp('<' + aTable[t].name + ' Language="(.*?)"><!\\[CDATA\\[([\\s\\S]*?)\\]\\]', "mi");
  848. var m = r.exec(aScript);
  849. var s = (m ? m[2] : "");
  850. var m1 = s.match(/function (.*?)\(/g);
  851. if (m1) for (var i = 0; i < m1.length; i++) {
  852. s = s.replace(m1[i], m1[i].replace(/function (.*?)\(/, "__tbl.__$1 = ") + m1[i]);
  853. }
  854. var m1 = s.match(/function (.*?)\{/g);
  855. if (m1) for (var i = 0; i < m1.length; i++) {
  856. s = s.replace(m1[i], m1[i] + '\nfor (var p in RemObjects.DataAbstract.Scripting) {\n' +
  857. 'eval("var " + p + " = RemObjects.DataAbstract.Scripting." + p);\n' +
  858. '};\n');
  859. }
  860. eval(s);
  861. };
  862. if (onSuccess) onSuccess();
  863. }, onError);
  864. };
  865. RemObjects.DataAbstract.RemoteDataAdapter.prototype.getData = function getData(aTable, aRequestInfo, onSuccess, onError) {
  866. var tableNames = new RemObjects.DataAbstract.Server.StringArray();
  867. if (aTable.constructor != Array) {
  868. aTable = [aTable];
  869. };
  870. for (var i = 0; i < aTable.length; tableNames.items.push(aTable[i++].name));
  871. var tableOptions = new RemObjects.DataAbstract.Server.TableRequestInfoArray();
  872. switch (aRequestInfo.constructor) {
  873. case RemObjects.DataAbstract.Server.TableRequestInfoArray:
  874. tableOptions = aRequestInfo;
  875. break;
  876. case RemObjects.DataAbstract.Server.TableRequestInfo:
  877. case RemObjects.DataAbstract.Server.TableRequestInfoV5:
  878. case RemObjects.DataAbstract.Server.TableRequestInfoV6:
  879. tableOptions.items.push(aRequestInfo);
  880. break;
  881. case Array:
  882. tableOptions.items = aRequestInfo;
  883. break;
  884. default:
  885. var requestInfo = RemObjects.DataAbstract.Util.createRequestInfo();
  886. for (var i = 0; i < aTable.length; i++) {
  887. tableOptions.items.push(requestInfo);
  888. };
  889. };
  890. for (var i = 0; i < aTable.length; i++) {
  891. if (aTable[i].dynamicWhere) {
  892. var requestInfoV5 = RemObjects.DataAbstract.Util.createRequestInfoV5(tableOptions.items[i].IncludeSchema.value,
  893. tableOptions.items[i].MaxRecords.value, tableOptions.items[i].UserFilter.value, tableOptions.items[i].Parameters.value.items);
  894. requestInfoV5.WhereClause.value = aTable[i].dynamicWhere.toXML();
  895. tableOptions.items[i] = requestInfoV5;
  896. };
  897. };
  898. var __onError, __onSuccess;
  899. if (arguments.length < 4) {
  900. __onError = arguments[arguments.length - 1];
  901. __onSuccess = arguments[arguments.length - 2];
  902. } else {
  903. __onError = onError;
  904. __onSuccess = onSuccess;
  905. };
  906. var that = this;
  907. this.fService.GetData(tableNames, tableOptions,
  908. function (result) {
  909. var streamer = that.createStreamer();
  910. var tmp = (that.fService.fMessage instanceof RemObjects.SDK.JSONMessage) ? RemObjects.UTIL.fromBase64(result) : result;
  911. streamer.setStream(tmp);
  912. streamer.initializeRead();
  913. for (var i = 0; i < aTable.length; i++) {
  914. streamer.readDataset(aTable[i]);
  915. };
  916. if (that.fAutoGetScripts) {
  917. that.intGetScripts(aTable, __onSuccess, __onError);
  918. } else if (__onSuccess) __onSuccess();
  919. }, __onError);
  920. };
  921. RemObjects.DataAbstract.RemoteDataAdapter.prototype.onChangeFail = function onChangeFail(aData) {
  922. RemObjects.UTIL.showMessage("Update failed for:\n" + RemObjects.UTIL.toJSON(aData));
  923. };
  924. RemObjects.DataAbstract.RemoteDataAdapter.prototype.applyUpdates = function applyUpdates(aTable, onSuccess, onError) {
  925. if (aTable.constructor != Array) {
  926. aTable = [aTable];
  927. };
  928. var __deltas = new RemObjects.DataAbstract.Deltas();
  929. for (var i = 0; i < aTable.length; i++) {
  930. aTable[i].post();
  931. var d = this.buildDelta(aTable[i]);
  932. if (d) __deltas.deltas.push(d);
  933. };
  934. if (__deltas.deltas.length > 0) {
  935. var that = this;
  936. var streamer = this.createStreamer();
  937. streamer.initializeWrite();
  938. streamer.writeDelta(__deltas, this.fSendReducedDelta);
  939. streamer.finalizeWrite();
  940. var tmp = streamer.getStream();
  941. this.fService.UpdateData(tmp, function (result) {
  942. var tmp = (that.fService.fMessage instanceof RemObjects.SDK.JSONMessage) ? RemObjects.UTIL.fromBase64(result) : result;
  943. var streamer = that.createStreamer();
  944. streamer.setStream(tmp);
  945. streamer.initializeRead();
  946. var __res = streamer.readDelta();
  947. for (var i = 0; i < __deltas.deltas.length; i++) {
  948. var processedTable = null;
  949. for (var t = 0; t < aTable.length; t++) {
  950. if (aTable[t].name == __deltas.deltas[i].name) {
  951. processedTable = aTable[t];
  952. break;
  953. };
  954. };
  955. var baseDelta = __deltas.deltas[i];
  956. var processedDelta = __res.findByName(__deltas.deltas[i].name);
  957. if (processedDelta) {
  958. for (var j = 0; j < processedDelta.data.length; j++) {
  959. if (processedTable) {
  960. switch (processedDelta.data[j].status) {
  961. case "failed":
  962. that.onChangeFail(processedDelta.data[j]);
  963. //remove from baseDelta
  964. baseDelta.data.splice(baseDelta.intFindId(processedDelta.data[j].recid), 1);
  965. break;
  966. case "resolved":
  967. if (processedTable.findId(processedDelta.data[j].recid)) {
  968. for (var k = 0; k < processedDelta.loggedfields.length; k++) {
  969. if (processedDelta.data[j]["new"][k] != processedDelta.data[j]["old"][k]) {
  970. var fieldNum = processedTable.fieldNumByName(processedDelta.loggedfields[k].name);
  971. processedTable.currentRow().__newValues[fieldNum] = processedDelta.data[j]["new"][k];
  972. processedTable.currentRow().__oldValues[fieldNum] = processedDelta.data[j]["new"][k];
  973. };
  974. };
  975. processedTable.currentRow().state = RemObjects.DataAbstract.Enum.RowStates.rsUnchanged;
  976. processedTable.currentRow().__oldValues = processedTable.currentRow().__newValues.slice();
  977. } else {
  978. var deleted = processedTable.intFindDeleted(processedDelta.data[j].recid);
  979. if (deleted != null) {
  980. processedTable.deletedRows.splice(deleted, 1);
  981. } else {
  982. RemObjects.UTIL.showMessage("Incorrect recid in resolved change:\n" + RemObjects.UTIL.toJSON(processedDelta.data[j]));
  983. };
  984. };
  985. break;
  986. };
  987. } else {
  988. RemObjects.UTIL.showMessage("Incorrect table name in result delta:\n" + RemObjects.UTIL.toJSON(processedDelta));
  989. };
  990. };
  991. };
  992. for (var j = 0; j < baseDelta.data.length; j++) {
  993. if (processedTable.findId(baseDelta.data[j].recid)) {
  994. processedTable.currentRow().state = RemObjects.DataAbstract.Enum.RowStates.rsUnchanged;
  995. processedTable.currentRow().__oldValues = [];
  996. };
  997. var deleted = processedTable.intFindDeleted(baseDelta.data[j].recid);
  998. if (deleted != null) {
  999. processedTable.deletedRows.splice(deleted, 1);
  1000. };
  1001. };
  1002. };
  1003. if (onSuccess) onSuccess(__res);
  1004. }, onError);
  1005. };
  1006. };
  1007. RemObjects.DataAbstract.JSONDataStreamer.prototype.setStream = function setStream(aStream) {
  1008. this.fStream = aStream;
  1009. };
  1010. RemObjects.DataAbstract.JSONDataStreamer.prototype.getStream = function getStream() {
  1011. return this.fStream;
  1012. };
  1013. RemObjects.DataAbstract.JSONDataStreamer.prototype.initializeRead = function () {
  1014. };
  1015. RemObjects.DataAbstract.JSONDataStreamer.prototype.initializeWrite = function () {
  1016. };
  1017. RemObjects.DataAbstract.JSONDataStreamer.prototype.finalizeWrite = function () {
  1018. };
  1019. RemObjects.DataAbstract.JSONDataStreamer.prototype.readDataset = function readDataset(dataset) {
  1020. dataset.rows = [];
  1021. dataset.fNextRecId = 0;
  1022. var rows = null;
  1023. var datasets = RemObjects.UTIL.parseJSON(this.fStream).datasets;
  1024. for (var i = 0; i < datasets.length; i++) {
  1025. if (datasets[i].schema) {
  1026. dataset.fields.length = 0;
  1027. dataset.keyfields.length = 0;
  1028. for (var j = 0; j < datasets[i].schema.fields.length; j++) {
  1029. var schemaField = datasets[i].schema.fields[j];
  1030. var datasetField = new RemObjects.DataAbstract.Field();
  1031. datasetField.name = schemaField.Name;
  1032. datasetField.type = schemaField.DataType;
  1033. datasetField.logChanges = schemaField.LogChanges;
  1034. if (schemaField.InPrimaryKey == true) {
  1035. datasetField.inPrimaryKey = true;
  1036. dataset.keyfields.push(schemaField.Name);
  1037. };
  1038. dataset.fields.push(datasetField);
  1039. };
  1040. };
  1041. if (datasets[i].name.toUpperCase() == dataset.name.toUpperCase()) {
  1042. rows = datasets[i].data.rows;
  1043. break;
  1044. };
  1045. };
  1046. if (!rows) throw new Error("readDataset: dataset not found - " + dataset.name);
  1047. for (var i = 0; i < rows.length; i++) {
  1048. var r = dataset.intAppendRow();
  1049. r.state = RemObjects.DataAbstract.Enum.RowStates.rsUnchanged;
  1050. r.__newValues = rows[i];
  1051. };
  1052. };
  1053. RemObjects.DataAbstract.JSONDataStreamer.prototype.writeDelta = function writeDelta(aDelta) {
  1054. this.fStream = RemObjects.UTIL.toJSON(aDelta);
  1055. };
  1056. RemObjects.DataAbstract.JSONDataStreamer.prototype.readDelta = function readDelta() {
  1057. var result = new RemObjects.DataAbstract.Deltas();
  1058. var remoteDelta = RemObjects.UTIL.parseJSON(this.fStream);
  1059. if (remoteDelta.deltas) {
  1060. for (var i = 0; i < remoteDelta.deltas.length; i++) {
  1061. result.deltas.push(remoteDelta.deltas[i]);
  1062. };
  1063. };
  1064. return result;
  1065. };
  1066. RemObjects.DataAbstract.Bin2DataStreamer.prototype.setStream = function setStream(aStream) {
  1067. this.fStream = aStream;
  1068. };
  1069. RemObjects.DataAbstract.Bin2DataStreamer.prototype.getStream = function getStream() {
  1070. return this.fStream;
  1071. };
  1072. RemObjects.DataAbstract.Bin2DataStreamer.prototype.initializeRead = function initializeRead() {
  1073. if (this.fStream.substr(0, 8) != "DABIN200")
  1074. throw new Error("Bin2DataStreamer.initializeRead: incorrect stream header");
  1075. this.fStreamPos = 8;
  1076. this.fStreamInfoPos = this.readInteger();
  1077. };
  1078. RemObjects.DataAbstract.Bin2DataStreamer.prototype.initializeWrite = function initializeWrite() {
  1079. };
  1080. RemObjects.DataAbstract.Bin2DataStreamer.prototype.finalizeWrite = function finalizeWrite() {
  1081. this.fStream = "DABIN200" + this.fParser.encodeInt(this.fStreamInfoPos + 12, 32, false) + this.fStream;
  1082. };
  1083. RemObjects.DataAbstract.Bin2DataStreamer.prototype.readByte = function readByte() {
  1084. var result = this.fParser.decodeInt(this.fStream.substr(this.fStreamPos, 1), 8, false);
  1085. this.fStreamPos += 1;
  1086. return result;
  1087. };
  1088. RemObjects.DataAbstract.Bin2DataStreamer.prototype.readInteger = function readInteger() {
  1089. var result = this.fParser.decodeInt(this.fStream.substr(this.fStreamPos, 4), 32, false);
  1090. this.fStreamPos += 4;
  1091. return result;
  1092. };
  1093. RemObjects.DataAbstract.Bin2DataStreamer.prototype.readAnsiStringWithLength = function readAnsiStringWithLength() {
  1094. var len = this.fParser.decodeInt(this.fStream.substr(this.fStreamPos, 4), 32, false);
  1095. this.fStreamPos += 4;
  1096. var result = this.fStream.substr(this.fStreamPos, len);
  1097. this.fStreamPos += len;
  1098. return result;
  1099. };
  1100. RemObjects.DataAbstract.Bin2DataStreamer.prototype.readUtf8StringWithLength = function readUtf8StringWithLength() {
  1101. var len = this.fParser.decodeInt(this.fStream.substr(this.fStreamPos, 4), 32, true);
  1102. this.fStreamPos += 4;
  1103. if (len == -1) return null;
  1104. var result = RemObjects.UTIL.byteArrayToStr(this.fStream.substr(this.fStreamPos, len));
  1105. this.fStreamPos += len;
  1106. return result;
  1107. };
  1108. RemObjects.DataAbstract.Bin2DataStreamer.prototype.read = function read(aType) {
  1109. var value;
  1110. switch (aType) {
  1111. case "datFixedChar"://ok
  1112. case "datString"://ok
  1113. case "datMemo"://ok
  1114. var len = this.fParser.decodeInt(this.fStream.substr(this.fStreamPos, 4), 32, false);
  1115. this.fStreamPos += 4;
  1116. value = this.fStream.substr(this.fStreamPos, len);
  1117. this.fStreamPos += len;
  1118. break;
  1119. case "datBlob":
  1120. case "datCursor":
  1121. var len = this.fParser.decodeInt(this.fStream.substr(this.fStreamPos, 4), 32, false);
  1122. this.fStreamPos += 4;
  1123. value = this.fStream.substr(this.fStreamPos, len);
  1124. this.fStreamPos += len;
  1125. break;
  1126. /* value = "";
  1127. for (var i = this.fStreamPos; i < this.fStreamPos + len; i++) {
  1128. value += String.fromCharCode(this.fStream.charCodeAt(i) & 0xFF);
  1129. };
  1130. this.fStreamPos += len;
  1131. break;
  1132. */
  1133. case "datWideString"://ok
  1134. case "datFixedWideChar"://ok
  1135. case "datWideMemo"://ok
  1136. case "datXml"://ok
  1137. var len = this.fParser.decodeInt(this.fStream.substr(this.fStreamPos, 4), 32, false);
  1138. this.fStreamPos += 4;
  1139. value = RemObjects.UTIL.byteArrayToUtf16(this.fStream.substr(this.fStreamPos, len));
  1140. this.fStreamPos += len;
  1141. break;
  1142. case "datAutoInc"://ok
  1143. case "datInteger"://ok
  1144. value = this.fParser.decodeInt(this.fStream.substr(this.fStreamPos, 4), 32, true);
  1145. this.fStreamPos += 4;
  1146. break;
  1147. case "datSmallInt"://ok
  1148. value = this.fParser.decodeInt(this.fStream.substr(this.fStreamPos, 2), 16, true);
  1149. this.fStreamPos += 2;
  1150. break;
  1151. case "datDateTime"://ok
  1152. var utcValue = this.fParser.decodeFloat(this.fStream.substr(this.fStreamPos, 8), 52, 11);
  1153. utcValue = new Date(Math.round((utcValue - 25569.0) * 86400000));
  1154. value = new Date(utcValue.getUTCFullYear(), utcValue.getUTCMonth(), utcValue.getUTCDate(), utcValue.getUTCHours(), utcValue.getUTCMinutes(), utcValue.getUTCSeconds());
  1155. //value = this.fParser.decodeFloat(this.fStream.substr(this.fStreamPos, 8), 52, 11);
  1156. //value = new Date(Math.round((value - 25569.0) * 86400000));
  1157. this.fStreamPos += 8;
  1158. break;
  1159. case "datCurrency"://ok
  1160. value = this.fParser.decodeInt(this.fStream.substr(this.fStreamPos, 6), 48, true) / 10000;
  1161. this.fStreamPos += 8;
  1162. break;
  1163. case "datFloat"://ok
  1164. value = this.fParser.decodeFloat(this.fStream.substr(this.fStreamPos, 8), 52, 11);
  1165. this.fStreamPos += 8;
  1166. break;
  1167. case "datSingleFloat": //ok
  1168. value = this.fParser.decodeFloat(this.fStream.substr(this.fStreamPos, 4), 23, 8);
  1169. this.fStreamPos += 4;
  1170. break;
  1171. case "datBoolean"://ok
  1172. value = !(this.fParser.decodeInt(this.fStream.substr(this.fStreamPos, 1), 8, false) == 0);
  1173. this.fStreamPos += 1;
  1174. break;
  1175. case "datByte"://ok
  1176. value = this.fParser.decodeInt(this.fStream.substr(this.fStreamPos, 1), 8, false);
  1177. this.fStreamPos += 1;
  1178. break;
  1179. case "datLargeInt"://ok
  1180. case "datLargeAutoInc"://ok
  1181. value = this.fParser.decodeInt(this.fStream.substr(this.fStreamPos, 6), 48, true);
  1182. this.fStreamPos += 8;
  1183. break;
  1184. case "datLargeUInt"://ok
  1185. value = this.fParser.decodeInt(this.fStream.substr(this.fStreamPos, 6), 48, false);
  1186. this.fStreamPos += 8;
  1187. break;
  1188. case "datShortInt"://ok
  1189. value = this.fParser.decodeInt(this.fStream.substr(this.fStreamPos, 1), 8, true);
  1190. this.fStreamPos += 1;
  1191. break;
  1192. case "datWord"://ok
  1193. value = this.fParser.decodeInt(this.fStream.substr(this.fStreamPos, 2), 16, false);
  1194. this.fStreamPos += 2;
  1195. break;
  1196. case "datDecimal"://ok
  1197. var decimal = [];
  1198. for (var i = 0; i < 6; i++) {
  1199. decimal[i] = this.fParser.decodeInt(this.fStream.substr(this.fStreamPos, 2), 16, false);
  1200. this.fStreamPos += 2;
  1201. };
  1202. decimal[6] = this.fParser.decodeInt(this.fStream.substr(this.fStreamPos, 4), 32, false);
  1203. this.fStreamPos += 4;
  1204. value = parseFloat(RemObjects.UTIL.decimalToString(decimal));
  1205. break;
  1206. case "datGuid"://ok
  1207. value = "{" + this.fStream.substr(this.fStreamPos, 36) + "}";
  1208. this.fStreamPos += 36;
  1209. break;
  1210. case "datCardinal"://ok
  1211. value = this.fParser.decodeInt(this.fStream.substr(this.fStreamPos, 4), 32, false);
  1212. this.fStreamPos += 4;
  1213. break;
  1214. /*
  1215. datBlob: BlobToStreamAsStr(Stream, Value);
  1216. * */
  1217. default:
  1218. throw new Error("Bin2DataStreamer.read: unknown type " + aType);
  1219. };
  1220. return value;
  1221. };
  1222. RemObjects.DataAbstract.Bin2DataStreamer.prototype.readParam = function readParam(aPropCount) {
  1223. var result = {};
  1224. for (var i = 0; i < aPropCount; i++) {
  1225. result[this.readAnsiStringWithLength()] = this.readUtf8StringWithLength();
  1226. };
  1227. return result;
  1228. };
  1229. RemObjects.DataAbstract.Bin2DataStreamer.prototype.readField = function readField(aPropCount) {
  1230. function camelize(str) {
  1231. return str.substr(0, 1).toLowerCase() + str.substr(1);
  1232. };
  1233. var result = new RemObjects.DataAbstract.Field();
  1234. try {
  1235. for (var i = 0; i < aPropCount; i++) {
  1236. result[camelize(this.readAnsiStringWithLength())] = this.readUtf8StringWithLength();
  1237. };
  1238. result.type = result.dataType;
  1239. if (result.type == "datAutoInc" || result.type == "datLargeAutoInc") {
  1240. result.fAutoIncSequence = -1;
  1241. };
  1242. result.logChanges = (result.logChanges == "True");
  1243. return result;
  1244. } catch (e) {
  1245. throw new Error("Bin2DataStreamer.readField: " + e.message);
  1246. };
  1247. };
  1248. RemObjects.DataAbstract.Bin2DataStreamer.prototype.readDataset = function readDataset(aDataset) {
  1249. if (this.readByte() != 0) {//schema present
  1250. this.readInteger(); //skip schema end position
  1251. var fieldCount = this.readInteger();
  1252. var propCount = this.readInteger();
  1253. aDataset.fields = [];
  1254. aDataset.keyfields = [];
  1255. for (var i = 0; i < fieldCount; i++) {
  1256. var f = this.readField(propCount);
  1257. aDataset.fields.push(f);
  1258. if (f.inPrimaryKey.toLowerCase() == "true") {
  1259. aDataset.keyfields.push(f.name);
  1260. };
  1261. };
  1262. var paramCount = this.readInteger();
  1263. propCount = this.readInteger();
  1264. for (var i = 0; i < paramCount; i++) {
  1265. this.readParam(propCount);
  1266. };
  1267. } else {
  1268. this.readInteger(); //skip schema end position
  1269. };
  1270. var rowCount = this.readInteger();
  1271. var fieldCount = this.readInteger();
  1272. aDataset.rows = [];
  1273. aDataset.fNextRecId = 0;
  1274. for (var i = 0; i < fieldCount; i++) {
  1275. this.readAnsiStringWithLength(); //skip field name
  1276. this.readByte(); //skip field type
  1277. this.readInteger(); //skip field size
  1278. };
  1279. var bitMaskSize = Math.floor((fieldCount + 7) / 8);
  1280. for (var i = 0; i < rowCount; i++) {
  1281. var r = aDataset.intAppendRow();
  1282. r.state = RemObjects.DataAbstract.Enum.RowStates.rsUnchanged;
  1283. var bitMask = "";
  1284. for (var b = 0; b < bitMaskSize; b++) {
  1285. bitMask += RemObjects.UTIL.zeroPad(this.fParser.decodeInt(this.fStream.substr(this.fStreamPos + bitMaskSize - 1 - b, 1), 8, false).toString(2), 8);
  1286. };
  1287. var bitMaskArray = bitMask.split("").reverse();
  1288. this.fStreamPos += bitMaskSize;
  1289. for (var j = 0; j < fieldCount; j++) {
  1290. r.__newValues[j] = (bitMaskArray[j] == '1') ? null : this.read(aDataset.fields[j].type);
  1291. };
  1292. };
  1293. };
  1294. RemObjects.DataAbstract.Bin2DataStreamer.prototype.writeInteger = function writeInteger(aValue) {
  1295. this.write("datInteger", aValue);
  1296. };
  1297. RemObjects.DataAbstract.Bin2DataStreamer.prototype.writeByte = function writeByte(aValue) {
  1298. this.fStream += this.fParser.encodeInt(aValue, 8, true);
  1299. };
  1300. RemObjects.DataAbstract.Bin2DataStreamer.prototype.writeAnsiStringWithLength = function writeAnsiStringWithLength(aValue) {
  1301. this.fStream += this.fParser.encodeInt(aValue.length, 32, false) + aValue;
  1302. };
  1303. RemObjects.DataAbstract.Bin2DataStreamer.prototype.write = function write(aType, aValue) {
  1304. switch (aType) {
  1305. case "datFixedChar"://ok
  1306. case "datString"://ok
  1307. case "datMemo"://ok
  1308. case "datBlob":
  1309. case "datCursor":
  1310. this.writeAnsiStringWithLength(aValue);
  1311. break;
  1312. case "datWideString"://ok
  1313. case "datFixedWideChar"://ok
  1314. case "datWideMemo"://ok
  1315. case "datXml"://ok
  1316. this.fStream += this.fParser.encodeInt(aValue.length * 2, 32, true);
  1317. this.fStream += RemObjects.UTIL.utf16ToByteArray(aValue);
  1318. break;
  1319. case "datAutoInc"://ok
  1320. case "datInteger"://ok
  1321. this.fStream += this.fParser.encodeInt(aValue, 32, true);
  1322. break;
  1323. case "datSmallInt"://ok
  1324. this.fStream += this.fParser.encodeInt(aValue, 16, true);
  1325. break;
  1326. case "datDateTime"://todo:test
  1327. if (!(aValue instanceof Date)) {
  1328. throw new Error("Not a Date value: " + aValue);
  1329. };
  1330. this.fStream += this.fParser.encodeFloat((aValue - aValue.getTimezoneOffset() * 60000) / 86400000 + 25569.0, 52, 11);
  1331. break;
  1332. case "datCurrency":
  1333. var cur = this.fParser.encodeInt(aValue * 10000, 48, true);
  1334. this.fStream += cur;
  1335. if ((cur.charCodeAt(cur.length - 1) == 0) || (cur.charCodeAt(cur.length - 1) == 0xFF)) {
  1336. this.fStream += cur.substr(cur.length - 1, 1) + cur.substr(cur.length - 1, 1);
  1337. };
  1338. break;
  1339. case "datFloat"://ok
  1340. this.fStream += this.fParser.encodeFloat(aValue, 52, 11);
  1341. break;
  1342. case "datSingleFloat": //ok
  1343. this.fStream += this.fParser.encodeFloat(aValue, 23, 8);
  1344. break;
  1345. case "datBoolean"://ok
  1346. this.fStream += this.fParser.encodeInt(aValue ? 1 : 0, 8, false);
  1347. break;
  1348. case "datByte"://ok
  1349. this.fStream += this.fParser.encodeInt(aValue, 8, false);
  1350. break;
  1351. case "datLargeInt"://ok
  1352. case "datLargeAutoInc"://ok
  1353. var large = this.fParser.encodeInt(aValue, 48, true);
  1354. this.fStream += large;
  1355. if ((large.charCodeAt(large.length - 1) == 0) || (large.charCodeAt(large.length - 1) == 0xFF)) {
  1356. this.fStream += large.substr(large.length - 1, 1) + large.substr(large.length - 1, 1);
  1357. };
  1358. break;
  1359. case "datLargeUInt"://ok
  1360. var large = this.fParser.encodeInt(aValue, 48, false);
  1361. this.fStream += large;
  1362. if ((large.charCodeAt(large.length - 1) == 0) || (large.charCodeAt(large.length - 1) == 0xFF)) {
  1363. this.fStream += large.substr(large.length - 1, 1) + large.substr(large.length - 1, 1);
  1364. };
  1365. break;
  1366. case "datShortInt"://ok
  1367. this.fStream += this.fParser.encodeInt(aValue, 8, true);
  1368. break;
  1369. case "datWord"://ok
  1370. this.fStream += this.fParser.encodeInt(aValue, 16, false);
  1371. break;
  1372. case "datDecimal"://ok
  1373. var decimal = RemObjects.UTIL.stringToDecimal(aValue.toString());
  1374. for (var i = 0; i < 6; i++) {
  1375. this.fStream += this.fParser.encodeInt(decimal[i], 16, false);
  1376. };
  1377. this.fStream += this.fParser.encodeInt(decimal[6], 32, false);
  1378. break;
  1379. case "datGuid"://ok
  1380. this.fStream += aValue.substr(1, 36);
  1381. break;
  1382. case "datCardinal"://ok
  1383. this.fStream += this.fParser.encodeInt(aValue, 32, false);
  1384. break;
  1385. /*
  1386. datBlob: BlobToStreamAsStr(Stream, Value);
  1387. * */
  1388. default:
  1389. throw new Error("Bin2DataStreamer.write: unknown type " + aType);
  1390. };
  1391. };
  1392. RemObjects.DataAbstract.Bin2DataStreamer.prototype.writeDelta = function writeDelta(aDeltas, aSendReducedDelta) {
  1393. function indexOf(anArray, aValue) {
  1394. for (var i = 0; i < anArray.length; i++) {
  1395. if (anArray[i] == aValue) return i;
  1396. };
  1397. return -1;
  1398. };
  1399. var offsets = [];
  1400. for (var d = 0; d < aDeltas.deltas.length; d++) {
  1401. offsets.push(this.fStream.length);
  1402. var aDelta = aDeltas.deltas[d];
  1403. this.writeInteger(aDelta.data.length); //changes count
  1404. this.writeInteger(aDelta.loggedfields.length); //fields count
  1405. for (var i = 0; i < aDelta.loggedfields.length; i++) {
  1406. this.writeAnsiStringWithLength(RemObjects.UTIL.strToByteArray(aDelta.loggedfields[i].name));
  1407. this.writeByte(indexOf(RemObjects.DataAbstract.DADataType, aDelta.loggedfields[i].type));
  1408. };
  1409. this.writeInteger(aDelta.keyfields.length); //key fields count
  1410. for (var i = 0; i < aDelta.keyfields.length; i++) {
  1411. this.writeAnsiStringWithLength(RemObjects.UTIL.strToByteArray(aDelta.keyfields[i]));
  1412. };
  1413. this.writeByte(aSendReducedDelta ? 1 : 0); //hasReducedDelta
  1414. this.writeInteger(aDelta.data.length); //changes count
  1415. var bitMaskSize = Math.floor((aDelta.loggedfields.length + 7) / 8);
  1416. var bitMaskOld;
  1417. var bitMaskNew;
  1418. for (var i = 0; i < aDelta.data.length; i++) {
  1419. bitMaskOld = new Array(bitMaskSize);
  1420. bitMaskNew = new Array(bitMaskSize);
  1421. for (var j = 0; j < aDelta.loggedfields.length; j++) {
  1422. bitMaskNew[j] = (aDelta.data[i]["new"][j] == null || typeof (aDelta.data[i]["new"][j]) == 'undefined') ? "0" : "1";
  1423. bitMaskOld[j] = (aDelta.data[i].old[j] == null || typeof (aDelta.data[i].old[j]) == 'undefined') ? "0" : "1";
  1424. };
  1425. this.writeInteger(indexOf(RemObjects.DataAbstract.Enum.ChangeTypeNames, aDelta.data[i].changetype));
  1426. this.writeInteger(aDelta.data[i].recid);
  1427. this.writeInteger(RemObjects.DataAbstract.Enum.ChangeStatus.csPending);
  1428. this.writeAnsiStringWithLength("");
  1429. // this.fStream += this.fParser.encodeInt(parseInt(bitMaskOld.reverse().join(""), 2), bitMaskSize * 8, false);
  1430. // bitMaskOld.reverse();
  1431. for (var b = 0; b < bitMaskSize; b++) {
  1432. this.fStream += this.fParser.encodeInt(parseInt(bitMaskOld.slice(b * 8, (b + 1) * 8).reverse().join(""), 2), 8, false);
  1433. };
  1434. for (var j = 0; j < aDelta.loggedfields.length; j++) {
  1435. if (bitMaskOld[j] == "1") {
  1436. this.write(aDelta.loggedfields[j].type, aDelta.data[i].old[j]);
  1437. };
  1438. };
  1439. // this.fStream += this.fParser.encodeInt(parseInt(bitMaskNew.reverse().join(""), 2), bitMaskSize * 8, false);
  1440. // bitMaskNew.reverse();
  1441. for (var b = 0; b < bitMaskSize; b++) {
  1442. this.fStream += this.fParser.encodeInt(parseInt(bitMaskNew.slice(b * 8, (b + 1) * 8).reverse().join(""), 2), 8, false);
  1443. };
  1444. for (var j = 0; j < aDelta.loggedfields.length; j++) {
  1445. if (bitMaskNew[j] == "1") {
  1446. this.write(aDelta.loggedfields[j].type, aDelta.data[i]["new"][j]);
  1447. };
  1448. };
  1449. };
  1450. };
  1451. this.fStreamInfoPos = this.fStream.length; //will be used in finalizeWrite
  1452. this.writeInteger(aDeltas.deltas.length); //delta count
  1453. for (var i = 0; i < aDeltas.deltas.length; i++) {
  1454. this.writeInteger(1); //etDelta
  1455. this.writeAnsiStringWithLength(RemObjects.UTIL.strToByteArray(aDeltas.deltas[i].name));
  1456. this.writeInteger(offsets[i] + 12); //first delta position
  1457. };
  1458. };
  1459. RemObjects.DataAbstract.Bin2DataStreamer.prototype.readDelta = function readDelta() {
  1460. var savedPos = this.fStreamPos;
  1461. this.fStreamPos = this.fStreamInfoPos;
  1462. var deltaCount = this.readInteger();
  1463. var result = new RemObjects.DataAbstract.Deltas();
  1464. for (var d = 0; d < deltaCount; d++) {
  1465. var delta = new RemObjects.DataAbstract.Delta();
  1466. var deltaType = this.readInteger();
  1467. delta.name = RemObjects.UTIL.byteArrayToStr(this.readAnsiStringWithLength());
  1468. var deltaPos = this.readInteger();
  1469. result.deltas.push(delta);
  1470. };
  1471. this.fStreamPos = savedPos;
  1472. for (var d = 0; d < deltaCount; d++) {
  1473. delta = result.deltas[d];
  1474. var changesCount = this.readInteger();
  1475. if (changesCount != 0) {
  1476. var fieldsCount = this.readInteger();
  1477. for (var i = 0; i < fieldsCount; i++) {
  1478. delta.loggedfields[i] = {};
  1479. delta.loggedfields[i].name = RemObjects.UTIL.byteArrayToStr(this.readAnsiStringWithLength());
  1480. delta.loggedfields[i].type = RemObjects.DataAbstract.DADataType[this.readByte()];
  1481. };
  1482. var keyFieldsCount = this.readInteger();
  1483. for (var i = 0; i < keyFieldsCount; i++) {
  1484. delta.keyfields[i] = RemObjects.UTIL.byteArrayToStr(this.readAnsiStringWithLength());
  1485. };
  1486. if (changesCount != 0) {
  1487. this.readByte(); //reduced?
  1488. changesCount = this.readInteger();
  1489. var bitMaskSize = Math.floor((fieldsCount + 7) / 8);
  1490. // var bitMaskOld;
  1491. // var bitMaskNew;
  1492. for (var i = 0; i < changesCount; i++) { //read changes
  1493. var change = new RemObjects.DataAbstract.Change();
  1494. change.changetype = RemObjects.DataAbstract.Enum.ChangeTypeNames[this.readInteger()];
  1495. change.recid = this.readInteger();
  1496. change.status = RemObjects.DataAbstract.Enum.ChangeStatusNames[this.readInteger()];
  1497. change.message = RemObjects.UTIL.byteArrayToStr(this.readAnsiStringWithLength());
  1498. // bitMaskOld = this.fParser.decodeInt(this.fStream.substr(this.fStreamPos, bitMaskSize), bitMaskSize * 8);
  1499. // this.fStreamPos += bitMaskSize;
  1500. // bitMaskOld = bitMaskOld.toString(2).split("").reverse();
  1501. var bitMaskOld = "";
  1502. for (var b = 0; b < bitMaskSize; b++) {
  1503. bitMaskOld += RemObjects.UTIL.zeroPad(this.fParser.decodeInt(this.fStream.substr(this.fStreamPos + bitMaskSize - 1 - b, 1), 8, false).toString(2), 8);
  1504. };
  1505. var bitMaskOld = bitMaskOld.split("").reverse();
  1506. this.fStreamPos += bitMaskSize;
  1507. for (var j = 0; j < fieldsCount; j++) {
  1508. change.old[j] = (bitMaskOld[j] == "1") ? this.read(delta.loggedfields[j].type) : null;
  1509. };
  1510. // bitMaskNew = this.fParser.decodeInt(this.fStream.substr(this.fStreamPos, bitMaskSize), bitMaskSize * 8);
  1511. // this.fStreamPos += bitMaskSize;
  1512. // bitMaskNew = bitMaskNew.toString(2).split("").reverse();
  1513. var bitMaskNew = "";
  1514. for (var b = 0; b < bitMaskSize; b++) {
  1515. bitMaskNew += RemObjects.UTIL.zeroPad(this.fParser.decodeInt(this.fStream.substr(this.fStreamPos + bitMaskSize - 1 - b, 1), 8, false).toString(2), 8);
  1516. };
  1517. var bitMaskNew = bitMaskNew.split("").reverse();
  1518. this.fStreamPos += bitMaskSize;
  1519. for (var j = 0; j < fieldsCount; j++) {
  1520. change["new"][j] = (bitMaskNew[j] == "1") ? this.read(delta.loggedfields[j].type) : null;
  1521. };
  1522. delta.data.push(change);
  1523. };
  1524. };
  1525. };
  1526. }
  1527. return result;
  1528. };
  1529. RemObjects.DataAbstract.DynamicWhere.prototype.toXML = function toXML() {
  1530. if (!this.fExpression) throw new Error("Dynamic Where: fExpression is null");
  1531. return '<query xmlns="http://www.remobjects.com/schemas/dataabstract/queries/5.0" version="5.0"><where>' +
  1532. this.fExpression.toXML() + '</where></query>';
  1533. };
  1534. RemObjects.DataAbstract.ConstantExpression.prototype.toXML = function toXML() {
  1535. return '<constant type="' + this.fType + '" null="' + this.fNull + '">' + this.fValue + '</constant>';
  1536. };
  1537. RemObjects.DataAbstract.NullExpression.prototype.toXML = function toXML() {
  1538. return '<null />';
  1539. };
  1540. RemObjects.DataAbstract.FieldExpression.prototype.toXML = function toXML() {
  1541. return '<field>' + this.fName + '</field>';
  1542. };
  1543. RemObjects.DataAbstract.MacroExpression.prototype.toXML = function toXML() {
  1544. return '<macro>' + this.fName + '</macro>';
  1545. };
  1546. RemObjects.DataAbstract.ListExpression.prototype.toXML = function toXML() {
  1547. var result = "<list>";
  1548. for (var i = 0; i < this.fItems.length; i++) {
  1549. result += this.fItems[i].toXML();
  1550. };
  1551. result += "</list>";
  1552. return result;
  1553. };
  1554. RemObjects.DataAbstract.UnaryExpression.prototype.toXML = function toXML() {
  1555. if (!this.fNode) throw new Error("UnaryExpression: fNode is null");
  1556. return '<unaryoperation' + (this.fOperator ? ' operator="' + this.fOperator + '"' : '') + '>'
  1557. + this.fNode.toXML() + '</unaryoperation>';
  1558. };
  1559. RemObjects.DataAbstract.BinaryExpression.prototype.toXML = function toXML() {
  1560. if (!(this.fNode1 || this.fNode2)) throw new Error("BinaryExpression: fNode1 or fNode2 is null");
  1561. return '<binaryoperation operator="' + this.fOperator + '">'
  1562. + this.fNode1.toXML() + this.fNode2.toXML() + '</binaryoperation>';
  1563. };
  1564. RemObjects.DataAbstract.BetweenExpression.prototype.toXML = function toXML() {
  1565. if (!(this.fNode1 || this.fNode2 || this.fNode3)) throw new Error("BetweenExpression: fNode1 or fNode2 or fNode3 is null");
  1566. return '<between>'
  1567. + this.fNode1.toXML() + this.fNode2.toXML() + this.fNode3.toXML() + '</between>';
  1568. };
  1569. RemObjects.DataAbstract.ParameterExpression.prototype.toXML = function toXML() {
  1570. return '<parameter type="' + this.fType + '"' + (this.fSize ? ' size="' + this.fSize + '"' : '') + '>'
  1571. + this.fName + '</parameter>';
  1572. };
  1573. RemObjects.DataAbstract.Views.HtmlTableView = function HtmlTAbleView(aTable, aHtmlTableId) {
  1574. var htmlTable = document.getElementById(aHtmlTableId);
  1575. var tRow = "";
  1576. for (var i = 0; i < aTable.fields.length; i++) {
  1577. tRow += "<td>" + aTable.fields[i].name + "</td>";
  1578. };
  1579. tRow = '<tr class="da_htmlTableHeader">' + tRow + "</tr>";
  1580. var r = aTable.first();
  1581. while (r) {
  1582. tRow += '<tr class = "da_htmlTableLine">';
  1583. for (var i = 0; i < aTable.fields.length; i++) {
  1584. tRow += "<td>" + (aTable.fields[i].type == "datBlob" ? "(Blob)" : r.__newValues[i]) + "</td>";
  1585. };
  1586. tRow += "</tr>";
  1587. r = aTable.next();
  1588. };
  1589. htmlTable.innerHTML = "<tbody>" + tRow + "</tbody>";
  1590. };
  1591. RemObjects.DataAbstract.Views.VerticalHtmlTableView = function VerticalHtmlTableView(aTable, aHtmlTableId) {
  1592. var htmlTable = document.getElementById(aHtmlTableId);
  1593. var tRow = "<td></td><td></td>";
  1594. var r = aTable.currentRow();
  1595. for (var i = 0; i < aTable.fields.length; i++) {
  1596. tRow += "<tr>";
  1597. tRow += '<td class="da_HtmlTableHeader">' + aTable.fields[i].name + "</td>";
  1598. tRow += "<td>" + (aTable.fields[i].type == "datBlob" ? "(Blob)" : r.__newValues[i]) + "</td>";
  1599. tRow += "</tr>";
  1600. };
  1601. htmlTable.innerHTML = "<tbody>" + tRow + "</tbody>";
  1602. };