[Bio] / FigKernelPackages / FIGMODELdatabase.pm Repository:
ViewVC logotype

View of /FigKernelPackages/FIGMODELdatabase.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.21 - (download) (as text) (annotate)
Wed Sep 1 17:31:30 2010 UTC (9 years, 3 months ago) by dejongh
Branch: MAIN
CVS Tags: rast_rel_2010_0928, rast_rel_2010_1206
Changes since 1.20: +22 -37 lines
Get config info from the FIGMODEL instead of duplicating it in FIGMODELdatabase

use lib "/home/chenry/public_html/FIGdisk/dist/releases/snap-2006-0223/cee/lib/ModelSEED/";
use DBMaster;
use Sapling;
use ModelObjectType;

package FIGMODELdatabase;
use strict;
use Fcntl qw/:DEFAULT :seek :flock/;

=head1

=head2 Introduction
Module for loading and altering data in the model database.
There will be a local and remote version of this module.
The remote version will be implemented using the server technology.

=head2 Core Object Methods

=head3 new
Definition:
	FIGMODELdatabase = FIGMODELdatabase->new();
Description:
	This is the constructor for the FIGMODELdatabase object.
=cut

sub new {
	my ($class,$DatabaseDirectory,$figmodel) = @_;
	my $self;
	$self->{"_database root directory"}->[0] = $DatabaseDirectory;
	$self->{"_figmodel"}->[0] = $figmodel;
	bless $self;
	return $self;
}

=head3 figmodel
Definition:
	FIGMODEL = FIGMODELdatabase->figmodel();
Description:
	Returns a FIGMODEL object
=cut
sub figmodel {
	my ($self) = @_;
	return $self->{"_figmodel"}->[0];
}

=head3 fail
Definition:
	-1 = FIGMODEL->fail();
Description:
	Standard return for failed functions.
=cut
sub fail {
	my ($self) = @_;
	return $self->figmodel()->fail();
}

=head3 success
Definition:
	1 = FIGMODEL->success();
Description:
	Standard return for successful functions.
=cut
sub success {
	my ($self) = @_;
	return $self->figmodel()->success();
}

=head3 config
Definition:
	ref::key value = FIGMODELdatabase->config(string::key);
Description:
	Trying to avoid using calls that assume configuration data is stored in a particular manner.
	Call this function to get file paths etc.
=cut

sub config {
	my ($self,$key) = @_;

	return $self->figmodel()->config($key);
}

=head3 get_object_manager
Definition:
	databasehandle:database handle for input object type = FIGMODELdatabase->get_object_manager(string::type);
Description:
=cut
sub get_object_manager {
	my ($self,$type) = @_;
	my $ppoObjects = {"bof"=>1,"reaction"=>1,"compound"=>1,"queue"=>1,"job"=>1,"mgjob"=>1,"rastjob"=>1,"rasttestjob"=>1,"model"=>1,"user"=>1,"mgmodel"=>1,"fbaresult"=>1,"media"=>1,"mediacpd"=>1,"complex"=>1,"role"=>1,"cpxrole"=>1,"cpdals"=>1,"cpdbof"=>1,"cpdgrp"=>1,"cpdrxn"=>1,"rxnals"=>1,"rxncpx"=>1,"rxngrp"=>1,"rxnmdl"=>1};
	if (!defined($self->{_dbhandles}->{$type})) {
		if (defined($ppoObjects->{$type})) {
			#Checking on the status of the database and returned undefined if the status is zero
			if ($self->config("PPO_tbl_".$type)->{status}->[0] == 0) {
				return undef;	
			}
			my $temp = DBMaster->new(-database => $self->config("PPO_tbl_".$type)->{name}->[0],
	                           -host     => $self->config("PPO_tbl_".$type)->{host}->[0],
	                           -user     => $self->config("PPO_tbl_".$type)->{user}->[0],
	                           -password => $self->config("PPO_tbl_".$type)->{password}->[0],
	                           -port     => $self->config("PPO_tbl_".$type)->{port}->[0],
	                           -socket   => $self->config("PPO_tbl_".$type)->{"socket"}->[0]);
	    	$self->{_dbhandles}->{$type} = $temp;
		} else {
			$self->{_dbhandles}->{$type} = ModelObjectType->new($self->figmodel(),$type);
		}
	}
	if (defined($ppoObjects->{$type})) {
		my $table = $self->config("PPO_tbl_".$type)->{table}->[0];
		return $self->{_dbhandles}->{$type}->$table();
	}
	return $self->{_dbhandles}->{$type};
}

=head3 get_object
Definition:
	PPOobject:first object matching specified type and query = FIGMODELdatabase->get_object(string::type,{}:query);
Description:
=cut
sub get_object {
	my ($self,$type,$query) = @_;
	my $objMgr = $self->get_object_manager($type);
	if (!defined($objMgr)) {
		return undef;	
	}
	my $objs = $objMgr->get_objects($query);
	if (!defined($objs->[0])) {
		return undef;	
	}
	return $objs->[0];
}

=head3 get_objects
Definition:
	[PPOobject]:objects matching specified type and query = FIGMODELdatabase->get_object(string::type,{}:query);
Description:
=cut
sub get_objects {
	my ($self,$type,$query) = @_;
	my $objMgr = $self->get_object_manager($type);
	if (!defined($objMgr)) {
		return undef;	
	}
	return $objMgr->get_objects($query);
}

=head3 get_object_manager
Definition:
	databasehandle:database handle for input object type = FIGMODELdatabase->get_object_manager(string::type);
Description:
=cut
sub check_out_new_id {
	my ($self,$type) = @_;
	if (!defined($self->{_dbhandles}->{id})) {
		$self->{_dbhandles}->{id} = DBMaster->new(-database => $self->config("PPO_tbl_id")->{name}->[0],
    	                   -host     => $self->config("PPO_tbl_id")->{host}->[0],
                           -user     => $self->config("PPO_tbl_id")->{user}->[0],
                           -password => $self->config("PPO_tbl_id")->{password}->[0],
                           -port     => $self->config("PPO_tbl_id")->{port}->[0],
                           -socket   => $self->config("PPO_tbl_id")->{"socket"}->[0]);
	}
	#Get the id
	my $data = $self->{_dbhandles}->{id}->backend()->dbh->selectrow_arrayref('select id,prefix,digits from ModelDB.CURRENTID where (object = "'.$type.'") for update;');
	#Iterate the ID
	$self->{_dbhandles}->{id}->backend()->dbh->do('UPDATE ModelDB.CURRENTID SET id = id + 1 WHERE (object = "'.$type.'");');
    $self->{_dbhandles}->{id}->backend()->dbh->commit();
 	#Creating the id
 	while (length($data->[0]) < $data->[2]) {
 		$data->[0] = "0".$data->[0];
 	}
 	return $data->[1].$data->[0];
}

=head3 is_type
Definition:
	(0/1) = FIGMODELdatabase->is_type(string::type);
Description:
	Checks if the input string is an object type in the database. "1" for yes, "0" for no.
=cut
sub is_type {
	my ($self,$type) = @_;
	if (defined($self->figmodel()->config("object types")->{$type})) {
		return 1;
	}
	return 0;
}

=head3 db_link
Definition:
	{string:from type IDs => [string]:list of to type IDs} = FIGMODELdatabase->db_link(string:link from type,string:link to type,{string:type=>[string]:type list]});
Description:
	Returns a hash with the "from type" as keys and arrays of "to types" as values.
=cut
sub db_link {
	my ($self,$fromType,$toType,$idlist) = @_;
	my $result;
	foreach my $id (@{$idlist}) {
		if ($fromType eq "interval") {
			if ($toType eq "feature") {
				my $IntervalTable = $self->GetDBTable("INTERVAL TABLE");
	            if (defined($IntervalTable)) {
	            	my $Row = $IntervalTable->get_row_by_key($id,"ID");
	           		if (defined($Row) && defined($Row->{"START"}->[0]) && defined($Row->{"END"}->[0])) {
	                	my $GeneList = $self->figmodel()->genes_of_interval($Row->{"START"}->[0],$Row->{"END"}->[0],$Row->{GENOME}->[0]);
	                	for(my $i=0; $i < @{$GeneList}; $i++) {
	                		$GeneList->[$i] = "fig|".$Row->{GENOME}->[0].".".$GeneList->[$i];
	                	}
	                	if (defined($GeneList)) {
	                		$result->{$id} = $GeneList;
	                  	}
	                }
	            }
			}
		} elsif ($fromType eq "strain") {
			if ($toType eq "interval") {
				my $StrainTable = $self->GetDBTable("STRAIN TABLE");
              	if (defined($StrainTable)) {
                	my $Row = $StrainTable->get_row_by_key($id,"ID");
                	if (defined($Row) && defined($Row->{"INTERVALS"})) {
                  		$result->{$id} = $Row->{"INTERVALS"};
                	}
              	}	
			} elsif ($toType eq "feature") {
				my $temp = $self->db_link("strain","interval",[$id]);
				if (defined($temp->{$id})) {
					my $newArray;
					for (my $i=0; $i < @{$temp->{$id}}; $i++) {
						my $temptwo = $self->db_link("interval","feature",[$temp->{$id}->[$i]]);
						if (defined($temptwo->{$temp->{$id}->[$i]})) {
							push(@{$newArray},@{$temptwo->{$temp->{$id}->[$i]}});
						}
					}
				}
			}
		} else {
			my $tbl = $self->GetLinkTable(uc($toType),uc($fromType));
			if (!defined($tbl)) {
				$tbl = $self->GetLinkTable(uc($fromType),uc($toType));
			}
			if (defined($tbl)) {
				my @rows = $tbl->get_rows_by_key($id,uc($fromType));
				for (my $i=0; $i < @rows; $i++) {
					push(@{$result->{$id}},$rows[$i]->{uc($toType)}->[0]);
				}
			}
		}
	}
	return $result;
}

=head3 set_cache
Definition:
	FIGMODELdatabase->set_cache(string::key,ref::data);
Description:
	Caching data
=cut
sub set_cache {
	my ($self,$key,$data) = @_;

	$self->{CACHE}->{$key} = $data;
}

=head3 get_cache
Definition:
	ref::data = FIGMODELdatabase->get_cache(string::key);
Description:
	Caching data
=cut

sub get_cache {
	my ($self,$key) = @_;

	return $self->{CACHE}->{$key};
}

=head3 load_multiple_column_file
Definition:
	[[string]] = FIGMODELdatabase->load_multiple_column_file(string::filename,string::delimiter);
Description:
	Parses the two dimensional file specified by the input filename
=cut
sub load_multiple_column_file {
	my ($self,$Filename,$Delimiter) = @_;

	my $DataArrayRefArrayRef = [];
	if (open (INPUT, "<$Filename")) {
		while (my $Line = <INPUT>) {
			chomp($Line);
			my $Data = [];
			$Data->[0] = $Line;
			if (length($Delimiter) > 0) {
				@{$Data} = split(/$Delimiter/,$Line);
			}
			push(@{$DataArrayRefArrayRef},$Data);
		}
		close(INPUT);
	} else {
		$self->figmodel()->error_message("FIGMODELdatabase->load_multiple_column_file(".$Filename.",".$Delimiter."): could not load file!");
	}
	return $DataArrayRefArrayRef;
}

=head3 load_single_column_file
Definition:
	[string] = FIGMODELdatabase->load_single_column_file(string::filename,string::delimiter);
Description:
	Parses the single column file specified by the input filename
=cut
sub load_single_column_file {
	my ($self,$Filename,$Delimiter) = @_;
	if (!defined($Delimiter)) {
		$Delimiter = "";	
	}
	my $DataArrayRef = [];
	if (open (INPUT, "<$Filename")) {
		while (my $Line = <INPUT>) {
			chomp($Line);

			if (length($Delimiter) > 0) {
				my @Data = split(/$Delimiter/,$Line);
				$Line = $Data[0];
			}

			push(@{$DataArrayRef},$Line);
		}
		close(INPUT);
	} else {
		$self->figmodel()->error_message("FIGMODELdatabase->load_single_column_file(".$Filename.",".$Delimiter."): could not load file!");
	}
	return $DataArrayRef;
}

=head3 load_table
Definition:
	FIGMODELTable = FIGMODELdatabase->load_table(string::filename,string::delimiter,string::item delimiter,int::heading line,[string]::hash columns);
Description:
	Uses the input arguments to load the specified table.
=cut
sub load_table {
	my ($self,$Filename,$Delimiter,$ItemDelimiter,$HeadingLine,$HashColumns) = @_;
	if (!-e $Filename) {
		return undef;	
	}
	return FIGMODELTable::load_table($Filename,$Delimiter,$ItemDelimiter,$HeadingLine,$HashColumns);
}

=head3 create_table
Definition:
	FIGMODELTable = FIGMODELdatabase->create_table(string::table name);
Description:
	Creating table based on name
=cut
sub create_table {
	my ($self,$TableName) = @_;
	my $NewTable;
	if ($TableName eq "BIOMASS TABLE") {
		if (!-e $self->config("Reaction database directory")->[0]."masterfiles/BiomassReactionTable.txt") {
			$NewTable = FIGMODELTable->new(["DATABASE","REACTANTS","EQUATION","ORGANISMS","ESSENTIAL REACTIONS"],$self->config("Reaction database directory")->[0]."masterfiles/BiomassReactionTable.txt",["DATABASE","REACTANTS","ORGANISMS"],";","|",undef);
		}
	}
	if (defined($NewTable)) {
		$NewTable->save();
	}
	return $NewTable;
}

=head3 add_model_to_db
Definition:
	{string => [string]}::row for new model in model table = FIGMODELdatabase->add_model_to_db(string::id,{string=>[string]}::metadata);
Description:
	This function adds the input model data to the model database file if the model name is unique
	The second argument provides various metadata for the model including:
		owner (name of the owner of the model: default is master)
		users (list of users and user groups who have rights to model: default is all)
		rights (list of rights corresponding with each user in the user list: default is view)
		genome (ID of the genome the model is capturing: default is UNKNOWN)
		source (can be RAST, SEED, or a pubmed ID indicating where the model came from: default is SEED)
		comments (can be any comment provided for the model: default is undefined)
		date (date model was published/generate: default is: default is date if upload)
		overwrite (indicates if an existing model with the same name should be overwritten: default is 0)
	Returns FIGMODEL->success for
=cut

sub add_model_to_db {
	my ($self,$id,$metadata,$ConserveModelName) = @_;

	#Making sure an ID has been provided
	if (!defined($id)) {
		$self->figmodel()->error_message("FIGMODELdatabase:add_model_to_db:No model ID provided.");
		return undef;
	}
	
	#Setting the user if it's not already defined
	if (!defined($metadata->{"owner"}->[0])) {
		$metadata->{"owner"}->[0] = "master";
	}

	#Adding the user's ID to the model ID if the user is not "master"
	if ($metadata->{"owner"}->[0] ne "master") {
		my $userDB = $self->get_object_manager("user");
		my $userList = $userDB->get_objects( {'login' => $metadata->{"owner"}->[0]} );
		if (defined($userList) && defined($userList->[0])) {
			$id = $id.".".$userList->[0]->_id();
		} else {
			$self->figmodel()->error_message("FIGMODEL:add_model_to_db:User ".$metadata->{"owner"}->[0]." not found in database. Check username.");
			return undef;
		}
	}
	
	#Getting the object manager for the models
	my $modelDB;
	if (defined($metadata->{source}->[0]) && $metadata->{source}->[0] eq "MGRAST") {
		$modelDB = $self->get_object_manager("mgmodel");
	} else {
		$modelDB = $self->get_object_manager("model");
	}
	
	#Checking if the model already exists
	my $model;
	my $modelList = $modelDB->get_objects( {'id' => $id} );
	if (defined($modelList) && defined($modelList->[0])) {
		$model = $modelList->[0];
	}
	#If the model exists, we update the model with the input metadata
	if (defined($model)) {
		if (!defined($metadata) || !defined($metadata->{"overwrite"}->[0]) || $metadata->{"overwrite"}->[0] == 0) {
			$self->figmodel()->error_message("FIGMODEL:add_model_to_db:".$id." already exists and overwrite request was not provided.");
			return undef;
		} else {
			#Copying over metadata
			my @Keys = keys(%{$metadata});
			foreach my $key (@Keys) {
				if ($key ne "id" && defined($modelList->[0]->$key)) {
					$modelList->[0]->$key($metadata->{$key});
				}
			}
			return $self->figmodel()->get_model();
		}
	}

	#Setting the defaults in the provided metadata
	if (!defined($metadata->{"users"}->[0])) {
		$metadata->{"users"}->[0] = $metadata->{"owner"}->[0];
	}
	if (!defined($metadata->{"rights"}->[0])) {
		$metadata->{"rights"}->[0] = "view";
	}
	if (!defined($metadata->{"genome"}->[0])) {
		$metadata->{"genome"}->[0] = "unknown";
	}
	if (!defined($metadata->{"source"}->[0])) {
		$metadata->{"source"}->[0] = "unknown";
	}
	if (!defined($metadata->{"message"}->[0])) {
		$metadata->{"message"}->[0] = "None";
	}
	if (!defined($metadata->{"class"}->[0])) {
		$metadata->{"class"}->[0] = "unknown";
	}
	if (!defined($metadata->{"version"}->[0])) {
		$metadata->{"version"}->[0] = 0;
	}
	if (!defined($metadata->{"status"}->[0])) {
		$metadata->{"status"}->[0] = -2;
	}
	if (!defined($metadata->{"builtDate"}->[0])) {
		$metadata->{"builtDate"}->[0] = 0;
	}
	if (!defined($metadata->{"autoCompleteMedia"}->[0])) {
		$metadata->{"autoCompleteMedia"}->[0] = "Complete";
		my $tbl = $self->get_table("MINIMALMEDIA");
		if (defined($tbl) && defined($tbl->get_row_by_key($metadata->{"genome"}->[0],"Organism"))) {
			$metadata->{"autoCompleteMedia"}->[0] = $tbl->get_row_by_key($metadata->{"genome"}->[0],"Organism")->{"Minimal media"}->[0];
		}
	}
	if (!defined($metadata->{"biomassReaction"}->[0])) {
		$metadata->{"biomassReaction"}->[0] = "NONE";
	}
	
	#Adding the model to the database
	$model = $modelDB->create({'id' => $id,
					 'owner' => $metadata->{"owner"}->[0],
					 'users' => "|".$metadata->{"users"}->[0]."|",
					 'rights' => $metadata->{"rights"}->[0],
					 'genome' => $metadata->{"genome"}->[0],
					 'source' => $metadata->{"source"}->[0],
					 'modificationDate' => time(),
					 'builtDate' => $metadata->{"builtDate"}->[0],
					 'autocompleteDate' => -1,
					 'status' => $metadata->{"status"}->[0],
					 'version' => $metadata->{"version"}->[0],
					 'autocompleteVersion' => 0,
					 'message' => $metadata->{"message"}->[0],
					 'cellwalltype' => $metadata->{"class"}->[0],
					 'autoCompleteMedia' => $metadata->{"autoCompleteMedia"}->[0],
					 'biomassReaction' => $metadata->{"biomassReaction"}->[0],
					 'growth' => 0,
					 'noGrowthCompounds' => "NONE"});
	
	if (defined($model)) {
		return $self->figmodel()->get_model($model->id());
	}
	return undef;
}

=head3 genericLock
Definition:
	FIGMODELdatabase->genericLock(string::lock name);
Description:
	This function locks the database for a given lock name.
=cut
sub genericLock {
	my($self,$name) = @_;
	#Making the directory if it does not already exist
	my $ltdirs = $self->config("locked table list filename");
	my $ltdir = $ltdirs->[0];
	if (!-d $ltdir) {
	    system("mkdir ".$ltdir);
	}
	#Creating the lock file
	my $lock = $ltdir.$name.".lock";
	while(-e $lock) {
		sleep(2);
	}
	$self->print_array_to_file($lock,["LOCKED"]);
	return $self->figmodel()->success();
}

=head3 genericUnlock
Definition:
	FIGMODELdatabase->genericUnlock(string::lock name);
Description:
	This function unlocks the database for a given lock name.
=cut
sub genericUnlock {
	my($self,$name) = @_;
	#Deleting the lock file
	my $ltdirs = $self->config("locked table list filename");
	my $ltdir = $ltdirs->[0];
	my $lock = $ltdir.$name.".lock";
	unlink($lock);
	return $self->figmodel()->success();
}

=head3 LockDBTable
Definition:
	FIGMODELTable = FIGMODELdatabase->LockDBTable(string::table name);
Description:
	This function checks out a table from the database for editing. This table can then no longer be checked out for editing by any other programing running.
=cut
sub LockDBTable {
	my($self,$TableName) = @_;
	#Locking to the tablename
	$self->genericLock($TableName);
	#Clearing the cached table data
	$self->figmodel()->database()->ClearDBTable($TableName);
	#Loading and returning the tale data from file
	my $currentUser = $self->figmodel()->user();
	$self->figmodel()->authenticate_user("master","MasterPassword");
	my $tbl = $self->GetDBTable($TableName);
	$self->figmodel()->authenticate_user($currentUser,"UserPassword");
	return $tbl;
}

=head3 UnlockDBTable
Definition:
	status(1/0) = FIGMODELdatabase->UnlockDBTable(string::table name);
Description:
	This function checks a table into the database freeing the table for editing by other programs.
=cut
sub UnlockDBTable {
	my($self,$TableName) = @_;
	#Unlocking the file
	$self->genericUnlock($TableName);
	return $self->figmodel()->success();
}

=head3 ManageFileLocking
Definition:
	FIGMODELdatabase->ManageFileLocking($FileHandle,$Operation,$UseFcntl);
Description:
	This function handles all file locking for the FIGMODELdatabase package. Possible values for $Operation are:
	LOCK_EX: exclusive lock for writing
	LOCK_SH: shared lock for simultaneous reading
	LOCK_UN: removes the lock
Example:
=cut

sub ManageFileLocking {
    my($self,$FileHandle,$Operation,$UseFcntl) = @_;

	#Qualifying the filehandle
    $FileHandle = FIGMODEL::qualify_to_ref($FileHandle, caller());

	#Implementing the lock using flock
    if (!defined($UseFcntl) || $UseFcntl == 0) {
		if ($Operation == LOCK_EX) {
			my $arg = pack("ssll", F_WRLCK, SEEK_SET, 0, 0);
			my $rc = fcntl($FileHandle, F_SETLKW, $arg);
			return $rc;
		} elsif ($Operation == LOCK_SH) {
			my $arg = pack("ssll", F_RDLCK, SEEK_SET, 0, 0);
			my $rc = fcntl($FileHandle, F_SETLKW, $arg);
			return $rc;
		} elsif ($Operation == LOCK_UN) {
			my $arg = pack("ssll", F_UNLCK, SEEK_SET, 0, 0);
			my $rc = fcntl($FileHandle, F_SETLKW, $arg);
			return $rc;
		}
	} else {
		return CORE::flock($FileHandle, $Operation);
	}
}

=head3 update_row
Definition:
	status(1/0) = FIGMODELdatabase->update_row(string::table,{string=>[string]}::row,string::unique key);
Description:
	Updates the input row in the specified table
=cut
sub update_row {
	my ($self,$tablename,$row,$key) = @_;

	#Checking that a table and query have been provided
	if (!defined($tablename) || !defined($row) || !defined($key) || !defined($row->{$key}->[0])) {
		$self->figmodel()->error_message("FIGMODELdatabase:update_row:Must provide table, key, and value.");
		return $self->figmodel()->fail();
	}

	#Getting the database table:may be pulled from a flat file or from SQL
	my $table = $self->LockDBTable($tablename);
	if (!defined($table)) {
		$self->figmodel()->error_message("FIGMODEL:update_row:".$tablename." not found in database.");
		return $self->figmodel()->fail();
	}

	#Querying to see if the row is already in the table
	$row->{"last_modified"}->[0] = time();
	my $ExistingRow = $table->get_row_by_key($row->{$key}->[0],$key);
	if (defined($ExistingRow)) {
		$table->replace_row($ExistingRow,$row);
	} else {
		$table->add_row($row);
	}

	#Saving updated table to database
	$table->save();
	$self->UnlockDBTable($tablename);

	return $self->figmodel()->success();
}

=head3 get_row_by_key
Definition:
	{string=>[string]}::table row = FIGMODELdatabase->get_row_by_key(string::table,string::value,string::key);
Description:
=cut
sub get_row_by_key {
	my ($self,$tablename,$value,$key) = @_;

	#Checking that a table and query have been provided
	if (!defined($tablename) || !defined($value) || !defined($key)) {
		$self->figmodel()->error_message("FIGMODELdatabase:get_row_by_key:Must provide table, key, and value.");
		return undef;
	}

	#Getting the database table:may be pulled from a flat file or from SQL
	my $table = $self->GetDBTable($tablename);
	if (!defined($table)) {
		$self->figmodel()->error_message("FIGMODELdatabase:get_row_by_key:".$tablename." not found in database.");
		return undef;
	}

	#Getting first table row matching the query
	return $table->get_row_by_key($value,$key);
}

=head3 get_object_from_db
Definition:
	{string=>[string]}::table row = FIGMODELdatabase->get_object_from_db(string:type,{string:key=>value});
Description:
=cut
sub get_object_from_db {
	my ($self,$type,$searchhash) = @_;

	#Checking that a table and query have been provided
	if (!defined($type) || !defined($searchhash)) {
		$self->figmodel()->error_message("FIGMODELdatabase:get_object_from_db:Must provide type and search terms.");
		return undef;
	}
	
	#Getting the database table:may be pulled from a flat file or from SQL
	my $table = $self->GetDBTable($type);
	if (!defined($table)) {
		return undef;
	}
	my @searchkeys = keys(%{$searchhash}); 
	for (my $i=0; $i < @searchkeys; $i++) {
		$table = $table->get_table_by_key($searchhash->{$searchkeys[$i]},$searchkeys[$i]);
	}
	return $table->get_row(0);
}

=head3 add_object_to_db
Definition:
	{string:key=>value}:object = FIGMODELdatabase->add_object_to_db({string:key=>value}:object);
Description:
=cut
sub add_object_to_db {
	my ($self,$object,$update) = @_;

	#Checking that a table and query have been provided
	if (!defined($object)) {
		$self->figmodel()->error_message("FIGMODELdatabase:add_object_to_db:Object must be provided.");
		return undef;
	}
	
	#Locking the table or making sure it's already locked
	my $newlock = 0;
	if (!defined($self->{"LOCKS"}->{$object->{_type}})) {
		$newlock = 1;
		$self->LockDBTable($object->{_type});
	}
	my $tbl = $self->GetDBTable($object->{_type});
	
	#Checking if another object with the same primary key already exists
	my $existing_object = $self->get_object_from_db($object->{_type},{$object->{_key}=>$object->{$object->{_key}}->[0]});
	if (defined($existing_object)) {
		if (defined($update) && $update == 1) {
			my @objkeys = keys(%{$object});
			for (my $i=0; $i < @objkeys; $i++) {
				if ($objkeys[$i] !~ m/^_/) {
					$existing_object->{$objkeys[$i]} = $object->{$objkeys[$i]};
				} 
			}
		}
		return $existing_object;
	}
	
	#Adding the object
	$tbl->add_row($object);
	
	#If the lock is new, unlocking the table
	if ($newlock == 1) {
		$tbl->save();
		$self->UnlockDBTable($object->{_type});
	}
	return $object;
}

=head3 add_columns_to_db
Definition:
	FIGMODELdatabase->add_columns_to_db({string:new column name=>value:default value});
Description:
=cut
sub add_columns_to_db {
	my ($self,$type,$columns) = @_;
	
	if (!defined($type) || !defined($columns)) {
		$self->figmodel()->error_message("FIGMODELdatabase:add_columns_to_db:Columnn and object type must be provided.");
		return $self->fail();
	}
	#Locking the table or making sure it's already locked
	my $newlock = 0;
	if (!defined($self->{"LOCKS"}->{$type})) {
		$newlock = 1;
		$self->LockDBTable($type);
	}
	my $tbl = $self->GetDBTable($type);
	if (!defined($tbl)) {
		$self->figmodel()->error_message("FIGMODELdatabase:add_columns_to_db:could not load object table of type:".$type);
		return $self->fail();
	}
	my @columnNames = keys(%{$columns});
	$tbl->add_headings(@columnNames);
	for (my $j=0; $j < $tbl->size(); $j++) {
		for (my $i=0; $i < @columnNames; $i++) {
			if (!defined($tbl->get_row($j)->{$columnNames[$i]})) {
				$tbl->get_row($j)->{$columnNames[$i]}->[0] = $columns->{$columnNames[$i]};
			}
		}
	}
	
	#If the lock is new, unlocking the table
	if ($newlock == 1) {
		$tbl->save();
		$self->UnlockDBTable($type);
	}
	return $self->success();
}



=head3 save_table
Definition:
	FIGMODELdatabase->save_table(FIGMODELTable::table);
Description:
	Saves the input table to file
=cut

sub save_table {
	my ($self,$table,$filename,$delimiter,$itemdelimiter,$prefix) = @_;

	$table->save($filename,$delimiter,$itemdelimiter,$prefix);
}

=head3 GetDBTable
Definition:
	(1/0) = FIGMODELdatabase->GetDBTable([string]::authorized user list,string::user ID);
Description:
	Checks to see if the input user is authorized to view an object based on the authorized user list 
=cut
sub check_user {
	my ($self,$users,$user) = @_;
	
	for (my $i=0; $i < @{$users}; $i++) {
		if (lc($users->[$i]) eq "all" || $users->[$i] eq $user)	{
			return 1;
		}
	}
	
	return 0;
}

sub ClearDBTable {
	my ($self,$TableName,$Delete) = @_;

	if (defined($Delete) && $Delete eq "DELETE") {
		delete $self->{"CACHE"}->{$TableName};
	}
	$self->{"CACHE"}->{$TableName} = undef;
}

sub ClearDBModel {
	my ($self,$ModelName,$Delete) = @_;

	if (defined($Delete) && ($Delete eq "DELETE" || $Delete eq "1")) {
		delete $self->{"CACHE"}->{"MODEL_".$ModelName};
	}
	$self->{"CACHE"}->{"MODEL_".$ModelName} = undef;
}

=head3 create_table_prototype

Definition:
	FIGMODELTable::table = FIGMODELdatabase->create_table_prototype(string::table);
Description:
	Returns a empty FIGMODELTable with all the metadata associated with the input table name
	
=cut
sub create_table_prototype {
	my ($self,$TableName) = @_;
	
	#Checking if the table definition exists in the FIGMODELconfig file
	if (!defined($self->figmodel()->config($TableName))) {
		$self->figmodel()->error_message("FIGMODELdatabase:create_table_prototype:Definition not found for ".$TableName);
		return undef;
	}
	#Checking that this is a database table
	if (!defined($self->config($TableName)->{tabletype}) || $self->config($TableName)->{tabletype}->[0] ne "DatabaseTable") {
		$self->figmodel()->error_message("FIGMODELdatabase:create_table_prototype:".$TableName." is not a database table!");
		return undef;
	}
	if (!defined($self->config($TableName)->{delimiter})) {
		$self->config($TableName)->{delimiter}->[0] = ";";
	}
	if (!defined($self->config($TableName)->{itemdelimiter})) {
		$self->config($TableName)->{itemdelimiter}->[0] = "|";
	}
	my $prefix;
	if (defined($self->config($TableName)->{prefix})) {
		$prefix = join("\n",@{$self->config($TableName)->{prefix}});
	}
	my $tbl = FIGMODELTable->new($self->config($TableName)->{columns},$self->config("Reaction database directory")->[0].$self->config($TableName)->{filename}->[0],$self->config($TableName)->{hashcolumns},$self->config($TableName)->{delimiter}->[0],$self->config($TableName)->{itemdelimiter}->[0],$prefix);
	return $tbl;
}

=head3 get_table

Definition:
	FIGMODELTable::table = FIGMODELdatabase->get_table(string::table);
Description:
	Returns the requested FIGMODELTable
	
=cut
sub get_table {
	my ($self,$TableName,$NoCache) = @_;
	
	if ((!defined($NoCache) || $NoCache == 0) && defined($self->{_cache}->{$TableName})) {
		return $self->{_cache}->{$TableName};
	}
	#Checking if the table definition exists in the FIGMODELconfig file
	if (!defined($self->figmodel()->config($TableName))) {
		$self->figmodel()->error_message("FIGMODELdatabase:create_table_prototype:Definition not found for ".$TableName);
		return undef;
	}
	#Checking that this is a database table
	if (!defined($self->config($TableName)->{tabletype}) || $self->config($TableName)->{tabletype}->[0] ne "DatabaseTable") {
		$self->figmodel()->error_message("FIGMODELdatabase:create_table_prototype:".$TableName." is not a database table!");
		return undef;
	}
	if (!defined($self->config($TableName)->{headingline})) {
		$self->config($TableName)->{headingline}->[0] = 0;
	}
	if (!defined($self->config($TableName)->{columndelimiter})) {
		$self->config($TableName)->{columndelimiter}->[0] = "\t";
	} elsif ($self->config($TableName)->{columndelimiter}->[0] eq "SC") {
		$self->config($TableName)->{columndelimiter}->[0] = ";";
	}
	$self->config($TableName)->{delimiter}->[0] = $self->config($TableName)->{columndelimiter}->[0];
	if (!defined($self->config($TableName)->{itemdelimiter})) {
		$self->config($TableName)->{itemdelimiter}->[0] = "|";
	}
	#Loading the table
	$self->{_cache}->{$TableName} = FIGMODELTable::load_table($self->config("Reaction database directory")->[0].$self->config($TableName)->{filename}->[0],$self->config($TableName)->{delimiter}->[0],$self->config($TableName)->{itemdelimiter}->[0],$self->config($TableName)->{headingline}->[0],$self->config($TableName)->{hashcolumns}); 
	return $self->{_cache}->{$TableName};
}

=head3 GetDBTable
Definition:
	FIGMODELTable::table = FIGMODELdatabase->GetDBTable(string::table,int::cache entire table);
Description:
	Returns a FIGMODELTable object containing the data for the specified table.
	The second argument is optional, but if this argument is equal to "1" and the specified table is in SQL, the table will not be loaded entirely from SQL.
=cut
sub GetDBTable {
	my ($self,$TableName) = @_;

	#Checking if the table is already loaded
	if (defined($self->{"CACHE"}->{$TableName})) {
		return $self->{"CACHE"}->{$TableName};
	}

	#Loading the table list if it is not already loaded
	if ($TableName ne "TABLE LIST" && !defined($self->{"CACHE"}->{"TABLE LIST"})) {
		my $Table = $self->GetDBTable("TABLE LIST");
	}

	#Declaring all variables used in this function
	my ($Filename,$Delimiter,$ItemDelimiter,$HeadingLine,$HashColumns);
	#Check that table list has been loaded
	if ($TableName eq "TABLE LIST") {
	        my $names = $self->config("table list filename");
		$Filename = $names->[0];
		$Delimiter = "\t";
		$ItemDelimiter = "`";
		$HeadingLine = 0;
		$HashColumns->[0] = "NAME";
	} elsif (!defined($self->{"CACHE"}->{"TABLE LIST"}->{$TableName})) {
		return undef;
	} else {
		$Filename = $self->{"CACHE"}->{"TABLE LIST"}->{$TableName}->[0]->{"FILENAME"}->[0];
		#Translating variable filenames
		$_ = $Filename;
		my @MatchArray = /\{([^\}]+)\}/g;
		foreach my $Tag (@MatchArray) {
			if (defined($self->GetProtectVariable($Tag))) {
				my $Replace = $self->GetProtectVariable($Tag);
				$Tag = "\{".$Tag."\}";
				$Filename =~ s/$Tag/$Replace/;
			} elsif (defined($self->config($Tag))) {
			        my $names = $self->config($Tag);
				my $Replace = $names->[0];
				$Tag = "\{".$Tag."\}";
				$Filename =~ s/$Tag/$Replace/;
			}
		}
		$Delimiter = $self->{"CACHE"}->{"TABLE LIST"}->{$TableName}->[0]->{"DELIMITER"}->[0];
		$ItemDelimiter = "";
		if (defined($self->{"CACHE"}->{"TABLE LIST"}->{$TableName}->[0]->{"ITEM DELIMITER"})) {
			$ItemDelimiter = $self->{"CACHE"}->{"TABLE LIST"}->{$TableName}->[0]->{"ITEM DELIMITER"}->[0];
		}
		$HeadingLine = 0;
		if (defined($self->{"CACHE"}->{"TABLE LIST"}->{$TableName}->[0]->{"HEADING LINE"})) {
			$HeadingLine = $self->{"CACHE"}->{"TABLE LIST"}->{$TableName}->[0]->{"HEADING LINE"}->[0];
		}
		$HashColumns = $self->{"CACHE"}->{"TABLE LIST"}->{$TableName}->[0]->{"HASH COLUMNS"};
	}

	$self->{"CACHE"}->{$TableName} = FIGMODELTable::load_table($Filename,$Delimiter,$ItemDelimiter,$HeadingLine,$HashColumns);
	if (!defined($self->{"CACHE"}->{$TableName})) {
		$self->{"CACHE"}->{$TableName} = $self->create_table($TableName);
	}

	#Removing private reactions
	if (lc($self->figmodel()->user()) ne "master") {
		if ($TableName eq "MODELS") {
			my $tbl = $self->{"CACHE"}->{$TableName};
			for (my $i=0; $i < $tbl->size(); $i++) {
				if ($self->check_user($tbl->get_row($i)->{users},$self->figmodel()->user()) == 0) {
					my $id = $tbl->get_row($i)->{id}->[0];
					$tbl->delete_row($i);
					$i--;
				}
			}
		} elsif ($TableName eq "REACTIONS" || $TableName eq "COMPOUNDS") {
			my $tbl = $self->{"CACHE"}->{$TableName};
			my $type = "REACTION";
			if ($TableName eq "COMPOUNDS") {
				$type = "COMPOUND";
			}
			my $linktbl = $self->GetLinkTable($type,"SOURCE");
			my $ModelTable = $self->GetDBTable("MODELS");
			for (my $i=0; $i < $tbl->size(); $i++) {
				my $id = $tbl->get_row($i)->{"DATABASE"}->[0];
				my $row = $linktbl->get_row_by_key($id,$type);
				if (defined($row)) {
					my $authorized = 0;
					for (my $j=0; $j < @{$row->{"SOURCE"}};$j++) {
						if ($row->{"SOURCE"}->[$j] eq "KEGG"  || defined($ModelTable->get_row_by_key($row->{"SOURCE"}->[$j],"id"))) {
							$authorized = 1;
							last;
						}
					}
					if ($authorized == 0) {
						$tbl->delete_row($i);
						$i--;
					}
				}
			}
		}
	}

	return $self->{"CACHE"}->{$TableName};
}

=head3 GetProtectVariable
Definition:
	string::variable value = FIGMODELdatabase->GetProtectVariable(string::variable name,0/1::delete variable);
Description:
	getting the value of the specified protected variable
=cut
sub GetProtectVariable {
	my ($self,$VariableName,$DeleteVariable) = @_;
	if (defined($self->{"PROTECTED VARIABLES"}->{$VariableName}->[0])) {
		my $Variable = $self->{"PROTECTED VARIABLES"}->{$VariableName}->[0];
		if (defined($DeleteVariable) && $DeleteVariable == 1) {
			delete $self->{"PROTECTED VARIABLES"}->{$VariableName};
		}
		return $Variable;
	}
	return undef;
}

=head3 SetProtectedVariable
Definition:
	FIGMODELdatabase->SetProtectedVariable(string::variable name,string::variable value);
Description:
	setting the value of the specified protected variable
=cut
sub SetProtectedVariable {
	my ($self,$VariableName,$VariableValue) = @_;
	$self->{"PROTECTED VARIABLES"}->{$VariableName}->[0] = $VariableValue;
}

=head3 GetDBModel
Definition:
	FIGMODELTable = FIGMODELdatabase->GetDBModel(string::model id);
Description:
	setting the value of the specified protected variable
=cut
sub GetDBModel {
	my ($self,$ModelName) = @_;

	if (defined($self->{"CACHE"}->{"MODEL_".$ModelName})) {
		return $self->{"CACHE"}->{"MODEL_".$ModelName};
	}

	my $model = $self->figmodel()->get_model($ModelName);
	if (!defined($model)) {
		$self->figmodel()->error_message("FIGMODELdatabase:GetDBModel: Could not find model ".$ModelName);
		return undef;
	}
	$self->SetProtectedVariable("MODEL DIRECTORY",$model->filename());
	my $ModelTable = $self->GetDBTable("MODEL BUFFER TABLE");
	if (defined($ModelTable)) {
		$self->{"CACHE"}->{"MODEL_".$ModelName} = $ModelTable;
	}
	$self->{"CACHE"}->{"MODEL BUFFER TABLE"} = undef;
	$self->GetProtectVariable("MODEL DIRECTORY",1);

	return $ModelTable;
}

=head3 GetDBModelGenes
Definition:
	FIGMODELTable = FIGMODELdatabase->GetDBModelGenes(string::model id);
Description:
	returns a FIGMODELTable with the model genes
=cut
sub GetDBModelGenes {
	my ($self,$modelID) = @_;

	#Getting model data
	my $model = $self->figmodel()->get_model($modelID);
	if (!defined($model)) {
		print STDERR "FIGMODELdatabase:GetDBModelGenes:Could not find model ".$modelID." in database!";
		return undef;
	}
	return $model->feature_table();
}

=head3 save_cpd_translation
Definition:
	FIGMODELdatabase->save_cpd_translation({string::model ID => string::cpd id},string::model id);
Description:
	saving the compound translation file for a model
=cut
sub save_cpd_translation {
	my ($self,$tanslation,$model) = @_;

	my $filename = $self->figmodel()->config("Translation directory")->[0]."CpdTo".$model.".txt";
	my $filedata;
	my @cpds = keys(%{$tanslation});
	for (my $i=0; $i < @cpds; $i++) {
		push(@{$filedata},$tanslation->{$cpds[$i]}."\t".$cpds[$i]);
	}
	$self->print_array_to_file($filename,$filedata);
}

=head3 save_rxn_translation
Definition:
	FIGMODELdatabase->save_rxn_translation({string::model ID => string::cpd id},string::model id);
Description:
	saving the reaction translation file for a model
=cut
sub save_rxn_translation {
	my ($self,$tanslation,$model) = @_;

	my $filename = $self->figmodel()->config("Translation directory")->[0]."RxnTo".$model.".txt";
	my $filedata;
	my @rxns = keys(%{$tanslation});
	for (my $i=0; $i < @rxns; $i++) {
		push(@{$filedata},$tanslation->{$rxns[$i]}."\t".$rxns[$i]);
	}
	$self->print_array_to_file($filename,$filedata);
}

=head3 print_array_to_file
Definition:
	FIGMODELdatabase->print_array_to_file(string::filename,[string::file lines],0/1::append);
Description:
	saving array to file
=cut
sub print_array_to_file {
	my ($self,$filename,$arrayRef,$Append) = @_;

	if (defined($Append) && $Append == 1) {
		open (OUTPUT, ">>$filename");
	} else {
		open (OUTPUT, ">$filename");
	}
	foreach my $Item (@{$arrayRef}) {
		if (length($Item) > 0) {
			print OUTPUT $Item."\n";
		}
	}
	close(OUTPUT);
}

=head3 print_multicolumn_array_to_file
Definition:
	FIGMODELdatabase->print_multicolumn_array_to_file(string::filename,[string::file lines],string::delimiter);
Description:
	saving array to file
=cut
sub print_multicolumn_array_to_file {
	my ($self,$Filename,$ArrayRef,$Delimiter) = @_;

	if (open (OUTPUT, ">$Filename")) {
		foreach my $Item (@{$ArrayRef}) {
			if (@{$Item} > 0) {
				print OUTPUT join($Delimiter,@{$Item})."\n";
			}
		}
		close(OUTPUT);
	} else {
		die "Cannot open $Filename: $!";
	}
}

=head3 build_link_file
Definition:
	(0/1)::status = FIGMODELdatabase->build_link_file(string::entity one,string::entity two);
Description:
	This function prints a flatfile that makes it possible to rapidly translate one entity into another.
	The first entity is always the reference entity in the table, with one row in the table for each unique ID.
	Currently generates linking files for the following entity pairs:
	reaction->subsystem
=cut

sub build_link_file {
	my($self,$EntityOne,$EntityTwo) = @_;

	my $Table = FIGMODELTable->new([$EntityOne,$EntityTwo,"DATA"],$self->config("Reaction database directory")->[0]."linkfiles/".$EntityOne."-".$EntityTwo.".tbl",[$EntityOne,$EntityTwo],"\t","|",undef);
	if ($EntityOne eq "REACTION") {
		if ($EntityTwo eq "SUBSYSTEM") {
			my $ReactionTable = $self->GetDBTable("REACTIONS");
			for (my $i=0; $i < $ReactionTable->size(); $i++) {
				my $Row = $ReactionTable->get_row($i);
				my $Subsystems = $self->figmodel()->subsystems_of_reaction($Row->{"DATABASE"}->[0]);
				if (defined($Subsystems)) {
					$Table->add_row({"REACTION" => [$Row->{"DATABASE"}->[0]],"SUBSYSTEM" => $Subsystems});
				}
			}
			$Table->save();
			return $self->success();
		} elsif ($EntityTwo eq "COMPOUND") {
			my $ReactionTable = $self->GetDBTable("REACTIONS");
			for (my $i=0; $i < $ReactionTable->size(); $i++) {
				my $Row = $ReactionTable->get_row($i);
				my ($Reactants,$Products) = $self->figmodel()->GetReactionSubstrateDataFromEquation($Row->{EQUATION}->[0]);
				for (my $i=0; $i < @{$Reactants}; $i++) {
					$Table->add_row({"REACTION" => [$Row->{"DATABASE"}->[0]],"COMPOUND" => $Reactants->{DATABASE}->[0]});
				}
				for (my $i=0; $i < @{$Products}; $i++) {
					$Table->add_row({"REACTION" => [$Row->{"DATABASE"}->[0]],"COMPOUND" => $Products->{DATABASE}->[0]});
				}
			}
			$Table->save();
			return $self->success();
		} elsif ($EntityTwo eq "MODEL") {
			for (my $i=0; $i < $self->figmodel()->number_of_models(); $i++) {
				my $model = $self->figmodel()->get_model($i);
				my $rxnTbl = $model->reaction_table();
				for (my $j=0; $j < $rxnTbl->size(); $j++) {
					my $row = $rxnTbl->get_row($j);
					my $newRow = $Table->get_row_by_key($row->{LOAD}->[0],"REACTION");
					if (!defined($newRow)) {
						$Table->add_row({"REACTION"=>[$row->{LOAD}->[0]],"MODEL"=>[$model->id()]});
					} else {
						$Table->add_data($newRow,"MODEL",$model->id(),1);
					}
				}
			}
			$Table->save();
			return $self->success();
		} elsif ($EntityTwo eq "SOURCE") {
			#Getting the complete list of translation files
			my @TranslationFiles = glob($self->config("Translation directory")->[0]."RxnTo*");
			for (my $i=0; $i < @TranslationFiles; $i++) {
				if ($TranslationFiles[$i] =~ m/RxnTo(.+)\.txt/) {
					my $ModelName = $1;
					if ($ModelName ne "All") {
						my $transdata = $self->load_multiple_column_file($TranslationFiles[$i],"\t");
						for (my $j=0; $j < @{$transdata}; $j++) {
							my $row = $Table->get_row_by_key($transdata->[$j]->[0],"REACTION",1);
							$Table->add_data($row,"SOURCE",$ModelName,1);
						}
					}
				}
			}
			$Table->save();
			return $self->success();
		}
	} elsif ($EntityOne eq "MODEL") {
		if ($EntityTwo eq "BOF") {
			my $modelManager = $self->get_object_manager("model");
			my $models = $modelManager->get_objects();
			for (my $i=0; $i < @{$models}; $i++) {
				my $mdl = $self->figmodel()->get_model($models->[$i]->id());
				if (defined($mdl)) {
					my $biorxn = $mdl->get_biomass();
					if (defined($biorxn)) {
						$Table->add_row({MODEL => [$mdl->id()],BOF => [$biorxn->{LOAD}->[0]]});
					}
				}
			}
			$Table->save();
			return $self->success();
		}
	} elsif ($EntityOne eq "COMPOUND") {
		if ($EntityTwo eq "BOF") {
			my $tbl = $self->figmodel()->database()->get_table("BIOMASS");
			for (my $i=0; $i < $tbl->size(); $i++) {
				my $row = $tbl->get_row($i);
				my @array = split(/\s/,$row->{EQUATION}->[0]);
				my $sign = -1;
				for (my $j=0; $j < @array;$j++) {
					if ($array[$j] =~ m/cpd\d\d\d\d\d/) {
						my $coef = $sign;
						if ($j > 0 && $array[$j-1] =~ m/\((.+)\)/) {
							$coef = $sign*$1;
						}
						$Table->add_row({COMPOUND => [$array[$j]],BOF => [$row->{DATABASE}->[0]], DATA => [$coef]});
					} elsif ($array[$j] =~ m/=/) {
						$sign = 1;
					}
				}
			}
			$Table->save();
			return $self->success();
		} elsif ($EntityTwo eq "SOURCE") {
			#Getting the complete list of translation files
			my @TranslationFiles = glob($self->config("Translation directory")->[0]."CpdTo*");
			for (my $i=0; $i < @TranslationFiles; $i++) {
				if ($TranslationFiles[$i] =~ m/CpdTo(.+)\.txt/) {
					my $ModelName = $1;
					if ($ModelName ne "All") {
						my $transdata = $self->load_multiple_column_file($TranslationFiles[$i],"\t");
						for (my $j=0; $j < @{$transdata}; $j++) {
							my $row = $Table->get_row_by_key($transdata->[$j]->[0],"COMPOUND",1);
							$Table->add_data($row,"SOURCE",$ModelName,1);
						}
					}
				}
			}
			$Table->save();
			return $self->success();
		}
	} elsif ($EntityOne eq "SUBSYSTEM") {
		if ($EntityTwo eq "CLASS") {
			if (!defined($self->fig())) {
				return $self->fail();
			}
			my @SubsystemList = $self->fig()->all_subsystems();
			for (my $i=0; $i < @SubsystemList; $i++) {
				my $class = $self->fig()->subsystem_classification($SubsystemList[$i]);
				if (defined($class)) {
					my $row = $Table->get_row_by_key($SubsystemList[$i],"SUBSYSTEM",1);
					push(@{$row->{CLASS}},@{$class});
				}
			}
			$Table->save();
			return $self->success();
		}
	}
	return $self->fail();
}

=head3 get_link_table
Definition:
	FIGMODELTable::Entity link table = FIGMODELdatabase->get_link_table([string]:entity list);
Description:
	This function returns a FIGMODELTable with two columns corresponding to the two input entity types.
	This table can be used to translate from one entity type into another.
=cut
sub get_link_table {
	my($self,$entityList) = @_;

	my $id = join("_",@{$entityList});
	if (!defined($self->{_links}->{$id})) {
		my $tbl;
		if (!-e $self->figmodel()->directory()."ReactionDB/linkfiles/".$id.".tbl") {
			$tbl = $self->$id($entityList);
		} else {
			$self->{_links}->{$id} = $self->load_table($self->figmodel()->directory()."ReactionDB/linkfiles/".$id.".tbl","\t","|",0,$entityList);
		}
	}
	
	return $self->{_links}->{$id};
}

=head3 update_link_table
Definition:
	FIGMODELTable::Entity link table = FIGMODELdatabase->update_link_table([string]:entity list);
Description:
	
=cut
sub update_link_table {
	my($self,$entityList) = @_;

	my $id = join("_",@{$entityList});
	$self->{_links}->{$id} = $self->$id($entityList);
}

=head3 link_generation_functions
Description:
	The following are custom functions written for each type of link in the database
=cut
sub interval_model_media {
	my($self,$entityList) = @_;
	my $id = join("_",@{$entityList});
	my $headings;
	push(@{$headings},@{$entityList});
	push(@{$headings},("in silico","experiment","status"));
	my $tbl;
	if (!-e $self->figmodel()->directory()."ReactionDB/linkfiles/".$id.".tbl") {
		$tbl = FIGMODELTable->new($headings,$self->figmodel()->directory()."ReactionDB/linkfiles/".$id.".tbl",$entityList,"\t","|",undef);
	} else {
		$tbl = $self->load_table($self->figmodel()->directory()."ReactionDB/linkfiles/".$id.".tbl","\t","|",0,$entityList);
	}
	
	my $input = $self->GetDBTable("STRAIN SIMULATIONS");
	for (my $i=0; $i < $input->size(); $i++) {
		my $row = $input->get_row($i);
		if ($row->{ID}->[0] =~ m/^\d+$/) {
			for (my $j=0; $j < @{$row->{MEDIA}};$j++) {
				my $newrow = $tbl->get_table_by_key($row->{ID}->[0],"interval")->get_table_by_key($row->{MEDIA}->[$j],"media")->get_row_by_key($row->{MODEL}->[0],"model");
				if (!defined($newrow)) {
					$newrow = $tbl->add_row({"interval" => [$row->{ID}->[0]], "model" => [$row->{MODEL}->[0]], "media" => [$row->{MEDIA}->[$j]]});
				}
				$newrow->{"in silico"}->[0] = $row->{GROWTH}->[$j];
			}
		}
	}
	
	$input = $self->GetDBTable("INTERVAL TABLE");
	for (my $i=0; $i < $input->size(); $i++) {
		my $row = $input->get_row($i);
		for (my $j=0; $j < @{$row->{GROWTH}};$j++) {
			my @temp = split(/:/,$row->{GROWTH}->[$j]);
			if (@temp >= 2) {
				my $subtbl = $tbl->get_table_by_key($row->{ID}->[0],"interval")->get_table_by_key($temp[0],"media");
				for (my $k=0;$k < $subtbl->size(); $k++) {
					my $subrow = $subtbl->get_row($k);
					$subrow->{"experiment"}->[0] = $temp[1];
					if ($subrow->{"in silico"}->[0] > 0.000001) {
						if ($subrow->{"experiment"}->[0] > 0.000001) {
							$subrow->{"status"}->[0] = "CP";
						} else {
							$subrow->{"status"}->[0] = "FP";
						}
					} elsif ($subrow->{"experiment"}->[0] > 0.000001) {
						$subrow->{"status"}->[0] = "FN";
					} else {
						$subrow->{"status"}->[0] = "CN";
					}
				}
			}
		}
	}
	
	$self->save_table($tbl);
	return $tbl;
}

=head3 GetLinkTable
Definition:
	FIGMODELTable::Entity link table = FIGMODELdatabase->GetLinkTable(string::entity one,string::entity two);
Description:
	This function returns a FIGMODELTable with two columns corresponding to the two input entity types.
	This table can be used to translate from one entity type into another.
=cut
sub GetLinkTable {
	my($self,$EntityOne,$EntityTwo) = @_;

	#Loading the table from file if it has not already been cached
	if (!defined($self->get_cache("LINK-".$EntityOne."-".$EntityTwo))) {
		if (-e $self->config("Reaction database directory")->[0]."linkfiles/".$EntityOne."-".$EntityTwo.".tbl") {
			$self->set_cache("LINK-".$EntityOne."-".$EntityTwo,$self->load_table($self->config("Reaction database directory")->[0]."linkfiles/".$EntityOne."-".$EntityTwo.".tbl","\t","|",0,[$EntityOne,$EntityTwo]));
		}
	}

	return $self->get_cache("LINK-".$EntityOne."-".$EntityTwo);
}

=head3 mg_model_data
Definition:
	MGRAST::Metadata::meta data for model = FIGMODELdatabase->mg_model_data(string::metagenome id);
Description:
	Returns the metadata object for the specified genome id
=cut
sub mg_model_data {
	my($self,$genome_id) = @_;

	if (!defined($self->{_mg_model_data})) {
		require MGRAST::Metadata;
		my $mddb = MGRAST::Metadata->new();
		my $results = $mddb->_handle()->Search->get_objects({});
		foreach (@$results){
			$self->{_mg_model_data}->{$_->job()->genome_id} = $_;
		}
	}

	return $self->{_mg_model_data}->{$genome_id};
}

=head3 get_genome_feature_table
Definition:
	FIGMODELTable = FIGMODELdatabase->get_genome_feature_table(string::genome id,0/1::get sequences);
Description:
	This functions gets the genome data for the input genome ID from the SEED using the all_features_detailed_fast function.
	The data is then formatted into a FIGMODELTable object and returned.
=cut
sub get_genome_feature_table {
	my($self,$OrganismID,$GetSequences) = @_;

	#Returning the cached table if it exists
	if (defined($self->get_cache($OrganismID."-FEATURETABLE"))) {
		return $self->get_cache($OrganismID."-FEATURETABLE");
	}

	#Creating a new table
	my $names = $self->config("database message file directory");
	my $featuretbl = new FIGMODELTable(["ID","ALIASES","TYPE","LOCATION","MIN LOCATION","MAX LOCATION","ROLES","SEQUENCE"],$names->[0]."Features-".$OrganismID.".txt",["ID","ALIASES","TYPE","ROLES"],"\t","|",undef);

	#Getting the data for the genome from the SEED
	my $source = "SEED";
	my $owner = "master";
	my $name = "Unknown";
	my $taxonomy = "Unknown";
	my $size = "NA";
	if ($OrganismID =~ m/^444\d\d\d\d\.\d+$/) {
		$source = "MGRAST";
	} else {
		#Getting fig object for genome
		my $fig = $self->figmodel()->fig($OrganismID);
		$source = $fig->{_source};
		$owner = $fig->{_owner};
		#If a fig object exists, it is used to get the genome data
		if (defined($fig)) {
			if ($fig->{_source} =~ m/^RAST/) {
				$name = $fig->{_name};
				$taxonomy = $fig->{_taxonomy};
				$size = $fig->{_size};
			} else {
				$name = $fig->orgname_of_orgid($OrganismID);
				$taxonomy = $fig->taxonomy_of($OrganismID);
				$taxonomy =~ s/;\s/;/g;
				$taxonomy =~ s/;/|/g;
				$size = $fig->genome_szdna($OrganismID);
			}
			my $GenomeData = $fig->all_features_detailed_fast($OrganismID);
			#Sorting GenomeData by gene location on the chromosome
			my @Sorted = sort { $a->[4] <=> $b->[4] } @$GenomeData;
			$GenomeData = ();
			push(@{$GenomeData},@Sorted);
			#Inserting the data from the two dimensional array into the table object
			foreach my $Row (@{$GenomeData}) {
				my $RoleArray;
				if (defined($Row->[6])) {
					push(@{$RoleArray},$self->figmodel()->roles_of_function($Row->[6]));
				} else {
					$RoleArray = ["NONE"];
				}
				my $AliaseArray;
				push(@{$AliaseArray},split(/,/,$Row->[2]));
				if (defined($GetSequences) && $GetSequences == 1) {
					my $Sequence = $fig->get_translation($Row->[0]);
					if (defined($Sequence) && length($Sequence) > 0) {
						$featuretbl->add_row({"ID" => [$Row->[0]],"ALIASES" => $AliaseArray,"TYPE" => [$Row->[3]],"LOCATION" => [$Row->[1]],"MIN LOCATION" => [$Row->[4]],"MAX LOCATION" => [$Row->[5]],"ROLES" => $RoleArray,"SEQUENCE" => [$Sequence]});
					} else {
						$featuretbl->add_row({"ID" => [$Row->[0]],"ALIASES" => $AliaseArray,"TYPE" => [$Row->[3]],"LOCATION" => [$Row->[1]],"MIN LOCATION" => [$Row->[4]],"MAX LOCATION" => [$Row->[5]],"ROLES" => $RoleArray});
					}
				} else {
					$featuretbl->add_row({"ID" => [$Row->[0]],"ALIASES" => $AliaseArray,"TYPE" => [$Row->[3]],"LOCATION" => [$Row->[1]],"MIN LOCATION" => [$Row->[4]],"MAX LOCATION" => [$Row->[5]],"ROLES" => $RoleArray});
				}
			}
		}
	}

	$featuretbl->set_metadata("NAME",$name);
	$featuretbl->set_metadata("TAXONOMY",$taxonomy);
	$featuretbl->set_metadata("SOURCE",$source);
	$featuretbl->set_metadata("OWNER",$owner);
	$featuretbl->set_metadata("SIZE",$size);
	$self->set_cache($OrganismID."-FEATURETABLE",$featuretbl);
	return $featuretbl;
}

=head3 get_media
Definition:
	{string=>[string]} = FIGMODELdatabase->get_media(string::media id);
Description:
	Returns the media row from the media table
=cut
sub get_media {
	my($self,$id) = @_;

	my $tbl = $self->GetDBTable("MEDIA");
	if (!defined($tbl)) {
		return undef;
	}

	if ($id =~ m/^\d+$/) {
		return $tbl->get_row($id);
	}
	return $tbl->get_row_by_key($id,"NAME");
}

=head3 get_media_number
Definition:
	int = FIGMODELdatabase->get_media_number();
Description:
	Returns the number of media formulations in the database
=cut
sub get_media_number {
	my($self) = @_;

	my $tbl = $self->GetDBTable("MEDIA");
	return $tbl->size();
}

=head3 get_compound
Definition:
	{string=>[string]}::compound data = FIGMODEL->get_compound(string::compound ID);
Description:
=cut
sub get_compound {
	my ($self,$id) = @_;

	if ($id =~ m/^\d+$/) {
		my $cpdtbl = $self->GetDBTable("COMPOUNDS");
		if (!defined($cpdtbl)) {
			return undef;
		}
		return $cpdtbl->get_row($id);
	}
	return $self->get_row_by_key("COMPOUNDS",$id,"DATABASE");
}

=head3 get_compound_number
Definition:
	int = FIGMODEL->get_compound_number();
Description:
=cut
sub get_compound_number {
	my ($self) = @_;

	my $cpdtbl = $self->database()->GetDBTable("COMPOUNDS");
	if (!defined($cpdtbl)) {
		return 0;
	}
	return $cpdtbl->size();
}

=head3 ConsolidateMediaFiles
Definition:
	FIGMODELdatabase->ConsolidateMediaFiles();
Description:
	This function consolidates all of the various media formulations in the Media directory into a single file.
	This file is formated as a FIGMODELTable, and it is used by the mpifba code to determine media formulations.
	The file will be in the masterfiles directory names: MediaTable.txt.
=cut
sub ConsolidateMediaFiles {
	my ($self) = @_;

	#Creating a new media table
	my $names = $self->config("Reaction database directory");
	my $MediaTable = FIGMODELTable->new(["NAME","NAMES","COMPOUNDS","MAX","MIN"],$names->[0]."masterfiles/MediaTable.txt",["NAME","COMPOUNDS"],";","|",undef);
	#Loading media formulations into table
	my $mediadir = $self->config("Media directory");
	my @Filenames = glob($mediadir->[0]."*");
	foreach my $Filename (@Filenames) {
		if ($Filename !~ m/Test/ && $Filename =~ m/\/([^\/]+)\.txt/) {
			my $MediaName = $1;
			my $MediaFormulation = $self->load_table($Filename,";","",0,undef);
			my ($CompoundList,$NameList,$MaxList,$MinList);
			for (my $i=0; $i < $MediaFormulation->size(); $i++) {
				if ($MediaFormulation->get_row($i)->{"VarName"}->[0] =~ m/cpd\d\d\d\d\d/) {
					push(@{$CompoundList},$MediaFormulation->get_row($i)->{"VarName"}->[0]);
					my $CompoundData = $self->get_compound($MediaFormulation->get_row($i)->{"VarName"}->[0]);
					if (defined($CompoundData) && defined($CompoundData->{NAME}->[0])) {
						push(@{$NameList},$CompoundData->{NAME}->[0]);
					}
					push(@{$MinList},$MediaFormulation->get_row($i)->{"Min"}->[0]);
					push(@{$MaxList},$MediaFormulation->get_row($i)->{"Max"}->[0]);
				}
			}
			$MediaTable->add_row({"NAME" => [$MediaName],"NAMES" => $NameList,"COMPOUNDS" => $CompoundList,"MAX" => $MaxList,"MIN" => $MinList});
		}
	}

	#Saving the table
	$MediaTable->save();

	return $MediaTable;
}

=head3 FillInMissingMediaFiles
Definition:
	FIGMODELdatabase->FillInMissingMediaFiles();
Description:
=cut

sub FillInMissingMediaFiles {
	my($self) = @_;
	
	my $tbl = $self->GetDBTable("MEDIA");
	for (my $i=0; $i < $tbl->size(); $i++) {
		my $row = $tbl->get_row($i);
		if (!-e $self->figmodel()->config("Media directory")->[0].$row->{NAME}->[0].".txt") {
			my $output = ["VarName;VarType;VarCompartment;Min;Max"];
			for (my $j=0; $j < @{$row->{COMPOUNDS}}; $j++) {
				push(@{$output},$row->{COMPOUNDS}->[$j].";DRAIN_FLUX;e;".$row->{MIN}->[$j].";".$row->{MAX}->[$j]);
			}
			$self->print_array_to_file($self->figmodel()->config("Media directory")->[0].$row->{NAME}->[0].".txt",$output);
		}
	}
}

=head3 ProcessDatabaseWithMFAToolkit
Definition:
	FIGMODELdatabase->ProcessDatabaseWithMFAToolkit(string||[string]::list of entities to be processed);
Description:
	This function uses the MFAToolkit to process the entire reaction database. This involves balancing reactions, calculating thermodynamic data, and parsing compound structure files for charge and formula.
	This function should be run when reactions are added or changed, or when structures are added or changed.
	The database should probably be backed up before running the function just in case something goes wrong.
=cut

sub ProcessDatabaseWithMFAToolkit {
	my($self,$processlist) = @_;
	#Checking that the processlist exists
	if (!defined($processlist) || $processlist eq "ALL") {
		my @FilenameList = glob($self->config("compound directory")->[0]."cpd*");
		for (my $j=0; $j < @FilenameList; $j++) {
			if ($FilenameList[$j] =~ m/(cpd\d\d\d\d\d)/) {
				push(@{$processlist},$1);
			}
		}
		@FilenameList = glob($self->config("reaction directory")->[0]."rxn*");
		for (my $j=0; $j < @FilenameList; $j++) {
			if ($FilenameList[$j] =~ m/(rxn\d\d\d\d\d)/) {
				push(@{$processlist},$1);
			}
		}
	}
	#Getting unique directory for output
	my $outputfolder = $self->figmodel()->filename();
	#Ensuring that the newcompounds and newreactions directories exist
	if (!-d $self->config("Reaction database directory")->[0]."newreactions/") {
		system("mkdir ".$self->config("Reaction database directory")->[0]."newreactions/");
	}
	if (!-d $self->config("Reaction database directory")->[0]."newcompounds/") {
		system("mkdir ".$self->config("Reaction database directory")->[0]."newcompounds/");
	}
	if (!-d $self->config("Reaction database directory")->[0]."oldreactions/") {
		system("mkdir ".$self->config("Reaction database directory")->[0]."oldreactions/");
	}
	if (!-d $self->config("Reaction database directory")->[0]."oldcompounds/") {
		system("mkdir ".$self->config("Reaction database directory")->[0]."oldcompounds/");
	}
	#Printing the process list to file if it exists
	$self->print_array_to_file($self->config("MFAToolkit input files")->[0].$outputfolder."-processList.txt",$processlist);
	#Eliminating the mfatoolkit errors from the compound and reaction files
	for (my $j=0; $j < @{$processlist}; $j++) {
		my $Data = $self->figmodel()->LoadObject($processlist->[$j]);
		for (my $i=0; $i < @{$Data->{"orderedkeys"}}; $i++) {
			if ($Data->{"orderedkeys"}->[$i] eq "MFATOOLKIT ERRORS") {
				splice(@{$Data->{"orderedkeys"}},$i,1);
				last;
			}
		}
		$self->figmodel()->SaveObject($Data);
	}
	#Running the mfatoolkit
	system($self->figmodel()->GenerateMFAToolkitCommandLineCall($outputfolder,"processdatabase","NONE",["ArgonneProcessing"],{"entities to process" => $outputfolder."-processList.txt"},"DBProcessing-".$outputfolder.".log"));
	#Backing up the current reaction and compound directories
	for (my $i=0; $i < @{$processlist}; $i++) {
		if ($processlist->[$i] =~ m/cpd\d\d\d\d\d/) {
			system("cp ".$self->config("compound directory")->[0].$processlist->[$i]." ".$self->config("Reaction database directory")->[0]."oldcompounds/".$processlist->[$i]);
			system("cp ".$self->config("Reaction database directory")->[0]."newcompounds/".$processlist->[$i]." ".$self->config("compound directory")->[0].$processlist->[$i]);
		} elsif ($processlist->[$i] =~ m/rxn\d\d\d\d\d/) {
			system("cp ".$self->config("reaction directory")->[0].$processlist->[$i]." ".$self->config("Reaction database directory")->[0]."oldreactions/".$processlist->[$i]);
			system("cp ".$self->config("Reaction database directory")->[0]."newreactions/".$processlist->[$i]." ".$self->config("reaction directory")->[0].$processlist->[$i]);
		}
	}
	system("rm ".$self->config("MFAToolkit input files")->[0].$outputfolder."-processList.txt");
	$self->figmodel()->clearing_output($outputfolder,"DBProcessing-".$outputfolder.".log");
	return $self->figmodel()->success();
}

=head3 check_for_file
Definition:
    [string]:filelines = FIGMODELdatabase->check_for_file([string]:filename)
Description:
=cut
sub check_for_file {
	my ($self,$input) = @_;
	
	if (@{$input} == 1 && -e $input->[0]) {
		return $self->load_single_column_file($input->[0]);
	}
	return $input;
}

=head3 convert_ids_to_search_terms
Definition:
    {string:term => [string]:IDs} = FIGMODELdatabase->convert_ids_to_search_terms([string]:IDs)
Description:
=cut
sub convert_ids_to_search_terms {
	my ($self,$IDList) = @_;

	#Converting the $IDList into a flat array ref of IDs
	my $NewIDList;
	if (defined($IDList) && ref($IDList) ne 'ARRAY') {
		my @TempArray = split(/,/,$IDList);
		for (my $j=0; $j < @TempArray; $j++) {
			push(@{$NewIDList},$TempArray[$j]);
		}
	} elsif (defined($IDList)) {
		for (my $i=0; $i < @{$IDList}; $i++) {
			my @TempArray = split(/,/,$IDList->[$i]);
			for (my $j=0; $j < @TempArray; $j++) {
				push(@{$NewIDList},$TempArray[$j]);
			}
		}
	}

	#Determining the type of each ID
	my $TypeLists;
	if (defined($NewIDList)) {
		for (my $i=0; $i < @{$NewIDList}; $i++) {
			if ($NewIDList->[$i] ne "ALL") {
				if ($NewIDList->[$i] =~ m/^fig\|(\d+\.\d+)\.(.+)$/) {
					push(@{$TypeLists->{"feature"}},$NewIDList->[$i]);
				} elsif ($NewIDList->[$i] =~ m/^figint\|(\d+\.\d+)\.(.+)$/) {
					push(@{$TypeLists->{"interval"}},$2);
				} elsif ($NewIDList->[$i] =~ m/^figstr\|(\d+\.\d+)\.(.+)$/) {
					push(@{$TypeLists->{"strain"}},$2);
				} elsif ($NewIDList->[$i] =~ m/^figmodel\|(.+)$/) {
					push(@{$TypeLists->{"model"}},$2);
				} elsif ($NewIDList->[$i] =~ m/^fig\|(\d+\.\d+)$/ || $NewIDList->[$i] =~ m/^(\d+\.\d+)$/) {
					push(@{$TypeLists->{"genome"}},$1);
				} elsif ($NewIDList->[$i] =~ m/^(rxn\d\d\d\d\d)$/) {
					push(@{$TypeLists->{"reaction"}},$1);
				} elsif ($NewIDList->[$i] =~ m/^(cpd\d\d\d\d\d)$/) {
					push(@{$TypeLists->{"compound"}},$1);
				} else {
					push(@{$TypeLists->{"model"}},$NewIDList->[$i]);
				}
			}
		}
	}

	return $TypeLists;
}

=head3 get_erdb_table
Definition:
     = FIGMODELdatabase->get_erdb_table()
Description:
=cut
sub get_erdb_table {
#	my ($self) = @_;
#	my $obj = Sapling->new();
#	
#	my @ids = $obj->GetFlat("Model","Model(class) = ? and Model(totalGenes) > ?",["Gram positive","1000"],"id");
#	print "All ids:".join(",",@ids)."\n";
#	
#	my @objects = $obj->GetList("Model","Model(class) = ? and Model(totalGenes) > ?",["Gram positive","1000"]);
#	
#	#Changing feild
#	$obj->UpdateEntity("Model",$objects[0]->PrimaryValue("id"),%$hash);
#	
#	#Inserting new object
#	$obj->InsertObject("Model",%$hash);
#	
#	#Deleting element and everything attached to element
#	$obj->Delete("Model","iJR904");
#	
#	my @ids = $obj->GetFlat("Model","Model(class) = ? and Model(totalGenes) > ?",["Gram positive","1000"],"id");
#	
#	
#	
#	
#	my @value = $objects[0]->Value("id");
#	print "Single value:".$value[0]."\n";
#	print "Single value:".$objects[0]->PrimaryValue("id")."\n";
#	
#	my @info = $obj->GetAll("Model","Model(class) = ? and Model(totalGenes) > ?",["Gram positive","1000"],["id","totalGenes"]);
#	print "ID:".$info[0]->[0]."\tTotal genes:".$info[0]->[1]."\n";
}

sub load_ppo {
	my($self,$object) = @_;
	if ($object eq "media") {
		my $mediaTbl = $self->figmodel()->database()->get_table("MEDIA");
		for (my $i=0; $i < $mediaTbl->size(); $i++) {
			my $row = $mediaTbl->get_row($i);
			my $aerobic = 0;
			for (my $j=0; $j < @{$row->{COMPOUNDS}}; $j++) {
				if ($row->{COMPOUNDS}->[$j] eq "cpd00007" && $row->{MAX}->[$j] > 0) {
					$aerobic = 1;
					last;
				}
			}
			my $mediaMgr = $self->figmodel()->database()->get_object_manager("media");
			$mediaMgr->create({id=>$row->{NAME}->[0],owner=>"master",modificationDate=>time(),creationDate=>time(),aerobic=>$aerobic});
		}
	} elsif ($object eq "mediacpd") {
		my $mediaTbl = $self->figmodel()->database()->get_table("MEDIA");
		for (my $i=0; $i < $mediaTbl->size(); $i++) {
			my $row = $mediaTbl->get_row($i);
			my $alreadySeed;
			for (my $j=0; $j < @{$row->{COMPOUNDS}}; $j++) {
				if (!defined($alreadySeed->{$row->{COMPOUNDS}->[$j]})) {
					$alreadySeed->{$row->{COMPOUNDS}->[$j]} = 1;
					my $max = 100;
					my $conc = 0.001;
					if (defined($row->{MAX}->[$j])) {
						$max = $row->{MAX}->[$j];
					}
					my $mediaMgr = $self->figmodel()->database()->get_object_manager("mediacpd");
					$mediaMgr->create({MEDIA=>$row->{NAME}->[0],COMPOUND=>$row->{COMPOUNDS}->[$j],concentration=>$conc,maxFlux=>$max});
				} else {
					print "Compound ".$row->{COMPOUNDS}->[$j]." repeated in ".$row->{NAME}->[0]." media!\n";
				}
			}
		}
	} elsif ($object eq "compound") {
		my $tbl = $self->figmodel()->database()->get_table("COMPOUNDS");
		for (my $i=0; $i < $tbl->size(); $i++) {
			my $row = $tbl->get_row($i);
			my $name = $row->{NAME}->[0];
			for (my $j=1; $j < @{$row->{NAME}}; $j++) {
				if (length($name) > 32) {
					$name = $row->{NAME}->[$j];
					last;
				}
			}
			if (length($name) > 32) {
				$name = substr($name,32);
			}
			my $dataHash = {id=>$row->{DATABASE}->[0],name=>$name,owner=>"master",users=>"all",modificationDate=>time(),creationDate=>time()};
			if (defined($row->{STRINGCODE}->[0])) {
				$dataHash->{stringcode} = $row->{STRINGCODE}->[0];
			}
			if (defined($row->{DELTAG}->[0])) {
				$dataHash->{deltaG} = $row->{DELTAG}->[0];
			}
			if (defined($row->{DELTAGERR}->[0])) {
				$dataHash->{deltaGErr} = $row->{DELTAGERR}->[0];
			}
			if (defined($row->{FORMULA}->[0])) {
				$dataHash->{formula} = $row->{FORMULA}->[0];
			}
			if (defined($row->{MASS}->[0])) {
				$dataHash->{mass} = $row->{MASS}->[0];
			}
			if (defined($row->{CHARGE}->[0])) {
				$dataHash->{charge} = $row->{CHARGE}->[0];
			}
			my $fileData = FIGMODELObject->load($self->config("compound directory")->[0].$row->{DATABASE}->[0],"\t");		
			if (defined($fileData->{PKA})) {
				$dataHash->{pKa} = join(";",@{$fileData->{PKA}});
			}
			if (defined($fileData->{PKB})) {
				$dataHash->{pKb} = join(";",@{$fileData->{PKB}});
			}
			if (defined($fileData->{STRUCTURAL_CUES})) {
				$dataHash->{structuralCues} = join(";",@{$fileData->{STRUCTURAL_CUES}});
			}
			my $cpdMgr = $self->figmodel()->database()->get_object_manager("compound");
			$cpdMgr->create($dataHash);
		}
	} elsif ($object eq "cpdals") {
		my $aliasHash;
		my $tbl = $self->figmodel()->database()->get_table("COMPOUNDS");
		for (my $i=0; $i < $tbl->size(); $i++) {
			my $row = $tbl->get_row($i);
			for (my $j=0; $j < @{$row->{NAME}}; $j++) {
				if (!defined($aliasHash->{$row->{DATABASE}->[0]}->{name}->{lc($row->{NAME}->[$j])})) {
					$aliasHash->{$row->{DATABASE}->[0]}->{name}->{lc($row->{NAME}->[$j])} = 1;
					my $cpdMgr = $self->figmodel()->database()->get_object_manager("cpdals");
					$cpdMgr->create({COMPOUND=>$row->{DATABASE}->[0],alias=>$row->{NAME}->[$j],type=>"name"});
					my @searchNames = $self->figmodel()->ConvertToSearchNames($row->{NAME}->[$j]);
					for (my $k=0; $k < @searchNames; $k++) {
						if (!defined($aliasHash->{$row->{DATABASE}->[0]}->{searchname}->{lc($searchNames[$k])})) {
							$aliasHash->{$row->{DATABASE}->[0]}->{searchname}->{lc($searchNames[$k])} = 1;
							my $cpdMgr = $self->figmodel()->database()->get_object_manager("cpdals");
							$cpdMgr->create({COMPOUND=>$row->{DATABASE}->[0],alias=>lc($searchNames[$k]),type=>"searchname"});
						}
					}
				}
			}
		}
		my @files = glob($self->figmodel()->config("Translation directory")->[0]."CpdTo*");
		for (my $i=0; $i < @files; $i++) {
			if ($files[$i] !~ m/CpdToAll/ && $files[$i] =~ m/CpdTo(.+)\.txt/) {
				my $type = $1;
				my $data = $self->load_multiple_column_file($files[$i],"\t");
				for (my $j=0; $j < @{$data}; $j++) {
					my $cpdMgr = $self->figmodel()->database()->get_object_manager("cpdals");
					$cpdMgr->create({COMPOUND=>$data->[$j]->[0],alias=>$data->[$j]->[1],type=>$type});
				}
			}
		}
		my $data = $self->load_multiple_column_file($self->figmodel()->config("Translation directory")->[0]."ObsoleteCpdIDs.txt","\t");
		for (my $j=0; $j < @{$data}; $j++) {
			my $cpdMgr = $self->figmodel()->database()->get_object_manager("cpdals");
			$cpdMgr->create({COMPOUND=>$data->[$j]->[0],alias=>$data->[$j]->[1],type=>"obsolete"});
		}
	} elsif ($object eq "reaction") {
		my $tbl = $self->figmodel()->database()->get_table("REACTIONS");
		for (my $i=0; $i < $tbl->size(); $i++) {
			my $row = $tbl->get_row($i);
			my $name = $row->{DATABASE}->[0];
			if (defined($row->{NAME}->[0])){
				$name = $row->{NAME}->[0];
				for (my $j=1; $j < @{$row->{NAME}}; $j++) {
					if (length($name) > 250 && length($row->{NAME}->[$j]) < 32) {
						$name = $row->{NAME}->[$j];
						last;
					}
				}
				if (length($name) > 250) {
					$name = substr($name,250);
				}
			}
			my $rxnObj = $self->figmodel()->LoadObject($row->{DATABASE}->[0]);
			my $thermodynamicReversibility = "<=>";
			my $definition = "NONE";
			if (defined($rxnObj) && defined($rxnObj->{DEFINITION}->[0])) {
				$definition = $rxnObj->{DEFINITION}->[0];
			}
			if (defined($rxnObj) && defined($rxnObj->{"THERMODYNAMIC REVERSIBILITY"}->[0])) {
				$thermodynamicReversibility = $rxnObj->{"THERMODYNAMIC REVERSIBILITY"}->[0];
			}
			my $dataHash = {id=>$row->{DATABASE}->[0],name=>$name,thermoReversibility=>$thermodynamicReversibility,reversibility=>$self->figmodel()->reversibility_of_reaction($row->{DATABASE}->[0]),definition=>$definition,code=>$row->{CODE}->[0],equation=>$row->{EQUATION}->[0],owner=>"master",users=>"all",modificationDate=>time(),creationDate=>time()};
			if (defined($row->{ENZYME}->[0])) {
				$dataHash->{enzyme} = "|".join("|",@{$row->{ENZYME}})."|";
			}
			if (defined($row->{DELTAG}->[0])) {
				$dataHash->{deltaG} = $row->{DELTAG}->[0];
			}
			if (defined($row->{DELTAGERR}->[0])) {
				$dataHash->{deltaGErr} = $row->{DELTAGERR}->[0];
			}
			
			if (defined($rxnObj->{STRUCTURAL_CUES})) {
				$dataHash->{structuralCues} = "|".join("|",@{$rxnObj->{STRUCTURAL_CUES}})."|";
			}
			my $rxnMgr = $self->figmodel()->database()->get_object_manager("reaction");
			$rxnMgr->create($dataHash);
			my ($reactants,$products) = $self->figmodel()->GetReactionSubstrateDataFromEquation($row->{EQUATION}->[0]);
			if (defined($reactants)) {
				for (my $j=0; $j < @{$reactants}; $j++) {
					my $cpdrxnMgr = $self->figmodel()->database()->get_object_manager("cpdrxn");
					$cpdrxnMgr->create({COMPOUND=>$reactants->[$j]->{DATABASE}->[0],REACTION=>$row->{DATABASE}->[0],coefficient=>-1*$reactants->[$j]->{COEFFICIENT}->[0],compartment=>$reactants->[$j]->{COMPARTMENT}->[0],cofactor=>"false"});
				}
			}
			if (defined($products)) {
				for (my $j=0; $j < @{$products}; $j++) {
					my $cpdrxnMgr = $self->figmodel()->database()->get_object_manager("cpdrxn");
					$cpdrxnMgr->create({COMPOUND=>$products->[$j]->{DATABASE}->[0],REACTION=>$row->{DATABASE}->[0],coefficient=>$products->[$j]->{COEFFICIENT}->[0],compartment=>$products->[$j]->{COMPARTMENT}->[0],cofactor=>"false"});
				}
			}
		}
	} elsif ($object eq "rxnals") {
		my @files = glob($self->figmodel()->config("Translation directory")->[0]."RxnTo*");
		for (my $i=0; $i < @files; $i++) {
			if ($files[$i] !~ m/RxnToAll/ && $files[$i] =~ m/RxnTo(.+)\.txt/) {
				my $type = $1;
				my $data = $self->load_multiple_column_file($files[$i],"\t");
				for (my $j=0; $j < @{$data}; $j++) {
					my $rxnMgr = $self->figmodel()->database()->get_object_manager("rxnals");
					$rxnMgr->create({REACTION=>$data->[$j]->[0],alias=>$data->[$j]->[1],type=>$type});
				}
			}
		}
		my $data = $self->load_multiple_column_file($self->figmodel()->config("Translation directory")->[0]."ObsoleteRxnIDs.txt","\t");
		for (my $j=0; $j < @{$data}; $j++) {
			my $rxnMgr = $self->figmodel()->database()->get_object_manager("rxnals");
			$rxnMgr->create({REACTION=>$data->[$j]->[0],alias=>$data->[$j]->[1],type=>"obsolete"});
		}
	} elsif ($object eq "bof") {
		my $aliasHash;
		my $tbl = $self->figmodel()->database()->get_table("BIOMASS");
		my $botTempTbl = $self->figmodel()->database()->GetDBTable("BIOMASS TEMPLATE");
		my $groupHash;
		my $grpIndex = {L=>"pkg00001",W=>"pkg00001",C=>"pkg00001"};
		my $mdlMgr = $self->figmodel()->database()->get_object_manager("model");
		for (my $i=0; $i < $tbl->size(); $i++) {
			my $row = $tbl->get_row($i);
			my $cpdMgr = $self->figmodel()->database()->get_object_manager("bof");
			my $data = {id=>$row->{DATABASE}->[0],name=>"Biomass",equation=>$row->{EQUATION}->[0],protein=>"0.5284",DNA=>"0.026",RNA=>"0.0655",lipid=>"0.075",cellWall=>"0.25",cofactor=>"0.10",modificationDate=>time(),creationDate=>time()};
			$data->{owner} = "master";
			$data->{users}  = "all";
			my $mdlObjs = $mdlMgr->get_objects({biomassReaction=>$row->{DATABASE}->[0]});
			if (defined($mdlObjs->[0]) && !defined($mdlObjs->[1])) {
				$data->{owner} = $mdlObjs->[0]->owner();
				$data->{users}  = $mdlObjs->[0]->users();
			}
			my ($lccdata,$coef,$package);
			my ($reactants,$products) = $self->figmodel()->GetReactionSubstrateDataFromEquation($row->{EQUATION}->[0]);
			#Populating the compound biomass table
			my $hash;
			for (my $j=0; $j < @{$reactants}; $j++) {
				my $category = "U";#Unknown
				my $tempRow = $botTempTbl->get_row_by_key($reactants->[$j]->{DATABASE}->[0],"ID");
				if (defined($tempRow) && $tempRow->{CLASS}->[0] eq "LIPIDS") {
					$category = "L";#Lipid
				} elsif (defined($tempRow) && $tempRow->{CLASS}->[0] eq "CELL WALL") {
					$category = "W";#Cell wall
				} elsif (defined($tempRow) && $tempRow->{CLASS}->[0] eq "COFACTOR") {
					$category = "C";#Cofactor
				} elsif (defined($tempRow) && $tempRow->{CLASS}->[0] eq "ENERGY") {
					$category = "E";#Energy
				} elsif (defined($tempRow)) {
					$category = "M";#Macromolecule
				}
				$lccdata->{$category}->{$reactants->[$j]->{DATABASE}->[0]} = "-".$reactants->[$j]->{COEFFICIENT}->[0];
				if (!defined($hash->{$reactants->[$j]->{DATABASE}->[0]}->{$row->{DATABASE}->[0]}->{$reactants->[$j]->{COMPARTMENT}->[0]})) {
					$hash->{$reactants->[$j]->{DATABASE}->[0]}->{$row->{DATABASE}->[0]}->{$reactants->[$j]->{COMPARTMENT}->[0]} = 1;
					my $cpdbofMgr = $self->figmodel()->database()->get_object_manager("cpdbof");
					$cpdbofMgr->create({COMPOUND=>$reactants->[$j]->{DATABASE}->[0],BIOMASS=>$row->{DATABASE}->[0],coefficient=>(-1*$reactants->[$j]->{COEFFICIENT}->[0]),compartment=>$reactants->[$j]->{COMPARTMENT}->[0],category=>$category});	
				}
			}
			for (my $j=0; $j < @{$products}; $j++) {
				my $category = "U";#Unknown
				my $tempRow = $botTempTbl->get_row_by_key($products->[$j]->{DATABASE}->[0],"ID");
				if (defined($tempRow) && $tempRow->{CLASS}->[0] eq "LIPIDS") {
					$category = "L";#Lipid
				} elsif (defined($tempRow) && $tempRow->{CLASS}->[0] eq "CELL WALL") {
					$category = "W";#Cell wall
				} elsif (defined($tempRow) && $tempRow->{CLASS}->[0] eq "COFACTOR") {
					$category = "C";#Cofactor
				} elsif (defined($tempRow) && $tempRow->{CLASS}->[0] eq "ENERGY") {
					$category = "E";#Energy
				} elsif (defined($tempRow)) {
					$category = "M";#Macromolecule
				}
				$lccdata->{$category}->{$products->[$j]->{DATABASE}->[0]} = "-".$products->[$j]->{COEFFICIENT}->[0];
				if (!defined($hash->{$products->[$j]->{DATABASE}->[0]}->{$row->{DATABASE}->[0]}->{$products->[$j]->{COMPARTMENT}->[0]})) {
					$hash->{$products->[$j]->{DATABASE}->[0]}->{$row->{DATABASE}->[0]}->{$products->[$j]->{COMPARTMENT}->[0]} = 1;
					my $cpdbofMgr = $self->figmodel()->database()->get_object_manager("cpdbof");
					$cpdbofMgr->create({COMPOUND=>$products->[$j]->{DATABASE}->[0],BIOMASS=>$row->{DATABASE}->[0],coefficient=>$products->[$j]->{COEFFICIENT}->[0],compartment=>$products->[$j]->{COMPARTMENT}->[0],category=>$category});	
				}
			}
			my $types = ["L","C","W"];
			my $typeNames = {L=>"Lipid",C=>"Cofactor",W=>"CellWall"};
			for (my $j=0; $j < @{$types}; $j++) {
				if (!defined($lccdata->{$types->[$j]})) {
					$coef->{$types->[$j]} = "NONE";
					$package->{$types->[$j]} = "NONE";
				} else {
					my @list = sort(keys(%{$lccdata->{$types->[$j]}}));
					for (my $k=0; $k < @list; $k++) {
						$coef->{$types->[$j]} .= $lccdata->{$types->[$j]}->{$list[$k]}.";";
					}
					my $key = join(";",@list);
					if (!defined($groupHash->{$types->[$j]}->{$key})) {
						$groupHash->{$types->[$j]}->{$key} = $grpIndex->{$types->[$j]};
						for (my $k=0; $k < @list; $k++) {
							print "Creating compound group:";
							my $cpdGrpMgr = $self->figmodel()->database()->get_object_manager("cpdgrp");
							$cpdGrpMgr->create({COMPOUND=>$list[$k],grouping=>$grpIndex->{$types->[$j]},type=>$typeNames->{$types->[$j]}."Package"});
							print "DONE\n";
						}
						$grpIndex->{$types->[$j]}++;
					}
					$package->{$types->[$j]} = $groupHash->{$types->[$j]}->{$key};
				}
			}
			$data->{cofactorPackage} = $package->{"C"};
			$data->{lipidPackage} = $package->{"L"};
			$data->{cellWallPackage} = $package->{"W"};
			$data->{DNACoef} = "-0.284|1|-0.216|-0.216|-0.284";
			$data->{RNACoef} = "1|-0.262|-0.323|-0.199|-0.215";
			$data->{proteinCoef} = "1|-0.0637|-0.0999|-0.0653|-0.0790|-0.0362|-0.0472|-0.0637|-0.0529|-0.0277|-0.0133|-0.0430|-0.0271|-0.0139|-0.0848|-0.0200|-0.0393|-0.0362|-0.0751|-0.0456|-0.0660";
			$data->{lipidCoef} = $coef->{"L"};
			$data->{cellWallCoef} = $coef->{"W"};
			$data->{cofactorCoef} = $coef->{"C"};
			$data->{energy} = 40;
			if (defined($row->{"ESSENTIAL REACTIONS"})) {
				$data->{essentialRxn} = join("|",@{$row->{"ESSENTIAL REACTIONS"}});
			}
			print "Creating biomass reaction.";
			$cpdMgr->create($data);
			print "Done.\n";
		}
	}
}

=head3 add_biomass_reaction_from_file
Definition:
	(success/fail) = FIGMODELdatabase>add_biomass_reaction_from_file(string:biomass ID);
=cut
sub add_biomass_reaction_from_file {
	my($self,$biomassID) = @_;
	my $object = $self->LoadObject($biomassID);
	#Parsing equation
	my ($reactants,$products) = $self->figmodel()->GetReactionSubstrateDataFromEquation($object->{EQUATION}->[0]);
	#Populating the compound biomass table
	my $energy = 0;
	my $compounds;
	$compounds->{RNA} = {cpd00002=>0,cpd00012=>0,cpd00038=>0,cpd00052=>0,cpd00062=>0};
	$compounds->{protein} = {cpd00001=>0,cpd00023=>0,cpd00033=>0,cpd00035=>0,cpd00039=>0,cpd00041=>0,cpd00051=>0,cpd00053=>0,cpd00054=>0,cpd00060=>0,cpd00065=>0,cpd00066=>0,cpd00069=>0,cpd00084=>0,cpd00107=>0,cpd00119=>0,cpd00129=>0,cpd00132=>0,cpd00156=>0,cpd00161=>0,cpd00322=>0};
	$compounds->{DNA} = {cpd00012=>0,cpd00115=>0,cpd00241=>0,cpd00356=>0,cpd00357=>0};
	for (my $j=0; $j < @{$reactants}; $j++) {
		my $category = "U";
		if ($reactants->[$j]->{DATABASE}->[0] eq "cpd00002" || $reactants->[$j]->{DATABASE}->[0] eq "cpd00001") {
			$category = "E";
			if ($energy < $reactants->[$j]->{COEFFICIENT}->[0]) {
				$energy = floor($reactants->[$j]->{COEFFICIENT}->[0]);
			}
		}
		if (defined($compounds->{protein}->{$reactants->[$j]->{DATABASE}->[0]})) {
			$compounds->{protein}->{$reactants->[$j]->{DATABASE}->[0]} = $reactants->[$j]->{COEFFICIENT}->[0];
			$category = "P";
		} elsif (defined($compounds->{RNA}->{$reactants->[$j]->{DATABASE}->[0]})) {
			$compounds->{RNA}->{$reactants->[$j]->{DATABASE}->[0]} = $reactants->[$j]->{COEFFICIENT}->[0];
			$category = "R";
		} elsif (defined($compounds->{DNA}->{$reactants->[$j]->{DATABASE}->[0]})) {
			$compounds->{DNA}->{$reactants->[$j]->{DATABASE}->[0]} = $reactants->[$j]->{COEFFICIENT}->[0];
			$category = "D";
		}
		my $cpdbofMgr = $self->database()->get_object_manager("cpdbof");
		$cpdbofMgr->create({COMPOUND=>$reactants->[$j]->{DATABASE}->[0],BIOMASS=>$biomassID,coefficient=>-1*$reactants->[$j]->{COEFFICIENT}->[0],compartment=>$reactants->[$j]->{COMPARTMENT}->[0],category=>$category});	
	}
	for (my $j=0; $j < @{$products}; $j++) {
		my $category = "U";
		if ($products->[$j]->{DATABASE}->[0] eq "cpd00008" || $products->[$j]->{DATABASE}->[0] eq "cpd00009" || $products->[$j]->{DATABASE}->[0] eq "cpd00067") {
			$category = "E";
			if ($energy < $products->[$j]->{COEFFICIENT}->[0]) {
				$energy = floor($products->[$j]->{COEFFICIENT}->[0]);
			}
		} elsif ($products->[$j]->{DATABASE}->[0] eq "cpd11416") {
			$category = "M";
		}
		my $cpdbofMgr = $self->database()->get_object_manager("cpdbof");
		$cpdbofMgr->create({COMPOUND=>$products->[$j]->{DATABASE}->[0],BIOMASS=>$biomassID,coefficient=>$products->[$j]->{COEFFICIENT}->[0],compartment=>$products->[$j]->{COMPARTMENT}->[0],category=>$category});	
	}
	my $package = {lipid=>"NONE",cellWall=>"NONE",cofactor=>"NONE"};
	my $coef = {protein=>"NONE",DNA=>"NONE",RNA=>"NONE",lipid=>"NONE",cellWall=>"NONE",cofactor=>"NONE"};
	my $types = ["protein","DNA","RNA","lipid","cellWall","cofactor"];
	my $packages;
	my $packageHash;
	for (my $i=0; $i < @{$types}; $i++) {
		my @entities = sort(keys(%{$compounds->{$types->[$i]}}));
		if (@entities > 0 && $types->[$i] eq "lipid" && $types->[$i] eq "cellWall" && $types->[$i] eq "cofactor") {
			my $cpdgrpMgr = $self->get_object_manager("cpdgrp");
			my $cpdgrpObs = $cpdgrpMgr->get_objects({type=>$types->[$i]."Package"});
			for (my $j=0; $j < @{$cpdgrpObs}; $j++) {
				$packages->{$types->[$i]}->{$cpdgrpObs->[$j]->grouping()}->{$cpdgrpObs->[$j]->COMPOUND()} = 1;
			}
			my @packageList = keys(%{$packages->{$types->[$i]}});
			for (my $j=0; $j < @packageList; $j++) {
				$packageHash->{join("|",sort(keys(%{$packages->{$types->[$i]}->{$packageList[$j]}})))} = $packageList[$j];
			}
			if (defined($packageHash->{join("|",@entities)})) {
				$package->{$types->[$i]} = $packageHash->{join("|",@entities)};
			} else {
				my $newPackageID = $self->check_out_new_id($types->[$i]."Pkg");
				my @cpdList = keys(%{$compounds->{$types->[$i]}});
				for (my $j=0; $j < @cpdList; $j++) {
					$cpdgrpMgr = $self->get_object_manager("cpdgrp");
					$cpdgrpMgr->create({COMPOUND=>$cpdList[$j],grouping=>$newPackageID,type=>$types->[$i]."Package"});	
				}
			}
		}
		for (my $j=0; $j < @entities; $j++) {
			if ($j > 0) {
				$coef->{$types->[$i]} .= "|";
			}
			$coef->{$types->[$i]} .= $compounds->{$types->[$i]}->{$entities[$j]};
		}
	}
	my $data = {owner=>"master",name=>$object->{NAME}->[0],users=>"all",equation=>$object->{EQUATION}->[0],modificationData=>time(),creationDate=>time(),id=>$biomassID,cofactorPackage=>$package->{cofactor},lipidPackage=>$package->{lipid},cellWallPackage=>$package->{cellWall},protein=>"0",DNA=>"0",RNA=>"0",lipid=>"0",cellWall=>"0",cofactor=>"0",proteinCoef=>$coef->{protein},DNACoef=>$coef->{DNA},RNACoef=>$coef->{RNA},lipidCoef=>$coef->{lipid},cellWallCoef=>$coef->{cellWall},cofactorCoef=>$coef->{cofactor},energy=>$energy};
	my $bofMgr = $self->database()->get_object_manager("bof");
	my $bofObj = $bofMgr->get_objects({id=>$biomassID});
	if (!defined($bofObj->[0])) {
		$bofMgr->create($data);
	} else {
		$bofObj->[0]->owner($data->{owner});
		$bofObj->[0]->name($data->{name});
		$bofObj->[0]->users($data->{users});
		$bofObj->[0]->equation($data->{equation});
		$bofObj->[0]->modificationData($data->{modificationData});
		$bofObj->[0]->creationDate($data->{creationDate});
		$bofObj->[0]->cofactorPackage($data->{cofactorPackage});
		$bofObj->[0]->lipidPackage($data->{lipidPackage});
		$bofObj->[0]->cellWallPackage($data->{cellWallPackage});
		$bofObj->[0]->protein($data->{protein});
		$bofObj->[0]->DNA($data->{DNA});
		$bofObj->[0]->RNA($data->{RNA});
		$bofObj->[0]->lipid($data->{lipid});
		$bofObj->[0]->cellWall($data->{cellWall});
		$bofObj->[0]->cofactor($data->{cofactor});
		$bofObj->[0]->proteinCoef($data->{proteinCoef});
		$bofObj->[0]->DNACoef($data->{DNACoef});
		$bofObj->[0]->RNACoef($data->{RNACoef});
		$bofObj->[0]->lipidCoef($data->{lipidCoef});
		$bofObj->[0]->cellWallCoef($data->{cellWallCoef});
		$bofObj->[0]->cofactorCoef($data->{cofactorCoef});
		$bofObj->[0]->energy($data->{energy});
	}
}

1;

MCS Webmaster
ViewVC Help
Powered by ViewVC 1.0.3