A FragmentedModel represents a model which consists of fragments (ModelFragment).
The main purpose of this class is to resolve references across fragments and to keep the references consistent while fragments are added or removed. This way it also plays an important role in keeping the model fragments consistent and thus ModelFragment objects should only be accessed via this interface. Overall unresolved references after the resolution step are also maintained.
A FragmentedModel can also keep an RGen::Environment object up to date while fragments are added or removed. The environment must be registered with the constructor.
Reference resolution is based on arbitrary identifiers. The identifiers must be provided in the fragments' indices. The FragmentedModel takes care to maintain the overall index.
Creates a fragmented model. Options:
:env environment which will be updated as model elements are added and removed
# File lib/rgen/fragment/fragmented_model.rb, line 31 def initialize(options={}) @environment = options[:env] @fragments = [] @index = nil @fragment_change_listeners = [] @fragment_index = {} end
Add a fragment.
# File lib/rgen/fragment/fragmented_model.rb, line 52 def add_fragment(fragment) invalidate_cache @fragments << fragment fragment.elements.each{|e| @environment << e} if @environment @fragment_change_listeners.each{|l| l.call(fragment, :added)} end
Adds a proc which is called when a fragment is added or removed The proc receives the fragment and one of :added, :removed
# File lib/rgen/fragment/fragmented_model.rb, line 42 def add_fragment_change_listener(listener) @fragment_change_listeners << listener end
Returns the overall index. This is a Hash mapping identifiers to model elements accessible via the identifier.
# File lib/rgen/fragment/fragmented_model.rb, line 112 def index fragments.each do |f| if !@fragment_index[f] || (@fragment_index[f].object_id != f.index.object_id) @fragment_index[f] = f.index invalidate_cache end end return @index if @index @index = {} fragments.each do |f| f.index.each do |i| (@index[i[0]] ||= []) << i[1] end end @index end
Removes the fragment. The fragment will be unresolved using unresolve_fragment.
# File lib/rgen/fragment/fragmented_model.rb, line 61 def remove_fragment(fragment) raise "fragment not part of model" unless @fragments.include?(fragment) invalidate_cache @fragments.delete(fragment) @fragment_index.delete(fragment) unresolve_fragment(fragment) fragment.elements.each{|e| @environment.delete(e)} if @environment @fragment_change_listeners.each{|l| l.call(fragment, :removed)} end
# File lib/rgen/fragment/fragmented_model.rb, line 46 def remove_fragment_change_listener(listener) @fragment_change_listeners.delete(listener) end
Resolve references between fragments. It is assumed that references within fragments have already been resolved. This method can be called several times. It will update the overall unresolved references.
Options:
:fragment_provider: Only if a +fragment_provider+ is given, the resolve step can be reverted later on by a call to unresolve_fragment. The fragment provider is a proc which receives a model element and must return the fragment in which the element is contained. :use_target_type: reference resolver uses the expected target type to narrow the set of possible targets
# File lib/rgen/fragment/fragmented_model.rb, line 85 def resolve(options) @fragments.each do |f| f.resolve_external(index, options) end end
Remove all references between this fragment and all other fragments. The references will be replaced with unresolved references (MMProxy objects).
# File lib/rgen/fragment/fragmented_model.rb, line 94 def unresolve_fragment(fragment) fragment.unresolve_external @fragments.each do |f| if f != fragment f.unresolve_external_fragment(fragment) end end end
Generated with the Darkfish Rdoc Generator 2.