Skip to content

Adding the --csv option to search and retrieve. #28

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Nov 24, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ libraryDependencies += "io.spray" %% "spray-json" % "1.3.3"
libraryDependencies += "de.vandermeer" % "asciitable" % "0.3.2"
libraryDependencies += "com.lihaoyi" %% "fansi" % "0.2.5"
libraryDependencies += "org.scala-lang" % "scala-reflect" % scalaVersion.value
libraryDependencies += "au.com.bytecode" % "opencsv" % "2.4"

debianPackageDependencies := Seq("java8-runtime-headless")

Expand Down
2 changes: 2 additions & 0 deletions src/main/scala/de/upb/cs/swt/delphi/cli/Config.scala
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ package de.upb.cs.swt.delphi.cli
case class Config(server: String = sys.env.getOrElse("DELPHI_SERVER", "https://delphi.cs.uni-paderborn.de/api/"),
verbose: Boolean = false,
raw: Boolean = false,
csv: String = "",
silent: Boolean = false,
list : Boolean = false,
mode: String = "",
Expand All @@ -36,5 +37,6 @@ case class Config(server: String = sys.env.getOrElse("DELPHI_SERVER", "https://d
opts: List[String] = List()) {

lazy val consoleOutput = new ConsoleOutput(this)
lazy val csvOutput = new CsvOutput(this)

}
69 changes: 69 additions & 0 deletions src/main/scala/de/upb/cs/swt/delphi/cli/CsvOutput.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// Copyright (C) 2018 The Delphi Team.
// See the LICENCE file distributed with this work for additional
// information regarding copyright ownership.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package de.upb.cs.swt.delphi.cli

import java.io.{BufferedWriter, FileWriter}

import de.upb.cs.swt.delphi.cli.artifacts.Result
import au.com.bytecode.opencsv.CSVWriter

import scala.collection.JavaConverters._

/**
* Export search and retrieve results to .csv file.
*
* @author Lisa Nguyen Quang Do
* @author Ben Hermann
*
*/

class CsvOutput(config: Config) {

def exportResult(value: Any): Unit = {
printToCsv(
value match {
case results :
Seq[Result] if results.headOption.getOrElse(Seq.empty[Array[String]]).isInstanceOf[Result] => resultsToCsv(results)
case _ => Seq.empty[Array[String]]
}
)
}

def printToCsv(table : Seq[Array[String]]): Unit = {
val outputFile = new BufferedWriter(new FileWriter(config.csv, /* append = */false))
val csvWriter = new CSVWriter(outputFile)
csvWriter.writeAll(seqAsJavaList(table))
outputFile.close()
}

def resultsToCsv(results : Seq[Result]) : Seq[Array[String]] = {
val headOption = results.headOption.getOrElse()
if (!headOption.isInstanceOf[Result]) {
Seq.empty[Array[String]]
} else {
val fieldNames = headOption.asInstanceOf[Result].fieldNames()
val tableHeader : Array[String] =
fieldNames.+:("discovered at").+:("version").+:("groupId").+:("artifactId").+:("source").+:("Id").toArray
results.map {
e => {
Array(e.id, e.metadata.source, e.metadata.artifactId, e.metadata.groupId, e.metadata.version,
e.metadata.discovered).++(fieldNames.map(f => e.metricResults(f).toString))
}
}.+:(tableHeader)
}
}
}
7 changes: 4 additions & 3 deletions src/main/scala/de/upb/cs/swt/delphi/cli/DelphiCLI.scala
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ object DelphiCLI extends App {

implicit val system = ActorSystem()


val cliParser = {
new scopt.OptionParser[Config]("delphi-cli") {
head("Delphi Command Line Tool", s"(${BuildInfo.version})")
Expand All @@ -55,15 +54,17 @@ object DelphiCLI extends App {
.children(
arg[String]("id").action((x, c) => c.copy(id = x)).text("The ID of the project to retrieve"),
opt[Unit]('f', "file").action((_, c) => c.copy(opts = List("file"))).text("Use to load the ID from file, " +
"with the filepath given in place of the ID")
"with the filepath given in place of the ID"),
opt[String]("csv").action((x, c) => c.copy(csv = x)).text("Path to the output .csv file (overwrites existing file)")
)

cmd("search").action((s, c) => c.copy(mode = "search"))
.text("Search artifact using a query.")
.children(
arg[String]("query").action((x,c) => c.copy(query = x)).text("The query to be used."),
opt[Int]("limit").action((x, c) => c.copy(limit = Some(x))).text("The maximal number of results returned."),
opt[Unit](name="list").action((_, c) => c.copy(list = true)).text("Output results as list (raw option overrides this)")
opt[Unit](name="list").action((_, c) => c.copy(list = true)).text("Output results as list (raw option overrides this)"),
opt[String]("csv").action((x, c) => c.copy(csv = x)).text("Path to the output .csv file (overwrites existing file)")
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,23 @@ package de.upb.cs.swt.delphi.cli.artifacts

import spray.json.DefaultJsonProtocol

case class RetrieveResult(val id: String,
val metadata: ArtifactMetadata,
val metricResults: Map[String, Int]) {
trait Result{
val id: String
val metadata: ArtifactMetadata
val metricResults: Map[String, Int]

def toMavenIdentifier() : String = s"${metadata.groupId}:${metadata.artifactId}:${metadata.version}"

def fieldNames() : List[String] = metricResults.keys.toList.sorted
}

case class SearchResult(val id: String,
val metadata: ArtifactMetadata,
val metricResults: Map[String, Int]) {
def toMavenIdentifier() : String = s"${metadata.groupId}:${metadata.artifactId}:${metadata.version}"
case class SearchResult(id: String,
metadata: ArtifactMetadata,
metricResults: Map[String, Int]) extends Result

def fieldNames() : List[String] = metricResults.keys.toList.sorted
}
case class RetrieveResult(id: String,
metadata: ArtifactMetadata,
metricResults: Map[String, Int]) extends Result

case class ArtifactMetadata(val artifactId: String,
val source: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,4 +80,6 @@ trait Command {
protected def error(implicit config: Config): String => Unit = config.consoleOutput.outputError _
protected def success(implicit config: Config): String => Unit = config.consoleOutput.outputSuccess _

protected def exportResult(implicit config: Config): Any => Unit = config.csvOutput.exportResult _

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import akka.stream.ActorMaterializer
import de.upb.cs.swt.delphi.cli.Config
import de.upb.cs.swt.delphi.cli.artifacts.RetrieveResult
import de.upb.cs.swt.delphi.cli.artifacts.SearchResultJson._
import de.upb.cs.swt.delphi.cli.commands.SearchCommand.information
import spray.json.DefaultJsonProtocol

import scala.concurrent.Await
Expand Down Expand Up @@ -62,7 +63,9 @@ object RetrieveCommand extends Command with SprayJsonSupport with DefaultJsonPro
result.map(s => {
if (config.raw) {
reportResult(config)(s)
} else {
}

if (!config.raw || !config.csv.equals("")) {
val unmarshalledFuture = Unmarshal(s).to[List[RetrieveResult]]

unmarshalledFuture.transform {
Expand All @@ -71,6 +74,11 @@ object RetrieveCommand extends Command with SprayJsonSupport with DefaultJsonPro
success(config)(s"Found ${unmarshalled.size} item(s).")
reportResult(config)(unmarshalled)

if(!config.csv.equals("")) {
exportResult(config)(unmarshalled)
information(config)("Results written to file '" + config.csv + "'")
}

Success(unmarshalled)
}
case Failure(e) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import akka.util.ByteString
import de.upb.cs.swt.delphi.cli.Config
import de.upb.cs.swt.delphi.cli.artifacts.SearchResult
import de.upb.cs.swt.delphi.cli.artifacts.SearchResultJson._
import de.upb.cs.swt.delphi.cli.commands.RetrieveCommand.information
import spray.json.DefaultJsonProtocol

import scala.concurrent.duration._
Expand Down Expand Up @@ -77,7 +78,9 @@ object SearchCommand extends Command with SprayJsonSupport with DefaultJsonProto

if (config.raw || result.equals("")) {
reportResult(config)(result)
} else {
}

if(!(config.raw || result.equals("")) || !config.csv.equals("")) {
val unmarshalledFuture = Unmarshal(result).to[List[SearchResult]]

val processFuture = unmarshalledFuture.transform {
Expand Down Expand Up @@ -108,6 +111,11 @@ object SearchCommand extends Command with SprayJsonSupport with DefaultJsonProto
reportResult(config)(results)

information(config)(f"Query took $queryRuntime%.2fs.")

if(!config.csv.equals("")) {
exportResult(config)(results)
information(config)("Results written to file '" + config.csv + "'")
}
}

case class Query(query: String,
Expand Down