Class Aquarium::Aspects::Pointcut
In: lib/aquarium/aspects/pointcut.rb
lib/aquarium/aspects/pointcut_composition.rb
Parent: Object

Pointcut (composition)

Since Pointcuts are queries, they can be composed, i.e., unions and intersections of them can be computed, yielding new Pointcuts.

Methods

Included Modules

Aquarium::Utils::ArrayUtils Aquarium::Utils::HashUtils Aquarium::Utils::OptionsUtils Aquarium::Utils::SetUtils ExclusionHandler DefaultObjectsHandler

Constants

POINTCUT_CANONICAL_OPTIONS = { "default_objects" => %w[default_object], "join_points" => %w[join_point], "exclude_pointcuts" => %w[exclude_pointcut], "attributes" => %w[attribute accessing], "attribute_options" => %w[attribute_option], }
CANONICAL_OPTIONS = Aquarium::Finders::TypeFinder::CANONICAL_OPTIONS.merge( Aquarium::Finders::MethodFinder::METHOD_FINDER_CANONICAL_OPTIONS.merge(POINTCUT_CANONICAL_OPTIONS))
ATTRIBUTE_OPTIONS_VALUES = %w[reading writing changing]

Attributes

candidate_join_points  [W] 
candidate_join_points  [R] 
candidate_objects  [R] 
candidate_objects  [W] 
candidate_types  [R] 
candidate_types  [W] 
candidate_types_excluded  [R] 
candidate_types_excluded  [W] 
join_points_matched  [R] 
join_points_matched  [W] 
join_points_not_matched  [R] 
join_points_not_matched  [W] 
specification  [R] 
specification  [W] 
specification  [R] 

Public Class methods

[Source]

     # File lib/aquarium/aspects/pointcut.rb, line 250
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].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.

[Source]

     # File lib/aquarium/aspects/pointcut.rb, line 191
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

[Source]

     # File lib/aquarium/aspects/pointcut.rb, line 280
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

&(pointcut2)

Alias for and

==(other)

Alias for eql?

[Source]

    # File lib/aquarium/aspects/pointcut_composition.rb, line 24
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

[Source]

     # File lib/aquarium/aspects/pointcut.rb, line 276
276:       def any_type_related_options_given?
277:         objects_given? or join_points_given? or types_given? or types_and_descendents_given? or types_and_ancestors_given? or types_and_nested_types_given?
278:       end

[Source]

     # File lib/aquarium/aspects/pointcut.rb, line 220
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

[Source]

     # File lib/aquarium/aspects/pointcut.rb, line 207
207:       def eql? other
208:         object_id == other.object_id || 
209:         (self.class === other &&
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_not_matched == other.join_points_not_matched &&
215:          join_points_matched == other.join_points_matched)  # not_matched is probably smaller, so do first.
216:       end

[Source]

     # File lib/aquarium/aspects/pointcut.rb, line 263
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

[Source]

     # File lib/aquarium/aspects/pointcut.rb, line 272
272:       def init_methods_specification
273:         match_all_methods if ((no_methods_specified? and no_attributes_specified?) or all_methods_specified?)
274:       end

[Source]

     # File lib/aquarium/aspects/pointcut.rb, line 224
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
intersection(pointcut2)

Alias for and

[Source]

    # File lib/aquarium/aspects/pointcut_composition.rb, line 9
 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
to_s()

Alias for inspect

union(pointcut2)

Alias for or

|(pointcut2)

Alias for or

Protected Instance methods

[Source]

     # File lib/aquarium/aspects/pointcut.rb, line 301
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

[Source]

     # File lib/aquarium/aspects/pointcut.rb, line 293
293:       def match_all_methods
294:         @specification[:methods] = Set.new([:all])
295:       end

[Source]

     # File lib/aquarium/aspects/pointcut.rb, line 306
306:       def no_attributes_specified?
307:         @specification[:attributes].nil? or @specification[:attributes].empty?
308:       end

[Source]

     # File lib/aquarium/aspects/pointcut.rb, line 297
297:       def no_methods_specified?
298:         @specification[:methods].nil? or @specification[:methods].empty?
299:       end

[Validate]