436 lines
11 KiB
C#
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 };
|
|
// }
|
|
// }
|
|
|
|
|
|
//}
|
|
}
|