@@ -2,14 +2,19 @@ package api
22
33import api .Permission ._
44import play .api .libs .iteratee .Enumerator
5+
56import scala .concurrent .{ExecutionContext , Future }
67import play .api .libs .concurrent .Execution .Implicits ._
78import play .api .mvc .Controller
89import play .api .Logger
910import javax .inject .Inject
10- import java .util .{TimeZone , Date }
11+ import java .util .{Date , TimeZone }
12+
1113import services ._
12- import models .{File , Dataset , Collection , ProjectSpace , User , UserStatus }
14+ import models .{Collection , Dataset , File , ProjectSpace , UUID , User , UserStatus }
15+ import util .Parsers
16+
17+ import scala .collection .mutable .ListBuffer
1318
1419
1520/**
@@ -25,10 +30,10 @@ class Reporting @Inject()(selections: SelectionService,
2530 val dateFormat = new java.text.SimpleDateFormat (" yyyy-MM-dd'T'HH:mm:ss.SSS'Z'" )
2631 dateFormat.setTimeZone(TimeZone .getTimeZone(" GMT" ))
2732
28- def fileMetrics () = ServerAdminAction { implicit request =>
33+ def fileMetrics (since : Option [ String ], until : Option [ String ] ) = ServerAdminAction { implicit request =>
2934 Logger .debug(" Generating file metrics report" )
3035
31- val results = files.getMetrics( )
36+ val results = files.getIterator( None , since, until )
3237 var headerRow = true
3338 val enum = Enumerator .generateM({
3439 val chunk = if (headerRow) {
@@ -58,10 +63,10 @@ class Reporting @Inject()(selections: SelectionService,
5863 )
5964 }
6065
61- def datasetMetrics () = ServerAdminAction { implicit request =>
66+ def datasetMetrics (since : Option [ String ], until : Option [ String ] ) = ServerAdminAction { implicit request =>
6267 Logger .debug(" Generating dataset metrics report" )
6368
64- val results = datasets.getMetrics( )
69+ val results = datasets.getIterator( None , since, until )
6570 var headerRow = true
6671 val enum = Enumerator .generateM({
6772 val chunk = if (headerRow) {
@@ -135,10 +140,10 @@ class Reporting @Inject()(selections: SelectionService,
135140 collections.getMetrics().foreach(coll => {
136141 contents += _buildCollectionRow(coll, true )
137142 })
138- datasets.getMetrics( ).foreach(ds => {
143+ datasets.getIterator( None , None , None ).foreach(ds => {
139144 contents += _buildDatasetRow(ds, true )
140145 })
141- files.getMetrics( ).foreach(f => {
146+ files.getIterator( None , None , None ).foreach(f => {
142147 contents += _buildFileRow(f)
143148 })
144149
@@ -223,7 +228,7 @@ class Reporting @Inject()(selections: SelectionService,
223228 )
224229 }
225230
226- def _buildFileRow (f : File ): String = {
231+ private def _buildFileRow (f : File ): String = {
227232 var contents = " "
228233
229234 // Parent datasets, collections & spaces are sublists within the columns
@@ -287,7 +292,7 @@ class Reporting @Inject()(selections: SelectionService,
287292 return contents
288293 }
289294
290- def _buildDatasetRow (ds : Dataset , returnAllColums : Boolean = false ): String = {
295+ private def _buildDatasetRow (ds : Dataset , returnAllColums : Boolean = false ): String = {
291296 """ returnAllColumns will include empty columns to align with file rows on report"""
292297 var contents = " "
293298
@@ -341,7 +346,7 @@ class Reporting @Inject()(selections: SelectionService,
341346 return contents
342347 }
343348
344- def _buildCollectionRow (coll : Collection , returnAllColums : Boolean = false ): String = {
349+ private def _buildCollectionRow (coll : Collection , returnAllColums : Boolean = false ): String = {
345350 """ returnAllColumns will include empty columns to align with file rows on report"""
346351
347352 var contents = " "
@@ -389,4 +394,110 @@ class Reporting @Inject()(selections: SelectionService,
389394 return contents
390395 }
391396
397+ def spaceStorage (id : UUID , since : Option [String ], until : Option [String ]) = ServerAdminAction { implicit request =>
398+ // Iterate over the files of every dataset in the space
399+ val results = datasets.getIterator(Some (id), None , None ) // TODO: Can't use time filters here if user intends files
400+
401+ var headerRow = true
402+ val enum = Enumerator .generateM({
403+ val chunk = if (headerRow) {
404+ val header = " file_type,id,name,owner,owner_email,owner_id,size_kb,uploaded,location,parent_datasets,parent_collections,parent_spaces,space_owners,space_admins\n "
405+ headerRow = false
406+ Some (header.getBytes(" UTF-8" ))
407+ } else {
408+ scala.concurrent.blocking {
409+ if (results.hasNext) {
410+ try {
411+ val ds = results.next
412+
413+ // Each file in the dataset inherits same parent info from dataset
414+ val ds_list = ds.id.stringify
415+ var coll_list = " "
416+ var space_list = " "
417+ val space_ids : ListBuffer [UUID ] = ListBuffer .empty
418+ var j = 1
419+ var k = 1
420+ ds.collections.foreach(coll => {
421+ if (! coll_list.contains(coll.uuid)) {
422+ coll_list += (if (j> 1 ) " , " else " " ) + coll.uuid
423+ j += 1
424+ }
425+ })
426+ ds.spaces.foreach(sp => {
427+ if (! space_list.contains(sp.uuid)) {
428+ space_list += (if (k> 1 ) " , " else " " ) + sp.uuid
429+ space_ids += sp
430+ k += 1
431+ }
432+ })
433+
434+ // Get admin and owner of space(s)
435+ // TODO: Should we include email and/or name too?
436+ var space_owner_list = " "
437+ var space_admin_list = " "
438+ var l = 1
439+ var m = 1
440+ spaces.get(space_ids.toList).found.foreach(sp => {
441+ space_owner_list += (if (l> 1 ) " , " else " " ) + sp.creator.uuid
442+ l += 1
443+ spaces.getUsersInSpace(sp.id, Some (" Admin" )).foreach(spadmin => {
444+ space_admin_list += (if (m> 1 ) " , " else " " ) + spadmin.id.uuid
445+ m += 1
446+ })
447+ })
448+
449+ var contents = " "
450+ files.get(ds.files).found.foreach(f => {
451+ // TODO: Need to redesign File model because this is gonna be so slow...
452+ val sinceOK = {
453+ since match {
454+ case None => true
455+ case Some (t) => (Parsers .fromISO8601(t).before(f.uploadDate))
456+ }
457+ }
458+ val untilOK = {
459+ until match {
460+ case None => true
461+ case Some (t) => (Parsers .fromISO8601(t).after(f.uploadDate))
462+ }
463+ }
464+
465+ if (sinceOK && untilOK) {
466+ // build next row of storage report
467+ contents += " \" " + f.contentType+ " \" ,"
468+ contents += " \" " + f.id.toString+ " \" ,"
469+ contents += " \" " + f.filename+ " \" ,"
470+ contents += " \" " + f.author.fullName+ " \" ,"
471+ contents += " \" " + f.author.email.getOrElse(" " )+ " \" ,"
472+ contents += " \" " + f.author.id+ " \" ,"
473+ contents += (f.length/ 1000 ).toInt.toString+ " ,"
474+ contents += dateFormat.format(f.uploadDate)+ " ,"
475+ contents += " \" " + f.loader_id+ " \" ,"
476+ contents += " \" " + ds_list+ " \" ,"
477+ contents += " \" " + coll_list+ " \" ,"
478+ contents += " \" " + space_list+ " \" ,"
479+ contents += " \" " + space_owner_list+ " \" ,"
480+ contents += " \" " + space_admin_list+ " \" "
481+ contents += " \n "
482+ }
483+ })
484+ // Submit all file rows for this dataset at once
485+ Some (contents.getBytes(" UTF-8" ))
486+ }
487+ catch {
488+ case _ => Some (" " .getBytes(" UTF-8" ))
489+ }
490+ }
491+ else None
492+ }
493+ }
494+
495+ Future (chunk)
496+ })
497+
498+ Ok .chunked(enum .andThen(Enumerator .eof)).withHeaders(
499+ " Content-Type" -> " text/csv" ,
500+ " Content-Disposition" -> (" attachment; filename=SpaceStorage" + id.stringify+ " .csv" )
501+ )
502+ }
392503}
0 commit comments