NameSpaceRegistry.h

// NameSpaceRegistry.h
//
// Author David Barrett-Lennard
// (C)opyright Cedanet Pty Ltd 2008

@import "Object.h"
@import "SubString.h"

namespace ceda
{
$adt NameSpace;

///////////////////////////////////////////////////////////////////////////////////////////////////
/*
Namespace registries
--------------------

All the reflected interfaces, classes etc are registered in a namespace tree.  Each namespace node
registers all items in the one map, keyed by string.  This means that it is necessary for all items
to have unique names - even different types.  This restriction is not conventional in C++ (which for
example, within the same namespace allows for a class to have the same name as a global variable).
This restriction is made in the interests of easing cross language support, such as with the Python
language.
*/

///////////////////////////////////////////////////////////////////////////////////////////////////
// ENSType

$enum+ ENSType
{
    NST_Unknown,

    @for (rType in mRegistryTypes)
    {
        NST_@@rType,

    }
};

///////////////////////////////////////////////////////////////////////////////////////////////////
// NameSpaceElement

$struct+ NameSpaceElement
{
    // Define a default ctor so this type is not a POD, so dynamic invocation works correctly
    // when a NameSpaceElement is a return type of a function
    NameSpaceElement() { type = NST_Unknown; item = nullptr; }
    ~NameSpaceElement() { type = NST_Unknown; item = nullptr; }
    
    $ENSType GetType() const { return type; }
    
    @for (rType in mRegistryTypes)
    {
        @def R = Reflected@@rType
        $const R* As@@rType() const 
        { 
            cxAssert(type == NST_@@rType); 
            return (const R*) item; 
        }
    }
    
    /////////////// State ////////////////////////
    
    ENSType type;
    const void* item;
};

///////////////////////////////////////////////////////////////////////////////////////////////////
// NameSpaceElementIterator

/*
Allows for iteration through all the elements in a namespace.  Typically a client will write a 
loop using the iterator as follows.

    void Example(NameSpace* ns)
    {
        NameSpaceIterator* i = GetIterator(ns);
               
        while(!AtEnd(i))
        {
            NameSpaceElement nse = GetElement(i);
            SubString name = GetName(i);
            < process nse >            
            Next(i);
        }
        Close(i);
    }

It is important for the iterator to be closed (even if it is not actually used)
*/

$adt+ NameSpaceElementIterator
{
    bool AtEnd() const;
    void Next();
    SubString GetName() const;
    NameSpaceElement GetElement() const;
    void Close();
};


///////////////////////////////////////////////////////////////////////////////////////////////////
// ChildNameSpaceIterator

/*
Allows for iteration through all the child namespaces in a namespace.
*/

$adt+ ChildNameSpaceIterator
{
    bool AtEnd() const;
    void Next();
    SubString GetName() const;
    NameSpace* GetNameSpace() const;
    void Close();
};


///////////////////////////////////////////////////////////////////////////////////////////////////
// NameSpace

$adt+ NameSpace
{
    ConstStringZ GetName() const;
    
    // Look up an element with the given name
    NameSpaceElement FindElement(SubString name) const;

    // Look up element using a relative path. todo : do we search upwards?
    // Possible return values :
    //     NSE_OK
    //     NSE_COLON_EXPECTED
    //     NSE_IDENTIFIER_EXPECTED
    //     NSE_NAME_NOT_FOUND
    //     NSE_NOT_A_NAMESPACE
    ENameSpaceError FindElementWithRelativePath(SubString relativePath, NameSpaceElement& nse) const;

    // Allow for iteration over all elements in this namespace.  The returned iterator must be closed,
    // regardless of whether it is used or not.
    NameSpaceElementIterator* GetElementIterator() const;

    // Look up a child namespace with the given name.  Returns nullptr if not found.
    NameSpace* FindChildNameSpace(SubString name) const;
    
    ChildNameSpaceIterator* GetChildNameSpaceIterator() const;
};

$function+ NameSpace* GetTheRootNameSpace();

} // namespace ceda