class Aquarium::Aspects::Pointcut
Pointcut
¶ ↑
Pointcuts are queries on JoinPoints combined with binding of context data to that will be useful during advice execution. The Pointcut
locates the join points that match the input criteria, remembering the found join points as well as the the criteria that yielded no matches (mostly useful for debugging Pointcut
definitions)
Pointcut
(composition)¶ ↑
Since Pointcuts are queries, they can be composed, i.e., unions and intersections of them can be computed, yielding new Pointcuts.
Constants
- ATTRIBUTE_OPTIONS_VALUES
- CANONICAL_OPTIONS
- POINTCUT_CANONICAL_OPTIONS
Attributes
Public Class Methods
# File lib/aquarium/aspects/pointcut.rb 250 def self.make_attribute_reading_writing_options options_hash 251 result = {} 252 [:writing, :changing, :reading].each do |attr_key| 253 next if options_hash[attr_key].nil? or options_hash[attr_key].to_s.empty? 254 result[:attributes] ||= Set.new([]) 255 result[:attribute_options] ||= Set.new([]) 256 result[:attributes].merge(Aquarium::Utils::ArrayUtils.make_array(options_hash[attr_key])) 257 attr_opt = attr_key == :reading ? :readers : :writers 258 result[:attribute_options] << attr_opt 259 end 260 result 261 end
Construct a Pointcut
for methods in types or objects.
Pointcut.new :join_points => [...] | :type{s} => [...] | :object{s} => [...] {, :method{s} => [], :method_options => [...], :attribute{s} => [...], :attribute_options[...]}
where the “{}” indicate optional elements. Most of the arguments have many synonyms, shown below, to promote an English-like DSL.
The options include the following.
Join Points¶ ↑
Specify one or an array of join_points.
-
:join_points => join_point || [join_point_list]
-
:join_point => join_point || [join_point_list]
-
:for_join_points => join_point || [join_point_list]
-
:for_join_point => join_point || [join_point_list]
-
:on_join_points => join_point || [join_point_list]
-
:on_join_point => join_point || [join_point_list]
-
:within_join_points => join_point || [join_point_list]
-
:within_join_point => join_point || [join_point_list]
Types¶ ↑
Specify a type, type name, type name regular expression or an array of the same. (Mixed is allowed.)
-
:types => type || [type_list]
-
:type => type || [type_list]
-
:for_types => type || [type_list]
-
:for_type => type || [type_list]
-
:on_types => type || [type_list]
-
:on_type => type || [type_list]
-
:within_types => type || [type_list]
-
:within_type => type || [type_list]
Types and Ancestors or Descendents¶ ↑
Specify a type, type name, type name regular expression or an array of the same. (Mixed is allowed.) The ancestors or descendents will also be found. To find both ancestors and descendents, use both options.
-
:types_and_descendents => type || [type_list]
-
:type_and_descendents => type || [type_list]
-
:types_and_ancestors => type || [type_list]
-
:type_and_ancestors => type || [type_list]
-
:for_types_and_ancestors => type || [type_list]
-
:for_type_and_ancestors => type || [type_list]
-
:on_types_and_descendents => type || [type_list]
-
:on_type_and_descendents => type || [type_list]
-
:on_types_and_ancestors => type || [type_list]
-
:on_type_and_ancestors => type || [type_list]
-
:within_types_and_descendents => type || [type_list]
-
:within_type_and_descendents => type || [type_list]
-
:within_types_and_ancestors => type || [type_list]
-
:within_type_and_ancestors => type || [type_list]
Types and Nested Types¶ ↑
Specify a type, type name, type name regular expression or an array of the same. (Mixed is allowed.) The nested (enclosed) types will also be found.
-
:types_and_nested_types => type || [type_list]
-
:type_and_nested_types => type || [type_list]
-
:types_and_nested => type || [type_list]
-
:type_and_nested => type || [type_list]
-
:for_types_and_nested_types => type || [type_list]
-
:for_type_and_nested_types => type || [type_list]
-
:for_types_and_nested => type || [type_list]
-
:for_type_and_nested => type || [type_list]
-
:on_types_and_nested_types => type || [type_list]
-
:on_type_and_nested_types => type || [type_list]
-
:on_types_and_nested => type || [type_list]
-
:on_type_and_nested => type || [type_list]
-
:within_types_and_nested_types => type || [type_list]
-
:within_type_and_nested_types => type || [type_list]
-
:within_types_and_nested => type || [type_list]
-
:within_type_and_nested => type || [type_list]
Objects¶ ↑
-
:objects => object || [object_list]
-
:object => object || [object_list]
-
:for_objects => object || [object_list]
-
:for_object => object || [object_list]
-
:on_objects => object || [object_list]
-
:on_object => object || [object_list]
-
:within_objects => object || [object_list]
-
:within_object => object || [object_list]
“Default” Objects¶ ↑
An “internal” flag used by Aspect::DSL#pointcut. When no object or type is specified explicitly, the value of :default_objects will be used, if defined. Aspect::DSL#pointcut sets the value to self
, so the user doesn't have to specify a type or object in the contexts where that would be useful, e.g., pointcuts defined within a type for join points within itself. WARNING: This flag is subject to change, so don't use it explicitly!
-
:default_objects => object || [object_list]
-
:default_object => object || [object_list]
Methods¶ ↑
A method name, name regular expession or an array of the same. By default, if neither :methods
nor :attributes
are specified, all public instance methods will be found, with the method option :exclude_ancestor_methods
implied, unless explicit method options are given.
-
:methods => method || [method_list]
-
:method => method || [method_list]
-
:within_methods => method || [method_list]
-
:within_method => method || [method_list]
-
:calling => method || [method_list]
-
:calls_to => method || [method_list]
-
:invoking => method || [method_list]
-
:invocations_of => method || [method_list]
-
:sending_message_to => method || [method_list]
Method Options¶ ↑
One or more options supported by Aquarium::Finders::MethodFinder
. The :exclude_ancestor_methods
option is most useful.
-
:method_options => [options]
Attributes¶ ↑
An attribute name, regular expession or array of the same. WARNING This is syntactic sugar for the corresponding attribute readers and/or writers methods. The actual attribute accesses are not advised, which can lead to unexpected behavior. A goal before V1.0 is to support actual attribute accesses, if possible.
-
:attributes => attribute || [attribute_list]
-
:attribute => attribute || [attribute_list]
-
:reading => attribute || [attribute_list]
-
:writing => attribute || [attribute_list]
-
:changing => attribute || [attribute_list]
-
:accessing => attribute || [attribute_list]
If :reading
is specified, just attribute readers are matched. If :writing
is specified, just attribute writers are matched. If :accessing
is specified, both readers and writers are matched. Any matches will be joined with the matched :methods.
.
Attribute Options¶ ↑
One or more of :readers
, :reader
(synonymous), :writers
, and/or :writer
(synonymous). By default, both readers and writers are matched. :reading => ...
is synonymous with :attributes => ..., :attribute_options => [:readers]
. :writing => ...
and :changing => ...
are synonymous with :attributes => ..., :attribute_options => [:writers]
. :accessing => ...
is synonymous with :attributes => ...
.
-
:attribute_options => [options]
Exclusion Options¶ ↑
Exclude the specified “things” from the matched join points. If pointcuts are excluded, they should be subsets of the matched pointcuts. Otherwise, the resulting pointcut will be empty!
-
:exclude_pointcuts => pc || [pc_list]
-
:exclude_pointcut => pc || [pc_list]
-
:exclude_join_points => jp || [jp_list]
-
:exclude_join_point => jp || [jp_list]
-
:exclude_types => type || [type_list]
-
:exclude_types => type || [type_list]
-
:exclude_type => type || [type_list]
-
:exclude_types_and_descendents => type || [type_list]
-
:exclude_type_and_descendents => type || [type_list]
-
:exclude_types_and_ancestors => type || [type_list]
-
:exclude_type_and_ancestors => type || [type_list]
-
:exclude_types_and_nested_types => type || [type_list]
-
:exclude_type_and_nested_types => type || [type_list]
-
:exclude_types_and_nested => type || [type_list]
-
:exclude_type_and_nested => type || [type_list]
-
:exclude_objects => object || [object_list]
-
:exclude_object => object || [object_list]
-
:exclude_methods => method || [method_list]
-
:exclude_method => method || [method_list]
-
:exclude_attributes => attribute || [attribute_list]
-
:exclude_attribute => attribute || [attribute_list]
The exclude_
prefix works with the synonyms of the options shown.
Pointcut.new
also accepts all the “universal” options documented in Aquarium::Utils::OptionsUtils
.
# File lib/aquarium/aspects/pointcut.rb 191 def initialize options = {} 192 init_specification options, CANONICAL_OPTIONS, (ATTRIBUTE_OPTIONS_VALUES + Advice::KINDS_IN_PRIORITY_ORDER) do 193 finish_specification_initialization 194 end 195 return if noop 196 init_candidate_types 197 init_candidate_objects 198 init_candidate_join_points 199 init_join_points 200 end
# File lib/aquarium/aspects/pointcut.rb 280 def self.validate_attribute_options spec_hash, options_hash 281 raise Aquarium::Utils::InvalidOptions.new(":all is not yet supported for :attributes.") if spec_hash[:attributes] == Set.new([:all]) 282 if options_hash[:reading] and (options_hash[:writing] or options_hash[:changing]) 283 unless options_hash[:reading].eql?(options_hash[:writing]) or options_hash[:reading].eql?(options_hash[:changing]) 284 raise Aquarium::Utils::InvalidOptions.new(":reading and :writing/:changing can only be used together if they refer to the same set of attributes.") 285 end 286 end 287 end
Public Instance Methods
# File lib/aquarium/aspects/pointcut_composition.rb 24 def and pointcut2 25 result = Aquarium::Aspects::Pointcut.new 26 result.specification = specification.and(pointcut2.specification) do |value1, value2| 27 value1 & value2 28 # value1.intersection_using_eql_comparison value2 29 end 30 result.join_points_matched = join_points_matched.intersection_using_eql_comparison pointcut2.join_points_matched 31 result.join_points_not_matched = join_points_not_matched.intersection_using_eql_comparison pointcut2.join_points_not_matched 32 result.candidate_types = candidate_types.intersection pointcut2.candidate_types 33 result.candidate_objects = candidate_objects.intersection pointcut2.candidate_objects 34 result 35 end
# File lib/aquarium/aspects/pointcut.rb 220 def empty? 221 return join_points_matched.empty? && join_points_not_matched.empty? 222 end
Two Considered equivalent only if the same join points matched and not_matched sets are equal, the specifications are equal, and the candidate types and candidate objects are equal. if you care only about the matched join points, then just compare join_points_matched
# File lib/aquarium/aspects/pointcut.rb 207 def eql? other 208 object_id == other.object_id || 209 (self.class == other.class && 210 specification == other.specification && 211 candidate_types == other.candidate_types && 212 candidate_types_excluded == other.candidate_types_excluded && 213 candidate_objects == other.candidate_objects && 214 join_points_matched == other.join_points_matched && 215 join_points_not_matched == other.join_points_not_matched) 216 end
# File lib/aquarium/aspects/pointcut.rb 263 def finish_specification_initialization 264 @specification.merge! Pointcut.make_attribute_reading_writing_options(@original_options) 265 # Map the method options to their canonical values: 266 @specification[:method_options] = Aquarium::Finders::MethodFinder.init_method_options(@specification[:method_options]) 267 use_default_objects_if_defined unless any_type_related_options_given? 268 Pointcut::validate_attribute_options @specification, @original_options 269 init_methods_specification 270 end
# File lib/aquarium/aspects/pointcut.rb 272 def init_methods_specification 273 match_all_methods if ((no_methods_specified? and no_attributes_specified?) or all_methods_specified?) 274 end
# File lib/aquarium/aspects/pointcut.rb 224 def inspect 225 "Pointcut: {specification: #{specification.inspect}, candidate_types: #{candidate_types.inspect}, candidate_types_excluded: #{candidate_types_excluded.inspect}, candidate_objects: #{candidate_objects.inspect}, join_points_matched: #{join_points_matched.inspect}, join_points_not_matched: #{join_points_not_matched.inspect}}" 226 end
# File lib/aquarium/aspects/pointcut_composition.rb 9 def or pointcut2 10 result = Aquarium::Aspects::Pointcut.new 11 result.specification = specification.or(pointcut2.specification) do |value1, value2| 12 value1.union_using_eql_comparison value2 13 end 14 result.join_points_matched = join_points_matched.union_using_eql_comparison pointcut2.join_points_matched 15 result.join_points_not_matched = join_points_not_matched.union_using_eql_comparison pointcut2.join_points_not_matched 16 result.candidate_types = candidate_types.union pointcut2.candidate_types 17 result.candidate_objects = candidate_objects.union pointcut2.candidate_objects 18 result 19 end
Protected Instance Methods
# File lib/aquarium/aspects/pointcut.rb 301 def all_methods_specified? 302 methods_spec = @specification[:methods].to_a 303 methods_spec.include?(:all) or methods_spec.include?(:all_methods) 304 end
# File lib/aquarium/aspects/pointcut.rb 293 def match_all_methods 294 @specification[:methods] = Set.new([:all]) 295 end
# File lib/aquarium/aspects/pointcut.rb 306 def no_attributes_specified? 307 @specification[:attributes].nil? or @specification[:attributes].empty? 308 end
# File lib/aquarium/aspects/pointcut.rb 297 def no_methods_specified? 298 @specification[:methods].nil? or @specification[:methods].empty? 299 end