Medical Imaging Interaction Toolkit  2018.4.99-08619e4f
Medical Imaging Interaction Toolkit
mitkPropertyRelationRuleBase.cpp
Go to the documentation of this file.
1 /*============================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center (DKFZ)
6 All rights reserved.
7 
8 Use of this source code is governed by a 3-clause BSD license that can be
9 found in the LICENSE file.
10 
11 ============================================================================*/
12 
14 
15 #include <mitkDataNode.h>
16 #include <mitkExceptionMacro.h>
17 #include <mitkNodePredicateBase.h>
18 #include <mitkStringProperty.h>
19 #include <mitkUIDGenerator.h>
20 
21 #include <mutex>
22 #include <regex>
23 #include <algorithm>
24 
26 {
27  return true;
28 }
29 
31 {
32  return owner != nullptr;
33 }
34 
36 {
37  return owner != nullptr;
38 }
39 
41 {
42  return PropertyKeyPath().AddElement("MITK").AddElement("Relations");
43 }
44 
46 {
47  return ruleID == this->GetRuleID();
48 }
49 
51 {
52  auto path = GetRootKeyPath();
53  if (instanceID.empty())
54  {
55  path.AddAnyElement();
56  }
57  else
58  {
59  path.AddElement(instanceID);
60  }
61 
62  if (!propName.empty())
63  {
64  path.AddElement(propName);
65  }
66 
67  return path;
68 }
69 
70 std::string mitk::PropertyRelationRuleBase::GetRIIPropertyRegEx(const std::string propName, const InstanceIDType &instanceID) const
71 {
72  return PropertyKeyPathToPropertyRegEx(GetRIIPropertyKeyPath(propName, instanceID));
73 }
74 
76 {
77  return GetRIIPropertyKeyPath("relationUID", instanceID);
78 }
79 
81 {
82  return GetRIIPropertyKeyPath("ruleID", instanceID);
83 }
84 
86 {
87  return GetRIIPropertyKeyPath("destinationUID", instanceID);
88 }
89 
90 //workaround until T24729 is done. Please remove if T24728 is done
91 //then could directly use owner->GetPropertyKeys() again.
93 {
94  std::vector<std::string> keys;
95  auto sourceCasted = dynamic_cast<const mitk::DataNode*>(owner);
96  if (sourceCasted) {
97  auto sourceData = sourceCasted->GetData();
98  if (sourceData) {
99  keys = sourceData->GetPropertyKeys();
100  }
101  else {
102  keys = sourceCasted->GetPropertyKeys();
103  }
104  }
105  else {
106  keys = owner->GetPropertyKeys();
107  }
108  return keys;
109 }
110 //end workaround for T24729
111 
113 {
114  return !this->GetExistingRelations(owner).empty();
115 }
116 
118  const IPropertyProvider* source, const IPropertyProvider* destination, RelationType requiredRelation) const
119 {
120  auto relTypes = this->GetRelationTypes(source, destination);
121 
122 
123  if (requiredRelation == RelationType::None)
124  {
125  return !relTypes.empty();
126  }
127 
128  RelationVectorType allowedTypes = { RelationType::Complete };
129  if (requiredRelation == RelationType::Data)
130  {
131  allowedTypes.emplace_back(RelationType::Data);
132  }
133  else if (requiredRelation == RelationType::ID)
134  {
135  allowedTypes.emplace_back(RelationType::ID);
136  }
137 
138  return relTypes.end() != std::find_first_of(relTypes.begin(), relTypes.end(), allowedTypes.begin(), allowedTypes.end());
139 }
140 
142  const IPropertyProvider* source, const IPropertyProvider* destination) const
143 {
144  if (!source)
145  {
146  mitkThrow() << "Error. Passed source pointer is NULL";
147  }
148  if (!destination)
149  {
150  mitkThrow() << "Error. Passed owner pointer is NULL";
151  }
152 
153  auto instanceIDs_IDLayer = this->GetInstanceID_IDLayer(source, destination);
154  auto relIDs_dataLayer = this->GetRelationUIDs_DataLayer(source, destination, {});
155  if (relIDs_dataLayer.size() > 1)
156  {
157  MITK_WARN << "Property relation on data level is ambiguous. First relation is used. Relation UID: "
158  << relIDs_dataLayer.front().first;
159  }
160 
161  bool hasComplete = instanceIDs_IDLayer.end() != std::find_if(instanceIDs_IDLayer.begin(), instanceIDs_IDLayer.end(), [&](const InstanceIDVectorType::value_type& instanceID)
162  {
163  auto relID_IDlayer = this->GetRelationUIDByInstanceID(source, instanceID);
164  auto ruleID_IDlayer = this->GetRuleIDByInstanceID(source, instanceID);
165 
166  return relIDs_dataLayer.end() != std::find_if(relIDs_dataLayer.begin(), relIDs_dataLayer.end(), [&](const DataRelationUIDVectorType::value_type& relID)
167  {
168  return relID.first == relID_IDlayer && relID.second == ruleID_IDlayer;
169  });
170  });
171 
172  bool hasID = instanceIDs_IDLayer.end() != std::find_if(instanceIDs_IDLayer.begin(), instanceIDs_IDLayer.end(), [&](const InstanceIDVectorType::value_type& instanceID)
173  {
174  auto relID_IDlayer = this->GetRelationUIDByInstanceID(source, instanceID);
175  auto ruleID_IDlayer = this->GetRuleIDByInstanceID(source, instanceID);
176 
177  return relIDs_dataLayer.end() == std::find_if(relIDs_dataLayer.begin(), relIDs_dataLayer.end(), [&](const DataRelationUIDVectorType::value_type& relID)
178  {
179  return relID.first == relID_IDlayer && relID.second == ruleID_IDlayer;
180  });
181  });
182 
183  bool hasData = relIDs_dataLayer.end() != std::find_if(relIDs_dataLayer.begin(), relIDs_dataLayer.end(), [&](const DataRelationUIDVectorType::value_type& relID)
184  {
185  return instanceIDs_IDLayer.end() == std::find_if(instanceIDs_IDLayer.begin(), instanceIDs_IDLayer.end(), [&](const InstanceIDVectorType::value_type& instanceID)
186  {
187  auto relID_IDlayer = this->GetRelationUIDByInstanceID(source, instanceID);
188  auto ruleID_IDlayer = this->GetRuleIDByInstanceID(source, instanceID);
189  return relID.first == relID_IDlayer && relID.second == ruleID_IDlayer;
190  });
191  });
192 
193  RelationVectorType result;
194 
195  if (hasData)
196  {
197  result.emplace_back(RelationType::Data);
198  }
199  if (hasID)
200  {
201  result.emplace_back(RelationType::ID);
202  }
203  if (hasComplete)
204  {
205  result.emplace_back(RelationType::Complete);
206  }
207 
208  return result;
209 }
210 
212  const IPropertyProvider *source, RelationType layer) const
213 {
214  if (!source)
215  {
216  mitkThrow() << "Error. Passed source pointer is NULL";
217  }
218 
219  RelationUIDVectorType relationUIDs;
220  InstanceIDVectorType instanceIDs;
221 
222  if (layer != RelationType::Data)
223  {
224  auto ruleIDRegExStr = this->GetRIIPropertyRegEx("ruleID");
225  auto regEx = std::regex(ruleIDRegExStr);
226 
227  //workaround until T24729 is done. You can use directly source->GetPropertyKeys again, when fixed.
228  const auto keys = GetPropertyKeys(source);
229  //end workaround for T24729
230 
231  for (const auto& key : keys)
232  {
233  if (std::regex_match(key, regEx))
234  {
235  auto idProp = source->GetConstProperty(key);
236  auto ruleID = idProp->GetValueAsString();
237  if (this->IsSupportedRuleID(ruleID))
238  {
239  auto instanceID = this->GetInstanceIDByPropertyName(key);
240  instanceIDs.emplace_back(instanceID);
241  relationUIDs.push_back(this->GetRelationUIDByInstanceID(source, instanceID));
242  }
243  }
244  }
245  }
246 
247  if (layer == RelationType::ID)
248  {
249  return relationUIDs;
250  }
251 
252  DataRelationUIDVectorType relationUIDandRuleID_Data;
253  if (layer != RelationType::ID)
254  {
255  relationUIDandRuleID_Data = this->GetRelationUIDs_DataLayer(source, nullptr, instanceIDs);
256  }
257 
258  RelationUIDVectorType relationUIDs_Data;
259  std::transform(relationUIDandRuleID_Data.begin(), relationUIDandRuleID_Data.end(), std::back_inserter(relationUIDs_Data),
260  [](const DataRelationUIDVectorType::value_type& v) { return v.first; });
261 
262  if (layer == RelationType::Data)
263  {
264  return relationUIDs_Data;
265  }
266 
267  std::sort(relationUIDs.begin(), relationUIDs.end());
268  std::sort(relationUIDs_Data.begin(), relationUIDs_Data.end());
269 
270  RelationUIDVectorType result;
271 
272  if (layer == RelationType::Complete)
273  {
274  std::set_intersection(relationUIDs.begin(), relationUIDs.end(), relationUIDs_Data.begin(), relationUIDs_Data.end(), std::back_inserter(result));
275  }
276  else
277  {
278  std::set_union(relationUIDs.begin(), relationUIDs.end(), relationUIDs_Data.begin(), relationUIDs_Data.end(), std::back_inserter(result));
279  }
280 
281  return result;
282 }
283 
285  const IPropertyProvider *source, const IPropertyProvider *destination) const
286 {
287  if (!source)
288  {
289  mitkThrow() << "Error. Passed source pointer is NULL";
290  }
291  if (!destination)
292  {
293  mitkThrow() << "Error. Passed destination pointer is NULL";
294  }
295 
296  RelationUIDVectorType relUIDs_id;
297 
298  auto instanceIDs = this->GetInstanceID_IDLayer(source, destination);
299  for (const auto& instanceID : instanceIDs)
300  {
301  relUIDs_id.push_back(this->GetRelationUIDByInstanceID(source, instanceID));
302  }
303 
304  DataRelationUIDVectorType relationUIDandRuleID_Data = this->GetRelationUIDs_DataLayer(source,destination,instanceIDs);
305  RelationUIDVectorType relUIDs_Data;
306  std::transform(relationUIDandRuleID_Data.begin(), relationUIDandRuleID_Data.end(), std::back_inserter(relUIDs_Data),
307  [](const DataRelationUIDVectorType::value_type& v) { return v.first; });
308 
309  std::sort(relUIDs_id.begin(), relUIDs_id.end());
310  std::sort(relUIDs_Data.begin(), relUIDs_Data.end());
311 
312  RelationUIDVectorType result;
313  std::set_union(relUIDs_id.begin(), relUIDs_id.end(), relUIDs_Data.begin(), relUIDs_Data.end(), std::back_inserter(result));
314 
315  return result;
316 }
317 
320 {
321  auto result = this->GetRelationUIDs(source, destination);
322 
323  if (result.empty())
324  {
326  }
327  else if(result.size()>1)
328  {
329  mitkThrow() << "Cannot return one(!) relation UID. Multiple relations exists for given rule, source and destination.";
330  }
331 
332  return result[0];
333 }
334 
336 {
337  return std::string();
338 };
339 
341  const IPropertyProvider *source, const InstanceIDType &instanceID) const
342 {
343  RelationUIDType result;
344 
345  if (instanceID != NULL_INSTANCE_ID())
346  {
347  auto idProp = source->GetConstProperty(
349 
350  if (idProp.IsNotNull())
351  {
352  result = idProp->GetValueAsString();
353  }
354  }
355 
356  if (result.empty())
357  {
359  }
360 
361  return result;
362 }
363 
365  const IPropertyProvider *source, const RelationUIDType &relationUID) const
366 {
367  if (!source)
368  {
369  mitkThrow() << "Error. Passed source pointer is NULL";
370  }
371 
372  InstanceIDType result = NULL_INSTANCE_ID();
373 
374  auto destRegExStr =
376  auto regEx = std::regex(destRegExStr);
377  std::smatch instance_matches;
378 
379  //workaround until T24729 is done. You can use directly source->GetPropertyKeys again, when fixed.
380  const auto keys = GetPropertyKeys(source);
381  //end workaround for T24729
382 
383  for (const auto &key : keys)
384  {
385  if (std::regex_search(key, instance_matches, regEx))
386  {
387  auto idProp = source->GetConstProperty(key);
388  if (idProp->GetValueAsString() == relationUID)
389  {
390  if (instance_matches.size()>1)
391  {
392  result = instance_matches[1];
393  break;
394  }
395  }
396  }
397  }
398 
399  return result;
400 }
401 
403  const IPropertyProvider *source, const IPropertyProvider *destination) const
404 {
405  if (!source)
406  {
407  mitkThrow() << "Error. Passed source pointer is NULL";
408  }
409  if (!destination)
410  {
411  mitkThrow() << "Error. Passed destination pointer is NULL";
412  }
413 
414  auto identifiable = CastProviderAsIdentifiable(destination);
415 
416  InstanceIDVectorType result;
417 
418  if (identifiable)
419  { // check for relations of type Connected_ID;
420 
421  auto destRegExStr = this->GetRIIPropertyRegEx("destinationUID");
422  auto regEx = std::regex(destRegExStr);
423  std::smatch instance_matches;
424 
425  auto destUID = identifiable->GetUID();
426 
427  //workaround until T24729 is done. You can use directly source->GetPropertyKeys again, when fixed.
428  const auto keys = GetPropertyKeys(source);
429  //end workaround for T24729
430 
431  for (const auto &key : keys)
432  {
433  if (std::regex_search(key, instance_matches, regEx))
434  {
435  auto idProp = source->GetConstProperty(key);
436  if (idProp->GetValueAsString() == destUID)
437  {
438  if (instance_matches.size()>1)
439  {
440  auto instanceID = instance_matches[1];
441  if (this->IsSupportedRuleID(GetRuleIDByInstanceID(source, instanceID)))
442  {
443  result.push_back(instanceID);
444  }
445  }
446  }
447  }
448  }
449  }
450 
451  return result;
452 }
453 
455 {
456  auto identifiable = dynamic_cast<const Identifiable*>(destination);
457 
458  if (!identifiable)
459  { //This check and pass through to data is needed due to solve T25711. See Task for more information.
460  //This could be removed at the point we can get rid of DataNodes or they get realy transparent.
461  auto node = dynamic_cast<const DataNode*>(destination);
462  if (node && node->GetData())
463  {
464  identifiable = dynamic_cast<const Identifiable*>(node->GetData());
465  }
466  }
467 
468  return identifiable;
469 }
470 
472 {
473  if (!source)
474  {
475  mitkThrow() << "Error. Passed source pointer is NULL";
476  }
477  if (!destination)
478  {
479  mitkThrow() << "Error. Passed destination pointer is NULL";
480  }
481  if (this->IsAbstract())
482  {
483  mitkThrow() << "Error. This is an abstract property relation rule. Abstract rule must not make a connection. Please use a concrete rule.";
484  }
485 
486  auto instanceIDs = this->GetInstanceID_IDLayer(source, destination);
487  bool hasIDlayer = !instanceIDs.empty();
488 
489  auto relUIDs_data = this->GetRelationUIDs_DataLayer(source, destination, {});
490 
491  if (relUIDs_data.size() > 1)
492  {
493  MITK_WARN << "Property relation on data level is ambiguous. First relation is used. RelationUID ID: "
494  << relUIDs_data.front().first;
495  }
496 
497  bool hasDatalayer = !relUIDs_data.empty();
498 
499  RelationUIDType relationUID = this->CreateRelationUID();
500 
501  InstanceIDType instanceID = NULL_INSTANCE_ID();
502 
503  if (hasIDlayer)
504  {
505  instanceID = instanceIDs.front();
506  }
507  else if (hasDatalayer)
508  {
509  try
510  {
511  instanceID = this->GetInstanceIDByRelationUID(source, relUIDs_data.front().first);
512  }
513  catch(...)
514  { }
515  }
516 
517  if(instanceID == NULL_INSTANCE_ID())
518  {
519  instanceID = this->CreateNewRelationInstance(source, relationUID);
520  }
521 
522  auto relUIDKey =
524  source->SetProperty(relUIDKey, mitk::StringProperty::New(relationUID));
525 
526  auto ruleIDKey =
528  source->SetProperty(ruleIDKey, mitk::StringProperty::New(this->GetRuleID()));
529 
530  if (!hasIDlayer)
531  {
532  auto identifiable = this->CastProviderAsIdentifiable(destination);
533 
534  if (identifiable)
535  {
536  auto destUIDKey =
538  source->SetProperty(destUIDKey, mitk::StringProperty::New(identifiable->GetUID()));
539  }
540  }
541 
542  this->Connect_datalayer(source, destination, instanceID);
543 
544  return relationUID;
545 }
546 
548 {
549  if (source == nullptr)
550  {
551  mitkThrow() << "Error. Source is invalid. Cannot disconnect.";
552  }
553 
554  if (destination == nullptr)
555  {
556  mitkThrow() << "Error. Destination is invalid. Cannot disconnect.";
557  }
558 
559  try
560  {
561  const auto relationUIDs = this->GetRelationUIDs(source, destination);
562  for (const auto& relUID: relationUIDs)
563  {
564  this->Disconnect(source, relUID, layer);
565  }
566  }
567  catch (const NoPropertyRelationException &)
568  {
569  // nothing to do and no real error in context of disconnect.
570  }
571 }
572 
574 {
575  if (source == nullptr)
576  {
577  mitkThrow() << "Error. Source is invalid. Cannot disconnect.";
578  }
579 
580  if (layer == RelationType::Data || layer == RelationType::Complete)
581  {
582  this->Disconnect_datalayer(source, relationUID);
583  }
584 
585  auto instanceID = this->GetInstanceIDByRelationUID(source, relationUID);
586  if ((layer == RelationType::ID || layer == RelationType::Complete) && instanceID != NULL_INSTANCE_ID())
587  {
588  auto instancePrefix = PropertyKeyPathToPropertyName(GetRootKeyPath().AddElement(instanceID));
589 
590  //workaround until T24729 is done. You can use directly source->GetPropertyKeys again, when fixed.
591  const auto keys = GetPropertyKeys(source);
592  //end workaround for T24729
593 
594 
595  for (const auto &key : keys)
596  {
597  if (key.find(instancePrefix) == 0)
598  {
599  source->RemoveProperty(key);
600  }
601  }
602  }
603 }
604 
605 mitk::PropertyRelationRuleBase::RelationUIDType mitk::PropertyRelationRuleBase::CreateRelationUID()
606 {
607  UIDGenerator generator;
608  return generator.GetUID();
609 }
610 
616 
617 mitk::PropertyRelationRuleBase::InstanceIDType mitk::PropertyRelationRuleBase::CreateNewRelationInstance(
618  IPropertyOwner *source, const RelationUIDType &relationUID) const
619 {
620  std::lock_guard<std::mutex> guard(relationCreationLock);
621 
623  // Get all existing instanc IDs
624 
625  std::vector<int> instanceIDs;
626  InstanceIDType newID = "1";
627 
628  auto destRegExStr =
630  auto regEx = std::regex(destRegExStr);
631  std::smatch instance_matches;
632 
633  //workaround until T24729 is done. You can use directly source->GetPropertyKeys again, when fixed.
634  const auto keys = GetPropertyKeys(source);
635  //end workaround for T24729
636 
637 
638  for (const auto &key : keys)
639  {
640  if (std::regex_search(key, instance_matches, regEx))
641  {
642  if (instance_matches.size()>1)
643  {
644  instanceIDs.push_back(std::stoi(instance_matches[1]));
645  }
646  }
647  }
648 
650  // Get new ID
651 
652  std::sort(instanceIDs.begin(), instanceIDs.end());
653  if (!instanceIDs.empty())
654  {
655  newID = std::to_string(instanceIDs.back() + 1);
656  }
657 
659  // reserve new ID
660  auto relUIDKey =
662  source->SetProperty(relUIDKey, mitk::StringProperty::New(relationUID));
663 
664  return newID;
665 }
666 
667 itk::LightObject::Pointer mitk::PropertyRelationRuleBase::InternalClone() const
668 {
669  return Superclass::InternalClone();
670 }
671 
672 
674 {
675  auto proppath = PropertyNameToPropertyKeyPath(propName);
676  auto ref = GetRootKeyPath();
677 
678  if (proppath.GetSize() < 3 || !(proppath.GetFirstNode() == ref.GetFirstNode()) || !(proppath.GetNode(1) == ref.GetNode(1)))
679  {
680  mitkThrow() << "Property name is not for a RII property or containes no instance ID. Wrong name: " << propName;
681  }
682 
683  return proppath.GetNode(2).name;
684 }
685 
687  const InstanceIDType &instanceID) const
688 {
689  if (!source)
690  {
691  mitkThrow() << "Error. Source is invalid. Cannot deduce rule ID";
692  }
693 
694  auto path = GetRIIRuleIDPropertyKeyPath(instanceID);
695  auto name = PropertyKeyPathToPropertyName(path);
696 
697  const auto prop = source->GetConstProperty(name);
698 
699  std::string result;
700 
701  if (prop.IsNotNull())
702  {
703  result = prop->GetValueAsString();
704  }
705 
706  if (result.empty())
707  {
708  mitkThrowException(NoPropertyRelationException) << "Error. Source has no property relation with the passed instance ID. Instance ID: " << instanceID;
709  }
710 
711  return result;
712 }
713 
715  const InstanceIDType& instanceID) const
716 {
717  if (!source)
718  {
719  mitkThrow() << "Error. Source is invalid. Cannot deduce rule ID";
720  }
721 
722  auto path = GetRIIDestinationUIDPropertyKeyPath(instanceID);
723  auto name = PropertyKeyPathToPropertyName(path);
724 
725  const auto prop = source->GetConstProperty(name);
726 
727  std::string result;
728 
729  if (prop.IsNotNull())
730  {
731  result = prop->GetValueAsString();
732  }
733 
734  return result;
735 }
736 
737 
738 namespace mitk
739 {
745  class NodePredicateRuleFunction : public NodePredicateBase
746  {
747  public:
748  using FunctionType = std::function<bool(const mitk::IPropertyProvider *, const mitk::PropertyRelationRuleBase *)>;
749 
750  mitkClassMacro(NodePredicateRuleFunction, NodePredicateBase)
751  mitkNewMacro2Param(NodePredicateRuleFunction, const FunctionType &, PropertyRelationRuleBase::ConstPointer)
752 
753  ~NodePredicateRuleFunction() override = default;
754 
755  bool CheckNode(const mitk::DataNode *node) const override
756  {
757  if (!node)
758  {
759  return false;
760  }
761 
762  return m_Function(node, m_Rule);
763  };
764 
765  protected:
766  explicit NodePredicateRuleFunction(const FunctionType &function, PropertyRelationRuleBase::ConstPointer rule) : m_Function(function), m_Rule(rule)
767  {
768  };
769 
770  FunctionType m_Function;
772  };
773 
774 } // namespace mitk
775 
777 {
778  auto check = [](const mitk::IPropertyProvider *node, const mitk::PropertyRelationRuleBase *rule) {
779  return rule->IsSourceCandidate(node);
780  };
781 
782  return NodePredicateRuleFunction::New(check, this).GetPointer();
783 }
784 
786 {
787  auto check = [](const mitk::IPropertyProvider *node, const mitk::PropertyRelationRuleBase *rule) {
788  return rule->IsDestinationCandidate(node);
789  };
790 
791  return NodePredicateRuleFunction::New(check, this).GetPointer();
792 }
793 
795 {
796  auto check = [](const mitk::IPropertyProvider *node, const mitk::PropertyRelationRuleBase *rule)
797  {
798  return rule->IsSource(node);
799  };
800 
801  return NodePredicateRuleFunction::New(check, this).GetPointer();
802 }
803 
805  const IPropertyProvider *destination, RelationType exclusiveRelation) const
806 {
807  if (!destination)
808  {
809  mitkThrow() << "Error. Passed destination pointer is NULL";
810  }
811 
812  auto check = [destination, exclusiveRelation](const mitk::IPropertyProvider *node,
813  const mitk::PropertyRelationRuleBase *rule) {
814  return rule->HasRelation(node, destination, exclusiveRelation);
815  };
816 
817  return NodePredicateRuleFunction::New(check, this).GetPointer();
818 }
819 
821  const IPropertyProvider *source, RelationType exclusiveRelation) const
822 {
823  if (!source)
824  {
825  mitkThrow() << "Error. Passed source pointer is NULL";
826  }
827 
828  auto check = [source, exclusiveRelation](const mitk::IPropertyProvider *node,
829  const mitk::PropertyRelationRuleBase *rule) {
830  return rule->HasRelation(source, node, exclusiveRelation);
831  };
832 
833  return NodePredicateRuleFunction::New(check, this).GetPointer();
834 }
835 
837  const IPropertyProvider *source, RelationUIDType relationUID) const
838 {
839  if (!source)
840  {
841  mitkThrow() << "Error. Passed source pointer is NULL";
842  }
843 
844  auto relUIDs = this->GetExistingRelations(source);
845  if (std::find(relUIDs.begin(), relUIDs.end(), relationUID) == relUIDs.end())
846  {
847  mitkThrow()
848  << "Error. Passed relationUID does not identify a relation instance of the passed source for this rule instance.";
849  };
850 
851  auto check = [source, relationUID](const mitk::IPropertyProvider *node, const mitk::PropertyRelationRuleBase *rule) {
852  try
853  {
854  auto relevantUIDs = rule->GetRelationUIDs(source, node);
855  for (const auto& aUID : relevantUIDs)
856  {
857  if (aUID == relationUID)
858  {
859  return true;
860  }
861  }
862  }
863  catch(const NoPropertyRelationException &)
864  {
865  return false;
866  }
867  return false;
868  };
869 
870  return NodePredicateRuleFunction::New(check, this).GetPointer();
871 }
virtual RuleIDType GetRuleID() const =0
NodePredicateBase::ConstPointer GetSourceCandidateIndicator() const
std::mutex relationCreationLock
const Identifiable * CastProviderAsIdentifiable(const mitk::IPropertyProvider *provider) const
MITKCORE_EXPORT std::string PropertyKeyPathToPropertyName(const PropertyKeyPath &tagPath)
Generated unique IDs.
NodePredicateBase::ConstPointer GetConnectedSourcesDetector() const
NodePredicateBase::ConstPointer GetSourcesDetector(const IPropertyProvider *destination, RelationType exclusiveRelation=RelationType::None) const
NodePredicateBase::ConstPointer GetDestinationCandidateIndicator() const
RelationUIDType GetRelationUID(const IPropertyProvider *source, const IPropertyProvider *destination) const
virtual bool IsSupportedRuleID(const RuleIDType &ruleID) const
RelationVectorType GetRelationTypes(const IPropertyProvider *source, const IPropertyProvider *destination) const
DataCollection - Class to facilitate loading/accessing structured data.
PropertyKeyPath & AddElement(const ElementNameType &name)
InstanceIDVectorType GetInstanceID_IDLayer(const IPropertyProvider *source, const IPropertyProvider *destination) const
NodePredicateBase::ConstPointer GetDestinationDetector(const IPropertyProvider *source, RelationUIDType relationUID) const
virtual BaseProperty::ConstPointer GetConstProperty(const std::string &propertyKey, const std::string &contextName="", bool fallBackOnDefaultContext=true) const =0
Get property by its key.
virtual void Disconnect_datalayer(IPropertyOwner *source, const RelationUIDType &relationUID) const =0
#define mitkNewMacro2Param(classname, typea, typeb)
Definition: mitkCommon.h:85
static PropertyKeyPath GetRIIRelationUIDPropertyKeyPath(const InstanceIDType &instanceID="")
RelationUIDType Connect(IPropertyOwner *source, const IPropertyProvider *destination) const
static PropertyKeyPath GetRIIDestinationUIDPropertyKeyPath(const InstanceIDType &instanceID="")
std::string GetRIIPropertyRegEx(const std::string propName="", const InstanceIDType &instanceID="") const
static PropertyKeyPath GetRIIRuleIDPropertyKeyPath(const InstanceIDType &instanceID="")
virtual void Connect_datalayer(IPropertyOwner *source, const IPropertyProvider *destination, const InstanceIDType &instanceID) const =0
RelationUIDType GetRelationUIDByInstanceID(const IPropertyProvider *source, const InstanceIDType &instanceID) const
InstanceIDType GetInstanceIDByRelationUID(const IPropertyProvider *source, const RelationUIDType &relationUID) const
BaseData * GetData() const
Get the data object (instance of BaseData, e.g., an Image) managed by this DataNode.
#define MITK_WARN
Definition: mitkLogMacros.h:19
virtual void RemoveProperty(const std::string &propertyKey, const std::string &contextName="", bool fallBackOnDefaultContext=false)=0
Removes a property. If the property does not exist, nothing will be done.
virtual std::vector< std::string > GetPropertyKeys(const std::string &contextName="", bool includeDefaultContext=false) const =0
Query keys of existing properties.
virtual DataRelationUIDVectorType GetRelationUIDs_DataLayer(const IPropertyProvider *source, const IPropertyProvider *destination, const InstanceIDVectorType &instances_IDLayer) const =0
#define mitkClassMacro(className, SuperClassName)
Definition: mitkCommon.h:40
#define mitkThrow()
MITKCORE_EXPORT PropertyKeyPath PropertyNameToPropertyKeyPath(const std::string &propertyName)
bool HasRelation(const IPropertyProvider *source, const IPropertyProvider *destination, RelationType requiredRelation=RelationType::None) const
NodePredicateBase::ConstPointer GetDestinationsDetector(const IPropertyProvider *source, RelationType exclusiveRelation=RelationType::None) const
void Disconnect(IPropertyOwner *source, const IPropertyProvider *destination, RelationType layer=RelationType::Complete) const
std::vector< RelationUIDType > RelationUIDVectorType
#define mitkThrowException(classname)
itk::LightObject::Pointer InternalClone() const override
std::vector< std::pair< RelationUIDType, RuleIDType > > DataRelationUIDVectorType
virtual bool IsSourceCandidate(const IPropertyProvider *owner) const
static InstanceIDType GetInstanceIDByPropertyName(const std::string propName)
RuleIDType GetRuleIDByInstanceID(const IPropertyProvider *source, const InstanceIDType &instanceID) const
Interface for evaluation conditions used in the DataStorage class GetSubset() method.
RelationUIDVectorType GetExistingRelations(const IPropertyProvider *source, RelationType layer=RelationType::None) const
std::vector< InstanceIDType > InstanceIDVectorType
static std::vector< std::string > GetPropertyKeys(const IPropertyProvider *owner)
std::vector< RelationType > RelationVectorType
Class that can be used to specify nested or wild carded property keys. E.g. for the use in context of...
static PropertyKeyPath GetRIIPropertyKeyPath(const std::string propName, const InstanceIDType &instanceID)
Base class of identifiable objects.
static Pointer New()
MITKCORE_EXPORT std::string PropertyKeyPathToPropertyRegEx(const PropertyKeyPath &tagPath)
Class for nodes of the DataTree.
Definition: mitkDataNode.h:57
bool IsSource(const IPropertyProvider *owner) const
virtual void SetProperty(const std::string &propertyKey, BaseProperty *property, const std::string &contextName="", bool fallBackOnDefaultContext=false)=0
Add new or change existent property.
RelationUIDVectorType GetRelationUIDs(const IPropertyProvider *source, const IPropertyProvider *destination) const
std::string GetDestinationUIDByInstanceID(const IPropertyProvider *source, const InstanceIDType &instanceID) const
virtual bool IsDestinationCandidate(const IPropertyProvider *owner) const