<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">###############################################################################
#
#   Class: NaturalDocs::ClassHierarchy::Class
#
###############################################################################
#
#   An object that stores information about a class in the hierarchy.  It does not store its &lt;SymbolString&gt;; it assumes that it will
#   be stored in a hashref where the key is the &lt;SymbolString&gt;.
#
###############################################################################

# This file is part of Natural Docs, which is Copyright (C) 2003-2008 Greg Valure
# Natural Docs is licensed under the GPL

use strict;
use integer;

package NaturalDocs::ClassHierarchy::Class;


#
#   Constants: Members
#
#   The class is implemented as a blessed arrayref.  The keys are the constants below.
#
#   DEFINITIONS - An existence hashref of all the &lt;FileNames&gt; which define this class.  Undef if none.
#   PARENTS - An existence hashref of the &lt;SymbolStrings&gt; of all the parents this class has.
#   CHILDREN - An existence hashref of the &lt;SymbolStrings&gt; of all the children this class has.
#   PARENT_REFERENCES - A hashref of the parent &lt;ReferenceStrings&gt; this class has.  The keys are the &lt;ReferenceStrings&gt;,
#                                      and the values are existence hashrefs of all the &lt;FileNames&gt; that define them.  Undef if none.
#
use NaturalDocs::DefineMembers 'DEFINITIONS', 'PARENTS', 'CHILDREN', 'PARENT_REFERENCES';
# Dependency: New() depends on the order of these constants, as well as the class not being derived from any other.


###############################################################################
# Group: Modification Functions


#
#   Function: New
#
#   Creates and returns a new class.
#
sub New
    {
    # Dependency: This function depends on the order of the constants, as well as the class not being derived from any other.
    my ($package, $definitionFile) = @_;

    my $object = [ undef, undef, undef, undef ];
    bless $object, $package;

    return $object;
    };


#
#   Function: AddDefinition
#
#   Adds a rew definition of this class and returns if that was the first definition.
#
#   Parameters:
#
#       file - The &lt;FileName&gt; the definition appears in.
#
#   Returns:
#
#       Whether this was the first definition of this class.
#
sub AddDefinition #(file)
    {
    my ($self, $file) = @_;

    my $wasFirst;

    if (!defined $self-&gt;[DEFINITIONS])
        {
        $self-&gt;[DEFINITIONS] = { };
        $wasFirst = 1;
        };

    $self-&gt;[DEFINITIONS]-&gt;{$file} = 1;

    return $wasFirst;
    };


#
#   Function: DeleteDefinition
#
#   Removes the definition of this class and returns if there are no more definitions.  Note that if there are no more
#   definitions, you may still want to keep the object around if &lt;HasChildren()&gt; returns true.
#
#   Parameters:
#
#       file - The &lt;FileName&gt; the definition appears in.
#
#   Returns:
#
#       Whether this deleted the last definition of this class.
#
sub DeleteDefinition #(file)
    {
    my ($self, $file) = @_;

    if (defined $self-&gt;[DEFINITIONS])
        {
        delete $self-&gt;[DEFINITIONS]-&gt;{$file};

        if (!scalar keys %{$self-&gt;[DEFINITIONS]})
            {
            $self-&gt;[DEFINITIONS] = undef;
            return 1;
            };
        };

    return undef;
    };


#
#   Function: AddParentReference
#
#   Adds a parent reference to the class and return whether it resulted in a new parent class.
#
#   Parameters:
#
#       reference - The &lt;ReferenceString&gt; used to determine the parent.
#       file - The &lt;FileName&gt; the parent reference is in.
#       referenceTranslations - A hashref of what each reference currently resolves to.  The keys are the
#                                         &lt;ReferenceStrings&gt; and the values are class &lt;SymbolStrings&gt;.  It should include an entry for
#                                         the reference parameter above.
#
#   Returns:
#
#       If the reference adds a new parent, it will return that parent's &lt;SymbolString&gt;.  Otherwise it will return undef.
#
sub AddParentReference #(reference, file, referenceTranslations)
    {
    my ($self, $reference, $file, $referenceTranslations) = @_;

    if (!defined $self-&gt;[PARENT_REFERENCES])
        {  $self-&gt;[PARENT_REFERENCES] = { };  };
    if (!defined $self-&gt;[PARENTS])
        {  $self-&gt;[PARENTS] = { };  };


    if (!exists $self-&gt;[PARENT_REFERENCES]-&gt;{$reference})
        {
        $self-&gt;[PARENT_REFERENCES]-&gt;{$reference} = { $file =&gt; 1 };

        my $symbol = $referenceTranslations-&gt;{$reference};

        if (!exists $self-&gt;[PARENTS]-&gt;{$symbol})
            {
            $self-&gt;[PARENTS]-&gt;{$symbol} = 1;
            return $symbol;
            }
        else
            {  return undef;  };
        }
    else
        {
        $self-&gt;[PARENT_REFERENCES]-&gt;{$reference}-&gt;{$file} = 1;
        return undef;
        };
    };

#
#   Function: DeleteParentReference
#
#   Deletes a parent reference from the class and return whether it resulted in a loss of a parent class.
#
#   Parameters:
#
#       reference - The &lt;ReferenceString&gt; used to determine the parent.
#       file - The &lt;FileName&gt; the parent declaration is in.
#       referenceTranslations - A hashref of what each reference currently resolves to.  The keys are the
#                                         &lt;ReferenceStrings&gt; and the values are class &lt;SymbolStrings&gt;.  It should include an entry for
#                                         the reference parameter above.
#
#   Returns:
#
#       If this causes a parent class to be lost, it will return that parent's &lt;SymbolString&gt;.  Otherwise it will return undef.
#
sub DeleteParentReference #(reference, file, referenceTranslations)
    {
    my ($self, $reference, $file, $referenceTranslations) = @_;

    if (defined $self-&gt;[PARENT_REFERENCES] &amp;&amp; exists $self-&gt;[PARENT_REFERENCES]-&gt;{$reference} &amp;&amp;
        exists $self-&gt;[PARENT_REFERENCES]-&gt;{$reference}-&gt;{$file})
        {
        delete $self-&gt;[PARENT_REFERENCES]-&gt;{$reference}-&gt;{$file};

        # Quit if there are other definitions of this reference.
        if (scalar keys %{$self-&gt;[PARENT_REFERENCES]-&gt;{$reference}})
            {  return undef;  };

        delete $self-&gt;[PARENT_REFERENCES]-&gt;{$reference};

        if (!scalar keys %{$self-&gt;[PARENT_REFERENCES]})
            {  $self-&gt;[PARENT_REFERENCES] = undef;  };

        my $parent = $referenceTranslations-&gt;{$reference};

        # Check if any other references resolve to the same parent.
        if (defined $self-&gt;[PARENT_REFERENCES])
            {
            foreach my $parentReference (keys %{$self-&gt;[PARENT_REFERENCES]})
                {
                if ($referenceTranslations-&gt;{$parentReference} eq $parent)
                    {  return undef;  };
                };
            };

        # If we got this far, no other parent references resolve to this symbol.

        delete $self-&gt;[PARENTS]-&gt;{$parent};

        if (!scalar keys %{$self-&gt;[PARENTS]})
            {  $self-&gt;[PARENTS] = undef;  };

        return $parent;
        }
    else
        {  return undef;  };
    };


#
#   Function: AddChild
#   Adds a child &lt;SymbolString&gt; to the class.  Unlike &lt;AddParentReference()&gt;, this does not keep track of anything other than
#   whether it has it or not.
#
#   Parameters:
#
#       child - The &lt;SymbolString&gt; to add.
#
sub AddChild #(child)
    {
    my ($self, $child) = @_;

    if (!defined $self-&gt;[CHILDREN])
        {  $self-&gt;[CHILDREN] = { };  };

    $self-&gt;[CHILDREN]-&gt;{$child} = 1;
    };

#
#   Function: DeleteChild
#   Deletes a child &lt;SymbolString&gt; from the class.  Unlike &lt;DeleteParentReference()&gt;, this does not keep track of anything other
#   than whether it has it or not.
#
#   Parameters:
#
#       child - The &lt;SymbolString&gt; to delete.
#
sub DeleteChild #(child)
    {
    my ($self, $child) = @_;

    if (defined $self-&gt;[CHILDREN])
        {
        delete $self-&gt;[CHILDREN]-&gt;{$child};

        if (!scalar keys %{$self-&gt;[CHILDREN]})
            {  $self-&gt;[CHILDREN] = undef;  };
        };
    };



###############################################################################
# Group: Information Functions

#
#   Function: Definitions
#   Returns an array of the &lt;FileNames&gt; that define this class, or an empty array if none.
#
sub Definitions
    {
    my ($self) = @_;

    if (defined $self-&gt;[DEFINITIONS])
        {  return keys %{$self-&gt;[DEFINITIONS]};  }
    else
        {  return ( );  };
    };

#
#   Function: IsDefinedIn
#   Returns whether the class is defined in the passed &lt;FileName&gt;.
#
sub IsDefinedIn #(file)
    {
    my ($self, $file) = @_;

    if (defined $self-&gt;[DEFINITIONS])
        {  return exists $self-&gt;[DEFINITIONS]-&gt;{$file};  }
    else
        {  return 0;  };
    };

#
#   Function: IsDefined
#   Returns whether the class is defined in any files.
#
sub IsDefined
    {
    my ($self) = @_;
    return defined $self-&gt;[DEFINITIONS];
    };

#
#   Function: ParentReferences
#   Returns an array of the parent &lt;ReferenceStrings&gt;, or an empty array if none.
#
sub ParentReferences
    {
    my ($self) = @_;

    if (defined $self-&gt;[PARENT_REFERENCES])
        {  return keys %{$self-&gt;[PARENT_REFERENCES]};  }
    else
        {  return ( );  };
    };

#
#   Function: HasParentReference
#   Returns whether the class has the passed parent &lt;ReferenceString&gt;.
#
sub HasParentReference #(reference)
    {
    my ($self, $reference) = @_;
    return (defined $self-&gt;[PARENT_REFERENCES] &amp;&amp; exists $self-&gt;[PARENT_REFERENCES]-&gt;{$reference});
    };

#
#   Function: HasParentReferences
#   Returns whether the class has any parent &lt;ReferenceStrings&gt;.
#
sub HasParentReferences
    {
    my ($self) = @_;
    return defined $self-&gt;[PARENT_REFERENCES];
    };

#
#   Function: Parents
#   Returns an array of the parent &lt;SymbolStrings&gt;, or an empty array if none.
#
sub Parents
    {
    my ($self) = @_;

    if (defined $self-&gt;[PARENTS])
        {  return keys %{$self-&gt;[PARENTS]};  }
    else
        {  return ( );  };
    };

#
#   Function: HasParents
#   Returns whether the class has any parent &lt;SymbolStrings&gt; defined.
#
sub HasParents
    {
    my ($self) = @_;
    return defined $self-&gt;[PARENTS];
    };

#
#   Function: Children
#   Returns an array of the child &lt;SymbolStrings&gt;, or an empty array if none.
#
sub Children
    {
    my ($self) = @_;

    if (defined $self-&gt;[CHILDREN])
        {  return keys %{$self-&gt;[CHILDREN]};  }
    else
        {  return ( );  };
    };

#
#   Function: HasChildren
#   Returns whether any child &lt;SymbolStrings&gt; are defined.
#
sub HasChildren
    {
    my ($self) = @_;
    return defined $self-&gt;[CHILDREN];
    };


#
#   Function: ParentReferenceDefinitions
#   Returns an array of the &lt;FileNames&gt; which define the passed parent &lt;ReferenceString&gt;, or an empty array if none.
#
sub ParentReferenceDefinitions #(reference)
    {
    my ($self, $reference) = @_;

    if (defined $self-&gt;[PARENT_REFERENCES] &amp;&amp; exists $self-&gt;[PARENT_REFERENCES]-&gt;{$reference})
        {  return keys %{$self-&gt;[PARENT_REFERENCES]-&gt;{$reference}};  }
    else
        {  return ( );  };
    };


1;
</pre></body></html>