Skip to content

Commit

Permalink
Fixed uuids at rest api.
Browse files Browse the repository at this point in the history
  • Loading branch information
Acarus committed Sep 21, 2016
1 parent 7488ab7 commit 54975ed
Show file tree
Hide file tree
Showing 7 changed files with 64 additions and 100 deletions.
Expand Up @@ -16,6 +16,7 @@


package org.kaaproject.kaa.server.common.core.algorithms; package org.kaaproject.kaa.server.common.core.algorithms;


import java.io.IOException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
Expand All @@ -26,7 +27,7 @@
import org.apache.avro.Schema.Type; import org.apache.avro.Schema.Type;
import org.apache.avro.generic.GenericData; import org.apache.avro.generic.GenericData;
import org.codehaus.jackson.JsonNode; import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.node.ArrayNode; import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.node.ObjectNode; import org.codehaus.jackson.node.ObjectNode;


import static org.kaaproject.kaa.server.common.core.algorithms.CommonConstants.*; import static org.kaaproject.kaa.server.common.core.algorithms.CommonConstants.*;
Expand Down Expand Up @@ -92,20 +93,50 @@ public static void copyJsonProperties(JsonProperties src, JsonProperties dst) {
} }
} }


public static String injectUuids(String json, Schema schema) throws IOException {
return injectUuids(json.getBytes(), schema);
}


public static void injectUuids(JsonNode json) { public static String injectUuids(byte[] content, Schema schema) throws IOException {
boolean containerWithoutId = json.isContainerNode() && !json.has(UUID_FIELD); ObjectMapper objectMapper = new ObjectMapper();
boolean notArray = !json.isArray(); JsonNode root = objectMapper.readTree(content);
boolean childIsNotArray = !(json.size() == 1 && json.getElements().next() instanceof ArrayNode); injectUuidsFromJsonNodes(root, schema);
return root.toString();
}


if (containerWithoutId && notArray && childIsNotArray) { public static String injectUuids(JsonNode root, Schema schema) {
((ObjectNode)json).put(UUID_FIELD, (Integer)null); return injectUuidsFromJsonNodes(root, schema).toString();
}

private static JsonNode injectUuidsFromJsonNodes(JsonNode json, Schema schema) {
if (json == null) {
return json;
} }


for (JsonNode node : json) { switch (schema.getType()) {
if (node.isContainerNode()) case RECORD:
injectUuids(node); schema.getFields().stream()
.filter(f -> !f.name().equals(UUID_FIELD))
.forEach(f -> injectUuidsFromJsonNodes(json.get(f.name()), f.schema()));

boolean addressable = schema.getFields().stream().filter(f -> f.name().equals(UUID_FIELD)).findFirst().isPresent();
if (addressable) {
((ObjectNode) json).put(UUID_FIELD, (Integer) null);
}
break;
case UNION:
schema.getTypes()
.forEach(s -> injectUuidsFromJsonNodes(json.get(s.getName()), s));
break;
case ARRAY:
schema.getElementType().getTypes()
.forEach(s -> injectUuidsFromJsonNodes(json.get(s.getName()), s));
break;
default:
return json;
} }

return json;
} }


public static void removeUuids(JsonNode json) { public static void removeUuids(JsonNode json) {
Expand Down
Expand Up @@ -17,6 +17,7 @@
package org.kaaproject.kaa.server.common.core.algorithms; package org.kaaproject.kaa.server.common.core.algorithms;




import org.apache.avro.Schema;
import org.codehaus.jackson.JsonNode; import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.map.ObjectMapper;
import org.junit.Assert; import org.junit.Assert;
Expand All @@ -28,17 +29,18 @@
public class AvroUtilsTest { public class AvroUtilsTest {
private JsonNode data; private JsonNode data;
private JsonNode dataWithUUIDs; private JsonNode dataWithUUIDs;
private Schema avroSchema;


@Before @Before
public void setUp() throws IOException { public void setUp() throws IOException {
data = new ObjectMapper().readTree(AvroUtilsTest.class.getClassLoader().getResourceAsStream("uuids/data.json")); data = new ObjectMapper().readTree(AvroUtilsTest.class.getClassLoader().getResourceAsStream("uuids/data.json"));
dataWithUUIDs = new ObjectMapper().readTree(AvroUtilsTest.class.getClassLoader().getResourceAsStream("uuids/data_with_uuids.json")); dataWithUUIDs = new ObjectMapper().readTree(AvroUtilsTest.class.getClassLoader().getResourceAsStream("uuids/data_with_uuids.json"));
avroSchema = new Schema.Parser().parse(AvroUtilsTest.class.getClassLoader().getResourceAsStream("uuids/schema.json"));
} }


@Test @Test
public void testInjectUuids() throws IOException { public void testInjectUuids() throws IOException {
AvroUtils.injectUuids(data); String jsonWithUUIds = AvroUtils.injectUuids(data, avroSchema);
String jsonWithUUIds = data.toString();
Assert.assertTrue("Generated json is not equal json with UUIDs", jsonWithUUIds.equals(dataWithUUIDs.toString())); Assert.assertTrue("Generated json is not equal json with UUIDs", jsonWithUUIds.equals(dataWithUUIDs.toString()));
} }


Expand Down
21 changes: 1 addition & 20 deletions common/core/src/test/resources/uuids/data.json
@@ -1,22 +1,3 @@
{ {
"AddressList": { "label": "a"
"array": [
{
"label": "Kaa website",
"url": "http://www.kaaproject.org"
},
{
"label": "Kaa GitHub repository",
"url": "https://github.com/kaaproject/kaa"
},
{
"label": "Kaa docs",
"url": "http://docs.kaaproject.org/display/KAA/Kaa+IoT+Platform+Home"
},
{
"label": "Kaa configuration design reference",
"url": "http://docs.kaaproject.org/display/KAA/Configuration"
}
]
}
} }
25 changes: 1 addition & 24 deletions common/core/src/test/resources/uuids/data_with_uuids.json
@@ -1,27 +1,4 @@
{ {
"AddressList": { "label": "a",
"array": [
{
"label": "Kaa website",
"url": "http://www.kaaproject.org",
"__uuid":null
},
{
"label": "Kaa GitHub repository",
"url": "https://github.com/kaaproject/kaa",
"__uuid":null
},
{
"label": "Kaa docs",
"url": "http://docs.kaaproject.org/display/KAA/Kaa+IoT+Platform+Home",
"__uuid":null
},
{
"label": "Kaa configuration design reference",
"url": "http://docs.kaaproject.org/display/KAA/Configuration",
"__uuid":null
}
]
},
"__uuid":null "__uuid":null
} }
8 changes: 8 additions & 0 deletions common/core/src/test/resources/uuids/schema.json
@@ -0,0 +1,8 @@
{
"type":"record",
"name": "someFields",
"fields":[
{"name":"label", "type":"string"},
{"name":"__uuid", "type":"string"}
]
}
Expand Up @@ -47,6 +47,7 @@
import org.kaaproject.kaa.common.dto.UpdateStatus; import org.kaaproject.kaa.common.dto.UpdateStatus;
import org.kaaproject.kaa.common.dto.VersionDto; import org.kaaproject.kaa.common.dto.VersionDto;
import org.kaaproject.kaa.common.dto.ctl.CTLSchemaDto; import org.kaaproject.kaa.common.dto.ctl.CTLSchemaDto;
import org.kaaproject.kaa.server.common.core.algorithms.AvroUtils;
import org.kaaproject.kaa.server.common.core.algorithms.generation.DefaultRecordGenerationAlgorithm; import org.kaaproject.kaa.server.common.core.algorithms.generation.DefaultRecordGenerationAlgorithm;
import org.kaaproject.kaa.server.common.core.algorithms.generation.DefaultRecordGenerationAlgorithmImpl; import org.kaaproject.kaa.server.common.core.algorithms.generation.DefaultRecordGenerationAlgorithmImpl;
import org.kaaproject.kaa.server.common.core.algorithms.schema.SchemaCreationException; import org.kaaproject.kaa.server.common.core.algorithms.schema.SchemaCreationException;
Expand Down Expand Up @@ -271,24 +272,27 @@ private void validateUuids(ConfigurationDto currentConfiguration, ConfigurationD
try { try {
EndpointGroup endpointGroup = endpointGroupDao.findById(currentConfiguration.getEndpointGroupId()); EndpointGroup endpointGroup = endpointGroupDao.findById(currentConfiguration.getEndpointGroupId());
GenericAvroConverter<GenericRecord> avroConverter; GenericAvroConverter<GenericRecord> avroConverter;
Schema avroSchema;
KaaData body = null; KaaData body = null;
if (endpointGroup != null) { if (endpointGroup != null) {
if (endpointGroup.getWeight() == 0) { if (endpointGroup.getWeight() == 0) {
LOG.debug("Create default UUID validator with base schema: {}", configurationSchema.getBaseSchema()); LOG.debug("Create default UUID validator with base schema: {}", configurationSchema.getBaseSchema());
BaseSchema baseSchema = new BaseSchema(configurationSchema.getBaseSchema()); BaseSchema baseSchema = new BaseSchema(configurationSchema.getBaseSchema());
uuidValidator = new DefaultUuidValidator(baseSchema, new BaseDataFactory()); uuidValidator = new DefaultUuidValidator(baseSchema, new BaseDataFactory());
avroConverter = new GenericAvroConverter<GenericRecord>(baseSchema.getRawSchema()); avroConverter = new GenericAvroConverter<GenericRecord>(baseSchema.getRawSchema());
avroSchema = new Schema.Parser().parse(baseSchema.getRawSchema());
} else { } else {
LOG.debug("Create default UUID validator with override schema: {}", configurationSchema.getOverrideSchema()); LOG.debug("Create default UUID validator with override schema: {}", configurationSchema.getOverrideSchema());
OverrideSchema overrideSchema = new OverrideSchema(configurationSchema.getOverrideSchema()); OverrideSchema overrideSchema = new OverrideSchema(configurationSchema.getOverrideSchema());
uuidValidator = new DefaultUuidValidator(overrideSchema, new OverrideDataFactory()); uuidValidator = new DefaultUuidValidator(overrideSchema, new OverrideDataFactory());
avroConverter = new GenericAvroConverter<GenericRecord>(overrideSchema.getRawSchema()); avroConverter = new GenericAvroConverter<GenericRecord>(overrideSchema.getRawSchema());
avroSchema = new Schema.Parser().parse(overrideSchema.getRawSchema());
} }
GenericRecord previousRecord = null; GenericRecord previousRecord = null;
if (previousConfiguration != null) { if (previousConfiguration != null) {
previousRecord = avroConverter.decodeJson(previousConfiguration.getBody()); previousRecord = avroConverter.decodeJson(previousConfiguration.getBody());
} }
GenericRecord currentRecord = avroConverter.decodeJson(currentConfiguration.getBody()); GenericRecord currentRecord = avroConverter.decodeJson(AvroUtils.injectUuids(currentConfiguration.getBody(), avroSchema));
body = uuidValidator.validateUuidFields(currentRecord, previousRecord); body = uuidValidator.validateUuidFields(currentRecord, previousRecord);
} }
if (body != null) { if (body != null) {
Expand Down
Expand Up @@ -18,10 +18,6 @@


import org.apache.avro.Schema; import org.apache.avro.Schema;
import org.apache.avro.generic.GenericRecord; import org.apache.avro.generic.GenericRecord;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.node.ArrayNode;
import org.codehaus.jackson.node.ObjectNode;
import org.hibernate.StaleObjectStateException; import org.hibernate.StaleObjectStateException;
import org.kaaproject.avro.ui.converter.FormAvroConverter; import org.kaaproject.avro.ui.converter.FormAvroConverter;
import org.kaaproject.avro.ui.shared.RecordField; import org.kaaproject.avro.ui.shared.RecordField;
Expand Down Expand Up @@ -49,6 +45,7 @@
import org.kaaproject.kaa.server.admin.shared.services.GroupService; import org.kaaproject.kaa.server.admin.shared.services.GroupService;
import org.kaaproject.kaa.server.admin.shared.services.KaaAdminServiceException; import org.kaaproject.kaa.server.admin.shared.services.KaaAdminServiceException;
import org.kaaproject.kaa.server.admin.shared.services.ServiceErrorCode; import org.kaaproject.kaa.server.admin.shared.services.ServiceErrorCode;
import org.kaaproject.kaa.server.common.core.algorithms.AvroUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
Expand Down Expand Up @@ -341,17 +338,12 @@ public ConfigurationRecordFormDto deactivateConfigurationRecordForm(String confi
public RecordField getConfigurationRecordDataFromFile(String schema, String fileItemName) throws KaaAdminServiceException { public RecordField getConfigurationRecordDataFromFile(String schema, String fileItemName) throws KaaAdminServiceException {
checkAuthority(KaaAuthorityDto.TENANT_DEVELOPER, KaaAuthorityDto.TENANT_USER); checkAuthority(KaaAuthorityDto.TENANT_DEVELOPER, KaaAuthorityDto.TENANT_USER);
try { try {
byte[] body = getFileContent(fileItemName);

Schema avroSchema = new Schema.Parser().parse(schema); Schema avroSchema = new Schema.Parser().parse(schema);
JsonNode json = new ObjectMapper().readTree(body); byte[] body = getFileContent(fileItemName);
json = injectUuids(json, avroSchema); body = AvroUtils.injectUuids(body, avroSchema).getBytes();
body = json.toString().getBytes();

GenericAvroConverter<GenericRecord> converter = new GenericAvroConverter<>(schema); GenericAvroConverter<GenericRecord> converter = new GenericAvroConverter<>(schema);
GenericRecord record = converter.decodeJson(body); GenericRecord record = converter.decodeJson(body);
RecordField recordData = FormAvroConverter.createRecordFieldFromGenericRecord(record); return FormAvroConverter.createRecordFieldFromGenericRecord(record);
return recordData;
} catch (Exception e) { } catch (Exception e) {
throw Utils.handleException(e); throw Utils.handleException(e);
} }
Expand Down Expand Up @@ -555,35 +547,4 @@ private List<SchemaInfoDto> toConfigurationSchemaInfos(List<VersionDto> schemas,
} }
return schemaInfos; return schemaInfos;
} }

private JsonNode injectUuids(JsonNode json, Schema schema) {
if (json == null) return json;
String UUID_FIELD = "__uuid";

switch (schema.getType()) {
case RECORD:
schema.getFields().stream()
.filter(f -> !f.name().equals(UUID_FIELD))
.forEach(f -> injectUuids(json.get(f.name()), f.schema()));

boolean addressable = schema.getFields().stream().filter(f -> f.name().equals(UUID_FIELD)).findFirst().isPresent();
if (addressable) {
((ObjectNode) json).put(UUID_FIELD, (Integer) null);
}
break;
case UNION:
schema.getTypes()
.forEach(s -> injectUuids(json.get(s.getName()), s));
break;
case ARRAY:
schema.getElementType().getTypes()
.forEach(s -> injectUuids(json.get(s.getName()), s));
break;
default:
return json;
}

return json;
}

} }

0 comments on commit 54975ed

Please sign in to comment.