/Dicom/Data/DicomMatch.cs

https://github.com/charlescrichton/mdcm · C# · 400 lines · 313 code · 55 blank · 32 comment · 19 complexity · 1b9bb7c07cf23680b894e72d290170c4 MD5 · raw file

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Text.RegularExpressions;
  5. using Dicom;
  6. using Dicom.Data;
  7. using Dicom.Utility;
  8. namespace Dicom.Data {
  9. public enum DicomMatchOperator : byte {
  10. /// <summary>All rules match</summary>
  11. And,
  12. /// <summary>Any rule matches</summary>
  13. Or
  14. }
  15. public interface IDicomMatchRule {
  16. bool Match(DcmDataset dataset);
  17. }
  18. public class DicomMatch : IDicomMatchRule {
  19. #region Private Members
  20. private DicomMatchOperator _operator;
  21. private IList<IDicomMatchRule> _rules;
  22. #endregion
  23. #region Public Constructor
  24. public DicomMatch() {
  25. _rules = new List<IDicomMatchRule>();
  26. _operator = DicomMatchOperator.And;
  27. }
  28. public DicomMatch(DicomMatchOperator op) {
  29. _rules = new List<IDicomMatchRule>();
  30. _operator = op;
  31. }
  32. public DicomMatch(params IDicomMatchRule[] rules) {
  33. _rules = new List<IDicomMatchRule>(rules);
  34. _operator = DicomMatchOperator.And;
  35. }
  36. public DicomMatch(DicomMatchOperator op, params IDicomMatchRule[] rules) {
  37. _rules = new List<IDicomMatchRule>(rules);
  38. _operator = op;
  39. }
  40. #endregion
  41. #region Public Properties
  42. public DicomMatchOperator Operator {
  43. get { return _operator; }
  44. set { _operator = value; }
  45. }
  46. #endregion
  47. #region Public Methods
  48. public void Add(IDicomMatchRule rule) {
  49. _rules.Add(rule);
  50. }
  51. public bool Match(DcmDataset dataset) {
  52. if (_operator == DicomMatchOperator.Or) {
  53. foreach (IDicomMatchRule rule in _rules)
  54. if (rule.Match(dataset))
  55. return true;
  56. return false;
  57. }
  58. else {
  59. foreach (IDicomMatchRule rule in _rules)
  60. if (!rule.Match(dataset))
  61. return false;
  62. return true;
  63. }
  64. }
  65. public override string ToString() {
  66. StringBuilder sb = new StringBuilder();
  67. foreach (IDicomMatchRule rule in _rules) {
  68. if (rule is DicomMatch)
  69. sb.AppendLine("(((").AppendLine(rule.ToString()).AppendLine(")))");
  70. else
  71. sb.AppendLine(rule.ToString());
  72. }
  73. return sb.ToString();
  74. }
  75. #endregion
  76. }
  77. /// <summary>
  78. /// Negates the return value of a match rule.
  79. /// </summary>
  80. public class NegativeDicomMatchRule : IDicomMatchRule {
  81. #region Private Members
  82. private IDicomMatchRule _rule;
  83. #endregion
  84. #region Public Constructor
  85. public NegativeDicomMatchRule(IDicomMatchRule rule) {
  86. _rule = rule;
  87. }
  88. #endregion
  89. #region Public Methods
  90. public bool Match(DcmDataset dataset) {
  91. return !_rule.Match(dataset);
  92. }
  93. public override string ToString() {
  94. return String.Format("not {0}", _rule);
  95. }
  96. #endregion
  97. }
  98. /// <summary>
  99. /// Checks that a DICOM element exists.
  100. /// </summary>
  101. public class ExistsDicomMatchRule : IDicomMatchRule {
  102. #region Private Members
  103. private DicomTag _tag;
  104. #endregion
  105. #region Public Constructor
  106. public ExistsDicomMatchRule(DicomTag tag) {
  107. _tag = tag;
  108. }
  109. #endregion
  110. #region Public Methods
  111. public bool Match(DcmDataset dataset) {
  112. return dataset.Contains(_tag);
  113. }
  114. public override string ToString() {
  115. return String.Format("{0} exists", _tag);
  116. }
  117. #endregion
  118. }
  119. /// <summary>
  120. /// Checks if a DICOM element exists and has a value.
  121. /// </summary>
  122. public class EmptyDicomMatchRule : IDicomMatchRule {
  123. #region Private Members
  124. private DicomTag _tag;
  125. #endregion
  126. #region Public Constructor
  127. public EmptyDicomMatchRule(DicomTag tag) {
  128. _tag = tag;
  129. }
  130. #endregion
  131. #region Public Methods
  132. public bool Match(DcmDataset dataset) {
  133. if (dataset.Contains(_tag)) {
  134. string value = dataset.GetValueString(_tag).Trim();
  135. return String.IsNullOrEmpty(value);
  136. }
  137. return true;
  138. }
  139. public override string ToString() {
  140. return String.Format("{0} empty", _tag);
  141. }
  142. #endregion
  143. }
  144. /// <summary>
  145. /// Compares a DICOM element value against a string.
  146. /// </summary>
  147. public class EqualsDicomMatchRule : IDicomMatchRule {
  148. #region Private Members
  149. private DicomTag _tag;
  150. private string _value;
  151. #endregion
  152. #region Public Constructor
  153. public EqualsDicomMatchRule(DicomTag tag, string value) {
  154. _tag = tag;
  155. _value = value;
  156. }
  157. #endregion
  158. #region Public Methods
  159. public bool Match(DcmDataset dataset) {
  160. if (dataset.Contains(_tag)) {
  161. string value = dataset.GetValueString(_tag);
  162. return _value == value;
  163. }
  164. return false;
  165. }
  166. public override string ToString() {
  167. return String.Format("{0} equals '{1}'", _tag, _value);
  168. }
  169. #endregion
  170. }
  171. /// <summary>
  172. /// Checks if a DICOM element value starts with a string.
  173. /// </summary>
  174. public class StartsWithDicomMatchRule : IDicomMatchRule {
  175. #region Private Members
  176. private DicomTag _tag;
  177. private string _value;
  178. #endregion
  179. #region Public Constructor
  180. public StartsWithDicomMatchRule(DicomTag tag, string value) {
  181. _tag = tag;
  182. _value = value;
  183. }
  184. #endregion
  185. #region Public Methods
  186. public bool Match(DcmDataset dataset) {
  187. if (dataset.Contains(_tag)) {
  188. string value = dataset.GetValueString(_tag);
  189. return value.StartsWith(_value);
  190. }
  191. return false;
  192. }
  193. public override string ToString() {
  194. return String.Format("{0} starts with '{1}'", _tag, _value);
  195. }
  196. #endregion
  197. }
  198. /// <summary>
  199. /// Checks if a DICOM element value ends with a string.
  200. /// </summary>
  201. public class EndsWithDicomMatchRule : IDicomMatchRule {
  202. #region Private Members
  203. private DicomTag _tag;
  204. private string _value;
  205. #endregion
  206. #region Public Constructor
  207. public EndsWithDicomMatchRule(DicomTag tag, string value) {
  208. _tag = tag;
  209. _value = value;
  210. }
  211. #endregion
  212. #region Public Methods
  213. public bool Match(DcmDataset dataset) {
  214. if (dataset.Contains(_tag)) {
  215. string value = dataset.GetValueString(_tag);
  216. return value.EndsWith(_value);
  217. }
  218. return false;
  219. }
  220. public override string ToString() {
  221. return String.Format("{0} ends with '{1}'", _tag, _value);
  222. }
  223. #endregion
  224. }
  225. /// <summary>
  226. /// Checks if a DICOM element value contains a string.
  227. /// </summary>
  228. public class ContainsDicomMatchRule : IDicomMatchRule {
  229. #region Private Members
  230. private DicomTag _tag;
  231. private string _value;
  232. #endregion
  233. #region Public Constructor
  234. public ContainsDicomMatchRule(DicomTag tag, string value) {
  235. _tag = tag;
  236. _value = value;
  237. }
  238. #endregion
  239. #region Public Methods
  240. public bool Match(DcmDataset dataset) {
  241. if (dataset.Contains(_tag)) {
  242. string value = dataset.GetValueString(_tag);
  243. return value.Contains(_value);
  244. }
  245. return false;
  246. }
  247. public override string ToString() {
  248. return String.Format("{0} contains '{1}'", _tag, _value);
  249. }
  250. #endregion
  251. }
  252. /// <summary>
  253. /// Matches a wildcard pattern against a DICOM element value.
  254. /// </summary>
  255. public class WildcardDicomMatchRule : IDicomMatchRule {
  256. #region Private Members
  257. private DicomTag _tag;
  258. private string _pattern;
  259. #endregion
  260. #region Public Constructor
  261. public WildcardDicomMatchRule(DicomTag tag, string pattern) {
  262. _tag = tag;
  263. _pattern = pattern;
  264. }
  265. #endregion
  266. #region Public Methods
  267. public bool Match(DcmDataset dataset) {
  268. if (dataset.Contains(_tag)) {
  269. string value = dataset.GetValueString(_tag);
  270. return Wildcard.Match(_pattern, value);
  271. }
  272. return false;
  273. }
  274. public override string ToString() {
  275. return String.Format("{0} wildcard match '{1}'", _tag, _pattern);
  276. }
  277. #endregion
  278. }
  279. /// <summary>
  280. /// Matches regular expression pattern against a DICOM element value.
  281. /// </summary>
  282. public class RegexDicomMatchRule : IDicomMatchRule {
  283. #region Private Members
  284. private DicomTag _tag;
  285. private string _pattern;
  286. private Regex _regex;
  287. #endregion
  288. #region Public Constructor
  289. public RegexDicomMatchRule(DicomTag tag, string pattern) {
  290. _tag = tag;
  291. _pattern = pattern;
  292. _regex = new Regex(_pattern);
  293. }
  294. #endregion
  295. #region Public Methods
  296. public bool Match(DcmDataset dataset) {
  297. if (dataset.Contains(_tag)) {
  298. string value = dataset.GetValueString(_tag);
  299. return _regex.IsMatch(value);
  300. }
  301. return false;
  302. }
  303. public override string ToString() {
  304. return String.Format("{0} regex match '{1}'", _tag, _pattern);
  305. }
  306. #endregion
  307. }
  308. /// <summary>
  309. /// Matches a DICOM element value against a set of strings.
  310. /// </summary>
  311. public class OneOfDicomMatchRule : IDicomMatchRule {
  312. #region Private Members
  313. private DicomTag _tag;
  314. private string[] _values;
  315. #endregion
  316. #region Public Constructor
  317. public OneOfDicomMatchRule(DicomTag tag, params string[] values) {
  318. _tag = tag;
  319. _values = values;
  320. }
  321. #endregion
  322. #region Public Methods
  323. public bool Match(DcmDataset dataset) {
  324. if (dataset.Contains(_tag)) {
  325. string value = dataset.GetValueString(_tag);
  326. foreach (string v in _values)
  327. if (v == value)
  328. return true;
  329. }
  330. return false;
  331. }
  332. public override string ToString() {
  333. StringBuilder sb = new StringBuilder();
  334. sb.AppendFormat("{0} is one of ['", _tag);
  335. for (int i = 0; i < _values.Length; i++) {
  336. if (i > 0)
  337. sb.Append("', '");
  338. sb.Append(_values[i]);
  339. }
  340. sb.Append("']");
  341. return sb.ToString();
  342. }
  343. #endregion
  344. }
  345. }