FilterDeclaration.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  1. /* ========================================================================
  2. * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved.
  3. *
  4. * OPC Foundation MIT License 1.00
  5. *
  6. * Permission is hereby granted, free of charge, to any person
  7. * obtaining a copy of this software and associated documentation
  8. * files (the "Software"), to deal in the Software without
  9. * restriction, including without limitation the rights to use,
  10. * copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. * copies of the Software, and to permit persons to whom the
  12. * Software is furnished to do so, subject to the following
  13. * conditions:
  14. *
  15. * The above copyright notice and this permission notice shall be
  16. * included in all copies or substantial portions of the Software.
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  18. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  19. * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  20. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  21. * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  22. * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  23. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  24. * OTHER DEALINGS IN THE SOFTWARE.
  25. *
  26. * The complete license agreement can be found here:
  27. * http://opcfoundation.org/License/MIT/1.00/
  28. * ======================================================================*/
  29. using System;
  30. using System.Text;
  31. using System.Collections.Generic;
  32. using Opc.Ua;
  33. using Opc.Ua.Client;
  34. namespace OpcUaHelper
  35. {
  36. /// <summary>
  37. /// Stores a type declaration retrieved from a server.
  38. /// </summary>
  39. public class TypeDeclaration
  40. {
  41. /// <summary>
  42. /// The node if for the type.
  43. /// </summary>
  44. public NodeId NodeId;
  45. /// <summary>
  46. /// The fully inhierited list of instance declarations for the type.
  47. /// </summary>
  48. public List<InstanceDeclaration> Declarations;
  49. }
  50. /// <summary>
  51. /// Stores an instance declaration fetched from the server.
  52. /// </summary>
  53. public class InstanceDeclaration
  54. {
  55. /// <summary>
  56. /// The type that the declaration belongs to.
  57. /// </summary>
  58. public NodeId RootTypeId;
  59. /// <summary>
  60. /// The browse path to the instance declaration.
  61. /// </summary>
  62. public QualifiedNameCollection BrowsePath;
  63. /// <summary>
  64. /// The browse path to the instance declaration.
  65. /// </summary>
  66. public string BrowsePathDisplayText;
  67. /// <summary>
  68. /// A localized path to the instance declaration.
  69. /// </summary>
  70. public string DisplayPath;
  71. /// <summary>
  72. /// The node id for the instance declaration.
  73. /// </summary>
  74. public NodeId NodeId;
  75. /// <summary>
  76. /// The node class of the instance declaration.
  77. /// </summary>
  78. public NodeClass NodeClass;
  79. /// <summary>
  80. /// The browse name for the instance declaration.
  81. /// </summary>
  82. public QualifiedName BrowseName;
  83. /// <summary>
  84. /// The display name for the instance declaration.
  85. /// </summary>
  86. public string DisplayName;
  87. /// <summary>
  88. /// The description for the instance declaration.
  89. /// </summary>
  90. public string Description;
  91. /// <summary>
  92. /// The modelling rule for the instance declaration (i.e. Mandatory or Optional).
  93. /// </summary>
  94. public NodeId ModellingRule;
  95. /// <summary>
  96. /// The data type for the instance declaration.
  97. /// </summary>
  98. public NodeId DataType;
  99. /// <summary>
  100. /// The value rank for the instance declaration.
  101. /// </summary>
  102. public int ValueRank;
  103. /// <summary>
  104. /// The built-in type parent for the data type.
  105. /// </summary>
  106. public BuiltInType BuiltInType;
  107. /// <summary>
  108. /// A localized name for the data type.
  109. /// </summary>
  110. public string DataTypeDisplayText;
  111. /// <summary>
  112. /// An instance declaration that has been overridden by the current instance.
  113. /// </summary>
  114. public InstanceDeclaration OverriddenDeclaration;
  115. }
  116. /// <summary>
  117. /// A field in a filter declaration.
  118. /// </summary>
  119. public class FilterDeclarationField
  120. {
  121. /// <summary>
  122. /// Creates a new instance of a FilterDeclarationField.
  123. /// </summary>
  124. public FilterDeclarationField()
  125. {
  126. Selected = true;
  127. DisplayInList = false;
  128. FilterEnabled = false;
  129. FilterOperator = FilterOperator.Equals;
  130. FilterValue = Variant.Null;
  131. InstanceDeclaration = null;
  132. }
  133. /// <summary>
  134. /// Creates a new instance of a FilterDeclarationField.
  135. /// </summary>
  136. public FilterDeclarationField( InstanceDeclaration instanceDeclaration )
  137. {
  138. Selected = true;
  139. DisplayInList = false;
  140. FilterEnabled = false;
  141. FilterOperator = FilterOperator.Equals;
  142. FilterValue = Variant.Null;
  143. InstanceDeclaration = instanceDeclaration;
  144. }
  145. /// <summary>
  146. /// Creates a new instance of a FilterDeclarationField.
  147. /// </summary>
  148. public FilterDeclarationField( FilterDeclarationField field )
  149. {
  150. Selected = field.Selected;
  151. DisplayInList = field.DisplayInList;
  152. FilterEnabled = field.FilterEnabled;
  153. FilterOperator = field.FilterOperator;
  154. FilterValue = field.FilterValue;
  155. InstanceDeclaration = field.InstanceDeclaration;
  156. }
  157. /// <summary>
  158. /// Whether the field is returned as part of the event notification.
  159. /// </summary>
  160. public bool Selected;
  161. /// <summary>
  162. /// Whether the field is displayed in the list view.
  163. /// </summary>
  164. public bool DisplayInList;
  165. /// <summary>
  166. /// Whether the filter is enabled.
  167. /// </summary>
  168. public bool FilterEnabled;
  169. /// <summary>
  170. /// The filter operator to use in the where clause.
  171. /// </summary>
  172. public FilterOperator FilterOperator;
  173. /// <summary>
  174. /// The filter value to use in the where clause.
  175. /// </summary>
  176. public Variant FilterValue;
  177. /// <summary>
  178. /// The instance declaration associated with the field.
  179. /// </summary>
  180. public InstanceDeclaration InstanceDeclaration;
  181. }
  182. /// <summary>
  183. /// A declararion of an event filter.
  184. /// </summary>
  185. public class FilterDeclaration
  186. {
  187. /// <summary>
  188. /// Creates a new instance of a FilterDeclaration.
  189. /// </summary>
  190. public FilterDeclaration()
  191. {
  192. EventTypeId = Opc.Ua.ObjectTypeIds.BaseEventType;
  193. Fields = new List<FilterDeclarationField>( );
  194. }
  195. /// <summary>
  196. /// Creates a new instance of a FilterDeclaration.
  197. /// </summary>
  198. public FilterDeclaration( TypeDeclaration eventType, FilterDeclaration template )
  199. {
  200. EventTypeId = eventType.NodeId;
  201. Fields = new List<FilterDeclarationField>( );
  202. foreach (InstanceDeclaration instanceDeclaration in eventType.Declarations)
  203. {
  204. if (instanceDeclaration.NodeClass == NodeClass.Method)
  205. {
  206. continue;
  207. }
  208. if (NodeId.IsNull( instanceDeclaration.ModellingRule ))
  209. {
  210. continue;
  211. }
  212. FilterDeclarationField element = new FilterDeclarationField( instanceDeclaration );
  213. Fields.Add( element );
  214. // set reasonable defaults.
  215. if (template == null)
  216. {
  217. if (instanceDeclaration.RootTypeId == Opc.Ua.ObjectTypeIds.BaseEventType && instanceDeclaration.BrowseName != Opc.Ua.BrowseNames.EventId)
  218. {
  219. element.DisplayInList = true;
  220. }
  221. }
  222. // preserve filter settings.
  223. else
  224. {
  225. foreach (FilterDeclarationField field in template.Fields)
  226. {
  227. if (field.InstanceDeclaration.BrowsePathDisplayText == element.InstanceDeclaration.BrowsePathDisplayText)
  228. {
  229. element.DisplayInList = field.DisplayInList;
  230. element.FilterEnabled = field.FilterEnabled;
  231. element.FilterOperator = field.FilterOperator;
  232. element.FilterValue = field.FilterValue;
  233. break;
  234. }
  235. }
  236. }
  237. }
  238. }
  239. /// <summary>
  240. /// Creates a new instance of a FilterDeclaration.
  241. /// </summary>
  242. public FilterDeclaration( FilterDeclaration declaration )
  243. {
  244. EventTypeId = declaration.EventTypeId;
  245. Fields = new List<FilterDeclarationField>( declaration.Fields.Count );
  246. for (int ii = 0; ii < declaration.Fields.Count; ii++)
  247. {
  248. Fields.Add( new FilterDeclarationField( declaration.Fields[ii] ) );
  249. }
  250. }
  251. /// <summary>
  252. /// Returns the event filter defined by the filter declaration.
  253. /// </summary>
  254. public EventFilter GetFilter()
  255. {
  256. EventFilter filter = new EventFilter( );
  257. filter.SelectClauses = GetSelectClause( );
  258. filter.WhereClause = GetWhereClause( );
  259. return filter;
  260. }
  261. /// <summary>
  262. /// Adds a simple field to the declaration.
  263. /// </summary>
  264. public void AddSimpleField( QualifiedName browseName, BuiltInType dataType, bool displayInList )
  265. {
  266. AddSimpleField( new QualifiedName[] { browseName }, NodeClass.Variable, dataType, ValueRanks.Scalar, displayInList );
  267. }
  268. /// <summary>
  269. /// Adds a simple field to the declaration.
  270. /// </summary>
  271. public void AddSimpleField( QualifiedName browseName, BuiltInType dataType, int valueRank, bool displayInList )
  272. {
  273. AddSimpleField( new QualifiedName[] { browseName }, NodeClass.Variable, dataType, valueRank, displayInList );
  274. }
  275. /// <summary>
  276. /// Adds a simple field to the declaration.
  277. /// </summary>
  278. public void AddSimpleField( QualifiedName[] browseNames, BuiltInType dataType, int valueRank, bool displayInList )
  279. {
  280. AddSimpleField( browseNames, NodeClass.Variable, dataType, valueRank, displayInList );
  281. }
  282. /// <summary>
  283. /// Adds a simple field to the declaration.
  284. /// </summary>
  285. public void AddSimpleField( QualifiedName[] browseNames, NodeClass nodeClass, BuiltInType dataType, int valueRank, bool displayInList )
  286. {
  287. FilterDeclarationField field = new FilterDeclarationField( );
  288. field.DisplayInList = displayInList;
  289. field.InstanceDeclaration = new InstanceDeclaration( );
  290. field.InstanceDeclaration.NodeClass = nodeClass;
  291. if (browseNames != null)
  292. {
  293. field.InstanceDeclaration.BrowseName = browseNames[browseNames.Length - 1];
  294. field.InstanceDeclaration.BrowsePath = new QualifiedNameCollection( );
  295. StringBuilder path = new StringBuilder( );
  296. for (int ii = 0; ii < browseNames.Length; ii++)
  297. {
  298. if (path.Length > 0)
  299. {
  300. path.Append( '/' );
  301. }
  302. path.Append( browseNames[ii] );
  303. field.InstanceDeclaration.BrowsePath.Add( browseNames[ii] );
  304. }
  305. field.InstanceDeclaration.BrowsePathDisplayText = path.ToString( );
  306. }
  307. field.InstanceDeclaration.BuiltInType = dataType;
  308. field.InstanceDeclaration.DataType = (uint)dataType;
  309. field.InstanceDeclaration.ValueRank = valueRank;
  310. field.InstanceDeclaration.DataTypeDisplayText = dataType.ToString( );
  311. if (valueRank >= 0)
  312. {
  313. field.InstanceDeclaration.DataTypeDisplayText += "[]";
  314. }
  315. field.InstanceDeclaration.DisplayName = field.InstanceDeclaration.BrowseName.Name;
  316. field.InstanceDeclaration.DisplayPath = field.InstanceDeclaration.BrowsePathDisplayText;
  317. field.InstanceDeclaration.RootTypeId = ObjectTypeIds.BaseEventType;
  318. Fields.Add( field );
  319. }
  320. /// <summary>
  321. /// Returns the select clause defined by the filter declaration.
  322. /// </summary>
  323. public SimpleAttributeOperandCollection GetSelectClause()
  324. {
  325. SimpleAttributeOperandCollection selectClause = new SimpleAttributeOperandCollection( );
  326. SimpleAttributeOperand operand = new SimpleAttributeOperand( );
  327. operand.TypeDefinitionId = Opc.Ua.ObjectTypeIds.BaseEventType;
  328. operand.AttributeId = Attributes.NodeId;
  329. selectClause.Add( operand );
  330. foreach (FilterDeclarationField field in Fields)
  331. {
  332. if (field.Selected)
  333. {
  334. operand = new SimpleAttributeOperand( );
  335. operand.TypeDefinitionId = field.InstanceDeclaration.RootTypeId;
  336. operand.AttributeId = (field.InstanceDeclaration.NodeClass == NodeClass.Object) ? Attributes.NodeId : Attributes.Value;
  337. operand.BrowsePath = field.InstanceDeclaration.BrowsePath;
  338. selectClause.Add( operand );
  339. }
  340. }
  341. return selectClause;
  342. }
  343. /// <summary>
  344. /// Returns the where clause defined by the filter declaration.
  345. /// </summary>
  346. public ContentFilter GetWhereClause()
  347. {
  348. ContentFilter whereClause = new ContentFilter( );
  349. ContentFilterElement element1 = whereClause.Push( FilterOperator.OfType, EventTypeId );
  350. EventFilter filter = new EventFilter( );
  351. foreach (FilterDeclarationField field in Fields)
  352. {
  353. if (field.FilterEnabled)
  354. {
  355. SimpleAttributeOperand operand1 = new SimpleAttributeOperand( );
  356. operand1.TypeDefinitionId = field.InstanceDeclaration.RootTypeId;
  357. operand1.AttributeId = (field.InstanceDeclaration.NodeClass == NodeClass.Object) ? Attributes.NodeId : Attributes.Value;
  358. operand1.BrowsePath = field.InstanceDeclaration.BrowsePath;
  359. LiteralOperand operand2 = new LiteralOperand( );
  360. operand2.Value = field.FilterValue;
  361. ContentFilterElement element2 = whereClause.Push( field.FilterOperator, operand1, operand2 );
  362. element1 = whereClause.Push( FilterOperator.And, element1, element2 );
  363. }
  364. }
  365. return whereClause;
  366. }
  367. /// <summary>
  368. /// Returns the value for the specified browse name.
  369. /// </summary>
  370. public T GetValue<T>( QualifiedName browseName, VariantCollection fields, T defaultValue )
  371. {
  372. if (fields == null || fields.Count == 0)
  373. {
  374. return defaultValue;
  375. }
  376. if (browseName == null)
  377. {
  378. browseName = QualifiedName.Null;
  379. }
  380. for (int ii = 0; ii < this.Fields.Count; ii++)
  381. {
  382. if (this.Fields[ii].InstanceDeclaration.BrowseName == browseName)
  383. {
  384. if (ii >= fields.Count + 1)
  385. {
  386. return defaultValue;
  387. }
  388. object value = fields[ii + 1].Value;
  389. if (typeof( T ).IsInstanceOfType( value ))
  390. {
  391. return (T)value;
  392. }
  393. break;
  394. }
  395. }
  396. return defaultValue;
  397. }
  398. /// <summary>
  399. /// The type of event.
  400. /// </summary>
  401. public NodeId EventTypeId;
  402. /// <summary>
  403. /// The list of declarations for the fields.
  404. /// </summary>
  405. public List<FilterDeclarationField> Fields;
  406. }
  407. }