Class: RGen::Fragment::FragmentedModel
- Inherits:
-
Object
- Object
- RGen::Fragment::FragmentedModel
- Defined in:
- lib/rgen/fragment/fragmented_model.rb
Overview
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.
Instance Attribute Summary collapse
-
#environment ⇒ Object
readonly
Returns the value of attribute environment.
-
#fragments ⇒ Object
readonly
Returns the value of attribute fragments.
Instance Method Summary collapse
-
#add_fragment(fragment) ⇒ Object
Add a fragment.
-
#add_fragment_change_listener(listener) ⇒ Object
Adds a proc which is called when a fragment is added or removed The proc receives the fragment and one of :added, :removed.
-
#index ⇒ Object
Returns the overall index.
-
#initialize(options = {}) ⇒ FragmentedModel
constructor
Creates a fragmented model.
-
#remove_fragment(fragment) ⇒ Object
Removes the fragment.
- #remove_fragment_change_listener(listener) ⇒ Object
-
#resolve(options = {}) ⇒ Object
Resolve references between fragments.
-
#unresolve_fragment(fragment) ⇒ Object
Remove all references between this fragment and all other fragments.
-
#unresolved_refs ⇒ Object
Returns the overall unresolved references.
Constructor Details
#initialize(options = {}) ⇒ FragmentedModel
Creates a fragmented model. Options:
:env
environment which will be updated as model elements are added and removed
31 32 33 34 35 36 37 |
# File 'lib/rgen/fragment/fragmented_model.rb', line 31 def initialize(={}) @environment = [:env] @fragments = [] @index = nil @fragment_change_listeners = [] @fragment_index = {} end |
Instance Attribute Details
#environment ⇒ Object (readonly)
Returns the value of attribute environment.
24 25 26 |
# File 'lib/rgen/fragment/fragmented_model.rb', line 24 def environment @environment end |
#fragments ⇒ Object (readonly)
Returns the value of attribute fragments.
23 24 25 |
# File 'lib/rgen/fragment/fragmented_model.rb', line 23 def fragments @fragments end |
Instance Method Details
#add_fragment(fragment) ⇒ Object
Add a fragment.
52 53 54 55 56 57 |
# 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 |
#add_fragment_change_listener(listener) ⇒ Object
Adds a proc which is called when a fragment is added or removed The proc receives the fragment and one of :added, :removed
42 43 44 |
# File 'lib/rgen/fragment/fragmented_model.rb', line 42 def add_fragment_change_listener(listener) @fragment_change_listeners << listener end |
#index ⇒ Object
Returns the overall index. This is a Hash mapping identifiers to model elements accessible via the identifier.
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/rgen/fragment/fragmented_model.rb', line 113 def index # Invalidate the cache when any fragment's local index changes. # Assumption: If the local index content changes, there is a new index object. 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 |
#remove_fragment(fragment) ⇒ Object
Removes the fragment. The fragment will be unresolved using unresolve_fragment.
61 62 63 64 65 66 67 68 69 |
# 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 |
#remove_fragment_change_listener(listener) ⇒ Object
46 47 48 |
# File 'lib/rgen/fragment/fragmented_model.rb', line 46 def remove_fragment_change_listener(listener) @fragment_change_listeners.delete(listener) end |
#resolve(options = {}) ⇒ Object
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
85 86 87 88 89 90 |
# File 'lib/rgen/fragment/fragmented_model.rb', line 85 def resolve(={}) local_index = index @fragments.each do |f| f.resolve_external(local_index, ) end end |
#unresolve_fragment(fragment) ⇒ Object
Remove all references between this fragment and all other fragments. The references will be replaced with unresolved references (MMProxy objects).
95 96 97 98 99 100 101 102 |
# File 'lib/rgen/fragment/fragmented_model.rb', line 95 def unresolve_fragment(fragment) fragment.unresolve_external @fragments.each do |f| if f != fragment f.unresolve_external_fragment(fragment) end end end |
#unresolved_refs ⇒ Object
Returns the overall unresolved references.
106 107 108 |
# File 'lib/rgen/fragment/fragmented_model.rb', line 106 def unresolved_refs @fragments.collect{|f| f.unresolved_refs}.flatten end |