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