Friday, August 30, 2013

Composite pattern using Rational Software Architect

In software engineering, the design patterns are reusable solutions to a commonly occurring problem within a given context. Currently I am involved in a UML modeling project that needs a design pattern for objects that have the same composition, same code and tree structured data.

Unfortunately, every time I visit customers I find, in most of them, that the software code quality is poor. I will not analyze in this post why this happens because there are many influencing factors such as cost, inexperienced programmers, misdirection, etc..

What I know, is that many programmers do not use development methodologies including the use of pattern matching.

Anyway, I will explain how to use the composite pattern in a few steps, modeling in UML and programming in Java using the based Eclipse tool Rational Software Architect for WebSphere (RSA).

As brief introduction, the composite pattern describes that a group of objects are to be treated in the same way as a single instance of an object. The intent of a composite is to "compose" objects into tree structures to represent part-whole hierarchies.


More info on Wikipedia: Composite pattern.

For now I leave the theory aside and I will explain the procedures. I divided the procedures into three steps: modeling, transformation and code execution.

Procedure to create the UML model:
  1. Open RSA and open the Modeling perspective
  2. Create a new project. File -> New -> Project...
  3. Select General -> Project and click Next
  4. Write in Project name: Composite Pattern and click Finish


  5. Create a model UML, File -> New -> Model
  6. Select Standard template and click Next
  7. Select General -> Blank Package and in File name: org
  8. Browse Destination folder and select Composite Pattern, click Finish


  9. On package org, add the following UML packages in cascaded: jif, develop and composite
  10. Add the following UML classes in composite package: Composite class, Component class and Leaf class and IComponent interface
  11. Add the following UML interface in composite package: IComponent interface
  12. Open the Main freeform diagram and drag the UML elements and Save the changes


  13. Add in IComponent interface the following operations: getName with String value return and without inputs parameters, getParent with IComponent value return and without input parameters, add without return and IComponent as input parameter, remove without return and IComponent as input parameter and getChilds with java.util.Set value return and without input parameters
  14. Repeat same operations described in the previous step for Composite class
  15. In the Component class add the following attribute name as String type and protected
  16. Add in Leaf class the following operations: getName with String value return and without inputs parameters, getParent with Component value return and without input parameters
  17. Create an Interface Realization from Component to IComponent
  18. Create a Generalizarion from Composite to Component
  19. Create a Generalization from Leaf to Component
  20. Create a Composition Association from Composite to Component


  21. Save changes

Procedure to transform UML to Java:

  1. Create a Java project, New -> Other, select in the wizard window the Java Project option and then click Next
  2. Write the Project name: Composite and click Finish
  3. In menu, Modeling -> Transform -> New Configuration
  4. Write in name uml2java and select in Configuration file destination the java project Composite
  5. In Java Transformations select UML to Java


  6. Click Next
  7. Select the Source, Composite Pattern -> Models -> org
  8. Select the Target, Composite -> src
  9. Click Finish
  10. Run the transformation to generate de Java source code

Procedure to run the example:
  1. Resolve the warnings that transformation has left:
    Set is a raw type. References to generic type Set<E> should be parameterized to: 
    Set<IComponent>
    - In Composite class, initialize the attribute component: 
    private Set<IComponent> component = new HashSet<IComponent>();
    - Remove the @generated tags
  2. Implement the Composite class:
    - Create constructor

    public Composite(String name) {
    super.name = name;
    }
    - Add the return value in the getName method
    public String getName() {
    return super.name;
    }
    - Add array components
    public void add(IComponent component) {
    this.component.add(component);
    }
    - Add the return value in the getChilds method
            public Set<IComponent> getChilds() {
    return component;
    }

  3. Implement the Leaf class:
    - Create constructor

    public Leaf(String name) {
    super.name = name;
    }
    - Add the return value in the getName method
    public String getName() {
    return super.name;
    }
  4. Create a class (Test.java) to run an example composite pattern:
    - In the main method, 

    IComponent componentA = new Composite("ComponentA");
    IComponent componentB = new Composite("ComponentB");
    IComponent componentC = new Composite("ComponentC");
    IComponent componentD = new Composite("ComponentD");
    IComponent leafA = new Leaf("leafA");
    IComponent leafB = new Leaf("leafB");
    IComponent leafC = new Leaf("leafC");
    IComponent leafD = new Leaf("leafD");
    componentD.add(leafD);
    componentC.add(leafC);
    componentB.add(leafB);
    componentB.add(componentC);
    componentA.add(leafA);
    componentA.add(componentB);
    componentA.add(componentD);

It takes a structure as shown in the following diagram:


Note: At the end of the post you can find the source files for the sample.

When running the test class generates the following structure:


ComponentA
 ComponentD
  leafD
 leafA
 ComponentB
  ComponentC
   leafC
  leafB

Composite Pattern example applied to automotive engineering:

Here I leave an example of how it can be applied in the real world.


Source Files:

- IComponent.java

package jif.develop.composite;

import java.util.Set;

/** 
 * @author Jorge Iglesias
 */
public interface IComponent {
public String getName();
public IComponent getParent();
public void add(IComponent component);
public void remove(IComponent component);
public Set<IComponent> getChilds();
}

- Component.java
package jif.develop.composite;

import java.util.Set;

/** 
 * @author Jorge Iglesias
 */
public class Component implements IComponent {

protected String name;

public String getName() {
return null;
}

public IComponent getParent() {
return null;
}

public void add(IComponent component) {
}

public void remove(IComponent component) {
}

public Set<IComponent> getChilds() {
return null;
}
}

- Composite.java
package jif.develop.composite;

import java.util.HashSet;
import java.util.Set;

/** 
 * @author Jorge Iglesias
 */
public class Composite extends Component {

private Set<IComponent> component = new HashSet<IComponent>();

public Composite(String name) {
super.name = name;
}

public String getName() {
return super.name;
}

public IComponent getParent() {
//TODO: to be implemented
return null;
}

public void add(IComponent component) {
this.component.add(component);
}

public void remove(IComponent component) {
//TODO: to be implemented
}

public Set<IComponent> getChilds() {
return component;
}
}

- Leaf.java
package jif.develop.composite;

/** 
 * @author Jorge Iglesias
 */
public class Leaf extends Component {

public Leaf(String name) {
super.name = name;
}

public String getName() {
return super.name;
}

public IComponent getParent() {
return null;
}
}
- Test.java
package jif.develop.composite;

/** 
 * @author Jorge Iglesias
 */
public class Test {

public static void main(String[] args) {
IComponent componentA = new Composite("ComponentA");
IComponent componentB = new Composite("ComponentB");
IComponent componentC = new Composite("ComponentC");
IComponent componentD = new Composite("ComponentD");
IComponent leafA = new Leaf("leafA");
IComponent leafB = new Leaf("leafB");
IComponent leafC = new Leaf("leafC");
IComponent leafD = new Leaf("leafD");
componentD.add(leafD);
componentC.add(leafC);
componentB.add(leafB);
componentB.add(componentC);
componentA.add(leafA);
componentA.add(componentB);
componentA.add(componentD);
printTree(componentA,0);
}
static void printTree(IComponent c, int depth) {
String d = "";
for (int i = 0; i < depth; i++) {
d+=" "; 
}
System.out.println(d + c.getName());
if (c instanceof Composite) {
if (c.getChilds().size() > 0) {
depth++;

for (IComponent component : c.getChilds()) {
printTree(component, depth);
}
}
}
}
}





3 comments:

  1. Hi, Its really informative post .
    Composite design pattern is based on creating a tree structure in such a way that an individual leaf of the tree can be treated just like entire tree composition.
    Java composite design pattern
    OO design pattern
    composite tree design




    ReplyDelete
  2. Hi,
    Very useful post. I am beginner trying to create the above example in my local RSA. While creating the class diagram, as mentioned by you , I tried to use java types like java.util.Set in return type of method, but I am not able to select the same. I am only able to use the model elements created in return type. Please advise how I can use java types from the jre library in the class diagram.

    Thanks and Regards,
    Anuradha

    ReplyDelete
  3. Thanks Anuradha,

    About your question, you need to extend the UML metamodel for this particular use, instead of changing the metamodel, you can create a set of stereotypes and constraints and group them into a custom UML profile.

    Extending the UML metamodel:
    - http://pic.dhe.ibm.com/infocenter/rsawshlp/v7r5m0/index.jsp?topic=%2Fcom.ibm.xtools.profiles.doc%2Ftopics%2Ftprofover.html

    Thanks for you comment.

    Regards,

    Jorge

    ReplyDelete