NBTExplorer/Model/Search/SearchRule.cs

310 lines
9 KiB
C#
Raw Normal View History

2013-08-07 05:19:04 +00:00
using System;
using System.Collections.Generic;
using System.Text;
using Substrate.Nbt;
namespace NBTExplorer.Model.Search
{
2013-08-08 05:21:51 +00:00
public enum NumericOperator
{
Equals,
NotEquals,
GreaterThan,
LessThan,
Any,
}
public enum StringOperator
{
Equals,
NotEquals,
Contains,
NotContains,
StartsWith,
EndsWith,
Any,
}
public enum WildcardOperator
{
Equals,
NotEquals,
Any,
}
2013-08-07 05:19:04 +00:00
public abstract class SearchRule
{
2013-08-09 02:48:05 +00:00
public static readonly Dictionary<NumericOperator, string> NumericOpStrings = new Dictionary<NumericOperator, string>() {
2013-08-08 05:21:51 +00:00
{ NumericOperator.Equals, "=" },
{ NumericOperator.NotEquals, "!=" },
{ NumericOperator.GreaterThan, ">" },
{ NumericOperator.LessThan, "<" },
{ NumericOperator.Any, "ANY" },
};
2013-08-09 02:48:05 +00:00
public static readonly Dictionary<StringOperator, string> StringOpStrings = new Dictionary<StringOperator, string>() {
2013-08-08 05:21:51 +00:00
{ StringOperator.Equals, "=" },
{ StringOperator.NotEquals, "!=" },
{ StringOperator.Contains, "Contains" },
{ StringOperator.NotContains, "Does not Contain" },
{ StringOperator.StartsWith, "Begins With" },
{ StringOperator.EndsWith, "Ends With" },
{ StringOperator.Any, "ANY" },
};
2013-08-09 02:48:05 +00:00
public static readonly Dictionary<WildcardOperator, string> WildcardOpStrings = new Dictionary<WildcardOperator, string>() {
2013-08-08 05:21:51 +00:00
{ WildcardOperator.Equals, "=" },
{ WildcardOperator.NotEquals, "!=" },
{ WildcardOperator.Any, "ANY" },
};
public abstract string NodeDisplay { get; }
2013-08-07 05:19:04 +00:00
public virtual bool Matches (TagCompoundDataNode container, List<TagDataNode> matchedNodes)
{
return false;
}
2013-08-08 05:21:51 +00:00
public virtual bool CanAddRules
{
get { return false; }
}
protected static TagDataNode GetChild (TagCompoundDataNode container, string name)
{
foreach (var child in container.Nodes) {
TagDataNode tagChild = child as TagDataNode;
if (tagChild != null && tagChild.NodeName == name)
return tagChild;
}
return null;
}
2013-08-07 05:19:04 +00:00
}
public abstract class GroupRule : SearchRule
{
2013-08-08 05:21:51 +00:00
protected GroupRule ()
{
Rules = new List<SearchRule>();
}
2013-08-07 05:19:04 +00:00
public List<SearchRule> Rules { get; set; }
2013-08-08 05:21:51 +00:00
public override bool CanAddRules
{
get { return true; }
}
2013-08-07 05:19:04 +00:00
}
public class UnionRule : GroupRule
{
public override string NodeDisplay
{
get { return "Match Any"; }
}
public override bool Matches (TagCompoundDataNode container, List<TagDataNode> matchedNodes)
{
foreach (var rule in Rules) {
if (rule.Matches(container, matchedNodes))
return true;
}
return false;
}
}
public class IntersectRule : GroupRule
{
public override string NodeDisplay
{
get { return "Match All"; }
}
public override bool Matches (TagCompoundDataNode container, List<TagDataNode> matchedNodes)
{
foreach (var rule in Rules) {
if (!rule.Matches(container, matchedNodes))
return false;
}
return true;
}
}
public class RootRule : IntersectRule
{
public override string NodeDisplay
{
get { return "Search Rules"; }
}
}
public abstract class TagRule : SearchRule
{
public TagType TagType { get; set; }
public string Name { get; set; }
protected T LookupTag<T> (TagCompoundDataNode container, string name)
where T : TagNode
{
return container.NamedTagContainer.GetTagNode(name) as T;
}
}
public abstract class IntegralTagRule<T> : TagRule
where T : TagNode
{
public long Value { get; set; }
2013-08-08 05:21:51 +00:00
public NumericOperator Operator { get; set; }
2013-08-07 05:19:04 +00:00
public override string NodeDisplay
{
2013-08-08 05:21:51 +00:00
get { return string.Format("{0} {1} {2}", Name, NumericOpStrings[Operator], Operator != NumericOperator.Any ? Value.ToString() : ""); }
2013-08-07 05:19:04 +00:00
}
public override bool Matches (TagCompoundDataNode container, List<TagDataNode> matchedNodes)
{
2013-08-08 05:21:51 +00:00
TagDataNode childNode = GetChild(container, Name);
2013-08-07 05:19:04 +00:00
T data = LookupTag<T>(container, Name);
2013-08-08 05:21:51 +00:00
if (data != null && data.ToTagLong() == Value) {
if (!matchedNodes.Contains(childNode))
matchedNodes.Add(childNode);
return true;
}
return false;
2013-08-07 05:19:04 +00:00
}
}
public class ByteTagRule : IntegralTagRule<TagNodeByte>
{ }
public class ShortTagRule : IntegralTagRule<TagNodeShort>
{ }
public class IntTagRule : IntegralTagRule<TagNodeInt>
{ }
2013-08-09 02:48:05 +00:00
public class LongTagRule : IntegralTagRule<TagNodeLong>
2013-08-07 05:19:04 +00:00
{ }
public abstract class FloatTagRule<T> : TagRule
where T : TagNode
{
public double Value { get; set; }
2013-08-08 05:21:51 +00:00
public NumericOperator Operator { get; set; }
2013-08-07 05:19:04 +00:00
public override string NodeDisplay
{
2013-08-08 05:21:51 +00:00
get { return string.Format("{0} {1} {2}", Name, NumericOpStrings[Operator], Operator != NumericOperator.Any ? Value.ToString() : ""); }
2013-08-07 05:19:04 +00:00
}
public override bool Matches (TagCompoundDataNode container, List<TagDataNode> matchedNodes)
{
2013-08-08 05:21:51 +00:00
TagDataNode childNode = GetChild(container, Name);
2013-08-07 05:19:04 +00:00
T data = LookupTag<T>(container, Name);
2013-08-08 05:21:51 +00:00
if (data != null && data.ToTagDouble() == Value) {
if (!matchedNodes.Contains(childNode))
matchedNodes.Add(childNode);
return true;
}
return false;
2013-08-07 05:19:04 +00:00
}
}
public class FloatTagRule : FloatTagRule<TagNodeFloat>
{ }
public class DoubleTagRule : FloatTagRule<TagNodeDouble>
{ }
public class StringTagRule : TagRule
{
public string Value { get; set; }
2013-08-08 05:21:51 +00:00
public StringOperator Operator { get; set; }
2013-08-07 05:19:04 +00:00
public override string NodeDisplay
{
2013-08-08 05:21:51 +00:00
get { return string.Format("{0} {1} {2}", Name, StringOpStrings[Operator], Operator != StringOperator.Any ? '"' + Value + '"' : ""); }
2013-08-07 05:19:04 +00:00
}
public override bool Matches (TagCompoundDataNode container, List<TagDataNode> matchedNodes)
{
2013-08-08 05:21:51 +00:00
TagDataNode childNode = GetChild(container, Name);
2013-08-07 05:19:04 +00:00
TagNodeString data = LookupTag<TagNodeString>(container, Name);
2013-08-08 05:21:51 +00:00
if (data != null && data.ToTagString() == Value) {
if (!matchedNodes.Contains(childNode))
matchedNodes.Add(childNode);
return true;
}
return false;
2013-08-07 05:19:04 +00:00
}
}
public class WildcardRule : SearchRule
{
public string Name { get; set; }
public string Value { get; set; }
2013-08-08 05:21:51 +00:00
public WildcardOperator Operator { get; set; }
2013-08-07 05:19:04 +00:00
public override string NodeDisplay
{
2013-08-08 05:21:51 +00:00
get { return string.Format("{0} {1} {2}", Name, WildcardOpStrings[Operator], Operator != WildcardOperator.Any ? Value : ""); }
2013-08-07 05:19:04 +00:00
}
public override bool Matches (TagCompoundDataNode container, List<TagDataNode> matchedNodes)
{
TagDataNode childNode = GetChild(container, Name);
TagNode tag = container.NamedTagContainer.GetTagNode(Name);
if (tag == null)
return false;
try {
switch (tag.GetTagType()) {
case TagType.TAG_BYTE:
case TagType.TAG_INT:
case TagType.TAG_LONG:
case TagType.TAG_SHORT:
if (long.Parse(Value) == tag.ToTagLong()) {
if (!matchedNodes.Contains(childNode))
matchedNodes.Add(childNode);
return true;
}
break;
case TagType.TAG_FLOAT:
case TagType.TAG_DOUBLE:
if (double.Parse(Value) == tag.ToTagDouble()) {
if (!matchedNodes.Contains(childNode))
matchedNodes.Add(childNode);
2013-08-09 06:02:22 +00:00
return true;
2013-08-07 05:19:04 +00:00
}
break;
case TagType.TAG_STRING:
if (Value == tag.ToTagString()) {
if (!matchedNodes.Contains(childNode))
matchedNodes.Add(childNode);
2013-08-09 06:02:22 +00:00
return true;
2013-08-07 05:19:04 +00:00
}
break;
}
}
catch { }
return false;
}
2013-08-08 05:21:51 +00:00
2013-08-07 05:19:04 +00:00
}
}