[CONNECT C++] ItemTypeLibraryMgr

I mentioned ItemTypeLibraryMgr in a post on the Forum.  It's a helper class to wrap common usage of the MicroStationAPI with Item Type libraries. Use at your own risk.  Support is not included.

You need these headers...

#include <Mstn/MdlApi/MdlApi.h>
#include <Mstn/MicroStation.r.h>
#include <DgnPlatform/DgnPlatform.r.h>
#include <ECObjects/ECObjects.h>

Here's the class declaration...

struct ItemTypeLibraryMgr
{
  const WString      libName_;
  ///  Construct an Item Type Library Manager for the named library.
  ItemTypeLibraryMgr    (WCharCP  libName) : libName_ (libName) {}
  ///  Determine if the Item Type Library exists in the active DGN file.
  bool        ExistsInActiveFile  ()  const;
  ///  Determine if the Item Type Library exists in a given DGN file.
  bool        ExistsInFile    (DgnFileR              dgnfile)  const;
  ///  Get a pointer to a library from the active DGN file.
  ItemTypeLibraryPtr  Get          ()  const;
  ///  Get a pointer to a library from a given DGN file.
  ItemTypeLibraryPtr  Get          (DgnFileR              dgnfile)  const;
  /// Find a library by searching DGNLibs.
  bool                FindAndCopyDefFromDgnLib    (WCharCP          libName)    const;
  /// Find a library by searching DGNLibs.
  /// This method below is fine, but we've taken a different route.
  bool                CopyFromDgnLib              (WCharCP            libName)    const;
  ///  Copy a library from a given DGN file to the active DGN file.
  ///  Returns  true if the copy succeeded.  
  bool        CopyToActive    (DgnFileR              dgnfile)  const;
  ///  Search for a named DgnLib.
  ///  Looks in folders specified by MS_DGNLIBLIST.
  ///  dgnLib: Pointer to a DGN file.
  ///  fileName: DgnLib name to seek. 
  ///  Returns true if DgnLib is found and our Item Type library is defined in that file.  
  bool        FindDgnLib (DgnFilePtr&         dgnLib,
                         WCharCP              fileName)  const;
  ///  Check whether our Item Type library is defined in the active DGN file.
  static  bool    EnsureAnnotatorLibraryIsAvailable  ();
  ///  Check whether a specified Item Type library is defined in the active DGN file.
  ///  If not defined, create Item Type and Report definitions.
  static  bool    EnsureLibraryIsAvailable  (WCharCP        libName,
                                            ItemDataCollectionCR  itemData,
                                            AggregatorCollectionCR  aggregateData,
                                            ReportDefsCR      reportDefs);

  ///  Warn about missing Item Type library: cannot proceed.
  static  void    WarnAndUnload        ();
};

Implementation: this uses the app's message lists stored in MDL resource files, which are not included here.

///////////////////////////////////////////////////////////////////////
bool    ItemTypeLibraryMgr::ExistsInActiveFile  ()  const
{
  DgnFileP  pDgnFile  { MicroStation::GetActiveDgnFile () };
  return ExistsInFile (*pDgnFile);
}
///////////////////////////////////////////////////////////////////////
bool    ItemTypeLibraryMgr::ExistsInFile    (DgnFileR    dgnfile)  const
{
  const ItemTypeLibraryPtr  lib      { Get (dgnfile) };
  return lib.IsValid ();
}
///////////////////////////////////////////////////////////////////////
ItemTypeLibraryPtr  ItemTypeLibraryMgr::Get      ()  const
{
  DgnFileP  pDgnFile  { MicroStation::GetActiveDgnFile () };
  return Get (*pDgnFile);
}
///////////////////////////////////////////////////////////////////////
ItemTypeLibraryPtr  ItemTypeLibraryMgr::Get      (DgnFileR      dgnFile)  const
{
  return ItemTypeLibrary::FindByName (libName_.c_str (), dgnFile);
}
///////////////////////////////////////////////////////////////////////
bool        ItemTypeLibraryMgr::CopyToActive  (DgnFileR      dgnFile)  const
{
  ItemTypeLibraryPtr    lib    { Get (dgnFile) };
  if (lib.IsValid ())
  {
    const bool       Replace  { true };
    ItemTypeLibraryPtr  clone   { lib->CloneForFile (*MicroStation::GetActiveDgnFile (), Replace)   };
    if (clone.IsValid ())
    {
      return clone->Write ();
    }
  }
  return false;
}
///////////////////////////////////////////////////////////////////////
bool    ItemTypeLibraryMgr::FindDgnLib      (DgnFilePtr&          dgnLib,
                          WCharCP              fileName)  const
{
  bool        found    { false };
  BeFileName      dgnLibFile;
  if (SUCCESS == mdlFile_find (&dgnLibFile, fileName, L"MS_DGNLIBLIST", nullptr))
  {
    DgnDocumentPtr  document  { DgnDocument::CreateForLocalFile (dgnLibFile.c_str ()) };
    dgnLib     = DgnFile::Create (*document, DgnFileOpenMode::ReadOnly);
    StatusInt       openForReadStatus { 0 };
    DgnPlatform::DgnFileStatus  dgnOpenStatus  = dgnLib->LoadDgnFile (&openForReadStatus);
      if (DGNFILE_STATUS_Success == dgnOpenStatus)
    {
      // TODO: not sure this is necessary
      dgnLib->FillDictionaryModel ();
      found  = ExistsInFile (*dgnLib);
    }
  }
  return found;
}
///////////////////////////////////////////////////////////////////////
//  static
void    ItemTypeLibraryMgr::WarnAndUnload        ()
{
  WString         error;
  mdlOutput_rscsPrintf (error, 0, MESSAGELIST_Errors, ERROR_DgnLib, ItemTypes::LibraryName ().c_str ());
  const long        msgAttributes  { 0 };
  NotifyMessageDetails  msg (OutputMessagePriority::Error, error.c_str (),  error.c_str (), msgAttributes, OutputMessageAlert::Dialog);
  NotificationManager::OutputMessage (msg);
  mdlDialog_cmdNumberQueue (false, CMD_MDL_UNLOAD, mdlSystem_getCurrTaskID (), MSInputQueuePos::INPUTQ_EOQ);
}
///////////////////////////////////////////////////////////////////////
//  static
bool    ItemTypeLibraryMgr::EnsureAnnotatorLibraryIsAvailable  ()
{
  return EnsureLibraryIsAvailable  (ItemTypes::LibraryName ().c_str (), g_itemData, g_aggregates, g_reportDefs);
}
///////////////////////////////////////////////////////////////////////
//  static
bool    ItemTypeLibraryMgr::EnsureLibraryIsAvailable  (WCharCP        libName,
                              ItemDataCollectionCR  itemData,
                              AggregatorCollectionCR  aggregateData,
                              ReportDefsCR      reportDefs)
{
  WString        announce;
  ItemTypeLibraryMgr  libMgr  (libName);
  bool        found  { libMgr.ExistsInActiveFile () };
  if (found)
  {
    ItemTypeLibraryPtr  pLib  { libMgr.Get () };
    mdlOutput_rscsPrintf (announce, 0, MESSAGELIST_Messages, MESSAGE_LibraryFound, libName);
    mdlOutput_messageCenter (DgnPlatform::OutputMessagePriority::Info, announce.c_str (), announce.c_str (), DgnPlatform::OutputMessageAlert::None);
  }
  else
  {
        SchemaDefinition schemaDef (libName, itemData);
        found   = schemaDef.Create ();

    mdlOutput_rscsPrintf (announce, 0, MESSAGELIST_Messages, MESSAGE_LibraryCreated, libName);
    mdlOutput_messageCenter (DgnPlatform::OutputMessagePriority::Info, announce.c_str (), announce.c_str (), DgnPlatform::OutputMessageAlert::None);
    }

    if (found)
    {
    const UInt32    nReports  { ReportDefinitions::ExistInActiveFile (reportDefs)};
    if (0 == nReports)
    {
        const UInt32  nNewReports { ReportDefinitions::Create (reportDefs) };
    }
  }

  return found;
}
///////////////////////////////////////////////////////////////////////
bool        ItemTypeLibraryMgr::CopyFromDgnLib (WCharCP    libName)  const
{
    ItemTypeLibraryMgr  libMgr (libName);
    bool        copied { false };
    if (!libMgr.ExistsInActiveFile ())
    {
        if (libMgr.FindAndCopyDefFromDgnLib (libName))
        {
            copied = true;
        }
        else
        {
            WString         warn;
            mdlOutput_rscsPrintf (warn, 0, MESSAGELIST_Errors, ERROR_DgnLibFind, libName);
            const long        msgAttributes {0};
            NotifyMessageDetails  notify (OutputMessagePriority::Warning, warn.c_str (), warn.c_str (), msgAttributes, OutputMessageAlert::Balloon);
            NotificationManager::OutputMessage (notify);
        }
    }
    return copied;
}
///////////////////////////////////////////////////////////////////////
bool        ItemTypeLibraryMgr::FindAndCopyDefFromDgnLib (WCharCP libName)    const
{
    bool        found { false };
    DgnFilePtr  dgnLibFile;
    if (FindDgnLib (dgnLibFile, libName))
    {
        if (ExistsInFile (*dgnLibFile))
        {
            ItemTypeLibraryPtr  pLib2 = Get (*dgnLibFile);
            if (CopyToActive (*dgnLibFile))
            {
                found = true;
                ItemTypeLibraryPtr  pLib3 = Get ();
            }
            else
            {
                WString         warn;
                mdlOutput_rscsPrintf (warn, 0, MESSAGELIST_Errors, ERROR_DgnLibCopy, ItemTypes::LibraryName ().c_str ());
                const long        msgAttributes {0};
                NotifyMessageDetails  notify (OutputMessagePriority::Warning, warn.c_str (), warn.c_str (), msgAttributes, OutputMessageAlert::Balloon);
                NotificationManager::OutputMessage (notify);
            }
        }
    }
    return found;
}