# $Id: COMMON.pm,v 1.47 2006/06/29 19:16:43 xy128994 Exp $
# Copyright 2004 Sun Microsystems, Inc., All Rights Reserved.
# Sun Proprietary/Confidential: For Internal Use Only
package DeviceReport::COMMON;

use strict;
use base 'DeviceReport';

use Catalog::ReportClass;
use COMMON;
use DeviceReport;
use System;

sub new {
  my($class, $type) = @_;

  my $this = { "type" => $type };
  bless ($this, "DeviceReport::COMMON");
  return $this;
}


# New Common Report fru list map using ReportClass.
# report - hash of report values.
# q - ui options: filter, locale
sub fruListMap {
  my($class, $report, $q) = @_;

  my $filter = $q->{filter} || "logical";
  my $locale = $q->{locale};

  my $system     = createFromReport Catalog::ReportClass($report);
  my $type       = $class->{type};
  my $model      = new Catalog::Model($type);
  my $components = $system->getSubComponents($filter, $model);
  my(%S);

  foreach my $component (@$components){
	 my $code = $class->_fruCode($model, $component);
	 my $key  = $component->getComponentKey();
	 my $id   = $component->getPath();

	 my $info =
		{
		 name     => $component->getDisplayName(),
		 id       => $id,
		 key      => $key,
		 avail    => $component->getProperty("_Availability"),
		 state    => $component->getProperty("_EnabledState"),
		 status   => $component->getStatus(),
		 type     => $component->getProperty("_Caption"),
		 class    => $component->getClassName(),
		 revision => $component->getProperty("_FirmwareVersion")
		};
	 my $fru  = $component->getFRU();
	 if ($fru){
		$code = "FRU";
		$info->{revision} = $fru->getProperty("_Firmware");
		$info->{model}    = $fru->getProperty("_Model");
		$info->{vendor}   = $fru->getProperty("_Vendor");
		$info->{serial}   = $fru->getProperty("_SerialNumber");
	 }

         if ($code eq "LOGICAL") {

                $info->{onPreferredManager} = $component->getProperty("onPreferredManager");
                $info->{preferredManager} = $component->getProperty("preferredManager");
                $info->{currentManager} = $component->getProperty("currentManager");
		$info->{action} = $component->getProperty("_action");
         }

	 $S{$code}{$id} = $info;
  }
  return \%S;
} # fruListMap

# Common Report XML version of fruList
sub fruListXML {
  my($class, $report, $q) = @_;
  my $map = $class->fruListMap($report, $q);
  return DeviceReport->xml($map, "ID,SYSTEM");
}

sub summaryMap {
  my($class, $report, $q) = @_;
  my $summary    = $q->{summary}; # summary
  my $locale     = $q->{locale};
  my $rep        = $report->content();
  my $system     = createFromReport Catalog::ReportClass($report->content());
  my $type       = $report->id('category');
  my $model      = new Catalog::Model($type);
  my $components = $system->getSubComponents("logical", $model);

  my(%S);
  $S{HEADER} = $class->xmlHeader($rep);
  $S{SAN}    = $class->san_info($report);

  $S{ID}     = $class->_FillID($report);
  $S{SYSTEM} = $class->_FillSystem($system);

  foreach my $component (@$components){
	 my $className = $component->getClassName();
	 my $id        = $component->getPath();

	 if ($model->isA($className, "fcport")){
		$S{PORT}{$id} = $class->summaryPort($component);
	 }
	 elsif ($model->isA($className, "pool")) {
		$S{LOGICAL}{$id} = $class->summaryExtent($component);
	 }
	 elsif ($model->isA($className, "vdisk")) {
		$S{LOGICAL}{$id} = $class->summaryExtent($component);
	 }
	 elsif ($model->isA($className, "volume")) {
		$S{LOGICAL}{$id} = $class->summaryVolume($component);
	 }
	 else {
		my $code = $class->_fruCode($model, $component);
		$S{$code}{$id} = $class->summaryComponent($component);
	 }
  }
  return \%S;
}

sub summaryComponent {
  my ($class, $dev) = @_;
  my $fru = $dev->getFRU();

  my $info =
	 {
	  name         => $dev->getDisplayName(),
	  id           => $dev->getPath(),
	  key          => $dev->getKey(),
	  state        => $dev->getState(),
	  status       => $dev->getStatus(),
	  availability => $dev->getProperty("_Availability"),
	  type         => $dev->getProperty("_Caption"),
	  class        => $dev->getClassName(),
	  revision     => $dev->getProperty("_FirmwareVersion"),
	  keyLabel     => "serialNo",
	  keyValue     => $dev->getKey()
	 };
  if ($fru){
	 my $var = $fru->getProperty("_Firmware");
	 $info->{revision} = $var if ($var);
	 $info->{model}    = $fru->getProperty("_Model");
	 $info->{vendor}   = $fru->getProperty("_Vendor");
	 $info->{serial}   = $fru->getProperty("_SerialNumber");
  }
  return $info;
}

sub summaryPort {
  my ($class, $port) = @_;
  return
	 {
	  name     => $port->getDisplayName(),
	  id       => $port->getPath(),
	  key      => $port->getKey(),
	  state    => $port->getProperty("_EnabledState"),
	  status   => $port->getStatus(),
	  revision => $port->getProperty("_Revision"),
	  keyLabel => "WWN",
	  keyValue => $port->{"_WWN"},
	  type     => $port->getProperty("_Caption"),
	  class    => $port->getClassName(),
	  serial   => $port->getProperty("_PortNumber")
	 };
}

sub summaryExtent {
  my($class, $extent) = @_;

  return
	 {
	  name      => $extent->getDisplayName(),
	  id        => $extent->getPath(),
	  key       => $extent->getKey(),
	  type      => $extent->getProperty("_Caption"),
	  class     => $extent->getClassName(),
	  state     => $extent->getProperty("_MountState") || $extent->getState(),
	  status    => $extent->getStatus(),
	  raidLevel => $extent->getProperty("_RaidLevel"),
	  wwn       => $extent->getProperty("_WWN"),
	  capacity  => $extent->getProperty("_Capacity"),
	  disks     => $extent->getProperty("_BasedOn")
	 };
}

sub summaryVolume {
  my($class, $volume) = @_;

  return
	 {
	  name        => $volume->getDisplayName(),
	  id          => $volume->getPath(),
	  key         => $volume->getKey(),
	  type        => $volume->getProperty("_Caption"),
	  class       => $volume->getClassName(),
	  status      => $volume->getStatus(),
	  sourcePool  => $volume->getProperty("_SourceVdisk"),
	  sourceVdisk => $volume->getProperty("_SourceVdisk")
	 };
}

sub summaryXML {
  my($class, $report, $q) = @_;
  my $map = $class->summaryMap($report, $q);
  return $class->_summaryXMLfromMap($map);
}

sub _summaryXMLfromMap {
  my($class, $map) = @_;
  my $out = "<REPORT>\n";
  $out .= " <CONTENT>\n";
  $out .= DeviceReport->xml($map, "ID,SYSTEM");
  $out .= " </CONTENT>\n";
  $out .= "</REPORT>\n";
  return $out;
}

sub summaryFilterXML {
  my($class, $report, $summary) = @_;

  my $rep = $report->content();

  my $out = "<REPORT>\n";
  $out .= " <CONTENT>\n";
  foreach my $el (sort keys %$rep) {
	 if (substr($el,0, length($summary)) eq $summary) {
		$out .= "  <VALUE ID=\"$el\">" . 
		  Client->xmlEncode($rep->{$el}) . "</VALUE>\n";
	 }	
  }	
  $out .= " </CONTENT>\n";
  $out .= "</REPORT>\n";
}

sub _fruCode {
  my($class, $model, $component) = @_;
  my $dptype = $model->getProperty($component->getClassName(),
											  "_DevicePhysicalType");

# <value map="0">Logical</value>
# <value map="1">Sub-Component</value>
# <value map="2">FRU</value>
  if ($dptype->{"default"} eq "0"){
	 return "LOGICAL";
  }
  if ($dptype->{"default"} eq "1"){
	 return "COMPONENT";
  }
  if ($dptype->{"default"} eq "2"){
	 return "FRU";
  }

  # If not set guess fru if component has a fru.
  if ($component->getFRU()){
	 return "FRU";
  }	
  return "COMPONENT";
}

# 
# Client/InstrReport.pm Client/Inventory.pm
sub xmlFruList {
  my($class, $report, $q) = @_;
  my $map = $class->fruListMap($report->content(), $q);
  my $out =  DeviceReport->xml($map, "ID,SYSTEM");
  return ($map, $out);
}

sub xmlSummary {
  my($class, $report, $q) = @_;

  my $map = $class->summaryMap($report, $q);
  my $summary = $q->{summary}; # summary

  if ($summary){
	 return ($map, $class->summaryFilterXML($report, $summary));
  }
  return ($map, $class->_summaryXMLfromMap($map));
}


##############################################################################
# OLD REPORT METHODS.

sub fruList  { "ctrl,disk,pcu,midplane,sfp,fan,battery,iom"}
sub compList { "device,tempsensor" }



# Used by Client::Inventory::fruList
sub old_xmlFruList {
  my($class, $report, $q) = @_;

  my $filter = $q->{filter};

  my $rep = $report->content();
  my $FRU = COMMON->fruMap($rep);
  my $fru_list  = $class->fruList();
  my $comp_list = $class->compList();
  my(%S);

  foreach my $el (sort keys %$rep) {
       my @L = split(/\./, $el);
       my $k = "$L[0].$L[1]";
       next if ($filter && $k !~ /^$filter/);
       if (index(",$fru_list,$comp_list,", ",$L[0],") >= 0 && $L[2] eq "_DeviceID") {

              my $code = index(",$fru_list," , ",$L[0],") >= 0 ? "FRU" : "COMPONENT";

	      my $fruKey = $rep->{"$L[0].$L[1]._Realized"};
              my $F      = $FRU->{$fruKey};
              $S{$code}{$k}            = { name    => $rep->{"$k._Name"},
                                           id    => $k,
                                         avail   => $rep->{"$k._Availability"},
                                         state   => $rep->{"$k._EnabledState"},
                                         status  => $rep->{"$k._Status"},
                                         type    => $rep->{"$k._Caption"},
                                        revision => $F->{fwRev},
                                           model => $F->{model},
                                          vendor => $F->{vendor},
                                          serial => $F->{serial},
                                       };
       }
   }
   my $out = DeviceReport->xml(\%S, "ID,SYSTEM");
   return (\%S, $out);
}


# used by Client::InstrReport::summary
# called by new GUI framework
# return standard data structure.
#
sub xmlHeader {
  my($class, $rep) = @_;

  return  {
      device_name     => {order => 1, value => $rep->{'id.device_name'} },
      device_type     => {order => 2, value => $rep->{'id.device_type'} },
      device_key      => {order => 3, value => $rep->{'id.device_key'}  },
      device_ip       => {order => 4, value => $rep->{'id.ipno'}        },
      system_revision => {order => 5, value => $rep->{"system._Version"}},
      nvsram_revision => {order => 6, value => $rep->{"system.nvsram"}},
      };
}

sub _FillID {
  my($class, $rep) = @_;

  my $rid = $rep->{'_id'};

  my $id =  {
				 'id.ip'          =>  { value => $rep->{'id.ip'}},
				 'id.ipno'        =>  { value => $rep->{'id.ipno'}},
				 'id.mgmtLevel'   =>  { value => $rep->{'id.mgmtLevel'}},
				 'id.name'        =>  { value => $rep->{'id.name'}},
				 'id.key'         =>  { value => $rep->{'id.key'}}
				};
  foreach my $name (keys %$rid){
	 my $rname = "id.device_" . $name;
	 $id->{$rname} = { value => $rid->{$name}};
  }
  return $id;
}

sub _FillSystem {
  my($class, $system) = @_;

  my %SYSTEM;
  my $vars = $system->{vars};

  foreach my $name (keys %$vars){
     if ($name ne ""){
        $SYSTEM{"system." . $name} = { value => $vars->{$name}};
     }
  }
  return \%SYSTEM;
}

# Not used?
sub getFRUPerLogical {
  my($class, $rep, $logicalClass) = @_;
  return $class->getFRUCount($rep, $logicalClass) . " / " .
	 $rep->{"$logicalClass.count"};
}

# Not used?
# Get the number of fru's associated with a logical class in a report.
sub getFRUCount {
  my($class, $rep, $logicalClass) = @_;

  my $logicalCount = $rep->{"$logicalClass.count"};
  my $x;
  my $fruCount = 0;
  # The index always starts at 1.
  for ($x = 1; $x <= $logicalCount; $x++){
     if ($rep->{"$logicalClass.$x._Realized"}){
        $fruCount++;
     }
  }
  return $fruCount;
}



# used by Client::InstrReport::summary
sub old_xmlSummary {
  my($class, $report, $q) = @_;

  return $class->_xmlSummary0($report, $q);
}

# internal sub
sub _xmlSummary0 {
  my($class, $report, $q) = @_;

  my $rep = $report->content();

  my $summary = $q->{summary}; # summary
  my $normal  = $q->{normal};  # normalized
  my (%S, %VD);
  my $out = "<REPORT>\n";
  $out .= " <CONTENT>\n";

  $S{HEADER} = $class->xmlHeader($rep);

  my $FRU = COMMON->fruMap($rep);

  my $fru_list  = $class->fruList();
  my $comp_list = $class->compList();

  $S{SAN} = $class->san_info($report);

  foreach my $el (sort keys %$rep) {
       my @L = split(/\./, $el);
       my $k = "$L[0].$L[1]";
       if (!$summary) {
        if (index(",$fru_list,$comp_list,", ",$L[0],") >= 0 && $L[2] eq "_DeviceID") {

	      my $fruKey = $rep->{"$L[0].$L[1]._Realized"};
              my $F = $FRU->{$fruKey};
              my $code = index(",$fru_list,", ",$L[0],") >= 0 ? "FRU" : "COMPONENT";

              $S{$code}{$k}            = { name    => $rep->{"$k._Name"},
                                           id    => $k,
#                                         state   => $rep->{"$k._EnabledState"},
#                                         status  => $rep->{"$k._Status"},
                                         state   => $class->getState($rep, $k),
                                         status  => $class->getStatus($rep, $k),
                                   availability  => $rep->{"$k._Availability"},
                                         type    => $rep->{"$k._Caption"},
                                        revision => $F->{fwRev},
                                           model => $F->{model},
                                          vendor => $F->{vendor},
                                          serial => $F->{serial},
                                        keyLabel => "serialNo",
                                        keyValue => $rep->{$el},
                                       };
          } elsif ($L[0] eq "fcport" && $L[2] eq "_Caption") {
             if ($rep->{"$k._Name"}) {
                $S{PORT}{$k} = {    name => $rep->{"$k._Name"},
                                   id => $k,
                               state  => $class->getState($rep, $k),
                               status => $class->getStatus($rep, $k),
                             revision => $rep->{"$k._Revision"},
                             keyLabel => "WWN",
                             keyValue => $rep->{"$k._WWN"},
                                 type => $rep->{"$k._Caption"},
                               serial => $rep->{"$k._Caption"},
                                 };
             }
          } elsif ($L[0] eq "system") {
              $S{SYSTEM}{$k} = { value => $rep->{$el} };

          } elsif ($L[0] eq "id") {
              $S{ID}{$k} =  { value => $rep->{$el} };

          } elsif (($L[0] eq "pool") && ($L[2] eq "_Caption")) {
              $S{LOGICAL}{$k} =  { name    => $rep->{"$k._Name"}, 
                                    id     => $k,
                                  type     => $rep->{"$k._Caption"},
                                  state    => $rep->{"$k._MountState"},
                                 status    => $class->getStatus($rep, $k),
                                 raidLevel => $rep->{"$k._RaidLevel"},
                                       wwn => $rep->{"$k.WWN"},
                                  capacity => $rep->{"$k.capacity"},
                                     disks => $rep->{"$k.diskSet"},
                                 };

          } elsif (($L[0] eq "vdisk") && ($L[2] eq "_Caption")) {
              $S{LOGICAL}{$k} =  { name    => $rep->{"$k._Name"}, 
                                    id     => $k,
                                  type     => $rep->{"$k._Caption"},
                                  state    => $rep->{"$k._MountState"},
                                 status    => $class->getStatus($rep, $k),
                                 raidLevel => $rep->{"$k._RaidLevel"},
                                       wwn => $rep->{"$k.WWN"},
                                  capacity => $rep->{"$k.capacity"},
                                     disks => $rep->{"$k.diskSet"},
                                 };

          } elsif (index(",volume,lun,", ",$L[0],") >= 0  && $L[2] eq "_Caption") {
              $S{LOGICAL}{$k} =  { name     => $rep->{"$k._Name"}, 
                                    id      => $k,
                                  type      => $rep->{"$k._Caption"},
                                 status     => $class->getStatus($rep, $k),
                                 sourcePool => $rep->{"$k._SourceVdisk"},
                                sourceVdisk => $rep->{"$k._SourceVdisk"},
                                 };
                                           
          } else {
              #$S{OTHER}{"$L[0].$L[1]"} = 1;
          }
       } elsif (substr($el,0, length($summary)) eq $summary) {
          $out .= "   <VALUE ID=\"$el\">" . Client->xmlEncode($rep->{$el}) . "</VALUE>\n";
       }
  }

  if (!$summary) {
    $out .= DeviceReport->xml(\%S, "ID,SYSTEM");
  }

  $out .= " </CONTENT>\n";
  $out .= "</REPORT>\n";
  return (\%S, $out);
}


# Returns the contents of the _Status field from the report.
# If status is "Other", substitute the _RawStatus field contents.
sub getStatus
{
  my($class, $report, $prefix) = @_;

  my $status = $report->{"$prefix._Status"};
  if ($status eq "Other")
  {
     $status = $report->{"$prefix._RawStatus"};
  }

  return $status;

}

# Returns the contents of the _EnabledState field from the report.
# Translate the numerical value to a String value.
# If status is "Other", substitute the contents of the _OtherEnabledState 
# field.
sub getState
{
  my($class, $report, $prefix) = @_;

  my $state = $report->{"$prefix._EnabledState"};


  if ($state eq '1')
  {
     $state = $report->{"$prefix._OtherEnabledState"};
  }
  else
  {
     if ($state eq '2')
     {
        $state = "Enabled";
     }
     elsif ($state eq '3')
     {
        $state = "Disabled";
     }
     elsif ($state eq '4')
     {
        $state = "Shutting Down";
     }
     elsif ($state eq '5')
     {
        $state = "Not Applicable";
     }
     elsif ($state eq '6')
     {
        $state = "Enabled but Offline";
     }
     elsif ($state eq '7')
     {
        $state = "In Test";
     }
     elsif ($state eq '8')
     {
        $state = "Deferred";
     }
     elsif ($state eq '9')
     {
        $state = "Quiesced";
     }
     elsif ($state eq '10')
     {
        $state = "Starting";
     }
     else
     {
        $state = "Unknown";
     }

  }
  return $state
}


1;
