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

Dienstag, 18. Oktober 2011

Xtext Objective C Formatter/Beautifier

This post shows how I integrated uncrustify into Xtext. At the end of this post you will be able to package uncrustify with your language UI plugin and run uncrustify as part of a MWE2 workflow (the described approach was tested with Xtext 2.0 on Mac OS X 10.7).

First, you have to get uncrustify. Unpack it, run ./configure and then make. The binary is located in the src/ folder and is named uncrustify - what a surprise. Create a folder formatting/ in your language's UI plugin. Copy the binary into this folder. To tell uncrustify how to format the code we have to supply it with a config file. A config file for objective c can be found here. Download this file and put it into the formatting/ folder. Besides the binary and a config file we need a shell script that runs uncrustify. Create a file formatSource.sh in formatting/. The shell script looks like this:
#! /bin/sh

touch files.txt
find . -name "*.[hm]" > files.txt

while read line; do
./uncrustify_osx -l OC -c ./uncrustify_obj_c.cfg --no-backup $line
done < files.txt  
rm files.txt 
This script will look for *.h and *.m files recursively down from its location, run over them, and format them without creating a backup copy.

Now that we have the necessary files for running uncrustify ... oh well ... we must be able to run uncrustify from within java. For executing shell scripts from within a java process - welcome platform dependency - check out my ShellCommandExecutor. This class is also used for making the shell script formatSource.sh executable after copying it to a language project:
private void copyFormattingFiles(final IProject project){
 Bundle bundle = SystemDslActivator.getInstance().getBundle();
 IPath scriptPath = copyFile("formatting/formatSource.sh"     , "formatSource.sh",      project, bundle);
 IPath binaryPath = copyFile("formatting/uncrustify_osx",       "uncrustify_osx",       project, bundle);

 copyFile("formatting/uncrustify_obj_c.cfg", "uncrustify_obj_c.cfg", project, bundle);

 //make script and binary executable
 try {
  ShellCommandExecutor.execute("chmod", "+x", scriptPath.toString());
  ShellCommandExecutor.execute("chmod", "+x", binaryPath.toString());
 } catch (Exception e) {
  //TODO: write to error log
 }
}
The above method can be found in this class. The execution of formatSource.sh in a MWE2 workflow component looks like this:
public class ObjectiveCFormatter extends org.eclipse.emf.mwe.core.lib.AbstractWorkflowComponent2{

private static final String SCRIPT_PATH = "./formatSource.sh";

@Override
protected void invokeInternal(WorkflowContext ctx, ProgressMonitor monitor, Issues issues) {
try{
 CommandResult cr = ShellCommandExecutor.execute(SCRIPT_PATH, new String[]{});

 if (cr.success){
  System.out.println("Formatting complete!");
 } else{
  issues.addError(cr.output);
 }
}catch (Exception e){
 issues.addError(e.getMessage());
}
}
}
If you add this component after your objective c generator in your workflow all *.h and *.m files will be formatted as described by the uncrustify objective c config file.

regards,

steven

Dienstag, 19. Juli 2011

LaTex: Linebreak, NewLine in Caption

I you want to have a line break, a.k.a. new line, in your latex document's captions import the package "caption" like this:

\usepackage{caption}


In your caption's you can add the \newline command:


\begin{figure}

\centering

\includegraphics{}

\caption{Bla Bla Bla \newline Bla Bla Bla after line break}

\label{fig:aLabel}

\end{figure}


regards

Dienstag, 15. März 2011

Montag, 7. März 2011

CoreData Performance Measurement

world,

check out this evaluation on CoreData Performance.


s