RoyZeng / odata4j

Automatically exported from code.google.com/p/odata4j
0 stars 0 forks source link

Edm parsing not working for subclassed entities. #267

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
>>> What steps will reproduce the problem?
1. Create a Jersey consumer
2. Call getEntitySets() on the consumer to retrieve the available entity sets.
3. Enumerate over the entity sets returned, and call getEntities( href ) with 
the href provided by the result of the previous step.

Pseudocode follows:

Consumer c = new Consumer();
Enumerable<EntitySetInfo> sets = c.getEntitySets();

for( EntitySetInfo set : sets ) {
     Enumerable<OEntity> entities = c.getEntities( set.getHref() ).execute();
     for( OEntity entity : entities ) {
         // do something with it
     }
}

>>> What is the expected output? What do you see instead?

Expected result is to be provided with Enumerable<OEntity> containing the 
entities in the set.

Instead, I get an exception as shown below:

 E/AndroidRuntime(6750): org.odata4j.exceptions.NotFoundException: EdmEntitySet Narrative is not found
 E/AndroidRuntime(6750):    at org.odata4j.edm.EdmDataServices.getEdmEntitySet(EdmDataServices.java:72)
 E/AndroidRuntime(6750):    at org.odata4j.internal.EdmDataServicesDecorator.getEdmEntitySet(EdmDataServicesDecorator.java:41)
 E/AndroidRuntime(6750):    at org.odata4j.format.xml.AtomFeedFormatParser.parseEntry(AtomFeedFormatParser.java:366)
 E/AndroidRuntime(6750):    at org.odata4j.format.xml.AtomFeedFormatParser.parseFeed(AtomFeedFormatParser.java:168)
 E/AndroidRuntime(6750):    at org.odata4j.format.xml.AtomFeedFormatParser.parse(AtomFeedFormatParser.java:156)
 E/AndroidRuntime(6750):    at org.odata4j.format.xml.AtomFeedFormatParser.parse(AtomFeedFormatParser.java:1)
 E/AndroidRuntime(6750):    at org.odata4j.consumer.ConsumerQueryEntitiesRequest.doRequest(ConsumerQueryEntitiesRequest.java:64)
 E/AndroidRuntime(6750):    at org.odata4j.consumer.ConsumerQueryEntitiesRequest.getEntries(ConsumerQueryEntitiesRequest.java:47)
 E/AndroidRuntime(6750):    at org.odata4j.consumer.ConsumerQueryEntitiesRequest.execute(ConsumerQueryEntitiesRequest.java:37)
 E/AndroidRuntime(6750):    at com.greatcall.link.clientserver.SyncAdapter.onPerformSync(SyncAdapter.java:69)
 E/AndroidRuntime(6750):    at android.content.AbstractThreadedSyncAdapter$SyncThread.run(AbstractThreadedSyncAdapter.java:254)

What version of the product are you using? On what operating system?

I'm using odata4j-0.8.0-SNAPSHOT-clientbundle.jar built from fork of 
https://github.com/odata4j/odata4j. No changes were made. Our forked repo is 
https://github.com/GreatCall-Android/odata4j.

The code is being run on Android 4.1;

Please provide any additional information below.

It looks like the OData4J library is failing to recognized the subclassed 
FeedItem records, such as the one it complains about, Narrative. When I traced 
through the code, the failure appears to occur in the portion that is dealing 
with this xml snippet:

     <category term="GreatCall.DataService.Services.Link.View.Narrative" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />

When it attempts to dereference the term attribute, it looks in a collection 
that contains only FeedItem and IncidentData. None of the subclasses are there.

The attached document contains the various queries that are made by the 
framework to the service, and what the service returns.

Original issue reported on code.google.com by gcandroi...@gmail.com on 16 Aug 2013 at 8:42

Attachments:

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
Wrong file attached. Here is the correct file.

Original comment by gcandroi...@gmail.com on 16 Aug 2013 at 8:44

Attachments:

GoogleCodeExporter commented 9 years ago
The culprit is in EdmDataServices.getEdmEntitySet( EdmEntityType type ).

This function searches the entity set collection looking for a source for the 
type specified in the parameter. The type provided by the framework is, in this 
case, a subclass of FeedItem called Narrative. The function, however, does not 
travel up the inheritance chain of the supplied type to determine whether the 
entity set's type is a superclass.

After putting in a search it seems to work.

The new function looks like this:

public EdmEntitySet getEdmEntitySet(final EdmEntityType type) {
    if (type == null)
      throw new IllegalArgumentException("type cannot be null");
    EdmEntitySet ees = Enumerable.create(getEntitySets())
        .firstOrNull(new Predicate1<EdmEntitySet>() {
          @Override
          public boolean apply(EdmEntitySet input) {
            boolean rv = false;

            // travel up the inheritance chain to validate.
            // if type is a an instance or subclass of the input, return true.

            EdmEntityType subclass = type;

            while( !rv && null != subclass ) {
              rv = subclass.equals( input.getType() );
              subclass = subclass.getBaseType();
            }

            return rv;
          }
        });

    if (ees != null) {
      return ees;
    }
    throw new NotFoundException("EdmEntitySet " + type.getName() + " is not found");
  }

I don't know what side effects this change might have, but this caused the 
error to go away.

Original comment by gcandroi...@gmail.com on 20 Aug 2013 at 8:57