Breadcrumbs framework for Grails

This post describes a simple framework that can be used for implementing breadcrumbs in a Grails application. lets get started…

The three main components of this framework are:

  • Breadcrumb configuration XML which is used to defined breadcrumb hierarchy and attributes.
  • Breadcrumb manager which is used for parsing/loading XML configuration file, finding correct breadcrumb for the page and in general managing breadcrumb implementation
  • Custom tag <g:breadCrumb> which is used to embedded breadcrumbs on pages.

Lets look at breadcrumbs.xml first, I placed this XML in WEB-INF folder of the application right next to applicationContext.xml

breadcrumbs.xml

<!-- Bread crumb configuration XML -->
<breadcrumbs>
	<!-- Mapping is used to define the navigation structure for a bread crumb, it is based on the site map.
		 matchController and matchAction are used to figure location of requested page on the site by matching
		 the controller/action of the request to matchController/matchAction combination. Once a match is found
		 bread crumb hierarchy is resolved and information crumbs tag is used to get details related to each
		 bread crumb. All attributes in <nav> tag are mandatory
	-->
	<map>
		<nav id="homeCrumb" matchController="samplePages" matchAction="homeBreadCrumbPage">
			<!-- levels navigation -->
			<nav id="itemsLevel1Crumb" matchController="samplePages" matchAction="level1BreadCrumbPage">
				<nav id="itemsLevel2Crumb" matchController="samplePages" matchAction="level2BreadCrumbPage">
					<nav id="itemsLevel3Crumb" matchController="samplePages" matchAction="level3BreadCrumbPage">
						<nav id="showItemCrumb" matchController="samplePages" matchAction="itemDetailsBreadCrumbPage"/>
					</nav>
				</nav>
			</nav>
			<nav id="simple1Crumb" matchController="samplePages" matchAction="simpleBreadCrumb"/>
			<nav id="simple2Crumb" matchController="samplePages" matchAction="simpleBreadCrumbWithAttr"/>
			<!-- levels navigation -->
		</nav>
	</map>

		<!-- Information in <crumb> tag is used to figure out detail of individual bread crumb, the navigation bread crumb
			 and details are matched using id attribute. If for a 'id' in navigation map no details bread crumb id is found
			 then the 'id' is ignored.

			  - Optional viewController and viewAction attributes in XML should be supplied together, if any one of them
			  is missing other will be ignored.

			  - viewController/viewAction combination has a higher precedence than viewTemplate, viewTemplate attribute
			  will be ignored if both are present

			  - linkToController/linkToAction combination has a higher precedent than link, link attribute  will be ignored
			  if both are present

			  - Optional linkToController and linkToAction attributes in XML should be supplied together, if any one of them
			  is missing other will be ignored

			  - If rendering of a bread crumb is delegated to action/template then bread crumb title needs to be generated by
				renderer

			  - Optional parameters can be supplied for each id in JSON format i.e. params = { foo: 'bar' , key: 'value'}

			  - Requested page is given an opportunity to define the title/link if the bread crumb by supplying title/link attribute
			    If these are supplied then configured title/link in XML are overridden
		-->
	<crumbs>
		<crumb id="homeCrumb" title="Home" linkToController="samplePages" linkToAction="homeBreadCrumbPage" />
		<crumb id="itemsLevel1Crumb" viewController="breadCrumb" viewAction="renderLevel1Crumb" />
		<crumb id="itemsLevel2Crumb" viewController="breadCrumb" viewAction="renderLevel2Crumb" />
		<crumb id="itemsLevel3Crumb" viewController="breadCrumb" viewAction="renderLevel3Crumb" />
		<crumb id="showItemCrumb" />
		<crumb id="simple1Crumb" title="Simple1"/>
		<crumb id="simple2Crumb"/>
	</crumbs>
</breadcrumbs>

XML file is divided into two sections, first section is used to define hierarchical relationship between the views for which we need to display breadcrumbs. For each element we define matchController/matchAction attributes which are used by our custom tag to figure out its position in breadcrumb hierarchy based on current page. We also define unique ‘id’ attribute for each element, this is used in second section of XML to define properties used while rendering the breadcrumb. Please go though the comments in the XML for more details.

Now lets look at elements that provide breadcrumb manager implementation

The first code element is BreadCrumb.groovy which provides an object for holding properties loaded from XML for each breadcrumb

BreadCrumb.groovy

package org.breadcrumbs

import org.apache.commons.lang.builder.EqualsBuilder
import org.apache.commons.lang.builder.HashCodeBuilder

/**
 * class for handling BreadCrumbs
 * 
 */
class BreadCrumb {
	
	// mandatory bread crumb identifier, checked while parsing XML
	String id
	
	// Title to be used for the Bread Crumb (optional)
	String title
	
	// Controller to be used to render the view (optional)
	String viewController
	
	// Action to be used to render the view (optional)
	String viewAction
	
	// If controller/action is not required, only template can 
	// be supplied for rendering the view (optional)
	String viewTemplate
	
	// link that needs to attached to bread crumb title (optional)
	String link
	
	// Controller that should be used to create link for title (optional)
	String linkToController
	
	// Action that should be used to create link for title (optional)
	String linkToAction
	
	// crumb parameters map, loaded from XML configuration
	def params 
	
	/*
	 * Create a copy of bread crumb instance
	 */
	def getCopy () {
		def paramList = [:]
		for ( e in params ) 
			paramList.put (e.key, e.value)
                 
		return new BreadCrumb(title: this.title, link: this.link, 
				viewController: this.viewController, viewAction: this.viewAction, viewTemplate: this.viewTemplate,
				linkToController: this.linkToController, linkToAction: this.linkToAction, params: paramList)
	}
	
	@Override
	int hashCode () { 
		return new HashCodeBuilder().append(this.id).toHashCode() 
	}
	
	@Override
	boolean equals (Object other) { 
		if(other?.is(this)) 
			return true 
		if(!(other instanceof BreadCrumb)) 
			return false 
		
		return new EqualsBuilder().append(this.id, other.id).isEquals() 
	}
}

Second element is custom exception for breadcrumbs
BreadCrumbException.groovy

package org.breadcrumbs

/**
 * class to handle bread crumb Exceptions 
 */
class BreadCrumbException extends Exception  {
    
	BreadCrumbException() {
		super();
	}
	
	BreadCrumbException(Exception e) {
		super(e);
	}
	
	BreadCrumbException (String text) {
		super (text);
	}
}

Third and last element is BreadCrumbManager.groovy which provides lazy loaded singelton instance as breadcrumb manager
BreadCrumbManager.groovy

package org.breadcrumbs

import org.apache.commons.logging.LogFactory
import grails.converters.XML
import org.codehaus.groovy.grails.commons.ApplicationHolder
import grails.converters.*
import org.codehaus.groovy.grails.web.json.*
import org.codehaus.groovy.grails.web.converters.exceptions.ConverterException

import org.breadcrumbs.BreadCrumbException


/**
 * Singleton class for managing BreadCrumbs
 */
class BreadCrumbManager {
	
	private static def log = LogFactory.getLog("grails.app.BreadCrumbManager")
	
	private static def NAVIGATION_TAG = "nav"
	private static def CRUMB_DETAIL_TAG = "crumb"
	private static def CRUMB_DELIMITER = "."
	private static def ALL_ACTION_WILDCARD = "*"	
	private static def XML_FILE_PATH = "WEB-INF/breadcrumbs.xml" 
	
	// instance is not lazy loading because bread crumbs are required on all pages
	private static BreadCrumbManager manager = new BreadCrumbManager()
	
	// Map stores bread crumb navigation id's for matchers
	private def matcherToCrumbIdsMap 
	// Map stores bread crumb instance for each bread crumb id
	private def crumbIdDetailMap                           
		
	/**
	 * private constructor for creating BreadCrumbManager instance
	 */
	private BreadCrumbManager() {
		matcherToCrumbIdsMap = [:]
		crumbIdDetailMap = [:]
		// load navigation maps and bread crumb attributes from XML instances
		loadBreadCrumbsFromXML()
	}
	
	/**
	 * Return existing BreadCrumb manager instance 
	 */
	static BreadCrumbManager getInstance() {
		return manager
	}
	
	/**
	 * Match and retrieve bread crumbs navigation list 
	 * 
	 * @param  controller: controller to be matched
	 * @param  action: action to be matched
	 * 
	 * @return list of applicable bread crumb instances
	 */
	def getBreadCrumbs (def controller, def action) {
		
		def key = getMatcherKey(controller, action)
		def crumbs = matcherToCrumbIdsMap.get(key)
		
		if (!crumbs) {
			// if id not for for specific controller/action combination, try to get
			// an id applicable to all actions of a controller
			def alternatekey = getMatcherKey(controller, ALL_ACTION_WILDCARD)
			crumbs = matcherToCrumbIdsMap.get(alternatekey)
		}
		
		// log if still not found
		if (!crumbs) {
			log.warn "No matching crumbs for key ${key}" 
		} else {
			log.debug "Matching crumbs for key ${key} : ${crumbs}" 
			
			def crumbArray = crumbs.split('\\.')
			def crumbList = []
			crumbArray.each { crumb ->
				def crumbObj = crumbIdDetailMap.get(crumb)
				
				if (crumbObj) {
					// create a copy of original crumb object and add to list
					crumbList.add (crumbObj.getCopy())
				} else {
					log.info "Crumb details not found for '${crumb}' "
				}
			}
			return crumbList
		}
	}
	
	/**
	 * Construct a matcher key from controller and action  
	 * 
	 * @param  controller: controller to be matched
	 * @param  action: action to be matched
	 * 
	 * @return matcher string
	 */
	def getMatcherKey(def controller, def action) {
		if (controller && action)
			return "${controller.toLowerCase()}/${action.toLowerCase()}"
	}
	
	/**
	 * load navigation map and crumb details from XML  
	 * 
	 */
	private loadBreadCrumbsFromXML () {
		// get application context and resource
		def file = ApplicationHolder.application.getParentContext().getResource(XML_FILE_PATH).getFile()  
		log.debug "Loading breadcrumbs from file " + file.getAbsolutePath()  
		
		def xml = new XmlParser().parse(file)
		xml.depthFirst().each { node ->
			
			if (node.name() == NAVIGATION_TAG) {
					// throw exception if any of the required attributes are missing
					if (!node.@id || !node.@matchController || !node.@matchAction) {
						throw new BreadCrumbException("Required attribute for navigation missing, please validate XML ")
					}	
					
					def key = getMatcherKey(node.@matchController, node.@matchAction)
					
					if (matcherToCrumbIdsMap.get(key)) {
						throw new BreadCrumbException("Duplicate matcher key found: ${key}")
					} else {
						def p = node.parent()
						def crumbs = node.@id
						// move towards top of tree from current node to get crumb hierarchy 	
						while(p?.parent() != null) {
							if (p.name() == NAVIGATION_TAG) {
								crumbs = p.@id + CRUMB_DELIMITER + crumbs
							}
							p = p.parent()
						}
						
						log.debug "Putting matcher key: ${key} for crumb navigation ${crumbs} "
						matcherToCrumbIdsMap.put(key, crumbs.toLowerCase())
					}
			} else {
				if (node.name() == CRUMB_DETAIL_TAG) {
					def id = node.@id
					if (!id) {
						throw new BreadCrumbException("Required attribute 'id' for crumb  missing, please validate XML ")
					}
					
					def crumbParams
					
					if (node.@params) {
						// try parsing params
						try {
								crumbParams = JSON.parse(node.@params) // Parse a JSON param string
						} catch(ConverterException exp) {
							throw new BreadCrumbException("Params: ${node.@params} specified in incorrect format " +
									"for id: '${id}' , please validate XML ")
						}
					}
				
					log.debug "Putting crumb detail for id: ${id}"
					// create a bread crumb object and save it on details map
					crumbIdDetailMap.put(id.toLowerCase(), new BreadCrumb(title: node.@title, link: node.@link, 
							viewController : node.@viewController, viewAction: node.@viewAction, 
							viewTemplate: node.@viewTemplate, linkToController: node.@linkToController,
							linkToAction: node.@linkToAction, params: crumbParams))
				}
			}
		}
	}
}

Now lets have a look at the BreadCrumbTagLib which is defined in grails-app/taglib directory
BreadCrumbTagLib.groovy

package org.breadcrumbs

import org.breadcrumbs.BreadCrumbManager;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.LogFactory; 

class BreadCrumbTagLib {
	
	static def log = LogFactory.getLog("grails.app.breadCrumbTag")
	
	def breadCrumb = { attrs , body ->
	
			def manager = BreadCrumbManager.getInstance()
			def uri = request.getRequestURI() 
			def context = request.getContextPath() 
			
			def controller = params.controller
			def action = params.action
			
			def attrTitle =  attrs.title
			def attrLink = attrs.link
				
			// if controller and action are missing from params try to get them from request url
			if (!controller && !action && uri && context && uri.indexOf(context) != -1) {
				def uriParams = uri.substring(uri.indexOf(context) + (context.length() + 1), uri.length())
				def uriArray = uriParams.split('/')
				
				if (uriArray.size() >= 2 ) {
					controller = uriArray[0]
					action = uriArray[1]                       
				}
			}
			
			def crumbs = manager.getBreadCrumbs(controller, action)
			
			if (crumbs) {
				out << '<div class="breadcrumb"><ul>'
				def size = crumbs.size()
				crumbs.eachWithIndex { crumb, index ->
					out << '<li>'
					
					// override title and link of breadcrumb on current page (i.e. last bread crumb in hierarchy)
					// if name, link attributes are supplied
					if (index == size - 1) {
						if (attrTitle)
							crumb.title = attrTitle
						if (attrLink)
							crumb.link = attrLink
					}
					// set title to undefined if not found, associated 
					// renderer if present can overwrite it
					if (!crumb.title)
						crumb.title = "undefined"
					if (crumb.title && crumb.title.size() > 40)
						crumb.title = crumb.title.substring(0, 40) + "..."
						
					if (crumb.viewController && crumb.viewAction) {
						def content = g.include(controller:crumb.viewController, action:crumb.viewAction, breadcrumb:crumb, params:params)
						out << content
					} else if (crumb.viewTemplate) {
						def content = g.include(view:crumb.viewTemplate, breadcrumb:crumb, params: params)
						out << content
					} else if (crumb.linkToController && crumb.linkToAction && (size - 1 > index)){
						out << "<a href=\"${g.createLink (controller: crumb.linkToController, action: crumb.linkToAction)}\">${crumb.title}</a>"
					// if crumb has a link and its not the last vread crumb then show link else
					// just show the text
					} else if (crumb.link && (size - 1 > index)){
						out << "<a href=\"${crumb.link}\">${crumb.title}</a>"
					} else {
						out << "${crumb.title}"
					}
					out << "</li>"
					// do not print for last bread crumb
					if (size - 1 > index)
						out << "<li>&raquo;</li>"
				}
				out << "</ul></div>"
			}
	}
}

Lets also define basic css that is used for displaying breadcrumbs on pages

breadcrumbs.css


.breadcrumblist_selected {
	color:#a4db2f;
}

.breadcrumblist_selected a {
	text-decoration:none!important;
}

.breadcrumb {
	padding-left:15px; margin-top:5px; width:600px;
}
.breadcrumb ul {
	margin:0; padding:0;
}
.breadcrumb ul li {
	display:inline; font-size:14px; color:#FF9900
}
.breadcrumb ul li a {
	color:#2cbe0c
}

Now lets look at the demo code for breadcrumb implementation
Starting URL for the demo application will be something like http://localhost:8080/sample/samplePages/homeBreadCrumbPage if deployed on localhost on port 8080

Following is the controller code used for displaying sample pages in demo, each action defined in the controller refers to a demo page
samplePagesController.groovy

package com.pages

class samplePagesController {
	
	def homeBreadCrumbPage = { }

	def allItemsBreadCrumbPage = { }

	def level1BreadCrumbPage = { }
	
	def level2BreadCrumbPage = { }
	
	def level3BreadCrumbPage = { }
	
	def itemDetailsBreadCrumbPage = { }
	
	def simpleBreadCrumb = { }
	
	def simpleBreadCrumbWithAttr = { }
}

Lets look at the code for some of the views, code for remaining views can be found in zipped code attached with the post

Simple breadcrumb page includes the css that we defined for breadcrumbs and has a <g:breadCrumb/> tag at a place where breadcrumb needs to be displayed

simpleBreadCrumb.gsp

<html>
	<head>
		<link rel="stylesheet" href="${resource(dir:'css',file:'breadcrumbs.css')}" />
	</head>
  	<body>
	<g:breadCrumb/>
	<h3>Simple breadcrumbs</h3>
	</body>
</html>

The image below how breadcrumb will be shown in running application, The ‘Home’ link is clickable and will take user to page defined in configuration XML, please note that for the displayed page, controller is ‘samplePages’ and action is ‘simpleBreadCrumb’. If you look at first section of configuration XML you will figure out how breadcrumb hierarchy is being displayed

The next sample view that we are going to look at is itemDetailsBreadCrumbPage.gsp

itemDetailsBreadCrumbPage.gsp

<html>
	<head>
		<link rel="stylesheet" href="${resource(dir:'css',file:'breadcrumbs.css')}" />
	</head>
  	<body>
	<g:breadCrumb title='Selected Item'/>
	<h3>Item Details Page</h3>
	</body>
</html>

The image below shows how the breadcrumb will get rendered on runtime

Please note that the drop down displayed for breadcrumbs are clickable, we will shortly discuss how we displayed drop downs instead of text for these breadcrumbs but important point to note here is that you can have complex elements like sliders and popups here instead of drop downs as breadcrumb elements.

OK, lets see how these drop downs were displayed
We have following configuration in breadcrumbs.xml for this page

	<nav id="showItemCrumb" matchController="samplePages" matchAction="itemDetailsBreadCrumbPage"/>

The navigation hierarchy that we get for this page is homeCrumb->itemsLevel1Crumb->itemsLevel2Crumb->itemsLevel3Crumb->showItemCrumb

When we start rendering each breadcrumb in hierarchy and encounter ‘itemsLevel1Crumb’ we know that for this breadcrumb we need to execute controller ‘breadCrumb’ and action ‘renderLevel1Crumb’ to get the content so we invoke it

		<crumb id="itemsLevel1Crumb" viewController="breadCrumb" viewAction="renderLevel1Crumb" />
		<crumb id="itemsLevel2Crumb" viewController="breadCrumb" viewAction="renderLevel2Crumb" />
		<crumb id="itemsLevel3Crumb" viewController="breadCrumb" viewAction="renderLevel3Crumb" />

Following is the source code for controller breadCrumb
breadCrumbController.groovy

package org.breadcrumb

class breadCrumbController {

    def renderLevel1Crumb = { }
	
	def renderLevel2Crumb = { }
	
	def renderLevel3Crumb = { }
}

Following are the contents if renderLevel1Crumb.gsp
renderLevel1Crumb.gsp

<select>
<option>Level1 - A</option>
<option>Level1 - B</option>
<option>Level1 - C</option>
<option>Level1 - D</option>
</select>

Hence the breadcrumb with id ‘itemsLevel1Crumb’ gets rendered into a drop down, similar is the case with other drop down breadcrumbs.

You can download the code here. Note that application was created with grails 1.2.2

Use following URL for running the demo after deploying it on grails (please update host/port configuration)
http://localhost:8080/sample/samplePages/homeBreadCrumbPage

Java developers prepare for upcoming trends in software industry!

The Only Thing That Is Constant Is Change”

Like everything else ecosystem around java professional is also changing and from what I gather future holds bigger changes then we are used to. Experts and veterans are already debating if java is dying, some feel that Java has reached its peak and nothing major can be done with its present language core. Only time will tell what future of java is going to be, but consensus is that whether or not java survives, JVM is here to stay i.e. dominant language of the future will have to support JVM. I personally feel that java is not going anywhere soon and may still be one of dominant language for years to come. In any case java professionals should be aware of uncertainty that java as a language faces in future and should prepare accordingly.

Learn Functional Language

As you may have already observed processors have stopped getting faster, and the number of cores available in a CPU are growing rapidly. In order to utilize a multi core processor, the operating system must be able to recognize multi-threading and the software must have simultaneous multi-threading technology (SMT) written into its code. SMT enables parallel multi-threading wherein the cores are served multi-threaded instructions in parallel. Without SMT the software will only recognize one core so  an average user with multi-core processor will notice the difference in performance if software is SMT aware. So bottom line is that we need to build concurrent software’s to make best use of hardware available to us.

Compilers can’t automatically parallelize imperative/object-oriented code, so programming styles have to change. Algorithmically simple concurrency can be achieved using libraries and extensions to existing languages. For example we can use the concurrent package in Java. But building complex, fine-grained concurrent systems quickly runs into a complexity wall in languages like Java. The answer is functional programming, functional languages like Erlang, Haskell and Scala offer better support for concurrency with features  like actor concurrency, software transactional memory and nested data parallelism. So learn a functional programming language. As a Java programmer, the easiest way to go is learning Scala. Parallelization is going to be huge and knowing how to write scalable and maintainable code for parallel systems will be a big plus.

Follow the Cloud

Another trend that has already gained a level of momentum is Cloud computing. Cloud computing that way I understand it is a virtualized, self monitoring, self healing and automatically configured network of computers managed with awareness of the user load and service level required for each of the applications deployed on it. As the load on an application increases more resources are allocated to it automatically from the network to maintain the service level. As the load decreases the resources are de-allocated automatically. Considering that applications deployed on the network will have different peak times, instead of allocating dedicated hardware to each of the application we can have a shared virtualized hardware infrastructure which translates into cost saving.  This network of computers is called a cloud because users and applications running on the network will not have the awareness of the physical hardware being used to service the request at a given point of time, so from this point of view the network is essentially a cloud of similar machines processing requests. The word “cloud” emphasizes the thinking which considers the whole network as a unit rather than a collection of units or machines.

Cloud development paradigms like distributed computing and scalability are not new to java, synergy between java and cloud computing is evident.  Java EE was designed to be deployed to a distributed environment. Cluster management and extensive monitoring and management capabilities are supported by major application servers. Most of the technological changes for supporting the cloud are focused at a system level and it’s largely unclear how exactly to prepare for this as a java professional, but be sure to watch trends carefully and study accordingly. One emergent impact of cloud is the implementation of persistence services. Some cloud providers, like Google or Amazon, don’t offer support for relational databases. So you either have to live with the map-like structure or try to install a relational database in the cloud. This necessitates some rethinking about how the persistence should be designed and can even impact the design of the user interface.

Chain of Creation

Allow me to propose a new creational design pattern “Chain of Creation”, as the name suggests the pattern is inspired by well known Behavioral pattern “Chain of Responsibility”. The Chain of Creation pattern delegates the task of creating the most suitable instance for processing a set of data to a group of related classes. Each of these classes is unaware of the capabilities of other classes in the chain and is only aware of its own capabilities in handling the data.  The only common link in these classes is the data that is passed between them, the data is passed along until an object which is capable of handling the data is created or the length of chain is exhausted in which case a null is returned.

Applicability

Chain of Creation can be used when

  • Without specifying explicitly you want to create an instance of class from several possible implementing classes based on available data.
  • A class can’t anticipate which kind of object it must create.
  • You want to encapsulate the capability of each class in the class itself so that it can be reused.
  • You want to be able to modify the set of related creational classes that are capable of handling data dynamically at run time.

Consequences of the Chain of Creation

  • The main purpose for this pattern is to reduce dependency between creator and created object.
  • The class made aware of its capabilities and hence can be reused.
  • Any changes to the capabilities of a class does not have impact other classes.

The example below provides a sample implementation for Chain of Creation pattern. The objective is to create a terrain from possible types available and then let the chain of classes provide most suitable vehicle for the terrain.

Terrain.java

package pattern.coc;

public interface Terrain {

	public boolean hasRoads();

	public boolean isRugged();

	public boolean isSandy();

}

City.java

package pattern.coc;

public class City implements Terrain {

	public String getName() {
		return "New Delhi";
	}

	public boolean hasRoads() {
		return true;
	}

	public boolean isRugged() {
		return false;
	}

	public boolean isSandy() {
		return false;
	}
}

Desert.java

package pattern.coc;

public class Desert implements Terrain {

	public String getName() {
		return "Thar Desert";
	}

	public boolean hasRoads() {
		return false;
	}

	public boolean isRugged() {
		return true;
	}

	public boolean isSandy() {
		return true;
	}
}

Forest.java

package pattern.coc;

public class Forest implements Terrain {

	public String getName() {
		return “Sariska Forest”;
	}

	public boolean hasRoads() {
		return false;
	}

	public boolean isRugged() {
		return true;
	}

	public boolean isSandy() {
		return false;
	}
}

Vehicle.java

package pattern.coc;

public interface Vehicle {

	public String getName();

	public void ignition();

	public void accelerate();

	public void brake();

	public void turnOff();
}

Creator.java

package pattern.coc;

public abstract class Creator {

	private Creator successor;

	public Vehicle create(Terrain terrain) {
		if (successor != null)
			return successor.create(terrain);
		else // no suitable creator found
			return null;
	}

	public void setSuccessor(Creator c) {
		this.successor = c;
	}
}

Car.java

package pattern.coc;

public class Car implements Vehicle {

	private static class CarCreator extends Creator {

		public Vehicle create(Terrain terrain) {

			if (!terrain.isRugged() && !terrain.isSandy() && terrain.hasRoads())
				return new Car();
			else
				return super.create(terrain);
		}
	}

	public static Creator getCreator() {
		return new CarCreator();
	}

	public String getName() {
		return "Car";
	}

	public void ignition() {
		System.out.println("Car ignition");
	}

	public void accelerate() {
		System.out.println("Car accelerated");
	}

	public void brake() {
		System.out.println("Car brake");
	}

	public void turnOff() {
		System.out.println("Car engine off");
	}
}

Jeep.java

package pattern.coc;

public class Jeep implements Vehicle {

	private static class JeepCreator extends Creator {

		public Vehicle create(Terrain terrain) {

			if (terrain.isRugged() && !terrain.isSandy() && !terrain.hasRoads())
				return new Jeep();
			else
				return super.create(terrain);
		}
	}

	public static Creator getCreator() {
		return new JeepCreator();
	}

	public String getName() {
		return "Jeep";
	}

	public void ignition() {
		System.out.println("Jeep ignition");
	}

	public void accelerate() {
		System.out.println("Jeep accelerated");
	}

	public void brake() {
		System.out.println("Jeep brake");
	}

	public void turnOff() {
		System.out.println("Jeep engine off");
	}
}

AVT.java

package pattern.coc;

public class AVT implements Vehicle {

	private static class AVTCreator extends Creator {

		public Vehicle create(Terrain terrain) {

		if (terrain.isRugged() && terrain.isSandy() && !terrain.hasRoads())
			return new AVT();
		else
			return super.create(terrain);
		}
	}

	public static Creator getCreator() {
		return new AVTCreator();
	}

	public String getName() {
		return “All-terrain Vehicle”;
	}

	public void ignition() {
		System.out.println(“AVT ignition”);
	}

	public void accelerate() {
		System.out.println(“AVT accelerated”);
	}

	public void brake() {
		System.out.println(“AVT brake”);
	}

	public void turnOff() {
		System.out.println(“AVT engine off”);
	}
}

Client.java

package pattern.coc;

public class Client {

	public static void main(String args[]) {

		Desert terrain = new Desert();
		Creator creator = Car.getCreator();
		Creator jeep = Jeep.getCreator();
		Creator avt = AVT.getCreator();
		creator.setSuccessor(jeep);
		jeep.setSuccessor(avt);

		Vehicle v = creator.create(terrain);
		System.out.println("Driving in " + terrain.getName() + " using " + v.getName());

		v.ignition();
		v.accelerate();
		v.brake();
		v.turnOff();
	}
}