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
- visibility: VisibilityKind Specifies the
visibility of the imported PackageableElement within the importing
Package. The default visibility is the same as that of the imported
element. If the imported element does not have a visibility, it is
possible to add visibility to the element import.
- alias: String
[0..1]
Specifies the name that should be added to the namespace of the
importing Pack-age in lieu of the name of the imported
PackagableElement. The aliased name must not clash with any other
member name in the importing Package. By default, no alias is used.
Associations
- importedElement: PackageableElement
[1]
Specifies the PackageableElement whose name is to be added to a
Namespace. Subsets DirectedRelationship::target.
- importingNamespace: Namespace
[1]
Specifies the Namespace that imports a PackageableElement from another
Package. Subsets DirectedRelationship::source and Element::owner.
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
- name: String
[0..1]
The name of the NamedElement.
- / qualifiedName: String [0..1] A
name which allows the NamedElement to be identified within a hierarchy
of nested Namespaces. It is constructed from the names of the
containing namespaces starting at the root of the hierarchy and ending
with the name of the NamedElement itself. This is a derived attribute.
- visibility: VisibilityKind
[0..1] Determines the visibility of
the NamedElement within different Namespaces within the overall model.
Package Dependencies ("Dependencies")
- supplierDependency: Dependency [*]Indicates the dependencies that
reference the supplier.
- clientDependency: Dependency[*]Indicates the dependencies that
reference the client.
Associations
- / namespace: Namespace [0..1]
Specifies the namespace that owns the NamedElement. Subsets Element::owner.
This is a derived union.
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
- elementImport: ElementImport
[*]
References the ElementImports owned by the Namespace. Subsets Ele-
- ment::ownedElement.·
- / importedMember: PackageableElement
[*] References
the PackageableElements that are members of this Namespace as a result
of either PackageImports or ElementImports. Subsets Namespace::member.
- / member: NamedElement
[*]
A collection of NamedElements identifiable within the Namespace, either
by being owned or by being introduced by importing or inheritance. This
is a derived union.
- / ownedMember: NamedElement
[*]
A collection of NamedElements owned by the Namespace. Subsets Element::ownedElement
and Namespace::member. This is a derived union.
- ownedRule:
Constraint[*]
Specifies a set of Constraints owned by this Namespace. Subsets Namespace::owned-
- Member.
- packageImport: PackageImport
[*]
References the PackageImports owned by the Namespace. Subsets Element::ownedElement.
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
- visibility: VisibilityKind [1] Indicates
that packageable elements must always have a visibility, i.e.,
visibility is not optional. Redefines NamedElement::visibility.
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
- visibility:
VisibilityKind
Specifies the visibility of the imported PackageableElements within the
import-ing Namespace, i.e., whether imported elements will in turn be
visible to other packages that use that importingPackage as an
importedPackage. If the PackageImport is public, the imported elements
will be visible outside the package, while if it is private they will
not.
By default, the value of visibility is public
.
Associations
- importedPackage: Package
[1]
Specifies the Package whose members are imported into a Namespace.
Subsets Directe-dRelationship::target.
- importingNamespace: Namespace [1]
Specifies the Namespace that imports the members from a Package.
Subsets Direct-edRelationship::source and Element::owner.
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:
- public
- private
- protected
- package
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.
-
A public element is visible to all elements that can access the
contents of the namespace that owns it.
-
A private element is only visible inside the namespace that owns it.
-
A protected element is visible to elements that have a generalization
relationship to the namespace that owns it.
-
A package element is owned by a namespace that is not a package, and is
visible to elements that are in the same packge as its owning
namespace. Only named elements that are not owned by packages can be
marked as having package visibility. Any element marked as having
package element is visible to all elements within the nearest enclosing
package (given that other owning elements have proper visibility).
Outside the nearest enclosing package, an element marked as having
package visibility is not visible.
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.