Docs‎ > ‎CA Live API Creator‎ > ‎Rules‎ > ‎

Insert Into From

Context

It is a very common requirement to copy one or more source rows to target rows.  A corollary requirement is that the created target rows are usually children of the source rows, and require proper initialization of their attributes.  The general concept is loosely analogous to the SQL Insert Into Select From command.
  • Auditing
This is simply a copy of the current row, under the proper conditions.  We work a common example below.
  • Deep Copy
It is a common requirement to "clone" a Business Object, meaning a "master" and its related objects.  For example, a customer might like to create a new order by copying an old one.

  • Bill of Materials explosion
This is widely regarded as a particularly tough pattern.  We shall see it is, in fact, a variant of a deep copy, and can be solved with just a few rules.


Solution: Insert Into From

We can provide such services with ad hoc Java code, either in our application or (better, for re-use!) in our Business Logic Components.  But this pattern is so prevalent that this is simply reinventing the wheel.  

We can save cost and increase agility with re-usable Insert Into From service for copying.  We can then invoke these from our Action rules under the appropriate conditions.  This class provides a set of similar services, which we review in the sub-sections below:

 Example  Description Service
Auditing This is simply a copy of the current row, with provisions for audit conditions and target attribute initialization. insertChildFrom

Deep Copy It is a common requirement to "clone" a Business Object, meaning a "master" and its related objects.  For example, a customer might like to create a new order by copying an old one. copyMyAttributesFrom
Bill of Materials Explosion A variation of deep copy insertChildrenFrom 



Examples


Auditing

The most common case of auditing follows the pattern:

When a source object is altered meeting an audit condition,
copy the source object to a child target object,
initializing appropriate target attributes

The Audit Salary Changes example follows this pattern:

When a source object Employee is altered meeting an audit condition of salary changes,
copy the source object to a child target object EmployeeAudit,
initializing appropriate target attributes to record the old salary

So, we simply supply an Event Rule in the employees:

if (row.baseSalary != oldRow.baseSalary)
SysLogic.insertChildFrom("employee_audits", logicContext);

So, from our pattern:
  • the source object employees is the origin of the rule, the audit condition is the salary change
  • the child target object employee_audits is the first parameter
  • the target attribute initialization is described below
Common to all variations of this pattern is the initialization of created objects, described in the sub-section below.


Target Object Attribute Initialization

All variations of this pattern create one or more target objects.  Clearly, a mechanism is required to initialize the attributes of such created objects:
  • copy like-named attributes from parent

  • The system next copies like named attributes from the source to the target.  In the example above, this will set the Salary attribute.

    • set foreign key
    Insert Into always creates 1 or more children of the source object, so we need to set the foreign key of the created child.  In our example, we link the target child EmployeeAudit to the source parent Employee.

    The system uses the heuristic to introspect the target (child) for an entity-type method that returns the type of the source (parent).  (Note: an exception is raised in the rare case where more than one such method is found).

    • copy like-named attributes from source
    This applies only to insertChildrenFrom.  The system next copies like named attributes from the children rows being copied.  In the example above, this will set the Salary attribute.
    • target object derivation rules
    target objects are always saved after they are created, which invokes their business logic.  So, you can define formulas etc on these objects.



    Deep Copy

    << this section is undergoing revision - please skip for now >>

    The copy operation often includes not just (scalar) attributes, but also related data.  For example, if we want to create a new Purchaseorder from an existing one, we need to clone both the Purchaseorder and the Lineitems.

    Business logic is initiated only when performing transactions (inserts, updates and deletes) to the database.  The sections below illustrate you can trigger this logic from either the source (copied) object, or from the target (inserted) object.  You can also build services which expose the functionality more explicitly.  Unlike manually coded services, such services can be thin, since they can invoke the domain-encapsulated business logic.

    Copy from Target

    See clonePurchaseorder example described here, and utilizes the InsertIntoFrom#copyMyAttributesFrom service. This particular example provides an interface  where the client inserts a Purchaseorder, setting an Entity attribute (clonedFrom) as the source of the deep copy.  As above, the functionality is invoked via an action rule:

    /**
     * Deep copy of clonedFrom PO (if non-null) to this new PO.
     */
    @Action
    public void actionClonedFromPurchaseorder() {
    if (logicContext.verb == Verb.INSERT && logicContext.logicNestLevel == 0 && 
                                                 purchaseorder.clonedFrom != null)    {
    String[] deepCopy = ["lineitems", "lineitemUsages"]
    InsertIntoFrom.copyMyAttributesFrom (
                  logicContext,              // indicates current object (copy target)
                  purchaseorder.clonedFrom,  // copy source
                  deepCopy)                  // collections to copy
    }
    }


    Copy from Source

    Another design approach is to update an existing order, whose logic create a copy of itself.  That example is described here.

    Alert: using transient attributes

    You may be tempted to set an transient attribute to trigger the copy operations.  This is actually an excellent idea, but will fail since Hibernate detects updates which involve only transient attributes, and prunes the update.  This of course prevents logic execution.



    Bill of Materials Explosion

    When ordering a Product that is a kit, we want to reduce inventory for each of the components of the kit.

    The key requirement is to populate the SubItems for a kit-based Lineitem (see the database structure), by copying the ProductBillofMaterials to the subItems.  You can do this with the following explodeBillofMaterials Event rule on Lineitem:

     if (logicContext.verb == "INSERT" && row.product.count_components > 0)  {

         SysLogic.insertChildrenFrom("lineitems", row.product.components, logicContext); 

     }


    The remaining logic (4 rules) is simply to properly arrange for quantities (i.e., if you buy 2 planes, you need 8 engines).  The Bill Of Materials Explosion example is an advanced example used in the Training.




    Insert Into Operation

    While there varying formulations of InsertIntoFrom, we can illustrate their operation by describing the example above.  The basic idea is to create a series of (target) Lineitem objects, 1 for each (source) component object.

    There are 3 key players:
    1. Parent - the object that issues the InsertIntoFrom, here a Lineitem

    2. Source - the objects being copies, here a list: lineitem.product.components

    3. Target - the class in which rows are inserted - here, also Lineitem (the created sub items)
    The system iterates over the Source list, creating a target instance that is initialized as follows:
    • copyAttributesFromTo copies like named attributes from the Parent to the Target
    In our example, the Target SubItem is linked to the Order
    • link the Target to the Parent (there is a presumed one-to-many relationship from the Parent to the Target)
    This links the Target SubItem to the Parent Lineitem (role name: kitItem)
    • link the Target to the Source (there is an optional one-to-many relationship from the Parent to the Target, the caller specifies whether this linkage exists with the aLinkToSource parameter
    In our example, this linkage does not occur - the helper used sets the aLinkToSource = false
    • copyAttributesFromTo copies like named attributes from the Source to the Target
    In our example, this copies ProductBillofMaterials.kitNumberRequired to the Target (SubItem) kitNumberRequired
    • after the copy operations, Target logic is invoked
    In our example, lineitems rules compute qtyOrdered as

    row.kitNumberRequired * row.kitItem.qtyOrdered


    The copyAttributesFromTo copies like-named attributes, as noted above; note that:
    • Primary key attributes are not copied

    • Non-null values are over-written, so, for example, copied Source values override copied Parent values