jkevan commented on code in PR #426:
URL: https://github.com/apache/unomi/pull/426#discussion_r879557019
##########
extensions/json-schema/services/src/main/java/org/apache/unomi/schema/impl/SchemaServiceImpl.java:
##########
@@ -139,103 +150,192 @@ public void saveSchema(String schema) {
public boolean deleteSchema(String schemaId) {
// forbidden to delete predefined Unomi schemas
if (!predefinedUnomiJSONSchemaById.containsKey(schemaId)) {
- schemasById.remove(schemaId);
+ // remove persisted schema
return persistenceService.remove(schemaId,
JsonSchemaWrapper.class);
}
return false;
}
@Override
public void loadPredefinedSchema(InputStream schemaStream) throws
IOException {
- String jsonSchema = IOUtils.toString(schemaStream);
-
- // check that schema is valid and get the id
- JsonNode schemaNode =
jsonSchemaFactory.getSchema(jsonSchema).getSchemaNode();
- String schemaId = schemaNode.get("$id").asText();
- String target = schemaNode.at("/self/target").asText();
- JsonSchemaWrapper jsonSchemaWrapper = new JsonSchemaWrapper(schemaId,
jsonSchema, target);
-
- predefinedUnomiJSONSchemaById.put(schemaId, jsonSchemaWrapper);
- schemasById.put(schemaId, jsonSchemaWrapper);
+ String schema = IOUtils.toString(schemaStream);
+ JsonSchemaWrapper jsonSchemaWrapper = buildJsonSchemaWrapper(schema);
+ predefinedUnomiJSONSchemaById.put(jsonSchemaWrapper.getItemId(),
jsonSchemaWrapper);
}
@Override
public boolean unloadPredefinedSchema(InputStream schemaStream) {
JsonNode schemaNode =
jsonSchemaFactory.getSchema(schemaStream).getSchemaNode();
String schemaId = schemaNode.get("$id").asText();
+ return predefinedUnomiJSONSchemaById.remove(schemaId) != null;
+ }
- return predefinedUnomiJSONSchemaById.remove(schemaId) != null &&
schemasById.remove(schemaId) != null;
+ private JsonSchemaWrapper buildJsonSchemaWrapper(String schema) {
+ JsonSchema jsonSchema = jsonSchemaFactory.getSchema(schema);
+ JsonNode schemaNode = jsonSchema.getSchemaNode();
+
+ String schemaId = schemaNode.get("$id").asText();
+ String target = schemaNode.at("/self/target").asText();
+ String name = schemaNode.at("/self/name").asText();
+ String extendsSchemaId = schemaNode.at("/self/extends").asText();
+
+ if ("events".equals(target) &&
!name.matches("[_A-Za-z][_0-9A-Za-z]*")) {
+ throw new IllegalArgumentException(
+ "The \"/self/name\" value should match the following
regular expression [_A-Za-z][_0-9A-Za-z]* for the Json schema on events");
+ }
+
+ return new JsonSchemaWrapper(schemaId, schema, target,
extendsSchemaId, new Date());
}
- @Override
- public JsonSchemaWrapper getSchema(String schemaId) {
- return schemasById.get(schemaId);
+ private void refreshJSONSchemas() {
+ // use local variable to avoid concurrency issues.
+ Map<String, JsonSchemaWrapper> schemasByIdReloaded = new HashMap<>();
+ schemasByIdReloaded.putAll(predefinedUnomiJSONSchemaById);
+
schemasByIdReloaded.putAll(persistenceService.getAllItems(JsonSchemaWrapper.class).stream().collect(Collectors.toMap(Item::getItemId,
s -> s)));
+
+ // flush cache if size is different (can be new schema or deleted
schemas)
+ boolean changes = schemasByIdReloaded.size() != schemasById.size();
+ // check for modifications
+ if (!changes) {
+ for (JsonSchemaWrapper reloadedSchema :
schemasByIdReloaded.values()) {
+ JsonSchemaWrapper oldSchema =
schemasById.get(reloadedSchema.getItemId());
+ if (oldSchema == null ||
!oldSchema.getTimeStamp().equals(reloadedSchema.getTimeStamp())) {
+ changes = true;
+ break;
+ }
+ }
+ }
+
+ if (changes) {
+ schemasById.clear();
+ schemasById.putAll(schemasByIdReloaded);
+
+ initExtensions(schemasByIdReloaded);
+ initJsonSchemaFactory();
+ }
}
- private URIFetcher getUriFetcher() {
- return uri -> {
- logger.debug("Fetching schema {}", uri);
- JsonSchemaWrapper jsonSchemaWrapper =
schemasById.get(uri.toString());
- if (jsonSchemaWrapper == null) {
- logger.error("Couldn't find schema {}", uri);
- return null;
+ private void initExtensions(Map<String, JsonSchemaWrapper> schemas) {
+ Map<String, Set<String>> extensionsReloaded = new HashMap<>();
+ // lookup extensions
+ List<JsonSchemaWrapper> schemaExtensions = schemas.values()
+ .stream()
+ .filter(jsonSchemaWrapper ->
StringUtils.isNotBlank(jsonSchemaWrapper.getExtendsSchemaId()))
+ .collect(Collectors.toList());
+
+ // build new in RAM extensions map
+ for (JsonSchemaWrapper extension : schemaExtensions) {
+ String extendedSchemaId = extension.getExtendsSchemaId();
+ if (!extension.getItemId().equals(extendedSchemaId)) {
+ if (!extensionsReloaded.containsKey(extendedSchemaId)) {
+ extensionsReloaded.put(extendedSchemaId, new HashSet<>());
+ }
+
extensionsReloaded.get(extendedSchemaId).add(extension.getItemId());
+ } else {
+ logger.warn("A schema cannot extends himself, please fix your
schema definition for schema: {}", extendedSchemaId);
}
- return IOUtils.toInputStream(jsonSchemaWrapper.getSchema());
- };
+ }
+
+ extensions.clear();
+ extensions.putAll(extensionsReloaded);
Review Comment:
Since the map can be accessible by multiple Threads, mostly http clients, it
have to be concurrent.
I'm not sure that variable reassignation is better than map manipulation in
a concurrent world.
But I'm defenitly interested on discussion/guidlines about it if you have
answers on the topic :)
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]