File: qualified_name_resolver.rb

package info (click to toggle)
ruby-rgen 0.10.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,428 kB
  • sloc: ruby: 11,344; xml: 1,368; yacc: 72; makefile: 10
file content (97 lines) | stat: -rw-r--r-- 2,917 bytes parent folder | download | duplicates (11)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
require 'rgen/instantiator/reference_resolver'

module RGen

module Instantiator

# This is a resolver resolving element identifiers which are qualified names.
class QualifiedNameResolver

  attr_reader :nameAttribute
  attr_reader :separator
  attr_reader :leadingSeparator

  def initialize(rootElements, options={})
    @rootElements = rootElements
    @nameAttribute = options[:nameAttribute] || "name"
    @separator = options[:separator] || "/"
    @leadingSeparator = options.has_key?(:leadingSeparator) ? options[:leadingSeparator] : true
    @elementByQName = {}
    @visitedQName = {}
    @childReferences = {}
    @resolverDelegate = ReferenceResolver.new(:identifier_resolver => method(:resolveIdentifier))
  end

  def resolveIdentifier(qualifiedName)
    return @elementByQName[qualifiedName] if @elementByQName.has_key?(qualifiedName)
    path = qualifiedName.split(separator).reject{|s| s == ""}
    if path.size > 1
      parentQName = (leadingSeparator ? separator : "") + path[0..-2].join(separator)
      parents = resolveIdentifier(parentQName)
      parents = [parents].compact unless parents.is_a?(Array)
      children = parents.collect{|p| allNamedChildren(p)}.flatten
    elsif path.size == 1
      parentQName = ""
      children = allRootNamedChildren
    else
      return @elementByQName[qualifiedName] = nil
    end
    # if the parent was already visited all matching elements are the hash 
    if !@visitedQName[parentQName]
      children.each do |c|
        name = c.send(nameAttribute)
        if name
          qname = parentQName + ((parentQName != "" || leadingSeparator) ? separator : "") + name
          existing = @elementByQName[qname]
          if existing 
            @elementByQName[qname] = [existing] unless existing.is_a?(Array)
            @elementByQName[qname] << c
          else
            @elementByQName[qname] = c 
          end
        end
      end
      # all named children of praent have been checked and hashed
      @visitedQName[parentQName] = true
    end
    @elementByQName[qualifiedName] ||= nil
  end

  def resolveReferences(unresolvedReferences, problems=[])
    @resolverDelegate.resolve(unresolvedReferences, :problems => problems)
  end

  private

  def allNamedChildren(element)
    childReferences(element.class).collect do |r|
      element.getGenericAsArray(r.name).collect do |c|
        if c.respond_to?(nameAttribute)
          c
        else
          allNamedChildren(c)
        end
      end
    end.flatten
  end

  def allRootNamedChildren
    @rootElements.collect do |e|
      if e.respond_to?(nameAttribute)
        e
      else
        allNamedChildren(e)
      end
    end.flatten
  end

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

end

end

end