diff --git a/core/lib/Drupal/Core/CoreBundle.php b/core/lib/Drupal/Core/CoreBundle.php
index bbc4e2e..f501043 100644
--- a/core/lib/Drupal/Core/CoreBundle.php
+++ b/core/lib/Drupal/Core/CoreBundle.php
@@ -55,6 +55,8 @@ public function build(ContainerBuilder $container) {
       ->setFactoryMethod('getConnection')
       ->addArgument('slave');
     $container->register('typed_data', 'Drupal\Core\TypedData\TypedDataManager');
+    $container->register('constraint', 'Drupal\Core\Validation\Constraint\ConstraintManager');
+
     // Add the user's storage for temporary, non-cache data.
     $container->register('lock', 'Drupal\Core\Lock\DatabaseLockBackend');
     $container->register('user.tempstore', 'Drupal\user\TempStoreFactory')
diff --git a/core/lib/Drupal/Core/Entity/Entity.php b/core/lib/Drupal/Core/Entity/Entity.php
index c6e041e..5500f65 100644
--- a/core/lib/Drupal/Core/Entity/Entity.php
+++ b/core/lib/Drupal/Core/Entity/Entity.php
@@ -370,4 +370,9 @@ public function isDefaultRevision($new_value = NULL) {
     }
     return $return;
   }
+
+  // @todo: remove after merge with EntityNG.
+  public function getConstraintsObjects() {
+    return array();
+  }
 }
diff --git a/core/lib/Drupal/Core/Entity/EntityFormController.php b/core/lib/Drupal/Core/Entity/EntityFormController.php
index 2e9daac..27001f0 100644
--- a/core/lib/Drupal/Core/Entity/EntityFormController.php
+++ b/core/lib/Drupal/Core/Entity/EntityFormController.php
@@ -48,12 +48,39 @@ public function build(array $form, array &$form_state, EntityInterface $entity)
     $entity = $this->getEntity($form_state);
     $form = $this->form($form, $form_state, $entity);
 
+    // Retrieve the constraints as objects.
+    $constraint_set = $entity->getConstraintsObjects();
+
+    // Loop all constraints.
+    foreach ($constraint_set as $field_name => $constraints) {
+      // Handle field constraints.
+      if (isset($form[$field_name]) && !empty($constraints['field'])) {
+        foreach ($constraints['field'] as $constraint) {
+          // @todo: find a better way to handle this, or use constraints passed
+          // by the field / typedData
+          if (!isset($form[$field_name][0])) {
+            $form[$field_name] += $constraint->convertToFormAPI();
+          }
+        }
+      }
+      // Handle typedData constraints.
+      if (isset($form[$field_name]) && !empty($constraints[0])) {
+        foreach ($constraints[0] as $constraint) {
+          if (!isset($form[$field_name][0])) {
+            $form[$field_name] = $constraint->convertToFormAPI() + $form[$field_name];
+          }
+        }
+      }
+    }
+
+    // Add a #bound_to so you can specify the field name.
+    // Same logic as above, but reversed.
+
     // Retrieve and add the form actions array.
     $actions = $this->actionsElement($form, $form_state);
     if (!empty($actions)) {
       $form['actions'] = $actions;
     }
-
     return $form;
   }
 
diff --git a/core/lib/Drupal/Core/Entity/EntityFormControllerNG.php b/core/lib/Drupal/Core/Entity/EntityFormControllerNG.php
index 812a192..19ae5af 100644
--- a/core/lib/Drupal/Core/Entity/EntityFormControllerNG.php
+++ b/core/lib/Drupal/Core/Entity/EntityFormControllerNG.php
@@ -34,11 +34,17 @@ public function form(array $form, array &$form_state, EntityInterface $entity) {
    * Overrides EntityFormController::validate().
    */
   public function validate(array $form, array &$form_state) {
-    // @todo Exploit the Field API to validate the values submitted for the
-    // entity properties.
     $entity = $this->buildEntity($form, $form_state);
-    $info = $entity->entityInfo();
+    if ($violation_set = $entity->validate()) {
+      $error_counter = 0;
+      foreach ($violation_set as $name => $violations) {
+        foreach ($violations as $violation) {
+          form_set_error('errors_' . $error_counter++, t($violation->getMessage(), $violation->getMessageArguments() + array('%label' => $violation->getTargetLabel())));
+        }
+      }
+    }
 
+    $info = $entity->entityInfo();
     if (!empty($info['fieldable'])) {
       $entity->setCompatibilityMode(TRUE);
       field_attach_form_validate($entity->entityType(), $entity, $form, $form_state);
diff --git a/core/lib/Drupal/Core/Entity/EntityNG.php b/core/lib/Drupal/Core/Entity/EntityNG.php
index 35ef89d..d356405 100644
--- a/core/lib/Drupal/Core/Entity/EntityNG.php
+++ b/core/lib/Drupal/Core/Entity/EntityNG.php
@@ -12,6 +12,7 @@
 use Drupal\Component\Uuid\Uuid;
 use ArrayIterator;
 use InvalidArgumentException;
+use Drupal\Core\Validation\Violation;
 
 /**
  * Implements Entity Field API specific enhancements to the Entity class.
@@ -413,4 +414,85 @@ public function __clone() {
       }
     }
   }
+
+  /**
+   * Validates the entity.
+   *
+   * @return array
+   *   Array containing all violations
+   *
+   * @see Drupal\Core\Validation\Violation\Violation.
+   */
+  public function validate() {
+    $violations = array();
+    // Loop over all properties in all languages.
+    foreach ($this->getTranslationLanguages(TRUE) as $langcode => $language) {
+      foreach ($this->getTranslation($langcode) as $name => $property) {
+        $violations[$name] = $property->validate();
+      }
+    }
+
+    // Validate entity global constraints.
+    $definition = $this->entityInfo();
+    if (isset($definition['constraints'])) {
+      foreach ($definition['constraints'] as $constraint_id => $constraint_info) {
+        if ($constraint = drupal_container()->get('constraint')->create($constraint_id, (array)$constraint_info, $this)) {
+          if (!$constraint->validate($this)) {
+            $violations['entity'][] = new Violation\EntityViolation($constraint, $this);
+          }
+        }
+      }
+    }
+    return $violations;
+  }
+
+  /**
+   * Get all constraints objects for the entity.
+   *
+   * @return array
+   *   Array containing all constraints.
+   *
+   * @see Drupal\Core\Validation\Constraint\ConstraintInterface.
+   */
+  public function getConstraintsObjects() {
+    $constraints = array();
+
+    // Loop over all properties, the constraints are the same for all languages.
+    foreach ($this->getProperties() as $name => $property) {
+      $constraints[$name] = $property->getConstraintsObjects();
+    }
+
+    // Add the constraints of the entity level.
+    $definition = $this->entityInfo();
+    if (isset($definition['constraints'])) {
+      foreach ($definition['constraints'] as $constraint_id => $constraint_info) {
+        if ($constraint = drupal_container()->get('constraint')->create($constraint_id, (array)$constraint_info, $this)) {
+           $constraints['entity'][] = $constraint;
+        }
+      }
+    }
+
+    return $constraints;
+  }
+
+  /**
+   * Get all constraints for the entity.
+   *
+   * @return array
+   *   Array containing all constraints.
+   *
+   * @see Drupal\Core\Validation\Constraint\ConstraintInterface.
+   */
+  public function getConstraints() {
+    $constraints = array();
+
+    // Loop over all properties, the constraints are the same for all languages.
+    foreach ($this->getProperties() as $name => $property) {
+      $constraints[$name] = $property->getConstraints();
+    }
+
+    // @todo: Add the constraints of the entity level.
+
+    return $constraints;
+  }
 }
diff --git a/core/lib/Drupal/Core/Entity/Field/FieldItemBase.php b/core/lib/Drupal/Core/Entity/Field/FieldItemBase.php
index 5c71aa3..00bad20 100644
--- a/core/lib/Drupal/Core/Entity/Field/FieldItemBase.php
+++ b/core/lib/Drupal/Core/Entity/Field/FieldItemBase.php
@@ -15,6 +15,7 @@
 use ArrayIterator;
 use IteratorAggregate;
 use InvalidArgumentException;
+use Drupal\Core\Validation\Violation;
 
 /**
  * An entity field item.
@@ -121,10 +122,39 @@ public function getString() {
   }
 
   /**
+   * Implements TypedDataInterface::getConstraints().
+   */
+  public function getConstraints() {
+    $property_definition = $this->getPropertyDefinitions();
+    if (isset($property_definition['value']['constraints'])) {
+      return $property_definition['value']['constraints'];
+    }
+    return array();
+  }
+
+  /**
    * Implements TypedDataInterface::validate().
    */
   public function validate() {
-    // @todo implement
+    $violations = array();
+    foreach($this->getProperties() as $property) {
+      $violations += $property->validate();
+    }
+    return $violations;
+
+    $property_definition = $this->getPropertyDefinitions();
+    if (isset($property_definition['value']['constraints'])) {
+      $constraints = $property_definition['value']['constraints'];
+      foreach ($constraints as $constraint => $constraint_info) {
+        if ($constraint = drupal_container()->get('constraint')->create($constraint, (array)$constraint_info, $this)) {
+          // @todo: is there are better way for $this->value['value']?
+          if (!$constraint->validate($this->getValue(), 'typedata validate value')) {
+            $violations[] = new Violation\Violation(format_string('%value is not valid.', array('%value' => $this->value['value'])) , $constraint, $this);
+          }
+        }
+      }
+    }
+    return $violations;
   }
 
   /**
diff --git a/core/lib/Drupal/Core/Entity/Field/Type/EntityReferenceItem.php b/core/lib/Drupal/Core/Entity/Field/Type/EntityReferenceItem.php
index a60e65e..3683ff8 100644
--- a/core/lib/Drupal/Core/Entity/Field/Type/EntityReferenceItem.php
+++ b/core/lib/Drupal/Core/Entity/Field/Type/EntityReferenceItem.php
@@ -39,6 +39,10 @@ public function getPropertyDefinitions() {
         // @todo: Lookup the entity type's ID data type and use it here.
         'type' => 'integer',
         'label' => t('Entity ID'),
+        'constraints' => array(
+          'notnull' => TRUE,
+          'min' => 0,
+        ),
       );
       self::$propertyDefinitions[$entity_type]['entity'] = array(
         'type' => 'entity',
diff --git a/core/lib/Drupal/Core/Entity/Field/Type/EntityTranslation.php b/core/lib/Drupal/Core/Entity/Field/Type/EntityTranslation.php
index 0db4657..52d910e 100644
--- a/core/lib/Drupal/Core/Entity/Field/Type/EntityTranslation.php
+++ b/core/lib/Drupal/Core/Entity/Field/Type/EntityTranslation.php
@@ -242,5 +242,6 @@ public function access(\Drupal\user\User $account = NULL) {
    */
   public function validate($value = NULL) {
     // @todo implement
+    return array();
   }
 }
diff --git a/core/lib/Drupal/Core/Entity/Field/Type/EntityWrapper.php b/core/lib/Drupal/Core/Entity/Field/Type/EntityWrapper.php
index 97449e7..e277da0 100644
--- a/core/lib/Drupal/Core/Entity/Field/Type/EntityWrapper.php
+++ b/core/lib/Drupal/Core/Entity/Field/Type/EntityWrapper.php
@@ -129,6 +129,7 @@ public function getString() {
    */
   public function validate($value = NULL) {
     // TODO: Implement validate() method.
+    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 e7a5960..809f052 100644
--- a/core/lib/Drupal/Core/Entity/Field/Type/Field.php
+++ b/core/lib/Drupal/Core/Entity/Field/Type/Field.php
@@ -14,6 +14,7 @@
 use ArrayIterator;
 use IteratorAggregate;
 use InvalidArgumentException;
+use Drupal\Core\Validation\Violation;
 
 /**
  * An entity field, i.e. a list of field items.
@@ -114,10 +115,91 @@ public function getString() {
   }
 
   /**
+   * Return constraints objects for each delta.
+   */
+  public function getConstraintsObjects() {
+    $constraints = array();
+    $field_info_constraints = array();
+
+    // Use field_info_instance('entity', 'field_name', 'bundle'));
+    // to get the constraints fron the field definition. They will apply to
+    // all delta's.
+    $field_info = field_info_instance($this->parent->entityType, $this->name, $this->parent->bundle ? $this->parent->bundle : $this->parent->entityType);
+    if (isset($field_info->definition['constraints'])) {
+      foreach($field_info->definition['constraints'] as $constraint_id => $constraint_info) {
+        if ($constraint = drupal_container()->get('constraint')->create($constraint_id, (array)$constraint_info, $this)) {
+           $constraints['field'][] = $constraint;
+        }
+      }
+    }
+
+    // Iterate and use TypedData::validate().
+    foreach ($this->getIterator() as $delta => $item) {
+      if ($item_constraints = $item->getConstraintsObjects()) {
+        $constraints[$delta] = $item_constraints;
+      }
+    }
+
+    return $constraints;
+  }
+
+  /**
+   * Return constraints for each delta.
+   */
+  public function getConstraints() {
+    $constraints = array();
+    $field_info_constraints = array();
+
+    // Use field_info_instance('entity', 'field_name', 'bundle'));
+    // to get the constraints fron the field definition. They will apply to
+    // all delta's.
+    $field_info = field_info_instance($this->parent->entityType, $this->name, $this->parent->bundle ? $this->parent->bundle : $this->parent->entityType);
+    if (isset($field_info->definition['constraints'])) {
+      $field_info_constraints = $field_info->definition['constraints'];
+    }
+
+    // Iterate and use TypedData::getConstraint().
+    $iterator = $this->getIterator();
+    if ($iterator->count()) {
+      foreach ($this->getIterator() as $delta => $item) {
+        $constraints[$delta] = array();
+        if ($item_constraint = $item->getConstraints()) {
+          $constraints[$delta] = $item_constraint + $field_info_constraints;
+        }
+        $constraints[$delta] += $field_info_constraints;
+      }
+    }
+    else {
+      // @todo: not every field is using the iterator.
+      $constraints['field'] = $field_info_constraints;
+    }
+    return $constraints;
+  }
+
+  /**
    * Implements TypedDataInterface::validate().
    */
   public function validate() {
-    // @todo implement
+    $violations = array();
+
+    // Iterate and use TypedData::validate().
+    foreach ($this->getIterator() as $delta => $item) {
+      $violations += $item->validate();
+    }
+
+    // Do validation on field level.
+    $constraints = $this->getConstraints();
+    if (isset($constraints['field'])) {
+      foreach($constraints['field'] as $constraint_id => $constraint_info) {
+        if ($constraint = drupal_container()->get('constraint')->create($constraint_id, (array)$constraint_info, $this)) {
+          if (!$constraint->validate($this)) {
+            $violations[] = new Violation\FieldViolation($constraint, $this);
+          }
+        }
+      }
+    }
+
+    return $violations;
   }
 
   /**
diff --git a/core/lib/Drupal/Core/Entity/Field/Type/IntegerItem.php b/core/lib/Drupal/Core/Entity/Field/Type/IntegerItem.php
index 1f4b4e6..3830711 100644
--- a/core/lib/Drupal/Core/Entity/Field/Type/IntegerItem.php
+++ b/core/lib/Drupal/Core/Entity/Field/Type/IntegerItem.php
@@ -32,6 +32,10 @@ public function getPropertyDefinitions() {
       self::$propertyDefinitions['value'] = array(
         'type' => 'integer',
         'label' => t('Integer value'),
+        'constraints' => array(
+          'nonnull' => TRUE,
+          'min' => 0,
+        ),
       );
     }
     return self::$propertyDefinitions;
diff --git a/core/lib/Drupal/Core/Plugin/Validation/Constraint/EntityTypeConstraint.php b/core/lib/Drupal/Core/Plugin/Validation/Constraint/EntityTypeConstraint.php
new file mode 100644
index 0000000..daccab0
--- /dev/null
+++ b/core/lib/Drupal/Core/Plugin/Validation/Constraint/EntityTypeConstraint.php
@@ -0,0 +1,45 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Validation\Constraint\EntityTypeConstraint.
+ */
+
+use Drupal\Core\Annotation\Plugin;
+use Drupal\Core\Annotation\Translation;
+
+namespace Drupal\Core\Plugin\Validation\Constraint;
+
+/**
+ * Checks if a value is a valid entity type.
+ *
+ * @Plugin(
+ *   id = "entity type",
+ *   label = @Translation("Entity type constraint", context = "Validation"),
+ *   message = @Translation("The value of %label is not a valid entity type.", context = "Validation"),
+ *   type = "field"
+ * )
+ */
+class EntityTypeConstraint extends \Drupal\Core\Validation\Constraint\Constraint {
+
+  /**
+   * Checks if a value is a valid entity type.
+   *
+   * @return boolean
+   *   TRUE if value is a known entity type, FALSE if the value is empty.
+   */
+  public function validate($value) {
+     return array_key_exists($value, entity_get_info());
+  }
+
+  /**
+   * Convert the constraint to form API structure.
+   *
+   * @return array
+   *   Array usable by the form API.
+   */
+  public function convertToFormAPI() {
+    return array(
+      '#choose' => array_keys(entity_get_info()),
+    );
+  }}
diff --git a/core/lib/Drupal/Core/Plugin/Validation/Constraint/EqualFieldsConstraint.php b/core/lib/Drupal/Core/Plugin/Validation/Constraint/EqualFieldsConstraint.php
new file mode 100644
index 0000000..be46601
--- /dev/null
+++ b/core/lib/Drupal/Core/Plugin/Validation/Constraint/EqualFieldsConstraint.php
@@ -0,0 +1,52 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Validation\Constraint\EqualFieldsConstraint.
+ */
+
+use Drupal\Core\Annotation\Plugin;
+use Drupal\Core\Annotation\Translation;
+
+namespace Drupal\Core\Plugin\Validation\Constraint;
+
+
+/**
+ * Checks if two fields are equal.
+ *
+ * @Plugin(
+ *   id = "equal.field",
+ *   label = @Translation("Equal fields constraint", context = "Validation"),
+ *   message = @Translation("The value of %field1 is different from %field2.", context = "Validation"),
+ *   type = "entity"
+ * )
+ */
+class EqualFieldsConstraint extends \Drupal\Core\Validation\Constraint\Constraint {
+
+  /**
+   * Checks if two fields are equal.
+   *
+   * @return boolean
+   *   TRUE if the fields are equal, FALSE if not.
+   */
+  public function validate($value) {
+    $this->addMessageArguments('%field1', $value->get($this->properties['field1'])->getName());
+    $this->addMessageArguments('%field2', $value->get($this->properties['field2'])->getName());
+    return $value->get($this->properties['field1'])->getValue() == $value->get($this->properties['field2'])->getValue();
+  }
+
+  /**
+   * Convert the constraint to form API structure.
+   *
+   * @return array
+   *   Array usable by the form API.
+   */
+  public function convertToFormAPI() {
+    return array(
+      '#equal' => array(
+        $this->properties['field1'],
+        $this->properties['field2'],
+      ),
+    );
+  }
+}
diff --git a/core/lib/Drupal/Core/Plugin/Validation/Constraint/MinValueConstraint.php b/core/lib/Drupal/Core/Plugin/Validation/Constraint/MinValueConstraint.php
new file mode 100644
index 0000000..32ecb32
--- /dev/null
+++ b/core/lib/Drupal/Core/Plugin/Validation/Constraint/MinValueConstraint.php
@@ -0,0 +1,52 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Validation\Constraint\MinValueConstraint.
+ */
+
+use Drupal\Core\Annotation\Plugin;
+use Drupal\Core\Annotation\Translation;
+
+namespace Drupal\Core\Plugin\Validation\Constraint;
+
+
+/**
+ * Checks if a value is greater than a minimal value.
+ *
+ * @Plugin(
+ *   id = "min",
+ *   label = @Translation("Min value constraint", context = "Validation"),
+ *   message = @Translation("The value of %label has to be greater than %min.", context = "Validation"),
+ *   type = "typedData",
+ *   properties = {
+ *     "min" = 0
+ *   }
+ * )
+ */
+class MinValueConstraint extends \Drupal\Core\Validation\Constraint\Constraint {
+
+  /**
+   * Checks if a value is greater than a minimal value.
+   *
+   * @return boolean
+   *   TRUE if the value is greater or equal, FALSE if the value is smaller.
+   */
+  public function validate($value) {
+    $this->addMessageArguments('%min', $this->properties['min']);
+    return $value >= $this->properties['min'];
+  }
+
+  /**
+   * Convert the constraint to form API structure.
+   *
+   * @return array
+   *   Array usable by the form API.
+   */
+  public function convertToFormAPI() {
+    return array(
+      '#type' => 'number',
+      '#min' => $this->properties['min'],
+    );
+  }
+}
diff --git a/core/lib/Drupal/Core/Plugin/Validation/Constraint/MinValueIntegerConstraint.php b/core/lib/Drupal/Core/Plugin/Validation/Constraint/MinValueIntegerConstraint.php
new file mode 100644
index 0000000..72c7dcd
--- /dev/null
+++ b/core/lib/Drupal/Core/Plugin/Validation/Constraint/MinValueIntegerConstraint.php
@@ -0,0 +1,51 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Validation\Constraint\MinValueIntegerConstraint.
+ */
+
+use Drupal\Core\Annotation\Plugin;
+use Drupal\Core\Annotation\Translation;
+
+namespace Drupal\Core\Plugin\Validation\Constraint;
+
+/**
+ * Checks if a value is greater than a minimal value.
+ *
+ * @Plugin(
+ *   id = "min.integer",
+ *   label = @Translation("Min integer constraint", context = "Validation"),
+ *   message = @Translation("The value of %label has to be greater than %min.", context = "Validation"),
+ *   type = "typedData",
+ *   properties = {
+ *     "min" = 0
+ *   }
+ * )
+ */
+class MinValueIntegerConstraint extends \Drupal\Core\Validation\Constraint\Constraint {
+
+  /**
+   * Checks if a value is greater than a minimal value.
+   *
+   * @return boolean
+   *   TRUE if the value is greater or equal, FALSE if the value is smaller.
+   */
+  public function validate($value) {
+    $this->addMessageArguments('%min', $this->properties['min']);
+    return $value >= $this->properties['min'];
+  }
+
+  /**
+   * Convert the constraint to form API structure.
+   *
+   * @return array
+   *   Array usable by the form API.
+   */
+  public function convertToFormAPI() {
+    return array(
+      '#type' => 'number',
+      '#min' => $this->properties['min'],
+    );
+  }
+}
diff --git a/core/lib/Drupal/Core/Plugin/Validation/Constraint/NotNullConstraint.php b/core/lib/Drupal/Core/Plugin/Validation/Constraint/NotNullConstraint.php
new file mode 100644
index 0000000..ea796cd
--- /dev/null
+++ b/core/lib/Drupal/Core/Plugin/Validation/Constraint/NotNullConstraint.php
@@ -0,0 +1,45 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Validation\Constraint\NotNullConstraint.
+ */
+
+use Drupal\Core\Annotation\Plugin;
+use Drupal\Core\Annotation\Translation;
+
+namespace Drupal\Core\Plugin\Validation\Constraint;
+
+/**
+ * Checks if a value is not NULL.
+ *
+ * @Plugin(
+ *   id = "notnull",
+ *   label = @Translation("Not null constraint", context = "Validation"),
+ *   message = @Translation("The value of %label can not be null.", context = "Validation"),
+ *   type = "typedData"
+ * )
+ */
+class NotNullConstraint extends \Drupal\Core\Validation\Constraint\Constraint {
+
+  /**
+   * Checks if a value is not NULL.
+   *
+   * @return boolean
+   *   TRUE if the value is not NULL, FALSE if the value is NULL.
+   */
+  public function validate($value) {
+     return !is_null($value);
+  }
+
+  /**
+   * Convert the constraint to form API structure.
+   *
+   * @return array
+   *   Array usable by the form API.
+   */
+  public function convertToFormAPI() {
+    // @todo: implementqtion needed.
+    return array('#notnull' => TRUE);
+  }
+}
diff --git a/core/lib/Drupal/Core/Plugin/Validation/Constraint/RequiredConstraint.php b/core/lib/Drupal/Core/Plugin/Validation/Constraint/RequiredConstraint.php
new file mode 100644
index 0000000..33473a4
--- /dev/null
+++ b/core/lib/Drupal/Core/Plugin/Validation/Constraint/RequiredConstraint.php
@@ -0,0 +1,45 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Validation\Constraint\RequiredConstraint.
+ */
+
+use Drupal\Core\Annotation\Plugin;
+use Drupal\Core\Annotation\Translation;
+
+namespace Drupal\Core\Plugin\Validation\Constraint;
+
+/**
+ * Checks if a value is given.
+ *
+ * @Plugin(
+ *   id = "required",
+ *   label = @Translation("Required constraint", context = "Validation"),
+ *   message = @Translation("The value of %label is required.", context = "Validation"),
+ *   type = "typedData"
+ * )
+ */
+class RequiredConstraint extends \Drupal\Core\Validation\Constraint\Constraint {
+
+  /**
+   * Checks if a value is given.
+   *
+   * @return boolean
+   *   TRUE if there's a value, FALSE if the value is empty.
+   */
+  public function validate($value) {
+     return !empty($value);
+  }
+
+  /**
+   * Convert the constraint to form API structure.
+   *
+   * @return array
+   *   Array usable by the form API.
+   */
+  public function convertToFormAPI() {
+    return array('#required' => TRUE);
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Plugin/Validation/Constraint/RequiredFieldConstraint.php b/core/lib/Drupal/Core/Plugin/Validation/Constraint/RequiredFieldConstraint.php
new file mode 100644
index 0000000..129420d
--- /dev/null
+++ b/core/lib/Drupal/Core/Plugin/Validation/Constraint/RequiredFieldConstraint.php
@@ -0,0 +1,34 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Validation\Constraint\RequiredFieldConstraint.
+ */
+
+use Drupal\Core\Annotation\Plugin;
+use Drupal\Core\Annotation\Translation;
+
+namespace Drupal\Core\Plugin\Validation\Constraint;
+
+/**
+ * Checks if a field has a value.
+ *
+ * @Plugin(
+ *   id = "required.field",
+ *   label = @Translation("Required field constraint", context = "Validation"),
+ *   message = @Translation("The value of %label is required.", context = "Validation"),
+ *   type = "field"
+ * )
+ */
+class RequiredFieldConstraint extends \Drupal\Core\Validation\Constraint\Constraint {
+
+  /**
+   * Checks if a field has a value.
+   *
+   * @return boolean
+   *   TRUE if there's a value, FALSE if the value is empty.
+   */
+  public function validate($value) {
+     return !$value->isEmpty();
+  }
+}
diff --git a/core/lib/Drupal/Core/TypedData/Type/Binary.php b/core/lib/Drupal/Core/TypedData/Type/Binary.php
index 7ec5e6b..6b65fab 100644
--- a/core/lib/Drupal/Core/TypedData/Type/Binary.php
+++ b/core/lib/Drupal/Core/TypedData/Type/Binary.php
@@ -79,6 +79,6 @@ public function getString() {
    * Implements TypedDataInterface::validate().
    */
   public function validate() {
-    // TODO: Implement validate() method.
+    return parent::validate();
   }
 }
diff --git a/core/lib/Drupal/Core/TypedData/Type/Boolean.php b/core/lib/Drupal/Core/TypedData/Type/Boolean.php
index 5714599..29f20e5 100644
--- a/core/lib/Drupal/Core/TypedData/Type/Boolean.php
+++ b/core/lib/Drupal/Core/TypedData/Type/Boolean.php
@@ -35,6 +35,6 @@ public function setValue($value) {
    * Implements TypedDataInterface::validate().
    */
   public function validate() {
-    // TODO: Implement validate() method.
+    return parent::validate();
   }
 }
diff --git a/core/lib/Drupal/Core/TypedData/Type/Date.php b/core/lib/Drupal/Core/TypedData/Type/Date.php
index 3c0f3a9..58392fd 100644
--- a/core/lib/Drupal/Core/TypedData/Type/Date.php
+++ b/core/lib/Drupal/Core/TypedData/Type/Date.php
@@ -57,6 +57,6 @@ public function getString() {
    * Implements TypedDataInterface::validate().
    */
   public function validate() {
-    // TODO: Implement validate() method.
+    return parent::validate();
   }
 }
diff --git a/core/lib/Drupal/Core/TypedData/Type/Duration.php b/core/lib/Drupal/Core/TypedData/Type/Duration.php
index 9fd8ceb..8450b77 100644
--- a/core/lib/Drupal/Core/TypedData/Type/Duration.php
+++ b/core/lib/Drupal/Core/TypedData/Type/Duration.php
@@ -63,6 +63,6 @@ public function getString() {
    * Implements TypedDataInterface::validate().
    */
   public function validate() {
-    // TODO: Implement validate() method.
+    return parent::validate();
   }
 }
diff --git a/core/lib/Drupal/Core/TypedData/Type/Float.php b/core/lib/Drupal/Core/TypedData/Type/Float.php
index 798499c..01b8adc 100644
--- a/core/lib/Drupal/Core/TypedData/Type/Float.php
+++ b/core/lib/Drupal/Core/TypedData/Type/Float.php
@@ -35,6 +35,6 @@ public function setValue($value) {
    * Implements TypedDataInterface::validate().
    */
   public function validate() {
-    // TODO: Implement validate() method.
+    return parent::validate();
   }
 }
diff --git a/core/lib/Drupal/Core/TypedData/Type/Integer.php b/core/lib/Drupal/Core/TypedData/Type/Integer.php
index 4e9b59a..086624c 100644
--- a/core/lib/Drupal/Core/TypedData/Type/Integer.php
+++ b/core/lib/Drupal/Core/TypedData/Type/Integer.php
@@ -35,6 +35,6 @@ public function setValue($value) {
    * Implements TypedDataInterface::validate().
    */
   public function validate() {
-    // TODO: Implement validate() method.
+    return parent::validate();
   }
 }
diff --git a/core/lib/Drupal/Core/TypedData/Type/Language.php b/core/lib/Drupal/Core/TypedData/Type/Language.php
index 67f4df8..b9db021 100644
--- a/core/lib/Drupal/Core/TypedData/Type/Language.php
+++ b/core/lib/Drupal/Core/TypedData/Type/Language.php
@@ -129,6 +129,6 @@ public function getString() {
    * Implements TypedDataInterface::validate().
    */
   public function validate() {
-    // TODO: Implement validate() method.
+    return parent::validate();
   }
 }
diff --git a/core/lib/Drupal/Core/TypedData/Type/String.php b/core/lib/Drupal/Core/TypedData/Type/String.php
index fef3248..2556fb0 100644
--- a/core/lib/Drupal/Core/TypedData/Type/String.php
+++ b/core/lib/Drupal/Core/TypedData/Type/String.php
@@ -35,6 +35,6 @@ public function setValue($value) {
    * Implements TypedDataInterface::validate().
    */
   public function validate() {
-    // TODO: Implement validate() method.
+    return parent::validate();
   }
 }
diff --git a/core/lib/Drupal/Core/TypedData/Type/TypedData.php b/core/lib/Drupal/Core/TypedData/Type/TypedData.php
index 1e70c53..9914ba1 100644
--- a/core/lib/Drupal/Core/TypedData/Type/TypedData.php
+++ b/core/lib/Drupal/Core/TypedData/Type/TypedData.php
@@ -8,6 +8,7 @@
 namespace Drupal\Core\TypedData\Type;
 
 use Drupal\Core\TypedData\TypedDataInterface;
+use Drupal\Core\Validation\Violation;
 
 /**
  * The abstract base class for typed data.
@@ -44,6 +45,16 @@ public function getType() {
   }
 
   /**
+   * Implements TypedDataInterface::getConstraints().
+   */
+  public function getConstraints() {
+    if (isset($this->definition['constraints'])) {
+      return $this->definition['constraints'];
+    }
+    return array();
+  }
+
+  /**
    * Implements TypedDataInterface::getDefinition().
    */
   public function getDefinition() {
@@ -70,4 +81,37 @@ public function setValue($value) {
   public function getString() {
     return (string) $this->getValue();
   }
+
+  /**
+   * Implements TypedDataInterface::getConstraints().
+   */
+  public function getConstraintsObjects() {
+    $constraints = array();
+
+    foreach ($this->getConstraints() as $constraint_id => $constraint_info) {
+      if ($constraint = drupal_container()->get('constraint')->create($constraint_id, (array)$constraint_info, $this)) {
+        $constraints[] = $constraint;
+      }
+    }
+
+    return $constraints;
+  }
+
+  /**
+   * Implements TypedDataInterface::validate().
+   */
+  public function validate() {
+    $violations = array();
+
+    foreach ($this->getConstraints() as $constraint_id => $constraint_info) {
+      if ($constraint = drupal_container()->get('constraint')->create($constraint_id, (array)$constraint_info, $this)) {
+        if (!$constraint->validate($this->getValue())) {
+          $violations[] = new Violation\TypedDataViolation($constraint, $this);
+        }
+      }
+    }
+
+    return $violations;
+  }
+
 }
diff --git a/core/lib/Drupal/Core/TypedData/Type/Uri.php b/core/lib/Drupal/Core/TypedData/Type/Uri.php
index 010fa03..dc4f18b 100644
--- a/core/lib/Drupal/Core/TypedData/Type/Uri.php
+++ b/core/lib/Drupal/Core/TypedData/Type/Uri.php
@@ -34,6 +34,6 @@ public function setValue($value) {
    * Implements TypedDataInterface::validate().
    */
   public function validate() {
-    // TODO: Implement validate() method.
+    return parent::validate();
   }
 }
diff --git a/core/lib/Drupal/Core/TypedData/TypedDataInterface.php b/core/lib/Drupal/Core/TypedData/TypedDataInterface.php
index 1a8ffe7..61bc273 100644
--- a/core/lib/Drupal/Core/TypedData/TypedDataInterface.php
+++ b/core/lib/Drupal/Core/TypedData/TypedDataInterface.php
@@ -23,6 +23,14 @@
   public function getType();
 
   /**
+   * Gets the constraints.
+   *
+   * @return array
+   *   Array of constraints.
+   */
+  public function getConstraints();
+
+  /**
    * Gets the data definition.
    *
    * @return array
diff --git a/core/lib/Drupal/Core/Validation/Constraint/Constraint.php b/core/lib/Drupal/Core/Validation/Constraint/Constraint.php
new file mode 100644
index 0000000..604b399
--- /dev/null
+++ b/core/lib/Drupal/Core/Validation/Constraint/Constraint.php
@@ -0,0 +1,182 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Validation\Constraint\Constraint.
+ */
+
+use Drupal\Core\Annotation\Plugin;
+use Drupal\Core\Annotation\Translation;
+
+namespace Drupal\Core\Validation\Constraint;
+
+/**
+ * Abstract base class.
+ */
+abstract class Constraint implements ConstraintInterface {
+
+  /**
+   * The error message.
+   *
+   * @var string
+   */
+  protected $message = '';
+
+  /**
+   * The argumens for the error message placeholders.
+   *
+   * @var string
+   */
+  protected $message_arguments = array();
+
+  /**
+   * Type of the constraint.
+   *
+   * @var string
+   *   Either '', 'entity', 'field' or 'typedData'
+   */
+  protected $type = '';
+
+  /**
+   * The javascript rules.
+   *
+   * @var array
+   *   Array containing all javascript rules to apply, keyed by ....
+   */
+  protected $js_rules = array();
+
+  /**
+   * The (optional) custom javascript rule definitions.
+   *
+   * @var array
+   *   Array of rules keyed by short name, pointing to a js file for each rule.
+   */
+  protected $js_custom_rules = array();
+
+  /**
+   * The data definition.
+   *
+   * @var array
+   */
+  protected $definition = array();
+
+  /**
+   * The properties.
+   *
+   * @var array
+   */
+  protected $properties = array();
+
+  /**
+   * Constructs a new constraint.
+   *
+   * @param array $definition
+   *   Definition as specified in the plugin definition.
+   *
+   * @param array $properties
+   *   Properties passed by the entity, field or typed data.
+   */
+  public function __construct(array $definition, array $properties) {
+    $this->definition = $definition;
+
+    if (isset($definition['message'])) {
+      $this->message = $definition['message'];
+    }
+    if (isset($definition['type'])) {
+      $this->type = $definition['type'];
+    }
+
+    // Get properties from plugin definition.
+    if (isset($definition['properties'])) {
+      $this->properties = $definition['properties'];
+    }
+
+    // Passed in properties override the definition properties.
+    if ($properties && is_array($properties)) {
+      $this->properties = $properties + $this->properties;
+    }
+  }
+
+  /**
+   * Sets the properties to use.
+   *
+   * @param array $properties
+   */
+  public function setProperties($properties) {
+    $this->properties = $properties + $this->properties;
+  }
+
+  /**
+   * Gets the properties.
+   *
+   * @return array
+   */
+  public function getProperties() {
+    return $this->properties;
+  }
+
+  /**
+   * Gets the error message.
+   *
+   * @return string
+   *   Error message.
+   */
+  public function getMessage() {
+    return $this->message;
+  }
+
+  /**
+   * Gets the error message arguments.
+   *
+   * @return array
+   *   Keyed array with arguments for the message.
+   */
+  public function getMessageArguments() {
+    return $this->message_arguments;
+  }
+
+  /**
+   * Add an error message argument.
+   *
+   * @param type $placeholder
+   *   Placeholder that needs to be replaced.
+   *
+   * @param type $value
+   *   Value used by the replace.
+   */
+  protected function addMessageArguments($placeholder, $value) {
+    $this->message_arguments += array($placeholder => $value);
+  }
+
+  /**
+   * Convert the constraint to form API structure.
+   *
+   * @return array
+   *   Array usable by the form API.
+   */
+  public function convertToFormAPI() {
+    return array();
+  }
+
+  /**
+   * Gets the javascript rules.
+   *
+   * @return array
+   *   Array containing all javascript rules to apply, keyed by ....
+   *   This data will get passed to clientside validation.
+   */
+  public function getJavascriptRules() {
+    return $this->$js_rules;
+  }
+
+  /**
+   * Gets the custom javascript rules.
+   *
+   * @return array
+   *   Array of rules keyed by short name, pointing to a js file for each rule.
+   *   This data will get attached to the form.
+   */
+  public function getJavascriptCustomRules() {
+    return $this->js_custom_rules;
+  }
+}
diff --git a/core/lib/Drupal/Core/Validation/Constraint/ConstraintBundle.php b/core/lib/Drupal/Core/Validation/Constraint/ConstraintBundle.php
new file mode 100644
index 0000000..091bd26
--- /dev/null
+++ b/core/lib/Drupal/Core/Validation/Constraint/ConstraintBundle.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\ConstraintBundle.
+ *
+ * Not needed for the moment, only need if this will be a module.
+ */
+
+namespace Drupal\Core\Validation\Constraint;
+
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\HttpKernel\Bundle\Bundle;
+
+/**
+ * Constraint dependency injection container.
+ */
+class ConstraintBundle extends Bundle {
+
+  /**
+   * Overrides Symfony\Component\HttpKernel\Bundle\Bundle::build().
+   */
+  public function build(ContainerBuilder $container) {
+    // Register the ConstraintManager class with the dependency injection container.
+    $container->register('plugin.manager.constraint', 'Drupal\Core\Validation\Constraint\ConstraintManager');
+  }
+}
diff --git a/core/lib/Drupal/Core/Validation/Constraint/ConstraintFactory.php b/core/lib/Drupal/Core/Validation/Constraint/ConstraintFactory.php
new file mode 100644
index 0000000..349d2b2
--- /dev/null
+++ b/core/lib/Drupal/Core/Validation/Constraint/ConstraintFactory.php
@@ -0,0 +1,70 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\Core\Validation\Constraint\ConstraintFactory.
+ */
+
+namespace Drupal\Core\Validation\Constraint;
+
+use Drupal\Component\Plugin\Factory\DefaultFactory;
+use Drupal\Component\Plugin\Exception\PluginException;
+
+/**
+ * A factory for constraint objects.
+ *
+ */
+class ConstraintFactory extends DefaultFactory {
+
+  /**
+   * Create a constraint class.
+   *
+   * @param string $plugin_id
+   *   The id of a plugin, i.e. the data type.
+   * @param array $configuration
+   *   The plugin configuration, i.e. the data definition.
+   * @param mixed $target
+   *   The object that needs to be validated.
+   *
+   * @return Drupal\Core\Validator\Constraint\Constraint
+   */
+  public function create($plugin_id, array $configuration, $target) {
+    $definition = FALSE;
+    // Check to see if there's a more specific constraint.
+    if ($target) {
+      // Checks to see if the target_object is typed data.
+      if (is_subclass_of($target, 'Drupal\Core\TypedData\TypedData')) {
+        $definition = $this->discovery->getDefinition($plugin_id . '.' . $target->getType());
+      }
+      // Checks to see if the target_object is a field.
+      if (get_class($target) == 'Drupal\Core\Entity\Field\Type\Field' || is_subclass_of($target, 'Drupal\Core\Entity\Field\Type\Field')) {
+        $definition = $this->discovery->getDefinition($plugin_id . '.field');
+      }
+      // Checks to see if the target_object is an entity.
+      if (get_class($target) == 'Drupal\Core\Entity' || is_subclass_of($target, 'Drupal\Core\Entity\EntityInterface')) {
+        $definition = $this->discovery->getDefinition($plugin_id . '.entity');
+      }
+    }
+    if (!$definition) {
+      $definition = $this->discovery->getDefinition($plugin_id);
+    }
+    if ($definition) {
+      $plugin_class = $definition['class'];
+      return new $plugin_class($definition, $configuration);
+    }
+  }
+
+  /**
+   * Implements Drupal\Component\Plugin\Factory\FactoryInterface::createInstance().
+   *
+   * @param string $plugin_id
+   *   The id of a plugin, i.e. the data type.
+   * @param array $configuration
+   *   The plugin configuration, i.e. the data definition.
+   *
+   * @return Drupal\Core\Validator\Constraint\Constraint
+   */
+  public function createInstance($plugin_id, array $configuration) {
+    return $this->create($plugin_id, $configuration, NULL);
+  }
+}
diff --git a/core/lib/Drupal/Core/Validation/Constraint/ConstraintInterface.php b/core/lib/Drupal/Core/Validation/Constraint/ConstraintInterface.php
new file mode 100644
index 0000000..18079c7
--- /dev/null
+++ b/core/lib/Drupal/Core/Validation/Constraint/ConstraintInterface.php
@@ -0,0 +1,50 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Validation\Constraint\ConstraintInterface.
+ */
+
+namespace Drupal\Core\Validation\Constraint;
+
+/**
+ * Interface for constraints.
+ *
+ */
+interface ConstraintInterface {
+
+  /**
+   * Validate a constraint.
+   *
+   * @param $value
+   *   Value to validate.
+   *
+   * @return boolean
+   *   TRUE if the value is valid, FALSE otherwise.
+   */
+  public function validate($value);
+
+  /**
+   * Gets the error message.
+   *
+   * @return string
+   *   Error message.
+   */
+  public function getMessage();
+
+  /**
+   * Gets the error message arguments.
+   *
+   * @return array
+   *   Keyed array with arguments for the message.
+   */
+  public function getMessageArguments();
+
+  /**
+   * Convert the constraint to form API structure.
+   *
+   * @return array
+   *   Array usable by the form API.
+   */
+  public function convertToFormAPI();
+}
diff --git a/core/lib/Drupal/Core/Validation/Constraint/ConstraintManager.php b/core/lib/Drupal/Core/Validation/Constraint/ConstraintManager.php
new file mode 100644
index 0000000..091ab55
--- /dev/null
+++ b/core/lib/Drupal/Core/Validation/Constraint/ConstraintManager.php
@@ -0,0 +1,70 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Validation\Constraint\ConstraintManager.
+ */
+
+namespace Drupal\Core\Validation\Constraint;
+
+use Drupal\Component\Plugin\PluginManagerBase;
+use Drupal\Core\Plugin\Discovery\AnnotatedClassDiscovery;
+
+/**
+ * Constraint plugin manager.
+ */
+class ConstraintManager extends PluginManagerBase {
+  /**
+   * Overrides Drupal\Component\Plugin\PluginManagerBase::__construct().
+   */
+  public function __construct() {
+    $this->discovery = new AnnotatedClassDiscovery('Validation', 'Constraint');
+    $this->factory = new ConstraintFactory($this->discovery);
+  }
+
+  /**
+   * Implements Drupal\Component\Plugin\PluginManagerInterface::createInstance().
+   *
+   * @param string $plugin_id
+   *   The id of a plugin, i.e. the data type.
+   *
+   * @return Drupal\Core\TypedData\TypedDataInterface
+   */
+  public function createInstance($plugin_id, array $configuration = array()) {
+    return $this->factory->createInstance($plugin_id, $configuration);
+  }
+
+  /**
+   * Implements Drupal\Component\Plugin\PluginManagerInterface::createInstance().
+   *
+   * @param string $plugin_id
+   *   The id of a plugin, i.e. the data type.
+   *
+   * @return Drupal\Core\TypedData\TypedDataInterface
+   */
+  public function create($plugin_id, array $configuration = array(), $typed_data = NULL) {
+    return $this->factory->create($plugin_id, $configuration, $typed_data);
+  }
+
+  /**
+   * Returns a list of Constraints that apply to a certain type.
+   *
+   * @param string $type
+   *   The type to filter on.
+   * @param boolean $include_general
+   *   Whether or not to include the ones with an empty type.
+   */
+  public function getList($type = NULL, $include_general = TRUE) {
+    $constraints = array();
+    $definitions = $this->getDefinitions();
+    foreach ($definitions as $plugin_id => $definition) {
+      if ($type === NULL || $definition['type'] == $type) {
+        $constraints[$plugin_id] = $definition;
+      }
+      elseif ($type === '' && $include_general) {
+        $constraints[$plugin_id] = $definition;
+      }
+    }
+    return $constraints;
+  }
+}
diff --git a/core/lib/Drupal/Core/Validation/README.txt b/core/lib/Drupal/Core/Validation/README.txt
new file mode 100755
index 0000000..6591347
--- /dev/null
+++ b/core/lib/Drupal/Core/Validation/README.txt
@@ -0,0 +1,123 @@
+Rough technical overview of how it is implemented right now
+
+Constraints can be defined on 3 levels:
+entity
+ - field [0..n]
+   - typedData [1..n]
+ - property [1..n]
+   - typedData [1..n]
+
+FormController->build() calls entity->getConstraintsObjects()
+  - gets a list of constraints keyed by field/property name
+
+Each constraint has a method convertToFormAPI() which returns an array containing keyed data compatibnle with the form API
+ex:
+return array(
+  '#type' => 'number',
+  '#min' => current($this->settings),
+);
+
+FormController->validate() calls $entity->validate
+  this loops over all fields and typedData, calling validate() on each
+  validate() will get the constraints and validates the value/field
+  all violations are collected and returned to the parent
+  FormController uses set_form_error for each violation
+
+Constraints uses the Plugin system for it's definition
+ex:
+ * @Plugin(
+ *   id = "min",
+ *   label = @Translation("MinValue"),
+ *   message = @Translation("The value of %label has to be greater than %min.")
+
+The message is added to the plugin system so it gets detected by l.d.o.
+The Constraint base class has a method addMessageArguments so it can prefill some placeholders
+ex:
+$this->addMessageArguments('%min', current($this->settings));
+
+The FormController calls uses getMessage, getMessageArguments, getObjectLabel to build the (translated) message.
+ex:
+form_set_error('error', 
+  t($violation->getMessage(), 
+  $violation->getMessageArguments() + array('%label' => $violation->getObjectLabel()))
+);
+
+Constraints:
+Indented to show parent - child relationship.
+The factory used to choose the most appropriate Constraint accepts an object as parameter, this is either a TypedData, a Field or an Entity. The factory looks at the type of the object ('integer, 'field', ...) and uses the most specific class it can find.
+
+Constraint.php
+  EntityTypeConstraint.php --> array('#choose' => array_keys(entity_get_info()))
+  EqualFieldsConstraint.php --> array('#equal' => array($this->settings[0], $this->settings[1]))
+  MinValueConstraint.php --> array('#type' => 'number', '#min' => current($this->settings))
+    MinValueIntegerConstraint.php --> array('#type' => 'number', '#min' => current($this->settings))
+  NotNullConstraint.php --> array('#notnull' => TRUE)
+  RequiredConstraint.php --> array('#required' => TRUE)
+    RequiredFieldConstraint.php --> inherited
+
+Connect the dots: Entity to FormAPI
+entity -> $form['#constraints']
+  - field -> $form['field_name']['#constraints']
+  - typedata -> $form['field_name'][$delta]['#constraints']
+
+Form key always has to match the field_name, or use #bound_to
+FormController adds data (Constraint) to the form elements, in phase 1 it also adds the FormAPI structure so it can run side by side.
+AfterBuild converts Constraints to FormAPI structure, in phase 1 some FormAPI elements are supported as well.
+
+@TODO: getConstraints on each field has to return full objects
+@TODO: add afterBuild method to FormController to handle the conversion
+
+
+
+Follow up issues:
+Add support for validation on forms not tight to an entity.
+
+Add clientside validation support, see [#1797438]
+  add it in an afterBuild phase, so form_alter still works.
+  use clientside_validation, but allow rule definition on the constraint.
+
+Add constraint selection on instance_field_settings_form
+  which constraints do we need to show: structured tree containing field_type - widget_type
+  some constraint cannot be removed (like IntegerConstraint on an Integer text field)
+
+List all field types and subtypes (like integer select list) and
+  provide all constraints
+  organize the constraints in a tree (inheritance) structure
+
+How to handle conflicts (like max < min)?
+
+Do we need weight/importance/priority on Constraints?
+
+Decide if we still support old '#required'
+  example before
+    $form['name'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Name'),
+      '#default_value' => 'default',
+      '#size' => 60,
+      '#weight' => -10,
+      '#maxlength' => 128,
+      '#required' => TRUE,
+    );
+  example after
+    $form['name'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Name'),
+      '#default_value' => 'default',
+      '#size' => 60,
+      '#weight' => -10,
+      '#constraints' => array(
+        new MaxLengthConstraint(array(
+          'message' => 'or use default one from constraint',
+          'maxlength' => 128,
+        )),
+        new RequiredFieldConstraint(array(
+          'message' => 'or use default one from constraint',
+        )),
+      ),
+    );
+
+Validation phase has to pickup the custom messages
+
+
+
diff --git a/core/lib/Drupal/Core/Validation/Validator/ValidatorInterface.php b/core/lib/Drupal/Core/Validation/Validator/ValidatorInterface.php
new file mode 100644
index 0000000..739e9ca
--- /dev/null
+++ b/core/lib/Drupal/Core/Validation/Validator/ValidatorInterface.php
@@ -0,0 +1,23 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Validation\Validator\ValidatorInterface.
+ */
+
+namespace Drupal\Core\Validation\Validator;
+
+/**
+ * Interface for validators.
+ *
+ */
+interface ValidatorInterface {
+
+  /**
+   * Validate.
+   *
+   * @return array
+   *   Array of violations.
+   */
+  public function validate();
+}
diff --git a/core/lib/Drupal/Core/Validation/Violation/EntityViolation.php b/core/lib/Drupal/Core/Validation/Violation/EntityViolation.php
new file mode 100644
index 0000000..b37a3fb
--- /dev/null
+++ b/core/lib/Drupal/Core/Validation/Violation/EntityViolation.php
@@ -0,0 +1,35 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\Core\Validation\Violation\EntityViolation.
+ */
+
+namespace Drupal\Core\Validation\Violation;
+
+/**
+ * Violation class for entities.
+ */
+class EntityViolation extends Violation {
+
+  /**
+   * Get the entity that caused the violation.
+   *
+   * @return Drupal\Core\Entity
+   *   The entity that failed validation.
+   */
+  public function getTarget() {
+    return $this->target;
+  }
+
+  /**
+   * Get the label of the entity that caused the violation.
+   *
+   * @return string
+   *   Label of the entity.
+   */
+  public function getTargetLabel() {
+    return $this->target->label();
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Validation/Violation/FieldViolation.php b/core/lib/Drupal/Core/Validation/Violation/FieldViolation.php
new file mode 100644
index 0000000..f4ed144
--- /dev/null
+++ b/core/lib/Drupal/Core/Validation/Violation/FieldViolation.php
@@ -0,0 +1,35 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\Core\Validation\Violation\FieldViolation.
+ */
+
+namespace Drupal\Core\Validation\Violation;
+
+/**
+ * Violation class for fields.
+ */
+class FieldViolation extends Violation {
+
+  /**
+   * Get the field that caused the violation.
+   *
+   * @return Drupal\Core\Entity\Field\Type\Field
+   *   The field that failed validation.
+   */
+  public function getTarget() {
+    return $this->target;
+  }
+
+  /**
+   * Get the label of the field that caused the violation.
+   *
+   * @return string
+   *   Label of the field.
+   */
+  public function getTargetLabel() {
+    return $this->target->getName();
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Validation/Violation/TypedDataViolation.php b/core/lib/Drupal/Core/Validation/Violation/TypedDataViolation.php
new file mode 100644
index 0000000..a3cd7b6
--- /dev/null
+++ b/core/lib/Drupal/Core/Validation/Violation/TypedDataViolation.php
@@ -0,0 +1,35 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\Core\Validation\Violation\TypedDataViolation.
+ */
+
+namespace Drupal\Core\Validation\Violation;
+
+/**
+ * Violation class for typed data.
+ */
+class TypedDataViolation extends Violation {
+
+  /**
+   * Get the typed data that caused the violation.
+   *
+   * @return Drupal\Core\TypedData\TypedDataInterface
+   *   The typed data that failed validation.
+   */
+  public function getTarget() {
+    return $this->target;
+  }
+
+  /**
+   * Get the label of the typed data that caused the violation.
+   *
+   * @return string
+   *   Label of the typed data.
+   */
+  public function getTargetLabel() {
+    return $this->target->getString();
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Validation/Violation/Violation.php b/core/lib/Drupal/Core/Validation/Violation/Violation.php
new file mode 100644
index 0000000..e645ded
--- /dev/null
+++ b/core/lib/Drupal/Core/Validation/Violation/Violation.php
@@ -0,0 +1,79 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\Core\Validation\Violation\Violation.
+ */
+
+namespace Drupal\Core\Validation\Violation;
+
+/**
+ * Violation class to store the failing constraint and related data.
+ */
+class Violation implements ViolationInterface {
+
+  protected $constraint;
+  protected $target;
+
+  /**
+   *
+   * @param Drupal\Core\Validation\Constraint\Constraint $constraint
+   *   Constraint that didn't validate.
+   * @param Object $target
+   *   Object that failed validation.
+   */
+  public function __construct($constraint, $target) {
+    $this->constraint = $constraint;
+    $this->target = $target;
+  }
+
+  /**
+   * Get the error message.
+   *
+   * @return string
+   *   Error message.
+   */
+  public function getMessage() {
+    return $this->constraint->getMessage();
+  }
+
+  /**
+   * Get the error message arguments.
+   *
+   * @return array
+   *   Keyed array with arguments for the message.
+   */
+  public function getMessageArguments() {
+    return $this->constraint->getMessageArguments();
+  }
+
+  /**
+   * Get the constraint.
+   *
+   * @return Drupal\Core\Constraint\ConstraintInterface
+   *   The constraint.
+   */
+  public function getConstraint() {
+    return $this->constraint;
+  }
+
+  /**
+   * Get the typed data that caused the violation.
+   *
+   * @return mixed
+   *   The typed data.
+   */
+  public function getTarget() {
+    return $this->target;
+  }
+
+  /**
+   * Get the typed data that caused the violation.
+   *
+   * @return mixed
+   *   The typed data.
+   */
+  public function getTargetLabel() {
+    return get_class($this->target);
+  }
+}
diff --git a/core/lib/Drupal/Core/Validation/Violation/ViolationInterface.php b/core/lib/Drupal/Core/Validation/Violation/ViolationInterface.php
new file mode 100644
index 0000000..8d0c344
--- /dev/null
+++ b/core/lib/Drupal/Core/Validation/Violation/ViolationInterface.php
@@ -0,0 +1,40 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Validation\Violation\ViolationInterface.
+ */
+
+namespace Drupal\Core\Validation\Violation;
+
+/**
+ * Interface for violations.
+ *
+ */
+interface ViolationInterface {
+
+  /**
+   * Get the constraint.
+   *
+   * @return Drupal\Core\Constraint\ConstraintInterface
+   *   The constraint.
+   */
+  public function getConstraint();
+
+  /**
+   * Get the object that got validated.
+   *
+   * @return mixed
+   *   The object being validated.
+   */
+  public function getTarget();
+
+  /**
+   * Get the object label that got validated.
+   *
+   * @return string
+   *   The label of the object being validated.
+   */
+  public function getTargetLabel();
+
+}
diff --git a/core/modules/field/field.crud.inc b/core/modules/field/field.crud.inc
index b8e2015..4ec1097 100644
--- a/core/modules/field/field.crud.inc
+++ b/core/modules/field/field.crud.inc
@@ -591,6 +591,7 @@ function _field_write_instance(&$instance, $update = FALSE) {
     'label' => $instance['field_name'],
     'description' => '',
     'deleted' => 0,
+    'constraints' => array(),
   );
 
   // Set default instance settings.
diff --git a/core/modules/field_ui/field_ui.admin.inc b/core/modules/field_ui/field_ui.admin.inc
index d301d76..81a66af 100644
--- a/core/modules/field_ui/field_ui.admin.inc
+++ b/core/modules/field_ui/field_ui.admin.inc
@@ -862,6 +862,27 @@ function field_ui_field_edit_form($form, &$form_state, $instance) {
     '#weight' => -10,
   );
 
+  // Allow user to select which constraints are enabled.
+  // @todo Construct a helper to easily build this.
+  // @todo Some constraints require parameters.
+  // @todo Some constraints only apply to certain fields.
+  $constraints = drupal_container()->get('constraint')->getList('field', FALSE);
+  if ($constraints) {
+    $form['instance']['constraints'] = array(
+      '#tree' => TRUE,
+      '#type' => 'fieldset',
+      '#title' => t('Enable the constraints you want to apply'),
+    );
+    foreach ($constraints as $constraint_id => $constraint_info) {
+      $form['instance']['constraints'][$constraint_id] = array(
+        '#type' => 'checkbox',
+        '#title' => t($constraints[$constraint_id]['label']),
+        '#default_value' => !empty($instance['constraints'][$constraint_id]),
+        '#weight' => -4,
+      );
+    }
+  }
+
   $form['instance']['required'] = array(
     '#type' => 'checkbox',
     '#title' => t('Required field'),
diff --git a/core/modules/system/lib/Drupal/system/Tests/Validation/ValidationConstraintTest.php b/core/modules/system/lib/Drupal/system/Tests/Validation/ValidationConstraintTest.php
new file mode 100644
index 0000000..a95b622
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Tests/Validation/ValidationConstraintTest.php
@@ -0,0 +1,71 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\system\Tests\Validation\ValidationConstraintTest.
+*/
+
+namespace Drupal\system\Tests\Validation;
+
+use Drupal\simpletest\UnitTestBase;
+use Drupal\Core\Plugin\Validation\Constraint;
+
+/**
+ * Tests the Drupal\Core\Validation\Constraint class.
+ */
+class ValidationConstraintTest extends UnitTestBase {
+
+  public static function getInfo() {
+    return array(
+      'name' => 'ValidationConstraintTest',
+      'description' => "Test constraint.",
+      'group' => 'Validation',
+    );
+  }
+
+  public function setUp() {
+    parent::setUp();
+  }
+
+  /**
+   * Tests NotNullConstraint.
+   */
+  public function testNotNullConstraint() {
+    $constraint = new Constraint\NotNullConstraint(array(), array());
+    $this->assertTrue($constraint->validate(1));
+    $this->assertTrue($constraint->validate(0));
+    $this->assertFalse($constraint->validate(NULL));
+  }
+  
+  /**
+   * Tests RequiredConstraint.
+   */
+  public function testRequiredConstraint() {
+    $constraint = new Constraint\RequiredConstraint(array(), array());
+    $this->assertTrue($constraint->validate('a value'));
+    $this->assertTrue($constraint->validate(array('a')));
+    $this->assertFalse($constraint->validate(NULL));
+    $this->assertFalse($constraint->validate(FALSE));
+    $this->assertFalse($constraint->validate(''));
+  }
+
+  /**
+   * Tests MinValueConstraint
+   */
+  public function testMinValueConstraint() {
+    // Test using the default value for min.
+    $constraint = new Constraint\MinValueConstraint(array('properties' => array('min' => 0)), array());
+    $this->assertTrue($constraint->validate(5));
+    $this->assertTrue($constraint->validate(0));
+    $this->assertTrue($constraint->validate(''));
+    $this->assertFalse($constraint->validate(-2));
+
+    // Test using a custom value for min.
+    $constraint = new Constraint\MinValueConstraint(array('properties' => array('min' => 0)), array('min' => 5));
+    $this->assertTrue($constraint->validate(5));
+    $this->assertFalse($constraint->validate(4));
+    $this->assertFalse($constraint->validate(0));
+    $this->assertFalse($constraint->validate(-10));
+    $this->assertFalse($constraint->validate(''));
+  }
+}
diff --git a/core/modules/system/tests/modules/entity_test/entity_test.info b/core/modules/system/tests/modules/entity_test/entity_test.info
index ce49e8a..e460ae0 100644
--- a/core/modules/system/tests/modules/entity_test/entity_test.info
+++ b/core/modules/system/tests/modules/entity_test/entity_test.info
@@ -4,4 +4,4 @@ package = Testing
 version = VERSION
 core = 8.x
 dependencies[] = field
-hidden = TRUE
+;hidden = TRUE
diff --git a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/EntityTestFormController.php b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/EntityTestFormController.php
index a65f06f..6410b9e 100644
--- a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/EntityTestFormController.php
+++ b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/EntityTestFormController.php
@@ -27,6 +27,7 @@ public function form(array $form, array &$form_state, EntityInterface $entity) {
       '#type' => 'textfield',
       '#title' => t('Name'),
       '#default_value' => $translation->name->value,
+      '#constraints' => $translation->name->getConstraints(),
       '#size' => 60,
       '#maxlength' => 128,
       '#required' => TRUE,
@@ -37,6 +38,7 @@ public function form(array $form, array &$form_state, EntityInterface $entity) {
       '#type' => 'textfield',
       '#title' => 'UID',
       '#default_value' => $translation->user_id->value,
+      '#constraints' => $translation->user_id->getConstraints(),
       '#size' => 60,
       '#maxlength' => 128,
       '#required' => TRUE,
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 3c948bd..e9f6d95 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
@@ -36,6 +36,16 @@
 class EntityTest extends EntityNG {
 
   /**
+   *  How to add entity constraints
+   *  constraints = {
+   *     "equal.field" = {
+   *       "user_id",
+   *       "name"
+   *     }
+   *   }
+   */
+    
+  /**
    * The entity ID.
    *
    * @var \Drupal\Core\Entity\Field\FieldInterface
