/* Ċ Ġ* ĠCopyright Ġ( C ) Ġ 2 0 2 0 ĠB os ch . IO ĠGmbH Ċ Ġ* ĠCopyright Ġ( C ) Ġ 2 0 2 1 ĠHERE ĠEurope ĠB . V . Ċ Ġ* Ċ Ġ* Ġ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 Ċ Ġ* Ċ Ġ* ĠĠĠĠ Ġhttps :// 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 . Ċ Ġ* Ċ Ġ* ĠSPDX - License - Identifier : ĠApache - 2 . 0 Ċ Ġ* ĠLicense - Filename : ĠLICENSE Ċ Ġ*/ Ċ Ċ package Ġorg . oss review toolkit . scanner . storage s Ċ Ċ import Ġjava . io . IOException Ċ import Ġjava . lang . IllegalArgumentException Ċ import Ġjava . time . Instant Ċ Ċ import Ġkotlinx . coroutines . Dispatch ers Ċ import Ġkotlinx . coroutines . run Blocking Ċ Ċ import Ġorg . oss review toolkit . clients . clear ly defined . Clear ly Defined Service Ċ import Ġorg . oss review toolkit . clients . clear ly defined . ComponentType Ċ import Ġorg . oss review toolkit . model . Artifact Provenance Ċ import Ġorg . oss review toolkit . model . Failure Ċ import Ġorg . oss review toolkit . model . Hash Ċ import Ġorg . oss review toolkit . model . Identifier Ċ import Ġorg . oss review toolkit . model . Package Ċ import Ġorg . oss review toolkit . model . Remote Artifact Ċ import Ġorg . oss review toolkit . model . Repository Provenance Ċ import Ġorg . oss review toolkit . model . Result Ċ import Ġorg . oss review toolkit . model . Scan Result Ċ import Ġorg . oss review toolkit . model . Success Ċ import Ġorg . oss review toolkit . model . Unknown Provenance Ċ import Ġorg . oss review toolkit . model . V cs Info Ċ import Ġorg . oss review toolkit . model . V cs Info C uration Data Ċ import Ġorg . oss review toolkit . model . V cs Type Ċ import Ġorg . oss review toolkit . model . config . Clear ly Defined Storage Configuration Ċ import Ġorg . oss review toolkit . model . json Mapper Ċ import Ġorg . oss review toolkit . model . utils . to Clear ly Defined Coordinates Ċ import Ġorg . oss review toolkit . model . utils . to Clear ly Defined Source Location Ċ import Ġorg . oss review toolkit . scanner . Scan Results Storage Ċ import Ġorg . oss review toolkit . scanner . Scanner Criteria Ċ import Ġorg . oss review toolkit . scanner . sc anners . scan code . generate Scanner Details Ċ import Ġorg . oss review toolkit . scanner . sc anners . scan code . generate Summary Ċ import Ġorg . oss review toolkit . utils . common . collect Messages AsString Ċ import Ġorg . oss review toolkit . utils . core . Ok HttpClient Helper Ċ import Ġorg . oss review toolkit . utils . core . log Ċ import Ġorg . oss review toolkit . utils . core . show StackTrace Ċ Ċ import Ġretrofit 2 . HttpException Ċ Ċ /** ĠThe Ġname Ġused Ġby ĠClear ly Defined Ġfor Ġthe ĠScan Code Ġtool . Ġ*/ Ċ private Ġconst Ġval ĠTO OL _ SCAN _ CODE Ġ= Ġ" scan code " Ċ Ċ /** Ċ Ġ* ĠConvert Ġa Ġ[ Clear ly Defined Service . Source Location ] Ġto Ġa Ġ[ Clear ly Defined Service . Coordinates ] Ġobject . Ċ Ġ*/ Ċ private Ġfun ĠClear ly Defined Service . Source Location . to Coordinates (): ĠClear ly Defined Service . Coordinates Ġ= ĊĠĠĠ ĠClear ly Defined Service . Coordinates ( type , Ġprovider , Ġnamespace , Ġname , Ġrevision ) Ċ Ċ /** Ċ Ġ* ĠConvert Ġa Ġ[ V cs Info ] Ġto Ġa Ġ[ V cs Info C uration Data ] Ġobject . Ċ Ġ*/ Ċ private Ġfun ĠV cs Info . to V cs Info C uration Data (): ĠV cs Info C uration Data Ġ= ĠV cs Info C uration Data ( type , Ġurl , Ġrevision , Ġpath ) Ċ Ċ /** Ċ Ġ* ĠGenerate Ġthe Ġcoordinates Ġfor ĠClear ly Defined Ġbased Ġon Ġthe Ġ[ id ], Ġthe Ġ[ vcs ], Ġand Ġa Ġ[ source Artifact ]. Ċ Ġ* ĠIf Ġinformation Ġabout Ġa ĠGit Ġrepository Ġin ĠGitHub Ġis Ġavailable , Ġthis Ġis Ġused . ĠOtherwise , Ġthe Ġcoordinates Ċ Ġ* Ġare Ġderived Ġfrom Ġthe Ġidentifier . ĠThrows Ġ[ IllegalArgumentException ] Ġif Ġgenerating Ġcoordinates Ġis Ġnot Ġpossible . Ċ Ġ*/ Ċ private Ġfun Ġpackage Coordinates ( ĊĠĠĠ Ġid : ĠIdentifier , ĊĠĠĠ Ġv cs : ĠV cs Info ?, ĊĠĠĠ Ġsource Artifact : ĠRemote Artifact ? Ċ ): ĠClear ly Defined Service . Coordinates Ġ{ ĊĠĠĠ Ġval Ġsource Location Ġ= Ġid . to Clear ly Defined Source Location ( vcs ?. to V cs Info C uration Data (), Ġsource Artifact ) ĊĠĠĠ Ġreturn Ġsource Location ?. to Coordinates () Ġ?: Ġid . to Clear ly Defined Coordinates () ĊĠĠĠĠĠĠĠ Ġ?: Ġthrow ĠIllegalArgumentException (" Unable Ġto Ġcreate ĠClear ly Defined Ġcoordinates Ġfor Ġ'${ id . to Coordinates ()} '. ") Ċ } Ċ Ċ /** Ċ Ġ* ĠGiven Ġa Ġlist Ġof Ġ[ tools ], Ġreturn Ġthe Ġversion Ġof ĠScan Code Ġthat Ġwas Ġused Ġto Ġscan Ġthe Ġpackage Ġwith Ġthe Ġgiven Ċ Ġ* Ġ[ coordinates ], Ġor Ġreturn Ġnull Ġif Ġno Ġsuch Ġtool Ġentry Ġis Ġfound . Ċ Ġ*/ Ċ private Ġfun Ġfind Scan Code Version ( tools : ĠList < String >, Ġcoordinates : ĠClear ly Defined Service . Coordinates ): ĠString ? Ġ{ ĊĠĠĠ Ġval Ġtool Url Ġ= Ġ"$ coordinates /$ TOOL _ SCAN _ CODE /" ĊĠĠĠ Ġreturn Ġtools . find Ġ{ Ġit . startsWith ( tool Url ) Ġ} ?. substring ( tool Url . length ) Ċ } Ċ Ċ /** Ċ Ġ* ĠA Ġ[ Success ] Ġresult Ġwith Ġan Ġempty Ġlist Ġof Ġ[ Scan Result ] s . Ċ Ġ*/ Ċ private Ġval ĠEMPTY _ RESULT Ġ= ĠSuccess < List < Scan Result >>( emptyList ()) Ċ Ċ /** Ċ Ġ* ĠA Ġstorage Ġimplementation Ġthat Ġtries Ġto Ġdownload ĠScan Code Ġresults Ġfrom ĠClear ly Defined . Ċ Ġ* Ċ Ġ* ĠThis Ġstorage Ġimplementation Ġmaps Ġthe Ġrequested Ġpackage Ġto Ġcoordinates Ġused Ġby ĠClear ly Defined . ĠIt Ġthen Ġtries Ċ Ġ* Ġto Ġfind Ġa Ġhar v ested ĠScan Code Ġresult Ġfor Ġthese Ġcoordinates Ġusing Ġthe ĠClear ly Defined ĠREST ĠAPI . Ċ Ġ*/ Ċ class ĠClear ly Defined Storage ( ĊĠĠĠ Ġ/** ĠThe Ġconfiguration Ġfor Ġthis Ġstorage Ġimplementation . Ġ*/ ĊĠĠĠ Ġval Ġconfiguration : ĠClear ly Defined Storage Configuration Ċ ) Ġ: ĠScan Results Storage () Ġ{ ĊĠĠĠ Ġ/** ĠThe Ġservice Ġfor Ġinteracting Ġwith ĠClear ly Defined . Ġ*/ ĊĠĠĠ Ġprivate Ġval Ġservice Ġby Ġlazy Ġ{ ĊĠĠĠĠĠĠĠ ĠClear ly Defined Service . create ( configuration . server Url , ĠOk HttpClient Helper . build Client ()) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġread Internal ( id : ĠIdentifier ): ĠResult < List < Scan Result >> Ġ= ĊĠĠĠĠĠĠĠ Ġread Package From Clear ly Defined ( id , Ġnull , Ġnull ) ĊĊĠĠĠ Ġoverride Ġfun Ġread Internal ( pkg : ĠPackage , Ġscanner Criteria : ĠScanner Criteria ): ĠResult < List < Scan Result >> Ġ= ĊĠĠĠĠĠĠĠ Ġread Package From Clear ly Defined ( pkg . id , Ġpkg . vcs , Ġpkg . source Artifact . take If Ġ{ Ġit . url . isNotEmpty () Ġ}) ĊĊĠĠĠ Ġoverride Ġfun Ġadd Internal ( id : ĠIdentifier , Ġscan Result : ĠScan Result ): ĠResult < Unit > Ġ= ĊĠĠĠĠĠĠĠ ĠFailure (" Adding Ġscan Ġresults Ġdirectly Ġto ĠClear ly Defined Ġis Ġnot Ġsupported .") ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠTry Ġto Ġobtain Ġa Ġ[ Scan Result ] Ġproduced Ġby ĠScan Code Ġfrom ĠClear ly Defined Ġfor Ġthe Ġpackage Ġwith Ġthe Ġgiven Ġ[ id ]. ĊĠĠĠĠ Ġ* ĠUse Ġthe ĠV CS Ġinformation Ġ[ vcs ] Ġand Ġan Ġoptional Ġ[ source Artifact ] Ġto Ġdetermine Ġthe Ġcoordinates Ġfor Ġlooking Ġup ĊĠĠĠĠ Ġ* Ġthe Ġresult . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprivate Ġfun Ġread Package From Clear ly Defined ( ĊĠĠĠĠĠĠĠ Ġid : ĠIdentifier , ĊĠĠĠĠĠĠĠ Ġv cs : ĠV cs Info ?, ĊĠĠĠĠĠĠĠ Ġsource Artifact : ĠRemote Artifact ? ĊĠĠĠ Ġ): ĠResult < List < Scan Result >> Ġ= ĊĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġrun Blocking ( Dispatch ers . IO ) Ġ{ Ġread From Clear ly Defined ( id , Ġpackage Coordinates ( id , Ġv cs , Ġsource Artifact )) Ġ} ĊĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠIllegalArgumentException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġe . show StackTrace () ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġlog . warn Ġ{ Ġ" Could Ġnot Ġobtain ĠClear ly Defined Ġcoordinates Ġfor Ġpackage Ġ'${ id . to Coordinates ()} '. " Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠEMPTY _ RESULT ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠTry Ġto Ġobtain Ġa Ġ[ Scan Result ] Ġproduced Ġby ĠScan Code Ġfrom ĠClear ly Defined Ġfor Ġthe Ġpackage Ġwith Ġthe Ġgiven Ġ[ id ], ĊĠĠĠĠ Ġ* Ġusing Ġthe Ġgiven Ġ[ coordinates ] Ġfor Ġlooking Ġup Ġthe Ġdata . ĠThese Ġmay Ġnot Ġnecessarily Ġbe Ġequivalent Ġto Ġthe ĊĠĠĠĠ Ġ* Ġidentifier , Ġas Ġwe Ġtry Ġto Ġlookup Ġsource Ġcode Ġresults Ġif Ġa ĠGitHub Ġrepository Ġis Ġknown . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprivate Ġsuspend Ġfun Ġread From Clear ly Defined ( ĊĠĠĠĠĠĠĠ Ġid : ĠIdentifier , ĊĠĠĠĠĠĠĠ Ġcoordinates : ĠClear ly Defined Service . Coordinates ĊĠĠĠ Ġ): ĠResult < List < Scan Result >> Ġ{ ĊĠĠĠĠĠĠĠ Ġval ĠstartTime Ġ= ĠInstant . now () ĊĠĠĠĠĠĠĠ Ġlog . info Ġ{ Ġ" Looking Ġup Ġresults Ġfor Ġ'${ id . to Coordinates ()} '. " Ġ} ĊĊĠĠĠĠĠĠĠ Ġreturn Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġtools Ġ= Ġservice . har vest Tools ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcoordinates . type , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcoordinates . provider , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcoordinates . namespace . or Empty (), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcoordinates . name , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcoordinates . revision . or Empty () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġfind Scan Code Version ( tools , Ġcoordinates )?. let Ġ{ Ġversion Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġload Scan Code Results ( coordinates , Ġversion , ĠstartTime ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġ?: ĠEMPTY _ RESULT ĊĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠHttp Exception ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġe . response ()?. error Body ()?. string ()?. let Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlog . error Ġ{ Ġ" Error Ġresponse Ġfrom ĠClear ly Defined Ġis : Ġ$ it " Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġhandle Exception ( id , Ġe ) ĊĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠIOException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠThere Ġare Ġsome Ġother Ġexceptions Ġthrown Ġby ĠRet rofit Ġto Ġbe Ġhandled Ġas Ġwell , Ġe . g . ĠConnect Exception . ĊĠĠĠĠĠĠĠĠĠĠĠ Ġhandle Exception ( id , Ġe ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠLog Ġthe Ġexception Ġthat Ġoccurred Ġduring Ġa Ġrequest Ġto ĠClear ly Defined Ġand Ġconstruct Ġan Ġerror Ġresult Ġfrom Ġit . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprivate Ġfun Ġhandle Exception ( id : ĠIdentifier , Ġe : ĠException ): ĠResult < List < Scan Result >> Ġ{ ĊĠĠĠĠĠĠĠ Ġe . show StackTrace () ĊĊĠĠĠĠĠĠĠ Ġval Ġmessage Ġ= Ġ" Error Ġwhen Ġreading Ġresults Ġfor Ġpackage Ġ'${ id . to Coordinates () }' Ġfrom ĠClear ly Defined : Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġe . collect Messages AsString () ĊĊĠĠĠĠĠĠĠ Ġlog . error Ġ{ Ġmessage Ġ} ĊĊĠĠĠĠĠĠĠ Ġreturn ĠFailure ( message ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠLoad Ġthe ĠScan Code Ġresults Ġfile Ġfor Ġthe Ġpackage Ġwith Ġthe Ġgiven Ġ[ coordinates ] Ġfrom ĠClear ly Defined . ĊĠĠĠĠ Ġ* ĠThe Ġresults Ġhave Ġbeen Ġproduced Ġby ĠScan Code Ġin Ġthe Ġgiven Ġ[ version ]; Ġuse Ġthe Ġ[ startTime ] Ġfor Ġmetadata . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprivate Ġsuspend Ġfun Ġload Scan Code Results ( ĊĠĠĠĠĠĠĠ Ġcoordinates : ĠClear ly Defined Service . Coordinates , ĊĠĠĠĠĠĠĠ Ġversion : ĠString , ĊĠĠĠĠĠĠĠ ĠstartTime : ĠInstant ĊĠĠĠ Ġ): ĠResult < List < Scan Result >> Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġtool Response Ġ= Ġservice . har vest Tool Data ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcoordinates . type , Ġcoordinates . provider , Ġcoordinates . namespace . or Empty (), Ġcoordinates . name , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcoordinates . revision . or Empty (), ĠTO OL _ SCAN _ CODE , Ġversion ĊĠĠĠĠĠĠĠ Ġ) ĊĊĠĠĠĠĠĠĠ Ġreturn Ġtool Response . use Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġjson Mapper . read Tree ( it . byte Stream ()) [" content "] ?. let Ġ{ Ġresult Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġdefinitions Ġ= Ġservice . get Definitions ( listOf ( coordinates )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġdescribed Ġ= Ġdefinitions . getValue ( coordinates ). described ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġsource Location Ġ= Ġdescribed . source Location ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġpro venance Ġ= Ġwhen Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsource Location Ġ== Ġnull Ġ-> ĠUnknown Provenance ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsource Location . type Ġ== ĠComponent Type . GIT Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠRepository Provenance ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġv cs Info Ġ= ĠV cs Info ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtype Ġ= ĠV cs Type . GIT , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġurl Ġ= Ġsource Location . url . or Empty (), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrevision Ġ= Ġsource Location . revision , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpath Ġ= Ġsource Location . path . or Empty () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġresolved Revision Ġ= Ġsource Location . revision ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠArtifact Provenance ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsource Artifact Ġ= ĠRemote Artifact ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġurl Ġ= Ġsource Location . url . or Empty (), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġhash Ġ= ĠHash . create ( described . hashes ?. sha 1 . or Empty ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġsummary Ġ= Ġgenerate Summary ( startTime , ĠInstant . now (), Ġ"", Ġresult ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġdetails Ġ= Ġgenerate Scanner Details ( result ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠSuccess ( listOf ( Scan Result ( pro venance , Ġdetails , Ġsummary ))) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġ?: ĠEMPTY _ RESULT ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ } Ċ