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
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
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
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
def unresolve_refs(rrefs)
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