Class Recursion

Folks,

I have started to play around a bit with classes and am building an XML data loader (yes, I could use XFiles or similar although not sure they actually support what I want to do?)

I want to load an XML file which has an unlimited set of child elements all of which are of the same type but form a hierarchy.

For example:

Etc.

So building a class but I am struggling how to do recursion in my class structure.

Item CLASS, TYPE
ItemName STRING(20)
Children QUEUE(Item) or QUEUE (&Item) don’t work
END

Also tried this but it doesn’t work as the QUEUE references an Item but it is bot declared yet and the item references the queue which is also not declared.

ChildrenQ QUEUE, TYPE
Child Item
END

Item CLASS,TYPE
ItemName String(20)
Children &ChildrenQ
END

Any thoughts?

This should work:

ChildrenQ QUEUE, TYPE
Child &Item
END
1 Like

Ironically I’m working on a new xFiles engine that does “tree parsing” (like the jFiles engine does) so yes, does what you would want it to do.
But as a learning exercise your approach is valuable to your learning curve.

When working with queues of NEW’d references
I find it extremely helpful to use my ctQueue class
to make it simple to ensure you are DISPOSEing everything correctly.

You just derive the .DEL() method, and take care of DISPOSE for ONE RECORD
Everything else is just taken care of for you.
When you dispose the class, the PARENT.DESTRUCT calls SELF.FREE() which in turn loops over the queue calling .DEL()

note: you don’t even have to check IF NOT (SELF.Q.Children &= NULL)
before disposing it, as DISPOSE( MyNullRef ) is safe - it just does nothing.

  INCLUDE('ctQueue.inc'),ONCE

gtItem      GROUP,TYPE
ItemName        STRING(42)
            ! whatever fields are of interest
            END 

gtItemTree  GROUP,TYPE
Item            LIKE(gtItem)
Children        &ctQ_ItemTree 
            END 

qtItemTree  QUEUE(gtItemTree),TYPE
            END 
          

ctQ_ItemTree CLASS(ctQueue),TYPE,MODULE('ctQ_ItemTree.clw'),LINK('ctQ_ItemTree.clw')
Q                 &qtItemTree
!------------------------
CONSTRUCT         PROCEDURE()
Del               PROCEDURE(),DERIVED 
AddItem           PROCEDURE(*gtItem xItem)    
AddChild          PROCEDURE(*gtItem xItem)


          END


  !for the 'ctQ_ItemTree.clw'

   MEMBER()
   INCLUDE('ctQ_ItemTree.inc'),ONCE
   MAP
   END

!=======================================
ctQ_ItemTree.CONSTRUCT      PROCEDURE()
   CODE
   SELF.Q     &= NEW qtItemTree
   CLEAR(SELF.Q)
   SELF.BaseQ &= SELF.Q 

!=======================================
ctQ_ItemTree.Del            PROCEDURE()!,DERIVED
   CODE
   DISPOSE(SELF.Q.Children)
   PARENT.Del()

!=======================================
ctQ_ItemTree.AddItem           PROCEDURE(*gtItem xItem)    
   CODE        
   SELF.Q.Item      = xItem
   SELF.Q.Children &= NULL
   ADD(SELF.Q)

!=======================================
ctQ_ItemTree.AddChild          PROCEDURE(*gtItem xItem)
   CODE 
   IF SELF.Q.Children &= NULL 
      SELF.Q.Children &= NEW ctQ_ItemTree 
      PUT(SELF.Q)
   END 
   SELF.Q.Children.AddItem( xItem )
2 Likes