# GenFakeIdentifyFile.cxx

    /*=========================================================================

      Program: GDCM (Grassroots DICOM). A DICOM library
      Module:  $URL$

      Copyright (c) 2006-2010 Mathieu Malaterre
      All rights reserved.
      See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details.

         This software is distributed WITHOUT ANY WARRANTY; without even
         the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
         PURPOSE.  See the above copyright notice for more information.

    =========================================================================*/
    #include "gdcmReader.h"
    #include "gdcmGlobal.h"
    #include "gdcmDummyValueGenerator.h"
    #include "gdcmMediaStorage.h"
    #include "gdcmWriter.h"
    #include "gdcmItem.h"
    #include "gdcmImageReader.h"
    #include "gdcmSequenceOfItems.h"
    #include "gdcmAttribute.h"
    #include "gdcmFile.h"
    #include "gdcmTag.h"
    #include "gdcmDict.h"
    #include "gdcmDictEntry.h"
    #include "gdcmDicts.h"
    #include "gdcmTransferSyntax.h"
    #include "gdcmUIDGenerator.h"
    #include "gdcmAnonymizer.h"

    #include <cstdlib>
    #include <cstring>

    gdcm::DataElement CreateFakeElement(gdcm::Tag const &tag, bool toremove)
    {
      static const gdcm::Global &g = gdcm::Global::GetInstance();
      static const gdcm::Dicts &dicts = g.GetDicts();
      static const gdcm::Dict &pubdict = dicts.GetPublicDict();
      static size_t countglobal = 0;
      static std::vector<gdcm::Tag> balcptags =
        gdcm::Anonymizer::GetBasicApplicationLevelConfidentialityProfileAttributes();
      size_t count = countglobal % balcptags.size();

      const gdcm::DictEntry &dictentry = pubdict.GetDictEntry(tag);

      gdcm::DataElement de;
      de.SetTag( tag );
      using gdcm::VR;
      const VR &vr = dictentry.GetVR();
      //if( vr != VR::INVALID )
      if( vr.IsDual() )
        {
        if( vr == VR::US_SS )
          {
          de.SetVR( VR::US );
          }
        else if( vr == VR::US_SS_OW )
          {
          de.SetVR( VR::OW );
          }
        else if( vr == VR::OB_OW )
          {
          de.SetVR( VR::OB );
          }
        }
      else
        {
        de.SetVR( vr );
        }
      using gdcm::VR;
      const char str[] = "BasicApplicationLevelConfidentialityProfileAttributes";
      const char safe[] = "This is safe to keep";
      if( de.GetVR() != VR::SQ )
        {
        if( toremove )
          de.SetByteValue( str, strlen(str) );
        else
          de.SetByteValue( safe, strlen(safe) );
        }
      else
        {
        // Create an item
        gdcm::Item it;
        it.SetVLToUndefined();
        gdcm::DataSet &nds = it.GetNestedDataSet();
        // Insert sequence into data set
        assert(de.GetVR() == gdcm::VR::SQ );
        gdcm::SmartPointer<gdcm::SequenceOfItems> sq = new gdcm::SequenceOfItems();
        sq->SetLengthToUndefined();
        de.SetValue(*sq);
        de.SetVLToUndefined();
        //ds.Insert(de);

        if( !toremove )
          {
          nds.Insert( CreateFakeElement( balcptags[count], true ) );
          countglobal++;
          }
        else
          {
          gdcm::Attribute<0x0008,0x0000> at1 = { 0 }; // This element has no reason to be 'anonymized'...
          nds.Insert( at1.GetAsDataElement() );
          gdcm::Attribute<0x000a,0x0000> at2 = { 0 };
          nds.Insert( at2.GetAsDataElement() );
          }
        sq->AddItem(it);
        }
      return de;
    }

    /*
     */
    int main(int argc, char *argv[])
    {
      if( argc < 2 )
        {
        std::cerr << argv[0] << " output.dcm" << std::endl;
        return 1;
        }
      using gdcm::Tag;
      using gdcm::VR;
      const char *outfilename = argv[1];

      std::vector<gdcm::Tag> balcptags =
        gdcm::Anonymizer::GetBasicApplicationLevelConfidentialityProfileAttributes();

      gdcm::Writer w;
      gdcm::File &f = w.GetFile();
      gdcm::DataSet &ds = f.GetDataSet();

      // Add attribute that need to be anonymized:
      std::vector<gdcm::Tag>::const_iterator it = balcptags.begin();
      for(; it != balcptags.end(); ++it)
        {
        ds.Insert( CreateFakeElement( *it, true ) );
        }

      // Add attribute that do NOT need to be anonymized:
      static const gdcm::Global &g = gdcm::Global::GetInstance();
      static const gdcm::Dicts &dicts = g.GetDicts();
      static const gdcm::Dict &pubdict = dicts.GetPublicDict();

      using gdcm::Dict;
      Dict::ConstIterator dictit = pubdict.Begin();
      for(; dictit != pubdict.End(); ++dictit)
        {
        const gdcm::Tag &dicttag = dictit->first;
        if( dicttag == Tag(0x6e65,0x6146) ) break;
        const gdcm::DictEntry &dictentry = dictit->second;
        ds.Insert( CreateFakeElement( dicttag, false ) );
        }
      ds.Remove( gdcm::Tag(0x400,0x500) );
      ds.Remove( gdcm::Tag(0x12,0x62) );
      ds.Remove( gdcm::Tag(0x12,0x63) );

      // Make sure to override any UID stuff
      gdcm::UIDGenerator uid;
      gdcm::DataElement de( Tag(0x8,0x18) ); // SOP Instance UID
      de.SetVR( VR::UI );
      const char *u = uid.Generate();
      de.SetByteValue( u, strlen(u) );
      //ds.Insert( de );
      ds.Replace( de );

      de.SetTag( Tag(0x8,0x16) ); // SOP Class UID
      de.SetVR( VR::UI );
      gdcm::MediaStorage ms( gdcm::MediaStorage::RawDataStorage );
      de.SetByteValue( ms.GetString(), strlen(ms.GetString()));
      ds.Replace( de ); // replace !

      gdcm::FileMetaInformation &fmi = f.GetHeader();
      //fmi.SetDataSetTransferSyntax( gdcm::TransferSyntax::ImplicitVRLittleEndian );
      fmi.SetDataSetTransferSyntax( gdcm::TransferSyntax::ExplicitVRLittleEndian );

      w.SetCheckFileMetaInformation( true );
      w.SetFileName( outfilename );
      if (!w.Write() )
        {
        return 1;
        }

      return 0;
    }