1 package io.apicurio.registry.maven.refs;
2
3 import com.fasterxml.jackson.databind.JsonNode;
4 import com.fasterxml.jackson.databind.ObjectMapper;
5 import io.apicurio.datamodels.Library;
6 import io.apicurio.datamodels.models.Document;
7 import io.apicurio.datamodels.util.ModelTypeUtil;
8 import io.apicurio.registry.content.ContentHandle;
9 import io.apicurio.registry.rest.client.models.VersionMetaData;
10 import io.apicurio.registry.types.ArtifactType;
11 import io.apicurio.registry.utils.protobuf.schema.ProtobufFile;
12
13 import java.nio.file.Path;
14 import java.util.HashSet;
15 import java.util.Set;
16
17
18
19
20
21
22
23
24
25
26 public class ReferenceIndex {
27
28 private static final ObjectMapper mapper = new ObjectMapper();
29
30 private Set<IndexedResource> index = new HashSet<>();
31 private Set<Path> schemaPaths = new HashSet<>();
32
33
34
35
36 public ReferenceIndex() {
37 }
38
39
40
41
42
43
44 public ReferenceIndex(Path schemaPath) {
45 this.schemaPaths.add(schemaPath);
46 }
47
48
49
50
51 public void addSchemaPath(Path path) {
52 this.schemaPaths.add(path);
53 }
54
55
56
57
58
59
60
61 public IndexedResource lookup(String resourceName, Path relativeToFile) {
62 return index.stream().filter(resource -> resource.matches(resourceName, relativeToFile, schemaPaths))
63 .findFirst().orElse(null);
64 }
65
66
67
68
69
70
71
72 public void index(String resourceName, VersionMetaData vmd) {
73 IndexedResource res = new IndexedResource(null, null, resourceName, null);
74 res.setRegistration(vmd);
75 this.index.add(res);
76 }
77
78
79
80
81
82
83
84 public void index(Path path, ContentHandle content) {
85 try {
86 JsonNode tree = mapper.readTree(content.content());
87
88
89 if (tree.has("openapi") || tree.has("swagger") || tree.has("asyncapi")) {
90 indexDataModels(path, content);
91 }
92
93 if (tree.has("$schema") && !tree.get("$schema").isNull()) {
94 indexJsonSchema(tree, path, content);
95 }
96
97 indexAvro(path, content, tree);
98 } catch (Exception e) {
99
100 }
101
102 try {
103 indexProto(path, content);
104 return;
105 } catch (Exception e) {
106
107 }
108 }
109
110 private void indexAvro(Path path, ContentHandle content, JsonNode parsed) {
111
112 String ns = parsed.get("namespace").asText();
113 String name = parsed.get("name").asText();
114 String resourceName = ns != null ? ns + "." + name : name;
115 IndexedResource resource = new IndexedResource(path, ArtifactType.AVRO, resourceName, content);
116 this.index.add(resource);
117 }
118
119 private void indexProto(Path path, ContentHandle content) {
120 ProtobufFile.toProtoFileElement(content.content());
121
122 IndexedResource resource = new IndexedResource(path, ArtifactType.PROTOBUF, null, content);
123 this.index.add(resource);
124 }
125
126 private void indexJsonSchema(JsonNode schema, Path path, ContentHandle content) {
127 String resourceName = null;
128 if (schema.has("$id")) {
129 resourceName = schema.get("$id").asText(null);
130 }
131 IndexedResource resource = new IndexedResource(path, ArtifactType.JSON, resourceName, content);
132 this.index.add(resource);
133 }
134
135 private void indexDataModels(Path path, ContentHandle content) {
136 Document doc = Library.readDocumentFromJSONString(content.content());
137 if (doc == null) {
138 throw new UnsupportedOperationException("Content is not OpenAPI or AsyncAPI.");
139 }
140
141 String type = ArtifactType.OPENAPI;
142 if (ModelTypeUtil.isAsyncApiModel(doc)) {
143 type = ArtifactType.ASYNCAPI;
144 }
145
146 IndexedResource resource = new IndexedResource(path, type, null, content);
147 this.index.add(resource);
148 }
149
150 }