Skip to content

[th2-2469] builders for parsed/raw messages and events#130

Open
andrew-drobynin wants to merge 37 commits intomasterfrom
th2-2469
Open

[th2-2469] builders for parsed/raw messages and events#130
andrew-drobynin wants to merge 37 commits intomasterfrom
th2-2469

Conversation

@andrew-drobynin
Copy link
Contributor

No description provided.

import com.google.protobuf.Timestamp
import java.time.Instant

abstract class MessageBuilder<T> {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment on lines +51 to +59
fun addNullField(field: String): ParsedMessageBuilder {
this.fields[field] = Value.newBuilder().setNullValue(NullValue.NULL_VALUE).build()
return this
}

fun addSimpleField(field: String, value: String): ParsedMessageBuilder {
this.fields[field] = Value.newBuilder().setSimpleValue(value).build()
return this
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should cover four types of values:
simple, message
list of simple, list of message

Copy link
Contributor Author

@andrew-drobynin andrew-drobynin Oct 11, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By common.proto in th2-grpc-common it can be:

message Value {
  oneof kind {
    NullValue null_value = 1;
    string simple_value = 2;
    Message message_value = 3;
    ListValue list_value = 4;
  }
}

I added methods for Message and ListValue.

Copy link
Member

@Nikita-Smirnov-Exactpro Nikita-Smirnov-Exactpro Oct 12, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

factory.createMessage("session alias") {
  metadata {
    sequence = 3425
    direction = FIRST
  }
  body {
    "a" to "value",
    "B" to message() {
      body {
        "c" to "value"
      }
    }
    "D" to list [
      message() { ... },
      message() { ... }
    ],
    "E" to list ["", "", ""]
  }
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

list[...] doesn't seem to be much different from built-in listOf(...), I would've prefer to use built-in collection builders where possible

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, I think we should not forget that the builder should work and be convenient in Java as well. The version above will be hard to use in Java. Also, it can be used only if we need to build a message right here. We can't imagine how we pass this builder as a parameter to another method.

We can achieve what you described above with Kotlin extension functions. I think we need to focus on the builder's API for Java

Copy link
Member

@Nikita-Smirnov-Exactpro Nikita-Smirnov-Exactpro Oct 13, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we combine both approaches in one builder?
For example
java:

 msg.metadata() // getter 
      .sequence(3425) // setter
      .direction(FIRST) // setter
 msg.body() // getter
      .put("a", "value")
      .put("B", factory.createMessage()
          .body()
              .put("c", "value"))
      ...

Comment on lines +93 to +95
public static Event start(IEventFactory eventFactory) {
return eventFactory.start();
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need this method here at all. We can simply call IEventFactory.start() instead

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@andreydrobynin @Nikita-Smirnov-Exactpro what do you think about that?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@OptimumOpium as I remember @Nikita-Smirnov-Exactpro asked to save back compatibility.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is a new method. How do we save backward compatibility here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I meant we want to have a new method with same name as an old. I think @Nikita-Smirnov-Exactpro can clarify it correctly than me.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From my point of view, it looks a bit strange. Why do I have to write Event.start(eventFactory) instead of eventFactory.start() in my code?

Comment on lines +112 to +114
public static Event from(Instant startTimestamp, IEventFactory eventFactory) {
return eventFactory.from(startTimestamp);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The same as for start method

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here also back compatibility


override fun from(startTimestamp: Instant, endTimestamp: Instant?) = from(startTimestamp, endTimestamp, this)

override fun from(startTimestamp: Instant, endTimestamp: Instant?, eventFactory: IEventFactory) =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need this method?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Nikita-Smirnov-Exactpro asked to add it. As I remember he wanted to have builder interface with old implementation (com.exactpro.th2.common.event.Event)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still don't understand why do we need a method in the factory that accepts the factory as one of the parameters. How is it connected to an old implementation?

protected static final ThreadLocal<ObjectMapper> OBJECT_MAPPER = ThreadLocal.withInitial(() -> new ObjectMapper().setSerializationInclusion(NON_NULL));

protected final String id = generateUUID();
protected String bookName;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should make it final and set in the constructor

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Nikita-Smirnov-Exactpro asked to have builder methods (e.g. bookName(), endTimestamp())

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand why we need the endTimestamp setter. But why do we need a setter for bookName? Why shouldn't we set it once in the constructor?

Comment on lines +93 to +95
public static Event start(IEventFactory eventFactory) {
return eventFactory.start();
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@andreydrobynin @Nikita-Smirnov-Exactpro what do you think about that?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants