« cclic_report/gpdb_putDesignsync bug | Main | Convertdb »

Cloning done

  • Implemented cloning procedure for DMD/CQ

How to clone a parent CQ record to a child

You would think that this would be clearly documented in the CQ manual but it isn't. The requirement is clear enough - "implement parent/child relationships for a CQ record... Oh and when a child is created could you copy everything from the parent and we'll change what's different in the child".

Implementing a parent/child relationship is pretty clear and documented - basically you create a reference link in the current record back to itself. CQ even has a parent/child control that handles manipulating the relationship allowing the user the controls to link in existing records, delete a parent/child relationship or add a new record as a child of this record. But there is nothing in there about copying data from the parent to the child. This you must do with hooks. But how to code the hooks?

I found a method for doing this and implemented the following. The trick is to add pre and post hooks to the New button of the parent/child control. This button is selected when the user wishes to add a new child record to this parent. The pre action hook, created as a Record Script set a session wide variable saying "Hey I'm adding a new child record to this parent". This variable contains the ID of the parent. The following code accomplishes this:

my $session = $entity->GetSession;

$session->NameValue ("ParentID", $entity->GetFieldValue ("id")->GetValue);

After creating this record script add it as the pre-action hook for the new button. Don't forget to toggle the Enable for CQ Web (I don't really understand why you would ever not toggle that).

For the post-action script you are basically saying "Hey I'm no longer adding a new child record to this parent" with the following code:

my $session = $entity->GetSession;

$session->NameValue ("ParentID", "");

What this does is effectively bound the time you are in this unique situation - any other time the global session variable ParentID will be blank. Now the cloning can begin...

In the default value hooks for each field you want cloned place the following call:

CloneField ($fieldname);

This is written as a call to a Global Script since the code will always be the same and because you'll have to do this for each field that you wish cloned.

Finally, create the following Global Script:

sub CloneField {
  my $fieldname = shift;
    
  # Check session wide global, ParentID, and if set retrieve
  # the parent record and clone this field
  my $session  = $entity->GetSession;
  my $parentID = $session->GetNameValue ("ParentID");

  if ($parentID ne "") {
    # If ParentID is not blank then we are adding a subtask.
    # Copy this field from the parent to this new child.

    # Get the parent record
    my $parent = $session->GetEntity ("ChangeRequest", $parentID);

    # Set the child field
    $entity->SetFieldValue (
	$fieldname,
	$parent->GetFieldValue ($fieldname)->GetValue
    );
  } # if
} # CloneField

This script checks to see if the session global "ParentID" is not blank, indicating that we are in this special mode of adding a new child to an existing parent, and if so, gets the parent record and the field value based on the passed in field name. Finally it sets the field value based on the field name to that of the value of the corresponding parent's field value.