7738a4aa3ff6937e0737b3a149beb74ccdb781f5
[nit.git] / contrib / neo_doxygen / src / neo_doxygen.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 # Doxygen XML to Neo4j
16 #
17 # ## Synopsis
18 #
19 # neo_doxygen project_name xml_output_dir [neo4j_url]
20 #
21 # ## Description
22 #
23 # Convert a Doxygen XML output into a model in Neo4j that is readable by the
24 # `nx` tool.
25 #
26 # ## Arguments
27 #
28 # * project_name: The internal name of the project. Must the same name as the
29 # one specified to the `nx` tool.
30 #
31 # * xml_output_dir: The directory where the XML documents generated by Doxygen
32 # are located.
33 #
34 # * neo4j_url: The URL of the instance of Neo4j to use.
35 # `http://localhost:7474` by default.
36 module neo_doxygen
37
38 import model
39 import doxml
40
41 # An importation task.
42 class NeoDoxygen
43 var client: Neo4jClient
44 var model: ProjectGraph is noinit
45
46 # How many operation can be executed in one batch?
47 private var batch_max_size = 1000
48
49 # Generate a graph from the specified project model.
50 #
51 # Parameters:
52 #
53 # * `name`: project name.
54 # * `dir`: Doxygen XML output directory path.
55 fun put_project(name: String, dir: String) do
56 model = new ProjectGraph(name)
57 # TODO Let the user select the language.
58 var reader = new CompoundFileReader(model, new JavaSource)
59 # Queue for sub-directories.
60 var directories = new Array[String]
61
62 if dir.length > 1 and dir.chars.last == "/" then
63 dir = dir.substring(0, dir.length - 1)
64 end
65 loop
66 for f in dir.files do
67 var path = dir/f
68 if path.file_stat.is_dir then
69 directories.push(path)
70 else if f.has_suffix(".xml") and f != "index.xml" then
71 print "Processing {path}..."
72 reader.read(path)
73 end
74 end
75 if directories.length <= 0 then break
76 dir = directories.pop
77 end
78 end
79
80 # Save the graph.
81 fun save do
82 model.put_edges
83 var nodes = model.all_nodes
84 print("Saving {nodes.length} nodes...")
85 push_all(nodes)
86 var edges = model.all_edges
87 print("Saving {edges.length} edges...")
88 push_all(edges)
89 end
90
91 # Save `neo_entities` in the database using batch mode.
92 private fun push_all(neo_entities: Collection[NeoEntity]) do
93 var batch = new NeoBatch(client)
94 var len = neo_entities.length
95 var sum = 0
96 var i = 1
97
98 for nentity in neo_entities do
99 batch.save_entity(nentity)
100 if i == batch_max_size then
101 do_batch(batch)
102 sum += batch_max_size
103 print("\t{sum * 100 / len}% done.")
104 batch = new NeoBatch(client)
105 i = 1
106 else
107 i += 1
108 end
109 end
110 do_batch(batch)
111 end
112
113 # Execute `batch` and check for errors.
114 #
115 # Abort if `batch.execute` returns errors.
116 private fun do_batch(batch: NeoBatch) do
117 var errors = batch.execute
118 if not errors.is_empty then
119 for e in errors do sys.stderr.write("{sys.program_name}: {e}\n")
120 exit(1)
121 end
122 end
123 end
124
125 if args.length != 2 and args.length != 3 then
126 stderr.write("Usage: {sys.program_name} project_name xml_output_dir [neo4j_url]\n")
127 exit(1)
128 end
129 var url = "http://localhost:7474"
130 if args.length >= 3 then
131 url = args[2]
132 end
133
134 var neo = new NeoDoxygen(new Neo4jClient(url))
135 neo.put_project(args[0], args[1])
136 neo.save