in OWL2DTDL/Relationship.cs [63:192]
public void MergeWith(Relationship other)
{
if (!other.Property.Resource.Equals(this.Property.Resource))
{
throw new Exception("Properties are not identical");
}
// If target classes are not the same, then we need to keep the most specific one
if (!other.Target.Resource.Equals(this.Target.Resource))
{
// If both target classes are both datatypes,
if (this.Target.IsDatatype() && other.Target.IsDatatype())
{
// If the two targets are of same type but not the same, fall back to rdf:Literal
if (
(this.Target.IsEnumerationDatatype() && other.Target.IsEnumerationDatatype()) ||
(this.Target.IsSimpleXsdWrapper() && other.Target.IsSimpleXsdWrapper()) ||
(this.Target.IsXsdDatatype() && other.Target.IsXsdDatatype()))
{
IGraph targetsGraph = this.Target.Graph;
IUriNode rdfLiteral = targetsGraph.CreateUriNode(VocabularyHelper.RDFS.Literal);
this.Target = new OntologyClass(rdfLiteral, targetsGraph);
this.MinimumCount = null;
this.MaximumCount = null;
return;
}
else
{
// Preference order is enumeration, custom xsd wrapper type, built-in xsd type
List<Relationship> relationshipCandidates = new List<Relationship>() { this, other };
relationshipCandidates.OrderBy(candidate => !candidate.Target.IsEnumerationDatatype())
.ThenBy(candidate => !candidate.Target.IsSimpleXsdWrapper())
.ThenBy(candidate => !candidate.Target.IsXsdDatatype());
if (relationshipCandidates.First() == this)
{
return;
}
else
{
this.Target = other.Target;
this.MinimumCount = other.MinimumCount;
this.MaximumCount = other.MaximumCount;
return;
}
}
}
// If this relationship has the more specific target class, keep it as-is, i.e., return
if (this.Target.SuperClassesWithOwlThing().Contains(other.Target))
{
return;
}
// If the other relationhip has the more specific target class, keep it instead and return
else if (other.Target.SuperClassesWithOwlThing().Contains(this.Target))
{
this.Target = other.Target;
this.MinimumCount = other.MinimumCount;
this.MaximumCount = other.MaximumCount;
return;
}
// The classes do not subsume one another; fall back to OWL:Thing as target class
else
{
IGraph targetsGraph = this.Target.Graph;
IUriNode owlThing = targetsGraph.CreateUriNode(VocabularyHelper.OWL.Thing);
this.Target = new OntologyClass(owlThing, targetsGraph);
this.MinimumCount = null;
this.MaximumCount = null;
return;
}
}
// If either restriction has an exact count, then that is the most specific restriction possible and min/max need not be inspected
if (ExactCount.HasValue || other.ExactCount.HasValue)
{
// If both restrictions have exact values they either diverge (e.g., caused by an inconsistent ontology) or they converge (no change is required)
if (ExactCount.HasValue && other.ExactCount.HasValue)
{
if (ExactCount.Value != other.ExactCount.Value)
{
throw new Exception("Conflicting ExactCounts");
}
// The exact value is identical; simply return
return;
}
// Assign exact count from other only if our own is null, else keep our old exactcount
ExactCount ??= other.ExactCount.Value;
return;
}
int? newMinimum = new int?();
if (MinimumCount.HasValue || other.MinimumCount.HasValue)
{
// If both have minimum counts, keep the larger one
if (MinimumCount.HasValue && other.MinimumCount.HasValue)
{
newMinimum = MinimumCount > other.MinimumCount ? MinimumCount : other.MinimumCount;
}
else
{
// Else, keep whichever is non-null
newMinimum = MinimumCount.HasValue ? MinimumCount : other.MinimumCount;
}
}
int? newMaximum = new int?();
if (MaximumCount.HasValue || other.MaximumCount.HasValue)
{
// If both have maximum counts, keep the smaller one
if (MaximumCount.HasValue && other.MaximumCount.HasValue)
{
newMaximum = MaximumCount < other.MaximumCount ? MaximumCount : other.MaximumCount;
}
else
{
// Else, keep whichever is non-null
newMaximum = MaximumCount.HasValue ? MaximumCount : other.MaximumCount;
}
}
// At this point newMinimum is maximized or null and newMaximum is minimized or null
// If they are inconsistent, i.e., newMinimum is larger than new Maximum, the model is inconsistent;
// throw an error; else store
if (newMinimum.HasValue && newMaximum.HasValue && newMinimum > newMaximum)
{
throw new Exception("Resulting min > resulting max");
}
MinimumCount = newMinimum;
MaximumCount = newMaximum;
}