Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Create a builder API #9

Closed
dlaidlaw opened this Issue · 16 comments

3 participants

@dlaidlaw

Extract the core features of the plugin to an API that can be used generically to convert EObjects to DBObjects and vice versa.

By doing this it will enable users of the conversion library to use the code in their own persistence frameworks, and allow converted objects to be customized individually before persistence. This would also have the side effect of removing the dependency on the IMongoDB object for those using the code outside of OSGi, and let users handle persistence in their own way.

@BryanHunt
Owner

Would you expect this API to abstract away the reserved keys like _eClass, or would that still be managed by the base algorithm?

@dlaidlaw
@BryanHunt BryanHunt was assigned
@jconlon

Great framework!

Have attributes longitude and latitude in my model and would like to persist this to MongoDB in a geo-spatial friendly form so I can index it with 2d, something like
{ .... location: { longitude : 40.93907, latitude : 73.9923} ....}

Can I do this now with the current code, or must I wait for this issue's resolution? If I must wait for resolution, do you have any ideas when you may get to this?
thanks...

@BryanHunt
Owner

I have yet to work on this issue. It will be part of the upcoming 0.5.0 release. I think I have just this issue and one other feature left before the 0.5.0 release, but given my current schedule, it may be a few more weeks before I get the release out. Contributions are always welcome if you "need it now".

@BryanHunt
Owner

Here is the first attempt at an API. It will definitely change as I refactor the code, but it gives you an idea as to where I'm headed.

public class EObjectBuilder
{
  public EObject buildEObject(DBCollection collection, DBObject dbObject, Resource resource, XMLResource.URIHandler uriHandler, boolean isProxy);

  /**
   * @param collection
   * @param dbObject
   * @param resource
   * @param uriHandler
   * @param resourceSet
   * @param eObject
   * @param attribute
   */
  protected void buildEObjectAttribute(DBCollection collection, DBObject dbObject, Resource resource, XMLResource.URIHandler uriHandler, ResourceSet resourceSet, EObject eObject, EAttribute attribute);

  /**
   * @param collection
   * @param dbObject
   * @param resource
   * @param uriHandler
   * @param eObject
   * @param reference
   */
  protected void buildEObjectReference(DBCollection collection, DBObject dbObject, Resource resource, XMLResource.URIHandler uriHandler, EObject eObject, EReference reference);

  protected EObject buildEObjectReference(DBCollection collection, DBObject dbReference, Resource resource, XMLResource.URIHandler uriHandler, boolean referenceResolvesProxies);

  /**
   * This function builds an EMF proxy object from the reference DBObject
   * 
   * @param collection the collection containing the referencing object
   * @param dbReference the MongoDB reference - must be of the form { ECLASS_KEY : eClassURI, PROXY_KEY : proxyURI }
   * @param resourceSet the resource set to use for building the proxy
   * @param uriHandler the resource URI handler used to resolve the relative proxy URI
   * @param referenceResolvedProxies flag indicating that the reference resolves proxies
   * @return the proxy object when referenceResolvedProxies is true, the resolved object otherwise
   */
  protected EObject buildProxy(DBCollection collection, DBObject dbReference, ResourceSet resourceSet, XMLResource.URIHandler uriHandler, boolean referenceResolvedProxies);

  /**
   * This function converts the raw value read from MongoDB into the correct type for
   * the given datatype.
   * 
   * @param eDataType the EMF datatype to convert to
   * @param value the raw MongoDB value to convert from
   * @return the converted value
   */
  protected Object convertMongoDBValueToEMFValue(EDataType eDataType, Object value)

  /**
   * This function creates an empty EObject from the given DBObject. The actual instance created
   * is determined by the EClass specified in the DBObject by the ECLASS_KEY. This function also
   * maintains a static cache of EClass URI to EClass for improved performance.
   * 
   * @param dbObject the object read from MongoDB
   * @param resourceSet the resourceSet that will be used to locate the EClass if it is not cached
   * @return the newly created object of type as specified by the data read from MongoDB
   */
  protected EObject createEObject(DBObject dbObject, ResourceSet resourceSet);
}
public class DBObjectBuilder
{
  public DBObject buildDBObject(DB db, EObject eObject, XMLResource.URIHandler uriHandler) throws IOException;

  protected Object buildDBReference(DB db, EReference eReference, EObject targetObject, XMLResource.URIHandler uriHandler) throws IOException;

  protected Object getDBAttributeValue(EAttribute attribute, Object rawValue);
}
@BryanHunt
Owner

I've started working on the refactoring and I have pushed the latest changes to the builders branch. Much more refactoring to come.

@BryanHunt
Owner

I believe the refactoring of the code into builders is complete. There may still be some minor refactoring of the MongoDBURIHandlerImpl, MongoDBInputStream, and MongoDBOutputStream. These changes have been pushed to the builders branch.

@BryanHunt
Owner

I've refactored MongoDBURIHandlerImpl, MongoDBInputStream, and MongoDBOutputStream. I believe this completes the refactoring.

I would appreciate it if the design could be reviewed before the next release which I hope to have complete in a week or two.

All code is available in the builders branch.

@jconlon

So the way I understand it is to extend the DBObjectBuilder and the EObjectBuilder and to tie these extensions in is by also extending the MongoDBInputStream & MongoDBOutputStream and overriding the createBuilder methods. Then of course to get these two extensions in I would also extend the MongoDBURIHandlerImpl.

Am I missing something? Is there a cleaner way to do this?

@BryanHunt
Owner

That sounds about right. I'm open to suggestions for a cleaner implementation. I suppose I could use a factory class pattern, but is that any cleaner?

@jconlon

Right or you can pass the builders into a static factory method, or pass them in the constructor of MongoDBURIHandlerImpl.

Or ... Why not follow the pattern you already have in place for the converters?

MongoDBURIHandlerImpl handler = new MongoDBURIHandlerImpl();
handler.getConverterService().addConverter(new MyMongoEmfConverter());
//so to add builders
handler.getBuilderService().addBuilders(new MyEObjectBuilder(), new MyDBObjectBuilder());

@jconlon

In order to override the framework classes, I will need changes to access some fields:

MongoDBOutputStream:
protected IConverterService converterService;

MongoDBInputStream:
protected HashMap eClassCache = ...

MongoDBURIHandlerImpl:
protected IMongoEmfQueryEngine queryEngine;
protected IConverterService converterService;

@BryanHunt
Owner

I've pushed some API changes to the builders branch. I now use the factory pattern for all of the sub components. Please have a look and let me know if this works for you. I'd like to get it merged into master and released this week.

@jconlon

This works fine and is much cleaner than before - thanks.

@BryanHunt
Owner

I've added the appropriate javadocs and I've merged all changes into master.

@jconlon

Looks good - thanks!

@BryanHunt BryanHunt closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.