222 lines
6.1 KiB
C#
222 lines
6.1 KiB
C#
using System;
|
|
using oodb.descriptor;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Runtime.Remoting.Metadata;
|
|
using System.Runtime.Remoting.Messaging;
|
|
using System.Collections;
|
|
using System.Reflection;
|
|
using System.Text.RegularExpressions;
|
|
using System.Xml.Xsl.Runtime;
|
|
using oodb.index;
|
|
namespace oodb
|
|
{
|
|
public class QueryField
|
|
{
|
|
public string FieldName { get; }
|
|
|
|
public QueryField(String fieldName)
|
|
{
|
|
FieldName = fieldName;
|
|
}
|
|
|
|
public Predicate Contains(object value)
|
|
{
|
|
return new Predicate.Contains(this, value);
|
|
}
|
|
}
|
|
|
|
public abstract class Predicate
|
|
{
|
|
public QueryField QueryField { get; }
|
|
|
|
public Predicate(QueryField queryField)
|
|
{
|
|
QueryField = queryField;
|
|
}
|
|
|
|
public virtual bool MatchesTextValues => false;
|
|
|
|
public virtual bool TextMatch(string textValue) { throw new NotSupportedException(); }
|
|
public abstract bool Match(object value);
|
|
|
|
public OrPredicate Or => new OrPredicate(this);
|
|
|
|
|
|
public class OrPredicate : Predicate
|
|
{
|
|
public HashSet<Predicate> Predicates { get; } = new HashSet<Predicate>();
|
|
|
|
public OrPredicate(Predicate creator)
|
|
:base(creator.QueryField)
|
|
{
|
|
Predicates.Add(creator);
|
|
}
|
|
|
|
public OrPredicate Contains(object value)
|
|
{
|
|
Predicates.Add(new Predicate.Contains(this.QueryField, value));
|
|
return this;
|
|
}
|
|
|
|
public override bool MatchesTextValues
|
|
{
|
|
get {
|
|
foreach (Predicate predicate in Predicates)
|
|
if (!predicate.MatchesTextValues)
|
|
return false;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
public override bool TextMatch(string textValue)
|
|
{
|
|
foreach (Predicate predicate in Predicates)
|
|
if (predicate.TextMatch(textValue))
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
public override bool Match(object value)
|
|
{
|
|
foreach (Predicate predicate in Predicates)
|
|
if (predicate.Match(value))
|
|
return true;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public class Contains : Predicate
|
|
{
|
|
public object Value { get; }
|
|
|
|
public Contains(QueryField queryField,object value)
|
|
:base(queryField)
|
|
{
|
|
Value = value;
|
|
}
|
|
|
|
public override bool Match(object value)
|
|
{
|
|
if ((Value == null) || String.Empty.Equals(Value))
|
|
return true;
|
|
|
|
if (value == null)
|
|
return false;
|
|
|
|
return (value as string).Contains(Value as string);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
public class Query<T> where T: Persistent
|
|
{
|
|
public virtual AlternativesQuery<T> Or(Query<T> alternativeQuery) => new AlternativesQuery<T>(this, alternativeQuery);
|
|
public virtual AlternativesQuery<T> Or(params Predicate[] predicates) => new AlternativesQuery<T>(this, new Query<T>(predicates));
|
|
|
|
public HashSet<Predicate> Predicates { get; } = new HashSet<Predicate>();
|
|
|
|
|
|
protected Query()
|
|
{
|
|
}
|
|
|
|
public Query(IEnumerable<Predicate> predicates)
|
|
{
|
|
foreach (Predicate predicate in predicates)
|
|
{
|
|
Predicates.Add(predicate);
|
|
}
|
|
}
|
|
|
|
public Query(params Predicate[] predicates)
|
|
{
|
|
foreach (Predicate predicate in predicates)
|
|
{
|
|
Predicates.Add(predicate);
|
|
}
|
|
}
|
|
|
|
public IEnumerable<Predicate> GetPredicates(QueryField queryField)
|
|
{
|
|
return Predicates.Where((x) => x.QueryField == queryField);
|
|
}
|
|
|
|
public virtual IEnumerable<T> Search(OODB oodb)
|
|
{
|
|
Descriptor descriptor = oodb.GetDescriptor<T>();
|
|
HashSet<QueryField> predicateFields = new HashSet<QueryField>();
|
|
|
|
foreach (Predicate predicate in Predicates)
|
|
{
|
|
predicateFields.Add(predicate.QueryField);
|
|
}
|
|
|
|
Guid[] results = null;
|
|
|
|
foreach (QueryField queryField in predicateFields)
|
|
{
|
|
FieldInfo fieldInfo = descriptor.GetFieldInfo(queryField.FieldName);
|
|
if (!oodb.StorageAdapter.HasSearchIndex(fieldInfo))
|
|
throw new NotSupportedException("Queries must use indexed fields");
|
|
|
|
SearchIndex searchIndex = oodb.StorageAdapter.GetSearchIndex(fieldInfo);
|
|
|
|
foreach (Predicate predicate in GetPredicates(queryField))
|
|
{
|
|
IEnumerable<Guid> myresults = searchIndex.Query(predicate);
|
|
if (results == null)
|
|
{
|
|
results = myresults.ToArray();
|
|
} else {
|
|
results = results.Intersect(myresults).ToArray();
|
|
}
|
|
}
|
|
}
|
|
|
|
return results.Select((id)=>oodb.Load<T>(id));
|
|
}
|
|
|
|
}
|
|
|
|
public class AlternativesQuery<T> : Query<T> where T:Persistent
|
|
{
|
|
public HashSet<Query<T>> Alternatives = new HashSet<Query<T>>();
|
|
|
|
public AlternativesQuery(params Query<T>[] queries)
|
|
{
|
|
foreach (Query<T> alternative in queries)
|
|
Alternatives.Add(alternative);
|
|
}
|
|
|
|
public override AlternativesQuery<T> Or(Query<T> alternativeQuery)
|
|
{
|
|
Alternatives.Add(alternativeQuery);
|
|
return this;
|
|
}
|
|
|
|
public override AlternativesQuery<T> Or(params Predicate[] predicates)
|
|
{
|
|
Alternatives.Add(new Query<T>(predicates));
|
|
return this;
|
|
}
|
|
|
|
public override IEnumerable<T> Search(OODB oodb)
|
|
{
|
|
return Alternatives.SelectMany((alternative) => alternative.Search(oodb)).Distinct();
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|