/// <summary>
        /// Gets the direct (rdf:type) and indirect (rdfs:subClassOf) instances of the given class within the given data graph
        /// </summary>
        internal static List <RDFPatternMember> GetInstancesOfClass(this RDFGraph dataGraph, RDFResource className, HashSet <long> visitContext = null)
        {
            var result = new List <RDFPatternMember>();

            if (className != null && dataGraph != null)
            {
                #region visitContext
                if (visitContext == null)
                {
                    visitContext = new HashSet <long>()
                    {
                        { className.PatternMemberID }
                    };
                }
                else
                {
                    if (!visitContext.Contains(className.PatternMemberID))
                    {
                        visitContext.Add(className.PatternMemberID);
                    }
                    else
                    {
                        return(result);
                    }
                }
                #endregion

                //rdf:type
                foreach (var triple in dataGraph.SelectTriplesByPredicate(RDFVocabulary.RDF.TYPE)
                         .SelectTriplesByObject(className))
                {
                    result.Add(triple.Subject);
                }

                //rdfs:subClassOf
                foreach (var triple in dataGraph.SelectTriplesByPredicate(RDFVocabulary.RDFS.SUB_CLASS_OF)
                         .SelectTriplesByObject(className))
                {
                    result.AddRange(dataGraph.GetInstancesOfClass((RDFResource)triple.Subject, visitContext));
                }
            }
            return(result);
        }
        /// <summary>
        /// Evaluates this constraint against the given data graph
        /// </summary>
        internal override RDFValidationReport ValidateConstraint(RDFShapesGraph shapesGraph, RDFGraph dataGraph, RDFShape shape, RDFPatternMember focusNode, List <RDFPatternMember> valueNodes)
        {
            RDFValidationReport     report         = new RDFValidationReport();
            List <RDFPatternMember> classInstances = dataGraph.GetInstancesOfClass(this.ClassType);

            #region Evaluation
            foreach (RDFPatternMember valueNode in valueNodes)
            {
                switch (valueNode)
                {
                //Resource
                case RDFResource valueNodeResource:
                    if (!classInstances.Any(x => x.Equals(valueNodeResource)))
                    {
                        report.AddResult(new RDFValidationResult(shape,
                                                                 RDFVocabulary.SHACL.CLASS_CONSTRAINT_COMPONENT,
                                                                 focusNode,
                                                                 shape is RDFPropertyShape ? ((RDFPropertyShape)shape).Path : null,
                                                                 valueNode,
                                                                 shape.Messages,
                                                                 shape.Severity));
                    }
                    break;

                //Literal
                case RDFLiteral valueNodeLiteral:
                    report.AddResult(new RDFValidationResult(shape,
                                                             RDFVocabulary.SHACL.CLASS_CONSTRAINT_COMPONENT,
                                                             focusNode,
                                                             shape is RDFPropertyShape ? ((RDFPropertyShape)shape).Path : null,
                                                             valueNode,
                                                             shape.Messages,
                                                             shape.Severity));
                    break;
                }
            }
            #endregion

            return(report);
        }
        /// <summary>
        /// Gets the focus nodes of the given shape
        /// </summary>
        internal static List <RDFPatternMember> GetFocusNodesOf(this RDFGraph dataGraph, RDFShape shape)
        {
            List <RDFPatternMember> result = new List <RDFPatternMember>();

            if (shape != null && dataGraph != null)
            {
                foreach (RDFTarget target in shape.Targets)
                {
                    switch (target)
                    {
                    //sh:targetClass
                    case RDFTargetClass targetClass:
                        result.AddRange(dataGraph.GetInstancesOfClass(target.TargetValue)
                                        .OfType <RDFResource>());
                        break;

                    //sh:targetNode
                    case RDFTargetNode targetNode:
                        result.Add(target.TargetValue);
                        break;

                    //sh:targetSubjectsOf
                    case RDFTargetSubjectsOf targetSubjectsOf:
                        result.AddRange(dataGraph.SelectTriplesByPredicate(target.TargetValue)
                                        .Select(x => x.Subject)
                                        .OfType <RDFResource>());
                        break;

                    //sh:targetObjectsOf
                    case RDFTargetObjectsOf targetObjectsOf:
                        result.AddRange(dataGraph.SelectTriplesByPredicate(target.TargetValue)
                                        .Select(x => x.Object)
                                        .OfType <RDFResource>());
                        break;
                    }
                }
            }
            return(RDFQueryUtilities.RemoveDuplicates(result));
        }