Click here to Skip to main content
Click here to Skip to main content

Building Tree Structure Domain Model

, 12 Dec 2008 CPOL
Rate this:
Please Sign up or sign in to vote.
How to build domain model with tree structure, thinking Object-Oriented

Introduction

When I was an MIS engineer, I maintained a schedule system. There are many jobs controlled by auto schedule system, see the example XML file below: Because the XML file is a tree structure, it can describe the job flow cleanly.

<Schedule>
<JobGroup>
<BatchJob id="1" name="job1"></BatchJob>
<BatchJob id="2" name="job2"></BatchJob>
<JobGroup id="3" name="job3">
<BatchJob id="4" name="job3-1"></BatchJob>
<BatchJob id="5" name="job3-2"></BatchJob>
<JobGroup id="6" name="job3-3">
<BatchJob id="7" name="job3-3-1"></BatchJob>
</JobGroup>
</JobGroup> 
</JobGroup>
</Schedule>

But how can we build a domain model with a programming language? There is a system design issue.

Background

The code is written in Java, compiled with JavaSE 5. You have to know the concepts of XML, UML and Design Pattern.

Using the Code

How to build a tree structure domain model? I use the composite design pattern!

treemodeluml

Consider the following source code:

Job is an abstract class and is the parent class of BatchJob and JobGroup:

package org.schedulemanager.demo.model;

import java.util.ArrayList;
import java.util.List;

public abstract class Job {
    protected String id;
    protected String name;
    protected String circle;
    protected String type;

    public final static String BATCHJOB = "BATCHJOB";
    public final static String JOBGROUP = "JOBGROUP";
    
    public final static String DAILY = "DAILY";
    public final static String WEEKLY = "WEEKLY";
    public final static String MONTHLY = "MONTHLY";
    
    public Job(String id) {
        this.id = id ;
    }
    
    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public abstract void addJob(Job job);
    public abstract List<job> getJobList();    

}

JobGroup is a job that does not do anything, it's the child of Job, but it is also the container of Job. JobGroup has a circle field to set the execute time.

package org.schedulemanager.demo.model;

import java.util.ArrayList;
import java.util.List;

public class JobGroup extends Job {
    private List<job> jobList;

    public JobGroup(String id, String name) {
        super(id);
        this.type = JOBGROUP;
        this.name = name;
        jobList = new ArrayList<job>();
    }
    
    public JobGroup(String id, String name, String circle) {
        this(id, name);
        this.circle = circle;
    }
    
    public List<job> getJobList() {
        return jobList;
    }
    public void addJob(Job job){
        if(job!=null && job.getId()!=null){
            jobList.add(job);
        }
    }
    public String getCircle() {
        return circle;
    }

    public void setCircle(String circle) {
        this.circle = circle;
    }
    public boolean removeJob(String id){
        boolean result = false;
        for(int i=0;i<joblist.size();i++)
		{ job="jobList.get(i);" jobid="job.getId();" result="true;"

BatchJob is a job to do something:

package org.schedulemanager.demo.model;

import java.util.List;

public class BatchJob extends Job {

    public BatchJob(String id, String name) {
        super(id);
        this.type = BATCHJOB;
        this.name = name;
    }
    public void addJob(Job job) {
        System.err.println("BatchJob can not addJob!");
    }
    public List<job> getJobList() {
        return null;
    }

    public String toString() {
        return "id:" + id 
                + ",name:" + name 
                + ",type:" + type ;
    }
}

I create a CommandLineView to display a job flow on the console:

package org.schedulemanager.demo.view;

import java.util.List;

import org.schedulemanager.demo.model.Job;

public class CommandLineView {
	private Job job;

	public Job getJob() {
		return job;
	}

	public void setJob(Job job) {
		this.job = job;
	}
	
	public void printAllJobs() {
		printAllJobs(job, 0);
	}
	
	public void printAllJobs(Job job , int depth) {
		List<Job> jobList = job.getJobList();
		if(jobList!=null && jobList.size()>0){
			for(int i=0;i<jobList.size();i++){
				printDepth(depth);
				Job subJob = jobList.get(i);
				if(subJob.getType().equalsIgnoreCase
					(Job.BATCHJOB)){
					System.out.print("-");	
					System.out.println(subJob);
				}else if(subJob.getType().equalsIgnoreCase
							(Job.JOBGROUP)){
					System.out.print("+");
					System.out.println(subJob);
					printAllJobs(subJob, depth + 1);
				}
				
			}//end for
		}
	}
	
	public void printDepth(int depth) {
		for(int i=0;i<depth;i++){
			System.out.print("\t");
		}
	}
}

The manager is responsible to assemble model and view:

package org.schedulemanager.demo;

import org.schedulemanager.demo.model.BatchJob;
import org.schedulemanager.demo.model.JobGroup;
import org.schedulemanager.demo.model.Job;
import org.schedulemanager.demo.view.CommandLineView;

public class Manager {
	private Job rootJob;
	public Manager() {
		initJobs();
	}
	
	public void initJobs(){
		rootJob = new JobGroup("0", "rootJob",Job.DAILY);
		
		Job job1 = new BatchJob("1","job1");
		Job job2 = new BatchJob("2","job2");
		Job job3 = new JobGroup("3","job3",Job.DAILY);
		Job job4 = new BatchJob("4","job3-1");
		Job job5 = new BatchJob("5","job3-2");
		Job job6 = new JobGroup("6","job3-3",Job.DAILY);
		Job job7 = new BatchJob("7","job3-3-1");
		Job job8 = new BatchJob("8","job4");
		Job job9 = new BatchJob("9","job5");
		
		job6.addJob(job7);
		job3.addJob(job4);
		job3.addJob(job5);
		job3.addJob(job6);
		job3.addJob(job8);
		rootJob.addJob(job1);
		rootJob.addJob(job2);
		rootJob.addJob(job3);
		rootJob.addJob(job9);
	}

	public void run(){
		CommandLineView view = new CommandLineView();
		view.setJob(rootJob);
		view.printAllJobs();
	}
	public static void main(String[] args) {
		Manager manager = new Manager();
		manager.run();
	}
}

The running result is shown below:

treemodeluml_cmd

You can also create other view (Web, GUI, etc.) easily with the domain model.

Points of Interest

Think about job dependency! Batch Job is in sequence. So the job dependency is an important issue. Our tree domain model is with scalability, we can add the job class dependencyList field. The additional UML is shown below:

treemodeljob

Summary

Thinking about this tree structure domain model, it can be useful with many practices, for example: project manage tool, file system, tree GUI, etc. Don't only think about the recursion algorithm to display tree structure, we can think and design more Object-Oriented by creating the domain model first.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

RipleyKuo
Software Developer
Taiwan Taiwan
No Biography provided

Comments and Discussions

 
GeneralMy vote of 1 PinmemberVickyC#18-Dec-08 1:50 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.1411022.1 | Last Updated 12 Dec 2008
Article Copyright 2008 by RipleyKuo
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid