# $Id: Implementation.pm,v 1.4 2004/11/19 23:41:42 sbrooks Exp $
# Copyright 2004 Sun Microsystems, Inc., All Rights Reserved.
# Sun Proprietary/Confidential: For Internal Use Only
package Catalog::Implementation;

use strict;
use System;
use Catalog::Entry;
use Catalog::XML;
use Debug;
use base 'Catalog::Entry';

use vars qw(%IMPLS);

# Create a new implementation
sub new {
  my ($class, $type, $dir) = @_;

  my $this = { "type"   => $type,
               "entry"  => "implementation.xml",
					"dir"    => $dir
				 };
  bless($this, "Catalog::Implementation");
  return $this->loadEntry();
}

# load all implementations
sub loadAll {
  my ($class) = @_;
  if (%IMPLS){
	 return \%IMPLS;
  }
  my $devs = $class->listEntries();
  foreach my $dev (keys %$devs) {
	 my $impl = new Catalog::Implementation($dev, $devs->{$dev});
	 $IMPLS{$dev} = $impl;
  }
  return \%IMPLS;
}

# Load an agent for a given module name.
sub loadAgent {
  my ($class, $modname) = @_;
  my $devs = $class->loadAll();

  my $type = lc($modname);
  my $imp  = $devs->{$type};

  if ((!$imp)||(!$imp->isEnabled())){
	 if (!eval "require \"Agent/${modname}.pm\"") {
		Debug->err(LOADING => "$modname: $@ \n");
		return undef;
	 }
	 my $f = "Agent::$modname";
	 my $agent = $f->new();
	 return (undef) if (!$agent->can('RUN'));
	 return $agent;
  }

  Debug->print2("Loading plug in agent for $type.");

  require Agent::COMMON;
  my $agent = new Agent::COMMON($type);
  return $agent;
}

sub load {
  my ($this) = @_;
  eval {
	 if ( -f $this->{file}){
		$this->{data} = Catalog::Implementation->read($this->{file});
	 }	
  };
  if ($@) {
	 $this->setError($@);
  }
}

sub getInterface {
  my ($this, $iname) = @_;
  my $imp = $this->{data};
  return $imp->{implementation}->{interface}->{$iname};
}

sub getInfo {
  my ($this) = @_;
  my $imp = $this->{data};
  use Data::Dumper;
  my $props = $imp->{implementation}->{info}->{property};
  my %info;
  foreach my $p (keys %$props) {
	 next if ($p eq "_ATT");
	 my $prop = $props->{$p};
	 $info{$prop->{_ATT}->{name}} = $prop->{_VAL};
  }
  return \%info;
}

# Return 0 if implementation enable attribute is false, otherwise return 1.
sub isEnabled {
  my ($this) = @_;
  my $enabled = $this->{data}{implementation}{_ATT}{enabled};
  if ($enabled eq "true") { return 1;}
  if ($enabled eq "false"){ return 0;}
  return 0; 
}

sub isSelectable {
  my ($this) = @_;
  my $imp = $this->{data};
  my $props = $imp->{implementation}->{info}->{property};
  return $props->{displayName}->{_VAL};
}


# file relative to SUNWstade
sub read {
  my($class, $file) = @_;

  my $imp = Catalog::XML->parseFile($file,
          {  ROOT => 'implementation',
             hash => { interface => 'name',
                       property  => 'name',
                       value     => 'name',
                     },
          });
  return $imp;
}

# Catalog.pm uses this.
sub readAll {
  my($class, $dir) = @_;
  my %IMPL;
  $dir = System->get_home() if (!$dir);
  my $L = $dir . Catalog->device_path();
  opendir(R, $L);
  my @dirs = readdir(R); closedir(R);
  foreach my $d (@dirs) {
     next if (substr($d,0,1) eq ".");
     if (-f "$L/$d/implementation.xml") {
        my $i = $class->read( "$L/$d/implementation.xml");
        $i->{implementation}{_ATT}{BASE_DIR} = $dir;
        my $type = $i->{implementation}{_ATT}{type};
        $IMPL{$type} = $i;
     }
  }
  return \%IMPL;
}

1;

