text: /**
   * Licensed to the Apache Software Foundation (ASF) under one
   * or more contributor license agreements.  See the NOTICE file
   * distributed with this work for additional information
   * regarding copyright ownership.  The ASF licenses this file
   * to you under the Apache License, Version 2.0 (the
   * "License"); you may not use this file except in compliance
   * with the License.  You may obtain a copy of the License at
   *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  /**
   * Mapper for <code>App.SliderAppType</code> and <code>App.SliderAppComponent</code> models
   * For nested models:
   * <ul>
   *   <li>
   *     Define property (P1) started with '$' in <code>map</code> (example - $components).
   *   </li>
   *   <li>
   *     Define property componentsMap (P1 without '$' and with suffix 'Map').
   *     It is used as map for nested models
   *   </li>
   *   <li>
   *     Define property componentsParentField (P1 without '$' and with suffix 'ParentField').
   *     It  is used as property in nested model to link it with parent model
   *   </li>
   * </ul>
   * @type {App.Mapper}
   */
  App.ApplicationTypeMapper = App.Mapper.createWithMixins(App.RunPeriodically, {
  
    /**
     * Map for parsing JSON received from server
     * Format:
     *  <code>
     *    {
     *      key1: 'path1',
     *      key2: 'path2',
     *      key3: 'path3'
     *    }
     *  </code>
     *  Keys - names for properties in App
     *  Values - pathes in JSON
     * @type {object}
     */
    map: {
      id: 'id',
      configs: 'typeConfigs',
      displayName: 'typeName',
      index: 'id',
      description: 'typeDescription',
      version: 'typeVersion',
      /**
       * Map array to nested models
       * Use <code>('$components').replace('$', '') + 'Map'</code> property as map
       * Use <code>('$components').replace('$', '') + 'Model'</code> property as model to save data
       */
      $components: 'typeComponents'
    },
  
    /**
     * Map for <code>App.SliderAppTypeComponent</code>
     * @type {object}
     */
    componentsMap: {
      id: 'id',
      name: 'name',
      displayName: 'displayName',
      defaultNumInstances: 'instanceCount',
      defaultYARNMemory: 'yarnMemory',
      defaultYARNCPU: 'yarnCpuCores',
      priority: 'priority'
    },
  
    /**
     * Nested model name - <code>App.SliderAppTypeComponent</code>
     * @type {string}
     */
    componentsModel: 'sliderAppTypeComponent',
  
    /**
     * Field in <code>App.SliderAppTypeComponent</code> with parent model link
     * @type {string}
     */
    componentsParentField: 'appType',
  
    /**
     * Load data from <code>App.urlPrefix + this.urlSuffix</code> one time
     * @method load
     * @return {$.ajax}
     */
    load: function() {
      console.log('App.ApplicationTypeMapper loading data');
      return App.ajax.send({
        name: 'mapper.applicationTypes',
        sender: this,
        success: 'parse'
      });
    },
  
    /**
     * Parse loaded data according to <code>map</code>
     * Load <code>App.SliderAppType</code> models
     * @param {object} data received from server data
     * @method parse
     */
    parse: function(data) {
      var map = this.get('map'),
        app_types = [],
        self = this;
      data.items.forEach(function(app_type) {
        var model = {};
        Ember.keys(map).forEach(function(key) {
          // Property should be parsed as array of nested models
          if ('$' == key[0]) {
            var k = key.replace('$', '');
            var components = self.parseNested(Ember.get(app_type, map[key]), k, app_type.id);
            // save nested models and then link them with parent model
            App.SliderApp.store.pushMany(self.get(k + 'Model'), components);
            Ember.set(model, k, components.mapProperty('id'));
          }
          else {
            Ember.set(model, key, Ember.getWithDefault(app_type, map[key], ''));
          }
        });
        app_types.pushObject(model);
      });
      App.SliderApp.store.pushMany('sliderAppType', app_types);
    },
  
    /**
     * Parse array of objects as list of nested models
     * @param {object[]} data data to parse
     * @param {string} k property name
     * @param {string} parentId parent model's id
     * @return {object[]} mapped models
     * @method parseNested
     */
    parseNested: function(data, k, parentId) {
      var models = [],
        map = this.get(k + 'Map'),
        parentField = this.get(k + 'ParentField');
      data.forEach(function(item) {
        var model = {id: item.id};
        model[parentField] = parentId; // link to parent model
        Ember.keys(map).forEach(function(key) {
          Ember.set(model, key, Ember.getWithDefault(item, map[key], ''));
        });
        models.pushObject(model);
      });
      return models;
    }
  
  });
  