lib/rgen/instantiator/json_instantiator.rb in rgen-0.5.3 vs lib/rgen/instantiator/json_instantiator.rb in rgen-0.5.4

- old
+ new

@@ -3,34 +3,63 @@ module RGen module Instantiator +# JsonInstantiator is used to create RGen models from JSON. +# +# Each JSON object needs to have an attribute "_class" which is used to find +# the metamodel class to instantiate. The value of "_class" should be the +# the relative qualified class name within the root package as a string. +# +# If the option "short_class_names" is set to true, unqualified class names can be used. +# In this case, metamodel classes are searched in the metamodel root package first. +# If this search is not successful, all subpackages will be searched for the class name. +# class JsonInstantiator + # Model elements will be created in evironment +env+, + # classes are looked for in metamodel package module +mm+, + # +options+ include: + # short_class_names: if true subpackages will be searched for unqualifed class names (default: true) + # The options are also passed to the underlying QualifiedNameResolver. + # def initialize(env, mm, options={}) @env = env @mm = mm @options = options + @short_class_names = !@options.has_key?(:short_class_names) || @options[:short_class_names] @unresolvedReferences = [] + @classes = {} + @classes_flat = {} + mm.ecore.eAllClasses.each do |c| + @classes[c.instanceClass.name.sub(mm.name+"::","")] = c + @classes_flat[c.name] = c + end @parser = JsonParser.new(self) end - # creates the elements described by the json string +str+ - # returns an array of ReferenceResolver::UnresolvedReference + # Creates the elements described by the json string +str+. + # Returns an array of ReferenceResolver::UnresolvedReference # describing the references which could not be resolved + # def instantiate(str) root = @parser.parse(str) resolver = QualifiedNameResolver.new(root, @options) resolver.resolveReferences(@unresolvedReferences) end def createObject(hash) className = hash["_class"] raise "no class information" unless className - clazz = @mm.const_get(className) - raise "class not found: #{className}" unless clazz + if @classes[className] + clazz = @classes[className].instanceClass + elsif @short_class_names && @classes_flat[className] + clazz = @classes_flat[className].instanceClass + else + raise "class not found: #{className}" + end hash.delete("_class") urefs = [] hash.keys.each do |k| f = eFeature(k, clazz) hash[k] = [hash[k]] if f.many && !hash[k].is_a?(Array) @@ -66,10 +95,14 @@ private def eFeature(name, clazz) @eFeature ||= {} @eFeature[clazz] ||= {} - @eFeature[clazz][name] ||= clazz.ecore.eAllStructuralFeatures.find{|f| f.name == name} + unless @eFeature[clazz][name] + feature = clazz.ecore.eAllStructuralFeatures.find{|f| f.name == name} + raise "feature '#{name}' not found in class '#{clazz}'" unless feature + end + @eFeature[clazz][name] ||= feature end end end