[CORD-873] CRUD for Core and Service model from Chameleon
Change-Id: I45c533feba6720b82de3681d862773047e7fd6f8
diff --git a/src/app/core/form/form.html b/src/app/core/form/form.html
index 4c7485a..5da8c4e 100644
--- a/src/app/core/form/form.html
+++ b/src/app/core/form/form.html
@@ -1,3 +1,4 @@
+<!--<pre>{{vm.config.inputs | json}}</pre>-->
 <form name="vm.{{vm.config.formName || 'form'}}" novalidate>
     <!--<div class="form-group" ng-repeat="(name, field) in vm.formField">-->
         <!--<xos-field name="name" field="field" ng-model="vm.ngModel[name]"></xos-field>-->
diff --git a/src/app/core/form/form.ts b/src/app/core/form/form.ts
index c0bd206..9de27ea 100644
--- a/src/app/core/form/form.ts
+++ b/src/app/core/form/form.ts
@@ -44,7 +44,7 @@
   options?: IXosFormInputOptions[];
 }
 
-export interface IXosFormConfig {
+export interface IXosFormCfg {
   exclude?: string[];
   actions: IXosFormAction[];
   feedback?: IXosFeedback;
diff --git a/src/app/core/header/header.spec.ts b/src/app/core/header/header.spec.ts
index c1d6062..73ba587 100644
--- a/src/app/core/header/header.spec.ts
+++ b/src/app/core/header/header.spec.ts
@@ -55,7 +55,7 @@
       .value('toastr', MockToastr)
       .value('toastrConfig', MockToastrConfig)
       .value('AuthService', MockAuth)
-      .value('NavigationService', {})
+      .value('XosNavigationService', {})
       .value('XosKeyboardShortcut', MockXosKeyboardShortcut)
       .value('StyleConfig', {
         logo: 'cord-logo.png',
diff --git a/src/app/core/header/header.ts b/src/app/core/header/header.ts
index 8926080..62e3ce9 100644
--- a/src/app/core/header/header.ts
+++ b/src/app/core/header/header.ts
@@ -14,7 +14,7 @@
 }
 
 class HeaderController {
-  static $inject = ['$scope', '$rootScope', '$state', 'AuthService', 'SynchronizerStore', 'toastr', 'toastrConfig', 'NavigationService', 'StyleConfig', 'SearchService', 'XosKeyboardShortcut'];
+  static $inject = ['$scope', '$rootScope', '$state', 'AuthService', 'SynchronizerStore', 'toastr', 'toastrConfig', 'XosNavigationService', 'StyleConfig', 'SearchService', 'XosKeyboardShortcut'];
   public notifications: INotification[] = [];
   public newNotifications: INotification[] = [];
   public version: string;
diff --git a/src/app/core/index.ts b/src/app/core/index.ts
index 318ffeb..d275a9f 100644
--- a/src/app/core/index.ts
+++ b/src/app/core/index.ts
@@ -4,8 +4,8 @@
 import routesConfig from './routes';
 import {xosLogin} from './login/login';
 import {xosTable} from './table/table';
-import {RuntimeStates} from './services/runtime-states';
-import {NavigationService} from './services/navigation';
+import {XosRuntimeStates} from './services/runtime-states';
+import {IXosNavigationService} from './services/navigation';
 import {PageTitle} from './services/page-title';
 import {ConfigHelpers} from './services/helpers/config.helpers';
 import {xosLinkWrapper} from './link-wrapper/link-wrapper';
@@ -15,7 +15,6 @@
 import 'angular-toastr';
 import {xosAlert} from './alert/alert';
 import {xosValidation} from './validation/validation';
-import {ModelSetup} from './services/helpers/model-setup.helpers';
 import {xosSidePanel} from './side-panel/side-panel';
 import {XosSidePanel} from './side-panel/side-panel.service';
 import {XosComponentInjector} from './services/helpers/component-injector.helpers';
@@ -33,12 +32,11 @@
     'ui.bootstrap.typeahead'
   ])
   .config(routesConfig)
-  .provider('RuntimeStates', RuntimeStates)
-  .service('NavigationService', NavigationService)
+  .provider('XosRuntimeStates', XosRuntimeStates)
+  .service('XosNavigationService', IXosNavigationService)
   .service('PageTitle', PageTitle)
   .service('XosFormHelpers', XosFormHelpers)
   .service('ConfigHelpers', ConfigHelpers)
-  .service('ModelSetup', ModelSetup)
   .service('XosSidePanel', XosSidePanel)
   .service('XosKeyboardShortcut', XosKeyboardShortcut)
   .service('XosComponentInjector', XosComponentInjector)
diff --git a/src/app/core/login/login.ts b/src/app/core/login/login.ts
index 673d9a8..183980a 100644
--- a/src/app/core/login/login.ts
+++ b/src/app/core/login/login.ts
@@ -1,18 +1,19 @@
 import {AuthService} from '../../datasources/rest/auth.rest';
 import './login.scss';
-import {IXosModelSetupService} from '../services/helpers/model-setup.helpers';
+
 import {IXosStyleConfig} from '../../../index';
+import {IXosModelDiscovererService} from '../../datasources/helpers/model-discoverer.service';
 
 class LoginCtrl {
-  static $inject = ['$log', 'AuthService', '$state', 'ModelSetup', 'StyleConfig'];
+  static $inject = ['$log', 'AuthService', '$state', 'XosModelDiscoverer', 'StyleConfig'];
   public loginStyle: any;
   public img: string;
-  /** @ngInject */
+
   constructor(
     private $log: ng.ILogService,
     private authService: AuthService,
     private $state: angular.ui.IStateService,
-    private ModelSetup: IXosModelSetupService,
+    private XosModelDiscoverer: IXosModelDiscovererService,
     private StyleConfig: IXosStyleConfig
   ) {
 
@@ -34,7 +35,7 @@
     })
       .then(res => {
         // after login set up models
-        return this.ModelSetup.setup();
+        return this.XosModelDiscoverer.discover();
       })
       .then(() => {
         this.$state.go('xos.dashboard');
diff --git a/src/app/core/nav/nav.spec.ts b/src/app/core/nav/nav.spec.ts
index 5101ba8..1d41f4b 100644
--- a/src/app/core/nav/nav.spec.ts
+++ b/src/app/core/nav/nav.spec.ts
@@ -29,7 +29,7 @@
     angular
       .module('xosNav', ['app/core/nav/nav.html', 'ui.router'])
       .component('xosNav', xosNav)
-      .service('NavigationService', NavigationService)
+      .service('XosNavigationService', NavigationService)
       .value('AuthService', AuthMock)
       .value('StyleConfig', {})
       .value('XosSidePanel', {})
diff --git a/src/app/core/nav/nav.ts b/src/app/core/nav/nav.ts
index 08ad48a..f537e5e 100644
--- a/src/app/core/nav/nav.ts
+++ b/src/app/core/nav/nav.ts
@@ -6,7 +6,7 @@
 import {IXosComponentInjectorService} from '../services/helpers/component-injector.helpers';
 
 class NavCtrl {
-  static $inject = ['$scope', '$state', 'NavigationService', 'AuthService', 'StyleConfig', 'XosSidePanel', 'XosComponentInjector'];
+  static $inject = ['$scope', '$state', 'XosNavigationService', 'AuthService', 'StyleConfig', 'XosSidePanel', 'XosComponentInjector'];
   public routes: IXosNavigationRoute[];
   public navSelected: string;
   public appName: string;
diff --git a/src/app/core/services/helpers/config.helpers.spec.ts b/src/app/core/services/helpers/config.helpers.spec.ts
index 3e90d33..ed41228 100644
--- a/src/app/core/services/helpers/config.helpers.spec.ts
+++ b/src/app/core/services/helpers/config.helpers.spec.ts
@@ -3,47 +3,60 @@
 import 'angular-ui-router';
 
 import {IXosConfigHelpersService, ConfigHelpers, IXosModelDefsField} from './config.helpers';
-import {IModeldef} from '../../../datasources/rest/modeldefs.rest';
+import {IXosModeldef} from '../../../datasources/rest/modeldefs.rest';
 import {IXosTableCfg} from '../../table/table';
-import {IXosFormInput, IXosFormConfig} from '../../form/form';
+import {IXosFormInput, IXosFormCfg} from '../../form/form';
 import {BehaviorSubject} from 'rxjs';
 
 let service: IXosConfigHelpersService;
 
-const model: IModeldef = {
+const model: IXosModeldef = {
   name: 'Test',
+  app: 'test',
   fields: [
     {
       type: 'number',
       name: 'id',
-      validators: {}
+      validators: []
     },
     {
       type: 'string',
       name: 'name',
-      validators: {
-        required: true
-      }
+      validators: [
+        {
+          bool_value: true,
+          name: 'required'
+        }
+      ]
     },
     {
       type: 'string',
       name: 'something',
-      validators: {
-        maxlength: 30
-      }
+      validators: [
+        {
+          int_value: 30,
+          name: 'maxlength'
+        }
+      ]
     },
     {
       type: 'number',
       name: 'else',
-      validators: {
-        min: 20,
-        max: 40
-      }
+      validators: [
+        {
+          int_value: 20,
+          name: 'min'
+        },
+        {
+          int_value: 40,
+          name: 'max'
+        }
+      ]
     },
     {
       type: 'date',
       name: 'updated',
-      validators: {}
+      validators: []
     },
   ]
 };
@@ -59,7 +72,7 @@
           return {id: 1};
         }
       })
-      .value('ModelStore', {
+      .value('XosModelStore', {
 
       })
       .value('$state', {
@@ -131,11 +144,6 @@
   });
 
   describe('the navigation methods', () => {
-    describe('urlFromCoreModels', () => {
-      it('should return the URL for a given model', () => {
-        expect(service.urlFromCoreModel('Test')).toBe('/core/tests');
-      });
-    });
     describe('stateFromCoreModels', () => {
 
       let state: ng.ui.IStateService;
@@ -156,7 +164,7 @@
 
   describe('the modelFieldsToColumnsCfg method', () => {
     it('should return an array of columns', () => {
-      const cols = service.modelFieldsToColumnsCfg(model.fields, 'testUrl/:id?');
+      const cols = service.modelFieldsToColumnsCfg({fields: model.fields, name: 'testUrl', app: 'test'});
       expect(cols[0].label).toBe('Id');
       expect(cols[0].prop).toBe('id');
       expect(cols[0].link).toBeDefined();
@@ -214,7 +222,7 @@
 
   describe('the modelToFormCfg method', () => {
     it('should return a form config', () => {
-      const config: IXosFormConfig = service.modelToFormCfg(model);
+      const config: IXosFormCfg = service.modelToFormCfg(model);
       expect(config.formName).toBe('TestForm');
       expect(config.actions.length).toBe(1);
       expect(config.actions[0].label).toBe('Save');
diff --git a/src/app/core/services/helpers/config.helpers.ts b/src/app/core/services/helpers/config.helpers.ts
index 28a16a3..2ac9394 100644
--- a/src/app/core/services/helpers/config.helpers.ts
+++ b/src/app/core/services/helpers/config.helpers.ts
@@ -1,16 +1,22 @@
 import * as _ from 'lodash';
 import * as pluralize from 'pluralize';
 import {IXosTableColumn, IXosTableCfg} from '../../table/table';
-import {IModeldef} from '../../../datasources/rest/modeldefs.rest';
-import {IXosFormConfig, IXosFormInput} from '../../form/form';
+import {IXosModeldef} from '../../../datasources/rest/modeldefs.rest';
+import {IXosFormCfg, IXosFormInput, IXosFormInputValidator} from '../../form/form';
 import {IXosAuthService} from '../../../datasources/rest/auth.rest';
 import {IXosModelStoreService} from '../../../datasources/stores/model.store';
-import {IXosState} from '../../../../index';
+import {IXosState} from '../runtime-states';
+
+export interface IXosModelDefsFieldValidators {
+  name: string;
+  bool_value?: boolean;
+  int_value?: number;
+}
 
 export interface IXosModelDefsField {
   name: string;
   type: string;
-  validators?: any;
+  validators?: IXosModelDefsFieldValidators[];
   hint?: string;
   relation?: {
     model: string;
@@ -20,23 +26,26 @@
 
 export interface IXosConfigHelpersService {
   excluded_fields: string[];
-  modelFieldsToColumnsCfg(fields: IXosModelDefsField[], baseUrl: string): IXosTableColumn[]; // TODO use a proper interface
-  modelToTableCfg(model: IModeldef, modelName: string): IXosTableCfg;
+  modelFieldsToColumnsCfg(model: IXosModeldef): IXosTableColumn[];
+  modelToTableCfg(model: IXosModeldef, modelName: string): IXosTableCfg;
   modelFieldToInputCfg(fields: IXosModelDefsField[]): IXosFormInput[];
-  modelToFormCfg(model: IModeldef): IXosFormConfig;
+  modelToFormCfg(model: IXosModeldef): IXosFormCfg;
   pluralize(string: string, quantity?: number, count?: boolean): string;
   toLabel(string: string, pluralize?: boolean): string;
   toLabels(string: string[], pluralize?: boolean): string[];
-  urlFromCoreModel(model: string): string;
   stateFromCoreModel(name: string): string;
   stateWithParams(name: string, model: any): string;
   stateWithParamsForJs(name: string, model: any): any;
 }
 
 export class ConfigHelpers implements IXosConfigHelpersService {
-  static $inject = ['$state', 'toastr', 'AuthService', 'ModelStore'];
+  static $inject = [
+    '$state',
+    'toastr',
+    'AuthService',
+    'XosModelStore'];
 
-  excluded_fields = [
+  public excluded_fields = [
     'created',
     'updated',
     'enacted',
@@ -59,11 +68,15 @@
     private $state: ng.ui.IStateService,
     private toastr: ng.toastr.IToastrService,
     private AuthService: IXosAuthService,
-    private ModelStore: IXosModelStoreService
+    private XosModelStore: IXosModelStoreService
   ) {
     pluralize.addIrregularRule('xos', 'xoses');
     pluralize.addPluralRule(/slice$/i, 'slices');
     pluralize.addSingularRule(/slice$/i, 'slice');
+    pluralize.addPluralRule(/library$/i, 'librarys');
+    pluralize.addPluralRule(/imagedeployments/i, 'imagedeploymentses');
+    pluralize.addPluralRule(/controllerimages/i, 'controllerimageses');
+
   }
 
   public pluralize(string: string, quantity?: number, count?: boolean): string {
@@ -91,9 +104,9 @@
     return this.capitalizeFirst(string);
   }
 
-  public modelToTableCfg(model: IModeldef, baseUrl: string): IXosTableCfg {
+  public modelToTableCfg(model: IXosModeldef, baseUrl: string): IXosTableCfg {
     const cfg = {
-      columns: this.modelFieldsToColumnsCfg(model.fields, model.name),
+      columns: this.modelFieldsToColumnsCfg(model),
       filter: 'fulltext',
       order: {field: 'id', reverse: false},
       pagination: {
@@ -125,10 +138,11 @@
     return cfg;
   }
 
-  public modelFieldsToColumnsCfg(fields: IXosModelDefsField[], modelName: string): IXosTableColumn[] {
-
+  public modelFieldsToColumnsCfg(model: IXosModeldef): IXosTableColumn[] {
+    const fields: IXosModelDefsField[] = model.fields;
+    const modelName: string = model.name;
     const columns =  _.map(fields, (f) => {
-      if (this.excluded_fields.indexOf(f.name) > -1) {
+      if (!angular.isDefined(f) || this.excluded_fields.indexOf(f.name) > -1) {
         return;
       }
       const col: IXosTableColumn =  {
@@ -147,7 +161,9 @@
           this.populateRelated(item, item[f.name], f);
           return item[f.name];
         };
-        col.link = item => this.stateWithParams(f.relation.model, item);
+        col.link = item => {
+          return this.stateWithParams(f.relation.model, item);
+        };
       }
 
       if (f.name === 'backend_status') {
@@ -175,11 +191,6 @@
     return columns;
   };
 
-  public urlFromCoreModel(name: string): string {
-
-    return `/core/${this.pluralize(name.toLowerCase())}`;
-  }
-
   public stateFromCoreModel(name: string): string {
     const state: ng.ui.IState = _.find(this.$state.get(), (s: IXosState) => {
       if (s.data) {
@@ -187,7 +198,7 @@
       }
       return false;
     });
-    return state.name;
+    return state ? state.name : null;
   }
 
   public stateWithParams(name: string, model: any): string {
@@ -204,32 +215,27 @@
   public modelFieldToInputCfg(fields: IXosModelDefsField[]): IXosFormInput[] {
 
     return _.map(fields, (f: IXosModelDefsField) => {
-      if (f.relation) {
-        const input: IXosFormInput = {
-          name: f.name,
-          label: this.toLabel(f.name),
-          type: 'select',
-          validators: f.validators,
-          hint: f.hint
-        };
-        this.populateSelectField(f, input);
-        return input;
-      }
-
-      return {
+      const input: IXosFormInput = {
         name: f.name,
         label: this.toLabel(f.name),
         type: f.type,
-        validators: f.validators
+        validators: this.formatValidators(f.validators),
+        hint: f.hint
       };
+      if (f.relation) {
+        input.type = 'select';
+        this.populateSelectField(f, input);
+        return input;
+      }
+      return input;
     })
       .filter(f => this.excluded_fields.indexOf(f.name) === -1);
   }
 
-  public modelToFormCfg(model: IModeldef): IXosFormConfig {
-    const formCfg: IXosFormConfig = {
+  public modelToFormCfg(model: IXosModeldef): IXosFormCfg {
+    const formCfg: IXosFormCfg = {
       formName: `${model.name}Form`,
-      exclude: ['backend_status', 'creator'],
+      exclude: ['backend_status', 'creator', 'id'],
       actions: [{
         label: 'Save',
         class: 'success',
@@ -258,12 +264,19 @@
       delete item.networks;
 
       // adding userId as creator
-      item.creator = this.AuthService.getUser().id;
+      // item.creator = this.AuthService.getUser().id;
+
+      // remove field added by xosTable
+      _.forEach(Object.keys(item), prop => {
+        if (prop.indexOf('-formatted') > -1) {
+          delete item[prop];
+        }
+      });
 
       item.$save()
         .then((res) => {
           if (res.status === 403 || res.status === 405 || res.status === 500) {
-            // TODO understand why 405 does not go directly in catch (it may be realted to ng-rest-gw)
+            // TODO understand why 405 does not go directly in catch (it may be related to ng-rest-gw)
             throw new Error();
           }
           formCfg.feedback = {
@@ -283,6 +296,15 @@
     return formCfg;
   }
 
+  private formatValidators(validators: IXosModelDefsFieldValidators[]): IXosFormInputValidator {
+    // convert validators as expressed from modelDefs,
+    // to the object required by xosForm
+    return _.reduce(validators, (formValidators: IXosFormInputValidator, v: IXosModelDefsFieldValidators) => {
+      formValidators[v.name] = v.bool_value ? v.bool_value : v.int_value;
+      return formValidators;
+    }, {});
+  }
+
   private fromCamelCase(string: string): string {
     return string.split(/(?=[A-Z])/).map(w => w.toLowerCase()).join(' ');
   }
@@ -304,12 +326,20 @@
     if (!fk || angular.isUndefined(fk) || fk === null) {
       return;
     }
-    this.ModelStore.query(field.relation.model)
+    this.XosModelStore.query(field.relation.model)
       .subscribe(res => {
         if (angular.isDefined(res) && angular.isDefined(fk)) {
           let ri = _.find(res, {id: fk});
           if (angular.isDefined(ri)) {
-            item[`${field.name}-formatted`] = angular.isDefined(ri.name) ? ri.name : ri.humanReadableName;
+            if (angular.isDefined(ri.name)) {
+              item[`${field.name}-formatted`] = ri.name;
+            }
+            else if (angular.isDefined(ri.humanReadableName)) {
+              item[`${field.name}-formatted`] = ri.humanReadableName;
+            }
+            else {
+              item[`${field.name}-formatted`] = ri.id;
+            }
           }
         }
       });
@@ -317,10 +347,14 @@
 
   // augment a select field with related model informations
   private populateSelectField(field: IXosModelDefsField, input: IXosFormInput): void {
-    this.ModelStore.query(field.relation.model)
+    this.XosModelStore.query(field.relation.model)
       .subscribe(res => {
         input.options = _.map(res, item => {
-          return {id: item.id, label: item.humanReadableName ? item.humanReadableName : item.name};
+          let opt = {id: item.id, label: item.humanReadableName ? item.humanReadableName : item.name};
+          if (!angular.isDefined(item.humanReadableName) && !angular.isDefined(item.name)) {
+            opt.label = item.id;
+          }
+          return opt;
         });
       });
   }
diff --git a/src/app/core/services/helpers/model-setup.helpers.ts b/src/app/core/services/helpers/model-setup.helpers.ts
deleted file mode 100644
index e79899d..0000000
--- a/src/app/core/services/helpers/model-setup.helpers.ts
+++ /dev/null
@@ -1,63 +0,0 @@
-import {ModeldefsService, IModeldef} from '../../../datasources/rest/modeldefs.rest';
-import {IXosConfigHelpersService} from './config.helpers';
-import {IRuntimeStatesService} from '../runtime-states';
-import {NavigationService} from '../navigation';
-import {IXosState} from '../../../../index';
-import * as _ from 'lodash';
-import IPromise = angular.IPromise;
-
-export interface IXosModelSetupService {
-  setup(): IPromise<null>;
-}
-
-export class ModelSetup {
-  static $inject = ['$rootScope', '$q', 'ModelDefs', 'ConfigHelpers', 'RuntimeStates', 'NavigationService'];
-
-  constructor(
-    private $rootScope: ng.IScope,
-    private $q: ng.IQService,
-    private ModelDefs: ModeldefsService,
-    private ConfigHelpers: IXosConfigHelpersService,
-    private RuntimeStates: IRuntimeStatesService,
-    private NavigationService: NavigationService
-  ) {
-
-  }
-
-  public setup(): IPromise<null> {
-    const d = this.$q.defer();
-    this.ModelDefs.get()
-      .then((models: IModeldef[]) => {
-        _.forEach(models, (m: IModeldef) => {
-          const stateUrl = `/${this.ConfigHelpers.pluralize(m.name.toLowerCase())}/:id?`;
-          const stateName = `xos.core.${this.ConfigHelpers.pluralize(m.name.toLowerCase())}`;
-          const state: IXosState = {
-            parent: 'core',
-            url: stateUrl,
-            component: 'xosCrud',
-            params: {
-              id: null
-            },
-            data: {
-              model: m.name,
-              related: m.relations,
-              xosTableCfg: this.ConfigHelpers.modelToTableCfg(m, stateUrl),
-              xosFormCfg: this.ConfigHelpers.modelToFormCfg(m)
-            }
-          };
-
-          this.RuntimeStates.addState(stateName, state);
-          this.NavigationService.add({
-            label: this.ConfigHelpers.pluralize(m.name),
-            state: stateName,
-            parent: 'xos.core'
-          });
-        });
-
-        d.resolve();
-      })
-      .catch(d.reject);
-
-    return d.promise;
-  }
-}
diff --git a/src/app/core/services/navigation.spec.ts b/src/app/core/services/navigation.spec.ts
index fbfb91c..82a235e 100644
--- a/src/app/core/services/navigation.spec.ts
+++ b/src/app/core/services/navigation.spec.ts
@@ -35,10 +35,10 @@
   });
 
   beforeEach(angular.mock.inject((
-    NavigationService: IXosNavigationService,
+    XosNavigationService: IXosNavigationService,
     _$log_: ng.ILogService
   ) => {
-    service = NavigationService;
+    service = XosNavigationService;
     $log = _$log_;
     spyOn($log, 'warn');
     defaultRoutes = [
diff --git a/src/app/core/services/navigation.ts b/src/app/core/services/navigation.ts
index e35c9f8..9869b5a 100644
--- a/src/app/core/services/navigation.ts
+++ b/src/app/core/services/navigation.ts
@@ -17,7 +17,9 @@
   add(route: IXosNavigationRoute): void;
 }
 
-export class NavigationService {
+// TODO support 3rd level to group service model under "Services"
+
+export class IXosNavigationService {
   static $inject = ['$log', 'StyleConfig'];
   private routes: IXosNavigationRoute[];
 
@@ -34,6 +36,10 @@
         label: 'Core',
         state: 'xos.core'
       },
+      // {
+      //   label: 'Service',
+      //   state: 'xos.services'
+      // },
     ];
     // adding configuration defined routes
     // this.routes = StyleConfig.routes.concat(defaultRoutes).reverse();
@@ -64,16 +70,20 @@
       return;
     }
 
-
     if (angular.isDefined(route.parent)) {
       // route parent should be a state for now
       const parentRoute = _.find(this.routes, {state: route.parent});
-
-      if (angular.isArray(parentRoute.children)) {
-        parentRoute.children.push(route);
+      if (angular.isDefined(parentRoute)) {
+        if (angular.isArray(parentRoute.children)) {
+          parentRoute.children.push(route);
+        }
+        else {
+          parentRoute.children = [route];
+        }
       }
       else {
-        parentRoute.children = [route];
+        this.$log.warn(`[XosNavigation] Parent State (${route.parent}) for state: ${route.state} does not exists`);
+        return;
       }
     }
     else {
diff --git a/src/app/core/services/runtime-states.spec.ts b/src/app/core/services/runtime-states.spec.ts
index 5dd44db..8b9015d 100644
--- a/src/app/core/services/runtime-states.spec.ts
+++ b/src/app/core/services/runtime-states.spec.ts
@@ -2,19 +2,19 @@
 import 'angular-mocks';
 import 'angular-ui-router';
 import {xosCore} from '../index';
-import {IRuntimeStatesService} from './runtime-states';
+import {IXosRuntimeStatesService} from './runtime-states';
 
-let service: IRuntimeStatesService, $state: ng.ui.IStateService;
+let service: IXosRuntimeStatesService, $state: ng.ui.IStateService;
 
 describe('The Navigation service', () => {
 
   beforeEach(angular.mock.module(xosCore));
 
   beforeEach(angular.mock.inject((
-    RuntimeStates: IRuntimeStatesService,
+    XosRuntimeStates: IXosRuntimeStatesService,
     _$state_: ng.ui.IStateService
   ) => {
-    service = RuntimeStates;
+    service = XosRuntimeStates;
     $state = _$state_;
   }));
 
diff --git a/src/app/core/services/runtime-states.ts b/src/app/core/services/runtime-states.ts
index 652b554..1f495ba 100644
--- a/src/app/core/services/runtime-states.ts
+++ b/src/app/core/services/runtime-states.ts
@@ -1,9 +1,14 @@
-import {IXosState} from '../../../index';
-export interface IRuntimeStatesService {
+export interface IXosState extends angular.ui.IState {
+  data: {
+    model: string
+  };
+};
+
+export interface IXosRuntimeStatesService {
   addState(name: string, state: ng.ui.IState): void;
 }
 
-export function RuntimeStates($stateProvider: ng.ui.IStateProvider): ng.IServiceProvider {
+export function XosRuntimeStates($stateProvider: ng.ui.IStateProvider): ng.IServiceProvider {
   this.$get = function($state: ng.ui.IStateService) {
     return {
       addState: function(name: string, state: IXosState) {