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

Loc_cached	SG_LOCATION.OID%TYPE DEFAULT NULL;
cache_key		VARCHAR2(1024) DEFAULT NULL;

CURSOR Loc_c (
		Loc_FEA_OID	IN SG_LOCATION.FEA_OID%TYPE,
		Loc_RANK	IN SG_LOCATION.RANK%TYPE)
RETURN SG_LOCATION%ROWTYPE IS
	SELECT t.* FROM SG_LOCATION t
	WHERE
		t.FEA_OID = Loc_FEA_OID
	AND	t.RANK = Loc_RANK
	;

FUNCTION get_oid(
		Loc_OID	IN SG_LOCATION.OID%TYPE DEFAULT NULL,
		Loc_START_POS	IN SG_LOCATION.START_POS%TYPE DEFAULT NULL,
		Loc_END_POS	IN SG_LOCATION.END_POS%TYPE DEFAULT NULL,
		Loc_STRAND	IN SG_LOCATION.STRAND%TYPE DEFAULT NULL,
		Loc_RANK	IN SG_LOCATION.RANK%TYPE,
		FEA_OID	IN SG_LOCATION.FEA_OID%TYPE,
		DBX_OID	IN SG_LOCATION.DBX_OID%TYPE DEFAULT NULL,
		TRM_OID	IN SG_LOCATION.TRM_OID%TYPE DEFAULT NULL,
		Dbx_ACCESSION	IN SG_DBXREF.ACCESSION%TYPE DEFAULT NULL,
		Dbx_DBNAME	IN SG_DBXREF.DBNAME%TYPE DEFAULT NULL,
		Dbx_VERSION	IN SG_DBXREF.VERSION%TYPE DEFAULT NULL,
		Fea_ENT_OID	IN SG_SEQFEATURE.ENT_OID%TYPE DEFAULT NULL,
		Fea_TYPE_TRM_OID	IN SG_SEQFEATURE.TYPE_TRM_OID%TYPE DEFAULT NULL,
		Fea_SOURCE_TRM_OID	IN SG_SEQFEATURE.SOURCE_TRM_OID%TYPE DEFAULT NULL,
		Fea_RANK	IN SG_SEQFEATURE.RANK%TYPE DEFAULT NULL,
		Trm_NAME	IN SG_TERM.NAME%TYPE DEFAULT NULL,
		ONT_OID	IN SG_TERM.ONT_OID%TYPE DEFAULT NULL,
		ONT_NAME	IN SG_ONTOLOGY.NAME%TYPE DEFAULT NULL,
		Trm_IDENTIFIER	IN SG_TERM.IDENTIFIER%TYPE DEFAULT NULL,
		do_DML		IN NUMBER DEFAULT BSStd.DML_NO)
RETURN SG_LOCATION.OID%TYPE
IS
	pk	SG_LOCATION.OID%TYPE DEFAULT NULL;
	Loc_row Loc_c%ROWTYPE;
	DBX_OID_	SG_DBXREF.OID%TYPE DEFAULT DBX_OID;
	FEA_OID_	SG_SEQFEATURE.OID%TYPE DEFAULT FEA_OID;
	TRM_OID_	SG_TERM.OID%TYPE DEFAULT TRM_OID;
	key_str	VARCHAR2(1024) DEFAULT FEA_OID || '|' || Loc_RANK || '|' || Fea_ENT_OID || '|' || Fea_TYPE_TRM_OID || '|' || Fea_SOURCE_TRM_OID || '|' || Fea_RANK;
BEGIN
	-- initialize
	IF (do_DML > BSStd.DML_NO) THEN
		pk := Loc_OID;
	END IF;
	-- look up
	IF pk IS NULL THEN
		IF (key_str = cache_key) THEN
			pk := Loc_cached;
		ELSE
			-- reset cache
			cache_key := NULL;
			Loc_cached := NULL;
                	-- look up SG_SEQFEATURE
                	IF (FEA_OID_ IS NULL) THEN
                		FEA_OID_ := Fea.get_oid(
                			ENT_OID => Fea_ENT_OID,
                			TYPE_TRM_OID => Fea_TYPE_TRM_OID,
                			SOURCE_TRM_OID => Fea_SOURCE_TRM_OID,
                			Fea_RANK => Fea_RANK);
                	END IF;
			-- do the look up
			FOR Loc_row IN Loc_c(FEA_OID_, Loc_RANK) LOOP
		        	pk := Loc_row.OID;
				-- cache result
			    	cache_key := key_str;
			    	Loc_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_DBXREF (this is optional)
		IF (DBX_OID_ IS NULL) AND (Dbx_ACCESSION IS NOT NULL) THEN
			DBX_OID_ := Dbx.get_oid(
				Dbx_ACCESSION => Dbx_ACCESSION,
				Dbx_DBNAME => Dbx_DBNAME,
				Dbx_VERSION => Dbx_VERSION);
			IF (DBX_OID_ IS NULL) THEN
			   raise_application_error(-20101,
				'failed to look up Dbx <' || Dbx_ACCESSION || '|' || Dbx_DBNAME || '|' || Dbx_VERSION || '>');
			END IF;
		END IF;
		-- look up SG_SEQFEATURE successful?
		IF (FEA_OID_ IS NULL) THEN
			raise_application_error(-20101,
				'failed to look up Fea <' || Fea_ENT_OID || '|' || Fea_TYPE_TRM_OID || '|' || Fea_SOURCE_TRM_OID || '|' || Fea_RANK || '>');
		END IF;
		-- look up SG_TERM (this is optional)
		IF (TRM_OID_ IS NULL) AND (Trm_Name IS NOT NULL) THEN
			TRM_OID_ := Trm.get_oid(
				Trm_NAME => Trm_NAME,
				ONT_OID => ONT_OID,
				ONT_NAME => ONT_NAME,
				Trm_IDENTIFIER => Trm_IDENTIFIER);
			IF (TRM_OID_ IS NULL) THEN
			   raise_application_error(-20101,
				'failed to look up Trm <' || Trm_NAME || '|' || ONT_OID || '|' || ONT_NAME || '|' || Trm_IDENTIFIER || '>');
			END IF;
		END IF;
	    	-- insert the record and obtain the primary key
	    	pk := do_insert(
		        START_POS => Loc_START_POS,
			END_POS => Loc_END_POS,
			STRAND => Loc_STRAND,
			RANK => Loc_RANK,
			FEA_OID => FEA_OID_,
			DBX_OID => DBX_OID_,
			TRM_OID => TRM_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(
			Loc_OID	=> pk,
		        Loc_START_POS => Loc_START_POS,
			Loc_END_POS => Loc_END_POS,
			Loc_STRAND => Loc_STRAND,
			Loc_RANK => Loc_RANK,
			Loc_FEA_OID => FEA_OID_,
			Loc_DBX_OID => DBX_OID_,
			Loc_TRM_OID => TRM_OID_);
	END IF;
	-- return the primary key
	RETURN pk;
END;

FUNCTION do_insert(
		START_POS	IN SG_LOCATION.START_POS%TYPE,
		END_POS	IN SG_LOCATION.END_POS%TYPE,
		STRAND	IN SG_LOCATION.STRAND%TYPE,
		RANK	IN SG_LOCATION.RANK%TYPE,
		FEA_OID	IN SG_LOCATION.FEA_OID%TYPE,
		DBX_OID	IN SG_LOCATION.DBX_OID%TYPE,
		TRM_OID	IN SG_LOCATION.TRM_OID%TYPE)
RETURN SG_LOCATION.OID%TYPE 
IS
	pk	SG_LOCATION.OID%TYPE;
BEGIN
	-- pre-generate the primary key value
	SELECT SG_Sequence_Fea.nextval INTO pk FROM DUAL;
	-- insert the record
	INSERT INTO SG_LOCATION (
		OID,
		START_POS,
		END_POS,
		STRAND,
		RANK,
		FEA_OID,
		DBX_OID,
		TRM_OID)
	VALUES (pk,
		START_POS,
		END_POS,
		STRAND,
		RANK,
		FEA_OID,
		DBX_OID,
		TRM_OID)
	;
	-- return the new pk value
	RETURN pk;
END;

PROCEDURE do_update(
		Loc_OID	IN SG_LOCATION.OID%TYPE,
		Loc_START_POS	IN SG_LOCATION.START_POS%TYPE,
		Loc_END_POS	IN SG_LOCATION.END_POS%TYPE,
		Loc_STRAND	IN SG_LOCATION.STRAND%TYPE,
		Loc_RANK	IN SG_LOCATION.RANK%TYPE,
		Loc_FEA_OID	IN SG_LOCATION.FEA_OID%TYPE,
		Loc_DBX_OID	IN SG_LOCATION.DBX_OID%TYPE,
		Loc_TRM_OID	IN SG_LOCATION.TRM_OID%TYPE)
IS
BEGIN
	-- update the record (and leave attributes passed as NULL untouched)
	UPDATE SG_LOCATION
	SET
		START_POS = NVL(Loc_START_POS, START_POS),
		END_POS = NVL(Loc_END_POS, END_POS),
		STRAND = NVL(Loc_STRAND, STRAND),
		RANK = NVL(Loc_RANK, RANK),
		FEA_OID = NVL(Loc_FEA_OID, FEA_OID),
		DBX_OID = NVL(Loc_DBX_OID, DBX_OID),
		TRM_OID = NVL(Loc_TRM_OID, TRM_OID)
	WHERE OID = Loc_OID
	;
END;

END Loc;
/

