# $Id: COMMON.pm,v 1.9 2006/03/16 20:02:08 sbrooks Exp $
# Copyright 2004 Sun Microsystems, Inc., All Rights Reserved.
# Sun Proprietary/Confidential: For Internal Use Only
package Revision::COMMON;

use strict;
use base 'Revision';

use Catalog::Implementation;
use Catalog::Revision;
use PDM::ConfigFile;
use System;
use Util;

sub new {
  my($class, $type) = @_;
  my $this = { type    => $type,
					rev     => new Catalog::Revision($type)
				 };
  bless($this, "Revision::COMMON");
  return $this;
}

sub class {
  my ($this) = @_;
  my $type = $this->type();
  return "oob." . $type;
}

sub description {
  my ($class, $type) = @_;
  if (!$type){
	 return "Common Revision for " .$class->modules_list();
  }
  my $impl = new Catalog::Implementation($type);
  if ($impl){
	 return $impl->getInfo("description") ||
		$impl->getInfo("displayName");
  }	
  return "Common revision not supported for $type";
}

sub type {
  my ($this) = @_;
  if (ref($this) eq "Revision::COMMON"){
	 return $this->{type};
  }
  return "COMMON";
}

sub enabled {
   my ($this) = @_;
	my $rev = $this->{rev};
	if ($rev){
	  return $rev->enabled();
	}
	return 0;
}

sub modules {
  my($class) = @_;
  my @mods;
  my $entries = Catalog::Implementation->loadAll();
  foreach my $ctype (keys %$entries){
	 my $impl = $entries->{$ctype};
	 next if (!$impl->canRevcheck());
	 next if (!$impl->isEnabled());
	 push(@mods, $ctype);
  }
  return \@mods;
}

sub modules_list {
  my($class, $sep) = @_;
  $sep = "|" if (!$sep);
  my $entries = Catalog::Implementation->loadAll();
  my $out;
  foreach my $ctype (keys %$entries){
	 my $impl = $entries->{$ctype};
	 next if (!$impl->canRevcheck());
	 next if (!$impl->isEnabled());
	 if ($out){
		$out.="|".$ctype;
	 }
	 else {
		$out = $ctype;
	 }
  }
  return $out;
}

sub RUN {
  my($class, $Matrix, $InstalledPatches) = @_;
  my $entries = Catalog::Implementation->loadAll();
  my($renv, $devs, $hosts, $notifs) = PDM::ConfigFile->read;

  my(@R);
  foreach my $ctype (keys %$entries){
	 my $impl = $entries->{$ctype};
	 next if (!$impl->isEnabled());
	 my $rev = new Revision::COMMON($ctype);
	 my $r   = $rev->TYPE_RUN($Matrix, $InstalledPatches, $devs);
	 push(@R, @$r);
  }
  return \@R;
}

sub REVISION {
  my($class, $Matrix, $InstalledPatches, $dev, $rep) = @_;
  my $rev = new Revision::COMMON($dev->{type});
  return $rev->TYPE_REVISION($Matrix, $InstalledPatches, $dev, $rep);
}

sub TYPE_RUN {
  my($this, $Matrix, $InstalledPatches, $devs) = @_;

  my(@R);
  my $type = $this->{type};


  foreach my $dev (@$devs) {
	 next if ($dev->{type} ne $type);
	 next if (!Util->isMineToMonitor($dev));

	 my $oreport = PDM->getOldReport($dev->{type} .":". $dev->{key});
	 if ($oreport){
		my $report  = $oreport->content();
		my $r1 = $this->TYPE_REVISION($Matrix, $InstalledPatches, $dev, $report);
		push(@R, @$r1);
	 }
	 else {
		my $lockerr = $this->checkLock($dev);
		if ($lockerr){
		  push(@R, $lockerr);
		}
		else {
		  my $agent  = Catalog::Implementation->loadAgent($type);
		  my $report = $agent->INSTRUMENTATION($dev);
		  my $r1 = $this->TYPE_REVISION($Matrix, $InstalledPatches,
												  $dev, $report);
		  push(@R, @$r1);
		}
	 }
  }

  if ($#R < 0) {
      push(@R,[$type, 'N/A', 'ERR', undef, undef,undef,undef,
            "No $type device, please check system setup"]);
  }
  return \@R;
}


# runs on only one device, dev is from the configFile
sub TYPE_REVISION {
  my($this, $Matrix, $InstalledPatches, $dev, $rep) = @_;
  my $type = $this->{type};

  my $rc  = createFromReport Catalog::ReportClass($rep);
  my $rev = $this->{rev};
  my(@R);

  my $rmap = $rc->getObjectMap();
  foreach my $name (keys %$rmap) {
	 my $comp = $rmap->{$name};

	 # Only perform the check if there is a physical component. 
	 # (ie. _Realized is set)
	 my $checkable = 0;
	 if ($comp->getComponentProperty("_Realized"))
	 {
	    $checkable = 1;
	 }

	 # However, allow checks on the system class as there may be code
	 # not associated with a particular FRU, but rather the entire 
	 # system.
	 if ($comp->getClassName() eq "system")
	 {
	    $checkable = 1;
	 }

	 if ($checkable){

	    my $revent = $rev->evaluateRevision($dev, $comp);
	    if ($revent){
		my $rtype = $type;
		if ($revent->{className}){
		  $rtype = $type . "." . $revent->{className};
		}
		my $rname = $revent->{device};
		if ($revent->{component}){
		  $rname = $rname . ":" . $revent->{component};
		}
		my $patch = $revent->{patch};
		push(@R, [$rtype, $rname, $revent->{status},
					 $revent->{curr_version},
					 $revent->{expected_version},
					 $revent->{current_patch},
					 $revent->{expected_patch},
					 $revent->{description}
					]);
	    }
	 }
  }
  if ($#R < 0) {
	 push(@R,[$type, 'N/A', 'NI', undef, undef,undef,undef,
				 "No revision rules used for $type device."]);
  }
  return \@R;
}

1;
