/*
 *
 *  Copyright (C) 2008-2020, OFFIS e.V.
 *  All rights reserved.  See COPYRIGHT file for details.
 *
 *  This software and supporting documentation were developed by
 *
 *    OFFIS e.V.
 *    R&D Division Health
 *    Escherweg 2
 *    D-26121 Oldenburg, Germany
 *
 *
 *  Module:  dcmdata
 *
 *  Author:  Michael Onken
 *
 *  Purpose: Test program for testing path features of DcmItem
 *           and DcmSequenceOfItem
 *
 */

#include "dcmtk/config/osconfig.h"   /* make sure OS specific configuration is included first */
#include "dcmtk/ofstd/oftest.h"
#include "dcmtk/dcmdata/dctk.h"
#include "dcmtk/dcmdata/dcpath.h"


static OFLogger tpathLogger = OFLog::getLogger("dcmtk.test.tpath");

#define CHECK_GOOD(check) OFCHECK((check).good())

#define RETURN_ERROR(msg) do { \
    OFOStringStream oss; \
    OFCondition cond; \
    oss << msg << OFStringStream_ends; \
    OFSTRINGSTREAM_GETSTR(oss, str) \
    cond = makeOFCondition(OFM_dcmdata, 1, OF_error, str); \
    OFSTRINGSTREAM_FREESTR(str) \
    return cond; \
} while (0)


static OFCondition testPathInsertionsWithoutWildcard(const OFString& path,
                                                     DcmDataset *dset,
                                                     const Uint16& expectedNumObjects,
                                                     const OFBool& expectFailed = OFFalse,
                                                     const OFBool& createIfNecessary = OFTrue)
{
  DcmPathProcessor proc;
  OFCondition result = proc.findOrCreatePath(dset, path, createIfNecessary);
  if (result.bad())
  {
    if (!expectFailed)
    {
      OFLOG_DEBUG(tpathLogger, "Path: " << path << " ... FAILED!");
      RETURN_ERROR("Path " << (createIfNecessary ? "insertion" : "lookup") << " failed: " << result.text());
    }
    return EC_Normal;
  }

  // get results
  OFList< DcmPath* > results;
  Uint32 numResults = proc.getResults(results);
  if (numResults != 1)
  {
    // non-wildcard insertion should ALWAYS only return one result
    OFLOG_DEBUG(tpathLogger, "Path: " << path << " ... FAILED!");
    RETURN_ERROR("Returned path list does contain more than one result but no wildcard was specified");
  }
  DcmPath* oneResult = * (results.begin());

  if (oneResult->size() != expectedNumObjects)
  {
    if (!expectFailed)
    {
      OFLOG_DEBUG(tpathLogger, "Path: " << path << " ... FAILED!");
      RETURN_ERROR("Returned object list does not contain " << expectedNumObjects << " but only " << oneResult->size() << "elements");
    }
  }
  else
  {
    OFListIterator(DcmPathNode*) it = oneResult->begin();
    for (Uint16 i=0; i < expectedNumObjects; i++)
    {
      if (*it == NULL)
      {
        OFLOG_DEBUG(tpathLogger, "Path: " << path << " ... FAILED!");
        RETURN_ERROR("Path insertion failed: One of the created objects is NULL");
      }
      it++;
    }
  }

  OFLOG_DEBUG(tpathLogger, "Path: " << path << " ... OK");
  return EC_Normal;
}

static OFCondition testPathInsertionsWithWildcard(const OFString& path,
                                                  DcmDataset *dset,
                                                  const Uint16& expectedNumResults,
                                                  const OFBool& expectFailed = OFFalse,
                                                  const OFBool& createIfNecessary = OFTrue)
{
  DcmPathProcessor proc;
  OFCondition result = proc.findOrCreatePath(dset, path, createIfNecessary);
  if (result.bad())
  {
    if (!expectFailed)
    {
      OFLOG_DEBUG(tpathLogger, "Path: " << path << " ... FAILED!");
      RETURN_ERROR("Path " << (createIfNecessary ? "insertion" : "lookup") << " failed: " << result.text());
    }
    return EC_Normal;
  }

  // get results
  OFList< DcmPath* > results;
  Uint32 numResults = proc.getResults(results);
  if ( (numResults != expectedNumResults) && !expectFailed )
  {
    OFLOG_DEBUG(tpathLogger, "Path: " << path << " ... FAILED!");
    RETURN_ERROR("Expected " << expectedNumResults << " but " << numResults << " results were returned");
  }
  // check results
  OFListIterator(DcmPath*) oneResult = results.begin();
  while (oneResult != results.end())
  {
    if (*oneResult)
    {
      OFListIterator(DcmPathNode*) it = (*oneResult)->begin();
      while (it != (*oneResult)->end())
      {
        if (*it == NULL)
        {
          OFLOG_DEBUG(tpathLogger, "Path: " << path << " ... FAILED!");
          RETURN_ERROR("Path insertion failed: One of the result paths contains NULL");
        }
        it++;
      }
    }
    else
    {
      OFLOG_DEBUG(tpathLogger, "Path: " << path << " ... FAILED!");
      RETURN_ERROR("Path insertion failed: One of the returned paths is NULL");
    }
    oneResult++;
  }
  OFLOG_DEBUG(tpathLogger, "Path: " << path << " ... OK");
  return EC_Normal;
}

OFTEST(dcmdata_pathAccess)
{
  /* make sure data dictionary is loaded */
  if (!dcmDataDict.isDictionaryLoaded())
  {
    OFCHECK_FAIL("no data dictionary loaded, check environment variable: " DCM_DICT_ENVIRONMENT_VARIABLE);
    return;
  }

  DcmFileFormat dcmff;
  DcmDataset *dset = dcmff.getDataset();
  OFString path;
  const OFString precalculatedDump =  /* break the dump into smaller parts because MSVC6 only accepts 2048 character string constants maximum */
    "# Dicom-Data-Set\n# Used TransferSyntax: Unknown Transfer Syntax\n(0040,a730) SQ (Sequence with explicit length #=6)      #   0, 1 ContentSequence\n"
    "  (fffe,e000) na (Item with explicit length #=0)          #   0, 1 Item\n  (fffe,e00d) na (ItemDelimitationItem for re-encoding)   #   0, 0 ItemDelimitationItem\n"
    "  (fffe,e000) na (Item with explicit length #=0)          #   0, 1 Item\n  (fffe,e00d) na (ItemDelimitationItem for re-encoding)   #   0, 0 ItemDelimitationItem\n"
    "  (fffe,e000) na (Item with explicit length #=0)          #   0, 1 Item\n  (fffe,e00d) na (ItemDelimitationItem for re-encoding)   #   0, 0 ItemDelimitationItem\n"
    "  (fffe,e000) na (Item with explicit length #=0)          #   0, 1 Item\n  (fffe,e00d) na (ItemDelimitationItem for re-encoding)   #   0, 0 ItemDelimitationItem\n"
    "  (fffe,e000) na (Item with explicit length #=0)          #   0, 1 Item\n  (fffe,e00d) na (ItemDelimitationItem for re-encoding)   #   0, 0 ItemDelimitationItem\n"
    "  (fffe,e000) na (Item with explicit length #=1)          #   0, 1 Item\n    (0040,a730) SQ (Sequence with explicit length #=4)      #   0, 1 ContentSequence\n"
    "      (fffe,e000) na (Item with explicit length #=0)          #   0, 1 Item\n      (fffe,e00d) na (ItemDelimitationItem for re-encoding)   #   0, 0 ItemDelimitationItem\n"
    "      (fffe,e000) na (Item with explicit length #=0)          #   0, 1 Item\n      (fffe,e00d) na (ItemDelimitationItem for re-encoding)   #   0, 0 ItemDelimitationItem\n"
    "      (fffe,e000) na (Item with explicit length #=0)          #   0, 1 Item\n      (fffe,e00d) na (ItemDelimitationItem for re-encoding)   #   0, 0 ItemDelimitationItem\n"
    "      (fffe,e000) na (Item with explicit length #=1)          #   0, 1 Item\n        (0040,a043) SQ (Sequence with explicit length #=1)      #   0, 1 ConceptNameCodeSequence\n"
    "          (fffe,e000) na (Item with explicit length #=2)          #   0, 1 Item\n            (0008,0100) SH (no value available)                     #   0, 0 CodeValue\n"
    "            (0008,0104) LO (no value available)                     #   0, 0 CodeMeaning\n          (fffe,e00d) na (ItemDelimitationItem for re-encoding)   #   0, 0 ItemDelimitationItem\n"
    "        (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) #   0, 0 SequenceDelimitationItem\n      (fffe,e00d) na (ItemDelimitationItem for re-encoding)   #   0, 0 ItemDelimitationItem\n"
    "    (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) #   0, 0 SequenceDelimitationItem\n  (fffe,e00d) na (ItemDelimitationItem for re-encoding)   #   0, 0 ItemDelimitationItem\n"
    "(fffe,e0dd) na (SequenceDelimitationItem for re-encod.) #   0, 0 SequenceDelimitationItem\n";

  const OFString precalculatedDump2 =
    "# Dicom-Data-Set\n# Used TransferSyntax: Unknown Transfer Syntax\n(0010,0020) LO (no value available)                     #   0, 0 PatientID\n"
    "(0040,a730) SQ (Sequence with explicit length #=6)      #   0, 1 ContentSequence\n  (fffe,e000) na (Item with explicit length #=1)          #   0, 1 Item\n"
    "    (0040,a730) SQ (Sequence with explicit length #=4)      #   0, 1 ContentSequence\n      (fffe,e000) na (Item with explicit length #=1)          #   0, 1 Item\n"
    "        (0010,0020) LO (no value available)                     #   0, 0 PatientID\n      (fffe,e00d) na (ItemDelimitationItem for re-encoding)   #   0, 0 ItemDelimitationItem\n"
    "      (fffe,e000) na (Item with explicit length #=0)          #   0, 1 Item\n      (fffe,e00d) na (ItemDelimitationItem for re-encoding)   #   0, 0 ItemDelimitationItem\n"
    "      (fffe,e000) na (Item with explicit length #=0)          #   0, 1 Item\n      (fffe,e00d) na (ItemDelimitationItem for re-encoding)   #   0, 0 ItemDelimitationItem\n"
    "      (fffe,e000) na (Item with explicit length #=1)          #   0, 1 Item\n        (0010,0010) PN (no value available)                     #   0, 0 PatientName\n"
    "      (fffe,e00d) na (ItemDelimitationItem for re-encoding)   #   0, 0 ItemDelimitationItem\n    (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) #   0, 0 SequenceDelimitationItem\n"
    "  (fffe,e00d) na (ItemDelimitationItem for re-encoding)   #   0, 0 ItemDelimitationItem\n  (fffe,e000) na (Item with explicit length #=1)          #   0, 1 Item\n"
    "    (0040,a730) SQ (Sequence with explicit length #=4)      #   0, 1 ContentSequence\n      (fffe,e000) na (Item with explicit length #=1)          #   0, 1 Item\n"
    "        (0010,0020) LO (no value available)                     #   0, 0 PatientID\n      (fffe,e00d) na (ItemDelimitationItem for re-encoding)   #   0, 0 ItemDelimitationItem\n"
    "      (fffe,e000) na (Item with explicit length #=0)          #   0, 1 Item\n      (fffe,e00d) na (ItemDelimitationItem for re-encoding)   #   0, 0 ItemDelimitationItem\n"
    "      (fffe,e000) na (Item with explicit length #=0)          #   0, 1 Item\n      (fffe,e00d) na (ItemDelimitationItem for re-encoding)   #   0, 0 ItemDelimitationItem\n"
    "      (fffe,e000) na (Item with explicit length #=1)          #   0, 1 Item\n        (0010,0010) PN (no value available)                     #   0, 0 PatientName\n"
    "      (fffe,e00d) na (ItemDelimitationItem for re-encoding)   #   0, 0 ItemDelimitationItem\n    (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) #   0, 0 SequenceDelimitationItem\n"
    "  (fffe,e00d) na (ItemDelimitationItem for re-encoding)   #   0, 0 ItemDelimitationItem\n  (fffe,e000) na (Item with explicit length #=1)          #   0, 1 Item\n"
    "    (0040,a730) SQ (Sequence with explicit length #=4)      #   0, 1 ContentSequence\n      (fffe,e000) na (Item with explicit length #=1)          #   0, 1 Item\n"
    "        (0010,0020) LO (no value available)                     #   0, 0 PatientID\n      (fffe,e00d) na (ItemDelimitationItem for re-encoding)   #   0, 0 ItemDelimitationItem\n"
    "      (fffe,e000) na (Item with explicit length #=0)          #   0, 1 Item\n      (fffe,e00d) na (ItemDelimitationItem for re-encoding)   #   0, 0 ItemDelimitationItem\n"
    "      (fffe,e000) na (Item with explicit length #=0)          #   0, 1 Item\n      (fffe,e00d) na (ItemDelimitationItem for re-encoding)   #   0, 0 ItemDelimitationItem\n"
    "      (fffe,e000) na (Item with explicit length #=1)          #   0, 1 Item\n        (0010,0010) PN (no value available)                     #   0, 0 PatientName\n"
    "      (fffe,e00d) na (ItemDelimitationItem for re-encoding)   #   0, 0 ItemDelimitationItem\n    (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) #   0, 0 SequenceDelimitationItem\n"
    "  (fffe,e00d) na (ItemDelimitationItem for re-encoding)   #   0, 0 ItemDelimitationItem\n  (fffe,e000) na (Item with explicit length #=1)          #   0, 1 Item\n"
    "    (0040,a730) SQ (Sequence with explicit length #=4)      #   0, 1 ContentSequence\n      (fffe,e000) na (Item with explicit length #=1)          #   0, 1 Item\n"
    "        (0010,0020) LO (no value available)                     #   0, 0 PatientID\n      (fffe,e00d) na (ItemDelimitationItem for re-encoding)   #   0, 0 ItemDelimitationItem\n"
    "      (fffe,e000) na (Item with explicit length #=0)          #   0, 1 Item\n      (fffe,e00d) na (ItemDelimitationItem for re-encoding)   #   0, 0 ItemDelimitationItem\n"
    "      (fffe,e000) na (Item with explicit length #=0)          #   0, 1 Item\n      (fffe,e00d) na (ItemDelimitationItem for re-encoding)   #   0, 0 ItemDelimitationItem\n"
    "      (fffe,e000) na (Item with explicit length #=1)          #   0, 1 Item\n        (0010,0010) PN (no value available)                     #   0, 0 PatientName\n"
    "      (fffe,e00d) na (ItemDelimitationItem for re-encoding)   #   0, 0 ItemDelimitationItem\n    (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) #   0, 0 SequenceDelimitationItem\n"
    "  (fffe,e00d) na (ItemDelimitationItem for re-encoding)   #   0, 0 ItemDelimitationItem\n  (fffe,e000) na (Item with explicit length #=1)          #   0, 1 Item\n"
    "    (0040,a730) SQ (Sequence with explicit length #=4)      #   0, 1 ContentSequence\n      (fffe,e000) na (Item with explicit length #=1)          #   0, 1 Item\n"
    "        (0010,0020) LO (no value available)                     #   0, 0 PatientID\n      (fffe,e00d) na (ItemDelimitationItem for re-encoding)   #   0, 0 ItemDelimitationItem\n"
    "      (fffe,e000) na (Item with explicit length #=0)          #   0, 1 Item\n      (fffe,e00d) na (ItemDelimitationItem for re-encoding)   #   0, 0 ItemDelimitationItem\n"
    "      (fffe,e000) na (Item with explicit length #=0)          #   0, 1 Item\n      (fffe,e00d) na (ItemDelimitationItem for re-encoding)   #   0, 0 ItemDelimitationItem\n"
    "      (fffe,e000) na (Item with explicit length #=1)          #   0, 1 Item\n        (0010,0010) PN (no value available)                     #   0, 0 PatientName\n"
    "      (fffe,e00d) na (ItemDelimitationItem for re-encoding)   #   0, 0 ItemDelimitationItem\n    (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) #   0, 0 SequenceDelimitationItem\n"
    "  (fffe,e00d) na (ItemDelimitationItem for re-encoding)   #   0, 0 ItemDelimitationItem\n  (fffe,e000) na (Item with explicit length #=1)          #   0, 1 Item\n"
    "    (0040,a730) SQ (Sequence with explicit length #=4)      #   0, 1 ContentSequence\n      (fffe,e000) na (Item with explicit length #=1)          #   0, 1 Item\n"
    "        (0010,0020) LO (no value available)                     #   0, 0 PatientID\n      (fffe,e00d) na (ItemDelimitationItem for re-encoding)   #   0, 0 ItemDelimitationItem\n"
    "      (fffe,e000) na (Item with explicit length #=0)          #   0, 1 Item\n      (fffe,e00d) na (ItemDelimitationItem for re-encoding)   #   0, 0 ItemDelimitationItem\n"
    "      (fffe,e000) na (Item with explicit length #=0)          #   0, 1 Item\n      (fffe,e00d) na (ItemDelimitationItem for re-encoding)   #   0, 0 ItemDelimitationItem\n"
    "      (fffe,e000) na (Item with explicit length #=2)          #   0, 1 Item\n        (0010,0010) PN (no value available)                     #   0, 0 PatientName\n"
    "        (0040,a043) SQ (Sequence with explicit length #=1)      #   0, 1 ConceptNameCodeSequence\n          (fffe,e000) na (Item with explicit length #=2)          #   0, 1 Item\n"
    "            (0008,0100) SH (no value available)                     #   0, 0 CodeValue\n            (0008,0104) LO (no value available)                     #   0, 0 CodeMeaning\n"
    "          (fffe,e00d) na (ItemDelimitationItem for re-encoding)   #   0, 0 ItemDelimitationItem\n        (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) #   0, 0 SequenceDelimitationItem\n"
    "      (fffe,e00d) na (ItemDelimitationItem for re-encoding)   #   0, 0 ItemDelimitationItem\n    (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) #   0, 0 SequenceDelimitationItem\n"
    "  (fffe,e00d) na (ItemDelimitationItem for re-encoding)   #   0, 0 ItemDelimitationItem\n(fffe,e0dd) na (SequenceDelimitationItem for re-encod.) #   0, 0 SequenceDelimitationItem\n";

  const Uint32 precalculatedLength = 148;
  const Uint32 precalculatedLength2 = 464;

  /* ********************************************************************* */
  /* Test insertions using no wildcards                                    */
  /* ********************************************************************* */

  OFLOG_DEBUG(tpathLogger, "These insertions should work:\n"
                        << "=============================");
  path = "PatientID";
  CHECK_GOOD(testPathInsertionsWithoutWildcard(path, dset, 1));
  path = "ContentSequence";
  CHECK_GOOD(testPathInsertionsWithoutWildcard(path, dset, 1));
  path = "(0040,A730)";
  CHECK_GOOD(testPathInsertionsWithoutWildcard(path, dset, 1));
  path = "(0040,A730)[5]";
  CHECK_GOOD(testPathInsertionsWithoutWildcard(path, dset, 2));
  path = "(0040,A730)[5].ContentSequence[3].ConceptNameCodeSequence[0].CodeValue";
  CHECK_GOOD(testPathInsertionsWithoutWildcard(path, dset, 7));
  path = "ContentSequence[5].ContentSequence[3].ConceptNameCodeSequence[0].(0008,0104)";
  CHECK_GOOD(testPathInsertionsWithoutWildcard(path, dset, 7));

  OFLOG_DEBUG(tpathLogger, "\nThese insertions should NOT work (wrong syntax):\n"
                          << "================================================");

  path = "ContentSequences";
  CHECK_GOOD(testPathInsertionsWithoutWildcard(path, dset, 1, OFTrue));
  path = "(1234,ContentSequences";
  CHECK_GOOD(testPathInsertionsWithoutWildcard(path, dset, 1, OFTrue));
  path = "(00X4,A730)";
  CHECK_GOOD(testPathInsertionsWithoutWildcard(path, dset, 1, OFTrue));
  path = "(0040,A730)[-5]";
  CHECK_GOOD(testPathInsertionsWithoutWildcard(path, dset, 2, OFTrue));
  path = "(0040,A730)[a].ContentSequence[3].ConceptNameCodeSequence[0].CodeValue";
  CHECK_GOOD(testPathInsertionsWithoutWildcard(path, dset, 7, OFTrue));

  OFLOG_DEBUG(tpathLogger, "\nThese find routines should work:\n"
                          << "================================");

  path = "PatientID";
  CHECK_GOOD(testPathInsertionsWithoutWildcard(path, dset, 1, OFFalse, OFFalse /* do not create */));
  path = "ContentSequence";
  CHECK_GOOD(testPathInsertionsWithoutWildcard(path, dset, 1, OFFalse, OFFalse /* do not create */));
  path = "(0040,A730)";
  CHECK_GOOD(testPathInsertionsWithoutWildcard(path, dset, 1, OFFalse, OFFalse /* do not create */));
  path = "(0040,A730)[5]";
  CHECK_GOOD(testPathInsertionsWithoutWildcard(path, dset, 2, OFFalse, OFFalse /* do not create */));
  path = "(0040,A730)[5].ContentSequence[3].ConceptNameCodeSequence[0].CodeValue";
  CHECK_GOOD(testPathInsertionsWithoutWildcard(path, dset, 7, OFFalse, OFFalse /* do not create */));
  path = "ContentSequence[5].ContentSequence[3].ConceptNameCodeSequence[0].(0008,0104)";
  CHECK_GOOD(testPathInsertionsWithoutWildcard(path, dset, 7, OFFalse, OFFalse /* do not create */));

  OFLOG_DEBUG(tpathLogger, "\nThese find routines should NOT work:\n"
                          << "====================================");

  path = "PatientName"; // was never inserted
  CHECK_GOOD(testPathInsertionsWithoutWildcard(path, dset, 1, OFTrue, OFFalse /* do not create */));
  path = "(0040,A730)[6]"; // we only have 6 items in there (not 7)
  CHECK_GOOD(testPathInsertionsWithoutWildcard(path, dset, 2, OFTrue, OFFalse /* do not create */));
  path = "ConceptNameCodeSequence"; // should not exist on main level
  CHECK_GOOD(testPathInsertionsWithoutWildcard(path, dset, 1, OFTrue, OFFalse /* do not create */));

  OFLOG_DEBUG(tpathLogger, "\nChecking dataset length:\n"
                          << "========================");
  Uint32 length = dset->calcElementLength(EXS_LittleEndianExplicit,EET_ExplicitLength);
  if (length == precalculatedLength)
  {
    OFLOG_DEBUG(tpathLogger, "Checking whether length of encoded dataset matches pre-calculated length ... OK");
  }
  else
  {
    OFLOG_DEBUG(tpathLogger, "Checking whether length of encoded dataset matches pre-calculated length ... FAILED!");
    OFLOG_DEBUG(tpathLogger, "Length is " << length << ", but should be " << precalculatedLength);
    OFLOG_DEBUG(tpathLogger, "Please check dump and adapt test in case of false alarm:" << OFendl);
    OFLOG_DEBUG(tpathLogger, "Dump of assembled test object:");
    OFLOG_DEBUG(tpathLogger, DcmObject::PrintHelper(*dset));
    OFLOG_DEBUG(tpathLogger, "Dump of pre-defined template:" << OFendl);
    OFLOG_DEBUG(tpathLogger, precalculatedDump);
    OFCHECK_FAIL("Wrong length");
  }

  /* ********************************************************************* */
  /* Test insertions using wildcards                                       */
  /* ********************************************************************* */

  OFLOG_DEBUG(tpathLogger, "\nThese wildcard insertions should work:\n"
                          << "======================================");
  path = "ContentSequence[*].ContentSequence[3].PatientName";
  CHECK_GOOD(testPathInsertionsWithWildcard(path, dset, 6, OFFalse /* should work*/, OFTrue /*do create*/));
  path = "ContentSequence[*].ContentSequence[0].PatientID";
  CHECK_GOOD(testPathInsertionsWithWildcard(path, dset, 6, OFFalse /* should work*/, OFTrue /*do create*/));

  OFLOG_DEBUG(tpathLogger, "\nTesting wildcard insertions should NOT work:\n"
                          << "============================================");
  path = "SourceImageSequence[*]";
  CHECK_GOOD(testPathInsertionsWithWildcard(path, dset, 0, OFTrue /* should fail*/, OFTrue /*do create*/));
  path = "ContentSequence[*].SourceImageSequence[*]";
  CHECK_GOOD(testPathInsertionsWithWildcard(path, dset, 0, OFTrue /* should fail*/, OFTrue /*do create*/));

  OFLOG_DEBUG(tpathLogger, "\nChecking dataset length:\n"
                          << "========================");
  length = dset->calcElementLength(EXS_LittleEndianExplicit,EET_ExplicitLength);
  if (length == precalculatedLength2)
  {
    OFLOG_DEBUG(tpathLogger, "Checking whether length of encoded dataset matches pre-calculated length ... OK");
  }
  else
  {
    OFLOG_DEBUG(tpathLogger, "Checking whether length of encoded dataset matches pre-calculated length ... FAILED!");
    OFLOG_DEBUG(tpathLogger, "Length is " << length << ", but should be " << precalculatedLength2);
    OFLOG_DEBUG(tpathLogger, "Please check dump and adapt test in case of false alarm:" << OFendl);
    OFLOG_DEBUG(tpathLogger, "Dump of assembled test object:");
    OFLOG_DEBUG(tpathLogger, DcmObject::PrintHelper(*dset));
    OFLOG_DEBUG(tpathLogger, "Dump of pre-defined template:" << OFendl);
    OFLOG_DEBUG(tpathLogger, precalculatedDump2);
    OFCHECK_FAIL("Wrong length");
  }
}
