public void MergeWith()

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;
        }