-- -*-Sql-*- mode (to keep my emacs happy)
--
-- API Package Body for Taxon.
--
-- Scaffold auto-generated by gen-api.pl. gen-api.pl is
-- Copyright 2002-2003 Genomics Institute of the Novartis Research Foundation
-- Copyright 2002-2008 Hilmar Lapp
-- 
--  This file is part of BioSQL.
--
--  BioSQL is free software: you can redistribute it and/or modify it
--  under the terms of the GNU Lesser General Public License as
--  published by the Free Software Foundation, either version 3 of the
--  License, or (at your option) any later version.
--
--  BioSQL is distributed in the hope that it will be useful,
--  but WITHOUT ANY WARRANTY; without even the implied warranty of
--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
--  GNU Lesser General Public License for more details.
--
--  You should have received a copy of the GNU Lesser General Public License
--  along with BioSQL. If not, see <http://www.gnu.org/licenses/>.
--

CREATE OR REPLACE
PACKAGE BODY Tax IS

taxon_cached SG_TAXON.OID%TYPE DEFAULT NULL;
cache_key VARCHAR2(128) DEFAULT NULL;

CURSOR Tax_c (
		Tax_NCBI_TAXON_ID	IN SG_TAXON.NCBI_TAXON_ID%TYPE)
RETURN SG_TAXON%ROWTYPE IS
	SELECT t.* FROM SG_TAXON t
	WHERE
		t.NCBI_TAXON_ID = Tax_NCBI_TAXON_ID
	;

FUNCTION get_oid(
		Tax_OID	IN SG_TAXON.OID%TYPE DEFAULT NULL,
		Tax_NCBI_TAXON_ID	IN SG_TAXON.NCBI_TAXON_ID%TYPE,
		Tax_NODE_RANK	IN SG_TAXON.NODE_RANK%TYPE DEFAULT NULL,
		Tax_GENETIC_CODE	IN SG_TAXON.GENETIC_CODE%TYPE DEFAULT NULL,
		Tax_MITO_GENETIC_CODE	IN SG_TAXON.MITO_GENETIC_CODE%TYPE DEFAULT NULL,
		Tax_LEFT_VALUE	IN SG_TAXON.LEFT_VALUE%TYPE DEFAULT NULL,
		Tax_RIGHT_VALUE	IN SG_TAXON.RIGHT_VALUE%TYPE DEFAULT NULL,
		TAX_PARENT_OID	IN SG_TAXON.TAX_OID%TYPE DEFAULT NULL,
		Tax_PARENT_NCBI_TAXON_ID	IN SG_TAXON.NCBI_TAXON_ID%TYPE DEFAULT NULL,
		Tnm_Name	IN SG_TAXON_NAME.NAME%TYPE DEFAULT NULL,
		Tnm_Name_Class	IN SG_TAXON_NAME.NAME_CLASS%TYPE DEFAULT NULL,
		do_DML		IN NUMBER DEFAULT BSStd.DML_NO)
RETURN SG_TAXON.OID%TYPE
IS
	pk	SG_TAXON.OID%TYPE DEFAULT NULL;
	key_str VARCHAR2(128) DEFAULT Tax_NCBI_TAXON_ID;
	Tax_row Tax_c%ROWTYPE;
	TAX_OID_	SG_TAXON.OID%TYPE DEFAULT TAX_PARENT_OID;
BEGIN
	-- initialize
	IF (do_DML > BSStd.DML_NO) THEN
		pk := Tax_OID;
	END IF;
	-- look up
	IF (pk IS NULL) THEN
		IF (key_str = cache_key) THEN
	        	pk := taxon_cached;
		ELSIF (Tax_NCBI_TAXON_ID IS NULL) AND 
		      (Tnm_Name IS NOT NULL) THEN
 			pk := Tnm.get_oid(Tnm_Name => Tnm_Name,
 			                  Tnm_Name_Class => Tnm_Name_Class);
		ELSE
			-- reset cache
			cache_key := NULL;
			taxon_cached :=	NULL;
			-- look up primary key
			IF (Tax_NCBI_TAXON_ID IS NOT NULL) THEN
				-- do the look up
			   	FOR Tax_row IN Tax_c(Tax_NCBI_TAXON_ID) LOOP
		        		pk := Tax_row.OID;
					-- cache result
			    		cache_key := key_str;
			    		taxon_cached := pk;
			   	END LOOP;
			END IF;
		END IF;
	END IF;
	-- insert/update if requested
	IF (pk IS NULL) AND 
	   ((do_DML = BSStd.DML_I) OR (do_DML = BSStd.DML_UI)) THEN
	    	-- look up foreign keys if not provided:
		-- look up parent SG_TAXON, insert if necessary
		IF (Tax_Parent_NCBI_Taxon_ID IS NOT NULL) THEN
			IF (TAX_OID_ IS NULL) THEN
				TAX_OID_ := Tax.get_oid(
					Tax_NCBI_TAXON_ID => Tax_NCBI_TAXON_ID,
					do_DML => do_DML);
		   	END IF;
		   	IF (TAX_OID_ IS NULL) THEN
				raise_application_error(-20101,
					'failed to look up Tax <' || Tax_NCBI_TAXON_ID || '>');
		   	END IF;
		END IF;
	    	-- insert the record and obtain the primary key
	    	pk := do_insert(
		        NCBI_TAXON_ID => Tax_NCBI_TAXON_ID,
			NODE_RANK => Tax_NODE_RANK,
			GENETIC_CODE => Tax_GENETIC_CODE,
			MITO_GENETIC_CODE => Tax_MITO_GENETIC_CODE,
			LEFT_VALUE => Tax_LEFT_VALUE,
			RIGHT_VALUE => Tax_RIGHT_VALUE,
			TAX_OID => TAX_OID_);
	ELSIF (do_DML = BSStd.DML_U) OR (do_DML = BSStd.DML_UI) THEN
	        -- update the record (note that not provided FKs will not
		-- be changed nor looked up)
		do_update(
			Tax_OID	=> pk,
		        Tax_NCBI_TAXON_ID => Tax_NCBI_TAXON_ID,
			Tax_NODE_RANK => Tax_NODE_RANK,
			Tax_GENETIC_CODE => Tax_GENETIC_CODE,
			Tax_MITO_GENETIC_CODE => Tax_MITO_GENETIC_CODE,
			Tax_LEFT_VALUE => Tax_LEFT_VALUE,
			Tax_RIGHT_VALUE => Tax_RIGHT_VALUE,
			Tax_TAX_OID => TAX_OID_);
	END IF;
	-- return the primary key
	RETURN pk;
END;

FUNCTION do_insert(
		NCBI_TAXON_ID	IN SG_TAXON.NCBI_TAXON_ID%TYPE,
		NODE_RANK	IN SG_TAXON.NODE_RANK%TYPE,
		GENETIC_CODE	IN SG_TAXON.GENETIC_CODE%TYPE,
		MITO_GENETIC_CODE	IN SG_TAXON.MITO_GENETIC_CODE%TYPE,
		LEFT_VALUE	IN SG_TAXON.LEFT_VALUE%TYPE,
		RIGHT_VALUE	IN SG_TAXON.RIGHT_VALUE%TYPE,
		TAX_OID	IN SG_TAXON.TAX_OID%TYPE)
RETURN SG_TAXON.OID%TYPE 
IS
	pk	SG_TAXON.OID%TYPE;
BEGIN
	-- pre-generate the primary key value
	SELECT SG_Sequence.nextval INTO pk FROM DUAL;
	-- insert the record
	INSERT INTO SG_TAXON (
		OID,
		NCBI_TAXON_ID,
		NODE_RANK,
		GENETIC_CODE,
		MITO_GENETIC_CODE,
		LEFT_VALUE,
		RIGHT_VALUE,
		TAX_OID)
	VALUES (pk,
		NCBI_TAXON_ID,
		NODE_RANK,
		GENETIC_CODE,
		MITO_GENETIC_CODE,
		LEFT_VALUE,
		RIGHT_VALUE,
		TAX_OID)
	;
	-- return the new pk value
	RETURN pk;
END;

PROCEDURE do_update(
		Tax_OID	IN SG_TAXON.OID%TYPE,
		Tax_NCBI_TAXON_ID	IN SG_TAXON.NCBI_TAXON_ID%TYPE,
		Tax_NODE_RANK	IN SG_TAXON.NODE_RANK%TYPE,
		Tax_GENETIC_CODE	IN SG_TAXON.GENETIC_CODE%TYPE,
		Tax_MITO_GENETIC_CODE	IN SG_TAXON.MITO_GENETIC_CODE%TYPE,
		Tax_LEFT_VALUE	IN SG_TAXON.LEFT_VALUE%TYPE,
		Tax_RIGHT_VALUE	IN SG_TAXON.RIGHT_VALUE%TYPE,
		Tax_TAX_OID	IN SG_TAXON.TAX_OID%TYPE)
IS
BEGIN
	-- update the record (and leave attributes passed as NULL untouched)
	UPDATE SG_TAXON t
	SET
		NCBI_TAXON_ID = NVL(Tax_NCBI_TAXON_ID, NCBI_TAXON_ID),
		NODE_RANK = NVL(Tax_NODE_RANK, NODE_RANK),
		GENETIC_CODE = NVL(Tax_GENETIC_CODE, GENETIC_CODE),
		MITO_GENETIC_CODE = NVL(Tax_MITO_GENETIC_CODE, MITO_GENETIC_CODE),
		LEFT_VALUE = NVL(Tax_LEFT_VALUE, LEFT_VALUE),
		RIGHT_VALUE = NVL(Tax_RIGHT_VALUE, RIGHT_VALUE),
		TAX_OID = NVL(Tax_TAX_OID, TAX_OID)
	WHERE OID = Tax_OID
	;
END;

END Tax;
/

