# This class exists for parsing functionality only.
# The derived Connector will get a static Array with all Deployments weaved in
# and an accessor method: get_all_deployments.
class Connector
# Logging capabilities for Connector-class itself, because it is only static
class << self
include Logging::Log
end
# temporal static variable
@@active_deploy = nil
# All deployments. Teamclass => Array of deployments
ClassDeployments = Hash.new
# RoleClass of BaseClass. TeamClass => [BaseClass => RoleClass]
TeamRoleclassOf = Hash.new
# This regular expression is used to split namespaces
NamespaceRE = /::/
# This singleton method is called only by derived classes from singleton
# methods. Self must be a derived class!
# Returns a list of all deployments that are suitable for the
# connectorclass (all deployments climbing from connectorclass until
# Connector).
#
# [return] list of deployments.
def Connector.get_all_deployments()
result = Array.new
connector = self
while (connector != Connector)
deploys = ClassDeployments[connector]
if (!deploys.nil?)
result = result.concat(deploys)
end
connector = connector.superclass
end
return result
end
# Add deployment in the context of a specific Connector.
# This deployment is remembered and returned by get_all_deployments
# called from given connector.
#
# [connector] the connector in which the deployment is active
# [deployment] the deployment to remember
# [return] nil
def Connector.add_deployment(connector, deployment)
deployments = ClassDeployments[connector]
if (deployments.nil?)
deployments = Array.new
ClassDeployments[connector] = deployments
ClassDeployments.rehash
end
deployments.push(deployment)
end
# Returns the roleclass of a given baseclass, if called from
# a connector.
# [baseclass] the relational baseclass
# [return] roleclass of the given baseclass in context of this connector(self) or nil.
def Connector.get_roleclass_of(baseclass)
result = nil
connector= self
savebase = baseclass
#climb in connector hierarchy until Connector class itself.
while (connector!=Connector and result.nil?)
teamhash = TeamRoleclassOf[connector]
#climb in baseclass hierarchy until Object
while (!teamhash.nil? and baseclass!=Object and result.nil?)
result = teamhash[baseclass]
baseclass = baseclass.superclass
end
connector = connector.superclass
baseclass = savebase
end
#if a classname is found, get the real class: <myTeam>::<result>
if (result.instance_of?(String))
result = self.const_get(result)
end
#this is a class or nil
return result
end
# Remember the given roleclass to the given baseclass in context of a given
# connector.
# [connector] context of the relation
# [baseclass] a baseclass
# [roleclass] the relational roleclass as string
def Connector.set_roleclass_of(connector, baseclass, roleclass)
teamhash = TeamRoleclassOf[connector]
if (teamhash.nil?)
teamhash = Hash.new
TeamRoleclassOf[connector] = teamhash
TeamRoleclassOf.rehash
end
# If the given roleclass is defined (->scoped) in the team, forget about
# the scope and remember just the classname. Through implicit inheritance
# the most specific type of this role is used -> myTeam::roleclass.
# If the given role is not defined in the team, remeber just the plain
# class, which will get instantiated during lifting.
classname = roleclass.name.split(NamespaceRE)[-1]
if (self.const_defined?(classname) and self.const_get(classname).instance_of?(Class))
teamhash[baseclass] = classname
else
teamhash[baseclass] = roleclass
end
end
# Given baseclass shall play the role of the given roleclass in the
# context of this connector (self).
# Rememeber relation from baseclass to roleclass in this context (self).
# Intercept baseclass.
#
# [roleclass] the role to apply
# [baseclass] the baseclass that gets the role applied
def Connector.play_role(roleclass, baseclass)
#check for valid classes
ot_assert(roleclass.instance_of?(Class), "play_role: need a class for role. got: #{roleclass.to_s}")
ot_assert(baseclass.instance_of?(Class), "play_role: need a class for base. got: #{baseclass.to_s}")
debug(self, "#{baseclass.name} played by #{roleclass.name}")
#create a deploy holder
@@active_deploy = Deploy.new(baseclass, roleclass)
if (block_given?)
yield
end
#add deployment descripor to list
add_deployment(self, @@active_deploy)
set_roleclass_of(self, baseclass, roleclass)
#generate default ctor for role class
Interceptor.generate_ctor(roleclass)
end
# Check if the given methods are valid.
# [rolemethod] the rolemethod to call
# [basemethod] the basemethod that gets called
def Connector.check_validity(rolemethod, basemethod)
#check for an active deployment descriptor
if (@@active_deploy.nil?)
raise ObjectTeam::TeamException, "no deployment active. call play_role with valid values first.", caller
end
#check for nil
if (rolemethod.nil? or basemethod.nil?)
raise ObjectTeam::TeamException, "check_validity: weave rolemethod (#{rolemethod}) to basemethod (#{basemethod}) - got nil!", caller
end
end
# Add a callin binding in the context of this connector.
# [mode] Mode::{AFTER|BEFORE|REPLACE|CALLIN}
# [weavemethod] method definition of rolemethod (String|Symbol)
# [basemethod] method definition of basemethod (String|Symbol|Regexp)
# [match_parameter] a proc object that adapts input parameter of basemethod.
def Connector.add_callin(mode, weavemethod, basemethod, match_parameter)
#check validity of given params and state
check_validity(weavemethod, basemethod)
debug(self, "new callin binding: #{weavemethod} #{Mode.to_string(mode)} #{basemethod}")
#intercept the method to make this callin work
Interceptor.intercept(@@active_deploy.baseclass, as_str(basemethod))
#create deployment and append to list
@@active_deploy.add_callin(Callin.new(as_str(basemethod), as_str(weavemethod), mode, match_parameter))
end
# Call role.weavemethod before base.basemethod (role.weavemethod <-before base.basemethod)
# [weavemethod] method definition of rolemethod (String|Symbol)
# [basemethod] method definition of basemethod (String|Symbol|Regexp)
# [match_parameter] a proc object that adapts input parameter of basemethod.
def Connector.before(weavemethod, basemethod, &match_parameter)
add_callin(Mode::BEFORE, weavemethod, basemethod, match_parameter)
end
# Call role.weavemethod after base.basemethod (role.weavemethod <-after base.basemethod)
# [weavemethod] method definition of rolemethod (String|Symbol)
# [basemethod] method definition of basemethod (String|Symbol|Regexp)
# [match_parameter] a proc object that adapts input parameter of basemethod.
def Connector.after(weavemethod, basemethod, &match_parameter)
add_callin(Mode::AFTER, weavemethod, basemethod, match_parameter)
end
# Make Role.weavemethod call available under base.basemethod. (role.weavemethod <- base.basemethod)
# [weavemethod] method definition of rolemethod (String|Symbol)
# [basemethod] method definition of basemethod (String|Symbol|Regexp)
# [match_parameter] a proc object that adapts input parameter of basemethod.
def Connector.callin(weavemethod, basemethod=weavemethod, &match_parameter)
#TODO: the weaved method could registered by a different name
add_callin(Mode::CALLIN, weavemethod, basemethod, match_parameter)
end
# Replace base.basemethod with role.weavemethod. (role.weavemethod <= base.basemethod)
# [weavemethod] method definition of rolemethod (String|Symbol)
# [basemethod] method definition of basemethod (String|Symbol|Regexp)
# [match_parameter] a proc object that adapts input parameter of basemethod.
def Connector.replace(weavemethod, basemethod, &match_parameter)
add_callin(Mode::REPLACE, weavemethod, basemethod, match_parameter)
end
# Delegate expected role method to the given basemethod. (role.method -> base.method)
# [weavemethod] method definition of rolemethod (String|Symbol)
# [basemethod] method definition of basemethod (String|Symbol)
# [match_parameter] a proc object that adapts input parameter of basemethod.
def Connector.delegate_to(weavemethod, basemethod, &match_parameter)
check_validity(weavemethod, basemethod)
debug(self, "new callout binding: #{weavemethod} delegate_to #{basemethod}")
#create deployment and append to list
@@active_deploy.add_callout(Callout.new(as_str(weavemethod), as_str(basemethod), match_parameter))
end
# Returns the string representation from given object.
# [object] is a {String|Symbol} => String
# [return] string representation of object.
def Connector.as_str(object)
result = object
if (object.is_a?(String) or object.is_a?(Array) or object.is_a?(Regexp))
result = object
elsif (object.is_a?(Symbol))
result = object.id2name
else
raise ObjectTeam::TeamException, "Need String - got #{object.class.name}: #{object.inspect}", caller
end
return result
end
#Java syntax compatibility --(start)-----------------------------------------------------------
def Connector.playRole(roleclass, baseclass, &block)
play_role(roleclass, baseclass, &block)
end
def Connector.delegateTo(weavemethod, basemethod, &match_parameter)
delegate_to(weavemethod, basemethod, &match_parameter)
end
#Java syntax compatibility --(end )-----------------------------------------------------------
end
# Connector.rb April 2002
#
# Copyright (c) 2002 by Matthias Veit <matthias_veit@yahoo.de>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
syntax highlighted by Code2HTML, v. 0.9.1