/* Use Case #1: Parse EML. Get entity list and attributes */

  CallingApplication --> DataManager.parseMetadata()
    DataManager --> EML200Parser.parse()
    DataManager --> EML200Parser.getEMLDataPackage()
  CallingApplication --> EMLDataPackage.getEntityList()
  CallingApplication --> Entity.getAttributeList()
  CallingApplication --> AttributeList.getAttributes()
  CallingApplication --> Attribute.getName()


/* Use Case #2: Download data table */

  CallingApplication --> DataManager.downloadData()
    DataManager --> DataManager.parseMetadata()                /* Use Case #1 */
    DataManager --> EMLDataPackage.getEntityList()
    DataManager --> Entity.getDownloadHandler()
    DataManager --> DownloadHandler.download()
      DownloadHandler --> Thread.start()
        DownloadHandler --> DownloadHandler.run()
          /* For all DataStorageInterface objects */
          DownloadHandler --> DataStorageInterface.startSerialize()
            /* Loop until all data is read from the input stream */
            DownloadHandler --> DownloadHandler.readBytes()
            DownloadHandler --> DownloadHandler.writeBytes()
          DownloadHandler --> DataStorageInterface.finishSerialize()
    DataManager --> DownloadHandler.isBusy()
    DataManager --> DownloadHandler.isComplete()
    DataManager --> DownloadHandler.isSuccess()    


/* Use Case #3: Load data table to DB */

  CallingApplication --> DataManager.loadDataToDB()
    DataManager --> DatabaseHandler.generateTable()
      DatabaseHandler --> TableMonitor.isTableInDB()
        /* if false */
        DatabaseHandler --> DatabaseAdapter.generateDDL()
          DatabaseAdapter --> DatabaseAdapter.getDataTypeMap()
        DatabaseHandler --> TableMonitor.addTableEntry()

        /* If the metadata can tell us the table size, and we are exceeding
           the allowed DB size, drop a table now before loading a new table
           into the DB */
        DatabaseHandler --> Entity.getTableSize()
          /* if database size exceeded */
          DatabaseHandler --> TableMonitor.dropOldestTable()
            TableMonitor --> TableMonitor.dropTableEntry()
          DatabaseHandler --> DatabaseHandler.dropTable()
            DatabaseHandler --> DatabaseAdapter.generateDropTableSQL()
          /* end if database size exceeded */
        /* end if false */

    DataManager --> DatabaseHandler.loadData()
      DatabaseHandler --> Entity.getDownloadHandler()
      DatabaseHandler --> DataStorageInterface.doesDataExist()

      /* if does exist */
        DownloadHandler --> DataStorageInterface.load()      
      /* else if does not exist */
        DownloadHandler --> DownloadHandler.getStorageClasses()
        DownloadHandler --> Thread.start()
        DownloadHandler --> DownloadHandler.run()
          /* For all DataStorageInterface objects */
          DownloadHandler --> DataStorageInterface.startSerialize()
            /* Loop until all data is read from the input stream */
            DownloadHandler --> DownloadHandler.readBytes()
            /* Write once to calling application and again to DatabaseHandler */
            DownloadHandler --> DownloadHandler.writeBytes()
            DownloadHandler --> DownloadHandler.writeBytes()
          DownloadHandler --> DataStorageInterface.finishSerialize()
      /* end if does exist */

      DatabaseHandler --> Entity.isSimpleDelimited() /* Determine physical format */
      DatabaseHandler --> createTextDataReader()   /* Of the appropriate subclass */
      DatabaseHandler --> TextDataReader.getOneRowDataVector()
      DatabaseHandler --> DatabaseAdapter.generateInsertSQL()
      DatabaseHandler --> DatabaseHandler.insertRow()
      /* check for failure of database insert due to space limitation or
         invalid data */

      /* Now we know the table size. If we didn't know it earlier, check again
        to see whether we need to drop old tables from the cache. */
      /* if database size exceeded */
      DatabaseHandler --> TableMonitor.dropOldestTable()
        TableMonitor --> TableMonitor.dropTableEntry()
      DatabaseHandler --> DatabaseHandler.dropTable()
        DatabaseHandler --> DatabaseAdapter.generateDropTableSQL()
      /* end if database size exceeded */


/* Use Case #4: Select data */

  CallingApplication --> DataManager.selectData()    /* Uses Cases #1, #2, #3 */
    DataManager --> DataManager.loadDataToDB()
    DataManager --> DatabaseHandler.selectData()
      DatabaseHandler --> DatabaseAdapter.transformSelectionSQL()
    DataManager --> TableMonitor.setLastUsageDate()


/* Use Case #5: Set database size */

  CallingApplication --> DataManager.setDatabaseSize()
    DataManager --> TableMonitor.setDBSize()


/* Use Case #6: Set table life priority */

  CallingApplication --> DataManager.setTableExpirationPolicy()
    DataManager --> TableMonitor.setTableExpirationPolicy()