/* Ċ Ġ* ĠCopyright Ġ 2 0 1 2 - 2 0 1 8 Ġthe Ġoriginal Ġauthor Ġor Ġauthors . Ċ Ġ* Ċ Ġ* Ġ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 Ġorg . nex ial . core . plugins . web Ċ Ċ import Ġcom . univ oc ity . parsers . csv . Csv Format Ċ import Ġcom . univ oc ity . parsers . csv . Csv Writer Ċ import Ġcom . univ oc ity . parsers . csv . Csv Writer Settings Ċ import Ġorg . apache . commons . collections 4 . Collection Utils Ċ import Ġorg . apache . commons . collections 4 . map . List Ordered Map Ċ import Ġorg . apache . commons . lang 3 . Boolean Utils Ċ import Ġorg . apache . commons . lang 3 . StringUtils Ċ import Ġorg . nex ial . commons . utils . File Util Ċ import Ġorg . nex ial . commons . utils . Resource Utils Ċ import Ġorg . nex ial . commons . utils . TextUtils Ċ import Ġorg . nex ial . core . N ex ial Const . DEF _ FILE _ ENCODING Ċ import Ġorg . nex ial . core . N ex ial Const . Data . Save Grid As CSV .* Ċ import Ġorg . nex ial . core . System Variables . getDefault Ċ import Ġorg . nex ial . core . System Variables . getDefault Bool Ċ import Ġorg . nex ial . core . model . ExecutionContext Ċ import Ġorg . nex ial . core . model . Step Result Ċ import Ġorg . nex ial . core . utils . Check Utils .* Ċ import Ġorg . nex ial . core . utils . Console Utils Ċ import Ġorg . openqa . selenium . By Ċ import Ġorg . openqa . selenium . Javascript Executor Ċ import Ġorg . openqa . selenium . WebElement Ċ import Ġorg . openqa . selenium . support . ui . Select Ċ import Ġjava . io . File Ċ import Ġjava . util .* Ċ Ċ class ĠTable Helper ( private Ġval Ġweb Command : ĠWeb Command ) Ġ{ ĊĠĠĠ Ġprivate Ġval Ġtable Header Loc ators Ġ= ĠlistOf ("./ thead //* [ Ġname () =' th ' Ġor Ġname () =' td ' Ġ] ", ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ"./ thead //* [ Ġname () =' TH ' Ġor Ġname () =' TD ' Ġ] ", ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ"./ tr / th ") ĊĠĠĠ Ġprivate Ġval Ġform Element Locator Ġ= Ġ". //* [" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" Ġname () =' input ' Ġor " Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" Ġname () =' submit ' Ġor " Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" Ġname () =' button ' Ġor " Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" Ġname () =' textarea ' Ġor " Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" Ġname () =' select ' Ġor " Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" Ġname () =' img '" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" ]" ĊĠĠĠ Ġprivate Ġval Ġcsv Safe Replacement Ġ= ĠList Ordered Map . list Ordered Map ( map Of (" Ġ\ n Ġ" Ġto Ġ" Ġ", ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠĠĠĠĠĠĠĠ Ġ" Ġ\ r \ n Ġ" Ġto Ġ" Ġ", ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠĠĠĠĠĠĠĠ Ġ" Ġ\ r Ġ" Ġto Ġ" Ġ", ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠĠĠĠĠĠĠĠ Ġ" Ġ\ t Ġ" Ġto Ġ" Ġ", ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠĠĠĠĠĠĠĠ Ġ" Ġ\ n " Ġto Ġ" Ġ", ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠĠĠĠĠĠĠĠ Ġ" Ġ\ r \ n " Ġto Ġ" Ġ", ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠĠĠĠĠĠĠĠ Ġ" Ġ\ r " Ġto Ġ" Ġ", ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠĠĠĠĠĠĠĠ Ġ" Ġ\ t " Ġto Ġ" Ġ", ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠĠĠĠĠĠĠĠ Ġ"\ n Ġ" Ġto Ġ" Ġ", ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠĠĠĠĠĠĠĠ Ġ"\ r \ n Ġ" Ġto Ġ" Ġ", ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠĠĠĠĠĠĠĠ Ġ"\ r Ġ" Ġto Ġ" Ġ", ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠĠĠĠĠĠĠĠ Ġ"\ t Ġ" Ġto Ġ" Ġ")) ĊĠĠĠ Ġprivate Ġval Ġgrid Data Meta Ġ= ĠResource Utils . load Resource ("/ org / nex ial / core / plugins / web / Grid Data Meta . js ") ĊĠĠĠ Ġprivate Ġval Ġcollect Infinite Grid Ġ= ĠResource Utils . load Resource ("/ org / nex ial / core / plugins / web / Collect Infinite Grid . js ") ĊĠĠĠ Ġprivate Ġval Ġmeta Rec Sep Ġ= Ġ"# $ #" ĊĊĠĠĠ Ġfun Ġsave Div s As Csv ( header Cells Loc : ĠString , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrow Locator : ĠString , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcell Locator : ĠString , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġnext Page Locator : ĠString , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfile : ĠString ): ĠStep Result Ġ{ ĊĠĠĠĠĠĠĠ Ġrequires NotBlank ( row Locator , Ġ" invalid Ġrow Locator ", Ġrow Locator ) ĊĠĠĠĠĠĠĠ Ġrequires NotBlank ( cell Locator , Ġ" invalid Ġcell Locator ", Ġcell Locator ) ĊĠĠĠĠĠĠĠ Ġrequires NotBlank ( file , Ġ" invalid Ġfile ", Ġfile ) ĊĊĠĠĠĠĠĠĠ Ġval Ġwriter Ġ= Ġnew Csv Writer ( file ) ĊĊĠĠĠĠĠĠĠ Ġval Ġmsg Prefix Ġ= Ġ" DIV Ġtable " ĊĊĠĠĠĠĠĠĠ Ġ// Ġheader ĊĠĠĠĠĠĠĠ Ġif Ġ(! web Command . context . isNull OrEmpty Or Blank Value ( header Cells Loc )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġdeep Scan Ġ= Ġweb Command . context . getBoolean Data ( DE EP _ SCAN , ĠgetDefault Bool ( DE EP _ SCAN )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwrite Csv Header ( msg Prefix , Ġwriter , Ġweb Command . find Elements ( header Cells Loc ), Ġdeep Scan ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġvar Ġpage Count Ġ= Ġ 0 ĊĠĠĠĠĠĠĠ Ġvar Ġfirst Row Ġ= Ġ"" ĊĊĠĠĠĠĠĠĠ Ġwhile Ġ( true ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġdata Ġrows Ġand Ġcells ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġrows Ġ= Ġweb Command . find Elements ( row Locator ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( rows Ġ== Ġnull Ġ|| ĠCollection Utils . isEmpty ( rows )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( page Count Ġ< Ġ 1 ) ĠConsole Utils . log ("$ msg Prefix Ġdoes Ġnot Ġcontain Ġusable Ġdata Ġcells ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbreak ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠConsole Utils . log ("$ msg Prefix Ġcollecting Ġdata Ġfor Ġpage Ġ${ page Count Ġ+ Ġ 1 }") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġhas Data Ġ= Ġtrue ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ( i Ġin Ġrows . indices ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġcell Content Ġ= Ġto Cell Content ( rows [ i ], Ġcell Locator ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( Collection Utils . isEmpty ( cell Content )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwriter . write Empty Row () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbreak ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( i Ġ== Ġ 0 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( page Count Ġ> Ġ 0 Ġ&& ĠStringUtils . equals ( first Row , Ġcell Content . toString ())) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġfound Ġduplicate ... Ġmaybe Ġwe Ġhave Ġreached Ġthe Ġend ? ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠConsole Utils . log ("$ msg Prefix Ġreached Ġthe Ġend Ġof Ġrecords ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġhas Data Ġ= Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbreak ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġmark Ġfirst Ġrow Ġfor Ġcomparison Ġagainst Ġsubsequent Ġpages ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfirst Row Ġ= Ġcell Content . toString () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwriter . write Row ( cell Content ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(! has Data ) Ġbreak ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġpage Count ++ ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(! click Next Page ( next Page Locator )) Ġbreak ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġwriter . flush () ĊĠĠĠĠĠĠĠ Ġwriter . close () ĊĊĠĠĠĠĠĠĠ Ġreturn ĠStep Result . success ("$ msg Prefix Ġscanned Ġand Ġwritten Ġto Ġ$ file ") ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġsave Table As Csv ( locator : ĠString , Ġnext Page Locator : ĠString , Ġfile : ĠString ): ĠStep Result Ġ{ ĊĠĠĠĠĠĠĠ Ġrequires NotBlank ( file , Ġ" Invalid Ġfile ", Ġfile ) ĊĊĠĠĠĠĠĠĠ Ġ// Ġexception Ġthrown Ġif Ġlocator Ġdoesn 't Ġresolve Ġto Ġelement ĊĠĠĠĠĠĠĠ Ġval Ġtable Ġ= Ġweb Command . to Element ( locator ) ĊĊĠĠĠĠĠĠĠ Ġval Ġwriter Ġ= Ġnew Csv Writer ( file ) ĊĊĠĠĠĠĠĠĠ Ġval Ġmsg Prefix Ġ= Ġ" Table Ġ'$ locator '" ĊĊĠĠĠĠĠĠĠ Ġvar Ġheaders : ĠList < WebElement > Ġ= ĠArrayList () ĊĠĠĠĠĠĠĠ Ġtable Header Loc ators . forEach ( fun ( locator : ĠString ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġrun Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( Collection Utils . isEmpty ( headers )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġheaders Ġ= Ġtable . find Elements ( web Command . locator Helper . findBy ( locator , Ġtrue )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ}) ĊĊĠĠĠĠĠĠĠ Ġval Ġdeep Scan Ġ= Ġweb Command . context . getBoolean Data ( DE EP _ SCAN , ĠgetDefault Bool ( DE EP _ SCAN )) ĊĠĠĠĠĠĠĠ Ġwrite Csv Header ( msg Prefix , Ġwriter , Ġheaders , Ġdeep Scan ) ĊĊĠĠĠĠĠĠĠ Ġvar Ġpage Count Ġ= Ġ 0 ĊĠĠĠĠĠĠĠ Ġvar Ġfirst Row Ġ= Ġ"" ĊĊĠĠĠĠĠĠĠ Ġwhile Ġ( true ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġtable Ġhas Ġbody ? ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġrows : ĠList < WebElement > Ġ= Ġtable . find Elements ( By . xpath (". // tbody / tr ")) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġtable Ġhas Ġrows Ġnot Ġtr apped Ġwithin Ġtbody ? ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġbut Ġwe Ġare Ġnot Ġconsidering ĠTH Ġhere Ġbecause Ġwe Ġare Ġnot Ġunder ĠT BODY . ĠThe ĠTH Ġin ĠTable Ġmight Ġbe Ġheader ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( Collection Utils . isEmpty ( rows )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrows Ġ= Ġtable . find Elements ( By . xpath (". // tr /* [ name () =' TD ' Ġor Ġname () =' td '] ")) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( Collection Utils . isEmpty ( rows )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( page Count Ġ< Ġ 1 ) ĠConsole Utils . log ("$ msg Prefix Ġdoes Ġnot Ġcontain Ġusable Ġdata Ġcells ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbreak ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠConsole Utils . log ( msg Prefix Ġ+ Ġ" Ġcollecting Ġdata Ġfor Ġpage Ġ" Ġ+ Ġ( page Count Ġ+ Ġ 1 )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġhas Data Ġ= Ġtrue ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ( i Ġin Ġrows . indices ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠConsole Utils . log ("$ msg Prefix Ġscanning Ġrow Ġ$ i ...") ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġcell Ġcan Ġbe ĠTD Ġor ĠTH Ġunder ĠT BODY ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġcells Ġ= Ġto Cell Content ( rows [ i ], Ġ". /* [ name () =' TD ' Ġor Ġname () =' td ' Ġor Ġname () =' TH ' Ġor Ġname () =' th '] ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( Collection Utils . isEmpty ( cells )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwriter . write Empty Row () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbreak ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( i Ġ== Ġ 0 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġcompare Ġthe Ġfirst Ġrow Ġof Ġevery Ġpage Ġafter Ġthe Ġ 1 st Ġpage ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( page Count Ġ> Ġ 0 Ġ&& ĠStringUtils . equals ( first Row , Ġcells . toString ())) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġfound Ġduplicate ... Ġmaybe Ġwe Ġhave Ġreached Ġthe Ġend ? ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠConsole Utils . log ("$ msg Prefix Ġreached Ġthe Ġend Ġof Ġrecords .") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġhas Data Ġ= Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbreak ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġmark Ġfirst Ġrow Ġfor Ġcomparison Ġagainst Ġnext Ġpage ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfirst Row Ġ= Ġcells . toString () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwriter . write Row ( cells ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(! has Data ) Ġbreak ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġpage Count ++ ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(! click Next Page ( next Page Locator )) Ġbreak ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ// Ġtable Ġhas Ġfooter Ġvia Ġt foot ? Ġwe Ġare Ġignoring Ġit ... ĊĊĠĠĠĠĠĠĠ Ġ// Ġwrite Ġto Ġtarget Ġfile ĊĠĠĠĠĠĠĠ Ġwriter . flush () ĊĠĠĠĠĠĠĠ Ġwriter . close () ĊĊĠĠĠĠĠĠĠ Ġval Ġtarget File Ġ= ĠFile ( file ) ĊĠĠĠĠĠĠĠ Ġif Ġ( web Command . context . getBoolean Data ( END _ TRIM , ĠgetDefault Bool ( END _ TRIM ))) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠConsole Utils . log ("$ msg Prefix Ġtri mm ing Ġoff Ġend - of - file Ġline Ġfeed ...") ĊĠĠĠĠĠĠĠĠĠĠĠ ĠFile Util . remove File End Line Feed ( target File ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġreturn ĠStep Result . success ("$ msg Prefix Ġscanned Ġand Ġwritten Ġto Ġ$ file ") ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* Ġ` config ` Ġcontains : ĊĠĠĠĠ Ġ* Ġ- Ġdata - viewport : Ġlocator Ġto Ġthe Ġscrolling Ġviewport ĊĠĠĠĠ Ġ* Ġ- Ġdata - row - xpath : Ġrelative ĠX PATH Ġto Ġeach Ġrow Ġfrom Ġits Ġparent Ġgrid ĊĠĠĠĠ Ġ* Ġ- Ġdata - cell - xpath : Ġrelative ĠX PATH Ġto Ġeach Ġcell Ġfrom Ġits Ġparent Ġrow ĊĠĠĠĠ Ġ* Ġ- Ġheader - cell : Ġlocator Ġto Ġidentify Ġindividual Ġheader Ġcells ĊĠĠĠĠ Ġ* Ġ- Ġlimit Ġ( optional ): Ġmaximum Ġnumber Ġof Ġrows Ġto Ġcollect . Ġ- 1 Ġmeans Ġun limited ĊĠĠĠĠ Ġ* Ġ- Ġwait Between Scroll Ġ( optional ): Ġmilliseconds Ġto Ġwait Ġbetween Ġeach Ġscroll Ġaction ĊĠĠĠĠ Ġ* Ġ- Ġn ex ial . web . save Grid . deep Scan Ġ( optional ): Ġoverride Ġexisting Ġsetting Ġin Ġcontext ĊĠĠĠĠ Ġ* Ġ- Ġn ex ial . web . save Grid . header . input Ġ( optional ): Ġoverride Ġexisting Ġsetting Ġin Ġcontext ĊĠĠĠĠ Ġ* Ġ- Ġn ex ial . web . save Grid . header . image Ġ( optional ): Ġoverride Ġexisting Ġsetting Ġin Ġcontext ĊĠĠĠĠ Ġ* Ġ- Ġn ex ial . web . save Grid . data . input Ġ( optional ): Ġoverride Ġexisting Ġsetting Ġin Ġcontext ĊĠĠĠĠ Ġ* Ġ- Ġn ex ial . web . save Grid . data . image Ġ( optional ): Ġoverride Ġexisting Ġsetting Ġin Ġcontext ĊĠĠĠĠ Ġ* Ġ- Ġn ex ial . web . save Grid . end . trim Ġ( optional ): Ġoverride Ġexisting Ġsetting Ġin Ġcontext ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* Ġ@ param Ġconfig ĠString ĊĠĠĠĠ Ġ* Ġ@ param Ġfile ĠString ĊĠĠĠĠ Ġ* Ġ@ return ĠStep Result ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġsave Infinite Div s As Csv ( config : ĠString , Ġfile : ĠString ): ĠStep Result Ġ{ ĊĠĠĠĠĠĠĠ Ġrequires NotBlank ( config , Ġ" Invalid Ġconfig ", Ġconfig ) ĊĠĠĠĠĠĠĠ Ġrequires NotBlank ( file , Ġ" Invalid Ġfile ", Ġfile ) ĊĊĠĠĠĠĠĠĠ Ġval Ġconfig Map Ġ= ĠText Utils . toMap ( StringUtils . remove ( config , Ġ"\ r "), Ġ"\ n ", Ġ"=" ) ĊĊĠĠĠĠĠĠĠ Ġ// Ġcheck Ġrequired Ġconfigs ĊĠĠĠĠĠĠĠ Ġrequires ( config Map . isNotEmpty (), Ġ" No Ġvalid Ġconfig Ġfound ", Ġconfig ) ĊĠĠĠĠĠĠĠ Ġrequires ( config Map . containsKey (" data - viewport "), Ġ" Invalid Ġconfig ; Ġdata - viewport Ġnot Ġfound ", Ġconfig ) ĊĠĠĠĠĠĠĠ Ġrequires ( config Map . containsKey (" data - row - xpath "), Ġ" Invalid Ġconfig ; Ġdata - row Ġnot Ġfound ", Ġconfig ) ĊĠĠĠĠĠĠĠ Ġrequires ( config Map . containsKey (" data - cell - xpath "), Ġ" Invalid Ġconfig ; Ġdata - cell Ġnot Ġfound ", Ġconfig ) ĊĊĠĠĠĠĠĠĠ Ġval Ġmsg Prefix Ġ= Ġ" Infinite ĠScroll ing ĠDIV " ĊĠĠĠĠĠĠĠ Ġval Ġwriter Ġ= Ġnew Csv Writer ( file ) ĊĠĠĠĠĠĠĠ Ġval Ġcontext Ġ= Ġweb Command . context ĊĠĠĠĠĠĠĠ Ġval Ġjs Exec Ġ= Ġweb Command . js Executor ĊĠĠĠĠĠĠĠ Ġval Ġdeep Scan Ġ= Ġresolve Config Boolean ( config Map , Ġcontext , ĠDE EP _ SCAN ) ĊĊĠĠĠĠĠĠĠ Ġ// Ġheader Ġ( not Ġrequired ) ĊĠĠĠĠĠĠĠ Ġval Ġheader Cells Loc Ġ= Ġconfig Map [" header - cell "] ĊĠĠĠĠĠĠĠ Ġif Ġ(! context . isNull OrEmpty Or Blank Value ( header Cells Loc )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwrite Csv Header ( msg Prefix , Ġwriter , Ġweb Command . find Elements ( header Cells Loc ), Ġdeep Scan ) ĊĊĠĠĠĠĠĠĠ Ġ// Ġviewport ĊĠĠĠĠĠĠĠ Ġval Ġviewport Loc Ġ= Ġconfig Map [" data - viewport "] ĊĠĠĠĠĠĠĠ Ġval Ġviewport Ġ= Ġweb Command . find Elements ( viewport Loc ). first OrNull () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ?: Ġreturn ĠStep Result . fail (" Unable Ġto Ġresolve Ġdata Ġviewport Ġvia Ġ'$ viewport Loc '") ĊĊĠĠĠĠĠĠĠ Ġ// Ġre usable Ġconfigs ĊĠĠĠĠĠĠĠ Ġval Ġrow Locator Ġ= Ġconfig Map [" data - row - xpath "] ĊĠĠĠĠĠĠĠ Ġval Ġcell Locator Ġ= Ġconfig Map [" data - cell - xpath "] ĊĠĠĠĠĠĠĠ Ġval Ġlimit Ġ= Ġ( config Map [" limit "] Ġ?: Ġ"- 1 "). toInt () ĊĠĠĠĠĠĠĠ Ġval Ġwait Between Scroll Ġ= Ġ( config Map [" wait Between Scroll "] Ġ?: Ġ" 6 0 0 "). toInt () ĊĊĠĠĠĠĠĠĠ ĠConsole Utils . log ("$ msg Prefix Ġcollecting Ġdata ") ĊĠĠĠĠĠĠĠ Ġjs Exec . execute Script ( collect Infinite Grid , Ġviewport , Ġrow Locator , Ġcell Locator , Ġdeep Scan , Ġlimit , Ġwait Between Scroll ) ĊĊĠĠĠĠĠĠĠ Ġ// Ġwait Ġfor Ġscript Ġto Ġfinish ĊĠĠĠĠĠĠĠ Ġvar Ġcollection InProgress : ĠAny Ġ= Ġ" true " ĊĠĠĠĠĠĠĠ Ġwhile Ġ( Objects . toString ( collection InProgress ) Ġ== Ġ" true ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠThread . sleep ( 5 0 0 ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcollection InProgress Ġ= Ġjs Exec . execute Script (" return Ġcollection InProgress ; ") ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġgrid Data Ġ= Ġjs Exec . execute Script (" return Ġcollection Results ; ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ?: Ġreturn ĠStep Result . fail (" Unable Ġto Ġretrieve Ġany Ġgrid Ġdata ") ĊĊĠĠĠĠĠĠĠ Ġval Ġgrid DataList Ġ= Ġmutable ListOf < List < Map < String , ĠString >> >() ĊĊĠĠĠĠĠĠĠ Ġval Ġgrid DataMap : ĠMap < *, Ġ*> Ġ= Ġgrid Data Ġas ĠMap < *, Ġ*> ĊĠĠĠĠĠĠĠ Ġif Ġ( grid DataMap . isEmpty () Ġ|| Ġ! grid DataMap . containsKey (" data ") Ġ|| Ġgrid DataMap [" data "] Ġ! is ĠList <* >) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĠStep Result . fail (" No Ġgrid Ġdata Ġfound ") ĊĊĠĠĠĠĠĠĠ Ġval Ġgrid DataArray Ġ= Ġgrid DataMap [" data "] Ġas ĠList < *> ĊĠĠĠĠĠĠĠ Ġgrid DataArray . forEach Ġ{ Ġrow Data Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( rowData Ġis ĠList <* >) Ġgrid DataList . add ( rowData . map Ġ{ Ġit Ġas ĠMap < String , ĠString > Ġ}. toList ()) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġdata Image Ġ= Ġresolve Config ( config Map , Ġcontext , ĠDATA _ IMAGE ) ĊĠĠĠĠĠĠĠ Ġval Ġdata Input Ġ= Ġresolve Config ( config Map , Ġcontext , ĠDATA _ INPUT ) ĊĠĠĠĠĠĠĠ Ġvar Ġrow Count Ġ= Ġ 0 ĊĊĠĠĠĠĠĠĠ Ġgrid DataList . forEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġcell Content Ġ= ĠArrayList < String >() ĊĠĠĠĠĠĠĠĠĠĠĠ Ġit . forEach Ġ{ Ġrow Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrun Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġcell Text Ġ= Ġrow [" text "] Ġ?: Ġ"" ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(! deep Scan ) Ġcell Content . add ( csv Safe ( cell Text )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġif Ġ( StringUtils . isNotEmpty ( cell Text ) Ġ&& ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ(! StringUtils . contains ( cell Text , Ġ"\ n ") Ġ|| Ġrow [" tag "] Ġ!= Ġ" select ")) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcell Content . add ( csv Safe ( cell Text )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( row [" tag "] Ġ== Ġ" img ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcell Content . add ( extract ImageData ( row , ĠImage Options . valueOf ( data Image ))) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcell Content . add ( extract InputData ( context , Ġrow , ĠInput Options . valueOf ( data Input ))) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( cell Content . isEmpty ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwriter . write Empty Row () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrow Count ++ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwriter . write Row ( cell Content ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġwriter . flush () ĊĠĠĠĠĠĠĠ Ġwriter . close () ĊĊĠĠĠĠĠĠĠ Ġval Ġtarget File Ġ= ĠFile ( file ) ĊĠĠĠĠĠĠĠ Ġif Ġ( resolve Config Boolean ( config Map , Ġcontext , ĠEND _ TRIM )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠConsole Utils . log ("$ msg Prefix Ġtri mm ing Ġoff Ġend - of - file Ġline Ġfeed ...") ĊĠĠĠĠĠĠĠĠĠĠĠ ĠFile Util . remove File End Line Feed ( target File ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġreturn ĠStep Result . success ("$ msg Prefix Ġ$ rowCount Ġscanned Ġand Ġwritten Ġto Ġ$ file ") ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* Ġassume Ġthe Ġconvention al Ġ< pre >& lt ; TABLE >, Ġ& lt ; TR >, Ġ& lt ; TD ></ pre > Ġconstructs . ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* Ġ@ param Ġconfig ĠString ĊĠĠĠĠ Ġ* Ġ@ param Ġfile ĠString ĊĠĠĠĠ Ġ* Ġ@ return ĠStep Result ĊĠĠĠĠ Ġ* Ġ@ see Ġ# save Infinite Div s As Csv ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġsave Infinite Table As Csv ( config : ĠString , Ġfile : ĠString ): ĠStep Result Ġ= Ġsave Infinite Div s As Csv ( config , Ġfile ) ĊĊĠĠĠ Ġfun Ġassert Table ( locator : ĠString , Ġrow : ĠString , Ġcolumn : ĠString , Ġtext : ĠString ): ĠStep Result Ġ{ ĊĠĠĠĠĠĠĠ Ġrequires Positive Number ( row , Ġ" invalid Ġrow Ġnumber ", Ġrow ) ĊĠĠĠĠĠĠĠ Ġrequires Positive Number ( column , Ġ" invalid Ġcolumn Ġnumber ", Ġcolumn ) ĊĊĠĠĠĠĠĠĠ Ġval Ġtable Ġ= Ġweb Command . to Element ( locator ) ĊĊĠĠĠĠĠĠĠ Ġval Ġcell : ĠWeb Element Ġ= Ġtable . findElement ( By . xpath (". // tr [$ row ]/ td [$ column ] ")) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ?: Ġreturn ĠStep Result . fail (" EXPECTED Ġcell Ġat ĠRow Ġ$ row ĠColumn Ġ$ column Ġof Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" table Ġ'$ locator ' ĠNOT Ġfound ") ĊĊĠĠĠĠĠĠĠ Ġval Ġactual Ġ= Ġcell . text ĊĠĠĠĠĠĠĠ Ġif Ġ( StringUtils . isBlank ( text )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġif Ġ( StringUtils . isBlank ( actual )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠStep Result . success (" found Ġempty Ġvalue Ġin Ġtable Ġ'$ locator '") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠStep Result . fail (" EXPECTED Ġempty Ġvalue Ġbut Ġfound Ġ'$ actual ' Ġinstead .") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġif Ġ( StringUtils . isBlank ( actual )) Ġreturn ĠStep Result . fail (" EXPECTED Ġ'$ text ' Ġbut Ġfound Ġempty Ġvalue Ġinstead .") ĊĊĠĠĠĠĠĠĠ Ġval Ġmsg Prefix Ġ= Ġ" EXPECTED Ġ'$ text ' Ġin Ġtable Ġ'$ locator '" ĊĠĠĠĠĠĠĠ Ġreturn Ġif Ġ( StringUtils . equals ( text , Ġactual )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠStep Result . success ( msg Prefix ) ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠStep Result . fail ("$ msg Prefix Ġbut Ġfound Ġ'$ actual ' Ġinstead .") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġwrite Csv Header ( msg Prefix : ĠString , Ġwriter : ĠCsv Writer , Ġheaders : ĠList < WebElement > ?, Ġdeep Scan : ĠBoolean ) Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( headers Ġ== Ġnull Ġ|| ĠCollection Utils . isEmpty ( headers )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠConsole Utils . log ("$ msg Prefix Ġdoes Ġnot Ġcontain Ġusable Ġheaders ") ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġheader Names Ġ= ĠArrayList < String >() ĊĠĠĠĠĠĠĠĠĠĠĠ Ġheaders . forEach Ġ{ Ġheader Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġweb Command . scroll Into View ( header ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( header . is Displayed ) Ġheader Names . add ( if Ġ( deep Scan ) Ġdeep Scan ( header , Ġtrue ) Ġelse Ġcsv Safe ( header . text )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ ĠConsole Utils . log ("$ msg Prefix Ġ- Ġcollected Ġheaders : Ġ$ header Names ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwriter . write Headers ( header Names ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġto Cell Content ( row : ĠWeb Element , Ġcell Locator : ĠString ): ĠList < String > Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġcells : ĠList < WebElement > Ġ= Ġrow . find Elements ( web Command . locator Helper . findBy ( cell Locator , Ġtrue )) ĊĊĠĠĠĠĠĠĠ Ġval Ġcell Content Ġ= ĠArrayList < String >() ĊĠĠĠĠĠĠĠ Ġif Ġ( Collection Utils . isEmpty ( cells )) Ġreturn Ġcell Content ĊĊĠĠĠĠĠĠĠ Ġval Ġdeep Scan Ġ= Ġweb Command . context . getBoolean Data ( DE EP _ SCAN , ĠgetDefault Bool ( DE EP _ SCAN )) ĊĊĠĠĠĠĠĠĠ Ġcells . forEach Ġ{ Ġcell Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġrun Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġweb Command . scroll Into View ( cell ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( cell . is Displayed ) Ġcell Content . add ( if Ġ( deep Scan ) Ġdeep Scan ( cell , Ġfalse ) Ġelse Ġcsv Safe ( cell . text )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġreturn Ġcell Content ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* Ġdetermine Ġthe Ġtext Ġfor Ġcheckbox , Ġradio Ġbutton , Ġimage , Ġbutton , Ġselect , Ġtext Ġbox , Ġtextarea , Ġetc . ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* ĠNote Ġthat Ġthis Ġmethod Ġonly Ġchecks Ġfor Ġ 1 Ġelement Ġtype . ĊĠĠĠĠ Ġ* Ġ@ param Ġcell ĠWeb Element ĊĠĠĠĠ Ġ* Ġ@ return ĠString ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprivate Ġfun Ġdeep Scan ( cell : ĠWeb Element , Ġis Header : ĠBoolean ): ĠString Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġcell Text Ġ= Ġcell . text ĊĊĠĠĠĠĠĠĠ Ġ// Ġno Ġnewline Ġmeans Ġthe Ġcell Ġprobably Ġdoesn 't Ġcontain Ġ< SELECT > Ġor Ġ< TEXT AREA > ĊĠĠĠĠĠĠĠ Ġif Ġ( StringUtils . isNotEmpty ( cell Text ) Ġ&& Ġ! StringUtils . contains ( cell Text , Ġ"\ n ")) Ġreturn Ġcsv Safe ( cell Text ) ĊĊĠĠĠĠĠĠĠ Ġ// Ġcover Ġcases Ġfor Ġcheckbox , Ġradio , Ġsubmit , Ġbutton , Ġtext Ġbox , Ġpassword , Ġemail , Ġupload , Ġinput - image , Ġtext Ġarea , Ġselect ĊĠĠĠĠĠĠĠ Ġval Ġinputs Ġ= Ġcell . find Elements < WebElement >( By . xpath ( form Element Locator )) ĊĠĠĠĠĠĠĠ Ġif Ġ( inputs . isEmpty ()) Ġreturn Ġcsv Safe ( cell Text ) ĊĊĠĠĠĠĠĠĠ Ġval Ġjs Exec Ġ= Ġweb Command . js Executor ĊĠĠĠĠĠĠĠ Ġval Ġcontext Ġ= Ġweb Command . context ĊĠĠĠĠĠĠĠ Ġval Ġheader Image Ġ= Ġcontext . getString Data ( HEADER _ IMAGE , ĠgetDefault ( HEADER _ IMAGE )) ĊĠĠĠĠĠĠĠ Ġval Ġdata Image Ġ= Ġcontext . getString Data ( DATA _ IMAGE , ĠgetDefault ( DATA _ IMAGE )) ĊĠĠĠĠĠĠĠ Ġval Ġheader Input Ġ= Ġcontext . getString Data ( HEADER _ INPUT , ĠgetDefault ( HEADER _ INPUT )) ĊĠĠĠĠĠĠĠ Ġval Ġdata Input Ġ= Ġcontext . getString Data ( DATA _ INPUT , ĠgetDefault ( DATA _ INPUT )) ĊĊĠĠĠĠĠĠĠ Ġval Ġmeta Map Ġ= Ġjs Element Meta ( js Exec , Ġgrid Data Meta , Ġinputs [ 0 ]) ĊĠĠĠĠĠĠĠ Ġ// Ġ< SELECT > Ġelement Ġwill Ġex hibit Ġnewline Ġin Ġit 's Ġtext Ġrepresentation . ĠSo Ġif Ġwe Ġare Ġnot Ġdealing Ġwith ĊĠĠĠĠĠĠĠ Ġ// Ġ< SELECT > Ġthen Ġ` cell Text ` Ġshould Ġbe Ġreturned Ġas Ġthis Ġpoint ĊĠĠĠĠĠĠĠ Ġif Ġ( meta Map . isEmpty () Ġ|| Ġ( StringUtils . isNotEmpty ( cell Text ) Ġ&& Ġmeta Map [" tag "] Ġ!= Ġ" select ")) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġcsv Safe ( cell Text ) ĊĊĠĠĠĠĠĠĠ Ġreturn Ġcsv Safe ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( meta Map [" tag "] Ġ== Ġ" img ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġextract ImageData ( meta Map , ĠImage Options . valueOf ( if Ġ( is Header ) Ġheader Image Ġelse Ġdata Image )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġextract InputData ( context , Ġmeta Map , ĠInput Options . valueOf ( if Ġ( is Header ) Ġheader Input Ġelse Ġdata Input )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ}) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġextract ImageData ( meta Map : ĠMap < String , ĠString >, Ġimage Option : ĠImage Options ) Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhen Ġ( image Option ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠImage Options . filename Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġsrc Ġ= Ġmeta Map [" src "] Ġ?: Ġ"" ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( StringUtils . contains ( src , Ġ"/ ")) ĠStringUtils . substring After Last ( src , Ġ"/") Ġelse Ġsrc ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠImage Options . type ĠĠĠĠ Ġ-> Ġ" image " ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse ĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ-> ĠStringUtils . default String ( meta Map [ image Option . toString ()]) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġextract InputData ( context : ĠExecutionContext , Ġrow : ĠMap < String , ĠString >, Ġdata Option : ĠInput Options ) Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( row [" tag "] Ġ== Ġ" select ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( data Option Ġ== ĠInput Options . state Ġ|| Ġdata Option Ġ== ĠInput Options . value ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠText Utils . toString ( StringUtils . split ( row [" selected "], Ġ"\ n "), Ġcontext . text Delim , Ġ"", Ġ"") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠStringUtils . default String ( row [ data Option . toString ()]) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġif Ġ( data Option Ġ== ĠInput Options . state ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhen Ġ( row [" type "]) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" checkbox " Ġ-> Ġif Ġ( StringUtils . equals ( Objects . toString ( row [" checked "]), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" true ")) Ġ" checked " Ġelse Ġ" unchecked " ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" radio " ĠĠĠ Ġ-> Ġif Ġ( StringUtils . equals ( Objects . toString ( row [" checked "]), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" true ")) Ġ" selected " Ġelse Ġ" un selected " ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse ĠĠĠĠĠĠ Ġ-> ĠStringUtils . default String ( row [" value "]) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠStringUtils . default String ( row [ data Option . toString ()]) ĊĊĠĠĠ Ġprivate Ġfun Ġresolve Config Boolean ( config Map : ĠMap < String , ĠString >, Ġcontext : ĠExecutionContext , Ġkey : ĠString ) Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( config Map . containsKey ( key )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠBoolean Utils . to Boolean ( config Map [ key ]) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcontext . getBoolean Data ( key , ĠgetDefault Bool ( key )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġresolve Config ( config Map : ĠMap < String , ĠString >, Ġcontext : ĠExecutionContext , Ġkey : ĠString ) Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠ Ġconfig Map [ key ] Ġ?: Ġcontext . getString Data ( key , ĠgetDefault ( key )) ĊĊĠĠĠ Ġprivate Ġfun Ġjs Element Meta ( js Exec : ĠJavascript Executor , Ġscript : ĠString , Ġelement : ĠWeb Element ): ĠMap < String , ĠString > Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠ ĠText Utils . toMap ( Objects . toString ( js Exec . execute Script ( script , Ġelement , Ġmeta Rec Sep ), Ġ""), Ġmeta Rec Sep , Ġ"=" ) ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* Ġdetermine Ġthe Ġtext Ġfor Ġcheckbox , Ġradio Ġbutton , Ġimage , Ġbutton , Ġselect , Ġtext Ġbox , Ġtextarea , Ġetc . ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* ĠNote Ġthat Ġthis Ġmethod Ġonly Ġchecks Ġfor Ġ 1 Ġelement Ġtype . ĊĠĠĠĠ Ġ* Ġ@ param Ġcell ĠWeb Element ĊĠĠĠĠ Ġ* Ġ@ return ĠString ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprivate Ġfun Ġresolve Display Text ( cell : ĠWeb Element , Ġis Header : ĠBoolean ): ĠString Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġcell Text Ġ= Ġcell . text ĊĊĠĠĠĠĠĠĠ Ġ// Ġno Ġnewline Ġmeans Ġthe Ġcell Ġprobably Ġdoesn 't Ġcontain Ġ< SELECT > ĊĠĠĠĠĠĠĠ Ġif Ġ(! StringUtils . contains ( cell Text , Ġ"\ n ") Ġ&& ĠStringUtils . isNotEmpty ( cell Text )) Ġreturn Ġcsv Safe ( cell Text ) ĊĊĠĠĠĠĠĠĠ Ġ// Ġnow Ġwe 're Ġnot Ġsure .. Ġmaybe Ġwe Ġneed Ġto Ġcapture Ġdata Ġfrom Ġ< SELECT > ĊĠĠĠĠĠĠĠ Ġval Ġcontext Ġ= Ġweb Command . context ĊĊĠĠĠĠĠĠĠ Ġval Ġdata Option Ġ= ĠInput Options . valueOf ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( is Header ) Ġcontext . getString Data ( HEADER _ INPUT , ĠgetDefault ( HEADER _ INPUT )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġcontext . getString Data ( DATA _ INPUT , ĠgetDefault ( DATA _ INPUT ))) ĊĊĠĠĠĠĠĠĠ Ġval Ġselects Ġ= Ġcell . find Elements < WebElement >( By . xpath (". // select ")) ĊĠĠĠĠĠĠĠ Ġif Ġ( select s . isNotEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġy ep ... Ġdefinitely Ġhas Ġ< SELECT > ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġfirst Element Ġ= Ġselects [ 0 ] ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġif Ġ( first Element . is Displayed ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( data Option Ġ== ĠInput Options . state Ġ|| Ġdata Option Ġ== ĠInput Options . value ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠSelect ( first Element ). all Selected Options . join ToString ( separator Ġ= Ġcontext . text Delim , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠĠĠĠĠĠĠĠ Ġtransform Ġ= Ġ{ Ġit . text Ġ}) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse ĠStringUtils . default String ( first Element . getAttribute ( data Option . toString ())) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ"" ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġif Ġ( StringUtils . isNotEmpty ( cell Text )) Ġreturn Ġcsv Safe ( cell Text ) ĊĠĠĠĠĠĠĠ Ġ// Ġno pe , Ġwe Ġdon 't Ġhave Ġ< SELECT > ĊĊĠĠĠĠĠĠĠ Ġ// Ġcover Ġcases Ġfor Ġcheckbox , Ġradio , Ġsubmit , Ġbutton , Ġtext Ġbox , Ġpassword , Ġemail , Ġupload , Ġinput - image ĊĠĠĠĠĠĠĠ Ġval Ġlocator Inputs Ġ= Ġ". //* [ Ġname () =' input ' Ġor Ġname () =' submit ' Ġor Ġname () =' button ' Ġor Ġname () =' textarea ' Ġ] " ĊĠĠĠĠĠĠĠ Ġval Ġinputs Ġ= Ġcell . find Elements < WebElement >( By . xpath ( locator Inputs )) ĊĠĠĠĠĠĠĠ Ġif Ġ( inputs . isNotEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġfirst Element Ġ= Ġinputs [ 0 ] ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġif Ġ( first Element . is Displayed ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( data Option Ġ== ĠInput Options . state ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhen Ġ( first Element . getAttribute (" type ")) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" checkbox " Ġ-> Ġif Ġ( StringUtils . equals ( first Element . getAttribute (" checked "), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" true ")) Ġ" checked " Ġelse Ġ" unchecked " ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" radio " ĠĠĠ Ġ-> Ġif Ġ( StringUtils . equals ( first Element . getAttribute (" checked "), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" true ")) Ġ" selected " Ġelse Ġ" un selected " ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse ĠĠĠĠĠĠ Ġ-> ĠStringUtils . default String ( first Element . getAttribute (" value ")) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse ĠStringUtils . default String ( first Element . getAttribute ( data Option . toString ())) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ"" ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġimages Ġ= Ġcell . find Elements < WebElement >( By . xpath (". // img ")) ĊĠĠĠĠĠĠĠ Ġif Ġ( images . isNotEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġimage Option Ġ= ĠImage Options . valueOf ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( is Header ) Ġcontext . getString Data ( HEADER _ IMAGE , ĠgetDefault ( HEADER _ IMAGE )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġcontext . getString Data ( DATA _ IMAGE , ĠgetDefault ( DATA _ IMAGE ))) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġfirst Element Ġ= Ġimages [ 0 ] ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġif Ġ( first Element . is Displayed ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( image Option Ġ== ĠImage Options . filename ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġsrc Ġ= Ġfirst Element . getAttribute (" src ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( StringUtils . contains ( src , Ġ"/ ")) ĠStringUtils . substring After Last ( src , Ġ"/") Ġelse Ġsrc ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġif Ġ( image Option Ġ== ĠImage Options . type ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" image " ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠStringUtils . default String ( first Element . getAttribute ( image Option . toString ())) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ"" ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ// Ġfinally Ġ/ Ġgive Ġup ĊĠĠĠĠĠĠĠ Ġreturn Ġ"" ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġinternal Ġfun Ġcsv Safe ( text : ĠString ): ĠString Ġ{ ĊĠĠĠĠĠĠĠ Ġvar Ġsafe Ġ= Ġtext ĊĠĠĠĠĠĠĠ Ġcsv Safe Replacement . forEach Ġ{ Ġ( search , Ġreplace ) Ġ-> Ġsafe Ġ= ĠStringUtils . replace ( safe , Ġsearch , Ġreplace ) Ġ} ĊĠĠĠĠĠĠĠ Ġsafe Ġ= ĠStringUtils . replace ( safe , Ġ"\ r ", Ġ"") ĊĠĠĠĠĠĠĠ Ġsafe Ġ= ĠStringUtils . replace ( safe , Ġ"\ n ", Ġ" Ġ") ĊĠĠĠĠĠĠĠ Ġsafe Ġ= ĠStringUtils . replace ( safe , Ġ"\ t ", Ġ" Ġ") ĊĊĠĠĠĠĠĠĠ Ġval Ġtrim Ġ= Ġweb Command . context . getBoolean Data ( DATA _ TRIM , ĠgetDefault Bool ( DATA _ TRIM )) ĊĠĠĠĠĠĠĠ Ġif Ġ( trim ) Ġsafe Ġ= ĠStringUtils . trim ( safe ) ĊĊĠĠĠĠĠĠĠ Ġreturn Ġsafe ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġnew Csv Writer ( file : ĠString ): ĠCsv Writer Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġformat Ġ= ĠCsv Format () ĊĠĠĠĠĠĠĠ Ġformat . delimiter Ġ= Ġweb Command . context . text Delim [ 0 ] ĊĠĠĠĠĠĠĠ Ġformat . set Line Separator ("\ n ") ĊĠĠĠĠĠĠĠ Ġval Ġsettings Ġ= ĠCsv Writer Settings () ĊĠĠĠĠĠĠĠ Ġsettings . format Ġ= Ġformat ĊĠĠĠĠĠĠĠ Ġreturn ĠCsv Writer ( File ( file ), ĠDEF _ FILE _ ENCODING , Ġsettings ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġclick Next Page ( next Page Locator : ĠString ): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġif Ġ( web Command . context . isNull OrEmpty Or Blank Value ( next Page Locator )) Ġfalse Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġnext Page Ġ= Ġweb Command . findElement ( next Page Locator ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( next Page Ġ== Ġnull Ġ|| Ġ! next Page . is Displayed Ġ|| Ġ! next Page . isEnabled ) Ġfalse Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġnext Page . click () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ } Ċ