1
2 '''
3 Peach 2 DOM. Peach XML files are parsed into an object model using
4 these classes. The document object is Peach and all objects extend
5 from Element.
6
7 @author: Michael Eddington
8 @version: $Id: dom.py 1135 2008-08-16 19:16:51Z meddingt $
9 '''
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38 import sys, copy, re, types, new, base64
39 from Peach.Transformers.encode import WideChar
40 from Peach import Transformers
41 from Peach.Engine.common import *
42 import Peach
43 PeachModule = Peach
44 import Ft.Xml.Domlette
45 from Ft.Xml.Domlette import Print, PrettyPrint
46
47 try:
48 import Ft.Xml.Domlette
49 from Ft.Xml.Catalog import GetDefaultCatalog
50 from Ft.Xml.InputSource import InputSourceFactory
51 from Ft.Lib.Resolvers import SchemeRegistryResolver
52 from Ft.Lib import Uri
53 from Ft.Xml import Parse
54 except:
55 print "\nError loading 4Suite XML library. This library"
56 print "can be installed from the dependencies folder or"
57 print "downloaded from http://4suite.org/.\n\n"
58 raise
59
62
64 '''
65 Copying objects in our DOM is a crazy business. Here we
66 try and help out as much as we can.
67 '''
68
69
70
71
72
73
74
75
76 node = self.node
77 parent = self.parent
78 me = getattr(self, '__deepcopy__')
79
80
81 if isinstance(self, ElementWithChildren):
82
83 _childrenHash = self._childrenHash
84 _children = self._children
85 children = self.children
86
87
88 self._childrenHash = {}
89 self.children = None
90
91
92 self.node = None
93 self.parent = None
94 delattr(self, '__deepcopy__')
95
96 if self.elementType == 'block' or self.elementType == 'namespace':
97 toXml = getattr(self, 'toXml')
98 setattr(self, 'toXml', None)
99
100 e = copy.deepcopy(self, memo)
101 e.__deepcopy__ = new.instancemethod(PeachDeepCopy, e, e.__class__)
102
103 if e.elementType == 'block':
104 e.toXml = new.instancemethod(BlockToXml, e, e.__class__)
105 setattr(self, 'toXml', toXml)
106
107 elif e.elementType == 'namespace':
108 e.toXml = new.instancemethod(NamespaceToXml, e, e.__class__)
109 setattr(self, 'toXml', toXml)
110
111 if isinstance(self, ElementWithChildren):
112
113 self._childrenHash = _childrenHash
114 self._children = _children
115 self.children = children
116
117
118
119
120
121 if isinstance(e, ElementWithChildren):
122 children = e._children
123 e._children = []
124 e.children = Empty()
125
126 for c in children:
127 if isinstance(c, Element) and not hasattr(c, 'name'):
128 c.name = "The Lost Element"
129 e.append(c)
130
131 self.node = node
132 self.parent = parent
133 setattr(self, '__deepcopy__', me)
134
135 return e
136
138 '''
139 Element in our template tree.
140 '''
141
142 __CurNameNum = 0
143
144 - def __init__(self, name = None, parent = None):
145
146 self.name = name
147
148 self.parent = parent
149
150 self.hasChildren = False
151
152 self.elementType = None
153 self.node = None
154 self.ref = None
155
156 self.__deepcopy__ = new.instancemethod(PeachDeepCopy, self, self.__class__)
157
158 if self.name == None or len(self.name) == 0:
159 self.name = self.getUniqueName()
160
162 '''
163 Will generate (yield) all values of a specific type
164 in the tree starting with us.
165 '''
166
167 if isinstance(self, type):
168 yield self
169
176 getUniqueName = staticmethod(getUniqueName)
177
179 '''
180 Return fully qualified name inside of data map
181 '''
182
183 name = self.name
184
185 parent = self.parent
186 while parent != None and isinstance(parent, DataElement):
187 name = "%s.%s" % (parent.name, name)
188 parent = parent.parent
189
190 return name
191
193 '''
194 Get the root of this DOM tree
195 '''
196
197 stack = []
198
199 root = self
200 stack.append(root)
201 while root.parent != None and root.parent not in stack:
202 root = root.parent
203 stack.append(root)
204
205 if root.parent != None and root.parent in stack:
206 raise Exception("Error: getRoot found a recursive relationship! EEk!")
207
208 return root
209
211 '''
212 Print out a map of the dom.
213 '''
214 print (" "*level) + "- %s [%s](%s)" % (self.name, self.elementType, str(self)[-9:])
215
217 '''
218 Convert to an XML DOM object tree for use in xpath queries.
219 '''
220
221 owner = parent.ownerDocument
222 if owner == None:
223 owner = parent
224
225 if hasattr(self, 'ref') and self.ref != None:
226 node = owner.createElementNS(None, self.ref)
227 else:
228 node = owner.createElementNS(None, self.name)
229
230 node.setAttributeNS(None, "elementType", self.elementType)
231 node.setAttributeNS(None, "name", self.name)
232
233 if hasattr(self, 'ref') and self.ref != None:
234 self._setXmlAttribute(node, "ref", self.ref)
235 if hasattr(self, 'defaultValue') and self.defaultValue != None:
236 self._setXmlAttribute(node, "defaultValue", self.defaultValue)
237 if hasattr(self, 'currentValue') and self.currentValue != None:
238 self._setXmlAttribute(node, "currentValue", self.currentValue)
239 if hasattr(self, 'value') and self.value != None:
240 self._setXmlAttribute(node, "value", self.value)
241
242 dict[node] = self
243 dict[self] = node
244
245 parent.appendChild(node)
246
247 return node
248
250 '''
251 Set an XML attribute with handling for UnicodeDecodeError.
252 '''
253
254 try:
255 value = str(value)
256 node.setAttributeNS(None, key, value)
257
258 except UnicodeDecodeError:
259 node.setAttributeNS(None, "%s-Encoded" % key, "base64")
260 node.setAttributeNS(None, key, base64.b64encode(value))
261
263 '''
264 Get an XML attribute with handling for UnicdeDecodeError.
265 '''
266
267 if not node.hasAttributeNS(None, key):
268 return None
269
270 value = str(node.getAttributeNS(None, key))
271 if node.hasAttributeNS(None, "%s-Encoded" % key):
272 value = base64.b64decode(value)
273
274 return value
275
277 '''
278 Update our object based on an XML DOM object.
279 All we are taking for now is defaultValue.
280 '''
281
282 if node.hasAttributeNS(None, 'defaultValue'):
283 self.defaultValue = self._getXmlAttribute(node, "defaultValue")
284
285
286 if node.hasAttributeNS(None, 'currentValue'):
287 self.currentValue = self._getXmlAttribute(node, "currentValue")
288
289
290 if node.hasAttributeNS(None, 'value'):
291 self.value = self._getXmlAttribute(node, "value")
292
293
294 - def copy(self, parent):
295 newSelf = copy.deepcopy(self)
296 self._FixParents(newSelf, parent)
297
298 return newSelf
299
301 '''
302 Walk down from start and fix parent settings on children
303 '''
304
305
306
307 if start == None:
308 start = self
309
310 if parent != None:
311 start.parent = parent
312
313
314
315
316
317
318
319
320
321
322
323
324
325 if hasattr(start, 'children'):
326 for child in start:
327 self._FixParents(child, start)
328
329
331
332 name = self.name
333 node = self
334
335 while node.parent != None:
336
337
338
339 node = node.parent
340 name = "%s.%s" % (node.name, name)
341
342 return name
343
345 '''
346 Get the next sibling or return None
347 '''
348
349 if self.parent == None:
350 return None
351
352
353 ourIndex = self.parent._children.index(self)
354
355
356 if len(self.parent._children) <= (ourIndex+1):
357 return None
358
359
360 return self.parent._children[ourIndex+1]
361
363 '''
364 Get the prior sibling or return None
365 '''
366
367 if self.parent == None:
368 return None
369
370
371 ourIndex = self.parent._children.index(self)
372
373
374 if ourIndex == 0:
375 return None
376
377 return self.parent._children[ourIndex-1]
378
379
380
381
382
383
384
386 '''
387 Checks to see if origional parsed XML has a
388 child node with the specified name.
389 '''
390
391 for child in self.node.childNodes:
392 if child.hasAttributeNS(None, 'name') and child.getAttributeNS(None, 'name') == name:
393 return True
394
395 return False
396
397
399 '''
400 Set an attribute on an XML Element. We only set the
401 attribute in the following cases:
402
403 1. We have no attached xml node or self.ref == None
404 2. We have a node, and the node has that attribute
405 3. The value is not None
406
407 '''
408
409 if name == 'name' and self.GuidRegex.search(value):
410 return
411
412
413 if value == default or value == None:
414 return
415
416 if self.node != None and not self.node.hasAttributeNS(None, name):
417 return
418
419 node.setAttributeNS(None, name, str(value))
420
421 GuidRegex = re.compile('^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$')
423 '''
424 Verify that we should serialize child node. Checks
425 to see if we have an attached xml node and that xml
426 node has the child. If we don't have an attached
427 xml node then say we should add child.
428 '''
429
430 if self.ref == None or self.node == None:
431 return True
432
433 for c in self.node.childNodes:
434
435 if c.nodeName.lower() == child.elementType:
436 if c.hasAttributeNS(None, 'name'):
437 if c.getAttributeNS(None, 'name') == child.name:
438 return True
439 else:
440 if self.GuidRegex.search(child.name) == True:
441 return True
442
443 return False
444
445
447 '''
448 Contains functions that cause Element to act as a
449 hash table and array for children. Also children can
450 be accessed by name via self.children.name.
451 '''
452
453 - def __init__(self, name = None, parent = None):
454 Element.__init__(self, name, parent)
455 self._children = []
456 self._childrenHash = {}
457 self.children = Empty()
458 self.hasChildren = True
459
460
462 '''
463 Will generate (yield) all values of a specific type
464 in the tree starting with us.
465 '''
466
467 if isinstance(self, type):
468 yield self
469
470 for child in self:
471 for e in child.genElementsByType(type):
472 yield e
473
475 '''
476 Print out a map of the dom.
477 '''
478 print ""
479 print (" "*level) + "+ %s [%s](%s)" % (self.name, self.elementType, str(self)[-9:])
480
481 for child in self:
482 if isinstance(child, Element):
483 child.printDomMap(level+1)
484
485 if child.parent != self:
486 raise Exception("Error: printDomMap: %s.parent != self : %s:%s " % (child.name, child.name, repr(child.parent)))
487
489 '''
490 Verify parent child relationship across DOM Tree
491 '''
492 for child in self:
493 if isinstance(child, Element):
494 if child.parent != self:
495 raise Exception("Error: verifyDomMap: %s.parent != self : %s:%s " % (child.name, child.name, repr(child.parent)))
496
497 if isinstance(child, ElementWithChildren):
498 child.verifyDomMap()
499
501 '''
502 Convert to an XML DOM boject tree for use in xpath queries.
503 '''
504
505
506 if isinstance(self, DataElement):
507 self.getValue()
508
509 node = Element.toXmlDom(self, parent, dict)
510
511 for child in self._children:
512
513 child.toXmlDom(node, dict)
514
515 return node
516
518 '''
519 Update our object based on an XML DOM object.
520 All we are taking for now is defaultValue.
521 '''
522
523 Element.updateFromXmlDom(self, node, dict)
524
525 if node.hasChildNodes():
526 for child in node.childNodes:
527 dict[child].updateFromXmlDom(child, dict)
528
530 '''
531 Set data elements defaultValue based on a Data object.
532 '''
533
534 if data.fileName != None:
535 fd = open(data.fileName, "rb")
536 stuff = fd.read()
537 fd.close()
538
539 parent = self.parent
540 while parent.parent != None: parent = parent.parent
541
542 cracker = PeachModule.Engine.incoming.DataCracker(parent)
543 cracker.haveAllData = True
544 cracker.crackData(self, stuff, "setDefaultValue")
545
546 if PeachModule.Engine.engine.Engine.debug:
547 dict = {}
548 doc = Ft.Xml.Domlette.NonvalidatingReader.parseString("<Peach/>")
549
550 node = self.toXmlDom(doc.rootNode.firstChild, dict)
551
552 print "*****POST setDefaults on [%s] *************" % self.name
553 PrettyPrint(doc, asHtml=1)
554 print "******************"
555
556 return
557
558 if data.expression != None:
559
560 stuff = peachEval(data.expression)
561
562 parent = self.parent
563 while parent.parent != None: parent = parent.parent
564
565 cracker = PeachModule.Engine.incoming.DataCracker(parent)
566 cracker.haveAllData = True
567 cracker.crackData(self, stuff, "setDefaultValue")
568
569 return
570
571 for field in data:
572 obj = self
573
574 for name in field.name.split('.'):
575
576 if hasattr(obj.children, name):
577 obj = getattr(obj.children, name)
578
579 else:
580 raise str("setDefaults(): Unable to locate field %s" % field.name)
581
582 obj.currentValue = field.value
583
584
585
586
587
588
589
590
591
592
593
594
596 if obj in self._children:
597 raise Exception("object already child of element")
598
599
600 if self._childrenHash.has_key(obj.name):
601 self[obj.name] = obj
602 return
603
604
605 self._children.append(obj)
606 if obj.name != None:
607 self._childrenHash[obj.name] = obj
608 setattr(self.children, obj.name, obj)
609
611 return self._children.index(obj)
612
613 - def insert(self, index, obj):
614 if obj in self._children:
615 raise Exception("object already child of element")
616
617 self._children.insert(index, obj)
618 if obj.name != None:
619 self._childrenHash[obj.name] = obj
620 setattr(self.children, obj.name, obj)
621
623 if(len(self._children) >= 1):
624 return self._children[0]
625
626 return None
627
629 if(len(self._children) >= 1):
630 return self._children[-1]
631
632 return None
633
635 return self._childrenHash.has_key(name)
636
637
638
639
641 return self._children.__len__()
642
648
650 if type(key) == int:
651 oldObj = self._children[key]
652 if oldObj.name != None:
653 del self._childrenHash[oldObj.name]
654
655
656 if value.name != None:
657 self._childrenHash[value.name] = value
658 setattr(self.children, value.name, value)
659
660 return self._children.__setitem__(key, value)
661
662 else:
663 if key in self._childrenHash:
664
665 inx = self._children.index( self._childrenHash[key] )
666 self._children[inx] = value
667 self._childrenHash[key] = value
668 setattr(self.children, value.name, value)
669 else:
670 self._children.append(value)
671 self._childrenHash[key] = value
672 setattr(self.children, value.name, value)
673
675 if type(key) == int:
676 obj = self._children[key]
677 if obj.name != None:
678 del self._childrenHash[obj.name]
679 delattr(self.children, obj.name)
680
681 return self._children.__delitem__(key)
682
683 obj = self._childrenHash[key]
684 self._children.remove(obj)
685 del self._childrenHash[key]
686 delattr(self.children, key)
687
690
693
694
696 '''
697 Data elements compose the Data Modle. This is the base
698 class for String, Number, Block, Template, etc.
699
700 When iterating over the Peach DOM if an element
701 isinstance(obj, DataElement) it is part of a data model.
702 '''
703 - def __init__(self, name = None, parent = None):
704 ElementWithChildren.__init__(self, name, parent)
705
706 if name != None and (name.find(".") > -1 or name.find(":") > -1):
707 raise PeachException("Name '%s' contains characters not allowed in names such as period (.) or collen (:)" % name)
708
709
710 self.onArrayNext = None
711
712
713 self.transformer = None
714
715
716 self.fixup = None
717
718
719 self.relations = []
720
721
722 self._minOccurs = 1
723
724 self._maxOccurs = 1
725
726
727 self.defaultValue = None
728
729 self.currentValue = None
730
731 self.value = None
732
733
734
735 self.when = None
736
737 self._inInternalValue = False
738
739
740 self.array = None
741 self.arrayPosition = None
742 self.arrayMinOccurs = None
743 self.arrayMaxOccurs = None
744
745
746 self.pos = None
747
748 self.rating = None
749
750
751 self.isStatic = False
752
753
754 self.relationStringBuffer = None
755
769
771 if value == None:
772 self._maxOccurs = None
773
774 else:
775 self._minOccurs = str(value)
776
777
778 minOccurs = property(get_minOccurs, set_minOccurs)
779
781 if self._maxOccurs == None:
782 return None
783
784 return eval(str(self._maxOccurs))
785
787 if value == None:
788 self._maxOccurs = None
789 else:
790 self._maxOccurs = str(value)
791
792
793 maxOccurs = property(get_maxOccurs, set_maxOccurs)
794
796 '''
797 Yield all children data elements. Recursive
798 '''
799
800 for child in self:
801 if isinstance(child, DataElement):
802 yield child
803 child.genAllChildDataElements()
804
806
807 if node == None:
808 node = self
809
810 for relation in node.relations:
811 if relation.type == 'size':
812 return True
813
814 return False
815
817
818 if node == None:
819 node = self
820
821 for relation in node.relations:
822 if relation.type == 'offset':
823 return True
824
825 return False
826
828
829 if node == None:
830 node = self
831
832 for relation in node.relations:
833 if relation.type == 'offset':
834 return relation
835
836 return False
837
839
840 if node == None:
841 node = self
842
843 for relation in node.relations:
844 if relation.type == 'size':
845 return relation
846
847 return None
848
850
851 if node == None:
852 node = self
853
854 for relation in node.relations:
855 if relation.type == 'when':
856 return relation
857
858 return None
859
861
862 if node == None:
863 node = self
864
865 for relation in node.relations:
866 if relation.type == 'when':
867 return True
868
869 return False
870
872
873 if node == None:
874 node = self
875
876 for relation in node.relations:
877 if relation.type == 'count':
878 return True
879
880 return False
881
883
884 if node == None:
885 node = self
886
887 for relation in node.relations:
888 if relation.type == 'count':
889 return relation
890
891 return None
892
894 '''
895 This will get fully qualified name of this element starting with the
896 root node of the data model.
897 '''
898
899 name = self.name
900 node = self
901
902 while node.parent != None and isinstance(node.parent, DataElement):
903 node = node.parent
904 name = "%s.%s" % (node.name, name)
905
906 return name
907
909 '''
910 Return the root of this data map. This should always return
911 a Template object.
912 '''
913
914 root = self
915 while root.parent != None and isinstance(root.parent, DataElement):
916 root = root.parent
917
918 return root
919
921 '''
922 Will find first element in array named "name".
923
924 This method should allow for more natural reuse of Blocks/Templates
925 w/o the user needing to think about it.
926
927 @type name: string
928 @param name: Array to find. Does not support dotted name.
929 @rtype: DataElement
930 @return: DataElement or None
931 '''
932
933
934
935 for block in self._findAllBlocksGoingUp():
936 for node in self._findArrayByName(block, name):
937 return node
938
939 return None
940
942 '''
943 A generator that returns each instance of name in a data model.
944 '''
945
946
947 if node.array == name and node.arrayPosition == 0:
948 yield node
949
950
951 for child in node._children:
952 if isinstance(child, DataElement) and child.array == name and child.arrayPosition == 0:
953 yield child
954
955
956 for child in node._children:
957 if isinstance(child, DataElement):
958 for n in self._findArrayByName(child, name):
959 yield n
960
961
962
964 '''
965 Will find a data element in this data map by name. The search
966 pattern we use is to locate each block we are a member of
967 starting with the nearest. At each block we look down to see
968 if we can resolve the name. If not we move closer towards the
969 root of the data model.
970
971 This method should allow for more natural reuse of Blocks/Templates
972 w/o the user needing to think about it.
973
974 @type name: string
975 @param name: Name of element to find. Can be full or relative.
976 @rtype: DataElement
977 @return: DataElement or None
978 '''
979
980 names = name.split('.')
981
982 if self.name == names[0]:
983 obj = self._checkDottedName(self, names)
984 if obj != None:
985 return obj
986
987 for block in self._findAllBlocksGoingUp():
988 for node in self._findDataElementByName(block, names[0]):
989 obj = self._checkDottedName(node, names)
990 if obj != None:
991 return obj
992
993 return None
994
995 - def find(self, name):
996 '''
997 Alias for findDataElementByName.
998
999 Will find a data element in this data map by name. The search
1000 pattern we use is to locate each block we are a member of
1001 starting with the nearest. At each block we look down to see
1002 if we can resolve the name. If not we move closer towards the
1003 root of the data model.
1004
1005 This method should allow for more natural reuse of Blocks/Templates
1006 w/o the user needing to think about it.
1007
1008 @type name: string
1009 @param name: Name of element to find. Can be full or relative.
1010 @rtype: DataElement
1011 @return: DataElement or None
1012 '''
1013 return self.findDataElementByName(name)
1014
1016 '''
1017 Generator that locates all blocks by walking up
1018 our tree.
1019 '''
1020
1021 obj = self
1022 if isinstance(obj, Block) or isinstance(obj, Template):
1023 yield obj
1024
1025 while obj.parent != None and isinstance(obj.parent, DataElement):
1026 obj = obj.parent
1027
1028 if isinstance(obj, Block) or isinstance(obj, Template):
1029 yield obj
1030
1032 '''
1033 A generator that returns each instance of name in a data model.
1034 '''
1035
1036
1037 if node.name == name:
1038 yield node
1039
1040
1041 if node.has_key(name):
1042 yield node[name]
1043
1044
1045 for child in node._children:
1046 if isinstance(child, DataElement):
1047 for n in self._findDataElementByName(child, name):
1048 yield n
1049
1050
1051
1053 '''
1054 Internal helper method, not for use!
1055 '''
1056
1057 if node.name != names[0]:
1058 return None
1059
1060 obj = node
1061 for i in range(1, len(names)):
1062 if not obj.has_key(names[i]):
1063 return None
1064
1065 obj = obj[names[i]]
1066
1067 return obj
1068
1079
1081 '''
1082 Instead of returning all relations starting with
1083 root we will walk up looking for relations.
1084 '''
1085
1086 history = []
1087
1088 if node == None:
1089 node = self
1090
1091 cur = node.parent
1092 while cur != None:
1093 for r in self._getAllRelationsInDataModel(cur.parent, history):
1094 yield r
1095
1096 cur = cur.parent
1097
1098 for r in self._getAllRelationsInDataModel(None, history):
1099 yield r
1100
1102 '''
1103 Generator that gets all relations in data model.
1104 '''
1105
1106 if history == None:
1107 history = []
1108
1109 if node == None:
1110 node = self.getRootOfDataMap()
1111
1112 if isinstance(node, Relation):
1113 yield node
1114
1115 if isinstance(node, DataElement):
1116 for child in node._children:
1117 if child not in history:
1118 history.append(child)
1119 for r in self._getAllRelationsInDataModel(child, history):
1120 if r not in history:
1121 history.append(r)
1122 yield r
1123
1125 '''
1126 Check if this data element is part of an array.
1127 '''
1128
1129 if self.array != None:
1130 return True
1131
1133 '''
1134 Return number of elements in array.
1135 '''
1136
1137 if not self.isArray():
1138 return -1
1139
1140 maxPos = int(self.arrayPosition)
1141 for c in self.parent:
1142 if isinstance(c, DataElement) and c.array == self.array:
1143 if int(c.arrayPosition) > maxPos:
1144 maxPos = int(c.arrayPosition)
1145
1146 return maxPos+1
1147
1149 '''
1150 Return array element at position num.
1151 '''
1152
1153 if not self.isArray():
1154 return None
1155
1156 for c in self.parent:
1157 if isinstance(c, DataElement) and c.array == self.array:
1158 if int(c.arrayPosition) > maxPos:
1159 return c
1160
1161 return None
1162
1164 '''
1165 Return how many times this element occurs. If it is part
1166 of an array the array size is returned, otherwise we will
1167 look at the min/max and any count relations.
1168 '''
1169
1170
1171 if self.isArray():
1172 return self.getArrayCount()
1173
1174
1175 rel = self.getRelationOfThisElement()
1176 if rel != None and rel.type == 'count':
1177 try:
1178 cnt = int(rel.parent.getInternalValue())
1179
1180 if cnt < self.minOccurs:
1181 cnt = self.minOccurs
1182 elif cnt > self.maxOccurs:
1183 cnt = self.maxOccurs
1184
1185 return cnt
1186
1187 except:
1188
1189 pass
1190
1191
1192
1193 if self.minOccurs > 1:
1194 return self.minOccurs
1195
1196 return 1
1197
1199 '''
1200 Return the internal value of this date element. This
1201 value comes before any modifications such as packing,
1202 padding, truncating, etc.
1203
1204 For Numbers this is the python int or long value.
1205 '''
1206 raise Exception("TODO: Implement me!")
1207
1209 '''
1210 This is common logic that was being duplicated across several data
1211 elements. The logic is used in getInternalValue() to check if a
1212 relation of size-of or count-of should modify the value.
1213
1214 @rtype: string or number
1215 @return: the value passed in or an integer if the value needed to be changed.
1216 '''
1217
1218 if self._HasSizeofRelation(self) and not self._inInternalValue:
1219 try:
1220 self._inInternalValue = True
1221 relation = self._GetSizeofRelation(self)
1222 value = len(relation.getOfElement().getValue())
1223 value = relation.setValue(value)
1224
1225 finally:
1226 self._inInternalValue = False
1227
1228 elif self._HasCountofRelation(self) and not self._inInternalValue:
1229
1230 self._inInternalValue = True
1231 try:
1232
1233 relation = self._GetCountofRelation(self)
1234 ofElement = relation.getOfElement()
1235
1236
1237 ofElement.getValue()
1238
1239 value = ofElement.getCount()
1240 value = relation.setValue(value)
1241
1242 finally:
1243 self._inInternalValue = False
1244
1245 return value
1246
1248 '''
1249 Get the value of this data element pre-transformers.
1250 '''
1251
1252 raise Exception("TODO: Implement me!")
1253
1270
1272 '''
1273 Set the default value for this data element.
1274 '''
1275 self.defaultValue = value
1276
1278 '''
1279 Set the current value for this data element
1280 '''
1281 self.currentValue = value
1282 self.getValue()
1283
1285 '''
1286 Reset the value of this data element back to
1287 the default.
1288 '''
1289 self.currentValue = None
1290 self.value = None
1291
1293 '''
1294 Reset the entire data model.
1295 '''
1296
1297 if node == None:
1298 node = self.getRootOfDataMap()
1299
1300 node.reset()
1301
1302 for c in node._children:
1303 if isinstance(c, DataElement()):
1304 self.resetDataModel(c)
1305
1307
1308
1309
1310 root = node
1311 while root.parent != None:
1312 root = root.parent
1313
1314
1315
1316 if hasattr(root, 'realParent'):
1317
1318 root.parent = root.realParent
1319
1320
1321
1323
1324
1325
1326 root = node
1327 while not hasattr(root, 'realParent') and root.parent != None:
1328 root = root.parent
1329
1330
1331
1332 root.parent = None
1333
1335 '''
1336 Calculate length
1337 '''
1338
1339 environment = {
1340 'self' : self
1341 }
1342
1343 try:
1344 self._fixRealParent(self)
1345 return evalEvent(self.lengthCalc, environment)
1346 finally:
1347 self._unFixRealParent(self)
1348
1349
1364
1365 -class Fixup(ElementWithChildren):
1366 '''
1367 Fixup DOM element. Child of data elements only.
1368 '''
1369 - def __init__(self, parent, fixup = None):
1374
1375
1376 -class Param(ElementWithChildren):
1381
1382
1383 -class Peach(ElementWithChildren):
1384 '''
1385 This is our root node container.
1386 '''