File: json_serializer.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 (121 lines) | stat: -rw-r--r-- 3,715 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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
module RGen

module Serializer

class JsonSerializer

  def initialize(writer, opts={})
    @writer = writer
    @elementIdentifiers = {}
    @identAttrName = opts[:identAttrName] || "name"
    @separator = opts[:separator] || "/"
    @leadingSeparator = opts.has_key?(:leadingSeparator) ? opts[:leadingSeparator] : true 
    @featureFilter = opts[:featureFilter]
    @identifierProvider = opts[:identifierProvider]
  end

  def elementIdentifier(element)
    ident = @identifierProvider && @identifierProvider.call(element)
    ident || (element.is_a?(RGen::MetamodelBuilder::MMProxy) && element.targetIdentifier) || qualifiedElementName(element)
  end

  # simple identifier calculation based on qualified names
  # prerequisits:
  # * containment relations must be bidirectionsl
  # * local name stored in single attribute +@identAttrName+ for all classes
  #
  def qualifiedElementName(element)
    return @elementIdentifiers[element] if @elementIdentifiers[element]
    localIdent = ((element.respond_to?(@identAttrName) && element.getGeneric(@identAttrName)) || "").strip
    parentRef = element.class.ecore.eAllReferences.select{|r| r.eOpposite && r.eOpposite.containment}.first
    parent = parentRef && element.getGeneric(parentRef.name)
    if parent
      if localIdent.size > 0
        parentIdent = qualifiedElementName(parent)
        result = parentIdent + @separator + localIdent
      else
        result = qualifiedElementName(parent)
      end
    else
      result = (@leadingSeparator ? @separator : "") + localIdent
    end
    @elementIdentifiers[element] = result
  end

  def serialize(elements)
    if elements.is_a?(Array)
      write("[ ")
      elements.each_with_index do |e, i| 
        serializeElement(e)
        write(",\n") unless i == elements.size-1 
      end
      write("]")
    else
      serializeElement(elements)
    end
  end

  def serializeElement(element, indent="")
    write(indent + "{ \"_class\": \""+element.class.ecore.name+"\"")
    element.class.ecore.eAllStructuralFeatures.each do |f|
      next if f.derived
      value = element.getGeneric(f.name)
      unless value == [] || value.nil? || 
        (f.is_a?(RGen::ECore::EReference) && f.eOpposite && f.eOpposite.containment) || 
        (@featureFilter && !@featureFilter.call(f)) 
        write(", ")
        writeFeature(f, value, indent)
      end
    end
    write(" }")
  end

  def writeFeature(feat, value, indent)
    write("\""+feat.name+"\": ")
    if feat.is_a?(RGen::ECore::EAttribute)
      if value.is_a?(Array)
        write("[ "+value.collect{|v| attributeValue(v, feat)}.join(", ")+" ]")
      else
        write(attributeValue(value, feat))
      end
    elsif !feat.containment
      if value.is_a?(Array)
        write("[ "+value.collect{|v| "\""+elementIdentifier(v)+"\""}.join(", ")+" ]")
      else
        write("\""+elementIdentifier(value)+"\"")
      end
    else
      if value.is_a?(Array)
        write("[ \n")
        value.each_with_index do |v, i|
          serializeElement(v, indent+"  ")
          write(",\n") unless i == value.size-1
        end
        write("]")
      else
        write("\n")
        serializeElement(value, indent+"  ")
      end
    end
  end

  def attributeValue(value, a)
    if a.eType == RGen::ECore::EString || a.eType.is_a?(RGen::ECore::EEnum)
      "\""+value.to_s.gsub('\\','\\\\\\\\').gsub('"','\\"').gsub("\n","\\n").gsub("\r","\\r").
        gsub("\t","\\t").gsub("\f","\\f").gsub("\b","\\b")+"\""
    else
      value.to_s
    end
  end
   
  private

  def write(s)
    @writer.write(s) 
  end
end

end

end