Embed
Email

Hibernate

Document Sample
Hibernate
Shared by: HC111124214916
Categories
Tags
Stats
views:
6
posted:
11/24/2011
language:
English
pages:
65
Hibernate

Hibernate

• Hibernate is a powerful, high performance

object/relational persistence and query service.

Hibernate lets you develop persistent classes following

object-oriented idiom - including association, inheritance,

polymorphism, composition, and collections. Hibernate

allows you to express queries in its own portable SQL

extension (HQL), as well as in native SQL, or with an

object-oriented Criteria and Example API.

• Unlike many other persistence solutions, Hibernate does

not hide the power of SQL from you and guarantees that

your investment in relational technology and knowledge

is as valid as always. The LGPL open source license

allows the use of Hibernate and NHibernate in open

source and commercial projects.

Java Persistence with Hibernate



• The Java Persistence API is the standard object/relational mapping

and persistence management interface of the Java EE 5.0 platform.

As part of the EJB 3.0 specification effort, it is supported by all major

vendors of the Java industry.

• Hibernate implements the Java Persistence object/relational

mapping and persistence management interfaces with the Hibernate

Annotations and Hibernate EntityManager modules, on top of the

mature and powerful Hibernate Core.

• The Hibernate modules can be stacked and combined as desired.

You can use the Hibernate Java Persistence provider in any

environment, Java SE 5.0 or Java EE 5.0. The Hibernate Java

Persistence provider is fully certified and passes the Sun TCK.

Hibernate Annotations

• Project Lead: Emmanuel BernardLatest release: 3.4.0 GA

(Changelog) (Road Map)Release date: 20.08.2008Requirements:

Hibernate Core 3.3.x, JDK 5.0Hibernate, like all other

object/relational mapping tools, requires metadata that governs the

transformation of data from one representation to the other (and vice

versa). As an option, you can now use JDK 5.0 annotations for

object/relational mapping with Hibernate 3.2. You can use

annotations in addition to or as a replacement of XML mapping

metadata.

• The Hibernate Annotations package includes:

• Standardized Java Persistence and EJB 3.0 (JSR 220)

object/relational mapping annotations

• Hibernate-specific extension annotations for performance

optimization and special mappings

• You can use Hibernate extension annotations on top of standardized

Java Persistence annotations to utilize all native Hibernate features.

More jar file downloads

• You will need persistence and ejb jar files: ejb,

persistence, jndi, geronimo-ejb, ejb3-persistence

and javaee.

• Hibernate tutorials:

• http://www.hibernate.org/hib_docs/reference/en/

html/tutorial.html

• http://www.roseindia.net/hibernate/index.shtml

• http://www.hibernate.org/hib_docs/reference/en/

html/tutorial-webapp.html

• http://www.inf.ed.ac.uk/teaching/courses/ec/han

douts/quickstart.pdf

Hibernate tutorials

• I hope to put two or three tutorials here. Right

now there is just one, an application program

running against a mysql db, with just one table,

using hibernate.

• Hibernate standardizes the db interface. A config

file specifies the actual db service and the

dialect to use, and other config files, called hbm,

map the individual tables. Instead of provider-

specific connection and query details, the

program uses the hibernate “interface” to

interact with the database.

First hibernate tutorial

• Using hibernate with a mysql database and a

few simple java classes.

• Link for tutorial:

http://www.hibernate.org/hib_docs/reference/en/

html/tutorial-firstapp.html

• This tutorial has many omissions, most notably

library jar files needed, also a few errors or typos

about where files go. I also had to modify some

classes (HibernateUtil) somewhat to get it to

work.

ant

• You’ll use ant and a build file appears in the next

slide. If you change directories or file names

you’ll have to make modifications in the ant

script.

• Recall, ant must be in the system path and all

your java stuff must be in the path/classpath for

the ant build to work.

• Note, the build requires directories called src,

bin and lib. Contents are detailed later.

build.xml





























































Notes about lib directory

• You’ll need the following jars:

– hibernate

– cp30

– antlr

– jta

– dom4j

– commons logging and collections

– Just 2 files from slf4j(simple and api)…note screen

shot!!!

– You won’t need hsqldb – that’s another db service

connector, but you will need the mysql-java db

connector

My lib directory

Directory structure

• Your_App_dir

– bin

– src

• log4j.properties

• hibernate.cfg.xml

• Event.hbm.xml

• hibernate.properties --- not included in this example

• events(dir)

– Event.java

• util(dir)

– EventManager.java

– HibernateUtil.java

– Lib (see previous slide)

HibernateUtil.java

package util;

//you can find this class in eclipse, netbeans or online, with few variations

import org.hibernate.*;

import org.hibernate.cfg.*;

public class HibernateUtil {

private static final SessionFactory sessionFactory;

static {

try {

System.out.println("in try for build session factory");

// Create the SessionFactory from hibernate.cfg.xml

sessionFactory = new Configuration().configure().buildSessionFactory();

System.out.println("back from build session factory");

} catch (Throwable ex) {

// Make sure you log the exception, as it might be swallowed

System.err.println("Initial SessionFactory creation failed." + ex);

System.out.println("Initial SessionFactory creation failed." + ex);

throw new ExceptionInInitializerError(ex);

} }

public static SessionFactory getSessionFactory() {

return sessionFactory; }}

EventManager.java entirety also in slide notes

package events;

import org.hibernate.*;

import org.hibernate.cfg.*;

import java.util.Date;

import java.util.*;

import util.HibernateUtil;

public class EventManager {



public static void main(String[] args) {//main

EventManager mgr = new EventManager();

System.out.println("Event Manager before if") ; /////I stuck in all these println

if (args[0].equals("store")) {//if

System.out.println("create and store");

mgr.createAndStoreEvent("My Event", new Date());

}//if

else if (args[0].equals("list")) {

System.out.println("list events");

List events = mgr.listEvents();

for (int i = 0; i





























hibernate.cfg.xml contains connection info,

db name, user name & pw and other

information











com.mysql.jdbc.Driver

jdbc:mysql://localhost/mydb

root





10



org.hibernate.dialect.MySQLDialect



true

update







Log4j.properties

log4j.appender.stdout=org.apache.log4j.ConsoleAppender

log4j.appender.stdout.Target=System.out

log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p

%c{1}:%L - %m%n

log4j.rootLogger=info, stdout

log4j.logger.org.hibernate.test=info

log4j.logger.org.hibernate.tool.hbm2ddl=debug

remark

• You’ll need to create a mysql database

and table for this example and you need to

start the database server before running

the example.

• Run the example in the root directory on

the commandline either with

ant run –Daction=store

• Or

ant run –Daction=list

black screen output for store (when it works)

C:\hibernateexample>ant run -Daction=store

Buildfile: build.xml

clean:

[delete] Deleting directory C:\hibernateexample\bin

[mkdir] Created dir: C:\hibernateexample\bin

copy-resources:

[copy] Copying 6 files to C:\hibernateexample\bin

[copy] Copied 2 empty directories to 1 empty directory under C:\hibernateex

ample\bin

compile:

[javac] Compiling 3 source files to C:\hibernateexample\bin

run:

[java] Event Manager before if

[java] create and store

[java] Event Manager... create and store method

[java] in try for build session factory

>>

[java] 719 [main] INFO org.hibernate.tool.hbm2ddl.SchemaUpdate - schema upd

ate complete

[java] back from build session factory

[java] .. before begin transaction

[java] .. transaction started

[java] Hibernate: insert into EVENTS (EVENT_DATE, title) values (?, ?)

[java] session save completed

[java] after commit in create and save

[java] 907 [main] INFO org.hibernate.impl.SessionFactoryImpl - closing

[java] 907 [main] INFO org.hibernate.connection.DriverManagerConnectionProv

ider - cleaning up connection pool: jdbc:mysql://localhost/mydb

[java] Event Manager: completed if



BUILD SUCCESSFUL

Total time: 2 seconds

C:\hibernateexample>

Run –list when it works…entirety in notes

C:\hibernateexample>ant run -Daction=list

Buildfile: build.xml

clean:



copy-resources:



compile:

[javac] Compiling 3 source files to C:\hibernateexample\bin

run:

>>>

[java] 531 [main] INFO org.hibernate.impl.SessionFactoryImpl - building ses

sion factory

[java] 719 [main] INFO org.hibernate.impl.SessionFactoryObjectFactory - Not

binding factory to JNDI, no JNDI name configured

[java] 719 [main] INFO org.hibernate.tool.hbm2ddl.SchemaUpdate - Running hb

m2ddl schema update

[java] 719 [main] INFO org.hibernate.tool.hbm2ddl.SchemaUpdate - fetching d

atabase metadata

[java] 719 [main] INFO org.hibernate.tool.hbm2ddl.SchemaUpdate - updating s

chema

[java] 734 [main] INFO org.hibernate.tool.hbm2ddl.TableMetadata - table fou

nd: mydb.events

[java] 734 [main] INFO org.hibernate.tool.hbm2ddl.TableMetadata - columns:

- schema update complete

[java] back from build session factory

[java] Hibernate: select event0_.EVENT_ID as EVENT1_0_, event0_.EVENT_DATE

as EVENT2_0_, event0_.title as title0_ from EVENTS event0_

[java] Event: My Event Time: 2009-03-03 00:00:00.0

[java] 1062 [main] INFO org.hibernate.impl.SessionFactoryImpl - closing

[java] Event Manager: completed if

[java] 1062 [main] INFO org.hibernate.connection.DriverManagerConnectionPro

vider - cleaning up connection pool: jdbc:mysql://localhost/mydb



BUILD SUCCESSFUL

Total time: 2 seconds

C:\hibernateexample>

Your project

notes

• First, of course, get the original tutorial working.

• Modify the EventManager so it opens a JFrame with two

button, list and store, a textfield and a textarea.

• You are welcome to make a different table but you don’t

have to.

• (E.C. You may want another button to delete * from

db/table)

• List button will display stored events in a textarea.

• Store button will get data for the event from a textfield.

• E.C. The tutorial code uses a timestamp, but maybe

something else like a string with MM/DD/YY format

would be nicer.

So what’s the point of hibernate?

• A uniform connection (that session thingy)

and sql dialect in your object. This doesn’t

change as you port your application.

• The hibernate.cfg.xml (NOT your java

code) gets modified if you port your app,

or change database servers.

The hibernate webapp

WEB-INF\web.xml









Event Manager

events.EventManagerServlet







Event Manager

/eventmanager





Where do files go? Shown in

another slide but note…

• Hibernate.cfg goes in classes dir

• Event.hbm.xml goes into Events dir (I

think)

The 1-table hibernate web app

• http://www.hibernate.org/hib_docs/reference/e

n/html/tutorial-webapp.html

• This tutorial came from hibernate.org. I think it is

basically correct, although I made changes to

the servlet trying to fix unrelated problems. I also

used my own HibernateUtil class (shown in

previous tutorial).

• Not very many details about the directory

structure were given in the tutorial, but I give

them here.

Servlet running in tomcat

Servlet entirety in slide notes

package events;

import java.io.*;

import java.net.*;

import java.text.SimpleDateFormat;

import java.util.Date;

import java.util.Iterator;

import java.util.List;

import javax.servlet.*;

import javax.servlet.http.*;

import util.HibernateUtil;

import org.hibernate.*;

public class EventManagerServlet extends HttpServlet {

SessionFactory sessionFactory;

Session session;

Servlet continued

protected void processRequest(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

response.setContentType("text/html;charset=UTF-8");

SimpleDateFormat dateFormatter = new SimpleDateFormat("dd.MM.yyyy");

PrintWriter out = response.getWriter();

out.println("Event Manager");

try {

// Begin unit of work

// HibernateUtil.getSessionFactory().getCurrentSession().beginTransaction();

sessionFactory = HibernateUtil.getSessionFactory();

session =sessionFactory.openSession();

session.beginTransaction();

// Handle actions

if ("store".equals(request.getParameter("action"))) {

String eventTitle = request.getParameter("eventTitle");

String eventDate = request.getParameter("eventDate");



if ("".equals(eventTitle) || "".equals(eventDate)) {

out.println("Please enter event title and date.");

} else {

System.out.println("before call to create and store");

createAndStoreEvent(eventTitle, dateFormatter.parse(eventDate));

out.println("Added event."); } }



printEventForm(out);

listEvents(out, dateFormatter);



// End unit of work

//HibernateUtil.getSessionFactory().getCurrentSession().getTransaction().commit();

session.getTransaction().commit();

System.out.println("commit after save");

} catch (Exception ex) {

HibernateUtil.getSessionFactory().getCurrentSession().getTransaction().rollback();

throw new ServletException(ex);

}

}

Servlet continued

private void printEventForm(PrintWriter out) {

out.println("Add new event:");

out.println("");

out.println("Title: ");

out.println("Date (e.g. 24.12.2009): ");

out.println("");

out.println("");

}



private void listEvents(PrintWriter out, SimpleDateFormat dateFormatter) {



List result = HibernateUtil.getSessionFactory().getCurrentSession().createCriteria(Event.class).list();



if (result.size() > 0) {

out.println("Events in database:");

out.println("");

out.println("");

out.println("Event title");

out.println("Event date");

out.println("");

for (Iterator it = result.iterator(); it.hasNext();) {

Event event = (Event) it.next();

out.println("");

out.println("" + event.getTitle() + "");

out.println("" + dateFormatter.format(event.getDate()) + "");

out.println("");

}

out.println("");

}

}

Servlet continued

protected void createAndStoreEvent(String title, Date theDate) {

Event theEvent = new Event();

theEvent.setTitle(title);

theEvent.setDate(theDate);



HibernateUtil.getSessionFactory().getCurrentSession().save(theEvent);

}



protected void doGet(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

processRequest(request, response);

}



protected void doPost(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

processRequest(request, response);

}

}

One line added to cfg











com.mysql.jdbc.Driver

jdbc:mysql://localhost/mydb

root





10



org.hibernate.dialect.MySQLDialect



true

update

thread







This build puts webapp war file one directory up

(like in C:)













































































Package things in WEB-INF as

shown here

• WEB-INF

– classes (dir)

• events(dir)

– Event.class (no changes to this file)

– EventManagerServlet.class

– Event.hbm.xml (no changes to this file)

• util(dir)

– HibernateUtil.class (this file same as in previous project)

• Hibernate.cfg.xml (shown above – one line added)

• If it can’t find tableclass.hbm.xml then put them here

– lib(dir) (no changes to this)

– log4j.properties(no changes to this)

– web.xml (shown above)

Jar

• I used jar instead of ant build:

jar –cvf appname.war WEB-INF

Creates a jar called appname.war from

contents of WEB-INF



You’ll need to move files and directories as

per earlier slide before creating a war file.

What’s next?

• I will put a 2nd hibernate project here to be

assigned after the hibernate desktop app. I

haven’t finished working on it, but it will

likely involve CRUD against a database

using one or more servlets, like your

servlet database project, except use a

hibernate interface.

Two examples: multiple tables & crud





• documentation

http://www.hibernate.org/hib_docs/referen

ce/en/html/

Adding to tables & listing

• I modified previous example, adding a

people table and displaying contents of

two tables.

• I did not do a select, I just printed the

event title in the same position. But since

the numbers are allocated sequentially, I

could have used select title from Event

where id=number

My tables

• My People table and my Event table both

have ids as primary key, autoincremented.

• In the hbm, these are identified as

Dir structure

• WEB-INF

– log4j.properties

– web.xml

– lib (contents shown later)

– classes

• hibernate.cfg.xml

• util

– Same HibernateUtil.java as previous

• events

– Same Event.java as previous

– People.java

– EventManagerServlet.java

– People.hbm.xml

– Event.hbm.xml (unchanged from prev example)

some of these may be unnecessary

but I whittled it down some

Entire Servlet in notes

package events;

import java.io.*;

import java.net.*;

import java.text.SimpleDateFormat;

import java.util.Date;

import java.util.Iterator;

import java.util.List;

import javax.servlet.*;

import javax.servlet.http.*;

import util.HibernateUtil;

import org.hibernate.*;

public class EventManagerServlet extends HttpServlet {

SessionFactory sessionFactory;

List result1,result2;

Session session;

protected void processRequest(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {



response.setContentType("text/html;charset=UTF-8");

SimpleDateFormat dateFormatter = new SimpleDateFormat("dd.MM.yyyy");

PrintWriter out = response.getWriter();

out.println("Event Manager");

try {

// Begin unit of work

// HibernateUtil.getSessionFactory().getCurrentSession().beginTransaction();

sessionFactory = HibernateUtil.getSessionFactory();

session =sessionFactory.openSession();

session.beginTransaction();

Servlet…print form, get session

// Handle actions

if ("store".equals(request.getParameter("action"))) {



String eventTitle = request.getParameter("eventTitle");

String eventDate = request.getParameter("eventDate");

String name = request.getParameter("name");

String phone = request.getParameter("phone");

if ("".equals(eventTitle) || "".equals(eventDate)||name.equals("")||phone.equals("")) {

out.println("Please enter person, event title and date.");

} else {



System.out.println("before call to create and store");

createAndStoreEvent(name, phone,eventTitle, dateFormatter.parse(eventDate));

out.println("Added event.");

}

}



// Print page



printEventForm(out);

System.out.println("back in process ...about to call listevents");

listEvents(out, dateFormatter);



// End unit of work

//HibernateUtil.getSessionFactory().getCurrentSession().getTransaction().commit();

session.getTransaction().commit();

System.out.println("commit after save");

} catch (Exception ex) {

System.out.println(ex.toString());

HibernateUtil.getSessionFactory().getCurrentSession().getTransaction().rollback();

throw new ServletException(ex);

}

}

Servlet: the form and table of events

private void printEventForm(PrintWriter out) {

out.println("Add new event:");

out.println("");

out.println("Title: ");

out.println("Date (e.g. 24.12.2009): ");

out.println("Contact person: ");

out.println("Phone(e.g. (123) 432-1111: ");

out.println("");

out.println("");

}



private void listEvents(PrintWriter out, SimpleDateFormat dateFormatter) {



result1 = session.createCriteria(Event.class).list();



if (result1.size() > 0) {

out.println("Event Info in database:");

out.println("");

out.println("");

out.println("Event title");

out.println("Event date");

out.println("Event id");

out.println("");



for (Iterator it = result1.iterator(); it.hasNext();) {



Event event = (Event) it.next();

out.println("");



out.println("" + event.getTitle()+ "");

out.println("" + dateFormatter.format(event.getDate()) + "");

out.println("" + event.getId() + "");

out.println("");

}

out.println("");

}//if

Servlet… list table of people

int num=0;

result2 = session.createCriteria(People.class).list();

if (result2.size() > 0) {

out.println("People Info in database:");

out.println("");

out.println("");

out.println("Person");

out.println("Phone");

out.println("Event coordinating");

out.println("");



String unknown="unknown";

for (Iterator it = result2.iterator(); it.hasNext();) {

People person=(People)it.next();

out.println("");

out.println("" + person.getName() + "");

out.println("" + person.getPhone() + "");

out.println("" + ((Event)result1.get(num)).getTitle() + "");

num++;

out.println("");

}

out.println("");

}

}

Create and store

protected void createAndStoreEvent(String name,String phone,String title, Date theDate) {

System.out.println("in create and store method");

Event theEvent = new Event();

People person=new People();

theEvent.setTitle(title);

theEvent.setDate(theDate);



person.setName(name);

person.setPhone(phone);

System.out.println("about to get current session and save event");

session.save(theEvent);

System.out.println("about to get current session and save person");

session.save(person);

System.out.println("done with saves");

}



protected void doGet(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

System.out.println("in do get");

processRequest(request, response);

}



protected void doPost(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

System.out.println("in do post");

doGet(request, response);

}

}

events.People.java

public class People{

private String name;

private String phone;

private long id;

public People() {}



public long getId(){return id;}



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



public String getName() {

return name;

}



public void setName(String name) {

this.name = name;

}



public String getPhone() {

return phone;

}

public void setPhone(String phone) {

this.phone = phone;

}

}

The primary key may be generated, native or

assigned. The strategy must be specified in the

hbm.xml. This is People.hbm.xml

























Same hibernate.cfg.xml except

People table has been added.











com.mysql.jdbc.Driver

jdbc:mysql://localhost/mydb

root





10



org.hibernate.dialect.MySQLDialect

org.hibernate.cache.NoCacheProvider





true

update

thread









ant build – still needs to be modified to build

WEB-INF and classes dirs, and copy files to

there, then jar































































CRUD example

• The student table

Hibernate student info servlet

remarks

• Just one table marked

• Link above gives good information on how

to conduct queries.

• I used radiobuttons to indicate function

desired.

• I used the same ant/build and jar

commands as before.

• Same directory structure.

• Servlet in slide notes

Student.hbm.xml





































Some bits of the servlet

try {

// Begin unit of work

// HibernateUtil.getSessionFactory().getCurrentSession().beginTransaction();

sessionFactory = HibernateUtil.getSessionFactory();

session =sessionFactory.openSession();

session.beginTransaction();

if ("store".equals(request.getParameter("action"))) {

String name = request.getParameter("name");

String gpa = request.getParameter("gpa");

String year = request.getParameter("year");

String age = request.getParameter("age");

String sex = request.getParameter("sex");

if ("".equals(name) || "".equals(sex)||year.equals("")||gpa.equals("")||age.equals("")) {

out.println("Please enter name, age, sex, gpa, year and sex.");

} else {

System.out.println("before call to create and store");

createAndStoreEvent(name, age,year,sex,gpa);

out.println("Added event."); } }

else if ("list".equals(request.getParameter("action"))) {

// Print page

System.out.println("back in process ...about to call listevents");

listStudents(out);

}

Delete action

else if ("delete".equals(request.getParameter("action"))) {

String name = request.getParameter("name");

List marked=session.createQuery("from Student as

student where student.name=?").setString(0,name).list();

if(marked.size()>0){

Student student=(Student)marked.get(0);

out.println("deleting...."+ student.getName());

session.delete(student);

}

else {out.println("no match found");}

}else{//update

String name = request.getParameter("name");

String gpa = request.getParameter("gpa");

String year = request.getParameter("year");

String age = request.getParameter("age");

String sex = request.getParameter("sex");

List marked=session.createQuery("from Student as student where

student.name=?").setString(0,name).list();



if(marked.size()>0&&!"".equals(sex)&&!year.equals("")&&!gpa.equals("")&&!age.equal

s("")) {

Student student=(Student)marked.get(0);

student.setAge(Integer.parseInt(age));

student.setYear(year);

student.setGpa(Double.parseDouble(gpa));

student.setSex(sex);

session.update(student);

}

else {out.println("no match found");}

}

/*else a getinfo choice could look about the same



*/

I used radiobuttons

private void printStudentForm(PrintWriter out) {

out.println("Student info form:");

out.println("");

out.println("Name: ");

out.println("Age: ");

out.println("Sex(Male/Female): ");

out.println("Year: ");

out.println("GPA: ");

out.println(" List");

out.println("

Store");

out.println(" Update");

out.println(" Delete");



out.println("");

out.println("");

}

List students

private void listStudents(PrintWriter out) {



result1 = session.createCriteria(Student.class).list();



if (result1.size() > 0) {

out.println("Student Info:");

out.println("");

out.println("");

out.println("Student name");

out.println("Student Age");

out.println("GPA");

out.println("Sex");

out.println("Year");

out.println("");



for (Iterator it = result1.iterator(); it.hasNext();) {



Student student = (Student) it.next();

out.println("");



out.println("" + student.getName()+ "");

out.println("" + student.getAge() + "");

out.println("" + student.getGpa() + "");

out.println("" + student.getSex() + "");

out.println("" + student.getYear() + "");

out.println("");

}

out.println("");

}//if



}

Hibernate configuration











com.mysql.jdbc.Driver

jdbc:mysql://localhost/mydb

root





10



org.hibernate.dialect.MySQLDialect



true

update







web-xml









StudentInfo

data.StudentInfoServlet







StudentInfo

/studentinfo






Related docs
Other docs by HC111124214916
96 5258
Views: 1  |  Downloads: 0
Why did the Renaissance happen?
Views: 1  |  Downloads: 0
Universidad Polit�cnica del Litoral
Views: 0  |  Downloads: 0
EP Framing question:
Views: 0  |  Downloads: 0
question9
Views: 0  |  Downloads: 0
MISSION STATEMENT
Views: 0  |  Downloads: 0
SERIES 4000
Views: 0  |  Downloads: 0
By registering with docstoc.com you agree to our
privacy policy

You are almost ready to download!

You are almost ready to download!