You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@olingo.apache.org by Frédéric SOUCHU <Fr...@ingenico.com> on 2015/04/20 11:35:13 UTC

[OData 4.0 Server] Created enum serialization bug + fix + unit tests proposal

I created:
https://issues.apache.org/jira/browse/OLINGO-633

+ spent it a bit of time creating a unit test & fix (see attached).

Can an official Olingo contributor review my fix proposal and commit it in master branch?

Cheers,
Frederic

From: Frédéric SOUCHU
Sent: 17 April 2015 18:15
To: user@olingo.apache.org
Subject: [OData4.0] Enum serialization bug - fix proposal under way

There is a bug in the way enumerated values are serialized when values are overlapping.
This type:
return new EnumType()
              .setName("CarType")
              .setFlags(false)
              .setUnderlyingType(EdmPrimitiveTypeKind.Int32.getFullQualifiedName())
              .setMembers(
                     Arrays.asList(
new EnumMember()
                     .setName("NotProvided")
                     .setValue("0"),
new EnumMember()
.setName("SuperCar")
.setValue("1"),
new EnumMember()
.setName("MonsterCar")
.setValue("2"),
new EnumMember()
.setName("SpaceCar")
.setValue("3"),
new EnumMember()
.setName("SlowCar")
.setValue("4")));

With values set as:
entitySet.getEntities().add(new Entity()
.addProperty(createPrimitive("Id", 1))
...
.addProperty(new PropertyImpl(CarsEdmProvider.ETN_CARTYPE.getFullQualifiedNameAsString(), "Type", ValueType.ENUM, rnd.nextInt(5))));

Will produce the following incorrect output (using the Cars sample):
{
Id: 1
Model: "F1 W03"
ModelYear: "2012"
Price: 189189.43
Currency: "EUR"
Type: "NotProvided,SlowCar" // it should be a single value...
}

Looking at the code, it seems the Enum has always been thought as a list of exclusive binary values :[
I'll propose a fix (see the yellow parts) and *test* early next week (on top of creating a bug!).

       protected String constructEnumValue(final long value)
                     throws EdmPrimitiveTypeException {
              long remaining = value;
              StringBuilder result = new StringBuilder();

              for (final EdmMember member : getMembers()) {
                     if (isFlags()) {
                            final long memberValue = Long.parseLong(member.getValue());
                            if ((memberValue & remaining) == memberValue) {
                                   if (result.length() > 0) {
                                          result.append(',');
                                   }
                                   result.append(member.getName());
                                   remaining ^= memberValue;
                            }
                     } else {
                            final long memberValue =  Long.parseLong(member.getValue());
                            if (value == memberValue) {
                                   return member.getName();
                            }
                     }
              }

              if (remaining != 0) {
                     throw new EdmPrimitiveTypeException("The value '" + value
                                   + "' is not valid.");
              }
              return result.toString();
       }

Regards,
Frederic

Re: [OData 4.0 Server] Created enum serialization bug + fix + unit tests proposal

Posted by "Bolz, Michael" <mi...@sap.com>.
Hi Frederic,

I will take a look into your contribution.

Best regards,
Michael


> On 20 Apr 2015, at 11:35, Frédéric SOUCHU <Fr...@ingenico.com> wrote:
> 
> I created:
> https://issues.apache.org/jira/browse/OLINGO-633 <https://issues.apache.org/jira/browse/OLINGO-633>
>  
> + spent it a bit of time creating a unit test & fix (see attached).
>  
> Can an official Olingo contributor review my fix proposal and commit it in master branch?
>  
> Cheers,
> Frederic
>  
> From: Frédéric SOUCHU 
> Sent: 17 April 2015 18:15
> To: user@olingo.apache.org <ma...@olingo.apache.org>
> Subject: [OData4.0] Enum serialization bug - fix proposal under way
>  
> There is a bug in the way enumerated values are serialized when values are overlapping.
> This type:
> return new EnumType()
>               .setName("CarType")
>               .setFlags(false)
>               .setUnderlyingType(EdmPrimitiveTypeKind.Int32.getFullQualifiedName())
>               .setMembers(
>                      Arrays.asList(
> new EnumMember()
>                      .setName("NotProvided")
>                      .setValue("0"),
> new EnumMember()
> .setName("SuperCar")
> .setValue("1"),
> new EnumMember()
> .setName("MonsterCar")
> .setValue("2"),
> new EnumMember()
> .setName("SpaceCar")
> .setValue("3"),
> new EnumMember()
> .setName("SlowCar")
> .setValue("4")));
>  
> With values set as:
> entitySet.getEntities().add(new Entity()
> .addProperty(createPrimitive("Id", 1))
> …
> .addProperty(new PropertyImpl(CarsEdmProvider.ETN_CARTYPE.getFullQualifiedNameAsString(), "Type", ValueType.ENUM,rnd.nextInt(5))));
>  
> Will produce the following incorrect output (using the Cars sample):
> {
> Id: 1
> Model: "F1 W03"
> ModelYear: "2012"
> Price: 189189.43
> Currency: "EUR"
> Type: "NotProvided,SlowCar" // it should be a single value… 
> }
>  
> Looking at the code, it seems the Enum has always been thought as a list of exclusive binary values :[
> I’ll propose a fix (see the yellow parts) and *test* early next week (on top of creating a bug!).
>  
>        protected String constructEnumValue(final long value)
>                      throws EdmPrimitiveTypeException {
>               long remaining = value;
>               StringBuilder result = new StringBuilder();
>  
>               for (final EdmMember member : getMembers()) {
>                      if (isFlags()) {
>                             final long memberValue = Long.parseLong(member.getValue());
>                             if ((memberValue & remaining) == memberValue) {
>                                    if (result.length() > 0) {
>                                           result.append(',');
>                                    }
>                                    result.append(member.getName());
>                                    remaining ^= memberValue;
>                             }
>                      } else {
>                             final long memberValue =  Long.parseLong(member.getValue());
>                             if (value == memberValue) {
>                                    return member.getName();
>                             }
>                      }
>               }
>  
>               if (remaining != 0) {
>                      throw new EdmPrimitiveTypeException("The value '" + value
>                                    + "' is not valid.");
>               }
>               return result.toString();
>        }
>  
> Regards,
> Frederic
> <EmdEnumTest.java><EdmEnumTypeImpl.java>