Components:
Product Line Diff

Product Line Diff

As a deployed system is maintained over time, its corresponding architecture should be modified to stay consistent with the code.  Sometimes an architect may want to know exactly what has changed between two versions of an architecture.  Also, it is often necessary to propagate the changes made to one architecture to different architecture.  This can include moving features from one variant of a product line architecture (PLA) to another variant or moving features across different versions (or branches of development).  The PLADiff component is able to calculate the difference between any two architectures in terms of architectural elements (as defined by xADL 2.0) .  This difference is then captured in a diff document.  The diff document can then be passed to the PLAMerge component in order to propagate the changes to another architecture.

The PLADiff component starts at a specified location (either a type or an ArchStructure) and compares all the elements by their descriptions.  If the element (component, connector, variants) has a complex type it will then recursively perform diff on the types.  Similarly if the type has a substructure, it will recursively diff on the ArchStructure within the substructure.  The following table summarizes what the diff algorithm compares when checking the different types of elements.

Element
Comparisons
Component
1. Description
Connector
1. Description
Link
1. Description
2. Type (class in XArchLibs)
3. Optional guard (if its an optional link)
Interface
1. Description
2. Type (class in XArchLibs)
3. Interface type
4. Direction
5. Optional guard (if its an optional link)
Optional
1. String of the guard
Signature
1. Description
2. Type (class in XArchLibs)
3. Signature (interface) type
4. Direction
5. Optional guard (if its an optional link)
Variant
1. String of the guard
Signature Interface Mapping
1. Description
2. Type (class in XArchLibs)
3. Optional guard (if its an optional link)
Substructure
N/A

It may be misleading that the algorithm only compares the description for components and connectors, this is because of the changes in interface, optional guard, or the component/connector type is captured separately.  Similarly for variants we only compare the guard, the changes in the actual type of the variant is captured separately.  This in essence allows for fine-grained differencing.  So during merge, we do not replace a component with another component, but instead tries to make the components (and its type) look the same.  Finally, the algorithm never compares substructures but instead will compare the elements within the substructure directly. 

An example diff and its resulting diff document can be found here.


The PLADiff component can be invoked through the UI driver or manually by sending the PerformPLADiffMessage request.

PerformPLADiffMessage

public PerformPLADiffMessage(String origArchURL,
    String newArchURL, String diffURL,
    String origStartingID, String newStartingID,
    boolean isStructural, String componentID)

Parameters:
origArchURL - This is the URL of the original (base) xADL architecture to diff on.
newArchURL - This is the URL of the new xADL architecture to compare with.
diffURL - This is the URL of the resulting diff document
origStartingID - This is the ID of the ArchStructure or type-version element in the original architecture where we should start the diff process
newStartingID - This is the ID of the ArchStructure or type-version element in the new architecture where we should start the diff process
isStructural - This flag is true if the IDs passed in corresponds to an ArchStructure element, false if its a type-version element .
componentID - This is ID of the component requesting the diff service. This ID is the same as the ID in the PLADiffStatusMessage that corresponds to this diff process. This is to allow the requesting component to only listen in on the progress messages it cares about. This field can be null.

Then to invoke PLADiff:


/* In a C2Component*/
// Create the message // This invokes the diff process on the architectures // specified. // -baseURL: the URL of the base architecture // -newURL: the URL of the architecture to compare against // -diffURL: The URL of the resulting diff document // -origStartingID, newStartingID: IDs of the elements // to start the diff process for the original and new // architectures respectively. // -We pass in true if the IDs corresponds to ArchStructures // -compID: The component ID of the requesting component // (this component) PerformPLADiffMessage diffMessage = new PerformPLADiffMessage(baseURL, newURL, diffURL, origStartingID, newStartingID, true, compID);

// Sends the request upwards
sendToAll(diffMessage, topIface);
 


When the diff process has completed, it will send out the following message:

PLADiffStatusMessage

public PLADiffStatusMessage(String diffArchURL,
    String componentID, int currentValue, int upperBound,
    boolean isDone, boolean errorOccurred, Exception error)

Parameters:
diffArchURL - This is the URL of the resulting diff document.
componentID - This is the ID of the component who requested the diff service. This field may be null
currentValue - This is the numerical representation of the current progress.
upperBound - This is total expected work that is required.
isDone - This is a flag to signal whether or not the diff process has completed. Note: this will be true in the case of errors.
errorOccurred - This flag to signal whether or not an error has occurred.
error - This is the actual exception that occurred, please refer to the list below.
Exceptions:
PLADiffException -This exception is thrown when the diff encounters some (internal) error that its not able to recover from.
MissingElementException - This exception is thrown when the algorithm cannot find a required element in the architecture description.
BrokenLinkException - This exception is thrown when a HREF resolves to null.

Please note that although the message can contain progress information (currentValue and upperBound), these fields currently are not used. The PLADiff component does not report on its progress during the diff process but only sends out this message when it has finished. All of these values can be obtained through a simple get operation, getX() where X is the field name. For example, getDiffArchURL() would get the diffArchURL value, getComponentID() would get the componentID value, and so forth.


Additional questions about the PLADiff component should be sent to Ping H. Chen.