Atomic Domains of Java Library Classes CSIS Department Kennesaw State University

Atomic Domains of Java Library Classes
Hisham M. Haddad, Woranuch Kaensaksiri, and Arjun Vasudevan
CSIS Department
Kennesaw State University
Kennesaw, Georgia 30144
Abstract - Component reuse is evolving technology that is
facing some challenges. One issue is the ease of reuse and the
need for reuse solutions that facilitate self-selection of reus-
able components. This work builds on the “Atomic Domains
and Wrappers” framework model that promotes highly reus-
able domain-specific software components. Through illustra-
tive applications, the framework is applied to Java library
classes to demonstrate the use of atomic domains to achieve
effective component reuse. This work in an effort to facilitate
software reuse and minimize coding effort when using library
components organized into cohesive atomic domains. This
work is a contribution to component-based development.
Keywords: Software Reuse, Atomic Domains, Java Atomic
Domains, Reusable Java Domains.
1 Introduction
Various approaches to the ease and effectiveness of
component reuse [1,2,3] have been researched. This work
attempts to further explore the application of the Atomic Do-
mains framework [4,5,6,7] in developing reusable domain-
specific components. The concept of atomic domains pro-
motes component reuse. The general model of the Atomic
Domains framework focuses on the developer’s perspective of
application development with reuse. The model facilitates
effective domain-specific component reuse as applied by its
wrapper. In this work, the components are source code, and
the domain is Java applications using the Java library compo-
nents. The application of the framework requires an effort to
construct each atomic domain and its wrapper. The program-
ming effort can vary. In this work, the effort is specific to the
Java library components and is illustrated by sample Java-
based atomic domains that are kept simple for proof of con-
cept purpose. This work is a contribution to component-based
software development that has become a defacto requirement
for many in today’s software industry.
2 Atomic Domain Framework
The Atomic Domain framework defines each atomic
domain based on one related context. All reusable (and irre-
ducible) components related to the context are conceptually
placed in the same atomic domain [5]. Each atomic domain is
associated with a wrapper, which includes a wrapper manager
component. Application domain rules are built into the wrap-
per manager and are part of its construction process. The rules
determine how the user application selects components from
the atomic domain. Each atomic domain is associated with a
command that is referenced in the application source code. The
command refers to all components within the respective atomic
domain. The command does not act as a single library call or an
overloaded function. The atomic domain components are hidden
from the developer and can only be referenced by the wrapper
manager. When the command is used in the developer’s source
code, the compiler supplies all required data to the wrapper
manager through the wrapper’s API. The wrapper manager
evaluates the command at the point it is used in the application
source code and determines which component(s) to return to the
application based on application domain rules [7].
3 Java Atomic Domains
The goal of this work is to apply the Atomic Domains
framework model to the Java library classes and packages to
facilitate effective reuse of library components in the develop-
ment of Java applications, ease component management, and
minimize coding effort. To achieve this goal, our approach is to
develop illustrative atomic domains of related Java library com-
ponents, and develop applications to demonstrate component
reuse through the wrappers of developed atomic domains.
Analysis of the Java library showed that the library includes a
large number of related components (classes and packages).
Sample applications selected for this work include the following:
Linear-Data Structure (DS) Atomic Domain: The DS atomic
domain and its wrapper manager, called DSWrapper, are imple-
mented as a class that includes data structure classes such as
linked-list, stack, and vector. The purpose of wrapping reusable
components into an atomic domain has been applied to data
structure classes to minimize the design overhead and coding
effort. To demonstrate the concept of wrapping existing compo-
nents and retaining their original functionalities, the DSWrapper
class defines a set of methods such as: add, clear, get, getSize,
remove, and set as its API. This atomic domain is kept simple
for illustration purposes.
Non-Linear Data Structure (NDS) Atomic Domain: The NDS
atomic domain and its wrapper manager, called NDSWrapper,
are implemented as a class that includes non-linear data struc-
tures such as Tree, Binary Tree, UGraph (un-weighted graph),
and Abstract Graph. Like the DS atomic domain, wrapping reus-
able components into an atomic domain helps reduce coding
effort and speeds up application development. The included
components retain their original functionalities. The NDSWrap-
per class defines methods for Tree, Graph, and Binary Tree
structures. The Tree methods include createNode, deleteNode,
setRoot, setLeave, create1stBranch, createBranch, and cre-
ateTree; the Graph methods include createUgraph, addEdge,
and getShortestPath; and the Binary Tree methods include
search, insert, delete and getRoot. It should be noted that the
linear and non-linear data structure components are separated
into 2 atomic domains for illustration purposes. If such con-
cepts are fully implemented in Java, many of the cumbersome
design and coding of applications can be eliminated. From a
programmer’s perspective, this means less coding effort and
fewer visible components to be accounted for.
GUI Atomic Domain: The GUI atomic domain and its wrap-
per, called GUIWrapper, include a number of GUI compo-
nents such as button, checkboxes, dropdown lists, menu, and
others. A GUI component, such as a button, can be associated
with several classes. To build a button, the developer has to
use a class to specify the color of the button, another class to
apply a border to the button, and another class to specify the
font style of the label or a class to specify an image picture for
the button, and so on. This lengthy process can be repeated to
build all the components that make up the application inter-
face. With atomic domains, wrapping related components into
an atomic domain can speed up the coding process signifi-
cantly. With the GUI components (classes) being wrapped
into one atomic domain, the application developer can use one
reference to interact with the atomic domain (GUIWrapper) to
build needed GUI components.
GUI components share common methods. For example, most
GUI components define methods to change background and
foreground colors, methods to modify label names, and oth-
ers. The GUIWrapper (implemented as a class) incorporates
most of these methods. This makes learning how to reuse GUI
components easier by giving the user an abstract view of the
GUIWrapper class with its methods that can provide the same
functionalities of all the methods of many different GUI com-
ponents. To motivate the wrapping of existing components
and retaining their original functionalities, the GUIWrapper
class defines methods such as: setBackgroundColor, setFor-
groundColor, setFont, setLabelName, setVisibility, isVisible,
setEnabled, isEnable, setNewSize, getText, addActionLis-
tener, and addFocusListener. These methods provide the same
functionalities as the individual methods.
Input/Output (IO) Atomic Domain: The IO atomic domain
and its wrapper, called IOWrapper and is implemented as a
class, includes a number of I/O classes such as File, ObjectIn-
putStream, ObjectOutputStream, FileInputStream, FileOut-
putStream, BufferedReader, BufferedWriter, FileReader,
FileWriter, DataInputStream, and DataOutputStream. Because
of the nature of Java and in order to build an application with
IO capabilities, the programmer has to use several library
classes, such as the File class, to associate a file name and
location with a File object during runtime. Also, InputStream
and OutputStream classes are used to allow the application to
read and write to a secondary storage device, and several
more classes are used to handle the buffering process. With
the IOWrapper and instead of having to decide how many
classes and which one to use for IO process, the application
developer can use one reference to the IOWrapper class and the
wrapper manager creates necessary I/O components for the ap-
plication. The listed IO components share common methods. For
example, these IO components provide a link between the run-
ning program and a file object on an IO device. These IO com-
ponents also have similar methods used to transfer data
(read/write) to and from a file located on the IO device. IO
classes do not have as many methods as the GUI classes because
they provide a different type of service. To demonstrate the
wrapping of existing components and retaining their original
functionalities, the IOWrapper class defines methods such as
readLine, read, writeFile, newLine, readFile, closeReader-
Stream, and closeWriterStream.
4 Illustrative Applications
Selected applications are described in this section to illus-
trate how Java atomic domains and their wrappers facilitate
effective reuse of components in the development of Java appli-
cations. The approach is to contrast programming effort (lines of
code) with and without using atomic domains. The selected ap-
plications are Nine Tail, Tree, Payroll, and Bank Account. These
applications use the Java atomic domains described above.
Nine Tail Application: The Nine Tail application uses Breadth-
First Search (BFS) algorithm to solve the Nail Tail problem.
Nine coins are placed in a three by three matrix with some fac-
ing up and others facing down. A legal move is to take any coin
that is facing up and reverse it, together with the coins adjacent
to it. The task is to find the minimum number of moves that lead
to all coins facing down. The problem is solved when all coins
are facing down. This application utilizes the NDSWrapper
class. Figures 1 and 2 show the source code before and after
using the NDSWrapper class in the solution. The coding effort in
Figure-2 is simpler than that in Figure-1.
Tree Application: The Tree application creates a folder struc-
ture and allows user to add, delete, and update values under a
specified node. This application utilizes the NDSWrapper class.
Figures 3 and 4 show the source code before and after using the
NDS atomic domain. In Figure-3 the user needs to explicitly
identify all the non-linear data structure components and their
types while in Figure-4 the user creates all the NDS objects from
the same wrapper class.
Bank Account Application: The Bank Account example illus-
trates the process of creating account objects and allowing the
user to save account information into a file. This application
utilizes the GUIWrapper, IOWrapper, and DSWrapper classes.
Figures 5 and 6 show partial code before and after using the
GUI, IO, and DS atomic domains. The omitted code in both
Figures is identical. In Figure-5, the user needs to explicitly
identify all required GUI, IO, and DS components and their
types; while in Figure-6 the user creates all GUI, IO, and DS
objects from respective same wrapper class. The coding effort in
Figure-6 is simpler than that in Figure-5.
public String toString() {
StringBuilder result = new StringBuilder();
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
result.append(matrix[i][j] + " ");
}
result.append("\n");
}
return result.toString();
}
}
private void createEdges() {
for (Node node : nodes) {
int u = nodes.indexOf(node); // node index
int[][] matrix = node.matrix; // matrix for the
node
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (matrix[i][j] == 0) {
Node adjacentNode =
getAdjacentNode(matrix, i, j);
// Application Nine Tail without using the
// NDSWrapper classes
import java.util.*;
public class NineTailModel {
private ArrayList<Node> nodes = new Array-
List<Node>(); // Vertices
private ArrayList<AbstractGraph.Edge> edges =
new ArrayList<AbstractGraph.Edge>(); // Store
edges
private UnweightedGraph graph; // Define a
graph
private AbstractGraph.Tree tree; // Define a
tree
public NineTailModel() {
createNodes(); // Create nodes
createEdges(); // Create edges
graph = new UnweightedGraph(edges, nodes);
tree = graph.bfs(511);
}
private void createNodes() {
for (int k1 = 0; k1 <= 1; k1++) {
for (int k2 = 0; k2 <= 1; k2++) {
for (int k3 = 0; k3 <= 1; k3++) {
for (int k4 = 0; k4 <= 1; k4++) {
for (int k5 = 0; k5 <= 1; k5++) {
for (int k6 = 0; k6 <= 1; k6++) {
for (int k7 = 0; k7 <= 1; k7++) {
for (int k8 = 0; k8 <= 1; k8++) {
for (int k9 = 0; k9 <= 1; k9++) {
nodes.add(new Node(k1, k2, k3,
k4,k5, k6, k7, k8, k9));
} } } } } } } } } }
public static class Node {
int[][] matrix = new int[3][3];
Node(int ...numbers) { // Variable-length
argument
int k = 0;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
matrix[i][j] = numbers[k++];
}
}
}
Node(int[][] numbers) {
this.matrix = numbers;
}
public boolean equals(Object o) {
int[][] anotherMatrix = ((Node)o).matrix;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (matrix[i][j] != anotherMa-
trix[i][j]) {
return false;
}
}
}
return true; // Nodes with the same matrix
values
}
i
nt v = nodes.indexOf(adjacentNode);
edges.add(new AbstractGraph.Edge(v, u));
} } } } }
private Node getAdjacentNode(int[][] matrix, int i,
int j) {
int[][] matrixOfNextNode = new int[3][3];
for (int i1 = 0; i1 < 3; i1++) {
for (int j1 = 0; j1 < 3; j1++) {
matrixOfNextNode[i1][j1] = matrix[i1][j1];
}
}
flipACell(matrixOfNextNode, i - 1, j);// Top
flipACell(matrixOfNextNode, i + 1,j); // Bottom
flipACell(matrixOfNextNode, i, j - 1);// Left
flipACell(matrixOfNextNode, i, j + 1);// Right
flipACell(matrixOfNextNode, i, j); // Self
return new Node(matrixOfNextNode);
}
private void flipACell(int[][] matrix, int i, int
j) {
if (i >= 0 && i <= 2 && j >= 0 && j <= 2) { //
Within boundary
if (matrix[i][j] == 0) {
matrix[i][j] = 1; // Flip from 0 to 1
}
else {
matrix[i][j] = 0; // Flip from 1 to 0
} } }
public LinkedList<Node> getShortestPath(Node node)
{
Iterator iterator =
tree.pathIterator(nodes.indexOf(node));
LinkedList list = new LinkedList();
while (iterator.hasNext())
list.addFirst(iterator.next());
return list;
} }
Figure-1: Application Nine Tail without using the NDSWrapper Class.
Payroll Application: The Payroll application calculates the
check amount by allowing the user to enter the hours worked
and the pay rate. The application allows the user to save the
check amount to a text file. This application uses the GUI-
Wrapper and IOWrapper classes to create the user interface
and to add saving to file capability. Without atomic domains, the
user needs to explicitly identify all required GUI components
and their types; while with atomic domains the user creates all
GUI objects from the same wrapper classes. Coding with the
later approach is simpler than with the former approach.
Figure-2: Application Nine Tail using the NDSWrapper Class.
// Application Nine Tail with using the
// NDSWrapper classes
import java.util.*;
public class NineTailModel {
private NDSWrapper ugraph = new NDSWrap-
per("ugraph");;
private ArrayList<NDSWrapper.Node> nodes = new
ArrayList<NDSWrapper.Node>(); // Vertices
public NineTailModel() {
ugraph = new NDSWrapper("ugraph");
createNodes(); // Create nodes
createEdges(); // Create edges
ugraph.createUgraph(nodes);
}
private void createNodes() {
for (int k1 = 0; k1 <= 1; k1++) {
for (int k2 = 0; k2 <= 1; k2++) {
for (int k3 = 0; k3 <= 1; k3++) {
for (int k4 = 0; k4 <= 1; k4++) {
for (int k5 = 0; k5 <= 1; k5++) {
for (int k6 = 0; k6 <= 1; k6++) {
for (int k7 = 0; k7 <= 1; k7++) {
for (int k8 = 0; k8 <= 1; k8++) {
for (int k9 = 0; k9 <= 1; k9++) {
nodes.add(new NDSWrapper.Node(k1,
k2, k3, k4,k5, k6, k7, k8, k9));
} } } } } } } } } }
private void createEdges() {
for (NDSWrapper.Node node : nodes) {
int u = nodes.indexOf(node); // node index
int[][] matrix = node.matrix; // matrix for
the node
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (matrix[i][j] == 0) {
NDSWrapper.Node adjacentNode =
getAdjacentNode(matrix, i, j);
int v = nodes.indexOf(adjacentNode);
ugraph.addEdge(v, u);
} } } } }
private NDSWrapper.Node getAdjacentNode(int[][] ma-
trix, int i, int j) {
int[][] matrixOfNextNode = new int[3][3];
for (int i1 = 0; i1 < 3; i1++) {
for (int j1 = 0; j1 < 3; j1++) {
matrixOfNextNode[i1][j1] = matrix[i1][j1];
}
}
flipACell(matrixOfNextNode, i - 1, j); // Top
neighbor
flipACell(matrixOfNextNode, i + 1, j); // Bottom
neighbor
flipACell(matrixOfNextNode, i, j - 1); // Left
neighbor
flipACell(matrixOfNextNode, i, j + 1); // Right
neighbor
flipACell(matrixOfNextNode, i, j); // Flip
self
return new NDSWrapper.Node(matrixOfNextNode);
}
private void flipACell(int[][] matrix, int i, int
j) {
if (i >= 0 && i <= 2 && j >= 0 && j <= 2) { //
Within boundary
if (matrix[i][j] == 0) {
matrix[i][j] = 1; // Flip from 0 to 1
}
else {
matrix[i][j] = 0; // Flip from 1 to 0
}
}
}
public LinkedList<NDSWrapper.Node> getShortest-
Path(NDSWrapper.Node node){
LinkedList list = new LinkedList();
list = ugraph.getShortestPath(nodes,node);
return list;
}
}
5 Conclusion
The implementation of component reuse ranges from
isolated solution such as using new languages [8], wrapping
legacy components [9], refactoring [10], program mining [11],
product line technologies [12,13], and product populations
[14] to the use of current industry standards for distributed
components. This work supports the local component model,
where a component is defined as Java source code of a mod-
ule, class, function, or code snippet. The presented applica-
tions focus on Java classes as components. The components’
atomic domains group similar and related Java components
that are bound with a wrapper, and the domain is utilized via a
single atomic reference in the application source code. These
applications illustrate ease of reuse as well as encourage a
higher amount of reuse of Java library components.
The initial outcomes from this work indicate promising
results. The example applications illustrate the possibility of
achieving effective reuse of Java components and that the
programming effort for the application developer can be made
easier. Instead of requiring detailed knowledge of every library
component and package and their methods, with this approach
the application developer needs to know about smaller number
of components (atomic domains) and their methods. From lines
of code perspective, some atomic domains can reduce source
code significantly, such as in the case of the Payroll and Bank
Account applications. In other cases, such as the GUI atomic
domain, the user creates many objects (components) from a
single atomic domain without the need to know the internal
details for each created object. During the development we
found that using atomic domains and their wrappers is easier to
get the applications developed than not using these wrapper
classes. In addition to having to deal with few wrapper classes,
the management overhead of such classes was improved com-
pared to dealing with the many classes in the library.
Future work will focus on identifying more related compo-
nents in the Java library, developing more concrete atomic do-
mains and their wrappers; developing more illustrative applica-
tions, and studying improvement in coding effort (with vs. with-
out wrapper classes).
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JRootPane;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
public class TreeWrap extends JFrame {
private JTree tree;
private String nodename, parentname, rootname;
private DefaultTreeModel model;
private DefaultMutableTreeNode nNode;
private DefaultMutableTreeNode dNode;
private DefaultMutableTreeNode parent, outdoor,
indoor,ski, soccer, tennis, pingpong, iceskate, chess;
private String [] sport = {"Outdoor
Sport","Ski","Soccer","Tennis",
"Indoor
Sport","Pingpong","Ice skate","Chess"};
ReadImage img, oimg, cimg;
Image i1, i2, i3;
ImageIcon licon, oicon, cicon;
DefaultTreeCellRenderer renderer, renderer2;
public TreeWrap(int indexicon){
parent = new DefaultMutableTreeNode("Sport",
true);
outdoor = new DefaultMutableTreeNode("Outdoor
Sport");
indoor = new DefaultMutableTreeNode("Indoor
Sport");
ski = new DefaultMutableTreeNode("Ski");
soccer = new DefaultMutableTreeNode("Soccer");
tennis = new DefaultMutableTreeNode("Tennis");
pingpong = new DefaultMutableTreeNode("Pingpong");
iceskate = new DefaultMutableTreeNode("Ice
Skate");
chess = new DefaultMutableTreeNode("Chess");
parent.add(outdoor);
parent.add(indoor);
outdoor.add(ski);
outdoor.add(soccer);
outdoor.add(tennis);
indoor.add(pingpong);
indoor.add(iceskate);
indoor.add(chess);
tree = new JTree(parent);
setCustomIcon();
setNoIcon();
setStandardIcon();
if (indexicon == 1){
tree.setCellRenderer(renderer); // custom icon
}else if(indexicon ==2){
tree.setCellRenderer(renderer2); // no icon
}
tree.setBackground(Color.PINK);
setTitle("Sample tree");
setDefaultCloseOpera-
tion(JFrame.EXIT_ON_CLOSE);
Dimension d = new Dimension(600, 600);
setSize(d.width, d.height);
setLayout(new BorderLayout());
add(tree, BorderLayout.CENTER);
setUndecorated(true);
getRoot-
Pane().setWindowDecorationStyle(JRootPane.PLAIN_DIALOG
);
setVisible(true);
}
public void setFont(int index, int size){
GraphicsEnvironment gEnv = GraphicsEnviron-
ment.getLocalGraphicsEnvironment();
String envfonts[] =
gEnv.getAvailableFontFamilyNames();
tree.setFont(new Font(envfonts[index],
Font.BOLD,size));
}
public void AddNode(String nodename, String parent-
name){ model = (DefaultTreeModel)tree.getModel();
nNode = new DefaultMutableTreeNode(nodename);
if (parentname == "Sport"){
model.insertNodeInto(nNode, parent, par-
ent.getChildCount());
}else if (parentname == "Outdoor Sport"){
model.insertNodeInto(nNode, outdoor, out-
door.getChildCount());
}else if (parentname == "Indoor Sport"){
model.insertNodeInto(nNode, indoor, in-
door.getChildCount());
}else if (parentname == "Ski"){
model.insertNodeInto(nNode, ski,
ski.getChildCount());
}else if (parentname == "Soccer"){
model.insertNodeInto(nNode, soccer, soc-
cer.getChildCount());
}else if (parentname == "Tennis"){
model.insertNodeInto(nNode, tennis, ten-
nis.getChildCount());
}else if (parentname == "Pingpong"){
model.insertNodeInto(nNode, pingpong, ping-
pong.getChildCount());
}else if (parentname == "Ice Skate"){
model.insertNodeInto(nNode, iceskate,
iceskate.getChildCount());
}else if (parentname == "Chess"){
model.insertNodeInto(nNode, chess,
chess.getChildCount());
} }
public void deleteNode(String nodename){
model = (DefaultTreeModel) (tree.getModel());
if (nodename == "Sport"){
model.removeNodeFromParent(parent);
}else if (nodename == "Outdoor Sport"){
model.removeNodeFromParent(outdoor);
}else if (nodename == "Indoor Sport"){
model.removeNodeFromParent(indoor);
}else if (nodename == "Ski"){
model.removeNodeFromParent(ski);
}else if (nodename == "Soccer"){
model.removeNodeFromParent(soccer);
}else if (nodename == "Tennis"){
model.removeNodeFromParent(tennis);
}else if (nodename == "Pingpong"){
model.removeNodeFromParent(pingpong);
}else if (nodename == "Ice Skate"){
model.removeNodeFromParent(iceskate);
}else if (nodename == "Chess"){
model.removeNodeFromParent(chess);
} }
public String[] getSport() { return sport; }
public void setStandardIcon(){}
public void setNoIcon(){
renderer2 = new DefaultTreeCellRenderer();
renderer2.setOpenIcon(null);
renderer2.setClosedIcon(null);
renderer2.setLeafIcon(null);
}
public void setCustomIcon(){
img = new ReadImage(0); oimg = new ReadImage(1);
cimg = new ReadImage(2);
i1 = img.getImage(); i2 = oimg.getImage();
i3 = cimg.getImage();
licon = new ImageIcon(i1); oicon = new ImageIcon(i2);
cicon = new ImageIcon(i3);
renderer = new DefaultTreeCellRenderer();
renderer.setOpenIcon(oicon);
renderer.setClosedIcon(cicon);
renderer.setLeafIcon(licon);
} }
Figure-3: Application Tree without using NDSWrapper class.
1 / 7 100%
La catégorie de ce document est-elle correcte?
Merci pour votre participation!

Faire une suggestion

Avez-vous trouvé des erreurs dans linterface ou les textes ? Ou savez-vous comment améliorer linterface utilisateur de StudyLib ? Nhésitez pas à envoyer vos suggestions. Cest très important pour nous !