void DatabaseWrapperBase::AddAttachment(int64_t id,
                                        const FileInfo& attachment)
{
    SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO AttachedFiles VALUES(?, ?, ?, ?, ?, ?, ?, ?)");
    s.BindInt64(0, id);
    s.BindInt(1, attachment.GetContentType());
    s.BindString(2, attachment.GetUuid());
    s.BindInt64(3, attachment.GetCompressedSize());
    s.BindInt64(4, attachment.GetUncompressedSize());
    s.BindInt(5, attachment.GetCompressionType());
    s.BindString(6, attachment.GetUncompressedMD5());
    s.BindString(7, attachment.GetCompressedMD5());
    s.Run();
}
TEST(StorageAccessor, Compression)
{
  FilesystemStorage s("UnitTestsStorage");
  StorageAccessor accessor(s);

  std::string data = "Hello world";
  FileInfo info = accessor.Write(data, FileContentType_DicomAsJson, CompressionType_ZlibWithSize, true);
  
  std::string r;
  accessor.Read(r, info);

  ASSERT_EQ(data, r);
  ASSERT_EQ(CompressionType_ZlibWithSize, info.GetCompressionType());
  ASSERT_EQ(11u, info.GetUncompressedSize());
  ASSERT_EQ(FileContentType_DicomAsJson, info.GetContentType());
  ASSERT_EQ("3e25960a79dbc69b674cd4ec67a72c62", info.GetUncompressedMD5());
  ASSERT_NE(info.GetUncompressedMD5(), info.GetCompressedMD5());
}
TEST_P(DatabaseWrapperTest, Simple)
{
  int64_t a[] = {
    index_->CreateResource("a", ResourceType_Patient),   // 0
    index_->CreateResource("b", ResourceType_Study),     // 1
    index_->CreateResource("c", ResourceType_Series),    // 2
    index_->CreateResource("d", ResourceType_Instance),  // 3
    index_->CreateResource("e", ResourceType_Instance),  // 4
    index_->CreateResource("f", ResourceType_Instance),  // 5
    index_->CreateResource("g", ResourceType_Study)      // 6
  };

  ASSERT_EQ("a", index_->GetPublicId(a[0]));
  ASSERT_EQ("b", index_->GetPublicId(a[1]));
  ASSERT_EQ("c", index_->GetPublicId(a[2]));
  ASSERT_EQ("d", index_->GetPublicId(a[3]));
  ASSERT_EQ("e", index_->GetPublicId(a[4]));
  ASSERT_EQ("f", index_->GetPublicId(a[5]));
  ASSERT_EQ("g", index_->GetPublicId(a[6]));

  ASSERT_EQ(ResourceType_Patient, index_->GetResourceType(a[0]));
  ASSERT_EQ(ResourceType_Study, index_->GetResourceType(a[1]));
  ASSERT_EQ(ResourceType_Series, index_->GetResourceType(a[2]));
  ASSERT_EQ(ResourceType_Instance, index_->GetResourceType(a[3]));
  ASSERT_EQ(ResourceType_Instance, index_->GetResourceType(a[4]));
  ASSERT_EQ(ResourceType_Instance, index_->GetResourceType(a[5]));
  ASSERT_EQ(ResourceType_Study, index_->GetResourceType(a[6]));

  {
    std::list<std::string> t;
    index_->GetAllPublicIds(t, ResourceType_Patient);

    ASSERT_EQ(1u, t.size());
    ASSERT_EQ("a", t.front());

    index_->GetAllPublicIds(t, ResourceType_Series);
    ASSERT_EQ(1u, t.size());
    ASSERT_EQ("c", t.front());

    index_->GetAllPublicIds(t, ResourceType_Study);
    ASSERT_EQ(2u, t.size());

    index_->GetAllPublicIds(t, ResourceType_Instance);
    ASSERT_EQ(3u, t.size());
  }

  index_->SetGlobalProperty(GlobalProperty_FlushSleep, "World");

  index_->AttachChild(a[0], a[1]);
  index_->AttachChild(a[1], a[2]);
  index_->AttachChild(a[2], a[3]);
  index_->AttachChild(a[2], a[4]);
  index_->AttachChild(a[6], a[5]);

  int64_t parent;
  ASSERT_FALSE(index_->LookupParent(parent, a[0]));
  ASSERT_TRUE(index_->LookupParent(parent, a[1])); ASSERT_EQ(a[0], parent);
  ASSERT_TRUE(index_->LookupParent(parent, a[2])); ASSERT_EQ(a[1], parent);
  ASSERT_TRUE(index_->LookupParent(parent, a[3])); ASSERT_EQ(a[2], parent);
  ASSERT_TRUE(index_->LookupParent(parent, a[4])); ASSERT_EQ(a[2], parent);
  ASSERT_TRUE(index_->LookupParent(parent, a[5])); ASSERT_EQ(a[6], parent);
  ASSERT_FALSE(index_->LookupParent(parent, a[6]));

  std::string s;

  CheckNoParent(a[0]);
  CheckNoParent(a[6]);
  CheckParentPublicId("a", a[1]);
  CheckParentPublicId("b", a[2]);
  CheckParentPublicId("c", a[3]);
  CheckParentPublicId("c", a[4]);
  CheckParentPublicId("g", a[5]);

  std::list<std::string> l;
  index_->GetChildrenPublicId(l, a[0]); ASSERT_EQ(1u, l.size()); ASSERT_EQ("b", l.front());
  index_->GetChildrenPublicId(l, a[1]); ASSERT_EQ(1u, l.size()); ASSERT_EQ("c", l.front());
  index_->GetChildrenPublicId(l, a[3]); ASSERT_EQ(0u, l.size()); 
  index_->GetChildrenPublicId(l, a[4]); ASSERT_EQ(0u, l.size()); 
  index_->GetChildrenPublicId(l, a[5]); ASSERT_EQ(0u, l.size()); 
  index_->GetChildrenPublicId(l, a[6]); ASSERT_EQ(1u, l.size()); ASSERT_EQ("f", l.front());

  index_->GetChildrenPublicId(l, a[2]); ASSERT_EQ(2u, l.size()); 
  if (l.front() == "d")
  {
    ASSERT_EQ("e", l.back());
  }
  else
  {
    ASSERT_EQ("d", l.back());
    ASSERT_EQ("e", l.front());
  }

  std::list<MetadataType> md;
  index_->ListAvailableMetadata(md, a[4]);
  ASSERT_EQ(0u, md.size());

  index_->AddAttachment(a[4], FileInfo("my json file", FileContentType_DicomAsJson, 42, "md5", 
                                       CompressionType_Zlib, 21, "compressedMD5"));
  index_->AddAttachment(a[4], FileInfo("my dicom file", FileContentType_Dicom, 42, "md5"));
  index_->AddAttachment(a[6], FileInfo("world", FileContentType_Dicom, 44, "md5"));
  index_->SetMetadata(a[4], MetadataType_Instance_RemoteAet, "PINNACLE");
  
  index_->ListAvailableMetadata(md, a[4]);
  ASSERT_EQ(1u, md.size());
  ASSERT_EQ(MetadataType_Instance_RemoteAet, md.front());
  index_->SetMetadata(a[4], MetadataType_ModifiedFrom, "TUTU");
  index_->ListAvailableMetadata(md, a[4]);
  ASSERT_EQ(2u, md.size());

  std::map<MetadataType, std::string> md2;
  index_->GetAllMetadata(md2, a[4]);
  ASSERT_EQ(2u, md2.size());
  ASSERT_EQ("TUTU", md2[MetadataType_ModifiedFrom]);
  ASSERT_EQ("PINNACLE", md2[MetadataType_Instance_RemoteAet]);

  index_->DeleteMetadata(a[4], MetadataType_ModifiedFrom);
  index_->ListAvailableMetadata(md, a[4]);
  ASSERT_EQ(1u, md.size());
  ASSERT_EQ(MetadataType_Instance_RemoteAet, md.front());

  index_->GetAllMetadata(md2, a[4]);
  ASSERT_EQ(1u, md2.size());
  ASSERT_EQ("PINNACLE", md2[MetadataType_Instance_RemoteAet]);


  ASSERT_EQ(21u + 42u + 44u, index_->GetTotalCompressedSize());
  ASSERT_EQ(42u + 42u + 44u, index_->GetTotalUncompressedSize());

  index_->SetMainDicomTag(a[3], DicomTag(0x0010, 0x0010), "PatientName");

  int64_t b;
  ResourceType t;
  ASSERT_TRUE(index_->LookupResource(b, t, "g"));
  ASSERT_EQ(7, b);
  ASSERT_EQ(ResourceType_Study, t);

  ASSERT_TRUE(index_->LookupMetadata(s, a[4], MetadataType_Instance_RemoteAet));
  ASSERT_FALSE(index_->LookupMetadata(s, a[4], MetadataType_Instance_IndexInSeries));
  ASSERT_EQ("PINNACLE", s);

  std::string u;
  ASSERT_TRUE(index_->LookupMetadata(u, a[4], MetadataType_Instance_RemoteAet));
  ASSERT_EQ("PINNACLE", u);
  ASSERT_FALSE(index_->LookupMetadata(u, a[4], MetadataType_Instance_IndexInSeries));

  ASSERT_TRUE(index_->LookupGlobalProperty(s, GlobalProperty_FlushSleep));
  ASSERT_FALSE(index_->LookupGlobalProperty(s, static_cast<GlobalProperty>(42)));
  ASSERT_EQ("World", s);

  FileInfo att;
  ASSERT_TRUE(index_->LookupAttachment(att, a[4], FileContentType_DicomAsJson));
  ASSERT_EQ("my json file", att.GetUuid());
  ASSERT_EQ(21u, att.GetCompressedSize());
  ASSERT_EQ("md5", att.GetUncompressedMD5());
  ASSERT_EQ("compressedMD5", att.GetCompressedMD5());
  ASSERT_EQ(42u, att.GetUncompressedSize());
  ASSERT_EQ(CompressionType_Zlib, att.GetCompressionType());

  ASSERT_TRUE(index_->LookupAttachment(att, a[6], FileContentType_Dicom));
  ASSERT_EQ("world", att.GetUuid());
  ASSERT_EQ(44u, att.GetCompressedSize());
  ASSERT_EQ("md5", att.GetUncompressedMD5());
  ASSERT_EQ("md5", att.GetCompressedMD5());
  ASSERT_EQ(44u, att.GetUncompressedSize());
  ASSERT_EQ(CompressionType_None, att.GetCompressionType());

  ASSERT_EQ(0u, listener_->deletedFiles_.size());
  ASSERT_EQ(0u, listener_->deletedResources_.size());

  CheckTableRecordCount(7, "Resources");
  CheckTableRecordCount(3, "AttachedFiles");
  CheckTableRecordCount(1, "Metadata");
  CheckTableRecordCount(1, "MainDicomTags");

  index_->DeleteResource(a[0]);
  ASSERT_EQ(5u, listener_->deletedResources_.size());
  ASSERT_EQ(2u, listener_->deletedFiles_.size());
  ASSERT_FALSE(std::find(listener_->deletedFiles_.begin(), 
                         listener_->deletedFiles_.end(),
                         "my json file") == listener_->deletedFiles_.end());
  ASSERT_FALSE(std::find(listener_->deletedFiles_.begin(), 
                         listener_->deletedFiles_.end(),
                         "my dicom file") == listener_->deletedFiles_.end());

  CheckTableRecordCount(2, "Resources");
  CheckTableRecordCount(0, "Metadata");
  CheckTableRecordCount(1, "AttachedFiles");
  CheckTableRecordCount(0, "MainDicomTags");

  index_->DeleteResource(a[5]);
  ASSERT_EQ(7u, listener_->deletedResources_.size());

  CheckTableRecordCount(0, "Resources");
  CheckTableRecordCount(0, "AttachedFiles");
  CheckTableRecordCount(2, "GlobalProperties");

  ASSERT_EQ(3u, listener_->deletedFiles_.size());
  ASSERT_FALSE(std::find(listener_->deletedFiles_.begin(), 
                         listener_->deletedFiles_.end(),
                         "world") == listener_->deletedFiles_.end());
}