LogicAJ Pointcuts
Logic Meta-Variables
The main distinction between LogicAJ and AspectJ is LogicAJ's concept of logic meta-variables:
- A logic meta-variable (LMV) is a metavariable that matches one base language element (e.g. a field access). Syntactically, it is an identifier with a prepended question mark: LMV ::=?Identifier
- A logic list meta-variable (LLMV) is a metavariable that matches a list of base langauge elements (e.g. a parameter list). Syntactically, it is an identifier with two prepended question marks: LLMV ::=??Identifier
Meta-variables are like named wildcards. Unlike with wildcards, one can refer to the value matched by a meta-variable by using the same meta-variable in another expression within the same scope. All occurrences of the same meta-variable in a scope must match the same value.
If a meta-variable occurs only once in a scope it can be replaced by the “anonymous” metavariable, whose name is the underscore: ”?_”. Every occurrence of the anonymous meta-variable is considered to be a different meta-variable (matches of the anonymous metavariable do not
need to agree on the matched value). The underscore can also be used as an anonymous list meta-variable, ”??_”.
Anonymous meta-variables are the equivlent of simple wildcards. ”?_” is equivalent to ”*” and ”??_” is equivalent to ”..”.
Although meta-variables subsume wildcards, the AspectJ-like wildcard syntax is supported in LogicAJ for backward compatibility and for the convenience of former AspectJ programmers.
Valid Bindings
A “binding” is a value for a meta-variable. Valid (component) types for meta-variables bindings are:
- string - String literals (“value”)
- float - float values
- int - integer values
- identifier - a Java identifier
- type - fully qualified names (e.g. java.lang.Object)
- param - method parameters (e.g. ??params in method( ?_ ?type.??params(..))
- expr - expressions (e.g. ??args in args(??args) )
Checking the type of meta-variables is done at weave-time, not at compile-time of individual aspects. So you will get weaving errors if e.g. a variable of type identifier is used in an arithmetic expression. However, you will never get run-time exceptions because of wrong types, as would be the case if you used reflection. Compile-time checking of meta-variable types will be part of a future release.
You may use fully qualified names, identifiers or strings where a value of type type is expected and vice versa. The value will be automatically converted, e.g.:
type(?stringType) && equals(?stringType, java.lang.String)
is equivalent to
equals(?stringType, "java.lang.String")
Also an automatic conversion is attempted for string values used in arithmetic expressions. Of course, this will result in a weaving error if the value can not be converted.
Patterns with Metavariables
Meta-variables and list meta-variables can be used in advice, introductions and the patterns of pointcuts. In patterns, they can be used (at least) wherever wildcards (*, **, or ..) can be used in AspectJ:
| MethodPat ::= [ ModifiersPat ] TypePat TypePat . NamePat ( [ ArgOrParamListPat ] ) [ throws TypeListPat ] FieldPat ::= [ ModifiersPat ] TypePat TypePat . NamePat |
|
| TypeListPat ::= TypePat ( , TypePat)* TypePat::= ( NamePat . )* NamePat ( [] )* | ! TypePat | TypePat && TypePat | TypePat || TypePat ArgOrParamListPat ::= ArgOrParamPat ( , ArgOrParamPat ) * ArgOrParamPat ::= TypePat | AdviceParamName | .. | LLMV |
AdviceParamName ::= Identifier NamePat ::= LMV | ( *| \? | Identifier )+ ModifiersPat::= LLMV | ( [ ! ] Modifier )+ Modifier::= public | protected ... | volatile |
Pointcuts Documentation
Below, the type of an argument is postfixed to the argument name separated by a colon. If the type is omitted arbitrary meta-variable types can be used. See also the the Valid Bindings paragraph above.
Selective Pointcuts With Metavariables
| General Syntax | Examples | ||
| call(MethodPat|ConstructorPat) | call ( void Foo.m(int) ) a call to the method void Foo.m(int) call ( Foo.new(..) ) a call to any constructor of Foo | ||
| execution(MethodPat|ConstructorPat) | execution ( * Foo.*(..) throws IOException ) the execution of any method of Foo that is declared to throw IOException execution ( !public Foo .new(..) ) the execution of any non-public constructor of Foo | ||
| withincode(MethodPat|ConstructorPat) | withincode ( void Figure.move() ) any join point where the associated code is defined in the method void Figure.move() | ||
| get(FieldPat) | get ( int Point.x ) when int Point.x is read | ||
| set(FieldPat) | set ( !private * Point.* ) when any field of Point is assigned | ||
| within(TypePat) | within( com.bigboxco.* ) any join point where the associated code is defined in the package com.bigboxco | ||
| target(TypePat | Var) | target( java.io.InputPort ) any join point where the target (receiver) object is an instance of java.io.InputPort The target pointcut can also be used to bind advice parameters: after(Object o) : call(..) && target(o) {...} | ||
| this(TypePat | Var) | this( Point )any join point where the currently executing object is an instance of Point | ||
| args(ArgsPat) | args( java.io.InputPort, int )any join point where there are two arguments, the first an instance of java.io.InputPort, and the second an int args( *, int ) any join point where there are two arguments, the second of which is an int. args( short, .., short ) any join point with at least two arguments, the first and last of which are shorts | ||
| receiverIsThis() | checks that the receiver of the join point is this | ||
Predicate Pointcuts
| General Syntax | Examples | ||
| equals( Arg1, Arg2) | Checks if first and second argument equal | ||
| jointPoint(Arg:string) | |||
| constructName(Name:string) | |||
| replace(?String:string,?SearchCharacter:string,?ReplaceCharacter:string,?Result:string) | e.g. replace("asdf","s","f","afdf" | ||
| var(?var) | Checks if ?var is not bound. | ||
| debug(Message:string, ?lmv1:lmv,...) | Generates trace data for the current pointcut definition, see also Pointcut Debugging | ||
| Class Member | |||
| method(MethodPat) | selects matching methods and binds meta-variables in the pattern; the optional LMV binds the body of the method, e.g: method ( void Foo.?m(int) ) selects all method in the type Foo with return type void and int parameter; all method names are bound to ?m | ||
| field(FieldPat) | selects matching fields and binds meta-variables in the pattern; the optional LMV binds the initializer of the field | ||
| directsubtype(Subtype:type, Supertype:type) | binds Subtype to direct subtype of the second argument Supertype | ||
| subtype(Subtype:type, Supertype:type) | binds Subtype to all subtypes (interfaces or classes) of the second argument Supertype | ||
| inner(InnerClass:type) | binds InnerClass to inner classes | ||
| local(LocalClass:type) | binds LocalClass to local classes~n e.g. void m() { class C { ...}; } | ||
| String Literal | |||
| subString(?String:string, ?Start:int, ?Length:int, ?After:int, ?Sub:string) | substring maintains the following relation:Sub is a sub-string of Str that starts at Before, has Len characters and Str contains After characters after the match. | ||
| camelCase(?Identifier:identifier, ?CamelCaseIdentifier:identifier) | example: camelCase(myField,MyField) | ||
| upperCase(?AnyCase:string, ?UpperCase:string) | Converts the characters of ?AnyCase into upper case and binds the string to ?UpperCase. | ||
| lowerCase(?AnyCase:string, ?LowerCase:string) | Converts the characters of AnyCase into lower case and binds the string to LowerCase. | ||
| stringToCharacters(?String,??Characters) | Converts between a ?String and and a list of ??Characters. Characters are Strings of length one. | ||
| List | |||
| member(Member,List:list) | Checks if the first argument is a member of the list bound to the second argument; the second argument must already be bound | ||
| length(List:list,Int:int) | Succeeds if Int represents the number of elements of list List. | ||
| outer(Inner:type, Outer:type) | Binds Outer to the outer class of an inner/local/anonymous class | ||
| split(?Head, ??TailList:list, ??List:list) | Separates ??List in the ?Head element and the Tail of the list. Tail can be an empty list. | ||
| concat(Arg1:string, Arg2:string, Arg3:string) | The third Arg forms the concatenation of the first and the second Arg | ||
| concat(Arg1:string, Arg2:string, Arg3:string, Arg4:string) | Arg4 forms the concatenation of Arg1,..,Arg3 | ||
| concat(Arg1:string, Arg2:string, Arg3:string, Arg4:string, Arg5:string) | Arg5 forms the concatenation of Arg1,..,Arg4 | ||
| removeElements(??RemoveElements:list, ??FromList:list, ??ResultList:list) | Removes ??RemoveElements from ??FromList and binds the resulting list to ??ResultList. | ||
| Types | |||
| concreteAspect(?Type:type) | Bind ?Type to the enclosing concrete aspect's class. | ||
| pattern( Arg, RegEx:string [, groupX:string] ) | Checks if the pattern RegEx matches the first argument. E.g. pattern("bbacc","(.*)a(.*)",?Match1, "cc") where ?Match1 matches the first group ("aa"). Be aware: Shorthand characters like \w do not work. Use [a-z] etc. instead. For details on the RegEx flavour see also the last paragraph of the SWI-Prolog RegEx documentation. | ||
| types(??Elements:list, ??Types:list | Unifies ??Types with the list of types of ??Elements, where Elements may contain parameter declarations or argument expressions | ||
| package(?Package:string) | Unifies ?Package with the packages defined in the project | ||
| sourcetype(PType:type) | Checks if Type is available in source code. Otherwise it was read from a library (as byte code). This is important since LogicAJ only weaves aspects into source classes. | ||
| typename(?Type:type,?SimpleTypeName:string) | binds the type name of ?Type to ?SimpleTypeName | ||
| typepackage(?Type:type,?PackageName:string) | binds the package name of ?Type to ?PackageName | ||
| packagetolist(?Package:string,??PackageNames:list | e.g. packagetolist("org.cs3", ["org","cs3"]) | ||
| arrayType(?ComponentType:type, ?Arity:int, ?Type:type) | e.g. arrayType("java.lang.Object[]",1, "java.lang.Object[]") | ||
| aspect(?Type:type) | check if ?Type is an aspect class | ||
| type(?Type:type) | selects matching types and binds meta-variables in the pattern, e.g.: type(?type) or type(?packagename.?name) binds ?package to the complete package name of the package of all types and ?name to the name of the type notice:in future ?packagename will only bind package name parts without dots, e.g. pack1;lists of (sub-)package names may be bound with ??package,e.g. type(??prefix.?api.internal.??rest.?classname) | ||
| class(?Class:type) | like type(..), but ensures that TypePat is a class | ||
| interface(?Interface:type) | Checks if ?Interface is an interface. | ||
| enum(?Enumeration:type) | Checks if ?Enumeration is an enumeraration. | ||
| annotationType(?Annotation:type) | Checks if ?Annotation is an annotation type. | ||
| Arithmetic | |||
| lt(Number1:int,Number2:int) | True if Number1 is smaller than Number2 | ||
| le(Number1:int,Number2:int) | True if Number1 is smaller or equal to Number2 | ||
| gt(Number1:int, Number2:int) | True if Number1 is greater than Number2 | ||
| ge(Number1:int, Number2:int) | True if Number1 is greater or equal to Number2 | ||
| ge(Number1:int, Number2:int,Sum:int) | True if Sum=Number1+Number2. At least two of the three arguments must be instantiated to integers. | ||

