angular.module('read-and-learn').controller('readController', function ($scope, $rootScope, $http, Upload, $timeout) {

  $scope.documents = null;

  var cluster_id = 'scf9b13b48_1835_48cf_ac7f_143b7bb8712b';
  var config_id = 'example-config';
  var collection_id = 'example-collection3';

  getAllDocuments();

  $scope.read = function(file) {
    $scope.documents = null;

    if (file)
      $scope.file = 'data/' + file;
    else
      $scope.file = 'data/samplePDF.pdf';

    // Call API to convert documents into normalized sets of answer units
    $http({
      method: 'POST',
      url: '/api/document-conversion',
      data: { 'file': $scope.file }
    }).then(function successCallback(response) {

      var author = getDocumentAuthor(response.data.metadata);

      var answersToConvert = response.data.answer_units.length;
      var answersConverted = 0;

      for (var i = 0; i < response.data.answer_units.length; i++) {
        var doc = {};
        doc.id = author + ' ' + $scope.file + (i + 1); // TODO Improve solution to check if document is already readed
        doc.author = author;
        doc.bibliography = $scope.file;
        doc.title = response.data.answer_units[i].title;
        doc.body = response.data.answer_units[i].content[0].text;

        console.log(doc);

        // Add documents to a collection
        $http({
          method: 'POST',
          url: '/api/retrieve-and-rank/'+cluster_id+'/'+config_id+'/'+collection_id,
          data: {
            'data': doc
          }
        }).then(function successCallback(response) {
          answersConverted++;
          if (answersConverted === answersToConvert)
            getAllDocuments();

        }, function errorCallback(response) {
          // TODO Treat error
          getAllDocuments();
        });
      }

    }, function errorCallback(response) {
      // TODO Treat error
      getAllDocuments();
    });
  };

  $scope.upload = function(files, errFiles) {
    $scope.files = files;
    $scope.errFiles = errFiles;
    angular.forEach(files, function(file) {
      file.upload = Upload.upload({
        url: '/api/upload',
        data: {
          file: file
        }
      });

      file.upload.then(function successCallback(response) {
        $timeout(function () {
          file.result = response.data;
          // Convert document
          $scope.read(response.config.data.file.name);
        });
      }, function errorCallback(response) {
        if (response.status > 0)
          $scope.errorMsg = response.status + ': ' + response.data;
      }, function (evt) {
        file.progress = Math.min(100, parseInt(100.0 * evt.loaded / evt.total));
      });
    });
  };

  function getAllDocuments() {
    $http({
      method: 'GET',
      url: '/api/retrieve-and-rank/'+cluster_id+'/'+config_id+'/'+collection_id+'/documents'
    }).then(function successCallback(response) {
      if (response.data.docs.length > 0)
        $scope.documents = [];

      $scope.answers = 0;

      // Count distinct documents
      var currentDoc = null;
      for (var i = 0; i < response.data.docs.length; i++) {
        if (response.data.docs[i].bibliography[0] !== currentDoc) {
          var doc = {
            "id" : response.data.docs[i].id[0],
            "author" : response.data.docs[i].author[0],
            "bibliography" : response.data.docs[i].bibliography[0],
            "title" : response.data.docs[i].title[0],
            "body" : response.data.docs[i].body[0]
          };
          $scope.documents.push(doc);
          currentDoc = response.data.docs[i].bibliography[0];
        }
      }
      // Count answer units
      $scope.answers = response.data.numFound;
    }, function errorCallback(response) {
      // TODO Treat error
    });
  }

  /**
   * Find author information in document metadata
   * @param  {Object}   metadata  Metadata array
   * @return {String}             Author name
   *
   * @author  filipecorrea@br.ibm.com
   * @since   2015-12-16
   * @version 0.1.0
   */
  function getDocumentAuthor(metadata) {
    for (var i = 0; i < metadata.length; i++) {
      if (metadata[i].name === 'author')
        return metadata[i].content;
    }
  }

});

@@ -1270,35 +1270,8 @@
 t;%0A%0A
-        console.log(doc);%0A%0A
     
@@ -3251,16 +3251,49 @@
 uthor%22 :
+ (response.data.docs%5Bi%5D.author) ?
  respons
@@ -3316,16 +3316,21 @@
 uthor%5B0%5D
+ : ''
 ,%0A      
@@ -3347,24 +3347,63 @@
 liography%22 :
+ (response.data.docs%5Bi%5D.bibliography) ?
  response.da
@@ -3428,16 +3428,21 @@
 raphy%5B0%5D
+ : ''
 ,%0A      
@@ -3456,16 +3456,48 @@
 title%22 :
+ (response.data.docs%5Bi%5D.title) ?
  respons
@@ -3519,16 +3519,21 @@
 title%5B0%5D
+ : ''
 ,%0A      
@@ -3546,16 +3546,47 @@
 %22body%22 :
+ (response.data.docs%5Bi%5D.body) ?
  respons
@@ -3607,16 +3607,21 @@
 .body%5B0%5D
+ : ''
 %0A       
@@ -3687,37 +3687,19 @@
 ntDoc = 
-response.data.docs%5Bi%5D
+doc
 .bibliog
@@ -3703,19 +3703,16 @@
 iography
-%5B0%5D
 ;%0A      
@@ -4161,24 +4161,73 @@
 metadata) %7B%0A
+    console.log(metadata);%0A    if (metadata) %7B%0A  
     for (var
@@ -4264,24 +4264,26 @@
 ++) %7B%0A      
+  
 if (metadata
@@ -4313,16 +4313,18 @@
         
+  
 return m
@@ -4343,21 +4343,65 @@
 ontent;%0A
-    %7D
+%0A        return '';%0A      %7D%0A    %7D%0A%0A    return '';
 %0A  %7D%0A%0A%7D)

Add interface data validation