Kernel ­ the Namespaces Diagram

The Namespaces diagram of the Kernel package is shown in Figure 6.


In order to locate the metaclasses that are referenced from this diagram,
· See "DirectedRelationship (from Kernel)"
· See "Element (from Kernel)"
· See "Package (from Kernel)".

 ElementImport (from Kernel)

An element import identifies an element in another package, and allows the element to be referenced using its name without a qualifier.

Description

An element import is defined as a directed relationship between an importing namespace and a packageable element. The name of the packageable element or its alias is to be added to the namespace of the importing namespace. It is also possible to control whether the imported element can be further imported.

Attributes


Associations
Constraints

[1] The visibility of an ElementImport is either public or private.

self.visibility = #public or self.visibility = #private

[2] An importedElement has either public visibility or no visibility at all.

self.importedElement.visibility.notEmpty() implies self.importedElement.visibility = #public

Additional Operations

[1] The query getName() returns the name under which the imported PackageableElement will be known in the importing namespace.

ElementImport::getName(): String;
    getName =
        if self.alias->notEmpty() then
            self.alias
        else
            self.importedElement.name
        endif

Semantics

An element import adds the name of a packageable element from a package to the importing namespace. It works by reference, which means that it is not possible to add features to the element import itself, but it is possible to modify the referenced element in the namespace from which it was imported. An element import is used to selectively import individual elements without relying on a package import.

In case of a nameclash with an outer name (an element that is defined in an enclosing namespace is available using its unqualified name in enclosed namespaces) in the importing namespace, the outer name is hidden by an ele-ment import, and the unqualified name refers to the imported element. The outer name can be accessed using its qual-ified name.

If more than one element with the same name would be imported to a namespace as a consequence of element imports or package imports, the names of the imported elements must be qualified in order to be used and the ele-ments are not added to the importing namespace. If the name of an imported element is the same as the name of an element owned by the importing namespace, the name of the imported element must be qualified in order to be used and is not added to the importing namespace.

An imported element can be further imported by other namespaces using either element or member imports.The visibility of the ElementImport may be either the same or more restricted than that of the imported element.

Notation

An element import is shown using a dashed arrow with an open arrowhead from the importing namespace to the imported element. The keyword «import» is shown near the dashed arrow if the visibility is public, otherwise the key-word «access» is shown.

If an element import has an alias, this is used in lieu of the name of the imported element. The aliased name may be shown after or below the keyword «import».

Presentation options

If the imported element is a package, the keyword may optionally be preceded by element, i.e., «element import».As an alternative to the dashed arrow, it is possible to show an element import by having a text that uniquely identifies the imported element within curly brackets either below or after the name of the namespace. The textual syntax is then:

{element import <qualifiedName>} or {element access <qualifiedName>}

Optionally, the aliased name may be show as well:

{element import <qualifiedName> as <alias>} or {element access <qualifiedName> as <alias>}

Examples
The element import that is shown in Figure 7 allows elements in the package Program to refer to the type Time in Types without qualification. However, they still need to refer explicitly to Types::Integer, since this element is not imported.

In Figure 8, the element import is combined with aliasing, meaning that the type Types::Real will be referred to as Double in the package Shapes.




NamedElement (from Kernel, Dependencies)

A named element is an element in a model that may have a name.

Description

A named element represents elements that may have a name. The name is used for identification of the named element within the namespace in which it is defined. A named element also has a qualified name that allows it to be unambiguously identified within a hierarchy of nested namespaces. NamedElement is an abstract metaclass.

Attributes


Package Dependencies ("Dependencies")

Associations

Constraints

[1] If there is no name, or one of the containing namespaces has no name, there is no qualified name.

(self.name->isEmpty() or self.allNamespaces()->select(ns | ns.name->isEmpty())->notEmpty())
    implies self.qualifiedName->isEmpty()

[2] When there is a name, and all of the containing namespaces have a name, the qualified name is constructed from the names of the containing namespaces.

(self.name->notEmpty() and self.allNamespaces()->select(ns | ns.name->isEmpty())->isEmpty()) implies
    self.qualifiedName = self.allNamespaces()->iterate( ns : Namespace; result: String = self.name |
            ns.name->union(self.separator())->union(result))

[3] If a NamedElement is not owned by a Namespace, it does not have a visibility.

namespace->isEmpty() implies visibility->isEmpty()

Additional Operations

[1] The query allNamespaces() gives the sequence of namespaces in which the NamedElement is nested, working outwards.
       NamedElement::allNamespaces(): Sequence(Namespace);
       allNamespaces =
            if self.namespace->isEmpty()
            then Sequence{}
            else self.name.allNamespaces()->prepend(self.namespace)
            endif
[2] The query isDistinguishableFrom() determines whether two NamedElements may logically co-exist within a Namespace.By default, two named elements are distinguishable if (a) they have unrelated types or (b) they have related types but different names.

NamedElement::isDistinguishableFrom(n:NamedElement, ns: Namespace): Boolean;
    isDistinguishable =
        if self.oclIsKindOf(n.oclType) or n.oclIsKindOf(self.oclType)
        then ns.getNamesOfMember(self)->intersection(ns.getNamesOfMember(n))->isEmpty()
        else true
        endif

[3] The query separator() gives the string that is used to separate names when constructing a qualified name.

NamedElement::separator(): String;
separator = `::'

Semantics

The name attribute is used for identification of the named element within namespaces where its name is accessible. Note that the attribute has a multiplicity of [ 0..1 ] which provides for the possibility of the absence of a name (which is different from the empty name).

The visibility attribute provides the means to constrain the usage of a named element in different namespaces within a model.

It is intended for use in conjunction with import and generalization mechanisms.

Notation

No additional notation.

 Namespace (from Kernel)

A namespace is an element in a model that contains a set of named elements that can be identified by name.

Description

A namespace is a named element that can own other named elements. Each named element may be owned by at most one namespace. A namespace provides a means for identifying named elements by name. Named elements can be identified by name in a namespace either by being directly owned by the namespace or by being introduced into the namespace by other means e.g. importing or inheriting. Namespace is an abstract metaclass.

A namespace can own constraints. The constraint does not necessarily apply to the namespace itself, but may also apply to elements in the namespace.

A namespace has the ability to import either individial members or all members of a package, thereby making it possible to refer to those named elements without qualification in the importing namespace. In the case of conflicts, it is necessary to use qualified names or aliases to disambiguate the referenced elements.

Attributes

No additional attributes.

Associations

Constraints

[1] All the members of a Namespace are distinguishable within it.

membersAreDistinguishable()

[2] The importedMember property is derived from the ElementImports and the PackageImports.

self.importedMember->includesAll(self.importedMembers(self.elementImport.importedElement.asSet()-
    >union(self.packageImport.importedPackage->collect(p | p.visibleMembers()))))

Additional Operations

[1] The query getNamesOfMember() gives a set of all of the names that a member would have in a Namespace. In general a member can have multiple names in a Namespace if it is imported more than once with different aliases. The query takes account of importing. It gives back the set of names that an element would have in an importing namespace, either because it is owned, or if not owned then imported individually, or if not individually then from a package.

Namespace::getNamesOfMember(element: NamedElement): Set(String);
    getNamesOfMember =
        if self.ownedMember ->includes(element)
        then Set{}->include(element.name)
        else let elementImports: ElementImport = self.elementImport->select(ei | ei.importedElement = element) in
            if elementImports->notEmpty()
            then elementImports->collect(el | el.getName())
            else
                self.packageImport->select(pi | pi.importedPackage.visibleMembers()->includes(element))->
                        collect(pi | pi.importedPackage.getNamesOfMember(element))
            endif
        endif

[2] The Boolean query membersAreDistinguishable() determines whether all of the namespace's members are distinguishable within it.

Namespace::membersAreDistinguishable() : Boolean;
membersAreDistinguishable =
    self.member->forAll( memb |
        self.member->excluding(memb)->forAll(other |
            memb.isDistinguishableFrom(other, self)))

[3] The query importMembers() defines which of a set of PackageableElements are actually imported into the namespace.This excludes hidden ones, i.e., those which have names that conflict with names of owned members, and also excludeselements which would have the same name when imported.

Namespace::importMembers(imps: Set(PackageableElement)): Set(PackageableElement);
importMembers = self.excludeCollisions(imps)->select(imp | self.ownedMember->forAll(mem |
    mem.imp.isDistinguishableFrom(mem, self)))

[4] The query excludeCollisions() excludes from a set of PackageableElements any that would not be distinguishable from each other in this namespace.

Namespace::excludeCollisions(imps: Set(PackageableElements)): Set(PackageableElements);
    excludeCollisions = imps->reject(imp1 | imps.exists(imp2 | not imp1.isDistinguishableFrom(imp2, self)))

Semantics

A namespace provides a container for named elements. It provides a means for resolving composite names, such as name1::name2::name3. The member association identifies all named elements in a namespace called N that can be referred to by a composite name of the form N::<x>. Note that this is different from all of the names that can be referred to unqualified within N, because that set also includes all unhidden members of enclosing namespaces.

Named elements may appear within a namespace according to rules that specify how one named element is distinguishable from another. The default rule is that two elements are distinguishable if they have unrelated types, or related types but different names. This rule may be overridden for particular cases, such as operations which are distinguished by their signature.

The ownedRule constraints for a Namespace represent well formedness rules for the constrained elements. These constraints are evaluated when determining if the model elements are well formed.

Notation

No additional notation. Concrete subclasses will define their own specific notation.

PackageableElement (from Kernel)

A packageable element indicates a named element that may be owned directly by a package.

Description

A packageable element indicates a named element that may be owned directly by a package.

Attributes

Associations

No additional associations.

Constraints

No additional constraints.

Semantics

No additional semantics.

Notation

No additional notation.

 PackageImport (from Kernel)

A package import is a relationship that allows the use of unqualified names to refer to package members from other namespaces.

Description

A package import is defined as a directed relationship that identifies a package whose members are to be imported by a namespace.

Attributes
By default, the value of visibility is public
.
Associations

Constraints

[1] The visibility of a PackageImport is either public or private.

self.visibility = #public or self.visibility = #private

Semantics

A package import is a relationship between an importing namespace and a package, indicating that the importing namespace adds the names of the members of the package to its own namespace. Conceptually, a package import is equivalent to having an element import to each individual member of the imported namespace, unless there is already a separately-defined element import.

Notation

A package import is shown using a dashed arrow with an open arrowhead from the importing namespace to the imported package. A keyword is shown near the dashed arrow to identify which kind of package import that is intended. The predefined keywords are «import» for a public package import , and «access» for a private package import.

Presentation options

As an alternative to the dashed arrow, it is possible to show an element import by having a text that uniquely identi-fies the imported element within curly brackets either below or after the name of the namespace. The textual syntax is then:

{import <qualifiedName>} or {access <qualifiedName>}

Examples

In Figure 9, a number of package imports are shown. The elements in Types are imported to ShoppingCart, and then further imported WebShop. However, the elements of Auxiliary are only accessed from ShoppingCart, and cannot be referenced using unqualified names from WebShop.



VisibilityKind (from Kernel)


VisibilityKind is an enumeration type that defines literals to determine the visibility of elements in a model.

Description

VisibilityKind is an enumeration of the following literal values:
Additional Operations

[1] The query bestVisibility() examines a set of VisibilityKinds that includes only public and private, and returns public as the preferred visibility.

VisibilityKind::bestVisibility(vis: Set(VisibilityKind)) : VisibilityKind;
pre: not vis->includes(#protected) and not vis->includes(#package)
bestVisibility = if vis->includes(#public) then #public else #private endif

Semantics

VisibilityKind is intended for use in the specification of visibility in conjunction with, for example, the Imports, Generalizations and Packages packages. Detailed semantics are specified with those mechanisms. If the Visibility package is used without those packages, these literals will have different meanings, or no meanings.


In circumstances where a named element ends up with multiple visibilities, for example by being imported multiple times, public visibility overrides private visibility, i.e., if an element is imported twice into the same namespace, once using a public import and once using a private import, it will be public.