The Friday Night Project #6 – Simple Quotation Engine

UDA
The UDA channel is for Teradata’s Unified Data Architecture including the Analytical Ecosystem and other UDA influences. This channel provides information specific to the integration and co-existence of multiple systems, in particular when a mix of Aster, Teradata, and Hadoop are present. It is also meant to support information around the UDA enabling technologies so products like Viewpoint, Data Mover, Connectors, QueryGrid, etc.
Teradata Employee

The Friday Night Project #6 – Simple Quotation Engine

TZA-InsuranceProcess is a set of APIs which provide a Suite of Business Processes that represent TZA-Insurance, ranging from a simple Quotation Engine for the demonstration of the architectural concepts, through Complex Insurance and Quotation Management for Web and Web service applications to Insurance Summaries that can be represented in a Web Portal.

These APIs are written in Java and provide a series of Business Processes that behave independently from each other or which can be orchestrated to provide a larger Business Service or Process. These APIs are embedded into a single jar file [known as TZA-InsuranceProcess.jar] which relies upon other Teradata implicit objects [as jar files] which are included in its classpath, such as tdcommons-context.jar and tdcommons-access.jar.

Creating the TZA-InsuranceProcess Project.

Start up your Eclipse IDE (including the Teradata Plug-In) against your Friday Night Project Workspace.

Workspace Launcher

Once the IDE is started, create a New Project.

  • Select File -> New -> Project -> Java -> Java Project -> Next
  • In the New Java Project Dialog fill in the Project name: TZA-InsuranceProcess.

New Java Project

  • Select Next >
  • In the Java Settings dialog select the "src" directory and select "Remove source folder 'src' from build path".
  • Select the "Create a new source Folder" link.
  • Define the Folder name: as "src/java" and select Finish.
  • Repeat for the rest of the normal Source Folders we will use src/config and src/resources.
  • Finally change the Default Output folder to TZA-InsuranceProcess/build and select Finish.

New Java Project - Java Settings


Add external Libraries (JAR files) to the "/lib/build" directory.

Within the Insurance Process where we wish to use external Libraries (JAR files) we place them in a User Library directory (/lib/build - to indicate these are needed at build time rather than runtime) that can then be referenced as part of the Class Path of the application during the build process.

  • Right click on TZA-InsuranceProcess project and select New > Folder
  • Set the Folder name: = 'lib/build' and Select Finish.

New Folder for lib/build

Within the Project Explorer view the TZA-InsuranceProcess project with the "src/java", "src/config", "src/resources" and "lib/build" folders will look like this.

Project Explorer with Source and Lib/build


Populate the TZA-InsuranceProcess Project.

We now start to populate the TZA-InsuranceProcess Project with elements such as the JDBC Driver JAR’s that allows us to access the Teradata Database.

When we need to add an external library such as commons-logging we can download a copy of the required library (typically these downloads come as a large .ZIP or .TAR file that require you to extract the required jar files using an approach appropriate to your Operating System, such WinZip on Windows), and save the required jar files to the /lib/build directory and then add them to the application classpath.

Add JDBC Driver

The first thing we do to populate the TZA-InsuranceProcess Project is add the necessary JAR files to the “lib/build” folder.

  • Add the Teradata JDBC Driver JAR’s you downloaded and used as part of the Getting started with teradata plug in for eclipse exercise.
  • Copy the two JAR files, namely tdgssconfig.jar and terajdbc4.jar from the download location (typically C:\TeraJDBC) and Paste them into the “lib/build” folder within the TZA-InsuranceProcess project.

Add commons-logging.

So we start by downloading the Apache commons-logging from http://commons.apache.org/logging/.

  • Download the latest commons-logging.jar file to your local /lib/build directory.

Add tdcommons-context.

We use Context Capture to maintain a record of application context throughout the Thread of Execution. To utilize these Teradata Common Components download the tdcommons-context.ZIP file and unzip tdcommons-context.jar into the /lib/build directory of your project.

  • Select tdcommons-context.zip (Open with WinZip) and export tdcommons-context.jar into the /lib/build directory of the project.

Add tdcommons-access.

The Teradata Access approach is used to provide a consistent approach to accessing a Teradata Database through a JDBC based Data Source / Connection Pool. To utilize these Teradata Common Components download tdcommons-access.jar and save it to the /lib/build directory of your project.

  • Select tdcommons-access.zip (Open with WinZip) and export tdcommons-access.jar into the /lib/build directory of the project.

Refresh Eclipse

Whenever changes are made to the directory structure of an Eclipse Project (out with the Eclipse environment) it is necessary to let Eclipse know what is going on "under the covers".

  • Select the TZA-InsuranceProcess project and use the F5 function key to refresh the environment.
  • Alternatively Right Click on TZA-InsuranceProcess project and select the Refresh option.

Within the Project Explorer view the TZA-InsuranceProcess "lib/build" folders will look like this.

Project Explorer with Jars.


Add the JAR's in /lib/build Folder to the classpath

Once all the libraries / JAR files have been added to the /lib/build directory they can be added to the project classpath within Eclipse, this allows Eclipse to make these classes available within the editing environment and compile all of the code without errors.

  • Right click on TZA-InsuranceProcess and select Build Path > Configure Build Path...
  • In the Properties for TZA-InsuranceProperties dialog select the "Libraries" tab -> Add Library... -> User Library
  • Select Next >, User Libraries..., New... and provide a User library name like InsuranceProcessBuildLib.
  • Use the Add JARs.. button to browse to the TZA-InsuranceProcess/lib/build directory.
  • Add all the JAR files to the classpath (Use the Shift Key to select all the files at once).
  • Select Open to "Add" these to your 'InsuranceProcessBuildLib' User Library.

Add User Library

  • Select OK, then Finish, then OK.

The InsuranceProcessBuildLib and it's associated JAR files will appear in Project Explorer like this.

Project Explorer with User Lib


Create Application and System level exceptions

The TZA-InsuranceProcess defines two general Caught Exceptions that can be used by Applications (ApplicationException and SystemException). ApplicationException is intended to indicate where some form of Application Error occurred (such as invalid parameters), which the calling Application should remedy. SystemException is intended to indicate when a system problem has occurred (such as the requested database not being available), which the calling application should gracefully handle.

Add Exception Package

We start by adding a Java Package to the src/java folder to hold the exception classes (note this illustrates the concept of Cohesion where we group similar elements in a single place).

  • Create a new package within src/java (Right Click src/java -> New -> Package ->
  • Set the Name: = com.teradata.tza.insurance.process.exception.

Add ApplicationException

Start by creating a new class (ApplicationException.java) in package com.teradata.tza.insurance.process.exception.

  • Right Click on src/java and select New -> Class
  • Browse to the Package "com.teradata.tza.insurance.process.exception".
  • Set the class Name to ApplicationException.
  • Click Finish and a template source file will open within the Eclipse editor.

The ApplicationException class can then be built up by replacing the template code with the following code segment within the ApplicationException.java file using copy and paste.

/** 
* The contents of this file are Teradata Public Content and have been released to the Public Domain.
* Please see the license.txt file in the top level directory for more information.
*
* @author John.Dewey@Teradata.com
*/
package com.teradata.tza.insurance.process.exception;

public class ApplicationException extends Exception
{
private static final long serialVersionUID = -702331128279336834L;
private Throwable cause; // Exception that generated DataAccessException
private String msg; // Application specific message
private int errorCode; // Application specific error code

public ApplicationException (String msg, Exception cause)
{
super(msg, cause);
this.msg = msg;
}

public ApplicationException (String msg)
{
super(msg);
this.msg = msg;
}

public Throwable getCause()
{
return cause;
}

public void setCause(Throwable cause)
{
this.cause = cause;
}

public String getMsg()
{
return msg;
}

public void setMsg(String msg)
{
this.msg = msg;
}

public int getErrorCode()
{
return errorCode;
}

public void setErrorCode(int errorCode)
{
this.errorCode = errorCode;
}
}

Add SystemException

Repeat the above for the SystemException class.

  • Right Click on src/java and select New -> Class
  • Browse to the Package "com.teradata.tza.insurance.process.exception".
  • Set the class Name to SystemException.
  • Click Finish and a template source file will open within the Eclipse editor.

The SystemException class can then be built up by replacing the template code with the following code segment within the SystemException.java file using copy and paste.

/** 
* The contents of this file are Teradata Public Content and have been released to the Public Domain.
* Please see the license.txt file in the top level directory for more information.
*
* @author John.Dewey@Teradata.com
*/
package com.teradata.tza.insurance.process.exception;

public class SystemException extends Exception
{
private static final long serialVersionUID = -3211803697447692517L;
private Throwable cause; // Exception that generated DataAccessException
private String msg; // Application specific message
private int errorCode; // Application specific error code

public SystemException (String msg, Exception cause)
{
super(msg, cause);
this.msg = msg;
}

public SystemException (String msg)
{
super(msg);
this.msg = msg;
}

public Throwable getCause()
{
return cause;
}

public void setCause(Throwable cause)
{
this.cause = cause;
}

public String getMsg()
{
return msg;
}

public void setMsg(String msg)
{
this.msg = msg;
}

public int getErrorCode()
{
return errorCode;
}

public void setErrorCode(int errorCode)
{
this.errorCode = errorCode;
}
}


Ant Build of Jar file

We use an Ant build.xml file to create a local copy of the TZA-InsuranceProcess.jar file into a distribution directory (/dist) within the TZA-InsuranceProcess project. From there we can include it (just like any other dependent Jar file) within any project we wish to create.

  • Right Click TZA-InsuranceProcess, Select New -> Other.. -> XML -> XML -> Next
  • Give the file name build.xml.
  • Click Finish and a template XML file will open within the Eclipse editor

The build.xml class can then be built up by replacing the template XML with the following XML segment within the build.xml file using copy and paste.

<?xml version="1.0"?>
<project name="TZA-InsuranceProcess - Local Build" basedir="." default="jar">

<property name="project.title" value="TZA-InsuranceProcess" />
<property name="project.package" value="com.teradata.tza.insurance.process" />

<property name="build.classes.dir" value="./build" />
<property name="dist.dir" value="./dist" />

<property name="revision" value="1.0-SNAPSHOT"/>

<target name="jar">
<delete dir="${dist.dir}"/>
<mkdir dir="${dist.dir}" />
<jar basedir="${build.classes.dir}" jarfile="${dist.dir}/${project.title}.jar" />
</target>

</project>

Add Buildfile to Ant View

The TZA-InsuranceProcess build.xml can be run from a stand alone Ant environment or from within Eclipse.

  • In Eclipse select Windows -> Show View -> Other... -> Ant -> Ant to open the Ant view

  • Within the Ant view select the Add Buildfiles.. option.

Add Buildfiles

  • Use the Buildfile Selection Dialog to find the TZA-InsuranceProcess build.xml and add it to this view.

Buildfile Selection

  • In the Ant View open up the TZA-InsuranceProcess - Build file.
  • Double Click the "jar [default]" task to create the TZA-InsuranceProcess.jar file.

Local Build jar Target

Refresh Eclipse

Because the Ant build works at the Hard Disk Level you need to Refresh Eclipse so it can pick up changes such as the creation of the /dist directory and the TZA-InsuranceProcess.jar.

  • Select the TZA-InsuranceProcess project and use the F5 function key to refresh the environment
  • Open up the dist directory and the TZA-InsuranceProcess.jar file will be visible.

Project Explorer with dist and jar

So that gets us the very basic structure and operations of the Insurance Process project constructed and ready to be populated with real Business Objects, Business Services and Data Access Objects.


Simple Quotation Engine

Having setup the basic TZA-InsuranceProcess Project it is now possible to populate the first part of the TZA-InsuranceProcess project namely the Simple Quotation Engine.

The Insurance Quotation Engine business process is a relatively simple set of classes that demonstrate the full vertical of a core Business Process starting with a Business Service layer that uses a collection of Business Objects (that represent a Physical Property or House that is to be insured) that act as input parameters to a getQuotation method of the business service. This Business Service utilizes a derived Business Object that is dynamically populated via a Data Access Object that represents Zip Code Risk Factors within an underlying Repository or Database.


Create the TZA-InsuranceProcess Business Objects

A small number of Business Objects are required to operate the Quotation Engine business process so we will define these first. All the source code for the Business Objects required by TZA-InsuranceProcess project is collected under the com.teradata.tza.insurance.process.businessObject package.

  • Select the TZA-InsuranceProcess project
  • Select File -> New -> Other.. -> Java -> Package.
  • Set the package Name: = "com.teradata.tza.insurance.process.businessObject"

New Java Package (BusinessObject)

  • Select Finish and the wizard will create this package.

Add the Property, Ownership & Property Type classes

The Property class describes all of the physical elements used to describe the Property (House, Apartment, etc) that we will be insuring. The Ownership class simply defines the different types of Ownership allowed (i.e. Owned, Rented, Mortgaged), similarly the PropertyType class defines the different types of Property available (i.e. Apartment, Condominium, Townhouse etc). Note these are Plain Old Java Objects (POJO’s) with getters and setters providing access to their internal properties (sorry for the overloaded terms Toto) and a zero argument constructor making them a Java Bean.

To add the Property class create a new class (Property.java) in package com.teradata.tza.insurance.process.businessObject.

  • Right Click on src/java and select New -> Class
  • Browse to the Package "com.teradata.tza.insurance.process.businessObject".
  • Set the class Name to Property.
  • Click Finish and a template source file will open within the Eclipse editor.

The Property class can then be built up by replacing the template code with the following code segment within the Property.java file using copy and paste.

/** 
* The contents of this file are Teradata Public Content and have been released to the Public Domain.
* Please see the license.txt file in the top level directory for more information.
*
* @author Mike.Coutts@Teradata.com
*/
package com.teradata.tza.insurance.process.businessObject;

import java.math.BigDecimal;
import com.teradata.tza.insurance.process.businessObject.Ownership;
import com.teradata.tza.insurance.process.businessObject.PropertyType;

public class Property implements java.io.Serializable
{
private static final long serialVersionUID = -6901762120759397839L;

private Integer propertyID;
private Integer customerID;

private java.lang.String houseNameNumber = "";
private java.lang.String streetAddress1 = "";
private java.lang.String streetAddress2 = "";
private java.lang.String streetAddress3 = "";
private java.lang.String streetAddress4 = "";
private java.lang.String city = "";
private java.lang.String state = "";
private java.lang.String zipCode = "";
private Ownership ownership = new Ownership(Ownership.Owned);
private int numBedrooms = 0;
private java.lang.String yearBuilt = "1970";
private PropertyType propertyType = new PropertyType(PropertyType.Detached);
private java.math.BigDecimal buildingsAmountInsured = new java.math.BigDecimal(0.00);
private boolean buildingsCover = false;
private boolean buildingsAccidentalCover = false;
private java.math.BigDecimal contentsAmountInsured = new java.math.BigDecimal(0.00);
private boolean contentsCover = false;
private boolean contentsAccidentalCover;
private java.math.BigDecimal singleItemLimit = new java.math.BigDecimal(0.00);
private boolean alarmed = false;
private boolean securityPatrolled = false;

public Property()
{
}

public Property
(
Integer propertyID,
Integer customerID,
java.lang.String houseNameNumber,
java.lang.String streetAddress1,
java.lang.String streetAddress2,
java.lang.String streetAddress3,
java.lang.String streetAddress4,
java.lang.String city,
java.lang.String state,
java.lang.String zipCode,
Ownership ownership,
int numBedrooms,
java.lang.String yearBuilt,
PropertyType propertyType,
java.math.BigDecimal buildingsAmountInsured,
boolean buildingsCover,
boolean buildingsAccidentalCover,
java.math.BigDecimal contentsAmountInsured,
boolean contentsCover,
boolean contentsAccidentalCover,
java.math.BigDecimal singleItemLimit,
boolean alarmed,
boolean securityPatrolled)
{
this.propertyID = propertyID;
this.customerID = customerID;
this.houseNameNumber = houseNameNumber;
this.streetAddress1 = streetAddress1;
this.streetAddress2 = streetAddress2;
this.streetAddress3 = streetAddress3;
this.streetAddress4 = streetAddress4;
this.city = city;
this.state = state;
this.zipCode = zipCode;
this.ownership = ownership;
this.numBedrooms = numBedrooms;
this.yearBuilt = yearBuilt;
this.propertyType = propertyType;
this.buildingsAmountInsured = buildingsAmountInsured;
this.buildingsCover = buildingsCover;
this.buildingsAccidentalCover = buildingsAccidentalCover;
this.contentsAmountInsured = contentsAmountInsured;
this.contentsCover = contentsCover;
this.contentsAccidentalCover = contentsAccidentalCover;
this.singleItemLimit = singleItemLimit;
this.alarmed = alarmed;
this.securityPatrolled = securityPatrolled;
}

/**
* Gets the propertyID for this Property.
*
* @return propertyID
*/
public Integer getPropertyID()
{
return propertyID;
}

/**
* Sets the propertyID value for this Property.
*
* @param propertyID
*/
public void setPropertyID(Integer propertyID)
{
this.propertyID = propertyID;
}

/**
* Gets the customerID associated with this Property.
*
* @return customerID
*/
public Integer getCustomerID()
{
return customerID;
}

/**
* Sets the customerID value for this Property.
*
* @param customerID
*/
public void setCustomerID(Integer customerID)
{
this.customerID = customerID;
}

/**
* Gets the houseNameNumber value for this PropertyDetails.
*
* @return houseNameNumber
*/
public java.lang.String getHouseNameNumber()
{
return houseNameNumber;
}

/**
* Sets the houseNameNumber value for this PropertyDetails.
*
* @param houseNameNumber
*/
public void setHouseNameNumber(java.lang.String houseNameNumber)
{
this.houseNameNumber = houseNameNumber;
}

/**
* Gets the streetAddress1 value for this PropertyDetails.
*
* @return streetAddress1
*/
public java.lang.String getStreetAddress1()
{
return streetAddress1;
}

/**
* Sets the streetAddress1 value for this PropertyDetails.
*
* @param streetAddress1
*/
public void setStreetAddress1(java.lang.String streetAddress1)
{
this.streetAddress1 = streetAddress1;
}

/**
* Gets the streetAddress2 value for this PropertyDetails.
*
* @return streetAddress2
*/
public java.lang.String getStreetAddress2()
{
return streetAddress2;
}

/**
* Sets the streetAddress2 value for this PropertyDetails.
*
* @param streetAddress2
*/
public void setStreetAddress2(java.lang.String streetAddress2)
{
this.streetAddress2 = streetAddress2;
}

/**
* Gets the streetAddress3 value for this PropertyDetails.
*
* @return streetAddress3
*/
public java.lang.String getStreetAddress3()
{
return streetAddress3;
}

/**
* Sets the streetAddress3 value for this PropertyDetails.
*
* @param streetAddress3
*/
public void setStreetAddress3(java.lang.String streetAddress3)
{
this.streetAddress3 = streetAddress3;
}

/**
* Gets the streetAddress4 value for this PropertyDetails.
*
* @return streetAddress4
*/
public java.lang.String getStreetAddress4()
{
return streetAddress4;
}

/**
* Sets the streetAddress4 value for this PropertyDetails.
*
* @param streetAddress4
*/
public void setStreetAddress4(java.lang.String streetAddress4)
{
this.streetAddress4 = streetAddress4;
}

/**
* Gets the city value for this PropertyDetails.
*
* @return city
*/
public java.lang.String getCity()
{
return city;
}

/**
* Sets the city value for this PropertyDetails.
*
* @param city
*/
public void setCity(java.lang.String city)
{
this.city = city;
}

/**
* Gets the state value for this PropertyDetails.
*
* @return state
*/
public java.lang.String getState()
{
return state;
}

/**
* Sets the state value for this PropertyDetails.
*
* @param state
*/
public void setState(java.lang.String state)
{
this.state = state;
}

/**
* Gets the zipCode value for this PropertyDetails.
*
* @return zipCode
*/
public java.lang.String getZipCode()
{
return zipCode;
}

/**
* Sets the zipCode value for this PropertyDetails.
*
* @param zipCode
*/
public void setZipCode(java.lang.String zipCode)
{
this.zipCode = zipCode;
}

/**
* Gets the ownership value for this PropertyDetails.
*
* @return ownership
*/
public Ownership getOwnership()
{
return ownership;
}

/**
* Sets the ownership value for this PropertyDetails.
*
* @param ownership
*/
public void setOwnership(Ownership ownership)
{
this.ownership = ownership;
}

/**
* Gets the numBedrooms value for this PropertyDetails.
*
* @return numBedrooms
*/
public int getNumBedrooms()
{
return numBedrooms;
}

/**
* Sets the numBedrooms value for this PropertyDetails.
*
* @param numBedrooms
*/
public void setNumBedrooms(int numBedrooms)
{
this.numBedrooms = numBedrooms;
}

/**
* Gets the yearBuilt value for this PropertyDetails.
*
* @return yearBuilt
*/
public java.lang.String getYearBuilt()
{
return yearBuilt;
}

/**
* Sets the yearBuilt value for this PropertyDetails.
*
* @param yearBuilt
*/
public void setYearBuilt(java.lang.String yearBuilt)
{
this.yearBuilt = yearBuilt;
}

/**
* Gets the propertyType value for this PropertyDetails.
*
* @return propertyType
*/
public PropertyType getPropertyType()
{
return propertyType;
}

/**
* Sets the propertyType value for this PropertyDetails.
*
* @param propertyType
*/
public void setPropertyType(PropertyType propertyType)
{
this.propertyType = propertyType;
}

/**
* Gets the buildingsAmountInsured value for this PropertyDetails.
*
* @return buildingsAmountInsured
*/
public java.math.BigDecimal getBuildingsAmountInsured()
{
return buildingsAmountInsured;
}

/**
* Sets the buildingsAmountInsured value for this PropertyDetails.
*
* @param buildingsAmountInsured
*/
public void setBuildingsAmountInsured(java.math.BigDecimal buildingsAmountInsured)
{
this.buildingsAmountInsured = buildingsAmountInsured;
}

/**
* Gets the buildingsCover value for this PropertyDetails.
*
* @return buildingsCover
*/
public boolean isBuildingsCover()
{
return buildingsCover;
}

/**
* Sets the buildingsCover value for this PropertyDetails.
*
* @param buildingsCover
*/
public void setBuildingsCover(boolean buildingsCover)
{
this.buildingsCover = buildingsCover;
}

/**
* Gets the buildingsAccidentalCover value for this PropertyDetails.
*
* @return buildingsAccidentalCover
*/
public boolean isBuildingsAccidentalCover()
{
return buildingsAccidentalCover;
}

/**
* Sets the buildingsAccidentalCover value for this PropertyDetails.
*
* @param buildingsAccidentalCover
*/
public void setBuildingsAccidentalCover(boolean buildingsAccidentalCover)
{
this.buildingsAccidentalCover = buildingsAccidentalCover;
}

/**
* Gets the contentsAmountInsured value for this PropertyDetails.
*
* @return contentsAmountInsured
*/
public java.math.BigDecimal getContentsAmountInsured()
{
return contentsAmountInsured;
}

/**
* Sets the contentsAmountInsured value for this PropertyDetails.
*
* @param contentsAmountInsured
*/
public void setContentsAmountInsured(java.math.BigDecimal contentsAmountInsured) {

this.contentsAmountInsured = contentsAmountInsured;
}

/**
* Gets the contentsCover value for this PropertyDetails.
*
* @return contentsCover
*/
public boolean isContentsCover()
{
return contentsCover;
}

/**
* Sets the contentsCover value for this PropertyDetails.
*
* @param contentsCover
*/
public void setContentsCover(boolean contentsCover)
{
this.contentsCover = contentsCover;
}

/**
* Gets the contentsAccidentalCover value for this PropertyDetails.
*
* @return contentsAccidentalCover
*/
public boolean isContentsAccidentalCover()
{
return contentsAccidentalCover;
}

/**
* Sets the contentsAccidentalCover value for this PropertyDetails.
*
* @param contentsAccidentalCover
*/
public void setContentsAccidentalCover(boolean contentsAccidentalCover)
{
this.contentsAccidentalCover = contentsAccidentalCover;
}

/**
* Gets the singleItemLimit value for this PropertyDetails.
*
* @return singleItemLimit
*/
public java.math.BigDecimal getSingleItemLimit()
{
return singleItemLimit;
}

/**
* Sets the singleItemLimit value for this PropertyDetails.
*
* @param singleItemLimit
*/
public void setSingleItemLimit(java.math.BigDecimal singleItemLimit)
{
this.singleItemLimit = singleItemLimit;
}

/**
* Gets the alarmed value for this PropertyDetails.
*
* @return alarmed
*/
public boolean isAlarmed()
{
return alarmed;
}

/**
* Sets the alarmed value for this PropertyDetails.
*
* @param alarmed
*/
public void setAlarmed(boolean alarmed)
{
this.alarmed = alarmed;
}

/**
* Gets the securityPatrolled value for this PropertyDetails.
*
* @return securityPatrolled
*/
public boolean isSecurityPatrolled()
{
return securityPatrolled;
}

/**
* Sets the securityPatrolled value for this PropertyDetails.
*
* @param securityPatrolled
*/
public void setSecurityPatrolled(boolean securityPatrolled)
{
this.securityPatrolled = securityPatrolled;
}

public boolean equals(Property property)
{
return equals
(
property.getHouseNameNumber(),
property.getStreetAddress1(),
property.getStreetAddress2(),
property.getStreetAddress3(),
property.getStreetAddress4(),
property.getCity(),
property.getState(),
property.getZipCode(),
new Ownership(property.getOwnership().toString()),
property.getNumBedrooms(),
property.getYearBuilt(),
new PropertyType(property.getPropertyType().toString()),
property.getBuildingsAmountInsured(),
property.isBuildingsCover(),
property.isBuildingsAccidentalCover(),
property.getContentsAmountInsured(),
property.isContentsCover(),
property.isContentsAccidentalCover(),
property.getSingleItemLimit(),
property.isAlarmed(),
property.isSecurityPatrolled()
);
}

public boolean equals
(
String houseNameNumber,
String streetAddress1,
String streetAddress2,
String streetAddress3,
String streetAddress4,
String city,
String state,
String zipCode,
Ownership ownership,
int numBedrooms,
String yearBuilt,
PropertyType propertyType,
BigDecimal buildingsAmountInsured,
Boolean buildingsCover,
Boolean buildingsAccidentalCover,
BigDecimal contentsAmountInsured,
Boolean isContentsCover,
Boolean contentsAccidentalCover,
BigDecimal singleItemLimit,
Boolean alarmed,
Boolean securityPatrolled)
{
// TODO null parameter checking
if (this.houseNameNumber != null && houseNameNumber != null && this.houseNameNumber.equals(houseNameNumber) &&
this.streetAddress1 != null && streetAddress1 != null && this.streetAddress1.equals(streetAddress1) &&
this.streetAddress2 != null && streetAddress2 != null && this.streetAddress2.equals(streetAddress2) &&
this.streetAddress3 != null && streetAddress3 != null && this.streetAddress3.equals(streetAddress3) &&
this.streetAddress4 != null && streetAddress4 != null && this.streetAddress4.equals(streetAddress4) &&
this.city != null && city != null && this.city.equals(city) &&
this.state != null && state != null && this.state.equals(state) &&
this.zipCode != null && zipCode != null && this.zipCode.equals(zipCode) &&
this.ownership != null && ownership != null && (this.ownership.equals(ownership)) &&
this.numBedrooms == numBedrooms &&
this.yearBuilt != null && yearBuilt != null && this.yearBuilt.equals(yearBuilt) &&
this.propertyType != null && propertyType != null && this.propertyType.equals(propertyType) &&
this.buildingsAmountInsured != null && buildingsAmountInsured != null && this.buildingsAmountInsured.equals(buildingsAmountInsured) &&
this.buildingsCover == buildingsCover &&
this.buildingsAccidentalCover == buildingsAccidentalCover &&
this.contentsAmountInsured != null && contentsAmountInsured != null && this.contentsAmountInsured.equals(contentsAmountInsured) &&
this.contentsCover == contentsCover &&
this.contentsAccidentalCover == contentsAccidentalCover &&
this.singleItemLimit != null && singleItemLimit != null && this.singleItemLimit.equals(singleItemLimit) &&
this.alarmed == alarmed &&
this.securityPatrolled == securityPatrolled)
{
return true;
}
else
{
return false;
}
}

}

Repeat for Ownership by creating a new class (Ownership.java) in package com.teradata.tza.insurance.process.businessObject.

  • Right Click on src/java and select New -> Class
  • Browse to the Package "com.teradata.tza.insurance.process.businessObject".
  • Set the class Name to Ownership.
  • Click Finish and a template source file will open within the Eclipse editor.

The Ownership class can then be built up by replacing the template code with the following code segment within the Ownership.java file using copy and paste.

/**
* The contents of this file are Teradata Public Content and have been released to the Public Domain.
* Please see the license.txt file in the top level directory for more information.
*
* @author Mike.Coutts@Teradata.com
*/

package com.teradata.tza.insurance.process.businessObject;

public class Ownership
{
private Integer ownershipID = new Integer(0);
private String description = "";

public static final String Rented = "Rented";
public static final String Owned = "Owned";
public static final String Mortgaged = "Mortgaged";

public Ownership()
{
}

public Ownership(String ownershipSchema)
{
super();
description = ownershipSchema;
if (ownershipSchema.equals(Rented))
{
ownershipID = new Integer(0);
}
else if (ownershipSchema.equals(Owned))
{
ownershipID = new Integer(1);
}
else if (ownershipSchema.equals(Mortgaged))
{
ownershipID = new Integer(2);
}
}

public Ownership(Ownership ownership)
{
this.ownershipID = ownership.getOwnershipID();
this.description = ownership.getDescription();
}

public Ownership(Integer ownershipID, String description)
{
super();
this.ownershipID = ownershipID;
this.description = description;
}

public Integer getOwnershipID()
{
return ownershipID;
}

public void setOwnershipID(Integer ownershipID)
{
this.ownershipID = ownershipID;
}

public String getDescription()
{
return description;
}

public void setDescription(String description)
{
this.description = description;
}
} // end Ownership

Repeat for PropertyType by creating a new class (PropertyType.java) in package com.teradata.tza.insurance.process.businessObject.

  • Right Click on src/java and select New -> Class
  • Browse to the Package "com.teradata.tza.insurance.process.businessObject".
  • Set the class Name to PropertyType.
  • Click Finish and a template source file will open within the Eclipse editor.

The PropertyType class can then be built up by replacing the template code with the following code segment within the PropertyType.java file using copy and paste.

/**
* The contents of this file are Teradata Public Content and have been released to the Public Domain.
* Please see the license.txt file in the top level directory for more information.
*
* @author Mike.Coutts@Teradata.com
*/
package com.teradata.tza.insurance.process.businessObject;

public class PropertyType
{
private Integer propertyTypeID = new Integer(0);
private String description = "";

public static final String Apartment = "Apartment";
public static final String Condominium = "Condominium";
public static final String Townhouse = "Townhouse";
public static final String Duplex = "Duplex";
public static final String Detached = "Detached";

public PropertyType()
{
}

public PropertyType(String propertyTypeSchema)
{
super();
description = propertyTypeSchema;
if (propertyTypeSchema.equals(Apartment))
{
propertyTypeID = new Integer(0);
}
else if (propertyTypeSchema.equals(Condominium))
{
propertyTypeID = new Integer(1);
}
else if (propertyTypeSchema.equals(Townhouse))
{
propertyTypeID = new Integer(2);
}
else if (propertyTypeSchema.equals(Duplex))
{
propertyTypeID = new Integer(3);
}
else if (propertyTypeSchema.equals(Detached))
{
propertyTypeID = new Integer(4);
}
}

public PropertyType(PropertyType propertyType)
{
super();
this.propertyTypeID = propertyType.getPropertyTypeID();
this.description = propertyType.getDescription();
}

public PropertyType(Integer propertyTypeID, String description)
{
super();
this.propertyTypeID = propertyTypeID;
this.description = description;
}

public Integer getPropertyTypeID()
{
return propertyTypeID;
}

public void setPropertyTypeID(Integer propertyTypeID)
{
this.propertyTypeID = propertyTypeID;
}

public String getDescription()
{
return description;
}

public void setDescription(String description)
{
this.description = description;
}
} // end PropertyType

Add the Zip Code Risk Factors class

The ZipCodeRiskFactors class represents the Risk Factors associated with a given range of ZipCodes (between a Start and an End value). To add this create a new class (ZipCodeRiskFactors.java) in package com.teradata.tza.insurance.process.businessObject.

  • Right Click on src/java and select New -> Class
  • Browse to the Package "com.teradata.tza.insurance.process.businessObject".
  • Set the class Name to ZipCodeRiskFactors.
  • Click Finish and a template source file will open within the Eclipse editor.

The ZipCodeRiskFactors class can then be built up by replacing the template code with the following code segment within the ZipCodeRiskFactors.java file using copy and paste.

/** 
* The contents of this file are Teradata Public Content and have been released to the Public Domain.
* Please see the license.txt file in the top level directory for more information.
*
* @author Mike.Coutts@Teradata.com
*/
package com.teradata.tza.insurance.process.businessObject;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class ZipCodeRiskFactors
{
/** Logger for this class **/
private static Log log = LogFactory.getLog(ZipCodeRiskFactors.class);

private String zipCode = "10000";
private Double theftRisk = new Double(1.0);
private Double fireRisk = new Double(1.0);
private Double floodRisk = new Double(1.0);
private Double subsidenceRisk = new Double(1.0);
private Double otherRisk = new Double(1.0);

public ZipCodeRiskFactors()
{
// Base Constructor uses the default/neutral 1.0 risk factors
log.debug("ZipCodeRiskFactors");
}

public ZipCodeRiskFactors(String zipCode)
{
this.zipCode = zipCode;
log.debug("ZipCodeRiskFactors(" + zipCode + ")");
}

public String getZipCode()
{
return zipCode;
}

public void setZipCode(String zipCode)
{
this.zipCode = zipCode;
}

public Double getTheftRisk()
{
return theftRisk;
}

public void setTheftRisk(Double theftRisk)
{
this.theftRisk = theftRisk;
}

public Double getFloodRisk()
{
return floodRisk;
}

public void setFloodRisk(Double floodRisk)
{
this.floodRisk = floodRisk;
}

public Double getFireRisk()
{
return fireRisk;
}

public void setFireRisk(Double fireRisk)
{
this.fireRisk = fireRisk;
}

public Double getSubsidenceRisk()
{
return subsidenceRisk;
}

public void setSubsidenceRisk(Double subsidenceRisk)
{
this.subsidenceRisk = subsidenceRisk;
}

public Double getOtherRisk()
{
return otherRisk;
}

public void setOtherRisk(Double otherRisk)
{
this.otherRisk = otherRisk;
}
} // end ZipCodeRiskFactors

Within the Project Explorer view the TZA-InsuranceProcess businesObject package folder will look like this.

Project Explorer with BusinessObject Package


Create the Repository / Data Access Objects.

The first three Business Objects (Property, Ownership and PropertyType) can be seen as inputs to the Simple Quotation Engine Business Process while the values within a given instance of the ZipCodeRiskFactors class is obtained from the underlying Repository or Database based upon the ZipCode provided as part of the Property object.

At this stage a single Repository object is required to allow us to map from the ZipCodeRiskFactors Relational Table in the database to an instance of the ZipCodeRiskFactors Object within the Java application. This process of Object / Relational (O/R) mapping is conducted by a Data Access Object (DAO) either through discrete Code and SQL (as in this case) or through the use of some O/R Mapping Technology (such as iBatis or Hibernate). As before, in line with our Cohesion Principle, we collect all of the Data Oriented or Repository Classes into a single package.

  • Select the TZA-InsuranceProcess project
  • Select File -> New -> Other.. -> Java -> Package.
  • Set the package Name: = "com.teradata.tza.insurance.process.quoteEngine.repository"
  • Select Finish and the wizard will create this package.

New Java Project - Repository

Add the ZipCodeRiskFactorsDao Interface.

In accordance with the Solid Architecture Principles we discussed a couple of week ago we will create an Interface class and a Concrete implementation of the ZipCodeRiskFactors DAO class. This will also prepare the ground for the configurable wiring of these Java classes through the Spring Framework (this becomes increasingly significant both as application size and complexity increases as well as when we want to try out different Implementations say based on a Macro or a Stored Procedure).

  • Right Click on src/java and select New -> Interface
  • Browse to the Package "com.teradata.tza.insurance.process.quoteEngine.repository".
  • Set the class Name to ZipCodeRiskFactorsDao.
  • Click Finish and a template source file will open within the Eclipse editor.

The ZipCodeRiskFactorsDoa Interface can then be built up by replacing the template code with the following code segment within the ZipCodeRiskFactorsDoa.java file using copy and paste.

/** 
* The contents of this file are Teradata Public Content and have been released to the Public Domain.
* Please see the license.txt file in the top level directory for more information.
*
* @author Mike.Coutts@Teradata.com
*/
package com.teradata.tza.insurance.process.quoteEngine.repository;

import com.teradata.commons.access.TaoSession;
import com.teradata.commons.access.exception.DataAccessException;
import com.teradata.tza.insurance.process.businessObject.ZipCodeRiskFactors;

public interface ZipCodeRiskFactorsDao
{
public void setTaoSession(TaoSession taoSession);
public ZipCodeRiskFactors find(String zipCode) throws DataAccessException;
}

Add the JdbcZipCodeRiskFactorsDao Class.

For the Simple Quotation Engine we will be using a pure JDBC implementation of the ZipCodeRiskFactorsDao interface. This means we will be embedding the required SQL directly within the Java code. This provides for the greatest amount of control over how we access the underlying repository but does so at the cost of requiring us to change Java code should we need to change the table or repository structure.

To add the JdbcZipCodeRiskFactorsDao class:

  • Within TZA-InsuranceProcess Right Click on src/java and select New -> Class
  • Browse to the Package "com.teradata.tza.insurance.process.quoteEngine.repository".
  • Set the class Name to JdbcZipCodeRiskFactorsDao.
  • Click Finish and a template source file will open within the Eclipse editor.

The JdbcZipCodeRiskFactorsDoa Class can then be built up by replacing the template code with the following code segment within the JdbcZipCodeRiskFactorsDoa.java file using copy and paste.

/** 
* The contents of this file are Teradata Public Content and have been released to the Public Domain.
* Please see the license.txt file in the top level directory for more information.
*
* @author Mike.Coutts@Teradata.com
*/
package com.teradata.tza.insurance.process.quoteEngine.repository;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.teradata.tza.insurance.process.businessObject.ZipCodeRiskFactors;

import com.teradata.commons.access.TaoSession;
import com.teradata.commons.access.exception.DBException;
import com.teradata.commons.access.exception.DataAccessException;

public class JdbcZipCodeRiskFactorsDao implements ZipCodeRiskFactorsDao
{

/** Logger for this class **/
private static Log log = LogFactory.getLog(JdbcZipCodeRiskFactorsDao.class);

private TaoSession taoSession = null;
public void setTaoSession(TaoSession taoSession)
{
this.taoSession = taoSession;
}

/**
*
* @param zipCode
* @return ZipCodeRiskFactors
* @throws DataAccessException
*/
public ZipCodeRiskFactors find(String zipCode) throws DataAccessException
{
// Note: we are hard coding the SQL within the Data Access Object
String queryString = new String ("Select fireRisk, floodRisk, theftRisk, subsidenceRisk, otherRisk from ZipCodeRiskFactors where ? BETWEEN StartZipRange AND EndZipRange");

// Create ZipCodeRiskFactors object
ZipCodeRiskFactors zipCodeRiskFactors = new ZipCodeRiskFactors();
ResultSet rs = null;
PreparedStatement stmt = null;

try
{
// Create prepared statement
stmt = taoSession.prepareSQLStatement(queryString);

// Set prepared statement parameters
stmt.setInt(1, new Integer(zipCode).intValue());

// Execute prepared statement
rs = taoSession.execute(stmt);

// Check result set
if (rs.next())
{
// Map result set to Customer object
zipCodeRiskFactors.setFireRisk(rs.getDouble("fireRisk"));
zipCodeRiskFactors.setFloodRisk(rs.getDouble("floodRisk"));
zipCodeRiskFactors.setTheftRisk(rs.getDouble("theftRisk"));
zipCodeRiskFactors.setSubsidenceRisk(rs.getDouble("subsidenceRisk"));
zipCodeRiskFactors.setOtherRisk(rs.getDouble("otherRisk"));
}
else
{
// Result set empty - Throw zipCodeRiskFactors not found exception
zipCodeRiskFactors = null;
DataAccessException daEx = new DataAccessException("ZipCodeRiskFactors for " + zipCode + " not found");
throw daEx;
}
}
// Check for unrecoverable database errors
catch (SQLException ex)
{
// Translate SQLException to DBException
log.error(TaoSession.FindError + ":" + ex.getMessage());
DBException dbEx = new DBException(TaoSession.FindError, ex);
throw dbEx;
}
catch (DBException ex)
{
log.error(TaoSession.FindError + ":" + ex.getDbMsg());
throw ex;
}
finally
{
// Close result set and statement to prevent leaks
try
{
if (rs != null)
rs.close();

if (stmt != null)
stmt.close();
}
catch (SQLException ex)
{
log.error("Error closing result set or statement" + ex);
DBException dbEx = new DBException ("Error closing result set or statement", ex);
throw dbEx;
}
}

return zipCodeRiskFactors;
}

} // end JdbcZipCodeRiskFactorsDao

Create the Business Process

Finally we can create the Quotation Engine (the Basic Business Process for TZA-Insurance). This is an extremely simple algorithm that uses the Property Value as a basic starting point and then adds and subtracts from it dependent upon the attributes of the property (number of bedrooms, age of the property, does it have an alarm etc). Finally it multiplies the resultant quotation by the values in the ZipCodeRiskFactors Business Object associated with the ZipCode provided as part of the physical address of the property. Where a risk is greater the 1.0 the quotation will increase, where it is less then 1.0 the quotation will reduce.

  • Select the TZA-InsuranceProcess project
  • Select File -> New -> Other.. -> Java -> Package.
  • Set the package Name: = "com.teradata.tza.insurance.process.quoteEngine.businessProcess"
  • Select Finish and the wizard will create this package.

New Java Package - Business Process

Add the QuotationEngine Interface.

Again we provide a separate Interface and Implementation. To create the QuotationEngine Interface start with the TZA-InsuranceProcess:

  • Right Click on src/java and select New -> Interface
  • Browse to the Package "com.teradata.tza.insurance.process.quoteEngine.businessProcess".
  • Set the interface Name to QuotationEngine.
  • Click Finish and a template source file will open within the Eclipse editor.

The QuotationEngine Interface can then be built up by replacing the template code with the following code segment within the QuotationEngine.java file using copy and paste.

/** 
* The contents of this file are Teradata Public Content and have been released to the Public Domain.
* Please see the license.txt file in the top level directory for more information.
*
* @author Mike.Coutts@Teradata.com
*/
package com.teradata.tza.insurance.process.quoteEngine.businessProcess;

import java.io.Serializable;
import java.math.BigDecimal;

import com.teradata.commons.access.TaoSessionManager;
import com.teradata.tza.insurance.process.exception.ApplicationException;
import com.teradata.tza.insurance.process.exception.SystemException;
import com.teradata.tza.insurance.process.businessObject.Property;

public interface QuotationEngine extends Serializable
{
public void setTaoSessionManager(TaoSessionManager taoSessionManager);
public BigDecimal getQuotation(Property propertyDetails) throws ApplicationException, SystemException;
}

Add the ZipCodeQuotationEngine Class.

This first simple implementation of the QuotationEngine is based solely upon the ZipCode of the Property being issured so we call it the ZipCodeQuotationEngine. To create this start with the TZA-InsuranceProcess:

  • Right Click on src/java and select New -> Class
  • Browse to the Package "com.teradata.tza.insurance.process.quoteEngine.businessProcess".
  • Set the interface Name to ZipCodeQuotationEngine.
  • Click Finish and a template source file will open within the Eclipse editor.

The ZipCodeQuotationEngine class can then be built up by replacing the template code with the following code segment within the ZipCodeQuotationEngine.java file using copy and paste.

/** 
* The contents of this file are Teradata Public Content and have been released to the Public Domain.
* Please see the license.txt file in the top level directory for more information.
*
* @author Mike.Coutts@Teradata.com
*/
package com.teradata.tza.insurance.process.quoteEngine.businessProcess;

import java.math.BigDecimal;
import java.lang.NumberFormatException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.teradata.tza.insurance.process.exception.ApplicationException;
import com.teradata.tza.insurance.process.exception.SystemException;
import com.teradata.tza.insurance.process.businessObject.Ownership;
import com.teradata.tza.insurance.process.businessObject.Property;
import com.teradata.tza.insurance.process.businessObject.PropertyType;
import com.teradata.tza.insurance.process.businessObject.ZipCodeRiskFactors;
import com.teradata.tza.insurance.process.quoteEngine.repository.ZipCodeRiskFactorsDao;
import com.teradata.commons.access.TaoSessionManager;
import com.teradata.commons.access.TaoSession;
import com.teradata.commons.access.exception.*;

public class ZipCodeQuotationEngine implements QuotationEngine
{

/** the logger */
private static Log logger = LogFactory.getLog(ZipCodeQuotationEngine.class);
private static final long serialVersionUID = 1L;

// Number of decimals to retain. Also referred to as "scale".
private static int DECIMALS = 2;
// Hundred and Thousand values for mathematics processing
private static BigDecimal HUNDRED = new BigDecimal("100");
private static BigDecimal THOUSAND = new BigDecimal("1000");

private TaoSession taoSession = null;
private TaoSessionManager taoSessionManager = null;
public void setTaoSessionManager(TaoSessionManager taoSessionManager)
{
this.taoSessionManager = taoSessionManager;
}

private ZipCodeRiskFactorsDao zipCodeRiskFactorsDao;
public void setZipCodeRiskFactorsDao(ZipCodeRiskFactorsDao zipCodeRiskFactorsDao)
{
this.zipCodeRiskFactorsDao = zipCodeRiskFactorsDao;
}

/**
*
*/
public BigDecimal getQuotation(Property propertyDetails) throws ApplicationException, SystemException
{
logger.info("getZipCodeQuotation for " +
propertyDetails.getHouseNameNumber() + " " + propertyDetails.getStreetAddress1() + " " + propertyDetails.getZipCode());

BigDecimal buildingsQuote = new BigDecimal(0.00);
BigDecimal contentsQuote = new BigDecimal(0.00);

// Get the different Risk Factors based upon the Property Details
try
{
// Create Session
taoSession = taoSessionManager.getSession();
logger.debug("Session created:" + taoSession);

// Initialize DAO objects - set current session
zipCodeRiskFactorsDao.setTaoSession(taoSession);

// Begin session / transaction
taoSession.beginSession();
taoSession.beginTransaction();

// Get zipCodeRiskFactors
ZipCodeRiskFactors zipCodeRiskFactors = zipCodeRiskFactorsDao.find(propertyDetails.getZipCode());

// Commit transaction
taoSession.commitTransaction();

// If Buildings Cover required
if (propertyDetails.isBuildingsCover())
{
// initial quote is based on Amount insured / 1000
buildingsQuote = propertyDetails.getBuildingsAmountInsured();

// check amount is greater than 1000
if (buildingsQuote.compareTo(THOUSAND) == 1)
buildingsQuote = buildingsQuote.divide(THOUSAND, BigDecimal.ROUND_HALF_UP);
else
buildingsQuote = new BigDecimal(10.00);

// Convert Year built into a Number
int yearBuilt = 2000;
try
{
Integer x = new Integer(propertyDetails.getYearBuilt());
yearBuilt = x.intValue();
}
catch (NumberFormatException ex)
{
}

// The Property Age adds an appropriate % (older costs more to replace)
if (yearBuilt < 1837)
{
// Pre_1837: +25%
buildingsQuote = buildingsQuote.add(getPercentage(buildingsQuote, new BigDecimal("25")));
}
else if (yearBuilt < 1919)
{
// _1837_1919: +20%
buildingsQuote = buildingsQuote.add(getPercentage(buildingsQuote, new BigDecimal("20")));
}
else if (yearBuilt < 1945)
{
// _1920_1945: +15%
buildingsQuote = buildingsQuote.add(getPercentage(buildingsQuote, new BigDecimal("15")));
}
else if (yearBuilt < 1979)
{
// _1946_1979: +10%
buildingsQuote = buildingsQuote.add(getPercentage(buildingsQuote, new BigDecimal("10")));
}
else if (yearBuilt < 1989)
{
// _1980_1989: +5%
buildingsQuote = buildingsQuote.add(getPercentage(buildingsQuote, new BigDecimal("5")));
}
else
{
// _1990_Onwards: +0%
}

// The Property type adds/subtracts a small %
if (propertyDetails.getPropertyType().equals(PropertyType.Detached))
{
// Detached-House(0) - 10%
buildingsQuote = buildingsQuote.subtract(getPercentage(buildingsQuote, new BigDecimal("10")));
}
else if (propertyDetails.getPropertyType().equals(PropertyType.Duplex))
{
// Semi-Detached House(1) -5%
buildingsQuote = buildingsQuote.subtract(getPercentage(buildingsQuote, new BigDecimal("5")));
}
else if (propertyDetails.getPropertyType().equals(PropertyType.Townhouse))
{
// Townhouse(2) + 0%
// buildingsQuote = buildingsQuote.add(getPercentage(buildingsQuote, new BigDecimal("10")));
}
else if (propertyDetails.getPropertyType().equals(PropertyType.Condominium))
{
// Condominium(3) + 5%
buildingsQuote = buildingsQuote.add(getPercentage(buildingsQuote, new BigDecimal("5")));
}
else if (propertyDetails.getPropertyType().equals(PropertyType.Apartment))
{
// Appartment + 10%
buildingsQuote = buildingsQuote.add(getPercentage(buildingsQuote, new BigDecimal("10")));
}

// number of bedrooms adds 5% per
if (propertyDetails.getNumBedrooms() > 0)
buildingsQuote = buildingsQuote.add(getPercentage(buildingsQuote, new BigDecimal("5").multiply(new BigDecimal(propertyDetails.getNumBedrooms()))));

// ownership -5% owned, flat mortgaged, +5% rented
if (propertyDetails.getOwnership().equals(Ownership.Owned))
{
// Owned(1) -5%
buildingsQuote = buildingsQuote.subtract(getPercentage(buildingsQuote, new BigDecimal("5")));
}
else if (propertyDetails.getOwnership().equals(Ownership.Rented))
{
// Rented(2) + 5%
buildingsQuote = buildingsQuote.add(getPercentage(buildingsQuote, new BigDecimal("5")));
}

// if Alarm fitted subtract 5%
if (propertyDetails.isAlarmed())
buildingsQuote = buildingsQuote.subtract(getPercentage(buildingsQuote, new BigDecimal("5")));

// if security patrolled /neighborhood watch -5%
if(propertyDetails.isSecurityPatrolled())
buildingsQuote = buildingsQuote.subtract(getPercentage(buildingsQuote, new BigDecimal("5")));

// if accidental damage to building covered +5%
if(propertyDetails.isBuildingsAccidentalCover())
buildingsQuote = buildingsQuote.add(getPercentage(buildingsQuote, new BigDecimal("5")));

// modify the quote based upon ZipCode use the zipCodeRiskFactor object for this
logger.info("BuildingsQuote = " + buildingsQuote);
buildingsQuote = buildingsQuote.multiply(new BigDecimal(zipCodeRiskFactors.getFireRisk()));
buildingsQuote = buildingsQuote.multiply(new BigDecimal(zipCodeRiskFactors.getFloodRisk()));
buildingsQuote = buildingsQuote.multiply(new BigDecimal(zipCodeRiskFactors.getTheftRisk()));
buildingsQuote = buildingsQuote.multiply(new BigDecimal(zipCodeRiskFactors.getSubsidenceRisk()));
buildingsQuote = buildingsQuote.multiply(new BigDecimal(zipCodeRiskFactors.getOtherRisk()));
}

// if contents are covered work out the contents quote
if (propertyDetails.isContentsCover())
{
// initial quote is based on Amount insured / 1000
contentsQuote = propertyDetails.getContentsAmountInsured();
if (contentsQuote.compareTo(THOUSAND) == 1)
contentsQuote = contentsQuote.divide(THOUSAND, BigDecimal.ROUND_HALF_UP);
else
contentsQuote = new BigDecimal(1.00);

// Single Item Limit banded to add percentage
if (propertyDetails.getSingleItemLimit().compareTo(new BigDecimal(1500)) == -1)
{
}
else if (propertyDetails.getSingleItemLimit().compareTo(new BigDecimal(2000)) == -1)
contentsQuote = contentsQuote.add(getPercentage(contentsQuote, new BigDecimal("5")));
else if (propertyDetails.getSingleItemLimit().compareTo(new BigDecimal(2500)) == -1)
contentsQuote = contentsQuote.add(getPercentage(contentsQuote, new BigDecimal("10")));
else if (propertyDetails.getSingleItemLimit().compareTo(new BigDecimal(3000)) == -1)
contentsQuote = contentsQuote.add(getPercentage(contentsQuote, new BigDecimal("15")));
else if (propertyDetails.getSingleItemLimit().compareTo(new BigDecimal(3500)) == -1)
contentsQuote = contentsQuote.add(getPercentage(contentsQuote, new BigDecimal("20")));
else
contentsQuote = contentsQuote.add(getPercentage(contentsQuote, new BigDecimal("25")));

// ownership -5% owned, flat mortgaged, +5% rented
if (propertyDetails.getOwnership().equals(Ownership.Owned))
{
// Owned(1) -5%
contentsQuote = contentsQuote.subtract(getPercentage(contentsQuote, new BigDecimal("5")));
}
else if (propertyDetails.getOwnership().equals(Ownership.Rented))
{
// Rented(2) + 5%
contentsQuote = contentsQuote.add(getPercentage(contentsQuote, new BigDecimal("5")));
}

// if Alarm fitted -5%
if (propertyDetails.isAlarmed())
contentsQuote = contentsQuote.subtract(getPercentage(contentsQuote, new BigDecimal("5")));

// if security patrolled /neighborhood watch -5%
if(propertyDetails.isSecurityPatrolled())
contentsQuote = contentsQuote.subtract(getPercentage(contentsQuote, new BigDecimal("5")));

// if accidental damage to building covered +5%
if(propertyDetails.isContentsAccidentalCover())
contentsQuote = contentsQuote.add(getPercentage(contentsQuote, new BigDecimal("5")));

// modify the quote based upon ZipCode use the zipCodeRiskFactor object for this
logger.info("ContentsQuote = " + contentsQuote);
contentsQuote = contentsQuote.multiply(new BigDecimal(zipCodeRiskFactors.getFireRisk()));
contentsQuote = contentsQuote.multiply(new BigDecimal(zipCodeRiskFactors.getFloodRisk()));
contentsQuote = contentsQuote.multiply(new BigDecimal(zipCodeRiskFactors.getTheftRisk()));
contentsQuote = contentsQuote.multiply(new BigDecimal(zipCodeRiskFactors.getSubsidenceRisk()));
contentsQuote = contentsQuote.multiply(new BigDecimal(zipCodeRiskFactors.getOtherRisk()));
}
}
// Catch recoverable application error - zipCodeRiskFactors not found
catch (DataAccessException ex)
{
// Rollback Transaction
taoSession.rollbackTransaction();

// Throw Application Exception
ApplicationException appEx = new ApplicationException("getQuotation exception", ex);
throw appEx;
}
// Catch unrecoverable database error
catch (DBException ex)
{
// Rollback Transaction
taoSession.rollbackTransaction();

// Throw System Exception
SystemException sysEx = new SystemException("getQuotation exception", ex);
throw sysEx;
}
// Always end session
finally
{
taoSession.endSession();
}

return buildingsQuote.add(contentsQuote);

}

private BigDecimal getPercentage(BigDecimal source, BigDecimal percentage)
{
// Ensure we have sufficient scale for the calculation
if (percentage.scale() < 4)
percentage = percentage.setScale(4);

// Calculate the percentage - multiply by 100 divide by percentage.
BigDecimal result = source.multiply(percentage);
result = result.divide(HUNDRED, BigDecimal.ROUND_HALF_UP);
return rounded(result);
}

private BigDecimal rounded(BigDecimal aNumber)
{
return aNumber.setScale(DECIMALS, BigDecimal.ROUND_HALF_UP);
}
} // end ZipCodeQuotationEngine

Wiring up POJO’s with the Spring Framework

The Spring Framework [http://www.springsource.org/] uses XML based configuration files to define which concrete Implementation of a given Interface is to be used. It can also be used to include supporting libraries that your code may wish to use.

Within a Business Process library (Jar) we will use the Spring Framework to wire up the various elements of the process from the Business Service through to the Repository. To use the Spring Framework we add a new package to the src/resources directory called com.teradata.tza.insurance.process.quoteEngine.

  • Right Click on src/resources and select New -> Package
  • Set the Package Name = "com.teradata.tza.insurance.process.quoteEngine".
  • Select Finish and the wizard will create this package.

New Java Resource Package - Quote Engine

Add the sqlQuoteEngineAppContext.xml

This file allows us to "wire" Plain Old Java Objects (POJO's) together and is used to configure how this part of the application will operate. As we will be building the different elements of the Insurance Quotation business process within different projects within the Friday Night Project we need build this XML file additively.

To add sqlQuoteEngineAppContext.xml start with the TZA-InsuranceProcess:

  • Right click on the com.teradata.tza.insurance.process.quoteEngine package.
  • Select New -> Other.. -> XML -> XML and set the file name as sqlQuoteEngineAppContext.xml.
  • Select Finish and a template XML file will open within the Eclipse editor.

The sqlQuoteEngineAppContext.xml file can then be built up by replacing the template code with the following code segments within the sqlQuoteEngineAppContext.xml file using copy and paste.

NOTE: There is a bug in the way the xsi:schemaLocation is displayed by this source viewer (it converts it to an HREF URL) the line should be as follows:

xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

<!-- TZA-InsuranceProcess SQL Quotation Engine -->
<bean id="sqlQuotationEngine"
class="com.teradata.tza.insurance.process.quoteEngine.businessProcess.ZipCodeQuotationEngine"
scope="prototype">
<property name="taoSessionManager" ref="jdbcTaoSessionManager"/>
<property name="zipCodeRiskFactorsDao" ref="zipCodeRiskFactorsDao"/>
</bean>

<bean id="zipCodeRiskFactorsDao"
class="com.teradata.tza.insurance.process.quoteEngine.repository.JdbcZipCodeRiskFactorsDao"
scope="prototype">
</bean>

</beans>


Rebuild the TZA-InsuranceProcess.jar

Having added all of the components necessary for the Simple Quotation Engine we can rebuild the TZA-InsuranceProcess Jar file.

  • Within the Ant View: Open up the TZA-InsuranceProcess - Local Build file.
  • Double Click the jar default task to create the TZA-InsuranceProcess.jar file.

Refresh Eclipse

Because the Ant build works at the Hard Disk Level you need to Refresh Eclipse so it can pick up changes such as the creation of the /dist directory and the TZA-InsuranceProcess.jar.

  • Select the TZA-InsuranceProcess project and use the F5 function key to refresh the environment.
  • Open up the /dist directory and the TZA-InsuranceProcess.jar file will be visible.

Project Explorer - TZA-InsuranceProcess Final


So this illustrates the code and resources necessary to build the simplest Quotation Engine possible, which takes a number of Business Objects as Input. From these a single critical element, the Zip Code, is used to index into the Zip Code Risk Factors control table, via JDBC, in order to provide for Location based Risk Factors as the final input to the Quotation Engine.

Next week on the Friday Night Project we will create our first simple Console Veneer that will demonstrate the use of this business process.

2 REPLIES

Re: The Friday Night Project #6 – Simple Quotation Engine

Hello, Mike!
In "The Friday Night Project #5 - TZA-Database" you missed dbc settings for the TZA_UserGrants in the jdbc.properties ))
Teradata Employee

Re: The Friday Night Project #6 – Simple Quotation Engine

Thanks, I had not spotted that so I added the dbc settings from the jdbc.properties file in my dev environment.