diff --git a/addressfield.module b/addressfield.module
index 177d92b..e90d01b 100644
--- a/addressfield.module
+++ b/addressfield.module
@@ -146,10 +146,31 @@ function addressfield_process_format_form($format, &$form_state, $complete_form)
     ctools_plugin_load_function('addressfield', 'format', $handler, 'format callback');
   }
 
-  _addressfield_process_format_form($format, $format['#address'], $format['#required']);
+  // Load field infos and prepare settings concerning non empty fields
+  $field = field_info_field($format['#field_name']);
+  $required = array(
+    'general' => !empty($format['#required']),
+    'non_empty_fields' => $field['settings']['non_empty_fields'],
+    'non_empty_fields_op' => $field['settings']['non_empty_fields_op'],
+  );
+
+  _addressfield_process_format_form($format, $format['#address'], $required);
+
+  // If the subfields operator is set to "any" add a note to the field for the
+  // users to understand which fields are important.
+  if (!$required['general']) {
+    $format['#description'] = t('You must at least fill one of the fields marked with a double asterisk (**) or this address field will be considered as empty.');
+  }
+  elseif ($field['settings']['non_empty_fields_op'] == 'or') {
+    $format['#description'] = t('This field is required so you must at least fill one of the fields marked with a double asterisk (**).');
+  }
+
   return $format;
 }
 
+/**
+ * Build one field's delta form.
+ */
 function _addressfield_process_format_form(&$format, $address, $required) {
   foreach (element_children($format) as $key) {
     $child = &$format[$key];
@@ -170,9 +191,18 @@ function _addressfield_process_format_form(&$format, $address, $required) {
           $child['#type'] = 'textfield';
         }
       }
-      if (!$required) {
+      // Subfields are required by default
+      // Keep the subfields as required only if the main field is required and
+      // if the non-empty operator is set to "all" and the subfield is required 
+      // for the main field to be considered as filled.
+      if (!$required['general'] || $required['non_empty_fields_op'] == 'or' || ($required['non_empty_fields_op'] == 'and' && empty($required['non_empty_fields'][$key]))) {
         unset($child['#required']);
       }
+      // On a field using an "any" operator, add a special symbol to 
+      // indicate which subfields should be entered to fill the field.
+      if ((!$required['general'] || $required['non_empty_fields_op'] == 'or') && !empty($required['non_empty_fields'][$key])) {
+        $child['#title'] .= ' **';
+      }
 
       $child['#default_value'] = $address[$key];
     }
@@ -300,7 +330,10 @@ function addressfield_field_info() {
   $fields['addressfield'] = array(
     'label' => t('Postal address'),
     'description' => t('A field type used for storing postal addresses according the xNAL standard.'),
-    'settings' => array(),
+    'settings' => array(
+      'non_empty_fields' => array('country' => 'country'),
+      'non_empty_fields_op' => 'or',
+    ),
     'instance_settings' => array(),
     'default_widget' => 'addressfield_standard',
     'default_formatter' => 'addressfield_default',
@@ -312,6 +345,33 @@ function addressfield_field_info() {
 }
 
 /**
+ * Implements hook_field_settings_form().
+ */
+function addressfield_field_settings_form($field, $instance, $has_data) {
+  $form = array();
+  $options = array();
+  foreach($field['columns'] as $name => $info) {
+    $options[$name] = $info['description'];
+  }
+  $form['non_empty_fields'] = array(
+    '#title' => t('Required fields for non-empty address'),
+    '#description' => t('Select the fields that trigger a value to be considered as not empty. The value of the operator field below will define if any or all of this fields must have a value, for the address to be considered non-empty, i.e. the address will be stored and displayed.'),
+    '#options' => $options,
+    '#type' => 'checkboxes',
+    '#default_value' => !empty($field['settings']['non_empty_fields']) ? $field['settings']['non_empty_fields'] : array('country'),
+    '#required' => TRUE,
+  );
+  $form['non_empty_fields_op'] = array(
+    '#title' => t('Operator'),
+    '#options' => array('and' => 'All', 'or' => 'Any'),
+    '#type' => 'radios',
+    '#default_value' => !empty($field['settings']['non_empty_fields_op']) ? $field['settings']['non_empty_fields_op'] : 'any',
+    '#required' => TRUE,
+  );
+  return $form;
+}
+
+/**
  * Returns an array of default values for the addressfield form elements.
  */
 function addressfield_default_values($available_countries = NULL) {
@@ -348,9 +408,68 @@ function addressfield_default_values($available_countries = NULL) {
  * Implements hook_field_is_empty().
  */
 function addressfield_field_is_empty($item, $field) {
-  // Every address field must have at least a country value or it is considered
-  // empty, even if it has name information.
-  return empty($item['country']);
+  $non_empty_fields = !empty($field['settings']['non_empty_fields']) ? array_filter($field['settings']['non_empty_fields']) : array('country' => 'country');
+  $non_empty_fields_op = !empty($field['settings']['non_empty_fields_op']) ? $field['settings']['non_empty_fields_op'] : 'or';
+  $filtered_item = array_filter(array_intersect_key($item, $non_empty_fields));
+  if ($non_empty_fields_op == 'or') {
+    $result = empty($filtered_item);
+  }
+  else {
+    $result = count($filtered_item) != count($non_empty_fields);
+  }
+  return $result;
+}
+
+/**
+ * Implements hook_field_validate().
+ *
+ * For each field delta, define if all subfields are properly filled.
+ *
+ * If the field is required, the only delta to be considered as required is the
+ * first one.
+ * If the subfields operator is "all" (and) all the marked subfields must be 
+ * filled for the field to be valid.
+ * If the subfields operator is "any" (or) at least one of the marked subfields 
+ * must be filled for the field to be valid.
+ * In all cases, if the field is not valid regarding the previous rules, but one
+ * of the subfields has been filled, send an error to the user to alert him. 
+ */
+function addressfield_field_validate($entity_type, $entity, $field, $instance, $langcode, $items, &$errors) {
+  $first = TRUE;
+  foreach ($items as $delta => $item) {
+    // Field is considered as empty.
+    if (addressfield_field_is_empty($item, $field)) {
+      // Get real address subfields' values and remove system ones
+      $useful_values = array_filter($item);
+      unset($useful_values['element_key']);
+      unset($useful_values['country']);
+      unset($useful_values['_weight']);
+      // Prepare field machine name
+      $field_name = implode('][', array($field['field_name'], $langcode, $delta));
+
+      // If the field is required and the first delta.
+      // The test on the entity type is a hack to avoid an error to be fired in 
+      // the field configuration screen.
+      if ($instance['required'] && $first && !empty($entity_type)) {
+        if ($field['settings']['non_empty_fields_op'] == 'and') {
+          form_set_error($field_name, t('The %fieldname field is required so you must fill all the fields marked with a double asterisk (**).', array('%fieldname' => check_plain($instance['label']))));
+        }
+        else {
+          form_set_error($field_name, t('The %fieldname field is required so you must fill at least one of the fields marked with a double asterisk (**).', array('%fieldname' => check_plain($instance['label']))));
+        }
+      }
+      // If the field is not required but some subfields are filled.
+      elseif (!empty($useful_values)) {
+        if ($field['settings']['non_empty_fields_op'] == 'and') {
+          form_set_error($field_name, t('It seems you tried to fill the %fieldname field but you must fill all the fields marked with a double asterisk (**) for this address to be valid.', array('%fieldname' => check_plain($instance['label']))));
+        }
+        else {
+          form_set_error($field_name, t('It seems you tried to fill the %fieldname field but you must fill at least one of the fields marked with a double asterisk (**) for this address to be valid.', array('%fieldname' => check_plain($instance['label']))));
+        }
+      }
+    }
+    $first = FALSE;
+  }
 }
 
 /**
