JavaScript Extension Development API for Oracle Visual Builder Cloud Service - Classic Applications

Class: bop/js/spi/operation/OperationProvider

SPI object representing a single Operation Provider.

OperationProvider is responsible for providing all Operation that can be performed on Entities defined in the corresponding EntityProvider.

For example, if you have REST service like this:

  • GET /employeeAll
    --> Which gets all employees. Assume only Fistname and Lastname fields are returned.
  • GET /employee/{id}
    --> Which gets single employee defined using the given ID. Assume all fields (Firstname, Lastname, Age and Salary) are returned.
  • CREATE /employee
    --> Which creates new employee.
  • DELETE /employee/{id}
    --> Which delete employee using the given ID.
  • UPDATE /employee/{id}
    --> Which updates data for employee with the given ID.
Your OperationProvider need to have the single Operation created for each of these REST calls. Those Operations needs to be described precisely using OperationBuilder, OperationInput and OperationOutput objects so that Application Builder allow Business User to use only UI features that are supported by these REST call itself. For example Operation that correspond to the GET/employeeAll REST call, need to define and use different OperationOutput because the REST call returns only two fields instead of the full set of them. Based to that information, Application Builder UI adapt automatically.

OperationProvider is one of the two main parts required to implement custom BOP. The other one is EntityProvider.

Version:
  • 17.1.1
Source:
See:
Examples

Example of typical implementation of custom OperationProvider used inside of the custom BOP.

define([
    'operation/js/api/Operation',
    'operation/js/api/Operator',
    'bop/js/api/operation/OperationBuilder',
    'bop/js/api/operation/OperationInput',
    'bop/js/api/operation/OperationOutput',
    '{{package}}/js/Employee'
], function (
    Operation,
    Operator,
    OperationBuilder,
    OperationInput,
    OperationOutput,
    Employee
) {

    var CustomOperationProvider = function () {
        this._operations = [];

        var employee = Abcs.Entities().findById('my.custom.bop.Employee');
        var id = employee.getProperty('my.custom.bop.Employee.ID');
        var firstname = employee.getProperty('my.custom.bop.Employee.Firstname');
        var lastname = employee.getProperty('my.custom.bop.Employee.Lastname');
        var age = employee.getProperty('my.custom.bop.Employee.Age');

        var partialOutput = new OperationOutput({
            entity: employee
        }).property(firstname).
            property(lastname);

        var idInput = new OperationInput({
            entity: employee
        }).parameter({
            property: id,
            required: true
        });

        var firstnameLastnameInput = new OperationInput({
            entity: employee
        }).parameter(firstname).
            parameter(lastname).
            operators([
                Operator.EQUALS,
                Operator.NOT_EQUALS,
                Operator.STARTS_WITH,
                Operator.ENDS_WITH,
                Operator.CONTAINS,
                Operator.NOT_CONTAINS
            ]);

        var getAllEmployees = new OperationBuilder({
            name: 'Find all Employees',
            type: Operation.Type.READ_MANY,
            performs: function() {
                // Assume there is an Employee object as part of our BOP extension implementation which builds the URL based
                // on the "operationInputData" values, makes the real REST call and returns relevant OperationResult instance
                return Promise.resolve(Employee.getAll());
            }
        }).description('Longer description of what this Operation does').
            returns(partialOutput).
            takes(firstnameLastnameInput).
            build();

        var getEmployeeByID = new OperationBuilder({
            name: 'Find Employee by ID',
            type: Operation.Type.READ_ONE,
            performs: function(operationInputData) {
                // Assume there is an Employee object as part of our BOP extension implementation which builds the URL based
                // on the "operationInputData" values, makes the real REST call and returns relevant OperationResult instance
                return Promise.resolve(Employee.findByID(operationInputData));
            }
        }).specialType(Operation.SpecialType.QUERY_BY_ID).
            takes(idInput).
            returns(employee).
            build();

        // Register all relevant operations
        this._operations.push(getAllEmployees);
        this._operations.push(getEmployeeByID);

        // ..include the same for all other REST calls
    };

    CustomOperationProvider.prototype.getOperations = function() {
        return this._operations;
    };

    return CustomOperationProvider;
});

Example of typical implementation of custom OperationProvider used inside of the custom BOP that defines a ResourceProvider so that it can make use of the default authenticator

define([
    'bop/js/api/operation/BOPAuthenticators',
    'bop/js/api/operation/OperationBuilder',
    'bop/js/api/operation/OperationInput',
    'bop/js/api/operation/OperationOutput',
    'operation/js/api/Operation',
    'operation/js/api/Operator'
], function (
    BOPAuthenticators,
    OperationBuilder,
    OperationInput,
    OperationOutput,
    Operation,
    Operator
) {

    var CustomOperationProvider = function (dependencies) {
        var self = this;
        this._dependencies = dependencies;
        this._operations = [];

        var employee = Abcs.Entities().findById('my.custom.bop.Employee');
        var id = employee.getProperty('my.custom.bop.Employee.ID');
        var firstname = employee.getProperty('my.custom.bop.Employee.Firstname');
        var lastname = employee.getProperty('my.custom.bop.Employee.Lastname');
        var age = employee.getProperty('my.custom.bop.Employee.Age');

        var employeeCollectionResouce = 'my.custom.bop.Employee[]'
        var employeeResouce = 'my.custom.bop.Employee'

        var partialOutput = new OperationOutput({
            entity: employee
        }).property(firstname).
            property(lastname);

        var idInput = new OperationInput({
            entity: employee
        }).parameter({
            property: id,
            required: true
        });

        var firstnameLastnameInput = new OperationInput({
            entity: employee
        }).parameter(firstname).
            parameter(lastname).
            operators([
                Operator.EQUALS,
                Operator.NOT_EQUALS,
                Operator.STARTS_WITH,
                Operator.ENDS_WITH,
                Operator.CONTAINS,
                Operator.NOT_CONTAINS
            ]);

        var getAllEmployees = new OperationBuilder({
            name: 'Find all Employees',
            type: Operation.Type.READ_MANY,
            performs: function() {
                // Make an AJAX request to get hold of the list of employees
                return self.getAuthenticator({
                   url : ....
                   method : ....
                });
            }
        }).description('Longer description of what this Operation does').
            returns(partialOutput).
            takes(firstnameLastnameInput).
            build();

        var getEmployeeByID = new OperationBuilder({
            name: 'Find Employee by ID',
            type: Operation.Type.READ_ONE,
            performs: function(operationInputData) {
                // Make an AJAX request to get hold of the detauls of an
                // employee
                return self.getAuthenticator({
                   url : ....
                   method : ....
                });
            }
        }).specialType(Operation.SpecialType.QUERY_BY_ID).
            takes(idInput).
            returns(employee).
            build();

        // Register all relevant operations
        this._operations.push(getAllEmployees);
        this._operations.push(getEmployeeByID);

        // ..include the same for all other REST calls
    };

    CustomOperationProvider.prototype.getOperations = function() {
        return this._operations;
    };

    // Required if using the built in authenticator
    CustomOperationProvider.prototype.getAuthenticator = function() {
        return BOPAuthenticators.getDefault(
            this._dependencies,
            new CustomResourceProvider());
    };

    return CustomOperationProvider;
});

define([
    'bop/js/api/resource/Resource',
    'bop/js/spi/resource/ResourceProvider'
], function (
    Resource,
    ResourceProvider
) {

    var CustomResourceProvider = function () {
        var parent = Resource.create({
            id : 'employee_collection',
            template : '/employee',
            entity : 'my.custom.bop.Employee'
        });
        var child = Resource.createChild(parent, {
            id : 'employee_instance',
            template : '{id}',
        });

        this._resources = [parent, child];
    };

    CustomResourceProvider.prototype.getResources = function() {
        return this._resources;
    };

    return CustomResourceProvider;
});

Methods

getAuthenticator() → {bop/js/spi/operation/BOPAuthenticator}

stable API

Returns the default implementation of bop/js/api/operation/BOPAuthenticator but it need to be overriden in most cases to define the white list of allowed resources and there mappings to entities.

Version:
  • 17.1.1
Source:
Returns:
  • The {bop/js/spi/operation/BOPAuthenticator} for this provider.
Type
bop/js/spi/operation/BOPAuthenticator
Examples

Example of typical implementation of custom OperationProvider used inside of the custom BOP that defines a ResourceProvider so that it can make use of the default authenticator

define([
    'bop/js/api/operation/BOPAuthenticators',
    'bop/js/api/operation/OperationBuilder',
    'bop/js/api/operation/OperationInput',
    'bop/js/api/operation/OperationOutput',
    'operation/js/api/Operation',
    'operation/js/api/Operator'
], function (
    BOPAuthenticators,
    OperationBuilder,
    OperationInput,
    OperationOutput,
    Operation,
    Operator
) {

    var CustomOperationProvider = function (dependencies) {
        this._dependencies = dependencies;
    };

    CustomOperationProvider.prototype.getOperations = function() {
        return [];
    };

    // Required if using the built in authenticator
    CustomOperationProvider.prototype.getAuthenticator = function() {
        return BOPAuthenticators.getDefault(
            this._dependencies,
            new CustomResourceProvider());
    };

    return CustomOperationProvider;
});

define([
    'bop/js/api/resource/Resource',
    'bop/js/spi/resource/ResourceProvider'
], function (
    Resource,
    ResourceProvider
) {

    var CustomResourceProvider = function () {
        var parent = Resource.create({
            id : 'employee_collection',
            template : '/employee',
            entity : 'my.custom.bop.Employee'
        });
        var child = Resource.createChild(parent, {
            id : 'employee_instance',
            template : '{id}',
        });

        this._resources = [parent, child];
    };

    CustomResourceProvider.prototype.getResources = function() {
        return this._resources;
    };

    return CustomResourceProvider;
});

Example of typical implementation of custom OperationProvider used inside of the custom BOP that defines a custom BOPAuthenticator so that it can provide it's own authentication method

define([
    'bop/js/api/operation/BOPAuthenticators',
    'bop/js/api/operation/OperationBuilder',
    'bop/js/api/operation/OperationInput',
    'bop/js/api/operation/OperationOutput',
    'operation/js/api/Operation',
    'operation/js/api/Operator'
], function (
    BOPAuthenticators,
    OperationBuilder,
    OperationInput,
    OperationOutput,
    Operation,
    Operator
) {

    var CustomOperationProvider = function () {
    };

    CustomOperationProvider.prototype.getOperations = function() {
        return [];
    };

    // Required if using the built in authenticator
    CustomOperationProvider.prototype.getAuthenticator = function() {
        return new CustomBOPAuthenticator();
    };

    return CustomOperationProvider;
});

define([
    'bop/js/spi/operation/BOPAuthenticator',
    'operation/js/api/OperationResult'
], function (
    BOPAuthenticator,
    OperationResult
) {

    var CustomBOPAuthenticator = function () {
    };

    CustomBOPAuthenticator.prototype.invoke = function(authentication, ajaxObject) {
       return new Promise(function (fulfil, reject) {

           ajaxObject.headers = ajaxObject.headers || {};
           ajavObject.headers['customAuthHeader'] = some key

           // Based on the authenticator so far set up the ajax request
           // with sensible defaults
           //
           $.ajax(ajaxObjectClone).done(function (data, status, jqXHR) {
               fulfil(OperationResult.success(data));
           }).fail(function (jqXHR, textStatus, errorThrown) {
               reject(OperationResult.fail(textStatus, jqXHR.status));
           });
       });
    };

    return CustomBOPAuthenticator;
});

getOperations() → {Array.<operation/js/api/Operation>}

stable API

Gets the array of Operations provided by this OperationProvider.

Version:
  • 17.1.1
Source:
Returns:
Type
Array.<operation/js/api/Operation>