package Ernad::ReportState; use strict; use warnings; use Carp qw(confess); use Data::Dumper; use Encode; use File::Basename; use File::Copy; use Ernad::Common; use Ernad::Erimp; use Krichel::Shoti; use Krichel::File; our $UNKNOWN = 'unknown'; # Unknown state our $STATEFILE = 'state'; # Filename our $RiffExtension= '.amf.xml'; # A Riff's extension our $e; $e=$main::e; #if(not defined($e)) { # $e=$Erimp::e; #} ## constructor sub new { my $this = shift; my $class = ref($this) || $this; my $rs = {}; bless $rs, $class; my $repcode=shift(); if(not $repcode) { my ( $package, $filename, $line ) = caller; my $error="Your package $package file $filename line $line called "; $error.="new Reportstate without repcode."; confess $error; } my $e=shift or confess 'I need an erimp.'; if(not $e->{'report'}->{$repcode}->{'path'}) { if(not $e->{'r'}) { confess "My erimp does not see its recon."; } $e->{'r'}->load($repcode); } my $Path=$e->{'report'}->{$repcode}->{'path'}; my $path=$e->{'report'}->{$repcode}->{'path'}; $rs->{'repcode'}=$repcode; $rs->{'path'}=$path; $rs->{'stage'}='unknown'; $rs->{'e'}=$e; $rs->{'rix'}=''; $rs->{'file'}=''; return $rs; } # The name, current sub repcode() { my $rs = shift(); return $rs->{'repcode'}; } # The path, current sub path() { my $rs = shift(); return $rs->{'path'}; } ## The stage, current sub stage() { my $rs = shift(); my $stage_to_set = shift // ''; my $e=$rs->{'e'}; my $source_dir=$e->{'const'}->{'source_dir'}; ## set the stage if($stage_to_set) { ## Stage is going to be set ## Find the most recent file in new stage $rs->{'stage'} = $stage_to_set; if($rs->{'stage'} ne $source_dir) { my $search_path=$rs->{'path'}.'/'.$rs->{'stage'}; $rs->{'file'} = $e->{'d'}->most_recent_rif($search_path); ## set back to the source of no oldest file can be found if(not $rs->{'file'} ) { $rs->{'stage'} = $source_dir; } } else { $rs->{'file'} = ''; } $rs->{'rix'} = ''; $rs->save_to_state_file(); } return $rs->{'stage'}; } # The full path to report file sub file() { my $rs = shift(); if(not defined($rs->{'path'})) { ## 2020-01-13: better reporting here my $d_rs=Dumper $rs; confess 'I need a path.' . $d_rs; } if(not defined($rs->{'stage'})) { confess 'I need a stage.'; } if(not defined($rs->{'file'})) { die 'I need a file.'; } ## immergency maintenance on 2019-06-19 if(-f $rs->{'file'}) { return $rs->{'file'}; } return $rs->{'path'}.'/'.$rs->{'stage'}.'/'.$rs->{'file'}; } # report XML? sub rix() { my $rs = shift(); return $rs->{'rix'}; } # Returns report timestamp, rather the issuedate sub timestamp() { my $rs = shift(); if(not $rs->{'file'}) { return ''; } my @s; @s = split( "_", $rs->{'file'} ); return $s[0]; } ## Loads sub load { my $rs = shift(); my $issuedate=shift // ''; my $e=$rs->{'e'}; # Build up filename of state file my $rif_ext=$e->{'const'}->{'rif_ext'}; ## check all folders and find which one contains latest report my $current_stage = ''; my $current_file = ''; my @stages=@{$e->{'const'}->{'stages'}}; if($e->{'testing'}) { open(L,'> '.$e->{'dir'}->{'test'}.'/report_state_load.log'); print L "start\n"; } foreach my $stage (@stages) { ## files in the stage my $file_found_in_stage = $e->{'d'}->most_recent_rif( $rs->{'path'}.'/'.$stage, 'do_lax') // ''; if($e->{'testing'}) { print L "stage $stage, found file_found_in_stage $file_found_in_stage\n"; } ## skip if there no files in the analyzed folder if( $file_found_in_stage eq '') { if($e->{'testing'}) { print L "no file found, next ...\n"; } next; } ## initialize stage if( $current_stage eq '' ) { if($e->{'testing'}) { print L "setting current_file to $file_found_in_stage\n"; } $current_file = $file_found_in_stage; if($e->{'testing'}) { print L "setting stage to $stage\n"; } $current_stage = $stage; } #elsif(&Ernad::Common::is_first_rif_more_recent($file_found_in_stage,$current_file)) { elsif($e->{'f'}->is_first_more_recent($file_found_in_stage,$current_file)) { if($e->{'testing'}) { print L "updating current_file to $file_found_in_stage\n"; } $current_file=$file_found_in_stage; $current_stage=$stage; if($e->{'testing'}) { print L "updating stage to $stage\n"; } } } if($e->{'testing'}) { close L; } ## source is the default stage if($current_file eq '') { $current_stage = $e->{'const'}->{'source_dir'}; } ## set values $rs->{'stage'} = $current_stage; $rs->{'file'} = $current_file // ''; #if(not (not $current_file or $current_file eq './' or $current_file eq '..')) { if($current_file) { #$rs->{'update_tist'}=&Ernad::Common::get_rif_tist($current_file) $rs->{'update_tist'}=$e->{'f'}->tist($current_file) } ## case of an empty report if(not defined($rs->{'update_tist'})) { $rs->{'update_tist'}=time; } $rs->{'rix'} = ''; } sub load_from_stage { my $rs=shift; my $stage=shift // confess "I need a stage here."; ## files in the stage my $e=$rs->{'e'}; my $file_found_in_stage = $e->{'d'}->most_recent_rif( $rs->{'path'}.'/'.$stage ); if($e->{'testing'}) { print L "stage $stage, found file_found_in_stage $file_found_in_stage\n"; } ## skip if there no files in the analyzed folder if($file_found_in_stage eq '') { if($e->{'testing'}) { print L "no file found, next ...\n"; } return 0; } $rs->{'file'}=$file_found_in_stage; ## rs->file() gives the full path $rs->{'rix'}= &Krichel::File::load($rs->file()); $rs->save_to_state_file(); return 1; } sub set_stage { my $rs=shift; my $stage=shift // confess "I need a stage here."; my $e=$rs->{'e'}; if($stage eq 'source') { $rs->{'stage'} = $e->{'const'}->{'source_dir'}; $rs->{'file'} = ''; return 0; } ## files in the stage my $to_find = $rs->{'path'}.'/'.$stage; my $file_found_in_stage = $e->{'d'}->most_recent_rif( $to_find ); if($e->{'testing'}) { print L "stage $stage, found file_found_in_stage $file_found_in_stage\n"; } ## skip if there no files in the analyzed folder if($file_found_in_stage eq '') { confess "no file found in $stage at $to_find"; return 0; } $rs->{'stage'}=$stage; $rs->{'file'}=$file_found_in_stage; ## rs->file() gives the full path $rs->{'rix'}= &Krichel::File::load($rs->file()); $rs->save_to_state_file(); return 1; } ## Parses and loads in memory xml report sub load_rix { my $rs = shift(); ## wellington #if( $Ernad::Common::Config{'DebugInfo'} ) { #print "trying to load ". $rs->{'file'}."
\n"; #} ### my $file=$rs->file() // ''; if(not $file) { confess 'I have no file to load rix from'; } if(not -f $file) { ## just remove the state file, as the bad reference is likely be there my $state_file=$rs->{'state_file'}; if($state_file) { unlink $state_file; } ##confess "I don't have the file '$file'."; if(not $rs->{'no_reload'}) { $rs->{'no_reload'}=1; $rs->load(); my $file=$rs->file() // ''; if(not $file) { confess 'I have no file to load rix from, even after reload.'; } } } else { ## in case it does not exits, we can reload $rs->{'can_reload'}=1; } $rs->{'rix'} = &Krichel::File::load( $rs->file()); return $rs->{'rix'}; } ## Generates filename sub generate_file_name { my $rs = shift(); my $file = shift // $rs->{'file'}; if(not $file ) { confess "I need a file here."; } my $e=$rs->{'e'}; ## Xmas 2017 my $bana=basename($file); my $dina=dirname($file); if(not $bana=~m|^(\d{4}-\d{2}-\d{2})|) { confess "I have a bad filename $file."; } my $date=$1; my $now=&Krichel::Shoti::now(); my $new_file=$date.'_'.$now.$e->{'const'}->{'rif_ext'}; return $new_file; } ## saves the state file sub save_to_state_file() { my $rs = shift(); my $e=$rs->{'e'}; my @toStore; $toStore[0] = $rs->{'stage'}; $toStore[1] = $rs->{'file'}; $rs->{'state_file'}=$rs->{'path'}.'/'.$e->{'const'}->{'state_file'}; if(not $rs->{'stage_file'}) { my $state_file = $rs->{'path'}.'/'.$e->{'const'}->{'state_file'}; $rs->{'state_file'}=$state_file; } ###Ernad::Common::save_to_file( \@toStore, $rs->{'state_file'}); } ## Saves the state sub save { my $rs = shift(); my $new_stage=shift // $rs->{'stage'}; my @toStore; my $e=$rs->{'e'}; ## Filename must be set to process if(not $rs->{'file'} ) { $rs->save_to_state_file(); return; } my $old_stage = $rs->{'stage'}; my $old_file = $rs->{'file'}; ## Generate new filename, main change of Xmas 2017 my $new_file = $rs->generate_file_name(); if( $rs->{'rix'} ) { # If report is in memory # then save it as xml in utf-8 encoding my $out_file=$rs->{'path'}.'/'.$new_stage.'/'.$new_file; &Krichel::File::prepare($out_file); open(OUT, "> $out_file"); binmode(OUT,":utf8:"); my $out_string=decode_utf8($rs->{'rix'}->toString() ); $out_string.="\n"; print OUT $out_string; close OUT; } else { # Report is not in memory # it means it wasnt changed # so simply copy it ### Wellington my $old_file=$rs->{'path'}.'/'."$old_stage".'/'.$old_file; my $new_file=$rs->{'path'}.'/'."$new_stage".'/'.$new_file; #if( $Ernad::Common::Config{'DebugInfo'} ) { # print "I copy $old_file to $new_file
\n"; #} copy($old_file, $new_file); } # Update state and file $rs->{'stage'} = $new_stage; $rs->{'file'} = $new_file; # $rs->save_to_state_file(); } ## creates a new source file sub create_from_source { my $rs = shift(); my $type = shift(); # presorted or unsorted my $dt = shift(); # Date of the file my $e=$rs->{'e'}; ## get filename my $source_dir = $e->{'const'}->{'source_dir'}; my $created_dir = $e->{'const'}->{'created_dir'}; ## up will become the general case. Then the type will not ## be require. I still have to check the xslt my $glob = $rs->{'path'}.'/'.$source_dir.'/'.$dt."*" ; my $old_file = $e->{'d'}->get_last_file($glob); ## in case we still store by us/ps/sd if($old_file == 0) { my $glob = $rs->{'path'}.'/'.$source_dir.'/'.$type.'/'.$dt."*" ; # my $old_file = Ernad::Common::get_last_file($glob); $old_file = $e->{'d'}->get_last_file($glob); } ## generate new filename, main change of Xmas 2017 my $new_file_name = $rs->generate_file_name( $old_file ); my $new_file = $rs->{'path'}.'/'.$created_dir.'/'.$new_file_name; ## copy if($old_file =~m|\.gz$|) { if($e->{'testing'}) { open(L,'> '.$e->{'dir'}->{'test'}.'/report_state_load.log'); print L "I zcat $old_file to $new_file
\n"; } system("/bin/zcat $old_file > $new_file"); } else { #if($e->{'testing'}) { # print L "I copy $old_file to $new_file
\n"; #} copy($old_file, $new_file); } ## update members $rs->{'stage'} = $e->{'const'}->{'created_dir'}; $rs->{'file'} = $new_file_name; $rs->{'rix'} = ''; $rs->save_to_state_file(); } sub vadoc_file { my $rs = shift; my $vadoc_type= shift // confess "I need a vadoc_type here"; my $issuedate=$rs->issuedate() // confess "I can't get the issuedate."; my $e=$rs->{'e'}; my $vadoc_file=$rs->{'path'}.'/'.$e->{'const'}->{'vadoc_dir'}.'/'.$issuedate.'_'.$vadoc_type.'.xml'; &Krichel::File::prepare($vadoc_file); $rs->{'vadoc_file'}->{$vadoc_type}=$vadoc_file; return $vadoc_file; } sub delete_vadoc_file { my $rs = shift; my $vadoc_type= shift // confess "I need a vadoc_type here"; my $vadoc_file = $rs->{'vadoc_file'}->{$vadoc_type} // return 0; if(not -f $vadoc_file) { return 0; } unlink $vadoc_file; } sub save_vadoc { my $rs = shift; my $vadoc_type= shift // confess "I need a vadoc_type here"; my $vadoc=shift; my $ref_doc=ref $vadoc; if($ref_doc ne 'XML::LibXML::Document') { confess "I need a doc here, but you gave me a $ref_doc"; } my $vadoc_file=$rs->vadoc_file($vadoc_type); $vadoc->toFile($vadoc_file,1); return $vadoc; } sub load_vadoc { my $rs = shift; my $vadoc_type= shift // confess "I need a vadoc_type here"; my $vadoc_file=$rs->vadoc_file($vadoc_type); if(not -f $vadoc_file) { return ''; } my $vadoc=&Krichel::File::load($vadoc_file); $rs->{'vadoc'}->{$vadoc_type}=$vadoc; return $vadoc; } ## sub issuedate { my $rs=shift; my $date=shift // ''; my $e=$rs->{'e'} or confess 'I need an erimp.'; if($date) { $rs->{'issuedate'}=$date; return $date; } my $file=$rs->{'file'} // ''; if(not $file) { $rs->{'file'} = $e->{'d'}->most_recent_rif($file); } $file=$rs->{'file'} // return 0; $date=$e->{'f'}->issuedate($file) // ''; if($date) { $rs->{'issuedate'}=$date; return $date; } confess "I could not find issuedate on '$file'."; } ## update the editor data sub update_editor { my $rs=shift; my $e=$rs->{'e'} or die 'no erimp'; my $dm=Dumper $rs; my $rix=$rs->{'rix'} // '' ; if(not $rix) { $rs->load_rix(); } $rix=$rs->{'rix'}; if(not $rix) { die "no rix"; } $rs->{'rix'}=$e->{'x'}->update_editor($rix); # $rix->toFile("/tmp/rix.xml"); } 1;