~ubuntu-branches/ubuntu/hoary/gnucash/hoary

« back to all changes in this revision

Viewing changes to src/engine/Transaction-xml-parser-v1.c

  • Committer: Bazaar Package Importer
  • Author(s): James A. Treacy
  • Date: 2002-03-16 14:14:59 UTC
  • Revision ID: james.westby@ubuntu.com-20020316141459-wtkyyrpfovryhl1s
Tags: upstream-1.6.6
ImportĀ upstreamĀ versionĀ 1.6.6

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/********************************************************************\
 
2
 * Transaction-xml-parser-v1.c                                      *
 
3
 * Copyright (C) 2000 Gnumatic, Inc.                                *
 
4
 *                                                                  *
 
5
 * This program is free software; you can redistribute it and/or    *
 
6
 * modify it under the terms of the GNU General Public License as   *
 
7
 * published by the Free Software Foundation; either version 2 of   *
 
8
 * the License, or (at your option) any later version.              *
 
9
 *                                                                  *
 
10
 * This program is distributed in the hope that it will be useful,  *
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
 
13
 * GNU General Public License for more details.                     *
 
14
 *                                                                  *
 
15
 * You should have received a copy of the GNU General Public License*
 
16
 * along with this program; if not, contact:                        *
 
17
 *                                                                  *
 
18
 * Free Software Foundation           Voice:  +1-617-542-5942       *
 
19
 * 59 Temple Place - Suite 330        Fax:    +1-617-542-2652       *
 
20
 * Boston, MA  02111-1307,  USA       gnu@gnu.org                   *
 
21
\********************************************************************/
 
22
 
 
23
#include "config.h"
 
24
 
 
25
#include <string.h>
 
26
 
 
27
#include "sixtp.h"
 
28
#include "sixtp-utils.h"
 
29
#include "sixtp-parsers.h"
 
30
#include "sixtp-writers.h"
 
31
#include "sixtp-xml-write-utils.h"
 
32
 
 
33
#include "Transaction.h"
 
34
#include "TransactionP.h"
 
35
#include "Group.h"
 
36
 
 
37
/****************************************************************************/
 
38
/* <transaction> (parent <ledger-data>)
 
39
 
 
40
   This block does nothing but pass the ledger-data account group down
 
41
   to its children.  It generates no data of its own, so it doesn't
 
42
   need any cleanup.
 
43
 
 
44
   input: AccountGroup*
 
45
 
 
46
   to-children-via-*result: AccountGroup*
 
47
 
 
48
   returns: NA
 
49
   
 
50
   start: pass input to children.
 
51
 
 
52
   characters: ignore whitespace only
 
53
 
 
54
   end: NA
 
55
 
 
56
   cleanup-result: NA
 
57
 
 
58
   cleanup-chars: NA
 
59
 
 
60
   fail: NA
 
61
 
 
62
   result-fail: NA
 
63
 
 
64
   chars-fail: NA
 
65
 
 
66
 */
 
67
 
 
68
static gboolean
 
69
transaction_start_handler(GSList* sibling_data, gpointer parent_data,
 
70
                          gpointer global_data, gpointer *data_for_children,
 
71
                          gpointer *result, const gchar *tag, gchar **attrs)
 
72
{
 
73
  /* pass the parent data down to the children */
 
74
  *data_for_children = parent_data;
 
75
  return(TRUE);
 
76
}
 
77
 
 
78
/****************************************************************************/
 
79
/* <restore> (lineage <transaction> <ledger-data>)
 
80
   
 
81
   restores a given transaction.  We allocate the new transaction in
 
82
   the start block, the children modify it, and in the end block, we
 
83
   see if the resultant account is OK, and if so, we add it to the
 
84
   ledger-data's account group.
 
85
 
 
86
   from parent: AccountGroup*
 
87
 
 
88
   for children: new Transaction*
 
89
 
 
90
   result: NA
 
91
   
 
92
   -----------
 
93
 
 
94
   start: create new Transaction*, and store in data_for_children.
 
95
 
 
96
   chars: allow and ignore only whitespace.
 
97
 
 
98
   end: commit transaction to group if appropriate.
 
99
 
 
100
   cleanup-result: NA
 
101
 
 
102
   cleanup-chars: NA
 
103
 
 
104
   fail: delete Transaction* in data_for_children
 
105
 
 
106
   result-fail: NA
 
107
 
 
108
   chars-fail: NA
 
109
 
 
110
 */
 
111
 
 
112
static gboolean
 
113
txn_restore_start_handler(GSList* sibling_data, gpointer parent_data,
 
114
                          gpointer global_data, gpointer *data_for_children,
 
115
                          gpointer *result, const gchar *tag, gchar **attrs)
 
116
{
 
117
  Transaction *trans = xaccMallocTransaction();
 
118
  g_return_val_if_fail(trans, FALSE);
 
119
  xaccTransBeginEdit(trans);
 
120
  *data_for_children = trans;
 
121
  return(TRUE);
 
122
}
 
123
 
 
124
static gboolean
 
125
txn_restore_end_handler(gpointer data_for_children,
 
126
                        GSList  *data_from_children, GSList *sibling_data,
 
127
                        gpointer parent_data, gpointer global_data,
 
128
                        gpointer *result, const gchar *tag)
 
129
{
 
130
  AccountGroup *ag = (AccountGroup *) parent_data;
 
131
  Transaction *trans = (Transaction *) data_for_children;
 
132
 
 
133
  g_return_val_if_fail(trans, FALSE);
 
134
  if(!ag) {
 
135
    xaccTransDestroy(trans);
 
136
    xaccTransCommitEdit(trans);
 
137
    return(FALSE);
 
138
  }
 
139
 
 
140
  if(!xaccTransGetGUID(trans)) {
 
141
    /* must at least have a GUID for a restore */
 
142
    xaccTransDestroy(trans);
 
143
    xaccTransCommitEdit(trans);
 
144
    return(FALSE);
 
145
  }
 
146
    
 
147
  /* FIXME: what if the trans has no splits? */
 
148
  xaccTransCommitEdit(trans);
 
149
 
 
150
  return(TRUE);
 
151
}
 
152
 
 
153
static gboolean
 
154
txn_restore_after_child_handler(gpointer data_for_children,
 
155
                           GSList* data_from_children,
 
156
                           GSList* sibling_data,
 
157
                           gpointer parent_data,
 
158
                           gpointer global_data,
 
159
                           gpointer *result,
 
160
                           const gchar *tag,
 
161
                           const gchar *child_tag,
 
162
                           sixtp_child_result *child_result)
 
163
{
 
164
  Transaction *trans = (Transaction *) data_for_children;
 
165
  g_return_val_if_fail(trans, FALSE);
 
166
  if(!child_result) return(TRUE);
 
167
  if(child_result->type != SIXTP_CHILD_RESULT_NODE) return(TRUE);
 
168
  if(strcmp(child_result->tag, "slots") == 0) {
 
169
    kvp_frame *f = (kvp_frame *) child_result->data;
 
170
    g_return_val_if_fail(f, FALSE);
 
171
    if(trans->kvp_data) kvp_frame_delete(trans->kvp_data);
 
172
    trans->kvp_data = f;
 
173
    child_result->should_cleanup = FALSE;
 
174
  }
 
175
  return(TRUE);
 
176
}
 
177
 
 
178
static void
 
179
txn_restore_fail_handler(gpointer data_for_children,
 
180
                         GSList* data_from_children,
 
181
                         GSList* sibling_data,
 
182
                         gpointer parent_data,
 
183
                         gpointer global_data,
 
184
                         gpointer *result,
 
185
                         const gchar *tag)
 
186
{
 
187
  Transaction *trans = (Transaction *) data_for_children;
 
188
  if(trans) {
 
189
    xaccTransDestroy(trans);
 
190
    xaccTransCommitEdit(trans);
 
191
  }
 
192
}
 
193
 
 
194
/****************************************************************************/
 
195
/* <guid> (lineage <restore> <transaction>)
 
196
   
 
197
   restores a given account's guid.
 
198
 
 
199
   from parent: Transaction*
 
200
   for children: NA
 
201
   result: NA
 
202
   -----------
 
203
   start: NA
 
204
   characters: return string copy for accumulation in end handler.
 
205
   end: concatenate all chars and set as transaction GUID if not duplicate.
 
206
 
 
207
   cleanup-result: NA
 
208
   cleanup-chars: g_free the result string.
 
209
   fail: NA
 
210
   result-fail: NA
 
211
   chars-fail: g_free the result string.
 
212
 
 
213
 */
 
214
 
 
215
static gboolean
 
216
txn_restore_guid_end_handler(gpointer data_for_children,
 
217
                             GSList  *data_from_children, GSList *sibling_data,
 
218
                             gpointer parent_data, gpointer global_data,
 
219
                             gpointer *result, const gchar *tag)
 
220
{
 
221
  Transaction *t = (Transaction *) parent_data;
 
222
  gchar *txt = NULL;
 
223
  GUID gid;
 
224
  gboolean ok;
 
225
 
 
226
  g_return_val_if_fail(t, FALSE);
 
227
 
 
228
  txt = concatenate_child_result_chars(data_from_children);
 
229
  g_return_val_if_fail(txt, FALSE);
 
230
  
 
231
  ok = string_to_guid(txt, &gid);
 
232
  g_free(txt);
 
233
 
 
234
  g_return_val_if_fail(ok, FALSE);
 
235
 
 
236
  if(xaccTransLookup(&gid)) {
 
237
    return(FALSE);
 
238
  }
 
239
 
 
240
  xaccTransSetGUID(t, &gid);
 
241
  return(TRUE);
 
242
}
 
243
 
 
244
/****************************************************************************/
 
245
/* <num> (lineage <restore> <transaction>)
 
246
   
 
247
   restores a given transaction's num.
 
248
 
 
249
   from parent: Transaction*
 
250
   for children: NA
 
251
   result: NA
 
252
   -----------
 
253
   start: NA
 
254
   characters: return string copy for accumulation in end handler.
 
255
   end: concatenate all chars and set as transaction num.
 
256
 
 
257
   cleanup-result: NA
 
258
   cleanup-chars: g_free the result string.
 
259
   fail: NA
 
260
   result-fail: NA
 
261
   chars-fail: g_free the result string.
 
262
 
 
263
 */
 
264
 
 
265
static gboolean
 
266
txn_restore_num_end_handler(gpointer data_for_children,
 
267
                            GSList  *data_from_children, GSList *sibling_data,
 
268
                            gpointer parent_data, gpointer global_data,
 
269
                            gpointer *result, const gchar *tag)
 
270
{
 
271
  Transaction *t = (Transaction *) parent_data;
 
272
  gchar *txt = NULL;
 
273
  
 
274
  g_return_val_if_fail(t, FALSE);
 
275
  
 
276
  txt = concatenate_child_result_chars(data_from_children);
 
277
  g_return_val_if_fail(txt, FALSE);
 
278
  
 
279
  xaccTransSetNum(t, txt);
 
280
  g_free(txt);
 
281
  return(TRUE);
 
282
}
 
283
 
 
284
/****************************************************************************/
 
285
/* <description> (lineage <restore> <transaction>)
 
286
   
 
287
   restores a given transaction's description.
 
288
 
 
289
   from parent: Transaction*
 
290
   for children: NA
 
291
   result: NA
 
292
   -----------
 
293
   start: NA
 
294
   characters: return string copy for accumulation in end handler.
 
295
   end: concatenate all chars and set as transaction description.
 
296
 
 
297
   cleanup-result: NA
 
298
   cleanup-chars: g_free the result string.
 
299
   fail: NA
 
300
   result-fail: NA
 
301
   chars-fail: g_free the result string.
 
302
 
 
303
 */
 
304
 
 
305
static gboolean
 
306
txn_restore_description_end_handler(gpointer data_for_children,
 
307
                                    GSList  *data_from_children, GSList *sibling_data,
 
308
                                    gpointer parent_data, gpointer global_data,
 
309
                                    gpointer *result, const gchar *tag)
 
310
{
 
311
  Transaction *t = (Transaction *) parent_data;
 
312
  gchar *txt = NULL;
 
313
  
 
314
  g_return_val_if_fail(t, FALSE);
 
315
  
 
316
  txt = concatenate_child_result_chars(data_from_children);
 
317
  g_return_val_if_fail(txt, FALSE);
 
318
  
 
319
  xaccTransSetDescription(t, txt);
 
320
  g_free(txt);
 
321
  return(TRUE);
 
322
}
 
323
 
 
324
/****************************************************************************/
 
325
/* <date-posted> (lineage <restore> <transaction>)
 
326
   
 
327
   restores a given transaction's posted date.
 
328
 
 
329
   Just uses a generic_timespec parser, but with our own end handler.
 
330
 
 
331
   end: set date posted.
 
332
 
 
333
 */
 
334
 
 
335
static gboolean
 
336
txn_rest_date_posted_end_handler(gpointer data_for_children,
 
337
                                 GSList  *data_from_children, GSList *sibling_data,
 
338
                                 gpointer parent_data, gpointer global_data,
 
339
                                 gpointer *result, const gchar *tag)
 
340
{
 
341
  Transaction *t = (Transaction *) parent_data;
 
342
  TimespecParseInfo *info = (TimespecParseInfo *) data_for_children;
 
343
  
 
344
  g_return_val_if_fail(info, FALSE);
 
345
  if(!t || !timespec_parse_ok(info)) {
 
346
    g_free(info);
 
347
    return(FALSE);
 
348
  }
 
349
 
 
350
  xaccTransSetDateTS(t, &(info->ts));
 
351
  g_free(info);
 
352
  return(TRUE);
 
353
}
 
354
 
 
355
/****************************************************************************/
 
356
/* <date-entered> (lineage <restore> <transaction>)
 
357
   
 
358
   restores a given transaction's entered date.
 
359
 
 
360
   Just uses a generic_timespec parser, but with our own end handler.
 
361
 
 
362
   end: set date entered.
 
363
 
 
364
 */
 
365
 
 
366
static gboolean
 
367
txn_rest_date_entered_end_handler(gpointer data_for_children,
 
368
                                  GSList  *data_from_children, GSList *sibling_data,
 
369
                                  gpointer parent_data, gpointer global_data,
 
370
                                  gpointer *result, const gchar *tag)
 
371
{
 
372
  Transaction *t = (Transaction *) parent_data;
 
373
  TimespecParseInfo *info = (TimespecParseInfo *) data_for_children;
 
374
  
 
375
  g_return_val_if_fail(info, FALSE);
 
376
  if(!t || !timespec_parse_ok(info)) {
 
377
    g_free(info);
 
378
    return(FALSE);
 
379
  }
 
380
 
 
381
  xaccTransSetDateEnteredTS(t, &(info->ts));
 
382
  g_free(info);
 
383
  return(TRUE);
 
384
}
 
385
 
 
386
 
 
387
 
 
388
/****************************************************************************/
 
389
 
 
390
/* <split> (lineage <restore> <transaction> <ledger-data>)
 
391
   
 
392
   Restores a given split.  We allocate the new split in the start
 
393
   block, the children modify it, and in the end block, we see if the
 
394
   resultant split is OK, and if so, we add it to the input Transaction*
 
395
   account group.
 
396
 
 
397
   from parent: Transaction*
 
398
   for children: new Split*
 
399
   result: NA
 
400
   -----------
 
401
   start: create new Split*, and store in data_for_children.
 
402
   chars: allow and ignore only whitespace.
 
403
   end: commit split to transaction if appropriate.
 
404
   cleanup-result: NA
 
405
   cleanup-chars: NA
 
406
   fail: delete Transaction* in data_for_children
 
407
   result-fail: NA
 
408
   chars-fail: NA
 
409
 
 
410
 */
 
411
 
 
412
static gboolean
 
413
txn_restore_split_start_handler(GSList* sibling_data, gpointer parent_data,
 
414
                                gpointer global_data,
 
415
                                gpointer *data_for_children, gpointer *result,
 
416
                                const gchar *tag, gchar **attrs)
 
417
{
 
418
  Split *s = xaccMallocSplit();
 
419
  g_return_val_if_fail(s, FALSE);
 
420
  *data_for_children = s;
 
421
  return(TRUE);
 
422
}
 
423
 
 
424
static gboolean
 
425
txn_restore_split_end_handler(gpointer data_for_children,
 
426
                              GSList  *data_from_children, GSList *sibling_data,
 
427
                              gpointer parent_data, gpointer global_data,
 
428
                              gpointer *result, const gchar *tag)
 
429
{
 
430
  Transaction *t = (Transaction *) parent_data;
 
431
  Split *s = (Split *) data_for_children;
 
432
 
 
433
  g_return_val_if_fail(s, FALSE);
 
434
  if(!t) {
 
435
    xaccSplitDestroy(s);
 
436
    return(FALSE);
 
437
  }
 
438
 
 
439
  if(!xaccSplitGetGUID(s)) {
 
440
    /* must at least have a GUID for a restore */
 
441
    xaccSplitDestroy(s);
 
442
    return(FALSE);
 
443
  }
 
444
    
 
445
  xaccTransAppendSplit(t, s);
 
446
  return(TRUE);
 
447
}
 
448
 
 
449
static gboolean
 
450
txn_restore_split_after_child_handler(gpointer data_for_children,
 
451
                           GSList* data_from_children,
 
452
                           GSList* sibling_data,
 
453
                           gpointer parent_data,
 
454
                           gpointer global_data,
 
455
                           gpointer *result,
 
456
                           const gchar *tag,
 
457
                           const gchar *child_tag,
 
458
                           sixtp_child_result *child_result)
 
459
{
 
460
  Split *s = (Split *) data_for_children;
 
461
  g_return_val_if_fail(s, FALSE);
 
462
  if(!child_result) return(TRUE);
 
463
  if(child_result->type != SIXTP_CHILD_RESULT_NODE) return(TRUE);
 
464
 
 
465
  if(strcmp(child_result->tag, "slots") == 0) {
 
466
    kvp_frame *f = (kvp_frame *) child_result->data;
 
467
    g_return_val_if_fail(f, FALSE);
 
468
    if(s->kvp_data) kvp_frame_delete(s->kvp_data);
 
469
    s->kvp_data = f;
 
470
    child_result->should_cleanup = FALSE;
 
471
  }
 
472
  else if(strcmp(child_result->tag, "quantity") == 0) {
 
473
    gnc_numeric *n = (gnc_numeric *) child_result->data;
 
474
    g_return_val_if_fail(n, FALSE);
 
475
    xaccSplitSetShareAmount(s, *n);
 
476
    /* let the normal child_result handler clean up n */
 
477
  }
 
478
  else if(strcmp(child_result->tag, "value") == 0) {
 
479
    gnc_numeric *n = (gnc_numeric *) child_result->data;
 
480
    g_return_val_if_fail(n, FALSE);
 
481
    xaccSplitSetValue(s, *n);
 
482
    /* let the normal child_result handler clean up n */
 
483
  }
 
484
 
 
485
  return(TRUE);
 
486
}
 
487
 
 
488
static void
 
489
txn_restore_split_fail_handler(gpointer data_for_children,
 
490
                         GSList* data_from_children,
 
491
                         GSList* sibling_data,
 
492
                         gpointer parent_data,
 
493
                         gpointer global_data,
 
494
                         gpointer *result,
 
495
                         const gchar *tag)
 
496
{
 
497
  Split *s = (Split *) data_for_children;
 
498
  if(s) xaccSplitDestroy(s);
 
499
}
 
500
 
 
501
/****************************************************************************/
 
502
/* <guid> (lineage <split> <restore> <transaction>)
 
503
   
 
504
   restores a given split's guid.
 
505
 
 
506
   from parent: Split*
 
507
   for children: NA
 
508
   result: NA
 
509
   -----------
 
510
   start: NA
 
511
   characters: return string copy for accumulation in end handler.
 
512
   end: concatenate all chars and set as split GUID if not duplicate.
 
513
 
 
514
   cleanup-result: NA
 
515
   cleanup-chars: g_free the result string.
 
516
   fail: NA
 
517
   result-fail: NA
 
518
   chars-fail: g_free the result string.
 
519
 
 
520
 */
 
521
 
 
522
static gboolean
 
523
txn_restore_split_guid_end_handler(gpointer data_for_children,
 
524
                                   GSList  *data_from_children, GSList *sibling_data,
 
525
                                   gpointer parent_data, gpointer global_data,
 
526
                                   gpointer *result, const gchar *tag)
 
527
{
 
528
  Split *s = (Split *) parent_data;
 
529
  gchar *txt = NULL;
 
530
  GUID gid;
 
531
  gboolean ok;
 
532
 
 
533
  g_return_val_if_fail(s, FALSE);
 
534
 
 
535
  txt = concatenate_child_result_chars(data_from_children);
 
536
  g_return_val_if_fail(txt, FALSE);
 
537
  
 
538
  ok = string_to_guid(txt, &gid);
 
539
  g_free(txt);
 
540
 
 
541
  g_return_val_if_fail(ok, FALSE);
 
542
 
 
543
  if(xaccSplitLookup(&gid)) {
 
544
    return(FALSE);
 
545
  }
 
546
 
 
547
  xaccSplitSetGUID(s, &gid);
 
548
  return(TRUE);
 
549
}
 
550
 
 
551
/****************************************************************************/
 
552
/* <memo> (lineage <split> <restore> <transaction>)
 
553
   
 
554
   restores a given split's memo.
 
555
 
 
556
   from parent: Split*
 
557
   for children: NA
 
558
   result: NA
 
559
   -----------
 
560
   start: NA
 
561
   characters: return string copy for accumulation in end handler.
 
562
   end: concatenate all chars and set as split description.
 
563
 
 
564
   cleanup-result: NA
 
565
   cleanup-chars: g_free the result string.
 
566
   fail: NA
 
567
   result-fail: NA
 
568
   chars-fail: g_free the result string.
 
569
 
 
570
 */
 
571
 
 
572
static gboolean
 
573
txn_restore_split_memo_end_handler(gpointer data_for_children,
 
574
                                   GSList  *data_from_children, GSList *sibling_data,
 
575
                                   gpointer parent_data, gpointer global_data,
 
576
                                   gpointer *result, const gchar *tag)
 
577
{
 
578
  Split *s = (Split *) parent_data;
 
579
  gchar *txt = NULL;
 
580
  
 
581
  g_return_val_if_fail(s, FALSE);
 
582
  
 
583
  txt = concatenate_child_result_chars(data_from_children);
 
584
  g_return_val_if_fail(txt, FALSE);
 
585
  
 
586
  xaccSplitSetMemo(s, txt);
 
587
  g_free(txt);
 
588
  return(TRUE);
 
589
}
 
590
 
 
591
/****************************************************************************/
 
592
/* <action> (lineage <split> <restore> <transaction>)
 
593
   
 
594
   restores a given split's action.
 
595
 
 
596
   from parent: Split*
 
597
   for children: NA
 
598
   result: NA
 
599
   -----------
 
600
   start: NA
 
601
   characters: return string copy for accumulation in end handler.
 
602
   end: concatenate all chars and set as split action.
 
603
 
 
604
   cleanup-result: NA
 
605
   cleanup-chars: g_free the result string.
 
606
   fail: NA
 
607
   result-fail: NA
 
608
   chars-fail: g_free the result string.
 
609
 
 
610
 */
 
611
 
 
612
static gboolean
 
613
txn_restore_split_action_end_handler(gpointer data_for_children,
 
614
                                     GSList  *data_from_children, GSList *sibling_data,
 
615
                                     gpointer parent_data, gpointer global_data,
 
616
                                     gpointer *result, const gchar *tag)
 
617
{
 
618
  Split *s = (Split *) parent_data;
 
619
  gchar *txt = NULL;
 
620
  
 
621
  g_return_val_if_fail(s, FALSE);
 
622
  
 
623
  txt = concatenate_child_result_chars(data_from_children);
 
624
  g_return_val_if_fail(txt, FALSE);
 
625
  
 
626
  xaccSplitSetAction(s, txt);
 
627
  g_free(txt);
 
628
  return(TRUE);
 
629
}
 
630
 
 
631
/****************************************************************************/
 
632
/* <reconcile-state> (lineage <split> <restore> <transaction>)
 
633
   
 
634
   restores a given split's reconcile-state.
 
635
 
 
636
   from parent: Split*
 
637
   for children: NA
 
638
   result: NA
 
639
   -----------
 
640
   start: NA
 
641
   characters: return string copy for accumulation in end handler.
 
642
   end: concatenate all chars and set as split reconcile-state.
 
643
 
 
644
   cleanup-result: NA
 
645
   cleanup-chars: g_free the result string.
 
646
   fail: NA
 
647
   result-fail: NA
 
648
   chars-fail: g_free the result string.
 
649
 
 
650
 */
 
651
 
 
652
static gboolean
 
653
txn_restore_split_reconcile_state_end_handler(gpointer data_for_children,
 
654
                                              GSList  *data_from_children, GSList *sibling_data,
 
655
                                              gpointer parent_data, gpointer global_data,
 
656
                                              gpointer *result, const gchar *tag)
 
657
{
 
658
  Split *s = (Split *) parent_data;
 
659
  gchar *txt = NULL;
 
660
  
 
661
  g_return_val_if_fail(s, FALSE);
 
662
  
 
663
  txt = concatenate_child_result_chars(data_from_children);
 
664
  g_return_val_if_fail(txt, FALSE);
 
665
  
 
666
  if(strlen(txt) != 1) {
 
667
    g_free(txt);
 
668
    return(FALSE);
 
669
  }
 
670
 
 
671
  xaccSplitSetReconcile(s, txt[0]);
 
672
  g_free(txt);
 
673
  return(TRUE);
 
674
}
 
675
 
 
676
/****************************************************************************/
 
677
/* <reconcile-date> (lineage <split> <restore> <transaction>)
 
678
   
 
679
   restores a given split's reconcile-date.
 
680
 
 
681
   Just uses a generic_timespec parser, but with our own end handler.
 
682
 
 
683
   end: set reconcile-date.
 
684
 
 
685
 */
 
686
 
 
687
static gboolean
 
688
txn_restore_split_reconcile_date_end_handler(gpointer data_for_children,
 
689
                                             GSList  *data_from_children, GSList *sibling_data,
 
690
                                             gpointer parent_data, gpointer global_data,
 
691
                                             gpointer *result, const gchar *tag)
 
692
{
 
693
  Split *s = (Split *) parent_data;
 
694
  TimespecParseInfo *info = (TimespecParseInfo *) data_for_children;
 
695
  
 
696
  g_return_val_if_fail(info, FALSE);
 
697
  if(!s || !timespec_parse_ok(info)) {
 
698
    g_free(info);
 
699
    return(FALSE);
 
700
  }
 
701
 
 
702
  xaccSplitSetDateReconciledTS(s, &(info->ts));
 
703
  g_free(info);
 
704
  return(TRUE);
 
705
}
 
706
 
 
707
/****************************************************************************/
 
708
/* <account> (lineage <split> <restore> <transaction>)
 
709
   
 
710
   restores a given split's account.
 
711
 
 
712
   from parent: Split*
 
713
   for children: NA
 
714
   result: NA
 
715
   -----------
 
716
   start: NA
 
717
   characters: return string copy for accumulation in end handler.
 
718
   end: concatenate all chars and set as split account if GUID OK.
 
719
 
 
720
   cleanup-result: NA
 
721
   cleanup-chars: g_free the result string.
 
722
   fail: NA
 
723
   result-fail: NA
 
724
   chars-fail: g_free the result string.
 
725
 
 
726
 */
 
727
 
 
728
static gboolean
 
729
txn_restore_split_account_end_handler(gpointer data_for_children,
 
730
                                      GSList  *data_from_children, GSList *sibling_data,
 
731
                                      gpointer parent_data, gpointer global_data,
 
732
                                      gpointer *result, const gchar *tag)
 
733
{
 
734
  Split *s = (Split *) parent_data;
 
735
  Account *acct;
 
736
  gchar *txt = NULL;
 
737
  GUID gid;
 
738
  gboolean ok;
 
739
  
 
740
  g_return_val_if_fail(s, FALSE);
 
741
  
 
742
  txt = concatenate_child_result_chars(data_from_children);
 
743
  g_return_val_if_fail(txt, FALSE);
 
744
  
 
745
  ok = string_to_guid(txt, &gid);
 
746
  g_free(txt);
 
747
  
 
748
  g_return_val_if_fail(ok, FALSE);
 
749
  
 
750
  acct = xaccAccountLookup(&gid);
 
751
  g_return_val_if_fail(acct, FALSE);
 
752
 
 
753
  xaccAccountInsertSplit(acct, s);
 
754
  return(TRUE);
 
755
}
 
756
 
 
757
 
 
758
/****************************************************************************/
 
759
 
 
760
 
 
761
/****************************************************************************/
 
762
 
 
763
static sixtp *
 
764
gnc_txn_restore_split_parser_new(void) 
 
765
{
 
766
  sixtp *top_level;
 
767
  
 
768
  if(!(top_level =
 
769
       sixtp_set_any(sixtp_new(), FALSE,
 
770
                     SIXTP_START_HANDLER_ID, txn_restore_split_start_handler,
 
771
                     SIXTP_CHARACTERS_HANDLER_ID,
 
772
                     allow_and_ignore_only_whitespace,
 
773
                     SIXTP_END_HANDLER_ID, txn_restore_split_end_handler,
 
774
                     SIXTP_FAIL_HANDLER_ID, txn_restore_split_fail_handler,
 
775
                     SIXTP_AFTER_CHILD_HANDLER_ID,
 
776
                     txn_restore_split_after_child_handler,
 
777
                     SIXTP_NO_MORE_HANDLERS)))
 
778
  {
 
779
      return NULL;
 
780
  }
 
781
 
 
782
  if(!sixtp_add_some_sub_parsers(
 
783
         top_level, TRUE,
 
784
         "guid", restore_char_generator(txn_restore_split_guid_end_handler),
 
785
         "memo", restore_char_generator(txn_restore_split_memo_end_handler),
 
786
         "action",
 
787
         restore_char_generator(txn_restore_split_action_end_handler),
 
788
         "account",
 
789
         restore_char_generator(txn_restore_split_account_end_handler),
 
790
         "reconcile-state",
 
791
         restore_char_generator(txn_restore_split_reconcile_state_end_handler),
 
792
         "reconcile-date", 
 
793
         generic_timespec_parser_new(
 
794
             txn_restore_split_reconcile_date_end_handler),
 
795
         "quantity", generic_gnc_numeric_parser_new(),
 
796
         "value", generic_gnc_numeric_parser_new(),
 
797
         "slots", kvp_frame_parser_new(),
 
798
         0))
 
799
  {
 
800
      return NULL;
 
801
  }
 
802
 
 
803
  return(top_level);
 
804
}
 
805
 
 
806
/***************************************************************************/
 
807
 
 
808
sixtp *
 
809
gnc_transaction_parser_new(void) 
 
810
{
 
811
  sixtp *top_level;
 
812
  sixtp *restore_pr;
 
813
 
 
814
  if(!(top_level =
 
815
       sixtp_set_any(sixtp_new(), FALSE,
 
816
                     SIXTP_START_HANDLER_ID, transaction_start_handler,
 
817
                     SIXTP_CHARACTERS_HANDLER_ID,
 
818
                     allow_and_ignore_only_whitespace,
 
819
                     SIXTP_AFTER_CHILD_HANDLER_ID,
 
820
                     txn_restore_after_child_handler,
 
821
                     SIXTP_NO_MORE_HANDLERS)))
 
822
  {
 
823
      return NULL;
 
824
  }
 
825
 
 
826
  /* <restore> */
 
827
  if(!(restore_pr =
 
828
       sixtp_set_any(sixtp_new(), FALSE,
 
829
                     SIXTP_START_HANDLER_ID, txn_restore_start_handler,
 
830
                     SIXTP_END_HANDLER_ID, txn_restore_end_handler,
 
831
                     SIXTP_FAIL_HANDLER_ID, txn_restore_fail_handler,
 
832
                     SIXTP_AFTER_CHILD_HANDLER_ID,
 
833
                     txn_restore_after_child_handler,
 
834
                     SIXTP_NO_MORE_HANDLERS)))
 
835
  {
 
836
      sixtp_destroy(top_level);
 
837
      return(NULL);
 
838
  }
 
839
  sixtp_add_sub_parser(top_level, "restore", restore_pr);
 
840
 
 
841
  if(!(sixtp_add_some_sub_parsers(
 
842
           restore_pr, TRUE,
 
843
           "guid", restore_char_generator(txn_restore_guid_end_handler),
 
844
           "num", restore_char_generator(txn_restore_num_end_handler),
 
845
           "description",
 
846
           restore_char_generator(txn_restore_description_end_handler),
 
847
           "date-posted",
 
848
           generic_timespec_parser_new(txn_rest_date_posted_end_handler),
 
849
           "date-entered",
 
850
           generic_timespec_parser_new(txn_rest_date_entered_end_handler),
 
851
           "slots", kvp_frame_parser_new(),
 
852
           "split", gnc_txn_restore_split_parser_new(),
 
853
           0)))
 
854
  {
 
855
      sixtp_destroy(top_level);
 
856
      return NULL;
 
857
  }
 
858
 
 
859
  return(top_level);
 
860
}