Module jdk.dynalink
Package jdk.dynalink

Class NamespaceOperation

java.lang.Object
jdk.dynalink.NamespaceOperation
All Implemented Interfaces:
Operation

public final class NamespaceOperation extends Object implements Operation
Describes an operation that operates on at least one Namespace of an object. E.g. a property getter would be described as
 Operation propertyGetter = new NamespaceOperation(
     StandardOperation.GET,
     StandardNamespace.PROPERTY);
 
They are often combined with NamedOperation, e.g. to express a property getter for a property named "color", you would construct:
 Operation colorPropertyGetter = new NamedOperation(
     new NamespaceOperation(
         StandardOperation.GET,
         StandardNamespace.PROPERTY),
     "color");
 

While NamespaceOperation can be constructed directly, it is often convenient to use the Operation.withNamespace(Namespace) and Operation.withNamespaces(Namespace...) factory methods instead, e.g.:

 Operation getElementOrPropertyEmpty =
     StandardOperation.GET
         .withNamespace(StandardNamespace.PROPERTY)
         .named("color");
 

Operations on multiple namespaces

If multiple namespaces are specified, the namespaces are treated as alternatives to each other in order of preference. The semantics of such operation is "first applicable". That is, a composite of GET:PROPERTY|ELEMENT:color should be interpreted as get the property named "color" on the object, but if the property does not exist, then get the collection element named "color" instead.

Operations with multiple namespaces are helpful in implementation of languages that don't distinguish between one or more of the namespaces, or when expressing operations against objects that can be considered both ordinary objects and collections, e.g. Java Map objects. A GET:PROPERTY|ELEMENT:empty operation against a Java map will always match the Map.isEmpty() property, but GET:ELEMENT|PROPERTY:empty will actually match a map element with key "empty" if the map contains that key, and only fall back to the isEmpty() property getter if the map does not contain the key. If the source language mandates this semantics, it can be easily achieved using operations on multiple namespaces.

Even if the language itself doesn't distinguish between some of the namespaces, it can be helpful to map different syntaxes to different namespace orderings. E.g. the source expression obj.color could map to GET:PROPERTY|ELEMENT|METHOD:color, but a different source expression that looks like collection element access obj[key] could be expressed instead as GET:ELEMENT|PROPERTY|METHOD in order to favor the element semantics. Finally, if the retrieved value is subsequently called, then it makes sense to bring METHOD to the front of the namespace list: the getter part of the source expression obj.color() could be GET:METHOD|PROPERTY|ELEMENT:color and the one for obj[key]() could be GET:METHOD|ELEMENT|PROPERTY.

The base operation of a namespace operation can not itself be a namespace or named operation, but rather one of simple operations such are elements of StandardOperation. A namespace operation itself can serve as the base operation of a named operation, though; a typical way to construct e.g. the GET:ELEMENT|PROPERTY:empty from above would be:

 Operation getElementOrPropertyEmpty = StandardOperation.GET
     .withNamespaces(
         StandardNamespace.ELEMENT,
         StandardNamespace.PROPERTY)
     .named("empty");
 

Since:
9