1use std::convert::TryFrom;
10
11use crate::{
12 attribute::AttributeId, match_extension_object_owned, status_code::StatusCode,
13 AttributeOperand, ContentFilter, ContentFilterElement, DataTypeId, ElementOperand,
14 ExtensionObject, FilterOperator, LiteralOperand, MethodId, NodeId, NumericRange, ObjectId,
15 ObjectTypeId, QualifiedName, ReferenceTypeId, SimpleAttributeOperand, VariableId,
16 VariableTypeId, Variant,
17};
18
19#[derive(PartialEq)]
20pub enum OperandType {
22 ElementOperand,
24 LiteralOperand,
26 AttributeOperand,
28 SimpleAttributeOperand,
30}
31
32#[derive(Debug, Clone)]
33pub enum Operand {
35 ElementOperand(ElementOperand),
37 LiteralOperand(LiteralOperand),
39 AttributeOperand(AttributeOperand),
41 SimpleAttributeOperand(SimpleAttributeOperand),
43}
44
45impl From<i8> for LiteralOperand {
46 fn from(v: i8) -> Self {
47 Self::from(Variant::from(v))
48 }
49}
50
51impl From<u8> for LiteralOperand {
52 fn from(v: u8) -> Self {
53 Self::from(Variant::from(v))
54 }
55}
56
57impl From<i16> for LiteralOperand {
58 fn from(v: i16) -> Self {
59 Self::from(Variant::from(v))
60 }
61}
62
63impl From<u16> for LiteralOperand {
64 fn from(v: u16) -> Self {
65 Self::from(Variant::from(v))
66 }
67}
68
69impl From<i32> for LiteralOperand {
70 fn from(v: i32) -> Self {
71 Self::from(Variant::from(v))
72 }
73}
74
75impl From<u32> for LiteralOperand {
76 fn from(v: u32) -> Self {
77 Self::from(Variant::from(v))
78 }
79}
80
81impl From<f32> for LiteralOperand {
82 fn from(v: f32) -> Self {
83 Self::from(Variant::from(v))
84 }
85}
86
87impl From<f64> for LiteralOperand {
88 fn from(v: f64) -> Self {
89 Self::from(Variant::from(v))
90 }
91}
92
93impl From<bool> for LiteralOperand {
94 fn from(v: bool) -> Self {
95 Self::from(Variant::from(v))
96 }
97}
98
99impl From<&str> for LiteralOperand {
100 fn from(v: &str) -> Self {
101 Self::from(Variant::from(v))
102 }
103}
104
105impl From<NodeId> for LiteralOperand {
106 fn from(v: NodeId) -> Self {
107 Self::from(Variant::from(v))
108 }
109}
110
111impl From<ObjectId> for LiteralOperand {
112 fn from(v: ObjectId) -> Self {
113 Self::from(Variant::NodeId(Box::new(v.into())))
114 }
115}
116
117impl From<VariableId> for LiteralOperand {
118 fn from(v: VariableId) -> Self {
119 Self::from(Variant::NodeId(Box::new(v.into())))
120 }
121}
122
123impl From<MethodId> for LiteralOperand {
124 fn from(v: MethodId) -> Self {
125 Self::from(Variant::NodeId(Box::new(v.into())))
126 }
127}
128
129impl From<DataTypeId> for LiteralOperand {
130 fn from(v: DataTypeId) -> Self {
131 Self::from(Variant::NodeId(Box::new(v.into())))
132 }
133}
134
135impl From<ObjectTypeId> for LiteralOperand {
136 fn from(v: ObjectTypeId) -> Self {
137 Self::from(Variant::NodeId(Box::new(v.into())))
138 }
139}
140
141impl From<VariableTypeId> for LiteralOperand {
142 fn from(v: VariableTypeId) -> Self {
143 Self::from(Variant::NodeId(Box::new(v.into())))
144 }
145}
146
147impl From<ReferenceTypeId> for LiteralOperand {
148 fn from(v: ReferenceTypeId) -> Self {
149 Self::from(Variant::NodeId(Box::new(v.into())))
150 }
151}
152
153impl From<()> for LiteralOperand {
154 fn from(_v: ()) -> Self {
155 Self::from(Variant::from(()))
156 }
157}
158
159impl From<Variant> for LiteralOperand {
160 fn from(v: Variant) -> Self {
161 LiteralOperand { value: v }
162 }
163}
164
165impl TryFrom<ExtensionObject> for Operand {
166 type Error = StatusCode;
167
168 fn try_from(v: ExtensionObject) -> Result<Self, Self::Error> {
169 let operand = match_extension_object_owned!(v,
170 v: ElementOperand => Self::ElementOperand(v),
171 v: LiteralOperand => Self::LiteralOperand(v),
172 v: AttributeOperand => Self::AttributeOperand(v),
173 v: SimpleAttributeOperand => Self::SimpleAttributeOperand(v),
174 _ => return Err(StatusCode::BadFilterOperandInvalid)
175 );
176
177 Ok(operand)
178 }
179}
180
181impl From<Operand> for ExtensionObject {
182 fn from(v: Operand) -> Self {
183 match v {
184 Operand::ElementOperand(op) => ExtensionObject::from_message(op),
185 Operand::LiteralOperand(op) => ExtensionObject::from_message(op),
186 Operand::AttributeOperand(op) => ExtensionObject::from_message(op),
187 Operand::SimpleAttributeOperand(op) => ExtensionObject::from_message(op),
188 }
189 }
190}
191
192impl From<&Operand> for ExtensionObject {
193 fn from(v: &Operand) -> Self {
194 Self::from(v.clone())
195 }
196}
197
198impl From<(FilterOperator, Vec<Operand>)> for ContentFilterElement {
199 fn from(v: (FilterOperator, Vec<Operand>)) -> ContentFilterElement {
200 ContentFilterElement {
201 filter_operator: v.0,
202 filter_operands: Some(v.1.iter().map(|op| op.into()).collect()),
203 }
204 }
205}
206
207impl From<ElementOperand> for Operand {
208 fn from(v: ElementOperand) -> Operand {
209 Operand::ElementOperand(v)
210 }
211}
212
213impl From<LiteralOperand> for Operand {
214 fn from(v: LiteralOperand) -> Self {
215 Operand::LiteralOperand(v)
216 }
217}
218
219impl From<SimpleAttributeOperand> for Operand {
220 fn from(v: SimpleAttributeOperand) -> Self {
221 Operand::SimpleAttributeOperand(v)
222 }
223}
224
225impl Operand {
226 pub fn element(index: u32) -> Operand {
228 ElementOperand { index }.into()
229 }
230
231 pub fn literal<T>(literal: T) -> Operand
233 where
234 T: Into<LiteralOperand>,
235 {
236 Operand::LiteralOperand(literal.into())
237 }
238
239 pub fn simple_attribute<T>(
241 type_definition_id: T,
242 browse_path: &str,
243 attribute_id: AttributeId,
244 index_range: NumericRange,
245 ) -> Operand
246 where
247 T: Into<NodeId>,
248 {
249 SimpleAttributeOperand::new(type_definition_id, browse_path, attribute_id, index_range)
250 .into()
251 }
252
253 pub fn operand_type(&self) -> OperandType {
255 match self {
256 Operand::ElementOperand(_) => OperandType::ElementOperand,
257 Operand::LiteralOperand(_) => OperandType::LiteralOperand,
258 Operand::AttributeOperand(_) => OperandType::AttributeOperand,
259 Operand::SimpleAttributeOperand(_) => OperandType::SimpleAttributeOperand,
260 }
261 }
262
263 pub fn is_element(&self) -> bool {
265 self.operand_type() == OperandType::ElementOperand
266 }
267
268 pub fn is_literal(&self) -> bool {
270 self.operand_type() == OperandType::LiteralOperand
271 }
272
273 pub fn is_attribute(&self) -> bool {
275 self.operand_type() == OperandType::AttributeOperand
276 }
277
278 pub fn is_simple_attribute(&self) -> bool {
280 self.operand_type() == OperandType::SimpleAttributeOperand
281 }
282}
283
284#[derive(Debug, Default)]
292pub struct ContentFilterBuilder {
293 elements: Vec<ContentFilterElement>,
294}
295
296impl ContentFilterBuilder {
297 pub fn new() -> Self {
299 Self::default()
300 }
301
302 fn add_element(
303 mut self,
304 filter_operator: FilterOperator,
305 filter_operands: Vec<Operand>,
306 ) -> Self {
307 let filter_operands = filter_operands.iter().map(ExtensionObject::from).collect();
308 self.elements.push(ContentFilterElement {
309 filter_operator,
310 filter_operands: Some(filter_operands),
311 });
312 self
313 }
314
315 pub fn eq<T, S>(self, o1: T, o2: S) -> Self
317 where
318 T: Into<Operand>,
319 S: Into<Operand>,
320 {
321 self.add_element(FilterOperator::Equals, vec![o1.into(), o2.into()])
322 }
323
324 pub fn is_null<T>(self, o1: T) -> Self
326 where
327 T: Into<Operand>,
328 {
329 self.add_element(FilterOperator::IsNull, vec![o1.into()])
330 }
331
332 pub fn gt<T, S>(self, o1: T, o2: S) -> Self
334 where
335 T: Into<Operand>,
336 S: Into<Operand>,
337 {
338 self.add_element(FilterOperator::GreaterThan, vec![o1.into(), o2.into()])
339 }
340
341 pub fn lt<T, S>(self, o1: T, o2: S) -> Self
343 where
344 T: Into<Operand>,
345 S: Into<Operand>,
346 {
347 self.add_element(FilterOperator::LessThan, vec![o1.into(), o2.into()])
348 }
349
350 pub fn gte<T, S>(self, o1: T, o2: S) -> Self
352 where
353 T: Into<Operand>,
354 S: Into<Operand>,
355 {
356 self.add_element(
357 FilterOperator::GreaterThanOrEqual,
358 vec![o1.into(), o2.into()],
359 )
360 }
361
362 pub fn lte<T, S>(self, o1: T, o2: S) -> Self
364 where
365 T: Into<Operand>,
366 S: Into<Operand>,
367 {
368 self.add_element(FilterOperator::LessThanOrEqual, vec![o1.into(), o2.into()])
369 }
370
371 pub fn like<T, S>(self, o1: T, o2: S) -> Self
373 where
374 T: Into<Operand>,
375 S: Into<Operand>,
376 {
377 self.add_element(FilterOperator::Like, vec![o1.into(), o2.into()])
378 }
379
380 pub fn not<T>(self, o1: T) -> Self
382 where
383 T: Into<Operand>,
384 {
385 self.add_element(FilterOperator::Not, vec![o1.into()])
386 }
387
388 pub fn between<T, S, U>(self, o1: T, o2: S, o3: U) -> Self
390 where
391 T: Into<Operand>,
392 S: Into<Operand>,
393 U: Into<Operand>,
394 {
395 self.add_element(
396 FilterOperator::Between,
397 vec![o1.into(), o2.into(), o3.into()],
398 )
399 }
400
401 pub fn in_list<T, S>(self, o1: T, list_items: Vec<S>) -> Self
403 where
404 T: Into<Operand>,
405 S: Into<Operand>,
406 {
407 let mut filter_operands = Vec::with_capacity(list_items.len() + 1);
409 filter_operands.push(o1.into());
410 list_items.into_iter().for_each(|list_item| {
411 filter_operands.push(list_item.into());
412 });
413 self.add_element(FilterOperator::InList, filter_operands)
414 }
415
416 pub fn and<T, S>(self, o1: T, o2: S) -> Self
418 where
419 T: Into<Operand>,
420 S: Into<Operand>,
421 {
422 self.add_element(FilterOperator::And, vec![o1.into(), o2.into()])
423 }
424
425 pub fn or<T, S>(self, o1: T, o2: S) -> Self
427 where
428 T: Into<Operand>,
429 S: Into<Operand>,
430 {
431 self.add_element(FilterOperator::Or, vec![o1.into(), o2.into()])
432 }
433
434 pub fn cast<T, S>(self, o1: T, o2: S) -> Self
436 where
437 T: Into<Operand>,
438 S: Into<Operand>,
439 {
440 self.add_element(FilterOperator::Cast, vec![o1.into(), o2.into()])
441 }
442
443 pub fn bitwise_and<T, S>(self, o1: T, o2: S) -> Self
445 where
446 T: Into<Operand>,
447 S: Into<Operand>,
448 {
449 self.add_element(FilterOperator::BitwiseAnd, vec![o1.into(), o2.into()])
450 }
451
452 pub fn bitwise_or<T, S>(self, o1: T, o2: S) -> Self
454 where
455 T: Into<Operand>,
456 S: Into<Operand>,
457 {
458 self.add_element(FilterOperator::BitwiseOr, vec![o1.into(), o2.into()])
459 }
460
461 pub fn of_type<T>(self, type_id: T) -> Self
463 where
464 T: Into<Operand>,
465 {
466 self.add_element(FilterOperator::OfType, vec![type_id.into()])
467 }
468
469 pub fn build(self) -> ContentFilter {
471 ContentFilter {
472 elements: Some(self.elements),
473 }
474 }
475}
476
477impl SimpleAttributeOperand {
478 pub fn new<T>(
480 type_definition_id: T,
481 browse_path: &str,
482 attribute_id: AttributeId,
483 index_range: NumericRange,
484 ) -> Self
485 where
486 T: Into<NodeId>,
487 {
488 const ESCAPE_PATTERN: &str = "###!!!###@@@$$$$";
490 let browse_path = browse_path.replace(r"\/", ESCAPE_PATTERN);
492 let browse_path = browse_path
496 .split('/')
497 .map(|s| QualifiedName::new(0, s.replace(ESCAPE_PATTERN, "/")))
498 .collect();
499 SimpleAttributeOperand {
500 type_definition_id: type_definition_id.into(),
501 browse_path: Some(browse_path),
502 attribute_id: attribute_id as u32,
503 index_range,
504 }
505 }
506
507 pub fn new_value<T>(type_definition_id: T, browse_path: &str) -> Self
510 where
511 T: Into<NodeId>,
512 {
513 Self::new(
514 type_definition_id,
515 browse_path,
516 AttributeId::Value,
517 NumericRange::None,
518 )
519 }
520}