diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php
index a5000ce..490470d 100644
--- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php
+++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php
@@ -8,6 +8,7 @@
 namespace Drupal\Core\Config\Entity;
 
 use Drupal\Core\Entity\Entity;
+use Drupal\Core\TypedData\ContextAwareInterface;
 
 /**
  * Defines a base configuration entity class.
@@ -126,4 +127,53 @@ public function getExportProperties() {
     return $properties;
   }
 
+  /**
+   * Implements Drupal\Core\Entity\EntityInterface::getBCEntity().
+   */
+  public function getBCEntity() {
+    return $this;
+  }
+
+  /**
+   * Implements Drupal\Core\Entity\EntityInterface::getOriginalEntity().
+   */
+  public function getOriginalEntity() {
+    return $this;
+  }
+
+  /**
+   * Implements \Drupal\Core\TypedData\ContextAwareInterface::getName().
+   */
+  public function getName() {
+    return NULL;
+  }
+
+  /**
+   * Implements \Drupal\Core\TypedData\ContextAwareInterface::getRoot().
+   */
+  public function getRoot() {
+    return $this;
+  }
+
+  /**
+   * Implements \Drupal\Core\TypedData\ContextAwareInterface::getPropertyPath().
+   */
+  public function getPropertyPath() {
+    return '';
+  }
+
+  /**
+   * Implements \Drupal\Core\TypedData\ContextAwareInterface::getParent().
+   */
+  public function getParent() {
+    return NULL;
+  }
+
+  /**
+   * Implements \Drupal\Core\TypedData\ContextAwareInterface::setContext().
+   */
+  public function setContext($name = NULL, ContextAwareInterface $parent = NULL) {
+    // As entities are always the root of the tree, we do not need to set any
+    // context.
+  }
 }
diff --git a/core/lib/Drupal/Core/Entity/DatabaseStorageController.php b/core/lib/Drupal/Core/Entity/DatabaseStorageController.php
index 16b5a56..a9f08ab 100644
--- a/core/lib/Drupal/Core/Entity/DatabaseStorageController.php
+++ b/core/lib/Drupal/Core/Entity/DatabaseStorageController.php
@@ -56,6 +56,13 @@ class DatabaseStorageController implements EntityStorageControllerInterface {
   protected $entityFieldInfo;
 
   /**
+   * Static cache of field definitions per bundle.
+   *
+   * @var array
+   */
+  protected $fieldDefinitions;
+
+  /**
    * Additional arguments to pass to hook_TYPE_load().
    *
    * Set before calling Drupal\Core\Entity\DatabaseStorageController::attachLoad().
@@ -687,15 +694,17 @@ public function getFieldDefinitions(array $constraints) {
       }
     }
 
-    $definitions = $this->entityFieldInfo['definitions'];
+    $bundle = !empty($constraints['bundle']) ? $constraints['bundle'] : FALSE;
 
     // Add in per-bundle properties.
-    // @todo: Should this be statically cached as well?
-    if (!empty($constraints['bundle']) && isset($this->entityFieldInfo['bundle map'][$constraints['bundle']])) {
-      $definitions += array_intersect_key($this->entityFieldInfo['optional'], array_flip($this->entityFieldInfo['bundle map'][$constraints['bundle']]));
-    }
+    if (!isset($this->fieldDefinitions[$bundle])) {
+      $this->fieldDefinitions[$bundle] = $this->entityFieldInfo['definitions'];
 
-    return $definitions;
+      if ($bundle && isset($this->entityFieldInfo['bundle map'][$constraints['bundle']])) {
+        $this->fieldDefinitions[$bundle] += array_intersect_key($this->entityFieldInfo['optional'], array_flip($this->entityFieldInfo['bundle map'][$constraints['bundle']]));
+      }
+    }
+    return $this->fieldDefinitions[$bundle];
   }
 
   /**
diff --git a/core/lib/Drupal/Core/Entity/DatabaseStorageControllerNG.php b/core/lib/Drupal/Core/Entity/DatabaseStorageControllerNG.php
index 10a7a77..5b538c8 100644
--- a/core/lib/Drupal/Core/Entity/DatabaseStorageControllerNG.php
+++ b/core/lib/Drupal/Core/Entity/DatabaseStorageControllerNG.php
@@ -77,20 +77,17 @@ public function __construct($entityType) {
    *   A new entity object.
    */
   public function create(array $values) {
-    $entity = new $this->entityClass(array(), $this->entityType);
+    // We have to determine the bundle first.
+    $bundle = $this->bundleKey ? $values[$this->bundleKey] : FALSE;
+    $entity = new $this->entityClass(array(), $this->entityType, $bundle);
 
-    // Make sure to set the bundle first.
-    if ($this->bundleKey) {
-      $entity->{$this->bundleKey} = $values[$this->bundleKey];
-      unset($values[$this->bundleKey]);
-    }
     // Set all other given values.
     foreach ($values as $name => $value) {
       $entity->$name = $value;
     }
 
     // Assign a new UUID if there is none yet.
-    if ($this->uuidKey && !isset($entity->{$this->uuidKey})) {
+    if ($this->uuidKey && !isset($entity->{$this->uuidKey}->value)) {
       $uuid = new Uuid();
       $entity->{$this->uuidKey}->value = $uuid->generate();
     }
@@ -109,19 +106,20 @@ protected function attachLoad(&$queried_entities, $load_revision = FALSE) {
 
     // Attach fields.
     if ($this->entityInfo['fieldable']) {
+      // Prepare BC compatible entities for field API.
+      $bc_entities = array();
+      foreach ($queried_entities as $key => $entity) {
+        $bc_entities[$key] = $entity->getBCEntity();
+      }
+
       if ($load_revision) {
-        field_attach_load_revision($this->entityType, $queried_entities);
+        field_attach_load_revision($this->entityType, $bc_entities);
       }
       else {
-        field_attach_load($this->entityType, $queried_entities);
+        field_attach_load($this->entityType, $bc_entities);
       }
     }
 
-    // Loading is finished, so disable compatibility mode now.
-    foreach ($queried_entities as $entity) {
-      $entity->setCompatibilityMode(FALSE);
-    }
-
     // Call hook_entity_load().
     foreach (module_implements('entity_load') as $module) {
       $function = $module . '_entity_load';
@@ -150,13 +148,14 @@ protected function attachLoad(&$queried_entities, $load_revision = FALSE) {
   protected function mapFromStorageRecords(array $records, $load_revision = FALSE) {
 
     foreach ($records as $id => $record) {
-      $entity = new $this->entityClass(array(), $this->entityType);
-      $entity->setCompatibilityMode(TRUE);
-
+      $values = array();
       foreach ($record as $name => $value) {
-        $entity->{$name}[LANGUAGE_DEFAULT][0]['value'] = $value;
+        // Avoid unnecessary array hierarchies to save memory.
+        $values[$name][LANGUAGE_DEFAULT] = $value;
       }
-      $records[$id] = $entity;
+      $bundle = $this->bundleKey ? $record->{$this->bundleKey} : FALSE;
+      // Turn the record into an entity class.
+      $records[$id] = new $this->entityClass($values, $this->entityType, $bundle);
     }
     return $records;
   }
@@ -179,11 +178,6 @@ public function save(EntityInterface $entity) {
 
       // Create the storage record to be saved.
       $record = $this->maptoStorageRecord($entity);
-      // Update the original values so that the compatibility mode works with
-      // the update values, what is required by field API attachers.
-      // @todo Once field API has been converted to use the Field API, move
-      // this after insert/update hooks.
-      $entity->updateOriginalValues();
 
       if (!$entity->isNew()) {
         if ($entity->isDefaultRevision()) {
@@ -215,6 +209,7 @@ public function save(EntityInterface $entity) {
         $this->postSave($entity, FALSE);
         $this->invokeHook('insert', $entity);
       }
+      $entity->updateOriginalValues();
 
       // Ignore slave server temporarily.
       db_ignore_slave();
@@ -270,8 +265,7 @@ protected function saveRevision(EntityInterface $entity) {
   /**
    * Overrides DatabaseStorageController::invokeHook().
    *
-   * Invokes field API attachers in compatibility mode and disables it
-   * afterwards.
+   * Invokes field API attachers with a BC entity.
    */
   protected function invokeHook($hook, EntityInterface $entity) {
     $function = 'field_attach_' . $hook;
@@ -281,9 +275,7 @@ protected function invokeHook($hook, EntityInterface $entity) {
       $function = 'field_attach_delete_revision';
     }
     if (!empty($this->entityInfo['fieldable']) && function_exists($function)) {
-      $entity->setCompatibilityMode(TRUE);
-      $function($this->entityType, $entity);
-      $entity->setCompatibilityMode(FALSE);
+      $function($this->entityType, $entity->getBCEntity());
     }
 
     // Invoke the hook.
@@ -311,7 +303,6 @@ protected function mapToRevisionStorageRecord(EntityInterface $entity) {
     foreach ($this->entityInfo['schema_fields_sql']['revision_table'] as $name) {
       $record->$name = $entity->$name->value;
     }
-
     return $record;
   }
 }
diff --git a/core/lib/Drupal/Core/Entity/Entity.php b/core/lib/Drupal/Core/Entity/Entity.php
index 1b511e1..adbb047 100644
--- a/core/lib/Drupal/Core/Entity/Entity.php
+++ b/core/lib/Drupal/Core/Entity/Entity.php
@@ -9,6 +9,7 @@
 
 use Drupal\Component\Uuid\Uuid;
 use Drupal\Core\Language\Language;
+use Drupal\Core\TypedData\ContextAwareInterface;
 use IteratorAggregate;
 
 /**
@@ -379,4 +380,53 @@ public function getExportProperties() {
     return array();
   }
 
+  /**
+   * Implements Drupal\Core\Entity\EntityInterface::getBCEntity().
+   */
+  public function getBCEntity() {
+    return $this;
+  }
+
+  /**
+   * Implements Drupal\Core\Entity\EntityInterface::getOriginalEntity().
+   */
+  public function getOriginalEntity() {
+    return $this;
+  }
+
+  /**
+   * Implements \Drupal\Core\TypedData\ContextAwareInterface::getName().
+   */
+  public function getName() {
+    return NULL;
+  }
+
+  /**
+   * Implements \Drupal\Core\TypedData\ContextAwareInterface::getRoot().
+   */
+  public function getRoot() {
+    return $this;
+  }
+
+  /**
+   * Implements \Drupal\Core\TypedData\ContextAwareInterface::getPropertyPath().
+   */
+  public function getPropertyPath() {
+    return '';
+  }
+
+  /**
+   * Implements \Drupal\Core\TypedData\ContextAwareInterface::getParent().
+   */
+  public function getParent() {
+    return NULL;
+  }
+
+  /**
+   * Implements \Drupal\Core\TypedData\ContextAwareInterface::setContext().
+   */
+  public function setContext($name = NULL, ContextAwareInterface $parent = NULL) {
+    // As entities are always the root of the tree, we do not need to set any
+    // context.
+  }
 }
diff --git a/core/lib/Drupal/Core/Entity/EntityBCDecorator.php b/core/lib/Drupal/Core/Entity/EntityBCDecorator.php
new file mode 100644
index 0000000..9f77649
--- /dev/null
+++ b/core/lib/Drupal/Core/Entity/EntityBCDecorator.php
@@ -0,0 +1,368 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Entity\EntityBCDecorator.
+ */
+
+namespace Drupal\Core\Entity;
+
+use IteratorAggregate;
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\TypedData\ContextAwareInterface;
+
+/**
+ * Implements a decorator providing backwards compatible entity field access.
+ *
+ * Allows using entities converted to the new Entity Field API with the Drupal 7
+ * way of accessing fields or properties.
+ *
+ * Note: We access the protected 'values' and 'fields' properties of the entity
+ * via the magic getter - which returns them by reference for us. We do so, as
+ * providing references to this arrays makes $entity->values and $entity->fields
+ * to references itself as well, which is problematic during __clone() (this is
+ * something that would not be easy to fix as an unset() on the variable is
+ * problematic with the magic getter/setter then).
+ */
+class EntityBCDecorator implements IteratorAggregate, EntityInterface {
+
+  /**
+   * The EntityInterface object being decorated.
+   *
+   * @var \Drupal\Core\Entity\EntityInterface
+   */
+  protected $decorated;
+
+  /**
+   * Constructs a Drupal\Core\Entity\EntityCompatibilityDecorator object.
+   *
+   * @param \Drupal\Core\Entity\EntityInterface $decorated
+   *   The decorated entity.
+   */
+  function __construct(EntityNG $decorated) {
+    $this->decorated = $decorated;
+  }
+
+  /**
+   * Overrides Entity::getOriginalEntity().
+   */
+  public function getOriginalEntity() {
+    return $this->decorated;
+  }
+
+  /**
+   * Overrides Entity::getBCEntity().
+   */
+  public function getBCEntity() {
+    return $this;
+  }
+
+  /**
+   * Implements the magic method for getting object properties.
+   *
+   * Directly accesses the plain field values, as done in Drupal 7.
+   */
+  public function &__get($name) {
+    // Make sure $this->decorated->values reflects the latest values.
+    if (!empty($this->decorated->fields[$name])) {
+      foreach ($this->decorated->fields[$name] as $langcode => $field) {
+        $this->decorated->values[$name][$langcode] = $field->getValue();
+      }
+      // Values might be changed by reference, so remove the field object to
+      // avoid them becoming out of sync.
+      unset($this->decorated->fields[$name]);
+    }
+    // Allow accessing field values in entity default languages other than
+    // LANGUAGE_DEFAULT by mapping the values to LANGUAGE_DEFAULT.
+    $langcode = $this->decorated->language()->langcode;
+    if ($langcode != LANGUAGE_DEFAULT && isset($this->decorated->values[$name][LANGUAGE_DEFAULT]) && !isset($this->decorated->values[$name][$langcode])) {
+      $this->decorated->values[$name][$langcode] = &$this->decorated->values[$name][LANGUAGE_DEFAULT];
+    }
+
+    if (!isset($this->decorated->values[$name])) {
+      $this->decorated->values[$name] = NULL;
+    }
+    return $this->decorated->values[$name];
+  }
+
+  /**
+   * Implements the magic method for setting object properties.
+   *
+   * Directly writes to the plain field values, as done by Drupal 7.
+   */
+  public function __set($name, $value) {
+    if (is_array($value) && $definition = $this->decorated->getPropertyDefinition($name)) {
+      // If field API sets a value with a langcode in entity language, move it
+      // to LANGUAGE_DEFAULT.
+      foreach ($value as $langcode => $data) {
+        if ($langcode != LANGUAGE_DEFAULT && $langcode == $this->decorated->language()->langcode) {
+          $value[LANGUAGE_DEFAULT] = $data;
+          unset($value[$langcode]);
+        }
+      }
+    }
+    $this->decorated->values[$name] = $value;
+    unset($this->decorated->fields[$name]);
+  }
+
+  /**
+   * Implements the magic method for isset().
+   */
+  public function __isset($name) {
+    $value = $this->__get($name);
+    return isset($value);
+  }
+
+  /**
+   * Implements the magic method for unset().
+   */
+  public function __unset($name) {
+    $value = &$this->__get($name);
+    $value = array();
+  }
+
+  /**
+   * Forwards the call to the decorated entity.
+   */
+  public function access($operation = 'view', \Drupal\user\Plugin\Core\Entity\User $account = NULL) {
+    return $this->decorated->access($account);
+  }
+
+  /**
+   * Forwards the call to the decorated entity.
+   */
+  public function get($property_name) {
+    return $this->decorated->get($property_name);
+  }
+
+  /**
+   * Forwards the call to the decorated entity.
+   */
+  public function set($property_name, $value) {
+    return $this->decorated->set($property_name, $value);
+  }
+
+  /**
+   * Forwards the call to the decorated entity.
+   */
+  public function getProperties($include_computed = FALSE) {
+    return $this->decorated->getProperties($include_computed);
+  }
+
+  /**
+   * Forwards the call to the decorated entity.
+   */
+  public function getPropertyValues() {
+    return $this->decorated->getPropertyValues();
+  }
+
+  /**
+   * Forwards the call to the decorated entity.
+   */
+  public function setPropertyValues($values) {
+    return $this->decorated->setPropertyValues($values);
+  }
+
+  /**
+   * Forwards the call to the decorated entity.
+   */
+  public function getPropertyDefinition($name) {
+    return $this->decorated->getPropertyDefinition($name);
+  }
+
+  /**
+   * Forwards the call to the decorated entity.
+   */
+  public function getPropertyDefinitions() {
+    return $this->decorated->getPropertyDefinitions();
+  }
+
+  /**
+   * Forwards the call to the decorated entity.
+   */
+  public function isEmpty() {
+    return $this->decorated->isEmpty();
+  }
+
+  /**
+   * Forwards the call to the decorated entity.
+   */
+  public function getIterator() {
+    return $this->decorated->getIterator();
+  }
+
+  /**
+   * Forwards the call to the decorated entity.
+   */
+  public function id() {
+    return $this->decorated->id();
+  }
+
+  /**
+   * Forwards the call to the decorated entity.
+   */
+  public function uuid() {
+    return $this->decorated->uuid();
+  }
+
+  /**
+   * Forwards the call to the decorated entity.
+   */
+  public function isNew() {
+    return $this->decorated->isNew();
+  }
+
+  /**
+   * Forwards the call to the decorated entity.
+   */
+  public function isNewRevision() {
+    return $this->decorated->isNewRevision();
+  }
+
+  /**
+   * Forwards the call to the decorated entity.
+   */
+  public function setNewRevision($value = TRUE) {
+    return $this->decorated->setNewRevision($value);
+  }
+
+  /**
+   * Forwards the call to the decorated entity.
+   */
+  public function enforceIsNew($value = TRUE) {
+    return $this->decorated->enforceIsNew($value);
+  }
+
+  /**
+   * Forwards the call to the decorated entity.
+   */
+  public function entityType() {
+    return $this->decorated->entityType();
+  }
+
+  /**
+   * Forwards the call to the decorated entity.
+   */
+  public function bundle() {
+    return $this->decorated->bundle();
+  }
+
+  /**
+   * Forwards the call to the decorated entity.
+   */
+  public function label($langcode = NULL) {
+    return $this->decorated->label($langcode);
+  }
+
+  /**
+   * Forwards the call to the decorated entity.
+   */
+  public function uri() {
+    return $this->decorated->uri();
+  }
+
+  /**
+   * Forwards the call to the decorated entity.
+   */
+  public function save() {
+    return $this->decorated->save();
+  }
+
+  /**
+   * Forwards the call to the decorated entity.
+   */
+  public function delete() {
+    return $this->decorated->delete();
+  }
+
+  /**
+   * Forwards the call to the decorated entity.
+   */
+  public function createDuplicate() {
+    return $this->decorated->createDuplicate();
+  }
+
+  /**
+   * Forwards the call to the decorated entity.
+   */
+  public function entityInfo() {
+    return $this->decorated->entityInfo();
+  }
+
+  /**
+   * Forwards the call to the decorated entity.
+   */
+  public function getRevisionId() {
+    return $this->decorated->getRevisionId();
+  }
+
+  /**
+   * Forwards the call to the decorated entity.
+   */
+  public function isDefaultRevision($new_value = NULL) {
+    return $this->decorated->isDefaultRevision($new_value);
+  }
+
+  /**
+   * Forwards the call to the decorated entity.
+   */
+  public function language() {
+    return $this->decorated->language();
+  }
+
+  /**
+   * Forwards the call to the decorated entity.
+   */
+  public function getTranslationLanguages($include_default = TRUE) {
+    return $this->decorated->getTranslationLanguages($include_default);
+  }
+
+  /**
+   * Forwards the call to the decorated entity.
+   */
+  public function getTranslation($langcode, $strict = TRUE) {
+    return $this->decorated->getTranslation($langcode, $strict);
+  }
+
+  /**
+   * Forwards the call to the decorated entity.
+   */
+  public function getName() {
+    return $this->decorated->getName();
+  }
+
+  /**
+   * Forwards the call to the decorated entity.
+   */
+  public function getRoot() {
+    return $this->decorated->getRoot();
+  }
+
+  /**
+   * Forwards the call to the decorated entity.
+   */
+  public function getPropertyPath() {
+    return $this->decorated->getPropertyPath();
+  }
+
+  /**
+   * Forwards the call to the decorated entity.
+   */
+  public function getParent() {
+    return $this->decorated->getParent();
+  }
+
+  /**
+   * Forwards the call to the decorated entity.
+   */
+  public function setContext($name = NULL, ContextAwareInterface $parent = NULL) {
+    $this->decorated->setContext($name, $parent);
+  }
+
+  /**
+   * Forwards the call to the decorated entity.
+   */
+  public function getExportProperties() {
+    $this->decorated->getExportProperties();
+  }
+}
diff --git a/core/lib/Drupal/Core/Entity/EntityFormControllerNG.php b/core/lib/Drupal/Core/Entity/EntityFormControllerNG.php
index 812a192..51bc911 100644
--- a/core/lib/Drupal/Core/Entity/EntityFormControllerNG.php
+++ b/core/lib/Drupal/Core/Entity/EntityFormControllerNG.php
@@ -23,9 +23,7 @@ public function form(array $form, array &$form_state, EntityInterface $entity) {
     // entity properties.
     $info = $entity->entityInfo();
     if (!empty($info['fieldable'])) {
-      $entity->setCompatibilityMode(TRUE);
-      field_attach_form($entity->entityType(), $entity, $form, $form_state, $this->getFormLangcode($form_state));
-      $entity->setCompatibilityMode(FALSE);
+      field_attach_form($entity->entityType(), $entity->getBCEntity(), $form, $form_state, $this->getFormLangcode($form_state));
     }
     return $form;
   }
@@ -40,9 +38,7 @@ public function validate(array $form, array &$form_state) {
     $info = $entity->entityInfo();
 
     if (!empty($info['fieldable'])) {
-      $entity->setCompatibilityMode(TRUE);
-      field_attach_form_validate($entity->entityType(), $entity, $form, $form_state);
-      $entity->setCompatibilityMode(FALSE);
+      field_attach_form_validate($entity->entityType(), $entity->getBCEntity(), $form, $form_state);
     }
 
     // @todo Remove this.
@@ -82,9 +78,7 @@ public function buildEntity(array $form, array &$form_state) {
 
     // Copy field values to the entity.
     if ($info['fieldable']) {
-      $entity->setCompatibilityMode(TRUE);
-      field_attach_submit($entity_type, $entity, $form, $form_state);
-      $entity->setCompatibilityMode(FALSE);
+      field_attach_submit($entity_type, $entity->getBCEntity(), $form, $form_state);
     }
     return $entity;
   }
diff --git a/core/lib/Drupal/Core/Entity/EntityInterface.php b/core/lib/Drupal/Core/Entity/EntityInterface.php
index a3e4a62..94ecc3b 100644
--- a/core/lib/Drupal/Core/Entity/EntityInterface.php
+++ b/core/lib/Drupal/Core/Entity/EntityInterface.php
@@ -8,6 +8,7 @@
 namespace Drupal\Core\Entity;
 
 use Drupal\Core\TypedData\AccessibleInterface;
+use Drupal\Core\TypedData\ContextAwareInterface;
 use Drupal\Core\TypedData\ComplexDataInterface;
 use Drupal\Core\TypedData\TranslatableInterface;
 
@@ -17,7 +18,7 @@
  * When implementing this interface which extends Traversable, make sure to list
  * IteratorAggregate or Iterator before this interface in the implements clause.
  */
-interface EntityInterface extends ComplexDataInterface, AccessibleInterface, TranslatableInterface {
+interface EntityInterface extends ContextAwareInterface, ComplexDataInterface, AccessibleInterface, TranslatableInterface {
 
   /**
    * Returns the entity identifier (the entity's machine name or numeric ID).
@@ -190,4 +191,23 @@ public function isDefaultRevision($new_value = NULL);
    */
   public function getExportProperties();
 
+  /**
+   * Gets a backward compatibility decorator entity.
+   *
+   * @return \Drupal\Core\Entity\EntityInterface
+   *   The backward compatible entity.
+   *
+   * @see \Drupal\Core\Entity\EntityInterface::getOriginalEntity()
+   */
+  public function getBCEntity();
+
+  /**
+   * Removes any possible (backward compatibility) decorator in use.
+   *
+   * @return \Drupal\Core\Entity\EntityInterface
+   *   The original, not backward compatible entity object.
+   *
+   * @see \Drupal\Core\Entity\EntityInterface::getBCEntity()
+   */
+  public function getOriginalEntity();
 }
diff --git a/core/lib/Drupal/Core/Entity/EntityNG.php b/core/lib/Drupal/Core/Entity/EntityNG.php
index c486aa8..7df5b1e 100644
--- a/core/lib/Drupal/Core/Entity/EntityNG.php
+++ b/core/lib/Drupal/Core/Entity/EntityNG.php
@@ -26,6 +26,13 @@
 class EntityNG extends Entity {
 
   /**
+   * Local cache holding the value of the bundle field.
+   *
+   * @var string
+   */
+  protected $bundle;
+
+  /**
    * The plain data values of the contained fields.
    *
    * This always holds the original, unchanged values of the entity. The values
@@ -50,22 +57,69 @@ class EntityNG extends Entity {
   protected $fields = array();
 
   /**
-   * Whether the entity is in pre-Entity Field API compatibility mode.
+   * An instance of the backward compatibility decorator.
+   *
+   * @var EntityBCDecorator
+   */
+  protected $bcEntity;
+
+  /**
+   * Local cache for field definitions.
    *
-   * If set to TRUE, field values are written directly to $this->values, thus
-   * must be plain property values keyed by language code. This must be enabled
-   * when calling legacy field API attachers.
+   * @see self::getPropertyDefinitions()
+   *
+   * @var array
+   */
+  protected $fieldDefinitions;
+
+  /**
+   * Overrides Entity::__construct().
+   */
+  public function __construct(array $values, $entity_type, $bundle = FALSE) {
+    $this->entityType = $entity_type;
+    $this->bundle = $bundle ? $bundle : $this->entityType;
+    foreach ($values as $key => $value) {
+      $this->values[$key] = $value;
+    }
+    $this->init();
+  }
+
+  /**
+   * Gets the typed data type of the entity.
    *
-   * @var bool
+   * @return string
+   */
+  public function getType() {
+    return $this->entityType;
+  }
+
+  /**
+   * Initialize the object. Invoked upon construction and wake up.
    */
-  protected $compatibilityMode = FALSE;
+  protected function init() {
+    // We unset all defined properties, so magic getters apply.
+    unset($this->langcode);
+  }
 
+  /**
+   * Magic __wakeup() implemenation.
+   */
+  public function __wakeup() {
+    $this->init();
+  }
 
   /**
-   * Overrides Entity::id().
+   * Implements Drupal\Core\Entity\EntityInterface::id().
    */
   public function id() {
-    return $this->get('id')->value;
+    return $this->id->value;
+  }
+
+  /**
+   * Implements Drupal\Core\Entity\EntityInterface::bundle().
+   */
+  public function bundle() {
+    return $this->bundle;
   }
 
   /**
@@ -105,9 +159,11 @@ protected function getTranslatedField($property_name, $langcode) {
         $this->fields[$property_name][$langcode] = $this->getTranslatedField($property_name, LANGUAGE_DEFAULT);
       }
       else {
-        $value = isset($this->values[$property_name][$langcode]) ? $this->values[$property_name][$langcode] : NULL;
-        $context = array('parent' => $this, 'name' => $property_name);
-        $this->fields[$property_name][$langcode] = typed_data()->create($definition, $value, $context);
+        $value = NULL;
+        if (isset($this->values[$property_name][$langcode])) {
+          $value = $this->values[$property_name][$langcode];
+        }
+        $this->fields[$property_name][$langcode] = typed_data()->getPropertyInstance($this, $property_name, $value);
       }
     }
     return $this->fields[$property_name][$langcode];
@@ -144,18 +200,14 @@ public function getIterator() {
    * Implements ComplexDataInterface::getPropertyDefinition().
    */
   public function getPropertyDefinition($name) {
-    // First try getting property definitions which apply to all entities of
-    // this type. Then if this fails add in definitions of optional properties
-    // as well. That way we can use property definitions of base properties
-    // when determining the optional properties of an entity.
-    $definitions = entity_get_controller($this->entityType)->getFieldDefinitions(array());
-
-    if (isset($definitions[$name])) {
-      return $definitions[$name];
+    if (!isset($this->fieldDefinitions)) {
+      $this->getPropertyDefinitions();
+    }
+    if (isset($this->fieldDefinitions[$name])) {
+      return $this->fieldDefinitions[$name];
     }
-    // Add in optional properties if any.
-    if ($definitions = $this->getPropertyDefinitions()) {
-      return isset($definitions[$name]) ? $definitions[$name] : FALSE;
+    else {
+      return FALSE;
     }
   }
 
@@ -163,10 +215,13 @@ public function getPropertyDefinition($name) {
    * Implements ComplexDataInterface::getPropertyDefinitions().
    */
   public function getPropertyDefinitions() {
-    return entity_get_controller($this->entityType)->getFieldDefinitions(array(
-      'entity type' => $this->entityType,
-      'bundle' => $this->bundle(),
-    ));
+    if (!isset($this->fieldDefinitions)) {
+      $this->fieldDefinitions = entity_get_controller($this->entityType)->getFieldDefinitions(array(
+        'entity type' => $this->entityType,
+        'bundle' => $this->bundle,
+      ));
+    }
+    return $this->fieldDefinitions;
   }
 
   /**
@@ -208,7 +263,13 @@ public function isEmpty() {
    * Implements TranslatableInterface::language().
    */
   public function language() {
-    return $this->get('langcode')->language;
+    $language = $this->get('langcode')->language;
+    if (!$language) {
+      // Make sure we return a proper language object.
+      // @todo Refactor this, see: http://drupal.org/node/1834542.
+      $language = language_default();
+    }
+    return $language;
   }
 
   /**
@@ -236,6 +297,9 @@ public function getTranslation($langcode, $strict = TRUE) {
         $fields[$name] = $this->getTranslatedField($name, $langcode);
       }
     }
+    // @todo: Add a way to get the definition of a translation to the
+    // TranslatableInterface and leverage TypeDataManager::getPropertyInstance
+    // also.
     $translation_definition = array(
       'type' => 'entity_translation',
       'constraints' => array(
@@ -243,11 +307,11 @@ public function getTranslation($langcode, $strict = TRUE) {
         'bundle' => $this->bundle(),
       ),
     );
-    $translation = typed_data()->create($translation_definition, $fields, array(
-      'parent' => $this,
-      'name' => $langcode,
-    ));
+    $translation = typed_data()->create($translation_definition, $fields);
     $translation->setStrictMode($strict);
+    if ($translation instanceof ContextAwareInterface) {
+      $translation->setContext('@' . $langcode, $this);
+    }
     return $translation;
   }
 
@@ -256,89 +320,101 @@ public function getTranslation($langcode, $strict = TRUE) {
    */
   public function getTranslationLanguages($include_default = TRUE) {
     $translations = array();
-    // Build an array with the translation langcodes set as keys.
+    // Build an array with the translation langcodes set as keys. Empty
+    // translations must be filtered out.
     foreach ($this->getProperties() as $name => $property) {
-      if (isset($this->values[$name])) {
-        $translations += $this->values[$name];
+      foreach ($this->fields[$name] as $langcode => $field) {
+        if (!$field->isEmpty()) {
+          $translations[$langcode] = TRUE;
+        }
+        if (isset($this->values[$name])) {
+          foreach ($this->values[$name] as $langcode => $values) {
+            if ($values && !(isset($this->fields[$name][$langcode]) && $this->fields[$name][$langcode]->isEmpty())) {
+              $translations[$langcode] = TRUE;
+            }
+          }
+        }
       }
-      $translations += $this->fields[$name];
     }
     unset($translations[LANGUAGE_DEFAULT]);
 
     if ($include_default) {
       $translations[$this->language()->langcode] = TRUE;
     }
-
-    // Now get languages based upon translation langcodes. Empty languages must
-    // be filtered out as they concern empty/unset properties.
-    $languages = array_intersect_key(language_list(LANGUAGE_ALL), array_filter($translations));
-    return $languages;
+    // Now get languages based upon translation langcodes.
+    return array_intersect_key(language_list(LANGUAGE_ALL), $translations);
   }
 
   /**
-   * Enables or disable the compatibility mode.
-   *
-   * @param bool $enabled
-   *   Whether to enable the mode.
+   * Overrides Entity::translations().
    *
-   * @see EntityNG::compatibilityMode
+   * @todo: Remove once Entity::translations() gets removed.
    */
-  public function setCompatibilityMode($enabled) {
-    $this->compatibilityMode = (bool) $enabled;
-    if ($enabled) {
-      $this->updateOriginalValues();
-      $this->fields = array();
-    }
+  public function translations() {
+    return $this->getTranslationLanguages(FALSE);
   }
 
   /**
-   * Returns whether the compatibility mode is active.
+   * Overrides Entity::getBCEntity().
    */
-  public function getCompatibilityMode() {
-    return $this->compatibilityMode;
+  public function getBCEntity() {
+    if (!isset($this->bcEntity)) {
+      $this->bcEntity = new EntityBCDecorator($this);
+    }
+    return $this->bcEntity;
   }
 
   /**
    * Updates the original values with the interim changes.
-   *
-   * Note: This should be called by the storage controller during a save
-   * operation.
    */
   public function updateOriginalValues() {
-    foreach ($this->fields as $name => $properties) {
-      foreach ($properties as $langcode => $property) {
-        $this->values[$name][$langcode] = $property->getValue();
+    if (!$this->fields) {
+      return;
+    }
+    foreach ($this->getPropertyDefinitions() as $name => $definition) {
+      if (empty($definition['computed']) && !empty($this->fields[$name])) {
+        foreach ($this->fields[$name] as $langcode => $field) {
+          $this->values[$name][$langcode] = $field->getValue();
+        }
       }
     }
   }
 
   /**
-   * Magic getter: Gets the property in default language.
+   * Implements the magic method for setting object properties.
    *
+   * Uses default language always.
    * For compatibility mode to work this must return a reference.
    */
   public function &__get($name) {
-    if ($this->compatibilityMode) {
-      if (!isset($this->values[$name])) {
-        $this->values[$name] = NULL;
-      }
-      return $this->values[$name];
-    }
     if (isset($this->fields[$name][LANGUAGE_DEFAULT])) {
       return $this->fields[$name][LANGUAGE_DEFAULT];
     }
-    if ($this->getPropertyDefinition($name)) {
-      $return = $this->get($name);
+    // Inline getPropertyDefinition() to speed up things.
+    if (!isset($this->fieldDefinitions)) {
+      $this->getPropertyDefinitions();
+    }
+    if (isset($this->fieldDefinitions[$name])) {
+      $return = $this->getTranslatedField($name, LANGUAGE_DEFAULT);
       return $return;
     }
-    if (!isset($this->$name)) {
-      $this->$name = NULL;
+    // Allow the EntityBCDecorator to directly access the values and fields.
+    // @todo: Remove once the EntityBCDecorator gets removed.
+    if ($name == 'values' || $name == 'fields') {
+      return $this->$name;
+    }
+    // Else directly read/write plain values. That way, fields not yet converted
+    // to the entity field API can always be directly accessed.
+    if (!isset($this->values[$name])) {
+      $this->values[$name] = NULL;
     }
-    return $this->$name;
+    return $this->values[$name];
   }
 
   /**
-   * Magic getter: Sets the property in default language.
+   * Implements the magic method for setting object properties.
+   *
+   * Uses default language always.
    */
   public function __set($name, $value) {
     // Support setting values via property objects.
@@ -346,41 +422,40 @@ public function __set($name, $value) {
       $value = $value->getValue();
     }
 
-    if ($this->compatibilityMode) {
-      $this->values[$name] = $value;
-    }
-    elseif (isset($this->fields[$name][LANGUAGE_DEFAULT])) {
+    if (isset($this->fields[$name][LANGUAGE_DEFAULT])) {
       $this->fields[$name][LANGUAGE_DEFAULT]->setValue($value);
     }
     elseif ($this->getPropertyDefinition($name)) {
-      $this->get($name)->setValue($value);
+      $this->getTranslatedField($name, LANGUAGE_DEFAULT)->setValue($value);
     }
+    // Else directly read/write plain values. That way, fields not yet converted
+    // to the entity field API can always be directly accessed.
     else {
-      $this->$name = $value;
+      $this->values[$name] = $value;
     }
   }
 
   /**
-   * Magic method.
+   * Implements the magic method for isset().
    */
   public function __isset($name) {
-    if ($this->compatibilityMode) {
-      return isset($this->values[$name]);
+    if ($this->getPropertyDefinition($name)) {
+      return $this->get($name)->getValue() !== NULL;
     }
-    elseif ($this->getPropertyDefinition($name)) {
-      return $this->get($name)->valueIsSet();
+    else {
+      return isset($this->values[$name]);
     }
   }
 
   /**
-   * Magic method.
+   * Implements the magic method for unset.
    */
   public function __unset($name) {
-    if ($this->compatibilityMode) {
-      unset($this->values[$name]);
+    if ($this->getPropertyDefinition($name)) {
+      $this->get($name)->setValue(NULL);
     }
-    elseif ($this->getPropertyDefinition($name)) {
-      $this->get($name)->unsetValue();
+    else {
+      unset($this->values[$name]);
     }
   }
 
@@ -404,13 +479,30 @@ public function createDuplicate() {
    * Implements a deep clone.
    */
   public function __clone() {
+    $this->bcEntity = NULL;
+
     foreach ($this->fields as $name => $properties) {
       foreach ($properties as $langcode => $property) {
         $this->fields[$name][$langcode] = clone $property;
         if ($property instanceof ContextAwareInterface) {
-          $this->fields[$name][$langcode]->setParent($this);
+          $this->fields[$name][$langcode]->setContext($name, $this);
         }
       }
     }
   }
+
+  /**
+   * Overrides Entity::label() to access the label field with the new API.
+   */
+  public function label($langcode = NULL) {
+    $label = NULL;
+    $entity_info = $this->entityInfo();
+    if (isset($entity_info['label_callback']) && function_exists($entity_info['label_callback'])) {
+      $label = $entity_info['label_callback']($this->entityType, $this, $langcode);
+    }
+    elseif (!empty($entity_info['entity_keys']['label']) && isset($this->{$entity_info['entity_keys']['label']})) {
+      $label = $this->{$entity_info['entity_keys']['label']}->value;
+    }
+    return $label;
+  }
 }
diff --git a/core/lib/Drupal/Core/Entity/EntityRenderController.php b/core/lib/Drupal/Core/Entity/EntityRenderController.php
index eb3147e..f942ae0 100644
--- a/core/lib/Drupal/Core/Entity/EntityRenderController.php
+++ b/core/lib/Drupal/Core/Entity/EntityRenderController.php
@@ -68,23 +68,8 @@ public function buildContent(array $entities = array(), $view_mode = 'full', $la
 
     // Prepare and build field content, grouped by view mode.
     foreach ($view_modes as $view_mode => $view_mode_entities) {
-      $call_prepare = array();
-      // To ensure hooks are only run once per entity, check for an
-      // entity_view_prepared flag and only process relevant entities.
-      foreach ($view_mode_entities as $entity) {
-        if (empty($entity->entity_view_prepared) || $entity->entity_view_prepared != $view_mode) {
-          // Add this entity to the items to be prepared.
-          $call_prepare[$entity->id()] = $entity;
-
-          // Mark this item as prepared for this view mode.
-          $entity->entity_view_prepared = $view_mode;
-        }
-      }
-
-      if (!empty($call_prepare)) {
-        field_attach_prepare_view($this->entityType, $call_prepare, $displays[$view_mode], $langcode);
-        module_invoke_all('entity_prepare_view', $call_prepare, $this->entityType);
-      }
+      field_attach_prepare_view($this->entityType, $view_mode_entities, $displays[$view_mode], $langcode);
+      module_invoke_all('entity_prepare_view', $view_mode_entities, $this->entityType);
 
       foreach ($view_mode_entities as $entity) {
         $entity->content += field_attach_view($this->entityType, $entity, $displays[$view_mode][$entity->bundle()], $langcode);
diff --git a/core/lib/Drupal/Core/Entity/Field/FieldItemBase.php b/core/lib/Drupal/Core/Entity/Field/FieldItemBase.php
index 5c71aa3..a1fdc6b 100644
--- a/core/lib/Drupal/Core/Entity/Field/FieldItemBase.php
+++ b/core/lib/Drupal/Core/Entity/Field/FieldItemBase.php
@@ -7,8 +7,7 @@
 
 namespace Drupal\Core\Entity\Field;
 
-use Drupal\Core\TypedData\Type\TypedData;
-use Drupal\Core\TypedData\ComplexDataInterface;
+use Drupal\Core\TypedData\ContextAwareTypedData;
 use Drupal\Core\TypedData\ContextAwareInterface;
 use Drupal\Core\TypedData\TypedDataInterface;
 use Drupal\user;
@@ -24,21 +23,7 @@
  *
  * @see \Drupal\Core\Entity\Field\FieldItemInterface
  */
-abstract class FieldItemBase extends TypedData implements IteratorAggregate, FieldItemInterface {
-
-  /**
-   * The item delta or name.
-   *
-   * @var integer
-   */
-  protected $name;
-
-  /**
-   * The parent entity field.
-   *
-   * @var \Drupal\Core\Entity\Field\FieldInterface
-   */
-  protected $parent;
+abstract class FieldItemBase extends ContextAwareTypedData implements IteratorAggregate, FieldItemInterface {
 
   /**
    * The array of properties.
@@ -52,10 +37,10 @@
   protected $properties = array();
 
   /**
-   * Implements TypedDataInterface::__construct().
+   * Overrides ContextAwareTypedData::__construct().
    */
-  public function __construct(array $definition) {
-    $this->definition = $definition;
+  public function __construct(array $definition, $name = NULL, ContextAwareInterface $parent = NULL) {
+    parent::__construct($definition, $name, $parent);
 
     // Initialize all property objects, but postpone the creating of computed
     // properties to a second step. That way computed properties can safely get
@@ -63,17 +48,15 @@ public function __construct(array $definition) {
     $step2 = array();
     foreach ($this->getPropertyDefinitions() as $name => $definition) {
       if (empty($definition['computed'])) {
-        $context = array('name' => $name, 'parent' => $this);
-        $this->properties[$name] = typed_data()->create($definition, NULL, $context);
+        $this->properties[$name] = typed_data()->getPropertyInstance($this, $name);
       }
       else {
-        $step2[$name] = $definition;
+        $step2[] = $name;
       }
     }
 
-    foreach ($step2 as $name => $definition) {
-      $context = array('name' => $name, 'parent' => $this);
-      $this->properties[$name] = typed_data()->create($definition, NULL, $context);
+    foreach ($step2 as $name) {
+      $this->properties[$name] = typed_data()->getPropertyInstance($this, $name);
     }
   }
 
@@ -96,14 +79,19 @@ public function getValue() {
    */
   public function setValue($values) {
     // Treat the values as property value of the first property, if no array is
-    // given and we only have one property.
-    if (!is_array($values) && count($this->properties) == 1) {
+    // given.
+    if (!is_array($values)) {
       $keys = array_keys($this->properties);
       $values = array($keys[0] => $values);
     }
 
     foreach ($this->properties as $name => $property) {
-      $property->setValue(isset($values[$name]) ? $values[$name] : NULL);
+      if (isset($values[$name])) {
+        $property->setValue($values[$name]);
+      }
+      else {
+        $property->setValue(NULL);
+      }
     }
     // @todo: Throw an exception for invalid values once conversion is
     // totally completed.
@@ -178,35 +166,6 @@ public function __unset($name) {
     }
   }
 
-  /**
-   * Implements ContextAwareInterface::getName().
-   */
-  public function getName() {
-    return $this->name;
-  }
-
-  /**
-   * Implements ContextAwareInterface::setName().
-   */
-  public function setName($name) {
-    $this->name = $name;
-  }
-
-  /**
-   * Implements ContextAwareInterface::getParent().
-   *
-   * @return \Drupal\Core\Entity\Field\FieldInterface
-   */
-  public function getParent() {
-    return $this->parent;
-  }
-
-  /**
-   * Implements ContextAwareInterface::setParent().
-   */
-  public function setParent($parent) {
-    $this->parent = $parent;
-  }
 
   /**
    * Implements ComplexDataInterface::getProperties().
@@ -249,7 +208,12 @@ public function getIterator() {
    */
   public function getPropertyDefinition($name) {
     $definitions = $this->getPropertyDefinitions();
-    return isset($definitions[$name]) ? $definitions[$name] : FALSE;
+    if (isset($definitions[$name])) {
+      return $definitions[$name];
+    }
+    else {
+      return FALSE;
+    }
   }
 
   /**
@@ -271,7 +235,7 @@ public function __clone() {
     foreach ($this->properties as $name => $property) {
       $this->properties[$name] = clone $property;
       if ($property instanceof ContextAwareInterface) {
-        $this->properties[$name]->setParent($this);
+        $this->properties[$name]->setContext($name, $this);
       }
     }
   }
diff --git a/core/lib/Drupal/Core/Entity/Field/Type/BooleanItem.php b/core/lib/Drupal/Core/Entity/Field/Type/BooleanItem.php
index 131d0a2..39f61b5 100644
--- a/core/lib/Drupal/Core/Entity/Field/Type/BooleanItem.php
+++ b/core/lib/Drupal/Core/Entity/Field/Type/BooleanItem.php
@@ -15,7 +15,7 @@
 class BooleanItem extends FieldItemBase {
 
   /**
-   * Field definitions of the contained properties.
+   * Definitions of the contained properties.
    *
    * @see self::getPropertyDefinitions()
    *
diff --git a/core/lib/Drupal/Core/Entity/Field/Type/DateItem.php b/core/lib/Drupal/Core/Entity/Field/Type/DateItem.php
index eb1ab12..b53b97f 100644
--- a/core/lib/Drupal/Core/Entity/Field/Type/DateItem.php
+++ b/core/lib/Drupal/Core/Entity/Field/Type/DateItem.php
@@ -15,7 +15,7 @@
 class DateItem extends FieldItemBase {
 
   /**
-   * Field definitions of the contained properties.
+   * Definitions of the contained properties.
    *
    * @see self::getPropertyDefinitions()
    *
diff --git a/core/lib/Drupal/Core/Entity/Field/Type/EntityReferenceItem.php b/core/lib/Drupal/Core/Entity/Field/Type/EntityReferenceItem.php
index a60e65e..6c4a6fc 100644
--- a/core/lib/Drupal/Core/Entity/Field/Type/EntityReferenceItem.php
+++ b/core/lib/Drupal/Core/Entity/Field/Type/EntityReferenceItem.php
@@ -13,13 +13,13 @@
 /**
  * Defines the 'entityreference_field' entity field item.
  *
- * Required settings (below the definition's 'settings' key) are:
- *  - entity type: The entity type to reference.
+ * Available settings (below the definition's 'settings' key) are:
+ *   - entity type: (required) The entity type to reference.
  */
 class EntityReferenceItem extends FieldItemBase {
 
   /**
-   * Field definitions of the contained properties.
+   * Definitions of the contained properties.
    *
    * @see self::getPropertyDefinitions()
    *
@@ -71,8 +71,11 @@ public function setValue($values) {
     if (isset($values['value'])) {
       $this->properties['value']->setValue($values['value']);
     }
+    elseif (isset($values['entity'])) {
+      $this->properties['entity']->setValue($values['entity']);
+    }
     else {
-      $this->properties['entity']->setValue(isset($values['entity']) ? $values['entity'] : NULL);
+      $this->properties['entity']->setValue(NULL);
     }
     unset($values['entity'], $values['value']);
     if ($values) {
diff --git a/core/lib/Drupal/Core/Entity/Field/Type/EntityTranslation.php b/core/lib/Drupal/Core/Entity/Field/Type/EntityTranslation.php
index 280fca9..b4fe089 100644
--- a/core/lib/Drupal/Core/Entity/Field/Type/EntityTranslation.php
+++ b/core/lib/Drupal/Core/Entity/Field/Type/EntityTranslation.php
@@ -7,11 +7,9 @@
 
 namespace Drupal\Core\Entity\Field\Type;
 
-use Drupal\Core\TypedData\Type\TypedData;
 use Drupal\Core\TypedData\AccessibleInterface;
 use Drupal\Core\TypedData\ComplexDataInterface;
-use Drupal\Core\TypedData\ContextAwareInterface;
-use Drupal\Core\TypedData\TypedDataInterface;
+use Drupal\Core\TypedData\ContextAwareTypedData;
 use ArrayIterator;
 use IteratorAggregate;
 use InvalidArgumentException;
@@ -19,7 +17,7 @@
 /**
  * Makes translated entity properties available via the Field API.
  */
-class EntityTranslation extends TypedData implements IteratorAggregate, AccessibleInterface, ComplexDataInterface, ContextAwareInterface {
+class EntityTranslation extends ContextAwareTypedData implements IteratorAggregate, AccessibleInterface, ComplexDataInterface {
 
   /**
    * The array of translated properties, each being an instance of
@@ -30,20 +28,6 @@ class EntityTranslation extends TypedData implements IteratorAggregate, Accessib
   protected $properties = array();
 
   /**
-   * The language code of the translation.
-   *
-   * @var string
-   */
-  protected $langcode;
-
-  /**
-   * The parent entity.
-   *
-   * @var \Drupal\Core\Entity\EntityInterface
-   */
-  protected $parent;
-
-  /**
    * Whether the entity translation acts in strict mode.
    *
    * @var boolean
@@ -73,37 +57,6 @@ public function setStrictMode($strict = TRUE) {
   }
 
   /**
-   * Implements ContextAwareInterface::getName().
-   */
-  public function getName() {
-    // The name of the translation is the language code.
-    return $this->langcode;
-  }
-
-  /**
-   * Implements ContextAwareInterface::setName().
-   */
-  public function setName($name) {
-    // The name of the translation is the language code.
-    $this->langcode = $name;
-  }
-
-  /**
-   * Implements ContextAwareInterface::getParent().
-   *
-   * @return \Drupal\Core\Entity\EntityInterface
-   */
-  public function getParent() {
-    return $this->parent;
-  }
-
-  /**
-   * Implements ContextAwareInterface::setParent().
-   */
-  public function setParent($parent) {
-    $this->parent = $parent;
-  }
-  /**
    * Implements TypedDataInterface::getValue().
    */
   public function getValue() {
@@ -186,7 +139,12 @@ public function getIterator() {
    */
   public function getPropertyDefinition($name) {
     $definitions = $this->getPropertyDefinitions();
-    return isset($definitions[$name]) ? $definitions[$name] : FALSE;
+    if (isset($definitions[$name])) {
+      return $definitions[$name];
+    }
+    else {
+      return FALSE;
+    }
   }
 
   /**
@@ -235,7 +193,10 @@ public function isEmpty() {
    */
   public function access($operation = 'view', \Drupal\user\Plugin\Core\Entity\User $account = NULL) {
     $method = $operation . 'Access';
-    return entity_access_controller($this->parent->entityType())->$method($this->parent, $this->langcode, $account);
+    // @todo Add a way to set and get the langcode so that's more obvious what
+    // we're doing here.
+    $langocde = substr($this->getName(), 1);
+    return entity_access_controller($this->parent->entityType())->$method($this->parent, $langocde, $account);
   }
 
   /**
diff --git a/core/lib/Drupal/Core/Entity/Field/Type/EntityWrapper.php b/core/lib/Drupal/Core/Entity/Field/Type/EntityWrapper.php
index 97449e7..ffc9fd1 100644
--- a/core/lib/Drupal/Core/Entity/Field/Type/EntityWrapper.php
+++ b/core/lib/Drupal/Core/Entity/Field/Type/EntityWrapper.php
@@ -8,9 +8,9 @@
 namespace Drupal\Core\Entity\Field\Type;
 
 use Drupal\Core\Entity\EntityInterface;
-use Drupal\Core\TypedData\Type\TypedData;
 use Drupal\Core\TypedData\ComplexDataInterface;
 use Drupal\Core\TypedData\ContextAwareInterface;
+use Drupal\Core\TypedData\ContextAwareTypedData;
 use Drupal\Core\TypedData\TypedDataInterface;
 use ArrayIterator;
 use IteratorAggregate;
@@ -36,21 +36,7 @@
  *  - id source: If used as computed property, the ID property used to load
  *    the entity object.
  */
-class EntityWrapper extends TypedData implements IteratorAggregate, ComplexDataInterface, ContextAwareInterface {
-
-  /**
-   * The name.
-   *
-   * @var string
-   */
-  protected $name;
-
-  /**
-   * The parent data structure.
-   *
-   * @var mixed
-   */
-  protected $parent;
+class EntityWrapper extends ContextAwareTypedData implements IteratorAggregate, ComplexDataInterface {
 
   /**
    * The referenced entity type.
@@ -67,10 +53,10 @@ class EntityWrapper extends TypedData implements IteratorAggregate, ComplexDataI
   protected $id;
 
   /**
-   * Implements TypedDataInterface::__construct().
+   * Overrides ContextAwareTypedData::__construct().
    */
-  public function __construct(array $definition) {
-    $this->definition = $definition + array('constraints' => array());
+  public function __construct(array $definition, $name = NULL, ContextAwareInterface $parent = NULL) {
+    parent::__construct($definition, $name, $parent);
     $this->entityType = isset($this->definition['constraints']['entity type']) ? $this->definition['constraints']['entity type'] : NULL;
   }
 
@@ -120,8 +106,10 @@ public function setValue($value) {
    * Implements TypedDataInterface::getString().
    */
   public function getString() {
-    $entity = $this->getValue();
-    return $entity ? $entity->label() : '';
+    if ($entity = $this->getValue()) {
+      return $entity->label();
+    }
+    return '';
   }
 
   /**
@@ -135,17 +123,20 @@ public function validate($value = NULL) {
    * Implements IteratorAggregate::getIterator().
    */
   public function getIterator() {
-    $entity = $this->getValue();
-    return $entity ? $entity->getIterator() : new ArrayIterator(array());
+    if ($entity = $this->getValue()) {
+      return $entity->getIterator();
+    }
+    return new ArrayIterator(array());
   }
 
   /**
    * Implements ComplexDataInterface::get().
    */
   public function get($property_name) {
-    $entity = $this->getValue();
     // @todo: Allow navigating through the tree without data as well.
-    return $entity ? $entity->get($property_name) : NULL;
+    if ($entity = $this->getValue()) {
+      return $entity->get($property_name);
+    }
   }
 
   /**
@@ -156,39 +147,13 @@ public function set($property_name, $value) {
   }
 
   /**
-   * Implements ContextAwareInterface::getName().
-   */
-  public function getName() {
-    return $this->name;
-  }
-
-  /**
-   * Implements ContextAwareInterface::setName().
-   */
-  public function setName($name) {
-    $this->name = $name;
-  }
-
-  /**
-   * Implements ContextAwareInterface::getParent().
-   */
-  public function getParent() {
-    return $this->parent;
-  }
-
-  /**
-   * Implements ContextAwareInterface::setParent().
-   */
-  public function setParent($parent) {
-    $this->parent = $parent;
-  }
-
-  /**
    * Implements ComplexDataInterface::getProperties().
    */
   public function getProperties($include_computed = FALSE) {
-    $entity = $this->getValue();
-    return $entity ? $entity->getProperties($include_computed) : array();
+    if ($entity = $this->getValue()) {
+      return $entity->getProperties($include_computed);
+    }
+    return array();
   }
 
   /**
@@ -196,7 +161,12 @@ public function getProperties($include_computed = FALSE) {
    */
   public function getPropertyDefinition($name) {
     $definitions = $this->getPropertyDefinitions();
-    return isset($definitions[$name]) ? $definitions[$name] : FALSE;
+    if (isset($definitions[$name])) {
+      return $definitions[$name];
+    }
+    else {
+      return FALSE;
+    }
   }
 
   /**
@@ -211,8 +181,10 @@ public function getPropertyDefinitions() {
    * Implements ComplexDataInterface::getPropertyValues().
    */
   public function getPropertyValues() {
-    $entity = $this->getValue();
-    return $entity ? $entity->getPropertyValues() : array();
+    if ($entity = $this->getValue()) {
+      return $entity->getPropertyValues();
+    }
+    return array();
   }
 
   /**
diff --git a/core/lib/Drupal/Core/Entity/Field/Type/Field.php b/core/lib/Drupal/Core/Entity/Field/Type/Field.php
index 0e7a982..03d17e4 100644
--- a/core/lib/Drupal/Core/Entity/Field/Type/Field.php
+++ b/core/lib/Drupal/Core/Entity/Field/Type/Field.php
@@ -8,9 +8,10 @@
 namespace Drupal\Core\Entity\Field\Type;
 
 use Drupal\Core\Entity\Field\FieldInterface;
-use Drupal\Core\TypedData\TypedDataInterface;
-use Drupal\Core\TypedData\Type\TypedData;
 use Drupal\user\Plugin\Core\Entity\User;
+use Drupal\Core\TypedData\ContextAwareInterface;
+use Drupal\Core\TypedData\ContextAwareTypedData;
+use Drupal\Core\TypedData\TypedDataInterface;
 use ArrayIterator;
 use IteratorAggregate;
 use InvalidArgumentException;
@@ -26,21 +27,7 @@
  *
  * @see \Drupal\Core\Entity\Field\FieldInterface
  */
-class Field extends TypedData implements IteratorAggregate, FieldInterface {
-
-  /**
-   * The entity field name.
-   *
-   * @var string
-   */
-  protected $name;
-
-  /**
-   * The parent entity.
-   *
-   * @var \Drupal\Core\Entity\EntityInterface
-   */
-  protected $parent;
+class Field extends ContextAwareTypedData implements IteratorAggregate, FieldInterface {
 
   /**
    * Numerically indexed array of field items, implementing the
@@ -51,21 +38,33 @@ class Field extends TypedData implements IteratorAggregate, FieldInterface {
   protected $list = array();
 
   /**
-   * Flag to indicate if this field has been set.
-   *
-   * @var bool
+   * Overrides ContextAwareTypedData::__construct().
    */
-  protected $isset = FALSE;
+  public function __construct(array $definition, $name = NULL, ContextAwareInterface $parent = NULL) {
+    parent::__construct($definition, $name, $parent);
+    // Always initialize one empty item as usually that will be needed. That
+    // way prototypes created by
+    // \Drupal\Core\TypedData\TypedDataManager::getPropertyInstance() will
+    // already have one field item ready for use after cloning.
+    $this->list[0] = $this->createItem(0);
+  }
 
   /**
    * Implements TypedDataInterface::getValue().
    */
   public function getValue() {
-    $values = array();
-    foreach ($this->list as $delta => $item) {
-      $values[$delta] = !$item->isEmpty() ? $item->getValue() : NULL;
+    if (isset($this->list)) {
+      $values = array();
+      foreach ($this->list as $delta => $item) {
+        if (!$item->isEmpty()) {
+          $values[$delta] = $item->getValue();
+        }
+        else {
+          $values[$delta] = NULL;
+        }
+      }
+      return $values;
     }
-    return $values;
   }
 
   /**
@@ -75,19 +74,18 @@ public function getValue() {
    *   An array of values of the field items.
    */
   public function setValue($values) {
-    $this->isset = TRUE;
-    if (isset($values) && $values !== array()) {
+    if (!isset($values) || $values === array()) {
+      $this->list = $values;
+    }
+    else {
       // Support passing in only the value of the first item.
       if (!is_array($values) || !is_numeric(current(array_keys($values)))) {
         $values = array(0 => $values);
       }
 
-      if (!is_array($values)) {
-        throw new InvalidArgumentException("An entity field requires a numerically indexed array of items as value.");
-      }
       // Clear the values of properties for which no value has been passed.
-      foreach (array_diff_key($this->list, $values) as $delta => $item) {
-        unset($this->list[$delta]);
+      if (isset($this->list)) {
+        $this->list = array_intersect_key($this->list, $values);
       }
 
       // Set the values.
@@ -96,24 +94,13 @@ public function setValue($values) {
           throw new InvalidArgumentException('Unable to set a value with a non-numeric delta in a list.');
         }
         elseif (!isset($this->list[$delta])) {
-          $this->list[$delta] = $this->createItem($value);
+          $this->list[$delta] = $this->createItem($delta, $value);
         }
         else {
           $this->list[$delta]->setValue($value);
         }
       }
     }
-    else {
-      $this->list = array();
-    }
-  }
-
-  /**
-   * Mark this field as not set.
-   */
-  public function unsetValue() {
-    $this->list = array();
-    $this->isset = FALSE;
   }
 
   /**
@@ -123,10 +110,12 @@ public function unsetValue() {
    */
   public function getString() {
     $strings = array();
-    foreach ($this->list() as $item) {
-      $strings[] = $item->getString();
+    if (isset($this->list)) {
+      foreach ($this->list() as $item) {
+        $strings[] = $item->getString();
+      }
+      return implode(', ', array_filter($strings));
     }
-    return implode(', ', array_filter($strings));
   }
 
   /**
@@ -140,14 +129,16 @@ public function validate() {
    * Implements ArrayAccess::offsetExists().
    */
   public function offsetExists($offset) {
-    return array_key_exists($offset, $this->list);
+    return isset($this->list) && array_key_exists($offset, $this->list);
   }
 
   /**
    * Implements ArrayAccess::offsetUnset().
    */
   public function offsetUnset($offset) {
-    unset($this->list[$offset]);
+    if (isset($this->list)) {
+      unset($this->list[$offset]);
+    }
   }
 
   /**
@@ -160,7 +151,7 @@ public function offsetGet($offset) {
     // Allow getting not yet existing items as well.
     // @todo: Maybe add a public createItem() method in addition?
     elseif (!isset($this->list[$offset])) {
-      $this->list[$offset] = $this->createItem();
+      $this->list[$offset] = $this->createItem($offset);
     }
     return $this->list[$offset];
   }
@@ -170,9 +161,15 @@ public function offsetGet($offset) {
    *
    * @return \Drupal\Core\TypedData\TypedDataInterface
    */
-  protected function createItem($value = NULL) {
-    $context = array('parent' => $this);
-    return typed_data()->create(array('list' => FALSE) + $this->definition, $value, $context);
+  protected function createItem($offset = 0, $value = NULL) {
+    return typed_data()->getPropertyInstance($this, $offset, $value);
+  }
+
+  /**
+   * Implements ListInterface::getItemDefinition().
+   */
+  public function getItemDefinition() {
+    return array('list' => FALSE) + $this->definition;
   }
 
   /**
@@ -199,44 +196,17 @@ public function offsetSet($offset, $value) {
    * Implements IteratorAggregate::getIterator().
    */
   public function getIterator() {
-    return new ArrayIterator($this->list);
+    if (isset($this->list)) {
+      return new ArrayIterator($this->list);
+    }
+    return new ArrayIterator(array());
   }
 
   /**
    * Implements Countable::count().
    */
   public function count() {
-    return count($this->list);
-  }
-
-  /**
-   * Implements ContextAwareInterface::getName().
-   */
-  public function getName() {
-    return $this->name;
-  }
-
-  /**
-   * Implements ContextAwareInterface::setName().
-   */
-  public function setName($name) {
-    $this->name = $name;
-  }
-
-  /**
-   * Implements ContextAwareInterface::getParent().
-   *
-   * @return \Drupal\Core\Entity\EntityInterface
-   */
-  public function getParent() {
-    return $this->parent;
-  }
-
-  /**
-   * Implements ContextAwareInterface::setParent().
-   */
-  public function setParent($parent) {
-    $this->parent = $parent;
+    return isset($this->list) ? count($this->list) : 0;
   }
 
   /**
@@ -257,7 +227,7 @@ public function getPropertyDefinitions() {
    * Delegate.
    */
   public function __get($property_name) {
-    return $this->offsetGet(0)->__get($property_name);
+    return $this->offsetGet(0)->get($property_name)->getValue();
   }
 
   /**
@@ -272,14 +242,13 @@ public function get($property_name) {
    */
   public function __set($property_name, $value) {
     $this->offsetGet(0)->__set($property_name, $value);
-    $this->isset = TRUE;
   }
 
   /**
    * Delegate.
    */
   public function __isset($property_name) {
-    return $this->isset && $this->offsetGet(0)->__isset($property_name);
+    return $this->offsetGet(0)->__isset($property_name);
   }
 
   /**
@@ -293,29 +262,27 @@ public function __unset($property_name) {
    * Implements ListInterface::isEmpty().
    */
   public function isEmpty() {
-    foreach ($this->list as $item) {
-      if (!$item->isEmpty()) {
-        return FALSE;
+    if (isset($this->list)) {
+      foreach ($this->list as $item) {
+        if (!$item->isEmpty()) {
+          return FALSE;
+        }
       }
     }
     return TRUE;
   }
 
   /**
-   * Determines if this field has been set.
-   *
-   * @return bool
-   */
-  public function valueIsSet() {
-    return $this->isset;
-  }
-
-  /**
    * Implements a deep clone.
    */
   public function __clone() {
-    foreach ($this->list as $delta => $property) {
-      $this->list[$delta] = clone $property;
+    if (isset($this->list)) {
+      foreach ($this->list as $delta => $property) {
+        $this->list[$delta] = clone $property;
+        if ($property instanceof ContextAwareInterface) {
+          $this->list[$delta]->setContext($delta, $this);
+        }
+      }
     }
   }
 
diff --git a/core/lib/Drupal/Core/Entity/Field/Type/IntegerItem.php b/core/lib/Drupal/Core/Entity/Field/Type/IntegerItem.php
index 1f4b4e6..2d1585f 100644
--- a/core/lib/Drupal/Core/Entity/Field/Type/IntegerItem.php
+++ b/core/lib/Drupal/Core/Entity/Field/Type/IntegerItem.php
@@ -15,7 +15,7 @@
 class IntegerItem extends FieldItemBase {
 
   /**
-   * Field definitions of the contained properties.
+   * Definitions of the contained properties.
    *
    * @see self::getPropertyDefinitions()
    *
diff --git a/core/lib/Drupal/Core/Entity/Field/Type/LanguageItem.php b/core/lib/Drupal/Core/Entity/Field/Type/LanguageItem.php
index f7b2a91..a6e548e 100644
--- a/core/lib/Drupal/Core/Entity/Field/Type/LanguageItem.php
+++ b/core/lib/Drupal/Core/Entity/Field/Type/LanguageItem.php
@@ -16,9 +16,9 @@
 class LanguageItem extends FieldItemBase {
 
   /**
-   * Array of property definitions of contained properties.
+   * Definitions of the contained properties.
    *
-   * @see PropertyEntityReferenceItem::getPropertyDefinitions()
+   * @see self::getPropertyDefinitions()
    *
    * @var array
    */
@@ -61,8 +61,11 @@ public function setValue($values) {
     if (!empty($values['value'])) {
       $this->properties['value']->setValue($values['value']);
     }
+    elseif (isset($values['language'])) {
+      $this->properties['language']->setValue($values['language']);
+    }
     else {
-      $this->properties['language']->setValue(isset($values['language']) ? $values['language'] : NULL);
+      $this->properties['language']->setValue(NULL);
     }
     unset($values['language'], $values['value']);
     if ($values) {
diff --git a/core/lib/Drupal/Core/Entity/Field/Type/StringItem.php b/core/lib/Drupal/Core/Entity/Field/Type/StringItem.php
index 7c8c57a..6d98a52 100644
--- a/core/lib/Drupal/Core/Entity/Field/Type/StringItem.php
+++ b/core/lib/Drupal/Core/Entity/Field/Type/StringItem.php
@@ -15,7 +15,7 @@
 class StringItem extends FieldItemBase {
 
   /**
-   * Field definitions of the contained properties.
+   * Definitions of the contained properties.
    *
    * @see self::getPropertyDefinitions()
    *
diff --git a/core/lib/Drupal/Core/TypedData/ComplexDataInterface.php b/core/lib/Drupal/Core/TypedData/ComplexDataInterface.php
index 71364ce..d6bffc6 100644
--- a/core/lib/Drupal/Core/TypedData/ComplexDataInterface.php
+++ b/core/lib/Drupal/Core/TypedData/ComplexDataInterface.php
@@ -12,6 +12,9 @@
 /**
  * Interface for complex data; i.e. data containing named and typed properties.
  *
+ * The name of a property has to be a valid PHP variable name, starting with
+ * an alphabetic character.
+ *
  * This is implemented by entities as well as by field item classes of
  * entities.
  *
diff --git a/core/lib/Drupal/Core/TypedData/ContextAwareInterface.php b/core/lib/Drupal/Core/TypedData/ContextAwareInterface.php
index 41c3031..d2b2d3b 100644
--- a/core/lib/Drupal/Core/TypedData/ContextAwareInterface.php
+++ b/core/lib/Drupal/Core/TypedData/ContextAwareInterface.php
@@ -2,7 +2,7 @@
 
 /**
  * @file
- * Definition of Drupal\Core\TypedData\ContextAwareInterface.
+ * Contains \Drupal\Core\TypedData\ContextAwareInterface.
  */
 
 namespace Drupal\Core\TypedData;
@@ -23,36 +23,48 @@
   public function getName();
 
   /**
-   * Sets the name of a property or item.
+   * Returns the parent data structure; i.e. either complex data or a list.
    *
-   * This method is supposed to be used by the parental data structure in order
-   * to provide appropriate context only.
+   * @return \Drupal\Core\TypedData\ComplexDataInterface|\Drupal\Core\TypedData\ListInterface
+   *   The parent data structure, either complex data or a list; or NULL if this
+   *   is the root of the typed data tree.
+   */
+  public function getParent();
+
+  /**
+   * Returns the root of the typed data tree.
    *
-   * @param string $name
-   *   The name to set for a property or item.
+   * Returns the root data for a tree of typed data objects; e.g. for an entity
+   * field item the root of the tree is its parent entity object.
    *
-   * @see ContextAwareInterface::getName()
+   * @return \Drupal\Core\TypedData\ComplexDataInterface|\Drupal\Core\TypedData\ListInterface
+   *   The root data structure, either complex data or a list.
    */
-  public function setName($name);
+  public function getRoot();
 
   /**
-   * Returns the parent data structure; i.e. either complex data or a list.
+   * Returns the property path of the data.
+   *
+   * The trail of property names relative to the root of the typed data tree,
+   * separated by dots; e.g. 'field_text.0.format'.
    *
-   * @return Drupal\Core\TypedData\ComplexDataInterface|Drupal\Core\TypedData\ListInterface
-   *   The parent data structure; either complex data or a list.
+   * @return string
+   *   The property path relative to the root of the typed tree, or an empty
+   *   string if this is the root.
    */
-  public function getParent();
+  public function getPropertyPath();
 
   /**
-   * Sets the parent of a property or item.
-   *
-   * This method is supposed to be used by the parental data structure in order
-   * to provide appropriate context only.
+   * Sets the context of a property or item via a context aware parent.
    *
-   * @param mixed $parent
-   *   The parent data structure; either complex data or a list.
+   * This method is supposed to be called by the factory only.
    *
-   * @see ContextAwareInterface::getParent()
+   * @param string $name
+   *   (optional) The name of the property or the delta of the list item,
+   *   or NULL if it is the root of a typed data tree. Defaults to NULL.
+   * @param \Drupal\Core\TypedData\ContextAwareInterface $parent
+   *   (optional) The parent object of the data property, or NULL if it is the
+   *   root of a typed data tree. Defaults to NULL.
    */
-  public function setParent($parent);
+  public function setContext($name = NULL, ContextAwareInterface $parent = NULL);
 }
diff --git a/core/lib/Drupal/Core/TypedData/ContextAwareTypedData.php b/core/lib/Drupal/Core/TypedData/ContextAwareTypedData.php
new file mode 100644
index 0000000..e713324
--- /dev/null
+++ b/core/lib/Drupal/Core/TypedData/ContextAwareTypedData.php
@@ -0,0 +1,109 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\TypedData\ContextAwareTypedData.
+ */
+
+namespace Drupal\Core\TypedData;
+
+/**
+ * An abstract base class for context aware typed data.
+ *
+ * This implementation requires parent typed data objects to implement the
+ * ContextAwareInterface also, such that the context can be derived from the
+ * parents.
+ *
+ * Classes deriving from this base class have to declare $value
+ * or override getValue() or setValue().
+ */
+abstract class ContextAwareTypedData extends TypedData implements ContextAwareInterface {
+
+  /**
+   * The property name.
+   *
+   * @var string
+   */
+  protected $name;
+
+  /**
+   * The parent typed data object.
+   *
+   * @var \Drupal\Core\TypedData\ContextAwareInterface
+   */
+  protected $parent;
+
+  /**
+   * Constructs a TypedData object given its definition and context.
+   *
+   * @param array $definition
+   *   The data definition.
+   * @param string $name
+   *   (optional) The name of the created property, or NULL if it is the root
+   *   of a typed data tree. Defaults to NULL.
+   * @param \Drupal\Core\TypedData\ContextAwareInterface $parent
+   *   (optional) The parent object of the data property, or NULL if it is the
+   *   root of a typed data tree. Defaults to NULL.
+   *
+   * @see Drupal\Core\TypedData\TypedDataManager::create()
+   */
+  public function __construct(array $definition, $name = NULL, ContextAwareInterface $parent = NULL) {
+    $this->definition = $definition;
+    $this->setContext($name, $parent);
+  }
+
+  /**
+   * Implements ContextAwareInterface::setContext().
+   */
+  public function setContext($name = NULL, ContextAwareInterface $parent = NULL) {
+    $this->parent = $parent;
+    $this->name = $name;
+  }
+
+  /**
+   * Implements ContextAwareInterface::getName().
+   */
+  public function getName() {
+    return $this->name;
+  }
+
+  /**
+   * Implements ContextAwareInterface::getRoot().
+   */
+  public function getRoot() {
+    if (isset($this->parent)) {
+      return $this->parent->getRoot();
+    }
+    return $this;
+  }
+
+  /**
+   * Implements ContextAwareInterface::getPropertyPath().
+   */
+  public function getPropertyPath() {
+    if (isset($this->parent)) {
+      $prefix = $this->parent->getPropertyPath();
+      return (strlen($prefix) ? $prefix . '.' : '') . $this->name;
+    }
+    elseif (isset($this->name)) {
+      return $this->name;
+    }
+    return '';
+  }
+
+  /**
+   * Implements ContextAwareInterface::getParent().
+   *
+   * @return \Drupal\Core\Entity\Field\FieldInterface
+   */
+  public function getParent() {
+    return $this->parent;
+  }
+
+  /**
+   * Implements TypedDataInterface::validate().
+   */
+  public function validate() {
+    // @todo: Implement validate() method.
+  }
+}
diff --git a/core/lib/Drupal/Core/TypedData/ListInterface.php b/core/lib/Drupal/Core/TypedData/ListInterface.php
index 4ce6af0..f6f906b 100644
--- a/core/lib/Drupal/Core/TypedData/ListInterface.php
+++ b/core/lib/Drupal/Core/TypedData/ListInterface.php
@@ -2,7 +2,7 @@
 
 /**
  * @file
- * Definition of Drupal\Core\TypedData\ListInterface.
+ * Contains \Drupal\Core\TypedData\ListInterface.
  */
 
 namespace Drupal\Core\TypedData;
@@ -29,4 +29,12 @@
    *   TRUE if the list is empty, FALSE otherwise.
    */
   public function isEmpty();
+
+  /**
+   * Gets the definition of a contained item.
+   *
+   * @return array
+   *   The data definition of contained items.
+   */
+  public function getItemDefinition();
 }
diff --git a/core/lib/Drupal/Core/TypedData/Type/Binary.php b/core/lib/Drupal/Core/TypedData/Type/Binary.php
index 7ec5e6b..303b71c 100644
--- a/core/lib/Drupal/Core/TypedData/Type/Binary.php
+++ b/core/lib/Drupal/Core/TypedData/Type/Binary.php
@@ -7,7 +7,7 @@
 
 namespace Drupal\Core\TypedData\Type;
 
-use Drupal\Core\TypedData\TypedDataInterface;
+use Drupal\Core\TypedData\TypedData;
 use InvalidArgumentException;
 
 /**
@@ -17,7 +17,7 @@
  * http://php.net/manual/en/language.types.resource.php. For setting the value
  * a PHP file resource or a (absolute) stream resource URI may be passed.
  */
-class Binary extends TypedData implements TypedDataInterface {
+class Binary extends TypedData {
 
   /**
    * The file resource URI.
diff --git a/core/lib/Drupal/Core/TypedData/Type/Boolean.php b/core/lib/Drupal/Core/TypedData/Type/Boolean.php
index 5714599..c8797ef 100644
--- a/core/lib/Drupal/Core/TypedData/Type/Boolean.php
+++ b/core/lib/Drupal/Core/TypedData/Type/Boolean.php
@@ -7,7 +7,7 @@
 
 namespace Drupal\Core\TypedData\Type;
 
-use Drupal\Core\TypedData\TypedDataInterface;
+use Drupal\Core\TypedData\TypedData;
 
 /**
  * The boolean data type.
@@ -15,7 +15,7 @@
  * The plain value of a boolean is a regular PHP boolean. For setting the value
  * any PHP variable that casts to a boolean may be passed.
  */
-class Boolean extends TypedData implements TypedDataInterface {
+class Boolean extends TypedData {
 
   /**
    * The data value.
diff --git a/core/lib/Drupal/Core/TypedData/Type/Date.php b/core/lib/Drupal/Core/TypedData/Type/Date.php
index 3c0f3a9..a534280 100644
--- a/core/lib/Drupal/Core/TypedData/Type/Date.php
+++ b/core/lib/Drupal/Core/TypedData/Type/Date.php
@@ -8,7 +8,7 @@
 namespace Drupal\Core\TypedData\Type;
 
 use Drupal\Core\Datetime\DrupalDateTime;
-use Drupal\Core\TypedData\TypedDataInterface;
+use Drupal\Core\TypedData\TypedData;
 use InvalidArgumentException;
 
 /**
@@ -19,7 +19,7 @@
  * class will work, including a DateTime object, a timestamp, a string
  * date, or an array of date parts.
  */
-class Date extends TypedData implements TypedDataInterface {
+class Date extends TypedData {
 
   /**
    * The data value.
diff --git a/core/lib/Drupal/Core/TypedData/Type/Duration.php b/core/lib/Drupal/Core/TypedData/Type/Duration.php
index 9fd8ceb..d979dcf 100644
--- a/core/lib/Drupal/Core/TypedData/Type/Duration.php
+++ b/core/lib/Drupal/Core/TypedData/Type/Duration.php
@@ -7,7 +7,7 @@
 
 namespace Drupal\Core\TypedData\Type;
 
-use Drupal\Core\TypedData\TypedDataInterface;
+use Drupal\Core\TypedData\TypedData;
 use DateInterval;
 use InvalidArgumentException;
 
@@ -19,7 +19,7 @@
  * supported by DateInterval::__construct, or an integer in seconds may be
  * passed.
  */
-class Duration extends TypedData implements TypedDataInterface {
+class Duration extends TypedData {
 
   /**
    * The data value.
diff --git a/core/lib/Drupal/Core/TypedData/Type/Float.php b/core/lib/Drupal/Core/TypedData/Type/Float.php
index 798499c..3e8369b 100644
--- a/core/lib/Drupal/Core/TypedData/Type/Float.php
+++ b/core/lib/Drupal/Core/TypedData/Type/Float.php
@@ -7,7 +7,7 @@
 
 namespace Drupal\Core\TypedData\Type;
 
-use Drupal\Core\TypedData\TypedDataInterface;
+use Drupal\Core\TypedData\TypedData;
 
 /**
  * The float data type.
@@ -15,7 +15,7 @@
  * The plain value of a float is a regular PHP float. For setting the value
  * any PHP variable that casts to a float may be passed.
  */
-class Float extends TypedData implements TypedDataInterface {
+class Float extends TypedData {
 
   /**
    * The data value.
diff --git a/core/lib/Drupal/Core/TypedData/Type/Integer.php b/core/lib/Drupal/Core/TypedData/Type/Integer.php
index 4e9b59a..4303511 100644
--- a/core/lib/Drupal/Core/TypedData/Type/Integer.php
+++ b/core/lib/Drupal/Core/TypedData/Type/Integer.php
@@ -7,7 +7,7 @@
 
 namespace Drupal\Core\TypedData\Type;
 
-use Drupal\Core\TypedData\TypedDataInterface;
+use Drupal\Core\TypedData\TypedData;
 
 /**
  * The integer data type.
@@ -15,7 +15,7 @@
  * The plain value of an integer is a regular PHP integer. For setting the value
  * any PHP variable that casts to an integer may be passed.
  */
-class Integer extends TypedData implements TypedDataInterface {
+class Integer extends TypedData {
 
   /**
    * The data value.
diff --git a/core/lib/Drupal/Core/TypedData/Type/Language.php b/core/lib/Drupal/Core/TypedData/Type/Language.php
index 67f4df8..50ae4b8 100644
--- a/core/lib/Drupal/Core/TypedData/Type/Language.php
+++ b/core/lib/Drupal/Core/TypedData/Type/Language.php
@@ -7,9 +7,8 @@
 
 namespace Drupal\Core\TypedData\Type;
 
-use Drupal\Core\TypedData\ContextAwareInterface;
-use Drupal\Core\TypedData\TypedDataInterface;
 use InvalidArgumentException;
+use Drupal\Core\TypedData\ContextAwareTypedData;
 
 /**
  * Defines the 'language' data type.
@@ -25,21 +24,7 @@
  *  - langcode source: If used as computed property, the langcode property used
  *    to load the language object.
  */
-class Language extends TypedData implements TypedDataInterface, ContextAwareInterface {
-
-  /**
-   * The name.
-   *
-   * @var string
-   */
-  protected $name;
-
-  /**
-   * The parent data structure.
-   *
-   * @var mixed
-   */
-  protected $parent;
+class Language extends ContextAwareTypedData {
 
   /**
    * The language code of the language if no 'langcode source' is used.
@@ -49,40 +34,14 @@ class Language extends TypedData implements TypedDataInterface, ContextAwareInte
   protected $langcode;
 
   /**
-   * Implements ContextAwareInterface::getName().
-   */
-  public function getName() {
-    return $this->name;
-  }
-
-  /**
-   * Implements ContextAwareInterface::setName().
-   */
-  public function setName($name) {
-    $this->name = $name;
-  }
-
-  /**
-   * Implements ContextAwareInterface::getParent().
-   */
-  public function getParent() {
-    return $this->parent;
-  }
-
-  /**
-   * Implements ContextAwareInterface::setParent().
-   */
-  public function setParent($parent) {
-    $this->parent = $parent;
-  }
-
-  /**
    * Implements TypedDataInterface::getValue().
    */
   public function getValue() {
     $source = $this->getLanguageCodeSource();
     $langcode = $source ? $source->getValue() : $this->langcode;
-    return $langcode ? language_load($langcode) : NULL;
+    if ($langcode) {
+      return language_load($langcode);
+    }
   }
 
   /**
diff --git a/core/lib/Drupal/Core/TypedData/Type/String.php b/core/lib/Drupal/Core/TypedData/Type/String.php
index fef3248..9248239 100644
--- a/core/lib/Drupal/Core/TypedData/Type/String.php
+++ b/core/lib/Drupal/Core/TypedData/Type/String.php
@@ -7,7 +7,7 @@
 
 namespace Drupal\Core\TypedData\Type;
 
-use Drupal\Core\TypedData\TypedDataInterface;
+use Drupal\Core\TypedData\TypedData;
 
 /**
  * The string data type.
@@ -15,7 +15,7 @@
  * The plain value of a string is a regular PHP string. For setting the value
  * any PHP variable that casts to a string may be passed.
  */
-class String extends TypedData implements TypedDataInterface {
+class String extends TypedData {
 
   /**
    * The data value.
diff --git a/core/lib/Drupal/Core/TypedData/Type/TypedData.php b/core/lib/Drupal/Core/TypedData/Type/TypedData.php
deleted file mode 100644
index 1e70c53..0000000
--- a/core/lib/Drupal/Core/TypedData/Type/TypedData.php
+++ /dev/null
@@ -1,73 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\Core\TypedData\Type\TypedData.
- */
-
-namespace Drupal\Core\TypedData\Type;
-
-use Drupal\Core\TypedData\TypedDataInterface;
-
-/**
- * The abstract base class for typed data.
- *
- * Classes deriving from this base class have to declare $value
- * or override getValue() or setValue().
- */
-abstract class TypedData implements TypedDataInterface {
-
-  /**
-   * The data definition.
-   *
-   * @var array
-   */
-  protected $definition;
-
-  /**
-   * Constructs a TypedData object given its definition.
-   *
-   * @param array $definition
-   *   The data definition.
-   *
-   * @see Drupal\Core\TypedData\TypedDataManager::create()
-   */
-  public function __construct(array $definition) {
-    $this->definition = $definition;
-  }
-
-  /**
-   * Implements TypedDataInterface::getType().
-   */
-  public function getType() {
-    return $this->definition['type'];
-  }
-
-  /**
-   * Implements TypedDataInterface::getDefinition().
-   */
-  public function getDefinition() {
-    return $this->definition;
-  }
-
-  /**
-   * Implements TypedDataInterface::getValue().
-   */
-  public function getValue() {
-    return $this->value;
-  }
-
-  /**
-   * Implements TypedDataInterface::setValue().
-   */
-  public function setValue($value) {
-    $this->value = $value;
-  }
-
-  /**
-   * Implements TypedDataInterface::getString().
-   */
-  public function getString() {
-    return (string) $this->getValue();
-  }
-}
diff --git a/core/lib/Drupal/Core/TypedData/Type/Uri.php b/core/lib/Drupal/Core/TypedData/Type/Uri.php
index 010fa03..52b9c3f 100644
--- a/core/lib/Drupal/Core/TypedData/Type/Uri.php
+++ b/core/lib/Drupal/Core/TypedData/Type/Uri.php
@@ -7,14 +7,14 @@
 
 namespace Drupal\Core\TypedData\Type;
 
-use Drupal\Core\TypedData\TypedDataInterface;
+use Drupal\Core\TypedData\TypedData;
 
 /**
  * The URI data type.
  *
  * The plain value of a URI is an absolute URI represented as PHP string.
  */
-class Uri extends TypedData implements TypedDataInterface {
+class Uri extends TypedData {
 
   /**
    * The data value.
diff --git a/core/lib/Drupal/Core/TypedData/TypedData.php b/core/lib/Drupal/Core/TypedData/TypedData.php
new file mode 100644
index 0000000..053bb70
--- /dev/null
+++ b/core/lib/Drupal/Core/TypedData/TypedData.php
@@ -0,0 +1,71 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\TypedData\TypedData.
+ */
+
+namespace Drupal\Core\TypedData;
+
+/**
+ * The abstract base class for typed data.
+ *
+ * Classes deriving from this base class have to declare $value
+ * or override getValue() or setValue().
+ */
+abstract class TypedData implements TypedDataInterface {
+
+  /**
+   * The data definition.
+   *
+   * @var array
+   */
+  protected $definition;
+
+  /**
+   * Constructs a TypedData object given its definition.
+   *
+   * @param array $definition
+   *   The data definition.
+   *
+   * @see Drupal\Core\TypedData\TypedDataManager::create()
+   */
+  public function __construct(array $definition) {
+    $this->definition = $definition;
+  }
+
+  /**
+   * Implements TypedDataInterface::getType().
+   */
+  public function getType() {
+    return $this->definition['type'];
+  }
+
+  /**
+   * Implements TypedDataInterface::getDefinition().
+   */
+  public function getDefinition() {
+    return $this->definition;
+  }
+
+  /**
+   * Implements TypedDataInterface::getValue().
+   */
+  public function getValue() {
+    return $this->value;
+  }
+
+  /**
+   * Implements TypedDataInterface::setValue().
+   */
+  public function setValue($value) {
+    $this->value = $value;
+  }
+
+  /**
+   * Implements TypedDataInterface::getString().
+   */
+  public function getString() {
+    return (string) $this->getValue();
+  }
+}
diff --git a/core/lib/Drupal/Core/TypedData/TypedDataFactory.php b/core/lib/Drupal/Core/TypedData/TypedDataFactory.php
index d245157..14b05d6 100644
--- a/core/lib/Drupal/Core/TypedData/TypedDataFactory.php
+++ b/core/lib/Drupal/Core/TypedData/TypedDataFactory.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\Core\TypedData;
 
+use InvalidArgumentException;
 use Drupal\Component\Plugin\Factory\DefaultFactory;
 use Drupal\Component\Plugin\Exception\PluginException;
 
@@ -25,28 +26,35 @@ class TypedDataFactory extends DefaultFactory {
    *   The id of a plugin, i.e. the data type.
    * @param array $configuration
    *   The plugin configuration, i.e. the data definition.
+   * @param string $name
+   *   (optional) If a property or list item is to be created, the name of the
+   *   property or the delta of the list item.
+   * @param mixed $parent
+   *   (optional) If a property or list item is to be created, the parent typed
+   *   data object implementing either the ListInterface or the
+   *   ComplexDataInterface.
    *
-   * @return Drupal\Core\TypedData\TypedDataInterface
+   * @return \Drupal\Core\TypedData\TypedDataInterface
    */
-  public function createInstance($plugin_id, array $configuration) {
+  public function createInstance($plugin_id, array $configuration, $name = NULL, $parent = NULL) {
     $type_definition = $this->discovery->getDefinition($plugin_id);
 
-    // Allow per-data definition overrides of the used classes and generally
-    // default to the data type definition.
-    $definition = $configuration + $type_definition;
+    if (!isset($type_definition)) {
+      throw new InvalidArgumentException(format_string('Invalid data type %plugin_id has been given.', array('%plugin_id' => $plugin_id)));
+    }
 
-    if (empty($definition['list'])) {
-      if (empty($definition['class'])) {
-        throw new PluginException(sprintf('The plugin (%s) did not specify an instance class.', $plugin_id));
-      }
-      $plugin_class = $definition['class'];
+    // Allow per-data definition overrides of the used classes.
+    $key = empty($configuration['list']) ? 'class' : 'list class';
+    if (isset($configuration[$key])) {
+      $class = $configuration[$key];
+    }
+    elseif (isset($type_definition[$key])) {
+      $class = $type_definition[$key];
     }
-    else {
-      if (empty($definition['list class'])) {
-        throw new PluginException(sprintf('The plugin (%s) did not specify a list instance class.', $plugin_id));
-      }
-      $plugin_class = $definition['list class'];
+
+    if (!isset($class)) {
+      throw new PluginException(sprintf('The plugin (%s) did not specify an instance class.', $plugin_id));
     }
-    return new $plugin_class($definition, $plugin_id, $this->discovery);
+    return new $class($configuration, $name, $parent);
   }
 }
diff --git a/core/lib/Drupal/Core/TypedData/TypedDataManager.php b/core/lib/Drupal/Core/TypedData/TypedDataManager.php
index a1522d8..91367ad 100644
--- a/core/lib/Drupal/Core/TypedData/TypedDataManager.php
+++ b/core/lib/Drupal/Core/TypedData/TypedDataManager.php
@@ -2,11 +2,12 @@
 
 /**
  * @file
- * Definition of Drupal\Core\TypedData\TypedDataManager.
+ * Contains \Drupal\Core\TypedData\TypedDataManager.
  */
 
 namespace Drupal\Core\TypedData;
 
+use InvalidArgumentException;
 use Drupal\Component\Plugin\PluginManagerBase;
 use Drupal\Core\Plugin\Discovery\CacheDecorator;
 use Drupal\Core\Plugin\Discovery\HookDiscovery;
@@ -16,6 +17,13 @@
  */
 class TypedDataManager extends PluginManagerBase {
 
+  /**
+   * An array of typed data property prototypes.
+   *
+   * @var array
+   */
+  protected $prototypes = array();
+
   public function __construct() {
     $this->discovery = new CacheDecorator(new HookDiscovery('data_type_info'), 'typed_data:types');
     $this->factory = new TypedDataFactory($this->discovery);
@@ -28,11 +36,18 @@ public function __construct() {
    *   The id of a plugin, i.e. the data type.
    * @param array $configuration
    *   The plugin configuration, i.e. the data definition.
+   * @param string $name
+   *   (optional) If a property or list item is to be created, the name of the
+   *   property or the delta of the list item.
+   * @param mixed $parent
+   *   (optional) If a property or list item is to be created, the parent typed
+   *   data object implementing either the ListInterface or the
+   *   ComplexDataInterface.
    *
-   * @return Drupal\Core\TypedData\TypedDataInterface
+   * @return \Drupal\Core\TypedData\TypedDataInterface
    */
-  public function createInstance($plugin_id, array $configuration) {
-    return $this->factory->createInstance($plugin_id, $configuration);
+  public function createInstance($plugin_id, array $configuration, $name = NULL, $parent = NULL) {
+    return $this->factory->createInstance($plugin_id, $configuration, $name, $parent);
   }
 
   /**
@@ -70,42 +85,126 @@ public function createInstance($plugin_id, array $configuration) {
    * @param mixed $value
    *   (optional) The data value. If set, it has to match one of the supported
    *   data type format as documented for the data type classes.
-   * @param array $context
-   *   (optional) An array describing the context of the data object, e.g. its
-   *   name or parent data structure. The context should be passed if a typed
-   *   data object is created as part of a data structure. The following keys
-   *   are supported:
-   *   - name: The name associated with the data.
-   *   - parent: The parent object containing the data. Must be an instance of
-   *     Drupal\Core\TypedData\ComplexDataInterface or
-   *     Drupal\Core\TypedData\ListInterface.
+   * @param string $name
+   *   (optional) If a property or list item is to be created, the name of the
+   *   property or the delta of the list item.
+   * @param mixed $parent
+   *   (optional) If a property or list item is to be created, the parent typed
+   *   data object implementing either the ListInterface or the
+   *   ComplexDataInterface.
    *
-   * @return Drupal\Core\TypedData\TypedDataInterface
+   * @return \Drupal\Core\TypedData\TypedDataInterface
    *
    * @see typed_data()
-   * @see Drupal\Core\TypedData\Type\Integer
-   * @see Drupal\Core\TypedData\Type\Float
-   * @see Drupal\Core\TypedData\Type\String
-   * @see Drupal\Core\TypedData\Type\Boolean
-   * @see Drupal\Core\TypedData\Type\Duration
-   * @see Drupal\Core\TypedData\Type\Date
-   * @see Drupal\Core\TypedData\Type\Uri
-   * @see Drupal\Core\TypedData\Type\Binary
-   * @see Drupal\Core\Entity\Field\EntityWrapper
+   * @see \Drupal\Core\TypedData\TypedDataManager::getPropertyInstance()
+   * @see \Drupal\Core\TypedData\Type\Integer
+   * @see \Drupal\Core\TypedData\Type\Float
+   * @see \Drupal\Core\TypedData\Type\String
+   * @see \Drupal\Core\TypedData\Type\Boolean
+   * @see \Drupal\Core\TypedData\Type\Duration
+   * @see \Drupal\Core\TypedData\Type\Date
+   * @see \Drupal\Core\TypedData\Type\Uri
+   * @see \Drupal\Core\TypedData\Type\Binary
+   * @see \Drupal\Core\Entity\Field\EntityWrapper
    */
-  function create(array $definition, $value = NULL, array $context = array()) {
-    $wrapper = $this->createInstance($definition['type'], $definition);
+  public function create(array $definition, $value = NULL, $name = NULL, $parent = NULL) {
+    $wrapper = $this->factory->createInstance($definition['type'], $definition, $name, $parent);
     if (isset($value)) {
       $wrapper->setValue($value);
     }
-    if ($wrapper instanceof ContextAwareInterface) {
-      if (isset($context['name'])) {
-        $wrapper->setName($context['name']);
+    return $wrapper;
+  }
+
+  /**
+   * Implements \Drupal\Component\Plugin\PluginManagerInterface::getInstance().
+   *
+   * @param array $options
+   *   An array of options with the following keys:
+   *   - object: The parent typed data object, implementing the
+   *     ContextAwareInterface and either the ListInterface or the
+   *     ComplexDataInterface.
+   *   - property: The name of the property to instantiate, or the delta of the
+   *     the list item to instantiate.
+   *   - value: The value to set. If set, it has to match one of the supported
+   *     data type formats as documented by the data type classes.
+   *
+   * @throws \InvalidArgumentException
+   *   If the given property is not known, or the passed object does not
+   *   implement the ListInterface or the ComplexDataInterface.
+   *
+   * @return \Drupal\Core\TypedData\TypedDataInterface
+   *   The new property instance.
+   *
+   * @see \Drupal\Core\TypedData\TypedDataManager::getPropertyInstance()
+   */
+  public function getInstance(array $options) {
+    return $this->getPropertyInstance($options['object'], $options['property'], $options['value']);
+  }
+
+  /**
+   * Get a typed data instance for a property of a given typed data object.
+   *
+   * This method will use prototyping for fast and efficient instantiation of
+   * many property objects with the same property path; e.g.,
+   * when multiple comments are used comment_body.0.value needs to be
+   * instantiated very often.
+   * Prototyping is done by the root object's data type and the given
+   * property path, i.e. all property instances having the same property path
+   * and inheriting from the same data type are prototyped.
+   *
+   * @param \Drupal\Core\TypedData\ContextAwareInterface $object
+   *   The parent typed data object, implementing the ContextAwareInterface and
+   *   either the ListInterface or the ComplexDataInterface.
+   * @param string $property_name
+   *   The name of the property to instantiate, or the delta of an list item.
+   * @param mixed $value
+   *   (optional) The data value. If set, it has to match one of the supported
+   *   data type formats as documented by the data type classes.
+   *
+   * @throws \InvalidArgumentException
+   *   If the given property is not known, or the passed object does not
+   *   implement the ListInterface or the ComplexDataInterface.
+   *
+   * @return \Drupal\Core\TypedData\TypedDataInterface
+   *   The new property instance.
+   *
+   * @see \Drupal\Core\TypedData\TypedDataManager::create()
+   */
+  public function getPropertyInstance(ContextAwareInterface $object, $property_name, $value = NULL) {
+    $key = $object->getRoot()->getType() . ':' . $object->getPropertyPath() . '.';
+    // If we are creating list items, we always use 0 in the key as all list
+    // items look the same.
+    $key .= is_numeric($property_name) ? 0 : $property_name;
+
+    // Make sure we have a prototype. Then, clone the prototype and set object
+    // specific values, i.e. the value and the context.
+    if (!isset($this->prototypes[$key])) {
+      if ($object instanceof ComplexDataInterface) {
+        $definition = $object->getPropertyDefinition($property_name);
       }
-      if (isset($context['parent'])) {
-        $wrapper->setParent($context['parent']);
+      elseif ($object instanceof ListInterface) {
+        $definition = $object->getItemDefinition();
       }
+      else {
+        throw new InvalidArgumentException("The passed object has to either implement the ComplexDataInterface or the ListInterface.");
+      }
+      // Make sure we have got a valid definition.
+      if (!$definition) {
+        throw new InvalidArgumentException('Property ' . check_plain($property_name) . ' is unknown.');
+      }
+
+      $this->prototypes[$key] = $this->create($definition, NULL, $property_name, $object);
     }
-    return $wrapper;
+
+    $property = clone $this->prototypes[$key];
+    // Update the parent relationship if necessary.
+    if ($property instanceof ContextAwareInterface) {
+      $property->setContext($property_name, $object);
+    }
+    // Set the passed data value.
+    if (isset($value)) {
+      $property->setValue($value);
+    }
+    return $property;
   }
 }
diff --git a/core/modules/jsonld/lib/Drupal/jsonld/JsonldEntityNormalizer.php b/core/modules/jsonld/lib/Drupal/jsonld/JsonldEntityNormalizer.php
index b35caf1..b286539 100644
--- a/core/modules/jsonld/lib/Drupal/jsonld/JsonldEntityNormalizer.php
+++ b/core/modules/jsonld/lib/Drupal/jsonld/JsonldEntityNormalizer.php
@@ -79,6 +79,14 @@ public function denormalize($data, $class, $format = null) {
       $values['langcode'] = language(LANGUAGE_TYPE_CONTENT)->langcode;
     }
     $entity = entity_create($typed_data_ids['entity_type'], $values);
+    // Make sure all empty entity fields default to NULL, so that afterwards it
+    // is possible to determine which fields were part of the data (even if they
+    // are empty).
+    foreach ($entity as $name => $field) {
+      if ($field->isEmpty()) {
+        $field->setValue(NULL);
+      }
+    }
 
     // For each attribute in the JSON-LD, add the values as fields to the newly
     // created entity. It is assumed that the JSON attribute names are the same
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
index 6e41540..4e3b101 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
@@ -2076,9 +2076,9 @@ protected function createTypedData($definition, $value = NULL, $context = array(
     // Assert the definition of the wrapper.
     $this->assertTrue($data instanceof \Drupal\Core\TypedData\TypedDataInterface, 'Typed data object is an instance of the typed data interface.');
     $definition = $data->getDefinition();
-    $this->assertTrue(!empty($definition['label']), $definition['label'] . ' data definition was returned.');
+    $this->assertTrue(!empty($definition['type']), format_string('!type data definition was returned.', array('!type' => $definition['type'])));
     // Assert that the correct type was constructed.
-    $this->assertEqual($data->getType(), $type, $definition['label'] . ' object returned type.');
+    $this->assertEqual($data->getType(), $type, format_string('!type object returned type.', array('!type' => $definition['type'])));
     return $data;
   }
 
diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityFieldTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityFieldTest.php
index 3dd810c..56f3873 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityFieldTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityFieldTest.php
@@ -221,10 +221,12 @@ public function testReadWrite() {
     $this->assertIdentical(count($entity->name), 0, 'Name field contains no items.');
     $this->assertIdentical($entity->name->getValue(), array(), 'Name field value is an empty array.');
 
+    $entity->name->value = 'foo';
+    $this->assertTrue($entity->name->value, 'foo', 'Name field set.');
     // Test removing all list items by setting it to NULL.
     $entity->name = NULL;
     $this->assertIdentical(count($entity->name), 0, 'Name field contains no items.');
-    $this->assertIdentical($entity->name->getValue(), array(), 'Name field value is an empty array.');
+    $this->assertNull($entity->name->getValue(), 'Name field value is NULL.');
 
     // Test get and set field values.
     $entity->name = 'foo';
@@ -319,6 +321,30 @@ public function testIntrospection() {
 
     // @todo: Once the user entity has definitions, continue testing getting
     // them from the $userref_values['entity'] property.
+
+    // Make sure provided contextual information is right.
+    $this->assertIdentical($entity->getRoot(), $entity, 'Entity is root object.');
+    $this->assertEqual($entity->getPropertyPath(), '');
+    $this->assertEqual($entity->getName(), '');
+    $this->assertEqual($entity->getParent(), NULL);
+
+    $field = $entity->user_id;
+    $this->assertIdentical($field->getRoot(), $entity, 'Entity is root object.');
+    $this->assertEqual($field->getPropertyPath(), 'user_id');
+    $this->assertEqual($field->getName(), 'user_id');
+    $this->assertIdentical($field->getParent(), $entity, 'Parent object matches.');
+
+    $field_item = $field[0];
+    $this->assertIdentical($field_item->getRoot(), $entity, 'Entity is root object.');
+    $this->assertEqual($field_item->getPropertyPath(), 'user_id.0');
+    $this->assertEqual($field_item->getName(), '0');
+    $this->assertIdentical($field_item->getParent(), $field, 'Parent object matches.');
+
+    $item_value = $field_item->get('entity');
+    $this->assertIdentical($item_value->getRoot(), $entity, 'Entity is root object.');
+    $this->assertEqual($item_value->getPropertyPath(), 'user_id.0.entity');
+    $this->assertEqual($item_value->getName(), 'entity');
+    $this->assertIdentical($item_value->getParent(), $field_item, 'Parent object matches.');
   }
 
   /**
diff --git a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/EntityTestStorageController.php b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/EntityTestStorageController.php
index e3b45fa..d24ade8 100644
--- a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/EntityTestStorageController.php
+++ b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/EntityTestStorageController.php
@@ -48,30 +48,38 @@ protected function buildPropertyQuery(QueryInterface $entity_query, array $value
    *   An array of entity objects implementing the EntityInterface.
    */
   protected function mapFromStorageRecords(array $records, $load_revision = FALSE) {
-    $records = parent::mapFromStorageRecords($records, $load_revision);
+    $property_values = $this->getPropertyValues($records, $load_revision);
 
-    // Load data of translatable properties.
-    $this->attachPropertyData($records, $load_revision);
+    foreach ($records as $id => $record) {
+      $values = isset($property_values[$id]) ? $property_values[$id] : array();
+
+      foreach ($record as $name => $value) {
+        $values[$name][LANGUAGE_DEFAULT][0]['value'] = $value;
+      }
+      $entity = new $this->entityClass($values, $this->entityType);
+      $records[$id] = $entity;
+    }
     return $records;
   }
 
   /**
    * Attaches property data in all languages for translatable properties.
    */
-  protected function attachPropertyData(&$queried_entities, $load_revision = FALSE) {
+  protected function getPropertyValues($records, $load_revision = FALSE) {
     $query = db_select('entity_test_property_data', 'data', array('fetch' => PDO::FETCH_ASSOC))
       ->fields('data')
-      ->condition('id', array_keys($queried_entities))
+      ->condition('id', array_keys($records))
       ->orderBy('data.id');
     if ($load_revision) {
       // Get revision id's.
       $revision_ids = array();
-      foreach ($queried_entities as $id => $entity) {
-        $revision_ids[] = $entity->get('revision_id')->value;
+      foreach ($records as $record) {
+        $revision_ids[] = $record->revision_id;
       }
       $query->condition('revision_id', $revision_ids);
     }
     $data = $query->execute();
+    $property_values = array();
 
     foreach ($data as $values) {
       $id = $values['id'];
@@ -79,9 +87,10 @@ protected function attachPropertyData(&$queried_entities, $load_revision = FALSE
       // LANGUAGE_DEFAULT as key.
       $langcode = empty($values['default_langcode']) ? $values['langcode'] : LANGUAGE_DEFAULT;
 
-      $queried_entities[$id]->name[$langcode][0]['value'] = $values['name'];
-      $queried_entities[$id]->user_id[$langcode][0]['value'] = $values['user_id'];
+      $property_values[$id]['name'][$langcode][0]['value'] = $values['name'];
+      $property_values[$id]['user_id'][$langcode][0]['value'] = $values['user_id'];
     }
+    return $property_values;
   }
 
   /**
diff --git a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/EntityTestTranslationController.php b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/EntityTestTranslationController.php
deleted file mode 100644
index e7ca050..0000000
--- a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/EntityTestTranslationController.php
+++ /dev/null
@@ -1,28 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\translation_entity\EntityTranslationController.
- */
-
-namespace Drupal\entity_test;
-
-use Drupal\Core\Entity\EntityInterface;
-use Drupal\translation_entity\EntityTranslationController;
-
-/**
- * Test entity translation controller.
- */
-class EntityTestTranslationController extends EntityTranslationController {
-
-  /**
-   * Overrides EntityTranslationControllerInterface::removeTranslation().
-   */
-  public function removeTranslation(EntityInterface $entity, $langcode) {
-    $translation = $entity->getTranslation($langcode);
-    foreach ($translation->getPropertyDefinitions() as $property_name => $langcode) {
-      $translation->$property_name = array();
-    }
-  }
-
-}
diff --git a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Plugin/Core/Entity/EntityTest.php b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Plugin/Core/Entity/EntityTest.php
index 9b4d368..22ac2ec 100644
--- a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Plugin/Core/Entity/EntityTest.php
+++ b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Plugin/Core/Entity/EntityTest.php
@@ -23,7 +23,7 @@
  *   form_controller_class = {
  *     "default" = "Drupal\entity_test\EntityTestFormController"
  *   },
- *   translation_controller_class = "Drupal\entity_test\EntityTestTranslationController",
+ *   translation_controller_class = "Drupal\translation_entity\EntityTranslationControllerNG",
  *   base_table = "entity_test",
  *   data_table = "entity_test_property_data",
  *   revision_table = "entity_test_property_revision",
@@ -74,14 +74,12 @@ class EntityTest extends EntityNG {
   public $user_id;
 
   /**
-   * Overrides Entity::__construct().
+   * Initialize the object. Invoked upon construction and wake up.
    */
-  public function __construct(array $values, $entity_type) {
-    parent::__construct($values, $entity_type);
-
+  protected function init() {
+    parent::init();
     // We unset all defined properties, so magic getters apply.
     unset($this->id);
-    unset($this->langcode);
     unset($this->uuid);
     unset($this->revision_id);
     unset($this->name);
diff --git a/core/modules/text/lib/Drupal/text/TextProcessed.php b/core/modules/text/lib/Drupal/text/TextProcessed.php
index 9284c2d..c73af6f 100644
--- a/core/modules/text/lib/Drupal/text/TextProcessed.php
+++ b/core/modules/text/lib/Drupal/text/TextProcessed.php
@@ -8,7 +8,7 @@
 namespace Drupal\text;
 
 use Drupal\Core\TypedData\ContextAwareInterface;
-use Drupal\Core\TypedData\Type\String;
+use Drupal\Core\TypedData\ContextAwareTypedData;
 use Drupal\Core\TypedData\ReadOnlyException;
 use InvalidArgumentException;
 
@@ -18,7 +18,7 @@
  * Required settings (below the definition's 'settings' key) are:
  *  - text source: The text property containing the to be processed text.
  */
-class TextProcessed extends String implements ContextAwareInterface {
+class TextProcessed extends ContextAwareTypedData {
 
   /**
    * The text property.
@@ -35,24 +35,10 @@ class TextProcessed extends String implements ContextAwareInterface {
   protected $format;
 
   /**
-   * The name.
-   *
-   * @var string
+   * Overrides ContextAwareTypedData::__construct().
    */
-  protected $name;
-
-  /**
-   * The parent data structure.
-   *
-   * @var \Drupal\Core\Entity\Field\FieldItemInterface
-   */
-  protected $parent;
-
-  /**
-   * Implements TypedDataInterface::__construct().
-   */
-  public function __construct(array $definition) {
-    $this->definition = $definition;
+  public function __construct(array $definition, $name = NULL, ContextAwareInterface $parent = NULL) {
+    parent::__construct($definition, $name, $parent);
 
     if (!isset($definition['settings']['text source'])) {
       throw new InvalidArgumentException("The definition's 'source' key has to specify the name of the text property to be processed.");
@@ -60,39 +46,18 @@ public function __construct(array $definition) {
   }
 
   /**
-   * Implements ContextAwareInterface::getName().
-   */
-  public function getName() {
-    return $this->name;
-  }
-
-  /**
-   * Implements ContextAwareInterface::setName().
-   */
-  public function setName($name) {
-    $this->name = $name;
-  }
-
-  /**
-   * Implements ContextAwareInterface::getParent().
-   *
-   * @return \Drupal\Core\Entity\Field\FieldItemInterface
+   * Overrides ContextAwareTypedData::setContext().
    */
-  public function getParent() {
-    return $this->parent;
-  }
-
-  /**
-   * Implements ContextAwareInterface::setParent().
-   */
-  public function setParent($parent) {
-    $this->parent = $parent;
-    $this->text = $parent->get($this->definition['settings']['text source']);
-    $this->format = $parent->get('format');
+  public function setContext($name = NULL, ContextAwareInterface $parent = NULL) {
+    parent::setContext($name, $parent);
+    if (isset($parent)) {
+      $this->text = $parent->get($this->definition['settings']['text source']);
+      $this->format = $parent->get('format');
+    }
   }
 
   /**
-   * Implements TypedDataInterface::getValue().
+   * Implements \Drupal\Core\TypedData\TypedDataInterface::getValue().
    */
   public function getValue($langcode = NULL) {
 
@@ -104,21 +69,28 @@ public function getValue($langcode = NULL) {
     $entity = $field->getParent();
     $instance = field_info_instance($entity->entityType(), $field->getName(), $entity->bundle());
 
-    if (!empty($instance['settings']['text_processing']) && $this->format->value) {
-      return check_markup($this->text->value, $this->format->value, $entity->language()->langcode);
+    if (!empty($instance['settings']['text_processing']) && $this->format->getValue()) {
+      return check_markup($this->text->getValue(), $this->format->getValue(), $entity->language()->langcode);
     }
     else {
       // If no format is available, still make sure to sanitize the text.
-      return check_plain($this->text->value);
+      return check_plain($this->text->getValue());
     }
   }
 
   /**
-   * Implements TypedDataInterface::setValue().
+   * Implements \Drupal\Core\TypedData\TypedDataInterface::setValue().
    */
   public function setValue($value) {
     if (isset($value)) {
       throw new ReadOnlyException('Unable to set a computed property.');
     }
   }
+
+  /**
+   * Implements \Drupal\Core\TypedData\TypedDataInterface::validate().
+   */
+  public function validate() {
+    // @todo: Implement.
+  }
 }
diff --git a/core/modules/text/lib/Drupal/text/Type/TextItem.php b/core/modules/text/lib/Drupal/text/Type/TextItem.php
index 07ae7f9..2077b42 100644
--- a/core/modules/text/lib/Drupal/text/Type/TextItem.php
+++ b/core/modules/text/lib/Drupal/text/Type/TextItem.php
@@ -10,12 +10,12 @@
 use Drupal\Core\Entity\Field\FieldItemBase;
 
 /**
- * Defines the 'text_item' and 'text_long_item' entity field items.
+ * Defines the 'text_field' and 'text_long_field' entity field items.
  */
 class TextItem extends FieldItemBase {
 
   /**
-   * Field definitions of the contained properties.
+   * Definitions of the contained properties.
    *
    * @see self::getPropertyDefinitions()
    *
diff --git a/core/modules/text/lib/Drupal/text/Type/TextSummaryItem.php b/core/modules/text/lib/Drupal/text/Type/TextSummaryItem.php
index b6438ff..67624c4 100644
--- a/core/modules/text/lib/Drupal/text/Type/TextSummaryItem.php
+++ b/core/modules/text/lib/Drupal/text/Type/TextSummaryItem.php
@@ -8,12 +8,12 @@
 namespace Drupal\text\Type;
 
 /**
- * Defines the 'text_with_summary' entity field item.
+ * Defines the 'text_with_summary_field' entity field item.
  */
 class TextSummaryItem extends TextItem {
 
   /**
-   * Field definitions of the contained properties.
+   * Definitions of the contained properties.
    *
    * @see self::getPropertyDefinitions()
    *
diff --git a/core/modules/translation_entity/lib/Drupal/translation_entity/EntityTranslationControllerNG.php b/core/modules/translation_entity/lib/Drupal/translation_entity/EntityTranslationControllerNG.php
new file mode 100644
index 0000000..4c4e9e6
--- /dev/null
+++ b/core/modules/translation_entity/lib/Drupal/translation_entity/EntityTranslationControllerNG.php
@@ -0,0 +1,26 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\translation_entity\EntityTranslationControllerNG.
+ */
+
+namespace Drupal\translation_entity;
+
+use Drupal\Core\Entity\EntityInterface;
+
+/**
+ * Test entity translation controller.
+ */
+class EntityTranslationControllerNG extends EntityTranslationController {
+
+  /**
+   * Overrides EntityTranslationController::removeTranslation().
+   */
+  public function removeTranslation(EntityInterface $entity, $langcode) {
+    $translation = $entity->getTranslation($langcode);
+    foreach ($translation->getPropertyDefinitions() as $property_name => $langcode) {
+      $translation->$property_name = array();
+    }
+  }
+}
diff --git a/core/modules/translation_entity/lib/Drupal/translation_entity/Tests/EntityTranslationUITest.php b/core/modules/translation_entity/lib/Drupal/translation_entity/Tests/EntityTranslationUITest.php
index eac0b7f..6ad80a3 100644
--- a/core/modules/translation_entity/lib/Drupal/translation_entity/Tests/EntityTranslationUITest.php
+++ b/core/modules/translation_entity/lib/Drupal/translation_entity/Tests/EntityTranslationUITest.php
@@ -292,7 +292,7 @@ protected function getEditValues($values, $langcode, $new = FALSE) {
    *   The translation object to act on.
    */
   protected function getTranslation(EntityInterface $entity, $langcode) {
-    return $entity instanceof EntityNG ? $entity->getTranslation($langcode) : $entity;
+    return $entity instanceof EntityNG ? $entity->getTranslation($langcode, FALSE) : $entity;
   }
 
   /**
diff --git a/core/modules/views/views_ui/lib/Drupal/views_ui/ViewUI.php b/core/modules/views/views_ui/lib/Drupal/views_ui/ViewUI.php
index a6503ec..db6c900 100644
--- a/core/modules/views/views_ui/lib/Drupal/views_ui/ViewUI.php
+++ b/core/modules/views/views_ui/lib/Drupal/views_ui/ViewUI.php
@@ -9,6 +9,7 @@
 
 use Drupal\views\ViewExecutable;
 use Drupal\Core\Database\Database;
+use Drupal\Core\TypedData\ContextAwareInterface;
 use Drupal\views\Plugin\views\query\Sql;
 use Drupal\views\Plugin\Core\Entity\View;
 use Drupal\views\ViewStorageInterface;
@@ -1080,4 +1081,52 @@ public function setOriginalID($id) {
     return $this->__call(__FUNCTION__, func_get_args());
   }
 
+  /**
+   * Implements Drupal\Core\Entity\EntityInterface::getBCEntity().
+   */
+  public function getBCEntity() {
+    return $this->__call(__FUNCTION__, func_get_args());
+  }
+
+  /**
+   * Implements Drupal\Core\Entity\EntityInterface::getOriginalEntity().
+   */
+  public function getOriginalEntity() {
+    return $this->__call(__FUNCTION__, func_get_args());
+  }
+
+  /**
+   * Implements \Drupal\Core\TypedData\ContextAwareInterface::getName().
+   */
+  public function getName() {
+    return $this->__call(__FUNCTION__, func_get_args());
+  }
+
+  /**
+   * Implements \Drupal\Core\TypedData\ContextAwareInterface::getRoot().
+   */
+  public function getRoot() {
+    return $this->__call(__FUNCTION__, func_get_args());
+  }
+
+  /**
+   * Implements \Drupal\Core\TypedData\ContextAwareInterface::getPropertyPath().
+   */
+  public function getPropertyPath() {
+    return $this->__call(__FUNCTION__, func_get_args());
+  }
+
+  /**
+   * Implements \Drupal\Core\TypedData\ContextAwareInterface::getParent().
+   */
+  public function getParent() {
+    return $this->__call(__FUNCTION__, func_get_args());
+  }
+
+  /**
+   * Implements \Drupal\Core\TypedData\ContextAwareInterface::setContext().
+   */
+  public function setContext($name = NULL, ContextAwareInterface $parent = NULL) {
+    return $this->__call(__FUNCTION__, func_get_args());
+  }
 }
