Posts mit dem Label orderbird werden angezeigt. Alle Posts anzeigen
Posts mit dem Label orderbird werden angezeigt. Alle Posts anzeigen

Dienstag, 27. Dezember 2011

orderbird - more than a POS


During christmas, I had a conversation with my uncle about orderbird which started like this:

my uncle: "Why should someone invest in orderbird? orderbird is just a Point of Sale (POS) system!"

me: "Because its not just a POS system. It will be THE platform provider for the gastronomy."

my uncle: "Platform Provider? Are you going to produce oil rigs?"

me: " ... No ... and ... No.
        orderbird will bring together all stakeholders relevant to gastronomy: gastronomists, guests,  suppliers.

All of them will do their daily business with orderbird:

  • Gastronomists run their restaurants with orderbird.
  • Guests reserve tables, place orders, and pay with orderbird.
  • For an optimal supply chain, suppliers and gastronomists work hand-in-hand with orderbird.
"

.. Ok, Ok, .. I must admit that the last elevator-pitch-part was added to make the dialog more appealing.



Seriously, orderbird's business model can be classified as a Multi-Sided Platform (MSP).
It does not strictly follow the MSP pattern as defined in BMG. Here's why:

Using a plain MSP business model, a MSP-company can hardly run profitabel without having customers that cover ALL customer segments that make up the MSP. Related to orderbird, this means that orderbird's business model would not work if orderbird only had gastronomists, only had guests, only had gastronomists and suppliers, and so forth.

This is only partially true. Ok, if orderbird only had guests and suppliers, the business model should surely be adapted. But in some settings it can be built and scaled incrementally. While bringing one sutomer segment onto the platform, profits can be made without having to wait for another customer segment to enter the platform.

Consider the current state of the evolution of orderbird's business model.
orderbird has entered the german gastronomy market successfully having the 100st customer reachable at the end of the beta phase. Until a critical mass is reached, orderbird will improve its POS system to help gastronomists getting even more out of their business and tapping on the revenue streams generated from its POS system.

While creating more value for gastronomists, orderbird is sketching and evaluating market entry strategies for bringing guests onto their platform. If a critical mass of customers is on the platform, the MSP model starts kicking! While offering guests an uncomplicated ordering and restaurant experience, gastronomists can profit from a better capacity utilization. And orderbird … orderbird is tapping on a new revenue stream: guest ordering. For every placed order orderbird will receive a turnover percentage. If guests pay via orderbird, a turnover percentage on these transactions is imaginable, too.

Besides the synergies among gastronomists and guests, the platform allows for better integration of gastronomists and supplier operations. Gastronomists will be able to choose from a variety of suppliers of beverages, food, and other goods they need to run their business. Suppliers can offer their products and services to a much broader audience.

Let's sum things up. If you thought about investing in orderbird, do not base your thoughts and calculations on the assumption that you will invest in a company that simply delivers a POS system. orderbird's business model follows the pattern of a Multi-sided Platform (MSP): orderbird will bring together all relevant gastronomy stakeholders. This consolidation of stakeholders will give orderbird the possibility to get a share on multiple gastronomy related markets: POS systems, guest orders and reservations, guest payments, and supply chains. The orderbird platform will be THE marketplace for the gastronomy.

Furthermore, what makes orderbird unique besides its business model is its team. The founder's talent and experience ranges from a deep understanding of the gastronomy market, to the planning and implementation of marketing and financial strategies, to a customer focussed development of software products. The founders are supported by a great team of software engineers, sales & support people, designers, partners and board of directors. The spirit and success of orderbird is reflected by the awards we earned so far.

I never felt so much enthusiasm and energy in a company!!

Rock on!

Sonntag, 20. November 2011

Xtext Serialization: Challenges serializing enums.

For the Xtext based modelling tool chain to model objective c (iPhone, iPad) applications for orderbird I needed to manipulate an Xtext model programmatically and serialize it back to disk.
I did encounter some challenges while serializing enums and want to share my experience in this post.

Here is a snippet of the grammar I am using for the well known use case of entity modelling:

EntityModel:
    (entities += Entity)*
;

Entity:
    (annotations+=Annotation)*
    'entity' name=ID '{' '}'
;

Annotation:
    '@' option=ConfigOption (':' value=ConfigValue)?
;   

enum ConfigOption:
    persistency
;   
   
enum ConfigValue:
    CoreData | FMDB
;

So, entities can be annotated to determine with which technology they will be stored persistently.

At first glance, serialization does not seem to be a hassle. Having an IResourceSetProvider, I can get the model from its XtextResource:

@Inject
private IResourceSetProvider provider;

private EntityModel loadEntityModelFromFile(IFile file) {
       
    ResourceSet xrs   = provider.get(file.getProject());
    URI uri           = URI.createPlatformResourceURI(file.getFullPath().toString(), true);
    Resource resource = xrs.getResource(uri, true);
    EntityModel em    = (EntityModel)resource.getContents().get(0);
   
    return em;
}

Now I can programmatically change the model and then serialize it back to disk by saving it in a XtextResource:

private void save(EntityModel em) {
   
    ResourceSet xrs  = provider.get(getProject());
    XtextResource xr =
        (XtextResource) xrs.getResource
                (URI.createPlatformResourceURI(getModelPath(), true) , true);
   
    xr.getContents().set(0, em);
               
    Map options = new HashMap();
    SaveOptions.defaultOptions().addTo(options);
    xr.save(options);
}

Serializing this model:

@persistency:CoreData
entity Foo {}

I get:

@persistencyentity Foo {}

The ConfigOption is missing! Hmmm, why? Xtext somehow assumes the ConfigOption to be transient (not serializable).

The Xtext documentation says "The default transient value service considers a model element to be transient if it is unset or equals its default value." and "By default, EMF returns false for eIsSet(..) if the value equals the default value."

Looking at the generated java code for the ecore meta model, the 'CoreData' literal is defined as the default:

/*
 * @generated
 */
public class AnnotationImpl extends EObjectImpl implements Annotation {
    //...   
   
    protected static final ConfigValue VALUE_EDEFAULT = ConfigValue.CORE_DATA;
    protected ConfigValue value                       = VALUE_EDEFAULT;
   
    //...
}

In order to tell Xtext which model elements can be considered as (non) transient, an instance of ITransientValueService has to be specified in your DSL's guice runtime module. This seems to be an easy task: Inherit from DefaultTransientValueService and overwrite isTransient(…) to yield the correct semantics:

public class DataDslTransientValueService extends DefaultTransientValueService {
   
    @Override
    public boolean isTransient(EObject owner, EStructuralFeature feature, int index) {
        if (owner instanceof Annotation && DataDslPackage.ANNOTATION__VALUE == feature.getFeatureID()) {
            return false;
        }
        return super.isTransient(owner, feature, index);
    }
}

… and hook it into the guice module:

public Class bindITransientValueService() {
    return DataDslTransientValueService.class;
}

Damn! Still the same errorneous output:

@persistencyentity Foo {}

A little bit of code archeology and debugging reveals that Xtext has two distinct hierarchies of the ITransientValueService interface.
One in the package org.eclipse.xtext.parsetree.reconstr and the other in the package org.eclipse.xtext.serializer.sequencer.

My DataDslTransientValueService implemented org.eclipse.xtext.parsetree.reconstr.ITransientValueService. But this does not seem to be sufficient. Thus, I also implemented org.eclipse.xtext.serializer.sequencer.ITransientValueService:

@SuppressWarnings("restriction")
public class SequencerTransientValueService extends TransientValueService {
   
    public ValueTransient isValueTransient(EObject semanticObject, EStructuralFeature feature) {
        if (semanticObject instanceof Annotation && DataDslPackage.ANNOTATION__VALUE == feature.getFeatureID()) {
            return ValueTransient.NO;
        }
       
        return super.isValueTransient(semanticObject, feature);
    }
}

My DSL's guice runtime module contains these two bindings for ITransientValueService:

public Class bindITransientValueService() {
    return DataDslTransientValueService.class;
}
   
public Class bindITransientValueService2() {
    return SequencerTransientValueService.class;
}

And finally the serialization yields the correct result!


As you might have noticed I annotated the SequencerTransientValueService with @SuppressWarnings("restriction"). The class org.eclipse.xtext.serializer.sequencer.TransientValueService seems not be intended for public use. But obviously it is required to get the serialization to work correctly.


At the time of writing this post, I also realized that my grammar's enum ConfigOption only has one literal that is defined as default and should thus not be serialized by default. But in my implementations of the two ITransientValueService interfaces I only specified ConfigValue to be non-transient. However, ConfigOption is serialized without adding the corresponding semantics to the implementations of the ITransientValueService. Maybe this is due to the Annotation's option attribute not being optional in the grammar as the value attribute is. And maybe I should study the Xtext documentation in more detail. Maybe ..

Regards,

steven