ln.objects/ng/Query.cs

197 lines
6.2 KiB
C#

// /**
// * File: Query.cs
// * Author: haraldwolff
// *
// * This file and it's content is copyrighted by the Author and / or copyright holder.
// * Any use wihtout proper permission is illegal and may lead to legal actions.
// *
// *
// **/
using System;
using System.Collections.Generic;
using ln.types.btree;
using System.Linq;
using ln.types.odb.ng.index;
using ln.types.odb.ng.storage;
using ln.objects.catalog;
namespace ln.types.odb.ng
{
public abstract class Query
{
private Query()
{
}
public static Query AND(Query query,params Query[] queries)
{
return new IMPL.AND(query, queries);
}
public static Query OR(Query query, params Query[] queries)
{
return new IMPL.OR(query, queries);
}
public static Query NOT(Query query)
{
return new IMPL.NOT(query);
}
public static Query Equals<T>(string propertyName, object value) => Equals(IndexPath.TranslatePropertyPath(typeof(T), propertyName), Mapper.Default.MapValue(value));
public static Query Equals(String propertyName, ODBEntity value)
{
if (object.ReferenceEquals(value,null))
value = ODBNull.Instance;
return IF(propertyName, (v) => value.CompareTo(v)==0);
}
public static Query EqualsNot<T>(string propertyName, ODBEntity value) => EqualsNot(IndexPath.TranslatePropertyPath(typeof(T), propertyName), value);
public static Query EqualsNot(String propertyName, ODBEntity value)
{
if (object.ReferenceEquals(value, null))
value = ODBNull.Instance;
return IF(propertyName, (v) => value.CompareTo(v)!=0);
}
public static Query Equals<T>(string propertyName, ODBEntity[] values) => Equals(IndexPath.TranslatePropertyPath(typeof(T), propertyName), values);
public static Query Equals(String propertyName, ODBEntity[] values)
{
return IF(propertyName, (v) => {
foreach (ODBEntity value in values)
if (value.CompareTo(v) == 0)
return true;
return false;
});
}
public static Query Contains<T, A>(string propertyName, IEnumerable<A> values)
{
ODBEntity[] oValues = values.Select(v => Mapper.Default.MapValue(v)).ToArray();
return IF(IndexPath.TranslatePropertyPath(typeof(T), propertyName), v => oValues.Contains(v));
}
public static Query IF<T>(string propertyName, Predicate<ODBEntity> predicate) => IF(IndexPath.TranslatePropertyPath(typeof(T),propertyName), predicate);
public static Query IF(string propertyName,Predicate<ODBEntity> predicate)
{
return new IMPL.IF(propertyName, predicate);
}
public abstract IEnumerable<Guid> Execute(IStorage storage);
class IMPL
{
public class IF : Query
{
public string PropertyName { get; }
public Predicate<ODBEntity> Predicate { get; }
public IF(string propertyName,Predicate<ODBEntity> predicate)
{
PropertyName = propertyName;
Predicate = predicate;
}
public override IEnumerable<Guid> Execute(IStorage storage)
{
return storage.GetDocumentIDs(PropertyName,Predicate);
}
}
public class AND : Query
{
public Query Query { get; }
public Query[] Queries { get; }
public AND(Query query, params Query[] queries)
{
Query = query;
Queries = queries;
}
public override IEnumerable<Guid> Execute(IStorage storage)
{
BTree<Guid> firstSet = new BTree<Guid>();
firstSet.AddRange(
Query.Execute(storage)
);
foreach (Query aQuery in Queries)
{
if (firstSet.Count == 0)
return new Guid[0];
BTree<Guid> nextSet = new BTree<Guid>();
foreach (Guid documentID in aQuery.Execute(storage))
{
if (firstSet.ContainsKey(documentID))
nextSet.Add(documentID);
}
firstSet = nextSet;
}
return firstSet.Keys;
}
}
public class OR : Query
{
public Query Query { get; }
public Query[] Queries { get; }
public OR(Query query, params Query[] queries)
{
Query = query;
Queries = queries;
}
public override IEnumerable<Guid> Execute(IStorage storage)
{
BTree<Guid> result = new BTree<Guid>();
result.TryAddRange(
Query.Execute(storage)
);
foreach (Query aQuery in Queries)
{
foreach (Guid documentID in aQuery.Execute(storage))
result.TryAdd(documentID);
}
return result.Keys;
}
}
public class NOT : Query
{
public Query Query { get; }
public NOT(Query query)
{
Query = query;
}
public override IEnumerable<Guid> Execute(IStorage storage)
{
BTree<Guid> notSet = new BTree<Guid>();
BTree<Guid> result = new BTree<Guid>();
notSet.AddRange(Query.Execute(storage));
foreach (Guid documentID in storage.GetDocumentIDs())
{
if (!notSet.ContainsKey(documentID))
result.Add(documentID);
}
return result.Keys;
}
}
}
}
}