Open UI: Property Set Methods (Copy, DeepCopy, Clone)

Open UI: New Property Set Structure
Open UI: Property Set Methods (Copy, DeepCopy, Clone)
Open UI: Property Set Methods (Fixing Copy)
Open UI: Property Set Methods (Why Clone?)

Let’s begin with the link to Bookshelf on the new Property Set structure in Open UI:

http://docs.oracle.com/cd/E14004_01/books/config_open_ui/appendix_a_API20.html#wp1232047

Underneath this diagram it strangely lists an incomplete list of Property Set methods.

AddChild Method
DeepCopy Method
Clone Method
Copy Method
GetChild Method
GetChildByType Method
InsertChildAt Method
RemoveChild Method
RemoveProperty Method
SetProperty Method


In general the Open UI chapter needs a lot of work in terms of accuracy, but true developers don’t let incomplete documentation get in the way of their learning.

Across this series on the new Open UI Property Set, we will cover some of the most interesting and some of the most confusing methods exposed by the new Property Set API.

We'll start with the most confusing! From the above list, we see 3 seemingly similar methods and their descriptions from bookshelf below (You can tell it was written by an engineer).

DeepCopy Method

The DeepCopy method makes a full copy of the inputPS property set and then parses this copy into the following property set:

this


Clone Method

The Clone method creates a new property set and does a full copy of the following property set:

this


Copy Method

The Copy method copies the following property set:

this




It reminds me of eating Yum Cha, which provides 100 different ways to eat Prawn. In this case, 3 different methods to copy a Property Set. From what I understand of Copy, it also performs a full copy, just like what DeepCopy and Clone claim to do.

We might have a better idea, if we can actually see what the Property Set looks like after calling each method, so I setup this two level hierarchy test case.

var ps=theApplication().NewPropertySet();
var psChild1=theApplication().NewPropertySet();
var psChild2=theApplication().NewPropertySet();
ps.SetType("Parent");
ps.SetValue("ParentValue");
ps.SetProperty("Mum","Georgette");
ps.SetProperty("Dad","George");
psChild1.SetType("Child 1");
psChild2.SetType("Child 2");
psChild1.SetProperty("Name","Bob");
psChild1.SetProperty("Gender","Male");
psChild2.SetProperty("Name","Jane");
psChild2.SetProperty("Gender","Female");
ps.AddChild(psChild1);
ps.AddChild(psChild2);

console.log( "---------------------Original PS---------------------\n"+
util.PSToStr(ps) );
var psCopy=theApplication().NewPropertySet();
psCopy.Copy(ps);

console.log( "---------------------Copy Method---------------------\n"+
util.PSToStr(psCopy) );
var psClone=ps.Clone();
console.log( "---------------------Clone Method---------------------\n"+
util.PSToStr(psClone) );
var psDeepCopy=theApplication().NewPropertySet();
psDeepCopy.DeepCopy(ps);
console.log( "---------------------DeepCopy Method---------------------\n"+
util.PSToStr(psDeepCopy) );


This is the result:



Interesting, they all output the same result.

To get a deeper understanding of what is happening, we need to inspect the function bodies for these methods to understand what the intent is for these different methods.

Copy Function Definition

function JSSPropertySet_Copy(old) {
var i;
var oldChild;
var name;
if (this.axObj != null) {
        if (old == null)
                return (false);
        this.axObj.Copy(old.axObj); // this should return a value
        return (true);
}
this.Reset();
if (old == null)
                return (false);
name = old.GetType();
if (name != null && name != "")
        this.SetType(name);
value = old.GetValue();
if (value != null && value != "")
        this.SetValue(value);
for (name in old.propArray)
        this.SetPropertyStr(name, old.propArray[name]);
for (i = 0; i < old.childArray.length; i++) {
        oldChild = old.childArray[i];
        if (oldChild == null)
                break;
        newChild = new JSSPropertySet();
        newChild.Copy(oldChild);
        this.AddChild(newChild);
}
return (true);  
}


"Copy" uses the current Property Set, and recursively walks through the Input PS, and copies it, to itself. It also looks like it has some legacy code from its prior ActiveX days


DeepCopy Function Definition

function JSSPropertySet_DeepCopy(inputPS) {
var i;
var name;
var value;
var oldPS;
var newPS;
if (inputPS instanceof JSSPropertySet) {
        name = inputPS.GetType();
        if (name != null && name != "")
                this.SetType(name);
        value = inputPS.GetValue();
        if (value != null && value != "")
                this.SetValue(value);
        for (name in inputPS.propArray)
                this.SetPropertyStr(name, inputPS.propArray[name]);
        for (i = 0; i < inputPS.childArray.length; i++) {
                oldPS = inputPS.childArray[i];
                if (oldPS == null)
                        break;
                newPS = oldPS.Clone();
                this.AddChild(newPS);
        }
        return true;
}
return false;
}


"DeepCopy" preserves the current Property Set, and relies on "Clone" to perform the recursive copy.

Clone Function Definition

function JSSPropertySet_Clone() {
var i;
var name;
var value;
var dup = new JSSPropertySet();
name = this.GetType();
if (name != null && name != "")
         dup.SetType(name);
value = this.GetValue();
if (value != null && value != "")
        dup.SetValue(value);
for (name in this.propArray)
        dup.SetPropertyStr(name, this.propArray[name]);
for (i = 0; i < this.childArray.length; i++) {
        oldChild = this.childArray[i];
        if (oldChild == null)
                        break;
        newChild = oldChild.Clone();
        dup.AddChild(newChild);
}
return (dup);   
}


"Clone" works slightly different, because it copies itself, and returns a Property Set.

We can now conclude that the intent is that all 3 methods (Copy, DeepCopy, Clone) performs a copy of the entire Tree.

Summary

1. Copy performs a reset on the current Property Set, and clears all variables before performing a Copy on the Input Property Set

2. DeepCopy merges the Input Property Set into itself, combining the properties of both Property Sets

3. Clone copies itself, and is assigned to another Property Set



While we can see that DeepCopy is different. Functionally Clone and Copy create a Fully Copy, so why did Siebel Invent Clone? The mystery thickens.

Maybe a more complex Property Set and some performance timings will reveal something interesting.

Intermission

By now you know the difference between Copy, DeepCopy and Clone, but there is still one more major twist on the plot.

There is also more script samples to come, and I don’t want you to overdose you on code. If you’ve already OD’d, you'll have some time to recover. Stay tuned for more Impossible Siebel.



2 comments:

  1. Nice one. Just saved an hour or two looking at the documentation and the output!

    ReplyDelete
  2. Thanks Richard,

    I've just discovered your site and videos. I'll definitely be spending some more time on there.

    ReplyDelete

Comments are open to all, please make it constructive.