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

candidate_join_points[RW]
candidate_objects[RW]
candidate_types[RW]
candidate_types_excluded[RW]
join_points_matched[RW]
join_points_not_matched[RW]
specification[RW]

Public Class Methods

make_attribute_reading_writing_options(options_hash) click to toggle source
# File lib/aquarium/aspects/pointcut.rb, line 250
def self.make_attribute_reading_writing_options options_hash
  result = {}
  [:writing, :changing, :reading].each do |attr_key|
    next if options_hash[attr_key].nil? or options_hash[attr_key].to_s.empty?
    result[:attributes] ||= Set.new([])
    result[:attribute_options] ||= Set.new([])
    result[:attributes].merge(Aquarium::Utils::ArrayUtils.make_array(options_hash[attr_key]))
    attr_opt = attr_key == :reading ? :readers : :writers
    result[:attribute_options] << attr_opt
  end
  result
end
new(options = {}) click to toggle source

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.

::new also accepts all the “universal” options documented in Aquarium::Utils::OptionsUtils.

# File lib/aquarium/aspects/pointcut.rb, line 191
def initialize options = {} 
  init_specification options, CANONICAL_OPTIONS, (ATTRIBUTE_OPTIONS_VALUES + Advice::KINDS_IN_PRIORITY_ORDER) do 
    finish_specification_initialization
  end
  return if noop
  init_candidate_types 
  init_candidate_objects
  init_candidate_join_points
  init_join_points
end
validate_attribute_options(spec_hash, options_hash) click to toggle source
# File lib/aquarium/aspects/pointcut.rb, line 280
def self.validate_attribute_options spec_hash, options_hash
  raise Aquarium::Utils::InvalidOptions.new(":all is not yet supported for :attributes.") if spec_hash[:attributes] == Set.new([:all])
  if options_hash[:reading] and (options_hash[:writing] or options_hash[:changing])
    unless options_hash[:reading].eql?(options_hash[:writing]) or options_hash[:reading].eql?(options_hash[:changing])
      raise Aquarium::Utils::InvalidOptions.new(":reading and :writing/:changing can only be used together if they refer to the same set of attributes.") 
    end
  end
end

Public Instance Methods

&(pointcut2)
Alias for: and
==(other)
Alias for: eql?
and(pointcut2) click to toggle source
# File lib/aquarium/aspects/pointcut_composition.rb, line 24
def and pointcut2
  result = Aquarium::Aspects::Pointcut.new
  result.specification           = specification.and(pointcut2.specification) do |value1, value2| 
    value1 & value2
    # value1.intersection_using_eql_comparison value2
  end
  result.join_points_matched     = join_points_matched.intersection_using_eql_comparison      pointcut2.join_points_matched
  result.join_points_not_matched = join_points_not_matched.intersection_using_eql_comparison  pointcut2.join_points_not_matched
  result.candidate_types         = candidate_types.intersection          pointcut2.candidate_types
  result.candidate_objects       = candidate_objects.intersection        pointcut2.candidate_objects
  result
end
Also aliased as: intersection, &
empty?() click to toggle source
# File lib/aquarium/aspects/pointcut.rb, line 220
def empty?
  return join_points_matched.empty? && join_points_not_matched.empty?
end
eql?(other) click to toggle source

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, line 207
def eql? other
  object_id == other.object_id || 
  (self.class == other.class &&
   specification == other.specification && 
   candidate_types == other.candidate_types && 
   candidate_types_excluded == other.candidate_types_excluded && 
   candidate_objects == other.candidate_objects && 
   join_points_matched == other.join_points_matched &&
   join_points_not_matched == other.join_points_not_matched)
end
Also aliased as: ==
finish_specification_initialization() click to toggle source
# File lib/aquarium/aspects/pointcut.rb, line 263
def finish_specification_initialization
  @specification.merge! Pointcut.make_attribute_reading_writing_options(@original_options)
  # Map the method options to their canonical values:
  @specification[:method_options] = Aquarium::Finders::MethodFinder.init_method_options(@specification[:method_options])
  use_default_objects_if_defined unless any_type_related_options_given?
  Pointcut::validate_attribute_options @specification, @original_options
  init_methods_specification
end
init_methods_specification() click to toggle source
# File lib/aquarium/aspects/pointcut.rb, line 272
def init_methods_specification
  match_all_methods if ((no_methods_specified? and no_attributes_specified?) or all_methods_specified?)
end
inspect() click to toggle source
# File lib/aquarium/aspects/pointcut.rb, line 224
def inspect
  "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}}"
end
Also aliased as: to_s
intersection(pointcut2)
Alias for: and
or(pointcut2) click to toggle source
# File lib/aquarium/aspects/pointcut_composition.rb, line 9
def or pointcut2
  result = Aquarium::Aspects::Pointcut.new
  result.specification           = specification.or(pointcut2.specification) do |value1, value2| 
    value1.union_using_eql_comparison value2
  end
  result.join_points_matched     = join_points_matched.union_using_eql_comparison     pointcut2.join_points_matched
  result.join_points_not_matched = join_points_not_matched.union_using_eql_comparison pointcut2.join_points_not_matched
  result.candidate_types         = candidate_types.union         pointcut2.candidate_types
  result.candidate_objects       = candidate_objects.union       pointcut2.candidate_objects
  result
end
Also aliased as: union, |
to_s()
Alias for: inspect
union(pointcut2)
Alias for: or
|(pointcut2)
Alias for: or

Protected Instance Methods

all_methods_specified?() click to toggle source
# File lib/aquarium/aspects/pointcut.rb, line 301
def all_methods_specified?
  methods_spec = @specification[:methods].to_a
  methods_spec.include?(:all) or methods_spec.include?(:all_methods)
end
match_all_methods() click to toggle source
# File lib/aquarium/aspects/pointcut.rb, line 293
def match_all_methods
  @specification[:methods] = Set.new([:all])
end
no_attributes_specified?() click to toggle source
# File lib/aquarium/aspects/pointcut.rb, line 306
def no_attributes_specified?
  @specification[:attributes].nil? or @specification[:attributes].empty?
end
no_methods_specified?() click to toggle source
# File lib/aquarium/aspects/pointcut.rb, line 297
def no_methods_specified?
  @specification[:methods].nil? or @specification[:methods].empty?
end