-
Notifications
You must be signed in to change notification settings - Fork 0
/
Property.cs
128 lines (112 loc) · 4.78 KB
/
Property.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
using VDS.RDF;
using VDS.RDF.Ontology;
using DotNetRdfExtensions;
using DotNetRdfExtensions.SHACL;
namespace SHACL2DTDL
{
class Property {
public enum PropertyType {
Data,
Object
}
public IUriNode WrappedProperty { get; }
public IUriNode? Target { get; }
public IEnumerable<INode> In { get; }
public int? MaxCardinality { get; set; }
public int? MinCardinality { get; set; }
public PropertyType Type { get; set; }
public IEnumerable<ILiteralNode> Labels { get; init; }
public IEnumerable<ILiteralNode> Comments { get; init; }
public string Name {
get {
return WrappedProperty.LocalName();
}
}
// TODO: Support different types of property paths, see https://www.w3.org/TR/shacl/#property-paths
// (currently we only support simple ) predicate paths, i.e., where ps.Path.NodeType = NodeType.Uri
public Property(PropertyShape pShape) {
// Set WrappedProperty
if (pShape.Path is not IUriNode) {
throw new ArgumentException($"Property path {pShape.Path} is not a URI node");
}
WrappedProperty = (IUriNode)pShape.Path;
// Set up labels and comments from property shape or (fallback) from wrapped property label/comment
if (pShape.Names.Count() > 0) {
Labels = pShape.Names;
}
else {
Labels = pShape.Path.RdfsLabels();
}
if (pShape.Descriptions.Count() > 0) {
Comments = pShape.Descriptions;
}
else {
Comments = pShape.Path.RdfsComments();
}
// Set Type & Target
if (pShape.Datatype is IUriNode || (pShape.NodeKind is IUriNode nodeKind1 && nodeKind1.LocalName() == "Literal")) {
Type = PropertyType.Data;
// Note: pShape.Datatype can be null
Target = pShape.Datatype;
}
else if (pShape.Class.FirstOrDefault() is IUriNode || pShape.NodeKind is IUriNode nodeKind2 && nodeKind2.LocalName() == "IRI") {
Type = PropertyType.Object;
// Note: pShape.Class.FirstOrDefault() can be null
Target = pShape.Class.FirstOrDefault();
}
else {
Type = PropertyType.Object;
}
In = pShape.In;
// Set cardinality
// Note: both of these can be null
MinCardinality = pShape.MinCount;
MaxCardinality = pShape.MaxCount;
}
public Property(OntologyProperty property) {
// Set WrappedProperty
if (property.Resource is not IUriNode) {
throw new ArgumentException($"Property path {property.Resource} is not a URI node");
}
WrappedProperty = (IUriNode)property.Resource;
Labels = property.Resource.RdfsLabels();
Comments = property.Resource.RdfsComments();
In = new List<INode>();
// Set Target if singleton URI exists
if (property.Ranges.Count() == 1) {
if (property.Ranges.First().Resource is IUriNode) {
OntologyClass range = property.Ranges.First();
IUriNode rangeNode = (IUriNode)range.Resource;
Target = rangeNode;
}
if (property.Ranges.First().IsEnumerationDatatype()) {
In = property.Ranges.First().AsEnumeration();
}
}
// If we are declared to be an OWL datatype property or if our range is explicitly a XSD, then we are a data property
if (WrappedProperty.TransitiveRdfTypes().Any(type => type.LocalName() == "DatatypeProperty") || (Target is not null && Target.IsXsdType())) {
Type = PropertyType.Data;
}
else {
// Otherwise, we're an object property
Type = PropertyType.Object;
}
// Set cardinality
if (WrappedProperty.TransitiveRdfTypes().Any(type => type.LocalName() == "FunctionalProperty")) {
MinCardinality = MaxCardinality = 1;
}
}
public class PropertyNameComparer: IEqualityComparer<Property>
{
public bool Equals(Property? one, Property? two) {
if (one is null || two is null) {
return false;
}
return StringComparer.InvariantCultureIgnoreCase.Equals(one.Name, two.Name);
}
public int GetHashCode(Property item) {
return StringComparer.InvariantCultureIgnoreCase.GetHashCode(item.Name);
}
}
}
}