Rem Copyright (c) 2008, 2010, Oracle and/or its affiliates. 
Rem All rights reserved. 
Rem
Rem    NAME
Rem      ime111.sql
Rem
Rem    DESCRIPTION
Rem      runs as SYS
Rem      
Rem      Internal downgrade script for Oracle Multimedia to 11.1.
Rem
Rem    NOTES
Rem      This script deletes all objects and types that have been added 
Rem       between 11.1 and 11.2. After this script is run, the imrelod.sql 
Rem       script is run to reload 11.1 Oracle Multimedia in the downgraded 
Rem       database.
Rem
Rem      The first downgrade script must drop all Oracle Multimedia java 
Rem       classes to ensure new java classes are not left invalid in the
Rem       downgraded database.
Rem

whenever sqlerror exit;

REM 
REM Make sure Oracle Multimedia schemas exist.
REM
REM Note - it is forbidden to exit in a downgrade script.  
REM However, it is an assumed impossible condition that we exist in the 
REM registry (which is the only way this script should be called) and our
REM schemas don't exist.  Therefore, we will exit here if our schemas don't
REM exist so we can figure out how we got in this situation.
REM 

@@imchksch.sql

whenever sqlerror continue;

REM
REM IMPORTANT... Dependencies must be checked in top level downgrade script.
REM
REM Make sure Oracle Multimedia dependencies are valid (and log errors and
REM continue if not).  Check Oracle Multimedia validity.
REM
@@imchkdep.sql 1 DOWNGRADING DOWNGRADED

alter session set current_schema="ORDSYS";
execute sys.dbms_registry.downgrading('ORDIM', 'Oracle Multimedia');

-- drop watermark methods
begin
  execute immediate 'ALTER TYPE ORDSYS.ORDImage
    DROP MEMBER PROCEDURE applyWatermark(SELF    IN OUT NOCOPY ORDSYS.ORDImage,
                               added_text IN    VARCHAR2,
                               dest    IN OUT NOCOPY ORDSYS.ORDImage,
                               logging OUT VARCHAR2,
                               watermark_properties IN ORDSYS.ORD_STR_LIST default null)
        CASCADE';
end;
/

begin
      execute immediate 'ALTER TYPE ORDSYS.ORDImage
        DROP MEMBER PROCEDURE applyWatermark(SELF    IN OUT NOCOPY ORDSYS.ORDImage,
                               added_image IN OUT NOCOPY ORDSYS.ORDImage,
                               dest    IN OUT NOCOPY ORDSYS.ORDImage,
                               logging OUT VARCHAR2,
                               watermark_properties IN ORDSYS.ORD_STR_LIST default null)
        CASCADE';
end;
/

begin
      execute immediate 'ALTER TYPE ORDSYS.ORDImage
        DROP STATIC PROCEDURE applyWatermark(imageBlob     IN BLOB,
                               added_text       IN VARCHAR2,
                               dest          IN OUT NOCOPY BLOB,
                               logging OUT VARCHAR2,
                               watermark_properties IN ordsys.ord_str_list default null)
        CASCADE';
end;
/

begin
      execute immediate 'ALTER TYPE ORDSYS.ORDImage
        DROP STATIC PROCEDURE applyWatermark(imageBlob     IN BLOB,
                               added_image      IN BLOB,
                               dest          IN OUT NOCOPY BLOB,
                               logging OUT VARCHAR2,
                               watermark_properties IN ordsys.ord_str_list default null)
        CASCADE';
end;
/

begin
      execute immediate 'ALTER TYPE ORDSYS.ORDImage
        DROP STATIC PROCEDURE applyWatermark(imageBfile    IN OUT NOCOPY BFILE,
                               added_text       IN VARCHAR2,
                               dest          IN OUT NOCOPY BLOB,
                               logging OUT VARCHAR2,
                               watermark_properties IN ordsys.ord_str_list default null)
        CASCADE';
end;
/

begin
      execute immediate 'ALTER TYPE ORDSYS.ORDImage
        DROP STATIC PROCEDURE applyWatermark(imageBfile    IN OUT NOCOPY BFILE,
                               added_image      IN OUT NOCOPY BFILE,
                               dest          IN OUT NOCOPY BLOB,
                               logging OUT VARCHAR2,
                               watermark_properties IN ordsys.ord_str_list default null)
        CASCADE';
end;
/

--
-- Drop the user-defined object constructors
--
begin
    execute immediate 'ALTER TYPE ORDSYS.ORDImage 
      DROP CONSTRUCTOR FUNCTION ORDImage( 
          SELF IN OUT NOCOPY ORDSYS.ORDImage, 
          data  IN BLOB,
          setProperties IN INTEGER DEFAULT 0)
          RETURN SELF AS RESULT CASCADE';
end;
/

begin
    execute immediate 'ALTER TYPE ORDSYS.ORDImage
      DROP CONSTRUCTOR FUNCTION ORDImage( 
          SELF IN OUT NOCOPY ORDSYS.ORDImage, 
          source_type       IN VARCHAR2 DEFAULT ''LOCAL'',
          source_location   IN VARCHAR2 DEFAULT NULL,
          source_name       IN VARCHAR2 DEFAULT NULL,
          setProperties  IN INTEGER DEFAULT 0)
          RETURN SELF AS RESULT CASCADE';
end;
/
begin
    execute immediate 'ALTER TYPE ORDSYS.ORDAudio 
      DROP CONSTRUCTOR FUNCTION ORDAudio( 
          SELF IN OUT NOCOPY ORDSYS.ORDAudio, 
          data  IN BLOB,
          setProperties IN INTEGER DEFAULT 0)
          RETURN SELF AS RESULT CASCADE';
end;
/

begin
    execute immediate 'ALTER TYPE ORDSYS.ORDAudio
      DROP CONSTRUCTOR FUNCTION ORDAudio( 
          SELF IN OUT NOCOPY ORDSYS.ORDAudio, 
          source_type       IN VARCHAR2 DEFAULT ''LOCAL'',
          source_location   IN VARCHAR2 DEFAULT NULL,
          source_name       IN VARCHAR2 DEFAULT NULL,
          setProperties  IN INTEGER DEFAULT 0)
          RETURN SELF AS RESULT CASCADE';
end;
/

begin
    execute immediate 'ALTER TYPE ORDSYS.ORDVideo 
      DROP CONSTRUCTOR FUNCTION ORDVideo( 
          SELF IN OUT NOCOPY ORDSYS.ORDVideo, 
          data  IN BLOB,
          setProperties IN INTEGER DEFAULT 0)
          RETURN SELF AS RESULT CASCADE';
end;
/
begin
    execute immediate 'ALTER TYPE ORDSYS.ORDVideo
      DROP CONSTRUCTOR FUNCTION ORDVideo( 
          SELF IN OUT NOCOPY ORDSYS.ORDVideo, 
          source_type       IN VARCHAR2 DEFAULT ''LOCAL'',
          source_location   IN VARCHAR2 DEFAULT NULL,
          source_name       IN VARCHAR2 DEFAULT NULL,
          setProperties  IN INTEGER DEFAULT 0)
          RETURN SELF AS RESULT CASCADE';
end;
/

begin
    execute immediate 'ALTER TYPE ORDSYS.ORDDoc 
      DROP CONSTRUCTOR FUNCTION ORDDoc( 
          SELF IN OUT NOCOPY ORDSYS.ORDDoc, 
          data  IN BLOB,
          setProperties IN INTEGER DEFAULT 0)
          RETURN SELF AS RESULT CASCADE';
end;
/

begin
    execute immediate 'ALTER TYPE ORDSYS.ORDDoc
      DROP CONSTRUCTOR FUNCTION ORDDoc( 
          SELF IN OUT NOCOPY ORDSYS.ORDDoc, 
          source_type       IN VARCHAR2 DEFAULT ''LOCAL'',
          source_location   IN VARCHAR2 DEFAULT NULL,
          source_name       IN VARCHAR2 DEFAULT NULL,
          setProperties  IN INTEGER DEFAULT 0)
          RETURN SELF AS RESULT CASCADE';
end;
/

-- need to reload ordimage package spec and body 
-- to make following downgrade work
-- because in 11.2, it uses ORD_STR_LIST, which was defined in 11.1
-- if we don't reload package here to remove the methods which use
-- ORD_STR_LIST type, 10.2 downgrade will fail.
create or replace package ordsys.ORDImg_Pkg
  authid current_user
AS
  FUNCTION ordimgB_setProperties(
    content       IN     BLOB,
    height        OUT BINARY_INTEGER,
    width         OUT BINARY_INTEGER,
    contentLength OUT INTEGER,
    fileFormat    OUT VARCHAR2,
    contentFormat       OUT VARCHAR2,
    compressionFormat   OUT VARCHAR2,
    mimeType   OUT VARCHAR2) return BINARY_INTEGER;

  FUNCTION ordimg_headerlessSetProperties(
    description    IN  VARCHAR2,
    height         OUT BINARY_INTEGER,
    width          OUT BINARY_INTEGER,
    fileFormat     OUT VARCHAR2,
    contentFormat       OUT VARCHAR2,
    compressionFormat   OUT VARCHAR2,
    mimeType       OUT VARCHAR2)
  return BINARY_INTEGER;

  FUNCTION ordimgB_process(
    command        IN     VARCHAR2,
    headerlessInfo IN     VARCHAR2,
    src            IN     BLOB,
    dest           IN OUT NOCOPY BLOB)
  return BINARY_INTEGER;

  FUNCTION ordimgF_setProperties(
    content        IN     BFILE,
    height         OUT BINARY_INTEGER,
    width          OUT BINARY_INTEGER,
    contentLength  OUT INTEGER,
    fileFormat     OUT VARCHAR2,
    contentFormat       OUT VARCHAR2,
    compressionFormat   OUT VARCHAR2,
    mimeType            OUT VARCHAR2)
  return BINARY_INTEGER;

  FUNCTION ordimgF_processCopy( 
    command        IN     VARCHAR2,
    headerlessInfo IN     VARCHAR2,
    src            IN     BFILE, 
    dest           IN OUT NOCOPY BLOB)
  return BINARY_INTEGER;

  PROCEDURE buildXMLAttributes(
    retAttributes     IN OUT NOCOPY CLOB,
    mimeType          IN VARCHAR2,
    width             IN INTEGER,
    height            IN INTEGER,
    fileFormat        IN VARCHAR2,
    contentFormat     IN VARCHAR2,
    compressionFormat IN VARCHAR2,
    contentLength     IN INTEGER,
    version           IN INTEGER);

  PROCEDURE copy(
    S    IN OUT NOCOPY ORDImage, 
    dest IN OUT NOCOPY ORDImage);

  PROCEDURE process(
    S       IN OUT NOCOPY ORDImage,
    command IN            VARCHAR2);

  PROCEDURE processCopy(
    S       IN OUT NOCOPY ORDImage,
    command IN            VARCHAR2,
    dest    IN OUT NOCOPY ORDImage);

  PROCEDURE setProperties(
    S       IN OUT NOCOPY ORDImage);
  
  PROCEDURE setProperties(
    S           IN OUT NOCOPY ORDImage,
    description IN            VARCHAR2);
  
  FUNCTION checkProperties(
    S IN ORDImage)
  RETURN BOOLEAN;

  PROCEDURE import(
    S              IN OUT NOCOPY ORDImage,
    ctx            IN OUT        RAW);

  PROCEDURE importFrom(
    S               IN OUT NOCOPY ORDImage,
    ctx             IN OUT        RAW,
    source_type     IN            VARCHAR2,
    source_location IN            VARCHAR2,
    source_name     IN            VARCHAR2);

  PROCEDURE getHeaderlessInfo(
          fileFormat        IN  VARCHAR2,
          height            IN  NUMBER,
          width             IN  NUMBER,
          compressionFormat IN  VARCHAR2,
          contentFormat     IN  VARCHAR2,
          info              OUT VARCHAR2);

  PROCEDURE copyContent(source IN OUT BFILE, dest IN OUT NOCOPY BLOB);

  PROCEDURE copyContent(source IN OUT NOCOPY BLOB, dest IN OUT NOCOPY BLOB);

  FUNCTION getImageProperties(
    content       IN     BLOB,
    height        OUT    NUMBER,
    width         OUT    NUMBER,
    contentLength OUT    NUMBER,
    fileFormat    OUT VARCHAR2,
    contentFormat       OUT VARCHAR2,
    compressionFormat   OUT VARCHAR2,
    mimeType            OUT VARCHAR2,
    addnlErrorText      OUT VARCHAR2)
  return    NUMBER;

  FUNCTION imageConvert(
    command        IN     VARCHAR2,
    headerlessInfo IN     VARCHAR2,
    src            IN     BLOB,
    dest           IN OUT NOCOPY BLOB,
    addnlErrorText    OUT VARCHAR2)
  return    NUMBER;

  FUNCTION largeImageConvert(
    command        IN     VARCHAR2,
    headerlessInfo IN     VARCHAR2,
    src            IN     BLOB,
    dest           IN OUT NOCOPY BLOB,
    addnlErrorText    OUT VARCHAR2)
  return    NUMBER;

  FUNCTION getImageProperties(
    content        IN     BFILE,
    height         OUT    NUMBER,
    width          OUT    NUMBER,
    contentLength  OUT    NUMBER,
    fileFormat     OUT VARCHAR2,
    contentFormat       OUT VARCHAR2,
    compressionFormat   OUT VARCHAR2,
    mimeType            OUT VARCHAR2,
    addnlErrorText      OUT VARCHAR2)
  return    NUMBER;

  FUNCTION imageConvert(
    command        IN     VARCHAR2,
    headerlessInfo IN     VARCHAR2,
    src            IN     BFILE,
    dest           IN OUT NOCOPY BLOB,
    addnlErrorText    OUT VARCHAR2)
  return    NUMBER;

  FUNCTION largeImageConvert(
    command        IN     VARCHAR2,
    headerlessInfo IN     VARCHAR2,
    src            IN     BFILE,
    dest           IN OUT NOCOPY BLOB,
    addnlErrorText    OUT VARCHAR2)
  return    NUMBER;

  -- METADATA RELATED METHODS
  PROCEDURE checkGetMetaArgs( metaType IN VARCHAR2 );
  PROCEDURE checkPutMetaArgs( xmlData  IN SYS.XMLTYPE,
                              metaType IN VARCHAR2,
                              encType  IN VARCHAR2 );
  FUNCTION buildXMLDoc(ordImg IN ORDImage) RETURN SYS.XMLType;
  FUNCTION packMetadataVector( xml1 IN SYS.XMLTYPE,
                               xml2 IN SYS.XMLTYPE,
                               xml3 IN SYS.XMLTYPE,
                               xml4 IN SYS.XMLTYPE ) 
  RETURN SYS.XMLSEQUENCETYPE;

  -- Java wrapper function
  FUNCTION getMetadata(imageBlob        IN BLOB,
                       metadataType     IN VARCHAR2,
                       meta1           OUT SYS.XMLTYPE,
                       meta2           OUT SYS.XMLTYPE,
                       meta3           OUT SYS.XMLTYPE,
                       errorText       OUT VARCHAR2)
  RETURN NUMBER;

  -- Java wrapper function
  FUNCTION getMetadata(imageBfile       IN BFILE,
                       metadataType     IN VARCHAR2,
                       meta1           OUT SYS.XMLTYPE,
                       meta2           OUT SYS.XMLTYPE,
                       meta3           OUT SYS.XMLTYPE,
                       errorText       OUT VARCHAR2)
  RETURN NUMBER;

  -- Java wrapper function
  FUNCTION  putMetadata(imageBlob       IN BLOB,
                        dest            IN OUT NOCOPY BLOB,
                        xmlData         IN SYS.XMLType,
                        metadataType    IN VARCHAR2,
                        encoding        IN VARCHAR2,
                        errorText      OUT VARCHAR2)
  RETURN NUMBER;

  -- Java wrapper function
  FUNCTION  putMetadata(imageBfile      IN BFILE,
                        dest            IN OUT NOCOPY BLOB,
                        xmlData         IN SYS.XMLType,
                        metadataType    IN VARCHAR2,
                        encoding        IN VARCHAR2,
                        errorText      OUT VARCHAR2)
  RETURN NUMBER;

  FUNCTION getDicomMetadata(
            optionString IN VARCHAR2,
            imgcontent   IN  BLOB,
            dcmXML       OUT XMLType,
            errStack     OUT VARCHAR2)
  RETURN   NUMBER;

  FUNCTION getDicomMetadata(
            optionString IN VARCHAR2,
            imgcontent   IN  BFILE,
            dcmXML       OUT XMLType,
            errStack     OUT VARCHAR2)
  RETURN   NUMBER;

  PROCEDURE setDebugLevel(debugLevel IN NUMBER);

END ORDImg_Pkg;
/
show errors;

create or replace type body ordsys.ORDImage as
  -- CONSTRUCTORS
  STATIC FUNCTION init RETURN ORDImage IS
  BEGIN
    RETURN ORDSYS.ORDImage(        -- ORDImage
        ORDSYS.ORDSource(          --   ORDSource
            empty_blob(),          --     localData
            NULL,                  --     srcType
            NULL,                  --     srcLocation
            NULL,                  --     srcName
            sysdate,               --     updateTime
            1),                    --     local flag
        NULL,            --   height
        NULL,            --   width
        NULL,            --   contentLength
        NULL,            --   fileFormat
        NULL,            --   contentFormat
        NULL,            --   compressionFormat
        NULL);            --   mimeType
  END init;

  STATIC FUNCTION init( srcType IN VARCHAR2,
			srcLocation IN VARCHAR2,
			srcName in VARCHAR2 ) RETURN ORDImage IS
  BEGIN
    RETURN ORDSYS.ORDImage(		-- ORDImage
		ORDSYS.ORDSource(	--   ORDSource
			empty_blob(),	--     localData
			srcType,	--     srcType
			srcLocation,	--     srcLocation
			srcName,	--     srcName
			sysdate,	--     updateTime
			0),		--     local flag
		NULL,			--   height
		NULL,			--   width
		NULL,			--   contentLength
		NULL,			--   fileFormat
		NULL,			--   contentFormat
		NULL,			--   compressionFormat
		NULL);			--   mimeType
  END init;

  -- IMAGE COPY METHOD
  MEMBER PROCEDURE copy(dest IN OUT NOCOPY ORDImage) IS
  BEGIN
      -- source must not be NULL
    IF (SELF.source IS NULL) THEN
       RAISE ORDImageExceptions.NULL_SOURCE;
    END IF;

    ORDSYS.ORDImg_Pkg.copy(SELF,dest);
  END copy;
	
  -- IMAGE PROCESS METHODS
  MEMBER PROCEDURE process(SELF    IN OUT NOCOPY ORDImage,
                           command IN            VARCHAR2) IS
  BEGIN
      -- source must not be NULL
    IF (SELF.source IS NULL) THEN
       RAISE ORDImageExceptions.NULL_SOURCE;
    END IF;

    ORDSYS.ORDImg_pkg.process(SELF,command);
  END process;

  MEMBER PROCEDURE processCopy(command IN            VARCHAR2, 
                               dest    IN OUT NOCOPY ORDImage) IS
  BEGIN
      -- source must not be NULL
    IF (SELF.source IS NULL) THEN
       RAISE ORDImageExceptions.NULL_SOURCE;
    END IF;

      -- source must not be NULL
    IF (dest.source IS NULL) THEN
       RAISE ORDImageExceptions.NULL_SOURCE;
    END IF;
    ORDSYS.ORDImg_pkg.processCopy(SELF,command,dest);
  END processCopy;

  -- IMAGE PROPERTY SET AND CHECK METHODS
  MEMBER PROCEDURE setProperties(SELF IN OUT NOCOPY ORDImage) IS
  BEGIN
      -- source must not be NULL
    IF (SELF.source IS NULL) THEN
       RAISE ORDImageExceptions.NULL_SOURCE;
    END IF;

    ORDSYS.ORDImg_pkg.setProperties(SELF);
  END setProperties;

  MEMBER PROCEDURE setProperties(SELF IN OUT NOCOPY ORDImage,
                                 description IN VARCHAR2) IS
  BEGIN
      -- source must not be NULL
    IF (SELF.source IS NULL) THEN
       RAISE ORDImageExceptions.NULL_SOURCE;
    END IF;
    ORDSYS.ORDImg_pkg.setProperties(SELF, description);
  END setProperties;

  MEMBER FUNCTION checkProperties RETURN BOOLEAN IS
  BEGIN
      -- source must not be NULL
    IF (SELF.source IS NULL) THEN
       RAISE ORDImageExceptions.NULL_SOURCE;
    END IF;
    RETURN (ORDSYS.ORDImg_Pkg.checkProperties(SELF));
  END checkProperties;

  -- IMAGE ATTRIBUTE ACCESSORS
  MEMBER FUNCTION getHeight RETURN INTEGER IS
  BEGIN
    RETURN SELF.height;
  END getHeight;

  MEMBER FUNCTION getWidth RETURN INTEGER IS
  BEGIN
    RETURN SELF.width;
  END getWidth;

  MEMBER FUNCTION getContentLength RETURN INTEGER IS
  BEGIN
    RETURN SELF.contentLength;
  END getContentLength;

  MEMBER FUNCTION getFileFormat RETURN VARCHAR2 IS
  BEGIN
    RETURN SELF.fileFormat;
  END getFileFormat;

  MEMBER FUNCTION getContentFormat RETURN VARCHAR2 IS
  BEGIN
    RETURN SELF.contentFormat;
  END getContentFormat;

  MEMBER FUNCTION getCompressionFormat RETURN VARCHAR2 IS
  BEGIN
    RETURN SELF.compressionFormat;
  END getCompressionFormat;

  -- METADATA RELATED METHODS
  MEMBER FUNCTION getMetadata(SELF         IN ORDImage,
                              metadataType IN VARCHAR2 DEFAULT 'ALL')
         RETURN SYS.XMLSEQUENCETYPE
  IS
    metaType      VARCHAR2(32)  := NULL;
    metaData     SYS.XMLSEQUENCETYPE := NULL;
    metaOrdImage SYS.XMLType    := NULL;
    metaIptc     SYS.XMLType    := NULL;
    metaExif     SYS.XMLType    := NULL;
    metaXmp      SYS.XMLType    := NULL;
    imageBfile   BFILE          := NULL;
    tempSrc      ORDSYS.ORDSOURCE := NULL;
    ctx          RAW(4)         := NULL;
    tempLob      BLOB           := NULL;
    tempMime     VARCHAR2(4000) := NULL;
    tempFormat   VARCHAR2(4000) := NULL;
    errorCode    NUMBER         := NULL;
    errorText    VARCHAR2(1024) := NULL;
    docCount     INTEGER        := 0;
  BEGIN
    -- to get results, source must be not null
    IF (SELF.source IS NULL) THEN
      RAISE ORDImageExceptions.NULL_SOURCE;
    END IF;

    -- check the arguments
    metaType := upper(substr(metadataType, 1,32));
    ORDSYS.ORDImg_Pkg.checkGetMetaArgs(metaType);

    -- get ordImage attibutes
    IF (metaType = 'ORDIMAGE') OR
       (metaType = 'ALL' )
    THEN
      metaOrdImage := ORDSYS.ORDImg_Pkg.buildXMLDoc(SELF);
    END IF;

    -- only non-foreign images go to Java
    IF (metaType <> 'ORDIMAGE') AND 
       ((SELF.fileFormat IS NULL) OR
       (SELF.fileFormat IS NOT NULL AND
        SELF.fileFormat NOT LIKE 'OTHER%')) THEN

      -- image in BLOB
      IF (SELF.source.isLocal = TRUE) THEN
        -- localData is not null
        IF SELF.source.localData IS NOT NULL THEN

          -- check content length first
          IF dbms_lob.getLength(SELF.source.localData) = 0 THEN
            ORDSYS.ORDIMErrorCodes.raiseExceptionWithMsg('IMG', 808);
          END IF;

          errorCode := ORDSYS.ORDImg_Pkg.getMetadata(
                                  SELF.source.localData,
                                  metaType, metaIptc, 
                                  metaExif, metaXmp, errorText);
        ELSE
          RAISE ORDImageExceptions.NULL_LOCAL_DATA;
        END IF;

      -- image in BFILE
      ELSIF lower(SELF.source.srcType) = 'file' THEN
        imageBfile := SELF.source.getBFILE;

        -- check content length first, no need to open BFILE
        IF dbms_lob.getLength(imageBfile) = 0 THEN
          ORDSYS.ORDIMErrorCodes.raiseExceptionWithMsg('IMG', 808);
        END IF;

        errorCode := ORDSYS.ORDImg_Pkg.getMetadata(imageBfile, 
                                                metaType, metaIptc,
                                                metaExif, metaXmp, errorText);
      -- other source, read into cached temp blob
      ELSE
        BEGIN
          -- create a local ordsource object because the (brain-damaged) 
          -- getContentInTempLob method is declared with SELF as an IN/OUT 
          -- parameter thus we need a modifiable ORDSource, and ours is not

          tempSrc := ORDSYS.ORDSource( NULL, 
                                       SELF.source.srcType,
                                       SELF.source.srcLocation,
                                       SELF.source.srcName,
                                       SYSDATE,
                                       0 );
                  
          tempSrc.getContentInTempLob(ctx, tempLob, tempMime,
                                          tempFormat, DBMS_LOB.CALL, TRUE );


          -- check content length first
          IF dbms_lob.getLength(tempLob) = 0 THEN
            DBMS_LOB.FREETEMPORARY(tempLob);
            ORDSYS.ORDIMErrorCodes.raiseExceptionWithMsg('IMG', 808);
          END IF;

          errorCode := ORDSYS.ORDImg_Pkg.getMetadata(tempLob, metaType,
                                                     metaIptc, metaExif,
                                                     metaXmp, errorText);
          DBMS_LOB.FREETEMPORARY(tempLob);
          EXCEPTION
          WHEN OTHERS THEN
            DBMS_LOB.FREETEMPORARY(tempLob);
            RAISE;
        END;
      END IF;

      IF (errorCode <> 0) THEN
        ORDSYS.ORDIMErrorCodes.raiseExceptionWithMsg2('ORD','IMG',
                                                    errorCode, '',
                                                    errorText);
      END IF;

    END IF;

    -- stuff the results in the return array
    -- this is ugly
    metaData := ORDSYS.ORDImg_Pkg.packMetadataVector(metaOrdImage,
                  metaIptc, metaExif, metaXmp);

    RETURN metaData;
  END getMetadata;

  MEMBER PROCEDURE putMetadata(SELF         IN OUT NOCOPY ORDImage,
                               xmlData      IN SYS.XMLType,
                               metadataType IN VARCHAR2 DEFAULT 'XMP',
                               encoding     IN VARCHAR2 DEFAULT 'UTF-8')
  IS
    tempBlob    BLOB            := NULL;
    metaType    VARCHAR2(32)    := NULL;
    encType     VARCHAR2(16)    := NULL;
    errorCode   NUMBER          := 0;
    errorText   VARCHAR2(1024) := '';
  BEGIN
    -- to get results, source must be not null
    IF (SELF.source IS NULL) THEN
      RAISE ORDImageExceptions.NULL_SOURCE;
    END IF;
    -- and the image must be local
    IF (SELF.source.isLocal <> TRUE)
    THEN
      RAISE ORDImageExceptions.DATA_NOT_LOCAL;
    END IF;

    IF (SELF.source.localData IS NULL) THEN
      RAISE ORDImageExceptions.NULL_LOCAL_DATA;
    END IF;

    -- check the arguments
    metaType := upper(substr(metadataType, 1, 32));
    encType  := upper(substr(encoding, 1, 16));
    ORDSYS.ORDImg_Pkg.checkPutMetaArgs( xmlData, metaType, encType );

    tempBlob := SELF.source.localData;
    errorCode := ORDSYS.ORDImg_Pkg.putMetadata(tempBlob, SELF.source.localData,
                                               xmlData, metaType, encType,
                                               errorText);
    IF (errorCode <> 0) THEN
      ORDSYS.ORDIMErrorCodes.raiseExceptionWithMsg2('ORD','IMG',
                                                  errorCode, '',
                                                  NVL(errorText,''));
    END IF;

    -- only updateTime and contentLength are changed by putMetadata
    -- so setProperties() call can be avoided.
    SELF.source.setUpdateTime(SYSDATE);
    SELF.contentLength := dbms_lob.getLength(SELF.source.localData);
  END putMetadata;

  MEMBER FUNCTION getDicomMetadata(SELF         IN ORDImage,
                              optionString IN VARCHAR2)
         RETURN XMLType
  IS
     dcmMetadata XMLType        := NULL;
     errorCode   NUMBER         := NULL;
     errorText   VARCHAR2(1024) := NULL;
     imageBfile  BFILE          := NULL;
     tempSrc     ORDSYS.ORDSOURCE := NULL;
     ctx         RAW(4)         := NULL;
     tempLob     BLOB           := NULL;
     tempMime    VARCHAR2(4000) := NULL;
     tempFormat   VARCHAR2(4000) := NULL;

  BEGIN
      -- source must not be NULL
    IF (SELF.source IS NULL) THEN
       RAISE ORDImageExceptions.NULL_SOURCE;
    END IF;
    IF (SELF.source.isLocal = TRUE) THEN
       -- image in BLOB
      IF SELF.source.localData is NOT NULL THEN

          -- check content length first
          IF dbms_lob.getLength(SELF.source.localData) = 0 THEN
             ORDSYS.ORDIMErrorCodes.raiseExceptionWithMsg('IMG', 808);
          END IF;

          errorCode := ORDSYS.ORDImg_Pkg.getDicomMetadata(optionString, SELF.source.localData, dcmMetadata, errorText);
      ELSE
          RAISE ORDImageExceptions.NULL_LOCAL_DATA;
      END IF;

       -- image in BFILE
    ELSIF lower(SELF.source.srcType) = 'file' THEN
         imageBfile := SELF.source.getBFILE;

         -- check content length first, no need to open BFILE
         IF dbms_lob.getLength(imageBfile) = 0 THEN
            ORDSYS.ORDIMErrorCodes.raiseExceptionWithMsg('IMG',808);
         END IF;

         errorCode := ORDSYS.ORDImg_Pkg.getDicomMetadata(optionString, imageBfile, dcmMetadata, errorText);

    -- other source, read into cached temp lob
    ELSE
        BEGIN
          -- create a local ordsource object because the (brain-damaged) 
          -- getContentInTempLob method is declared with SELF as an IN/OUT 
          -- parameter thus we need a modifiable ORDSource, and ours is not

          tempSrc := ORDSYS.ORDSource( NULL, 
                                       SELF.source.srcType,
                                       SELF.source.srcLocation,
                                       SELF.source.srcName,
                                       SYSDATE,
                                       0 );
                  
          tempSrc.getContentInTempLob(ctx, tempLob, tempMime,
                                          tempFormat, DBMS_LOB.CALL, TRUE );


          -- check content length first
          IF dbms_lob.getLength(tempLob) = 0 THEN
            DBMS_LOB.FREETEMPORARY(tempLob);
            ORDSYS.ORDIMErrorCodes.raiseExceptionWithMsg('IMG', 808);
          END IF;

          errorCode := ORDSYS.ORDImg_Pkg.getDicomMetadata(optionString, tempLob, dcmMetadata, errorText);

          DBMS_LOB.FREETEMPORARY(tempLob);
          EXCEPTION
          WHEN OTHERS THEN
               DBMS_LOB.FREETEMPORARY(tempLob);
               RAISE;
          END;
    END IF;

    IF (errorCode <> 0) THEN
       ORDSYS.ORDIMErrorCodes.raiseExceptionWithMsg2('ORD','IMG',errorCode,'',NVL(errorText,''));
    END IF;

    dcmMetadata := dcmMetadata.createSchemaBasedXML('http://xmlns.oracle.com/ord/meta/dicomImage');
    dcmMetadata.schemaValidate;

    RETURN dcmMetadata;

  END getDicomMetadata;

  -- LOCAL RELATED METHODS
  MEMBER PROCEDURE setLocal(SELF IN OUT NOCOPY ORDImage) IS
  BEGIN
      -- source must not be NULL
    IF (SELF.source IS NULL) THEN
       RAISE ORDImageExceptions.NULL_SOURCE;
    END IF;

    IF SELF.source.localData IS NOT NULL 
    THEN
      SELF.source.setLocal;
    ELSE
      RAISE ORDImageExceptions.NULL_LOCAL_DATA;
    END IF; 
  END setLocal;

  MEMBER PROCEDURE clearLocal(SELF IN OUT NOCOPY ORDImage) IS
  BEGIN
      -- source must not be NULL
    IF (SELF.source IS NULL) THEN
       RAISE ORDImageExceptions.NULL_SOURCE;
    END IF;

    SELF.source.clearLocal;
  END clearLocal;

  MEMBER FUNCTION  isLocal RETURN BOOLEAN IS
  BEGIN
      -- source must not be NULL
    IF (SELF.source IS NULL) THEN
       RAISE ORDImageExceptions.NULL_SOURCE;
    END IF;

    RETURN SELF.source.isLocal;
  END isLocal;

  -- DATE RELATED METHODS
  MEMBER FUNCTION  getUpdateTime RETURN DATE IS
  BEGIN
      -- source must not be NULL
    IF (SELF.source IS NULL) THEN
       RAISE ORDImageExceptions.NULL_SOURCE;
    END IF;

    RETURN SELF.source.getUpdateTime;
  END getUpdateTime;

  MEMBER PROCEDURE setUpdateTime(SELF IN OUT NOCOPY ORDImage,
                                 current_time DATE) IS
  BEGIN
      -- source must not be NULL
    IF (SELF.source IS NULL) THEN
       RAISE ORDImageExceptions.NULL_SOURCE;
    END IF;

    SELF.source.setUPdateTime(current_time);
  END setUpdateTime;

  -- MIMETYPE RELATED METHODS
  MEMBER FUNCTION  getMimeType RETURN VARCHAR2 IS
  BEGIN
    RETURN SELF.mimeType;
  END getMimeType;

  MEMBER PROCEDURE setMimeType(SELF IN OUT NOCOPY ORDImage,
                               mime IN VARCHAR2) IS
  BEGIN
    IF mime IS NULL THEN
      RAISE ORDImageExceptions.INVALID_MIME_TYPE; 
    END IF; 
      -- source must not be NULL
    IF (SELF.source IS NULL) THEN
       RAISE ORDImageExceptions.NULL_SOURCE;
    END IF;
 
    SELF.mimeType := mime;
    SELF.source.setUpdateTime(SYSDATE);
  END setMimeType;

  -- SOURCE RELATED METHODS
  MEMBER FUNCTION  getContent RETURN BLOB IS
  BEGIN
      -- source must not be NULL
    IF (SELF.source IS NULL) THEN
       RAISE ORDImageExceptions.NULL_SOURCE;
    END IF;

    RETURN SELF.source.getLocalContent;
  END getContent;

  MEMBER FUNCTION getBFILE RETURN BFILE IS
  BEGIN
      -- source must not be NULL
    IF (SELF.source IS NULL) THEN
       RAISE ORDImageExceptions.NULL_SOURCE;
    END IF;

    RETURN SELF.source.getBFILE;
  END getBFILE;

  MEMBER PROCEDURE deleteContent(SELF IN OUT NOCOPY ORDImage) IS
  BEGIN
      -- source must not be NULL
    IF (SELF.source IS NULL) THEN
       RAISE ORDImageExceptions.NULL_SOURCE;
    END IF;

    SELF.source.deleteLocalContent;
    SELF.source.setUpdateTime(SYSDATE);
  END deleteContent;

  MEMBER PROCEDURE setSource(SELF IN OUT NOCOPY ORDImage,
                             source_type     IN VARCHAR2,
                             source_location IN VARCHAR2,
                             source_name     IN VARCHAR2) IS
  BEGIN
      -- source must not be NULL
    IF (SELF.source IS NULL) THEN
       RAISE ORDImageExceptions.NULL_SOURCE;
    END IF;

    SELF.source.setSourceInformation(source_type,
                                     source_location,
                                     source_name);
    SELF.source.setUpdateTime(SYSDATE);
    SELF.source.clearLocal;
  END setSource;

  MEMBER FUNCTION  getSource RETURN VARCHAR2 IS
  BEGIN
      -- source must not be NULL
    IF (SELF.source IS NULL) THEN
       RAISE ORDImageExceptions.NULL_SOURCE;
    END IF;

    RETURN SELF.source.getSourceInformation;
  END getSource;

  MEMBER FUNCTION  getSourceType RETURN VARCHAR2 IS
  BEGIN
      -- source must not be NULL
    IF (SELF.source IS NULL) THEN
       RAISE ORDImageExceptions.NULL_SOURCE;
    END IF;

    RETURN SELF.source.getSourceType;
  END getSourceType;

  MEMBER FUNCTION  getSourceLocation RETURN VARCHAR2 IS
  BEGIN
      -- source must not be NULL
    IF (SELF.source IS NULL) THEN
       RAISE ORDImageExceptions.NULL_SOURCE;
    END IF;

    RETURN SELF.source.getSourceLocation;
  END getSourceLocation;

  MEMBER FUNCTION  getSourceName RETURN VARCHAR2 IS
  BEGIN
      -- source must not be NULL
    IF (SELF.source IS NULL) THEN
       RAISE ORDImageExceptions.NULL_SOURCE;
    END IF;

    RETURN SELF.source.getSourceName;
  END getSourceName;

  MEMBER PROCEDURE import(
                          SELF IN OUT NOCOPY ORDImage,
                          ctx IN OUT RAW) IS
  BEGIN
      -- source must not be NULL
    IF (SELF.source IS NULL) THEN
       RAISE ORDImageExceptions.NULL_SOURCE;
    END IF;
    ORDSYS.ORDImg_Pkg.import(SELF, ctx);
  END import;

  MEMBER PROCEDURE importFrom(
                          SELF IN OUT NOCOPY ORDImage,
                          ctx IN OUT RAW,
                          source_type IN VARCHAR2,
                          source_location IN VARCHAR2,
                          source_name IN VARCHAR2) IS
  BEGIN
      -- source must not be NULL
    IF (SELF.source IS NULL) THEN
       RAISE ORDImageExceptions.NULL_SOURCE;
    END IF;
    ORDSYS.ORDImg_Pkg.importFrom(SELF, ctx, 
                                 source_type,
                                 source_location,
                                 source_name);
  END importFrom;

  MEMBER PROCEDURE export(
                          SELF IN OUT NOCOPY     ORDImage,
                          ctx             IN OUT RAW,
                          source_type     IN     VARCHAR2,
                          source_location IN     VARCHAR2,
                          source_name     IN     VARCHAR2) IS
  BEGIN
      -- source must not be NULL
    IF (SELF.source IS NULL) THEN
       RAISE ORDImageExceptions.NULL_SOURCE;
    END IF;
    SELF.source.export(ctx,
                       source_type,
                       source_location,
                       source_name);
  END export;

  -- process command does not change the time stamp
  -- if the processor wants it can change it with
  -- the completion of the call.
  MEMBER FUNCTION  processSourceCommand(
                            SELF      IN OUT NOCOPY ORDImage,
                            ctx       IN OUT RAW,
                            cmd       IN VARCHAR2,
                            arguments IN VARCHAR2, 
                            result    OUT RAW)
  RETURN RAW
  IS
  BEGIN
      -- source must not be NULL
    IF (SELF.source IS NULL) THEN
       RAISE ORDImageExceptions.NULL_SOURCE;
    END IF;
    return SELF.source.processCommand(ctx, cmd, arguments, result);
  END;
  -- end processSourceCommand

  MEMBER FUNCTION openSource(SELF IN OUT NOCOPY ORDImage, 
                             userArg IN RAW,
                             ctx OUT RAW) 
  RETURN  INTEGER 
  IS 
  BEGIN
      -- source must not be NULL
    IF (SELF.source IS NULL) THEN
       RAISE ORDImageExceptions.NULL_SOURCE;
    END IF;
    return SELF.source.open(userArg, ctx);
  END;

  MEMBER FUNCTION closeSource(SELF IN OUT NOCOPY ORDImage, ctx IN OUT RAW) 
  RETURN INTEGER
  IS
  BEGIN
      -- source must not be NULL
    IF (SELF.source IS NULL) THEN
       RAISE ORDImageExceptions.NULL_SOURCE;
    END IF;
    return  SELF.source.close(ctx);
  END;

  MEMBER FUNCTION trimSource(SELF IN OUT NOCOPY ORDImage, ctx IN OUT RAW, 
                             newlen IN INTEGER) RETURN INTEGER
  IS
  BEGIN

      -- source must not be NULL
    IF (SELF.source IS NULL) THEN
       RAISE ORDImageExceptions.NULL_SOURCE;
    END IF;
    return  SELF.source.trim(ctx,newlen);
  END;

  MEMBER PROCEDURE readFromSource(SELF IN OUT NOCOPY ORDImage, ctx IN OUT RAW,
                                  startPos IN INTEGER,
                                  numBytes IN OUT INTEGER,
                                  buffer OUT RAW)
  IS 
  BEGIN
      -- source must not be NULL
    IF (SELF.source IS NULL) THEN
       RAISE ORDImageExceptions.NULL_SOURCE;
    END IF;
    SELF.source.read(ctx, startPos, numBytes, buffer);
  END;

  MEMBER PROCEDURE writeToSource(SELF  IN OUT NOCOPY ORDImage,
                                 ctx IN OUT RAW,
                                 startPos IN INTEGER,
                                 numBytes IN OUT INTEGER,
                                 buffer IN RAW)
  IS 
  BEGIN
      -- source must not be NULL
    IF (SELF.source IS NULL) THEN
       RAISE ORDImageExceptions.NULL_SOURCE;
    END IF;
    SELF.source.write(ctx, startPos, numBytes, buffer);
  END;

------------------------------------------------------------
--  Static Methods for the relational functional interface
--
-- All of the funtions starting with 'STATIC PROCEDURE'
-- or 'STATIC FUNCTION' are static object methods that 
-- make up the relational interface.
------------------------------------------------------------
  STATIC PROCEDURE export(ctx             IN OUT RAW,
                          local_data      IN BLOB,
                          source_type     IN VARCHAR2,
                          source_location IN VARCHAR2,
                          source_name     IN VARCHAR2)
  IS
    intSource ORDSYS.ORDSource := ORDSYS.ORDSource(NULL, 
            NULL, NULL, NULL, sysdate, 1);
  BEGIN
    intSource.localData := local_data;

    intSource.export(ctx, 
                  source_type,
                  source_location, 
                  source_name);
  END export;

  --
  STATIC PROCEDURE importFrom(ctx             IN OUT RAW,
                              local_data      IN OUT NOCOPY BLOB,
                              source_type     IN VARCHAR2,
                              source_location IN VARCHAR2,
                              source_name     IN VARCHAR2)
  IS
    intImage ORDSYS.ORDImage := ORDSYS.ORDImage(
            ORDSYS.ORDSource(NULL, NULL, NULL, NULL, sysdate, 1), 
            NULL, NULL, NULL, NULL, NULL, NULL, NULL);
    myformat VARCHAR2(40);
    mymime   VARCHAR2(4000);
  BEGIN
    intImage.source.localData := local_data;

    intImage.source.importFrom(ctx,
                  local_data,
                  mymime,
                  myformat,
                  source_type,
                  source_location,
                  source_name);
  END importFrom;

  --
  STATIC PROCEDURE importFrom(ctx             IN OUT RAW,
                              local_data      IN OUT NOCOPY BLOB,
                              source_type     IN VARCHAR2,
                              source_location IN VARCHAR2,
                              source_name     IN VARCHAR2,
                              format          OUT VARCHAR2,
                              mime_type       OUT VARCHAR2)
  IS
    intImage ORDSYS.ORDImage := ORDSYS.ORDImage(
            ORDSYS.ORDSource(NULL, NULL, NULL, NULL, sysdate, 1), 
            NULL, NULL, NULL, NULL, NULL, NULL, NULL);
  BEGIN
    intImage.source.localData := local_data;

    intImage.source.importFrom(ctx,
                  local_data,
                  mime_type,
                  format,
                  source_type,
                  source_location,
                  source_name);
  END importFrom;


  STATIC PROCEDURE getProperties(imageBlob         IN BLOB,
                                 attributes        IN OUT NOCOPY CLOB,
                                 mimeType          OUT VARCHAR2,
                                 width             OUT INTEGER,
                                 height            OUT INTEGER,
                                 fileFormat        IN OUT VARCHAR2,
                                 contentFormat     OUT VARCHAR2,
                                 compressionFormat OUT VARCHAR2,
                                 contentLength     OUT INTEGER)
  IS
    status BINARY_INTEGER;
  BEGIN
    IF imageBlob IS NULL THEN
      RAISE ORDImageExceptions.NULL_CONTENT;
    END IF;

    status := ORDImg_Pkg.ordimgB_setProperties(imageBlob, height, width, 
                            contentLength, fileFormat, 
                            contentFormat, compressionFormat, mimeType);

    IF (attributes IS NOT NULL)
    THEN
         ORDImg_Pkg.buildXMLAttributes(attributes, mimeType, width, height, 
                 fileFormat, contentFormat, compressionFormat, contentLength, 1);
    END IF;
  END getProperties;


  STATIC PROCEDURE getProperties(imageBlob         IN BLOB,
                                 attributes        IN OUT NOCOPY CLOB)
  IS
    status BINARY_INTEGER;
    mimeType VARCHAR2(4000);
    width INTEGER;
    height INTEGER;
    fileFormat VARCHAR2(4000);
    contentFormat VARCHAR2(4000);
    compressionFormat VARCHAR2(4000);
    contentLength INTEGER;
  BEGIN
    IF imageBlob IS NULL THEN
      RAISE ORDImageExceptions.NULL_CONTENT;
    END IF;

    status := ORDImg_Pkg.ordimgB_setProperties(imageBlob, height, width, 
                            contentLength, fileFormat, 
                            contentFormat, compressionFormat, mimeType);

    IF (attributes IS NOT NULL)
    THEN
         ORDImg_Pkg.buildXMLAttributes(attributes, mimeType, width, height, 
                 fileFormat, contentFormat, compressionFormat, contentLength, 1);
    END IF;
  END getProperties;


  STATIC PROCEDURE getProperties(imageBfile       IN OUT NOCOPY BFILE,
                                 attributes        IN OUT NOCOPY CLOB,
                                 mimeType          OUT VARCHAR2,
                                 width             OUT INTEGER,
                                 height            OUT INTEGER,
                                 fileFormat        IN OUT VARCHAR2,
                                 contentFormat     OUT VARCHAR2,
                                 compressionFormat OUT VARCHAR2,
                                 contentLength     OUT INTEGER)
  IS
    status BINARY_INTEGER;
    openedbfile BOOLEAN := FALSE;
  BEGIN
    IF imageBfile IS NULL THEN
      RAISE ORDImageExceptions.NULL_CONTENT;
    END IF;

    IF (DBMS_LOB.FILEISOPEN(imageBfile) = 0) THEN
      DBMS_LOB.FILEOPEN(imageBfile);
      openedbfile := TRUE;
    END IF;

    status := ORDImg_Pkg.ordimgF_setProperties(imageBfile, height, width, 
                            contentLength, fileFormat, 
                            contentFormat, compressionFormat, mimeType);

    IF openedbfile = TRUE THEN
       DBMS_LOB.FILECLOSE(imageBfile);
    END IF;

    IF (attributes IS NOT NULL)
    THEN
         ORDImg_Pkg.buildXMLAttributes(attributes, mimeType, width, height, 
                 fileFormat, contentFormat, compressionFormat, contentLength, 1);
    END IF;
  END getProperties;


  STATIC PROCEDURE getProperties(imageBfile       IN OUT NOCOPY BFILE,
                                 attributes        IN OUT NOCOPY CLOB)
  IS
    status BINARY_INTEGER;
    openedbfile BOOLEAN := FALSE;
    mimeType VARCHAR2(4000);
    width INTEGER;
    height INTEGER;
    fileFormat VARCHAR2(4000);
    contentFormat VARCHAR2(4000);
    compressionFormat VARCHAR2(4000);
    contentLength INTEGER;
  BEGIN
    IF imageBfile IS NULL THEN
      RAISE ORDImageExceptions.NULL_CONTENT;
    END IF;

    IF (DBMS_LOB.FILEISOPEN(imageBfile) = 0) THEN
      DBMS_LOB.FILEOPEN(imageBfile);
      openedbfile := TRUE;
    END IF;

    status := ORDImg_Pkg.ordimgF_setProperties(imageBfile, height, width, 
                            contentLength, fileFormat, 
                            contentFormat, compressionFormat, mimeType);

    IF openedbfile = TRUE THEN
       DBMS_LOB.FILECLOSE(imageBfile);
    END IF;

    IF (attributes IS NOT NULL)
    THEN
         ORDImg_Pkg.buildXMLAttributes(attributes, mimeType, width, height, 
                 fileFormat, contentFormat, compressionFormat, contentLength, 1);
    END IF;
  END getProperties;

  STATIC FUNCTION getMetadata(imageBlob    IN BLOB,
                              metadataType IN VARCHAR2 DEFAULT 'ALL')
  RETURN SYS.XMLSEQUENCETYPE 
  IS
    metaType     VARCHAR2(32)   := NULL;
    metaOrdImage SYS.XMLType    := NULL;
    metaIptc     SYS.XMLType    := NULL;
    metaExif     SYS.XMLType    := NULL;
    metaXmp      SYS.XMLType    := NULL;
    metaData     SYS.XMLSEQUENCETYPE := NULL;
    errorCode    NUMBER       := 0;
    errorText    VARCHAR2(1024) := '';
    docCount     INTEGER        := 0;
    ordImage     ORDSYS.ORDIMAGE := ORDSYS.ORDImage.init();
  BEGIN
    IF imageBlob IS NULL THEN
      RAISE ORDImageExceptions.NULL_CONTENT;
    END IF;

    -- check the arguments
    metaType  := upper(substr(metadataType, 1, 32));
    ORDSYS.ORDImg_Pkg.checkGetMetaArgs(metaType);

    -- check content length first
    IF dbms_lob.getLength( imageBlob ) = 0 THEN
      ORDSYS.ORDIMErrorCodes.raiseExceptionWithMsg('IMG', 808);
    END IF;

    IF (metaType = 'ORDIMAGE') OR
       (metaType = 'ALL')
    THEN
      errorCode := ORDImg_Pkg.ordimgB_setProperties(imageBlob, ordImage.height, 
                              ordImage.width, ordImage.contentLength, 
                              ordImage.fileFormat, ordImage.contentFormat, 
                              ordImage.compressionFormat, ordImage.MimeType);

      IF (errorCode <> 0) THEN
        ORDSYS.ORDIMErrorCodes.raiseExceptionWithMsg2('ORD','IMG',
                                                    errorCode, '',
                                                    NVL(errorText,''));
      END IF;

      metaOrdImage := ORDSYS.ORDImg_Pkg.buildXMLDoc(ordImage);
    END IF;

    IF metaType <> 'ORDIMAGE' THEN
      errorCode := ORDSYS.ORDImg_Pkg.getMetadata(imageBlob, metaType, metaIptc, 
                                                 metaExif, metaXmp, errorText);
      IF (errorCode <> 0) THEN
        ORDSYS.ORDIMErrorCodes.raiseExceptionWithMsg2('ORD','IMG',
                                                      errorCode, '',
                                                      NVL(errorText,''));
      END IF;
    END IF;

    -- stuff the results in the return array
    -- this is ugly
    metaData := ORDSYS.ORDImg_Pkg.packMetadataVector(metaOrdImage,
                  metaIptc, metaExif, metaXmp);

    RETURN metaData;

  END getMetadata;

  STATIC FUNCTION getMetadata(imageBfile   IN BFILE,
                              metadataType IN VARCHAR2 DEFAULT 'ALL')
                  RETURN SYS.XMLSEQUENCETYPE 
  IS
    metaType     VARCHAR2(32)   := NULL;
    metaOrdImage SYS.XMLType    := NULL;
    metaIptc     SYS.XMLType    := NULL;
    metaExif     SYS.XMLType    := NULL;
    metaXmp      SYS.XMLType    := NULL;
    metaData     SYS.XMLSEQUENCETYPE := NULL;
    errorCode    NUMBER       := 0;
    errorText    VARCHAR2(1024) := '';
    docCount     INTEGER        := 0;
    ordImage     ORDSYS.ORDIMAGE := ORDSYS.ORDImage.init();
    bFileOpen    BOOLEAN        := FALSE;
    imageBfile1  BFILE          := imageBfile;
  BEGIN
    -- this never seems to fire
    IF imageBfile IS NULL THEN
      RAISE ORDImageExceptions.NULL_CONTENT;
    END IF;

    -- check the arguments
    metaType  := upper(substr(metadataType, 1, 32));
    ORDSYS.ORDImg_Pkg.checkGetMetaArgs(metaType);

    -- open the BFILE
    IF (DBMS_LOB.FILEISOPEN(imageBfile1) = 0) THEN
      DBMS_LOB.FILEOPEN(imageBfile1);
    END IF;
    bFileOpen := TRUE;

    -- check  length 
    IF dbms_lob.getLength( imageBfile1 ) = 0 THEN
      ORDSYS.ORDIMErrorCodes.raiseExceptionWithMsg('IMG', 808);
    END IF;

    IF (metaType = 'ORDIMAGE') OR
       (metaType = 'ALL')
    THEN
      errorCode := ORDImg_Pkg.ordimgF_setProperties(imageBfile1, ordImage.height, 
                              ordImage.width, ordImage.contentLength, 
                              ordImage.fileFormat, ordImage.contentFormat, 
                              ordImage.compressionFormat, ordImage.mimeType);

      IF (errorCode <> 0) THEN
        ORDSYS.ORDIMErrorCodes.raiseExceptionWithMsg2('ORD','IMG',
                                                    errorCode, '',
                                                    NVL(errorText,''));
      END IF;

      metaOrdImage := ORDSYS.ORDImg_Pkg.buildXMLDoc(ordImage);
    END IF;

    IF metaType <> 'ORDIMAGE' THEN
      errorCode := ORDSYS.ORDImg_Pkg.getMetadata(imageBfile1, metaType, metaIptc, 
                                                 metaExif, metaXmp, errorText);
      IF (errorCode <> 0) THEN
        ORDSYS.ORDIMErrorCodes.raiseExceptionWithMsg2('ORD','IMG',
                                                      errorCode, '',
                                                      NVL(errorText,''));
      END IF;
    END IF;

    IF bFileOpen THEN
       DBMS_LOB.FILECLOSE(imageBfile1);
    END IF;

    -- stuff the results in the return array
    -- this is ugly
    metaData := ORDSYS.ORDImg_Pkg.packMetadataVector(metaOrdImage,
                  metaIptc, metaExif, metaXmp);

    RETURN metaData;

    EXCEPTION
      WHEN OTHERS THEN

        IF bFileOpen THEN
           DBMS_LOB.FILECLOSE(imageBfile1);
        END IF;

        RAISE;
  END getMetadata;

  STATIC PROCEDURE putMetadata(imageBlob    IN BLOB,
                               dest         IN OUT NOCOPY BLOB,
                               xmlData      IN SYS.XMLType,
                               metadataType IN VARCHAR2 DEFAULT 'XMP',
                               encoding     IN VARCHAR2 DEFAULT 'UTF-8')
  IS
    metaType    VARCHAR2(32)   := NULL;
    encType     VARCHAR2(16)   := NULL;
    errorCode   NUMBER         := 0;
    errorText   VARCHAR2(1024) := '';
  BEGIN
    -- to get results, src and dest must not be null
    IF imageBlob IS NULL THEN
      RAISE ORDImageExceptions.NULL_CONTENT;
    END IF;
    IF dest IS NULL then
      RAISE ORDImageExceptions.NULL_DESTINATION;
    END IF;

    -- check the arguments
    metaType := upper(substr(metadataType, 1, 32));
    encType  := upper(substr(encoding, 1, 16));
    ORDSYS.ORDImg_Pkg.checkPutMetaArgs( xmlData, metaType, encType );

    errorCode := ORDSYS.ORDImg_Pkg.putMetadata(imageBlob, dest,
                                               xmlData, metaType, encType,
                                               errorText);
    IF (errorCode <> 0) THEN
      ORDSYS.ORDIMErrorCodes.raiseExceptionWithMsg2('ORD','IMG',
                                                  errorCode, '',
                                                  NVL(errorText,''));
    END IF;
  END putMetadata;

  STATIC PROCEDURE putMetadata(imageBfile   IN BFILE,
                               dest         IN OUT NOCOPY BLOB,
                               xmlData      IN SYS.XMLType,
                               metadataType IN VARCHAR2 DEFAULT 'XMP',
                               encoding     IN VARCHAR2 DEFAULT 'UTF-8')
  IS
    metaType    VARCHAR2(32)   := NULL;
    encType     VARCHAR2(16)   := NULL;
    errorCode   NUMBER         := 0;
    errorText   VARCHAR2(1024) := '';
    bFileOpen    BOOLEAN       := FALSE;
    imageBfile1  BFILE         := imageBfile;
  BEGIN
    -- to get results, src and dest must not be null
    IF imageBfile IS NULL THEN
      RAISE ORDImageExceptions.NULL_CONTENT;
    END IF;
    IF dest IS NULL then
      RAISE ORDImageExceptions.NULL_DESTINATION;
    END IF;

    -- check the arguments
    metaType := upper(substr(metadataType, 1, 32));
    encType  := upper(substr(encoding, 1, 16));
    ORDSYS.ORDImg_Pkg.checkPutMetaArgs( xmlData, metaType, encType );

    IF (DBMS_LOB.FILEISOPEN(imageBfile1) = 0) THEN
      DBMS_LOB.FILEOPEN(imageBfile1);
    END IF;
    bFileOpen := TRUE;

    errorCode := ORDSYS.ORDImg_Pkg.putMetadata(imageBfile1, dest,
                                               xmlData, metaType, encType,
                                               errorText);

    IF bFileOpen THEN
       DBMS_LOB.FILECLOSE(imageBfile1);
    END IF;

    IF (errorCode <> 0) THEN
      ORDSYS.ORDIMErrorCodes.raiseExceptionWithMsg2('ORD','IMG',
                                                  errorCode, '',
                                                  NVL(errorText,''));
    END IF;

  END putMetadata;

  STATIC PROCEDURE process(imageBlob IN OUT NOCOPY BLOB,
                           command IN VARCHAR2)
  IS
    temp_lob         BLOB;
    headerlessInfo   VARCHAR2(4000);
    status           BINARY_INTEGER;
    localWidth       INTEGER := NULL;
    localHeight      INTEGER := NULL;
    localFileFormat  VARCHAR2(4000) := NULL;
    localContentFormat VARCHAR2(4000) := NULL;
    localCompressionFormat VARCHAR2(4000) := NULL;
  BEGIN
  -- Is this the best choice for an error to raise????
    IF (imageBlob IS NULL) THEN
      RAISE ORDImageExceptions.DATA_NOT_LOCAL;
    END IF;

    ORDImg_Pkg.getHeaderlessInfo(localFileFormat, localHeight, localWidth,
                      localCompressionFormat, localContentFormat, headerlessInfo);

    temp_lob:= imageBlob;
    status := ORDImg_Pkg.ordimgB_process(command,headerlessInfo,
                              temp_lob,imageBlob);    
  END process;

  STATIC PROCEDURE processCopy(imageBlob IN BLOB,
                               command IN     VARCHAR2, 
                               dest    IN OUT NOCOPY BLOB)
  IS
    headerlessInfo   VARCHAR2(4000);
    status           BINARY_INTEGER;
    localWidth       INTEGER := NULL;
    localHeight      INTEGER := NULL;
    localFileFormat  VARCHAR2(4000) := NULL;
    localContentFormat VARCHAR2(4000) := NULL;
    localCompressionFormat VARCHAR2(4000) := NULL;
  BEGIN
    IF (imageBlob IS NULL) THEN
      RAISE ORDImageExceptions.DATA_NOT_LOCAL;
    END IF;

    ORDImg_Pkg.getHeaderlessInfo(localFileFormat, localHeight, localWidth,
                      localCompressionFormat, localContentFormat, headerlessInfo);

    status := ORDImg_Pkg.ordimgB_process(command, headerlessInfo,
                              imageBlob,dest);    
  END processCopy;


  STATIC PROCEDURE processCopy(imageBfile IN OUT NOCOPY BFILE,
                               command IN VARCHAR2, 
                               dest    IN OUT NOCOPY BLOB)
  IS
    openedbfile BOOLEAN := FALSE;
    headerlessInfo   VARCHAR2(4000);
    status           BINARY_INTEGER;
    localWidth       INTEGER := NULL;
    localHeight      INTEGER := NULL;
    localFileFormat  VARCHAR2(4000) := NULL;
    localContentFormat VARCHAR2(4000) := NULL;
    localCompressionFormat VARCHAR2(4000) := NULL;
  BEGIN
      IF dest IS NULL THEN
          RAISE ORDImageExceptions.NULL_DESTINATION;
      END IF;

      IF (imageBfile IS NULL) THEN
          RAISE ORDImageExceptions.NULL_LOCAL_DATA;
      END IF;

      IF (DBMS_LOB.FILEISOPEN(imageBfile) = 0) THEN
          DBMS_LOB.FILEOPEN(imageBfile);
          openedbfile := TRUE;
      END IF;  

      ORDImg_Pkg.getHeaderlessInfo(localFileFormat, localHeight, localWidth,
                      localCompressionFormat, localContentFormat, headerlessInfo);

      status := ORDImg_Pkg.ordimgF_processCopy(command, headerlessInfo,
                                  imageBfile, dest);
        
      IF (openedbfile = TRUE) THEN
          DBMS_LOB.FILECLOSE(imageBfile);
      END IF;

  EXCEPTION
      WHEN OTHERS THEN
        IF (openedbfile = TRUE) THEN
          DBMS_LOB.FILECLOSE(imageBfile);
        END IF;
      RAISE;
  END processCopy;

----------------------------------------
-- The 'headerless' versions of the
-- preceeding functions
----------------------------------------
  STATIC PROCEDURE process(imageBlob     IN OUT NOCOPY BLOB,
                           command       IN VARCHAR2,
                           width         IN INTEGER,
                           height        IN INTEGER,
                           fileFormat    IN VARCHAR2,
                           contentFormat IN VARCHAR2,
                           compressionFormat IN VARCHAR2)
  IS
    temp_lob         BLOB;
    headerlessInfo   VARCHAR2(4000);
    status           BINARY_INTEGER;
  BEGIN
  -- Is this the best choice for an error to raise????
    IF (imageBlob IS NULL) THEN
      RAISE ORDImageExceptions.DATA_NOT_LOCAL;
    END IF;

    ORDImg_Pkg.getHeaderlessInfo(fileFormat, height, width,
                      compressionFormat, contentFormat, headerlessInfo);

    temp_lob:= imageBlob;
    status := ORDImg_Pkg.ordimgB_process(command,headerlessInfo,
                              temp_lob,imageBlob);    
  END process;

  STATIC PROCEDURE processCopy(imageBlob     IN BLOB,
                               command       IN VARCHAR2, 
                               dest          IN OUT NOCOPY BLOB,
                               width         IN INTEGER,
                               height        IN INTEGER,
                               fileFormat    IN VARCHAR2,
                               contentFormat IN VARCHAR2,
                               compressionFormat IN VARCHAR2)
  IS
    headerlessInfo   VARCHAR2(4000);
    status           BINARY_INTEGER;
  BEGIN
    IF (imageBlob IS NULL) THEN
      RAISE ORDImageExceptions.DATA_NOT_LOCAL;
    END IF;

    ORDImg_Pkg.getHeaderlessInfo(fileFormat, height, width,
                      compressionFormat, contentFormat, headerlessInfo);

    status := ORDImg_Pkg.ordimgB_process(command, headerlessInfo,
                              imageBlob,dest);    
  END processCopy;


  STATIC PROCEDURE processCopy(imageBfile    IN OUT NOCOPY BFILE,
                               command       IN VARCHAR2, 
                               dest          IN OUT NOCOPY BLOB,
                               width         IN INTEGER,
                               height        IN INTEGER,
                               fileFormat    IN VARCHAR2,
                               contentFormat IN VARCHAR2,
                               compressionFormat IN VARCHAR2)
  IS
    openedbfile BOOLEAN := FALSE;
    headerlessInfo   VARCHAR2(4000);
    status           BINARY_INTEGER;
  BEGIN
      IF dest IS NULL THEN
          RAISE ORDImageExceptions.NULL_DESTINATION;
      END IF;

      IF (imageBfile IS NULL) THEN
          RAISE ORDImageExceptions.NULL_LOCAL_DATA;
      END IF;

      IF (DBMS_LOB.FILEISOPEN(imageBfile) = 0) THEN
          DBMS_LOB.FILEOPEN(imageBfile);
          openedbfile := TRUE;
      END IF;  

      ORDImg_Pkg.getHeaderlessInfo(fileFormat, height, width,
                      compressionFormat, contentFormat, headerlessInfo);

      status := ORDImg_Pkg.ordimgF_processCopy(command, headerlessInfo,
                                  imageBfile, dest);
        
      IF (openedbfile = TRUE) THEN
          DBMS_LOB.FILECLOSE(imageBfile);
      END IF;

  EXCEPTION
      WHEN OTHERS THEN
        IF (openedbfile = TRUE) THEN
          DBMS_LOB.FILECLOSE(imageBfile);
        END IF;
      RAISE;
  END processCopy;

  STATIC FUNCTION getDicomMetadata(imageBlob IN BLOB,
                              optionString IN VARCHAR2)
         RETURN XMLType
  IS
     dcmMetadata XMLType := NULL;
     errorCode   NUMBER;
     errorText   VARCHAR2(1024) := NULL;
  BEGIN
    IF (imageBlob IS NULL) THEN
       RAISE ORDImageExceptions.NULL_CONTENT;
    END IF;

    -- check content length first
    IF dbms_lob.getLength( imageBlob ) = 0 THEN
       ORDSYS.ORDIMErrorCodes.raiseExceptionWithMsg('IMG',808);
    END IF;

    errorCode := ORDSYS.ORDImg_Pkg.getDicomMetadata(optionString, imageBlob, dcmMetadata, errorText);
    IF (errorCode <> 0) THEN
       ORDSYS.ORDIMErrorCodes.raiseExceptionWithMsg2('ORD','IMG',errorCode,'',NVL(errorText,''));
    END IF;

    dcmMetadata := dcmMetadata.createSchemaBasedXML('http://xmlns.oracle.com/ord/meta/dicomImage');
    dcmMetadata.schemaValidate;

    RETURN dcmMetadata;

  END getDicomMetadata;

  STATIC FUNCTION getDicomMetadata(imageBfile IN BFILE,
                              optionString IN VARCHAR2)
         RETURN XMLType
  IS
     dcmMetadata XMLType := NULL;
     errorCode   NUMBER := 0;
     errorText   VARCHAR2(1024) := NULL;
     bFileOpen   BOOLEAN := FALSE;
     imageBfile1 BFILE := imageBfile; -- FILEISIOPEN changes the state of
                                      -- the Bfile, since imageBfile is IN
                                      -- we need a local variable
  BEGIN
    IF (imageBfile IS NULL) THEN
       RAISE ORDImageExceptions.NULL_CONTENT;
    END IF;

    -- open the BFILE
    IF (DBMS_LOB.FILEISOPEN(imageBfile1) = 0) THEN
        DBMS_LOB.FILEOPEN(imageBfile1);
    END IF;
    bFileOpen := TRUE;

    -- check content length
    IF dbms_lob.getLength( imageBfile1 ) = 0 THEN
       ORDSYS.ORDIMErrorCodes.raiseExceptionWithMsg('IMG',808);
    END IF;

    errorCode := ORDSYS.ORDImg_Pkg.getDicomMetadata(optionString, imageBfile1, dcmMetadata, errorText);
    IF (errorCode <> 0) THEN
       ORDSYS.ORDIMErrorCodes.raiseExceptionWithMsg2('ORD','IMG',errorCode,'',NVL(errorText,''));
    END IF;

    IF bFileOpen THEN
       DBMS_LOB.FILECLOSE(imageBfile1);
    END IF;

    dcmMetadata := dcmMetadata.createSchemaBasedXML('http://xmlns.oracle.com/ord/meta/dicomImage');
    dcmMetadata.schemaValidate;

    RETURN dcmMetadata;

  END getDicomMetadata;
  
end;
/
show errors;

--
-- Reload Image Indexing which was removed in 11.2
--
-- From ordimspc.sql:
--
create or replace type ordsys.ordimgidxmethods
   AUTHID CURRENT_USER
   AS OBJECT
   (
   scanctx RAW(4),

   STATIC FUNCTION ODCIGetInterfaces(ifclist OUT SYS.ODCIOBJECTLIST)
   RETURN NUMBER,

   STATIC FUNCTION IndexCreateFunc(origtablename VARCHAR2,
				   colname       VARCHAR2,
				   tablename     VARCHAR2,
				   schemaname    VARCHAR2)
   RETURN PLS_INTEGER,

   STATIC FUNCTION ODCIIndexCreate (ia    SYS.ODCIINDEXINFO,
				    parms VARCHAR2,
				    env   SYS.ODCIENV)
   RETURN NUMBER,

   STATIC FUNCTION ODCIIndexDrop (ia  SYS.ODCIINDEXINFO,
				  env SYS.ODCIEnv)
   RETURN NUMBER,

   STATIC FUNCTION ODCIIndexInsert(ia        SYS.ODCIINDEXINFO,
				   rid       VARCHAR2,
				   newsig IN ORDSYS.ORDImageSignature,
				   env       SYS.ODCIEnv)
   RETURN NUMBER,

   STATIC FUNCTION ODCIIndexUpdate(ia        SYS.ODCIINDEXINFO,
				   rid       VARCHAR2,
				   oldsig IN ORDSYS.ORDImageSignature,
				   newsig IN ORDSYS.ORDImageSignature,
				   env       SYS.ODCIEnv)
   RETURN NUMBER,

   STATIC FUNCTION ODCIIndexDelete(ia        SYS.ODCIINDEXINFO,
				   rid       VARCHAR2,
                                   oldsig IN ORDSYS.ORDImageSignature,
				   env       SYS.ODCIEnv)
   RETURN NUMBER,

   STATIC FUNCTION ODCIIndexStart(sctx IN OUT ORDSYS.ORDIMGIDXMETHODS,
				  ia SYS.ODCIINDEXINFO,
				  pi SYS.ODCIPREDINFO,
				  qi SYS.ODCIQUERYINFO,
				  strt NUMBER,
				  stop NUMBER,
				  querysig     IN ORDSYS.ORDImageSignature,
				  weightstring IN VARCHAR2, 
				  threshold    IN FLOAT,
				  env              SYS.ODCIEnv)
   RETURN NUMBER,

   MEMBER FUNCTION ODCIIndexFetch(nrows IN NUMBER,
  		  rids OUT SYS.ODCIRIDLIST,
		  env      SYS.ODCIEnv)
   RETURN NUMBER
   IS Language C
   NAME "kidiidx_fetch" LIBRARY ORDIMLIBT
   WITH CONTEXT
   PARAMETERS(
             CONTEXT,
             self,
             self     INDICATOR STRUCT,
             nrows,
             nrows    INDICATOR,
             rids,
             rids     INDICATOR,
	     env,
	     env      INDICATOR STRUCT,
             RETURN   OCINumber
  ),

   MEMBER FUNCTION ODCIIndexClose(env SYS.ODCIEnv)
   RETURN NUMBER
   IS Language C
   NAME "kidiidx_close" LIBRARY ORDIMLIBT
   WITH CONTEXT
   PARAMETERS(
	     CONTEXT,
	     self,
	     self     INDICATOR STRUCT,
	     env,
	     env      INDICATOR STRUCT,
	     RETURN   OCINumber
   )
		 
   );
/
show errors;


-- it makes sense to add grant permission as soon as an
-- object is create instead of in the install scripts for
-- better maintainability.  Also this is necessary for
-- objects created for extensible indexing.



create or replace type ordsys.ordimageindexstats
   AUTHID CURRENT_USER
   AS OBJECT
   (
     dummy NUMBER(6),

     STATIC FUNCTION ODCIGetInterfaces(ifclist OUT SYS.ODCIOBJECTLIST)
     RETURN NUMBER,

     STATIC FUNCTION ODCIStatsCollect(ia      SYS.ODCIIndexInfo,
                                      options SYS.ODCIStatsOptions,
                                      stats   OUT RAW,
                                      env     SYS.ODCIEnv)
     RETURN NUMBER,

     STATIC FUNCTION ODCIStatsDelete(ia       SYS.ODCIIndexInfo,
                                     stats    OUT RAW,
                                     env      SYS.ODCIEnv)
     RETURN NUMBER,

     STATIC FUNCTION ODCIStatsSelectivity(pred       SYS.ODCIPredInfo,
                                          sel        OUT NUMBER,
                                          args       SYS.ODCIARGDESCLIST,
                                          strt       NUMBER,
                                          stop       NUMBER,
                                          sigcol     ORDSYS.ORDImageSignature,
                                          qsig       ORDSYS.ORDImageSignature,
                                          wstr       VARCHAR2,
                                          thresh     NUMBER,
                                          env        SYS.ODCIEnv)
     RETURN NUMBER,

     PRAGMA RESTRICT_REFERENCES(ODCIStatsSelectivity, WNDS, WNPS)

);
/
show errors;


-- End of ORDIMAGEINDEX removal section


-- Drop objects in orddata before dropping user to avoid 
--ORA-00604: error occurred at recursive SQL level 1

-- drop public synonyms
drop PUBLIC SYNONYM orddcm_dbrelease_docs;

--Remove all tables, views and sequences from ORDDATA
-- and then drop orddata 
-- NOTE: use explicit schema names for all select and drop statements
-- instead of alter session set current_schema="...."
-- This prevents the script doing something dangerous in the 
-- in another schema(possibly SYS) if the "alter session set current_schema"
-- statement fails because the user does not exist.

-- 
-- Remove Views
-- 
BEGIN
   for cur in ( select view_name from all_views 
                where owner='ORDDATA') loop
    begin
      EXECUTE IMMEDIATE ' DROP VIEW orddata.' || cur.view_name;

      EXCEPTION 
       WHEN OTHERS THEN
         NULL;
     END;
   end loop;
END;
/




--
-- Remove Sequences
--
BEGIN
    for cur in (select sequence_name from sys.dba_sequences
                where sequence_owner='ORDDATA') loop
      begin
        execute immediate ' DROP SEQUENCE orddata.' || cur.sequence_name;

        exception 
         when OTHERS then
           null;
      end;
    end loop;
END;
/



--
-- Remove Tables
--
BEGIN
    -- drop tables in reverse order of creation
    -- note: cannot drop nested tables, they are automatically dropped
    --       when the parent table is dropped
    for cur in (  select tab.table_name, tab.duration
                  from sys.dba_tables tab, sys.dba_objects obj
                  where tab.table_name = obj.object_name
                  and tab.owner='ORDDATA'
                  and tab.nested = 'NO'
                  order by obj.timestamp desc)  loop
     begin
       -- truncate session duration temp table to avoid error
       -- ORA-14452: attempt to create, alter or drop an index on 
       -- temporary table already in use
       if (cur.duration = 'SYS$SESSION') then
         execute immediate 'truncate table orddata.' ||  cur.table_name;
       end if;

       execute immediate ' DROP TABLE orddata.' || cur.table_name 
                           || ' cascade constraints purge';

       exception when OTHERS then
        null;
      end;
    end loop;
END;
/

-- NOTE: ORDSYS tables were left unchanged during upgrade.   
-- Any documents added between upgrade and downgrade will be lost.
DROP USER orddata CASCADE;


-- DROP schema stored tag document schema
-- http://xmlns.oracle.com/ord/dicom/attributeTag_1_0
--ok to use force option during downgrade
declare
  ex exception;
  --ignore ORA-31000: Resource '..' not an XDB schema document
  pragma exception_init( ex, -31000 );
BEGIN
  DBMS_XMLSCHEMA.DELETESCHEMA( 
                 'http://xmlns.oracle.com/ord/dicom/attributeTag_1_0',
                 DBMS_XMLSCHEMA.DELETE_CASCADE_FORCE );

  EXCEPTION
   --ignore ORA-31000: Resource '..' not an XDB schema document
   when ex then
     null;
END;
/

-- DROP manifest schema
-- http://xmlns.oracle.com/ord/dicom/manifest_1_0
--ok to use force option during downgrade
declare
  ex exception;
  --ignore ORA-31000: Resource '..' not an XDB schema document
  pragma exception_init( ex, -31000 );
BEGIN
  DBMS_XMLSCHEMA.DELETESCHEMA( 
                 'http://xmlns.oracle.com/ord/dicom/manifest_1_0',
                 DBMS_XMLSCHEMA.DELETE_CASCADE_FORCE );

  EXCEPTION
   --ignore ORA-31000: Resource '..' not an XDB schema document
   when ex then
     null;
END;
/


---- drop ORD_ADMIN package created in 11.2
drop package ORDSYS.ORD_ADMIN;
revoke select on sys.dba_indexes from ORDSYS;

-- set current_schema to ORDSYS before dropping Oracle Multimedia classes
alter session set current_schema="ORDSYS";

REM Drop all Oracle Multimedia java classes
@@imclnjav


-- The following should be at the end of the ORDIM part of the file
-- executed as ORDSYS
EXECUTE sys.dbms_registry.downgraded('ORDIM', '11.1.0');

REM
REM Downgrade Locator if Spatial is not installed
REM
alter session set current_schema="SYS";

COLUMN :script_name NEW_VALUE comp_file NOPRINT
Variable script_name varchar2(50)

declare
  mdsyscnt   NUMBER       := 0;
  sdo_status VARCHAR2(20) := NULL;
begin
  -- Check whether Locator is installed.
  -- If not, Do not downgrade Locator
  select count(*) into mdsyscnt from sys.dba_objects 
      where owner='MDSYS' and object_name = 'SDO_GEOMETRY';

  -- Check whether SDO is installed.
  -- If not installed or if OPTION OFF, downgrade Locator
  sdo_status := dbms_registry.status('SDO');
  if ((sdo_status is NULL or sdo_status = 'OPTION OFF') and 
      (mdsyscnt > 0)) then
    :script_name := '?/md/admin/loce111.sql';
  else
    :script_name := sys.dbms_registry.nothing_script;
  end if;
end;
/

REM Invoke Locator downgrade script
select :script_name from dual;
@&comp_file

alter session set current_schema="SYS";