Model
into a Neo4j database.nitc :: NeoModel :: _batch_max_size
How many operation can be executed in one batch?client
used to communicate with the Neo4j instance.
nitc :: NeoModel :: _mentities
Mentities associated to nodes.nitc :: NeoModel :: _toolcontext
The toolcontext used to init theNeoModel
tool.
nitc :: NeoModel :: batch_max_size
How many operation can be executed in one batch?nitc :: NeoModel :: batch_max_size=
How many operation can be executed in one batch?client
used to communicate with the Neo4j instance.
client
used to communicate with the Neo4j instance.
nitc :: NeoModel :: collect_model_edges
Collect all edges from the currentmodel
.
nitc :: NeoModel :: collect_model_nodes
Collect all nodes from the currentmodel
.
nitc :: NeoModel :: defaultinit
nitc :: NeoModel :: mentities=
Mentities associated to nodes.nitc :: NeoModel :: to_location
Get aLocation
from its string representation.
nitc :: NeoModel :: to_mclassdef
Build a newMClassDef
from a node
.
nitc :: NeoModel :: to_mentity
Get theMEntity
associated with node
.
nitc :: NeoModel :: to_mmodule
Build a newMModule
from a node
.
nitc :: NeoModel :: to_mpackage
Build a newMPackage
from a node
.
nitc :: NeoModel :: to_mparameter
Build a newMParameter
from node
.
nitc :: NeoModel :: to_mpropdef
Build a newMPropDef
from a node
.
nitc :: NeoModel :: to_mproperty
Build a newMProperty
from a node
.
nitc :: NeoModel :: to_visibility
Get aMVisibility
from its string representation.
nitc :: NeoModel :: toolcontext
The toolcontext used to init theNeoModel
tool.
nitc :: NeoModel :: toolcontext=
The toolcontext used to init theNeoModel
tool.
nitc :: NeoModel :: _batch_max_size
How many operation can be executed in one batch?client
used to communicate with the Neo4j instance.
nitc :: NeoModel :: _mentities
Mentities associated to nodes.nitc :: NeoModel :: _toolcontext
The toolcontext used to init theNeoModel
tool.
nitc :: NeoModel :: batch_max_size
How many operation can be executed in one batch?nitc :: NeoModel :: batch_max_size=
How many operation can be executed in one batch?core :: Object :: class_factory
Implementation used byget_class
to create the specific class.
client
used to communicate with the Neo4j instance.
client
used to communicate with the Neo4j instance.
nitc :: NeoModel :: collect_model_edges
Collect all edges from the currentmodel
.
nitc :: NeoModel :: collect_model_nodes
Collect all nodes from the currentmodel
.
nitc :: NeoModel :: defaultinit
core :: Object :: defaultinit
core :: Object :: is_same_instance
Return true ifself
and other
are the same instance (i.e. same identity).
core :: Object :: is_same_serialized
Isself
the same as other
in a serialization context?
core :: Object :: is_same_type
Return true ifself
and other
have the same dynamic type.
nitc :: NeoModel :: mentities=
Mentities associated to nodes.core :: Object :: native_class_name
The class name of the object in CString format.core :: Object :: output_class_name
Display class name on stdout (debug only).nitc :: NeoModel :: to_location
Get aLocation
from its string representation.
nitc :: NeoModel :: to_mclassdef
Build a newMClassDef
from a node
.
nitc :: NeoModel :: to_mentity
Get theMEntity
associated with node
.
nitc :: NeoModel :: to_mmodule
Build a newMModule
from a node
.
nitc :: NeoModel :: to_mpackage
Build a newMPackage
from a node
.
nitc :: NeoModel :: to_mparameter
Build a newMParameter
from node
.
nitc :: NeoModel :: to_mpropdef
Build a newMPropDef
from a node
.
nitc :: NeoModel :: to_mproperty
Build a newMProperty
from a node
.
nitc :: NeoModel :: to_visibility
Get aMVisibility
from its string representation.
nitc :: NeoModel :: toolcontext
The toolcontext used to init theNeoModel
tool.
nitc :: NeoModel :: toolcontext=
The toolcontext used to init theNeoModel
tool.
# Helper class that can save and load a `Model` into a Neo4j database.
class NeoModel
# The model name.
#
# Because we use only one Neo4j instance to store all the models,
# we need to mark their appartenance to a particular model and avoid loading all models.
#
# The name is used as a Neo label on each created nodes and used to load nodes from base.
var model_name: String
# The toolcontext used to init the `NeoModel` tool.
var toolcontext: ToolContext
# The Neo4j `client` used to communicate with the Neo4j instance.
var client: Neo4jClient
# Fill `model` using base pointed by `client`.
fun load(model: Model): Model do
var nodes: Array[NeoNode]
toolcontext.info("Loading package node...", 1)
nodes = client.nodes_with_labels([model_name, "MPackage"])
for node in nodes do to_mpackage(model, node)
toolcontext.info("Loading groups...", 1)
nodes = client.nodes_with_labels([model_name, "MGroup"])
for node in nodes do to_mgroup(model, node)
toolcontext.info("Loading modules...", 1)
nodes = client.nodes_with_labels([model_name, "MModule"])
for node in nodes do to_mmodule(model, node)
toolcontext.info("Loading classes...", 1)
nodes = client.nodes_with_labels([model_name, "MClass"])
for node in nodes do to_mclass(model, node)
toolcontext.info("Loading class definitions...", 1)
nodes = client.nodes_with_labels([model_name, "MClassDef"])
for node in nodes do to_mclassdef(model, node)
toolcontext.info("Loading properties...", 1)
nodes = client.nodes_with_labels([model_name, "MProperty"])
for node in nodes do to_mproperty(model, node)
toolcontext.info("Loading property definitions...", 1)
nodes = client.nodes_with_labels([model_name, "MPropDef"])
for node in nodes do to_mpropdef(model, node)
return model
end
# Save `model` in the base pointed by `client`.
fun save(model: Model) do
var nodes = collect_model_nodes(model)
toolcontext.info("Save {nodes.length} nodes...", 1)
push_all(nodes)
var edges = collect_model_edges(model)
toolcontext.info("Save {edges.length} edges...", 1)
push_all(edges)
end
# Save `neo_entities` in base using batch mode.
private fun push_all(neo_entities: Collection[NeoEntity]) do
var batch = new NeoBatch(client)
var len = neo_entities.length
var sum = 0
var i = 1
for nentity in neo_entities do
batch.save_entity(nentity)
if i == batch_max_size then
do_batch(batch)
sum += batch_max_size
toolcontext.info(" {sum * 100 / len}% done", 1)
batch = new NeoBatch(client)
i = 1
else
i += 1
end
end
do_batch(batch)
end
# How many operation can be executed in one batch?
private var batch_max_size = 1000
# Execute `batch` and check for errors.
#
# Abort if `batch.execute` returns errors.
private fun do_batch(batch: NeoBatch) do
var errors = batch.execute
if not errors.is_empty then
print errors
exit(1)
end
end
# Collect all nodes from the current `model`.
private fun collect_model_nodes(model: Model): Collection[NeoNode] do
for mpackage in model.mpackages do
mpackage.to_node(nodes, model_name)
for mgroup in mpackage.mgroups do mgroup.to_node(nodes, model_name)
end
return nodes.values
end
# Collect all edges from the current `model`.
#
# Actually collect all out_edges from all nodes.
private fun collect_model_edges(model: Model): Collection[NeoEdge] do
var edges = new HashSet[NeoEdge]
for node in nodes.values do edges.add_all(node.out_edges)
return edges
end
# Mentities associated to nodes.
#
# The key is the node’s id.
private var mentities = new HashMap[Int, MEntity]
# Nodes associated with MEntities.
private var nodes = new HashMap[MEntity, NeoNode]
# Get the `MEntity` associated with `node`.
fun to_mentity(model: Model, node: NeoNode): MEntity do
if node.labels.has("MPackage") then return to_mpackage(model, node)
if node.labels.has("MGroup") then return to_mgroup(model, node)
if node.labels.has("MModule") then return to_mmodule(model, node)
if node.labels.has("MClass") then return to_mclass(model, node)
if node.labels.has("MClassDef") then return to_mclassdef(model, node)
if node.labels.has("MProperty") then return to_mproperty(model, node)
if node.labels.has("MPropDef") then return to_mpropdef(model, node)
if node.labels.has("MType") then return to_mtype(model, node)
if node.labels.has("MParameter") then return to_mparameter(model, node)
abort
end
# Build a new `MPackage` from a `node`.
#
# REQUIRE `node.labels.has("MPackage")`
private fun to_mpackage(model: Model, node: NeoNode): MPackage do
var m = mentities.get_or_null(node.id.as(Int))
if m isa MPackage then return m
assert node.labels.has("MPackage")
var location = to_location(node["location"].to_s)
var mpackage = new MPackage(node["name"].to_s, model, location)
mentities[node.id.as(Int)] = mpackage
set_doc(node, mpackage)
mpackage.root = to_mgroup(model, node.out_nodes("ROOT").first)
return mpackage
end
# Build a new `MGroup` from a `node`.
#
# REQUIRE `node.labels.has("MGroup")`
private fun to_mgroup(model: Model, node: NeoNode): MGroup do
var m = mentities.get_or_null(node.id.as(Int))
if m isa MGroup then return m
assert node.labels.has("MGroup")
var location = to_location(node["location"].to_s)
var mpackage = to_mpackage(model, node.out_nodes("PROJECT").first)
var parent: nullable MGroup = null
var out = node.out_nodes("PARENT")
if not out.is_empty then
parent = to_mgroup(model, out.first)
end
var mgroup = new MGroup(node["name"].to_s, location, mpackage, parent)
mentities[node.id.as(Int)] = mgroup
set_doc(node, mgroup)
return mgroup
end
# Build a new `MModule` from a `node`.
#
# REQUIRE `node.labels.has("MModule")`
private fun to_mmodule(model: Model, node: NeoNode): MModule do
var m = mentities.get_or_null(node.id.as(Int))
if m isa MModule then return m
assert node.labels.has("MModule")
var ins = node.in_nodes("DECLARES")
var mgroup: nullable MGroup = null
if not ins.is_empty then
mgroup = to_mgroup(model, ins.first)
end
var name = node["name"].to_s
var location = to_location(node["location"].to_s)
var mmodule = new MModule(model, mgroup, name, location)
mentities[node.id.as(Int)] = mmodule
set_doc(node, mmodule)
var imported_mmodules = new Array[MModule]
for smod in node.out_nodes("IMPORTS") do
imported_mmodules.add to_mmodule(model, smod)
end
mmodule.set_imported_mmodules(imported_mmodules)
return mmodule
end
# Build a new `MClass` from a `node`.
#
# REQUIRE `node.labels.has("MClass")`
private fun to_mclass(model: Model, node: NeoNode): MClass do
var m = mentities.get_or_null(node.id.as(Int))
if m isa MClass then return m
assert node.labels.has("MClass")
var mmodule = to_mmodule(model, node.in_nodes("INTRODUCES").first)
var name = node["name"].to_s
var location = to_location(node["location"].to_s)
var kind = to_kind(node["kind"].to_s)
var visibility = to_visibility(node["visibility"].to_s)
var parameter_names = new Array[String]
if node.has_key("parameter_names") then
for e in node["parameter_names"].as(JsonArray) do
parameter_names.add e.to_s
end
end
var mclass = new MClass(mmodule, name, location, parameter_names, kind, visibility)
mentities[node.id.as(Int)] = mclass
set_doc(node, mclass)
return mclass
end
# Build a new `MClassDef` from a `node`.
#
# REQUIRE `node.labels.has("MClassDef")`
private fun to_mclassdef(model: Model, node: NeoNode): MClassDef do
var m = mentities.get_or_null(node.id.as(Int))
if m isa MClassDef then return m
assert node.labels.has("MClassDef")
var mmodule = to_mmodule(model, node.in_nodes("DEFINES").first)
var mtype = to_mtype(model, node.out_nodes("BOUNDTYPE").first).as(MClassType)
var location = to_location(node["location"].to_s)
var mclassdef = new MClassDef(mmodule, mtype, location)
mentities[node.id.as(Int)] = mclassdef
set_doc(node, mclassdef)
var supertypes = new Array[MClassType]
for sup in node.out_nodes("INHERITS") do
supertypes.add to_mtype(model, sup).as(MClassType)
end
mclassdef.set_supertypes(supertypes)
mclassdef.add_in_hierarchy
return mclassdef
end
# Build a new `MProperty` from a `node`.
#
# REQUIRE `node.labels.has("MProperty")`
private fun to_mproperty(model: Model, node: NeoNode): MProperty do
var m = mentities.get_or_null(node.id.as(Int))
if m isa MProperty then return m
assert node.labels.has("MProperty")
var intro_mclassdef = to_mclassdef(model, node.out_nodes("INTRO_CLASSDEF").first)
var name = node["name"].to_s
var location = to_location(node["location"].to_s)
var visibility = to_visibility(node["visibility"].to_s)
var mprop: nullable MProperty = null
if node.labels.has("MMethod") then
mprop = new MMethod(intro_mclassdef, name, location, visibility)
mprop.is_init = node["is_init"].as(Bool)
else if node.labels.has("MAttribute") then
mprop = new MAttribute(intro_mclassdef, name, location, visibility)
else if node.labels.has("MVirtualTypeProp") then
mprop = new MVirtualTypeProp(intro_mclassdef, name, location, visibility)
else if node.labels.has("MInnerClass") then
var inner = to_mclass(model, node.out_nodes("NESTS").first)
mprop = new MInnerClass(intro_mclassdef, name, location, visibility, inner)
end
if mprop == null then
print "not yet implemented to_mproperty for {node.labels.join(",")}"
abort
end
mentities[node.id.as(Int)] = mprop
set_doc(node, mprop)
return mprop
end
# Build a new `MPropDef` from a `node`.
#
# REQUIRE `node.labels.has("MPropDef")`
private fun to_mpropdef(model: Model, node: NeoNode): MPropDef do
var m = mentities.get_or_null(node.id.as(Int))
if m isa MPropDef then return m
assert node.labels.has("MPropDef")
var mclassdef = to_mclassdef(model, node.in_nodes("DECLARES").first)
var mproperty = to_mproperty(model, node.out_nodes("DEFINES").first)
var location = to_location(node["location"].to_s)
var mpropdef: nullable MPropDef = null
if node.labels.has("MMethodDef") then
mpropdef = new MMethodDef(mclassdef, mproperty.as(MMethod), location)
mpropdef.is_abstract = node["is_abstract"].as(Bool)
mpropdef.is_intern = node["is_intern"].as(Bool)
mpropdef.is_extern = node["is_extern"].as(Bool)
mentities[node.id.as(Int)] = mpropdef
mpropdef.msignature = to_mtype(model, node.out_nodes("SIGNATURE").first).as(MSignature)
else if node.labels.has("MAttributeDef") then
mpropdef = new MAttributeDef(mclassdef, mproperty.as(MAttribute), location)
mentities[node.id.as(Int)] = mpropdef
var static_mtype = node.out_nodes("TYPE")
if not static_mtype.is_empty then mpropdef.static_mtype = to_mtype(model, static_mtype.first)
else if node.labels.has("MVirtualTypeDef") then
mpropdef = new MVirtualTypeDef(mclassdef, mproperty.as(MVirtualTypeProp), location)
mentities[node.id.as(Int)] = mpropdef
var bound = node.out_nodes("BOUND")
if not bound.is_empty then mpropdef.bound = to_mtype(model, bound.first)
else if node.labels.has("MInnerClassDef") then
var inner = to_mclassdef(model, node.out_nodes("NESTS").first)
mpropdef = new MInnerClassDef(mclassdef,
mproperty.as(MInnerClass), location, inner)
mentities[node.id.as(Int)] = mpropdef
end
if mpropdef == null then
print "not yet implemented to_mpropdef for {node.labels.join(",")}"
abort
end
set_doc(node, mpropdef)
return mpropdef
end
# Build a new `MType` from a `node`.
#
# REQUIRE `node.labels.has("MType")`
private fun to_mtype(model: Model, node: NeoNode): MType do
var m = mentities.get_or_null(node.id.as(Int))
if m isa MType then return m
assert node.labels.has("MType")
if node.labels.has("MClassType") then
var mclass = to_mclass(model, node.out_nodes("CLASS").first)
var args = new Array[MType]
for narg in node.out_nodes("ARGUMENT") do
args.add to_mtype(model, narg)
end
var mtype = mclass.get_mtype(args)
mentities[node.id.as(Int)] = mtype
return mtype
else if node.labels.has("MParameterType") then
var mclass = to_mclass(model, node.out_nodes("CLASS").first)
var rank = node["rank"].to_s.to_i
var mtype = mclass.mparameters[rank]
mentities[node.id.as(Int)] = mtype
return mtype
else if node.labels.has("MNullableType") then
var intype = to_mtype(model, node.out_nodes("TYPE").first)
var mtype = intype.as_nullable
mentities[node.id.as(Int)] = mtype
return mtype
else if node.labels.has("MVirtualType") then
var mproperty = to_mproperty(model, node.out_nodes("PROPERTY").first)
assert mproperty isa MVirtualTypeProp
var mtype = mproperty.mvirtualtype
mentities[node.id.as(Int)] = mtype
return mtype
else if node.labels.has("MSignature") then
# Get all param nodes
var mparam_nodes = new HashMap[String, MParameter]
for pnode in node.out_nodes("PARAMETER") do
var mparam = to_mparameter(model, pnode)
mparam_nodes[mparam.name] = mparam
end
# Load params in the good order
var mparam_names = node["parameter_names"]
var mparameters = new Array[MParameter]
if mparam_names isa JsonArray then
for mparam_name in mparam_names do
var mparam = mparam_nodes[mparam_name.to_s]
mparameters.add mparam
end
end
var return_mtype: nullable MType = null
var ret_nodes = node.out_nodes("RETURNTYPE")
if not ret_nodes.is_empty then
return_mtype = to_mtype(model, ret_nodes.first)
end
var mtype = new MSignature(mparameters, return_mtype)
mentities[node.id.as(Int)] = mtype
return mtype
else if node.labels.has("MRawType") then
var mtype = new MRawType(model)
var parts = node["text"]
if parts isa JsonArray then
for p in parts do
mtype.parts.add(new MTypePart(model, p.to_s, null))
end
for pnode in node.out_nodes("LINK") do
assert pnode.labels.has("MTypePart")
if not pnode.out_nodes("TARGET").is_empty then
var rank = pnode["rank"]
var target = to_mentity(model, pnode.out_nodes("TARGET").first)
assert rank isa Int
mtype.parts[rank] = mtype.parts[rank].link_to(target)
end
end
end
mentities[node.id.as(Int)] = mtype
return mtype
end
print "not yet implemented to_mtype for {node.labels.join(",")}"
abort
end
# Build a new `MParameter` from `node`.
#
# REQUIRE `node.labels.has("MParameter")`
private fun to_mparameter(model: Model, node: NeoNode): MParameter do
var m = mentities.get_or_null(node.id.as(Int))
if m isa MParameter then return m
assert node.labels.has("MParameter")
var name = node["name"].to_s
var mtype = to_mtype(model, node.out_nodes("TYPE").first)
var is_vararg = node["is_vararg"].as(Bool)
var mparameter = new MParameter(name, mtype, is_vararg)
mentities[node.id.as(Int)] = mparameter
return mparameter
end
# Get a `Location` from its string representation.
private fun to_location(loc: String): nitc::Location do
return new nitc::Location.from_string(loc)
end
# Get a `MVisibility` from its string representation.
private fun to_visibility(vis: String): MVisibility do
if vis == intrude_visibility.to_s then
return intrude_visibility
else if vis == public_visibility.to_s then
return public_visibility
else if vis == protected_visibility.to_s then
return protected_visibility
else if vis == private_visibility.to_s then
return private_visibility
else if vis == package_visibility.to_s then
return package_visibility
else
return none_visibility
end
end
# Get a `MKind` from its string representation.
private fun to_kind(kind: String): MClassKind do
if kind == abstract_kind.to_s then
return abstract_kind
else if kind == concrete_kind.to_s then
return concrete_kind
else if kind == interface_kind.to_s then
return interface_kind
else if kind == enum_kind.to_s then
return enum_kind
else if kind == extern_kind.to_s then
return extern_kind
else
return raw_kind(kind)
end
end
# Extract the `MDoc` from `node` and link it to `mentity`.
private fun set_doc(node: NeoNode, mentity: MEntity) do
if node.has_key("mdoc") then
var lines = new Array[String]
for e in node["mdoc"].as(JsonArray) do
lines.add e.to_s#.replace("\n", "\\n")
end
var location = to_location(node["mdoc_location"].to_s)
var mdoc = new MDoc(location)
mdoc.content.add_all(lines)
mdoc.original_mentity = mentity
mentity.mdoc = mdoc
end
end
end
src/neo.nit:215,1--683,3