[
https://issues.apache.org/jira/browse/TINKERPOP3-581?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14391291#comment-14391291
]
stephen mallette commented on TINKERPOP3-581:
---------------------------------------------
I think that I might be mixing a few problems here. The point of
{{IoTest.shouldReadWriteVertexWith*GraphSON}} series of tests is to validate
that when doing a {{readVertex}} the data necessary to reconstruct a {{Vertex}}
from a {{DetachedVertex}} is present. Under usage of {{readVertex}} the user
supplies {{Function<DetachedVertex,Vertex>}} and
{{Function<DetachedEdge,Edge>}} to do that. The presumption is that the user
will know how to reconstruct things appropriately. For example, the lossy
nature of float is mitigated because the user knows to take the double from
GraphSON and flip it to float when creating the edge in the function). The
same could be said of id, where the user will see a {{Map}} for the id in the
{{DetachedVertex}} and thus convert it to the appropriate identifier type
(assuming the {{Graph}} implementation allows such things. I think the tests
probably need to be modified a bit to better suit this expectation - at the
same time it would be nice to adjust the tests a little to make sure that the
bulk of the tests aren't being ignored because of feature selection. I think I
will try to work on that for purpose of solving this issue.
That said, I think that I've been struggling with this issue because I've been
confusing this concept with a separate problem, which took me a while to
realize unfortunately and that is related to Gremlin Server and non-JVM
language bindings. Suppose someone wants to submit this from the PHP driver:
{noformat}
g.V(x).out()
{noformat}
and in this case "g" is Sqlg. what does the PHP driver need to supply in the
bindings for X to make this work? It could send a Map of the components of the
Sqlg id, but {{ g.V(map) }} won't work. I guess they could create a server
side convert function and do:
{noformat}
g.V(convert(x)).out()
{noformat}
that kinda stinks though. It makes me wonder if {{Graph}} implementations
should require {{ g.V( x ) }} to be more flexible based on features. For
example - if {{supportsNumericIds}} is true then maybe all these should be the
same:
{noformat}}
g.V(1)
g.V(1L)
g.V(1.0d)
g.V(1.0f)
{noformat}
if {{supportsCustomIds}} is true then maybe these should be the same:
{noformat}
vid = v.id()
m = v.id().toMap()
g.V(vid)
g.V(vid.toString())
g.V(m)
{noformat}
I'm sorta making stuff up there - i basically just want to ensure that
{{g.V()}} can respond to simple types that would be available via JSON data
types. This would force {{Graph}} implementations to properly account for
interoperability with non-JVM languages.
> GraphSONWriter and CustomId issue
> ---------------------------------
>
> Key: TINKERPOP3-581
> URL: https://issues.apache.org/jira/browse/TINKERPOP3-581
> Project: TinkerPop 3
> Issue Type: Bug
> Components: test-suite
> Reporter: pietermartin
> Priority: Critical
> Fix For: 3.0.0.GA
>
>
> Hi,
> I have had to change sqlg to use a custom id field but alas am struggling to
> get the graphson IoTests to pass.
> Sqlg's id now is in json
> {code}
> {"id": {"schema":"public", "table":"Person","id"123}}
> {code}
> I have overriden the folowing Graph.Io methods.
> {code}
> @Override
> public GraphSONMapper.Builder graphSONMapper() {
> final SimpleModule module = new SimpleModule();
> module.addSerializer(RecordId.class, new
> RecordId.RecordIdJacksonSerializer());
> module.addDeserializer(RecordId.class, new
> RecordId.CustomIdJacksonDeserializer());
> //return GraphSONMapper.build().addCustomModule(module);
> return
> GraphSONMapper.build().addCustomModule(module).embedTypes(true);
> }
> {code}
> and in RecordId
> {code}
> static class RecordIdJacksonSerializer extends StdSerializer<RecordId> {
> public RecordIdJacksonSerializer() {
> super(RecordId.class);
> }
> @Override
> public void serialize(final RecordId customId, final JsonGenerator
> jsonGenerator, final SerializerProvider serializerProvider)
> throws IOException {
> ser(customId, jsonGenerator, false);
> }
> @Override
> public void serializeWithType(final RecordId customId, final
> JsonGenerator jsonGenerator,
> final SerializerProvider
> serializerProvider, final TypeSerializer typeSerializer) throws IOException {
> ser(customId, jsonGenerator, true);
> }
> private void ser(final RecordId recordId, final JsonGenerator
> jsonGenerator, final boolean includeType) throws IOException {
> jsonGenerator.writeStartObject();
> if (includeType)
> jsonGenerator.writeStringField(GraphSONTokens.CLASS,
> RecordId.class.getName());
> SchemaTable schemaTable = recordId.getSchemaTable();
> jsonGenerator.writeObjectField("schema", schemaTable.getSchema());
> jsonGenerator.writeObjectField("table", schemaTable.getTable());
> jsonGenerator.writeObjectField("id", recordId.getId().toString());
> jsonGenerator.writeEndObject();
> }
> }
> static class CustomIdJacksonDeserializer extends
> StdDeserializer<RecordId> {
> public CustomIdJacksonDeserializer() {
> super(RecordId.class);
> }
> @Override
> public RecordId deserialize(final JsonParser jsonParser, final
> DeserializationContext deserializationContext) throws IOException,
> JsonProcessingException {
> String schema = null;
> String table = null;
> Long id = null;
> while (!jsonParser.getCurrentToken().isStructEnd()) {
> if (jsonParser.getText().equals("schema")) {
> jsonParser.nextToken();
> schema = jsonParser.getText();
> } else if (jsonParser.getText().equals("table")) {
> jsonParser.nextToken();
> table = jsonParser.getText();
> } else if (jsonParser.getText().equals("id")) {
> jsonParser.nextToken();
> id = Long.valueOf(jsonParser.getText());
> } else
> jsonParser.nextToken();
> }
> if (!Optional.ofNullable(schema).isPresent())
> throw deserializationContext.mappingException("Could not
> deserialze RecordId: 'schema' is required");
> if (!Optional.ofNullable(table).isPresent())
> throw deserializationContext.mappingException("Could not
> deserialze RecordId: 'table' is required");
> if (!Optional.ofNullable(id).isPresent())
> throw deserializationContext.mappingException("Could not
> deserialze RecordId: 'id' is required");
> return new RecordId(SchemaTable.of(schema, table), id);
> }
> }
> {code}
> When using {{.embedTypes(true)}} the serialization works but the lossy tests
> fail as Jackson then does not upgrade floats to doubles.
> If I omit the {{embedTypes(true)}} then the tests fail as the id is never
> deserialized to my custom RecordId.
> The test I am currently testing on is
> {{IoTest.shouldReadWriteVertexWithOUTOUTEdgesToGraphSON}}
> With {{embedTypes(true)}} ommited the test fails with
> {code}
> org.junit.ComparisonFailure:
> Expected :public.person:::1
> Actual :{schema=public, table=person, id=1}
> {code}
> With {{embedTypes(true)}} included the test fails with
> {code}
> java.lang.ClassCastException: java.lang.Float cannot be cast to
> java.lang.Double
> {code}
> Any ideas as to what to do?
> Thanks
> Pieter
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)