ln.objects/ng/index/IndexPath.cs

436 lines
11 KiB
C#

using System;
using System.Collections.Generic;
using System.Collections;
using System.Reflection;
using System.Linq;
using System.Runtime.InteropServices.ComTypes;
using ln.objects.catalog;
namespace ln.types.odb.ng.index
{
public abstract class IndexPath
{
public static IndexPath Build(Path path)
{
if (path.Element == null)
return new FinalPath(path);
if (path.Element.Equals("[]"))
return new ListPath();
return new DocumentPath();
}
public abstract IEnumerable<Index> GetIndeces();
public abstract bool Ensure(Path path);
public abstract bool Indexed(Path path);
public virtual void Replace(Guid documentID, ODBEntity value)
{
Remove(documentID);
Add(documentID, value);
}
public abstract void Add(Guid documentID, ODBEntity value);
public abstract void Remove(Guid documentID);
public abstract IEnumerable<Guid> GetDocumentIDs(Path path, Predicate<ODBEntity> predicate);
public virtual IEnumerable<Guid> GetDocumentIDs(string path, Predicate<ODBEntity> predicate)
{
return GetDocumentIDs(SplitPath(path), predicate);
}
public class DocumentPath : IndexPath
{
Dictionary<string, IndexPath> children = new Dictionary<string, IndexPath>();
public DocumentPath()
{
}
public override IEnumerable<Guid> GetDocumentIDs(Path path, Predicate<ODBEntity> predicate)
{
return children[path.Element].GetDocumentIDs(path.Next, predicate);
}
public override IEnumerable<Index> GetIndeces()
{
return children.Values.SelectMany((arg) => arg.GetIndeces());
}
public override bool Indexed(Path path)
{
if (children.ContainsKey(path.Element))
return children[path.Element].Indexed(path.Next);
return false;
}
public override void Remove(Guid documentID)
{
foreach (IndexPath next in children.Values)
next.Remove(documentID);
}
public override void Add(Guid documentID, ODBEntity value)
{
foreach (string childName in children.Keys)
{
children[childName].Add(documentID, (value as Document)[childName]);
}
}
public override void Replace(Guid documentID, ODBEntity value)
{
foreach (string childName in children.Keys)
{
children[childName].Replace(documentID, (value as Document)[childName]);
}
}
public override bool Ensure(Path path)
{
bool added = false;
if (!children.ContainsKey(path.Element))
{
children.Add(path.Element, IndexPath.Build(path.Next));
added = true;
}
return children[path.Element].Ensure(path.Next) || added;
}
}
class ListPath : IndexPath
{
IndexPath nextPath;
public ListPath()
{
}
public override IEnumerable<Index> GetIndeces() => nextPath.GetIndeces();
public override bool Ensure(Path path)
{
bool added = false;
if (nextPath == null)
{
nextPath = IndexPath.Build(path.Next);
added = true;
}
return nextPath.Ensure(path.Next) || added;
}
public override bool Indexed(Path path)
{
return nextPath.Indexed(path.Next);
}
public override IEnumerable<Guid> GetDocumentIDs(Path path, Predicate<ODBEntity> predicate)
{
return nextPath.GetDocumentIDs(path.Next, predicate);
}
public override void Remove(Guid documentID)
{
nextPath.Remove(documentID);
}
public override void Add(Guid documentID, ODBEntity value)
{
if (!ODBNull.Instance.Equals(value))
foreach (ODBEntity v in ((ODBList)value))
{
nextPath.Add(documentID, v);
}
}
}
class FinalPath : IndexPath
{
Path indexPath;
Index index;
public FinalPath(Path indexPath)
{
this.indexPath = indexPath;
}
public override IEnumerable<Index> GetIndeces() => new Index[] { index };
public override bool Indexed(Path path) => true;
public override IEnumerable<Guid> GetDocumentIDs(Path path, Predicate<ODBEntity> predicate)
{
return index.GetDocumentIDs(predicate);
}
public override void Remove(Guid documentID)
{
index.Remove(documentID);
}
public override void Add(Guid documentID, ODBEntity value)
{
index.Add(documentID, value);
}
public override void Replace(Guid documentID, ODBEntity value)
{
index.Replace(documentID, value);
}
public override bool Ensure(Path path)
{
if (path.Element != null)
throw new NotSupportedException();
if (index == null)
{
index = new SimpleIndex(indexPath);
return true;
}
return false;
}
}
public static Path SplitPath(string path)
{
List<string> pathTokens = new List<string>();
foreach (string primaryToken in path.Split('.'))
{
string suffix = "";
string token = primaryToken;
int i = token.IndexOf('[');
if (i > 0)
{
suffix = token.Substring(i);
token = token.Substring(0, i);
}
pathTokens.Add(token);
string s = suffix;
while (s.Length > 0)
{
if (s.StartsWith("[]", StringComparison.InvariantCulture))
{
pathTokens.Add("[]");
s = s.Substring(2);
}
else
{
throw new NotSupportedException();
}
}
}
return new Path(pathTokens.ToArray());
}
public static string TranslatePropertyPath(Type elementType, string propPath)
{
String[] path = propPath.Split('.');
Type currentType = elementType;
for (int n = 0; n < path.Length; n++)
{
string suffix = "";
string token = path[n];
int i = token.IndexOf('[');
if (i > 0)
{
suffix = token.Substring(i);
token = token.Substring(0, i);
}
FieldInfo fieldInfo = currentType.GetField(token, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (fieldInfo == null)
{
string backingFieldName = String.Format("<{0}>k__BackingField", token);
PropertyInfo propertyInfo = currentType.GetProperty(token, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
if (propertyInfo != null)
{
fieldInfo = currentType.GetField(backingFieldName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
if (fieldInfo == null)
throw new NotImplementedException("can't identify backing field for property");
}
else
{
throw new ArgumentOutOfRangeException(nameof(path));
}
}
token = fieldInfo.Name;
currentType = fieldInfo.FieldType;
string s = suffix;
while (s.Length > 0)
{
if (s.StartsWith("[]", StringComparison.InvariantCulture))
{
if (currentType.IsArray)
currentType = currentType.GetElementType();
else if (currentType.IsGenericType)
currentType = currentType.GetGenericArguments()[0];
else
throw new NotSupportedException();
s = s.Substring(2);
}
else
{
throw new NotSupportedException();
}
}
path[n] = String.Format("{0}{1}", token, suffix);
}
return String.Join(".", path);
}
}
//class wait {
// protected Index Index;
// IndexPath NextIndexPath;
// protected IndexPath()
// {}
// protected IndexPath(Index index)
// {
// Index = index;
// }
// public IndexPath(Index index, Queue<string> path)
// :this(index)
// {
// NextIndexPath = CreateNextIndexPath(path);
// }
// private IndexPath CreateNextIndexPath(Queue<string> path)
// {
// if (path.Count == 0)
// {
// return new IndexUpdatePath(Index);
// }
// else
// {
// return new PropertyPath(propertyIndex, path);
// }
// }
// public virtual void UpdateIndex(ODBDocument document)
// {
// propertyIndex.TryRemove(document.ID);
// UpdateIndex(document, document);
// }
// public virtual void UpdateIndex(ODBDocument document, ODBValue element)
// {
// NextIndexPath.UpdateIndex(document, element);
// }
// public virtual IEnumerable<ODBValue> Retrieve(ODBValue element)
// {
// return NextIndexPath.Retrieve(element);
// }
// class PropertyPath : IndexPath
// {
// string propertyName;
// public PropertyPath(PropertyIndex propertyIndex,Queue<string> path)
// :base(propertyIndex)
// {
// propertyName = path.Dequeue();
// NextIndexPath = CreateNextIndexPath(path);
// while (propertyName.EndsWith("[]",StringComparison.InvariantCulture))
// {
// NextIndexPath = new EnumPath(propertyIndex, NextIndexPath);
// propertyName = propertyName.Substring(0, propertyName.Length - 2);
// }
// }
// public override void UpdateIndex(ODBDocument document, ODBValue element)
// {
// if (element is ODBDocument)
// {
// ODBDocument edoc = element as ODBDocument;
// NextIndexPath.UpdateIndex(document, edoc[propertyName]);
// }
// }
// public override IEnumerable<ODBValue> Retrieve(ODBValue element)
// {
// if (element is ODBDocument)
// {
// ODBDocument edoc = element as ODBDocument;
// return NextIndexPath.Retrieve(edoc[propertyName]);
// }
// return new ODBValue[0];
// }
// }
// class EnumPath : IndexPath
// {
// public EnumPath(PropertyIndex propertyIndex,IndexPath nextIndexPath)
// : base(propertyIndex)
// {
// NextIndexPath = nextIndexPath;
// }
// public override void UpdateIndex(ODBDocument document, ODBValue element)
// {
// if (element is ODBList)
// {
// ODBList elist = element as ODBList;
// foreach (ODBValue le in elist)
// {
// NextIndexPath.UpdateIndex(document, le);
// }
// }
// }
// public override IEnumerable<ODBValue> Retrieve(ODBValue element)
// {
// if (element is ODBList)
// {
// ODBList elist = element as ODBList;
// return elist.SelectMany(e => NextIndexPath.Retrieve(e));
// }
// return new ODBValue[0];
// }
// }
// class IndexUpdatePath : IndexPath
// {
// public IndexUpdatePath(PropertyIndex propertyIndex)
// : base(propertyIndex)
// {
// }
// public override void UpdateIndex(ODBDocument document, ODBValue element)
// {
// propertyIndex.Add(element, document.ID);
// }
// public override IEnumerable<ODBValue> Retrieve(ODBValue element)
// {
// return new ODBValue[] { element };
// }
// }
//}
}