How are shared/placed the int of the ProtoMember/ProtoInclude in ProtoBuf? - protocol-buffers

I've several questions on how/where the ID of a [ProtoContract] should be declared.
Imagine the following code:
[ProtoContract]
[ProtoInclude(100, typeof(SomeClassA))]//1) CAN I USE 1 here?
public abstract class RootClass{
[ProtoMember(1)]
public int NodeId {get;set;}
}
[ProtoContract]
[ProtoInclude(200, typeof(SomeClassC)]//2) Should I declare this here or directly on the RootClass?
//3) Can I use the id 100 here?
//4) Can I use the id 1 here? or member + include share the id?
public class SomeClassA : RootClass{
[ProtoMember(1)]//5) CAN I USE 1 here? Since the parent already use it but it's a different class
public String Name{get;set;}
}
[ProtoContract]
public class SomeClassC : SomeClassA {
[ProtoMember(2)]
public int Count{get;set;}
}
[ProtoContract]
public class SomeClassD : SomeClassA {
[ProtoMember(2)] //6) Can I use 2 here? Since SomeClassC already use it and is a sibling?
public int Count{get;set;}
}
I've put several number with questions:
CAN I USE 1 here?
Should I declare this here or directly on the RootClass?
Can I use the id 100 here?
Can I use the id 1 here? or member + include share the id?
CAN I USE 1 here? Since the parent already use it but it's a different class
Can I use 2 here? Since SomeClassC already use it and is a sibling?
The thing is that we have a huge model with a lot of classes, which all herits from the same object, so I'm trying to figure out to which ID I should take care.

Short version:
the set of field numbers for a type is the union of the numbers defined against members (fields and properties), and the numbers defined for immediate subtypes (includes)
the set of field numbers must be unique within that single type - it is not required to consider base types or derived types
Longer version:
The reason for this is that subtypes are essentially mapped as optional fields:
[ProtoContract]
[ProtoInclude(100, typeof(SomeClassA))]
public abstract class RootClass{
[ProtoMember(1)]
public int NodeId {get;set;}
}
[ProtoContract]
[ProtoInclude(200, typeof(SomeClassC)]
public class SomeClassA : RootClass{
[ProtoMember(1)]
public String Name{get;set;}
}
[ProtoContract]
public class SomeClassC : SomeClassA {
[ProtoMember(2)]
public int Count{get;set;}
}
is, in terms of proto2 syntax:
message RootClass {
optional int32 NodeId = 1;
optional SomeClassA _notNamed = 100;
}
message SomeClassA {
optional string Name = 1;
optional SomeClassC _notNamed = 200;
}
message SomeClassC {
optional int32 Count = 2;
}
Note that at most 1 sub-type field will be used, so it can be considered oneof for the purposes of .proto. Any fields relating to the sub-type will be included in message SomeClassA, so there is no conflict with RootClass and they do not need to be unique. The numbers only need to be unique per message in the .proto sense.
To take the specific questions, then:
no, because that would conflict with NodeId
it should be declared on SomeClassA; protobuf-net is only expecting immediate descendants, and it keeps the numbering consistent and conveniently readable, since the field number is only required to not conflict with the members of SomeClassA
yes you can; there is no conflict
no, because that would conflict with Name
yes you can; there is no conflict
yes you can; there is no conflict - although actually protobuf-net won't even think of SomeClassD as a sibling anyway (it isn't advertised anywhere as an include) - but if there was a [ProtoInclude(201, typeof(SomeClassD))] on SomeClassA, then it would be fine. This would change our .proto to add:
optional SomeClassD _alsoNotNamed = 201;
to message SomeClassA, and add:
message SomeClassD {
optional int32 Count = 2;
}
Note that protobuf-net doesn't actually generate the .proto syntax unless you explicitly ask for it (via GetSchema<T> etc) - I'm including it purely for illustrative purposes in terms of the underlying protobuf concepts.

Related

Use Method that returns an Int inside a Stream

I have a simple method :
public int getPrice(String bookingName)
{
//return the price of a booking
}
I also have the class :
public class Booking
{
String name;
...
}
I want to group the bookings in a map(key = name of the booking, value = getPrice(bookingName)) so I did :
public TreeMap<String, Integer> bookingForName() {
return bookings.stream().
collect(Collectors.groupingBy(Booking::getName,Collectors.summingInt(getPrice(Booking::getName))));
}
This doesnt' work it says :
Multiple markers at this line:
- The target type of this expression must be a functional interface
- The method getPrice(String) in the type Manager is not applicable for the arguments `(Booking::getName)`
How can I do?
Thanks!
Your getPrice() method takes a String, not a functional interface, so you can't call getPrice(Booking::getName), and even if you could, summingInt doesn't accept an int.
Change:
Collectors.summingInt(getPrice(Booking::getName))
to:
Collectors.summingInt(b -> getPrice(b.getName()))
Also note that Collectors.groupingBy returns a Map, not a TreeMap. If you must have a TreeMap, you should call a different variant of groupingBy.
public TreeMap<String, Integer> bookingForName() {
return bookings.stream()
.collect(Collectors.groupingBy(Booking::getName,
TreeMap::new,
Collectors.summingInt(b -> getPrice(b.getName()))));
}

How to detect if JavaScript (ES6) class has a non-default constructor?

I would like to know by some form of reflection or other means if a given ES6 class has a user-written non-default constructor, or not.
Assuming that user-provided constructor has one argument or more, you can do that by checking the length property of the function(class). But if the constructor takes no argument, there is simply no way as far as I know
function Person(fName, lName) {
this.firstName = fName;
this.lastName = lName
}
console.log(Person.length);
function Person2() {}
console.log(Person2.length);
class Person3 {
constructor(f,l) {}
}
console.log(Person3.length);
class Person4 {
}
console.log(Person4.length);
You can invoke the Classname.prototype.constructor.toString() (where Classname is the inspected class name) and get the source string for the class. Which you can then parse and see if it was a constructor declared or not.
Presumably, you need a decent parser for that, but it's another story.
References:
http://www.ecma-international.org/ecma-262/6.0/#sec-function.prototype.tostring

Incorrect naming convention for fields in .proto files generated by protobuf-net?

I'm just getting started with Google Protocol Buffers and Marc Gravell's awesome protobuf-net program, and one thing I don't understand is the naming convention for the field declarations in a generated .proto file.
Here's what Google is recommending:
"Use underscore_separated_names for field names – for example, song_name."
https://developers.google.com/protocol-buffers/docs/style
"Note that method names always use camel-case naming, even if the field name in the .proto file uses lower-case with underscores (as it should)."
https://developers.google.com/protocol-buffers/docs/reference/java-generated
"Notice how these accessor methods use camel-case naming, even though the .proto file uses lowercase-with-underscores."
https://developers.google.com/protocol-buffers/docs/javatutorial
But when I use the Serializer.GetProto() method in protobuf-net on this:
[ProtoContract]
public partial class AuthEntry
{
private string _windowsAccount = "";
private string _machineNames = "*";
[ProtoMember(1)]
public string WindowsAccount
{
get { return _windowsAccount; }
set { _windowsAccount = value; }
}
[ProtoMember(2)]
public string MachineNames
{
get { return _machineNames; }
set { _machineNames = value; }
}
}
I get this:
message AuthEntry {
optional string WindowsAccount = 1;
optional string MachineNames = 2;
}
Instead of this, as I'd expected:
message AuthEntry {
optional string windows_account = 1;
optional string machine_names = 2;
}
I'm guessing it's no big deal, but just in case ...
The proto generation doesn't attempt to apply those conventions, because then it gets into the arms race of disambiguation, collisions, etc - no to mention the fun of finding word breaks in arbitrary names like CustomerIDReference (ok, that's an unlikely example, but you get the point). If you want to control that yourself - specify the Name property on either ProtoContractAttribute or ProtoMemberAttribute.

Many subclasses for one base class - protobuf performance

Right now I have an application where my iPhone app sends a request that is handled in .NET/C#, serialized to XML, and parsed on the app in objective-c. The current response class structure has one base class (BaseResponse) and many (over 25) subclasses for each type of request that corresponds to different things that need to be returned. Right now I'm looking to see if protobuf would be faster and easier than XML. From what I understand, a .proto file for this class structure is:
Message BaseResponse {
Required Int field1 = 1;
Optional SubResponse1 sub1= 2;
Optional SubResponse2 sub2 = 3;
Etc....
}
Message SubResponse1 {
....
}
Message SubResponse2 {
....
}
Etc for each sub response.
My question is: if I have over 25 of these optional elements (of which only 1 will be non null), does that completely wipe away the size and performance benefit of using protobuf? Does protobuf make sense for this application?
No, it does not impact the performance benefit - you'll just need to check which one is non-null in the objective-C code. Since protobuf only serializes the non-null values it will still be very efficient over the wire. The protobuf specification itself doesn't actually include inheritance, so you are right to say that you need to spoof it via encapsulation - but since you mention C#, note that what you have described (including how the data appears on the wire, i.e. it will be 100% comptible) can be done directly via inheritance if you use protobuf-net as the C# implementation - which should be possible with your existing model. For example:
[ProtoContract]
[ProtoInclude(2, typeof(SubResponse1))]
[ProtoInclude(3, typeof(SubResponse2))]
public class BaseResponse
{
// note Name and IsRequired here are optional - only
// included to match your example
[ProtoMember(1, IsRequired = true, Name="field1")]
public int Field1 { get; set; }
/*...*/
}
[ProtoContract]
public class SubResponse1 : BaseResponse
{/*...*/}
[ProtoContract]
public class SubResponse2 : BaseResponse
{/*...*/}
You can get the .proto via:
var proto = Serializer.GetProto<BaseResponse>();
Which gives:
message BaseResponse {
required int32 field1 = 1 [default = 0];
// the following represent sub-types; at most 1 should have a value
optional SubResponse1 SubResponse1 = 2;
optional SubResponse2 SubResponse2 = 3;
}
message SubResponse1 {
}
message SubResponse2 {
}

GroupSequence and ordered evaluation in JSR 303

In our application we have such a case:
Constraints should be evaluated in particular order. (cheap to expensive)
Constraints should not be evaluated after a violation per field.
All fields should be validated.
For first two, groupsequence is fitting very good. However for my 3rd requirement I could not find a way to solve.
public class AccountBean {
#CheepValidation
#ExpensiveValidation
#VeryExpensiveValidation
private String name;
#CheepValidation
#ExpensiveValidation
#VeryExpensiveValidation
private String surname
}
For example,
Let's say that, for name field VeryExpensiveValidationconstraint is violated and for surname field ExpensiveValidation constraint is violated.
For this case I should display:
For field name: Only VeryExpensiveValidation error message
For field surname: Only ExpensiveValidation error message
Note that for field surname we did not evaluate VeryExpensiveValidation constraint.
Is there a way to implement it with JSR 303?
Thanks
You can use groups and #GroupSequence, but it's a bit unwieldy.
public class AccountBean {
#CheapValidation(groups=Name1.class)
#ExpensiveValidation(groups=Name2.class)
#VeryExpensiveValidation(groups=Name3.class)
String name;
#CheapValidation(groups=Surname1.class)
#ExpensiveValidation(groups=Surname2.class)
#VeryExpensiveValidation(groups=Surname3.class)
String surname;
public interface Name1 {}
public interface Name2 {}
public interface Name3 {}
#GroupSequence({Name1.class, Name2.class, Name3.class})
public interface Name {}
public interface Surname1 {}
public interface Surname2 {}
public interface Surname3 {}
#GroupSequence({Surname1.class, Surname2.class, Surname3.class})
public interface Surname {}
}
Then validate with:
validator.validate(myAccountBean,
AccountBean.Name.class, AccountBean.Surname.class)
The key is to have two entirely independent group sequences.
Unfortunately, it seems you must explicitly list the groups for all the fields you want to validate. I wasn't able to get it working with a 'default' #GroupSequence. Can anyone improve on this?
I've implemented ordered validation with GroupSequence but, generally speaking, GroupSequence beans validation implementation is not transparent.
Meaning, untill first group is fully validated, you can not trigger the validation of the second group.
E.g.
I have 3 validated fields with custom validators. The idea is pretty straightforward: every field should be validated with the set of validators from top to bottom independently (descending cardinality).
#StringPropertyNotNullOrEmptyConstraint(message = "Group name is required", groups = {ValidationStep1.class})
private final StringProperty groupName;
#StringPropertyNotNullOrEmptyConstraint(message = "Group password is required", groups = {ValidationStep1.class})
#StringPropertyMatchConstraint(message = "The given password phrases do not match", dependentProperties = {"groupPasswordMatch"}, groups = {ValidationStep2.class})
private final StringProperty groupPassword;
#StringPropertyNotNullOrEmptyConstraint(message = "Group password match is required", groups = {ValidationStep1.class})
#StringPropertyMatchConstraint(message = "The given passwords phrases do not match", dependentProperties = {"groupPassword"}, groups = {ValidationStep2.class})
private final StringProperty groupPasswordMatch;
public interface ValidationStep1 {
}
public interface ValidationStep2 {
}
#GroupSequence({GroupDialogModel.class, ValidationStep1.class, ValidationStep2.class})
public interface GroupDialogModelValidationSequence {
}
ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
Validator validator = validatorFactory.getValidator();
Set<ConstraintViolation<GroupDialogModel>> constraintViolations = validator.validate(this, GroupDialogModelValidationSequence.class);
The caveat of this approach is that each field should go through ValidationStep1 first and only after each validation of step 1 succeeds it goes to step 2. For example, even if password fields are not empty, but contain different values, validation for them succeeds if group name field does not contain any value. And only after I enter some value to the group name, ValidationStep1 group succeeds and then it displays validation result of ValidationStep2 (passwords do not match).
Making each group for each field in every sequence is bad practice IMHO, but it seems like there is no other choice.
Any other solution is much appreciated.

Resources