Skip to content

Commit

Permalink
Merge pull request #3 from vitrivr/feature/segment-metadata
Browse files Browse the repository at this point in the history
Refactored metadata retrieval and implemented segment metadata retrieval
  • Loading branch information
Spiess authored Oct 26, 2021
2 parents f37e031 + fd3dec4 commit a9ad36f
Show file tree
Hide file tree
Showing 11 changed files with 258 additions and 141 deletions.
195 changes: 80 additions & 115 deletions Runtime/Vitrivr/UnityInterface/CineastApi/Model/Data/MetadataStore.cs
Original file line number Diff line number Diff line change
@@ -1,116 +1,81 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Org.Vitrivr.CineastApi.Model;
using UnityEngine;

namespace Vitrivr.UnityInterface.CineastApi.Model.Data
{
/// <summary>
/// Access and local representation of metadata
/// </summary>
[Serializable]
public class MetadataStore
{
public MetadataStore(string id)
{
ObjectId = id;
Initialized = false;
}

/// <summary>
/// Actual internal storage of metadata
/// </summary>
private Dictionary<string, Dictionary<string, string>> _storage =
new Dictionary<string, Dictionary<string, string>>();

public string ObjectId { get; private set; }

public bool Initialized { get; private set; }

public void Initialize(MediaObjectMetadataQueryResult data)
{
if (Initialized)
{
Debug.LogWarning("Attempt to init already init'ed metadata container using cache data");
return;
}

foreach (var meta in data.Content.Where(meta => meta.ObjectId == ObjectId))
{
if (!DomainExists(meta.Domain))
{
_storage.Add(meta.Domain, new Dictionary<string, string>());
}

var domain = _storage[meta.Domain];
domain.Add(meta.Key, meta.Value);
}

Initialized = true;
}

public async Task InitializeAsync()
{
if (Initialized)
{
Debug.LogWarning($"Attempted to initialize already initialized metadata for media object {ObjectId}!");
return;
}

var metadataResult = await CineastWrapper.MetadataApi.FindMetaByIdAsync(ObjectId);
if (!Initialized)
{
Initialize(metadataResult);
}
}

public async Task<Dictionary<string, Dictionary<string, string>>> GetAll()
{
if (!Initialized)
{
await InitializeAsync();
}

return _storage;
}

public bool DomainExists(string domain)
{
return _storage.ContainsKey(domain);
}

public string Get(string domain, string key)
{
return _storage[domain][key];
}

/// <summary>
/// Retrieves a metadata value using the DOMAIN.KEY notation
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
public string Get(string str)
{
var domainAndKey = str.Split('.');
if (domainAndKey.Length >= 1)
{
return _storage[domainAndKey[0]][domainAndKey[1]];
}

throw new ArgumentException("Cannot retrieve without domain");
}

public List<(string Key, string Value)> GetDomain(string domain)
{
var items = _storage[domain];
return items.Keys.Select(key => (key, items[key])).ToList();
}

public bool Exists(string domain, string key)
{
return DomainExists(domain) && _storage[domain].ContainsKey(key);
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using UnityEngine.Assertions;

namespace Vitrivr.UnityInterface.CineastApi.Model.Data
{
[Serializable]
public abstract class MetadataStore
{
/// <summary>
/// Actual internal storage of metadata
/// </summary>
protected Dictionary<string, Dictionary<string, string>> Storage =
new Dictionary<string, Dictionary<string, string>>();

public bool Initialized { get; protected set; }

public abstract Task InitializeAsync();

public async Task<Dictionary<string, Dictionary<string, string>>> GetAll()
{
if (!Initialized)
{
await InitializeAsync();
}

return Storage;
}

public bool DomainExists(string domain)
{
Assert.IsTrue(Initialized);
return Storage.ContainsKey(domain);
}

public string Get(string domain, string key)
{
Assert.IsTrue(Initialized);
return Storage[domain][key];
}

/// <summary>
/// Retrieves a metadata value using the DOMAIN.KEY notation.
/// Requires metadata to be initialized.
/// </summary>
public string Get(string str)
{
Assert.IsTrue(Initialized);
var domainAndKey = str.Split('.');
if (domainAndKey.Length >= 1)
{
return Storage[domainAndKey[0]][domainAndKey[1]];
}

throw new ArgumentException("Cannot retrieve without domain");
}

/// <summary>
/// Retrieves all metadata of a specific domain.
/// Requires metadata to be initialized.
/// </summary>
public List<(string Key, string Value)> GetDomain(string domain)
{
Assert.IsTrue(Initialized);
var items = Storage[domain];
return items.Keys.Select(key => (key, items[key])).ToList();
}

/// <summary>
/// Checks if a domain key pair exists in the metadata.
/// Requires metadata to be initialized.
/// </summary>
public bool Exists(string domain, string key)
{
Assert.IsTrue(Initialized);
return DomainExists(domain) && Storage[domain].ContainsKey(key);
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -31,24 +31,24 @@ public class ObjectData
/// </summary>
private List<SegmentData> _segments;

public ObjectMetadataStore Metadata { get; private set; }

/// <summary>
/// Constructs a new instance with the given id, for lazy loading.
/// </summary>
/// <param name="id"></param>
public ObjectData(string id)
{
_id = id;
Metadata = new MetadataStore(_id);
Metadata = new ObjectMetadataStore(_id);
}

/// <summary>
/// Constructs a new instance with the given wrapper content.
/// </summary>
/// <param name="descriptor"></param>
public ObjectData(MediaObjectDescriptor descriptor)
{
_id = descriptor.ObjectId;
Metadata = new MetadataStore(_id);
Metadata = new ObjectMetadataStore(_id);
Initialize(descriptor);
}

Expand All @@ -57,8 +57,6 @@ public ObjectData(MediaObjectDescriptor descriptor)
/// </summary>
public bool Initialized { get; private set; }

public MetadataStore Metadata { get; private set; }

/// <summary>
/// ID of this object's <see cref="MediaObjectDescriptor" />
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Org.Vitrivr.CineastApi.Model;
using UnityEngine;

namespace Vitrivr.UnityInterface.CineastApi.Model.Data
{
/// <summary>
/// Access and local representation of metadata
/// </summary>
[Serializable]
public class ObjectMetadataStore : MetadataStore
{
public ObjectMetadataStore(string id)
{
ObjectId = id;
Initialized = false;
}

public string ObjectId { get; private set; }

public void Initialize(MediaObjectMetadataQueryResult data)
{
if (Initialized)
{
Debug.LogWarning("Attempt to init already init'ed metadata container using cache data");
return;
}

foreach (var meta in data.Content.Where(meta => meta.ObjectId == ObjectId))
{
if (!Storage.ContainsKey(meta.Domain))
{
Storage.Add(meta.Domain, new Dictionary<string, string>());
}

var domain = Storage[meta.Domain];
domain.Add(meta.Key, meta.Value);
}

Initialized = true;
}

public override async Task InitializeAsync()
{
if (Initialized)
{
Debug.LogWarning($"Attempted to initialize already initialized metadata for media object {ObjectId}!");
return;
}

var metadataResult = await CineastWrapper.MetadataApi.FindMetaByIdAsync(ObjectId);
if (!Initialized)
{
Initialize(metadataResult);
}
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -27,23 +27,27 @@ public class SegmentData
// TODO: Consider combining lazy loading requests into batch requests every x seconds to reduce request overhead
private static readonly SemaphoreSlim InitLock = new SemaphoreSlim(1, 1);

public SegmentMetadataStore Metadata { get; private set; }


public SegmentData(string id)
{
_id = id;
Metadata = new SegmentMetadataStore(_id);
}

public SegmentData(MediaSegmentDescriptor descriptor)
{
_descriptor = descriptor;
_id = descriptor.SegmentId;
Metadata = new SegmentMetadataStore(_id);
Initialized = true;
}

/// <summary>
/// Runs asynchronous segment ID query to initialize the data for this segment.
/// </summary>
private async Task InitializeAsync()
private async Task InitializeAsync(bool withMetadata = true)
{
await InitLock.WaitAsync();
try
Expand All @@ -63,6 +67,11 @@ private async Task InitializeAsync()

var result = queryResult.Content[0];
Initialize(result);

if (withMetadata)
{
await Metadata.InitializeAsync();
}
}
finally
{
Expand Down Expand Up @@ -94,6 +103,18 @@ public void Initialize(MediaSegmentDescriptor data)
Initialized = true;
}

public void InitializeMeta(MediaSegmentMetadataQueryResult meta)
{
if (Metadata.Initialized)
{
Debug.LogWarning("Attempt to initialize already initialized segment metadata for media object with " +
$"id \"{Id}\". Using cached data.");
return;
}

Metadata.Initialize(meta);
}

/// <summary>
/// ID of the <see cref="MediaSegmentDescriptor"/>
/// </summary>
Expand Down
Loading

0 comments on commit a9ad36f

Please sign in to comment.