Use any previous message in a new message - scala

I have a protobuf file in which I define multiple messages which all inherit the same trait (using option (scalapb.message).extends = "Event"; inside of message definition).
I would like to create a new message called MultiEvent which may contain sequence of any of the messages inherited from Event.
Event is defined as simple trait Event in scala code.
The idea is to be able to send special message which contains multiple of messages at once.
syntax = "proto3";
import "scalapb/scalapb.proto";
package com.some.package;
message A {
option (scalapb.message).extends = "Event";
string name = 1;
}
message B {
option (scalapb.message).extends = "Event";
string field = 1;
}
message C {
option (scalapb.message).extends = "Event";
string otherField = 1;
}
message MultiEvent {
option (scalapb.message).extends = "Event";
repeated Event seq = 1; // this line is problematic
}
I got the error: "Event" is not defined..
Ideally from the code the field would be a simple Seq, which repeated provides, but it works only with scalar types.
I have found on internet that Any may be able to accomplish what I want, but I get errors when try to use it.
What is the usual way of solving problems like this? Enum? Conversion?
Thanks.

The usual way is oneof (in Protocol Buffers 3). repeated oneof is illegal:
Repeated oneof was in the initial proposal but as we later found out, there were lots many complicated corner cases in wire and API. We decided not to add repeated for oneof.
You can always define a message which wraps a oneof and have a repeated field of that message instead.
so
message Event {
oneof sealed_value {
A a = 1;
B b = 2;
C c = 3;
...
}
}
and then repeated Event as you currently have.
Using sealed_value as the name enables ScalaPB's sealed oneof support.

Related

Protobuf without serialization

As the name suggests I was wondering if it makes sense to use Protobuf without the requirement of having to serialize the data in any form at the moment (might change in future). I mean to use them purely as data structures to pass Information from one function to the other, all executed in the same address space. Or do you feel it may be an Overkill and see other alternatives.
Backgroud:
I have to design a lib that implements certain interfaces. At the moment, my collegues have implemented it using several functions taking arguments ..
Example:
void readA(int iIP1, int iIP2, Result& oOP)
void readB(std::string iIP1, Result& oOP)
void readC(std::vector<int> iIP1, Result& oOP)
I want to change this and provide just one interface function:
void ReadFn(ReadMsg& ip, ReadResult& res);
And the data structures are defined in Protobuf as below ..
message ReadMsg {
enum ReadWhat {
A = 0;
B = 1;
C = 2;
}
message readA {
int32 iIP1 = 1;
int32 iIP2 = 2;
}
message readB {
string IP1 = 1;
}
message readC {
repeated int IP1 = 1;
}
oneof actRead {
readA rA = 1;
readB rB = 2;
readC rC = 3;
}
}
It offers many advantages over traditional interface design(using functions), with very Little effort from my side. And it will be future proof should these components be deployed as Services in different processes/machines (ofcourse with additional implementation). But given that Protocol Buffers strength is their serialization Features, which I do not make use of at the moment, would you choose to use them in such trivial Tasks ?
Thank you
It can make sense to group function arguments into a struct if there are many of them. And it can make sense to combine your readA, readB and readC functions into a single function if they share a lot of common parts.
What doesn't, however, make sense in my opinion is introducing a separate .proto file and a protobuf dependency if you are not going to use it for serialization. Similar features for grouping data into reusable structures already exist in most languages. And when you use the built-in features of the language, all the code remains in the same place and is easier to understand.

How to add nested message into already created message ? (in Scala)

After adding nested message i recieve nested messages from main message and got nothing.
You can see it in logs: 1 and 2. Size of List 0 !
Any ideas?
message PacketPlayers
{
repeated PacketPlayer players = 1;
}
ScalaPB case classes are immutable. In your example, addPlayers would not modify the instance it's called on, but return a new instance of PacketPlayer that has the additional players.
It is possible to avoid mutable arrays and vars in constructing the new object. For example:
val players = onlinePlayers.keySet.map(makePacketPlayer)
val packetPlayers = PacketPlayers().withPlayers(players)

Casting Protobuf Messages to their Extended type

Im learning about protobuf and am playing with alexeyxo/protobuf-swift.
Is there a way to cast protobuf Messages into the type they extend?
proto file:
message Command_Login {
extend SessionCommand {
optional Command_Login ext = 1001;
}
optional string user_name = 1;
optional string password = 2;
}
Here is the swiftcode:
let commandContainerBuilder = CommandContainer.Builder()
commandContainerBuilder.sessionCommand.append(commandLogin)
// sessionCommand is an array of SessionCommand (of which Command_Login extends)
Error:
Cannot convert value of type CommandLogin? to expected argument type SessionCommand
Sorry, you've misinterpreted extensions. I say "sorry" because this is probably my fault -- I designed the "extensions" feature, and unfortunately by using the word "extend" I confused a lot of people.
You see, extensions have nothing to do with inheritance. In your example, you are not declaring that Command_Login is any kind of subclass of SessionCommand. This is easier to understand if we shift the declarations around a bit:
message Command_Login {
optional string user_name = 1;
optional string password = 2;
}
extend SessionCommand {
optional Command_Login ext = 1001;
}
The above is completely valid and exactly equivalent to your code except for one difference: In your version, the extension's name is Command_Login.ext (because you declared it nested inside Command_Login), but in my version the name is just ext (in the global scope). Other than namespacing, they function the same.
What the extend clause actually does is declare a new field on SessionContext, where the type of that field is Command_Login. If you happen to place an extend clause inside of a message block, this only matters for namespacing purposes, much like declaring static members of a class in C++ or Java.

How to change default ConflictResolver

As stated in title I'd like to change conflict resolver in my Drools project. I found following snippet on this site
ConflictResolver[] conflictResolvers =
new ConflictResolver[] { SalienceConflictResolver.getInstance( ),
FifoConflictResolver.getInstance( ) };
RuleBase ruleBase = java.io.RuleBaseLoader( url, CompositeConflitResolver( conflictResolver));
However it lacks of information where to put it and what sholud be url parameter.
Thank you in advance for any help.
As the documentation says:
Drools 4.0 supported custom conflict resolution strategies; while this
capability still exists in Drools it has not yet been exposed to the
end user via knowledge-api in Drools 5.0.
http://docs.jboss.org/drools/release/5.2.0.Final/drools-expert-docs/html/ch04.html
So if you are using Drools 5+ you will not be able to change conflict resolver unless you do some reflection magic. The Conflict Resolver is settled inside the Agenda object of the StatefulKnowledgeSession object. You can see this by using debugger (it's the content of Agenda object):
To replace ConflictResolver, first you need instance of StatefulKnowledgeSession (which will be ksession in the following snippet). Then you need to extract some nested private fields and after that you can replace field value with instance of i.e RandomConflictResolver. Full code:
Agenda agenda = ksession.getAgenda();
Field agendaField = agenda.getClass().getDeclaredField("agenda");
agendaField.setAccessible(true);
Object agendaObject = agendaField.get(agenda);
Field mainField = agendaObject.getClass().getDeclaredField("main");
mainField.setAccessible(true);
Object mainObject = mainField.get(agendaObject);
Field queueField = mainObject.getClass().getDeclaredField("queue");
queueField.setAccessible(true);
Object queueObject = queueField.get(mainObject);
Field comparatorField = queueObject.getClass().getDeclaredField("comparator");
comparatorField.setAccessible(true);
Object comparator = comparatorField.get(queueObject);
ConflictResolver randomResolver = org.drools.conflict.RandomConflictResolver.getInstance();
comparatorField.set(queueObject, randomResolver);
Based on : documentation and debugger session.
To demonstrate that the order of firings does not affect the overall outcome I'd use an AgendaFilter. I'm sketching the outline using 6.x, but this API hasn't changed since 5.x.
KieBase kieBase = ...;
Collection<KiePackage> packages = kieBase.getKiePackages();
List<Rule> rules = new ArrayList<>();
for( KiePackage p: packages ){
rules.addAll( p.getRules() );
}
Now you have all the rules. Build this simple filter that accepts a single rule:
class Selector implements AgendaFilter {
List<Rule> rules;
int ruleIndex;
Selector( List<Rule> rules ){
this.rules = rules;
}
void setRuleIndex( int value ){ this.ruleIndex = value; }
int getRulesSize(){ return rules.size(); }
boolean accept(Match match){
return match.getRule().equals( rules.get( ruleIndex ) );
}
}
Instantiate:
Selector selector = newSelector( rules );
You can now execute all rules that are activated (but see below):
for( int i = 0; i < selector.getRulesSize(); ++i ){
int fired = kieSession.fireAllRules( selector, i );
}
Any other permutation of 0..size-1 may produce another sequence of firings. You may do this systematically for a small number of rules, or you may use some random permutations.
A more efficient test would keep track of the Match data passed to the filter in the first run and use only these for successive executions.
Caution The approach outlined so far does not consider changes in Working Memory. It would be possibe for rule n to become activated when some rule n+k is fired. If you do have changes of Working Memory, you will have to
do {
int sumf = 0;
for( int i : somePermutation ){
int fired = kieSession.fireAllRules( selector, i );
sumf += fired;
}
} while( sumf > 0 );
I have never done a test like this. It seems that getting the correct result by depending on the innate order of rule firings is extremely rare, in contrast to getting all sorts of wrong results from this order.
Note Other permutations of the rule firing order are possible by changing the order of rules in the DRL (or in their packages?) or by changing the order of fact insertions into working memory. For certain scenarios, even this may provide enough test cases for showing what you intend.

How to support custom options with protobuf-net?

I use protobuf-net and ProtoGen.exe to parse following .proto file (given by another project)
enum RGBFlags { FLAG_RED = 1; FLAG_GREEN = 2; FLAG_BLUE = 4; }
message SomeMessage {
// Values from RGBFlags only allowed
optional int32 flags = 2;
}
My fellow programmers in C++ don't care about type safety and treat flags field as a plain integer. I wanted to be more strict and try to avoid such code:
SomeMessage foo = new SomeMessage();
foo.flags = (int)RGBFlags.FLAG_BLUE | (int)RGBFlags.FLAG_GREEN;
I thought that I could use protbuf custom options to amend proto code and modify XSLT transform of ProtoGet to generate necessary `[Flags]' annotations.
extend google.protobuf.EnumOptions {
optional bool generate_bit_field = 60000;
}
enum RGBFlags {
option (generate_bit_field) = true;
FLAG_RED = 1; FLAG_GREEN = 2; FLAG_BLUE = 4;
}
message SomeMessage {
// Values from RGBFlags only allowed
optional int32 flags = 2;
}
Problem is that all custom options appear as uninterpreted_option in the temporary file in ProtoGen.
Any idea what I could do to get [Flags] annotations in my code?
Re flags; the raw protobuf spec doesn't really have support for composite enum values, so in some ways I understand why they are doing it that way. And sadly there is no such this as partial enum, so you can't add the [Flags] in a separate code file.
Re custom options; it is an excellent question, and support for custom options has been raised before. It is definitely something I'd like to add, but relative to other features it simply isn't a massively demanded item, so (due to limited resource) it has not (yet) been investigated fully.
Therefore, I don't have a great answer for you; that feature isn't really there much right now. You could hard-code that one scenario in your xslt (for your specific types). Or wait until I get around to it (I don't have a specific timescale). Or take a peek yourself.