*** empty log message ***
git-svn-id: file:///Users/arjan/backup/gaphor/trunk/gaphor@37 a8418922-720d-0410-834f-a69b97ada669
This commit is contained in:
parent
b28d7bfba8
commit
4b063063d9
50
doc/storage.txt
Normal file
50
doc/storage.txt
Normal file
@ -0,0 +1,50 @@
|
||||
Saving and loading Gaphor diagrams
|
||||
|
||||
The idea is to keep the file format as simple and extensible as possible.
|
||||
|
||||
This is the format as used by Gaphor.
|
||||
|
||||
Everything interesting is between the `Gaphor' start and end tag.
|
||||
|
||||
The file is as flat as possible: UML elements (including Diagram) are at
|
||||
toplevel, no nesting.
|
||||
A UML element can have two tags: `Reference' and `Value'. Reference is used to
|
||||
point to other UML elements, Value has a value inside (an integer or astring).
|
||||
|
||||
Diagram is a special case. Since this element contains a diagram canvas inside,
|
||||
it may become pretty big (with lots of nested elements).
|
||||
This is handled by the load and save function of the Diagram class.
|
||||
All elements inside a canvas have a tag `Item'.
|
||||
|
||||
<?xml version="1.0" ?>
|
||||
<Gaphor version="1.0">
|
||||
<Model id="1">
|
||||
<Reference name="ownedElement" refid="2"/>
|
||||
<Reference name="ownedElement" refid="3"/>
|
||||
<Reference name="ownedElement" refid="4"/>
|
||||
</Model>
|
||||
<Diagram id="2">
|
||||
<Reference name="namespace" refid="1"/>
|
||||
<Canvas extents="(9.0, 9.0, 189.0, 247.0)" grid_bg="0xFFFFFFFF"
|
||||
grid_color="0x80ff" grid_int_x="10.0" grid_int_y="10.0"
|
||||
grid_ofs_x="0.0" grid_ofs_y="0.0" snap_to_grid="0"
|
||||
static_extents="0">
|
||||
<CanvasItem affine="(1.0, 0.0, 0.0, 1.0, 0.0, 0.0)" cid="0x8292114"
|
||||
type="CanvasGroup">
|
||||
<CanvasItem affine="(1.0, 0.0, 0.0, 1.0, 150.0, 50.0)" cid="0x8293e74"
|
||||
height="78.0" subject="3" type="Actor" width="38.0"/>
|
||||
<CanvasItem affine="(1.0, 0.0, 0.0, 1.0, 10.0, 10.0)" cid="0x82e7d74"
|
||||
height="26.0" subject="5" type="Comment" width="100.0"/>
|
||||
</CanvasItem>
|
||||
</Canvas>
|
||||
</Diagram>
|
||||
<Actor id="3">
|
||||
<Value name="name">
|
||||
<![CDATA[Actor]]> </Value>
|
||||
<Reference name="namespace" refid="1"/>
|
||||
</Actor>
|
||||
<UseCase id="4">
|
||||
<Reference name="namespace" refid="1"/>
|
||||
</UseCase>
|
||||
<Comment id="5"/>
|
||||
</Gaphor>
|
@ -32,6 +32,14 @@ Geometry = types.ListType
|
||||
FALSE = 0
|
||||
TRUE = not FALSE
|
||||
|
||||
elements = { }
|
||||
|
||||
def lookup (id):
|
||||
if elements.has_key(id):
|
||||
return elements[id]
|
||||
else:
|
||||
return None
|
||||
|
||||
class Enumeration_:
|
||||
'''The Enumerration class is an abstract class that can be used to create
|
||||
enumerated types. One should inherit from Enumeration and define a variable
|
||||
@ -105,7 +113,7 @@ class Element:
|
||||
attributes and relations are defined by a <class>._attrdef structure.
|
||||
A class does not need to define any local variables itself: Element will
|
||||
retrieve all information from the _attrdef structure.
|
||||
Element._hash is a table containing all assigned objects as weak references.
|
||||
elements is a table containing all assigned objects as weak references.
|
||||
This class has its own __del__() method. This means that it can not be freed
|
||||
by the garbage collector. Instead you should call Element::unlink() to
|
||||
remove all relationships with the element and then it will remove itself if
|
||||
@ -120,37 +128,39 @@ object if references are lehd by the object on the undo stack.
|
||||
_index = 1
|
||||
_attrdef = { 'presentation': ( Sequence, types.ObjectType ),
|
||||
'itemsOnUndoStack': (0, types.IntType ) }
|
||||
_hash = { }
|
||||
|
||||
def __init__(self):
|
||||
print "New object of type", self.__class__
|
||||
#print "New object of type", self.__class__
|
||||
self.__dict__['__id'] = Element._index
|
||||
self.__dict__['__signals'] = [ ]
|
||||
#Element._hash[Element._index] = weakref.ref (self)
|
||||
Element._hash[Element._index] = self
|
||||
elements[Element._index] = self
|
||||
Element._index += 1
|
||||
|
||||
def unlink(self):
|
||||
'''Remove all references to the object.'''
|
||||
#print 'Element.unlink()'
|
||||
#print 'Element.unlink():', self
|
||||
self.emit("unlink")
|
||||
if Element._hash.has_key(self.__dict__['__id']):
|
||||
del Element._hash[self.__dict__['__id']]
|
||||
if elements.has_key(self.__dict__['__id']):
|
||||
del elements[self.__dict__['__id']]
|
||||
for key in self.__dict__.keys():
|
||||
# In case of a cyclic reference, we should check if the element
|
||||
# not yet has been removed.
|
||||
if self.__dict__.has_key (key) and \
|
||||
key not in ( 'presentation', '__signals', '__id' ):
|
||||
key not in ( 'presentation', 'itemsOnUndoStack', \
|
||||
'__signals', '__id' ):
|
||||
if isinstance (self.__dict__[key], Sequence):
|
||||
# Remove each item in the sequence, then remove
|
||||
# the sequence from __dict__.
|
||||
for s in self.__dict__[key].list:
|
||||
del self.__dict__[key][s]
|
||||
list = self.__dict__[key].list
|
||||
while len (list) > 0:
|
||||
del self.__dict__[key][list[0]]
|
||||
del self.__dict__[key]
|
||||
else:
|
||||
# do a 'del self.key'
|
||||
if isinstance (self.__dict__[key], Element):
|
||||
self.__delattr__(key)
|
||||
#if isinstance (self.__dict__[key], Element):
|
||||
#print '\tunlink:', key
|
||||
self.__delattr__(key)
|
||||
return self
|
||||
|
||||
# Hooks for presentation elements to add themselves:
|
||||
@ -167,6 +177,9 @@ object if references are lehd by the object on the undo stack.
|
||||
|
||||
def undo_presentation (self, presentation):
|
||||
if not presentation in self.presentation:
|
||||
# Add myself to the 'elements' hash
|
||||
if len (self.presentation) == 0:
|
||||
elements[self.id] = self
|
||||
self.presentation = presentation
|
||||
self.itemsOnUndoStack -= 1
|
||||
assert self.itemsOnUndoStack >= 0
|
||||
@ -175,8 +188,14 @@ object if references are lehd by the object on the undo stack.
|
||||
if presentation in self.presentation:
|
||||
del self.presentation[presentation]
|
||||
self.itemsOnUndoStack += 1
|
||||
# Remove yourself from the 'elements' hash
|
||||
if len (self.presentation) == 0:
|
||||
if lookup (self.id):
|
||||
del elements[self.id]
|
||||
|
||||
def remove_undoability (self):
|
||||
if not self.__dict__.has_key ('itemsOnUndoStack'):
|
||||
return
|
||||
self.itemsOnUndoStack -= 1
|
||||
assert self.itemsOnUndoStack >= 0
|
||||
if len (self.presentation) == 0 and self.itemsOnUndoStack == 0:
|
||||
@ -184,7 +203,7 @@ object if references are lehd by the object on the undo stack.
|
||||
self.unlink()
|
||||
|
||||
def __get_attr_info(self, key, klass):
|
||||
'''Find the record for 'key' in the <class>._attrdef map.'''
|
||||
'''Find the record for 'key' in the <klass>._attrdef map.'''
|
||||
done = [ ]
|
||||
def real_get_attr_info(key, klass):
|
||||
if klass in done:
|
||||
@ -211,21 +230,23 @@ object if references are lehd by the object on the undo stack.
|
||||
self.__dict__[key] = Sequence(self, type)
|
||||
return self.__dict__[key]
|
||||
|
||||
def __del_seq_item(self, seq, val):
|
||||
try:
|
||||
index = seq.list.index(val)
|
||||
del seq.list[index]
|
||||
except ValueError:
|
||||
pass
|
||||
#def __del_seq_item(self, seq, val):
|
||||
#try:
|
||||
#index = seq.list.index(val)
|
||||
#del seq.list[index]
|
||||
# seq.list.remove (val)
|
||||
#except ValueError:
|
||||
# pass
|
||||
|
||||
def __getattr__(self, key):
|
||||
#print 'Element.__getattr__(' + key + ')'
|
||||
if key == 'id':
|
||||
return self.__dict__['__id']
|
||||
elif self.__dict__.has_key(key):
|
||||
# Key is already in the object
|
||||
return self.__dict__[key]
|
||||
else:
|
||||
#if key[0] != '_':
|
||||
#print 'Unknown attr: Element.__getattr__(' + key + ')'
|
||||
rec = self.__get_attr_info (key, self.__class__)
|
||||
if rec[0] is Sequence:
|
||||
# We do not have a sequence here... create it and return it.
|
||||
@ -264,13 +285,16 @@ object if references are lehd by the object on the undo stack.
|
||||
if rec[0] is not Sequence or xrec[0] is not Sequence:
|
||||
if rec[0] is Sequence:
|
||||
#print 'del-seq-item rec'
|
||||
self.__del_seq_item(self.__dict__[key], xself)
|
||||
#self.__del_seq_item(self.__dict__[key], xself)
|
||||
if xself in self.__dict__[key].list:
|
||||
self.__dict__[key].list.remove(xself)
|
||||
elif self.__dict__.has_key(key):
|
||||
#print 'del-item rec'
|
||||
del self.__dict__[key]
|
||||
if xrec[0] is Sequence:
|
||||
#print 'del-seq-item xrec'
|
||||
xself.__del_seq_item(xself.__dict__[rec[2]], self)
|
||||
#xself.__del_seq_item(xself.__dict__[rec[2]], self)
|
||||
xself.__dict__[rec[2]].list.remove (self)
|
||||
elif xself.__dict__.has_key(rec[2]):
|
||||
#print 'del-item xrec'
|
||||
del xself.__dict__[rec[2]]
|
||||
@ -297,15 +321,18 @@ object if references are lehd by the object on the undo stack.
|
||||
if not self.__dict__.has_key(key):
|
||||
return
|
||||
xval = self.__dict__[key]
|
||||
del self.__dict__[key]
|
||||
if len(rec) > 2: # Bi-directional relationship
|
||||
xrec = xval.__get_attr_info (rec[2], rec[1])
|
||||
if xrec[0] is Sequence:
|
||||
xval.__del_seq_item(xval.__dict__[rec[2]], self)
|
||||
#xval.__del_seq_item(xval.__dict__[rec[2]], self)
|
||||
#xval.__dict__[rec[2]].list.remove (self)
|
||||
# Handle it via sequence_remove()
|
||||
del xval.__dict__[rec[2]][self]
|
||||
else:
|
||||
del xval.__dict__[rec[2]]
|
||||
xval.emit(rec[2])
|
||||
self.emit (key)
|
||||
del self.__dict__[key]
|
||||
self.emit (key)
|
||||
xval.emit(rec[2])
|
||||
|
||||
def sequence_remove(self, seq, obj):
|
||||
'''Remove an entry. Should only be called by Sequence's implementation.
|
||||
@ -315,20 +342,24 @@ object if references are lehd by the object on the undo stack.
|
||||
if self.__dict__[key] is seq:
|
||||
break
|
||||
#print 'Element.sequence_remove', key
|
||||
seq_len = len (seq)
|
||||
rec = self.__get_attr_info (key, self.__class__)
|
||||
if rec[0] is not Sequence:
|
||||
raise AttributeError, 'Element: This should be called from Sequence'
|
||||
seq.list.remove(obj)
|
||||
if len(rec) > 2: # Bi-directional relationship
|
||||
xrec = obj.__get_attr_info (rec[2], rec[1])
|
||||
xrec = obj.__get_attr_info (rec[2], obj.__class__) #rec[1])
|
||||
if xrec[0] is Sequence:
|
||||
obj.__del_seq_item(obj.__dict__[rec[2]], self)
|
||||
#obj.__del_seq_item(obj.__dict__[rec[2]], self)
|
||||
#print 'sequence_remove: Sequence'
|
||||
obj.__dict__[rec[2]].list.remove (self)
|
||||
else:
|
||||
try:
|
||||
del obj.__dict__[rec[2]]
|
||||
except Exception, e:
|
||||
print 'ERROR: (Element.sequence_remove)', e
|
||||
|
||||
#try:
|
||||
#print 'sequence_remove: item'
|
||||
del obj.__dict__[rec[2]]
|
||||
#except Exception, e:
|
||||
# print 'ERROR: (Element.sequence_remove)', e
|
||||
assert len (seq) == seq_len - 1
|
||||
# Functions used by the signal functions
|
||||
def connect (self, signal_func, *data):
|
||||
self.__dict__['__signals'].append ((signal_func,) + data)
|
||||
@ -338,24 +369,81 @@ object if references are lehd by the object on the undo stack.
|
||||
self.__dict__['__signals'])
|
||||
|
||||
def emit (self, key):
|
||||
if not self.__dict__.has_key ('__signals'):
|
||||
print 'No __signals attribute in object', self
|
||||
return
|
||||
print 'emit', self, key
|
||||
#if not self.__dict__.has_key ('__signals'):
|
||||
# print 'No __signals attribute in object', self
|
||||
# return
|
||||
for signal in self.__dict__['__signals']:
|
||||
signal_func = signal[0]
|
||||
data = signal[1:]
|
||||
#print 'signal:', signal_func, 'data:', data
|
||||
signal_func (key, *data)
|
||||
|
||||
#def update_model():
|
||||
# '''Do a garbage collection on the hash table, also removing
|
||||
# weak references that do not point to valid objects.'''
|
||||
# gc.collect()
|
||||
# for k in Element._hash.keys():
|
||||
# if Element._hash[k]() is None:
|
||||
# del Element._hash[k]
|
||||
def save(self, document, parent):
|
||||
def save_children (obj):
|
||||
if isinstance (obj, Element):
|
||||
#subnode = document.createElement (key)
|
||||
subnode = document.createElement ('Reference')
|
||||
node.appendChild (subnode)
|
||||
subnode.setAttribute ('name', key)
|
||||
subnode.setAttribute ('refid', str(obj.__dict__['__id']))
|
||||
elif isinstance (obj, types.IntType) or \
|
||||
isinstance (obj, types.LongType) or \
|
||||
isinstance (obj, types.FloatType):
|
||||
subnode = document.createElement ('Value')
|
||||
node.appendChild (subnode)
|
||||
subnode.setAttribute ('name', key)
|
||||
text = document.createTextNode (str(obj))
|
||||
subnode.appendChild (text)
|
||||
elif isinstance (obj, types.StringType):
|
||||
subnode = document.createElement ('Value')
|
||||
node.appendChild (subnode)
|
||||
subnode.setAttribute ('name', key)
|
||||
cdata = document.createCDATASection (str(obj))
|
||||
subnode.appendChild (cdata)
|
||||
|
||||
#Element_hash_gc = update_model
|
||||
node = document.createElement (self.__class__.__name__)
|
||||
parent.appendChild (node)
|
||||
node.setAttribute ('id', str (self.__dict__['__id']))
|
||||
for key in self.__dict__.keys():
|
||||
if key not in ( 'presentation', 'itemsOnUndoStack', \
|
||||
'__signals', '__id' ):
|
||||
obj = self.__dict__[key]
|
||||
if isinstance (obj, Sequence):
|
||||
for item in obj.list:
|
||||
save_children (item)
|
||||
else:
|
||||
save_children (obj)
|
||||
return node
|
||||
|
||||
def load(self, node):
|
||||
for child in node.childNodes:
|
||||
if child.tagName == 'Reference':
|
||||
name = child.getAttribute ('name')
|
||||
refid = int (child.getAttribute ('refid'))
|
||||
refelement = lookup (refid)
|
||||
attr_info = self.__get_attr_info (name, self.__class__)
|
||||
if not isinstance (refelement, attr_info[1]):
|
||||
raise ValueError, 'Referenced item is of the wrong type'
|
||||
if attr_info[0] is Sequence:
|
||||
self.__ensure_seq (name, attr_info[1]).list.append (refelement)
|
||||
else:
|
||||
self.__dict__[name] = refelement
|
||||
elif child.tagName == 'Value':
|
||||
name = child.getAttribute ('name')
|
||||
subchild = child.firstChild
|
||||
attr_info = self.__get_attr_info (name, self.__class__)
|
||||
if issubclass (attr_info[1], types.IntType) or \
|
||||
issubclass (attr_info[1], types.LongType):
|
||||
self.__dict__[name] = int (subchild.data)
|
||||
elif issubclass (attr_info[1], types.FloatType):
|
||||
self.__dict__[name] = float (subchild.data)
|
||||
else:
|
||||
self.__dict__[name] = subchild.data
|
||||
|
||||
|
||||
###################################
|
||||
# Testing
|
||||
if __name__ == '__main__':
|
||||
|
||||
print '\n============== Starting Element tests... ============\n'
|
||||
@ -389,7 +477,7 @@ if __name__ == '__main__':
|
||||
a.unlink()
|
||||
del a
|
||||
|
||||
assert len (Element._hash) == 0
|
||||
assert len (elements) == 0
|
||||
|
||||
print '\tOK ==='
|
||||
|
||||
@ -421,7 +509,7 @@ if __name__ == '__main__':
|
||||
|
||||
a.unlink()
|
||||
|
||||
assert len (Element._hash) == 0
|
||||
assert len (elements) == 0
|
||||
|
||||
print '\tOK ==='
|
||||
|
||||
@ -468,7 +556,7 @@ if __name__ == '__main__':
|
||||
a.unlink()
|
||||
b.unlink()
|
||||
|
||||
assert len (Element._hash) == 0
|
||||
assert len (elements) == 0
|
||||
|
||||
print '\tOK ==='
|
||||
|
||||
@ -496,6 +584,18 @@ if __name__ == '__main__':
|
||||
assert a.ref is a
|
||||
assert a.seq.list == [ a ]
|
||||
|
||||
b = A()
|
||||
a.seq = b
|
||||
assert b.ref is a
|
||||
assert a.seq.list == [ a, b ]
|
||||
|
||||
|
||||
del a.seq[a]
|
||||
assert a.ref is None
|
||||
assert b.ref is a
|
||||
assert a.seq.list == [ b ]
|
||||
|
||||
b.unlink()
|
||||
a.unlink()
|
||||
a = A()
|
||||
b = A()
|
||||
@ -539,8 +639,8 @@ if __name__ == '__main__':
|
||||
a.unlink()
|
||||
b.unlink()
|
||||
|
||||
#print Element._hash
|
||||
assert len (Element._hash) == 0
|
||||
#print elements
|
||||
assert len (elements) == 0
|
||||
|
||||
print '\tOK ==='
|
||||
|
||||
@ -603,7 +703,7 @@ if __name__ == '__main__':
|
||||
a.unlink()
|
||||
b.unlink()
|
||||
|
||||
assert len (Element._hash) == 0
|
||||
assert len (elements) == 0
|
||||
|
||||
print '\tOK ==='
|
||||
|
||||
@ -660,7 +760,7 @@ if __name__ == '__main__':
|
||||
b.unlink()
|
||||
del b
|
||||
|
||||
assert len (Element._hash) == 0
|
||||
assert len (elements) == 0
|
||||
|
||||
print '\tOK ==='
|
||||
|
||||
@ -674,14 +774,14 @@ if __name__ == '__main__':
|
||||
a = A()
|
||||
b = A()
|
||||
|
||||
assert len (Element._hash) == 2
|
||||
assert len (elements) == 2
|
||||
|
||||
a.rel = b
|
||||
|
||||
a.unlink()
|
||||
b.unlink()
|
||||
|
||||
assert len (Element._hash) == 0
|
||||
assert len (elements) == 0
|
||||
|
||||
print '\tOK ==='
|
||||
|
||||
|
@ -9,4 +9,4 @@ ModelElements.py: $(GEN_UML) $(METAMODEL_XMI)
|
||||
grep -v "PresentationElement" genModelElements.py > ModelElements.py
|
||||
rm -f genModelElements.py
|
||||
|
||||
EXTRA_DIST=Element.py ModelElements.py __init__.py
|
||||
EXTRA_DIST=Element.py ModelElements.py management.py __init__.py
|
||||
|
@ -3,6 +3,7 @@
|
||||
#
|
||||
from Element import *
|
||||
from ModelElements import *
|
||||
from management import *
|
||||
|
||||
Attribute._attrdef['rawAttribute'] = ( '', String )
|
||||
Operation._attrdef['rawOperation'] = ( '', String )
|
||||
|
128
gaphor/UML/management.py
Normal file
128
gaphor/UML/management.py
Normal file
@ -0,0 +1,128 @@
|
||||
# vim: sw=4
|
||||
import UML, diagram
|
||||
|
||||
from xmllib import XMLParser
|
||||
from xml.dom.minidom import Document
|
||||
|
||||
# Somehow I did not manage it to use the minidom/SAX stuff to create a
|
||||
# decent parser, do I use this depricated (but workin ;) peace of code...
|
||||
# The GaphorParser reads a Gaphor file and creates a DOM representation of
|
||||
# the file.
|
||||
class GaphorParser (XMLParser):
|
||||
'''GaphorParser
|
||||
The GaphorParser examines an inut strream and creates a Document object
|
||||
using the elements found in the XML file. The only restruction that we
|
||||
test is the Gaphor tag and the version (currently only 1.0)'''
|
||||
def __init__ (self, **kw):
|
||||
self.doit = 0
|
||||
self.doc = Document()
|
||||
self.elements = { 'Gaphor': (self.start_Gaphor, self.end_Gaphor) }
|
||||
self.__stack = [ ]
|
||||
apply(XMLParser.__init__, (self,), kw)
|
||||
|
||||
def syntax_error(self, message):
|
||||
raise IOError, "XML document contains syntax errors: " + message
|
||||
|
||||
def start_Gaphor (self, attrs):
|
||||
if attrs['version'] != '1.0':
|
||||
raise Exception, 'Wrong version of Gaphor (' + \
|
||||
attrs['version'] + ')'
|
||||
else:
|
||||
node = self.doc.createElement('Gaphor')
|
||||
self.doc.appendChild (node)
|
||||
self.__stack.append (node)
|
||||
self.doit += 1
|
||||
|
||||
def end_Gaphor (self):
|
||||
self.doit -= 1
|
||||
|
||||
def unknown_starttag(self, tag, attrs):
|
||||
if self.doit:
|
||||
node = self.doc.createElement(tag)
|
||||
self.__stack[-1].appendChild (node)
|
||||
self.__stack.append (node)
|
||||
for key in attrs.keys():
|
||||
node.setAttribute (key, attrs[key])
|
||||
|
||||
def unknown_endtag(self, tag):
|
||||
self.__stack = self.__stack[:-1]
|
||||
|
||||
def handle_cdata(self, tag):
|
||||
cdata = self.doc.createCDATASection (tag)
|
||||
self.__stack[-1].appendChild (cdata)
|
||||
|
||||
def unknown_entityref(self, ref):
|
||||
raise ValueError, tag + " not supported."
|
||||
|
||||
def unknown_charref(self, ref):
|
||||
raise ValueError, tag + " not supported."
|
||||
|
||||
def save (filename=None):
|
||||
document = Document()
|
||||
rootnode = document.createElement ('Gaphor')
|
||||
document.appendChild (rootnode)
|
||||
rootnode.setAttribute ('version', '1.0')
|
||||
for e in UML.elements.values():
|
||||
print 'Saving object', e
|
||||
e.save(document, rootnode)
|
||||
|
||||
if not filename:
|
||||
print document.toxml(indent=' ', newl='\n')
|
||||
else:
|
||||
file = open (filename, 'w')
|
||||
if not file:
|
||||
raise IOError, 'Could not open file `%s\'' % (filename)
|
||||
document.writexml (file, indent='', addindent=' ', newl='\n')
|
||||
file.close()
|
||||
|
||||
def load (filename):
|
||||
'''Load a file and create a model if possible.
|
||||
Exceptions: IOError, ValueError.'''
|
||||
parser = GaphorParser()
|
||||
|
||||
f = open (filename, 'r')
|
||||
while 1:
|
||||
data = f.read(512)
|
||||
parser.feed (data)
|
||||
if len(data) != 512:
|
||||
break;
|
||||
parser.close()
|
||||
f.close()
|
||||
|
||||
# Now iterate over the tree and create every element in the UML.elements
|
||||
# table.
|
||||
rootnode = parser.doc.firstChild
|
||||
for node in rootnode.childNodes:
|
||||
try:
|
||||
if node.tagName == 'Diagram':
|
||||
cls = getattr (diagram, node.tagName)
|
||||
else:
|
||||
cls = getattr (UML, node.tagName)
|
||||
except:
|
||||
raise ValueError, 'Invalid field in Gaphor file: ' + node.tagName
|
||||
id = int (node.getAttribute('id'))
|
||||
old_index = UML.Element._index
|
||||
UML.Element._index = id
|
||||
cls()
|
||||
if old_index > id:
|
||||
UML.Element._index = old_index
|
||||
#print node.tagName, node.getAttribute('id')
|
||||
|
||||
# Second step: call Element.load() for every object in the element hash.
|
||||
# We also provide the XML node, so it can recreate it's state
|
||||
for node in rootnode.childNodes:
|
||||
id = int (node.getAttribute('id'))
|
||||
element = UML.lookup (id)
|
||||
assert element != None
|
||||
element.load (node)
|
||||
|
||||
|
||||
def flush():
|
||||
'''Flush all elements in the UML.elements'''
|
||||
while 1:
|
||||
try:
|
||||
(key, value) = UML.elements.popitem()
|
||||
except KeyError:
|
||||
break;
|
||||
value.unlink()
|
||||
UML.elements.clear()
|
@ -10,9 +10,12 @@ import diacanvas
|
||||
import UML
|
||||
import tree
|
||||
|
||||
uc = getattr (UML, 'UseCase')
|
||||
print 'getattr (UML, "UseCase") ->', uc
|
||||
|
||||
def mainquit(*args):
|
||||
for k in UML.Element._hash.keys():
|
||||
print "Element", k, ":", UML.Element._hash[k].__dict__
|
||||
for k in UML.elements.keys():
|
||||
print "Element", k, ":", UML.elements[k].__dict__
|
||||
print "Forcing Garbage collection:"
|
||||
gtk.main_quit()
|
||||
|
||||
@ -30,21 +33,21 @@ treemodel = tree.NamespaceModel(model)
|
||||
#item.move (30, 50)
|
||||
#item = canvas.root.add (diagram.Actor)
|
||||
#item.move (150, 50)
|
||||
item = dia.create_item (diagram.UseCase, (50, 150))
|
||||
usecase = item.get_subject()
|
||||
#dia.create_item (diagram.UseCase, (50, 200), subject=usecase)
|
||||
|
||||
item = dia.create_item (diagram.Actor, (150, 50))
|
||||
actor = item.get_subject()
|
||||
actor.name = "Actor"
|
||||
|
||||
item = dia.create_item (diagram.UseCase, (50, 150))
|
||||
usecase = item.get_subject()
|
||||
dia.create_item (diagram.UseCase, (50, 200), subject=usecase)
|
||||
|
||||
item = dia.create_item (diagram.Comment, (10,10))
|
||||
comment = item.get_subject()
|
||||
|
||||
del item
|
||||
del item#, actor, usecase, comment
|
||||
|
||||
#print "Comment.presentation:", comment.presentation.list
|
||||
#print "Actor.presentation:", actor.presentation.list
|
||||
print "Comment.presentation:", comment.presentation.list
|
||||
print "Actor.presentation:", actor.presentation.list
|
||||
print "UseCase.presentation:", usecase.presentation.list
|
||||
#view = diacanvas.CanvasView().set_canvas (dia.canvas)
|
||||
#display_diagram (dia)
|
||||
@ -61,16 +64,15 @@ treemodel.dump()
|
||||
print 'Going into main'
|
||||
gtk.main()
|
||||
|
||||
UML.save('x.xml')
|
||||
|
||||
del win
|
||||
|
||||
treemodel.dump()
|
||||
|
||||
#print "Comment.ann.Elem.:", comment.annotatedElement.list
|
||||
#print "Actor.comment:", actor.comment.list
|
||||
#print "UseCase.comment:", usecase.comment.list
|
||||
print "Comment.presentation:", comment.presentation.list
|
||||
print "Actor.presentation:", actor.presentation.list
|
||||
print "UseCase.presentation:", usecase.presentation.list
|
||||
#print "Comment.presentation:", comment.presentation.list
|
||||
#print "Actor.presentation:", actor.presentation.list
|
||||
#print "UseCase.presentation:", usecase.presentation.list
|
||||
print "removing diagram..."
|
||||
dia.unlink()
|
||||
del dia
|
||||
@ -78,17 +80,15 @@ del dia
|
||||
print "Comment.presentation:", comment.presentation.list
|
||||
print "Actor.presentation:", actor.presentation.list
|
||||
print "UseCase.presentation:", usecase.presentation.list
|
||||
actor.unlink()
|
||||
del actor
|
||||
usecase.unlink()
|
||||
del usecase
|
||||
comment.unlink()
|
||||
del comment
|
||||
#del dia
|
||||
|
||||
print "Garbage collection after gtk.main() has finished:"
|
||||
UML.flush()
|
||||
|
||||
print "Garbage collection after gtk.main() has finished (should be empty):",
|
||||
#UML.update_model()
|
||||
for k in UML.Element._hash.keys():
|
||||
print "Element", k, ":", UML.Element._hash[k].__dict__
|
||||
for k in UML.elements.keys():
|
||||
print "Element", k, ":", UML.elements[k].__dict__
|
||||
|
||||
print "Program ended normally..."
|
||||
|
63
tests/diagram-destroy.py
Normal file
63
tests/diagram-destroy.py
Normal file
@ -0,0 +1,63 @@
|
||||
#
|
||||
# Test the behavior of a UML tree with a Diagram as leaf. The whole tree
|
||||
# should be freed...
|
||||
#
|
||||
|
||||
import UML
|
||||
import diagram as dia
|
||||
import gc
|
||||
|
||||
model = UML.Model()
|
||||
model.name = "MyModel"
|
||||
|
||||
package = UML.Package()
|
||||
package.name = "Package"
|
||||
|
||||
model.ownedElement = package
|
||||
assert len(model.ownedElement.list) == 1
|
||||
assert model.ownedElement.list[0] is package
|
||||
assert package.namespace is model
|
||||
|
||||
actor = UML.Actor()
|
||||
actor.namespace = package
|
||||
assert len(package.ownedElement.list) == 1
|
||||
assert package.ownedElement.list[0] is actor
|
||||
assert actor.namespace is package
|
||||
|
||||
usecase = UML.UseCase()
|
||||
usecase.namespace = package
|
||||
assert len(package.ownedElement.list) == 2
|
||||
assert package.ownedElement.list[0] is actor
|
||||
assert package.ownedElement.list[1] is usecase
|
||||
assert usecase.namespace is package
|
||||
|
||||
diagram = dia.Diagram()
|
||||
diagram.namespace = package
|
||||
assert len(package.ownedElement.list) == 3
|
||||
assert package.ownedElement.list[0] is actor
|
||||
assert package.ownedElement.list[1] is usecase
|
||||
assert package.ownedElement.list[2] is diagram
|
||||
assert diagram.namespace is package
|
||||
|
||||
diagram.create_item (dia.Actor, pos=(0, 0), subject=actor)
|
||||
diagram.create_item (dia.UseCase, pos=(100, 100), subject=usecase)
|
||||
|
||||
#dia.destroy_diagrams()
|
||||
|
||||
model.unlink()
|
||||
del model
|
||||
usecase.unlink()
|
||||
del usecase
|
||||
actor.unlink()
|
||||
del actor
|
||||
package.unlink()
|
||||
del package
|
||||
diagram.unlink()
|
||||
del diagram
|
||||
|
||||
gc.collect()
|
||||
gc.set_debug (gc.DEBUG_LEAK)
|
||||
|
||||
print "Uncollectable objects found:", gc.garbage
|
||||
|
||||
|
31
tests/test-treemodel.py
Normal file
31
tests/test-treemodel.py
Normal file
@ -0,0 +1,31 @@
|
||||
|
||||
import UML, gtk
|
||||
from tree.namespace import *
|
||||
|
||||
import CreateModel
|
||||
|
||||
window = gtk.Window()
|
||||
window.connect('destroy', lambda win: gtk.main_quit())
|
||||
window.set_title('TreeView test')
|
||||
window.set_default_size(250, 400)
|
||||
|
||||
scrolled_window = gtk.ScrolledWindow()
|
||||
scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
|
||||
window.add(scrolled_window)
|
||||
|
||||
tree_model = NamespaceModel(CreateModel.model)
|
||||
|
||||
tree_view = gtk.TreeView(tree_model)
|
||||
cell = gtk.CellRendererText()
|
||||
# the text in the column comes from column 0
|
||||
column = gtk.TreeViewColumn('', cell, text=0)
|
||||
tree_view.append_column(column)
|
||||
|
||||
scrolled_window.add(tree_view)
|
||||
window.show_all()
|
||||
|
||||
tree_model.dump()
|
||||
|
||||
gtk.main()
|
||||
|
||||
tree_model.dump()
|
8
tests/test-xml.py
Normal file
8
tests/test-xml.py
Normal file
@ -0,0 +1,8 @@
|
||||
#
|
||||
# A simple parser
|
||||
#
|
||||
|
||||
import UML
|
||||
|
||||
UML.load ('../gaphor/x.xml')
|
||||
UML.save ('aa.xml')
|
Loading…
x
Reference in New Issue
Block a user