diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000000000000000000000000000000000000..1d8309a56b34f50343a9534ec68217e30754cb64
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,10 @@
+.git
+.dockerignore
+docker-compose.yml
+docker-compose.yaml
+Dockerfile
+.env*
+package-lock.json
+node_modules
+*.bak
+.editorconfig
diff --git a/.env-form-api b/.env-form-api
new file mode 100644
index 0000000000000000000000000000000000000000..72506c40968dca4e9ec64d22abd4f8a6c59457a4
--- /dev/null
+++ b/.env-form-api
@@ -0,0 +1 @@
+FORM_CREATOR_API_NODE_ENV=development
diff --git a/.gitignore b/.gitignore
index dd27e1a2765997dd47f9cd31bb36672e3269ce13..73ebd01968826de5bb4291d1bcd9d54c64e1d6e8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,4 +13,7 @@
 /coverage
 /build
 /dist
-
+*.bak
+.env
+docker-compose.yaml
+.editorconfig
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 294eafe63e05610927b192f5074483021dfef1c7..fdf4292066895a8eb033a0321249efb3e7869930 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,4 +1,17 @@
-image: node:6.12.2
+image: node:10-stretch
+services:
+    - postgres:10
+
+variables:
+    POSTGRES_DB: 'form-creator'
+    POSTGRES_HOST: 'postgres'
+    PGPASSWORD: '123mudar'
+    POSTGRES_PASSWORD: '123mudar'
+    POSTGRES_USER: 'runner'
+    POSTGRES_PASSWORD: '123mudar'
+    POSTGRES_PORT: 5432
+    image_version: ''
+    DOCKER_URL: 'dockerregistry.c3sl.ufpr.br:5000/c3sl/simmctic-form-creator-api'
 
 cache:
     paths:
@@ -6,10 +19,24 @@ cache:
 
 stages:
     - test
-
+    - build
+    - deploy
 
 run_test:
     stage: test
+    before_script:
+      - apt-get update -q -y
+      - apt-get install wget gnupg -y
+      - echo "deb http://apt.postgresql.org/pub/repos/apt/ stretch-pgdg main" > /etc/apt/sources.list.d/pgdg.list
+      - wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add -
+      - apt-get update -q -y
+      - apt-get install -y postgresql-client-10
+      - git clone --recurse-submodules https://gitlab.c3sl.ufpr.br/simmctic/form-creator/form-creator-database.git form-creator-database
+      - cd  form-creator-database
+      - psql-manager/manager.sh create workspace
+      - psql-manager/manager.sh fixture workspace
+      - cd ..
+      - rm -rf form-creator-database
     script:
         - yarn install --frozen-lockfile --silent --non-interactive
         - ln -s config.env.example config/test.env
@@ -17,3 +44,24 @@ run_test:
         - yarn run lint
     tags:
         - node
+
+build:
+    stage: build
+    script:
+        - image_version=$(grep \"version\" ./package.json |  cut -f2 -d':'| sed -e 's/"\|,//g' | tr -d ' ')
+        - docker build -t ${DOCKER_URL}:${image_version} -t ${DOCKER_URL}:latest .
+    tags:
+        - docker
+        - build
+
+deploy:
+    stage: deploy
+    script:
+        - image_version=$(grep \"version\" ./package.json |  cut -f2 -d':'| sed -e 's/"\|,//g' | tr -d ' ')
+        - docker push ${DOCKER_URL}:${image_version}
+        - docker push ${DOCKER_URL}:latest
+    tags:
+        - docker
+        - build
+    only:
+        - master
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000000000000000000000000000000000000..b7f04653bcfc2a735badcc78f03337f20f3ddbc6
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,233 @@
+# Changelog
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
+and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+
+## 1.0.0 - 19-08-2019
+### Changed
+- Create a stable version
+
+## 0.0.27 - 15-08-2019
+### Added
+- DbHandler methods to update database #32 (Gianfranco)
+- Reenabled UpdateType on EnumHandler wich reenabled a input
+- Update route tests
+### Changed
+- writeInputWithFormId method to return the id
+- readInputWithFormId to not list the disabled inputs
+- Fix tests of DiffHandler and DbHandler class
+- DiffHandler to detect reenabled requests
+- Update route to call the updateDatabase method
+
+
+## 0.0.26 - 26-07-2019
+### Changed
+- Write form route to create a formUpdate on create a new form #33 (Gianfranco)
+- Fix DiffHandler to add inputs with id
+- Fix tests of DiffHandler, OptHandler and Form route
+
+
+## 0.0.25 - 25-07-2019
+### Changed
+- Renamed routes from 'forms' to 'form' #31 (Gianfranco)
+
+
+## 0.0.24 - 23-07-2019
+### Added
+- DiffHandler to find out the differences between two forms (Gianfranco)
+- Sorter with methods to sort arrays
+- DiffHandler and Sorter tests
+### Changed
+- Main archive to add an update route #27
+- Api controller to update forms
+- TestHandler to test two FormUpdate objects
+
+
+## 0.0.23 - 10-07-2019
+### Changed
+- FormUpdate to receive an Form class (Gianfranco)
+- InputUpdate to receive an Input class
+- FormUpdate to receive an array of inputs
+- OptHandler to handle with the new features
+
+
+## 0.0.22 - 09-07-2019
+### Added
+- Created a new enum UpdateType (Gianfranco)
+- Add stringfy and parse methods to UpdateType
+
+
+## 0.0.21 - 01-07-2019
+### Added
+- Add InputUpdate and a FormUpdate Class to store updates from inputs and forms #26 (Gianfranco)
+- Create writeFormUpdate method to insert a FormUpdate into database
+- Create writeInputUpdate method to insert a InputUpdate into database
+- Create updateForm method to unify writeFormUpdate and writeInputUpdate methods
+- Create inputUpdate method in OptHandler
+- Create formUpdate method in OptHandler
+
+
+## 0.0.20 - 28-06-2019
+## Changed
+- Class Input to receive a Enabled atribute (Gianfranco)
+
+
+## 0.0.19 - 12-06-2019
+### Added
+- A route to POST a form Answer #21 (Horstmann)
+- Create ValidationError Class that extends error class, with the objective to return a dictionary of invalid answers (Horstmann)
+### Changed
+- DbHandler's tests to suite with new forms answers added (Horstmann)
+- ValidationHandler to validate a Forms Answer instead of inputsAnswer
+- ValidationHandler's tests to suite new method to validate a Forms Answer
+
+
+## 0.0.18 - 25-05-2019
+### Added
+- Create readFormAnswer method to read formAnswer from database #24 (Horstmann)
+- Create writeFormAnswer method to insert formAnswer into database #24 (Horstmann)
+- Create TestHandler to tests FormAnswers
+### Changed
+- Fix OptHandler to return id in inputAnswer
+
+
+## 0.0.17 - 25-05-2019
+### Added
+- inputAnswer method in OptHandler #23 (Horstmann)
+- formAnswer method in OptHandler #23 (Horstmann)
+
+### Changed
+-  FormsAnswer class to have an dictionary of InputsAnswer
+-  FormsAnswer's constructor to use dictionary
+
+
+## 0.0.16 - 06-05-2019
+### Added
+- A FormsAnswer Class to store answers from forms #22 (Horstmann)
+- A inputsAnswer Class to be the answer for each input in form #22 (Horstmann)
+### Changed
+-  Form's  constructor documentation
+-  Input's  constructor documentation
+
+
+## 0.0.15 - 26-04-2019
+### Added
+- A QueryOptions interface, that is used on dbHandler's executeQuery #20
+### Changed
+-  dbHandler's tests to fit into new interface
+### Security
+- Now dbHandler's executeQuery uses parametrized query to avoid SQL injection
+
+
+## 0.0.14 - 26-04-2019
+### Removed
+- Dummies files as Item and Collection #16 (Horstmann)
+
+
+## 0.0.13 - 26-04-2019
+### Added
+- A route to POST a form #10 (Horstmann)
+- Tests on route POST (Horstmann)
+### Changed
+- dbHandler's tests to suit with new forms and inputs insertion
+
+
+## 0.0.12 - 25-04-2019
+### Added
+- OptHandler to standardize constructors from Forms and Inputs #19 (Horstmann)
+- InputOptions  interface on class Input #19 (Horstmann)
+- FormOptions  interface on class Form #19 (Horstmann)
+### Changed
+- Tests to adapt to new standard of options
+- dbHandler's readInputValidationWithInputId method to return a InputOptions instead of an input
+- Tests to adapt to new standard of options
+- ErrorHandler to add a new error message
+
+
+
+## 0.0.11 - 17-04-2019
+### Added
+- ErrorHandler to standardize errors message through the project #17 (Horstmann)
+### Changed
+- TestHandler documentation title
+- dbHandler tests to use ErrorHandler #18 (Horstmann)
+
+
+## 0.0.10 - 16-04-2019
+### Added
+- TestHandler to test form and inputs #18 (Horstmann)
+### Changed
+- controller form tests to use testHandler #18 (Horstmann)
+- controller form to improve code coverage
+- dbHandler tests to use testHandler #18 (Horstmann)
+- ValidationType to has as arguments an array of strings
+- ValidationHandler to receive a string as size instead number as validation arguments
+- ValidationHandler to cast size to number
+- ValidationHandler tests to use string instead of number as validation arguments
+
+
+## 0.0.9 - 10-04-2019
+### Added
+- Method read in Form controller to get a Form
+
+
+## 0.0.8 - 10-04-2019
+### Changed
+- main.ts to remove more dummie class
+- dbHandler to include method listForms
+### Added
+- Form controller and method to list all forms
+
+
+## 0.0.7 - 10-04-2019
+### Changed
+- main.ts to include dbHandler Middleware and remove dummie class
+### Added
+- Create dbHandler Middleware to be able to access by routes #15 (Horstmann)
+
+
+## 0.0.6 - 01-04-2019
+### Changed
+- Input class to match with database model (Add id and description) (Horstmann)
+- Form class to match with database model (Remove version add description) (Horstmann)
+- enumHandler to remove sides whitespaces (Horstmann)
+### Added
+- Create readForm method to read form from database #7 (Horstmann)
+- Create readInput method to read input from database #7 (Horstmann)
+- Create writeForm method to insert form into database (Horstmann)
+- Comments to coverage ignore errors that are not reached on tests.
+
+
+## 0.0.5 - 19-03-2019
+### Changed
+- Remove tslint-stylish from package.json, package is deprecated (Horstmann)
+- Update yarn.lock to avoid vulnerabilities (Horstmann)
+- Update CI file to handle database (Horstmann)
+### Added
+- Class config using singleton patern, to centralize all configuration in one module (Horstmann)
+- DbHandler to be a layer between API and database #1 (Horstmann)
+
+## 0.0.4 - 12-02-2019
+### Added
+- Class Form #3 (Horstmann)
+
+
+## 0.0.3 - 07-02-2019
+### Changed
+- Added a new type of enum ValitationType #2 (Horstmann)
+### Added
+- ValidationHandle to valited answer given a input #2 (Horstmann)
+
+
+## 0.0.2 - 05-02-2019
+### Added
+- EnunHandler to handle types of inputs #4 (Horstmann)
+
+
+## 0.0.1 - 04-02-2019
+### Added
+- This CHANGELOG file to hopefully serve as an evolving example of a  standardized open source project CHANGELOG.
+- CI file to enable Gitlab Continuous Integration.
+- Docker files, as Dockerfile and docker-compose, to make easy development and Deploy #6 (Horstmann).
+- Update Node to 10.* #6 (Horstmann).
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..c0266c20f44ff59c5f6be6ab9f3d7d36c6348b08
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,38 @@
+FROM node:10-stretch-slim
+
+# Set an environment variable to store where the app is installed to inside of the Docker image.
+ENV WORKSPACE /app
+RUN mkdir -p $WORKSPACE
+
+# Change WORKSPACE owner
+RUN  chown -R node:node $WORKSPACE
+
+# Change running user
+USER node
+# This sets the context of where commands will be ran in and is documented
+# on Docker's website extensively.
+# Set app directory
+WORKDIR $WORKSPACE
+
+# Install app dependencies
+# A wildcard is used to ensure both package.json AND package-lock.json are copied
+# where available (npm@5+)
+COPY --chown=node:node package.json .
+COPY --chown=node:node yarn.lock .
+
+
+
+
+RUN  yarn install --frozen-lockfile --silent --non-interactive
+# If you are building your code for production
+# RUN yarn install --production --frozen-lockfile --silent --non-interactive
+
+
+# Bundle app source
+COPY --chown=node:node . .
+
+
+EXPOSE 3000
+
+
+CMD [ "yarn", "start" ]
diff --git a/package.json b/package.json
index 0b24d0421bef9961f4fc3da9420b9a82e0c86a2f..eef8fd87e5eea05c61f639a7607921047210ea5e 100644
--- a/package.json
+++ b/package.json
@@ -1,14 +1,14 @@
 {
-  "name": "ts-api-start-up",
-  "version": "0.0.1",
-  "description": "Typescript (API) base project",
+  "name": "form-creator-api",
+  "version": "1.0.0",
+  "description": "RESTful API used to manage and answer forms.",
   "main": "index.js",
   "scripts": {
-    "start": "scripts/start.sh config/config.env"
-    , "test": "scripts/test.sh config/test.env"
-    , "lint": "tslint -s node_modules/tslint-stylish -t stylish src/**/*.ts test/**/*.ts"
-    , "show-coverage": "xdg-open coverage/lcov-report/index.html"
-    , "doc-code": "typedoc --mode 'file' --module 'commonjs' --target 'ES6' --ignoreCompilerErrors --exclude '**/*.spec.ts' --out 'doc/code' 'src'"
+    "start": "scripts/start.sh config/config.env",
+    "test": "scripts/test.sh config/test.env",
+    "lint": "tslint -s node_modules/tslint-stylish -t stylish src/**/*.ts test/**/*.ts",
+    "show-coverage": "xdg-open coverage/lcov-report/index.html",
+    "doc-code": "typedoc --mode 'file' --module 'commonjs' --target 'ES6' --ignoreCompilerErrors --exclude '**/*.spec.ts' --out 'doc/code' 'src'"
   },
   "repository": {
     "type": "git",
@@ -19,8 +19,10 @@
   "dependencies": {
     "@types/async": "^2.0.50",
     "@types/express": "^4.16.0",
+    "@types/pg": "^7.4.13",
     "async": "^2.6.1",
     "express": "^4.16.4",
+    "pg": "^7.8.1",
     "ts-node": "^7.0.1",
     "typescript": "^3.2.2"
   },
@@ -32,8 +34,7 @@
     "istanbul": "1.1.0-alpha.1",
     "mocha": "^5.2.0",
     "supertest": "^3.3.0",
-    "tslint": "^5.12.1",
-    "tslint-stylish": "^2.1.0",
+    "tslint": "^5.13.1",
     "typedoc": "^0.14.1"
   }
 }
diff --git a/src/api/apiTypes.ts b/src/api/apiTypes.ts
index bd77cd86d235c392b919fb051ae9178c3b557ef4..716e3f4a4f2b18c2134f72e973aad7120ce5968d 100644
--- a/src/api/apiTypes.ts
+++ b/src/api/apiTypes.ts
@@ -20,7 +20,7 @@
  */
 
 import * as express from "express";
-import { Collection } from "../core/collection";
+import { DbHandler } from "../utils/dbHandler";
 
 /**
  * Extension of Express requests that suports the addition
@@ -31,8 +31,8 @@ import { Collection } from "../core/collection";
  * return a error the extension must be made.
  */
 export interface Request extends express.Request {
-    /** A collection object. Simulate a database. */
-    collection: Collection;
+    /** A Database handler instace */
+    db: DbHandler;
 }
 
 /**
diff --git a/src/api/controllers/form.spec.ts b/src/api/controllers/form.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ef1e8a001543d3c174f087d78409ea5ab57b582a
--- /dev/null
+++ b/src/api/controllers/form.spec.ts
@@ -0,0 +1,520 @@
+/*
+ * form-creator-api. RESTful API to manage and answer forms.
+ * Copyright (C) 2019 Centro de Computacao Cientifica e Software Livre
+ * Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR
+ *
+ * This file is part of form-creator-api.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+import { series, waterfall } from "async";
+import * as request from "supertest";
+import { expect } from "chai";
+import { QueryResult } from "pg";
+import * as server from "../../main";
+import { EnumHandler, InputType, UpdateType, ValidationType } from "../../utils/enumHandler";
+import { TestHandler } from "../../utils/testHandler";
+import { OptHandler } from "../../utils/optHandler";
+import { Form, FormOptions } from "../../core/form";
+import { FormUpdate, FormUpdateOptions } from "../../core/formUpdate";
+import { Input, InputOptions, Validation } from "../../core/input";
+import { InputUpdate, InputUpdateOptions } from "../../core/inputUpdate";
+import { DbHandler, QueryOptions } from "../../utils/dbHandler";
+import { configs } from "../../utils/config";
+
+describe("API data controller", () => {
+
+    const dbhandler = new DbHandler(configs.poolconfig);
+    
+    it("should respond 200 when getting a list of forms", (done) => {
+        request(server)
+            .get("/form")
+            .expect(200)
+            .expect((res: any) => {
+                expect(res.body).to.be.an("array");
+                expect(res.body[0].id).to.be.equal(1);
+                expect(res.body[0].title).to.be.equal("Form Title 1");
+                expect(res.body[0].description).to.be.equal("Form Description 1");
+
+                expect(res.body[1].id).to.be.equal(2);
+                expect(res.body[1].title).to.be.equal("Form Title 2");
+                expect(res.body[1].description).to.be.equal("Form Description 2");
+
+                expect(res.body[2].id).to.be.equal(3);
+                expect(res.body[2].title).to.be.equal("Form Title 3");
+                expect(res.body[2].description).to.be.equal("Form Description 3");
+
+            })
+            .end(done);
+    });
+
+
+    it("should respond 200 when getting valid form", (done) => {
+        request(server)
+            .get("/form/1")
+            .expect(200)
+            .expect((res: any) => {
+                expect(res.body).to.be.an("object");
+
+                const form: Form = new Form(OptHandler.form(res.body));
+                const inputObj1: InputOptions = {
+                    placement: 0
+                    , description: "Description Question 1 Form 1"
+                    , question: "Question 1 Form 1"
+                    , enabled: true
+                    , type: InputType.TEXT
+                    , validation: []
+                    , id: 1
+                };
+
+
+                const inputObj2: InputOptions = {
+                    placement: 1
+                    , description: "Description Question 2 Form 1"
+                    , question:  "Question 2 Form 1"
+                    , enabled: true
+                    , type: InputType.TEXT
+                    , validation: [
+                        { type: ValidationType.MAXCHAR, arguments: ["10"] }
+                        , { type: ValidationType.MINCHAR, arguments: ["2"] }
+                    ]
+                    , id: 3
+                };
+
+                const inputObj3: InputOptions = {
+                    placement: 2
+                    , description: "Description Question 3 Form 1"
+                    , question: "Question 3 Form 1"
+                    , enabled: true
+                    , type: InputType.TEXT
+                    , validation: [
+                        { type: ValidationType.REGEX, arguments: ["\\d{5}-\\d{3}"] }
+                        , { type: ValidationType.MANDATORY, arguments: [] }
+                    ]
+                    , id: 2
+                };
+
+                const formObj: FormOptions = {
+                    id: 1
+                    , title: "Form Title 1"
+                    , description: "Form Description 1"
+                    , inputs: [
+                        inputObj1
+                        , inputObj2
+                        , inputObj3
+                    ]
+                };
+                TestHandler.testForm(form, new Form( OptHandler.form(formObj)));
+
+            })
+            .end(done);
+    });
+
+    it("should respond 500 when getting inexistent form", (done) => {
+        request(server)
+            .get("/form/10")
+            .expect(500)
+            .expect((res: any) => {
+                const message = "Form with id: '10' not found. Some error has occurred. Check error property for details.";
+
+                expect(res.body).to.be.an("object");
+                expect(res.body).to.have.property("error");
+                expect(res.body.message).to.be.equal(message);
+            })
+            .end(done);
+    });
+
+    it("should respond 200 when posting valid form", (done) => {
+
+        request(server)
+            .post("/form")
+            .send({
+                title: 'Form Title 4'
+                , description: 'Form Description 4'
+                , inputs: [
+                    {
+                        placement: 0
+                        , description: 'Description Question 1 Form 4'
+                        , question: 'Question 1 Form 4'
+                        , enabled: true
+                        , type: InputType.TEXT
+                        , validation: []
+                    }
+                    , {
+                        placement: 1
+                        , description: 'Description Question 2 Form 4'
+                        , question: 'Question 2 Form 4'
+                        , enabled: true
+                        , type: InputType.TEXT
+                        , validation: [
+                            { type: 3, arguments: [ '10' ] }
+                            , { type: 4, arguments: [ '2' ] }
+                        ]
+                    }
+                    , {
+                        placement: 2
+                        , description: 'Description Question 3 Form 4'
+                        , question: 'Question 3 Form 4'
+                        , enabled: true
+                        , type: InputType.TEXT
+                        , validation: [
+                            { type: 1, arguments: [ '\\d{5}-\\d{3}' ] }
+                            , { type: 2, arguments: [] }
+                        ]
+                    }
+                ]
+            })
+            .expect(200)
+            .end(done);
+    });
+
+    it("should respond 500 when posting malformed form", (done) => {
+
+        request(server)
+            .post("/form")
+            .send({
+                description: 'Form Description 4'
+                , inputs: [
+                    {
+                        placement: 0
+                        , description: 'Description Question 1 Form 4'
+                        , question: 'Question 1 Form 4'
+                        , enabled: true
+                        , type: InputType.TEXT
+                        , validation: []
+                    }
+                    , {
+                        placement: 1
+                        , description: 'Description Question 2 Form 4'
+                        , question: 'Question 2 Form 4'
+                        , enabled: true
+                        , type: InputType.TEXT
+                        , validation: [
+                            { type: 3, arguments: [ '10' ] }
+                            , { type: 4, arguments: [ '2' ] }
+                        ]
+                    }
+                    , {
+                        placement: 2
+                        , description: 'Description Question 3 Form 4'
+                        , question: 'Question 3 Form 4'
+                        , enabled: true
+                        , type: InputType.TEXT
+                        , validation: [
+                            { type: 1, arguments: [ '\\d{5}-\\d{3}' ] }
+                            , { type: 2, arguments: [] }
+                        ]
+                    }
+                ]
+            })
+            .expect(500)
+            .expect((res: any) => {
+                const message = "Invalid Form. Check error property for details.";
+                expect(res.body).to.be.an("object");
+                expect(res.body).to.have.property("error");
+                expect(res.body.message).to.be.equal(message);
+            })
+            .end(done);
+    });
+    
+    it("should respond 200 when putting valid form update swap inputs", (done) => {
+        request(server)
+            .put("/form/1")
+            .send({
+                id: 1
+                , title: 'Form Title 1'
+                , description: 'Form Description 1'
+                , inputs: [
+                    {
+                        placement: 0
+                        , description: 'Description Question 1 Form 1'
+                        , question: 'Question 1 Form 1'
+                        , enabled: true
+                        , type: InputType.TEXT
+                        , validation: []
+                        , id: 1
+                    }
+                    , {
+                        placement: 1
+                        , description: 'Description Question 2 Form 1'
+                        , question: 'Question 2 Form 1'
+                        , enabled: true
+                        , type: InputType.TEXT
+                        , validation: [
+                            { type: 3, arguments: [ '10' ] }
+                            , { type: 4, arguments: [ '2' ] }
+                        ]
+                        , id: 2
+                    }
+                    , {
+                        placement: 2
+                        , description: 'Description Question 3 Form 1'
+                        , question: 'Question 3 Form 1'
+                        , enabled: true
+                        , type: InputType.TEXT
+                        , validation: [
+                            { type: 3, arguments: [ '10' ] }
+                            , { type: 4, arguments: [ '2' ] }
+                        ]
+                        , id: 3
+                    }
+                ]
+            })
+            .expect(200)
+            .expect((res: any) => {
+                const message = "Updated"
+                expect(res.body.message).to.be.equal(message);
+            })
+            .end(done);
+    });
+
+    it("should respond 200 when putting valid form update add inputs", (done) => {
+        request(server)
+            .put("/form/3")
+            .send({
+                id: 3
+                , title: 'Form Title 3'
+                , description: 'Form Description 3'
+                , inputs: [
+                    {
+                        placement: 0
+                        , description: 'Description Question 1 Form 3'
+                        , question: 'Question 1 Form 3'
+                        , enabled: true
+                        , type: InputType.TEXT
+                        , validation: [
+                            { type: ValidationType.MANDATORY, arguments: [] }
+                        ]
+                        , id: 6
+                    }
+                    , {
+                        placement: 1
+                        , description: 'Description Question 2 Form 3'
+                        , question: 'Question 2 Form 3'
+                        , enabled: true
+                        , type: InputType.TEXT
+                        , validation: [
+                            { type: 3, arguments: [ '10' ] }
+                            , { type: 4, arguments: [ '2' ] }
+                        ]
+                        , id: 7
+                    }
+                    , {
+                        placement: 3
+                        , description: 'Description Question 4 Form 3'
+                        , question: 'Question 4 Form 3'
+                        , enabled: true
+                        , type: InputType.TEXT
+                        , validation: []
+                        , id: undefined
+                    }
+                    , {
+                        placement: 4
+                        , description: 'Description Question 5 Form 3'
+                        , question: 'Question 5 Form 3'
+                        , enabled: true
+                        , type: InputType.TEXT
+                        , validation: [
+                            { type: 3, arguments: [ '10' ] }
+                            , { type: 4, arguments: [ '2' ] }
+                        ]
+                        , id: undefined
+                    }
+                    , {
+                        placement: 5
+                        , description: 'Description Question 6 Form 3'
+                        , question: 'Question 6 Form 3'
+                        , enabled: true
+                        , type: InputType.TEXT
+                        , validation: [
+                            { type: 3, arguments: [ '10' ] }
+                            , { type: 4, arguments: [ '2' ] }
+                        ]
+                        , id: undefined
+                    }
+                ]
+            })
+            .expect(200)
+            .expect((res: any) => {
+                const message = "Updated"
+                expect(res.body.message).to.be.equal(message);
+            })
+            .end(done);
+    });
+
+    it("should respond 200 when putting valid form update remove inputs", (done) => {
+        request(server)
+            .put("/form/3")
+            .send({
+                id: 3
+                , title: 'Form Title 3'
+                , description: 'Form Description 3'
+                , inputs: []
+            })
+        
+            .expect(200)
+            .expect((res: any) => {
+                const message = "Updated"
+                expect(res.body.message).to.be.equal(message);
+            })
+            .end(done);
+    });
+
+    it("should respond 200 when putting valid form update reenabled inputs", (done) => {
+        request(server)
+            .put("/form/3")
+            .send({
+                id: 3
+                , title: 'Form Title 3'
+                , description: 'Form Description 3'
+                , inputs: [
+                    {
+                        placement: 0
+                        , description: 'Description Question 1 Form 3'
+                        , question: 'Question 1 Form 3'
+                        , enabled: true
+                        , type: InputType.TEXT
+                        , validation: [
+                            { type: ValidationType.MANDATORY, arguments: [] }
+                        ]
+                        , id: 6
+                    }
+                    , {
+                        placement: 1
+                        , description: 'Description Question 2 Form 1'
+                        , question: 'Question 2 Form 1'
+                        , enabled: true
+                        , type: InputType.TEXT
+                        , validation: [
+                            { type: 3, arguments: [ '10' ] }
+                            , { type: 4, arguments: [ '2' ] }
+                        ]
+                        , id: 7
+                    }
+                ]
+            })
+        
+            .expect(200)
+            .expect((res: any) => {
+                const message = "Updated"
+                expect(res.body.message).to.be.equal(message);
+            })
+
+            .end(done);
+    });
+
+    it("should respond 500 when putting a valid form update for an inexistent form", (done) => {
+        request(server)
+            .put("/form/10")
+            .send({
+                id: 1
+                , title: 'Form Title 1'
+                , description: 'Form Description 1'
+                , inputs:[
+                    {
+                        placement: 0
+                        , description: 'Description Question 1 Form 6'
+                        , question: 'Question 1 Form 6'
+                        , enabled: true
+                        , type: InputType.TEXT
+                        , validation: []
+                        , id: 1
+                    }
+                    , {
+                        placement: 1
+                        , description: 'Description Question 2 Form 6'
+                        , question: 'Question 2 Form 6'
+                        , enabled: true
+                        , type: InputType.TEXT
+                        , validation: [
+                            { type: 3, arguments: [ '10' ] }
+                            , { type: 4, arguments: [ '2' ] }
+                        ]
+                        , id: 2
+                    }
+                    , {
+                        placement: 2
+                        , description: 'Description Question 3 Form 6'
+                        , question: 'Question 3 Form 6'
+                        , enabled: true
+                        , type: InputType.TEXT
+                        , validation: [
+                            { type: 3, arguments: [ '10' ] }
+                            , { type: 4, arguments: [ '2' ] }
+                        ]
+                    }
+                ]
+            })
+            .expect(500)
+            .expect((res: any) => {
+                const message = "Could not update Form. Some error has ocurred. Check error property for details.";
+                expect(res.body).to.be.an("object");
+                expect(res.body).to.have.property("error");
+                expect(res.body.message).to.be.equal(message);
+            })
+            .end(done);
+    });
+
+    it("should respond 500 when putting an malformed form update", (done) => {
+        request(server)
+            .put("/form/1")
+            .send({
+                id: 1
+                , inputs:[
+                    {
+                        placement: 0
+                        , description: 'Description Question 1 Form 1'
+                        , question: 'Question 1 Form 1'
+                        , enabled: true
+                        , type: InputType.TEXT
+                        , validation: []
+                        , id: 1
+                    }
+                    , {
+                        placement: 1
+                        , description: 'Description Question 2 Form 1'
+                        , question: 'Question 2 Form 1'
+                        , enabled: true
+                        , type: InputType.TEXT                        
+                        , validation: [
+                            { type: 3, arguments: [ '10' ] }
+                            , { type: 4, arguments: [ '2' ] }
+                        ]
+                        , id: 2
+                    }
+                    , {
+                        placement: 2
+                        , description: 'Description Question 3 Form 1'
+                        , question: 'Question 3 Form 1'
+                        , enabled: true
+                        , type: InputType.TEXT
+                        , validation: [
+                            { type: 3, arguments: [ '10' ] }
+                            , { type: 4, arguments: [ '2' ] }
+                        ]
+                    }
+                ]
+            })
+            .expect(500)
+            .expect((res: any) => {
+                const message = "Invalid Form. Check error property for details.";
+                expect(res.body).to.be.an("object");
+                expect(res.body).to.have.property("error");
+                expect(res.body.message).to.be.equal(message);
+            })
+            .end(done);
+    });
+
+});
diff --git a/src/api/controllers/form.ts b/src/api/controllers/form.ts
new file mode 100644
index 0000000000000000000000000000000000000000..df60bc1fcbbac3d04d17f08aad90c19b79f504a4
--- /dev/null
+++ b/src/api/controllers/form.ts
@@ -0,0 +1,177 @@
+/*
+ * form-creator-api. RESTful API to manage and answer forms.
+ * Copyright (C) 2019 Centro de Computacao Cientifica e Software Livre
+ * Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR
+ *
+ * This file is part of form-creator-api.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+import { waterfall } from "async";
+import { OptHandler } from "../../utils/optHandler";
+import { DiffHandler } from "../../utils/diffHandler";
+import { Form, FormOptions} from "../../core/form";
+import { FormUpdate, FormUpdateOptions } from "../../core/formUpdate";
+import { Response, NextFunction } from "express";
+import { Request } from "../apiTypes";
+
+export class FormCtrl {
+
+    public static list(req: Request, res: Response, next: NextFunction) {
+
+        req.db.listForms((err: Error, forms?: Form[]) => {
+            if (err){
+                res.status(500).json({
+                    message: "Could not list forms. Some error has occurred. Check error property for details.",
+                    error: err
+                });
+                return;
+            }
+            else{
+                const mappedForms = forms.map(form => ({
+                    id: form.id,
+                    title: form.title,
+                    description: form.description
+                }));
+                res.json(mappedForms);
+                return;
+            }
+
+        });
+
+    }
+
+    public static read(req: Request, res: Response, next: NextFunction) {
+        req.db.readForm(req.params.id, (err: Error, form?: Form) => {
+            if (err){
+                res.status(500).json({
+                    message: "Form with id: '"  + req.params.id + "' not found. Some error has occurred. Check error property for details.",
+                    error: err
+                });
+                return;
+            }
+            else{
+                res.json(form);
+                return;
+            }
+        });
+    }
+
+    public static write(req: Request, res: Response, next: NextFunction) {
+
+        let form: Form;
+        try {
+            form = new Form(OptHandler.form(req.body));
+        } catch(e) {
+            res.status(500).json({
+                message: "Invalid Form. Check error property for details.",
+                error: e.message
+            });
+            return;
+        }
+        waterfall ([
+            (callback: (err: Error, result?: FormUpdate) => void) => {
+                req.db.writeForm(form, (err: Error, formResult: Form) => {
+                    if (err) {
+                        callback(err);
+                    }
+                    else {
+                        const formOpts: FormOptions = {
+                            id: formResult.id
+                            , title: formResult.title
+                            , description: formResult.description
+                            , inputs: []
+                        };
+                        const formUpdate: FormUpdate = DiffHandler.diff(formResult, new Form (formOpts));
+                                  
+                        callback(null, formUpdate);
+                    }
+                });
+            },
+            (formUpdate: FormUpdate, callback: (err: Error, formId: number) => void) => {
+                req.db.updateForm(formUpdate, (err: Error) => {
+                        callback(err, formUpdate.form.id);
+                });
+            }
+        ], (err, resultId) => {
+            if (err) {
+                res.status(500).json({
+                    message: "Could not insert form. Some error has occurred. Check error property for details.",
+                    error: err.message
+                });
+            }
+            else {
+                res.json({
+                    id: resultId
+                    , message: "Form added. Id on key 'id'"
+                });
+            }
+            return;
+        });
+    }
+
+    public static update(req: Request, res: Response, next: NextFunction) {
+
+        let newForm: Form;
+        try {
+            newForm = new Form(OptHandler.form(req.body));
+        } catch(e) {
+            res.status(500).json({
+                message: "Invalid Form. Check error property for details.",
+                error: e.message
+            });
+            return;
+        }
+        waterfall([
+            (callback: (err: Error, result?: FormUpdate) => void) => {
+                req.db.readForm(req.params.id, (err: Error, oldForm: Form) => {
+                    if (err) {
+                        callback(err);
+                    }
+                    else {
+                        const formUpdate: FormUpdate = DiffHandler.diff(newForm, oldForm);
+                        callback(null, formUpdate);
+                    }
+                });
+            },
+            (formUpdate: FormUpdate, callback: (err: Error, formUpdateResult?: FormUpdate) => void) => {
+                req.db.updateDatabase(formUpdate, (err: Error, formUpdateResult: FormUpdate) => {
+                    if (err) {
+                        callback(err);
+                    }
+                    callback(null,formUpdateResult);
+                });
+            },
+            (formUpdate: FormUpdate, callback: (err: Error) => void) => {
+                req.db.updateForm(formUpdate, (err: Error) => {
+                    callback(err);
+                });
+            }
+        ], (err) => {
+            if (err) {
+                res.status(500).json({
+                    message: "Could not update Form. Some error has ocurred. Check error property for details.",
+                    error: err.message
+                });
+            }
+            else {
+                res.json({
+                    message: "Updated"
+                });
+            }
+            return;
+        });
+    }
+}
diff --git a/src/api/controllers/formAnswer.spec.ts b/src/api/controllers/formAnswer.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c88b2f0e621e89745952d51bb65dd9737ff83b56
--- /dev/null
+++ b/src/api/controllers/formAnswer.spec.ts
@@ -0,0 +1,72 @@
+/*
+ * form-creator-api. RESTful API to manage and answer forms.
+ * Copyright (C) 2019 Centro de Computacao Cientifica e Software Livre
+ * Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR
+ *
+ * This file is part of form-creator-api.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+ import * as request from "supertest";
+ import { expect } from "chai";
+ import * as server from "../../main";
+ import { EnumHandler,InputType, ValidationType } from "../../utils/enumHandler";
+ import { TestHandler } from "../../utils/testHandler";
+ import { OptHandler } from "../../utils/optHandler";
+ import { Form, FormOptions } from "../../core/form";
+ import { Input, InputOptions, Validation } from "../../core/input";
+
+
+ describe("API data controller", () => {
+
+        it("should respond 200 when posting valid form Answer", (done) => {
+
+             request(server)
+                 .post("/answer/1")
+                 .send({
+                     1:["Answer to Question 1 Form 1"]
+                     , 2:["12345-000"]
+                     , 3:["MAXCHAR 10"]
+                })
+                .expect(200)
+                .expect((res: any) => {
+                    expect(res.body.id).to.be.equal(7);
+                    expect(res.body.message).to.be.equal("Answered");
+                })
+                .end(done);
+        });
+
+        it("should respond 500 when posting invalid form Answer", (done) => {
+
+             request(server)
+                 .post("/answer/1")
+                 .send({
+                     1:["Answer to Question 1 Form 1"]
+                     , 2:["12a345-000"]
+                     , 3:["MAXCHAR 10 AND MORE"]
+                })
+                .expect(500)
+                .expect((res: any) => {
+                    const message = "Could not Create form Answer. Some error has occurred. Check error property for details.";
+                    expect(res.body).to.be.an("object");
+                    expect(res.body).to.have.property("error");
+                    expect(res.body.message).to.be.equal(message);
+                    expect(res.body.error["2"]).to.be.equal("RegEx do not match");
+                    expect(res.body.error["3"]).to.be.equal("Input answer must be lower than 10");
+                })
+                .end(done);
+        });
+
+ });
diff --git a/src/api/controllers/formAnswer.ts b/src/api/controllers/formAnswer.ts
new file mode 100644
index 0000000000000000000000000000000000000000..9549a66dd1c643f57f29b9e6e0f636c6b89658e1
--- /dev/null
+++ b/src/api/controllers/formAnswer.ts
@@ -0,0 +1,102 @@
+/*
+ * form-creator-api. RESTful API to manage and answer forms.
+ * Copyright (C) 2019 Centro de Computacao Cientifica e Software Livre
+ * Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR
+ *
+ * This file is part of form-creator-api.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+import { OptHandler } from "../../utils/optHandler";
+import { InputAnswerOptions, InputAnswerOptionsDict } from "../../core/inputAnswer";
+import { Form, FormOptions } from "../../core/form";
+import { FormAnswer, FormAnswerOptions } from "../../core/formAnswer";
+import { ValidationHandler } from "../../utils/validationHandler";
+import { Response, NextFunction } from "express";
+import { Request } from "../apiTypes";
+
+export class AnswerCtrl {
+
+    public static write(req: Request, res: Response, next: NextFunction) {
+
+        req.db.readForm(req.params.id, (err: Error, form?: Form) => {
+            if (err) {
+                res.status(500).json({
+                    message: "Form with id: '" + req.params.id + "' not found. Some error has occurred. Check error property for details.",
+                    error: err
+                });
+                return;
+            }
+            else {
+                let inputAnswerOptionsDict: InputAnswerOptionsDict = {}
+
+                for (const key of Object.keys(req.body)) {
+                    inputAnswerOptionsDict[parseInt(key, 10)] = [];
+                    for (const i in req.body[key]) {
+                        const tmpInputAnswerOption: InputAnswerOptions = {
+                            idInput: parseInt(key, 10)
+                            , placement: parseInt(i, 10)
+                            , value: req.body[key][i]
+                        }
+                        inputAnswerOptionsDict[parseInt(key, 10)].push(tmpInputAnswerOption);
+                    }
+                }
+
+
+                let formAnswerOpt: FormAnswerOptions = {
+                    form: form
+                    , timestamp: new Date(Date.now())
+                    , inputsAnswerOptions: inputAnswerOptionsDict
+                }
+
+                try{
+                    const formAnswer: FormAnswer = new FormAnswer(OptHandler.formAnswer(formAnswerOpt));
+                    ValidationHandler.validateFormAnswer(formAnswer);
+                    req.db.writeFormAnswer(formAnswer, (err: Error, formAnswerResult: FormAnswer) => {
+                        if (err){
+                            throw err;
+                        }
+                        else{
+                            res.json({
+                                id: formAnswerResult.id
+                                , message: "Answered"
+                            });
+                           return;
+                        }
+                    });
+                }
+                catch (e) {
+
+                    if( e.validationDict !== undefined){
+                        res.status(500).json({
+                            message: "Could not Create form Answer. Some error has occurred. Check error property for details."
+                            , error: e.validationDict
+                        });
+                    }else{
+                        res.status(500).json({
+                            message: "Could not Create form Answer. Some error has occurred. Check error property for details."
+                            , error: e.message
+                        });
+                    }
+                    return
+                }
+
+            }
+        });
+
+    }
+
+
+}
diff --git a/src/api/controllers/item.spec.ts b/src/api/controllers/item.spec.ts
deleted file mode 100644
index f767e0f3ef6b71e0a1ac359b83f78cf34f6b744c..0000000000000000000000000000000000000000
--- a/src/api/controllers/item.spec.ts
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * form-creator-api. RESTful API to manage and answer forms.
- * Copyright (C) 2019 Centro de Computacao Cientifica e Software Livre
- * Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR
- *
- * This file is part of form-creator-api.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-import * as request from "supertest";
-import { expect } from "chai";
-import * as server from "../../main";
-
-describe("API data controller", () => {
-
-    it("should respond 200 when posting valid item", (done) => {
-        request(server)
-            .post("/item")
-            .send({qtd: 30, name: "Arrow"})
-            .expect(200)
-            .expect((res: any) => {
-                const message = "Item added. Id on key 'id'";
-                expect(res.body).to.be.an("object");
-                expect(res.body).to.have.property("id");
-                expect(res.body).to.have.property("status");
-                expect(res.body.id).to.be.eql(0);
-                expect(res.body.status).to.be.eql(message);
-            })
-            .end(done);
-    });
-
-    it("should respond 500 when posting invalid item", (done) => {
-        request(server)
-            .post("/item")
-            .send({name: "Arrow"})
-            .expect(500)
-            .expect((res: any) => {
-                const message = "Invalid body. Check out request body keys";
-                expect(res.body).to.be.an("object");
-                expect(res.body).to.have.property("error");
-                expect(res.body.error).to.be.eql(message);
-            })
-            .end(done);
-    });
-
-    it("should respond 200 when putting valid item", (done) => {
-        request(server)
-            .put("/item/0")
-            .send({qtd: 29, name: "Arrow"})
-            .expect(200)
-            .expect((res: any) => {
-                const message = "Item updated. Id on key 'id'";
-                expect(res.body).to.be.an("object");
-                expect(res.body).to.have.property("id");
-                expect(res.body).to.have.property("status");
-                expect(res.body.id).to.be.eql("0");
-                expect(res.body.status).to.be.eql(message);
-            })
-            .end(done);
-    });
-
-    it("should respond 500 when putting invalid item", (done) => {
-        request(server)
-            .put("/item/0")
-            .send({name: "Arrow"})
-            .expect(500)
-            .expect((res: any) => {
-                const message = "Invalid body. Check out request body keys";
-                expect(res.body).to.be.an("object");
-                expect(res.body).to.have.property("error");
-                expect(res.body.error).to.be.eql(message);
-            })
-            .end(done);
-    });
-
-    it("should respond 500 when putting inexistent item", (done) => {
-        request(server)
-            .put("/item/1")
-            .send({name: "Arrow", qtd: 30})
-            .expect(500)
-            .expect((res: any) => {
-                const message = "Item with id: '1' not found";
-                expect(res.body).to.be.an("object");
-                expect(res.body).to.have.property("error");
-                expect(res.body.error).to.be.eql(message);
-            })
-            .end(done);
-    });
-
-    it("should respond 200 when getting valid item", (done) => {
-        request(server)
-            .get("/item/0")
-            .expect(200)
-            .expect((res: any) => {
-                expect(res.body).to.be.an("object");
-                expect(res.body).to.have.property("qtd");
-                expect(res.body).to.have.property("name");
-                expect(res.body.qtd).to.be.eql(29);
-                expect(res.body.name).to.be.eql("Arrow");
-            })
-            .end(done);
-    });
-
-    it("should respond 500 when getting inexistent item", (done) => {
-        request(server)
-            .get("/item/1")
-            .expect(500)
-            .expect((res: any) => {
-                const message = "Item with id: '1' not found";
-                expect(res.body).to.be.an("object");
-                expect(res.body).to.have.property("error");
-                expect(res.body.error).to.be.eql(message);
-            })
-            .end(done);
-    });
-
-    it("should respond 200 when deleting valid item", (done) => {
-        request(server)
-            .delete("/item/0")
-            .expect(200)
-            .expect((res: any) => {
-                const message = "Item deleted. Id on key 'id'";
-                expect(res.body).to.be.an("object");
-                expect(res.body).to.have.property("id");
-                expect(res.body).to.have.property("status");
-                expect(res.body.id).to.be.eql("0");
-                expect(res.body.status).to.be.eql(message);
-            })
-            .end(done);
-    });
-
-    it("should respond 500 when deleting inexistent item", (done) => {
-        request(server)
-            .delete("/item/0")
-            .expect(500)
-            .expect((res: any) => {
-                const message = "Item with id: '0' not found";
-                expect(res.body).to.be.an("object");
-                expect(res.body).to.have.property("error");
-                expect(res.body.error).to.be.eql(message);
-            })
-            .end(done);
-    });
-});
diff --git a/src/api/controllers/item.ts b/src/api/controllers/item.ts
deleted file mode 100644
index 022a5bcf4c4250bebce2b1af26dbd30c0dfbf2f9..0000000000000000000000000000000000000000
--- a/src/api/controllers/item.ts
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * form-creator-api. RESTful API to manage and answer forms.
- * Copyright (C) 2019 Centro de Computacao Cientifica e Software Livre
- * Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR
- *
- * This file is part of form-creator-api.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-import { Item } from "../../core/item";
-import { Response, NextFunction } from "express";
-import { Request } from "../apiTypes";
-
-export class ItemCtrl {
-    public static read(req: Request, res: Response, next: NextFunction) {
-        const item = req.collection.getItem(req.params.id);
-        if (item) {
-            res.json(item);
-            return;
-        }
-
-        else {
-            res.status(500).json({
-                error: "Item with id: '"  + req.params.id + "' not found"
-            });
-            return;
-        }
-    }
-
-    public static write(req: Request, res: Response, next: NextFunction) {
-        if (!Item.validator(req.body)) {
-            res.status(500).json({
-                error: "Invalid body. Check out request body keys"
-            });
-            return;
-        }
-
-        const item: Item = new Item(req.body.qtd, req.body.name);
-        const id = req.collection.addItem(item);
-        res.json({
-            id: id
-            , status: "Item added. Id on key 'id'"
-        });
-    }
-
-    public static update(req: Request, res: Response, next: NextFunction) {
-        if (!Item.validator(req.body)) {
-            res.status(500).json({
-                error: "Invalid body. Check out request body keys"
-            });
-            return;
-        }
-
-        const item: Item = new Item(req.body.qtd, req.body.name);
-        const updated = req.collection.updateItem(req.params.id, item);
-        if (updated) {
-            res.json({
-                id: req.params.id
-                , status: "Item updated. Id on key 'id'"
-            });
-        }
-
-        else {
-            res.status(500).json({
-                error: "Item with id: '"  + req.params.id + "' not found"
-            });
-        }
-    }
-
-    public static del(req: Request, res: Response, next: NextFunction) {
-        const i = req.collection.deleteItem(req.params.id);
-        if (i) {
-            res.json({
-                id: req.params.id
-                , status: "Item deleted. Id on key 'id'"
-            });
-        }
-
-        else {
-            res.status(500).json({
-                error: "Item with id: '"  + req.params.id + "' not found"
-            });
-        }
-    }
-}
diff --git a/src/api/middlewares/collection.ts b/src/api/middlewares/dbHandler.ts
similarity index 75%
rename from src/api/middlewares/collection.ts
rename to src/api/middlewares/dbHandler.ts
index 65a322498b8d8f011935650f833bd9fe5de85381..42bc7f4eb741c8fdd4b3aa3b5eb5b9f621985abc 100644
--- a/src/api/middlewares/collection.ts
+++ b/src/api/middlewares/dbHandler.ts
@@ -19,18 +19,20 @@
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
 
-import { Collection } from "../../core/collection";
+import { configs } from "../../utils/config";
+import { DbHandler } from "../../utils/dbHandler";
 import { Middleware } from "../apiTypes";
 
 /**
  * Creates a engine and middleware that
- * inserts the collection into the request objects.
+ * inserts the handler into the request objects.
  */
-export function CollectionMw (): Middleware {
-    const collection: Collection = new Collection();
 
-    return function collectionMiddleware(req, res, next) {
-        req.collection = collection;
+export function DbHandlerMw (): Middleware {
+    const db: DbHandler = new DbHandler(configs.poolconfig);
+
+    return function dbHandlerMiddleware(req, res, next) {
+        req.db = db;
         next();
     };
 }
diff --git a/src/core/collection.spec.ts b/src/core/collection.spec.ts
deleted file mode 100644
index a5c9f0f9a4e33eb1246fbca528495be8eb5ef090..0000000000000000000000000000000000000000
--- a/src/core/collection.spec.ts
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * form-creator-api. RESTful API to manage and answer forms.
- * Copyright (C) 2019 Centro de Computacao Cientifica e Software Livre
- * Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR
- *
- * This file is part of form-creator-api.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-import { expect } from "chai";
-import { Collection } from "./collection";
-import { Item } from "./item";
-
-describe("collection class", () => {
-
-    const collection = new Collection ();
-
-    it("should add 3 items to the collection", () => {
-        const items: Item[] = [
-            new Item(1, "Bow")
-            , new Item(30, "Arrow")
-            , new Item(1, "Sword")
-        ];
-
-        for (let i = 0; i < items.length; ++i) {
-            const id = collection.addItem(items[i]);
-            expect(id).to.be.equal(i);
-        }
-    });
-
-    it("should update the second item", () => {
-        const item: Item = new Item(29, "Arrow");
-
-        const updated = collection.updateItem(1, item);
-        expect(updated).to.be.true;
-    });
-
-    it("should NOT update a inexistent item", () => {
-        const item: Item = new Item(29, "Arrow");
-
-        const updated = collection.updateItem(3, item);
-        expect(updated).to.be.false;
-    });
-
-    it("should delete the third item", () => {
-        const deleted = collection.deleteItem(2);
-        expect(deleted).to.be.true;
-    });
-
-    it("should NOT delete a inexistent item", () => {
-        const deleted = collection.deleteItem(2);
-        expect(deleted).to.be.false;
-    });
-
-    it("should get the first item", () => {
-        const item = collection.getItem(0);
-        expect(item).to.be.an("object");
-        expect(item).to.have.property("qtd");
-        expect(item).to.have.property("name");
-        expect(item.qtd).to.be.equal(1);
-        expect(item.name).to.be.equal("Bow");
-    });
-
-    it("should NOT get a inexistent item", () => {
-        const item = collection.getItem(2);
-        expect(item).to.be.null;
-    });
-});
diff --git a/src/core/item.ts b/src/core/form.spec.ts
similarity index 74%
rename from src/core/item.ts
rename to src/core/form.spec.ts
index c627201768a3bea5921cb9b2db35d1f005c84c12..e70e86c32c425444b514a039a87452919a093d21 100644
--- a/src/core/item.ts
+++ b/src/core/form.spec.ts
@@ -18,17 +18,3 @@
  * You should have received a copy of the GNU Affero General Public License
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
-
-export class Item {
-    public readonly qtd: number;
-    public readonly name: string;
-
-    constructor(qtd: number, name: string) {
-        this.qtd = qtd;
-        this.name = name;
-    }
-
-    public static validator(json: any) {
-        return (typeof json.qtd === "number" && typeof json.name === "string");
-    }
-}
diff --git a/src/core/form.ts b/src/core/form.ts
new file mode 100644
index 0000000000000000000000000000000000000000..cc16ac3caa0d0a9e4bf230498e259401a9d76211
--- /dev/null
+++ b/src/core/form.ts
@@ -0,0 +1,65 @@
+/*
+ * form-creator-api. RESTful API to manage and answer forms.
+ * Copyright (C) 2019 Centro de Computacao Cientifica e Software Livre
+ * Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR
+ *
+ * This file is part of form-creator-api.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+import { OptHandler } from "../utils/optHandler";
+import { Input, InputOptions } from "./input";
+
+/** Parameters used to create a form object. */
+export interface FormOptions {
+    /** Unique identifier of a Form instance */
+    id?: number;
+
+    /** Form's title. An human-understandable identifier. Not unique */
+    title: string;
+
+    /** Form Description, as propose */
+    description: string;
+
+    /** Array of input. containing question */
+    inputs: InputOptions[];
+}
+/**
+ * Form Class to manage project's forms
+ */
+export class Form {
+     /** Unique identifier of a Form instance */
+     public readonly id: number;
+     /** Form's title. An human-understandable identifier. Not unique */
+     public readonly title: string;
+     /** Form Description, as propose */
+     public readonly description: string;
+     /** Array of input. containing question */
+     public readonly inputs: Input[];
+
+    /**
+     * Creates a new instance of Form Class
+     * @param options - FormOptions instance to create a form.
+     */
+     constructor(options: FormOptions) {
+         this.id =  options.id ? options.id : null;
+         this.title = options.title;
+         this.description = options.description;
+         this.inputs = options.inputs.map((i: any) => {
+             return new Input(OptHandler.input(i));
+         });
+     }
+
+ }
diff --git a/src/core/formAnswer.spec.ts b/src/core/formAnswer.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e70e86c32c425444b514a039a87452919a093d21
--- /dev/null
+++ b/src/core/formAnswer.spec.ts
@@ -0,0 +1,20 @@
+/*
+ * form-creator-api. RESTful API to manage and answer forms.
+ * Copyright (C) 2019 Centro de Computacao Cientifica e Software Livre
+ * Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR
+ *
+ * This file is part of form-creator-api.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
diff --git a/src/core/formAnswer.ts b/src/core/formAnswer.ts
new file mode 100644
index 0000000000000000000000000000000000000000..04f2ba671d2a879212bdc36bda1e519740c0850d
--- /dev/null
+++ b/src/core/formAnswer.ts
@@ -0,0 +1,71 @@
+/*
+ * form-creator-api. RESTful API to manage and answer forms.
+ * Copyright (C) 2019 Centro de Computacao Cientifica e Software Livre
+ * Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR
+ *
+ * This file is part of form-creator-api.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+import { OptHandler } from "../utils/optHandler";
+import { Form } from "./form";
+import { InputAnswer, InputAnswerDict, InputAnswerOptions, InputAnswerOptionsDict } from "./inputAnswer";
+
+/** Parameters used to create a FormAnswer object. */
+export interface FormAnswerOptions {
+     /** Unique identifier of a FormAnswer instance */
+    id?: number;
+
+    /** Form which answer is related to */
+    form: Form;
+
+    /** Time when it is answered */
+    timestamp: Date;
+
+    /** A dictionary of inputsAnswers. containing the answers */
+    inputsAnswerOptions: InputAnswerOptionsDict;
+}
+
+/**
+ * Form Class to manage project's forms
+ */
+export class FormAnswer {
+     /** Unique identifier of a FormAnswer instance */
+     public readonly id: number;
+     /** Form which answer is related to */
+     public readonly form: Form;
+     /** Time when it is answered */
+     public readonly timestamp: Date;
+     /** Array of inputsAnswer. containing the answers */
+     public readonly inputAnswers: InputAnswerDict;
+
+     /**
+      * Creates a new instance of FormAnswer Class
+      * @param options - FormAnswerOptions instance to create a FormAnswer.
+      */
+     constructor(options: FormAnswerOptions) {
+         this.id =  options.id ? options.id : null;
+         this.form = options.form;
+         this.timestamp = options.timestamp;
+         this.inputAnswers = {};
+         for (const key of  Object.keys(options.inputsAnswerOptions)){
+             this.inputAnswers[parseInt(key, 10)] =  options.inputsAnswerOptions[parseInt(key, 10)].map( (i: InputAnswerOptions) => {
+                 return new InputAnswer(i);
+             });
+
+         }
+     }
+
+ }
diff --git a/src/core/formUpdate.spec.ts b/src/core/formUpdate.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..7c54fe5df5900adac41751690faf6c95274c0dd3
--- /dev/null
+++ b/src/core/formUpdate.spec.ts
@@ -0,0 +1,92 @@
+/*
+ * form-creator-api. RESTful API to manage and answer forms.
+ * Copyright (C) 2019 Centro de Computacao Cientifica e Software Livre
+ * Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR
+ *
+ * This file is part of form-creator-api.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+import { expect } from "chai";
+import { InputType, UpdateType, ValidationType } from "../utils/enumHandler";
+import { TestHandler } from "../utils/testHandler";
+import { Form, FormOptions } from "./form";
+import { FormUpdate, FormUpdateOptions } from "./formUpdate";
+import { Input, InputOptions } from "./input";
+import { InputUpdate, InputUpdateOptions } from "./inputUpdate";
+
+describe("FormUpdate", () => {
+    it("should create a valid FormUpdate with id null", (done) => {
+
+        const inputObj: InputOptions = {
+            placement: 0
+            , description: "Description Question 1 Form 1"
+            , question: "Question 1 Form 1"
+            , enabled: true
+            , type: InputType.TEXT
+            , validation: []
+            , id: 1
+        };
+        const formObj: FormOptions = {
+            id: 1
+            , title: "Form Title 1"
+            , description: "Form Description 1"
+            , inputs: [ inputObj ]
+        };
+        const inputUpdateObj: InputUpdateOptions = {
+            input: inputObj
+            , inputOperation: UpdateType.ADD
+            , value: null
+        };
+        const formUpdateObj: FormUpdateOptions = {
+            form: formObj
+            , updateDate: new Date()
+            , inputUpdates: [ inputUpdateObj ]
+        };
+
+        const resFormUpdate: FormUpdate = new FormUpdate(formUpdateObj);
+
+        const expInput: Input = {
+            placement: 0
+            , description: "Description Question 1 Form 1"
+            , question: "Question 1 Form 1"
+            , enabled: true
+            , type: InputType.TEXT
+            , validation: []
+            , id: 1
+        };
+        const expForm: Form = {
+            id: 1
+            , title: "Form Title 1"
+            , description: "Form Description 1"
+            , inputs: [ expInput ]
+        };
+        const expInputUpdate: InputUpdate = {
+            input: expInput
+            , inputOperation: UpdateType.ADD
+            , value: null
+            , id: null
+        };
+        const expFormUpdate: FormUpdate = {
+            form: expForm
+            , updateDate: new Date()
+            , inputUpdates: [ expInputUpdate]
+            , id: null
+        };
+
+        TestHandler.testFormUpdate(resFormUpdate, expFormUpdate);
+        done();
+    });
+});
diff --git a/src/core/formUpdate.ts b/src/core/formUpdate.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5ee927dce8b5cbe52e8052a7df0c84742653477f
--- /dev/null
+++ b/src/core/formUpdate.ts
@@ -0,0 +1,61 @@
+/*
+ * form-creator-api. RESTful API to manage and answer forms.
+ * Copyright (C) 2019 Centro de Computacao Cientifica e Software Livre
+ * Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR
+ *
+ * This file is part of form-creator-api.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+import { Form, FormOptions } from "./form";
+import { InputUpdate, InputUpdateOptions } from "./inputUpdate";
+
+/** Parameters used to update a form object. */
+export interface FormUpdateOptions {
+    /** Unique identifier of a FormUpdate instance. */
+    id?: number;
+    /**  Changed Form. */
+    form: FormOptions;
+    /** Date which form was updated. */
+    updateDate: Date;
+    /** Array of InputUpdate containing changes on inputs. */
+    inputUpdates: InputUpdateOptions[];
+}
+
+/**
+ * FormUpdate Class to manage project's forms
+ */
+export class FormUpdate {
+    /** Unique identifier of a FormUpdate instance. */
+    public readonly id?: number;
+    /** Changed Form. */
+    public readonly form: Form;
+    /** Date which form was updated. */
+    public readonly updateDate: Date;
+    /** Array of InputUpdate containing changes on inputs. */
+    public readonly inputUpdates: InputUpdate[];
+    /**
+     * Creates a new instance of FormUpdate Class
+     * @param options - FormUpdateOptions instance to update a form.
+     */
+    constructor(options: FormUpdateOptions) {
+        this.id = options.id ? options.id : null;
+        this.form = new Form (options.form);
+        this.updateDate = options.updateDate;
+        this.inputUpdates = options.inputUpdates.map((i: any) => {
+            return new InputUpdate(i);
+        });
+    }
+}
diff --git a/src/core/input.spec.ts b/src/core/input.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..58df25055ad292cc0d05412c00283f102bc02c63
--- /dev/null
+++ b/src/core/input.spec.ts
@@ -0,0 +1,99 @@
+/*
+ * form-creator-api. RESTful API to manage and answer forms.
+ * Copyright (C) 2019 Centro de Computacao Cientifica e Software Livre
+ * Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR
+ *
+ * This file is part of form-creator-api.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+import { expect } from "chai";
+import { InputType, ValidationType } from "../utils/enumHandler";
+import { Input, InputOptions } from "./input";
+
+describe("Input with enabled atribute", () => {
+
+    it("should create a Input with option key 'enabled' as undefined", (done) => {
+        const options: InputOptions = {
+            placement: 0
+            , description: "Description Question 1"
+            , question: "Question 1"
+            , type: InputType.TEXT
+            , validation: []
+        };
+
+        const input: Input = new Input(options);
+
+        expect(input).to.be.a("object");
+        expect(input.enabled).to.be.equal(true);
+
+        done();
+    });
+
+    it("should create a Input with option key 'enabled' as null", (done) => {
+        const options: InputOptions = {
+            placement: 1
+            , description: "Description Question 2"
+            , question: "Question 2"
+            , enabled: null
+            , type: InputType.TEXT
+            , validation: []
+        };
+
+        const input: Input = new Input(options);
+
+        expect(input).to.be.a("object");
+        expect(input.enabled).to.be.equal(true);
+
+        done();
+    });
+
+    it("should create a Input with option key 'enabled' as true", (done) => {
+        const options: InputOptions = {
+            placement: 1
+            , description: "Description Question 2"
+            , question: "Question 2"
+            , enabled: true
+            , type: InputType.TEXT
+            , validation: []
+        };
+
+        const input: Input = new Input(options);
+
+        expect(input).to.be.a("object");
+        expect(input.enabled).to.be.equal(true);
+
+        done();
+    });
+
+    it("should create a Input with option key 'enabled' as false", (done) => {
+        const options: InputOptions = {
+            placement: 1
+            , description: "Description Question 2"
+            , question: "Question 2"
+            , enabled: false
+            , type: InputType.TEXT
+            , validation: []
+        };
+
+        const input: Input = new Input(options);
+
+        expect(input).to.be.a("object");
+        expect(input.enabled).to.be.equal(false);
+
+        done();
+    });
+
+});
diff --git a/src/core/input.ts b/src/core/input.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f7097aa46aede4916908aa5a513db39bb8b9c5fa
--- /dev/null
+++ b/src/core/input.ts
@@ -0,0 +1,89 @@
+/*
+ * form-creator-api. RESTful API to manage and answer forms.
+ * Copyright (C) 2019 Centro de Computacao Cientifica e Software Livre
+ * Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR
+ *
+ * This file is part of form-creator-api.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+import { InputType, ValidationType } from "../utils/enumHandler";
+
+/** Parameters used to create a input object. */
+export interface InputOptions {
+    /** Unique identifier of a Input instance. */
+     id?: number;
+    /** Place where input should be in the form. */
+     placement: number;
+    /** Input's Description */
+     description: string;
+    /** Question of input */
+     question: string;
+    /** Enabled/Disable input */
+     enabled?: boolean;
+    /** Type of input */
+     type: InputType;
+    /** Array contain all input's validation */
+     validation: Validation[];
+}
+/** Validation contains the type of it, and n arguments to validate if necessary */
+export interface Validation {
+
+    /** Enum Validation Type to identify the type of current validation */
+    type: ValidationType;
+    /** Array of any, to store informations about validadtion */
+    arguments: string[];
+}
+
+/**
+ * Input Class to manage project's inputs forms
+ */
+
+export class Input {
+    /** Unique identifier of a Input instance. */
+    public readonly id: number;
+    /** Place where input should be in the form. */
+    public readonly placement: number;
+    /** Input's Description */
+    public readonly description: string;
+    /** Question of input */
+    public readonly question: string;
+    /** Enabled/Disable input */
+    public readonly enabled: boolean;
+    /** Type of input */
+    public readonly type: InputType;
+    /** Array contain all input's validation */
+    public readonly validation: Validation[];
+
+    /**
+     * Creates a new instance of Input Class
+     * @param options - InputOptions instance to create a input.
+     */
+    constructor(options: InputOptions) {
+        this.id = options.id ? options.id : null;
+        this.placement = options.placement;
+        this.description = options.description;
+        this.question = options.question;
+        if ((options.enabled === undefined) || (options.enabled === null) ) {
+            this.enabled = true;
+        }
+        else {
+            this.enabled = options.enabled;
+        }
+        this.type = options.type;
+        this.validation = options.validation;
+    }
+
+}
diff --git a/src/core/inputAnswer.spec.ts b/src/core/inputAnswer.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e70e86c32c425444b514a039a87452919a093d21
--- /dev/null
+++ b/src/core/inputAnswer.spec.ts
@@ -0,0 +1,20 @@
+/*
+ * form-creator-api. RESTful API to manage and answer forms.
+ * Copyright (C) 2019 Centro de Computacao Cientifica e Software Livre
+ * Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR
+ *
+ * This file is part of form-creator-api.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
diff --git a/src/core/inputAnswer.ts b/src/core/inputAnswer.ts
new file mode 100644
index 0000000000000000000000000000000000000000..6737a5cb0c1e14c6dce27a2195c129e906310f4a
--- /dev/null
+++ b/src/core/inputAnswer.ts
@@ -0,0 +1,70 @@
+/*
+ * form-creator-api. RESTful API to manage and answer forms.
+ * Copyright (C) 2019 Centro de Computacao Cientifica e Software Livre
+ * Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR
+ *
+ * This file is part of form-creator-api.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+ /** Parameters used to create a input object. */
+ export interface InputAnswerOptions {
+     /** Unique identifier of a InputAnswer instance. */
+      id?: number;
+     /** Input id which this answer came from. */
+      idInput: number;
+     /** Place where answers should be (multivalored answers). */
+      placement: number;
+     /** Input's answer */
+      value: string;
+ }
+
+/** Parameters used to create a dictionary to uses as an collection of InputAnswerOptions Object. */
+ export interface InputAnswerOptionsDict {
+     /** A key is a identifier of a Input instance */
+    [key: number]: InputAnswerOptions[];
+}
+
+/** Parameters used to create a dictionary to uses as an collection of InputAnswer Object.. */
+ export interface InputAnswerDict {
+     /** A key is a identifier of a Input instance */
+    [key: number]: InputAnswer[];
+}
+
+/**
+ * Input Class to manage project's inputs forms
+ */
+ export class InputAnswer {
+    /** Unique identifier of a Input Answer instance. */
+    public readonly id: number;
+    /** A identifier of a Input instance. */
+    public readonly idInput: number;
+    /** Place where input should be in the form. */
+    public readonly placement: number;
+    /** Input's Description */
+    public readonly value: string;
+
+    /**
+     * Creates a new instance of InputAnswer Class
+     * @param options - InputOptionsAnswer instance to create a inputAnswer.
+     */
+    constructor(options: InputAnswerOptions) {
+        this.id = options.id ? options.id : null;
+        this.idInput = options.idInput;
+        this.placement = options.placement;
+        this.value = options.value;
+    }
+
+}
diff --git a/src/core/inputUpdate.spec.ts b/src/core/inputUpdate.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..3e6b91247229ee6af78a099bbdde620154ef8875
--- /dev/null
+++ b/src/core/inputUpdate.spec.ts
@@ -0,0 +1,67 @@
+/*
+ * form-creator-api. RESTful API to manage and answer forms.
+ * Copyright (C) 2019 Centro de Computacao Cientifica e Software Livre
+ * Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR
+ *
+ * This file is part of form-creator-api.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+import { expect } from "chai";
+import { InputType, UpdateType, ValidationType } from "../utils/enumHandler";
+import { TestHandler } from "../utils/testHandler";
+import { Input, InputOptions } from "./input";
+import { InputUpdate, InputUpdateOptions } from "./inputUpdate";
+
+describe("InputUpdate", () => {
+    it("should create a valid InputUpdate with id null", (done) => {
+
+        const inputObj: InputOptions = {
+            placement: 0
+            , description: "Description Question 1 Form 1"
+            , question: "Question 1 Form 1"
+            , enabled: true
+            , type: InputType.TEXT
+            , validation: []
+            , id: 1
+        };
+        const inputUpdateObj: InputUpdateOptions = {
+            input: inputObj
+            , inputOperation: UpdateType.ADD
+            , value: null
+        };
+
+        const resInputUpdate: InputUpdate = new InputUpdate(inputUpdateObj);
+
+        const expInput: Input = {
+            placement: 0
+            , description: "Description Question 1 Form 1"
+            , question: "Question 1 Form 1"
+            , enabled: true
+            , type: InputType.TEXT
+            , validation: []
+            , id: 1
+        };
+        const expInputUpdate: InputUpdate = {
+            input: expInput
+            , inputOperation: UpdateType.ADD
+            , value: null
+            , id: null
+        };
+
+        TestHandler.testInputUpdate(resInputUpdate, expInputUpdate);
+        done();
+    });
+});
diff --git a/src/core/inputUpdate.ts b/src/core/inputUpdate.ts
new file mode 100644
index 0000000000000000000000000000000000000000..48799dc322f7b277005dec3a2254ffbc707962d8
--- /dev/null
+++ b/src/core/inputUpdate.ts
@@ -0,0 +1,59 @@
+/*
+ * form-creator-api. RESTful API to manage and answer forms.
+ * Copyright (C) 2019 Centro de Computacao Cientifica e Software Livre
+ * Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR
+ *
+ * This file is part of form-creator-api.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+import { UpdateType } from "../utils/enumHandler";
+import { Input, InputOptions } from "./input";
+
+/** Parameters used to update a input object. */
+export interface InputUpdateOptions {
+    /** Unique identifier of a FormUpdate instance. */
+    id?: number;
+    /** Changed Input. */
+    input: InputOptions;
+    /** Update operation. */
+    inputOperation: UpdateType;
+    /** Update description. */
+    value: string;
+}
+
+/**
+ * InputUpdate Class to change project's inputs forms
+ */
+export class InputUpdate {
+    /** Unique identifier of a FormUpdate instance. */
+    public readonly id?: number;
+    /** Changed Input. */
+    public readonly input: Input;
+    /** Update operation. */
+    public readonly inputOperation: UpdateType;
+     /** Update description. */
+    public readonly value: string;
+    /**
+     * Creates a new instance of InputUpdate Class
+     * @param options - InputUpdateOptions instance to change a input.
+     */
+    constructor(options: InputUpdateOptions) {
+        this.id = options.id ? options.id : null;
+        this.input = new Input(options.input);
+        this.inputOperation = options.inputOperation;
+        this.value = options.value;
+    }
+}
diff --git a/src/main.ts b/src/main.ts
index 28fd22a24ec6ada905e5319e9db9c4e8d89ada62..110396cbee8c8c194ccfde88f431705abdc2ca28 100755
--- a/src/main.ts
+++ b/src/main.ts
@@ -36,23 +36,25 @@ const app = module.exports = express();
 const port = process.env.PORT;
 
 // Include middlewares
-import { CollectionMw } from "./api/middlewares/collection";
+import { DbHandlerMw } from "./api/middlewares/dbHandler";
 
 // Include controllers
-import { ItemCtrl } from "./api/controllers/item";
+import { FormCtrl } from "./api/controllers/form";
+import { AnswerCtrl } from "./api/controllers/formAnswer";
 
 // Setup middlewares
 app.use("/", bodyParser.json());
-app.use("/", CollectionMw());
+app.use("/", DbHandlerMw());
 
 // Setup routes
 
-app.get("/item/:id", ItemCtrl.read);
-app.post("/item", ItemCtrl.write);
-app.put("/item/:id", ItemCtrl.update);
-app.delete("/item/:id", ItemCtrl.del);
+app.get("/form/", FormCtrl.list);
+app.get("/form/:id", FormCtrl.read);
+app.put("/form/:id", FormCtrl.update);
+app.post("/form", FormCtrl.write);
+app.post("/answer/:id", AnswerCtrl.write);
 
 // Listening
 
 app.listen(port);
-console.log("Server listening on port 3000");
+console.log("Server listening on port " + port);
diff --git a/src/utils/config.spec.ts b/src/utils/config.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..3daebb1368f5adf30c78a566d116ddf957a60ad3
--- /dev/null
+++ b/src/utils/config.spec.ts
@@ -0,0 +1,33 @@
+/*
+ * form-creator-api. RESTful API to manage and answer forms.
+ * Copyright (C) 2019 Centro de Computacao Cientifica e Software Livre
+ * Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR
+ *
+ * This file is part of form-creator-api.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+ import { expect } from "chai";
+ import { configs } from "./config";
+
+ describe("Config Handler", () => {
+     it("should test configs", () => {
+
+         expect(configs.poolconfig["user"]).to.be.equal(process.env["POSTGRES_USER"]);
+         expect(configs.poolconfig["host"]).to.be.equal(process.env["POSTGRES_HOST"]);
+         expect(configs.poolconfig["database"]).to.be.equal(process.env["POSTGRES_DB"]);
+         expect(configs.poolconfig["password"]).to.be.equal(process.env["POSTGRES_PASSWORD"]);
+         expect(configs.poolconfig["port"]).to.be.equal(parseInt(process.env["POSTGRES_PORT"], 10));
+     });
+ });
diff --git a/src/utils/config.ts b/src/utils/config.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ce2eef0aa7496ac0a65c3b959576cca8073ff59c
--- /dev/null
+++ b/src/utils/config.ts
@@ -0,0 +1,56 @@
+/*
+ * form-creator-api. RESTful API to manage and answer forms.
+ * Copyright (C) 2019 Centro de Computacao Cientifica e Software Livre
+ * Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR
+ *
+ * This file is part of form-creator-api.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+import { PoolConfig } from "pg";
+
+class Config {
+    private static instance: Config;
+    private user: string;
+    private host: string;
+    private database: string;
+    private password: string;
+    private port: number;
+    public readonly poolconfig: PoolConfig;
+
+    private constructor(){
+        this.user = process.env["POSTGRES_USER"];
+        this.host = process.env["POSTGRES_HOST"];
+        this.database = process.env["POSTGRES_DB"];
+        this.password = process.env["POSTGRES_PASSWORD"];
+        this.port = parseInt(process.env["POSTGRES_PORT"], 10);
+        this.poolconfig = {
+           user: this.user,
+           database: this.database,
+           password: this.password,
+           host: this.host,
+           port: this.port,
+           max: 10,
+           idleTimeoutMillis: 3000
+       };
+
+    }
+
+    public static get Configurations(){
+        return this.instance || (this.instance = new this());
+    }
+}
+
+export const configs = Config.Configurations;
diff --git a/src/utils/dbHandler.spec.ts b/src/utils/dbHandler.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..441b866e4f6187196bf6cbde6d578f0a12a32486
--- /dev/null
+++ b/src/utils/dbHandler.spec.ts
@@ -0,0 +1,711 @@
+/*
+ * form-creator-api. RESTful API to manage and answer forms.
+ * Copyright (C) 2019 Centro de Computacao Cientifica e Software Livre
+ * Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR
+ *
+ * This file is part of form-creator-api.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+import { series } from "async";
+import { expect } from "chai";
+import { QueryResult } from "pg";
+import { Form, FormOptions } from "../core/form";
+import { FormAnswer, FormAnswerOptions } from "../core/formAnswer";
+import { FormUpdate, FormUpdateOptions } from "../core/formUpdate";
+import { Input, InputOptions, Validation } from "../core/input";
+import { InputAnswer, InputAnswerDict, InputAnswerOptions, InputAnswerOptionsDict } from "../core/inputAnswer";
+import { InputUpdate, InputUpdateOptions } from "../core/inputUpdate";
+import { configs } from "./config";
+import { DbHandler, QueryOptions } from "./dbHandler";
+import { InputType, UpdateType, ValidationType } from "./enumHandler";
+import { OptHandler } from "./optHandler";
+import { TestHandler } from "./testHandler";
+
+describe("Database Handler", () => {
+    const dbhandler = new DbHandler(configs.poolconfig);
+
+    it("should insert a form", (done) => {
+        const queryString: string = "INSERT INTO form(id, title, description)\
+            VALUES (5, 'Form Title 5', 'Form Description 5');";
+        const query: QueryOptions = {query: queryString, parameters: []};
+        dbhandler.executeQuery(query, (err: Error, result?: QueryResult) => {
+            expect(err).to.be.a("null");
+            expect(result.command).to.be.equal("INSERT");
+            expect(result.rowCount).to.be.equal(1);
+            done();
+
+        });
+    });
+
+    it("should insert a form and then rollback", (done) => {
+    series([
+        (cb: (err: Error, result?: QueryResult) =>  void) => {
+            dbhandler.begin(cb);
+        },
+        (callback: (err: Error, result?: QueryResult) =>  void) => {
+            const queryString: string = "INSERT INTO form(id, title, description)\
+            VALUES (6, 'Form Title 6', 'Form Description 6');";
+            const query: QueryOptions = {query: queryString, parameters: []};
+
+            dbhandler.executeQuery(query, callback);
+        },
+        (cb: (err: Error, result?: QueryResult) =>  void) => {
+            dbhandler.rollback(cb);
+        }
+    ], (err, results) => {
+
+        expect(err).to.be.a("null");
+        expect(results[0].command).to.be.equal("BEGIN");
+        expect(results[1].command).to.be.equal("INSERT");
+        expect(results[1].rowCount).to.be.equal(1);
+        expect(results[2].command).to.be.equal("ROLLBACK");
+        done();
+
+        });
+    });
+
+    it("should select all forms", (done) => {
+        const queryString: string = "SELECT * FROM form;";
+        const query: QueryOptions = {query: queryString, parameters: []};
+        dbhandler.executeQuery(query, (err: Error, result?: QueryResult) => {
+            expect(err).to.be.a("null");
+            expect(result.command).to.be.equal("SELECT");
+            expect(result.rowCount).to.be.equal(5);
+            done();
+
+        });
+    });
+
+    it("should remove non existent form", (done) => {
+        const queryString: string = "DELETE FROM form WHERE id=6;";
+
+        const query: QueryOptions = {query: queryString, parameters: []};
+
+        dbhandler.executeQuery(query, (err: Error, result?: QueryResult) => {
+            expect(err).to.be.a("null");
+            expect(result.command).to.be.equal("DELETE");
+            expect(result.rowCount).to.be.equal(0);
+            done();
+
+        });
+    });
+
+    it("should remove existent form", (done) => {
+        const queryString: string = "DELETE FROM form WHERE id=5;";
+        const query: QueryOptions = {query: queryString, parameters: []};
+        dbhandler.executeQuery(query, (err: Error, result?: QueryResult) => {
+            expect(err).to.be.a("null");
+            expect(result.command).to.be.equal("DELETE");
+            expect(result.rowCount).to.be.equal(1);
+            done();
+
+        });
+    });
+
+    it("should insert a input", (done) => {
+        const queryString: string = "INSERT INTO input(id_form, placement, input_type, enabled, question, description)\
+        VALUES\
+        (2, 3,'TEXT', TRUE, 'Question 3 Form 2', 'Description Question 3 Form 2'),\
+        (2, 4,'TEXT', TRUE, 'Question 4 Form 2', 'Description Question 4 Form 2');";
+        const query: QueryOptions = {query: queryString, parameters: []};
+        dbhandler.executeQuery(query,  (err: Error, result?: QueryResult) => {
+            expect(err).to.be.a("null");
+            expect(result.command).to.be.equal("INSERT");
+            expect(result.rowCount).to.be.equal(2);
+            done();
+        });
+    });
+
+    it("should select all inputs", (done) => {
+        const queryString: string = "SELECT * FROM input;";
+        const query: QueryOptions = {query: queryString, parameters: []};
+
+        dbhandler.executeQuery(query, (err: Error, result?: QueryResult) => {
+            expect(err).to.be.a("null");
+            expect(result.command).to.be.equal("SELECT");
+            expect(result.rowCount).to.be.equal(15);
+            done();
+
+        });
+    });
+
+    it("should remove non existent input", (done) => {
+        const queryString: string = "DELETE FROM input WHERE id=20;";
+        const query: QueryOptions = {query: queryString, parameters: []};
+
+        dbhandler.executeQuery(query, (err: Error, result?: QueryResult) =>  {
+            expect(err).to.be.a("null");
+            expect(result.command).to.be.equal("DELETE");
+            expect(result.rowCount).to.be.equal(0);
+            done();
+        });
+    });
+
+    it("should remove existent input", (done) => {
+        const queryString: string = "DELETE FROM input WHERE id=12 OR id=13 OR id=14 OR id=15;";
+        const query: QueryOptions = {query: queryString, parameters: []};
+
+        dbhandler.executeQuery(query, (err: Error, result?: QueryResult) => {
+            expect(err).to.be.a("null");
+            expect(result.command).to.be.equal("DELETE");
+            expect(result.rowCount).to.be.equal(4);
+            done();
+
+        });
+    });
+
+    it("should insert a input validations", (done) => {
+        const queryString: string = "INSERT INTO input_validation(id_input, validation_type)\
+        VALUES\
+        (2, 'MAXCHAR'),\
+        (5, 'MANDATORY');";
+        const query: QueryOptions = {query: queryString, parameters: []};
+
+        dbhandler.executeQuery(query, (err: Error, result?: QueryResult) => {
+            expect(err).to.be.a("null");
+            expect(result.command).to.be.equal("INSERT");
+            expect(result.rowCount).to.be.equal(2);
+            done();
+        });
+    });
+
+    it("should select all input validations", (done) => {
+        const queryString: string = "SELECT * FROM input_validation;";
+        const query: QueryOptions = {query: queryString, parameters: []};
+
+        dbhandler.executeQuery(query, (err: Error, result?: QueryResult) => {
+            expect(err).to.be.a("null");
+            expect(result.command).to.be.equal("SELECT");
+            expect(result.rowCount).to.be.equal(18);
+            done();
+        });
+    });
+
+    it("should remove non existent input validations", (done) => {
+        const queryString: string = "DELETE FROM input_validation WHERE id=21;";
+        const query: QueryOptions = {query: queryString, parameters: []};
+
+        dbhandler.executeQuery(query, (err: Error, result?: QueryResult) => {
+            expect(err).to.be.a("null");
+            expect(result.command).to.be.equal("DELETE");
+            expect(result.rowCount).to.be.equal(0);
+            done();
+        });
+    });
+
+    it("should remove existent input validations", (done) => {
+        const queryString: string = "DELETE FROM input_validation WHERE id=17 OR id=18;";
+        const query: QueryOptions = {query: queryString, parameters: []};
+
+        dbhandler.executeQuery(query, (err: Error, result?: QueryResult) => {
+            expect(err).to.be.a("null");
+            expect(result.command).to.be.equal("DELETE");
+            expect(result.rowCount).to.be.equal(2);
+            done();
+        });
+    });
+
+    it("should insert a input validations arguments", (done) => {
+        const queryString: string = "INSERT INTO input_validation_argument(id_input_validation, placement, argument)\
+        VALUES\
+        (1, 2, '10'),\
+        (2, 2, '2');";
+        const query: QueryOptions = {query: queryString, parameters: []};
+
+        dbhandler.executeQuery(query, (err: Error, result?: QueryResult) => {
+            expect(err).to.be.a("null");
+            expect(result.command).to.be.equal("INSERT");
+            expect(result.rowCount).to.be.equal(2);
+            done();
+        });
+
+    });
+
+    it("should select all input validations arguments", (done) => {
+        const queryString: string = "SELECT * FROM input_validation_argument;";
+        const query: QueryOptions = {query: queryString, parameters: []};
+
+        dbhandler.executeQuery(query, (err: Error, result?: QueryResult) => {
+            expect(err).to.be.a("null");
+            expect(result.command).to.be.equal("SELECT");
+            expect(result.rowCount).to.be.equal(13);
+            done();
+        });
+    });
+
+    it("should remove non existent input validations arguments", (done) => {
+        const queryString: string = "DELETE FROM input_validation_argument WHERE id=15;";
+        const query: QueryOptions = {query: queryString, parameters: []};
+
+        dbhandler.executeQuery(query, (err: Error, result?: QueryResult) => {
+            expect(err).to.be.a("null");
+            expect(result.command).to.be.equal("DELETE");
+            expect(result.rowCount).to.be.equal(0);
+            done();
+        });
+    });
+
+    it("should remove existent input validations arguments", (done) => {
+        const queryString: string = "DELETE FROM input_validation_argument WHERE id=12 OR id=13;";
+        const query: QueryOptions = {query: queryString, parameters: []};
+
+        dbhandler.executeQuery(query, (err: Error, result?: QueryResult) => {
+            expect(err).to.be.a("null");
+            expect(result.command).to.be.equal("DELETE");
+            expect(result.rowCount).to.be.equal(2);
+            done();
+        });
+    });
+
+    it("should insert a form answers", (done) => {
+        const queryString: string = "INSERT INTO form_answer(id ,id_form, answered_at)\
+        VALUES\
+        (8, 2, '2018-07-02 10:10:25-03'),\
+        (9, 3, '2018-06-03 10:11:25-03');";
+        const query: QueryOptions = {query: queryString, parameters: []};
+
+        dbhandler.executeQuery(query, (err: Error, result?: QueryResult) => {
+            expect(err).to.be.a("null");
+            expect(result.command).to.be.equal("INSERT");
+            expect(result.rowCount).to.be.equal(2);
+            done();
+        });
+    });
+
+    it("should select all form answers", (done) => {
+        const queryString: string = "SELECT * FROM form_answer;";
+        const query: QueryOptions = {query: queryString, parameters: []};
+
+        dbhandler.executeQuery(query, (err: Error, result?: QueryResult) => {
+            expect(err).to.be.a("null");
+            expect(result.command).to.be.equal("SELECT");
+            expect(result.rowCount).to.be.equal(9);
+            done();
+        });
+    });
+
+    it("should remove non existent form answer", (done) => {
+        const queryString: string = "DELETE FROM form_answer WHERE id=11;";
+        const query: QueryOptions = {query: queryString, parameters: []};
+
+        dbhandler.executeQuery(query, (err: Error, result?: QueryResult) => {
+            expect(err).to.be.a("null");
+            expect(result.command).to.be.equal("DELETE");
+            expect(result.rowCount).to.be.equal(0);
+            done();
+        });
+    });
+
+    it("should remove existent form answers", (done) => {
+        const queryString: string = "DELETE FROM form_answer WHERE id=8 OR id=9;";
+        const query: QueryOptions = {query: queryString, parameters: []};
+
+        dbhandler.executeQuery(query, (err: Error, result?: QueryResult) => {
+            expect(err).to.be.a("null");
+            expect(result.command).to.be.equal("DELETE");
+            expect(result.rowCount).to.be.equal(2);
+            done();
+        });
+
+    });
+
+    it("should insert a input answers", (done) => {
+        const queryString: string = "INSERT INTO input_answer(id, id_form_answer, id_input, value, placement)\
+        VALUES\
+        (18,1, 6,'Answer to Question 1 Form 3',1),\
+        (19,1, 7,'Answer to Question 2 Form 3',2);";
+        const query: QueryOptions = {query: queryString, parameters: []};
+
+        dbhandler.executeQuery(query, (err: Error, result?: QueryResult) => {
+            expect(err).to.be.a("null");
+            expect(result.command).to.be.equal("INSERT");
+            expect(result.rowCount).to.be.equal(2);
+            done();
+        });
+    });
+
+    it("should select all form answers", (done) => {
+        const queryString: string = "SELECT * FROM input_answer;";
+        const query: QueryOptions = {query: queryString, parameters: []};
+
+        dbhandler.executeQuery(query, (err: Error, result?: QueryResult) => {
+            expect(err).to.be.a("null");
+            expect(result.command).to.be.equal("SELECT");
+            expect(result.rowCount).to.be.equal(19);
+            done();
+        });
+    });
+
+    it("should remove non existent input answer", (done) => {
+        const queryString: string = "DELETE FROM input_answer WHERE id=25;";
+        const query: QueryOptions = {query: queryString, parameters: []};
+
+        dbhandler.executeQuery(query, (err: Error, result?: QueryResult) => {
+            expect(err).to.be.a("null");
+            expect(result.command).to.be.equal("DELETE");
+            expect(result.rowCount).to.be.equal(0);
+            done();
+        });
+    });
+
+    it("should remove existent input answers", (done) => {
+        const queryString: string = "DELETE FROM input_answer WHERE id=18 OR id=19;";
+        const query: QueryOptions = {query: queryString, parameters: []};
+
+        dbhandler.executeQuery(query, (err: Error, result?: QueryResult) => {
+            expect(err).to.be.a("null");
+            expect(result.command).to.be.equal("DELETE");
+            expect(result.rowCount).to.be.equal(2);
+            done();
+        });
+    });
+});
+
+describe("Read and Write on Database", () => {
+    const dbhandler = new DbHandler(configs.poolconfig);
+    it("should list all forms", (done) => {
+        dbhandler.listForms((err: Error, forms?: Form[]) => {
+            expect(err).to.be.a("null");
+            expect(forms.length).to.be.equal(4);
+            for (let i = 0; i < forms.length; i++){
+                expect(forms[i].id).to.be.equal(i + 1);
+                expect(forms[i].title).to.be.equal("Form Title " + (i + 1));
+                expect(forms[i].description).to.be.equal("Form Description " + (i + 1));
+            }
+            done();
+        });
+    });
+
+    it("should read an existent form", (done) => {
+        dbhandler.readForm(1, (err: Error, form: Form) => {
+            expect(err).to.be.a("null");
+
+            const inputObj1: InputOptions = {
+                placement: 0
+                , description: "Description Question 1 Form 1"
+                , question: "Question 1 Form 1"
+                , type: InputType.TEXT
+                , validation: []
+                , id: 1
+            };
+
+            const inputObj2: InputOptions = {
+                placement: 2
+                , description: "Description Question 2 Form 1"
+                , question:  "Question 2 Form 1"
+                , type: InputType.TEXT
+                , validation: [
+                    { type: ValidationType.MAXCHAR, arguments: ["10"] }
+                    , { type: ValidationType.MINCHAR, arguments: ["2"] }
+                ]
+                , id: 3
+            };
+
+            const inputObj3: InputOptions = {
+                placement: 1
+                , description: "Description Question 3 Form 1"
+                , question: "Question 3 Form 1"
+                , type: InputType.TEXT
+                , validation: [
+                    { type: ValidationType.REGEX, arguments: ["\\d{5}-\\d{3}"] }
+                    , { type: ValidationType.MANDATORY, arguments: [] }
+                ]
+                , id: 2
+            };
+            const formObj: FormOptions = {
+                id: 1
+                , title: "Form Title 1"
+                , description: "Form Description 1"
+                , inputs: [
+                    OptHandler.input(inputObj1)
+                    , OptHandler.input(inputObj3)
+                    , OptHandler.input(inputObj2)
+                ]
+            };
+
+            TestHandler.testForm(form, new Form(OptHandler.form(formObj)));
+
+            done();
+        });
+    });
+
+    it("should read a non existent form", (done) => {
+        dbhandler.readForm(10, (err: Error, form: Form) => {
+            expect(err).to.not.equal(null);
+            expect(form).to.be.undefined;
+
+            done();
+        });
+    });
+
+    it("should write form", (done) => {
+
+        const inputObj1: InputOptions = {
+            placement: 0
+            , description: "Description Question 1 Form 1"
+            , question: "Question 1 Form 1"
+            , enabled: true
+            , type: InputType.TEXT
+            , validation: [
+                { type: ValidationType.MANDATORY, arguments: [] }
+            ]
+        };
+
+        const inputObj2 = {
+            placement: 1
+            , description: "Description Question 2 Form 2"
+            , question:  "Question 2 Form 2"
+            , enabled: true
+            , type:  InputType.TEXT
+            , validation: [
+                { type: ValidationType.MINCHAR, arguments: ["5"] }
+            ]
+        };
+
+        const formObj: FormOptions = {
+            title: "Form Title 1"
+            , description: "Form Description 1"
+            , inputs: [
+                OptHandler.input(inputObj1)
+                , OptHandler.input(inputObj2)
+            ]
+        };
+
+        const form = new Form(OptHandler.form(formObj));
+        dbhandler.writeForm(form, (err: Error, formResult: Form) => {
+            expect(err).to.be.a("null");
+            expect(formResult.id).to.be.equal(5);
+            let inputId: number = 16;
+            for (const input of formResult.inputs){
+                expect(input.id).to.be.equal(inputId);
+                inputId++;
+            }
+            done();
+        });
+
+    });
+
+    it("should read an existent form Answer", (done) => {
+
+        const inputAnswersOpt1: InputAnswerOptions  = {
+            id: 5
+            , idInput: 1
+            , placement: 0
+            , value: "Answer to Question 1 Form 1"
+       };
+        const inputAnswersOpt2: InputAnswerOptions  = {
+            id: 6
+            , idInput: 2
+            , placement: 0
+            , value: "Answer to Question 2 Form 1"
+       };
+        const inputAnswersOpt3: InputAnswerOptions  = {
+            id: 7
+            , idInput: 3
+            , placement: 0
+            , value: "Answer to Question 3 Form 1"
+       };
+
+        const inputAnswerOptionsDict: InputAnswerOptionsDict = {1: [inputAnswersOpt1], 2: [inputAnswersOpt2], 3: [inputAnswersOpt3]};
+        const data: Date = new Date("2019-02-21 12:10:25");
+        dbhandler.readForm(1, (error: Error, form: Form) => {
+            const formAnswerOptions: FormAnswerOptions = {
+               id: 3
+               , form
+               , timestamp: data
+               , inputsAnswerOptions: inputAnswerOptionsDict
+           };
+            dbhandler.readFormAnswer(3, (err: Error, formAnswer: FormAnswer) => {
+               TestHandler.testFormAnswer(formAnswer, new FormAnswer(OptHandler.formAnswer(formAnswerOptions)));
+               done();
+
+           });
+        });
+
+    });
+
+    it("should read a non existent form Answer", (done) => {
+        dbhandler.readFormAnswer(25, (err: Error, formAnswer: FormAnswer) => {
+            expect(err).to.not.equal(null);
+            expect(formAnswer).to.be.undefined;
+
+            done();
+        });
+
+    });
+
+    it("should write form Answer", (done) => {
+
+        const inputAnswersOpt1: InputAnswerOptions  = {
+            id: 5
+            , idInput: 1
+            , placement: 0
+            , value: "Answer to Question 1 Form 1"
+       };
+        const inputAnswersOpt2: InputAnswerOptions  = {
+            id: 6
+            , idInput: 2
+            , placement: 0
+            , value: "Answer to Question 2 Form 1"
+       };
+        const inputAnswersOpt3: InputAnswerOptions  = {
+            id: 7
+            , idInput: 3
+            , placement: 0
+            , value: "Answer to Question 3 Form 1"
+       };
+        const inputAnswerOptionsDict: InputAnswerOptionsDict = {1: [inputAnswersOpt1], 2: [inputAnswersOpt2], 3: [inputAnswersOpt3]};
+        const data: Date = new Date(2019, 6, 4);
+        dbhandler.readForm(1, (error: Error, form: Form) => {
+           const formAnswerOptions: FormAnswerOptions = {
+               form
+               , timestamp: data
+               , inputsAnswerOptions: inputAnswerOptionsDict
+           };
+           const formAnswer = new FormAnswer(OptHandler.formAnswer(formAnswerOptions));
+
+           dbhandler.writeFormAnswer(formAnswer, (err: Error, formAnswerResult: FormAnswer) => {
+               expect(err).to.be.a("null");
+               expect(formAnswerResult.id).to.be.equal(8);
+               let inputAnswerId: number = 18;
+               for (const key of Object.keys(formAnswerResult.inputAnswers)){
+                   for (const inputAnswer of formAnswerResult.inputAnswers[parseInt(key, 10)]){
+                       expect(inputAnswer.id).to.be.equal(inputAnswerId);
+                       inputAnswerId++;
+                   }
+
+               }
+               done();
+           });
+       });
+    });
+
+    it("should insert an formUpdate", (done) => {
+        const inputObj1: InputOptions = {
+            placement: 0
+            , description: "Description Question 1 Form 1"
+            , question: "Question 1 Form 1"
+            , type: InputType.TEXT
+            , validation: []
+            , id: 1
+        };
+        const updateObj1: InputUpdateOptions = {
+            id: 1
+            , input: inputObj1
+            , inputOperation: UpdateType.REMOVE
+            , value: null
+        };
+
+        const inputObj2: InputOptions = {
+            placement: 1
+            , description: "Description Question 2 Form 1"
+            , question:  "Question 2 Form 1"
+            , type: InputType.TEXT
+            , validation: [
+                { type: ValidationType.MAXCHAR, arguments: ["10"] }
+                , { type: ValidationType.MINCHAR, arguments: ["2"] }
+            ]
+            , id: 3
+        };
+        const updateObj2: InputUpdateOptions = {
+            id: 2
+            , input: inputObj2
+            , inputOperation: UpdateType.REMOVE
+            , value: null
+        };
+
+        const inputObj3: InputOptions = {
+            placement: 2
+            , description: "Description Question 3 Form 1"
+            , question: "Question 3 Form 1"
+            , type: InputType.TEXT
+            , validation: [
+                { type: ValidationType.REGEX, arguments: ["\\d{5}-\\d{3}"] }
+                , { type: ValidationType.MANDATORY, arguments: [] }
+            ]
+            , id: 2
+        };
+        const updateObj3: InputUpdateOptions = {
+            id: 3
+            , input: inputObj3
+            , inputOperation: UpdateType.REMOVE
+            , value: null
+        };
+
+        const formObj: FormOptions = {
+            id: 1
+            , title: "Form Title 1"
+            , description: "Form Description 1"
+            , inputs: [
+                inputObj1
+                , inputObj2
+                , inputObj3
+            ]
+        };
+        const dateTMP: Date = new Date();
+        const formUpdateObj: FormUpdateOptions = {
+            id: 1
+            , form: formObj
+            , updateDate: dateTMP
+            , inputUpdates: [
+                updateObj1
+                , updateObj2
+                , updateObj3
+            ]
+        };
+
+        let formUpdateTmp: FormUpdate;
+
+        formUpdateTmp = new FormUpdate(formUpdateObj);
+        dbhandler.updateForm(formUpdateTmp, (err: Error) => {
+            expect(err).to.be.a("null");
+            done();
+        });
+    });
+
+    it("should not update database operation not recognized", (done) => {
+        const inputObj: Input = {
+            placement: 0
+            , description: "Description Question 1 Form 1"
+            , question: "Question 1 Form 1"
+            , enabled: true
+            , type: InputType.TEXT
+            , validation: []
+            , id: 1
+        };
+        const formObj: Form = {
+            id: 1
+            , title: "Form Title 1"
+            , description: "Form Description 1"
+            , inputs: [ inputObj ]
+        };
+
+        const inputUpdateObj: InputUpdate = {
+            input: inputObj
+            , inputOperation: 10
+            , value: "Invalid Operation"
+        };
+        const formUpdateObj: FormUpdate = {
+            form: formObj
+            , updateDate: new Date()
+            , inputUpdates: [ inputUpdateObj ]
+        };
+
+        dbhandler.updateDatabase(formUpdateObj, (err: Error) => {
+            expect(err).to.be.not.a("null");
+            done();
+        });
+    });
+});
diff --git a/src/utils/dbHandler.ts b/src/utils/dbHandler.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b7b06542be5bedee40930b1a9ce0801d6654785c
--- /dev/null
+++ b/src/utils/dbHandler.ts
@@ -0,0 +1,946 @@
+/*
+ * form-creator-api. RESTful API to manage and answer forms.
+ * Copyright (C) 2019 Centro de Computacao Cientifica e Software Livre
+ * Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR
+ *
+ * This file is part of form-creator-api.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+import { eachOfSeries, eachSeries, map, seq, waterfall } from "async";
+import { Pool, PoolConfig, QueryResult } from "pg";
+import { Form, FormOptions } from "../core/form";
+import { FormAnswer, FormAnswerOptions } from "../core/formAnswer";
+import { FormUpdate, FormUpdateOptions } from "../core/formUpdate";
+import { Input, InputOptions, Validation } from "../core/input";
+import { InputAnswer, InputAnswerDict, InputAnswerOptions, InputAnswerOptionsDict } from "../core/inputAnswer";
+import { InputUpdate, InputUpdateOptions } from "../core/inputUpdate";
+import { EnumHandler, InputType, UpdateType, ValidationType } from "./enumHandler";
+import { ErrorHandler} from "./errorHandler";
+import { OptHandler } from "./optHandler";
+import { Sorter } from "./sorter";
+
+/** Parameters used to create a parametrized query, to avoid SQL injection */
+export interface QueryOptions {
+    /** query string to execute */
+    query: string;
+
+    /** Array of input. containing question */
+    parameters: any[];
+}
+/**
+ * Class of the SGBD from the Form Creator Api perspective. Used to
+ * perform all the operations into the database that the Form Creator Api
+ * requires. This operations include read and write data.
+ */
+
+export class DbHandler {
+
+    /** Information used to connect with a PostgreSQL database. */
+    private pool: Pool;
+
+    /**
+     * Creates a new adapter with the database connection configuration.
+     * @param config - The information required to create a connection with
+     * the database.
+     */
+    constructor(config: PoolConfig) {
+        this.pool = new Pool(config);
+    }
+
+    /**
+     * Asynchronously executes a query and get its result.
+     * @param query - Query (SQL format) to be executed.
+     * @param cb - Callback function which contains the data read.
+     * @param cb.err - Error information when the method fails.
+     * @param cb.result - Query result.
+     */
+
+    public executeQuery(query: QueryOptions , cb: (err: Error, result?: QueryResult) =>  void): void{
+
+        this.pool.connect((err, client, done) => {
+
+            if (err) {
+                cb(err);
+                return;
+            }
+
+            client.query(query.query, query.parameters, (error, result) => {
+            // call 'done()' to release client back to pool
+                done();
+                cb(error, (result) ? result : null);
+            });
+        });
+    }
+
+    /**
+     * Asynchronously ends a transaction
+     */
+    public commit(cb: (err: Error, result?: QueryResult) =>  void){
+        this.executeQuery({query: "COMMIT;", parameters: []}, cb);
+    }
+    /**
+     * Asynchronously rollback a transaction
+     */
+    public rollback(cb: (err: Error, result?: QueryResult) =>  void){
+        this.executeQuery({query: "ROLLBACK;", parameters: []}, cb);
+    }
+
+    /**
+     * Asynchronously starts a transaction
+     */
+    public begin(cb: (err: Error, result?: QueryResult) =>  void){
+        this.executeQuery({query: "BEGIN;", parameters: []}, cb);
+    }
+
+    /**
+     * Asynchronously list all forms in database.
+     * @param cb - Callback function which contains the data read.
+     * @param cb.err - Error information when the method fails.
+     * @param cb.form - list of form or a empty list if there is no form on database.
+     */
+    public listForms(cb: (err: Error, forms?: Form[]) =>  void){
+        const query: QueryOptions = {query: "SELECT id, title, description FROM form;", parameters: []};
+        const forms: Form[] = [];
+
+        this.executeQuery(query, (err: Error, result?: QueryResult) => {
+            if (err) {
+                cb(err);
+                return;
+            }
+
+            for (const row of result.rows){
+                const formObj: FormOptions = {
+                    id: row["id"]
+                    , title: row["title"]
+                    , description: row["description"]
+                    , inputs: []
+                };
+                let formTmp: Form;
+                try{
+                    formTmp = new Form ( OptHandler.form(formObj));
+                }
+                catch (e){
+                    cb(e);
+                    return;
+                }
+
+                forms.push(formTmp);
+            }
+            cb(err, forms);
+        });
+    }
+
+    /**
+     * Asynchronously executes a query and get a Form.
+     * @param id - Form identifier to be founded.
+     * @param cb - Callback function which contains the data read.
+     * @param cb.err - Error information when the method fails.
+     * @param cb.form - Form or null if form not exists.
+     */
+    public readForm(id: number, cb: (err: Error, form?: Form) =>  void){
+
+        const queryString: string = "SELECT id, title, description FROM form WHERE id=$1;";
+        const query: QueryOptions = {query: queryString, parameters: [id]};
+
+        waterfall([
+            (callback: (err: Error, result?: QueryResult) =>  void) => {
+                this.begin(callback);
+            },
+            (result: QueryResult, callback: (err: Error, result?: QueryResult) =>  void) => {
+                this.executeQuery(query, callback);
+            },
+            (result: QueryResult, callback: (err: Error, form?: Form) =>  void) => {
+
+                if (result.rowCount !== 1){
+                    callback(ErrorHandler.badIdAmount(result.rowCount));
+                    return;
+                }
+                this.readInputWithFormId(id, (error: Error, inputsResult: Input[]) => {
+                    const formObj: FormOptions = {
+                        id: result.rows[0]["id"]
+                        , title: result.rows[0]["title"]
+                        , description: result.rows[0]["description"]
+                        , inputs: inputsResult
+                    };
+                    let formTmp: Form;
+
+                    try{
+                        formTmp = new Form ( OptHandler.form(formObj));
+                    }
+                    catch (e){
+                        callback(e);
+                        return;
+                    }
+
+                    callback(error, formTmp);
+                });
+            },
+            (form: Form, callback: (err: Error, form?: Form) =>  void) => {
+
+                this.commit((error: Error, result?: QueryResult) => {
+                    callback(error, form);
+                });
+            }
+        ], (err, result: Form) => {
+
+            if (err){
+                this.rollback( (error: Error, results?: QueryResult) => {
+                    cb(err);
+                    return;
+                });
+                return;
+            }
+            cb(err, result);
+
+        });
+
+    }
+
+    /**
+     * A private method to asynchronously executes a query and get a list of Inputs.
+     * @param id - Form identifier which inputs are linked to.
+     * @param cb - Callback function which contains the data read.
+     * @param cb.err - Error information when the method fails.
+     * @param cb.inputs - Input array or an empty list if there is no input linked to form.
+     */
+    private readInputWithFormId(id: number, cb: (err: Error, inputs?: InputOptions[]) =>  void){
+        const queryString: string = "SELECT id, placement, input_type, question, description FROM input WHERE id_form=$1 and enabled=true;";
+        const query: QueryOptions = {query: queryString, parameters: [id]};
+
+        this.executeQuery(query, (err: Error, result?: QueryResult) => {
+            map(result.rows, (innerResult, callback) => {
+                this.readInputValidationWithInputId(innerResult["id"], (error: Error, validationResult: Validation[]) => {
+                    const inputObj: InputOptions = {
+                        id: innerResult["id"]
+                        , placement: innerResult["placement"]
+                        , description: innerResult["description"]
+                        , question: innerResult["question"]
+                        , validation: validationResult
+                        , type: EnumHandler.parseInputType(innerResult["input_type"])
+                    };
+                    let inputTmp: InputOptions;
+                    try{
+                        inputTmp = OptHandler.input(inputObj);
+                    }
+                    catch (e){
+                        callback(e);
+                        return;
+                    }
+
+                    callback(error, inputTmp);
+                });
+            }, (errors, inputs: InputOptions[]) => {
+
+                if (errors){
+                    this.rollback( (error: Error, results?: QueryResult) => {
+                        cb(errors);
+                        return;
+                    });
+                    return;
+                }
+
+                const sortedInputs: InputOptions[] = Sorter.sortByPlacement(inputs);
+
+                cb(errors, sortedInputs);
+            });
+        });
+    }
+
+    /**
+     * A private method to asynchronously executes a query and get a list of Validations based on a Input id.
+     * @param id - Input identifier which validations are linked to.
+     * @param cb - Callback function which contains the data read.
+     * @param cb.err - Error information when the method fails.
+     * @param cb.validations - Validation array or an empty list if there is no validation for selected input.
+     */
+    private readInputValidationWithInputId(id: number, cb: (err: Error, validations?: Validation[]) =>  void){
+        const queryString: string = "SELECT id, validation_type FROM input_validation WHERE id_input=$1;";
+        const query: QueryOptions = {
+            query: queryString
+            , parameters: [id]
+        };
+
+        this.executeQuery(query, (err: Error, result?: QueryResult) => {
+            map(result.rows, (innerResult, callback) => {
+                this.readInputValidationArgumentWithInputValidationId(innerResult["id"], (error, argumentsArray) => {
+                    const validationTmp: Validation = {
+                        type:  EnumHandler.parseValidationType(innerResult["validation_type"]),
+                        arguments: argumentsArray
+                    };
+                    callback(error, validationTmp);
+                });
+            }, (errors, validation: Validation[]) => {
+                cb(errors, validation);
+            });
+        });
+
+    }
+
+    /**
+     * A private method to asynchronously executes a query and get a list of Validation Argument based on a Validation id.
+     * @param id - Validation identifier which Validation Arguments are linked to.
+     * @param cb - Callback function which contains the data read.
+     * @param cb.err - Error information when the method fails.
+     * @param cb.argumentsArray - Validation Arguments array or an empty list if there is no validation argument for selected input.
+     */
+    private readInputValidationArgumentWithInputValidationId(id: number, cb: (err: Error, argumentsArray?: any[]) =>  void){
+        const queryString: string = "SELECT id, argument, placement FROM \
+input_validation_argument WHERE \
+id_input_validation=$1;";
+        const query: QueryOptions = {
+            query: queryString
+            , parameters: [id]
+        };
+
+        // cb(null);
+
+        this.executeQuery(query, (error: Error, result?: QueryResult) => {
+
+            const sortedResult: any[] = Sorter.sortByPlacement(result.rows);
+            const argumentArrayTmp = [];
+            for (const innerResult of sortedResult){
+                argumentArrayTmp.push(innerResult["argument"]);
+            }
+
+            cb(error, argumentArrayTmp);
+        });
+
+    }
+
+    /**
+     * Asynchronously insert a form on Database and return it.
+     * @param form - Form to be inserted.
+     * @param cb - Callback function which contains the inserted data.
+     * @param cb.err - Error information when the method fails.
+     * @param cb.formResult - Form or null if form any error occurs.
+     */
+
+    public writeForm(form: Form, cb: (err: Error, formResult?: Form) =>  void){
+        const queryString: string = "INSERT INTO form (title, description) VALUES( $1, $2 ) RETURNING id;";
+        const query: QueryOptions = {
+            query: queryString
+            , parameters: [
+                form.title
+                , form.description
+            ]
+        };
+
+        waterfall([
+            (callback: (err: Error, result?: QueryResult) =>  void) => {
+                this.begin(callback);
+            },
+            (result: QueryResult, callback: (err: Error, result?: QueryResult) =>  void) => {
+                this.executeQuery(query, callback);
+            },
+            (result: QueryResult, callback: (err: Error, formId?: number) =>  void) => {
+                if (result.rowCount !== 1){
+                    callback(ErrorHandler.notInserted("Form"));
+                    return;
+                }
+                eachSeries(form.inputs, (input: Input, innerCallback) => {
+                    this.writeInputWithFormId(result.rows[0]["id"], input, innerCallback);
+                }, (error) => {
+                    if (error){
+                        callback(error);
+                        return;
+
+                    }
+                    callback(error, result.rows[0]["id"]);
+
+                });
+            },
+            (formId: number, callback: (err: Error, formId?: number) =>  void) => {
+
+                this.commit((error: Error, result?: QueryResult) => {
+                    callback(error, formId);
+                });
+            },
+            (formId: number, callback: (err: Error, formResult?: Form) =>  void) => {
+
+                this.readForm(formId, callback);
+
+            }
+        ], (err, result: Form) => {
+
+            if (err){
+                this.rollback( (error: Error, results?: QueryResult) => {
+                    cb(err);
+                    return;
+                });
+                return;
+            }
+            cb(err, result);
+
+        });
+    }
+
+    /**
+     * Asynchronously insert a Input on Database and return it.
+     * @param formId - Form identifier to relate with Input.
+     * @param input - Input to be inserted.
+     * @param cb - Callback function.
+     * @param cb.err - Error information when the method fails.
+     */
+    private writeInputWithFormId(formId: number, input: Input, cb: (err: Error, result?: number) =>  void){
+        const queryString: string = "INSERT INTO input (\
+id_form, placement, input_type, enabled, question, description)\
+VALUES ( $1, $2, $3, $4, $5, $6) RETURNING id;";
+
+        const query: QueryOptions = {
+            query: queryString
+            , parameters: [
+                formId
+                , input.placement
+                , EnumHandler.stringifyInputType(input.type)
+                , true
+                , input.question
+                , input.description
+            ]
+        };
+
+        this.executeQuery(query, (err: Error, result?: QueryResult) => {
+            if (err){
+                cb(err);
+                return;
+            }
+
+            if (result.rowCount !== 1){
+                cb(ErrorHandler.notInserted("Input"));
+                return;
+            }
+
+            eachSeries(input.validation, (validation: Validation, callback) => {
+
+                this.writeValidationWithInputId(result.rows[0]["id"], validation, callback);
+
+            }, (error) => {
+
+                cb(error, result.rows[0]["id"]);
+
+            });
+        });
+
+    }
+    /**
+     * Asynchronously insert a Validation on Database and return it.
+     * @param inputId - Input id to relate with Validation.
+     * @param validation - Validation to be inserted.
+     * @param cb - Callback function.
+     * @param cb.err - Error information when the method fails.
+     */
+    private writeValidationWithInputId(inputId: number, validation: Validation, cb: (err: Error) =>  void){
+
+        const queryString: string = "INSERT INTO input_validation\
+( id_input, validation_type) VALUES\
+( $1, $2 ) RETURNING id;";
+
+        const query: QueryOptions = {
+            query: queryString
+            , parameters: [
+                inputId
+                , EnumHandler.stringifyValidationType(validation.type)
+            ]
+        };
+
+        this.executeQuery(query, (err: Error, result?: QueryResult) => {
+
+            if (err){
+                cb(err);
+                return;
+            }
+
+            if (result.rowCount !== 1){
+                cb(ErrorHandler.notInserted("Validation"));
+                return;
+            }
+
+            eachOfSeries(validation.arguments, (argument, placement: number, callback) => {
+
+                this.writeValidationArgumentWithInputIdAndPlacement(result.rows[0]["id"], argument, placement, callback);
+            }, (error) => {
+                cb(error);
+            });
+
+        });
+
+    }
+
+    /**
+     * Asynchronously insert a Validation Argument on Database and return it.
+     * @param validationId - Validation identifier to relate with Argument.
+     * @param argument - Argument to be inserted.
+     * @param placement - placement where argument should be.
+     * @param cb - Callback function.
+     * @param cb.err - Error information when the method fails.
+     */
+    private writeValidationArgumentWithInputIdAndPlacement(validationId: number, argument: string, placement: number, cb: (err: Error) =>  void){
+
+        const queryString: string = "INSERT INTO input_validation_argument \
+( id_input_validation, argument, placement ) VALUES\
+( $1, $2, $3 ) RETURNING id;";
+
+        const query: QueryOptions = {
+            query: queryString
+            , parameters: [
+                validationId
+                , argument
+                , placement
+            ]
+        };
+
+        this.executeQuery(query, (err: Error, result?: QueryResult) => {
+
+            if (err){
+                cb(err);
+                return;
+            }
+
+            if (result.rowCount !== 1){
+                cb(ErrorHandler.notInserted("Validation Argument"));
+                return;
+            }
+
+            cb(err);
+
+        });
+
+    }
+
+    /**
+     * Asynchronously insert a form answer on Database and return it.
+     * @param formAnswer - FormAnswer to be inserted.
+     * @param cb - Callback function which contains the inserted data.
+     * @param cb.err - Error information when the method fails.
+     * @param cb.formAnswerResult - Form or null if form any error occurs.
+     */
+    public writeFormAnswer(formAnswer: FormAnswer, cb: (err: Error, formAnswerResult?: FormAnswer) =>  void){
+        const queryString: string = "INSERT INTO form_answer (id_form, answered_at) VALUES( $1, $2 ) RETURNING id;";
+        const query: QueryOptions = {
+            query: queryString
+            , parameters: [
+                formAnswer.form.id
+                , formAnswer.timestamp
+            ]
+        };
+
+        waterfall([
+            (callback: (err: Error, result?: QueryResult) =>  void) => {
+                this.begin(callback);
+            },
+            (result: QueryResult, callback: (err: Error, result?: QueryResult) =>  void) => {
+                this.executeQuery(query, callback);
+            },
+            (result: QueryResult, callback: (err: Error, formAnswerId?: number) =>  void) => {
+                if (result.rowCount !== 1){
+                    callback(ErrorHandler.notInserted("FormAnswer"));
+                    return;
+                }
+                // NOTE: Although this two "FOR"s the complexity is O(n)
+                // This first eachSeries iterates over the keys of the dictonary
+                eachSeries(Object.keys(formAnswer.inputAnswers), (key, outerCallback) => {
+                    // this second one iterates over the array of the objects within the current key
+
+                    eachSeries(formAnswer.inputAnswers[parseInt(key, 10)], (inputsAnswer: InputAnswer, innerCallback) => {
+                        this.writeInputAnswerWithFormId(result.rows[0]["id"], inputsAnswer, innerCallback);
+                    }, (error) => {
+                        if (error){
+                            outerCallback(error);
+                            return;
+                        }
+                        outerCallback(error);
+                    });
+                }, (error) => {
+                    if (error){
+                        callback(error);
+                        return;
+                    }
+                    callback(error, result.rows[0]["id"]);
+                });
+
+            },
+            (formAnswerId: number, callback: (err: Error, formId?: number) =>  void) => {
+
+                this.commit((error: Error, result?: QueryResult) => {
+                    callback(error, formAnswerId);
+                });
+            },
+            (formAnswerId: number, callback: (err: Error, formResult?: FormAnswer) =>  void) => {
+
+                this.readFormAnswer(formAnswerId, callback);
+
+            }
+        ], (err, result: FormAnswer) => {
+
+            if (err){
+                this.rollback( (error: Error, results?: QueryResult) => {
+                    cb(err);
+                    return;
+                });
+                return;
+            }
+            cb(err, result);
+
+        });
+    }
+
+    /**
+     * Asynchronously insert a Input Answer on Database and return it.
+     * @param formAnswerId - Form Answer identifier to relate with Input Answer.
+     * @param inputsAnswer - InputsAnswer to be inserted.
+     * @param cb - Callback function.
+     * @param cb.err - Error information when the method fails.
+     */
+    private writeInputAnswerWithFormId(formAnswerId: number, inputAnswer: InputAnswer, cb: (err: Error) =>  void){
+        const queryString: string = "INSERT INTO input_answer (\
+id_form_answer, id_input, value, placement)\
+VALUES ( $1, $2, $3, $4) RETURNING id;";
+
+        const query: QueryOptions = {
+            query: queryString
+            , parameters: [
+                formAnswerId
+                , inputAnswer.idInput
+                , inputAnswer.value
+                , inputAnswer.placement
+            ]
+        };
+
+        this.executeQuery(query, (err: Error, result?: QueryResult) => {
+            if (err){
+                cb(err);
+                return;
+            }
+
+            if (result.rowCount !== 1){
+                cb(ErrorHandler.notInserted("InputsAnswer"));
+                return;
+            }
+            cb(err);
+        });
+
+    }
+
+    /**
+     * Asynchronously executes a query and get a Form.
+     * @param id - Form identifier to be founded.
+     * @param cb - Callback function which contains the data read.
+     * @param cb.err - Error information when the method fails.
+     * @param cb.form - Form or null if form not exists.
+     */
+    public readFormAnswer(id: number, cb: (err: Error, formAnswer?: FormAnswer) =>  void){
+
+        const queryString: string = "SELECT id, id_form, answered_at FROM form_answer WHERE id=$1;";
+        const query: QueryOptions = {query: queryString, parameters: [id]};
+
+        waterfall([
+            (callback: (err: Error, result?: QueryResult) =>  void) => {
+                this.begin(callback);
+            },
+            (result: QueryResult, callback: (err: Error, result?: QueryResult) =>  void) => {
+                this.executeQuery(query, callback);
+            },
+            (result: QueryResult, callback: (err: Error, formAnswer?: FormAnswer) =>  void) => {
+                if (result.rowCount !== 1){
+                    callback(ErrorHandler.badIdAmount(result.rowCount));
+                    return;
+                }
+
+                this.readForm(result.rows[0]["id_form"], (err: Error, formResult: Form) => {
+                    this.readInputAnswerWithFormAnswerId(result.rows[0]["id"], (error: Error, inputsAnswerOptionsResult: InputAnswerOptionsDict) => {
+                        const formAnswerOpt: FormAnswerOptions = {
+                            id: result.rows[0]["id"]
+                            , form: formResult
+                            , inputsAnswerOptions: inputsAnswerOptionsResult
+                            , timestamp : result.rows[0]["answered_at"]
+                        };
+                        let formAnswerTmp: FormAnswer;
+
+                        try{
+                            formAnswerTmp = new FormAnswer ( OptHandler.formAnswer(formAnswerOpt));
+                        }
+                        catch (e){
+                            callback(e);
+                            return;
+                        }
+
+                        callback(error, formAnswerTmp);
+                    });
+                });
+            },
+            (formAnswer: FormAnswer, callback: (err: Error, formAnswer?: FormAnswer) =>  void) => {
+
+                this.commit((error: Error, result?: QueryResult) => {
+                    callback(error, formAnswer);
+                });
+            }
+        ], (err, result: FormAnswer) => {
+
+            if (err){
+                this.rollback( (error: Error, results?: QueryResult) => {
+                    cb(err);
+                    return;
+                });
+                return;
+            }
+            cb(err, result);
+
+        });
+
+    }
+
+    /**
+     * A private method to asynchronously executes a query and get a list of Inputs.
+     * @param id - Form identifier which inputs are linked to.
+     * @param cb - Callback function which contains the data read.
+     * @param cb.err - Error information when the method fails.
+     * @param cb.inputs - Input array or an empty list if there is no input linked to form.
+     */
+    private readInputAnswerWithFormAnswerId(id: number, cb: (err: Error, inputsAnswerResult?: InputAnswerOptionsDict) =>  void){
+        const queryString: string = "SELECT id, id_form_answer, id_input, value,\
+placement FROM input_answer WHERE id_form_answer=$1;";
+        const query: QueryOptions = {query: queryString, parameters: [id]};
+
+        this.executeQuery(query, (err: Error, result?: QueryResult) => {
+
+            const inputAnswersOpts: InputAnswerOptions[] = result.rows.map( (inputsAnswerResult) => {
+                const inputAnswersOpt: InputAnswerOptions = {
+                    id: inputsAnswerResult["id"]
+                    , idInput: inputsAnswerResult["id_input"]
+                    , value: inputsAnswerResult["value"]
+                    , placement: inputsAnswerResult["placement"]
+                };
+                return OptHandler.inputAnswer(inputAnswersOpt);
+            });
+
+            const inputsAnswerResults: InputAnswerOptionsDict = {};
+            for (const i of inputAnswersOpts){
+                // FIXME:  There is no coverage teste for this "IF"
+                // it happens because, until this date (04/Jun/2019) I did not implement multivalored inputs
+                // I hope someday someone implements it
+                if (  inputsAnswerResults[i["idInput"]] ) {
+                    inputsAnswerResults[i["idInput"]].push(i);
+                    inputsAnswerResults[i["idInput"]] = Sorter.sortByPlacement(inputsAnswerResults[i["idInput"]]);
+                }else{
+                    inputsAnswerResults[i["idInput"]] = [i];
+                }
+            }
+            cb(err, inputsAnswerResults);
+        });
+    }
+
+    /**
+     * Asynchronously insert a formUpdate and inputUpdates on Database.
+     * @param formUpdate - A FormUpdate with InputUpdates that should be inserted in the database.
+     * @param cb - Callback function.
+     * @param cb.err - Error information when the method fails.
+     */
+    public updateForm(formUpdate: FormUpdate, cb: (err: Error) => void) {
+
+        waterfall([
+            (callback: (err: Error, result?: QueryResult) =>  void) => {
+                this.begin(callback);
+            },
+            (result: QueryResult, callback: (err: Error, result?: number) =>  void) => {
+                this.writeFormUpdate(formUpdate, (err, idFormUpdate: number) => {
+                    if (err) {
+                        callback(err);
+                        return;
+                    }
+                    callback(null, idFormUpdate);
+                });
+            },
+            (idFormUpdate: number, callback: (err: Error) => void) => {
+                eachSeries(formUpdate.inputUpdates, (inputUpdates: InputUpdate, innerCallback) => {
+                    this.writeInputUpdate(idFormUpdate, inputUpdates, innerCallback);
+                }, (error) => {
+                    callback(error);
+                });
+            },
+            (callback: (err: Error) =>  void) => {
+                this.commit((error: Error, result?: QueryResult) => {
+                    callback(error);
+                });
+            }
+        ], (err) => {
+            if (err){
+                this.rollback( (error: Error, results?: QueryResult) => {
+                    cb(err);
+                    return;
+                });
+                return;
+            }
+            cb(null);
+        });
+
+    }
+
+    /**
+     * A private method that execute a query and insert a FormUpdate in the database
+     * @param formUpdate - Form Update to be inserted.
+     * @param cb - Callback function.
+     * @param cb.err - Error information when the method fails.
+     * @param cb.formUpdateId - The id of the inserted FormUpdate.
+     */
+    private writeFormUpdate(formUpdate: FormUpdate, cb: (err: Error, formUpdateId?: number) => void) {
+
+        const queryString: string = "INSERT INTO form_update (id_form, update_date) \
+                                     VALUES ( $1, $2 ) RETURNING id;";
+        const query: QueryOptions = {
+            query: queryString
+            , parameters: [
+                formUpdate.form.id
+                , formUpdate.updateDate
+            ]
+        };
+
+        this.executeQuery(query, (err: Error, result?: QueryResult) => {
+            if (err) {
+                cb(err);
+                return;
+            }
+            cb(err, result.rows[0].id);
+        });
+
+    }
+
+    /**
+     * A private method that execute a query and insert a InputUpdate in the database
+     * @param inputUpdate - Input Update to be inserted.
+     * @param cb - Callback function.
+     * @param cb.err - Error information when the method fails.
+     */
+    private writeInputUpdate(idFormUpdate: number, inputUpdate: InputUpdate, cb: (err: Error) => void) {
+
+        const queryString: string = "INSERT INTO input_update (id_form_update, id_input, input_operation_id, value) \
+                                     VALUES ( $1, $2, $3, $4 );";
+        const query: QueryOptions = {
+            query: queryString
+            , parameters: [
+                idFormUpdate
+                , inputUpdate.input.id
+                , inputUpdate.inputOperation
+                , inputUpdate.value
+            ]
+        };
+
+        this.executeQuery(query, (err: Error, result?: QueryResult) => {
+            cb(err);
+        });
+    }
+
+    /**
+     * A method that update the database based on a given FormUpdate object
+     * @param formUpdate - FormUpdate with the parameters to update the database.
+     * @param cb - Callback function.
+     * @param cb.err - Error information when the method fails.
+     * @param cb.formUpdateResult - A FormUpdate with updated id's.
+     */
+    public updateDatabase(formUpdate: FormUpdate, cb: (err: Error, formUpdateResult?: FormUpdate) => void) {
+
+        const formUpdateResult: FormUpdate = {
+            form: formUpdate.form
+            , updateDate: formUpdate.updateDate
+            , inputUpdates: []
+        };
+
+        eachSeries(formUpdate.inputUpdates, (inputUpdate, callback) => {
+            switch (inputUpdate.inputOperation) {
+                case UpdateType.ADD: {
+                    this.writeInputWithFormId(formUpdate.form.id, inputUpdate.input, (err: Error, id: number) => {
+                        if (err) {
+                            callback(err);
+                        }
+                        const inputOpt: InputOptions = inputUpdate.input;
+                        inputOpt.id = id;
+
+                        const inputUpdateOpt: InputUpdateOptions = {
+                            input: inputOpt
+                            , inputOperation: UpdateType.ADD
+                            , value: null
+                        };
+                        formUpdateResult.inputUpdates.push(new InputUpdate(inputUpdateOpt));
+                        callback(null);
+                    });
+                    break;
+                }
+                case UpdateType.REMOVE: {
+                    // Set enabled option in database as false
+                    this.updateInput(0, inputUpdate.input.id, "enabled", (err: Error) => {
+                        if (err) {
+                            callback(err);
+                        }
+                        formUpdateResult.inputUpdates.push(inputUpdate);
+                        callback(null);
+                    });
+                    break;
+                }
+                case UpdateType.SWAP: {
+                    // Update placement option in database of a input
+                    this.updateInput(inputUpdate.input.placement, inputUpdate.input.id, "placement", (err: Error) => {
+                        if (err) {
+                            callback(err);
+                        }
+                        formUpdateResult.inputUpdates.push(inputUpdate);
+                        callback(null);
+                    });
+                    break;
+                }
+                case UpdateType.REENABLED: {
+                    // Set enabled option in database as true
+                    this.updateInput(1, inputUpdate.input.id, "enabled", (err: Error) => {
+                        if (err) {
+                            callback(err);
+                        }
+                        formUpdateResult.inputUpdates.push(inputUpdate);
+                        callback(null);
+                    });
+                    break;
+                }
+                default: {
+                    callback(new Error ("Operation not recognized"));
+                }
+            }
+        }, (error) => {
+            if (error) {
+                cb(error);
+            }
+            cb(null, formUpdateResult);
+        });
+    }
+
+    /**
+     * A method that execute a query and update a input based on given parameters
+     * @param value - A number to be inserted in the database.
+     * @param id - The input id that should be updated
+     * @param field - The field on database that should be updated.
+     * @param cb - Callback function.
+     * @param cb.err - Error information when the method fails.
+     */
+    private updateInput(value: number, id: number, field: string, cb: (err: Error) => void) {
+        const queryString: string = "UPDATE input SET " + field + " = $1 WHERE id = $2";
+        const query: QueryOptions = {
+            query: queryString
+            , parameters: [
+                value
+                , id
+            ]
+        };
+        this.executeQuery(query, (err: Error, result?: QueryResult) => {
+            cb(err);
+         });
+    }
+
+}
diff --git a/src/utils/diffHandler.spec.ts b/src/utils/diffHandler.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..3867a89b77eb81b4e0df5cfa513ecf1293d38c19
--- /dev/null
+++ b/src/utils/diffHandler.spec.ts
@@ -0,0 +1,1041 @@
+/*
+ * form-creator-api. RESTful API to manage and answer forms.
+ * Copyright (C) 2019 Centro de Computacao Cientifica e Software Livre
+ * Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR
+ *
+ * This file is part of form-creator-api.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+import { expect } from "chai";
+import { Form, FormOptions } from "../core/form";
+import { FormUpdate, FormUpdateOptions } from "../core/formUpdate";
+import { Input, InputOptions, Validation } from "../core/input";
+import { InputUpdate, InputUpdateOptions } from "../core/inputUpdate";
+import { DiffHandler } from "./diffHandler";
+import { InputType, UpdateType, ValidationType } from "./enumHandler";
+import { TestHandler } from "./testHandler";
+
+describe("Diff Handler", () => {
+    it("should return a valid formUpdate remove type", (done) => {
+        const newInputObj1: Input = {
+            placement: 0
+            , description: "Description Question 1 Form 1"
+            , question: "Question 1 Form 1"
+            , enabled: true
+            , type: InputType.TEXT
+            , validation: []
+            , id: 1
+        };
+        const newInputObj2: Input = {
+            placement: 1
+            , description: "Description Question 2 Form 1"
+            , question:  "Question 2 Form 1"
+            , enabled: true
+            , type: InputType.TEXT
+            , validation: [
+                { type: ValidationType.MAXCHAR, arguments: ["10"] }
+                , { type: ValidationType.MINCHAR, arguments: ["2"] }
+            ]
+            , id: 3
+        };
+        const newFormObj: Form = {
+            id: 1
+            , title: "Form Title 1"
+            , description: "Form Description 1"
+            , inputs: [
+                newInputObj1
+                , newInputObj2
+            ]
+        };
+
+        const oldInputObj1: Input = {
+            placement: 0
+            , description: "Description Question 1 Form 1"
+            , question: "Question 1 Form 1"
+            , enabled: true
+            , type: InputType.TEXT
+            , validation: []
+            , id: 1
+        };
+        const oldInputObj2: Input = {
+            placement: 1
+            , description: "Description Question 2 Form 1"
+            , question:  "Question 2 Form 1"
+            , enabled: true
+            , type: InputType.TEXT
+            , validation: [
+                { type: ValidationType.MAXCHAR, arguments: ["10"] }
+                , { type: ValidationType.MINCHAR, arguments: ["2"] }
+            ]
+            , id: 3
+        };
+        const oldInputObj3: Input = {
+            placement: 2
+            , description: "Description Question 3 Form 1"
+            , question: "Question 3 Form 1"
+            , enabled: true
+            , type: InputType.TEXT
+            , validation: [
+                { type: ValidationType.REGEX, arguments: ["\\d{5}-\\d{3}"] }
+                , { type: ValidationType.MANDATORY, arguments: [] }
+            ]
+            , id: 2
+        };
+        const oldFormObj: Form = {
+            id: 1
+            , title: "Form Title 1"
+            , description: "Form Description 1"
+            , inputs: [
+                oldInputObj1
+                , oldInputObj2
+                , oldInputObj3
+            ]
+        };
+
+        const resFormUpdate = DiffHandler.diff(newFormObj, oldFormObj);
+
+        const expInputUpdate: InputUpdate = {
+            input: oldInputObj3
+            , inputOperation: UpdateType.REMOVE
+            , value: null
+        };
+        const expFormUpdate: FormUpdate = {
+            form: newFormObj
+            , updateDate: new Date()
+            , inputUpdates: [ expInputUpdate ]
+        };
+        TestHandler.testFormUpdate(resFormUpdate, expFormUpdate);
+        done();
+    });
+
+    it("should return a valid formUpdate add type", (done) => {
+        const newInputObj1: Input = {
+            placement: 0
+            , description: "Description Question 1 Form 1"
+            , question: "Question 1 Form 1"
+            , enabled: true
+            , type: InputType.TEXT
+            , validation: []
+            , id: 1
+
+        };
+        const newInputObj2: Input = {
+            placement: 1
+            , description: "Description Question 2 Form 1"
+            , question:  "Question 2 Form 1"
+            , enabled: true
+            , type: InputType.TEXT
+            , validation: [
+                { type: ValidationType.MAXCHAR, arguments: ["10"] }
+                , { type: ValidationType.MINCHAR, arguments: ["2"] }
+            ]
+            , id: 3
+        };
+        const newInputObj3: Input = {
+            placement: 2
+            , description: "Description Question 3 Form 1"
+            , question: "Question 3 Form 1"
+            , enabled: true
+            , type: InputType.TEXT
+            , validation: [
+                { type: ValidationType.REGEX, arguments: ["\\d{5}-\\d{3}"] }
+                , { type: ValidationType.MANDATORY, arguments: [] }
+            ]
+            , id: 2
+        };
+        const newInputObj4: Input = {
+            placement: 3
+            , description: "Description Question 4 Form 1"
+            , question: "Question 4 Form 1"
+            , enabled: true
+            , type: InputType.TEXT
+            , validation: []
+            , id: undefined
+        };
+
+        const newFormObj: Form = {
+            id: 1
+            , title: "Form Title 1"
+            , description: "Form Description 1"
+            , inputs: [
+                newInputObj1
+                , newInputObj2
+                , newInputObj3
+                , newInputObj4
+            ]
+        };
+
+        const oldInputObj1: Input = {
+            placement: 0
+            , description: "Description Question 1 Form 1"
+            , question: "Question 1 Form 1"
+            , enabled: true
+            , type: InputType.TEXT
+            , validation: []
+            , id: 1
+        };
+        const oldInputObj2: Input = {
+            placement: 1
+            , description: "Description Question 2 Form 1"
+            , question:  "Question 2 Form 1"
+            , enabled: true
+            , type: InputType.TEXT
+            , validation: [
+                { type: ValidationType.MAXCHAR, arguments: ["10"] }
+                , { type: ValidationType.MINCHAR, arguments: ["2"] }
+            ]
+            , id: 3
+        };
+        const oldInputObj3: Input = {
+            placement: 2
+            , description: "Description Question 3 Form 1"
+            , question: "Question 3 Form 1"
+            , enabled: true
+            , type: InputType.TEXT
+            , validation: [
+                { type: ValidationType.REGEX, arguments: ["\\d{5}-\\d{3}"] }
+                , { type: ValidationType.MANDATORY, arguments: [] }
+            ]
+            , id: 2
+        };
+        const oldFormObj: Form = {
+            id: 1
+            , title: "Form Title 1"
+            , description: "Form Description 1"
+            , inputs: [
+                oldInputObj1
+                , oldInputObj2
+                , oldInputObj3
+            ]
+        };
+
+        const resFormUpdate = DiffHandler.diff(newFormObj, oldFormObj);
+
+        const expInputUpdate: InputUpdate = {
+            input: newInputObj4
+            , inputOperation: UpdateType.ADD
+            , value: null
+        };
+        const expFormUpdate: FormUpdate = {
+            form: newFormObj
+            , updateDate: new Date()
+            , inputUpdates: [ expInputUpdate ]
+        };
+        TestHandler.testFormUpdate(resFormUpdate, expFormUpdate);
+        done();
+    });
+
+    it("should return a valid formUpdate swap type", (done) => {
+        const newInputObj1: Input = {
+            placement: 1
+            , description: "Description Question 1 Form 1"
+            , question: "Question 1 Form 1"
+            , enabled: true
+            , type: InputType.TEXT
+            , validation: []
+            , id: 1
+
+        };
+        const newInputObj2: Input = {
+            placement: 0
+            , description: "Description Question 2 Form 1"
+            , question:  "Question 2 Form 1"
+            , enabled: true
+            , type: InputType.TEXT
+            , validation: [
+                { type: ValidationType.MAXCHAR, arguments: ["10"] }
+                , { type: ValidationType.MINCHAR, arguments: ["2"] }
+            ]
+            , id: 3
+        };
+        const newInputObj3: Input = {
+            placement: 2
+            , description: "Description Question 3 Form 1"
+            , question: "Question 3 Form 1"
+            , enabled: true
+            , type: InputType.TEXT
+            , validation: [
+                { type: ValidationType.REGEX, arguments: ["\\d{5}-\\d{3}"] }
+                , { type: ValidationType.MANDATORY, arguments: [] }
+            ]
+            , id: 2
+        };
+        const newFormObj: Form = {
+            id: 1
+            , title: "Form Title 1"
+            , description: "Form Description 1"
+            , inputs: [
+                newInputObj1
+                , newInputObj2
+                , newInputObj3
+            ]
+        };
+
+        const oldInputObj1: Input = {
+            placement: 0
+            , description: "Description Question 1 Form 1"
+            , question: "Question 1 Form 1"
+            , enabled: true
+            , type: InputType.TEXT
+            , validation: []
+            , id: 1
+        };
+        const oldInputObj2: Input = {
+            placement: 1
+            , description: "Description Question 2 Form 1"
+            , question:  "Question 2 Form 1"
+            , enabled: true
+            , type: InputType.TEXT
+            , validation: [
+                { type: ValidationType.MAXCHAR, arguments: ["10"] }
+                , { type: ValidationType.MINCHAR, arguments: ["2"] }
+            ]
+            , id: 3
+        };
+        const oldInputObj3: Input = {
+            placement: 2
+            , description: "Description Question 3 Form 1"
+            , question: "Question 3 Form 1"
+            , enabled: true
+            , type: InputType.TEXT
+            , validation: [
+                { type: ValidationType.REGEX, arguments: ["\\d{5}-\\d{3}"] }
+                , { type: ValidationType.MANDATORY, arguments: [] }
+            ]
+            , id: 2
+        };
+        const oldFormObj: Form = {
+            id: 1
+            , title: "Form Title 1"
+            , description: "Form Description 1"
+            , inputs: [
+                oldInputObj1
+                , oldInputObj2
+                , oldInputObj3
+            ]
+        };
+
+        const resFormUpdate = DiffHandler.diff(newFormObj, oldFormObj);
+
+        const expInputUpdate1: InputUpdate = {
+            input: newInputObj1
+            , inputOperation: UpdateType.SWAP
+            , value: "" + 0
+        };
+
+        const expInputUpdate2: InputUpdate = {
+            input: newInputObj2
+            , inputOperation: UpdateType.SWAP
+            , value: "" + 1
+        };
+
+        const expFormUpdate: FormUpdate = {
+            form: newFormObj
+            , updateDate: new Date()
+            , inputUpdates: [
+                expInputUpdate1
+                , expInputUpdate2
+            ]
+        };
+        TestHandler.testFormUpdate(resFormUpdate, expFormUpdate);
+        done();
+    });
+
+    it("should return a valid formUpdate remove and add all", (done) => {
+        const newInputObj1: Input = {
+            placement: 0
+            , description: "Description Question 1 Form 1"
+            , question: "Question 1 Form 1"
+            , enabled: true
+            , type: InputType.TEXT
+            , validation: []
+            , id: undefined
+        };
+        const newInputObj2: Input = {
+            placement: 1
+            , description: "Description Question 2 Form 1"
+            , question:  "Question 2 Form 1"
+            , enabled: true
+            , type: InputType.TEXT
+            , validation: [
+                { type: ValidationType.MAXCHAR, arguments: ["10"] }
+                , { type: ValidationType.MINCHAR, arguments: ["2"] }
+            ]
+            , id: undefined
+        };
+        const newInputObj3: Input = {
+            placement: 2
+            , description: "Description Question 3 Form 1"
+            , question: "Question 3 Form 1"
+            , enabled: true
+            , type: InputType.TEXT
+            , validation: [
+                { type: ValidationType.REGEX, arguments: ["\\d{5}-\\d{3}"] }
+                , { type: ValidationType.MANDATORY, arguments: [] }
+            ]
+            , id: undefined
+        };
+
+        const newFormObj: Form = {
+            id: 1
+            , title: "Form Title 1"
+            , description: "Form Description 1"
+            , inputs: [
+                newInputObj1
+                , newInputObj2
+                , newInputObj3
+            ]
+        };
+
+        const oldInputObj1: Input = {
+            placement: 0
+            , description: "Description Question 1 Form 1"
+            , question: "Question 1 Form 1"
+            , enabled: true
+            , type: InputType.TEXT
+            , validation: []
+            , id: 1
+        };
+        const oldInputObj2: Input = {
+            placement: 1
+            , description: "Description Question 2 Form 1"
+            , question:  "Question 2 Form 1"
+            , enabled: true
+            , type: InputType.TEXT
+            , validation: [
+                { type: ValidationType.MAXCHAR, arguments: ["10"] }
+                , { type: ValidationType.MINCHAR, arguments: ["2"] }
+            ]
+            , id: 3
+        };
+        const oldInputObj3: Input = {
+            placement: 2
+            , description: "Description Question 3 Form 1"
+            , question: "Question 3 Form 1"
+            , enabled: true
+            , type: InputType.TEXT
+            , validation: [
+                { type: ValidationType.REGEX, arguments: ["\\d{5}-\\d{3}"] }
+                , { type: ValidationType.MANDATORY, arguments: [] }
+            ]
+            , id: 2
+        };
+        const oldFormObj: Form = {
+            id: 1
+            , title: "Form Title 1"
+            , description: "Form Description 1"
+            , inputs: [
+                oldInputObj1
+                , oldInputObj2
+                , oldInputObj3
+            ]
+        };
+
+        const resFormUpdate = DiffHandler.diff(newFormObj, oldFormObj);
+
+        const expInputUpdate1: InputUpdate = {
+            input: oldInputObj1
+            , inputOperation: UpdateType.REMOVE
+            , value: null
+        };
+        const expInputUpdate2: InputUpdate = {
+            input: oldInputObj3
+            , inputOperation: UpdateType.REMOVE
+            , value: null
+        };
+        const expInputUpdate3: InputUpdate = {
+            input: oldInputObj2
+            , inputOperation: UpdateType.REMOVE
+            , value: null
+        };
+        const expInputUpdate4: InputUpdate = {
+            input: newInputObj1
+            , inputOperation: UpdateType.ADD
+            , value: null
+        };
+        const expInputUpdate5: InputUpdate = {
+            input: newInputObj2
+            , inputOperation: UpdateType.ADD
+            , value: null
+        };
+        const expInputUpdate6: InputUpdate = {
+            input: newInputObj3
+            , inputOperation: UpdateType.ADD
+            , value: null
+        };
+
+        const expFormUpdate: FormUpdate = {
+            form: newFormObj
+            , updateDate: new Date()
+            , inputUpdates: [
+                expInputUpdate1
+                , expInputUpdate2
+                , expInputUpdate3
+                , expInputUpdate4
+                , expInputUpdate5
+                , expInputUpdate6
+            ]
+        };
+
+        TestHandler.testFormUpdate(resFormUpdate, expFormUpdate);
+        done();
+    });
+
+    it("should return a valid formUpdate all operations", (done) => {
+        const newInputObj1: Input = {
+            placement: 1
+            , description: "Description Question 1 Form 1"
+            , question: "Question 1 Form 1"
+            , enabled: true
+            , type: InputType.TEXT
+            , validation: []
+            , id: 1
+        };
+        const newInputObj2: Input = {
+            placement: 0
+            , description: "Description Question 2 Form 1"
+            , question:  "Question 2 Form 1"
+            , enabled: true
+            , type: InputType.TEXT
+            , validation: [
+                { type: ValidationType.MAXCHAR, arguments: ["10"] }
+                , { type: ValidationType.MINCHAR, arguments: ["2"] }
+            ]
+            , id: 2
+        };
+        const newInputObj3: Input = {
+            placement: 2
+            , description: "Description Question 3 Form 1"
+            , question: "Question 3 Form 1"
+            , enabled: true
+            , type: InputType.TEXT
+            , validation: [
+                { type: ValidationType.REGEX, arguments: ["\\d{5}-\\d{3}"] }
+                , { type: ValidationType.MANDATORY, arguments: [] }
+            ]
+            , id: 3
+        };
+        const newInputObj4: Input = {
+            placement: 3
+            , description: "Description Question 4 Form 1"
+            , question: "Question 4 Form 1"
+            , enabled: true
+            , type: InputType.TEXT
+            , validation: []
+            , id: undefined
+        };
+        const newFormObj: Form = {
+            id: 1
+            , title: "Form Title 1"
+            , description: "Form Description 1"
+            , inputs: [
+                newInputObj1
+                , newInputObj2
+                , newInputObj3
+                , newInputObj4
+            ]
+        };
+
+        const oldInputObj1: Input = {
+            placement: 0
+            , description: "Description Question 1 Form 1"
+            , question: "Question 1 Form 1"
+            , enabled: true
+            , type: InputType.TEXT
+            , validation: []
+            , id: 1
+        };
+        const oldInputObj2: Input = {
+            placement: 1
+            , description: "Description Question 2 Form 1"
+            , question:  "Question 2 Form 1"
+            , enabled: true
+            , type: InputType.TEXT
+            , validation: [
+                { type: ValidationType.MAXCHAR, arguments: ["10"] }
+                , { type: ValidationType.MINCHAR, arguments: ["2"] }
+            ]
+            , id: 2
+        };
+        const oldInputObj3: Input = {
+            placement: 2
+            , description: "Description Question 4 Form 1"
+            , question:  "Question 4 Form 1"
+            , enabled: true
+            , type: InputType.TEXT
+            , validation: [
+                { type: ValidationType.MAXCHAR, arguments: ["10"] }
+                , { type: ValidationType.MINCHAR, arguments: ["2"] }
+            ]
+            , id: 4
+        };
+        const oldFormObj: Form = {
+            id: 1
+            , title: "Form Title 1"
+            , description: "Form Description 1"
+            , inputs: [
+                oldInputObj1
+                , oldInputObj2
+                , oldInputObj3
+            ]
+        };
+
+        const resFormUpdate = DiffHandler.diff(newFormObj, oldFormObj);
+
+        const expInputUpdate1: InputUpdate = {
+            input: newInputObj1
+            , inputOperation: UpdateType.SWAP
+            , value: "" + 0
+        };
+        const expInputUpdate2: InputUpdate = {
+            input: newInputObj2
+            , inputOperation: UpdateType.SWAP
+            , value: "" + 1
+        };
+        const expInputUpdate3: InputUpdate = {
+            input: newInputObj3
+            , inputOperation: UpdateType.REENABLED
+            , value: null
+        };
+        const expInputUpdate4: InputUpdate = {
+            input: oldInputObj3
+            , inputOperation: UpdateType.REMOVE
+            , value: null
+        };
+        const expInputUpdate5: InputUpdate = {
+            input: newInputObj4
+            , inputOperation: UpdateType.ADD
+            , value: null
+        };
+
+        const expFormUpdate: FormUpdate = {
+            form: newFormObj
+            , updateDate: new Date()
+            , inputUpdates: [
+                expInputUpdate1
+                , expInputUpdate2
+                , expInputUpdate3
+                , expInputUpdate4
+                , expInputUpdate5
+            ]
+        };
+
+        TestHandler.testFormUpdate(resFormUpdate, expFormUpdate);
+        done();
+    });
+    it("should return a valid formUpdate remove and add all", (done) => {
+        const newInputObj1: Input = {
+            placement: 0
+            , description: "Description Question 1 Form 1"
+            , question: "Question 1 Form 1"
+            , enabled: true
+            , type: InputType.TEXT
+            , validation: []
+            , id: undefined
+        };
+        const newInputObj2: Input = {
+            placement: 1
+            , description: "Description Question 2 Form 1"
+            , question:  "Question 2 Form 1"
+            , enabled: true
+            , type: InputType.TEXT
+            , validation: [
+                { type: ValidationType.MAXCHAR, arguments: ["10"] }
+                , { type: ValidationType.MINCHAR, arguments: ["2"] }
+            ]
+            , id: undefined
+        };
+        const newInputObj3: Input = {
+            placement: 2
+            , description: "Description Question 3 Form 1"
+            , question: "Question 3 Form 1"
+            , enabled: true
+            , type: InputType.TEXT
+            , validation: [
+                { type: ValidationType.REGEX, arguments: ["\\d{5}-\\d{3}"] }
+                , { type: ValidationType.MANDATORY, arguments: [] }
+            ]
+            , id: undefined
+        };
+
+        const newFormObj: Form = {
+            id: 1
+            , title: "Form Title 1"
+            , description: "Form Description 1"
+            , inputs: [
+                newInputObj1
+                , newInputObj2
+                , newInputObj3
+            ]
+        };
+
+        const oldInputObj1: Input = {
+            placement: 0
+            , description: "Description Question 1 Form 1"
+            , question: "Question 1 Form 1"
+            , enabled: true
+            , type: InputType.TEXT
+            , validation: []
+            , id: 1
+        };
+        const oldInputObj2: Input = {
+            placement: 1
+            , description: "Description Question 2 Form 1"
+            , question:  "Question 2 Form 1"
+            , enabled: true
+            , type: InputType.TEXT
+            , validation: [
+                { type: ValidationType.MAXCHAR, arguments: ["10"] }
+                , { type: ValidationType.MINCHAR, arguments: ["2"] }
+            ]
+            , id: 3
+        };
+        const oldInputObj3: Input = {
+            placement: 2
+            , description: "Description Question 3 Form 1"
+            , question: "Question 3 Form 1"
+            , enabled: true
+            , type: InputType.TEXT
+            , validation: [
+                { type: ValidationType.REGEX, arguments: ["\\d{5}-\\d{3}"] }
+                , { type: ValidationType.MANDATORY, arguments: [] }
+            ]
+            , id: 2
+        };
+        const oldFormObj: Form = {
+            id: 1
+            , title: "Form Title 1"
+            , description: "Form Description 1"
+            , inputs: [
+                oldInputObj1
+                , oldInputObj2
+                , oldInputObj3
+            ]
+        };
+
+        const resFormUpdate = DiffHandler.diff(newFormObj, oldFormObj);
+
+        const expInputUpdate1: InputUpdate = {
+            input: oldInputObj1
+            , inputOperation: UpdateType.REMOVE
+            , value: null
+        };
+        const expInputUpdate2: InputUpdate = {
+            input: oldInputObj3
+            , inputOperation: UpdateType.REMOVE
+            , value: null
+        };
+        const expInputUpdate3: InputUpdate = {
+            input: oldInputObj2
+            , inputOperation: UpdateType.REMOVE
+            , value: null
+        };
+        const expInputUpdate4: InputUpdate = {
+            input: newInputObj1
+            , inputOperation: UpdateType.ADD
+            , value: null
+        };
+        const expInputUpdate5: InputUpdate = {
+            input: newInputObj2
+            , inputOperation: UpdateType.ADD
+            , value: null
+        };
+        const expInputUpdate6: InputUpdate = {
+            input: newInputObj3
+            , inputOperation: UpdateType.ADD
+            , value: null
+        };
+
+        const expFormUpdate: FormUpdate = {
+            form: newFormObj
+            , updateDate: new Date()
+            , inputUpdates: [
+                expInputUpdate1
+                , expInputUpdate2
+                , expInputUpdate3
+                , expInputUpdate4
+                , expInputUpdate5
+                , expInputUpdate6
+            ]
+        };
+        TestHandler.testFormUpdate(resFormUpdate, expFormUpdate);
+        done();
+    });
+
+    it("should return a valid formUpdate restore inputs", (done) => {
+        const newInputObj1: Input = {
+            placement: 0
+            , description: "Description Question 1 Form 1"
+            , question: "Question 1 Form 1"
+            , enabled: true
+            , type: InputType.TEXT
+            , validation: []
+            , id: 1
+        };
+        const newInputObj2: Input = {
+            placement: 2
+            , description: "Description Question 2 Form 1"
+            , question:  "Question 2 Form 1"
+            , enabled: true
+            , type: InputType.TEXT
+            , validation: [
+                { type: ValidationType.MAXCHAR, arguments: ["10"] }
+                , { type: ValidationType.MINCHAR, arguments: ["2"] }
+            ]
+            , id: 2
+        };
+        const newInputObj3: Input = {
+            placement: 1
+            , description: "Description Question 3 Form 1"
+            , question: "Question 3 Form 1"
+            , enabled: true
+            , type: InputType.TEXT
+            , validation: [
+                { type: ValidationType.REGEX, arguments: ["\\d{5}-\\d{3}"] }
+                , { type: ValidationType.MANDATORY, arguments: [] }
+            ]
+            , id: 3
+        };
+        const newFormObj: Form = {
+            id: 1
+            , title: "Form Title 1"
+            , description: "Form Description 1"
+            , inputs: [
+                newInputObj1
+                , newInputObj2
+                , newInputObj3
+            ]
+        };
+
+        const oldInputObj1: Input = {
+            placement: 0
+            , description: "Description Question 1 Form 1"
+            , question: "Question 1 Form 1"
+            , enabled: true
+            , type: InputType.TEXT
+            , validation: []
+            , id: 1
+        };
+        const oldInputObj2: Input = {
+            placement: 1
+            , description: "Description Question 2 Form 1"
+            , question:  "Question 3 Form 1"
+            , enabled: true
+            , type: InputType.TEXT
+            , validation: [
+                { type: ValidationType.MAXCHAR, arguments: ["10"] }
+                , { type: ValidationType.MINCHAR, arguments: ["2"] }
+            ]
+            , id: 3
+        };
+        const oldFormObj: Form = {
+            id: 1
+            , title: "Form Title 1"
+            , description: "Form Description 1"
+            , inputs: [
+                oldInputObj1
+                , oldInputObj2
+            ]
+        };
+
+        const resFormUpdate = DiffHandler.diff(newFormObj, oldFormObj);
+
+        const expInputUpdate1: InputUpdate = {
+            input: newInputObj2
+            , inputOperation: UpdateType.REENABLED
+            , value: null
+        };
+        const expFormUpdate: FormUpdate = {
+            form: newFormObj
+            , updateDate: new Date()
+            , inputUpdates: [
+                expInputUpdate1
+            ]
+        };
+
+        TestHandler.testFormUpdate(resFormUpdate, expFormUpdate);
+        done();
+    });
+
+    it("should return a valid formUpdate create a new Form", (done) => {
+        const newInputObj1: Input = {
+            placement: 1
+            , description: "Description Question 1 Form 1"
+            , question: "Question 1 Form 1"
+            , enabled: true
+            , type: InputType.TEXT
+            , validation: []
+            , id: null
+        };
+        const newInputObj2: Input = {
+            placement: 0
+            , description: "Description Question 2 Form 1"
+            , question:  "Question 2 Form 1"
+            , enabled: true
+            , type: InputType.TEXT
+            , validation: [
+                { type: ValidationType.MAXCHAR, arguments: ["10"] }
+                , { type: ValidationType.MINCHAR, arguments: ["2"] }
+            ]
+            , id: null
+        };
+        const newInputObj3: Input = {
+            placement: 2
+            , description: "Description Question 3 Form 1"
+            , question: "Question 3 Form 1"
+            , enabled: true
+            , type: InputType.TEXT
+            , validation: [
+                { type: ValidationType.REGEX, arguments: ["\\d{5}-\\d{3}"] }
+                , { type: ValidationType.MANDATORY, arguments: [] }
+            ]
+            , id: null
+        };
+        const newFormObj: Form = {
+            id: 1
+            , title: "Form Title 1"
+            , description: "Form Description 1"
+            , inputs: [
+                newInputObj1
+                , newInputObj2
+                , newInputObj3
+            ]
+        };
+
+        const oldFormObj: Form = {
+            id: 1
+            , title: "Form Title 1"
+            , description: "Form Description 1"
+            , inputs: []
+        };
+
+        const resFormUpdate = DiffHandler.diff(newFormObj, oldFormObj);
+
+        const expInputUpdate1: InputUpdate = {
+            input: newInputObj1
+            , inputOperation: UpdateType.ADD
+            , value: null
+        };
+        const expInputUpdate2: InputUpdate = {
+            input: newInputObj2
+            , inputOperation: UpdateType.ADD
+            , value: null
+        };
+        const expInputUpdate3: InputUpdate = {
+            input: newInputObj3
+            , inputOperation: UpdateType.ADD
+            , value: null
+        };
+
+        const expFormUpdate: FormUpdate = {
+            form: newFormObj
+            , updateDate: new Date()
+            , inputUpdates: [
+                expInputUpdate1
+                , expInputUpdate2
+                , expInputUpdate3
+            ]
+        };
+        TestHandler.testFormUpdate(resFormUpdate, expFormUpdate);
+        done();
+    });
+
+    it("should return a valid formUpdate remove all inputs", (done) => {
+
+        const newFormObj: Form = {
+            id: 1
+            , title: "Form Title 1"
+            , description: "Form Description 1"
+            , inputs: []
+        };
+
+        const oldInputObj1: Input = {
+            placement: 0
+            , description: "Description Question 1 Form 1"
+            , question: "Question 1 Form 1"
+            , enabled: true
+            , type: InputType.TEXT
+            , validation: []
+            , id: 1
+        };
+        const oldInputObj2: Input = {
+            placement: 1
+            , description: "Description Question 2 Form 1"
+            , question:  "Question 2 Form 1"
+            , enabled: true
+            , type: InputType.TEXT
+            , validation: [
+                { type: ValidationType.MAXCHAR, arguments: ["10"] }
+                , { type: ValidationType.MINCHAR, arguments: ["2"] }
+            ]
+            , id: 3
+        };
+        const oldInputObj3: Input = {
+            placement: 2
+            , description: "Description Question 3 Form 1"
+            , question: "Question 3 Form 1"
+            , enabled: true
+            , type: InputType.TEXT
+            , validation: [
+                { type: ValidationType.REGEX, arguments: ["\\d{5}-\\d{3}"] }
+                , { type: ValidationType.MANDATORY, arguments: [] }
+            ]
+            , id: 2
+        };
+        const oldFormObj: Form = {
+            id: 1
+            , title: "Form Title 1"
+            , description: "Form Description 1"
+            , inputs: [
+                oldInputObj1
+                , oldInputObj2
+                , oldInputObj3
+            ]
+        };
+
+        const resFormUpdate = DiffHandler.diff(newFormObj, oldFormObj);
+
+        const expInputUpdate1: InputUpdate = {
+            input: oldInputObj1
+            , inputOperation: UpdateType.REMOVE
+            , value: null
+        };
+        const expInputUpdate2: InputUpdate = {
+            input: oldInputObj3
+            , inputOperation: UpdateType.REMOVE
+            , value: null
+        };
+        const expInputUpdate3: InputUpdate = {
+            input: oldInputObj2
+            , inputOperation: UpdateType.REMOVE
+            , value: null
+        };
+
+        const expFormUpdate: FormUpdate = {
+            form: newFormObj
+            , updateDate: new Date()
+            , inputUpdates: [
+                expInputUpdate1
+                , expInputUpdate2
+                , expInputUpdate3
+            ]
+        };
+
+        TestHandler.testFormUpdate(resFormUpdate, expFormUpdate);
+        done();
+    });
+
+});
diff --git a/src/utils/diffHandler.ts b/src/utils/diffHandler.ts
new file mode 100644
index 0000000000000000000000000000000000000000..84cdc704e349b40a76651d9082709790acf7ac88
--- /dev/null
+++ b/src/utils/diffHandler.ts
@@ -0,0 +1,157 @@
+/*
+ * form-creator-api. RESTful API to manage and answer forms.
+ * Copyright (C) 2019 Centro de Computacao Cientifica e Software Livre
+ * Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR
+ *
+ * This file is part of form-creator-api.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+import { Form, FormOptions } from "../core/form";
+import { FormUpdate, FormUpdateOptions } from "../core/formUpdate";
+import { Input, InputOptions } from "../core/input";
+import { InputUpdate, InputUpdateOptions } from "../core/inputUpdate";
+import { InputType, UpdateType, ValidationType } from "./enumHandler";
+import { Sorter } from "./sorter";
+
+/**
+ * DiffHandler to find out the difference between two Forms then create and return a FormUpdate
+ */
+export class DiffHandler {
+
+    /**
+     * Return an FormUpdate object with the result of the difference between two Forms.
+     * @param newForm - The new Form that should be compared.
+     * @param oldForm - The old Form that was in the database.
+     * @returns - An FormUpdate object.
+     */
+    public static diff(newForm: Form, oldForm: Form): FormUpdate {
+
+        const sortedNewInputs: Input[] = Sorter.sortById(newForm.inputs).filter(DiffHandler.isIdValid);
+        const sortedOldInputs: Input[] = Sorter.sortById(oldForm.inputs);
+        const inputsToAdd: Input[] = Sorter.sortById(newForm.inputs).filter(DiffHandler.isNotIdValid);
+
+        const formUpdate: FormUpdate = {
+            form: newForm
+            , updateDate: new Date()
+            , inputUpdates: []
+        };
+
+        let i: number = 0;
+        let j: number = 0;
+
+        while ((i < sortedOldInputs.length) && (j < sortedNewInputs.length)) {
+            if (sortedNewInputs[j]["id"] === sortedOldInputs[i]["id"]) {
+                if ( sortedNewInputs[j].placement !== sortedOldInputs[i].placement ) {
+                    formUpdate.inputUpdates.push(DiffHandler.swapInput(sortedNewInputs[j], sortedOldInputs[i]));
+                }
+                j++;
+                i++;
+            }
+            else if (sortedNewInputs[j]["id"] < sortedOldInputs[i]["id"]) {
+                formUpdate.inputUpdates.push(DiffHandler.reenabledInput(sortedNewInputs[j]));
+                j++;
+            }
+            else {
+                formUpdate.inputUpdates.push(DiffHandler.removeInput(sortedOldInputs[i]));
+                i++;
+            }
+        }
+
+        while ((i < sortedOldInputs.length)) {
+            formUpdate.inputUpdates.push(DiffHandler.removeInput(sortedOldInputs[i]));
+            i++;
+        }
+
+        while ((j < sortedNewInputs.length)) {
+            if (sortedNewInputs[j].id !== null) {
+                formUpdate.inputUpdates.push(DiffHandler.reenabledInput(sortedNewInputs[j]));
+            }
+            j++;
+        }
+
+        j = 0;
+        while ((j < inputsToAdd.length)) {
+            formUpdate.inputUpdates.push(DiffHandler.addInput(inputsToAdd[j]));
+            j++;
+        }
+        return formUpdate;
+    }
+
+    /**
+     * Create an InputUpdate object which removes the given Input.
+     * @param input - An input to be removed
+     * @returns - An InputUpdate object.
+     */
+    private static removeInput(input: Input): InputUpdate {
+        const inputUpdate: InputUpdate = {
+            input
+            , inputOperation: UpdateType.REMOVE
+            , value: null
+        };
+        return inputUpdate;
+    }
+
+    /**
+     * Create an InputUpdate object which add the given Input.
+     * @param input - An input to be added
+     * @returns - An InputUpdate object.
+     */
+    private static addInput(input: Input): InputUpdate {
+        const inputUpdate: InputUpdate = {
+            input
+            , inputOperation: UpdateType.ADD
+            , value: null
+        };
+        return inputUpdate;
+    }
+
+    /**
+     * Create an InputUpdate object which change the placement of the given Input.
+     * @param input - An input to be changed
+     * @returns - An InputUpdate object.
+     */
+    private static swapInput(newInput: Input, oldInput: Input): InputUpdate {
+        const inputUpdate: InputUpdate = {
+            input: newInput
+            , inputOperation: UpdateType.SWAP
+            , value: "" + oldInput.placement
+        };
+        return inputUpdate;
+    }
+
+    /**
+     * Create an InputUpdate object which reenabled given Input.
+     * @param input - An input to be reenabled
+     * @returns - An InputUpdate object.
+     */
+    private static reenabledInput(input: Input): InputUpdate {
+        const inputUpdate: InputUpdate = {
+            input
+            , inputOperation: UpdateType.REENABLED
+            , value: null
+        };
+        return inputUpdate;
+    }
+
+    private static isIdValid(obj: any): boolean {
+        return ((obj.id !== null) && (obj.id !== undefined) && (obj.id > 0) && (typeof obj.id === "number"));
+    }
+
+    private static isNotIdValid(obj: any): boolean {
+        return !DiffHandler.isIdValid(obj);
+    }
+
+}
diff --git a/src/utils/enumHandler.spec.ts b/src/utils/enumHandler.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..dcc32ae289f123bd953a2ecbc09aee9744bb2c7e
--- /dev/null
+++ b/src/utils/enumHandler.spec.ts
@@ -0,0 +1,124 @@
+/*
+ * form-creator-api. RESTful API to manage and answer forms.
+ * Copyright (C) 2019 Centro de Computacao Cientifica e Software Livre
+ * Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR
+ *
+ * This file is part of form-creator-api.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+import { expect } from "chai";
+import { EnumHandler, InputType, UpdateType, ValidationType } from "./enumHandler";
+
+describe("Enum Handler", () => {
+
+    it("should stringify UpdateType ", () => {
+
+        const updateNone = EnumHandler.stringifyUpdateType(UpdateType.NONE);
+        const updateAdd = EnumHandler.stringifyUpdateType(UpdateType.ADD);
+        const updateRemove = EnumHandler.stringifyUpdateType(UpdateType.REMOVE);
+        const updateSwap = EnumHandler.stringifyUpdateType(UpdateType.SWAP);
+        const updateReenabled = EnumHandler.stringifyUpdateType(UpdateType.REENABLED);
+
+        expect(updateNone).to.be.equal("");
+        expect(updateAdd).to.be.equal("add");
+        expect(updateRemove).to.be.equal("remove");
+        expect(updateSwap).to.be.equal("swap");
+        expect(updateReenabled).to.be.equal("reenabled");
+    });
+
+    it("should parse string to UpdateType", () => {
+        const updateAdd = EnumHandler.parseUpdateType("add");
+        const updateAddCapitalLetters = EnumHandler.parseUpdateType("ADD");
+        const updateRemove = EnumHandler.parseUpdateType("remove");
+        const updateRemoveCapitalLetters = EnumHandler.parseUpdateType("REMOVE");
+        const updateSwap = EnumHandler.parseUpdateType("swap");
+        const updateSwapCapitalLetters = EnumHandler.parseUpdateType("SWAP");
+        const updateReenabled = EnumHandler.parseUpdateType("reenabled");
+        const updateReenabledCapitalLetters = EnumHandler.parseUpdateType("REENABLED");
+        const updateNone = EnumHandler.parseUpdateType("");
+        const updateFOOL = EnumHandler.parseUpdateType("fool");
+
+        expect(updateAdd).to.be.equal(UpdateType.ADD);
+        expect(updateAddCapitalLetters).to.be.equal(UpdateType.ADD);
+        expect(updateRemove).to.be.equal(UpdateType.REMOVE);
+        expect(updateRemoveCapitalLetters).to.be.equal(UpdateType.REMOVE);
+        expect(updateSwap).to.be.equal(UpdateType.SWAP);
+        expect(updateSwapCapitalLetters).to.be.equal(UpdateType.SWAP);
+        expect(updateNone).to.be.equal(UpdateType.NONE);
+        expect(updateFOOL).to.be.equal(UpdateType.NONE);
+    });
+
+    it("should stringify InputType ", () => {
+
+        const inputNone = EnumHandler.stringifyInputType(InputType.NONE);
+        const inputText = EnumHandler.stringifyInputType(InputType.TEXT);
+
+        expect(inputNone).to.be.equal("");
+        expect(inputText).to.be.equal("text");
+    });
+
+    it("should parse string to InputType", () => {
+        const inputText = EnumHandler.parseInputType("text");
+        const inputTextCapitalLetters = EnumHandler.parseInputType("TEXT");
+        const inputNone = EnumHandler.parseInputType("");
+        const inputFOOL = EnumHandler.parseInputType("fool");
+
+        expect(inputText).to.be.equal(InputType.TEXT);
+        expect(inputTextCapitalLetters).to.be.equal(InputType.TEXT);
+        expect(inputNone).to.be.equal(InputType.NONE);
+        expect(inputFOOL).to.be.equal(InputType.NONE);
+    });
+
+    it("should stringify ValidationType ", () => {
+
+        const validationRegex = EnumHandler.stringifyValidationType(ValidationType.REGEX);
+        const validationMandatory = EnumHandler.stringifyValidationType(ValidationType.MANDATORY);
+        const validationMaxChar = EnumHandler.stringifyValidationType(ValidationType.MAXCHAR);
+        const validationMinChar = EnumHandler.stringifyValidationType(ValidationType.MINCHAR);
+        const validationNone = EnumHandler.stringifyValidationType(ValidationType.NONE);
+
+        expect(validationNone).to.be.equal("");
+        expect(validationRegex).to.be.equal("regex");
+        expect(validationMandatory).to.be.equal("mandatory");
+        expect(validationMaxChar).to.be.equal("maxchar");
+        expect(validationMinChar).to.be.equal("minchar");
+    });
+
+    it("should parse string to ValidationType", () => {
+        const validationRegex = EnumHandler.parseValidationType("regex");
+        const validationRegexCapitalized = EnumHandler.parseValidationType("REGEX");
+        const validationMandatory = EnumHandler.parseValidationType("mandatory");
+        const validationMandatoryCapitalized = EnumHandler.parseValidationType("MANDATORY");
+        const validationMaxChar = EnumHandler.parseValidationType("maxchar");
+        const validationMaxCharyCapitalized = EnumHandler.parseValidationType("MAXCHAR");
+        const validationMinChar = EnumHandler.parseValidationType("minchar");
+        const validationMinCharyCapitalized = EnumHandler.parseValidationType("MINCHAR");
+        const validationNone = EnumHandler.parseValidationType("");
+        const validatioFOOL = EnumHandler.parseValidationType("fool");
+
+        expect(validationRegex).to.be.equal(ValidationType.REGEX);
+        expect(validationRegexCapitalized).to.be.equal(ValidationType.REGEX);
+        expect(validationMandatory).to.be.equal(ValidationType.MANDATORY);
+        expect(validationMandatoryCapitalized).to.be.equal(ValidationType.MANDATORY);
+        expect(validationMaxChar).to.be.equal(ValidationType.MAXCHAR);
+        expect(validationMaxCharyCapitalized).to.be.equal(ValidationType.MAXCHAR);
+        expect(validationMinChar).to.be.equal(ValidationType.MINCHAR);
+        expect(validationMinCharyCapitalized).to.be.equal(ValidationType.MINCHAR);
+        expect(validationNone).to.be.equal(ValidationType.NONE);
+        expect(validatioFOOL).to.be.equal(ValidationType.NONE);
+    });
+
+});
diff --git a/src/utils/enumHandler.ts b/src/utils/enumHandler.ts
new file mode 100644
index 0000000000000000000000000000000000000000..fdc1a2a9a64b93915f6562fc7fe5ab0e6172a35e
--- /dev/null
+++ b/src/utils/enumHandler.ts
@@ -0,0 +1,169 @@
+/*
+ * form-creator-api. RESTful API to manage and answer forms.
+ * Copyright (C) 2019 Centro de Computacao Cientifica e Software Livre
+ * Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR
+ *
+ * This file is part of form-creator-api.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+*/
+
+/**
+ * Available Input types
+ */
+export enum InputType {
+     /** Text type, when input is a text */
+    TEXT,
+    NONE
+}
+
+export enum UpdateType {
+    ADD,
+    REMOVE,
+    SWAP,
+    REENABLED,
+    NONE
+}
+
+/**
+ * Available Validation types
+ */
+export enum ValidationType {
+     /** Used as error code. No suitable validation found. */
+     NONE,
+     /** Regex type, when input need a regex to validate */
+     REGEX,
+     /** Mandatory type, when input is mandatory */
+     MANDATORY,
+     /** MaxChars type, when input has maximum char limit */
+     MAXCHAR,
+     /** MinChars type, when input has minimum char limit */
+     MINCHAR
+}
+
+/**
+ * Enum's handler. Manage parse through the project.
+ */
+export class EnumHandler {
+
+    /**
+     * Parse an enum(Input type) to string.
+     * @param a - Input type to be stringified.
+     * @returns - Input Type as string
+     */
+    public static stringifyInputType(a: InputType): string {
+        switch (a) {
+            case InputType.TEXT:
+                return "text";
+            default:
+                return  "";
+        }
+    }
+
+    /**
+     * Parse a string to enum(InputType).
+     * @param str - InputType in string format.
+     * @returns - Matching InputType
+     */
+    public static parseInputType(str: string): InputType {
+        str = str.toLocaleLowerCase().trimLeft().trimRight();
+        switch (str) {
+            case "text":
+                return InputType.TEXT;
+            default:
+                return InputType.NONE;
+        }
+    }
+
+    /**
+     * Parse an enum(Validation type) to string.
+     * @param a - Validation Type to be stringified.
+     * @returns - Validation Type as string
+     */
+    public static stringifyValidationType(a: ValidationType): string {
+        switch (a) {
+            case ValidationType.REGEX:
+                return "regex";
+            case ValidationType.MANDATORY:
+                return "mandatory";
+            case ValidationType.MAXCHAR:
+                return "maxchar";
+            case ValidationType.MINCHAR:
+                return "minchar";
+            default:
+                return  "";
+        }
+    }
+    /**
+     * Parse a string to enum(InputType).
+     * @param str - InputType in string format.
+     * @returns - Matching ValidationType
+     */
+    public static parseValidationType(str: string): ValidationType {
+        str = str.toLocaleLowerCase().trimLeft().trimRight();
+        switch (str) {
+            case "mandatory":
+                return ValidationType.MANDATORY;
+            case "regex":
+                return ValidationType.REGEX;
+            case "maxchar":
+                return ValidationType.MAXCHAR;
+            case "minchar":
+                return ValidationType.MINCHAR;
+            default:
+                return ValidationType.NONE;
+        }
+    }
+
+    /**
+     * Parse an UpdateType object to string
+     * @param a - Update type to be stringified.
+     * @returns - Update Type as string
+     */
+    public static stringifyUpdateType(a: UpdateType): string {
+        switch (a) {
+            case UpdateType.ADD:
+                return "add";
+            case UpdateType.REMOVE:
+                return "remove";
+            case UpdateType.SWAP:
+                return "swap";
+            case UpdateType.REENABLED:
+                return "reenabled";
+            default:
+                return  "";
+        }
+    }
+
+    /**
+     * Parse a string to UpdateType object
+     * @param str - UpdateType in string format.
+     * @returns - Matching UpdateType
+     */
+    public static parseUpdateType(str: string): UpdateType {
+        str = str.toLocaleLowerCase().trimLeft().trimRight();
+        switch (str) {
+            case "add":
+                return UpdateType.ADD;
+            case "remove":
+                return UpdateType.REMOVE;
+            case "swap":
+                return UpdateType.SWAP;
+            case "reenabled":
+                return UpdateType.REENABLED;
+            default:
+                return UpdateType.NONE;
+        }
+    }
+}
diff --git a/src/utils/errorHandler.ts b/src/utils/errorHandler.ts
new file mode 100644
index 0000000000000000000000000000000000000000..685c07e17e94e260bfaf63889b2188370f8c1728
--- /dev/null
+++ b/src/utils/errorHandler.ts
@@ -0,0 +1,53 @@
+/*
+ * form-creator-api. RESTful API to manage and answer forms.
+ * Copyright (C) 2019 Centro de Computacao Cientifica e Software Livre
+ * Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR
+ *
+ * This file is part of form-creator-api.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+ /**
+  * Error's handler. Manage error message through the project.
+  */
+ export class ErrorHandler {
+
+     /**
+      * Return an error instance with a default message when ids amount is different than 1.
+      * @param idNumber - Amount of ids found.
+      * @returns - An error instance with correct message.
+      */
+     public static badIdAmount(idNumber: number): Error{
+         return new Error("Bad amount of ids returned: found '" + idNumber + "' should be 1");
+     }
+
+     /**
+      * Return an error instance when a object is not inserted.
+      * @param objectName - Name of object, usually the name of the table.
+      * @returns - An error instance with correct message.
+      */
+     public static notInserted(objectName: string): Error{
+         return new Error(objectName + " not inserted");
+     }
+
+     /**
+      * Return an error when a object is not found.
+      * @param objectName - Name of object, usually the name of the table.
+      * @returns - An error instance with correct message.
+      */
+     public static notFound(objectName: string): Error{
+         return new Error("The dataType named '" + objectName + "' was not found");
+     }
+
+ }
diff --git a/src/utils/optHandler.spec.ts b/src/utils/optHandler.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..19a542f5fa1ea2a2dd26a59d5c4b55ebc0fd6f9f
--- /dev/null
+++ b/src/utils/optHandler.spec.ts
@@ -0,0 +1,1350 @@
+/*
+ * form-creator-api. RESTful API to manage and answer forms.
+ * Copyright (C) 2019 Centro de Computacao Cientifica e Software Livre
+ * Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR
+ *
+ * This file is part of form-creator-api.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+import { expect } from "chai";
+import { Form, FormOptions } from "../core/form";
+import { FormAnswer, FormAnswerOptions } from "../core/formAnswer";
+import { FormUpdate, FormUpdateOptions } from "../core/formUpdate";
+import { Input, InputOptions, Validation } from "../core/input";
+import { InputAnswer, InputAnswerDict, InputAnswerOptions, InputAnswerOptionsDict } from "../core/inputAnswer";
+import { InputUpdate, InputUpdateOptions } from "../core/inputUpdate";
+import { InputType, UpdateType, ValidationType } from "./enumHandler";
+import { ErrorHandler } from "./errorHandler";
+import { OptHandler } from "./optHandler";
+
+describe("Options Handler", () => {
+
+    it("should get error when missing Form title", () => {
+        const inputObj1: InputOptions = {
+            placement: 0
+            , description: "Description Question 1 Form 1"
+            , question: "Question 1 Form 1"
+            , type: InputType.TEXT
+            , validation: []
+            , id: 1
+        };
+
+        const inputObj2: InputOptions = {
+            placement: 1
+            , description: "Description Question 2 Form 1"
+            , question:  "Question 2 Form 1"
+            , type: InputType.TEXT
+            , validation: [
+                { type: ValidationType.MAXCHAR, arguments: ["10"] }
+                , { type: ValidationType.MINCHAR, arguments: ["2"] }
+            ]
+            , id: 3
+        };
+
+        const inputObj3: InputOptions = {
+            placement: 2
+            , description: "Description Question 3 Form 1"
+            , question: "Question 3 Form 1"
+            , type: InputType.TEXT
+            , validation: [
+                { type: ValidationType.REGEX, arguments: ["\\d{5}-\\d{3}"] }
+                , { type: ValidationType.MANDATORY, arguments: [] }
+            ]
+            , id: 2
+        };
+        const formObj: any = {
+            id: 1
+            , description: "Form Description 1"
+            , inputs: [
+                OptHandler.input(inputObj1)
+                , OptHandler.input(inputObj2)
+                , OptHandler.input(inputObj3)
+            ]
+        };
+        let formTmp: Form;
+        try{
+            formTmp = new Form ( OptHandler.form(formObj));
+        }catch (e){
+            expect(e).to.be.not.a("null");
+            expect(e.message).to.be.equal(ErrorHandler.notFound("Form title").message);
+            expect(formTmp).to.be.a("undefined");
+        }
+    });
+
+    it("should get error when missing Form description", () => {
+        const inputObj1: InputOptions = {
+            placement: 0
+            , description: "Description Question 1 Form 1"
+            , question: "Question 1 Form 1"
+            , type: InputType.TEXT
+            , validation: []
+            , id: 1
+        };
+
+        const inputObj2: InputOptions = {
+            placement: 1
+            , description: "Description Question 2 Form 1"
+            , question:  "Question 2 Form 1"
+            , type: InputType.TEXT
+            , validation: [
+                { type: ValidationType.MAXCHAR, arguments: ["10"] }
+                , { type: ValidationType.MINCHAR, arguments: ["2"] }
+            ]
+            , id: 3
+        };
+
+        const inputObj3: InputOptions = {
+            placement: 2
+            , description: "Description Question 3 Form 1"
+            , question: "Question 3 Form 1"
+            , type: InputType.TEXT
+            , validation: [
+                { type: ValidationType.REGEX, arguments: ["\\d{5}-\\d{3}"] }
+                , { type: ValidationType.MANDATORY, arguments: [] }
+            ]
+            , id: 2
+        };
+        const formObj: any = {
+            id: 1
+            , title: "Form Title 1"
+            , inputs: [
+                OptHandler.input(inputObj1)
+                , OptHandler.input(inputObj2)
+                , OptHandler.input(inputObj3)
+            ]
+        };
+        let formTmp: Form;
+
+        try{
+            formTmp = new Form ( OptHandler.form(formObj));
+        }catch (e){
+            expect(e).to.be.not.a("null");
+            expect(e.message).to.be.equal(ErrorHandler.notFound("Form description").message);
+            expect(formTmp).to.be.a("undefined");
+        }
+
+    });
+
+    it("should get error when missing Form inputs", () => {
+        const formObj: any = {
+            id: 1
+            , title: "Form Title 1"
+            , description: "Form Description 1"
+        };
+        let formTmp: Form;
+
+        try{
+            formTmp = new Form ( OptHandler.form(formObj));
+
+        }catch (e){
+            expect(e).to.be.not.a("null");
+            expect(e.message).to.be.equal(ErrorHandler.notFound("Form inputs").message);
+            expect(formTmp).to.be.a("undefined");
+        }
+
+    });
+
+    it("should get error when Form inputs is not an array", () => {
+        const formObj: any = {
+            id: 1
+            , title: "Form Title 1"
+            , description: "Form Description 1"
+        };
+        let formTmp: Form;
+
+        try{
+            formTmp = new Form ( OptHandler.form(formObj));
+
+        }catch (e){
+            expect(e).to.be.not.a("null");
+            expect(e.message).to.be.equal(ErrorHandler.notFound("Form inputs").message);
+            expect(formTmp).to.be.a("undefined");
+        }
+
+    });
+
+    it("should get error when missing Input placement", () => {
+        const inputObj: any = {
+            description: "Description Question 1 Form 1"
+            , question: "Question 1 Form 1"
+            , type: InputType.TEXT
+            , validation: []
+            , inputs: "Fool"
+            , id: 1
+        };
+        let inputTmp: Input;
+
+        try{
+            inputTmp = new Input(OptHandler.input(inputObj));
+
+        }catch (e){
+            expect(e).to.be.not.a("null");
+            expect(e.message).to.be.equal(ErrorHandler.notFound("Input placement").message);
+            expect(inputTmp).to.be.a("undefined");
+        }
+
+    });
+
+    it("should get error when missing Input description", () => {
+        const inputObj: any = {
+            placement: 0
+            , question: "Question 1 Form 1"
+            , type: InputType.TEXT
+            , validation: []
+            , id: 1
+        };
+        let inputTmp: Input;
+
+        try{
+            inputTmp = new Input(OptHandler.input(inputObj));
+
+        }catch (e){
+            expect(e).to.be.not.a("null");
+            expect(e.message).to.be.equal(ErrorHandler.notFound("Input description").message);
+            expect(inputTmp).to.be.a("undefined");
+        }
+
+    });
+
+    it("should get error when missing Input question ", () => {
+        const inputObj: any = {
+            placement: 0
+            , description: "Description Question 1 Form 1"
+            , type: InputType.TEXT
+            , validation: []
+            , id: 1
+        };
+        let inputTmp: Input;
+
+        try{
+            inputTmp = new Input(OptHandler.input(inputObj));
+
+        }catch (e){
+            expect(e).to.be.not.a("null");
+            expect(e.message).to.be.equal(ErrorHandler.notFound("Input question").message);
+            expect(inputTmp).to.be.a("undefined");
+        }
+
+    });
+
+    it("should get error when missing Input type", () => {
+        const inputObj: any = {
+            placement: 0
+            , description: "Description Question 1 Form 1"
+            , question: "Question 1 Form 1"
+            , validation: []
+            , id: 1
+        };
+        let inputTmp: Input;
+
+        try{
+            inputTmp = new Input(OptHandler.input(inputObj));
+
+        }catch (e){
+            expect(e).to.be.not.a("null");
+            expect(e.message).to.be.equal(ErrorHandler.notFound("Input type").message);
+            expect(inputTmp).to.be.a("undefined");
+        }
+
+    });
+
+    it("should get error when missing Input validation", () => {
+        const inputObj: any = {
+            placement: 0
+            , description: "Description Question 1 Form 1"
+            , question: "Question 1 Form 1"
+            , type: InputType.TEXT
+            , id: 1
+        };
+        let inputTmp: Input;
+
+        try{
+            inputTmp = new Input(OptHandler.input(inputObj));
+
+        }catch (e){
+            expect(e).to.be.not.a("null");
+            expect(e.message).to.be.equal(ErrorHandler.notFound("Input validation").message);
+            expect(inputTmp).to.be.a("undefined");
+        }
+
+    });
+
+    it("should get error when Input validation is not an array", () => {
+        const inputObj: any = {
+            placement: 0
+            , description: "Description Question 1 Form 1"
+            , question: "Question 1 Form 1"
+            , type: InputType.TEXT
+            , validation: "fool"
+            , id: 1
+        };
+        let inputTmp: Input;
+
+        try{
+            inputTmp = new Input(OptHandler.input(inputObj));
+
+        }catch (e){
+            expect(e).to.be.not.a("null");
+            expect(e.message).to.be.equal(ErrorHandler.notFound("Input validation").message);
+            expect(inputTmp).to.be.a("undefined");
+        }
+
+    });
+
+    it("should get error when FormAnswer has no form associated", () => {
+        const inputAnswersOpt1: InputAnswerOptions  = {
+            id: 1
+            , idInput: null
+            , placement: 0
+            , value: "Answer 1 to Question 1 Form 1"
+        };
+        const inputAnswersOpt2: InputAnswerOptions  = {
+            id: 2
+            , idInput: null
+            , placement: 0
+            , value: "Answer 1 to Question 2 Form"
+        };
+        const inputAnswersOpt3: InputAnswerOptions  = {
+            id: 3
+            , idInput: null
+            , placement: 0
+            , value: "Answer 1 to Question 3 Form"
+        };
+        const inputAnswersOpt4: InputAnswerOptions  = {
+            id: 4
+            , idInput: null
+            , placement: 1
+            , value: "Answer 2 to Question 3 Form"
+        };
+
+        const inputAnswerOptionsDict: InputAnswerOptionsDict = {1: [inputAnswersOpt1], 2: [inputAnswersOpt2], 3: [inputAnswersOpt3, inputAnswersOpt4]};
+        const data: Date = new Date(2019, 5, 15);
+        const formAnswerOptions: any = {
+            id: 1
+            , timestamp: data
+            , inputsAnswerOptions: inputAnswerOptionsDict
+        };
+        let formAnswerTmp: FormAnswer;
+
+        try{
+            formAnswerTmp =  new FormAnswer(OptHandler.formAnswer(formAnswerOptions));
+        }catch (e){
+            expect(e).to.be.not.a("null");
+            expect(e.message).to.be.equal(ErrorHandler.notFound("Form").message);
+            expect(formAnswerTmp).to.be.a("undefined");
+        }
+
+    });
+
+    it("should get error when FormAnswer has a form associated but not type form", () => {
+
+        const inputAnswersOpt1: InputAnswerOptions  = {
+            id: 1
+            , idInput: null
+            , placement: 0
+            , value: "Answer 1 to Question 1 Form 1"
+        };
+        const inputAnswersOpt2: InputAnswerOptions  = {
+            id: 2
+            , idInput: null
+            , placement: 0
+            , value: "Answer 1 to Question 2 Form"
+        };
+        const inputAnswersOpt3: InputAnswerOptions  = {
+            id: 3
+            , idInput: null
+            , placement: 0
+            , value: "Answer 1 to Question 3 Form"
+        };
+        const inputAnswersOpt4: InputAnswerOptions  = {
+            id: 4
+            , idInput: null
+            , placement: 1
+            , value: "Answer 2 to Question 3 Form"
+        };
+
+        const inputAnswerOptionsDict: InputAnswerOptionsDict = {1: [inputAnswersOpt1], 2: [inputAnswersOpt2], 3: [inputAnswersOpt3, inputAnswersOpt4]};
+        const data: Date = new Date(2019, 5, 15);
+        const formAnswerOptions: any = {
+            id: 1
+            , form: inputAnswersOpt4
+            , timestamp: data
+            , inputsAnswerOptions: inputAnswerOptionsDict
+        };
+        let formAnswerTmp: FormAnswer;
+
+        try{
+            formAnswerTmp =  new FormAnswer(OptHandler.formAnswer(formAnswerOptions));
+        }catch (e){
+            expect(e).to.be.not.a("null");
+            expect(e.message).to.be.equal(ErrorHandler.notFound("Form").message);
+            expect(formAnswerTmp).to.be.a("undefined");
+        }
+
+    });
+
+    it("should get error when FormAnswer has no date associated", () => {
+
+        const inputObj1: InputOptions = {
+            placement: 0
+            , description: "Description Question 1 Form 1"
+            , question: "Question 1 Form 1"
+            , type: InputType.TEXT
+            , validation: []
+            , id: 1
+        };
+
+        const inputObj2: InputOptions = {
+            placement: 1
+            , description: "Description Question 2 Form 1"
+            , question:  "Question 2 Form 1"
+            , type: InputType.TEXT
+            , validation: [
+                { type: ValidationType.MAXCHAR, arguments: ["10"] }
+                , { type: ValidationType.MINCHAR, arguments: ["2"] }
+            ]
+            , id: 3
+        };
+
+        const inputObj3: InputOptions = {
+            placement: 2
+            , description: "Description Question 3 Form 1"
+            , question: "Question 3 Form 1"
+            , type: InputType.TEXT
+            , validation: [
+                { type: ValidationType.REGEX, arguments: ["\\d{5}-\\d{3}"] }
+                , { type: ValidationType.MANDATORY, arguments: [] }
+            ]
+            , id: 2
+        };
+        const formObj: FormOptions = {
+            id: 1
+            , title: "Form Title 1"
+            , description: "Form Description 1"
+            , inputs: [
+                OptHandler.input(inputObj1)
+                , OptHandler.input(inputObj2)
+                , OptHandler.input(inputObj3)
+            ]
+        };
+        const formTmp: Form = new Form(OptHandler.form(formObj));
+
+        const inputAnswersOpt1: InputAnswerOptions  = {
+            id: 1
+            , idInput: null
+            , placement: 0
+            , value: "Answer 1 to Question 1 Form 1"
+        };
+        const inputAnswersOpt2: InputAnswerOptions  = {
+            id: 2
+            , idInput: null
+            , placement: 0
+            , value: "Answer 1 to Question 2 Form"
+        };
+        const inputAnswersOpt3: InputAnswerOptions  = {
+            id: 3
+            , idInput: null
+            , placement: 0
+            , value: "Answer 1 to Question 3 Form"
+        };
+        const inputAnswersOpt4: InputAnswerOptions  = {
+            id: 4
+            , idInput: null
+            , placement: 1
+            , value: "Answer 2 to Question 3 Form"
+        };
+
+        const inputAnswerOptionsDict: InputAnswerOptionsDict = {1: [inputAnswersOpt1], 2: [inputAnswersOpt2], 3: [inputAnswersOpt3, inputAnswersOpt4]};
+        const data: Date = new Date(2019, 5, 15);
+        const formAnswerOptions: any = {
+            id: 1
+            , form: formTmp
+            , inputsAnswerOptions: inputAnswerOptionsDict
+        };
+        let formAnswerTmp: FormAnswer;
+
+        try{
+            formAnswerTmp =  new FormAnswer(OptHandler.formAnswer(formAnswerOptions));
+        }catch (e){
+            expect(e).to.be.not.a("null");
+            expect(e.message).to.be.equal(ErrorHandler.notFound("Answer Date").message);
+            expect(formAnswerTmp).to.be.a("undefined");
+        }
+
+    });
+
+    it("should get error when FormAnswer has a date associated but not type Date", () => {
+
+        const inputObj1: InputOptions = {
+            placement: 0
+            , description: "Description Question 1 Form 1"
+            , question: "Question 1 Form 1"
+            , type: InputType.TEXT
+            , validation: []
+            , id: 1
+        };
+
+        const inputObj2: InputOptions = {
+            placement: 1
+            , description: "Description Question 2 Form 1"
+            , question:  "Question 2 Form 1"
+            , type: InputType.TEXT
+            , validation: [
+                { type: ValidationType.MAXCHAR, arguments: ["10"] }
+                , { type: ValidationType.MINCHAR, arguments: ["2"] }
+            ]
+            , id: 3
+        };
+
+        const inputObj3: InputOptions = {
+            placement: 2
+            , description: "Description Question 3 Form 1"
+            , question: "Question 3 Form 1"
+            , type: InputType.TEXT
+            , validation: [
+                { type: ValidationType.REGEX, arguments: ["\\d{5}-\\d{3}"] }
+                , { type: ValidationType.MANDATORY, arguments: [] }
+            ]
+            , id: 2
+        };
+        const formObj: FormOptions = {
+            id: 1
+            , title: "Form Title 1"
+            , description: "Form Description 1"
+            , inputs: [
+                OptHandler.input(inputObj1)
+                , OptHandler.input(inputObj2)
+                , OptHandler.input(inputObj3)
+            ]
+        };
+        const formTmp: Form = new Form(OptHandler.form(formObj));
+
+        const inputAnswersOpt1: InputAnswerOptions  = {
+            id: 1
+            , idInput: null
+            , placement: 0
+            , value: "Answer 1 to Question 1 Form 1"
+        };
+        const inputAnswersOpt2: InputAnswerOptions  = {
+            id: 2
+            , idInput: null
+            , placement: 0
+            , value: "Answer 1 to Question 2 Form"
+        };
+        const inputAnswersOpt3: InputAnswerOptions  = {
+            id: 3
+            , idInput: null
+            , placement: 0
+            , value: "Answer 1 to Question 3 Form"
+        };
+        const inputAnswersOpt4: InputAnswerOptions  = {
+            id: 4
+            , idInput: null
+            , placement: 1
+            , value: "Answer 2 to Question 3 Form"
+        };
+
+        const inputAnswerOptionsDict: InputAnswerOptionsDict = {1: [inputAnswersOpt1], 2: [inputAnswersOpt2], 3: [inputAnswersOpt3, inputAnswersOpt4]};
+        const data: Date = new Date(2019, 5, 15);
+        const formAnswerOptions: any = {
+            id: 1
+            , form: formTmp
+            , timestamp: "data"
+            , inputsAnswerOptions: inputAnswerOptionsDict
+        };
+        let formAnswerTmp: FormAnswer;
+
+        try{
+            formAnswerTmp =  new FormAnswer(OptHandler.formAnswer(formAnswerOptions));
+        }catch (e){
+            expect(e).to.be.not.a("null");
+            expect(e.message).to.be.equal(ErrorHandler.notFound("Answer Date").message);
+            expect(formAnswerTmp).to.be.a("undefined");
+        }
+
+    });
+
+    it("should get error when FormAnswer has no inputAnswerOptionsDict associatedr", () => {
+
+        const inputObj1: InputOptions = {
+            placement: 0
+            , description: "Description Question 1 Form 1"
+            , question: "Question 1 Form 1"
+            , type: InputType.TEXT
+            , validation: []
+            , id: 1
+        };
+
+        const inputObj2: InputOptions = {
+            placement: 1
+            , description: "Description Question 2 Form 1"
+            , question:  "Question 2 Form 1"
+            , type: InputType.TEXT
+            , validation: [
+                { type: ValidationType.MAXCHAR, arguments: ["10"] }
+                , { type: ValidationType.MINCHAR, arguments: ["2"] }
+            ]
+            , id: 3
+        };
+
+        const inputObj3: InputOptions = {
+            placement: 2
+            , description: "Description Question 3 Form 1"
+            , question: "Question 3 Form 1"
+            , type: InputType.TEXT
+            , validation: [
+                { type: ValidationType.REGEX, arguments: ["\\d{5}-\\d{3}"] }
+                , { type: ValidationType.MANDATORY, arguments: [] }
+            ]
+            , id: 2
+        };
+
+        const formObj: FormOptions = {
+            id: 1
+            , title: "Form Title 1"
+            , description: "Form Description 1"
+            , inputs: [
+                OptHandler.input(inputObj1)
+                , OptHandler.input(inputObj2)
+                , OptHandler.input(inputObj3)
+            ]
+        };
+
+        const formTmp: Form = new Form(OptHandler.form(formObj));
+
+        const inputAnswersOpt1: InputAnswerOptions  = {
+            id: 1
+            , idInput: null
+            , placement: 0
+            , value: "Answer 1 to Question 1 Form 1"
+        };
+        const inputAnswersOpt2: InputAnswerOptions  = {
+            id: 2
+            , idInput: null
+            , placement: 0
+            , value: "Answer 1 to Question 2 Form"
+        };
+        const inputAnswersOpt3: InputAnswerOptions  = {
+            id: 3
+            , idInput: null
+            , placement: 0
+            , value: "Answer 1 to Question 3 Form"
+        };
+        const inputAnswersOpt4: InputAnswerOptions  = {
+            id: 4
+            , idInput: null
+            , placement: 1
+            , value: "Answer 2 to Question 3 Form"
+        };
+
+        const inputAnswerOptionsDict: InputAnswerOptionsDict = {
+            1: [inputAnswersOpt1]
+            , 2: [inputAnswersOpt2]
+            , 3: [inputAnswersOpt3, inputAnswersOpt4]
+        };
+        const data: Date = new Date(2019, 5, 15);
+        const formAnswerOptions: any = {
+            id: 1
+            , form: formTmp
+            , timestamp: data
+        };
+        let formAnswerTmp: FormAnswer;
+
+        try{
+            formAnswerTmp =  new FormAnswer(OptHandler.formAnswer(formAnswerOptions));
+        }catch (e){
+            expect(e).to.be.not.a("null");
+            expect(e.message).to.be.equal(ErrorHandler.notFound("Input Answers").message);
+            expect(formAnswerTmp).to.be.a("undefined");
+        }
+
+    });
+
+    it("should test InputAnswerOptions when missing idInput", () => {
+
+        const inputObj1: InputOptions = {
+            placement: 0
+            , description: "Description Question 1 Form 1"
+            , question: "Question 1 Form 1"
+            , type: InputType.TEXT
+            , validation: []
+            , id: 1
+        };
+
+        const inputObj2: InputOptions = {
+            placement: 1
+            , description: "Description Question 2 Form 1"
+            , question:  "Question 2 Form 1"
+            , type: InputType.TEXT
+            , validation: [
+                { type: ValidationType.MAXCHAR, arguments: ["10"] }
+                , { type: ValidationType.MINCHAR, arguments: ["2"] }
+            ]
+            , id: 3
+        };
+
+        const inputObj3: InputOptions = {
+            placement: 2
+            , description: "Description Question 3 Form 1"
+            , question: "Question 3 Form 1"
+            , type: InputType.TEXT
+            , validation: [
+                { type: ValidationType.REGEX, arguments: ["\\d{5}-\\d{3}"] }
+                , { type: ValidationType.MANDATORY, arguments: [] }
+            ]
+            , id: 2
+        };
+        const formObj: FormOptions = {
+            id: 1
+            , title: "Form Title 1"
+            , description: "Form Description 1"
+            , inputs: [
+                OptHandler.input(inputObj1)
+                , OptHandler.input(inputObj2)
+                , OptHandler.input(inputObj3)
+            ]
+        };
+        const formTmp: Form = new Form(OptHandler.form(formObj));
+
+        const inputAnswersOpt1: any  = {
+            id: 1
+            , placement: 0
+            , value: "Answer 1 to Question 1 Form 1"
+        };
+
+        const inputAnswerOptionsDict: InputAnswerOptionsDict = {
+            1: [inputAnswersOpt1]
+        };
+        const data: Date = new Date(2019, 5, 15);
+        const formAnswerOptions: FormAnswerOptions = {
+            id: 1
+            , form: formTmp
+            , timestamp: data
+            , inputsAnswerOptions: inputAnswerOptionsDict
+        };
+        let formAnswerTmp: FormAnswer;
+
+        try{
+            formAnswerTmp =  new FormAnswer(OptHandler.formAnswer(formAnswerOptions));
+        }catch (e){
+            expect(e).to.be.not.a("null");
+            expect(e.message).to.be.equal(ErrorHandler.notFound("idInput").message);
+            expect(formAnswerTmp).to.be.a("undefined");
+        }
+    });
+
+    it("should test InputAnswerOptions when missing placement", () => {
+
+        const inputObj1: InputOptions = {
+            placement: 0
+            , description: "Description Question 1 Form 1"
+            , question: "Question 1 Form 1"
+            , type: InputType.TEXT
+            , validation: []
+            , id: 1
+        };
+
+        const inputObj2: InputOptions = {
+            placement: 1
+            , description: "Description Question 2 Form 1"
+            , question:  "Question 2 Form 1"
+            , type: InputType.TEXT
+            , validation: [
+                { type: ValidationType.MAXCHAR, arguments: ["10"] }
+                , { type: ValidationType.MINCHAR, arguments: ["2"] }
+            ]
+            , id: 3
+        };
+
+        const inputObj3: InputOptions = {
+            placement: 2
+            , description: "Description Question 3 Form 1"
+            , question: "Question 3 Form 1"
+            , type: InputType.TEXT
+            , validation: [
+                { type: ValidationType.REGEX, arguments: ["\\d{5}-\\d{3}"] }
+                , { type: ValidationType.MANDATORY, arguments: [] }
+            ]
+            , id: 2
+        };
+        const formObj: FormOptions = {
+            id: 1
+            , title: "Form Title 1"
+            , description: "Form Description 1"
+            , inputs: [
+                OptHandler.input(inputObj1)
+                , OptHandler.input(inputObj2)
+                , OptHandler.input(inputObj3)
+            ]
+        };
+        const formTmp: Form = new Form(OptHandler.form(formObj));
+
+        const inputAnswersOpt1: any  = {
+            id: 1
+            , idInput: null
+            , value: "Answer 1 to Question 1 Form 1"
+        };
+
+        const inputAnswerOptionsDict: InputAnswerOptionsDict = {
+            1: [inputAnswersOpt1]
+        };
+        const data: Date = new Date(2019, 5, 15);
+        const formAnswerOptions: FormAnswerOptions = {
+            id: 1
+            , form: formTmp
+            , timestamp: data
+            , inputsAnswerOptions: inputAnswerOptionsDict
+        };
+        let formAnswerTmp: FormAnswer;
+
+        try{
+            formAnswerTmp =  new FormAnswer(OptHandler.formAnswer(formAnswerOptions));
+        }catch (e){
+            expect(e).to.be.not.a("null");
+            expect(e.message).to.be.equal(ErrorHandler.notFound("Placement").message);
+            expect(formAnswerTmp).to.be.a("undefined");
+        }
+
+    });
+
+    it("should test InputAnswerOptions when missing Value", () => {
+
+        const inputObj1: InputOptions = {
+            placement: 0
+            , description: "Description Question 1 Form 1"
+            , question: "Question 1 Form 1"
+            , type: InputType.TEXT
+            , validation: []
+            , id: 1
+        };
+
+        const inputObj2: InputOptions = {
+            placement: 1
+            , description: "Description Question 2 Form 1"
+            , question:  "Question 2 Form 1"
+            , type: InputType.TEXT
+            , validation: [
+                { type: ValidationType.MAXCHAR, arguments: ["10"] }
+                , { type: ValidationType.MINCHAR, arguments: ["2"] }
+            ]
+            , id: 3
+        };
+
+        const inputObj3: InputOptions = {
+            placement: 2
+            , description: "Description Question 3 Form 1"
+            , question: "Question 3 Form 1"
+            , type: InputType.TEXT
+            , validation: [
+                { type: ValidationType.REGEX, arguments: ["\\d{5}-\\d{3}"] }
+                , { type: ValidationType.MANDATORY, arguments: [] }
+            ]
+            , id: 2
+        };
+        const formObj: FormOptions = {
+            id: 1
+            , title: "Form Title 1"
+            , description: "Form Description 1"
+            , inputs: [
+                OptHandler.input(inputObj1)
+                , OptHandler.input(inputObj2)
+                , OptHandler.input(inputObj3)
+            ]
+        };
+        const formTmp: Form = new Form(OptHandler.form(formObj));
+
+        const inputAnswersOpt1: any  = {
+            id: 1
+            , idInput: null
+            , placement: 0
+        };
+
+        const inputAnswerOptionsDict: InputAnswerOptionsDict = {
+            1: [inputAnswersOpt1]
+        };
+        const data: Date = new Date(2019, 5, 15);
+        const formAnswerOptions: FormAnswerOptions = {
+            id: 1
+            , form: formTmp
+            , timestamp: data
+            , inputsAnswerOptions: inputAnswerOptionsDict
+        };
+        let formAnswerTmp: FormAnswer;
+
+        try{
+            formAnswerTmp =  new FormAnswer(OptHandler.formAnswer(formAnswerOptions));
+        }catch (e){
+            expect(e).to.be.not.a("null");
+            expect(e.message).to.be.equal(ErrorHandler.notFound("Value").message);
+            expect(formAnswerTmp).to.be.a("undefined");
+        }
+
+    });
+
+    it("should test FormAnswer no error", () => {
+
+        const inputObj1: InputOptions = {
+            placement: 0
+            , description: "Description Question 1 Form 1"
+            , question: "Question 1 Form 1"
+            , type: InputType.TEXT
+            , validation: []
+            , id: 1
+        };
+
+        const inputObj2: InputOptions = {
+            placement: 1
+            , description: "Description Question 2 Form 1"
+            , question:  "Question 2 Form 1"
+            , type: InputType.TEXT
+            , validation: [
+                { type: ValidationType.MAXCHAR, arguments: ["10"] }
+                , { type: ValidationType.MINCHAR, arguments: ["2"] }
+            ]
+            , id: 3
+        };
+
+        const inputObj3: InputOptions = {
+            placement: 2
+            , description: "Description Question 3 Form 1"
+            , question: "Question 3 Form 1"
+            , type: InputType.TEXT
+            , validation: [
+                { type: ValidationType.REGEX, arguments: ["\\d{5}-\\d{3}"] }
+                , { type: ValidationType.MANDATORY, arguments: [] }
+            ]
+            , id: 2
+        };
+        const formObj: FormOptions = {
+            id: 1
+            , title: "Form Title 1"
+            , description: "Form Description 1"
+            , inputs: [
+                OptHandler.input(inputObj1)
+                , OptHandler.input(inputObj2)
+                , OptHandler.input(inputObj3)
+            ]
+        };
+        const formTmp: Form = new Form(OptHandler.form(formObj));
+
+        const inputAnswersOpt1: InputAnswerOptions  = {
+            id: 1
+            , idInput: null
+            , placement: 0
+            , value: "Answer 1 to Question 1 Form 1"
+        };
+        const inputAnswersOpt2: InputAnswerOptions  = {
+            id: 2
+            , idInput: null
+            , placement: 0
+            , value: "Answer 1 to Question 2 Form"
+        };
+        const inputAnswersOpt3: InputAnswerOptions  = {
+            id: 3
+            , idInput: null
+            , placement: 0
+            , value: "Answer 1 to Question 3 Form"
+        };
+        const inputAnswersOpt4: InputAnswerOptions  = {
+            id: 4
+            , idInput: null
+            , placement: 1
+            , value: "Answer 2 to Question 3 Form"
+        };
+
+        const inputAnswerOptionsDict: InputAnswerOptionsDict = {1: [inputAnswersOpt1], 2: [inputAnswersOpt2], 3: [inputAnswersOpt3, inputAnswersOpt4]};
+        const data: Date = new Date(2019, 5, 15);
+        const formAnswerOptions: any = {
+            id: 1
+            , form: formTmp
+            , timestamp: data
+            , inputsAnswerOptions: inputAnswerOptionsDict
+        };
+        let formAnswerTmp: FormAnswer;
+        try{
+            formAnswerTmp =  new FormAnswer(OptHandler.formAnswer(formAnswerOptions));
+        }finally{
+            expect(formAnswerTmp).to.not.be.a("undefined");
+        }
+    });
+
+    it("should test FormUpdate no error", () => {
+
+        const inputObj1: InputOptions = {
+            placement: 0
+            , description: "Description Question 1 Form 1"
+            , question: "Question 1 Form 1"
+            , type: InputType.TEXT
+            , validation: []
+            , id: 1
+        };
+        const updateObj1: InputUpdateOptions = {
+            id: 1
+            , input: inputObj1
+            , inputOperation: UpdateType.REMOVE
+            , value: null
+        };
+
+        const inputObj2: InputOptions = {
+            placement: 1
+            , description: "Description Question 2 Form 1"
+            , question:  "Question 2 Form 1"
+            , type: InputType.TEXT
+            , validation: [
+                { type: ValidationType.MAXCHAR, arguments: ["10"] }
+                , { type: ValidationType.MINCHAR, arguments: ["2"] }
+            ]
+            , id: 3
+        };
+        const updateObj2: InputUpdateOptions = {
+            id: 2
+            , input: inputObj2
+            , inputOperation: UpdateType.REMOVE
+            , value: null
+        };
+
+        const inputObj3: InputOptions = {
+            placement: 2
+            , description: "Description Question 3 Form 1"
+            , question: "Question 3 Form 1"
+            , type: InputType.TEXT
+            , validation: [
+                { type: ValidationType.REGEX, arguments: ["\\d{5}-\\d{3}"] }
+                , { type: ValidationType.MANDATORY, arguments: [] }
+            ]
+            , id: 2
+        };
+        const updateObj3: InputUpdateOptions = {
+            id: 3
+            , input: inputObj3
+            , inputOperation: UpdateType.REMOVE
+            , value: null
+        };
+
+        const formObj: FormOptions = {
+            id: 1
+            , title: "Form Title 1"
+            , description: "Form Description 1"
+            , inputs: [
+                inputObj1
+                , inputObj2
+                , inputObj3
+            ]
+        };
+        const dateTMP: Date = new Date();
+        const formUpdateObj: any = {
+            id: 1
+            , form: formObj
+            , updateDate: dateTMP
+            , inputUpdates: [
+                updateObj1
+                , updateObj2
+                , updateObj3
+            ]
+        };
+
+        let formUpdateTmp: FormUpdate;
+
+        try {
+            formUpdateTmp = new FormUpdate(OptHandler.formUpdate(formUpdateObj));
+        } finally {
+            expect(formUpdateTmp).to.be.a("object");
+        }
+    });
+
+    it("should get error FormUpdate inputUpdates is not an array", () => {
+
+        const inputObj1: InputOptions = {
+            placement: 0
+            , description: "Description Question 1 Form 1"
+            , question: "Question 1 Form 1"
+            , type: InputType.TEXT
+            , validation: []
+            , id: 1
+        };
+        const updateObj: InputUpdateOptions = {
+            id: 1
+            , input: inputObj1
+            , inputOperation: UpdateType.REMOVE
+            , value: null
+        };
+
+        const inputObj2: InputOptions = {
+            placement: 1
+            , description: "Description Question 2 Form 1"
+            , question:  "Question 2 Form 1"
+            , type: InputType.TEXT
+            , validation: [
+                { type: ValidationType.MAXCHAR, arguments: ["10"] }
+                , { type: ValidationType.MINCHAR, arguments: ["2"] }
+            ]
+            , id: 3
+        };
+
+        const inputObj3: InputOptions = {
+            placement: 2
+            , description: "Description Question 3 Form 1"
+            , question: "Question 3 Form 1"
+            , type: InputType.TEXT
+            , validation: [
+                { type: ValidationType.REGEX, arguments: ["\\d{5}-\\d{3}"] }
+                , { type: ValidationType.MANDATORY, arguments: [] }
+            ]
+            , id: 2
+        };
+
+        const formObj: FormOptions = {
+            id: 1
+            , title: "Form Title 1"
+            , description: "Form Description 1"
+            , inputs: [
+                inputObj1
+                , inputObj2
+                , inputObj3
+            ]
+        };
+        const dateTMP: Date = new Date();
+        const formUpdateObj: any = {
+            id: 1
+            , form: formObj
+            , updateDate: dateTMP
+            , inputUpdates: updateObj
+        };
+
+        let formUpdateTmp: FormUpdate;
+
+        try {
+            formUpdateTmp = new FormUpdate(OptHandler.formUpdate(formUpdateObj));
+        } catch (e) {
+            expect(e).to.be.not.a("null");
+            expect(e.message).to.be.equal(ErrorHandler.notFound("inputUpdates").message);
+            expect(formUpdateTmp).to.be.a("undefined");
+        }
+    });
+
+    it("should get error FormUpdate missing option key 'form'", () => {
+
+        const inputObj1: InputOptions = {
+            placement: 0
+            , description: "Description Question 1 Form 1"
+            , question: "Question 1 Form 1"
+            , type: InputType.TEXT
+            , validation: []
+            , id: 1
+        };
+        const updateObj1: InputUpdateOptions = {
+            id: 1
+            , input: inputObj1
+            , inputOperation: UpdateType.REMOVE
+            , value: null
+        };
+
+        const inputObj2: InputOptions = {
+            placement: 1
+            , description: "Description Question 2 Form 1"
+            , question:  "Question 2 Form 1"
+            , type: InputType.TEXT
+            , validation: [
+                { type: ValidationType.MAXCHAR, arguments: ["10"] }
+                , { type: ValidationType.MINCHAR, arguments: ["2"] }
+            ]
+            , id: 3
+        };
+        const updateObj2: InputUpdateOptions = {
+            id: 2
+            , input: inputObj2
+            , inputOperation: UpdateType.REMOVE
+            , value: null
+        };
+
+        const inputObj3: InputOptions = {
+            placement: 2
+            , description: "Description Question 3 Form 1"
+            , question: "Question 3 Form 1"
+            , type: InputType.TEXT
+            , validation: [
+                { type: ValidationType.REGEX, arguments: ["\\d{5}-\\d{3}"] }
+                , { type: ValidationType.MANDATORY, arguments: [] }
+            ]
+            , id: 2
+        };
+        const updateObj3: InputUpdateOptions = {
+            id: 3
+            , input: inputObj3
+            , inputOperation: UpdateType.REMOVE
+            , value: null
+        };
+
+        const dateTMP: Date = new Date();
+        const formUpdateObj: any = {
+            id: 1
+            , updateDate: dateTMP
+            , inputUpdates: [
+                updateObj1
+                , updateObj2
+                , updateObj3
+            ]
+        };
+
+        let formUpdateTmp: FormUpdate;
+
+        try {
+            formUpdateTmp = new FormUpdate(OptHandler.formUpdate(formUpdateObj));
+        } catch (e) {
+            expect(e).to.be.not.a("null");
+            expect(e.message).to.be.equal(ErrorHandler.notFound("form").message);
+            expect(formUpdateTmp).to.be.a("undefined");
+        }
+    });
+
+    it("should get error FormUpdate missing option key 'inputUpdates'", () => {
+
+        const inputObj1: InputOptions = {
+            placement: 0
+            , description: "Description Question 1 Form 1"
+            , question: "Question 1 Form 1"
+            , type: InputType.TEXT
+            , validation: []
+            , id: 1
+        };
+
+        const inputObj2: InputOptions = {
+            placement: 1
+            , description: "Description Question 2 Form 1"
+            , question:  "Question 2 Form 1"
+            , type: InputType.TEXT
+            , validation: [
+                { type: ValidationType.MAXCHAR, arguments: ["10"] }
+                , { type: ValidationType.MINCHAR, arguments: ["2"] }
+            ]
+            , id: 3
+        };
+
+        const inputObj3: InputOptions = {
+            placement: 2
+            , description: "Description Question 3 Form 1"
+            , question: "Question 3 Form 1"
+            , type: InputType.TEXT
+            , validation: [
+                { type: ValidationType.REGEX, arguments: ["\\d{5}-\\d{3}"] }
+                , { type: ValidationType.MANDATORY, arguments: [] }
+            ]
+            , id: 2
+        };
+
+        const formObj: FormOptions = {
+            id: 1
+            , title: "Form Title 1"
+            , description: "Form Description 1"
+            , inputs: [
+                inputObj1
+                , inputObj2
+                , inputObj3
+            ]
+        };
+
+        const dateTMP: Date = new Date();
+        const formUpdateObj: any = {
+            id: 1
+            , form: formObj
+            , updateDate: dateTMP
+        };
+
+        let formUpdateTmp: FormUpdate;
+
+        try {
+            formUpdateTmp = new FormUpdate(OptHandler.formUpdate(formUpdateObj));
+        } catch (e) {
+            expect(e).to.be.not.a("null");
+            expect(e.message).to.be.equal(ErrorHandler.notFound("inputUpdates").message);
+            expect(formUpdateTmp).to.be.a("undefined");
+        }
+    });
+
+    it("should get error InputUpdate missing option key 'input'", () => {
+        const updateObj: any = {
+            id: 1
+            , input: undefined
+            , inputOperation: UpdateType.REMOVE
+            , value: null
+        };
+
+        let updateTmp: InputUpdate;
+
+        try {
+            updateTmp = new InputUpdate(OptHandler.inputUpdate(updateObj));
+        } catch (e) {
+            expect(e).to.be.not.a("null");
+            expect(e.message).to.be.equal(ErrorHandler.notFound("input").message);
+            expect(updateTmp).to.be.a("undefined");
+        }
+    });
+
+    it("should get error InputUpdate missing option key 'inputOperation'", () => {
+
+        const inputObj: InputOptions = {
+            placement: 1
+            , description: "Description Question 2 Form 1"
+            , question:  "Question 2 Form 1"
+            , type: InputType.TEXT
+            , validation: []
+            , id: 1
+        };
+
+        const updateObj: any = {
+            id: 1
+            , input: inputObj
+            , value: "Remove question 3 from form 1"
+        };
+
+        let updateTmp: InputUpdate;
+
+        try {
+            updateTmp = new InputUpdate(OptHandler.inputUpdate(updateObj));
+        } catch (e) {
+            expect(e).to.be.not.a("null");
+            expect(e.message).to.be.equal(ErrorHandler.notFound("inputOperation").message);
+            expect(updateTmp).to.be.a("undefined");
+        }
+    });
+
+    it("should get error InputUpdate missing option key 'value'", () => {
+
+        const inputObj: InputOptions = {
+            placement: 1
+            , description: "Description Question 2 Form 1"
+            , question:  "Question 2 Form 1"
+            , type: InputType.TEXT
+            , validation: []
+            , id: 1
+        };
+
+        const updateObj: any = {
+            id: 1
+            , input: inputObj
+            , inputOperation: UpdateType.REMOVE
+        };
+
+        let updateTmp: InputUpdate;
+
+        try {
+            updateTmp = new InputUpdate(OptHandler.inputUpdate(updateObj));
+        } catch (e) {
+            expect(e).to.be.not.a("null");
+            expect(e.message).to.be.equal(ErrorHandler.notFound("value").message);
+            expect(updateTmp).to.be.a("undefined");
+        }
+    });
+});
diff --git a/src/utils/optHandler.ts b/src/utils/optHandler.ts
new file mode 100644
index 0000000000000000000000000000000000000000..36e8d46e3086bc427dc27ecb2861d54bc77e8ec2
--- /dev/null
+++ b/src/utils/optHandler.ts
@@ -0,0 +1,208 @@
+/*
+ * form-creator-api. RESTful API to manage and answer forms.
+ * Copyright (C) 2019 Centro de Computacao Cientifica e Software Livre
+ * Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR
+ *
+ * This file is part of form-creator-api.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+    import { Form, FormOptions } from "../core/form";
+    import { FormAnswerOptions } from "../core/formAnswer";
+    import { FormUpdate, FormUpdateOptions } from "../core/formUpdate";
+    import { InputOptions, Validation } from "../core/input";
+    import { InputAnswer, InputAnswerDict, InputAnswerOptions, InputAnswerOptionsDict } from "../core/inputAnswer";
+    import { InputUpdate, InputUpdateOptions } from "../core/inputUpdate";
+    import { InputType, UpdateType} from "./enumHandler";
+    import { ErrorHandler} from "./errorHandler";
+/**
+ * OptHandler to handle an object and transform into a Classoptions to be used in Class's constructor
+ */
+    export class OptHandler {
+     /**
+      * Return an FormOptions instance with a parsed object, The main objective is parse any error previously
+      * @param obj - object that should be parsed.
+      * @returns - An FormOptions instance.
+      */
+    public static form(obj: any): FormOptions{
+
+        if (obj.title === undefined ){
+            throw ErrorHandler.notFound("Form title");
+        }
+        if (obj.description  === undefined){
+            throw ErrorHandler.notFound("Form description");
+        }
+        if (obj.inputs  === undefined || !(obj.inputs instanceof Array)){
+            throw ErrorHandler.notFound("Form inputs");
+        }
+        const option: FormOptions = {
+            title: obj.title,
+            description: obj.description,
+            id: obj.id,
+            inputs: obj.inputs.map((i: any) => OptHandler.input(i))
+        };
+
+        return option;
+
+    }
+
+    /**
+     * Return an InputOptions instance with a parsed object, The main objective is parse any error previously
+     * @param obj - object that should be parsed.
+     * @returns - An InputOptions instance.
+     */
+    public static input(obj: any): InputOptions{
+        if (obj.placement === undefined){
+            throw ErrorHandler.notFound("Input placement");
+        }
+        if (obj.description === undefined){
+            throw ErrorHandler.notFound("Input description");
+        }
+        if (obj.question === undefined){
+            throw ErrorHandler.notFound("Input question");
+        }
+        if (obj.type === undefined){
+            throw ErrorHandler.notFound("Input type");
+        }
+        if (obj.validation === undefined || !(obj.validation instanceof Array)){
+            throw ErrorHandler.notFound("Input validation");
+        }
+
+        const option: InputOptions = {
+            id: obj.id,
+            placement: obj.placement,
+            description: obj.description,
+            question: obj.question,
+            enabled: obj.enabled,
+            type: obj.type,
+            validation: obj.validation.map((v: any) => {
+                return {type: v.type, arguments: v.arguments};
+            })
+        };
+
+        return option;
+    }
+
+    /**
+     * Return an formAnswerOptions instance with a parsed and validated object, The main objective is parse any error previously
+     * @param obj - object that should be parsed.
+     * @returns - An FormAnswerOptions instance.
+     */
+    public static formAnswer(obj: any): FormAnswerOptions{
+        if (obj.form === undefined || !(obj.form instanceof Form)){
+            throw ErrorHandler.notFound("Form");
+        }
+        if (obj.timestamp === undefined  || !(obj.timestamp instanceof Date)){
+            throw ErrorHandler.notFound("Answer Date");
+        }
+
+        if (obj.inputsAnswerOptions === undefined ){
+            throw ErrorHandler.notFound("Input Answers");
+        }
+
+        const inputsAnswerOptionsTmp: InputAnswerOptionsDict = {};
+        for (const key of  Object.keys(obj.inputsAnswerOptions)){
+            inputsAnswerOptionsTmp[parseInt(key, 10)] =  obj.inputsAnswerOptions[parseInt(key, 10)].map( (i: InputAnswerOptions) => {
+                return OptHandler.inputAnswer(i);
+            });
+
+        }
+
+        const option: FormAnswerOptions = {
+            id: obj.id
+            , form: obj.form
+            , timestamp: obj.timestamp
+            , inputsAnswerOptions: inputsAnswerOptionsTmp
+        };
+
+        return option;
+    }
+
+    /**
+     * Return an InputAnswerOptions instance with a parsed and validated object, The main objective is parse any error previously
+     * @param obj - object that should be parsed.
+     * @returns - An InputAnswerOptions instance.
+     */
+    public static inputAnswer(obj: any): InputAnswerOptions{
+        if (obj.idInput === undefined){
+            throw ErrorHandler.notFound("idInput");
+        }
+        if (obj.placement === undefined){
+            throw ErrorHandler.notFound("Placement");
+        }
+        if (obj.value === undefined){
+            throw ErrorHandler.notFound("Value");
+        }
+
+        const option: InputAnswerOptions = {
+            id: obj.id
+            , idInput: obj.idInput
+            , placement: obj.placement
+            , value: obj.value
+        };
+
+        return option;
+    }
+
+    /**
+     * Return an FormUpdateOptions instance with a parsed and validated object, The main objective is parse any error previously
+     * @param obj - object that should be parsed.
+     * @returns - An FormUpdateOptions instance.
+     */
+    public static formUpdate(obj: any): FormUpdateOptions {
+        if (obj.form === undefined) {
+            throw ErrorHandler.notFound("form");
+        }
+        if ((obj.inputUpdates === undefined) || !(obj.inputUpdates instanceof Array)) {
+            throw ErrorHandler.notFound("inputUpdates");
+        }
+
+        const option: FormUpdateOptions = {
+            id: obj.id
+            , form: OptHandler.form(obj.form)
+            , updateDate: obj.updateDate
+            , inputUpdates: obj.inputUpdates.map((i: any) => OptHandler.inputUpdate(i))
+        };
+
+        return option;
+    }
+
+    /**
+     * Return an FormUpdateOptions instance with a parsed and validated object, The main objective is to detect parsing errors previously
+     * @param obj - object that should be parsed.
+     * @returns - An FormUpdateOptions instance.
+     */
+    public static inputUpdate(obj: any): InputUpdateOptions {
+        if (obj.input === undefined) {
+            throw ErrorHandler.notFound("input");
+        }
+        if (obj.inputOperation === undefined) {
+            throw ErrorHandler.notFound("inputOperation");
+        }
+        if (obj.value === undefined) {
+            throw ErrorHandler.notFound("value");
+        }
+
+        const option: InputUpdateOptions = {
+            id: obj.id
+            , input: OptHandler.input(obj.input)
+            , inputOperation: obj.inputOperation
+            , value: obj.value
+        };
+
+        return option;
+    }
+
+}
diff --git a/src/utils/sorter.spec.ts b/src/utils/sorter.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..a8251e410087c2f63f682d6a6cc934f248d4bf66
--- /dev/null
+++ b/src/utils/sorter.spec.ts
@@ -0,0 +1,62 @@
+/*
+ * form-creator-api. RESTful API to manage and answer forms.
+ * Copyright (C) 2019 Centro de Computacao Cientifica e Software Livre
+ * Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR
+ *
+ * This file is part of form-creator-api.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+import { expect } from "chai";
+import { Sorter } from "./sorter";
+
+describe("Sorter", () => {
+
+    it("should sort objects with placement option", (done) => {
+
+        const reqArray: any[] = [
+            { placement: 5 }
+            , { placemente: 3 }
+            , { placemente: 1 }
+            , { placemente: 2 }
+            , { placemente: 1 }
+            , { placemente: 0 }
+            , { placemente: 4 }
+            , { placemente: 4 }
+            , { placemente: 3 }
+            , { placemente: 0 }
+        ];
+
+        const resArray: any[] = Sorter.sortByPlacement(reqArray);
+
+        const expArray: any[] = [
+            { placement: 0 }
+            , { placement: 0 }
+            , { placement: 1 }
+            , { placement: 1 }
+            , { placement: 2 }
+            , { placement: 3 }
+            , { placement: 3 }
+            , { placement: 4 }
+            , { placement: 4 }
+            , { placement: 5 }
+        ];
+
+        for (let i = 0; i < resArray.length; i++) {
+            expect(resArray[i].placement).to.be.equal(reqArray[i].placement);
+        }
+        done();
+    });
+});
diff --git a/src/utils/sorter.ts b/src/utils/sorter.ts
new file mode 100644
index 0000000000000000000000000000000000000000..41414791a6318fd9066802c41d7d43ef6559ed10
--- /dev/null
+++ b/src/utils/sorter.ts
@@ -0,0 +1,67 @@
+/*
+ * form-creator-api. RESTful API to manage and answer forms.
+ * Copyright (C) 2019 Centro de Computacao Cientifica e Software Livre
+ * Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR
+ *
+ * This file is part of form-creator-api.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+export class Sorter {
+
+    /**
+     * A public method to return a array sorted by placement field
+     * @param array - Array with objects that have placement field
+     * @returns - A sorted array by placement
+     */
+    public static sortByPlacement(array: any[]): any[] {
+
+        const sortedByPlacementArray: any[] = array.sort((obj1, obj2) => {
+            if (obj1["placement"] > obj2["placement"]) {
+                return 1;
+            }
+
+            if (obj1["placement"] < obj2["placement"]) {
+                return -1;
+            }
+
+            return 0;
+        });
+
+        return sortedByPlacementArray;
+    }
+
+    /**
+     * A public method to return a array sorted by id field
+     * @param array - Array with objects that have id field
+     * @returns - A sorted array by id
+     */
+    public static sortById(array: any[]): any[] {
+
+        const sortedByIdArray: any[] = array.sort((obj1, obj2) => {
+            if (obj1["id"] > obj2["id"]) {
+                return 1;
+            }
+
+            if (obj1["id"] < obj2["id"]) {
+                return -1;
+            }
+
+            return 0;
+        });
+
+        return sortedByIdArray;
+    }
+}
diff --git a/src/utils/testHandler.spec.ts b/src/utils/testHandler.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e70e86c32c425444b514a039a87452919a093d21
--- /dev/null
+++ b/src/utils/testHandler.spec.ts
@@ -0,0 +1,20 @@
+/*
+ * form-creator-api. RESTful API to manage and answer forms.
+ * Copyright (C) 2019 Centro de Computacao Cientifica e Software Livre
+ * Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR
+ *
+ * This file is part of form-creator-api.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
diff --git a/src/utils/testHandler.ts b/src/utils/testHandler.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f9cf76057d51f6a8c848fcd18f3c70b2ce8f6b74
--- /dev/null
+++ b/src/utils/testHandler.ts
@@ -0,0 +1,137 @@
+/*
+ * form-creator-api. RESTful API to manage and answer forms.
+ * Copyright (C) 2019 Centro de Computacao Cientifica e Software Livre
+ * Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR
+ *
+ * This file is part of form-creator-api.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+import { expect } from "chai";
+import { Form } from "../core/form";
+import { FormAnswer } from "../core/formAnswer";
+import { FormUpdate } from "../core/formUpdate";
+import { Input, Validation } from "../core/input";
+import { InputAnswer } from "../core/inputAnswer";
+import { InputUpdate } from "../core/inputUpdate";
+import { EnumHandler, InputType, UpdateType, ValidationType } from "./enumHandler";
+import { Sorter } from "./sorter";
+
+/**
+ * Test's handler. Manage tests through the project.
+ */
+export class TestHandler {
+
+    /**
+     * Verify if two forms are semantically equal;
+     * @param form - Form that should be tested
+     * @param stub - A model form that first param itend to be.
+     * @returns - True if forms are equal else false
+     */
+    public static testForm(form: Form, stub: Form){
+        expect(form.id).to.be.equal(stub.id);
+        expect(form.title).to.be.equal(stub.title);
+        expect(form.description).to.be.equal(stub.description);
+        expect(form.inputs.length).to.be.equal(stub.inputs.length);
+        for (let i = 0; i < form.inputs.length ; i++){
+            TestHandler.testInput(form.inputs[i], stub.inputs[i]);
+        }
+
+    }
+
+    /**
+     * Verify if two inputs are semantically equal;
+     * @param input - Input that should be tested
+     * @param stub - A model input that first param itend to be.
+     * @returns - True if inputs are equal else false
+     */
+    public static testInput(input: Input, stub: Input){
+        expect(input.id).to.be.equal(stub.id);
+        expect(input.placement).to.be.equal(stub.placement);
+        expect(input.description).to.be.equal(stub.description);
+        expect(input.question).to.be.equal(stub.question);
+        expect(input.type).to.be.equal(stub.type);
+        expect(input.validation.length).to.be.equal(stub.validation.length);
+        for (let i = 0; i < input.validation.length ; i++){
+            expect(input.validation[i].type).to.be.equal(stub.validation[i].type);
+            expect(input.validation[i].arguments.length).to.be.equal(stub.validation[i].arguments.length);
+            for (let j = 0; j < input.validation[i].arguments.length  ; j++){
+                expect(input.validation[i].arguments[j]).to.be.equal(stub.validation[i].arguments[j]);
+            }
+        }
+    }
+
+    /**
+     * Verify if two formAnswers are semantically equal;
+     * @param formAnswer - Form Answer that should be tested
+     * @param stub - A model formAnswer that first param itend to be.
+     * @returns - True if formAnswers are equal else false
+     */
+    public static testFormAnswer(formAnswer: FormAnswer, stub: FormAnswer){
+        expect(formAnswer.id).to.be.equal(stub.id);
+        TestHandler.testForm(formAnswer.form, stub.form);
+        for (const key of Object.keys(formAnswer.inputAnswers)){
+            formAnswer.inputAnswers[parseInt(key, 10)].forEach((inputAnswer, i) => {
+                TestHandler.testInputAnswer(inputAnswer, stub.inputAnswers[parseInt(key, 10)][i]);
+
+            });
+        }
+        expect(formAnswer.timestamp.toISOString()).to.be.equal(stub.timestamp.toISOString());
+
+    }
+
+    /**
+     * Verify if two inputAnswer are semantically equal;
+     * @param inputAnswer - inputAnswer that should be tested
+     * @param stub - A model inputAnswer that first param itend to be.
+     * @returns - True if inputAnswer are equal else false
+     */
+    public static testInputAnswer(inputAnswer: InputAnswer, stub: InputAnswer){
+        expect(inputAnswer.id).to.be.equal(stub.id);
+        expect(inputAnswer.idInput).to.be.equal(stub.idInput);
+        expect(inputAnswer.placement).to.be.equal(stub.placement);
+        expect(inputAnswer.value).to.be.equal(stub.value);
+    }
+
+    /**
+     * Verify if two FormUpdate are semantically equal;
+     * @param formUpdate - FormUpdate that should be tested
+     * @param stub - A model FormUpdate that first param itend to be.
+     * @returns - True if FormUpdate are equal else false
+     */
+    public static testFormUpdate(formUpdate: FormUpdate, stub: FormUpdate) {
+        const sortedFormInputs: InputUpdate[] = Sorter.sortById(formUpdate.inputUpdates);
+        const sortedStubInputs: InputUpdate[] = Sorter.sortById(stub.inputUpdates);
+
+        expect(formUpdate.id).to.be.equal(stub.id);
+        TestHandler.testForm(formUpdate.form, stub.form);
+        for (let i = 0; i < formUpdate.inputUpdates.length; i++) {
+            TestHandler.testInputUpdate(sortedFormInputs[i], sortedStubInputs[i]);
+        }
+    }
+
+    /**
+     * Verify if two InputUpdate are semantically equal;
+     * @param inputUpdate - InputUpdate that should be tested
+     * @param stub - A model InputUpdate that first param itend to be.
+     * @returns - True if InputUpdate are equal else false
+     */
+    public static testInputUpdate(inputUpdate: InputUpdate, stub: InputUpdate) {
+        expect(inputUpdate.id).to.be.equal(stub.id);
+        TestHandler.testInput(inputUpdate.input, stub.input);
+        expect(inputUpdate.inputOperation).to.be.equal(stub.inputOperation);
+        expect(inputUpdate.value).to.be.equal(stub.value);
+    }
+}
diff --git a/src/utils/validationError.spec.ts b/src/utils/validationError.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e70e86c32c425444b514a039a87452919a093d21
--- /dev/null
+++ b/src/utils/validationError.spec.ts
@@ -0,0 +1,20 @@
+/*
+ * form-creator-api. RESTful API to manage and answer forms.
+ * Copyright (C) 2019 Centro de Computacao Cientifica e Software Livre
+ * Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR
+ *
+ * This file is part of form-creator-api.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
diff --git a/src/core/collection.ts b/src/utils/validationError.ts
similarity index 52%
rename from src/core/collection.ts
rename to src/utils/validationError.ts
index ad7ebc2d83e3e69131aba9a7ddcd8f0dd9b09163..f440f973c472edac87d2f20e45aca7a52ea8d53e 100644
--- a/src/core/collection.ts
+++ b/src/utils/validationError.ts
@@ -19,49 +19,24 @@
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
 
-import { Item } from "./item";
-
-export class Collection {
-    private items: Item[];
-
-    constructor() {
-        this.items = [];
-    }
-
-    public addItem(i: Item): number {
-        this.items.push(i);
-        return this.items.length - 1;
-    }
-
-    public updateItem(id: number, it: Item): boolean {
-        if (this.items[id]) {
-            this.items[id] = it;
-            return true;
-        }
-
-        else {
-            return false;
-        }
-    }
-
-    public deleteItem(id: number): boolean {
-        if (this.items[id]) {
-            this.items[id] = null;
-            return true;
-        }
-
-        else {
-            return false;
-        }
-    }
-
-    public getItem(id: number): Item {
-        if (this.items[id]) {
-            return this.items[id];
-        }
-
-        else {
-            return null;
-        }
-    }
-}
+ /**
+  * Parameters used to create a dictionary to uses as an object of erro, returning all validations erros just once
+  */
+ export interface ValidationDict {
+      /** A key is a identifier of a Input instance, and the string is all invalid messages */
+     [key: number]: string;
+ }
+
+ /**
+  * ValidationError: Extends Error class
+  * Has a dict that allow us to know which answer is invalide
+  */
+ export class ValidationError extends Error{
+     /** A dict that allows user to know which Input Answer is invalid. */
+     public readonly validationDict: ValidationDict;
+
+     constructor(validationDict: ValidationDict, ...params: any[]){
+         super(...params);
+         this.validationDict = validationDict;
+     }
+ }
diff --git a/src/utils/validationHandler.spec.ts b/src/utils/validationHandler.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d526f647145ab5483979a418195556e42a3bbfda
--- /dev/null
+++ b/src/utils/validationHandler.spec.ts
@@ -0,0 +1,187 @@
+/*
+ * form-creator-api. RESTful API to manage and answer forms.
+ * Copyright (C) 2019 Centro de Computacao Cientifica e Software Livre
+ * Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR
+ *
+ * This file is part of form-creator-api.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+import { expect } from "chai";
+import { Form } from "../core/form";
+import { FormAnswer, FormAnswerOptions } from "../core/formAnswer";
+import { InputAnswerOptions, InputAnswerOptionsDict } from "../core/inputAnswer";
+import { configs } from "./config";
+import { DbHandler } from "./dbHandler";
+import { EnumHandler, InputType, ValidationType } from "./enumHandler";
+import { OptHandler } from "./optHandler";
+import { ValidationHandler } from "./validationHandler";
+
+describe("Validation Handler", () => {
+    const dbhandler = new DbHandler(configs.poolconfig);
+
+    it("should test when Input has a minimum char number", (done) => {
+        const inputAnswersOpt1: InputAnswerOptions = {
+            idInput: 4
+            , placement: 0
+            , value: "MIN 8"
+        };
+        const inputAnswersOpt2: InputAnswerOptions = {
+            idInput: 5
+            , placement: 0
+            , value: "Answer to Question 2 Form 2"
+        };
+        const inputAnswerOptionsDict: InputAnswerOptionsDict = {
+            4: [inputAnswersOpt1]
+            , 5: [inputAnswersOpt2]
+        };
+
+        const data: Date = new Date(2019, 6, 4);
+        dbhandler.readForm(2, (error: Error, form: Form) => {
+            const formAnswerOptions: FormAnswerOptions = {
+                form
+                , timestamp: data
+                , inputsAnswerOptions: inputAnswerOptionsDict
+            };
+            const formAnswer = new FormAnswer(OptHandler.formAnswer(formAnswerOptions));
+            try {
+                ValidationHandler.validateFormAnswer(formAnswer);
+            } catch (e) {
+                expect(e.validationDict["4"]).to.be.equal("Input answer must be greater than 8");
+                expect(e.validationDict["5"]).to.be.a("undefined");
+            }
+            done();
+        });
+    });
+
+    it("should test when Input is mandatory", (done) => {
+        const inputAnswersOpt1: InputAnswerOptions = {
+            idInput: 4
+            , placement: 0
+            , value: "Answer to Question 1 Form 2"
+        };
+        const inputAnswersOpt2: InputAnswerOptions = {
+            idInput: 5
+            , placement: 0
+            , value: ""
+        };
+        const inputAnswerOptionsDict: InputAnswerOptionsDict = {
+            4: [inputAnswersOpt1]
+            , 5: [inputAnswersOpt2]
+        };
+
+        const data: Date = new Date(2019, 6, 4);
+        dbhandler.readForm(2, (error: Error, form: Form) => {
+            const formAnswerOptions: FormAnswerOptions = {
+                form
+                , timestamp: data
+                , inputsAnswerOptions: inputAnswerOptionsDict
+            };
+            const formAnswer = new FormAnswer(OptHandler.formAnswer(formAnswerOptions));
+            try {
+                ValidationHandler.validateFormAnswer(formAnswer);
+            } catch (e) {
+                expect(e.validationDict["4"]).to.be.a("undefined");
+                expect(e.validationDict["5"]).to.be.equal("Input answer is mandatory");
+            }
+            done();
+        });
+    });
+
+    it("should test when Input has a maximum char number", (done) => {
+
+        const inputAnswersOpt1: InputAnswerOptions = {
+            idInput: 1
+            , placement: 0
+            , value: "Answer to Question 1 Form 1"
+        };
+        const inputAnswersOpt2: InputAnswerOptions = {
+            idInput: 2
+            , placement: 0
+            , value: "12345-000"
+        };
+        const inputAnswersOpt3: InputAnswerOptions = {
+            idInput: 3
+            , placement: 0
+            , value: "MORE THEN 10 CHAR"
+        };
+        const inputAnswerOptionsDict: InputAnswerOptionsDict = {
+            1: [inputAnswersOpt1]
+            , 2: [inputAnswersOpt2]
+            , 3: [inputAnswersOpt3]
+        };
+        const data: Date = new Date(2019, 6, 4);
+        dbhandler.readForm(1, (error: Error, form: Form) => {
+            const formAnswerOptions: FormAnswerOptions = {
+                form
+                , timestamp: data
+                , inputsAnswerOptions: inputAnswerOptionsDict
+            };
+            const formAnswer = new FormAnswer(OptHandler.formAnswer(formAnswerOptions));
+            try {
+                ValidationHandler.validateFormAnswer(formAnswer);
+            } catch (e) {
+                expect(e.validationDict["1"]).to.be.a("undefined");
+                expect(e.validationDict["2"]).to.be.a("undefined");
+                expect(e.validationDict["3"]).to.be.equal("Input answer must be lower than 10");
+            }
+            done();
+        });
+
+    });
+
+    it("should test when Input has a RegEx", (done) => {
+
+        const inputAnswersOpt1: InputAnswerOptions = {
+            idInput: 1
+            , placement: 0
+            , value: "Answer to Question 1 Form 1"
+        };
+        const inputAnswersOpt2: InputAnswerOptions = {
+            idInput: 2
+            , placement: 0
+            , value: "12aa345-000"
+        };
+        const inputAnswersOpt3: InputAnswerOptions = {
+            idInput: 3
+            , placement: 0
+            , value: "MAXCHAR 10"
+        };
+        const inputAnswerOptionsDict: InputAnswerOptionsDict = {
+            1: [inputAnswersOpt1]
+            , 2: [inputAnswersOpt2]
+            , 3: [inputAnswersOpt3]
+        };
+        const data: Date = new Date(2019, 6, 4);
+        dbhandler.readForm(1, (error: Error, form: Form) => {
+            const formAnswerOptions: FormAnswerOptions = {
+                form
+                , timestamp: data
+                , inputsAnswerOptions: inputAnswerOptionsDict
+            };
+            const formAnswer = new FormAnswer(OptHandler.formAnswer(formAnswerOptions));
+            try {
+                ValidationHandler.validateFormAnswer(formAnswer);
+            } catch (e) {
+                expect(e.validationDict["1"]).to.be.a("undefined");
+                expect(e.validationDict["3"]).to.be.a("undefined");
+                expect(e.validationDict["2"]).to.be.equal("RegEx do not match");
+            }
+            done();
+        });
+
+    });
+
+});
diff --git a/src/utils/validationHandler.ts b/src/utils/validationHandler.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d04a2d4db0c3359b06fc90c7edb63fa3c4683ae6
--- /dev/null
+++ b/src/utils/validationHandler.ts
@@ -0,0 +1,126 @@
+/*
+ * form-creator-api. RESTful API to manage and answer forms.
+ * Copyright (C) 2019 Centro de Computacao Cientifica e Software Livre
+ * Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR
+ *
+ * This file is part of form-creator-api.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+import { FormAnswer } from "../core/formAnswer";
+import { Input } from "../core/input";
+import { ValidationType } from "./enumHandler";
+import { ValidationDict, ValidationError  } from "./validationError";
+
+/**
+ * Validation's handler. Manage parse validation through the project.
+ */
+export class ValidationHandler {
+
+    /**
+     * Validate a string according given a regex.
+     * @param answer - Answer to be validated.
+     * @param regex - Regex to validate answer.
+     * @returns - true if answer match regex, else false.
+     */
+    private static validateByRegex(answer: string, regex: string): boolean{
+        const regexp = new RegExp(regex);
+        return regexp.test(answer);
+    }
+
+    /**
+     * Validate if is null, undefined nor ""
+     * @param answer - answer to be validated.
+     * @returns - true if not null, "" nor undefined, else false.
+     */
+    private static validateMandatory(answer: string): boolean{
+        return ((!answer) === false);
+    }
+
+    /**
+     * Validate if answer has minimum number of chars
+     * @param answer - Answer to be validated.
+     * @param size - Minimum size that answer should have.
+     * @returns - true if has at least Size chars, else false.
+     */
+    private static validateMinChar(answer: string, size: string): boolean{
+        return  (answer !== null && answer !== undefined && parseInt(size, 10) <= answer.length);
+    }
+
+    /**
+     * Validate if answer has minimum number of chars
+     * @param answer - Answer to be validated.
+     * @param size - Maximum size that answer should have.
+     * @returns - true if has at max Size chars, else false.
+     */
+    private static validateMaxChar(answer: string, size: string): boolean{
+        return  (answer !== null && answer !== undefined  && parseInt(size, 10) >= answer.length);
+    }
+
+    /**
+     * Validate if answer has minimum number of chars
+     * @param input - Input to validate answer.
+     * @param answer - Answer of input
+     * @returns - A string with all errors.
+     */
+    private static validateInput(input: Input, answer: string): string{
+        const errors: string[] = [];
+        for ( const validation of input.validation){
+
+            switch (validation.type) {
+                case ValidationType.REGEX:
+                    if (!this.validateByRegex(answer, validation.arguments[0])){
+                        errors.push("RegEx do not match");
+                    }
+                    break;
+                case ValidationType.MANDATORY:
+                    if (!(this.validateMandatory(answer))){
+                        errors.push("Input answer is mandatory");
+                    }
+                    break;
+                case ValidationType.MAXCHAR:
+                    if (!(this.validateMaxChar(answer, validation.arguments[0]))){
+                        errors.push("Input answer must be lower than " + validation.arguments[0]);
+                    }
+                    break;
+                case ValidationType.MINCHAR:
+                    if (!(this.validateMinChar(answer, validation.arguments[0]))){
+                        errors.push("Input answer must be greater than " + validation.arguments[0]);
+                    }
+                    break;
+            }
+
+        }
+        return errors.join(";");
+
+    }
+
+    public static validateFormAnswer(formAnswer: FormAnswer): void{
+        const errorsDict: ValidationDict = {};
+
+        for ( const input of formAnswer.form.inputs){
+            for (const answer of formAnswer.inputAnswers[input.id]){
+                const error: string =  this.validateInput(input, answer.value);
+                if (error !== "" && error !== undefined){
+                    errorsDict[input.id] = error;
+                }
+            }
+        }
+
+        if ( Object.keys(errorsDict).length > 0){
+            throw new ValidationError(errorsDict, "Validation Error");
+        }
+    }
+}
diff --git a/yarn.lock b/yarn.lock
new file mode 100644
index 0000000000000000000000000000000000000000..769e026da49d12db58011eef969866ed49de96fd
--- /dev/null
+++ b/yarn.lock
@@ -0,0 +1,1652 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+"@types/async@^2.0.50":
+  version "2.4.1"
+  resolved "https://registry.yarnpkg.com/@types/async/-/async-2.4.1.tgz#43c3b2c60eab41c25ca0009c07ca7d619d943119"
+  integrity sha512-C09BK/wXzbW+/JK9zckhe+FeSbg7NmvVjUWwApnw7ksRpUq3ecGLiq2Aw1LlY4Z/VmtdhSaIs7jO5/MWRYMcOA==
+
+"@types/body-parser@*":
+  version "1.17.0"
+  resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.17.0.tgz#9f5c9d9bd04bb54be32d5eb9fc0d8c974e6cf58c"
+  integrity sha512-a2+YeUjPkztKJu5aIF2yArYFQQp8d51wZ7DavSHjFuY1mqVgidGyzEQ41JIVNy82fXj8yPgy2vJmfIywgESW6w==
+  dependencies:
+    "@types/connect" "*"
+    "@types/node" "*"
+
+"@types/chai@^4.1.7":
+  version "4.1.7"
+  resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.1.7.tgz#1b8e33b61a8c09cbe1f85133071baa0dbf9fa71a"
+  integrity sha512-2Y8uPt0/jwjhQ6EiluT0XCri1Dbplr0ZxfFXUz+ye13gaqE8u5gL5ppao1JrUYr9cIip5S6MvQzBS7Kke7U9VA==
+
+"@types/connect@*":
+  version "3.4.32"
+  resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.32.tgz#aa0e9616b9435ccad02bc52b5b454ffc2c70ba28"
+  integrity sha512-4r8qa0quOvh7lGD0pre62CAb1oni1OO6ecJLGCezTmhQ8Fz50Arx9RUszryR8KlgK6avuSXvviL6yWyViQABOg==
+  dependencies:
+    "@types/node" "*"
+
+"@types/cookiejar@*":
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/@types/cookiejar/-/cookiejar-2.1.1.tgz#90b68446364baf9efd8e8349bb36bd3852b75b80"
+  integrity sha512-aRnpPa7ysx3aNW60hTiCtLHlQaIFsXFCgQlpakNgDNVFzbtusSY8PwjAQgRWfSk0ekNoBjO51eQRB6upA9uuyw==
+
+"@types/events@*":
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7"
+  integrity sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==
+
+"@types/express-serve-static-core@*":
+  version "4.16.1"
+  resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.16.1.tgz#35df7b302299a4ab138a643617bd44078e74d44e"
+  integrity sha512-QgbIMRU1EVRry5cIu1ORCQP4flSYqLM1lS5LYyGWfKnFT3E58f0gKto7BR13clBFVrVZ0G0rbLZ1hUpSkgQQOA==
+  dependencies:
+    "@types/node" "*"
+    "@types/range-parser" "*"
+
+"@types/express@^4.16.0":
+  version "4.16.1"
+  resolved "https://registry.yarnpkg.com/@types/express/-/express-4.16.1.tgz#d756bd1a85c34d87eaf44c888bad27ba8a4b7cf0"
+  integrity sha512-V0clmJow23WeyblmACoxbHBu2JKlE5TiIme6Lem14FnPW9gsttyHtk6wq7njcdIWH1njAaFgR8gW09lgY98gQg==
+  dependencies:
+    "@types/body-parser" "*"
+    "@types/express-serve-static-core" "*"
+    "@types/serve-static" "*"
+
+"@types/fs-extra@^5.0.3":
+  version "5.0.5"
+  resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-5.0.5.tgz#080d90a792f3fa2c5559eb44bd8ef840aae9104b"
+  integrity sha512-w7iqhDH9mN8eLClQOYTkhdYUOSpp25eXxfc6VbFOGtzxW34JcvctH2bKjj4jD4++z4R5iO5D+pg48W2e03I65A==
+  dependencies:
+    "@types/node" "*"
+
+"@types/glob@*":
+  version "7.1.1"
+  resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.1.tgz#aa59a1c6e3fbc421e07ccd31a944c30eba521575"
+  integrity sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==
+  dependencies:
+    "@types/events" "*"
+    "@types/minimatch" "*"
+    "@types/node" "*"
+
+"@types/handlebars@^4.0.38":
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/@types/handlebars/-/handlebars-4.1.0.tgz#3fcce9bf88f85fe73dc932240ab3fb682c624850"
+  integrity sha512-gq9YweFKNNB1uFK71eRqsd4niVkXrxHugqWFQkeLRJvGjnxsLr16bYtcsG4tOFwmYi0Bax+wCkbf1reUfdl4kA==
+  dependencies:
+    handlebars "*"
+
+"@types/highlight.js@^9.12.3":
+  version "9.12.3"
+  resolved "https://registry.yarnpkg.com/@types/highlight.js/-/highlight.js-9.12.3.tgz#b672cfaac25cbbc634a0fd92c515f66faa18dbca"
+  integrity sha512-pGF/zvYOACZ/gLGWdQH8zSwteQS1epp68yRcVLJMgUck/MjEn/FBYmPub9pXT8C1e4a8YZfHo1CKyV8q1vKUnQ==
+
+"@types/lodash@^4.14.110":
+  version "4.14.122"
+  resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.122.tgz#3e31394c38cf1e5949fb54c1192cbc406f152c6c"
+  integrity sha512-9IdED8wU93ty8gP06ninox+42SBSJHp2IAamsSYMUY76mshRTeUsid/gtbl8ovnOwy8im41ib4cxTiIYMXGKew==
+
+"@types/marked@^0.4.0":
+  version "0.4.2"
+  resolved "https://registry.yarnpkg.com/@types/marked/-/marked-0.4.2.tgz#64a89e53ea37f61cc0f3ee1732c555c2dbf6452f"
+  integrity sha512-cDB930/7MbzaGF6U3IwSQp6XBru8xWajF5PV2YZZeV8DyiliTuld11afVztGI9+yJZ29il5E+NpGA6ooV/Cjkg==
+
+"@types/mime@*":
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/@types/mime/-/mime-2.0.0.tgz#5a7306e367c539b9f6543499de8dd519fac37a8b"
+  integrity sha512-A2TAGbTFdBw9azHbpVd+/FkdW2T6msN1uct1O9bH3vTerEHKZhTXJUQXy+hNq1B0RagfU8U+KBdqiZpxjhOUQA==
+
+"@types/minimatch@*", "@types/minimatch@3.0.3":
+  version "3.0.3"
+  resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"
+  integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==
+
+"@types/mocha@^5.2.5":
+  version "5.2.6"
+  resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-5.2.6.tgz#b8622d50557dd155e9f2f634b7d68fd38de5e94b"
+  integrity sha512-1axi39YdtBI7z957vdqXI4Ac25e7YihYQtJa+Clnxg1zTJEaIRbndt71O3sP4GAMgiAm0pY26/b9BrY4MR/PMw==
+
+"@types/node@*":
+  version "11.11.0"
+  resolved "https://registry.yarnpkg.com/@types/node/-/node-11.11.0.tgz#070e9ce7c90e727aca0e0c14e470f9a93ffe9390"
+  integrity sha512-D5Rt+HXgEywr3RQJcGlZUCTCx1qVbCZpVk3/tOOA6spLNZdGm8BU+zRgdRYDoF1pO3RuXLxADzMrF903JlQXqg==
+
+"@types/pg-types@*":
+  version "1.11.4"
+  resolved "https://registry.yarnpkg.com/@types/pg-types/-/pg-types-1.11.4.tgz#8d7c59fb509ce3dca3f8bae589252051c639a9a8"
+  integrity sha512-WdIiQmE347LGc1Vq3Ki8sk3iyCuLgnccqVzgxek6gEHp2H0p3MQ3jniIHt+bRODXKju4kNQ+mp53lmP5+/9moQ==
+  dependencies:
+    moment ">=2.14.0"
+
+"@types/pg@^7.4.13":
+  version "7.4.13"
+  resolved "https://registry.yarnpkg.com/@types/pg/-/pg-7.4.13.tgz#4630494096bceee5ee562339502e3448c09703a8"
+  integrity sha512-jk/hFADnywyjnWXZ6IeNsAk2lZtKDInZWGs1ASxmLb3QBpwLDGcSvH5s6IIRlPqsXjwzu8btnNbQ5Cx+AX/CjA==
+  dependencies:
+    "@types/node" "*"
+    "@types/pg-types" "*"
+
+"@types/range-parser@*":
+  version "1.2.3"
+  resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.3.tgz#7ee330ba7caafb98090bece86a5ee44115904c2c"
+  integrity sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==
+
+"@types/serve-static@*":
+  version "1.13.2"
+  resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.2.tgz#f5ac4d7a6420a99a6a45af4719f4dcd8cd907a48"
+  integrity sha512-/BZ4QRLpH/bNYgZgwhKEh+5AsboDBcUdlBYgzoLX0fpj3Y2gp6EApyOlM3bK53wQS/OE1SrdSYBAbux2D1528Q==
+  dependencies:
+    "@types/express-serve-static-core" "*"
+    "@types/mime" "*"
+
+"@types/shelljs@^0.8.0":
+  version "0.8.3"
+  resolved "https://registry.yarnpkg.com/@types/shelljs/-/shelljs-0.8.3.tgz#f713f312dbae49ab5025290007e71ea32998e9a9"
+  integrity sha512-miY41hqc5SkRlsZDod3heDa4OS9xv8G77EMBQuSpqq86HBn66l7F+f8y9YKm+1PIuwC8QEZVwN8YxOOG7Y67fA==
+  dependencies:
+    "@types/glob" "*"
+    "@types/node" "*"
+
+"@types/superagent@*":
+  version "3.8.6"
+  resolved "https://registry.yarnpkg.com/@types/superagent/-/superagent-3.8.6.tgz#3676d8920d8979ea4ca57513f27995064f92dc43"
+  integrity sha512-YQjdsk27MLb6uyXjjywGyYeuqavwV3CirHt6btBz00HkKJyowdB8gjjB1zIZxrOybDRqO8FLjTZeEtmtC2hqxA==
+  dependencies:
+    "@types/cookiejar" "*"
+    "@types/node" "*"
+
+"@types/supertest@^2.0.7":
+  version "2.0.7"
+  resolved "https://registry.yarnpkg.com/@types/supertest/-/supertest-2.0.7.tgz#46ff6508075cd4519736be060f0d6331a5c8ca7b"
+  integrity sha512-GibTh4OTkal71btYe2fpZP/rVHIPnnUsYphEaoywVHo+mo2a/LhlOFkIm5wdN0H0DA0Hx8x+tKgCYMD9elHu5w==
+  dependencies:
+    "@types/superagent" "*"
+
+abbrev@1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
+  integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==
+
+abbrev@1.0.x:
+  version "1.0.9"
+  resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135"
+  integrity sha1-kbR5JYinc4wl813W9jdSovh3YTU=
+
+accepts@~1.3.5:
+  version "1.3.5"
+  resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.5.tgz#eb777df6011723a3b14e8a72c0805c8e86746bd2"
+  integrity sha1-63d99gEXI6OxTopywIBcjoZ0a9I=
+  dependencies:
+    mime-types "~2.1.18"
+    negotiator "0.6.1"
+
+ansi-regex@^2.0.0:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
+  integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8=
+
+ansi-styles@^2.2.1:
+  version "2.2.1"
+  resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
+  integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=
+
+ansi-styles@^3.2.1:
+  version "3.2.1"
+  resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
+  integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==
+  dependencies:
+    color-convert "^1.9.0"
+
+append-transform@^0.4.0:
+  version "0.4.0"
+  resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-0.4.0.tgz#d76ebf8ca94d276e247a36bad44a4b74ab611991"
+  integrity sha1-126/jKlNJ24keja61EpLdKthGZE=
+  dependencies:
+    default-require-extensions "^1.0.0"
+
+argparse@^1.0.7:
+  version "1.0.10"
+  resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911"
+  integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==
+  dependencies:
+    sprintf-js "~1.0.2"
+
+array-flatten@1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"
+  integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=
+
+arrify@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
+  integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=
+
+assertion-error@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b"
+  integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==
+
+async@1.x:
+  version "1.5.2"
+  resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a"
+  integrity sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=
+
+async@^2.1.4, async@^2.5.0, async@^2.6.1:
+  version "2.6.2"
+  resolved "https://registry.yarnpkg.com/async/-/async-2.6.2.tgz#18330ea7e6e313887f5d2f2a904bac6fe4dd5381"
+  integrity sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==
+  dependencies:
+    lodash "^4.17.11"
+
+asynckit@^0.4.0:
+  version "0.4.0"
+  resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
+  integrity sha1-x57Zf380y48robyXkLzDZkdLS3k=
+
+babel-code-frame@^6.22.0, babel-code-frame@^6.26.0:
+  version "6.26.0"
+  resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b"
+  integrity sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=
+  dependencies:
+    chalk "^1.1.3"
+    esutils "^2.0.2"
+    js-tokens "^3.0.2"
+
+babel-generator@^6.18.0:
+  version "6.26.1"
+  resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90"
+  integrity sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==
+  dependencies:
+    babel-messages "^6.23.0"
+    babel-runtime "^6.26.0"
+    babel-types "^6.26.0"
+    detect-indent "^4.0.0"
+    jsesc "^1.3.0"
+    lodash "^4.17.4"
+    source-map "^0.5.7"
+    trim-right "^1.0.1"
+
+babel-messages@^6.23.0:
+  version "6.23.0"
+  resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e"
+  integrity sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=
+  dependencies:
+    babel-runtime "^6.22.0"
+
+babel-runtime@^6.22.0, babel-runtime@^6.26.0:
+  version "6.26.0"
+  resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe"
+  integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4=
+  dependencies:
+    core-js "^2.4.0"
+    regenerator-runtime "^0.11.0"
+
+babel-template@^6.16.0:
+  version "6.26.0"
+  resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02"
+  integrity sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=
+  dependencies:
+    babel-runtime "^6.26.0"
+    babel-traverse "^6.26.0"
+    babel-types "^6.26.0"
+    babylon "^6.18.0"
+    lodash "^4.17.4"
+
+babel-traverse@^6.18.0, babel-traverse@^6.26.0:
+  version "6.26.0"
+  resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee"
+  integrity sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=
+  dependencies:
+    babel-code-frame "^6.26.0"
+    babel-messages "^6.23.0"
+    babel-runtime "^6.26.0"
+    babel-types "^6.26.0"
+    babylon "^6.18.0"
+    debug "^2.6.8"
+    globals "^9.18.0"
+    invariant "^2.2.2"
+    lodash "^4.17.4"
+
+babel-types@^6.18.0, babel-types@^6.26.0:
+  version "6.26.0"
+  resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497"
+  integrity sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=
+  dependencies:
+    babel-runtime "^6.26.0"
+    esutils "^2.0.2"
+    lodash "^4.17.4"
+    to-fast-properties "^1.0.3"
+
+babylon@^6.18.0:
+  version "6.18.0"
+  resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3"
+  integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==
+
+balanced-match@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
+  integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
+
+body-parser@1.18.3:
+  version "1.18.3"
+  resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.3.tgz#5b292198ffdd553b3a0f20ded0592b956955c8b4"
+  integrity sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=
+  dependencies:
+    bytes "3.0.0"
+    content-type "~1.0.4"
+    debug "2.6.9"
+    depd "~1.1.2"
+    http-errors "~1.6.3"
+    iconv-lite "0.4.23"
+    on-finished "~2.3.0"
+    qs "6.5.2"
+    raw-body "2.3.3"
+    type-is "~1.6.16"
+
+brace-expansion@^1.1.7:
+  version "1.1.11"
+  resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
+  integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
+  dependencies:
+    balanced-match "^1.0.0"
+    concat-map "0.0.1"
+
+browser-stdout@1.3.1:
+  version "1.3.1"
+  resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60"
+  integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==
+
+buffer-from@^1.0.0, buffer-from@^1.1.0:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
+  integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==
+
+buffer-writer@2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/buffer-writer/-/buffer-writer-2.0.0.tgz#ce7eb81a38f7829db09c873f2fbb792c0c98ec04"
+  integrity sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==
+
+builtin-modules@^1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f"
+  integrity sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=
+
+bytes@3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048"
+  integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=
+
+chai@^4.2.0:
+  version "4.2.0"
+  resolved "https://registry.yarnpkg.com/chai/-/chai-4.2.0.tgz#760aa72cf20e3795e84b12877ce0e83737aa29e5"
+  integrity sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==
+  dependencies:
+    assertion-error "^1.1.0"
+    check-error "^1.0.2"
+    deep-eql "^3.0.1"
+    get-func-name "^2.0.0"
+    pathval "^1.1.0"
+    type-detect "^4.0.5"
+
+chalk@^1.1.3:
+  version "1.1.3"
+  resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
+  integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=
+  dependencies:
+    ansi-styles "^2.2.1"
+    escape-string-regexp "^1.0.2"
+    has-ansi "^2.0.0"
+    strip-ansi "^3.0.0"
+    supports-color "^2.0.0"
+
+chalk@^2.3.0:
+  version "2.4.2"
+  resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
+  integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
+  dependencies:
+    ansi-styles "^3.2.1"
+    escape-string-regexp "^1.0.5"
+    supports-color "^5.3.0"
+
+check-error@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82"
+  integrity sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=
+
+color-convert@^1.9.0:
+  version "1.9.3"
+  resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
+  integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
+  dependencies:
+    color-name "1.1.3"
+
+color-name@1.1.3:
+  version "1.1.3"
+  resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
+  integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=
+
+combined-stream@^1.0.6:
+  version "1.0.7"
+  resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.7.tgz#2d1d24317afb8abe95d6d2c0b07b57813539d828"
+  integrity sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==
+  dependencies:
+    delayed-stream "~1.0.0"
+
+commander@2.15.1:
+  version "2.15.1"
+  resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f"
+  integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==
+
+commander@^2.12.1:
+  version "2.19.0"
+  resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a"
+  integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==
+
+commander@~2.17.1:
+  version "2.17.1"
+  resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf"
+  integrity sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==
+
+component-emitter@^1.2.0:
+  version "1.2.1"
+  resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6"
+  integrity sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=
+
+concat-map@0.0.1:
+  version "0.0.1"
+  resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
+  integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
+
+content-disposition@0.5.2:
+  version "0.5.2"
+  resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4"
+  integrity sha1-DPaLud318r55YcOoUXjLhdunjLQ=
+
+content-type@~1.0.4:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
+  integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
+
+cookie-signature@1.0.6:
+  version "1.0.6"
+  resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
+  integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw=
+
+cookie@0.3.1:
+  version "0.3.1"
+  resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb"
+  integrity sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=
+
+cookiejar@^2.1.0:
+  version "2.1.2"
+  resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.2.tgz#dd8a235530752f988f9a0844f3fc589e3111125c"
+  integrity sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==
+
+core-js@^2.4.0:
+  version "2.6.5"
+  resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.5.tgz#44bc8d249e7fb2ff5d00e0341a7ffb94fbf67895"
+  integrity sha512-klh/kDpwX8hryYL14M9w/xei6vrv6sE8gTHDG7/T/+SEovB/G4ejwcfE/CBzO6Edsu+OETZMZ3wcX/EjUkrl5A==
+
+core-util-is@~1.0.0:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
+  integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
+
+debug@2.6.9, debug@^2.6.8:
+  version "2.6.9"
+  resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
+  integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
+  dependencies:
+    ms "2.0.0"
+
+debug@3.1.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
+  integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==
+  dependencies:
+    ms "2.0.0"
+
+debug@^3.1.0:
+  version "3.2.6"
+  resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b"
+  integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==
+  dependencies:
+    ms "^2.1.1"
+
+deep-eql@^3.0.1:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df"
+  integrity sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==
+  dependencies:
+    type-detect "^4.0.0"
+
+default-require-extensions@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-1.0.0.tgz#f37ea15d3e13ffd9b437d33e1a75b5fb97874cb8"
+  integrity sha1-836hXT4T/9m0N9M+GnW1+5eHTLg=
+  dependencies:
+    strip-bom "^2.0.0"
+
+delayed-stream@~1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
+  integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk=
+
+depd@~1.1.2:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
+  integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=
+
+destroy@~1.0.4:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
+  integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=
+
+detect-indent@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208"
+  integrity sha1-920GQ1LN9Docts5hnE7jqUdd4gg=
+  dependencies:
+    repeating "^2.0.0"
+
+diff@3.5.0, diff@^3.1.0, diff@^3.2.0:
+  version "3.5.0"
+  resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12"
+  integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==
+
+ee-first@1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
+  integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=
+
+encodeurl@~1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
+  integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=
+
+escape-html@~1.0.3:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
+  integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=
+
+escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5:
+  version "1.0.5"
+  resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
+  integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
+
+esprima@^4.0.0:
+  version "4.0.1"
+  resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
+  integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
+
+esutils@^2.0.2:
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b"
+  integrity sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=
+
+etag@~1.8.1:
+  version "1.8.1"
+  resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
+  integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=
+
+express@^4.16.4:
+  version "4.16.4"
+  resolved "https://registry.yarnpkg.com/express/-/express-4.16.4.tgz#fddef61926109e24c515ea97fd2f1bdbf62df12e"
+  integrity sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg==
+  dependencies:
+    accepts "~1.3.5"
+    array-flatten "1.1.1"
+    body-parser "1.18.3"
+    content-disposition "0.5.2"
+    content-type "~1.0.4"
+    cookie "0.3.1"
+    cookie-signature "1.0.6"
+    debug "2.6.9"
+    depd "~1.1.2"
+    encodeurl "~1.0.2"
+    escape-html "~1.0.3"
+    etag "~1.8.1"
+    finalhandler "1.1.1"
+    fresh "0.5.2"
+    merge-descriptors "1.0.1"
+    methods "~1.1.2"
+    on-finished "~2.3.0"
+    parseurl "~1.3.2"
+    path-to-regexp "0.1.7"
+    proxy-addr "~2.0.4"
+    qs "6.5.2"
+    range-parser "~1.2.0"
+    safe-buffer "5.1.2"
+    send "0.16.2"
+    serve-static "1.13.2"
+    setprototypeof "1.1.0"
+    statuses "~1.4.0"
+    type-is "~1.6.16"
+    utils-merge "1.0.1"
+    vary "~1.1.2"
+
+extend@^3.0.0:
+  version "3.0.2"
+  resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
+  integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
+
+fileset@^2.0.2:
+  version "2.0.3"
+  resolved "https://registry.yarnpkg.com/fileset/-/fileset-2.0.3.tgz#8e7548a96d3cc2327ee5e674168723a333bba2a0"
+  integrity sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA=
+  dependencies:
+    glob "^7.0.3"
+    minimatch "^3.0.3"
+
+finalhandler@1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.1.tgz#eebf4ed840079c83f4249038c9d703008301b105"
+  integrity sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==
+  dependencies:
+    debug "2.6.9"
+    encodeurl "~1.0.2"
+    escape-html "~1.0.3"
+    on-finished "~2.3.0"
+    parseurl "~1.3.2"
+    statuses "~1.4.0"
+    unpipe "~1.0.0"
+
+form-data@^2.3.1:
+  version "2.3.3"
+  resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6"
+  integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==
+  dependencies:
+    asynckit "^0.4.0"
+    combined-stream "^1.0.6"
+    mime-types "^2.1.12"
+
+formidable@^1.2.0:
+  version "1.2.1"
+  resolved "https://registry.yarnpkg.com/formidable/-/formidable-1.2.1.tgz#70fb7ca0290ee6ff961090415f4b3df3d2082659"
+  integrity sha512-Fs9VRguL0gqGHkXS5GQiMCr1VhZBxz0JnJs4JmMp/2jL18Fmbzvv7vOFRU+U8TBkHEE/CX1qDXzJplVULgsLeg==
+
+forwarded@~0.1.2:
+  version "0.1.2"
+  resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84"
+  integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=
+
+fresh@0.5.2:
+  version "0.5.2"
+  resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
+  integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=
+
+fs-extra@^7.0.0:
+  version "7.0.1"
+  resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9"
+  integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==
+  dependencies:
+    graceful-fs "^4.1.2"
+    jsonfile "^4.0.0"
+    universalify "^0.1.0"
+
+fs.realpath@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
+  integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
+
+get-func-name@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41"
+  integrity sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=
+
+glob@7.1.2:
+  version "7.1.2"
+  resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15"
+  integrity sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==
+  dependencies:
+    fs.realpath "^1.0.0"
+    inflight "^1.0.4"
+    inherits "2"
+    minimatch "^3.0.4"
+    once "^1.3.0"
+    path-is-absolute "^1.0.0"
+
+glob@^7.0.0, glob@^7.0.3, glob@^7.1.1, glob@^7.1.3:
+  version "7.1.3"
+  resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1"
+  integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==
+  dependencies:
+    fs.realpath "^1.0.0"
+    inflight "^1.0.4"
+    inherits "2"
+    minimatch "^3.0.4"
+    once "^1.3.0"
+    path-is-absolute "^1.0.0"
+
+globals@^9.18.0:
+  version "9.18.0"
+  resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a"
+  integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==
+
+graceful-fs@^4.1.2, graceful-fs@^4.1.6:
+  version "4.1.15"
+  resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00"
+  integrity sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==
+
+growl@1.10.5:
+  version "1.10.5"
+  resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e"
+  integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==
+
+handlebars@*, handlebars@^4.0.3, handlebars@^4.0.6:
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.1.0.tgz#0d6a6f34ff1f63cecec8423aa4169827bf787c3a"
+  integrity sha512-l2jRuU1NAWK6AW5qqcTATWQJvNPEwkM7NEKSiv/gqOsoSQbVoWyqVEY5GS+XPQ88zLNmqASRpzfdm8d79hJS+w==
+  dependencies:
+    async "^2.5.0"
+    optimist "^0.6.1"
+    source-map "^0.6.1"
+  optionalDependencies:
+    uglify-js "^3.1.4"
+
+has-ansi@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91"
+  integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=
+  dependencies:
+    ansi-regex "^2.0.0"
+
+has-flag@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa"
+  integrity sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=
+
+has-flag@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
+  integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0=
+
+he@1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd"
+  integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0=
+
+highlight.js@^9.13.1:
+  version "9.15.6"
+  resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.15.6.tgz#72d4d8d779ec066af9a17cb14360c3def0aa57c4"
+  integrity sha512-zozTAWM1D6sozHo8kqhfYgsac+B+q0PmsjXeyDrYIHHcBN0zTVT66+s2GW1GZv7DbyaROdLXKdabwS/WqPyIdQ==
+
+http-errors@1.6.3, http-errors@~1.6.2, http-errors@~1.6.3:
+  version "1.6.3"
+  resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d"
+  integrity sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=
+  dependencies:
+    depd "~1.1.2"
+    inherits "2.0.3"
+    setprototypeof "1.1.0"
+    statuses ">= 1.4.0 < 2"
+
+iconv-lite@0.4.23:
+  version "0.4.23"
+  resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63"
+  integrity sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==
+  dependencies:
+    safer-buffer ">= 2.1.2 < 3"
+
+inflight@^1.0.4:
+  version "1.0.6"
+  resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
+  integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=
+  dependencies:
+    once "^1.3.0"
+    wrappy "1"
+
+inherits@2, inherits@2.0.3, inherits@~2.0.3:
+  version "2.0.3"
+  resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
+  integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
+
+interpret@^1.0.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.2.0.tgz#d5061a6224be58e8083985f5014d844359576296"
+  integrity sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==
+
+invariant@^2.2.2:
+  version "2.2.4"
+  resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6"
+  integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==
+  dependencies:
+    loose-envify "^1.0.0"
+
+ipaddr.js@1.8.0:
+  version "1.8.0"
+  resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.8.0.tgz#eaa33d6ddd7ace8f7f6fe0c9ca0440e706738b1e"
+  integrity sha1-6qM9bd16zo9/b+DJygRA5wZzix4=
+
+is-finite@^1.0.0:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa"
+  integrity sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=
+  dependencies:
+    number-is-nan "^1.0.0"
+
+is-utf8@^0.2.0:
+  version "0.2.1"
+  resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72"
+  integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=
+
+isarray@~1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
+  integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
+
+isexe@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
+  integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=
+
+istanbul-api@^1.1.0-alpha:
+  version "1.3.7"
+  resolved "https://registry.yarnpkg.com/istanbul-api/-/istanbul-api-1.3.7.tgz#a86c770d2b03e11e3f778cd7aedd82d2722092aa"
+  integrity sha512-4/ApBnMVeEPG3EkSzcw25wDe4N66wxwn+KKn6b47vyek8Xb3NBAcg4xfuQbS7BqcZuTX4wxfD5lVagdggR3gyA==
+  dependencies:
+    async "^2.1.4"
+    fileset "^2.0.2"
+    istanbul-lib-coverage "^1.2.1"
+    istanbul-lib-hook "^1.2.2"
+    istanbul-lib-instrument "^1.10.2"
+    istanbul-lib-report "^1.1.5"
+    istanbul-lib-source-maps "^1.2.6"
+    istanbul-reports "^1.5.1"
+    js-yaml "^3.7.0"
+    mkdirp "^0.5.1"
+    once "^1.4.0"
+
+istanbul-lib-coverage@^1.2.1:
+  version "1.2.1"
+  resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.1.tgz#ccf7edcd0a0bb9b8f729feeb0930470f9af664f0"
+  integrity sha512-PzITeunAgyGbtY1ibVIUiV679EFChHjoMNRibEIobvmrCRaIgwLxNucOSimtNWUhEib/oO7QY2imD75JVgCJWQ==
+
+istanbul-lib-hook@^1.2.2:
+  version "1.2.2"
+  resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-1.2.2.tgz#bc6bf07f12a641fbf1c85391d0daa8f0aea6bf86"
+  integrity sha512-/Jmq7Y1VeHnZEQ3TL10VHyb564mn6VrQXHchON9Jf/AEcmQ3ZIiyD1BVzNOKTZf/G3gE+kiGK6SmpF9y3qGPLw==
+  dependencies:
+    append-transform "^0.4.0"
+
+istanbul-lib-instrument@^1.10.2:
+  version "1.10.2"
+  resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.2.tgz#1f55ed10ac3c47f2bdddd5307935126754d0a9ca"
+  integrity sha512-aWHxfxDqvh/ZlxR8BBaEPVSWDPUkGD63VjGQn3jcw8jCp7sHEMKcrj4xfJn/ABzdMEHiQNyvDQhqm5o8+SQg7A==
+  dependencies:
+    babel-generator "^6.18.0"
+    babel-template "^6.16.0"
+    babel-traverse "^6.18.0"
+    babel-types "^6.18.0"
+    babylon "^6.18.0"
+    istanbul-lib-coverage "^1.2.1"
+    semver "^5.3.0"
+
+istanbul-lib-report@^1.1.5:
+  version "1.1.5"
+  resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-1.1.5.tgz#f2a657fc6282f96170aaf281eb30a458f7f4170c"
+  integrity sha512-UsYfRMoi6QO/doUshYNqcKJqVmFe9w51GZz8BS3WB0lYxAllQYklka2wP9+dGZeHYaWIdcXUx8JGdbqaoXRXzw==
+  dependencies:
+    istanbul-lib-coverage "^1.2.1"
+    mkdirp "^0.5.1"
+    path-parse "^1.0.5"
+    supports-color "^3.1.2"
+
+istanbul-lib-source-maps@^1.2.6:
+  version "1.2.6"
+  resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.6.tgz#37b9ff661580f8fca11232752ee42e08c6675d8f"
+  integrity sha512-TtbsY5GIHgbMsMiRw35YBHGpZ1DVFEO19vxxeiDMYaeOFOCzfnYVxvl6pOUIZR4dtPhAGpSMup8OyF8ubsaqEg==
+  dependencies:
+    debug "^3.1.0"
+    istanbul-lib-coverage "^1.2.1"
+    mkdirp "^0.5.1"
+    rimraf "^2.6.1"
+    source-map "^0.5.3"
+
+istanbul-reports@^1.5.1:
+  version "1.5.1"
+  resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-1.5.1.tgz#97e4dbf3b515e8c484caea15d6524eebd3ff4e1a"
+  integrity sha512-+cfoZ0UXzWjhAdzosCPP3AN8vvef8XDkWtTfgaN+7L3YTpNYITnCaEkceo5SEYy644VkHka/P1FvkWvrG/rrJw==
+  dependencies:
+    handlebars "^4.0.3"
+
+istanbul@1.1.0-alpha.1:
+  version "1.1.0-alpha.1"
+  resolved "https://registry.yarnpkg.com/istanbul/-/istanbul-1.1.0-alpha.1.tgz#781795656018a2174c5f60f367ee5d361cb57b77"
+  integrity sha1-eBeVZWAYohdMX2DzZ+5dNhy1e3c=
+  dependencies:
+    abbrev "1.0.x"
+    async "1.x"
+    istanbul-api "^1.1.0-alpha"
+    js-yaml "3.x"
+    mkdirp "0.5.x"
+    nopt "3.x"
+    which "^1.1.1"
+    wordwrap "^1.0.0"
+
+"js-tokens@^3.0.0 || ^4.0.0":
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
+  integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
+
+js-tokens@^3.0.2:
+  version "3.0.2"
+  resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b"
+  integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls=
+
+js-yaml@3.x, js-yaml@^3.7.0:
+  version "3.12.2"
+  resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.2.tgz#ef1d067c5a9d9cb65bd72f285b5d8105c77f14fc"
+  integrity sha512-QHn/Lh/7HhZ/Twc7vJYQTkjuCa0kaCcDcjK5Zlk2rvnUpy7DxMJ23+Jc2dcyvltwQVg1nygAVlB2oRDFHoRS5Q==
+  dependencies:
+    argparse "^1.0.7"
+    esprima "^4.0.0"
+
+jsesc@^1.3.0:
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b"
+  integrity sha1-RsP+yMGJKxKwgz25vHYiF226s0s=
+
+jsonfile@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb"
+  integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=
+  optionalDependencies:
+    graceful-fs "^4.1.6"
+
+lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.4:
+  version "4.17.11"
+  resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d"
+  integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==
+
+loose-envify@^1.0.0:
+  version "1.4.0"
+  resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
+  integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
+  dependencies:
+    js-tokens "^3.0.0 || ^4.0.0"
+
+make-error@^1.1.1:
+  version "1.3.5"
+  resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.5.tgz#efe4e81f6db28cadd605c70f29c831b58ef776c8"
+  integrity sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==
+
+marked@^0.4.0:
+  version "0.4.0"
+  resolved "https://registry.yarnpkg.com/marked/-/marked-0.4.0.tgz#9ad2c2a7a1791f10a852e0112f77b571dce10c66"
+  integrity sha512-tMsdNBgOsrUophCAFQl0XPe6Zqk/uy9gnue+jIIKhykO51hxyu6uNx7zBPy0+y/WKYVZZMspV9YeXLNdKk+iYw==
+
+media-typer@0.3.0:
+  version "0.3.0"
+  resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
+  integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=
+
+merge-descriptors@1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
+  integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=
+
+methods@^1.1.1, methods@^1.1.2, methods@~1.1.2:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
+  integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=
+
+mime-db@~1.37.0:
+  version "1.37.0"
+  resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.37.0.tgz#0b6a0ce6fdbe9576e25f1f2d2fde8830dc0ad0d8"
+  integrity sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==
+
+mime-types@^2.1.12, mime-types@~2.1.18:
+  version "2.1.21"
+  resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.21.tgz#28995aa1ecb770742fe6ae7e58f9181c744b3f96"
+  integrity sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==
+  dependencies:
+    mime-db "~1.37.0"
+
+mime@1.4.1:
+  version "1.4.1"
+  resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6"
+  integrity sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==
+
+mime@^1.4.1:
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
+  integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==
+
+minimatch@3.0.4, minimatch@^3.0.0, minimatch@^3.0.3, minimatch@^3.0.4:
+  version "3.0.4"
+  resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
+  integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
+  dependencies:
+    brace-expansion "^1.1.7"
+
+minimist@0.0.8:
+  version "0.0.8"
+  resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
+  integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=
+
+minimist@^1.2.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
+  integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=
+
+minimist@~0.0.1:
+  version "0.0.10"
+  resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf"
+  integrity sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=
+
+mkdirp@0.5.1, mkdirp@0.5.x, mkdirp@^0.5.1:
+  version "0.5.1"
+  resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
+  integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=
+  dependencies:
+    minimist "0.0.8"
+
+mocha@^5.2.0:
+  version "5.2.0"
+  resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.2.0.tgz#6d8ae508f59167f940f2b5b3c4a612ae50c90ae6"
+  integrity sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==
+  dependencies:
+    browser-stdout "1.3.1"
+    commander "2.15.1"
+    debug "3.1.0"
+    diff "3.5.0"
+    escape-string-regexp "1.0.5"
+    glob "7.1.2"
+    growl "1.10.5"
+    he "1.1.1"
+    minimatch "3.0.4"
+    mkdirp "0.5.1"
+    supports-color "5.4.0"
+
+moment@>=2.14.0:
+  version "2.24.0"
+  resolved "https://registry.yarnpkg.com/moment/-/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b"
+  integrity sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==
+
+ms@2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
+  integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
+
+ms@^2.1.1:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
+  integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==
+
+negotiator@0.6.1:
+  version "0.6.1"
+  resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9"
+  integrity sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=
+
+nopt@3.x:
+  version "3.0.6"
+  resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9"
+  integrity sha1-xkZdvwirzU2zWTF/eaxopkayj/k=
+  dependencies:
+    abbrev "1"
+
+number-is-nan@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
+  integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=
+
+on-finished@~2.3.0:
+  version "2.3.0"
+  resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947"
+  integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=
+  dependencies:
+    ee-first "1.1.1"
+
+once@^1.3.0, once@^1.4.0:
+  version "1.4.0"
+  resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
+  integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E=
+  dependencies:
+    wrappy "1"
+
+optimist@^0.6.1:
+  version "0.6.1"
+  resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686"
+  integrity sha1-2j6nRob6IaGaERwybpDrFaAZZoY=
+  dependencies:
+    minimist "~0.0.1"
+    wordwrap "~0.0.2"
+
+packet-reader@1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/packet-reader/-/packet-reader-1.0.0.tgz#9238e5480dedabacfe1fe3f2771063f164157d74"
+  integrity sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==
+
+parseurl@~1.3.2:
+  version "1.3.2"
+  resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3"
+  integrity sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=
+
+path-is-absolute@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
+  integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
+
+path-parse@^1.0.5, path-parse@^1.0.6:
+  version "1.0.6"
+  resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c"
+  integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==
+
+path-to-regexp@0.1.7:
+  version "0.1.7"
+  resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
+  integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=
+
+pathval@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.0.tgz#b942e6d4bde653005ef6b71361def8727d0645e0"
+  integrity sha1-uULm1L3mUwBe9rcTYd74cn0GReA=
+
+pg-connection-string@0.1.3:
+  version "0.1.3"
+  resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-0.1.3.tgz#da1847b20940e42ee1492beaf65d49d91b245df7"
+  integrity sha1-2hhHsglA5C7hSSvq9l1J2RskXfc=
+
+pg-int8@1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/pg-int8/-/pg-int8-1.0.1.tgz#943bd463bf5b71b4170115f80f8efc9a0c0eb78c"
+  integrity sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==
+
+pg-pool@^2.0.4:
+  version "2.0.6"
+  resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-2.0.6.tgz#7b561a482feb0a0e599b58b5137fd2db3ad8111c"
+  integrity sha512-hod2zYQxM8Gt482q+qONGTYcg/qVcV32VHVPtktbBJs0us3Dj7xibISw0BAAXVMCzt8A/jhfJvpZaxUlqtqs0g==
+
+pg-types@~2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/pg-types/-/pg-types-2.0.0.tgz#038ddc302a0340efcdb46d0581cc7caa2303cbba"
+  integrity sha512-THUD7gQll5tys+5eQ8Rvs7DjHiIC3bLqixk3gMN9Hu8UrCBAOjf35FoI39rTGGc3lM2HU/R+Knpxvd11mCwOMA==
+  dependencies:
+    pg-int8 "1.0.1"
+    postgres-array "~2.0.0"
+    postgres-bytea "~1.0.0"
+    postgres-date "~1.0.0"
+    postgres-interval "^1.1.0"
+
+pg@^7.8.1:
+  version "7.8.2"
+  resolved "https://registry.yarnpkg.com/pg/-/pg-7.8.2.tgz#d53ffcbbaa789e15e80ffec570603294d90116e8"
+  integrity sha512-5U4fjV43DnQxelkhyPdU3YfUbYVa21bNmreXRCM/gFFw09YxWaitWWITm/u0twUNF5EYOSDhkgyEAocgtpP9JQ==
+  dependencies:
+    buffer-writer "2.0.0"
+    packet-reader "1.0.0"
+    pg-connection-string "0.1.3"
+    pg-pool "^2.0.4"
+    pg-types "~2.0.0"
+    pgpass "1.x"
+    semver "4.3.2"
+
+pgpass@1.x:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/pgpass/-/pgpass-1.0.2.tgz#2a7bb41b6065b67907e91da1b07c1847c877b306"
+  integrity sha1-Knu0G2BltnkH6R2hsHwYR8h3swY=
+  dependencies:
+    split "^1.0.0"
+
+postgres-array@~2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/postgres-array/-/postgres-array-2.0.0.tgz#48f8fce054fbc69671999329b8834b772652d82e"
+  integrity sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==
+
+postgres-bytea@~1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/postgres-bytea/-/postgres-bytea-1.0.0.tgz#027b533c0aa890e26d172d47cf9ccecc521acd35"
+  integrity sha1-AntTPAqokOJtFy1Hz5zOzFIazTU=
+
+postgres-date@~1.0.0:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/postgres-date/-/postgres-date-1.0.3.tgz#e2d89702efdb258ff9d9cee0fe91bd06975257a8"
+  integrity sha1-4tiXAu/bJY/52c7g/pG9BpdSV6g=
+
+postgres-interval@^1.1.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/postgres-interval/-/postgres-interval-1.2.0.tgz#b460c82cb1587507788819a06aa0fffdb3544695"
+  integrity sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==
+  dependencies:
+    xtend "^4.0.0"
+
+process-nextick-args@~2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa"
+  integrity sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==
+
+progress@^2.0.0:
+  version "2.0.3"
+  resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8"
+  integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==
+
+proxy-addr@~2.0.4:
+  version "2.0.4"
+  resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.4.tgz#ecfc733bf22ff8c6f407fa275327b9ab67e48b93"
+  integrity sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==
+  dependencies:
+    forwarded "~0.1.2"
+    ipaddr.js "1.8.0"
+
+qs@6.5.2:
+  version "6.5.2"
+  resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"
+  integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==
+
+qs@^6.5.1:
+  version "6.6.0"
+  resolved "https://registry.yarnpkg.com/qs/-/qs-6.6.0.tgz#a99c0f69a8d26bf7ef012f871cdabb0aee4424c2"
+  integrity sha512-KIJqT9jQJDQx5h5uAVPimw6yVg2SekOKu959OCtktD3FjzbpvaPr8i4zzg07DOMz+igA4W/aNM7OV8H37pFYfA==
+
+range-parser@~1.2.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e"
+  integrity sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=
+
+raw-body@2.3.3:
+  version "2.3.3"
+  resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.3.tgz#1b324ece6b5706e153855bc1148c65bb7f6ea0c3"
+  integrity sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==
+  dependencies:
+    bytes "3.0.0"
+    http-errors "1.6.3"
+    iconv-lite "0.4.23"
+    unpipe "1.0.0"
+
+readable-stream@^2.3.5:
+  version "2.3.6"
+  resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf"
+  integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==
+  dependencies:
+    core-util-is "~1.0.0"
+    inherits "~2.0.3"
+    isarray "~1.0.0"
+    process-nextick-args "~2.0.0"
+    safe-buffer "~5.1.1"
+    string_decoder "~1.1.1"
+    util-deprecate "~1.0.1"
+
+rechoir@^0.6.2:
+  version "0.6.2"
+  resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384"
+  integrity sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=
+  dependencies:
+    resolve "^1.1.6"
+
+regenerator-runtime@^0.11.0:
+  version "0.11.1"
+  resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9"
+  integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==
+
+repeating@^2.0.0:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda"
+  integrity sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=
+  dependencies:
+    is-finite "^1.0.0"
+
+resolve@^1.1.6, resolve@^1.3.2:
+  version "1.10.0"
+  resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.10.0.tgz#3bdaaeaf45cc07f375656dfd2e54ed0810b101ba"
+  integrity sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg==
+  dependencies:
+    path-parse "^1.0.6"
+
+rimraf@^2.6.1:
+  version "2.6.3"
+  resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab"
+  integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==
+  dependencies:
+    glob "^7.1.3"
+
+safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
+  version "5.1.2"
+  resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
+  integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
+
+"safer-buffer@>= 2.1.2 < 3":
+  version "2.1.2"
+  resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
+  integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
+
+semver@4.3.2:
+  version "4.3.2"
+  resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.2.tgz#c7a07158a80bedd052355b770d82d6640f803be7"
+  integrity sha1-x6BxWKgL7dBSNVt3DYLWZA+AO+c=
+
+semver@^5.3.0:
+  version "5.6.0"
+  resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004"
+  integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==
+
+send@0.16.2:
+  version "0.16.2"
+  resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1"
+  integrity sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==
+  dependencies:
+    debug "2.6.9"
+    depd "~1.1.2"
+    destroy "~1.0.4"
+    encodeurl "~1.0.2"
+    escape-html "~1.0.3"
+    etag "~1.8.1"
+    fresh "0.5.2"
+    http-errors "~1.6.2"
+    mime "1.4.1"
+    ms "2.0.0"
+    on-finished "~2.3.0"
+    range-parser "~1.2.0"
+    statuses "~1.4.0"
+
+serve-static@1.13.2:
+  version "1.13.2"
+  resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.13.2.tgz#095e8472fd5b46237db50ce486a43f4b86c6cec1"
+  integrity sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==
+  dependencies:
+    encodeurl "~1.0.2"
+    escape-html "~1.0.3"
+    parseurl "~1.3.2"
+    send "0.16.2"
+
+setprototypeof@1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656"
+  integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==
+
+shelljs@^0.8.2:
+  version "0.8.3"
+  resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.3.tgz#a7f3319520ebf09ee81275b2368adb286659b097"
+  integrity sha512-fc0BKlAWiLpwZljmOvAOTE/gXawtCoNrP5oaY7KIaQbbyHeQVg01pSEuEGvGh3HEdBU4baCD7wQBwADmM/7f7A==
+  dependencies:
+    glob "^7.0.0"
+    interpret "^1.0.0"
+    rechoir "^0.6.2"
+
+source-map-support@^0.5.6:
+  version "0.5.10"
+  resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.10.tgz#2214080bc9d51832511ee2bab96e3c2f9353120c"
+  integrity sha512-YfQ3tQFTK/yzlGJuX8pTwa4tifQj4QS2Mj7UegOu8jAz59MqIiMGPXxQhVQiIMNzayuUSF/jEuVnfFF5JqybmQ==
+  dependencies:
+    buffer-from "^1.0.0"
+    source-map "^0.6.0"
+
+source-map@^0.5.3, source-map@^0.5.7:
+  version "0.5.7"
+  resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
+  integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=
+
+source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1:
+  version "0.6.1"
+  resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
+  integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
+
+split@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/split/-/split-1.0.1.tgz#605bd9be303aa59fb35f9229fbea0ddec9ea07d9"
+  integrity sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==
+  dependencies:
+    through "2"
+
+sprintf-js@~1.0.2:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
+  integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=
+
+"statuses@>= 1.4.0 < 2":
+  version "1.5.0"
+  resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
+  integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=
+
+statuses@~1.4.0:
+  version "1.4.0"
+  resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087"
+  integrity sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==
+
+string_decoder@~1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
+  integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==
+  dependencies:
+    safe-buffer "~5.1.0"
+
+strip-ansi@^3.0.0:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
+  integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=
+  dependencies:
+    ansi-regex "^2.0.0"
+
+strip-bom@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e"
+  integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=
+  dependencies:
+    is-utf8 "^0.2.0"
+
+superagent@^3.8.3:
+  version "3.8.3"
+  resolved "https://registry.yarnpkg.com/superagent/-/superagent-3.8.3.tgz#460ea0dbdb7d5b11bc4f78deba565f86a178e128"
+  integrity sha512-GLQtLMCoEIK4eDv6OGtkOoSMt3D+oq0y3dsxMuYuDvaNUvuT8eFBuLmfR0iYYzHC1e8hpzC6ZsxbuP6DIalMFA==
+  dependencies:
+    component-emitter "^1.2.0"
+    cookiejar "^2.1.0"
+    debug "^3.1.0"
+    extend "^3.0.0"
+    form-data "^2.3.1"
+    formidable "^1.2.0"
+    methods "^1.1.1"
+    mime "^1.4.1"
+    qs "^6.5.1"
+    readable-stream "^2.3.5"
+
+supertest@^3.3.0:
+  version "3.4.2"
+  resolved "https://registry.yarnpkg.com/supertest/-/supertest-3.4.2.tgz#bad7de2e43d60d27c8caeb8ab34a67c8a5f71aad"
+  integrity sha512-WZWbwceHUo2P36RoEIdXvmqfs47idNNZjCuJOqDz6rvtkk8ym56aU5oglORCpPeXGxT7l9rkJ41+O1lffQXYSA==
+  dependencies:
+    methods "^1.1.2"
+    superagent "^3.8.3"
+
+supports-color@5.4.0:
+  version "5.4.0"
+  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54"
+  integrity sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==
+  dependencies:
+    has-flag "^3.0.0"
+
+supports-color@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
+  integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=
+
+supports-color@^3.1.2:
+  version "3.2.3"
+  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6"
+  integrity sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=
+  dependencies:
+    has-flag "^1.0.0"
+
+supports-color@^5.3.0:
+  version "5.5.0"
+  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
+  integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
+  dependencies:
+    has-flag "^3.0.0"
+
+through@2:
+  version "2.3.8"
+  resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
+  integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=
+
+to-fast-properties@^1.0.3:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47"
+  integrity sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=
+
+trim-right@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003"
+  integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=
+
+ts-node@^7.0.1:
+  version "7.0.1"
+  resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-7.0.1.tgz#9562dc2d1e6d248d24bc55f773e3f614337d9baf"
+  integrity sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw==
+  dependencies:
+    arrify "^1.0.0"
+    buffer-from "^1.1.0"
+    diff "^3.1.0"
+    make-error "^1.1.1"
+    minimist "^1.2.0"
+    mkdirp "^0.5.1"
+    source-map-support "^0.5.6"
+    yn "^2.0.0"
+
+tslib@^1.8.0, tslib@^1.8.1:
+  version "1.9.3"
+  resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286"
+  integrity sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==
+
+tslint@^5.13.1:
+  version "5.13.1"
+  resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.13.1.tgz#fbc0541c425647a33cd9108ce4fd4cd18d7904ed"
+  integrity sha512-fplQqb2miLbcPhyHoMV4FU9PtNRbgmm/zI5d3SZwwmJQM6V0eodju+hplpyfhLWpmwrDNfNYU57uYRb8s0zZoQ==
+  dependencies:
+    babel-code-frame "^6.22.0"
+    builtin-modules "^1.1.1"
+    chalk "^2.3.0"
+    commander "^2.12.1"
+    diff "^3.2.0"
+    glob "^7.1.1"
+    js-yaml "^3.7.0"
+    minimatch "^3.0.4"
+    mkdirp "^0.5.1"
+    resolve "^1.3.2"
+    semver "^5.3.0"
+    tslib "^1.8.0"
+    tsutils "^2.27.2"
+
+tsutils@^2.27.2:
+  version "2.29.0"
+  resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.29.0.tgz#32b488501467acbedd4b85498673a0812aca0b99"
+  integrity sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==
+  dependencies:
+    tslib "^1.8.1"
+
+type-detect@^4.0.0, type-detect@^4.0.5:
+  version "4.0.8"
+  resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c"
+  integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==
+
+type-is@~1.6.16:
+  version "1.6.16"
+  resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.16.tgz#f89ce341541c672b25ee7ae3c73dee3b2be50194"
+  integrity sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==
+  dependencies:
+    media-typer "0.3.0"
+    mime-types "~2.1.18"
+
+typedoc-default-themes@^0.5.0:
+  version "0.5.0"
+  resolved "https://registry.yarnpkg.com/typedoc-default-themes/-/typedoc-default-themes-0.5.0.tgz#6dc2433e78ed8bea8e887a3acde2f31785bd6227"
+  integrity sha1-bcJDPnjti+qOiHo6zeLzF4W9Yic=
+
+typedoc@^0.14.1:
+  version "0.14.2"
+  resolved "https://registry.yarnpkg.com/typedoc/-/typedoc-0.14.2.tgz#769f457f4f9e4bdb8b5f3b177c86b6a31d8c3dc3"
+  integrity sha512-aEbgJXV8/KqaVhcedT7xG6d2r+mOvB5ep3eIz1KuB5sc4fDYXcepEEMdU7XSqLFO5hVPu0nllHi1QxX2h/QlpQ==
+  dependencies:
+    "@types/fs-extra" "^5.0.3"
+    "@types/handlebars" "^4.0.38"
+    "@types/highlight.js" "^9.12.3"
+    "@types/lodash" "^4.14.110"
+    "@types/marked" "^0.4.0"
+    "@types/minimatch" "3.0.3"
+    "@types/shelljs" "^0.8.0"
+    fs-extra "^7.0.0"
+    handlebars "^4.0.6"
+    highlight.js "^9.13.1"
+    lodash "^4.17.10"
+    marked "^0.4.0"
+    minimatch "^3.0.0"
+    progress "^2.0.0"
+    shelljs "^0.8.2"
+    typedoc-default-themes "^0.5.0"
+    typescript "3.2.x"
+
+typescript@3.2.x:
+  version "3.2.4"
+  resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.2.4.tgz#c585cb952912263d915b462726ce244ba510ef3d"
+  integrity sha512-0RNDbSdEokBeEAkgNbxJ+BLwSManFy9TeXz8uW+48j/xhEXv1ePME60olyzw2XzUqUBNAYFeJadIqAgNqIACwg==
+
+typescript@^3.2.2:
+  version "3.3.3333"
+  resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.3.3333.tgz#171b2c5af66c59e9431199117a3bcadc66fdcfd6"
+  integrity sha512-JjSKsAfuHBE/fB2oZ8NxtRTk5iGcg6hkYXMnZ3Wc+b2RSqejEqTaem11mHASMnFilHrax3sLK0GDzcJrekZYLw==
+
+uglify-js@^3.1.4:
+  version "3.4.9"
+  resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.9.tgz#af02f180c1207d76432e473ed24a28f4a782bae3"
+  integrity sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q==
+  dependencies:
+    commander "~2.17.1"
+    source-map "~0.6.1"
+
+universalify@^0.1.0:
+  version "0.1.2"
+  resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
+  integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==
+
+unpipe@1.0.0, unpipe@~1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
+  integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=
+
+util-deprecate@~1.0.1:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
+  integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
+
+utils-merge@1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
+  integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=
+
+vary@~1.1.2:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
+  integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=
+
+which@^1.1.1:
+  version "1.3.1"
+  resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
+  integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==
+  dependencies:
+    isexe "^2.0.0"
+
+wordwrap@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb"
+  integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=
+
+wordwrap@~0.0.2:
+  version "0.0.3"
+  resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107"
+  integrity sha1-o9XabNXAvAAI03I0u68b7WMFkQc=
+
+wrappy@1:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
+  integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
+
+xtend@^4.0.0:
+  version "4.0.1"
+  resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"
+  integrity sha1-pcbVMr5lbiPbgg77lDofBJmNY68=
+
+yn@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/yn/-/yn-2.0.0.tgz#e5adabc8acf408f6385fc76495684c88e6af689a"
+  integrity sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=