On Github blakehall / intro_to_entity_api
class DrupalDefaultEntityController implements DrupalEntityControllerInterface {
  /**
   * Constructor: sets basic variables.
   */
  public function __construct($entityType) {
    $this->entityType = $entityType;
    $this->entityInfo = entity_get_info($entityType);
    $this->entityCache = array();
    $this->hookLoadArguments = array();
    $this->idKey = $this->entityInfo['entity keys']['id'];
    // Check if the entity type supports revisions.
    if (!empty($this->entityInfo['entity keys']['revision'])) {
      $this->revisionKey = $this->entityInfo['entity keys']['revision'];
      $this->revisionTable = $this->entityInfo['revision table'];
    }
    else {
      $this->revisionKey = FALSE;
    }
    // Check if the entity type supports static caching of loaded entities.
    $this->cache = !empty($this->entityInfo['static cache']);
  }
}
          
        
interface DrupalEntityControllerInterface {
  public function __construct($entityType);
  public function resetCache(array $ids = NULL);
  public function load($ids = array(), $conditions = array());
}
          
        Where's the rest?
class Entity {
  /**
   * Creates a new entity.
   *
   * @see entity_create()
   */
  public function __construct(array $values = array(), $entityType = NULL) {
    if (empty($entityType)) {
      throw new Exception('Cannot create an instance of Entity without a specified entity type.');
    }
    $this->entityType = $entityType;
    $this->setUp();
    // Set initial values.
    foreach ($values as $key => $value) {
      $this->$key = $value;
    }
  }
}
          
        
interface EntityAPIControllerInterface extends DrupalEntityControllerInterface {
  public function delete($ids);
  public function invoke($hook, $entity);
  public function save($entity);
  public function create(array $values = array());
  public function export($entity, $prefix = '');
  public function import($export);
  public function buildContent($entity, $view_mode = 'full', $langcode = NULL);
  public function view($entities, $view_mode = 'full', $langcode = NULL, $page = NULL);
}
          
          
            provides methods and helper functions to support CRUD operations
          https://github.com/Lullabot/entity-api-demos
function videoentity_entity_info() {
  $info = array();
  // Our custom video entity needs to be defined here.
  // See http://drupal.org/node/1026420 and http://drupal.org/node/878804
  // for more documentation.
  $info['video'] = array(
    // Human readable label.
    'label' => t('Video'),
    // Table for storing entity data, defined in hook_schema().
    'base table' => 'videoentity_video',
    // This helps Entity API know how to query your custom table.
    'entity keys' => array(
      'id' => 'id',
      'label' => 'name',
    ),
   'bundles' => array(
      'video' => array(
        'label' => t('Video'),
        'admin' => array(
          'path' => 'admin/videoentity',
          'access arguments' => array('administer video'),
        ),
      ),
    ),
    // This is a uri function provided by the Entity contrib module.
    // It's a simple wrapper around the uri method in the controller class.
    'uri callback' => 'entity_class_uri',
    // These are the default controllers.
    // 'entity class' => 'Entity',
    'entity class' => 'VideoEntity',
    // 'controller class' => 'DrupalDefaultEntityController',
    // Other options provided by the EntityAPI contrib module:
    // 'controller class' => 'EntityAPIController ',
    // 'controller class' => 'EntityAPIControllerExportable',
    'controller class' => 'VideoEntityController',
     // The information below is used to extend the EntityDefaultUIController
     'admin ui' => array(
       'path' => 'admin/videoentity',
       'controller class' => 'VideoEntityUIController',
       'menu wildcard' => '%videoentity',
       'file' => 'videoentity.admin.inc',
     ),
     'module' => 'videoentity',
     // Access callback to determine permisisons.
     'access callback' => 'videoentity_access_callback',
 );
  return $info;
}
          
        
function file_entity_entity_property_info() {
  $info['file']['properties']['type'] = array(
    'label' => t('File type'),
    'type' => 'token',
    'description' => t('The type of the file.'),
    'setter callback' => 'entity_property_verbatim_set',
    'setter permission' => 'administer files',
    'options list' => 'file_entity_type_get_names',
    'required' => TRUE,
    'schema field' => 'type',
  );
  return $info;
}
          
        
function videoentity_entity_info() {
  $info = array();
  // Our custom video entity needs to be defined here.
  // See http://drupal.org/node/1026420 and http://drupal.org/node/878804
  // for more documentation.
  $info['video'] = array(
    // Tell FieldAPI that fields can be attached to our video entity
     'fieldable' => TRUE,
    'views controller class' => 'EntityDefaultViewsController',
  );
  return $info;
}
          
        
function videoentity_entity_info() {
  $info = array();
  // Our custom video entity needs to be defined here.
  // See http://drupal.org/node/1026420 and http://drupal.org/node/878804
  // for more documentation.
  $info['video'] = array(
    'views controller class' => 'EntityDefaultViewsController',
  );
  return $info;
}
          
        https://drupal.org/node/1021526
function videoentity_entity_info() {
  $info = array();
    'exportable' => TRUE,
  );
  return $info;
}
          
        
$entity->is_new_revision = TRUE;
          
        https://drupal.org/node/1021556
$node->field_number[LANGUAGE_NONE][0]['value'];
$wrapper = entity_metadata_wrapper('node', $node);
$wrapper->field_number->value();
$wrapper->author->mail->value();
$wrapper->author->mail->set('blake@example.com');