File: DynamicRefKeyword.txt

package info (click to toggle)
jsoncons 1.5.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 18,300 kB
  • sloc: cpp: 143,266; sh: 34; makefile: 8
file content (158 lines) | stat: -rw-r--r-- 6,959 bytes parent folder | download | duplicates (2)
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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
public KeywordConstraint GetConstraint(SchemaConstraint schemaConstraint, IReadOnlyList<KeywordConstraint> localConstraints, EvaluationContext context)
{
  var newUri = new Uri(context.Scope.LocalScope, Reference);
  var newBaseUri = new Uri(newUri.GetLeftPart(UriPartial.Query));
  var anchorName = Reference.OriginalString.Split('#').Last();

  JsonSchema? targetSchema = null;
  var targetBase = context.Options.SchemaRegistry.Get(newBaseUri) ??
                   throw new JsonSchemaException($"Cannot resolve base schema from `{newUri}`");

  foreach (var uri in context.Scope.Reverse())
  {
        var scopeRoot = context.Options.SchemaRegistry.Get(uri);
        if (scopeRoot == null)
                throw new Exception("This shouldn't happen");

        if (scopeRoot is not JsonSchema schemaRoot)
                throw new Exception("Does OpenAPI use anchors?");

        if (!schemaRoot.Anchors.TryGetValue(anchorName, out var anchor) || !anchor.IsDynamic) continue;

        if (targetBase is JsonSchema targetBaseSchema &&
            context.EvaluatingAs == SpecVersion.Draft202012 &&
            (!targetBaseSchema.Anchors.TryGetValue(anchorName, out var targetAnchor) || !targetAnchor.IsDynamic)) break;

        targetSchema = anchor.Schema;
        break;
  }

  if (targetSchema == null)
  {
        if (JsonPointer.TryParse(newUri.Fragment, out var pointerFragment))
        {
                if (targetBase == null)
                        throw new JsonSchemaException($"Cannot resolve base schema from `{newUri}`");

                targetSchema = targetBase.FindSubschema(pointerFragment!, context.Options);
        }
        else
        {
                var anchorFragment = newUri.Fragment.Substring(1);
                if (!AnchorKeyword.AnchorPattern.IsMatch(anchorFragment))
                        throw new JsonSchemaException($"Unrecognized fragment type `{newUri}`");

                if (targetBase is JsonSchema targetBaseSchema &&
                    targetBaseSchema.Anchors.TryGetValue(anchorFragment, out var anchorDefinition))
                        targetSchema = anchorDefinition.Schema;
        }

        if (targetSchema == null)
                throw new JsonSchemaException($"Cannot resolve schema `{newUri}`");
  }

  return new KeywordConstraint(Name, (e, c) => Evaluator(e, c, targetSchema));
}

Anchors
    public EvaluationResults Evaluate(JsonNode? root, EvaluationOptions? options = null)
    {
        options = EvaluationOptions.From(options ?? EvaluationOptions.Default);

        // BaseUri may change if $id is present
        // TODO: remove options.EvaluatingAs
        var evaluatingAs = DetermineSpecVersion(this, options.SchemaRegistry, options.EvaluateAs);
        PopulateBaseUris(this, this, BaseUri, options.SchemaRegistry, evaluatingAs, true);


        var context = new EvaluationContext(options, evaluatingAs, BaseUri);
        var constraint = BuildConstraint(JsonPointer.Empty, JsonPointer.Empty, JsonPointer.Empty, context.Scope);
        if (!BoolValue.HasValue)
                PopulateConstraint(constraint, context);

        var evaluation = constraint.BuildEvaluation(root, JsonPointer.Empty, JsonPointer.Empty, options);
        evaluation.Evaluate(context);

        if (options.AddAnnotationForUnknownKeywords && constraint.UnknownKeywords != null)
                evaluation.Results.SetAnnotation(_unknownKeywordsAnnotationKey, constraint.UnknownKeywords);

        var results = evaluation.Results;
        switch (options.OutputFormat)
        {
                case OutputFormat.Flag:
                        results.ToFlag();
                        break;
                case OutputFormat.List:
                        results.ToList();
                        break;
                case OutputFormat.Hierarchical:
                        break;
                default:
                        throw new ArgumentOutOfRangeException();
        }

        return results;
    }

    private static void PopulateBaseUris(JsonSchema schema, JsonSchema resourceRoot, Uri currentBaseUri, SchemaRegistry registry, SpecVersion evaluatingAs = SpecVersion.Unspecified, bool selfRegister = false)
    {
        if (schema.BoolValue.HasValue) return;
        evaluatingAs = DetermineSpecVersion(schema, registry, evaluatingAs);
        if (evaluatingAs is SpecVersion.Draft6 or SpecVersion.Draft7 &&
                schema.TryGetKeyword<RefKeyword>(RefKeyword.Name, out _))
        {
                schema.BaseUri = currentBaseUri;
                if (selfRegister)
                        registry.RegisterSchema(schema.BaseUri, schema);
        }
        else
        {
                var idKeyword = (IIdKeyword?)schema.Keywords!.FirstOrDefault(x => x is IIdKeyword);
                if (idKeyword != null)
                {
                        if (evaluatingAs <= SpecVersion.Draft7 &&
                            idKeyword.Id.OriginalString[0] == '#' &&
                            AnchorKeyword.AnchorPattern.IsMatch(idKeyword.Id.OriginalString.Substring(1)))
                        {
                                schema.BaseUri = currentBaseUri;
                                resourceRoot.Anchors[idKeyword.Id.OriginalString.Substring(1)] = (schema, false);
                        }
                        else
                        {
                                schema.IsResourceRoot = true;
                                schema.DeclaredVersion = evaluatingAs;
                                resourceRoot = schema;
                                schema.BaseUri = new Uri(currentBaseUri, idKeyword.Id);
                                registry.RegisterSchema(schema.BaseUri, schema);
                        }
                }
                else
                {
                        schema.BaseUri = currentBaseUri;
                        if (selfRegister)
                                registry.RegisterSchema(schema.BaseUri, schema);
                }

                if (schema.TryGetKeyword<AnchorKeyword>(AnchorKeyword.Name, out var anchorKeyword))
                {
                        resourceRoot.Anchors[anchorKeyword!.Anchor] = (schema, false);
                }

                if (schema.TryGetKeyword<DynamicAnchorKeyword>(DynamicAnchorKeyword.Name, out var dynamicAnchorKeyword))
                {
                        resourceRoot.Anchors[dynamicAnchorKeyword!.Value] = (schema, true);
                }

                schema.TryGetKeyword<RecursiveAnchorKeyword>(RecursiveAnchorKeyword.Name, out var recursiveAnchorKeyword);
                if (recursiveAnchorKeyword is { Value: true })
                        resourceRoot.RecursiveAnchor = schema;
        }

        var subschemas = schema.Keywords!.SelectMany(GetSubschemas);

        foreach (var subschema in subschemas)
        {
                PopulateBaseUris(subschema, resourceRoot, schema.BaseUri, registry, evaluatingAs);
        }
    }