text:
/**
 * @ngdoc module
 * @name fl.api_services
 * @requires fl.model_factory
 * @description
 * Floopstreet API service base functionality.
 * This module exports the following functionality:
 */

const _ = require('lodash');
const axios = require('axios');
const { FlExtensions, FlClassManager } = require('./object_system');
const {
    FlModelBase, FlModelCache, FlModelFactory, FlGlobalModelFactory
} = require('./model_factory');

const DEFAULT_SRV_CFG = {
    xsrfCookieName: 'XSRF-TOKEN',
    xsrfHeaderName: 'X-XSRF-TOKEN',
    modelFactory: FlModelFactory.defaultFactory()
};

/**
 * @ngdoc type
 * @name FlAPIService
 * @module fl.api_services
 * @requires FlModelFactory
 * @description FlAPIService is the base class for API services.
 *  This class implements the common functionality for communicating with a standard Rails resource
 *  API: it defines methods to trigger the standard actions **index**, **show**, **update**, and
 *  **destroy**. Clients then provide a configuration that customizes this generic implementation.
 *
 *  There are two ways to use this service:
 *  1. Create an instance of FlAPIService with appropriate configuration.
 *  2. Define a subclass that encapsulates the configuration and optionally also adds API-specific
 *     entry points.
 *
 * For example, say there is a server API at `/my/data` that manages instances
 *  of `My::Datum`; this API is a standard CRUD RESTful API as generated by Rails.
 *  The API returns data as a JSON object containing the keys `data` or `datum`
 *  (the former when collections are returned as by the :index action, the latter
 *  when single items are returned). Sumbission parameters are encapsulated in the
 *  `my_datum` key. You can create a service to communicate with this API like this:
 *  ```
 *  let srv = new FlAPIService({
 *    root_url_template: '/my/data',
 *    namespace: 'my_datum',
 *    data_names: [ 'data', 'datum' ]
 *  });
 *  ```
 *  Alternatively, you can define a subclass of FlAPIService:
 *  ```
 *  let MyAPIService = FlClassManager.make_class({
 *    name: 'MyAPIService',
 *    superclass: 'FlAPIService',
 *    initializer: function(srv_cfg) {
 *      this.__super_init('FlAPIService', {
 *        root_url_template: '/my/data',
 *        namespace: 'my_datum',
 *        data_names: [ 'data', 'datum' ]
 *      }, srv_cfg);
 *    }
 *  });
 *
 *  let srv = new MyAPIService();
 *  ```
 *  The second approach lets you define additional methods that implement triggering of
 *  custom APIs. It also makes it possible to register service classes with {@sref FlAPIServiceRegistry}.
 *
 *  To get a list of data:
 *  ```
 *  let srv = new MyDatumAPIService();
 *  srv.index()
 *     .then(function(data) {
 *       // do something with the returned data
 *     })
 *     .catch(function(e) {
 *       // report error
 *     });
 *  ```
 *  Or to update an item:
 *  ```
 *  let id = getItemId();
 *  let srv = new MyDatumAPIService();
 *  srv.update(id, { wrapped: { prop1: 'prop1 value' },
 *                   unwrapped: { to_hash: { verbosity: 'complete' } })
 *     .then(function(data) {
 *       // do something with the returned data
 *     })
 *     .catch(function(r) {
 *       // report error
 *     });
 *  ```
 *  Note that the submission data can be split into wrapped and unwrapped components; the service object
 *  places the wrapped in the appropriate namespace, using the API configuration options.
 *
 *  #### Two types of API methods
 *
 *  The service class defines two types of API methods. The first group consists of wrappers around
 *  the standard HTTP methods `GET`, `POST`, `PUT`, `PATCH`, `DELETE`, `HEAD`, which are named
 *  **get**, **post**, **put**, **patch**, **delete**, **head**, respectively.
 *
 *  The second group implements a higher level API to standard Rails controller actions
 *  `index`, `show`, `create`, `update`, and `destroy`, which are named
 *  **index**, **show**, **create**, **update**, and **destroy**, respectively.
 *  These methods call the appropriate lower level API described above; for example, **index** and
 *  **show** call **get**.
 *
 *  #### Automatic generation of data model instances
 *
 *  FlAPIService assumes that the API returns data objects as JSON representations; for example, it
 *  assumes that the response for the **index** action looks something like this:
 *  ```
 *  {
 *    "data":[
 *      {"type":"My::Datum","api_root":"/my/data","url_path":"/my/data/1","fingerprint":"My::Datum/1","id":1,"created_at":"...","updated_at":"..","value1":"...","value2":"..."},
 *      {"type":"My::Datum","api_root":"/my/data","url_path":"/my/data/2","fingerprint":"My::Datum/2","id":2,"created_at":"...","updated_at":"..","value1":"...","value2":"..."}
 *    ],
 *    "_pg":{"_c":2,"_s":20,"_p":2}
 *  }
 *  ```
 *  The **index** code uses {@sref FlModelFactory} to instantiate an array of model objects from the array
 *  of JSON structures returned in the **data** property, and therefore a model class should have been
 *  registered for the `My::Model` type. (If no such class has been registered, `null` is placed in
 *  the array.)
 *
 * #### The API protocol
 *
 * This service assumes that the server implements a specific API behavior. For successful responses,
 * the body of the response is a JSON object that contains at least one property, the data being
 * returned. The name of this property is API-dependent, and the value depends on the request action.
 * For **index**, it is an array of JSON representation of data objects; for **create** and **update**,
 * it is a single JSON representation of a data object; and for **delete** it is a status as described
 * below. Additional properties *may* be present; for example, **index** also returns pagination
 * controls in the **_pg** property.
 *
 * On error, the response returns an status code in the 400 or 500 range, and the body is a JSON
 * representation of the error.
 *
 * ##### Host (base) URLs
 *
 * The **root_url_template** in the configuration (and **shallow_root_url_template**) are slightly
 * misnamed, as they contain just the path component of the complete URL.
 * This is as it should be, because the API signature should not include the server address (because
 * the same API could be running on different servers).
 *
 * In a browser environment, the current page's server address is used if one is not provided, but in
 * other environments (for example, React native) there is no notion of a "current page" or
 * "currrent server address." In this latter case, the API user must specify an absolute URL; the
 * mechanism for doing so is to pass a **baseURL** option in the server configuration object argument
 * in the constructor or in the network call methods like {@sref FlAPIService#get} and
 * {@sref FlAPIService#index}.
 * For example, to create a service instance that communicates with the server
 * at `http://srv.example.com:80`, pass the **baseURL** argument in the constructor:
 * ```
 * function get_data_promise() {
 *   let srv = new MyAPIService({ baseURL : 'http://srv.example.com:80' });
 *
 *   return srv.index();
 * }
 * ```
 * Alternatively, you can customize the base URL for each function call:
 * ```
 * function get_data_promise(baseURL) {
 *   let srv = new MyAPIService();
 *
 *   return srv.index(null, { baseURL : baseURL })
 * };
 * ```
 * (This last examples is a bit contrived, but you get the idea.)
 * Either approach is acceptable, although placing the base URL in the constructor might be a bit
 * cleaner. On the other hand, if you have a long lived service object that needs to switch target
 * servers, the per-call customization is what you want.
 *
 * ##### The status object
 *
 * The status object as returned by the methods contains the following properties:
 * - If the repsonse body contains a status object:
 *   - **status** is the status identifier as returned by the API.
 *   - **message** is a message associated with the status.
 *   - **details** is an optional object containing additional status information.
 * - Otherwise:
 *   - **status** is the status code from the response (typically in the 200 range, but could be in the
 *     300s).
 *   - **message** is the message associated with the HTTP status code.
 *
 * ##### The error object
 *
 * - If the repsonse body contains an error object:
 *   - **status** is the status identifier as returned by the API.
 *   - **message** is a message associated with the status.
 *   - **details** is an optional object containing additional error information.
 * - Otherwise:
 *   - **status** is the status code from the response, which should be in the 400 or 500 range.
 *   - **message** is the message associated with the HTTP status code.
 *
 * ##### The pagination info
 *
 * Pagination info is an object that tracks the current state of a multipage query.
 * It contains the following properties:
 * - **_s** How many results to return per page.
 * - **_p** The next page to fetch, starting at 1 for the first page.
 * - **_c** How many results were returned by the last query. Note that, if `_c < _s`, then
 *   no more results are available.
 *
 * ##### URL templates
 *
 * The configuration property **root_url_template** is used to generate the root URL.
 * The value may contain replacement directives of the form `${expr}`, similar to the syntax
 * used for ES6 template literals; these directives are executed in the context of the service object
 * (`this`), and inserted in the template to generate the root URL.
 * For example, the template `/my/${parent.id}/dependents` will
 * generate a root URL `/my/1234/dependents`, where `1234` is the result of the expression
 * `parent.id` evaluated in the context of `this`. This implies that the service object using this
 * template has also set a property named **parent**, typically from an argument to the constructor.
 *
 * Templates with replacement directives are typically used with nested resource APIs. For example,
 * a list and list item API pair may define two service API objects, a regular one for lists, and a
 * nested one for list items (list contents).
 * The list API service may use a configuration and class descriptor like this:
 * ```
 * const LIST_API_CFG = {
 *   root_url_template: '/lists',
 *   namespace: 'list',
 *   data_names: [ 'list', 'lists' ]
 * };
 *
 * const LIST_SERVICE_DESC = {
 *   name: 'ListAPIService',
 *   superclass: 'FlAPIService',
 *   initializer: function(srv_cfg) {
 *     this.__super_init('FlAPIService', LIST_API_CFG, srv_cfg);
 *   }
 * };
 * ```
 * The nested list item API service is set up like this:
 * ```
 * const LIST_ITEM_API_CFG = {
 *   root_url_template: '/lists/${list.id}/list_items',
 *   shallow_root_url_template: '/list_items',
 *   namespace: 'list_item',
 *   data_names: [ 'list_item', 'list_items' ]
 * };
 *
 * const LIST_ITEM_SERVICE_DESC = {
 *   name: 'ListItemAPIService',
 *   superclass: 'FlNestedAPIService',
 *   initializer: function(list, srv_cfg) {
 *     this.__super_init('FlNestedAPIService', LIST_ITEM_API_CFG, srv_cfg);
 *     this.list = list;
 *   }
 * };
 * ```
 * Note how the root URL template contains the directive `${list.id}`, and how the constructor takes
 * the list object that provides the nesting resource; this list object is saved in the **this.list**
 * property. Individual list items are accessed via the `/list_items` URL; for example, the URL for the
 * `show` action for the list item with identifier 1234 in list `3456` is `/list_items/1234` rather
 * than `/lists/3456/list_items/1234`.
 *
 * ##### Rails nested resources
 *
 * The base service API class {@sref FlAPIService} can handle interactions with
 * {@sref Rails-nested-resources Rails nested resources} out of the box; however, we define a
 * specialized {@sref FlNestedAPIService} class that overrides the URL generation functionality to
 * support shallow routing as well as standard nested routing.
 *
 * #### Webpack
 *
 * API service code relies on registered data model classes to generate model instances of the
 * appropriate type. Unfortunately, {@sref Webpack} does not add a source file if its exports
 * are nowhere imported by the other files in the package. As a consequence, the data model class
 * associated with a given API service is not registered, and the data returned by **index** and
 * **show** is `null`. For example, the `MyAPIService` class listed above expects to retrieve
 * instances of the `My::Model` type, via the `MyModel` data model class:
 * ```
 * FlGlobalAPIServiceRegistry.register('my.services', { MyAPIService: 'My::Model' });
 * ```
 * If no other sources import `MyModel`, then a call to {@sref FlAPIService#show} attempts to
 * load the model class for `My::Model`, finds none, and returns `null`.
 *
 * Typically, the source file for a data model includes registration code like this:
 * ```
 * FlModelFactory.defaultFactory().register('my.models', [
 *   { service: MyModel, class_name: 'My::Model' }
 * ]);
 * ```
 * To ensure that the source file is packed (and therefore the class is registered), add the
 * following statement in the source for `MyAPIService`:
 * ```
 * const { MyModel } = require('my/models/my_model');
 * ```
 * (or equivalent).
 */

let FlAPIService = FlClassManager.make_class({
    name: 'FlAPIService',
    /**
     * @ngdoc method
     * @name FlAPIService#constructor
     * @description The constructor; called during `new` creation.
     *
     * @param {Object} api_cfg Configuration for the API object.
     * @property {String} api_cfg.root_url_template The template used to generate the path component
     *  of the URL.
     *  The value may contain replacement directives of the form `${expr}`, similar to the syntax
     *  used for ES6 template literals. For example, the template `/my/${parent.id}/dependents` will
     *  generate a root URL `/my/1234/dependents`, where `1234` is the result of the expression
     *  `parent.id` (looked up in **this**). Templates with replacement directives are
     *  typically used with nested resource APIs.
     * @property {String} api_cfg.namespace The parameter namespace for create/update calls.
     *  Parameters will be wrapped inside this namespace; for example, if the namespace is `ns`,
     *  then the submission parameters `{ p1: 1, p2: 2 }` are actually sent to the server as
     *  `{ ns: { p1: 1, p2: 2 } }`.
     * @property {Array} api_cfg.data_names An array of property names that contain
     *  response data. These are typically the singular and plural version of the
     *  object name. For the example above, use `[ 'datum', 'data' ]`; for an API that returns user
     *  objects, use `[ 'user', 'users' ]`.
     * @property {Array} api_cfg.pg_names An array of property names that contain the
     *  pagination controls. The service looks up each in the order in which they are listed
     *  in the array, and loads the first match in the pagination controls.
     *  The default value is the array `[ '_pg' ]`.
     * @param {Object} srv_cfg Configuration for the service. A few standard properties in the
     *  object are described below; various services may include additional ones.
     *  See the properties section for details.
     * @property {Object} srv_cfg.axios The underlying {@sref Axios} service to use for HTTP requests.
     *  By default, an instance of Axios is created and installed, but one can provide a custom
     *  instance if desired. This feature is often used for testing, to install a mocked version of Axios.
     * @property {Object} srv_cfg.modelFactory The instance of {@sref FlModelFactory} to use to create
     *  model instances.
     *  Defaults to {@sref FlGlobalModelFactory}.
     * @property {String} srv_cfg.xsrfCookieName The name of the cookie to use as a value for the XSRF token.
     *  Defaults to `XSRF-TOKEN`.
     * @property {String} srv_cfg.xsrfHeaderName The name of the http header that carries the XSRF token
     *  value.
     *  Defaults to `X-XSRF-TOKEN`.
     * @property {String} srv_cfg.xsrfToken The value of the XSRF token.
     *  Defaults to `undefined`.
     */
    initializer: function(api_cfg, srv_cfg) {
	this._api_cfg = _.merge({ }, (_.isObject(api_cfg)) ? api_cfg : { });
	this._srv_cfg = _.merge({ }, FlAPIService.getServiceConfig(), (_.isObject(srv_cfg)) ? srv_cfg : { });

	this._http_service = (_.isNil(this._srv_cfg.axios)) ? axios : this._srv_cfg.axios;
	this._pg_names = (_.isArray(this._api_cfg.pg_names)) ? this._api_cfg.pg_names : [ '_pg' ];
	if (_.isNil(this._srv_cfg.modelFactory)) this._srv_cfg.modelFactory = FlModelFactory.defaultFactory();

	this._showDidSucceed = null;
	this.pagination_controls = 'init';
    },
    instance_properties: {
	/**
	 * @ngdoc property
	 * @name FlAPIService#xsrfCookieName
	 * @description Accessor for the name of the XSRF cookie, from the current configuation.
	 *  This property is just an accessor for the `xsrfCookieName` configuration property
	 *  from the *srv_cfg* argument to the constructor.
	 *
	 * @param {String} name The name of the cookie to use as a value for the XSRF token.
	 *
	 * @return {String} The getter returns the name of the XSRF cookie from the current configuation.
	 */

	xsrfCookieName: {
	    get: function() { return this._srv_cfg.xsrfCookieName; },
	    set: function(name) { this._srv_cfg.xsrfCookieName = name; }
	},

	/**
	 * @ngdoc property
	 * @name FlAPIService#xsrfHeaderName
	 * @description Accessor for the name of http header that carries the XSRF token value,
	 *  from the current configuation.
	 *  This property is just an accessor for the `xsrfHeaderName` configuration property
	 *  from the *srv_cfg* argument to the constructor.
	 *
	 * @param {String} name The name of the http header that carries the XSRF token value.
	 *
	 * @return {String} The getter returns the name of the XSRF header from the current configuation.
	 */

	xsrfHeaderName: {
	    get: function() { return this._srv_cfg.xsrfHeaderName; },
	    set: function(name) { this._srv_cfg.xsrfHeaderName = name; }
	},

	/**
	 * @ngdoc property
	 * @name FlAPIService#xsrfToken
	 * @description Accessor for the value of the local XSRF token.
	 *  This property is just an accessor for the `xsrfToken` configuration property
	 *  from the *srv_cfg* argument to the constructor.
	 *
	 * @param {String} token The new value of the token.
	 *
	 * @return {String} The getter returns the current value of the local XSRF token.
	 */

	xsrfToken: {
	    get: function() { return this._srv_cfg.xsrfToken; },
	    set: function(token) { this._srv_cfg.xsrfToken = token; }
	},

	/**
	 * @ngdoc property
	 * @name FlAPIService#modelFactory
	 * @description Getter for **modelFactory** property.
	 *  This property is just an accessor for the `modelFactory` configuration property
	 *  from the *srv_cfg* argument to the constructor.
	 *
	 * @return {String} Returns the value of the **modelFactory** property in the object.
	 */

	modelFactory: {
	    get: function() { return this._srv_cfg.modelFactory; }
	},

	/**
	 * @ngdoc property
	 * @name FlAPIService#root_url_template
	 * @description Getter for **root_url_template** configuration property.
	 * @return {String} Returns the value of the **root_url_template** property in the API config object.
	 */

	root_url_template: {
	    get: function() {
		return this._api_cfg.root_url_template;
	    }
	},

	/**
	 * @ngdoc property
	 * @name FlAPIService#namespace
	 * @description Getter for the **namespace** configuration property.
	 * @return {String} Returns the value of the **namespace** property in the API config object.
	 */

	namespace: {
	    get: function() {
		return this._api_cfg.namespace;
	    }
	},

	/**
	 * @ngdoc property
	 * @name FlAPIService#data_names
	 * @description Getter for the **data_names** configuration property.
	 * @return {String} Returns the value of the **data_names** property in the API config object.
	 */

	data_names: {
	    get: function() {
		return this._api_cfg.data_names;
	    }
	},

	/**
	 * @ngdoc property
	 * @name FlAPIService#response
	 * @description Getter for the last response returned by the server.
	 * @return {Object} Returns the last response returned by the server.
	 */

	response: {
	    get: function() {
		return this._response;
	    }
	},

	/**
	 * @ngdoc property
	 * @name FlAPIService#error
	 * @description Getter for the last error returned by the server.
	 * @return {Object} Returns the last error returned by the server.
	 */

	error: {
	    get: function() {
		return this._error;
	    }
	},

	/**
	 * @ngdoc property
	 * @name FlAPIService#pagination_controls
	 * @description Accessors for pagination_controls.
	 *  The getter returns a hash containing key/value pairs:
	 *   - *_s* is an integer containing the page size (how many results are returned by the query).
	 *   - *_p* is an integer containing the 1-based index of the _next_ page to load.
	 *     For example, a value of 3 indicates that this is the _third_ page loaded.
	 *
	 *  The setter takes a hash with the same two key/value pairs, the string `'init'`, or
	 *  `null`; a value of `'init'` sets the default control values; any other value
	 *  (including  *null*) disables use of the pagination controls.
	 */

	pagination_controls: {
	    get: function() {
		return this._pagination_controls;
	    },
	    set: function(pg) {
		if (_.isObject(pg))
		{
		    this._pagination_controls = pg;
		}
		else if (_.isString(pg) && (pg == 'init'))
		{
		    this._pagination_controls = this.initial_pagination_controls;
		}
		else
		{
		    this._pagination_controls = null;
		}
	    }
	},

	/**
	 * @ngdoc property
	 * @name FlAPIService#initial_pagination_controls
	 * @description Get the initial pagination_controls.
	 *
	 * @return {Object} Returns a hash containing key/value pairs:
	 *  - *_s* is an integer containing the page size (how many results are returned by
	 *    the query). The value returned is 20.
	 *  - *_p* is an integer containing the 1-based index of the _next_ page to load.
	 *    For example, a value of 3 indicates that this is the _third_ page loaded.
	 *    The value returned is 1.
	 */

	initial_pagination_controls: {
	    get: function() {
		return { _s: 20, _p: 1 };
	    }
	}
    },
    instance_methods: {
	/**
	 * @ngdoc method
	 * @name FlAPIService#setConfig
	 * @description Sets initial values for the service configuration (the **srv_cfg**
	 *  argument to various instance methods).
	 *
	 * @param {Object} srv_cfg The configuration to merge into the existing state, or to
	 *  completely replace the existing configuration.
	 * @param {Boolean} replace If `true`, the *srv_cfg* value replaces the current configuration;
	 *  otherwise, the content of *srv_cfg* are merged into the current ones.
	 */

	setConfig: function(srv_cfg, replace) {
	    if (replace)
	    {
		this._srv_cfg = _.merge({ }, srv_cfg);
	    }
	    else
	    {
		this._srv_cfg = _.merge(this._srv_cfg, srv_cfg);
	    }
	},

	/**
	 * @ngdoc method
	 * @name FlAPIService#getConfig
	 * @description Gets the current configuration.
	 *
	 * @return {Object} Returns a copy of the current configuration.
	 */

	getConfig: function() {
	    return _.merge({ }, this._srv_cfg);
	},

	/**
	 * @ngdoc method
	 * @name FlAPIService#url_path_for
	 * @description Generates the path component of the URL for the given action.
	 *  This includes processing the root URL template, interpolating the replacement directives, and
	 *  adding action-specific components to the path.
	 *
	 * @param {String} action The name of the action. The base implementation supports the standard
	 *  Rails actions `index`, `create`, `show`, `update`, and `destroy`; subclasses can augment this set
	 *  as needed.
	 * @param {Object|Integer} [target] Some actions need a target object whose identifier to place
	 *  in the path. The value is either an object that contains a **id** property, or the
	 *  identifier itself.
	 *
	 * @return {String|null} Returns the URL path for the action; if *action* is not supported,
	 *  returns `null`.
	 */

	url_path_for: function(action, target) {
	    let root_path = this._expand_url_template(this.root_url_template);

	    let tid = (_.isUndefined(target)) ? undefined : this._id(target);

	    if ((action == 'index') || (action == 'create'))
	    {
		return root_path + '.json';
	    }
	    else if ((action == 'show') || (action == 'update') || (action == 'destroy'))
	    {
		return root_path + '/' + tid + '.json';
	    }
	    else
	    {
		return null;
	    }
	},

	/**
	 * @ngdoc method
	 * @name FlAPIService#get
	 * @description Execute a `GET` method.
	 *  This method is more or less a straight passthrough to the Axios `get` method.
	 *
	 * @param {String} url The target URL.
	 * @param {Object} [config] Configuration object to pass to the Axios `get` method; this object
	 *  is merged into the default HTTP configuration object.
	 *
	 * @return {Promise} Returns a promise that resolves or rejects based on the return value
	 *  from the Axios `get` method.
	 *  The error and response objects are also saved in the {@sref FlAPIService#error} and
	 *  {@sref FlAPIService#response} properties, respectively.
	 */

	get: function(url, config) {
	    let self = this;

	    return this._http_service.get(url, this._make_config(config))
		.then(function(r) {
 		    self._error = null;
		    self._response = r;
		    return Promise.resolve(r);
		})
		.catch(function(e) {
		    self._error = e;
		    self._response = e.response;
		    return Promise.reject(e);
		});
	},

	/**
	 * @ngdoc method
	 * @name FlAPIService#post
	 * @description Execute a `POST` method.
	 *  The actual call is to {@sref FlAPIService#process}, which then dispatches to the
	 *  Axios `post` method. As a consequence, the special processing implemented by
	 *  {@sref FlAPIService#process} is triggered; for example, the XSRF header is added to the
	 *  headers list if the **xsrfToken** configuration property is non-nil.
	 *
	 * @param {String} url The target URL.
	 * @param {Object} data The data to submit to the server; note that, differently from the "action"
	 *  methods {@sref FlAPIService#create} and {@sref FlAPIService#update}, the value of *data* is not
	 *  wrapped inside the namespace.
	 * @param {Object} [config] Configuration object to pass to axios.post; this object is
	 *  merged into the default service configuration.
	 *
	 * @return {Promise} Returns a promise that resolves or rejects based on the return value
	 *  from the Axios `post` method.
	 *  The response object is also saved in the {@sref FlAPIService#response} property.
	 */

	post: function(url, data, config) {
	    return this.process('post', url, data, config);
	},

	/**
	 * @ngdoc method
	 * @name FlAPIService#put
	 * @description Execute a `PUT` method.
	 *  The actual call is to {@sref FlAPIService#process}, which then dispatches to the
	 *  Axios `put` method. As a consequence, the special processing implemented by
	 *  {@sref FlAPIService#process} is triggered; for example, the XSRF header is added to the
	 *  headers list if the **xsrfToken** configuration property is non-nil.
	 *
	 * @param {String} url The target URL.
	 * @param {Object} data The data to submit to the server; note that, differently from the "action"
	 *  methods {@sref FlAPIService#create} and {@sref FlAPIService#update}, the value of *data* is not
	 *  wrapped inside the namespace.
	 * @param {Object} [config] Configuration object to pass to axios.put; this object is
	 *  merged into the default service configuration.
	 *
	 * @return {Promise} Returns a promise that resolves or rejects based on the return value
	 *  from the Axios `put` method.
	 *  The response object is also saved in the {@sref FlAPIService#response} property.
	 */

	put: function(url, data, config) {
	    return this.process('put', url, data, config);
	},

	/**
	 * @ngdoc method
	 * @name FlAPIService#patch
	 * @description Execute a `PATCH` method.
	 *  The actual call is to {@sref FlAPIService#process}, which then dispatches to the
	 *  Axios `patch` method. As a consequence, the special processing implemented by
	 *  {@sref FlAPIService#process} is triggered; for example, the XSRF header is added to the
	 *  headers list if the **xsrfToken** configuration property is non-nil.
	 *
	 * @param {String} url The target URL.
	 * @param {Object} data The data to submit to the server; note that, differently from the "action"
	 *  methods {@sref FlAPIService#create} and {@sref FlAPIService#update}, the value of *data* is not
	 *  wrapped inside the namespace.
	 * @param {Object} [config] Configuration object to pass to axios.patch; this object is
	 *  merged into the default service configuration.
	 *
	 * @return {Promise} Returns a promise that resolves or rejects based on the return value
	 *  from the Axios `patch` method.
	 *  The response object is also saved in the {@sref FlAPIService#response} property.
	 */

	patch: function(url, data, config) {
	    return this.process('patch', url, data, config);
	},

	/**
	 * @ngdoc method
	 * @name FlAPIService#delete
	 * @description Execute a `DELETE` method.
	 *  The actual call is to {@sref FlAPIService#process}, which then dispatches to the
	 *  Axios `delete` method. As a consequence, the special processing implemented by
	 *  {@sref FlAPIService#process} is triggered; for example, the XSRF header is added to the
	 *  headers list if the **xsrfToken** configuration property is non-nil.
	 *
	 * @param {String} url The target URL.
	 * @param {Object} [data] Data to send; this is typically an empty object.
	 * @param {Object} [config] Configuration object to pass to axios.delete; this object is
	 *  merged into the default HTTP configuration.
	 *
	 * @return On success, returns a resolved promise containing the response data.
	 *  On error, returns a rejected promise containing the response.
	 *  In all cases, the response object is also saved int the {@sref FlAPIService#response}
	 *  property.
	 */

	delete: function(url, data, config) {
	    return this.process('delete', url, data, config);
	},

	/**
	 * @ngdoc method
	 * @name FlAPIService#head
	 * @description Execute a `HEAD` method.
	 *  This method is more or less a straight passthrough to the Axios `head` method.
	 *
	 * @param {String} url The target URL.
	 * @param {Object} [config] Configuration object to pass to the Axios `head` method; this object
	 *  is merged into the default HTTP configuration object.
	 *
	 * @return {Promise} Returns a promise that resolves or rejects based on the return value
	 *  from the Axios `head` method.
	 *  The error and response objects are also saved in the {@sref FlAPIService#error} and
	 *  {@sref FlAPIService#response} properties, respectively.
	 */

	head: function(url, config) {
	    let self = this;

	    return this._http_service.head(url, this._make_config(config))
		.then(function(r) {
		    self._error = null;
		    self._response = r;
		    return Promise.resolve(r);
		})
		.catch(function(e) {
		    self._error = e;
		    self._response = e.response;
		    return Promise.reject(e);
		});
	},

	/**
	 * @ngdoc method
	 * @name FlAPIService#index
	 * @description Make an :index call by calling `axios.get` against the root URL.
	 *
	 * @param {Object} [params] Parameters to pass in the request; the contents of this object are
	 *  merged into *config.params*, and eventually make their way to the query string.
	 * @param {Object} [config] Configuration object to pass to `axios.get`; this object is
	 *  merged into the default HTTP configuration object.
	 *
	 * @return On success, returns a resolved promise containing the response data converted
	 *  to an array of model objects.
	 *  On error, returns a promise that rejects with the value
	 *  from the {@sref FlAPIService#get} method.
	 *  The error and response objects are also saved in the {@sref FlAPIService#error} and
	 *  {@sref FlAPIService#response} properties, respectively.
	 */

	index: function(params, config) {
	    let self = this;

	    return this.get(this.url_path_for('index'), this._make_index_config(params, config))
		.then(function(r) {
		    self._set_pagination_controls(r);
		    return Promise.resolve(self.modelFactory.create(self.response_data(r)));
		})
		.catch(function(e) {
		    return Promise.reject(e);
		});
	},

	/**
	 * @ngdoc method
	 * @name FlAPIService#setShowDidSucceed
	 * @description Register a callback for the :show action.
	 *  This function is called on a successful :show action; it takes one argument, the
	 *  model object created from the response from the `axios.get` call.
	 *
	 * @param {Function} cb A function that will be installed as the :show callback.
	 *  Set it to `null` to disable it (this is the default value).
	 *  This function can modify the model object before it is returned by the :show action.
	 */

	setShowDidSucceed: function(cb) {
	    this._showDidSucceed = cb;
	},

	/**
	 * @ngdoc method
	 * @name FlAPIService#_create_or_refresh_from_id
	 * @description Refresh an existing model instance, or create a new one.
	 *  This (internal) method is used in action implementation where the API returns object data,
	 *  such as for the `show` and `update` actions.
	 *  If those implementations are called with a model instance in the *id* parameter, then the
	 *  client has provided the target instance explicitly, and the implementation should use it.
	 *  Since model instances are cached, this only makes a difference if the target instance had
	 *  been created explicitly, rather than via the {@sref FlModelFactory#create} method: in this case,
	 *  the instance may not be cached, and using `create` would result in two copies of the
	 *  object floating around in the system. Use of this method helps avoiding that kind of problem.
	 *
	 * @param {Integer|String|Object} id A string or integer containing the identifier, or a model
	 *  instance from which the identifier is obtained.
	 * @param {Object} data The model data to use for the refresh or create.
	 *
	 * @return Returns the object that was refreshed: if *id* is an identifier, it returns the
	 *  object that was created by a call to {@sref FlModelFactory#create}; if it is a model instance,
	 *  it returns *id*.
	 */

	_create_or_refresh_from_id: function(id, data) {
	    if (!_.isNil(id.__class) && _.isFunction(id.refresh))
	    {
		// This looks like a model instance, so just refresh it.

		id.refresh(data);
		return id;
	    }
	    else
	    {
		return this.modelFactory.create(data);
	    }
	},

	/**
	 * @ngdoc method
	 * @name FlAPIService#show
	 * @description Make a :show call by calling `axios.get` against the root URL/:id.
	 *
	 * @param {Integer|String|Object} id A string or integer containing the identifier to append to
	 *  the root URL. You can also pass an object with an `id` property, whose value will be used
	 *  for the identifier; this makes it possible to pass model instances to the method.
	 * @param {Object} [params] Parameters to pass in the request; the contents of this object are
	 *  merged into *config.params*, and eventually make their way to the query string.
	 * @param {Object} [config] Configuration object to pass to `axios.get`; this object is
	 *  merged into the default HTTP configuration.
	 *
	 * @return On success, returns a resolved promise containing the response data converted to a
	 *  model object.
	 *  On error, returns a promise that rejects with the value
	 *  from the {@sref FlAPIService#get} method.
	 *  The error and response objects are also saved in the {@sref FlAPIService#error} and
	 *  {@sref FlAPIService#response} properties, respectively.
	 */

	show: function(id, params, config) {
	    let self = this;
	    return this.get(this.url_path_for('show', id), this._make_get_config(params, config))
		.then(function(r) {
		    let model = self._create_or_refresh_from_id(id, self.response_data(r));

		    if (_.isFunction(self._showDidSucceed))
		    {
			self._showDidSucceed.call(self, model);
		    }
		    return Promise.resolve(model);
		})
		.catch(function(e) {
		    return Promise.reject(e);
		});
	},

	/**
	 * @ngdoc method
	 * @name FlAPIService#process
	 * @description Make a processing call; this is the method that the high level
	 *  processing methods (**create**, **update**, **delete**) call.
	 *  A processing call causes the state of the server to change: a :create, :update, or
	 *  :destroy call (which are executed via a `POST`, `PATCH`, or `DELETE` method,
	 *  respectively). The `PUT` method is also supported, althoug the Rails API uses `PATCH`
	 *  now for updates.
	 *
	 *  If the **xsrfToken** property is defined, an XSRF header is generated.
	 *  The method also checks if the _data_ contain file objects, and if so sets up the `axios`
	 *  service to submit data in multipart form.
	 *
	 * @param {String} method The method to use: `post`, `patch`, `put`, `delete`.
	 * @param {String} url The URL of the server endpoint.
	 * @param {Object} data The data to submit to the server; see above for a discussion of
	 *  how the data are submitted.
	 * @param {Object} [config] Configuration object to pass to axios.patch; this object is
	 *  merged into the default HTTP configuration.
	 *
	 * @return {Promise} Returns a promise that resolves or rejects based on the return value
	 *  from the supported Axios processing methods.
	 *  It also returns a rejected promise if *method* is not the name of a supported method.
	 *  The error and response objects are also saved in the {@sref FlAPIService#error} and
	 *  {@sref FlAPIService#response} properties, respectively.
	 */

	process: function(method, url, data, config) {
	    let self = this;
	    let api_data = data;
	    let cfg = this._make_config(config);
	    let args;
	    let um = method.toLowerCase();

	    if (!_.isNil(self.xsrfToken))
	    {
		_.merge(cfg, { headers: { [self.xsrfHeaderName]: self.xsrfToken } });
	    }

	    if (self._has_file_item(api_data))
	    {
		self._add_content_type(cfg, undefined);
		let flat = { };
		self._flatten_data(api_data, flat, '');
		api_data = self._form_data(flat);
	    }

	    let m;
	    if (um == 'post')
	    {
		m = this._http_service.post;
		args = [ url, api_data, cfg ];
	    }
	    else if (um == 'patch')
	    {
		m = this._http_service.patch;
		args = [ url, api_data, cfg ];
	    }
	    else if (um == 'put')
	    {
		m = this._http_service.put;
		args = [ url, api_data, cfg ];
	    }
	    else if (um == 'delete')
	    {
		m = this._http_service.delete;
		args = [ url, cfg ];
	    }
	    else
	    {
		m = null;
	    }

	    if (m)
	    {
		return m.apply(this._http_service, args)
		    .then(function(r) {
			self._error = null;
			self._response = r;
			return Promise.resolve(r);
		    })
		    .catch(function(e) {
			self._error = e;
			self._response = e.response;
			return Promise.reject(e);
		    });
	    }
	    else
	    {
		return Promise.reject('unsupported processing method: ' + method);
	    }
	},

	/**
	 * @ngdoc method
	 * @name FlAPIService#create
	 * @description Make a :create call by calling `axios.post` against the root URL.
	 *  The actual call is to {@sref FlAPIService#process}, which then dispatches to `axios.post`.
	 *
	 * @param {Object} data The data to submit to the server. The object contains two properties,
	 *  **wrapped** and **unwrapped**. See {@sref FlAPIService#_wrap_data} for details.
	 * @param {Object} [config] Configuration object to pass to axios.post; this object is
	 *  merged into the default HTTP configuration.
	 *
	 * @return On success, returns a resolved promise containing the response data.
	 *  On error, returns a promise that rejects with the value
	 *  from the {@sref FlAPIService#post} method.
	 *  The error and response objects are also saved in the {@sref FlAPIService#error} and
	 *  {@sref FlAPIService#response} properties, respectively.
	 */

	create: function(data, config) {
	    let self = this;

	    return this.post(this.url_path_for('create'), this._wrap_data(data), config)
		.then(function(r) {
		    return Promise.resolve(self.modelFactory.create(self.response_data(r)));
		})
		.catch(function(e) {
		    return Promise.reject(e);
		});
	},

	/**
	 * @ngdoc method
	 * @name FlAPIService#update
	 * @description Make a :update call by calling `axios.patch` against the root URL/:id.
	 *  The actual call is to {@sref FlAPIService#process}, which then dispatches to `axios.patch`.
	 *
	 * @param {Integer|String|Object} id A string or integer containing the identifier to append to
	 *  the root URL. You can also pass an object with an `id` property, whose value will be used
	 * @param {Object} data The data to submit to the server. The object contains two properties,
	 *  **wrapped** and **unwrapped**. See {@sref FlAPIService#_wrap_data} for details.
	 * @param {Object} [config] Configuration object to pass to axios.patch; this object is
	 *  merged into the default HTTP configuration.
	 *
	 * @return On success, returns a resolved promise containing the response data.
	 *  On error, returns a promise that rejects with the value
	 *  from the {@sref FlAPIService#patch} method.
	 *  The error and response objects are also saved in the {@sref FlAPIService#error} and
	 *  {@sref FlAPIService#response} properties, respectively.
	 */

	update: function(id, data, config) {
	    let self = this;

	    return this.patch(this.url_path_for('update', id), this._wrap_data(data), config)
		.then(function(r) {
		    return Promise.resolve(self._create_or_refresh_from_id(id, self.response_data(r)));
		})
		.catch(function(e) {
		    return Promise.reject(e);
		});
	},

	/**
	 * @ngdoc method
	 * @name FlAPIService#destroy
	 * @description Make a :destroy call by calling `axios.delete` against the root URL/:id.
	 *  The actual call is to {@sref FlAPIService#process}, which then dispatches to `axios.delete`.
	 *
	 * @param {Integer|String|Object} id A string or integer containing the identifier to append to
	 *  the root URL. You can also pass an object with an `id` property, whose value will be used
	 *  for the identifier; this makes it possible to pass model instances to the method.
	 * @param {Object} [config] Configuration object to pass to axios.delete; this object is
	 *  merged into the default HTTP configuration.
	 *
	 * @return On success, returns a resolved promise containing the response data.
	 *  On error, returns a promise that rejects with the value
	 *  from the {@sref FlAPIService#delete} method.
	 *  The error and response objects are also saved in the {@sref FlAPIService#error} and
	 *  {@sref FlAPIService#response} properties, respectively.
	 */

	destroy: function(id, config) {
	    let self = this;
	    return this.delete(this.url_path_for('destroy', id), { }, config)
		.then(function(r) {
		    return Promise.resolve(self.response_status(r));
		})
		.catch(function(e) {
		    return Promise.reject(e);
		});
	},

	/**
	 * @ngdoc method
	 * @name FlAPIService#_make_config
	 * @description Build configuration parameters for a call to Axios.
	 *
	 *  Subclasses likely won't need to override this method.
	 *
	 * @param {Object} [config] Configuration object to pass to Axios; this object is
	 *  merged into the default HTTP configuration.
	 *
	 * @return {Object} Returns a configuration object where the values in config have been
	 *  merged into this._srv_cfg.
	 */

	_make_config: function(config) {
	    if (!_.isObject(config)) config = {};

	    return _.merge({}, this._srv_cfg, config);
	},

	/**
	 * @ngdoc method
	 * @name FlAPIService#_make_get_config
	 * @description Build configuration parameters for a `GET` method call to Axios.
	 *  The method first calls *_make_config*, and then merges the contents of *params* into the
	 *  configuration object.
	 *  It is meant to be used when setting up call parameters for a `GET` method, since *params*
	 *  are merged into *config.params*, and therefore will appear in the query string.
	 *
	 *  Subclasses likely won't need to override this method.
	 *
	 * @param {Object} [params] Parameters to pass in the request; the contents of this object are
	 *  merged into *config.params*, and eventually make their way to the query string.
	 * @param {Object} [config] Configuration object to pass to axios; this object is
	 *  merged into the default HTTP configuration.
	 *
	 * @return {Object} Returns a configuration object where the values in _config_ have been
	 *  merged into the default HTTP configuration.
	 */

	_make_get_config: function(params, config) {
	    let cfg = this._make_config(config);
	    if (_.isObject(params))
	    {
		let cfgp = (_.isObject(cfg.params)) ? cfg.params : {};
		cfg.params = _.merge({}, cfgp, params);
	    }

	    return cfg;
	},

	/**
	 * @ngdoc method
	 * @name FlAPIService#_make_index_config
	 * @description Build configuration parameters for an :index call to Axios.
	 *  The method first calls *_make_get_config*, then tags on the pagination controls
	 *  if they are enabled.
	 *  It is a specialized method to be used with `GET` calls that map to an :index action.
	 *
	 *  Subclasses likely won't need to override this method.
	 *
	 * @param {Object} [params] Parameters to pass in the request; the contents of this object are
	 *  merged into *config.params*, and eventually make their way to the query string.
	 * @param {Object} [config] Configuration object to pass to axios; this object is
	 *  merged into the default HTTP configuration.
	 *
	 * @return {Object} Returns a configuration object where the values in _config_ have been
	 *  merged into the default HTTP configuration.
	 *  Also, the pagination controls are placed in the
	 *  submission parameters if enabled. The first key name in the pagination control keys
	 *  array is used as the key.
	 */

	_make_index_config: function(params, config) {
	    let cfg = this._make_get_config(params, config);

	    if (this.pagination_controls)
	    {
		if (!_.isObject(cfg.params)) cfg.params = { };

		// The pagination controls are the starting set; if *params* contains :_pg, us that
		// value to overrid defaults

		let k = this._pg_names[0];
		let pg = (_.isObject(cfg.params._pg)) ? cfg.params._pg : { };

		cfg.params[k] = _.merge({}, this.pagination_controls, pg);
	    }

	    return cfg;
	},

	/**
	 * @ngdoc method
	 * @name FlAPIService#_set_pagination_controls
	 * @description Look for the pagination controls in the response data and extract them.
	 *  This method looks up all registered names for pagination controls and loads them
	 *  on the first hit.
	 *
	 * @param {Object} r The response object.
	 */

	_set_pagination_controls: function(r) {
	    let self = this;
	    let data = r.data;
	    _.forEach(this._pg_names, function(k, idx) {
		if (!_.isUndefined(data[k]))
		{
		    self.pagination_controls = data[k];
		    return;
		}
	    });
	},

	/**
	 * @ngdoc method
	 * @name FlAPIService#response_status
	 * @description Extract a status object from a successful response.
	 *
	 * @param {Object} r The response.
	 *
	 * @return {Object} Returns an object containing a status report:
	 *  - *:status* The response status.
	 *  - *:message* A string containing a status message.
	 */

	response_status: function(r) {
	    let s = {
		status: r.status
	    };

	    let rd = r.data;
	    if (_.isObject(rd) && _.isObject(rd._status))
	    {
		s = rd._status;
	    }
	    else
	    {
		s.message = r.statusText;
	    }

	    return s;
	},

	/**
	 * @ngdoc method
	 * @name FlAPIService#response_error
	 * @description Extract or generate an error object from a failed response.
	 *  The method tries to detect the type of response: a general HTTP response,
	 *  an API error status, or an exception raised.
	 *
	 * @param {Object} r The response object from Axios; this object describes a failed request,
	 *  including situations where Axios was unable to submit the request (for example, because the
	 *  target URL is unavailable).
	 *
	 * @return {Object} Returns an object containing an error report:
	 *  - *:status* The response status if a response was returned by thes server.
	 *  - *:message* A string containing an error message.
	 */

	response_error: function(r) {
	    let err = { };
	    let response = r.response;

	    if (_.isObject(response))
	    {
		if (response.status) err.status = response.status;

		let rd = response.data;
		if (_.isObject(rd) && _.isObject(rd._error))
		{
		    err = rd._error;
		}
		else
		{
		    err.message = "response error";
		    if (_.isString(response.statusText)) err.message = response.statusText;
		    if (_.isString(response.message)) err.message = response.message;

		    if (response.stack)
		    {
			err.details = {
			    stack: response.stack.split("\n")
			};
		    }
		}
	    }
	    else if (_.isError(r))
	    {
		err.message = r.message;
		err.name = r.name;
		if (r.stack)
		{
		    err.details = {
			stack: r.stack.split("\n")
		    };
		}
	    }

	    return err;
	},

	/**
	 * @ngdoc method
	 * @name FlAPIService#response_data
	 * @description Given a response, return the response data.
	 *  This method covers both successful and unsuccesful responses from the standard API.
	 *  It first checks that *response* is defined, since some requests may have failed before the
	 *  request is actually made (for example, if the server is down the connection is refused and
	 *  therefore there is no response).
	 *  It then checks if the *response.data* property is present, and looks for the two special
	 *  properties *response.data._error* and *response.data._status* which are generated by the
	 *  API to indicate an error or a status return; it returns their value if present.
	 *  Finally, it iterates over the values in the **data_names** configuration property,
	 *  looking for a property by that name in *response.data*; the first hit
	 *  is returned.
	 *
	 *  Most subclasses won't need to override this method.
	 *
	 * @param {Object} response The response, which should contain a **data** property.
	 *
	 * @return {Object|undefined} Returns the response data as described above; if *response* is
	 *  not an object, or if it does not contain the **data** property, it returns `undefined`.
	 */

	response_data: function(response) {
	    if (!_.isObject(response)) return undefined;

	    let data = response.data;
	    if (!_.isObject(data)) return undefined;

	    if (!_.isUndefined(data._status)) return data._status;
	    if (!_.isUndefined(data._error)) return data._error;

	    let ary = this._api_cfg.data_names;

	    if (ary)
	    {
		let idx;
		let len = ary.length;
		let name;

		for (idx=0 ; idx < len ; idx++)
		{
		    name = ary[idx];
		    if (data[name])
		    {
			return data[name];
		    }
		}
	    }

	    return null;
	},

	/**
	 * @ngdoc method
	 * @name FlAPIService#_expand_url_template
	 * @description Process a URL template, interpolate the replacement directives, and return
	 *  the expanded URL.
	 *  This method scans the contents of *tpl* for interpolation directives, which it expands in the
	 *  context of `this`, and inserts the value of the directive in the template; see the class
	 *  documentation for details.
	 * @param {String} tpl The template to process.
	 * @return {String} Returns the URL generated from the template and the state of the service
	 *  object.
	 */

	_expand_url_template: function(tpl) {
	    let self = this;
	    let pre;
	    let rest = tpl;
	    let fragments = new Array();
	    let idx = 0;
	    let fdx;
	    let expr;

	    while (idx >= 0)
	    {
		idx = rest.indexOf('${');
		if (idx < 0)
		{
		    // no more replacement directives: we are done

		    fragments.push(rest);
		}
		else
		{
		    fragments.push(rest.substring(0, idx));
		    fdx = rest.indexOf('}', idx);
		    if (fdx < 0) fdx = rest.length;
		    fragments.push(_.get(self, rest.substring(idx+2, fdx)));
		    rest = rest.substring(fdx+1);
		}
	    }

	    return fragments.join('');
	},

	_has_file_item: function(data) {
	    let k;
	    let v;
	    let self = this;

	    for (k in data)
	    {
		v = data[k];

		// File is defined in a browser environment, but not in Node.js.
		// We skip this test if File is not defined

		try {
		    if (v instanceof(File)) return true;
		} catch (x) {
		}

		if (_.isObject(v))
		{
		    if (self._has_file_item(v))
		    {
			return true;
		    }
		}
	    }

	    return false;
	},

	_flatten_data: function(data, f, root) {
	    let self = this;

	    _.forEach(data, function(v, k) {
		let fk = (root.length > 0) ? (root + '[' + k + ']') : k;

		if (v instanceof(File))
		{
		    f[fk] = v;
		}
		else if (_.isObject(v))
		{
		    self._flatten_data(v, f, fk);
		}
		else
		{
		    f[fk] = v;
		}
	    });
	},

	_form_data: function(data) {
	    let fd = new FormData();
	    let self = this;

	    _.forEach(data, function(v, k) {
		if (v instanceof(File))
		{
		    fd.append(k, v, v.name);
		}
		else
		{
		    fd.append(k, v);
		}
	    });
	    return fd;
	},

	_add_content_type: function(cfg, ct) {
	    if (_.isObject(cfg.headers))
	    {
		cfg.headers['Content-Type'] = ct;
	    }
	    else
	    {
		cfg.headers = { 'Content-Type': ct };
	    }
	},

	/**
	 * @ngdoc method
	 * @name FlAPIService#_id
	 * @description Converts an identifier parameter to an identifier value.
	 *  if *id* is an object with a non-null **id** property, the value of `id.id` is returned.
	 *  Otherwise, the value of *id* is returned as is.
	 *
	 * @param {Integer|String|Object} id A string or integer containing the identifier.
	 *  You can also pass an object with an `id` property, whose value will be used
	 *  for the identifier; this makes it possible to pass model instances to the method.
	 */

	_id: function(id) {
	    return (_.isObject(id) && _.has(id, 'id') && !_.isNil(id.id)) ? id.id : id;
	},

	/**
	 * @ngdoc method
	 * @name FlAPIService#_wrap_data
	 * @description Wrap submission data within the namespace if one is defined.
	 *  The *data* object contains two optional properties,
	 *  **wrapped** and **unwrapped**. The **wrapped** property is also an object that contains
	 *  data to be placed inside the service's namespace, so that the actual data will be in a
	 *  property named after the namespace. The **unwrapped** property is also an object, and is
	 *  merged into the submission data as-is.
	 *  For example, if the contents of *data* are
	 *  ```
	 *    {
	 *      wrapped: { p1: 10 },
	 *      unwrapped: { other: 20 }
	 *    }
	 *  ```
	 *  and the namespace is `ns`, then the return value is
	 *  ```
	 *    {
	 *      ns: { p1: 10 },
	 *      other: 20
	 *    }
	 *  ```
	 *
	 *  A common unwrapped property is **to_hash**, whose value is an object of configuration
	 *  options for the server method that generates a hash representation of a Ruby model; for
	 *  example, to get the verbose representation of an object:
	 *  ```
	 *    let srv = new MyAPIService();
	 *    srv
	 *      .show(123456, { unwrapped: { to_hash: { verbosity: 'verbose' } } })
	 *      .then(function(o) {
	 *        // process the returned object
	 *      });
	 *  ```
	 *
	 * @param {Object} data The data to submit to the server. The object contains two properties,
	 *  **wrapped** and **unwrapped**, which are processed as described above.
	 *
	 * @return {Object} If the namespace is defined, the return value is an object with one
	 *  property, the namespace, whose value is *data*. If no namespace is defined, then
	 *  *data* is returned.
	 */

	_wrap_data: function(data) {
	    let api_data = { };

	    if (_.isObject(data.unwrapped))
	    {
		_.merge(api_data, data.unwrapped);
	    }

	    if (_.isObject(data.wrapped))
	    {
		if (this.namespace)
		{
		    api_data[this.namespace] = data.wrapped;
		}
		else
		{
		    _.merge(api_data, data.wrapped);
		}
	    }

	    return api_data;
	}
    },
    class_properties: {
	/**
	 * @ngdoc property
	 * @name FlAPIService#modelFactory
	 * @classproperty
	 * @description Getter for **modelFactory** property.
	 *  This property is just an accessor for the `modelFactory` in the current configuration.
	 *
	 * @return {String} Returns the value of the **modelFactory** property in the object.
	 */

	modelFactory: {
	    get: function() { return this._srv_cfg.modelFactory; }
	},

	/**
	 * @ngdoc property
	 * @name FlAPIService#xsrfCookieName
	 * @classproperty
	 * @description Accessor for the name of the XSRF cookie from the current configuation
	 *  defaults. This property is just an accessor for the `xsrfCookieName` configuration property.
	 *
	 * @param {String} name The name of the cookie to use as a value for the XSRF token.
	 *
	 * @return {String} The getter returns the name of the XSRF cookie from the current configuation
	 *  defaults.
	 */

	xsrfCookieName: {
	    get: function() { return this._srv_cfg.xsrfCookieName; },
	    set: function(name) { this._srv_cfg.xsrfCookieName = name; }
	},

	/**
	 * @ngdoc property
	 * @name FlAPIService#xsrfHeaderName
	 * @classproperty
	 * @description Accessor for the name of the http header that carries the XSRF token value,
	 *  from the current configuation defaults.
	 *  This property is just an accessor for the `xsrfHeaderName` configuration property.
	 *
	 * @param {String} name The name of the http header that carries the XSRF token value.
	 *
	 * @return {String} The getter returns the name of the XSRF header from the current configuation
	 *  defaults.
	 */

	xsrfHeaderName: {
	    get: function() { return this._srv_cfg.xsrfHeaderName; },
	    set: function(name) { this._srv_cfg.xsrfHeaderName = name; }
	},

	/**
	 * @ngdoc property
	 * @name FlAPIService#xsrfToken
	 * @classproperty
	 * @description Accessor for the default (current) value of the XSRF token.
	 *  This property is the global, applicationwide, XSRF token. Instances of {@sref FlAPIService}
	 *  may override this value, but typically won't.
	 *
	 * @param {String} token The new value of the token.
	 *
	 * @return {String} The getter returns the current value of the global XSRF token.
	 */

	xsrfToken: {
	    get: function() { return this._srv_cfg.xsrfToken; },
	    set: function(token) { this._srv_cfg.xsrfToken = token; }
	}
    },
    class_methods: {
	/**
	 * @ngdoc method
	 * @name FlAPIService#setServiceConfig
	 * @classmethod
	 * @description Sets default values for the service configuration (the **srv_cfg**
	 *  argument to various instance methods).
	 *
	 * @param {Object} srv_cfg The configuration to merge into the existing defaults, or to
	 *  completely replace the existing defaults.
	 * @param {Boolean} replace If `true`, the *srv_cfg* value replaces the current defaults;
	 *  otherwise, the content of *srv_cfg* are merged into the current defaults.
	 */

	setServiceConfig: function(srv_cfg, replace) {
	    if (replace)
	    {
		this._srv_cfg = _.merge({ }, srv_cfg);
	    }
	    else
	    {
		this._srv_cfg = _.merge(this._srv_cfg, srv_cfg);
	    }
	},

	/**
	 * @ngdoc method
	 * @name FlAPIService#getServiceConfig
	 * @classmethod
	 * @description Gets the current global service default configuration.
	 *
	 * @return {Object} Returns a copy of the current default configuration.
	 */

	getServiceConfig: function() {
	    return _.merge({ }, this._srv_cfg);
	}
    },
    extensions: [ ]
});

FlAPIService._srv_cfg = _.merge({ }, DEFAULT_SRV_CFG);

/**
 * @ngdoc type
 * @name FlNestedAPIService
 * @extends FlAPIService
 * @module fl.api_services
 * @description FlNestedAPIService is the base class for API services that communicate with a
 *  {@sref Rails-nested-resources Rails nested resource}.
 *  This class modifies {@sref FlAPIService} to support the structure of nested resource APIs.
 *  It manages both standard and shallow nested resources, based on the value of the configuration
 *  variable **shallow_root_url_template**.
 *
 *  Like for {@sref FlAPIService}, there are two ways to use this service:
 *  1. Create an instance of FlAPIService with appropriate configuration.
 *  2. Define a subclass that encapsulates the configuration and optionally also adds API-specific
 *     entry points.
 *
 *  See the documentation for {@sref FlAPIService} for a discussion of these two approaches; we recommend
 *  creating subclasses.
 */

let FlNestedAPIService = FlClassManager.make_class({
    name: 'FlNestedAPIService',
    superclass: 'FlAPIService',
    /**
     * @ngdoc method
     * @name FlNestedAPIService#constructor
     * @description The constructor; called during `new` creation.
     *  Note that subclasses are expected to pass the parent resource's object or identifier as
     *  additional arguments.
     *
     * @param {Object} api_cfg Configuration for the API object; the following documentation lists
     *  options that are specific to this class; for the common ones, see {@sref FlAPIService#constructor}.
     * @property {String} api_cfg.shallow_root_url_template The template used to generate the shallow
     *  root URL. If this option is present, the instance expects that the Rails API uses a shallow
     *  setup, where the `index` and `create` actions are nested within a parent resource, and
     *  `show`, `update`, and `destroy` are scoped outside the parent.
     * @param {Object} srv_cfg Configuration for the service. See {@sref FlAPIService#constructor}
     *  for details.
     */
    initializer: function(api_cfg, srv_cfg) {
	this.__super_init('FlAPIService', api_cfg, srv_cfg);
    },
    instance_properties: {
	/**
	 * @ngdoc property
	 * @name FlAPIService#shallow_root_url_template
	 * @description Getter for **shallow_root_url_template** configuration property.
	 * @return {String} Returns the value of the **shallow_root_url_template** property in the API
	 *  config object. Note that a `null` or `undefined` return value implies that the API is not
	 *  shallow.
	 */

	shallow_root_url_template: {
	    get: function() {
		return this._api_cfg.shallow_root_url_template;
	    }
	}
    },
    instance_methods: {
	/**
	 * @ngdoc method
	 * @name FlNestedAPIService#url_path_for
	 * @description Overrides the base implementation to add support for shallow APIs.
	 *
	 * @param {String} action The name of the action. The implementation supports the standard
	 *  Rails actions `index`, `create`, `show`, `update`, and `destroy`; subclasses can augment this set
	 *  as needed.
	 * @param {Object|Integer} [target] Some actions need a target object whose identifier to place
	 *  in the path. The value is either an object that contains a **id** property, or the
	 *  identifier itself.
	 *
	 * @return {String|null} Returns the URL path for the action; if *action* is not supported,
	 *  returns `null`.
	 */

	url_path_for: function(action, target) {
	    let tpl = this.shallow_root_url_template;

	    // :index and :create are always nested

	    if (_.isNil(tpl) || (action == 'index') || (action == 'create'))
	    {
		return this.__super('FlAPIService', 'url_path_for', action, target);
	    }

	    let root_path = this._expand_url_template(tpl);
	    let tid = (_.isUndefined(target)) ? undefined : this._id(target);

	    if ((action == 'show') || (action == 'update') || (action == 'destroy'))
	    {
		return root_path + '/' + tid + '.json';
	    }
	    else
	    {
		return null;
	    }
	}
    },
    class_properties: {
    },
    class_methods: {
    },
    extensions: [ ]
});

/**
 * @ngdoc service
 * @name FlAPIServiceRegistry
 * @module fl.api_services
 * @requires FlModelFactory
 * @description FlAPIServiceRegistry is a service that implements a registry of API
 *  services. Use this registry to associate a given API service with the object type
 *  it manages.
 */

let FlAPIServiceRegistry = FlClassManager.make_class({
    name: 'FlAPIServiceRegistry',
    initializer: function() {
	this._services = { };
    },
    instance_properties: {
    },
    instance_methods: {
	/**
	 * @ngdoc method
	 * @name FlAPIServiceRegistry#register
	 * @description Register API services provided by a module for model factory services.
	 *  This function is typically called after an {@sref FlAPIService} subclass is defined,
	 *  to associate data types with API service classes.
	 *  For example, a module named **my_service** defines the API service `MyAPIService`,
	 *  which implements the API client for `My::Datum` resources.
	 *  The registration looks like this:
	 *  ```
	 *  let MyDatum = FlClassRegistry.make_class({
	 *    ...
	 *  });
	 *  FlModelFactory.defaultFactory().register('my_service', [
	 *    { service: MyDatum, class_name: 'My::Datum' }
	 *  ]);
	 *
	 *  let MyAPIService = FlClassRegistry.make_class({
	 *    ...
	 *  });
	 *
	 *  FlGlobalAPIServiceRegistry.register('my_service', {
	 *    'MyAPIService': 'My::Datum'
	 *  });
	 *  ```
	 *
	 * @param {String} module The module name.
	 * @param {Object} services A hash mapping the name of API services provided by the module
	 *  to model service names. Properties are API service names, and their values the
	 *  corresponding model service type name.
	 */

	register: function(module, services) {
	    let self = this;

	    _.forEach(services, function(sv, sk) {
		let k = self._normalize_name(sv);
		if (self._services[k])
		{
		    console.log("(FlAPIServiceRegistry): model service '"
				+ sv + "' is already registered with API service '"
				+ self._services[k].api_service + "'");
		}
		self._services[k] = { module: module, api_service: sk };
	    });
	},

	/**
	 * @ngdoc method
	 * @name FlAPIServiceRegistry#unregister
	 * @description Remove an API service from the registry.
	 *
	 * @param {string} name The service name.
	 */

	unregister: function(name) {
	    let kk = null;
	    let srv = _.find(this._services, function(s, k) {
		if (s.api_service == name)
		{
		    kk = k;
		    return true;
		}
		else
		{
		    return false;
		}
	    });

	    if (kk) delete this._services[kk];
	},

	/**
	 * @ngdoc method
	 * @name FlAPIServiceRegistry#service_info
	 * @description Given a model service name, return info about the corresponding API service.
	 *  Model services are subclasses of {@sref FlModelBase}.
	 *
	 * @param {String} name The model service name (for example, `MyDatum`), or the model
	 *  type name (for example, `My::Datum`) from an object's hash representation;
	 *  the colons will be stripped off.
	 *
	 * @return {Object} If *name* is registered, it returns an object
	 *  containing two properties: *module* is the module where the service resides,
	 *  and *api_service* is the name of the API service.
	 */

	service_info: function(name) {
	    let n = this._normalize_name(name);

	    return (_.isNil(this._services[n])) ? null : this._services[n];
	},

	/**
	 * @ngdoc method
	 * @name FlAPIServiceRegistry#create
	 * @description Given a model service name, return an instance of the
	 *  corresponding API service.
	 *  Model services are subclasses of {@sref FlModelBase}.
	 *  This method uses the class registry to fetch the service and return a new instance.
	 *
	 *  The first argument, *name*, is used to look up the service constructor. All other arguments
	 *  are passed to the constructor using spread syntax (`...args`). This supports constructors
	 *  with arbitrary argument lists. For example, the constructor for a nested API service typically
	 *  accepts the resting resource and the server configuration; when using `create`, pass these two
	 *  in the argument list:
	 *  ```
	 *  const SRV_CFG = { };
	 *  let res = get_my_resource();
	 *  let srv = FlGlobalAPIServiceRegistry.create('MyNestedService', res, SRV_CFG);
	 *  ```
	 *
	 * @param {String} name The model service name (for example, `MyDatum`), or the model
	 *  type name (for example, `My::Datum`) from an object's hash representation;
	 *  the colons will be stripped off.
	 * @param {any} [...args] All the other arguments in the method call are passed to the
	 *  constructor for the service.
	 *
	 * @return {Object} If *name* is registered, it returns an instance
	 *  of the corresponding API service.
	 */

	create: function(name) {
	    var info = this.service_info(name);
	    if (info)
	    {
		let srv = FlClassManager.get_class(info.api_service);
		if (_.isNil(srv))
		{
		    console.log("(FlAPIServiceRegistry): API service '" + info.api_service
				+ "' is not registered with the class manager");
		    return null;
		}

		let args = Array.from(arguments);
		args.shift();

		return new srv(...args);
	    }
	    else
	    {
		console.log("(FlAPIServiceRegistry): no API service for modelizer '" + name + "'");
		return null;
	    }
	},

	_normalize_name: function(s) {
	    return s.replace(/::/g, '');
	}
    },
    class_methods: {
    },
    extensions: [ ]
});

/**
 * @ngdoc service
 * @name FlGlobalAPIServiceRegistry
 * @module fl.api_services
 * @description
 * The global model factory. This is an instance of {@sref FlAPIServiceRegistry} that is globally accessible
 * and can be used as the applicationwide API service registry.
 */

const FlGlobalAPIServiceRegistry = new FlAPIServiceRegistry();

module.exports = { FlAPIService, FlNestedAPIService, FlAPIServiceRegistry, FlGlobalAPIServiceRegistry };


text:
package org.apache.drill.exec.rpc;

import io.netty.buffer.ByteBuf;

import com.google.protobuf.MessageLite;

public abstract class ListeningCommand<T extends MessageLite, C extends RemoteConnection> implements RpcCommand<T, C> {
  static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(ListeningCommand.class);

  private final RpcOutcomeListener<T> listener;

  public ListeningCommand(RpcOutcomeListener<T> listener) {
    this.listener = listener;
  }

  public abstract void doRpcCall(RpcOutcomeListener<T> outcomeListener, C connection);

  @Override
  public void connectionAvailable(C connection) {

    doRpcCall(new DeferredRpcOutcome(), connection);
  }

  @Override
  public void connectionSucceeded(C connection) {
    connectionAvailable(connection);
  }

  private class DeferredRpcOutcome implements RpcOutcomeListener<T> {

    @Override
    public void failed(RpcException ex) {
      listener.failed(ex);
    }

    @Override
    public void success(T value, ByteBuf buf) {
      listener.success(value, buf);
    }

  }

  @Override
  public void connectionFailed(FailureType type, Throwable t) {
    listener.failed(RpcException.mapException(
        String.format("Command failed while establishing connection.  Failure type %s.", type), t));
  }

}

redpajama_set_name: RedPajamaGithub


text:
using namespace vv;

value::regex::regex(const std::regex& val, const std::string& str)
  : basic_object {builtin::type::regex},
    value        {val, str}
{ }

value::regex_result::regex_result(gc::managed_ptr str, std::smatch&& val)
  : basic_object     {builtin::type::regex_result},
    value            {val, str}
{ }


text:
BOOST_FIXTURE_TEST_SUITE(TestUTXO, MWEBTestingSetup)

BOOST_AUTO_TEST_CASE(TxUTXO)
{
    CAmount amount = 12345;
    BlindingFactor blind;
    Output output = Output::Create(
        &blind,
        SecretKey::Random(),
        StealthAddress::Random(),
        amount
    );
    Commitment commit = Commitment::Switch(blind, amount);

    int32_t blockHeight = 20;
    mmr::LeafIndex leafIndex = mmr::LeafIndex::At(5);
    UTXO utxo{
        blockHeight,
        mmr::LeafIndex(leafIndex),
        Output(output)
    };

    //
    // Serialization
    //
    {
        std::vector<uint8_t> serialized = utxo.Serialized();

        Deserializer deserializer(serialized);
        BOOST_REQUIRE(deserializer.Read<int32_t>() == blockHeight);
        BOOST_REQUIRE(mmr::LeafIndex::At(deserializer.Read<uint64_t>()) == leafIndex);
        BOOST_REQUIRE(deserializer.Read<Output>() == output);
    }

    //
    // Getters
    //
    {
        BOOST_REQUIRE(utxo.GetBlockHeight() == blockHeight);
        BOOST_REQUIRE(utxo.GetLeafIndex() == leafIndex);
        BOOST_REQUIRE(utxo.GetOutput() == output);
        BOOST_REQUIRE(utxo.GetCommitment() == commit);
        BOOST_REQUIRE(utxo.GetRangeProof() == output.GetRangeProof());
        BOOST_REQUIRE(utxo.BuildProofData() == output.BuildProofData());
    }
}

BOOST_AUTO_TEST_SUITE_END()


text:
<ion-header>
  <ion-navbar>
    <ion-title>
      Ionic Blank
    </ion-title>
  </ion-navbar>
</ion-header>

<ion-content class="page-home" padding>
  The world is your oyster.

    If you get lost, the docs will be your guide.

  <button ion-button block (click)="btnCamara()">Cámara</button>
  <button ion-button block (click)="btnGaleria()">Galería</button>
  <ion-card>

Picture

Empty

  </ion-card>
</ion-content>


text:
using System;
using System.Collections.Generic;
using System.Linq;
using Melanchall.DryWetMidi.Common;
using Melanchall.DryWetMidi.MusicTheory;
using Melanchall.DryWetMidi.Interaction;

namespace Melanchall.DryWetMidi.Composing
{
    /// <summary>
    /// Provides a fluent API to build an instance of the <see cref="Composing.Pattern"/>.
    /// </summary>
    /// <example>
    /// <para>Following example shows how to create first four bars of Beethoven's 'Moonlight Sonata':</para>
    /// <code language="csharp">
    /// // Define a chord for bass part which is just an octave
    /// var bassChord = new[] { Interval.Twelve };
    ///
    /// // Build the composition
    /// var pattern = new PatternBuilder()
    ///
    ///     // The length of all main theme's notes within four first bars is
    ///     // triplet eight so set it which will free us from necessity to specify
    ///     // the length of each note explicitly
    ///     .SetNoteLength(MusicalTimeSpan.Eighth.Triplet())
    ///
    ///     // Anchor current time (start of the pattern) to jump to it
    ///     // when we'll start to program bass part
    ///     .Anchor()
    ///
    ///     // We will add notes relative to G#3.
    ///     // Instead of Octave.Get(3).GSharp it is possible to use Note.Get(NoteName.GSharp, 3)
    ///     .SetRootNote(Octave.Get(3).GSharp)
    ///
    ///     // Add first three notes and repeat them seven times which will
    ///     // give us two bars of the main theme
    ///                           // G#3
    ///     .Note(Interval.Zero)  // +0  (G#3)
    ///     .Note(Interval.Five)  // +5  (C#4)
    ///     .Note(Interval.Eight) // +8  (E4)
    ///     .Repeat(3, 7)         // repeat three previous notes seven times
    ///
    ///     // Add notes of the next two bars
    ///                           // G#3
    ///     .Note(Interval.One)   // +1  (A3)
    ///     .Note(Interval.Five)  // +5  (C#4)
    ///     .Note(Interval.Eight) // +8  (E4)
    ///     .Repeat(3, 1)         // repeat three previous notes
    ///     .Note(Interval.One)   // +1  (A3)
    ///     .Note(Interval.Six)   // +6  (D4)
    ///     .Note(Interval.Ten)   // +10 (F#4)
    ///     .Repeat(3, 1)         // repeat three previous notes
    ///                           // reaching the end of third bar
    ///     .Note(Interval.Zero)  // +0  (G#3)
    ///     .Note(Interval.Four)  // +4  (C4)
    ///     .Note(Interval.Ten)   // +10 (F#4)
    ///     .Note(Interval.Zero)  // +0  (G#3)
    ///     .Note(Interval.Five)  // +5  (C#4)
    ///     .Note(Interval.Eight) // +8  (E4)
    ///     .Note(Interval.Zero)  // +0  (G#3)
    ///     .Note(Interval.Five)  // +5  (C#4)
    ///     .Note(Intervaln.Seven) // +7  (D#4)
    ///     .Note(-Interval.Two)  // -2  (F#3)
    ///     .Note(Interval.Four)  // +4  (C4)
    ///     .Note(Interval.Seven) // +7  (D#4)
    ///
    ///     // Now we will program bass part. To start adding notes from the
    ///     // beginning of the pattern we need to move to the anchor we set
    ///     // above
    ///     .MoveToFirstAnchor()
    ///
    ///     // First two chords have whole length
    ///     .SetNoteLength(MusicalTimeSpan.Whole)
    ///
    ///                                             // insert a chord relative to
    ///     .Chord(bassChord, Octave.Get(2).CSharp) // C#2 (C#2, C#3)
    ///     .Chord(bassChord, Octave.Get(1).B)      // B1  (B1, B2)
    ///
    ///     // Remaining four chords has half length
    ///     .SetNoteLength(MusicalTimeSpan.Half)
    ///
    ///     .Chord(bassChord, Octave.Get(1).A)      // A1  (A1, A2)
    ///     .Chord(bassChord, Octave.Get(1).FSharp) // F#1 (F#1, F#2)
    ///     .Chord(bassChord, Octave.Get(1).GSharp) // G#1 (G#1, G#2)
    ///     .Repeat()                               // repeat the previous chord
    ///
    ///     // Build a pattern that can be then saved to a MIDI file
    ///     .Build();
    /// </code>
    /// </example>
    public sealed partial class PatternBuilder
    {
        #region Constants

        /// <summary>
        /// Default velocity that will be applied to all further notes and chords if it's not
        /// specified explicitly. Velocity can be altered with <see cref="SetVelocity(SevenBitNumber)"/>.
        /// </summary>
        public static readonly SevenBitNumber DefaultVelocity = Interaction.Note.DefaultVelocity;

        /// <summary>
        /// Default length that will be applied to all further notes and chords if it's not
        /// specified explicitly. The length can be altered with <see cref="SetNoteLength(ITimeSpan)"/>.
        /// </summary>
        public static readonly ITimeSpan DefaultNoteLength = MusicalTimeSpan.Quarter;

        /// <summary>
        /// Default step size that will be applied to all further move operations if it's not
        /// specified explicitly. Step size can be altered with <see cref="SetStep(ITimeSpan)"/>.
        /// </summary>
        public static readonly ITimeSpan DefaultStep = MusicalTimeSpan.Quarter;

        /// <summary>
        /// Default octave further notes and chords will be relative to if it's not
        /// specified explicitly. Octave can be altered with <see cref="SetOctave"/>.
        /// </summary>
        public static readonly Octave DefaultOctave = Octave.Middle;

        /// <summary>
        /// Default root note further notes will be based on if it's not specified explicitly.
        /// Root note can be altered with <see cref="SetRootNote(MusicTheory.Note)"/>.
        /// </summary>
        public static readonly MusicTheory.Note DefaultRootNote = Octave.Middle.C;

        #endregion

        #region Fields

        private readonly List<PatternAction> _actions = new List<PatternAction>();

        private readonly Dictionary<object, int> _anchorCounters = new Dictionary<object, int>();
        private int _globalAnchorsCounter = 0;

        #endregion

        #region Constructor

        /// <summary>
        /// Initializes a new instance of the <see cref="PatternBuilder"/>.
        /// </summary>
        public PatternBuilder()
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="PatternBuilder"/> with the specified pattern.
        /// </summary>
        /// <param name="pattern">Pattern to initialize builder with.</param>
        /// <remarks>
        /// <para>
        /// This constructor is equivalent to calling default one followed by
        /// <see cref="ReplayPattern(Composing.Pattern)"/> call. Using this constructor pattern builder's
        /// current position will be placed right after <paramref name="pattern"/> so all further actions
        /// will be relative to the end of <paramref name="pattern"/> rather than zero.
        /// </para>
        /// <para>
        /// To start with fresh pattern and place data starting from zero use <see cref="PatternBuilder()"/>
        /// constructor.
        /// </para>
        /// </remarks>
        /// <exception cref="ArgumentNullException"><paramref name="pattern"/> is <c>null</c>.</exception>
        public PatternBuilder(Pattern pattern)
        {
            ThrowIfArgument.IsNull(nameof(pattern), pattern);

            ReplayPattern(pattern);
        }

        #endregion

        #region Properties

        /// <summary>
        /// Gets the velocity that will be applied to all further notes and chords if it's not
        /// specified explicitly. Velocity can be altered with <see cref="SetVelocity(SevenBitNumber)"/>.
        /// </summary>
        /// <remarks>
        /// <para>
        /// There are methods to add notes and chords that don't take velocity as an argument. In these
        /// cases the value of the <see cref="Velocity"/> property will be used. For example,
        /// <see cref="Note(MusicTheory.Note)"/> or <see cref="Chord(IEnumerable{Interval}, MusicTheory.Note)"/>.
        /// </para>
        /// </remarks>
        public SevenBitNumber Velocity { get; private set; } = DefaultVelocity;

        /// <summary>
        /// Gets the length that will be applied to all further notes and chords if it's not
        /// specified explicitly. The length can be altered with <see cref="SetNoteLength(ITimeSpan)"/>.
        /// </summary>
        /// <remarks>
        /// <para>
        /// There are methods to add notes and chords that don't take length as an argument. In these
        /// cases the value of the <see cref="NoteLength"/> property will be used. For example,
        /// <see cref="Note(MusicTheory.Note)"/> or <see cref="Chord(IEnumerable{Interval}, MusicTheory.Note)"/>.
        /// </para>
        /// </remarks>
        public ITimeSpan NoteLength { get; private set; } = DefaultNoteLength;

        /// <summary>
        /// Gets the step size that will be applied to all further move operations if it's not
        /// specified explicitly. Step size can be altered with <see cref="SetStep(ITimeSpan)"/>.
        /// </summary>
        /// <remarks>
        /// <para>
        /// There are methods to move current builder's position that don't take step as an argument. In these
        /// cases the value of the <see cref="Step"/> property will be used. For example,
        /// <see cref="StepForward()"/> or <see cref="StepBack()"/>.
        /// </para>
        /// </remarks>
        public ITimeSpan Step { get; private set; } = DefaultStep;

        /// <summary>
        /// Gets the octave further notes and chords will be relative to if it's not
        /// specified explicitly. Octave can be altered with <see cref="SetOctave"/>.
        /// </summary>
        /// <remarks>
        /// <para>
        /// There are methods to add notes and chords where octave is not specified explicitly. In these
        /// cases the value of the <see cref="Octave"/> property will be used. For example,
        /// <see cref="Note(NoteName)"/> or <see cref="Chord(IEnumerable{Interval}, NoteName)"/>.
        /// </para>
        /// </remarks>
        public Octave Octave { get; private set; } = DefaultOctave;

        /// <summary>
        /// Gets the root note further notes will be based on if it's not specified explicitly.
        /// Root note can be altered with <see cref="SetRootNote(MusicTheory.Note)"/>.
        /// </summary>
        /// <remarks>
        /// <para>
        /// There are methods to add notes by interval where root note is not specified explicitly.
        /// In these cases the value of the <see cref="RootNote"/> property will be used. For example,
        /// <see cref="Note(Interval)"/>.
        /// </para>
        /// </remarks>
        public MusicTheory.Note RootNote { get; private set; } = DefaultRootNote;

        #endregion

        #region Methods

        /// <summary>
        /// Build an instance of the <see cref="Composing.Pattern"/> holding all actions
        /// defined via builder.
        /// </summary>
        /// <returns>An instance of the <see cref="Composing.Pattern"/> that holds all actions
        /// defined by the current <see cref="PatternBuilder"/>.</returns>
        public Pattern Build()
        {
            return new Pattern(_actions.ToList());
        }

        /// <summary>
        /// Replays all actions contained in the specified pattern.
        /// </summary>
        /// <param name="pattern">Pattern to replay actions of.</param>
        /// <remarks>
        /// <para>
        /// <see cref="ReplayPattern(Composing.Pattern)"/> inserts all actions from <paramref name="pattern"/>
        /// that were added by using methods of <see cref="PatternBuilder"/> to produce the specified pattern.
        /// These actions will be added as separate ones unlike <see cref="Pattern(Composing.Pattern)"/> which
        /// adds pattern as one single action.
        /// </para>
        /// </remarks>
        /// <returns>The current <see cref="PatternBuilder"/>.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="pattern"/> is <c>null</c>.</exception>
        public PatternBuilder ReplayPattern(Pattern pattern)
        {
            ThrowIfArgument.IsNull(nameof(pattern), pattern);

            foreach (var action in pattern.Actions)
            {
                AddAction(action);
            }

            return this;
        }

        private PatternBuilder AddAction(PatternAction patternAction)
        {
            var addAnchorAction = patternAction as AddAnchorAction;
            if (addAnchorAction != null)
                UpdateAnchorsCounters(addAnchorAction.Anchor);

            _actions.Add(patternAction);
            return this;
        }

        private int GetAnchorCounter(object anchor)
        {
            if (anchor == null)
                return _globalAnchorsCounter;

            int counter;
            if (!_anchorCounters.TryGetValue(anchor, out counter))
                throw new ArgumentException($"Anchor {anchor} doesn't exist.", nameof(anchor));

            return counter;
        }

        private void UpdateAnchorsCounters(object anchor)
        {
            _globalAnchorsCounter++;

            if (anchor == null)
                return;

            if (!_anchorCounters.ContainsKey(anchor))
                _anchorCounters.Add(anchor, 0);

            _anchorCounters[anchor]++;
        }

        #endregion
    }
}


text:
import os
import glob
import subprocess
import sys

from bcbio import utils
from bcbio.provenance import do
from bcbio.pipeline import config_utils
from bcbio.pipeline import datadict as dd
from bcbio import bam
from bcbio.chipseq import antibodies
from bcbio.log import logger
from bcbio.distributed.transaction import file_transaction

def run(name, chip_bam, input_bam, genome_build, out_dir, method, resources, data):
    """
    Run macs2 for chip and input samples avoiding
    errors due to samples.
    """
    # output file name need to have the caller name
    config = dd.get_config(data)
    out_file = os.path.join(out_dir, name + "_peaks_macs2.xls")
    macs2_file = os.path.join(out_dir, name + "_peaks.xls")
    if utils.file_exists(out_file):
        _compress_and_sort_bdg_files(out_dir, data)
        return _get_output_files(out_dir)
    macs2 = config_utils.get_program("macs2", config)
    antibody = dd.get_antibody(data)
    if antibody:
        antibody = antibody.lower()
        if antibody not in antibodies.SUPPORTED_ANTIBODIES:
            logger.error(f"{antibody} specified, but not listed as a supported antibody. Valid antibodies are {antibodies.SUPPORTED_ANTIBODIES}. If you know your antibody "
                        f"should be called with narrow or broad peaks, supply 'narrow' or 'broad' as the antibody.")
            sys.exit(1)
        antibody = antibodies.ANTIBODIES[antibody]
        logger.info(f"{antibody.name} specified, using {antibody.peaktype} peak settings.")
        peaksettings = select_peak_parameters(antibody)
    elif method == "atac":
        logger.info(f"ATAC-seq specified, using narrow peak settings.")
        peaksettings = " "
    else:
        peaksettings = " "
    options = " ".join(resources.get("macs2", {}).get("options", ""))
    genome_size = bam.fasta.total_sequence_length(dd.get_ref_file(data))
    genome_size = "" if options.find("-g") > -1 else "-g %s" % genome_size
    paired = "-f BAMPE" if bam.is_paired(chip_bam) else ""
    with utils.chdir(out_dir):
        cmd = _macs2_cmd(data)
        cmd += peaksettings
        try:
            do.run(cmd.format(**locals()), "macs2 for %s" % name)
            utils.move_safe(macs2_file, out_file)
        except subprocess.CalledProcessError:
            raise RuntimeWarning("macs2 terminated with an error. "
                                 "Please, check the message and report "
                                 "error if it is related to bcbio. "
                                 "You can add specific options for the sample "
                                 "setting resources as explained in docs: "
                                 "https://bcbio-nextgen.readthedocs.org/en/latest/contents/configuration.html#sample-specific-resources")
    _compress_and_sort_bdg_files(out_dir, data)
    return _get_output_files(out_dir)

def _get_output_files(out_dir):
    fns = [os.path.abspath(fn) for fn in glob.glob(os.path.join(out_dir, "*"))]
    peaks = None
    for fn in fns:
        if fn.endswith("narrowPeak"):
            peaks = fn
            break
        elif fn.endswith("broadPeak"):
            peaks = fn
            break
    return {"main": peaks, "macs2": fns}

def _compress_and_sort_bdg_files(out_dir, data):
    for fn in glob.glob(os.path.join(out_dir, "*bdg")):
        out_file = fn + ".gz"
        if utils.file_exists(out_file):
            continue
        bedtools = config_utils.get_program("bedtools", data)
        with file_transaction(out_file) as tx_out_file:
            cmd = f"sort -k1,1 -k2,2n {fn} | bgzip -c > {tx_out_file}"
            message = f"Compressing and sorting {fn}."
            do.run(cmd, message)

def _macs2_cmd(data):
    """Main command for macs2 tool."""
    method = dd.get_chip_method(data)
    if method.lower() == "chip":
        cmd = ("{macs2} callpeak -t {chip_bam} -c {input_bam} {paired} "
               "{genome_size} -n {name} --bdg {options} ")
    elif method.lower() == "atac":
        cmd = ("{macs2} callpeak -t {chip_bam} --nomodel "
               " {paired} {genome_size} -n {name} --bdg {options}"
               " --nolambda --keep-dup all")
    else:
        raise ValueError("chip_method should be chip or atac.")
    return cmd

def select_peak_parameters(antibody):
    if antibody.peaktype == "broad":
        return " --broad --broad-cutoff 0.05"
    elif antibody.peaktype == "narrow":
        return ""
    else:
        raise ValueError(f"{antibody.peaktype} not recognized.")


text:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="@android:color/white">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        style="@style/AppTheme.View.TextView.Big"
        android:text="@string/station_header"
        android:layout_marginTop="@dimen/small"
        android:layout_marginLeft="@dimen/small"
        android:textStyle="bold" />

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal"
        android:weightSum="2">

        <TableLayout

            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="match_parent"
            android:shrinkColumns="*"
            android:layout_marginTop="@dimen/small"
            android:layout_marginLeft="@dimen/small"
            android:layout_marginRight="@dimen/small">

            <TableRow android:layout_marginTop="@dimen/tiny">

                <TextView
                    style="@style/AppTheme.View.TextView"
                    android:text="@string/station_country_label" />

                <TextView
                    android:id="@+id/station_country"
                    style="@style/AppTheme.View.TextView"
                    android:gravity="center_horizontal"
                    android:text="@string/station_country_label" />
            </TableRow>

            <TableRow android:layout_marginTop="@dimen/tiny">

                <TextView
                    style="@style/AppTheme.View.TextView"
                    android:text="@string/station_city_label" />

                <TextView
                    android:id="@+id/station_city"
                    style="@style/AppTheme.View.TextView"
                    android:gravity="center_horizontal"
                    android:text="@string/station_city_label" />
            </TableRow>

            <TableRow android:layout_marginTop="@dimen/tiny">

                <TextView
                    style="@style/AppTheme.View.TextView"
                    android:text="@string/station_lat_label" />

                <TextView
                    android:id="@+id/station_lat"
                    style="@style/AppTheme.View.TextView"
                    android:gravity="center_horizontal"
                    android:text="@string/station_lat_label" />
            </TableRow>

            <TableRow android:layout_marginTop="@dimen/tiny">

                <TextView
                    style="@style/AppTheme.View.TextView"
                    android:text="@string/station_lon_label" />

                <TextView
                    android:id="@+id/station_lon"
                    style="@style/AppTheme.View.TextView"
                    android:gravity="center_horizontal"
                    android:text="@string/station_lon_label" />
            </TableRow>

        </TableLayout>

        <TextView
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            style="@style/AppTheme.View.TextView"
            android:paddingTop="@dimen/bigger"
            android:layout_marginRight="@dimen/small"
            android:text="@string/station_desc" />
    </LinearLayout>

</LinearLayout>


text:
module EmberDataActiveModelParser
  VERSION = "0.0.2"
end


text:
from time import sleep
from pyunicon.UCKeyboard import UCKeyboard
from pyunicon.UCMouse import UCMouse
from pyunicon.UCScreen import UCScreen
from pyunicon.util import UCKey

__author__ = 'cansik'

screen = UCScreen()
print(screen.get_size())

sleep(1)

mouse = UCMouse()
print('X, Y: %s, %s' % mouse.get_position())
mouse.move(200, 200)
print('X, Y: %s, %s' % mouse.get_position())
print('sleeping...')
print('moving...')
mouse.move(1000, 300)
print('X, Y: %s, %s' % mouse.get_position())
mouse.move(29, 594)
print('X, Y: %s, %s' % mouse.get_position())
print('clicking...')

mouse.click_left()

sleep(1)

keyboard = UCKeyboard()
print("send key")

keyboard.key_down(UCKey.UC_LEFT_SHIFT)
keyboard.send_key(UCKey.UC_H)
keyboard.key_up(UCKey.UC_LEFT_SHIFT)
keyboard.send_key(UCKey.UC_A)
keyboard.send_key(UCKey.UC_L)
keyboard.send_key(UCKey.UC_L)
keyboard.send_key(UCKey.UC_O)
keyboard.send_key(UCKey.UC_SPACE)
keyboard.send_key(UCKey.UC_W)
keyboard.send_key(UCKey.UC_O)
keyboard.send_key(UCKey.UC_R)
keyboard.send_key(UCKey.UC_L)
keyboard.send_key(UCKey.UC_D)
keyboard.send_key(UCKey.UC_RETURN)


text:
<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="lib_name">CuXtom Cam Lib</string>
</resources>