Class: Aquarium::Aspects::Pointcut
- Includes:
- DefaultObjectsHandler, ExclusionHandler, Utils::ArrayUtils, Utils::HashUtils, Utils::OptionsUtils, Utils::SetUtils
- Defined in:
- lib/aquarium/aspects/pointcut.rb,
lib/aquarium/aspects/pointcut_composition.rb
Overview
Pointcut (composition)
Since Pointcuts are queries, they can be composed, i.e., unions and intersections of them can be computed, yielding new Pointcuts.
Constant Summary collapse
- 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]
Instance Attribute Summary collapse
-
#candidate_join_points ⇒ Object
readonly
Returns the value of attribute candidate_join_points.
-
#candidate_objects ⇒ Object
readonly
Returns the value of attribute candidate_objects.
-
#candidate_types ⇒ Object
readonly
Returns the value of attribute candidate_types.
-
#candidate_types_excluded ⇒ Object
readonly
Returns the value of attribute candidate_types_excluded.
-
#join_points_matched ⇒ Object
readonly
Returns the value of attribute join_points_matched.
-
#join_points_not_matched ⇒ Object
readonly
Returns the value of attribute join_points_not_matched.
-
#specification ⇒ Object
readonly
Returns the value of attribute specification.
Class Method Summary collapse
- .make_attribute_reading_writing_options(options_hash) ⇒ Object
- .validate_attribute_options(spec_hash, options_hash) ⇒ Object
Instance Method Summary collapse
- #and(pointcut2) ⇒ Object (also: #intersection, #&)
- #any_type_related_options_given? ⇒ Boolean
- #empty? ⇒ Boolean
-
#eql?(other) ⇒ Boolean
(also: #==)
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.
- #finish_specification_initialization ⇒ Object
- #init_methods_specification ⇒ Object
-
#initialize(options = {}) ⇒ Pointcut
constructor
Construct a Pointcut for methods in types or objects.
- #inspect ⇒ Object (also: #to_s)
- #or(pointcut2) ⇒ Object (also: #union, #|)
Methods included from DefaultObjectsHandler
#default_objects_given, #default_objects_given?, #use_default_objects_if_defined
Methods included from Utils::ArrayUtils
#make_array, make_array, #strip_array_nils, strip_array_nils
Methods included from ExclusionHandler
#all_excluded_pointcuts, #is_excluded_join_point?, #is_excluded_method?, #is_excluded_pointcut?, #is_excluded_type_or_object?, #is_explicitly_excluded_method?, #join_point_excluded?, #matches_excluded_method_regex?, #set_calculated_excluded_pointcuts
Methods included from Utils::HashUtils
Methods included from Utils::SetUtils
#make_set, #strip_set_nils, strip_set_nils
Methods included from Utils::OptionsUtils
append_features, #hashify, #init_specification, universal_options, universal_prepositions, #validate_options
Constructor Details
#initialize(options = {}) ⇒ Pointcut
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.
191 192 193 194 195 196 197 198 199 200 |
# File 'lib/aquarium/aspects/pointcut.rb', line 191 def initialize = {} init_specification , 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 |
Instance Attribute Details
#candidate_join_points ⇒ Object
Returns the value of attribute candidate_join_points.
202 203 204 |
# File 'lib/aquarium/aspects/pointcut.rb', line 202 def candidate_join_points @candidate_join_points end |
#candidate_objects ⇒ Object
Returns the value of attribute candidate_objects.
202 203 204 |
# File 'lib/aquarium/aspects/pointcut.rb', line 202 def candidate_objects @candidate_objects end |
#candidate_types ⇒ Object
Returns the value of attribute candidate_types.
202 203 204 |
# File 'lib/aquarium/aspects/pointcut.rb', line 202 def candidate_types @candidate_types end |
#candidate_types_excluded ⇒ Object
Returns the value of attribute candidate_types_excluded.
202 203 204 |
# File 'lib/aquarium/aspects/pointcut.rb', line 202 def candidate_types_excluded @candidate_types_excluded end |
#join_points_matched ⇒ Object
Returns the value of attribute join_points_matched.
202 203 204 |
# File 'lib/aquarium/aspects/pointcut.rb', line 202 def join_points_matched @join_points_matched end |
#join_points_not_matched ⇒ Object
Returns the value of attribute join_points_not_matched.
202 203 204 |
# File 'lib/aquarium/aspects/pointcut.rb', line 202 def join_points_not_matched @join_points_not_matched end |
#specification ⇒ Object
Returns the value of attribute specification.
26 27 28 |
# File 'lib/aquarium/aspects/pointcut.rb', line 26 def specification @specification end |
Class Method Details
.make_attribute_reading_writing_options(options_hash) ⇒ Object
250 251 252 253 254 255 256 257 258 259 260 261 |
# File 'lib/aquarium/aspects/pointcut.rb', line 250 def self. result = {} [:writing, :changing, :reading].each do |attr_key| next if [attr_key].nil? or [attr_key].to_s.empty? result[:attributes] ||= Set.new([]) result[:attribute_options] ||= Set.new([]) result[:attributes].merge(Aquarium::Utils::ArrayUtils.make_array([attr_key])) attr_opt = attr_key == :reading ? :readers : :writers result[:attribute_options] << attr_opt end result end |
.validate_attribute_options(spec_hash, options_hash) ⇒ Object
280 281 282 283 284 285 286 287 |
# File 'lib/aquarium/aspects/pointcut.rb', line 280 def self. spec_hash, raise Aquarium::Utils::InvalidOptions.new(":all is not yet supported for :attributes.") if spec_hash[:attributes] == Set.new([:all]) if [:reading] and ([:writing] or [:changing]) unless [:reading].eql?([:writing]) or [:reading].eql?([: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 |
Instance Method Details
#and(pointcut2) ⇒ Object Also known as: intersection, &
24 25 26 27 28 29 30 31 32 33 34 35 |
# 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 |
#any_type_related_options_given? ⇒ Boolean
276 277 278 |
# File 'lib/aquarium/aspects/pointcut.rb', line 276 def 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? end |
#empty? ⇒ Boolean
220 221 222 |
# File 'lib/aquarium/aspects/pointcut.rb', line 220 def empty? return join_points_matched.empty? && join_points_not_matched.empty? end |
#eql?(other) ⇒ Boolean Also known as: ==
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
207 208 209 210 211 212 213 214 215 216 |
# 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 |
#finish_specification_initialization ⇒ Object
263 264 265 266 267 268 269 270 |
# File 'lib/aquarium/aspects/pointcut.rb', line 263 def finish_specification_initialization @specification.merge! Pointcut.(@original_options) # Map the method options to their canonical values: @specification[:method_options] = Aquarium::Finders::MethodFinder.(@specification[:method_options]) use_default_objects_if_defined unless Pointcut:: @specification, @original_options init_methods_specification end |
#init_methods_specification ⇒ Object
272 273 274 |
# 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 ⇒ Object Also known as: to_s
224 225 226 |
# 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 |
#or(pointcut2) ⇒ Object Also known as: union, |
9 10 11 12 13 14 15 16 17 18 19 |
# 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 |