    /**
     * @author Ed Spencer
     *
     * Ext.app.Application defines the set of {@link Ext.data.Model Models}, {@link Ext.app.Controller Controllers},
     * {@link Ext.app.Profile Profiles}, {@link Ext.data.Store Stores} and {@link Ext.Component Views} that an application
     * consists of. It automatically loads all of those dependencies and can optionally specify a {@link #launch} function
     * that will be called when everthing is ready.
     *
     * Sample usage:
     *
     *     Ext.application({
     *         name: 'MyApp',
     *
     *         models: ['User', 'Group'],
     *         stores: ['Users'],
     *         controllers: ['Users'],
     *         views: ['Main', 'ShowUser'],
     *
     *         launch: function() {
     *             Ext.create('MyApp.view.Main');
     *         }
     *     });
     *
     * Creating an Application instance is the only time in Sencha Touch 2 that we don't use Ext.create to create the new
     * instance. Instead, the {@link Ext#application} function instantiates an Ext.app.Application internally,
     * automatically loading the Ext.app.Application class if it is not present on the page already and hooking in to
     * {@link Ext#onReady} before creating the instance itself. An alternative is to use Ext.create inside an Ext.onReady
     * callback, but Ext.application is preferred.
     *
     * ## Dependencies
     *
     * Application follows a simple convention when it comes to specifying the controllers, views, models, stores and
     * profiles it requires. By default it expects each of them to be found inside the *app/controller*, *app/view*,
     * *app/model*, *app/store* and *app/profile* directories in your app - if you follow this convention you can just
     * specify the last part of each class name and Application will figure out the rest for you:
     *
     *     Ext.application({
     *         name: 'MyApp',
     *
     *         controllers: ['Users'],
     *         models: ['User', 'Group'],
     *         stores: ['Users'],
     *         views: ['Main', 'ShowUser']
     *     });
     *
     * The example above will load 6 files:
     *
     * * app/model/User.js
     * * app/model/Group.js
     * * app/store/Users.js
     * * app/controller/Users.js
     * * app/view/Main.js
     * * app/view/ShowUser.js
     *
     * ### Nested Dependencies
     *
     * For larger apps it's common to split the models, views and controllers into subfolders so keep the project
     * organized. This is especially true of views - it's not unheard of for large apps to have over a hundred separate
     * view classes so organizing them into folders can make maintenance much simpler.
     *
     * To specify dependencies in subfolders just use a period (".") to specify the folder:
     *
     *     Ext.application({
     *         name: 'MyApp',
     *
     *         controllers: ['Users', 'nested.MyController'],
     *         views: ['products.Show', 'products.Edit', 'user.Login']
     *     });
     *
     * In this case these 5 files will be loaded:
     *
     * * app/controller/Users.js
     * * app/controller/nested/MyController.js
     * * app/view/products/Show.js
     * * app/view/products/Edit.js
     * * app/view/user/Login.js
     *
     * Note that we can mix and match within each configuration here - for each model, view, controller, profile or store
     * you can specify either just the final part of the class name (if you follow the directory conventions), or the full
     * class name.
     *
     * ### External Dependencies
     *
     * Finally, we can specify application dependencies from outside our application by fully-qualifying the classes we
     * want to load. A common use case for this is sharing authentication logic between multiple applications. Perhaps you
     * have several apps that login via a common user database and you want to share that code between them. An easy way to
     * do this is to create a folder alongside your app folder and then add its contents as dependencies for your app.
     *
     * For example, let's say our shared login code contains a login controller, a user model and a login form view. We
     * want to use all of these in our application:
     *
     *     Ext.application({
     *         views: ['Auth.view.LoginForm', 'Welcome'],
     *         controllers: ['Auth.controller.Sessions', 'Main'],
     *         models: ['Auth.model.User']
     *     });
     *
     * This will load the following files:
     *
     * * Auth/view/LoginForm.js
     * * Auth/controller/Sessions.js
     * * Auth/model/User.js
     * * app/view/Welcome.js
     * * app/controller/Main.js
     *
     * The first three were loaded from outside our application, the last two from the application itself. Note how we can
     * still mix and match application files and external dependency files.
     *
     * You may be wondering how the framework understands what is a nested local dependency (like 'products.Edit' above)
     * and what is an external dependency (like 'Auth.view.LoginForm'). All it does here is look at the first letter of
     * each dependency. If it's lower case, it's treated as a nested local dependency and loaded from within the **app**
     * folder. If it's upper case, it's treated as an external dependency and not part of your application's namespace.
     *
     * This follows the simple convention that top-level namespaces should always start with a capital letter (e.g. "MyApp"
     * vs "myapp"), and that packages within a top-level namespace should always be lower case (e.g. "MyApp.views" vs
     * "MyApp.Views"). If the external dependencies are not honoring this convention (e.g. the 'Auth' namespace was 'auth'
     * instead) then you will need to just use Ext.require to load the dependencies manually.
     *
     * ## Launching
     *
     * The final item in the example above is a launch function. This is called as soon as all of the dependencies have
     * been loaded and the Controllers instantiated. Usually this function is used to create the initial UI of your
     * application, check authentication or initialize any other application-launching behavior.
     *
     * ## Adding to Home Screen
     *
     * iOS devices allow your users to add your app to their home screen for easy access. iOS allows you to customize
     * several aspects of this, including the icon that will appear on the home screen and the startup image. These can be
     * specified in the Ext.application setup block:
     *
     *     Ext.application({
     *         name: 'MyApp',
     *
     *         {@link #icon}: 'resources/img/icon.png',
     *         {@link #glossOnIcon}: false,
     *         {@link #phoneStartupScreen}: 'resources/img/phone_startup.png',
     *         {@link #tabletStartupScreen}: 'resources/img/tablet_startup.png'
     *     });
     *
     * When the user adds your app to the home screen, your resources/img/icon.png file will be used as the application
     * icon. We also used the {@link #glossOnIcon} configuration to turn off the gloss effect that is automatically added
     * to icons in iOS. Finally we used the {@link #phoneStartupScreen} and {@link #tabletStartupScreen} configurations to
     * provide the images that will be displayed while your application is starting up. See also {@link #phoneIcon},
     * {@link #tabletIcon} and {@link #statusBarStyle}.
     *
     * ## Find out more
     *
     * If you are not already familiar with writing applications with Sencha Touch 2 we recommend reading the
     * <a href="#!/guide/apps_intro">intro to applications</a> guide, which lays out the core principles of writing apps
     * with Sencha Touch 2.
     */
    Ext.define('Ext.app.Application', {
        extend: 'Ext.app.Controller',

        requires: [
            'Ext.app.History',
            'Ext.app.Profile',
            'Ext.app.Router',
            'Ext.app.Action'
        ],

        config: {
            /**
             * @cfg {String/Object} icon Path to the .png image file to use when your app is added to the home screen on an
             * iOS device. When passed in as a String, the same icon will be used for both phone and tablet devices. To set
             * different icons for tablets and phones see the {@link #tabletIcon} and {@link #phoneIcon} configs.
             * @accessor
             */

            /**
             * @cfg {String} tabletIcon Path to the .png image file to use when your app is added to the home screen on an
             * iOS **tablet** device (iPad).
             * @accessor
             */

            /**
             * @cfg {String} phoneIcon Path to the .png image file to use when your app is added to the home screen on an
             * iOS **phone** device (iPhone or iPod).
             * @accessor
             */

            /**
             * @cfg {Boolean} glossOnIcon If set to false, the 'gloss' effect added to home screen {@link #icon icons} on
             * iOS devices will be removed.
             * @accessor
             */

            /**
             * @cfg {String} statusBarStyle Allows you to set the style of the status bar when your app is added to the
             * home screen on iOS devices. Defaults to 'black'. Alternative is to set to 'black-translucent', which turns
             * the status bar semi-transparent and overlaps the app content. This is usually not a good option for web apps
             * @accessor
             */

            /**
             * @cfg {String} phoneStartupScreen Path to the .png image file that will be displayed while the app is
             * starting up once it has been added to the home screen of an iOS phone device (iPhone or iPod). This .png
             * file should be 320px wide and 460px high.
             * @accessor
             */

            /**
             * @cfg {String} tabletStartupScreen Path to the .png image file that will be displayed while the app is
             * starting up once it has been added to the home screen of an iOS tablet device (iPad). This .png file should
             * be 768px wide and 1004px high.
             * @accessor
             */

            /**
             * @cfg {Array} profiles The set of profiles to load for this Application. Each profile is expected to
             * exist inside the *app/profile* directory and define a class following the convention
             * AppName.profile.ProfileName. For example, in the code below, the classes *AppName.profile.Phone*
             * and *AppName.profile.Tablet* will be loaded. Note that we are able to specify
             * either the full class name (as with *AppName.profile.Tablet*) or just the final part of the class name
             * and leave Application to automatically prepend *AppName.profile.’* to each:
             *
             *     profiles: [
             *         'Phone',
             *         'AppName.profile.Tablet',
             *         'SomeCustomNamespace.profile.Desktop'
             *     ]
             * @accessor
             */
            profiles: [],

            /**
             * @cfg {Array} stores The set of stores to load for this Application. Each store is expected to
             * exist inside the *app/store* directory and define a class following the convention
             * AppName.store.StoreName. For example, in the code below, the *AppName.store.Users* class will be loaded.
             * Note that we are able to specify either the full class name (as with *AppName.store.Groups*) or just the
             * final part of the class name and leave Application to automatically prepend *AppName.store.’* to each:
             *
             *     stores: [
             *         'Users',
             *         'AppName.store.Groups',
             *         'SomeCustomNamespace.store.Orders'
             *     ]
             * @accessor
             */
            stores: [],

            /**
             * @cfg {Array} controllers The set of controllers to load for this Application. Each controller is expected to
             * exist inside the *app/controller* directory and define a class following the convention
             * AppName.controller.ControllerName. For example, in the code below, the classes *AppName.controller.Users*,
             * *AppName.controller.Groups* and *AppName.controller.Products* will be loaded. Note that we are able to specify
             * either the full class name (as with *AppName.controller.Products*) or just the final part of the class name
             * and leave Application to automatically prepend *AppName.controller.’* to each:
             *
             *     controllers: [
             *         'Users',
             *         'Groups',
             *         'AppName.controller.Products',
             *         'SomeCustomNamespace.controller.Orders'
             *     ]
             * @accessor
             */
            controllers: [],

            /**
             * @cfg {Array} models The set of models to load for this Application. Each model is expected to exist inside the
             * *app/model* directory and define a class following the convention AppName.model.ModelName. For example, in the
             * code below, the classes *AppName.model.User*, *AppName.model.Group* and *AppName.model.Product* will be loaded.
             * Note that we are able to specify either the full class name (as with *AppName.model.Product*) or just the
             * final part of the class name and leave Application to automatically prepend *AppName.model.* to each:
             *
             *     models: [
             *         'User',
             *         'Group',
             *         'AppName.model.Product',
             *         'SomeCustomNamespace.model.Order'
             *     ]
             * @accessor
             */
            models: [],

            /**
             * @cfg {Array} views The set of views to load for this Application. Each view is expected to exist inside the
             * *app/view* directory and define a class following the convention AppName.view.ViewName. For example, in the
             * code below, the classes *AppName.view.Users*, *AppName.view.Groups* and *AppName.view.Products* will be loaded.
             * Note that we are able to specify either the full class name (as with *AppName.view.Products*) or just the
             * final part of the class name and leave Application to automatically prepend *AppName.view.* to each:
             *
             *     views: [
             *         'Users',
             *         'Groups',
             *         'AppName.view.Products',
             *         'SomeCustomNamespace.view.Orders'
             *     ]
             * @accessor
             */
            views: [],

            /**
             * @cfg {Ext.app.History} history The global {@link Ext.app.History History} instance attached to this
             * Application. Read only
             * @accessor
             */
            history: {},

            /**
             * @cfg {String} name The name of the Application. This should be a single word without spaces or periods
             * because it is used as the Application's global namespace. All classes in your application should be
             * namespaced undef the Application's name - for example if your application name is 'MyApp', your classes
             * should be named 'MyApp.model.User', 'MyApp.controller.Users', 'MyApp.view.Main' etc
             * @accessor
             */
            name: null,

            /**
             * @cfg {String} appFolder The path to the directory which contains all application's classes.
             * This path will be registered via {@link Ext.Loader#setPath} for the namespace specified in the {@link #name name} config.
             * Defaults to 'app'
             * @accessor
             */
            appFolder : 'app',

            /**
             * @cfg {Ext.app.Router} router The global {@link Ext.app.Router Router} instance attached to this Application.
             * Read only.
             * @accessor
             */
            router: {},

            /**
             * @cfg
             * @private
             * Used internally as the collection of instantiated controllers. Use {@link #getController} instead
             * @accessor
             */
            controllerInstances: [],

            /**
             * @cfg
             * @private
             * Used internally as the collection of instantiated profiles
             * @accessor
             */
            profileInstances: [],

            /**
             * @cfg {Ext.app.Profile} currentProfile The {@link Ext.app.Profile Profile} that is currently active for the
             * Application. This is set once, automatically by the Application before launch. Read only.
             * @accessor
             */
            currentProfile: null,

            /**
             * @cfg {Function} launch An optional function that will be called when the Application is ready to be
             * launched. This is normally used to render any initial UI required by your application
             * @accessor
             */
            launch: Ext.emptyFn,

            /**
             * @private
             * @cfg {Boolean} enableLoader Private config to disable loading of Profiles at application construct time.
             * This is used by Sencha's unit test suite to test Application.js in isolation and is likely to be removed
             * in favor of a more pleasing solution by the time you use it.
             * @accessor
             */
            enableLoader: true
        },

        /**
         * @private
         * Cached regex for testing if a string contains a dot. Used internally by applyStores and similar
         * @property dotRe
         * @type RegExp
         */
        dotRe: /\./,

        /**
         * Constructs a new Application instance
         */
        constructor: function(config) {
            this.initConfig(config);

            //it's common to pass in functions to an application but because they are not predictable config names they
            //aren't ordinarily placed onto this so we need to do it manually
            for (var key in config) {
                this[key] = config[key];
            }

            // <deprecated product=touch since=2.0>
            if (config.autoCreateViewport) {
                console.log(
                    '[Ext.app.Application] autoCreateViewport has been deprecated in Sencha Touch 2. Please implement a ' +
                    'launch function on your Application instead and use Ext.create("MyApp.view.Main") to create your initial UI.'
                );
            }
            // </deprecated>

            if (this.getEnableLoader() !== false) {
                Ext.require(this.getProfiles(), this.onProfilesLoaded, this);
            }
        },

        /**
         * Dispatches a given {@link Ext.app.Action} to the relevant Controller instance. This is not usually called
         * directly by the developer, instead Sencha Touch's History support picks up on changes to the browser's url
         * and calls dispatch automatically.
         * @param {Ext.app.Action} action The action to dispatch
         * @param {Boolean} addToHistory True by default, sets the browser's url to the action's url
         */
        dispatch: function(action, addToHistory) {
            action = action || {};
            Ext.applyIf(action, {
                application: this
            });

            action = Ext.factory(action, Ext.app.Action);

            if (action) {
                var profile    = this.getCurrentProfile(),
                    profileNS  = profile ? profile.getNamespace() : undefined,
                    controller = this.getController(action.getController(), profileNS);

                if (controller) {
                    if (addToHistory !== false) {
                        this.getHistory().add(action, true);
                    }

                    controller.execute(action);
                }
            }
        },

        /**
         * Redirects the browser to the given url. This only affects the url after the #. You can pass in either a String
         * or a Model instance - if a Model instance is defined its {@link Ext.data.Model#toUrl toUrl} function is called,
         * which returns a string representing the url for that model. Internally, this uses your application's
         * {@link Ext.app.Router Router} to decode the url into a matching controller action and then calls
         * {@link #dispatch}.
         * @param {String/Ext.data.Model} url The String url to redirect to
         */
        redirectTo: function(url) {
            if (Ext.data && Ext.data.Model && url instanceof Ext.data.Model) {
                var record = url;

                url = record.toUrl();
            }

            var decoded = this.getRouter().recognize(url);

            if (decoded) {
                decoded.url = url;
                if (record) {
                    decoded.data = {};
                    decoded.data.record = record;
                }
                return this.dispatch(decoded);
            }
        },

        /**
         * @private
         * (documented on Controller's control config)
         */
        control: function(selectors, controller) {
            //if the controller is not defined, use this instead (the application instance)
            controller = controller || this;

            var dispatcher = this.getEventDispatcher(),
                refs = (controller) ? controller.getRefs() : {},
                selector, eventName, listener, listeners, ref;

            for (selector in selectors) {
                if (selectors.hasOwnProperty(selector)) {
                    listeners = selectors[selector];
                    ref = refs[selector];

                    //refs can be used in place of selectors
                    if (ref) {
                        selector = ref.selector || ref;
                    }
                    for (eventName in listeners) {
                        listener = listeners[eventName];

                        if (Ext.isString(listener)) {
                            listener = controller[listener];
                        }

                        dispatcher.addListener('component', selector, eventName, listener, controller);
                    }
                }
            }
        },

        /**
         * @private
         * Returns the Controller instance for the given controller name
         * @param {String} name The name of the Controller
         * @param {String} profileName Optional profile name. If passed, this is the same as calling
         * getController('profileName.controllerName')
         */
        getController: function(name, profileName) {
            var instances = this.getControllerInstances(),
                appName   = this.getName(),
                format    = Ext.String.format,
                topLevelName;

            if (name instanceof Ext.app.Controller) {
                return name;
            }

            if (instances[name]) {
                return instances[name];
            } else {
                topLevelName = format("{0}.controller.{1}", appName, name);
                profileName  = format("{0}.controller.{1}.{2}", appName, profileName, name);

                return instances[profileName] || instances[topLevelName];
            }
        },

        /**
         * @private
         * Callback that is invoked when all of the configured Profiles have been loaded. Detects the current profile and
         * gathers any additional dependencies from that profile, then loads all of those dependencies.
         */
        onProfilesLoaded: function() {
            var profiles  = this.getProfiles(),
                length    = profiles.length,
                instances = [],
                requires  = this.gatherDependencies(),
                current, i, profileDeps;

            for (i = 0; i < length; i++) {
                instances[i] = Ext.create(profiles[i], {
                    application: this
                });

                /*
                 * Note that we actually require all of the dependencies for all Profiles - this is so that we can produce
                 * a single build file that will work on all defined Profiles. Although the other classes will be loaded,
                 * the correct Profile will still be identified and the other classes ignored. While this feels somewhat
                 * inefficient, the majority of the bulk of an application is likely to be the framework itself. The bigger
                 * the app though, the bigger the effect of this inefficiency so ideally we will create a way to create and
                 * load Profile-specific builds in a future release.
                 */
                profileDeps = instances[i].getDependencies();
                requires = requires.concat(profileDeps.all);

                if (instances[i].isActive() && !current) {
                    current = instances[i];

                    this.setCurrentProfile(current);

                    this.setControllers(this.getControllers().concat(profileDeps.controller));
                    this.setModels(this.getModels().concat(profileDeps.model));
                    this.setViews(this.getViews().concat(profileDeps.view));
                    this.setStores(this.getStores().concat(profileDeps.store));
                }
            }

            this.setProfileInstances(instances);
            Ext.require(requires, this.loadControllerDependencies, this);
        },

        /**
         * @private
         * This is solely present for backwards compatibility with 1.x. In 1.x a Controller could specify additional
         * Models, Views and Stores to load. Here we look to see if any Controller is doing so and load them before
         * finalizing application bootup.
         */
        loadControllerDependencies: function() {
            var controllers = this.getControllers(),
                length = controllers.length,
                classes = [],
                name = this.getName(),
                format = Ext.String.format,
                controller, proto, i;

            for (i = 0; i < length; i++) {
                controller = Ext.ClassManager.classes[controllers[i]];
                proto = controller.prototype;

                Ext.each(proto.models, function(modelName) {
                    classes.push(format('{0}.model.{1}', name, modelName));
                }, this);

                Ext.each(proto.views, function(viewName) {
                    classes.push(format('{0}.view.{1}', name, viewName));
                }, this);

                Ext.each(proto.stores, function(storeName) {
                    classes.push(format('{0}.store.{1}', name, storeName));
                    this.setStores(this.getStores().concat([storeName]));
                }, this);
            }

            Ext.require(classes, this.onDependenciesLoaded, this);
        },

        /**
         * @private
         * Callback that is invoked when all of the Application + current Profile dependencies have been loaded.
         * Instantiates all of the controllers and stores then launches the app
         */
        onDependenciesLoaded: function() {
            var me = this,
                profile = this.getCurrentProfile(),
                launcher = this.getLaunch(),
                controllers, name;

            //<deprecated product=touch since=2.0>
            Ext.app.Application.appInstance = this;

            if (Ext.Router) {
                Ext.Router.setAppInstance(this);
            }
            //</deprecated>

            me.instantiateStores();
            me.instantiateControllers();
            controllers = this.getControllerInstances();

            if (profile) {
                profile.launch();
            }

            launcher.call(me);

            for (name in controllers) {
                controllers[name].launch(this);
            }

            me.redirectTo(window.location.hash.substr(1));
        },

        /**
         * @private
         * Gathers up all of the previously computed MVCS dependencies into a single array that we can pass to Ext.require
         */
        gatherDependencies: function() {
            var classes = this.getModels().concat(this.getViews()).concat(this.getControllers());

            Ext.each(this.getStores(), function(storeName) {
                if (Ext.isString(storeName)) {
                    classes.push(storeName);
                }
            }, this);

            return classes;
        },

        /**
         * @private
         * Should be called after dependencies are loaded, instantiates all of the Stores specified in the {@link #stores}
         * config. For each item in the stores array we make sure the Store is instantiated. When strings are specified,
         * the corresponding app/store/StoreName.js was loaded so we now instantiate a MyApp.store.StoreName, giving it the
         * id StoreName.
         */
        instantiateStores: function() {
            var stores  = this.getStores(),
                length  = stores.length,
                store, storeClass, storeName, splits, i;

            for (i = 0; i < length; i++) {
                store = stores[i];

                if (Ext.data && Ext.data.Store && !(store instanceof Ext.data.Store)) {
                    if (Ext.isString(store)) {
                        storeName = store;
                        storeClass = Ext.ClassManager.classes[store];

                        store = {
                            xclass: store
                        };

                        //we don't want to wipe out a configured storeId in the app's Store subclass so need
                        //to check for this first
                        if (storeClass.prototype.defaultConfig.storeId === undefined) {
                            splits = storeName.split('.');
                            store.id = splits[splits.length - 1];
                        }
                    }

                    stores[i] = Ext.factory(store, Ext.data.Store);
                }
            }

            this.setStores(stores);
        },

        /**
         * @private
         * Called once all of our controllers have been loaded
         */
        instantiateControllers: function() {
            var controllerNames = this.getControllers(),
                instances = {},
                length = controllerNames.length,
                name, i;

            for (i = 0; i < length; i++) {
                name = controllerNames[i];

                instances[name] = Ext.create(name, {
                    application: this
                });

                instances[name].init();
            }

            return this.setControllerInstances(instances);
        },

        /**
         * @private
         * As a convenience developers can locally qualify controller names (e.g. 'MyController' vs
         * 'MyApp.controller.MyController'). This just makes sure everything ends up fully qualified
         */
        applyControllers: function(controllers) {
            var length  = controllers.length,
                appName = this.getName(),
                name, i;

            for (i = 0; i < length; i++) {
                name = controllers[i];

                if (!name.match(this.dotRe)|| name.charCodeAt(0) > 96) {
                    controllers[i] = appName + '.controller.' + name;
                }
            }

            return controllers;
        },

        /**
         * @private
         * As a convenience developers can locally qualify store names (e.g. 'MyStore' vs
         * 'MyApp.store.MyStore'). This just makes sure everything ends up fully qualified
         */
        applyStores: function(stores) {
            var length  = stores.length,
                appName = this.getName(),
                name, i;

            for (i = 0; i < length; i++) {
                name = stores[i];

                if (Ext.isString(name) && (!name.match(this.dotRe) || name.charCodeAt(0) > 96)) {
                    stores[i] = appName + '.store.' + name;
                }
            }

            return stores;
        },

        /**
         * @private
         * As a convenience developers can locally qualify model names (e.g. 'MyModel' vs
         * 'MyApp.model.MyModel'). This just makes sure everything ends up fully qualified
         */
        applyModels: function(models) {
            var length  = models.length,
                appName = this.getName(),
                name, i;

            for (i = 0; i < length; i++) {
                name = models[i];

                if (Ext.isString(name) && (!name.match(this.dotRe) || name.charCodeAt(0) > 96)) {
                    models[i] = appName + '.model.' + name;
                }
            }

            return models;
        },

        /**
         * @private
         * As a convenience developers can locally qualify view names (e.g. 'MyView' vs
         * 'MyApp.view.MyView'). This just makes sure everything ends up fully qualified
         */
        applyViews: function(views) {
            var length  = views.length,
                appName = this.getName(),
                name, i;

            for (i = 0; i < length; i++) {
                name = views[i];

                if (Ext.isString(name) && (!name.match(this.dotRe) || name.charCodeAt(0) > 96)) {
                    views[i] = appName + '.view.' + name;
                }
            }

            return views;
        },

        /**
         * @private
         * As a convenience developers can locally qualify profile names (e.g. 'MyProfile' vs
         * 'MyApp.profile.MyProfile'). This just makes sure everything ends up fully qualified
         */
        applyProfiles: function(profiles) {
            var length  = profiles.length,
                appName = this.getName(),
                name, i;

            for (i = 0; i < length; i++) {
                name = profiles[i];

                if (Ext.isString(name) && (!name.match(this.dotRe) || name.charCodeAt(0) > 96)) {
                    profiles[i] = appName + '.profile.' + name;
                }
            }

            return profiles;
        },

        /**
         * @private
         * Checks that the name configuration has any whitespace, and trims them if found.
         */
        applyName: function(name) {
            var oldName;
            if (name && name.match(/ /g)) {
                oldName = name;
                name = name.replace(/ /g, "");

                // <debug>
                Ext.Logger.warn('Attempting to create an application with a name which contains whitespace ("' + oldName + '"). Renamed to "' + name + '".');
                // </debug>
            }

            return name;
        },

        /**
         * @private
         * Makes sure the app namespace exists, sets the `app` property of the namespace to this application and sets its loading path
         */
        updateName: function(newName) {
            Ext.ClassManager.setNamespace(newName + '.app', this);
            Ext.Loader.setPath(newName, this.getAppFolder());
        },

        /**
         * @private
         */
        applyRouter: function(config) {
            return Ext.factory(config, Ext.app.Router, this.getRouter());
        },

        /**
         * @private
         */
        applyHistory: function(config) {
            var history = Ext.factory(config, Ext.app.History, this.getHistory());

            history.on('change', this.onHistoryChange, this);

            return history;
        },

        /**
         * @private
         */
        onHistoryChange: function(url) {
            this.dispatch(this.getRouter().recognize(url), false);
        }
    }, function() {
        // <deprecated product=touch since=2.0>
        Ext.regApplication = function(config) {
            console.warn(
                '[Ext.app.Application] Ext.regApplication() is deprecated, please replace it with Ext.application()'
            );

            var appName = config.name,
                format  = Ext.String.format;

            Ext.ns(
                appName,
                format("{0}.controllers", appName),
                format("{0}.models", appName),
                format("{0}.views", appName)
            );

            Ext.application(config);
        };

        Ext.define('Ext.data.ProxyMgr', {
            singleton: true,

            registerType: function(name, cls) {
                console.warn(
                    'Ext.data.ProxyMgr no longer exists - instead of calling Ext.data.ProxyMgr.registerType just update ' +
                    'your custom Proxy class to set alias: "proxy.' + name + '"'
                );

                Ext.ClassManager.setAlias(cls, "proxy." + name);
            }
        });

        Ext.reg = function(alias, cls) {
            console.warn(
                'Ext.reg is deprecated, please set xtype: "' + alias + '" directly in your subclass instead'
            );

            Ext.ClassManager.setAlias(cls, alias);
        };

        Ext.redirect = function() {
            var app = Ext.app.Application.appInstance;

            console.log('[Ext.app.Application] Ext.redirect is deprecated, please use YourApp.redirectTo instead');

            if (app) {
                app.redirectTo.apply(app, arguments);
            }
        };

        Ext.dispatch = function() {
            var app = Ext.app.Application.appInstance;

            console.log('[Ext.app.Application] Ext.dispatch is deprecated, please use YourApp.dispatch instead');

            if (app) {
                app.dispatch.apply(app, arguments);
            }
        };

        // </deprecated>
    });