spike(services) - introduce services and injected data layer.

This spike introduces the concept of services and injected data layer.

Big changes:
- BaseModel/Resource does not have any data layer logic, it just forwards the call to the service layer which will actually handle the request
- BaseModel will resolve default values specified in the schema if not already done, this is handy for internal calls between endpoints
- BaseModel no longer listens to Eve default events, this functionality is moved in BaseService where we control the `pre_` and `post_` action events
- BaseService can have standard validation if needed
- extracted the default Eve implementation for the data layer in `eve_backend.py`, this decouples the services from the data layer implementation

Things remaining to be done: 
- rename `BaseModel` from `superdesk.models` to `BaseResource` and all the derived classes to end with `Resource`.

Basic way to declare an app with the default service implementation:
```javascript
from superdesk.models import BaseModel
from superdesk.services import BaseService
from superdesk import get_backend


preference_schema = {
    'preferences': {'type': 'dict', 'required': True}
}


def init_app(app):
    endpoint_name = 'preferences'
    service = BaseService(endpoint_name=endpoint_name, backend=get_backend())
    PreferencesModel(app=app, endpoint_name=endpoint_name, service=service)


class PreferencesModel(BaseModel):
    datasource = {'source': 'users', 'projection': {'preferences': 1}}
    schema = preference_schema
    resource_methods = ['GET']
    item_methods = ['GET', 'PATCH']
```
In the service layer we can specify what behavior we want to execute on the API calls by sub-classing `BaseService` class:
```javascript
from superdesk.models import BaseModel
from superdesk.notification import push_notification
from superdesk.utc import utcnow
from apps.archive.common import base_schema
from superdesk.services import BaseService
import superdesk


def init_app(app):
    endpoint_name = 'tasks'
    service = TasksService(endpoint_name=endpoint_name, backend=superdesk.get_backend())
    TaskModel(endpoint_name=endpoint_name, app=app, service=service)


class TaskModel(BaseModel):
    datasource = {
        'source': 'archive',
        'default_sort': [('_updated', -1)],
        'filter': {'task': {'$exists': True}},
        'elastic_filter': {'exists': {'field': 'task'}}  # eve-elastic specific filter
    }
    schema = {
        'slugline': base_schema['slugline'],
        'description_text': base_schema['description_text'],
        'type': base_schema['type'],
        'planning_item': BaseModel.rel('planning', True, type='string'),
        'task': {
            'type': 'dict',
            'schema': {
                'status': {
                    'type': 'string',
                    'allowed': ['todo', 'in-progress', 'done'],
                    'default': 'todo',
                    'required': True
                },
                'due_date': {'type': 'datetime'},
                'started_at': {'type': 'datetime'},
                'finished_at': {'type': 'datetime'},
                'user': BaseModel.rel('users', True),
                'desk': BaseModel.rel('desks', True),
                'basket': BaseModel.rel('content_view', True)
            }
        }
    }


class TasksService(BaseService):

    def update_times(self, doc):
        task = doc.get('task', {})
        status = task.get('status', None)
        if status == 'in-progress':
            task.setdefault('started_at', utcnow())

        if status == 'done':
            task.setdefault('finished_at', utcnow())

    def on_create(self, docs):
        for doc in docs:
            self.update_times(doc)

    def on_update(self, updates, original):
        self.update_times(updates)

    def on_created(self, docs):
        push_notification(self.endpoint_name, created=1)

    def on_updated(self, updates, original):
        push_notification(self.endpoint_name, updated=1)

    def on_deleted(self, doc):
        push_notification(self.endpoint_name, deleted=1)
```
Yup, it could work like that as well, actually it would probably be better. :+1: