Project

General

Profile

1
<?php
2
require_once('util/utilityFunctions.php');
3
require_once('objects/types.php');
4

    
5
class Entity {
6
  private $references = array();
7
  private $members = array();
8
  private $referrers = array();
9
  private $tableName;
10
  private $extensionType;
11
  private $inited;
12

    
13
  public function __construct($tableName,$node = null) {
14
    global $eList;
15
    // Entity name = table name
16
    $this->tableName = $tableName;
17
    $this->inited = False;
18
    $this->extensionType = '';
19

    
20
    if(!is_null($node)) {
21
      $this->init($tableName,$node);
22
      $this->inited = True;
23
    }
24
  }
25

    
26
  public function init($tableName,$node) {
27
    global $primitiveTypes;
28
    global $eList;
29
    $xpath = new DOMXPath($node->ownerDocument);
30
    $childNodesXPath = $xpath->query("child::node()",$node);
31
    $childNodes = array();
32
    foreach($childNodesXPath as $childNodeXPath) {
33
      $cNodeName = preg_replace("/.*:/","",$childNode->nodeName);
34
      if(!isIgnoreType($cNodeName)) {
35
        $childNodes[] = $childNodeXPath;
36
      }
37
    }
38

    
39
    for($i = 0; $i < count($childNodes); $i++) {
40
      $childNode = $childNodes[$i];
41

    
42
      $cNodeName = preg_replace("/.*:/","",$childNode->nodeName);
43

    
44
      if(isIgnoreType($cNodeName)) {
45
        continue;
46
      }
47

    
48
      #Very inefficient, but I want to be sure that I've handled all possible
49
      #attribute types.
50
      $attrs = $xpath->query("attribute::*",$childNode);
51
      foreach($attrs as $attr) {
52
        $attrName = $attr->name;
53
        if(!isKnownAttribute($attrName)) {
54
          throw new Exception("Encountered unkown attribute: $attrName in element $this->tableName.");
55
        }
56
      }
57

    
58
      switch($cNodeName) {
59
        #Untested
60
        case 'any':
61
          $any_e = $eList->newEntity($tableName . "_any_nodes");
62
          $any_e->addMember("node_name","models.CharField(max_length=255)");
63
          $any_e->addMember("node_value","models.TextField()");
64
          $any_e->addOneToManyReference($tableName . "_id",$this);
65
          $this->referrers['anyNode'] = $tableName . '_any_nodes';
66
          break;
67
        case 'anyAttribute':
68
          $any_a = $eList->newEntity($tableName . "_any_attr");
69
          $any_a->addMember("attr_name","models.CharField(max_length=255)");
70
          $any_a->addMember("attr_value","models.CharField(max_length=255)");
71
          $any_a->addOneToManyReference($tableName . "_id",$this);
72
          $this->referrers['anyAttribute'] = $tableName . '_any_attr';
73
          break;
74
        case 'attribute':
75
          $a_name = $childNode->getAttribute('name');
76
          if($a_name == '') {
77
            throw new Exception("Nodes defining attributes must have a name.  " .
78
                                "Unnamed attribute node found in $this->tableName.");
79
          }
80
          $default = $childNode->getAttribute('default');
81
          $use = $childNode->getAttribute('use');
82
          $type = preg_replace("/.*:/","",$childNode->getAttribute('type'));
83
          $guess = False;
84
          if($primitiveTypes[$type] != '') {
85
            $def = $primitiveTypes[$type];
86
          } else {
87
            $def = "models.CharField(max_length=255";
88
          }
89
          if($use == 'optional') {
90
            if($def == 'models.CharField(max_length=255') { $def .= ", "; }
91
            $def .= "null=True, blank=True";
92
          }
93
          if($default != '') {
94
            if($use == 'optional' ||
95
               $def == 'models.CharField(max_length=255') { 
96
              $def .= ", "; 
97
            }
98
            $def .= "default = '$default'";
99
          }
100
          $def .= ")";
101
          if($guess) { $def .= " # This is a guess"; }
102
          $this->addMember("attr_$a_name",$def);
103
          break;
104
        #Untested
105
        case 'group':
106
          if(hasImportantNodes($childNode)) {
107
            throw new Exception("No defined functionality for group nodes defining complex entities " .
108
                                "within other complex entities.");
109
          }
110
          $ref = preg_replace("/.*:/","",$childNode->getAttribute('ref'));
111
          if($ref == '') {
112
            throw new Exception("No defined functionality for group nodes " .
113
                                "that don't have a 'ref' attribute.");
114
          }
115
          $this->determineRelationship($ref,$ref,$childNode);
116
          break;
117
        case 'complexType':
118
          $name = $childNode->getAttribute('name');
119
          if($name != '') {
120
            throw new Exception("Named complexType definition within entity definition. " .
121
                                "This functionality is not yet implemented.");
122
          }
123
        case 'simpleType':
124
          $name = $childNode->getAttribute('name');
125
          if(isPrimitiveType($name)) {
126
            break;
127
          }
128
          if($name != '') {
129
            throw new Exception("Named simpleType definition within entity definition. " .
130
                                "This functionality is not yet implemented.");
131
          }
132
        case 'choice':
133
          # Fracking hack
134
          $isChoice = True;
135
        case 'complexContent':
136
        case 'simpleContent':
137
        case 'sequence':
138
          $minOccurs = $childNode->getAttribute('minOccurs');
139
          if($isChoice) {
140
            $minOccurs = 0;
141
          }
142
          $maxOccurs = $childNode->getAttribute('maxOccurs');
143
         
144
          #If defined, need to use pass these attribues through to child nodes.
145
          #Then, we add the grandchid nodes to the node list since we need the
146
          #grandchild nodes to complete the entity definition.
147
          $grandchildNodesXPath = $xpath->query("child::node()",$childNode);
148
          foreach($grandchildNodesXPath as $grandchildNodeXPath) {
149
            $gcNodeName = preg_replace("/.*:/","",$grandchildNodeXPath->nodeName);
150
            if(isIgnoreType($gcNodeName)) {
151
              continue;
152
            }
153

    
154
            if(((string)$minOccurs) != '') {
155
              $grandchildNodeXPath->setAttribute("minOccurs",$minOccurs);
156
            }
157
            if(((string)$maxOccurs) != '') {
158
              $grandchildNodeXPath->setAttribute("maxOccurs",$maxOccurs);
159
            }
160
            $childNodes[] = $grandchildNodeXPath;
161
          }
162

    
163
          #None of these have implemented functionality, need to fail if we reach
164
          #them during exection.
165
          $err_type = '';
166
          $default = $childNode->getAttribute('default');
167
          if($default != '' ) {
168
            $err_type = "default";
169
          }
170
          $use = $childNode->getAttribute('use');
171
          if($use != '' ) {
172
            $err_type = "use";
173
          }
174
          $mixed = $childNode->getAttribute('mixed');
175
          if($mixed != '' ) {
176
            $err_type = "mixed";
177
          }
178
          $type = $childNode->getAttribute('type');
179
          if($type != '' ) {
180
            $err_type = "type";
181
          }
182
          $namespace = $childNode->getAttribute('namespace');
183
          if($namespace != '' ) {
184
            $err_type = "namespace";
185
          }
186
          $nillable = $childNode->getAttribute('nillable');
187
          if($nillable != '' ) {
188
            $err_type = "nillable";
189
          }
190
          $ref = $childNode->getAttribute('ref');
191
          if($ref != '' ) {
192
            $err_type = "ref";
193
          }
194
          $base = $childNode->getAttribute('base');
195
          if($base != '' ) {
196
            $err_type = "base";
197
          }
198
          if($err_type != '') {
199
            throw new Exception("$err_type not defined for pass-through.");
200
          }
201
          break;
202
        case 'element':
203
          $this->handleElementCase($childNode);
204
          break;
205
        case 'extension':
206
          $name = findFirstAncestorName($childNode);
207
          $base = preg_replace("/.*:/","",$childNode->getAttribute('base'));
208
          if(isPrimitiveType($base)) {
209
            $grandchildNodesXPath = $xpath->query("child::node()",$childNode);
210
            foreach($grandchildNodesXPath as $grandchildNodeXPath) {
211
              $gcNodeName = preg_replace("/.*:/","",$grandchildNodeXPath->nodeName);
212
              if(isIgnoreType($gcNodeName)) {
213
                continue;
214
              }
215
              if($gcNodeName != 'attribute') {
216
                throw new Exception("Extension of primitive types can only add attributes, ".
217
                                    "found $gcNodeName.");
218
              }
219
              $a_name = $grandchildNodeXPath->getAttribute('name');
220
              if($a_name == '') {
221
                throw new Exception("Nodes defining attributes must have a name.  " .
222
                                    "Unnamed attribute node found in $this->tableName.");
223
              }
224
              $default = $grandchildNodeXPath->getAttribute('default');
225
              $use = $grandchildNodeXPath->getAttribute('use');
226
              $type = preg_replace("/.*:/","",$grandchildNodeXPath->getAttribute('type'));
227
              $guess = False;
228
              if($primitiveTypes[$type] != '') {
229
                $def = $primitiveTypes[$type];
230
              } else {
231
                $def = "models.CharField(max_length=255";
232
                $guess = True;
233
              }
234
              if($use == 'optional') {     
235
                if($def == 'models.CharField(max_length=255') { $def .= ", "; }
236
                $def .= "null=True, blank=True";
237
              }
238
              if($default != '') {
239
                if($use == 'optional' ||
240
                   $def == 'models.CharField(max_length=255') { $def .= ", "; }
241
                $def .= "default = '$default'";
242
              }
243
              $def .= ")";
244
              if($guess) { $def .= " # This is a guess"; }
245
              $this->addMember("attr_$a_name",$def);
246
            }
247
            $def = $primitiveTypes[$base] . ")";
248
            $this->addMember("primitive_type_value",$def);
249
          } else {
250
            $ref_e = $eList->getEntityForReference($base);
251
            $this->addOneToOneReference($base . "_extend",$ref_e);
252
            $this->extensionType = $base;
253

    
254
            $grandchildNodesXPath = $xpath->query("child::node()",$childNode);
255
            foreach($grandchildNodesXPath as $grandchildNodeXPath) {
256
              $gcNodeName = preg_replace("/.*:/","",$grandchildNodeXPath->nodeName);
257
              if(isIgnoreType($gcNodeName)) {
258
                continue;
259
              }
260
              $childNodes[] = $grandchildNodeXPath;
261
            }
262
          }
263
          break;
264
        case 'restriction':
265
        case 'union':
266
        case 'maxInclusive':
267
        case 'minInclusive':
268
        case 'minExclusive':
269
        case 'list':
270
        case 'pattern':
271
        case 'fractionDigits':
272
          throw new Exception("No functionality defined for nodes of type: $cNodeName");
273
          break;
274
        default:
275
          throw new Exception("Encountered uknown nodes type: $cNodeName");
276
          break;
277
      }
278
    }
279
  }
280

    
281
  public function handleElementCase($childNode) {
282
    global $eList;
283
    global $primitiveTypes;
284
    $ref = preg_replace("/.*:/","",$childNode->getAttribute('ref'));
285
    $type = preg_replace("/.*:/","",$childNode->getAttribute('type'));
286
    if($ref != '') { 
287
      $type = $ref; 
288
    }
289
    $name = $childNode->getAttribute('name');
290
    if($ref != '' && $name == '') {
291
      $name = $this->tableName . "_" . $ref;
292
    }
293

    
294
    if($name == '') {
295
      throw new Exception("All element nodes must have a name attribute, " .
296
                          "or a ref attribute to serve as the name.");
297
    }
298

    
299
    if($type != '') {
300
      $this->determineRelationship($name,$type,$childNode);
301
    } else {
302
      #Very hacky, but there a some cases where the element
303
      #has no type, and either 1) has some children nodes, but none of the
304
      #children nodes define a type, or 2) Has no useful nodes at all.
305
      # In this case the node is considered to be an anyType.
306
      $isDefined = False;
307
      $xpath = new DOMXPath($childNode->ownerDocument);
308
      $grandchildNodesXPath = $xpath->query("child::node()",$childNode);
309
      foreach($grandchildNodesXPath as $grandchildNodeXPath) {
310
        $gcNodeName = preg_replace("/.*:/","",$grandchildNodeXPath->nodeName);
311
        if(isIgnoreType($gcNodeName)) {
312
          continue;
313
        }
314
        if(hasImportantNodes($grandchildNodeXPath) || $grandchildNodeXPath->hasAttributes()) {
315
          $isDefined = True;
316
        }
317
      }
318
      if(!$isDefined) {
319
        $primitiveTypes[$name] = 'models.TextField(';
320
      }
321
      
322
      if(!isPrimitiveType($name)) {
323
        $eList->newEntity($name,$childNode);
324
      }
325
      $this->determineRelationship($name,$name,$childNode);
326
    }
327
  }
328

    
329
  public function determineRelationship($colName,$typeName,$node) {
330
    global $eList;
331
    global $primitiveTypes;
332

    
333
    $tableName = $this->tableName;
334

    
335
    $minOccurs = $node->getAttribute('minOccurs');
336
    $optional = $minOccurs == 0 ? True : False;
337
    $maxOccurs = $node->getAttribute('maxOccurs');
338
    $default = $node->getAttribute('default');
339
    $default = $node->getAttribute('use');
340

    
341
    if(isPrimitiveType($typeName)) {
342
      $def = $primitiveTypes[$typeName];
343
      if($use == 'optional' || $optional) {
344
        if($def == 'models.CharField(max_length=255') { $def .= ", "; }
345
        $def .= "null=True, blank=True";
346
      }
347
      if($default != '') {
348
        if($use == 'optional' || $optional || 
349
           $def == 'models.CharField(max_length=255') { 
350
          $def .= ", "; 
351
        }
352
        $def .= "default = '$default'";
353
      }
354
      $def .= ")";
355

    
356
      if(((string)$maxOccurs) == '' || $maxOccurs == 1) {
357
        $this->addMember($colName,$def);
358
      } else {
359
        $refName = $this->tableName . "_" . $colName;
360
        $new_e = $eList->getEntityForReference($refName);
361
        $new_e->addMember("primitive_type_value",$def);
362
        $new_e->addOneToManyReference($tableName . "_id",$this);
363
        $this->referrers[$colName] = $refName;
364
      }
365
    } else {
366
      $ref_e = $eList->getEntityForReference($typeName);
367
      if(((string)$maxOccurs) == '' || $maxOccurs == 1) {
368
        $this->addOneToOneReference($colName,$ref_e,$optional);
369
      } else {
370
#        echo "Need to define relationship between:\n  $tableName <--> $typeName\n";
371
#        echo "    (O)ne to Many\n    (M)any to Many\n";
372
#        echo "    Your choice:  ";
373
#        $handle = fopen ("php://stdin","r");
374
#        $line = fgets($handle);
375
$line = 'M';
376
        if(trim($line) == 'O' || trim($line) == 'o'){
377
          $ref_e->addOneToManyReference($colName,$this);
378
          $this->referrers[$colName] = $ref_e->getName();
379
        } else {
380
          $this->addManyToManyReference($colName,$ref_e,$tableName . "_" . $typeName . "_" . $colName);
381
        }
382
      }
383
    }
384
  }
385

    
386
  private function addReference($colName,$definition) {
387
    # Probably shouldn't allow duplicate entries, most likely points to a problem.
388
    if(array_key_exists($colName,$this->references)) {
389
     $curDef = $this->references[$colName];
390
     throw new Exception("Attempting to overwrite/reinsert member $colName:$curDef with $colName:$definition in entity " . $this->tableName . ".");
391
    }
392
    $this->references[$colName] = $definition;
393
  }
394

    
395
  public function isInited() {
396
    return $this->inited;
397
  }
398

    
399
  public function addOneToOneReference($colName,$e,$optional = False) {
400
    $eName = $e->getName();
401
    $relatedName = $this->tableName . "_" . $colName;
402
    #$def = "models.OneToOneField('$eName', primary_key=True,related_name='$relatedName'";
403
    $def = "models.ForeignKey('$eName', unique=True,related_name='$relatedName'";
404
    if($optional) {
405
      $def .= ", null=True, blank=True";
406
    }
407
    $def .= ")";
408
    $this->addReference($colName,$def); 
409
  }
410

    
411
  public function addOneToManyReference($colName,$e,$optional = False) {
412
    $eName = $e->getName();
413
    if($eName == $this->tableName) { 
414
      $eName = 'self'; 
415
    }
416
    $relatedName = $this->tableName . "_" . $colName;
417
    $def = "models.ForeignKey('$eName',related_name='$relatedName'";
418
    if($optional) {
419
      $def .= ", null=True, blank=True";
420
    }
421
    $def .= ")";
422
    $this->addReference($colName,$def); 
423
  }
424

    
425
  public function addManyToManyReference($colName,$e,$db_table = '') {
426
    $eName = $e->getName();
427
    $relatedName = $this->tableName . "_" . $colName;
428

    
429
    $def = "models.ManyToManyField('$eName',related_name='$relatedName'";
430

    
431
    #Django chokes if the table/relation names are too long.  54 characters seems to
432
    #be a decent magic number.
433
    if($db_table != '' && strlen($db_table) > 54) {
434
      $db_table = 'v_' . substr($db_table,0,54);
435
      $def .= ",db_table = '$db_table'";
436
    }
437
    $def .= ")";
438
    $this->addReference($colName,$def); 
439
  }
440

    
441
  public function addMember($colName, $definition) {
442
    # Probably shouldn't allow duplicate entries, most likely points to a problem.
443
    if(array_key_exists($colName,$this->members)) {
444
      $curDef = $this->members[$colName];
445
      if($curDef != $definition) {
446
        throw new Exception("Attempting to overwrite/reinsert member $colName:$curDef with $colName:$definition.");
447
      }
448
    }
449
    $this->members[$colName] = $definition;
450
  }
451

    
452
  public function getName() {
453
    return $this->tableName;
454
  }
455

    
456
  public function getReferences() {
457
    return $this->references;
458
  }
459

    
460
  public function getMembers() {
461
    return $this->members;
462
  }
463

    
464
  public function getReferrers() {
465
    return $this->referrers;
466
  }
467

    
468
  public function postProcess() {
469
    global $eList;
470

    
471
    #If we're dealing with extensions we need to pull the members, references, &
472
    #referrers of the base class.
473
    if($this->extensionType != '') {
474
      $base = $eList->getEntityForReference($this->extensionType);
475
      $baseReferences = $base->getReferences();
476
      $baseMembers = $base->getMembers();
477
      $baseReferrers = $base->getReferrers();
478

    
479
      $this->references = array_merge($this->references,$baseReferences);
480
      foreach(array_keys($this->references) as $k) {
481
        $def = $this->references[$k];
482
        $baseToken = $base->getName() . "_";
483
        $tableToken = $this->tableName . "_";
484
        $def = preg_replace("/$baseToken/","$tableToken",$def);
485
        $this->references[$k] = $def;
486
      }
487
        
488
      $this->members = array_merge($this->members,$baseMembers);
489
      $this->referrers = array_merge($this->referrers,$baseReferrers);
490

    
491
    }
492

    
493
  }
494

    
495
  public function toString() {
496
    $str = "class " . $this->tableName . "(models.Model):\n";
497
    #Needed to keep Django from choking:
498
    if(count($this->references) == 0 &&
499
       count($this->members) == 0) {
500
      $str .= "  id = models.AutoField(primary_key=True)";
501
    }
502

    
503
    foreach(array_keys($this->references) as $colName) {
504
      $def = $this->references[$colName];
505
      $str .= "  $colName = $def\n";
506
    }
507
    foreach(array_keys($this->members) as $colName) {
508
      $def = $this->members[$colName];
509
      $str .= "  $colName = $def\n";
510
    }
511

    
512
    $str .= "\n" . $this->makeExportFunction();
513
    $str .= "\n" . $this->makeImportFunction();
514
    $str .= "\n" . $this->makeExportDummyDataFunction();
515

    
516
    #truncate table names that are too long for Django/Postgre to support
517
    if(strlen($this->tableName) > 54) {
518
      $tabName = 'v_' . substr($this->tableName,0,54);
519
      $str .= "\n\n  class Meta:\n".
520
              "    db_table = u'$tabName'\n\n";
521
    }
522

    
523
    return $str;
524
  }
525

    
526
  public function makeImportFunction() {
527
    #Slightly different if there are no members
528
    if(count($this->references) == 0 &&
529
       count($this->members) == 0 &&
530
       count($this->referrers) == 0) {
531
      return "  def importVegX(self,node):\n"."    self.save()\n";
532
    }
533

    
534
    $def =  "  def importVegX(self,node):\n";
535

    
536
    if(preg_match_all("/([a-zA-Z]*)_extend/",implode(",",array_keys($this->references)),$matches) > 0) {
537
      $base = $matches[1][0];
538
      $def .= "    extendedEl = $base()\n".
539
              "    extendedEl.importVegX(node)\n".
540
              "    self.$base"."_extend = extendedEl\n\n";
541
    }
542

    
543
    $def .= "    self.save()\n";
544

    
545
    #Fun hack for anyAttribute & anyNode nodes
546
    if(preg_match("/_any_attr/",$this->tableName,$matches) > 0 ||
547
       preg_match("/_any_nodes/",$this->tableName,$matches) > 0) {
548
      return $def;
549
    }
550

    
551
    if(preg_match("/attr_/",implode(",",array_keys($this->members))) > 0 ||
552
       preg_match("/anyAttribute/",implode(",",array_keys($this->referrers))) > 0) {
553
      $def .= "    #attributes\n".
554
              "    for attr in node.attributes.keys():\n".
555
              "      aName = 'attr_' + attr\n".
556
              "      aVal = node.attributes[attr].nodeValue\n";
557
      $i = 0;
558
      foreach(array_keys($this->members) as $colName) {
559
        $ifStmt = $i == 0 ? 'if' : 'elif';
560
        if(preg_match("/^attr_/",$colName,$matches) > 0) {
561
          $i += 1;
562
          if(preg_match("/BooleanField/",$this->members[$colName],$matches) > 0) {
563
            $def .= "      $ifStmt aName == '$colName' and (aVal == 'true' or\n".
564
                    "      aVal == 'false' or aVal == 0 or aVal == 1):\n".
565
                    "        self.$colName = (aVal == 'true' or aVal == 1)\n";
566
          } else {
567
            $def .= "      $ifStmt aName == '$colName':\n".
568
                    "        self.$colName = aVal\n";
569
          }
570
        }
571
      }
572
    }
573
    if(preg_match("/anyAttribute/",implode(",",array_keys($this->referrers))) > 0) {
574
      $type = $this->referrers['anyAttribute'];
575
      $tIDName = $this->tableName . "_id";
576
      if(preg_match_all("/attr_/",implode(",",array_keys($this->members)),$matches) > 0) {
577
        $def .= "      else:\n".
578
                "        newEl = $type()\n".
579
                "        newEl.$tIDName = self\n".
580
                "        newEl.attr_name = attr\n".
581
                "        newEl.attr_value = aVal\n".
582
                "        newEl.save()\n";
583
      } else {
584
        $def .= "      newEl = $type()\n".
585
                "      newEl.$tIDName = self\n".
586
                "      newEl.attr_name = attr\n".
587
                "      newEl.attr_value = aVal\n".
588
                "      newEl.save()\n";
589
      }
590
    }
591
  
592
    if(count($this->members) - 
593
       preg_match_all("/attr_/",implode(",",array_keys($this->members)),$matches) -
594
       preg_match_all("/primitive_type_value/",implode(",",array_keys($this->members)),$matches) > 0 ||
595
       count($this->references) > 0 || count($this->referrers) > 0) {
596
      $def .= "    #members & relationships\n".
597
              "    for child in node.childNodes:\n".
598
              "      cName = child.nodeName\n";
599
    }
600

    
601
    $i = 0;
602
    if(count($this->members) - 
603
       preg_match_all("/attr_/",implode(",",array_keys($this->members)),$matches) -
604
       preg_match_all("/primitive_type_value/",implode(",",array_keys($this->members)),$matches) > 0) {
605
      foreach(array_keys($this->members) as $colName) {
606
        if(preg_match("/^attr_/",$colName) > 0) { continue; }
607
        $ifStmt = $i == 0 ? 'if' : 'elif';
608
        $i += 1;
609
        $def .= "      $ifStmt cName == '$colName':\n".
610
                "        cVal = child.childNodes[0].nodeValue\n".
611
                "        self.$colName = cVal\n";
612
      }
613
    }
614

    
615
    if(preg_match_all("/primitive_type_value/",implode(",",array_keys($this->members)),$matches) > 0) {
616
      $def .= "    cVal = node.childNodes[0].nodeValue\n".
617
              "    self.primitive_type_value = cVal\n";
618
    }
619

    
620
    foreach(array_keys($this->references) as $colName) {
621
      $ifStmt = $i == 0 ? 'if' : 'elif';
622
      $colDef = $this->references[$colName];
623

    
624
      if(preg_match("/(ForeignKey\(')([a-zA-Z]*)/",$colDef,$matches) > 0 &&
625
         preg_match("/unique/",$colDef) > 0 && preg_match("/_extend/",$colName) == 0) {
626
        $i += 1;
627
        $def .= "      $ifStmt cName == '$colName':\n".
628
                "        newEl = $matches[2]()\n".
629
                "        newEl.importVegX(child)\n".
630
                "        self.$colName = newEl\n";
631
      }
632
      if(preg_match("/(ManyToManyField\(')([a-zA-Z]*)/",$colDef,$matches) > 0) {
633
        $i += 1;
634
        $def .= "      $ifStmt cName == '$colName':\n".
635
                "        newEl = $matches[2]()\n".
636
                "        newEl.importVegX(child)\n".
637
                "        self.$colName.add(newEl)\n";
638
      }
639
    }
640

    
641
    if(count($this->referrers) > 0) {
642
      $def .= "      #These are the elements that refer to this one\n";
643
    }
644
    $allowAnyNode = False;
645
    foreach(array_keys($this->referrers) as $colName) {
646
      if($colName == 'anyAttribute' || $colName == 'anyNode') { continue; }
647
      $ifStmt = $i == 0 ? 'if' : 'elif';
648
      $i += 1;
649
      $colDef = $this->referrers[$colName];
650
      $elReferenceBack = $this->tableName . '_id';
651
      $def .= "      $ifStmt cName == '$colName':\n".
652
              "        newEl = $colDef()\n".
653
              "        newEl.$elReferenceBack = self\n".
654
              "        newEl.importVegX(child)\n";
655
    }
656
    if(preg_match("/anyNode/",implode(",",array_keys($this->referrers))) > 0) {
657
      $type = $this->referrers['anyNode'];
658
      $tIDName = $this->tableName . "_id";
659
      if($i > 0) {
660
        $def .= "      else:\n".
661
                "        newEl = $type()\n".
662
                "        newEl.$tIDName = self\n".
663
                "        newEl.node_name = cName\n".
664
                "        for grandchild in child.childNodes:\n".
665
                "          newEl.node_value += grandchild.toxml()\n".
666
                "        newEl.save()\n";
667
      } else {
668
        $def .= "      newEl = $type()\n".
669
                "      newEl.$tIDName = self\n".
670
                "      newEl.node_name = cName\n".
671
                "      for grandchild in child.childNodes:\n".
672
                "        newEl.node_value += grandchild.toxml()\n".
673
                "      newEl.save()\n";
674
      }
675
    }
676

    
677
    $def .= "\n    self.save()\n"; 
678
    return $def;
679
    
680
  }
681

    
682
  public function makeExportFunction() {
683
    #Slightly different if there are no members
684
    if(count($this->references) == 0 &&
685
       count($this->members) == 0 &&
686
       count($this->referrers) == 0) {
687
      return "  def exportVegX(self,myNode,doc):\n".
688
             "    return myNode\n";
689
    }
690

    
691
    $def =  "  def exportVegX(self,myNode,doc):\n";
692

    
693
    #Fun hack for anyAttribute & anyNode nodes
694
    if(preg_match("/_any_attr/",$this->tableName,$matches) > 0) {
695
      $def .= "    newAttr = doc.createAttribute(self.attr_name)\n".
696
              "    newAttr.value = self.attr_value\n".
697
              "    return newAttr\n";
698
      return $def;
699
    }
700
    if(preg_match("/_any_nodes/",$this->tableName,$matches) > 0) {
701
      $def .= "    newEl = doc.createElement(self.node_name)\n".
702
              "    newElText = doc.createTextNode(self.node_value)\n".
703
              "    newEl.appendChild(newElText)\n".
704
              "    return newEl\n\n";
705
      return $def;
706
    }
707

    
708
    foreach(array_keys($this->members) as $colName) {
709
      $nodeName = $colName;
710
      $nodeText = "str(self.$colName)";
711
      //Python's string representation of booleans is True/False but xsd requires
712
      //true/false (lowercase) so we need this hack.
713
      if(preg_match("/NullBooleanField/",$this->members[$colName],$matches) > 0) {
714
        $nodeText = "string.lower(str(self.$colName))";
715
      }
716
      if(preg_match("/^attr_/",$colName,$matches) > 0) {
717
        $nodeName = preg_replace("/^attr_/","",$colName);
718
        $def .= "    if self.$colName != None:\n".
719
                "      newAttr = doc.createAttribute('$nodeName')\n".
720
                "      newAttr.value = $nodeText\n".
721
                "      myNode.setAttributeNode(newAttr)\n\n";
722
      } else if(preg_match("/primitive_type_value/",$colName,$matches) > 0) {
723
        $def .= "    if self.$colName != None:\n".
724
                "      newElText = doc.createTextNode(self.$colName)\n".
725
                "      myNode.appendChild(newElText)\n\n";
726
      }else {
727
/*
728
        if(preg_match("/DateField/",$this->members[$colName],$matches) > 0 ||
729
           preg_match("/TimeField/",$this->members[$colName],$matches) > 0 ||
730
           preg_match("/PositiveIntegerField/",$this->members[$colName],$matches) > 0 ||
731
           preg_match("/NullBooleanField/",$this->members[$colName],$matches) > 0 ||
732
           preg_match("/FloatField/",$this->members[$colName],$matches) > 0) {
733
          $nodeText = "str(self.$colName)";
734
        }
735
*/
736
        $def .= "    if self.$colName != None:\n".
737
                "      newEl = doc.createElement('$colName')\n".
738
                "      newElText = doc.createTextNode($nodeText)\n".
739
                "      newEl.appendChild(newElText)\n".
740
                "      myNode.appendChild(newEl)\n\n";
741
      }
742
    }
743

    
744
    foreach(array_keys($this->references) as $colName) {
745
      $colDef = $this->references[$colName];
746

    
747
      if(preg_match("/(ForeignKey\(')([a-zA-Z]*)/",$colDef,$matches) > 0 &&
748
         preg_match("/unique/",$colDef) > 0) {
749
        if(preg_match("/_extend/",$colName) == 0) {
750
          $def .= "    if self.$colName != None:\n".
751
                  "      newEl = doc.createElement('$colName')\n".
752
                  "      myNode.appendChild(self.$colName.exportVegX(newEl,doc))\n\n";
753
        } else {
754
          $def .= "    if self.$colName != None:\n".
755
                  "      myNode = self.$colName.exportVegX(myNode,doc)\n\n";
756
        }
757
      }
758
      if(preg_match("/(ManyToManyField\(')([a-zA-Z]*)/",$colDef,$matches) > 0) {
759
        $def .= "    for childRef in self.$colName.all():\n".
760
                "      newEl = doc.createElement('$colName')\n".
761
                "      myNode.appendChild(childRef.exportVegX(newEl,doc))\n\n";
762
      }
763
    }
764

    
765
    foreach(array_keys($this->referrers) as $nodeName) {
766
      $nodeNameToUse = $nodeName;
767
      if($nodeName == 'anyAttribute') {
768
        $nodeNameToUse = 'any_attr';
769
        $relatedName = $this->tableName . '_' . $nodeNameToUse . '_' . $this->tableName . '_id';
770
        $def .= "    for childRef in self.$relatedName.all():\n".
771
                "      newEl = doc.createAttribute('$nodeName')\n".
772
                "      myNode.setAttributeNode(childRef.exportVegX(newEl,doc))\n\n";
773
      } else {
774
        if($nodeName == 'anyNode') {
775
          $nodeNameToUse = 'any_nodes';
776
        }
777
        $relatedName = $this->tableName . '_' . $nodeNameToUse . '_' . $this->tableName . '_id';
778
        $def .= "    for childRef in self.$relatedName.all():\n".
779
                "      newEl = doc.createElement('$nodeName')\n".
780
                "      myNode.appendChild(childRef.exportVegX(newEl,doc))\n\n";
781
      }
782
    }
783

    
784
    $def .= "    return myNode\n";
785
    return $def;
786
  }
787

    
788
  public function makeExportDummyDataFunction() {
789
    #Slightly different if there are no members
790
    if(count($this->references) == 0 &&
791
       count($this->members) == 0 &&
792
       count($this->referrers) == 0) {
793
      return "  def exportDummyVegX(self,myNode,doc,usedObjectsStack):\n".
794
             "    return myNode\n";
795
    }
796

    
797
    $def =  "  def exportDummyVegX(self,myNode,doc,usedObjectsStack):\n";
798

    
799
    #Fun hack for anyAttribute & anyNode nodes
800
    if(preg_match("/_any_attr/",$this->tableName,$matches) > 0) {
801
      $def .= "    newAttr = doc.createAttribute(getRandomString())\n".
802
              "    newAttr.value = getRandomString()\n".
803
              "    return newAttr\n";
804
      return $def;
805
    }
806
    if(preg_match("/_any_nodes/",$this->tableName,$matches) > 0) {
807
      $def .= "    newEl = doc.createElement(getRandomString())\n".
808
              "    newElText = doc.createTextNode(getRandomText())\n".
809
              "    newEl.appendChild(newElText)\n".
810
              "    return newEl\n\n";
811
      return $def;
812
    }
813

    
814
    foreach(array_keys($this->members) as $colName) {
815
      $nodeName = $colName;
816
      $colDef = $this->members[$colName];
817
      $randomFun = "getRandomString";
818
      if(preg_match("/FloatField/",$colDef,$matches) > 0) {
819
        $randomFun = "getRandomFloat";
820
      } else if(preg_match("/IntegerField/",$colDef,$matches) > 0) {
821
        $randomFun = "getRandomInt";
822
      } else if(preg_match("/TextField/",$colDef,$matches) > 0) {
823
        $randomFun = "getRandomText";
824
      } else if(preg_match("/DateField/",$colDef,$matches) > 0) {
825
        $randomFun = "getRandomDate";
826
      } else if(preg_match("/TimeField/",$colDef,$matches) > 0) {
827
        $randomFun = "getRandomTime";
828
      } else if(preg_match("/NullBooleanField/",$colDef,$matches) > 0) {
829
        $randomFun = "getRandomBool";
830
      }
831

    
832
      #Need to explicitly convert to string so minidom doesn't
833
      #roll over in nasty convulsions
834
      $randomFun = "str($randomFun())";
835
      if(preg_match("/^attr_/",$colName,$matches) > 0) {
836
        $nodeName = preg_replace("/^attr_/","",$colName);
837
        $def .= "    newAttr = doc.createAttribute('$nodeName')\n".
838
                "    newAttr.value = $randomFun\n".
839
                "    myNode.setAttributeNode(newAttr)\n\n";
840
      } else if(preg_match("/primitive_type_value/",$colName,$matches) > 0) {
841
        $def .= "    newElText = doc.createTextNode($randomFun)\n".
842
                "    myNode.appendChild(newElText)\n\n";
843
      }else {
844
        $def .= "    newEl = doc.createElement('$colName')\n".
845
                "    newElText = doc.createTextNode($randomFun)\n".
846
                "    newEl.appendChild(newElText)\n".
847
                "    myNode.appendChild(newEl)\n\n";
848
      }
849
    }
850

    
851
    foreach(array_keys($this->references) as $colName) {
852
      $colDef = $this->references[$colName];
853

    
854
      if(preg_match("/(ForeignKey\(')([a-zA-Z]*)/",$colDef,$matches) > 0 &&
855
         preg_match("/unique/",$colDef) > 0) {
856
        if(preg_match("/_extend/",$colName) == 0) {
857
          $def .= "    if '$matches[2]' not in usedObjectsStack:\n".
858
                  "      usedObjectsStack.append('$matches[2]')\n".
859
                  "      newEl = doc.createElement('$colName')\n".
860
                  "      newElObj = $matches[2]()\n".
861
                  "      myNode.appendChild(newElObj.exportDummyVegX(newEl,doc,usedObjectsStack))\n".
862
                  "      usedObjectsStack.pop()\n\n";
863
        } else {
864
          $def .= "    if '$matches[2]' not in usedObjectsStack:\n".
865
                  "      usedObjectsStack.append('$matches[2]')\n".
866
                  "      newElObj = $matches[2]()\n".
867
                  "      myNode = newElObj.exportDummyVegX(myNode,doc,usedObjectsStack)\n".
868
                  "      usedObjectsStack.pop()\n\n";
869
        }
870
      }
871
      if(preg_match("/(ManyToManyField\(')([a-zA-Z]*)/",$colDef,$matches) > 0) {
872
        $def .= "    if '$matches[2]' not in usedObjectsStack:\n".
873
                "      usedObjectsStack.append('$matches[2]')\n".
874
                "      newEl = doc.createElement('$colName')\n".
875
                "      newElObj = $matches[2]()\n".
876
                "      myNode.appendChild(newElObj.exportDummyVegX(newEl,doc,usedObjectsStack))\n".
877
                "      usedObjectsStack.pop()\n\n";
878
      }
879
    }
880

    
881
    foreach(array_keys($this->referrers) as $nodeName) {
882
      $colDef = $this->referrers[$nodeName];
883
      if($nodeName == 'anyAttribute') {
884
        $def .= "    if '$colDef' not in usedObjectsStack:\n".
885
                "      usedObjectsStack.append('$colDef')\n".
886
                "      newEl = doc.createAttribute(getRandomText())\n".
887
                "      childRef = $colDef()\n".
888
                "      myNode.setAttributeNode(childRef.exportDummyVegX(newEl,doc,usedObjectsStack))\n".
889
                "      usedObjectsStack.pop()\n\n";
890
      } else {
891
        $def .= "    if '$colDef' not in usedObjectsStack:\n".
892
                "      usedObjectsStack.append('$colDef')\n\n".
893
                "      newEl = doc.createElement('$nodeName')\n".
894
                "      childRef = $colDef()\n".
895
                "      myNode.appendChild(childRef.exportDummyVegX(newEl,doc,usedObjectsStack))\n".
896
                "      usedObjectsStack.pop()\n\n";
897
      }
898
    }
899

    
900
    $def .= "    return myNode\n";
901
    return $def;
902
  }
903

    
904
  public function makeSetupTestFunction() {
905
    if(isPrimitiveType($this->tableName)) { return ""; }
906

    
907
    $def = "  def setUp(self):\n".
908
           "    self.impl = getDOMImplementation()\n".
909
           "    self.newdoc = self.impl.createDocument(None, " . $this->tableName . ", None)\n".
910
           "    top_element = newdoc.documentElement\n";
911
  }
912

    
913
  public function makeImportTestFunction() {
914
  }
915

    
916
  public function makeExportTestFunction() {
917
  }
918

    
919
}
920
?>
(1-1/3)