Files
simulation_core/lib/Migrant/Migrant/ObjectIdentifier.cs

216 lines
7.4 KiB
C#

//
// Copyright (c) 2012-2024 Antmicro
//
// This file is licensed under the MIT License.
// Full license text is available in the LICENSE file.
using System;
using System.Runtime.Serialization;
using System.Collections.Generic;
namespace Antmicro.Migrant
{
/// <summary>
/// Gives consecutive, unique identifiers for presented objects during its lifetime.
/// Can also be used to retrive an object by its ID.
/// </summary>
/// <remarks>
/// The first returned id is 0. For given object, if it was presented to the class
/// earlier, the previously returned identificator is returned again. Note that the
/// objects presented to class are remembered, so they will not be collected until
/// the <c>ObjectIdentifier</c> lives.
/// </remarks>
public class ObjectIdentifier
{
/// <summary>
/// Initializes a new instance of the <see cref="Antmicro.Migrant.ObjectIdentifier"/> class.
/// </summary>
public ObjectIdentifier()
{
objectToId = new Dictionary<object, int>();
idToObject = new List<object>();
surrogateToObject = new Dictionary<object, object>();
}
/// <summary>
/// Initializes a new instance of the <see cref="Antmicro.Migrant.ObjectIdentifier"/> class, reusing given context.
/// </summary>
/// <param name="context">Context to reuse.</param>
public ObjectIdentifier(ObjectIdentifierContext context)
{
objectToId = new Dictionary<object, int>();
idToObject = context.GetObjects();
for(var i = 0; i < idToObject.Count; i++)
{
var objectToAdd = idToObject[i];
if(objectToAdd != null)
{
objectToId.Add(idToObject[i], i);
}
}
}
/// <summary>
/// Gets the context of object identifier that can be used for open stream serialization.
/// </summary>
public ObjectIdentifierContext GetContext()
{
return new ObjectIdentifierContext(idToObject);
}
/// <summary>
/// For a given object, returns its unique ID. The new ID is used if object was
/// not presented to this class earlier, otherwise the previously returned is used.
/// </summary>
/// <returns>
/// The object's unique ID.
/// </returns>
/// <param name='o'>
/// An object to give unique ID for.
/// </param>
/// <param name='isNew'>
/// Out parameter specifying if returned id has just been generated.
/// </param>
public int GetId(object o, out bool isNew)
{
int id;
if(objectToId.TryGetValue(o, out id))
{
isNew = false;
return id;
}
isNew = true;
id = idToObject.Count;
objectToId.Add(o, id);
idToObject.Add(o);
return id;
}
/// <summary>
/// For a given object, returns its unique ID. The new ID is used if object was
/// not presented to this class earlier, otherwise the previously returned is used.
/// </summary>
/// <returns>
/// The object's unique ID.
/// </returns>
/// <param name='o'>
/// An object to give unique ID for.
/// </param>
public int GetId(object o)
{
bool fake;
return GetId(o, out fake);
}
/// <summary>
/// Sets new identifier for object.
///
/// REMARK: Setting new mapping of object to id
/// does not remove the old one. As a reuslt,
/// after this operation asking for id of old
/// object and new object results in returing
/// the same identifier. This behaviour is intended
/// to support surrogated objects.
///
/// </summary>
/// <returns>The new identifier for object.</returns>
/// <param name="o">Object</param>
/// <param name="id">Identifier</param>
public void SetIdentifierForObject(object o, int id)
{
objectToId[o] = id;
idToObject[id] = o;
}
/// <summary>
/// For an ID which was previously returned by the <see cref="Antmicro.Migrant.ObjectIdentifier.GetId(object, out bool)" /> method,
/// returns an object for which this ID was generated.
/// </summary>
/// <returns>
/// The object for which given ID was returned.
/// </returns>
/// <param name='id'>
/// The unique ID, previously returned by the <see cref="Antmicro.Migrant.ObjectIdentifier.GetId(object, out bool)" /> method.
/// </param>
public object GetObject(int id)
{
if(idToObject.Count <= id || id < 0)
{
throw new ArgumentOutOfRangeException("id");
}
return idToObject[id];
}
/// <summary>
/// Adds an object to the collection that keeps track of all the surrogated objects.
/// </summary>
/// <param name="surrogate">
/// An instance of a surrogate for object o."
/// </param>
/// <param name="o">
/// A reference to the original object that will be surrogated during serialization.
/// </param>
public void AddSurrogatedObject(object surrogate, object o)
{
surrogateToObject[surrogate] = o;
}
/// <summary>
/// Returns an object added previously by the <see cref="Antmicro.Migrant.ObjectIdentifier.AddSurrogatedObject(object, object)" /> method.
/// </summary>
/// <param name="surrogate">
/// An instance of a surrogate for object o."
/// </param>
/// <param name="o">
/// A reference to the original object that will be surrogated during serialization.
/// </param>
/// <returns></returns>
public bool TryGetSurrogatedObject(object surrogate, out object o)
{
return surrogateToObject.TryGetValue(surrogate, out o);
}
/// <summary>
/// For an ID which was previously returned by the <see cref="Antmicro.Migrant.ObjectIdentifier.GetId(object, out bool)" /> method,
/// returns an object for which this ID was generated.
/// </summary>
/// <param name='id'>
/// The unique ID, previously returned by the <see cref="Antmicro.Migrant.ObjectIdentifier.GetId(object, out bool)" /> method.
/// </param>
public object this[int id]
{
get
{
return GetObject(id);
}
}
/// <summary>
/// Gets the count of the unique objects presented to class. It is also
/// the first unoccupied ID which will be returned for the new object.
/// </summary>
public int Count
{
get
{
return idToObject.Count;
}
}
/// <summary>
/// Clears internal elements.
/// </summary>
public void Clear()
{
idToObject.Clear();
objectToId.Clear();
}
private readonly Dictionary<object, int> objectToId;
private readonly List<object> idToObject;
private readonly Dictionary<object, object> surrogateToObject;
}
}