-- -*-Sql-*- mode (to keep my emacs happy)
--
-- API Package Body for Seqfeature.
--
-- 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 Fea IS

Fea_cached SG_SEQFEATURE.OID%TYPE DEFAULT NULL;
cache_key VARCHAR2(1024) DEFAULT NULL;

CURSOR Fea_c (
		Fea_ENT_OID	IN SG_SEQFEATURE.ENT_OID%TYPE,
		Fea_TYPE_TRM_OID	IN SG_SEQFEATURE.TYPE_TRM_OID%TYPE,
		Fea_SOURCE_TRM_OID	IN SG_SEQFEATURE.SOURCE_TRM_OID%TYPE,
		Fea_RANK	IN SG_SEQFEATURE.RANK%TYPE)
RETURN SG_SEQFEATURE%ROWTYPE IS
	SELECT t.* FROM SG_SEQFEATURE t
	WHERE
		t.ENT_OID = Fea_ENT_OID
	AND	t.TYPE_TRM_OID = Fea_TYPE_TRM_OID
	AND	t.SOURCE_TRM_OID = Fea_SOURCE_TRM_OID
	AND	t.RANK = Fea_RANK
	;

FUNCTION get_oid(
		Fea_OID	IN SG_SEQFEATURE.OID%TYPE DEFAULT NULL,
		Fea_RANK	IN SG_SEQFEATURE.RANK%TYPE,
		ENT_OID	IN SG_SEQFEATURE.ENT_OID%TYPE,
		TYPE_TRM_OID	IN SG_SEQFEATURE.TYPE_TRM_OID%TYPE,
		SOURCE_TRM_OID	IN SG_SEQFEATURE.SOURCE_TRM_OID%TYPE,
		Fea_DISPLAY_NAME	IN SG_SEQFEATURE.DISPLAY_NAME%TYPE DEFAULT NULL,
		Type_Trm_NAME	IN SG_TERM.NAME%TYPE DEFAULT NULL,
		Type_ONT_OID	IN SG_TERM.ONT_OID%TYPE DEFAULT NULL,
		Type_ONT_NAME	IN SG_ONTOLOGY.NAME%TYPE DEFAULT NULL,
		Type_Trm_IDENTIFIER	IN SG_TERM.IDENTIFIER%TYPE DEFAULT NULL,
		Source_Trm_NAME	IN SG_TERM.NAME%TYPE DEFAULT NULL,
		Source_ONT_OID	IN SG_TERM.ONT_OID%TYPE DEFAULT NULL,
		Source_ONT_NAME	IN SG_ONTOLOGY.NAME%TYPE DEFAULT NULL,
		Source_Trm_IDENTIFIER	IN SG_TERM.IDENTIFIER%TYPE DEFAULT NULL,
		Ent_IDENTIFIER	IN SG_BIOENTRY.IDENTIFIER%TYPE DEFAULT NULL,
		Ent_ACCESSION	IN SG_BIOENTRY.ACCESSION%TYPE DEFAULT NULL,
		Ent_DB_OID	IN SG_BIOENTRY.DB_OID%TYPE DEFAULT NULL,
		Ent_VERSION	IN SG_BIOENTRY.VERSION%TYPE DEFAULT NULL,
		do_DML		IN NUMBER DEFAULT BSStd.DML_NO)
RETURN SG_SEQFEATURE.OID%TYPE
IS
	pk	SG_SEQFEATURE.OID%TYPE DEFAULT NULL;
	Fea_row Fea_c%ROWTYPE;
	SOURCE_TRM_OID_	SG_TERM.OID%TYPE DEFAULT SOURCE_TRM_OID;
	TYPE_TRM_OID_	SG_TERM.OID%TYPE DEFAULT TYPE_TRM_OID;
	ENT_OID_	SG_BIOENTRY.OID%TYPE DEFAULT ENT_OID;
	key_str	VARCHAR2(1024) DEFAULT Source_TRM_OID || '|' || Type_TRM_OID || '|' || Ent_OID || '|' || Fea_RANK || '|' || Source_Trm_NAME || '|' || Source_ONT_OID || '|' || Source_ONT_NAME || '|' || Source_Trm_IDENTIFIER || '|' || Ent_ACCESSION || '|' || Ent_VERSION || '|' || Ent_DB_OID || '|' || Ent_IDENTIFIER || '|' || Type_Trm_NAME || '|' || Type_ONT_OID || '|' || Type_ONT_NAME || '|' || Type_Trm_IDENTIFIER;
BEGIN
	-- initialize
	IF (do_DML > BSStd.DML_NO) THEN
		pk := Fea_OID;
	END IF;
	-- look up
	IF pk IS NULL THEN
		IF (key_str = cache_key) THEN
			pk := Fea_cached;
		ELSE
			-- reset cache
			cache_key := NULL;
			Fea_cached := NULL;
                	-- look up SG_TERM for feature source
                	IF (SOURCE_TRM_OID_ IS NULL) THEN
                		SOURCE_TRM_OID_ := Trm.get_oid(
                			Trm_NAME => Source_Trm_NAME,
                			ONT_OID => Source_ONT_OID,
                			ONT_NAME => Source_ONT_NAME,
                			Trm_IDENTIFIER => Source_Trm_IDENTIFIER);
                	END IF;
                	-- look up SG_BIOENTRY
                	IF (ENT_OID_ IS NULL) THEN
                		ENT_OID_ := Ent.get_oid(
                			Ent_IDENTIFIER => Ent_IDENTIFIER,
                			Ent_ACCESSION => Ent_ACCESSION,
                			DB_OID => Ent_DB_OID,
                			Ent_VERSION => Ent_VERSION);
                	END IF;
                	-- look up SG_TERM feature type 
                	IF (TYPE_TRM_OID_ IS NULL) THEN
                		TYPE_TRM_OID_ := Trm.get_oid(
                			Trm_NAME => Type_Trm_NAME,
                			ONT_OID => Type_ONT_OID,
                			ONT_NAME => Type_ONT_NAME,
                			Trm_IDENTIFIER => Type_Trm_IDENTIFIER);
                	END IF;
			-- do the look up
			FOR Fea_row IN Fea_c(ENT_OID_, TYPE_TRM_OID_, SOURCE_TRM_OID_, Fea_RANK) LOOP
		        	pk := Fea_row.OID;
				-- cache result
			    	cache_key := key_str;
			    	Fea_cached := pk;
			END LOOP;
		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 SG_TERM for feature source successful?
		IF (SOURCE_TRM_OID_ IS NULL) THEN
			raise_application_error(-20101,
				'failed to look up Trm <' || Source_Trm_NAME || '|' || Source_ONT_OID || '|' || Source_ONT_NAME || '|' || Source_Trm_IDENTIFIER || '>');
		END IF;
		-- look up SG_BIOENTRY successful?
		IF (ENT_OID_ IS NULL) THEN
			raise_application_error(-20101,
				'failed to look up Ent <' || Ent_ACCESSION || '|' || Ent_VERSION || '|' || Ent_DB_OID || '|' || Ent_IDENTIFIER || '>');
		END IF;
		-- look up SG_TERM feature type successful?
		IF (TYPE_TRM_OID_ IS NULL) THEN
			raise_application_error(-20101,
				'failed to look up Trm <' || Type_Trm_NAME || '|' || Type_ONT_OID || '|' || Type_ONT_NAME || '|' || Type_Trm_IDENTIFIER || '>');
		END IF;
	    	-- insert the record and obtain the primary key
	    	pk := do_insert(
		        RANK => Fea_RANK,
			ENT_OID => ENT_OID_,
			TYPE_TRM_OID => TYPE_TRM_OID_,
			SOURCE_TRM_OID => SOURCE_TRM_OID_,
			DISPLAY_NAME => Fea_DISPLAY_NAME);
	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(
			Fea_OID	=> pk,
		        Fea_RANK => Fea_RANK,
			Fea_ENT_OID => ENT_OID_,
			Fea_TYPE_TRM_OID => TYPE_TRM_OID_,
			Fea_SOURCE_TRM_OID => SOURCE_TRM_OID_,
			Fea_DISPLAY_NAME => Fea_DISPLAY_NAME);
	END IF;
	-- return the primary key
	RETURN pk;
END;

FUNCTION do_insert(
		RANK	IN SG_SEQFEATURE.RANK%TYPE,
		ENT_OID	IN SG_SEQFEATURE.ENT_OID%TYPE,
		TYPE_TRM_OID	IN SG_SEQFEATURE.TYPE_TRM_OID%TYPE,
		SOURCE_TRM_OID	IN SG_SEQFEATURE.SOURCE_TRM_OID%TYPE,
		DISPLAY_NAME	IN SG_SEQFEATURE.DISPLAY_NAME%TYPE)
RETURN SG_SEQFEATURE.OID%TYPE 
IS
	pk	SG_SEQFEATURE.OID%TYPE;
BEGIN
	-- pre-generate the primary key value
	SELECT SG_Sequence.nextval INTO pk FROM DUAL;
	-- insert the record
	INSERT INTO SG_SEQFEATURE (
		OID,
		RANK,
		ENT_OID,
		TYPE_TRM_OID,
		SOURCE_TRM_OID,
		DISPLAY_NAME)
	VALUES (pk,
		RANK,
		ENT_OID,
		TYPE_TRM_OID,
		SOURCE_TRM_OID,
		DISPLAY_NAME)
	;
	-- return the new pk value
	RETURN pk;
END;

PROCEDURE do_update(
		Fea_OID	IN SG_SEQFEATURE.OID%TYPE,
		Fea_RANK	IN SG_SEQFEATURE.RANK%TYPE,
		Fea_ENT_OID	IN SG_SEQFEATURE.ENT_OID%TYPE,
		Fea_TYPE_TRM_OID	IN SG_SEQFEATURE.TYPE_TRM_OID%TYPE,
		Fea_SOURCE_TRM_OID	IN SG_SEQFEATURE.SOURCE_TRM_OID%TYPE,
		Fea_DISPLAY_NAME	IN SG_SEQFEATURE.DISPLAY_NAME%TYPE)
IS
BEGIN
	-- update the record (and leave attributes passed as NULL untouched)
	UPDATE SG_SEQFEATURE
	SET
		RANK = NVL(Fea_RANK, RANK),
		ENT_OID = NVL(Fea_ENT_OID, ENT_OID),
		TYPE_TRM_OID = NVL(Fea_TYPE_TRM_OID, TYPE_TRM_OID),
		SOURCE_TRM_OID = NVL(Fea_SOURCE_TRM_OID, SOURCE_TRM_OID),
		DISPLAY_NAME = NVL(Fea_DISPLAY_NAME, DISPLAY_NAME)
	WHERE OID = Fea_OID
	;
END;

END Fea;
/

