[GME-commit] GMESRC/SDK/Scripts GMETraversor.js, NONE, 1.1 GMETraversor.py, NONE, 1.1 GMETraversor.vbs, NONE, 1.1
Log messages of CVS commits
gme-commit at list.isis.vanderbilt.edu
Tue Apr 15 14:10:52 CDT 2008
Update of /project/gme-repository/GMESRC/SDK/Scripts
In directory escher:/tmp/cvs-serv29995
Added Files:
GMETraversor.js GMETraversor.py GMETraversor.vbs
Log Message:
Traversing and filtering methods for JScript, VBScript.
Python has helper methods for Models, References, Sets and Connections.
CVS User: Zoltan Molnar, ISIS (zolmol)
--- NEW FILE: GMETraversor.js ---
//#################################################################################
//#
//# This file contains JScript methods for project-wide traversal or query.
//# See bottom of the file for main()
//#
//#################################################################################
//#
//# Visitation according to the following graph traversals algorithms
//# _________________________________________________________________
//#
//# Breadth First method: Levelled
//# Depth First methods: PreOrder, InOrder, PostOrder
//# method names: traverse_levelled, traverse_preorder, traverse_inorder, traverse_postorder
//#
//# Children can be sorted during traversal by:
//# NameSort, IDSort, GUIDSort, AspectHorizSort, AspectVerticSort, AspectAbsSort
//#
//#################################################################################
//#
//# Query for objects based on different criteria
//# _____________________________________________
//#
//# filter() method:
//# Usable to do a project wide search based on Name, Kind, Role, ObjectType, Level.
//# ObjectType is an enum as follows:
//# Model = 1,
//# Atom = 2,
//# Reference = 3,
//# Connection = 4,
//# Set = 5,
//# Folder = 6
//# Level (depth) can be a space-separated list of numbers or dash-separated number pairs: e.g: 1-2 5 7
//#
//# filterScoped() method:
//# Usable to do a scoped search based on Name, Kind, Role, ObjectType, Level.
//# Starts from a container, performs search down in its containment tree.
//#
//#################################################################################
var g, p;
g = gme
p = project
//#######################################################################
//# general helpers
//#######################################################################
function cout3( gme, mStr, mType)
{
gme.ConsoleMessage( mStr, mType);
}
function cout( mStr, mType)
{
g.ConsoleMessage( mStr, mType);
}
function fancy( mInStr)
{
var fancy = "<head><style type=\"text/css\">" +
"td.special{ background-color:aqua;font-size: 100%;margin-left: 20px;font-family: times, sans-serif, arial}" +
"</style>" +
"</head>" +
"<table><tr><td class=\"special\">" +
mInStr +
"</td></tr></table>";
return fancy;
}
function makeLink( o)
{
return '<a href=mga:' + o.ID + '">' + o.Name + '</a>';
}
function coll2array( in_collection)
{
var a = new Array();
for( var j = 1; j <= in_collection.Count; ++j) { // indices from 1 ... count
a.push( in_collection.Item(j));
}
return a;
}
//#############################################################
// OBJTYPE_REFERENCE (3)
//#############################################################
function refersTo( r)
{
var tgt = null;
if( r.ObjType == 3)
tgt = r.Referred;
return tgt;
}
function setReferTo( r, o)
{
if( r.ObjType == 3)
r.Referred = o;
}
function referredBy( o)
{
return coll2array( o.ReferencedBy);
}
//#############################################################
// OBJTYPE_SET (5)
//#############################################################
function isMemberIn( s, o)
{
return s.ObjType == 5 && s.GetIsMemberDisp( o);
}
function members( s)
{
var mems = null;
if( s.ObjType == 5)
mems = coll2array( s.Members);
return mems;
}
function memberOfSets( o)
{
return coll2array( o.MemberOfSets)
}
function addToSet( s, o)
{
if( s.ObjType == 5)
s.AddMember( o);
}
function remFromSet( s, o)
{
if( s.ObjType == 5)
s.RemoveMember( o);
}
//#############################################################
// OBJTYPE_CONNECTION
//#############################################################
function connect( m, srco, dsto, conn_mrole)
{
if( m.ObjType == 1) // Model
{
var c = m.CreateSimpleConn( conn_mrole, srco, dsto, null, null);
c.Name = conn_mrole.Name;
}
}
function connectThruRefChain( m, srco, dsto, src_ref_chain, dst_ref_chain, conn_mrole)
{
if( m.ObjType == 1) // Model
{
var c = m.CreateSimpleConn( conn_mrole, srco, dsto, src_ref_chain, dst_ref_chain, conn_mrole);
c.Name = conn_mrole.Name;
}
}
function partOfConns( o)
{
var conn_points = coll2array( o.PartOfConns);
var conns = new Array();
for( i = 0; i < conn_points.length; ++i)
{
conns.push( conn_points[i].Owner);
}
return conns;
}
//#############################################################
// OBJTYPE_MODEL (1)
//#############################################################
function metaRoleByName( m, kind_str)
{
if( m.ObjType == 1) // Model
{
return m.Meta.GetRoleByNameDisp( kind_str);
}
return null;
}
function metaRole( o)
{
// it seems we don't have access to meta.dll
// because it does return undefined
return o.MetaRole;
}
function metaName( o)
{
// it seems we don't have access to meta.dll
// because it does return undefined
return o.Meta.Name;
}
function newChild( m, kind_str)
{
var nch = null;
if( m.ObjType == 1)
{
var mrole = metaRoleByName( m, kind_str);
if( null != mrole)
{
nch = m.CreateChildObject( mrole);
nch.Name = mrole.Name;
}
}
return nch;
}
function childByName( m, name_str)
{
var ch = null;
if( m.ObjType == 1)
{
ch = m.GetChildFCODisp( name_str);
}
return ch;
}
function children( m)
{
if( m.ObjType == 1)
{
return coll2array( m.ChildFCOs);
}
return null;
}
function parent( o)
{
if( o.ParentFolder) return o.ParentFolder; // by checking ParentFolder first, we can use the same
else if( o.ParentModel) return o.ParentModel; // implementation for folders and fcos, since folders
else return null; // have too a method named ParentFolder
}
//#######################################################################
//# transaction handlers
//#######################################################################
function begin( the_project )
{
try {
var terr = the_project.BeginTransactionInNewTerr(); // only on GME8
// under GME7 please use this: g.oleit.BeginTransaction();
return terr;
} catch(err) {
g.oleit.BeginTransaction();
}
}
function commit( the_project, terr )
{
//g.oleit.CommitTransaction();
//if( terr != null) terr.Flush();
the_project.CommitTransaction();
if( terr != null) {
cout( "Territory destroyed.", 1);
terr.Destroy();
}
}
function abort( the_project, terr )
{
//g.oleit.AbortTransaction(); // from GME8 on
//if( terr != null) terr.Flush();
the_project.AbortTransaction();
if( terr != null) {
cout( "Territory destroyed.", 1);
terr.Destroy();
}
}
//#######################################################################
//# sorters
//#######################################################################
function sortNumber(a, b)
{
return a - b;
}
function IDSort( x, y)
{
if( x.ID < y.ID) r = -1;
else if( x.ID > y.ID) r = 1;
else r = 0;
return r;
}
function GUIDSort( x, y)
{
if( x.GetGUIDDisp() < y.GetGUIDDisp()) r = -1;
else if( x.GetGUIDDisp() > y.GetGUIDDisp()) r = 1;
else r = 0;
return r;
}
function NameSort( x, y)
{
if( x.Name < y.Name) r = -1;
else if( x.Name > y.Name) r = 1;
else r = 0;
return r;
}
//#######################################################################
//# aspect sorter helper
//#######################################################################
function getAspectPos( object, aspectname)
{
var pos_array = object.GetRegistryValueDisp( 'PartRegs/' + aspectname + '/Position').split(',');
var int_array = new Array( parseInt( pos_array[0]), parseInt( pos_array[1]));
return int_array;
}
//#######################################################################
//# aspect sorters
//#######################################################################
function AspectAbsSort( a, b)
{
/*Since objects can be placed in different aspects
It is required for these comparators to define which
aspect information are they going to consider.
And since not all objects reside in a model (some sit in
a folder), those will throw exceptions when are asked
about their position in a certain aspect.
*/
var aspectname = 'SignalFlowAspect';
try {
var a_pos = getAspectPos( a, aspectname);
var b_pos = getAspectPos( b, aspectname);
var ax = a_pos[0], ay = a_pos[1];
var bx = b_pos[0], by = b_pos[1];
absa = ax * ax + ay * ay;
absb = bx * bx + by * by;
r = 0
if( absa < absb) r = -1;
else if( absa > absb) r = 1;
else r = IDSort( a, b);
return r;
}
catch(err) {
cout( 'Exc during comparing ' + a.Name + ' with ' + b.Name + ' in AspectAbsSort, Message = ' + err.message, 1)
return IDSort( a, b)
}
}
function AspectHorizSort( a, b)
{
var aspectname = 'SignalFlowAspect';
try {
// get pairs of coordinates like "86, 86"
var a_pos = getAspectPos( a, aspectname);
var b_pos = getAspectPos( b, aspectname);
var ax = a_pos[0], ay = a_pos[1];
var bx = b_pos[0], by = b_pos[1];
r = 0;
if( ax < bx) r = -1;
else if(ax > bx) r = 1;
else if(ay < by) r = -1;
else if(ay > by) r = 1;
else r = 0;
return r;
}
catch(err) {
cout( 'Exc during comparing ' + a.Name + ' with ' + b.Name + ' in AspectHorizSort, Message = ' + err.message, 1);
return IDSort( a, b)
}
}
function AspectVerticSort( a, b)
{
var aspectname = 'SignalFlowAspect';
try {
// get pairs of coordinates like "86, 86"
var a_pos = getAspectPos( a, aspectname);
var b_pos = getAspectPos( b, aspectname);
var ax = a_pos[0], ay = a_pos[1];
var bx = b_pos[0], by = b_pos[1];
r = 0;
if( ay < by) r = -1;
else if(ay > by) r = 1;
else if(ax < bx) r = -1;
else if(ax > bx) r = 1;
else r = 0;
return r;
}
catch(err) {
cout( 'Exc during comparing ' + a.Name + ' with ' + b.Name + ' in AspectVerticSort, Message = ' + err.message, 1);
return IDSort( a, b);
}
}
function handle( o)
{
cout( o.GetGUIDDisp() + " ~ " + o.ID + " ~ " + o.Name, 1);
//cout( "Handled", 2);
}
//#######################################################################
//# traversal algorithms
//#######################################################################
function traverse_postorder( currento, comparator)
{
// 1st: traverse subtrees
if( currento.ObjType == 1 || currento.ObjType == 6) // children for Models and Folders
{
var to_visit = coll2array( currento.ChildObjects);
to_visit.sort( comparator); // sorted with comparator
for( var oi = 0; oi < to_visit.length; ++oi)
{
traverse_postorder( to_visit[oi], comparator);
}
}
// 2nd: handle current node
handle( currento);
}
function traverse_preorder( currento, comparator)
{
// 1st: handle current node
handle( currento);
// 2nd: traverse subtrees
if( currento.ObjType == 1 || currento.ObjType == 6) // children for Models and Folders
{
var to_visit = coll2array( currento.ChildObjects);
//to_visit.sort( comparator); // sorted with comparator
for( var oi = 0; oi < to_visit.length; ++oi)
{
traverse_preorder( to_visit[oi], comparator);
}
}
}
function traverse_inorder( currento, comparator)
{
var to_visit = new Array();
var separate_at = 0;
var i = 0;
if( currento.ObjType == 1 || currento.ObjType == 6) // children for Models and Folders
{
to_visit = coll2array( currento.ChildObjects);
to_visit.sort( comparator); // sorted with comparator
separate_at = Math.floor( (1 + to_visit.length)/2); // element at separate_at will be in right children
// leftchildren need visitation before the current node
// rightchildren need visitation after the current node
// we figure out an index (separate_at) to split the list in 2
}
// 1st: traverse left children
//cout( "Left: from " + i + " to " + separate_at, 2);
for( i = 0; i < separate_at; ++i) {
traverse_inorder( to_visit[i], comparator);
}
// 2nd: handle current node
handle( currento);
// 3rd: traverse right children
//cout( "Right: from " + separate_at + " to " + to_visit.length, 2);
for( i = separate_at; i < to_visit.length; ++i) {
traverse_inorder( to_visit[i], comparator);
}
}
function traverse_levelled( rootfolder, cmp) // ' aka BFT, Breadth First Traversal
{ // ' non-recursive implementation with a fifo queue
var to_visit = new Array( rootfolder);
var i = 0;
while( i < to_visit.length)
{
var o = to_visit[i];
handle( o);
if( o.ObjType == 1 || o.ObjType == 6)
{
// convert childobjects into an array
var to_append = coll2array( o.ChildObjects);
//
// sort children
to_append.sort( cmp);
//
// append to the queue
to_visit = to_visit.concat( to_append);
}
++i;
}
}
function filter( oname, okind, orole, otype, level)
{
var flt = p.CreateFilter();
flt.Name = oname;
flt.Kind = okind;
flt.Role = orole;
flt.ObjType = otype;
flt.Level = level;
var res = p.AllFCOs( flt); // filter used project-wide
cout( "Results follow: ", 1);
for( var i = 1; i <= res.Count; ++i)
cout( res.Item(i).Name + " -> " + makeLink( res.Item(i)), 1);
return coll2array( res);
}
function filterScoped( scopeObject, oname, okind, orole, otype, level)
{
var flt = p.CreateFilter();
flt.Name = oname;
flt.Kind = okind;
flt.Role = orole;
flt.ObjType = otype;
flt.Level = level;
var res = scopeObject.GetDescendantFCOs( flt); // filter used only down under container object in the hierarchy tree
cout( "Results follow: ", 1);
for( var i = 1; i <= res.Count; ++i)
cout( res.Item(i).Name + " -> " + makeLink( res.Item(i)), 1);
return coll2array( res);
}
function testFilter()
{
var r1;
r1 = filter( "", "Model", "", "", ""); // kind based filtering
r1 = filterScoped( it.MgaModel, "", "Model", "", "", "");
for( var k = 0; k < r1.length; ++k)
cout( makeLink(r1[k]), 3);
}
function traverse()
{
var algo_text = new Array();
algo_text[traverse_preorder ] = 'Preorder traversal'; // dictionary, will help showing to the user which traversal is used
algo_text[traverse_postorder ] = 'Postorder traversal';
algo_text[ traverse_inorder ] = 'Inorder traversal';
algo_text[ traverse_levelled ] = 'Levelled traversal (BFS)';
var sort_text = new Array();
sort_text[ AspectAbsSort ] = 'Absolute Position'; // dictionary, will help showing to the user which sort is used
sort_text[ AspectHorizSort ] = 'Horizontal Position';
sort_text[ AspectVerticSort ] = 'Vertical Position';
sort_text[ NameSort ] = 'Name';
sort_text[ GUIDSort ] = 'GUID';
sort_text[ IDSort ] = 'ID';
//#-----------------------------------
//# select the sort criteria here
//#-----------------------------------
var used_sort = AspectAbsSort;
//#-----------------------------------
//# select traversal algorithm here
//#-----------------------------------
var used_algo = traverse_levelled;
cout( fancy('Examining project \'' + p.RootFolder.Name + '\' with ' + algo_text[used_algo] + ' method, sorting children by their ' + sort_text[ used_sort] + '.'), 1)
cout( "Traversing " + p.RootFolder.Name, 1);
used_algo( p.RootFolder, used_sort);
// or simply:
//traverse_levelled( p.RootFolder, IDSort);
//traverse_preorder( p.RootFolder, IDSort);
//traverse_postorder(p.RootFolder, IDSort);
//traverse_inorder( p.RootFolder, IDSort);
}
//#######################################################################
//# main
cout( fancy("--Greetings!--"), 1);
cout( "Hello World, this is JScript here!", 1);
var terr = begin(p);
try {
traverse();
//testFilter();
commit( p, terr);
}
catch(err) {
cout( "Exception [" + err.message + "]. Transaction will abort.", 3);
abort( p, terr);
}
cout( "Bye, bye!", 1);
--- NEW FILE: GMETraversor.vbs ---
'//#################################################################################
'//#
'//# This file contains VBScript methods for project-wide traversal or query.
'//# See bottom of the file for main()
'//#
'//#################################################################################
'//#
'//# Visitation according to the following graph traversals algorithms
'//# _________________________________________________________________
'//#
'//# Breadth First method: Levelled
'//# Depth First methods: PreOrder, InOrder, PostOrder
'//# method names: traverse_levelled, traverse_preorder, traverse_inorder, traverse_postorder
'//#
'//# Children can be sorted during traversal by:
'//# NameSort, IDSort, GUIDSort, AspectHorizSort, AspectVerticSort, AspectAbsSort
'//#
'//#################################################################################
'//#
'//# Query for objects based on different criteria
'//# _____________________________________________
'//#
'//# filter() method:
'//# Usable to do a project wide search based on Name, Kind, Role, ObjectType, Level.
'//# ObjectType is an enum as follows:
'//# Model = 1,
'//# Atom = 2,
'//# Reference = 3,
'//# Connection = 4,
'//# Set = 5,
'//# Folder = 6
'//# Level (depth) can be a space-separated list of numbers or dash-separated number pairs: e.g: 1-2 5 7
'//#
'//# filterScoped() method:
'//# Usable to do a scoped search based on Name, Kind, Role, ObjectType, Level.
'//# Starts from a container, performs search down in its containment tree.
'//#
'//#################################################################################
Set g = gme
Set p = project
Sub cout3( gme, mStr, mType)
gme.ConsoleMessage mStr, mType
End Sub
Sub cout( mStr, mType)
g.ConsoleMessage mStr, mType
End Sub
Function fancy( mInStr)
fancy = "<head><style type=""text/css"">" &_
"td.special{ background-color:aqua;font-size: 100%;margin-left: 20px;font-family: times, sans-serif, arial}" &_
"</style>" &_
"</head>" &_
"<table><tr><td class=""special"">" &_
mInStr &_
"</td></tr></table>"
End Function
Function makeLink( o)
makeLink = "<a href=mga:" & o.ID & """>" & o.Name & "</a>"
End Function
'********************************************************************
Sub begin( the_project )
the_project.BeginTransaction Nothing
End Sub
Sub commit( the_project )
the_project.CommitTransaction
End Sub
Sub abort( the_project )
the_project.AbortTransaction
End Sub
'********************************************************************
Sub handle( o)
msg = o.ID & " ~ " & o.GetGUIDDisp() & " ~ " & o.Name
cout msg, 1
End Sub
'********************************************************************
Sub traverse_preorder( currento)
' 1st: handle current node
Call handle( currento)
' 2nd: traverse subtrees
If currento.ObjType = 1 or currento.ObjType = 6 Then ' children for Models and Folders
Set to_visit = currento.ChildObjects
'Call sortMyArray( to_visit) ' sorted with comparator
For k = 1 to to_visit.Count
traverse_preorder( to_visit(k))
Next
End If
End Sub
Sub traverse_postorder( currento)
' 1st: traverse subtrees
If currento.ObjType = 1 or currento.ObjType = 6 Then ' children for Models and Folders
Set to_visit = currento.ChildObjects
'Call sortMyArray( to_visit) ' sorted with comparator
For k = 1 to to_visit.Count
traverse_postorder( to_visit(k))
Next
End If
' 2nd: handle current node
Call handle( currento)
End Sub
Sub traverse_inorder( currento)
current_len = 0
Dim to_visit()
If currento.ObjType = 1 or currento.ObjType = 6 Then ' children for Models and Folders
Set children = currento.ChildObjects
ReDim Preserve to_visit( children.Count)
' append the children to the to_visit list
For k = 1 to children.Count
Set to_visit(current_len) = children(k)
current_len = current_len + 1
Next
'Call sortMyArray( to_visit) ' sorted with comparator
End If
separate_at = current_len\2 ' trunc logic: [0..2], current len = 3, separate at = 1
' elem at index separate_at is in right children
' 1st: traverse left children
k = 0
While k < separate_at
traverse_inorder( to_visit(k))
k = k + 1
Wend
' 2nd: handle current node
Call handle( currento)
' 3rd: traverse right children
While k < current_len
traverse_inorder( to_visit(k))
k = k + 1
Wend
End Sub
Sub traverse_levelled( rootfolder) ' aka BFT, Breadth First Traversal, with a FIFO queue logic
Dim to_visit()
current_len = 1
ReDim to_visit( current_len)
Set to_visit(0) = rootfolder
i = LBound(to_visit)
While i < current_len
Set o = to_visit(i)
Call handle( o) ' handle the currently selected object
'
If o.ObjType = 1 or o.ObjType = 6 Then
Set children = o.ChildObjects
' cout "Combined size will be : " & current_len + children.Count, 1
ReDim Preserve to_visit( current_len + children.Count)
' append the children to the to_visit list
For k = 1 to children.Count
Set to_visit(current_len) = children(k)
current_len = current_len + 1
Next
End If
i = i + 1
Wend
End Sub
'********************************************************************
Function filter( fname, fkind, frole, otype, level)
Set flt = p.CreateFilter()
cout flt.Project.RootFolder.Name, 3
flt.Name = fname
flt.Kind = fkind
flt.Role = frole
flt.ObjType = otype
flt.Level = level
Set res = p.AllFCOs( flt) ' filter used project-wide
cout "Results follow: ", 1
For i = 1 to res.Count
cout res.Item(i).Name & " -> " & makeLink( res.Item(i)), 1
Next
Set filter = res
End Function
Function filterScoped( object, fname, fkind, frole, otype, level)
Set flt = p.CreateFilter()
flt.Name = fname
flt.Kind = fkind
flt.Role = frole
flt.ObjType = otype
flt.Level = level
Set res = object.GetDescendantFCOs( flt) ' filter used only down below container object in the hierarchy tree
cout "Results follow: ", 1
For i = 1 to res.Count
cout res.Item(i).Name & " -> " & makeLink( res.Item(i)), 1
Next
Set filterScoped = res
End Function
'********************************************************************
Sub test1( m)
'Call filter( "", "ModelProxy", "", "", "")
'Call filterScoped( it.MgaModel, "", "ModelProxy", "", "", "")
Set fres1 = filter( "", "Model", "", "", "")
Set fres2 = filterScoped( it.MgaModel, "", "Model", "", "", "")
cout "Filtered results follow", 2
For i = 1 to fres2.Count
cout makeLink( fres2.Item(i)), 2
Next
End Sub
'********************************************************************
'* main
On Error Resume Next ' turn off default error handler but only on this level (not in subs)
' On Error GoTo 0 ' turn on default error handler
' The saying is, that it works like SEH (Structured Exception Handling)
' Errors are propagated up in the stack, until somebody handles it
' in our case, somebody has a 'Resume Next' cmd and handles it
cout fancy("--Greetings!--"), 1
cout "Hello World, this is VBScript here!", 1
Call begin( p)
cout p.RootFolder.Name, 1
'Call traverse_levelled( p.RootFolder)
'Call traverse_postorder( p.RootFolder)
'Call traverse_preorder( p.RootFolder)
'Call traverse_inorder( p.RootFolder)
test1 it.mgamodel
Call commit( p)
If Err.Number <> 0 Then ' "Exception handling"
Call abort( p)
End If
--- NEW FILE: GMETraversor.py ---
#################################################################################
#
# This file contains Python methods for project-wide traversal or query.
# In addition it has helper methods for Model, Set, Reference objects.
# See bottom of the file for main()
#
#################################################################################
#
# Visitation according to the following graph traversals algorithms
# _________________________________________________________________
#
# Breath First method: Levelled
# Depth First methods: PreOrder, InOrder, PostOrder
# method names: traverse_levelled, traverse_preorder, traverse_inorder, traverse_postorder
#
# Children can be sorted during each traversal by:
# NameSort, IDSort, GUIDSort, AspectHorizSort, AspectVerticSort, AspectAbsSort
#
#
#################################################################################
#
# Query for objects based on different criteria
# _____________________________________________
#
#
# filter() method:
# Usable to do a project wide search based on Name, Kind, Role, ObjectType, Level.
# ObjectType is an enum as follows:
# Model = 1,
# Atom = 2,
# Reference = 3,
# Connection = 4,
# Set = 5,
# Folder = 6
# Level (depth) can be a space-separated list of numbers or dash-separated number pairs: e.g: 1-2 5 7
#
# filterScoped() method:
# Usable to do a scoped search based on Name, Kind, Role, ObjectType, Level.
# Starts from a container, performs search down in its containment tree.
#
#################################################################################
#
# Helper methods for different object types useable as follows
# ____________________________________________________________
#
# Models:
# MetaRoleObject = metaRoleByName( Model, KindString)
# MetaRoleObject = metaRole( Object)
# MetaNameString = metaName( Object)
# NewChild = newChild( Model, KindString)
# ClonedObject = clone( WhereModel, WhichObject)
# delObj( Object)
# ChildObject = childByName( Model, Name)
# ListOfChildren = childrenByKind( Model, KindString)
# ListOfChildren = children( Model)
# Parent = parent( Object)
# Connections:
# NewConn = connect( Model, Source, Destination, ConnectionMetaRole)
# NewConn = connectThruRefChain( Model, Source, Destination, SourceReferenceChain, DestinationReferenceChain, ConnectionMetaRole)
# ListOfConns = partOfConns( Object)
# References:
# Tgt = getReferred( Ref)
# setReferred( Ref, Tgt)
# clearReference( Ref)
# ListOfRefs = referredBy( Tgt)
# Sets:
# T/F = isMemberIn( Set, Member)
# ListOfMembers = members( Set)
# ListOfSets = memberOfSets( Member)
# addToSet( Set, Member)
# remFromSet( Set, Member)
#
#################################################################################
import win32com.client
p = project # pre-existing variable defined, implements IMgaProject interface (see Interfaces/Mga.idl)
g = gme # pre-existing variable defined, implements IGMEOLEApp interface (see Interfaces/GME.idl)
#############################################################
## OBJTYPE_REFERENCE (3)
#############################################################
def getReferred( r):
if( r and r.ObjType == 3):
return r.Referred
return
def setReferred( r, o):
if( r and r.ObjType == 3):
r.Referred = o
return
def clearReference( r):
""" Clears a reference's Referred property.
r.Referred = 0 does not work unfortunately
"""
if r.ObjType == 3:
try:
r.ClearRef() # from GME8 on
except:
cout( "Exception while clearing reference: " + r.Name + "!", 3)
raise
return
def referredBy( o):
return list( o.ReferencedBy)
#############################################################
## OBJTYPE_SET (5)
#############################################################
def isMemberIn( s, o):
# GetIsMemberDisp is not giving back correct results:
#return s.ObjType == 5 and s.GetIsMemberDisp( o)
# that's why an alternative implementation is used:
#s.GetIsMemberDisp( o)
return o in members(s)
def members( s):
if( s and s.ObjType == 5):
return list( s.Members)
return
def memberOfSets( o):
return list(o.MemberOfSets)
def addToSet( s, o):
if( s and s.ObjType == 5):
s.AddMember( o)
def remFromSet( s, o):
if( s and s.ObjType == 5):
s.RemoveMember( o)
#############################################################
## OBJTYPE_CONNECTION
#############################################################
def connect( m, srco, dsto, conn_mrole):
if( m.ObjType == 1): # Model
c = m.CreateSimpleConn( conn_mrole, srco, dsto, None, None)
c.Name = conn_mrole.Name
return c
return
def connectThruRefChain( m, srco, dsto, src_ref_chain, dst_ref_chain, conn_mrole):
if( m.ObjType == 1): # Model
c = m.CreateSimpleConn( conn_mrole, srco, dsto, src_ref_chain, dst_ref_chain)
c.Name = conn_mrole.Name
return c
return
def partOfConns( o):
conn_points = list( o.PartOfConns)
conns = []
for i in range(0, len(conn_points)):
conns.append( conn_points[i].Owner)
return conns
#############################################################
## OBJTYPE_MODEL (1)
#############################################################
def metaRoleByName( m, kind_str):
if m.ObjType == 1: # Model
return m.Meta.GetRoleByNameDisp( kind_str)
#return null
def metaRole( o):
return o.MetaRole
def metaName( o):
return o.Meta.Name
def newChild( m, kind_str):
if m.ObjType == 1:
mrole = metaRoleByName( m, kind_str)
if mrole:
nch = m.CreateChildObject( mrole)
nch.Name = mrole.Name
return nch
return
def clone( m, orig):
""" Clones orig object into m (model or folder).
If orig is a folder, m needs to a folder too.
"""
if m.ObjType not in (1, 6): return
if not orig: return
if m.ObjType == 6: # Target is a Folder
if orig.ObjType == 6: cloned = m.CopyFolderDisp( orig) # Orig is Folder too
else: cloned = m.CopyFCODisp( orig) # Orig is FCO
elif m.ObjType == 1:
cloned = m.CopyFCODisp( orig, metaRole( orig)) # Target is Model, Orig is FCO
if cloned:
cloned.Name = "Cloned" + orig.Name
return cloned
def delObj( o):
""" Deletes an object o from its parent
"""
if not o: return
try:
o.DestroyObject()
except:
cout( "Could not remove object '" + o.Name + "'!")
raise # raise again the same exception
return
def childByName( m, name_str):
if m.ObjType == 1:
return m.GetChildFCODisp( name_str)
return
def childrenByKind( m, kind_str):
if m.ObjType == 1:
return list(m.GetChildrenOfKind( kind_str))
return
def children( m):
if m.ObjType == 1:
return list(m.ChildFCOs)
return
def parent( o):
if o.ParentFolder : return o.ParentFolder # by checking ParentFolder first, we can use the same
elif o.ObjType != 6 and o.ParentModel : return o.ParentModel # implementation for folders and fcos, since folders
# have too a method named ParentFolder
return
#######################################################################
# filter on project
#######################################################################
def filter( name = "", kind = "", role = "", otype = "", level = ""):
flt = p.CreateFilter()
flt.Name = name
flt.Kind = kind
flt.Role = role
flt.ObjType = otype
flt.Level = level
res = p.AllFCOs( flt) # filter used project-wide
cout( "Results follow: ", 1)
for i in range(1, res.Count + 1):
cout( res.Item(i).Name + " -> " + makeLink( res.Item(i)), 1)
return list(res)
def filterScoped( object, name = "", kind = "", role = "", otype = "", level = ""):
flt = p.CreateFilter()
flt.Name = name
flt.Kind = kind
flt.Role = role
flt.ObjType = otype
flt.Level = level
res = object.GetDescendantFCOs( flt) # filter used only down below container object in the hierarchy tree
cout( "Results follow: ", 1)
for i in range(1, res.Count + 1):
cout( res.Item(i).Name, 1)
return list(res)
#######################################################################
# transaction handlers
#######################################################################
def begin( p_project ):
# alt1: return project.BeginTransactionInNewTerr() # only in GME8
# alt2: project.BeginTransaction( project.CreateTerritory( None, None, None))
# or more verbosely:
terr = p_project.CreateTerritory( None, None, None)
p_project.BeginTransaction( terr)
return terr
def commit( p_project, p_terr ):
p_project.CommitTransaction()
if p_terr:
p_terr.Destroy()
def abort( p_project, p_terr ):
p_project.AbortTransaction()
if p_terr:
p_terr.Destroy()
#######################################################################
# general helpers
#######################################################################
def cout3( _gme, _msg, _type = 1):
_gme.ConsoleMessage( _msg, _type)
def cout( _msg, _type = 1):
gme.ConsoleMessage( _msg, _type)
def fancy( _inStr):
""" Encloses incoming string into a html table cell, so
that it will be shown with custom fgcolor and bgcolor
"""
return '<head><style type="text/css">td.special{ background-color:aqua;font-size: 100%;margin-left: 20px;font-family: times, sans-serif, arial}</style></head><table><tr><td class="special">' + _inStr + '</td></tr></table>'
def fancy2( _inStr):
return '<p style="background-color: yellow">' + _inStr + '</p>'
def makeLink( o):
return '<a href=mga:' + o.ID + '">' + o.Name + '</a>'
#######################################################################
# sorters
#######################################################################
def IDSort( x, y):
if( x.ID < y.ID): r = -1
elif( x.ID > y.ID): r = 1
else: r = 0
return r
def GUIDSort( x, y):
if( x.GetGUIDDisp() < y.GetGUIDDisp()): r = -1
elif( x.GetGUIDDisp() > y.GetGUIDDisp()): r = 1
else: r = 0
return r
def NameSort( x, y):
if( x.Name < y.Name): r = -1
elif( x.Name > y.Name): r = 1
else: r = 0
return r
#######################################################################
# aspect sorter helper
#######################################################################
def getAspectPos( object, aspectname):
str_ax,str_ay = object.GetRegistryValueDisp( 'PartRegs/' + aspectname + '/Position').split(',')
return int(str_ax), int(str_ay)
#######################################################################
# aspect sorters
#######################################################################
def AspectAbsSort( a, b):
""" Since objects can be placed in different aspects
It is required for these comparators to define which
aspect information are they going to consider.
And since not all objects reside in a model (some sit in
a folder), those will throw exceptions when are asked
about their position in a certain aspect.
"""
aspectname = 'SignalFlowAspect'
try:
ax, ay = getAspectPos( a, aspectname)
bx, by = getAspectPos( b, aspectname)
absa = ax * ax + ay * ay;
absb = bx * bx + by * by;
r = 0
if( absa < absb) : r = -1
elif( absa > absb) : r = 1
else : r = IDSort( a, b)
return r
except:
cout( 'Exc during comparing ' + a.Name + ' with ' + b.Name + ' in AspectAbsSort', 1)
return IDSort( a, b)
def AspectHorizSort( a, b):
aspectname = 'SignalFlowAspect'
try:
# get pairs of coordinates like "86, 86"
ax, ay = getAspectPos( a, aspectname)
bx, by = getAspectPos( b, aspectname)
r = 0
if( ax < bx) : r = -1
elif(ax > bx) : r = 1
elif(ay < by) : r = -1
elif(ay > by) : r = 1
else : r = 0
return r
except:
cout( 'Exc during comparing ' + a.Name + ' with ' + b.Name + ' in AspectHorizSort', 1)
return IDSort( a, b)
def AspectVerticSort( a, b, aspectname = 'SignalFlowAspect'):
try:
# get pairs of coordinates like "86, 86"
ax, ay = getAspectPos( a, aspectname)
bx, by = getAspectPos( b, aspectname)
r = 0
if( ay < by) : r = -1
elif(ay > by) : r = 1
elif(ax < bx) : r = -1
elif(ax > bx) : r = 1
else : r = 0
return r
except:
cout( 'Exc during comparing ' + a.Name + ' with ' + b.Name + ' in AspectVerticSort', 1)
return IDSort( a, b)
#######################################################################
# a generic handler for a visited object (fco or folder)
#######################################################################
def handle( _gme, _obj):
try:
cout( _obj.ID + ' ~ ' + _obj.GetGUIDDisp() + ' ~ ' + _obj.Name)
finally:
pass
#
# or dump data to a file:
#
#f = open( 'c:\\visitation.txt', 'a')
#try:
# f.write( _obj.ID + '~' + _obj.GetGUIDDisp() + '~' + _obj.Name + '\n')
#finally:
# f.close()
return
#######################################################################
# traversal algorithms
#######################################################################
def traverse_postorder( _gme, _current, _comparator):
to_visit = [] # a list (!tuple)
if _current.ObjType in (1, 6): # children for Models and Folders
to_visit.extend( _current.ChildObjects) # remains a list
to_visit.sort( cmp = _comparator) # which can sort
# 1st: traverse subtrees
for o in to_visit:
traverse_postorder( _gme, o, _comparator)
# 2nd: handle current node
handle( _gme, _current)
return
def traverse_preorder( _gme, _current, _comparator):
to_visit = [] # a list (!tuple)
if _current.ObjType in (1, 6): # children for Models and Folders
to_visit.extend( _current.ChildObjects) # remains a list
to_visit.sort( cmp = _comparator) # which can sort
# 1st: handle current node
handle( _gme, _current)
# 2nd: traverse subtrees
for o in to_visit:
traverse_preorder( _gme, o, _comparator)
return
def traverse_inorder( _gme, _current, _comparator):
to_visit = [] # a list (!tuple)
if _current.ObjType in (1, 6): # children for Models and Folders
to_visit.extend( _current.ChildObjects) # remains a list
to_visit.sort( cmp = _comparator) # which can sort
separate_at = (1 + len(to_visit))/2 # element at separate_at will be in right children
# leftchildren need visitation before the current node
# rightchildren need visitation after the current node
# we figure out an index (separate_at) to split the list in 2
# 1st: traverse left children
for i in range( 0, separate_at):
traverse_inorder( _gme, to_visit[i], _comparator)
# 2nd: handle current node
handle( _gme, _current)
# 3rd: traverse right children
for i in range( separate_at, len(to_visit)):
traverse_inorder( _gme, to_visit[i], _comparator)
return
def traverse_levelled( _gme, _rootfolder, _comparator): # aka BFT, Breadth First Traversal with a fifo queue
to_visit = [] # a list (!tuple)
to_visit.append( _rootfolder)
while len( to_visit) > 0:
o = to_visit.pop(0) # pops the first element from the queue
handle( _gme, o) # handle current node
if o.ObjType in (1, 6): # children for Models and Folders
children = list( o.ChildObjects) # only a list
children.sort( cmp = _comparator) # can be sorted
to_visit.extend( children) # append children to the fifo queue
return
def traverse_invoker( _methodFunc, _gme, _rootFolder, _comparatorFunc):
_methodFunc( _gme, _rootFolder, _comparatorFunc) # simple call the _methodFunc with the provided parameters
return
#######################################################################
#
# Visitation according to the following graph traversals algorithms
#
#
# Depth First methods: PreOrder, InOrder, PostOrder
# Breath First method: Levelled
#
# Children can be sorted during each traversal by:
# Name : NameSort
# ObjectID (as strings) : IDSort
# GUID (as strings, as in the displayed format) : GUIDSort
# Horizontal Position (in a certain aspect) : AspectHorizSort
# Vertical Position (in a certain aspect) : AspectVerticSort
# Absolute Distance from (0,0) (in a certain aspect) : AspectAbsSort
#
def traverse():
algo_text={ traverse_preorder : 'Preorder traversal' # dictionary, will help showing to the user which traversal is used
, traverse_postorder : 'Postorder traversal'
, traverse_inorder : 'Inorder traversal'
, traverse_levelled : 'Levelled traversal (BFS)'}
sort_text={ AspectAbsSort : 'Absolute Position' # dictionary, will help showing to the user which sort is used
, AspectHorizSort : 'Horizontal Position'
, AspectVerticSort : 'Vertical Position'
, NameSort : 'Name'
, GUIDSort : 'GUID'
, IDSort : 'ID'}
#-----------------------------------
# select the sort criteria here
#-----------------------------------
used_sort = NameSort
#-----------------------------------
# select traversal algorithm here
#-----------------------------------
used_algo = traverse_levelled
cout( fancy('Examining project \'' + p.RootFolder.Name + '\' with ' + algo_text[used_algo] + ' method, sorting children by their ' + sort_text[ used_sort] + '.'), 1)
#-----------------------------------
traverse_invoker( used_algo, g, p.RootFolder, used_sort) # use this generic invoker or ...
#-----------------------------------
#traverse_preorder ( g, p.RootFolder, used_sort) # or any of these direct invokations
#traverse_postorder( g, p.RootFolder, used_sort)
#traverse_inorder ( g, p.RootFolder, used_sort)
#traverse_levelled ( g, p.RootFolder, used_sort)
##############################################################################################
#
# Variables existing when the script is executed are
# -----------------------------------------------------
#
# project : the project variable (see Interfaces/Mga.idl)
# gme : the main application window (see Interfaces/GME.idl for IGMEOLEApp)
# it : the actively shown model (view) (see Interfaces/GME.idl for IGMEOLEIt)
#
###############################################################################################
# main() begins
#
cout( 'Hello World, this is Python here!', 1)
terr = begin( p) # begin transaction (strictly needed to perform r/w operations on a IMgaProject)
try:
traverse() # do a traversal
commit(p, terr) # commit transaction (strictly needed to return the project in a consistent mode)
except:
cout( 'Need to abort', 2) # 2 means WARNING (yellow)
abort(p, terr) # abort transaction if something went wrong
cout( 'End of Script', 1)
More information about the GME-commit
mailing list