Class: Aquarium::Aspects::JoinPoint

Inherits:
Object
  • Object
show all
Defined in:
lib/aquarium/aspects/join_point.rb

Overview

JoinPoint

Encapsulates information about a Join Point that might be advised. JoinPoint objects are almost value objects; you can change the context object. TODO Separate out the read-only part from the variable part. This might require an API change!

Defined Under Namespace

Classes: Context, ContextNotCorrectlyDefined, ProceedMethodNotAvailable

Constant Summary collapse

NIL_OBJECT =

A “convenience” JoinPoint supporting the “Null Object Pattern.”

Aquarium::Utils::NilObject.new

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ JoinPoint

Create a join point object, specifying either one type or one object and a method. Only method join points are currently supported by Aquarium.

The supported options are

:type => type | type_name | type_name_regexp

A single type, type name or regular expression matching only one type. One and only one type or object is required. An error is raised otherwise.

:object => object

A single object. One and only one type or object is required. An error is raised otherwise.

:method_name | :method => method_name_or_symbol

A single method name or symbol. Only one is allowed, although the special flag :all is allowed, as long as only one method will be found, subject to the next option.

:class_method | :instance_method => true | false

Is the method a class or instance method? Defaults to :instance_method => true.

Note: The range of options is not as rich as for Pointcut, because it is expected that JoinPoint objects will be explicitly created only rarely by users of Aquarium. Most of the time, Pointcuts will be created.



120
121
122
123
124
125
126
127
128
129
130
# File 'lib/aquarium/aspects/join_point.rb', line 120

def initialize options = {}
  @target_type     = resolve_type options
  @target_object   = options[:object]
  @method_name     = options[:method_name] || options[:method]
  class_method     = options[:class_method].nil? ? false : options[:class_method]
  @instance_method = options[:instance_method].nil? ? (!class_method) : options[:instance_method]
  @instance_or_class_method  = @instance_method ? :instance : :class
  @visibility = Aquarium::Utils::MethodUtils.visibility(type_or_object, @method_name, class_or_instance_method_flag)
  @context = options[:context] || JoinPoint::Context.new
  assert_valid options
end

Instance Attribute Details

#contextObject

Returns the value of attribute context.



92
93
94
# File 'lib/aquarium/aspects/join_point.rb', line 92

def context
  @context
end

#instance_or_class_methodObject (readonly)

Returns the value of attribute instance_or_class_method.



93
94
95
# File 'lib/aquarium/aspects/join_point.rb', line 93

def instance_or_class_method
  @instance_or_class_method
end

#method_nameObject (readonly)

Returns the value of attribute method_name.



93
94
95
# File 'lib/aquarium/aspects/join_point.rb', line 93

def method_name
  @method_name
end

#target_objectObject (readonly)

Returns the value of attribute target_object.



93
94
95
# File 'lib/aquarium/aspects/join_point.rb', line 93

def target_object
  @target_object
end

#target_typeObject (readonly)

Returns the value of attribute target_type.



93
94
95
# File 'lib/aquarium/aspects/join_point.rb', line 93

def target_type
  @target_type
end

#visibilityObject (readonly)

Returns the value of attribute visibility.



93
94
95
# File 'lib/aquarium/aspects/join_point.rb', line 93

def visibility
  @visibility
end

Instance Method Details

#<=>(other) ⇒ Object



174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
# File 'lib/aquarium/aspects/join_point.rb', line 174

def <=> other
  return 0  if object_id == other.object_id 
  return 1  if other.nil?
  result = self.class <=> other.class
  return result unless result == 0
  result = compare_field(:target_object, other) {|f1,f2| f1.object_id <=> f2.object_id}
  return result unless result == 0
  result = compare_field(:instance_method, other) {|f1,f2| boolean_compare(f1,f2)}
  return result unless result == 0
  [:target_type, :method_name, :context].each do |field|
    result = compare_field field, other
    return result unless result == 0
  end
  0
end

#class_method?Boolean

Returns:

  • (Boolean)


99
100
101
# File 'lib/aquarium/aspects/join_point.rb', line 99

def class_method?
  !@instance_method
end

#dupObject



132
133
134
135
136
# File 'lib/aquarium/aspects/join_point.rb', line 132

def dup
  jp = super
  jp.context = @context.dup unless @context.nil?
  jp
end

#eql?(other) ⇒ Boolean Also known as: ==, ===

Returns:

  • (Boolean)


190
191
192
# File 'lib/aquarium/aspects/join_point.rb', line 190

def eql? other
  return (self <=> other) == 0
end

#exists?Boolean

Returns:

  • (Boolean)


144
145
146
147
148
149
150
151
# File 'lib/aquarium/aspects/join_point.rb', line 144

def exists?
  type_or_object_sym = @target_type ? :type : :object
  results = Aquarium::Finders::MethodFinder.new.find type_or_object_sym => type_or_object, 
                      :method => method_name, 
                      :method_options => [visibility, instance_or_class_method]
  raise Aquarium::Utils::LogicError("MethodFinder returned more than one item! #{results.inspect}") if (results.matched.size + results.not_matched.size) != 1
  return results.matched.size == 1 ? true : false
end

#inspectObject Also known as: to_s

todo: restore context output.



198
199
200
# File 'lib/aquarium/aspects/join_point.rb', line 198

def inspect
  "JoinPoint: {target_type = #{target_type.nil? ? target_type : target_type.name}, target_object = #{target_object.inspect}, method_name = #{method_name}, instance_method? #{instance_method?}, context = #{context.inspect}"
end

#instance_methodObject



170
171
172
# File 'lib/aquarium/aspects/join_point.rb', line 170

def instance_method
  @instance_method
end

#instance_method?Boolean

Returns:

  • (Boolean)


95
96
97
# File 'lib/aquarium/aspects/join_point.rb', line 95

def instance_method?
  @instance_method
end

#invoke_original_join_point(*args, &block) ⇒ Object

Invoke the join point itself, skipping any intermediate advice. This method can only be called if the join point has a context object defined that represents an actual runtime “state”. Use this method cautiously, at it could be “surprising” if some advice is not executed!



165
166
167
168
# File 'lib/aquarium/aspects/join_point.rb', line 165

def invoke_original_join_point *args, &block
  raise ContextNotCorrectlyDefined.new(":invoke_original_join_point can't be called unless the join point has a context object.") if context.nil?
  context.invoke_original_join_point self, *args, &block
end

#proceed(*args, &block) ⇒ Object

Invoke the join point itself (which could actually be aspect advice wrapping the original join point…). This method can only be called if the join point has a context object defined that represents an actual runtime “state”.



156
157
158
159
# File 'lib/aquarium/aspects/join_point.rb', line 156

def proceed *args, &block
  raise ContextNotCorrectlyDefined.new(":proceed can't be called unless the join point has a context object.") if context.nil?
  context.proceed self, *args, &block
end

#type_or_objectObject Also known as: target_type_or_object



138
139
140
# File 'lib/aquarium/aspects/join_point.rb', line 138

def type_or_object
  target_type || target_object
end