# File lib/rgen/fragment/model_fragment.rb, line 178
  def resolve_external(external_index, options)
    fragment_provider = options[:fragment_provider]
    resolver = RGen::Instantiator::ReferenceResolver.new(
      :identifier_resolver => proc {|ident| external_index[ident] })
    if fragment_provider
      @resolved_refs = {} if @resolved_refs.nil? || @resolved_refs == :dirty
      on_resolve = proc { |ur, target|
        target_fragment = fragment_provider.call(target)
        target_fragment ||= :unknown
        raise "can not resolve local reference in resolve_external, call resolve_local first" \
          if target_fragment == self
        @resolved_refs[target_fragment] ||= []
        @resolved_refs[target_fragment] << ResolvedReference.new(ur, target)
      } 
      @unresolved_refs = resolver.resolve(unresolved_refs, :on_resolve => on_resolve, :use_target_type => options[:use_target_type])
    else
      @unresolved_refs = resolver.resolve(unresolved_refs, :use_target_type => options[:use_target_type])
    end
  end

  # Marks a particular unresolved reference +uref+ as resolved to +target+ in +target_fragment+.

  #

  def mark_resolved(uref, target_fragment, target)
    @resolved_refs = {} if @resolved_refs.nil? || @resolved_refs == :dirty
    target_fragment ||= :unknown
    if target_fragment != self
      @resolved_refs[target_fragment] ||= []
      @resolved_refs[target_fragment] << ResolvedReference.new(uref, target)
    end
    @removed_urefs ||= []
    @removed_urefs << uref
  end

  # Unresolve outgoing references to all external fragments, i.e. references which used to

  # be represented by an unresolved reference from within this fragment.

  # Note, that there may be more references to external fragments due to references which 

  # were represented by unresolved references from within other fragments.

  # 

  def unresolve_external
    return if @resolved_refs.nil?
    raise "can not unresolve, missing fragment information" if @resolved_refs == :dirty || @resolved_refs[:unknown]
    rrefs = @resolved_refs.values.flatten
    @resolved_refs = {}
    unresolve_refs(rrefs)
  end

  # Like unresolve_external but only unresolve references to external fragment +fragment+

  #

  def unresolve_external_fragment(fragment)
    return if @resolved_refs.nil?
    raise "can not unresolve, missing fragment information" if @resolved_refs == :dirty || @resolved_refs[:unknown]
    rrefs = @resolved_refs[fragment]
    @resolved_refs.delete(fragment)
    unresolve_refs(rrefs) if rrefs
  end

  private

  # Turns resolved references +rrefs+ back into unresolved references

  #

  def unresolve_refs(rrefs)
    # make sure any removed_urefs have been removed, 

    # otherwise they will be removed later even if this method actually re-added them

    unresolved_refs
    rrefs.each do |rr|
      ur = rr.uref
      refs = ur.element.getGeneric(ur.feature_name)
      if refs.is_a?(Array)
        index = refs.index(rr.target)
        ur.element.removeGeneric(ur.feature_name, rr.target)
        ur.element.addGeneric(ur.feature_name, ur.proxy, index)
      else
        ur.element.setGeneric(ur.feature_name, ur.proxy)
      end
      @unresolved_refs << ur
    end
  end

  def collect_unresolved_refs
    unresolved_refs = []
    elements.each do |e|
      each_reference_target(e) do |r, t|
        if t.is_a?(RGen::MetamodelBuilder::MMProxy)
          unresolved_refs << 
            RGen::Instantiator::ReferenceResolver::UnresolvedReference.new(e, r.name, t)
        end
      end
    end
    unresolved_refs
  end

  def each_reference_target(element)
    non_containment_references(element.class).each do |r|
      element.getGenericAsArray(r.name).each do |t|
        yield(r, t)
      end
    end
  end

  def all_child_elements(element, childs)
    containment_references(element.class).each do |r|
      element.getGenericAsArray(r.name).each do |c|
        childs << c
        all_child_elements(c, childs)
      end
    end
  end

  def containment_references(clazz)
    @@containment_references_cache ||= {}
    @@containment_references_cache[clazz] ||=
      clazz.ecore.eAllReferences.select{|r| r.containment}
  end

  def non_containment_references(clazz)
    @@non_containment_references_cache ||= {}
    @@non_containment_references_cache[clazz] ||= 
      clazz.ecore.eAllReferences.select{|r| !r.containment}
  end 

end