# 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: :: 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 # # 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.