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

Class: bop/js/spi/BOP

SPI object representing a single Business Object Provider (shortly known as BOP).

Contains of two main parts:

  • EntityProvider which is an abstract representation of the data structure used by the REST service calls.
  • OperationProvider which is an abstract representation of all REST service calls available on that particular set of Entities.

For example, if you have REST service like this:

  • GET /employeeAll
    --> Which gets all employees. Lets assume only Fistname and Lastname fields are returned.
  • GET /employee/{id}
    --> Which gets single employee defined using the given ID. Lets 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 custom BOP need to contains:
  • One EntityProvider with a single Entity named "Employee" which will consists of Property for each field/column these REST calls are working with. So in the case described above you will have four Properties: "Firstname", "Lastname", "Age" and "Salary" inside your Employee Entity.
  • One OperationProvider with a 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 addapt automatically.

This object is pure, fully-customizable BOP with no restrictions. If you don't need any special treatment and rather looking for some simplification where you don't need to take care about parsing dependencies, generating static RT code and other parts of the Extension lifecycle, you can alternatively use SimpleBOP which is build on top the plain BOP and takes care of those stuff for you.

Version:
  • 17.1.1
Source:
See:
Example

Example of typical implementation of custom BOP.

define([
    '{{package}}/js/CustomEntityProvider',
    '{{package}}/js/CustomOperationProvider'
], function (
    CustomEntityProvider,
    CustomOperationProvider
) {

    var CustomBOP = function () {
    };

    CustomBOP.prototype.getEntityProvider = function () {
        return new CustomEntityProvider();
    };

    CustomBOP.prototype.getOperationProvider = function () {
        return new CustomOperationProvider();
    };

    CustomBOP.prototype.getId = function () {
        return 'my.custom.bop';
    };

    return new CustomBOP();
});

Methods

getEntityProvider() → {bop/js/spi/entity/EntityProvider}

stable API

Returns an instance of EntityProvider associated with this BOP.

Version:
  • 17.1.1
Source:
Returns:
Type
bop/js/spi/entity/EntityProvider
Examples

Typical implementation returning an instance of your hand-written EntityProvider.

CustomBOP.prototype.getEntityProvider = function () {
    return new CustomEntityProvider();
};

Example of typical implementation of custom EntityProvider which is used inside BOP.

define([
    'bop/js/api/entity/DataModelFactory',
    'entity/js/api/PropertyType'
], function (
    DataModelFactory,
    PropertyType
) {

    var CustomEntityProvider = function () {
        var firstname = DataModelFactory.createProperty({
            id: 'my.custom.bop.Employee.Firstname',
            name: 'Firstname',
            type: PropertyType.TEXT
        });
        var lastname = DataModelFactory.createProperty({
            id: 'my.custom.bop.Employee.Lastname',
            name: 'Lastname',
            type: PropertyType.TEXT
        });
        var age = DataModelFactory.createProperty({
            id: 'my.custom.bop.Employee.Age',
            name: 'Age',
            type: PropertyType.NUMBER
        });
        var employee = DataModelFactory.createEntity({
            id: 'my.custom.bop.Employee',
            singularName: 'Employee',
            pluralName: 'Employees',
            properties: [firstname, lastname, age]
        });

        this._entities = [employee];
    };

    CustomEntityProvider.prototype.getEntities = function() {
        return this._entities;
    };

    return CustomEntityProvider;
});

getId() → {String}

stable API

Gets an unique identifier of this BOP.

Version:
  • 17.1.1
Source:
Returns:
Type
String

getOperationProvider() → {bop/js/spi/operation/OperationProvider}

stable API

Returns an instance of OperationProvider associated with this BOP.

Version:
  • 17.1.1
Source:
Returns:
Type
bop/js/spi/operation/OperationProvider
Examples

Typical implementation returning an instance of your hand-written OperationProvider.

CustomBOP.prototype.getOperationProvider = function () {
    return new CustomOperationProvider();
};

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

define([
    'bop/js/api/operation/OperationBuilder',
    'bop/js/api/operation/OperationInput',
    'bop/js/api/operation/OperationOutput',
    'operation/js/api/Operation',
    'operation/js/api/Operator',
    '{{package}}/js/Employee'
], function (
    OperationBuilder,
    OperationInput,
    OperationOutput,
    Operation,
    Operator,
    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) {
                // Lets 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;
});